]>
git.saurik.com Git - apple/network_cmds.git/blob - ip6addrctl.tproj/ip6addrctl.c
1 /* $KAME: ip6addrctl.c,v 1.3 2003/12/16 08:14:28 suz Exp $ */
4 * Copyright (C) 2001 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/queue.h>
37 #include <sys/param.h>
38 #include <sys/ioctl.h>
39 #include <sys/sysctl.h>
42 #include <net/if_var.h>
44 #include <netinet/in.h>
45 #include <netinet6/in6_var.h>
55 static char *configfile
;
58 TAILQ_ENTRY(policyqueue
) pc_entry
;
59 struct in6_addrpolicy pc_policy
;
61 TAILQ_HEAD(policyhead
, policyqueue
);
62 struct policyhead policyhead
;
64 static void usage
__P((void));
65 static void get_policy
__P((void));
66 static void dump_policy
__P((void));
67 static int mask2plen
__P((struct sockaddr_in6
*));
68 static int parse_prefix
__P((const char *, struct in6_addrpolicy
*));
69 static void make_policy_fromfile
__P((char *));
70 static void plen2mask
__P((struct sockaddr_in6
*, int));
71 static void set_policy
__P((void));
72 static void add_policy
__P((char *, char *, char *));
73 static void delete_policy
__P((char *));
74 static void flush_policy
__P(());
81 TAILQ_INIT(&policyhead
);
83 if (argc
== 1 || strcasecmp(argv
[1], "show") == 0) {
86 } else if (strcasecmp(argv
[1], "add") == 0) {
89 add_policy(argv
[2], argv
[3], argv
[4]);
90 } else if (strcasecmp(argv
[1], "delete") == 0) {
93 delete_policy(argv
[2]);
94 } else if (strcasecmp(argv
[1], "flush") == 0) {
97 } else if (strcasecmp(argv
[1], "install") == 0) {
100 configfile
= argv
[2];
101 make_policy_fromfile(configfile
);
112 int mib
[] = { CTL_NET
, PF_INET6
, IPPROTO_IPV6
, IPV6CTL_ADDRCTLPOLICY
};
115 struct in6_addrpolicy
*pol
, *ep
;
117 if (sysctl(mib
, sizeof(mib
) / sizeof(mib
[0]), NULL
, &l
, NULL
, 0) < 0) {
118 err(1, "sysctl(IPV6CTL_ADDRCTLPOLICY)");
122 printf("no source-address-selection policy is installed\n");
125 if ((buf
= malloc(l
)) == NULL
) {
126 errx(1, "malloc failed");
129 if (sysctl(mib
, sizeof(mib
) / sizeof(mib
[0]), buf
, &l
, NULL
, 0) < 0) {
130 err(1, "sysctl(IPV6CTL_ADDRCTLPOLICY)");
134 ep
= (struct in6_addrpolicy
*)(buf
+ l
);
135 for (pol
= (struct in6_addrpolicy
*)buf
; pol
+ 1 <= ep
; pol
++) {
136 struct policyqueue
*new;
138 if ((new = malloc(sizeof(*new))) == NULL
)
139 errx(1, "malloc failed\n");
140 new->pc_policy
= *pol
;
141 TAILQ_INSERT_TAIL(&policyhead
, new, pc_entry
);
151 char addrbuf
[NI_MAXHOST
];
152 struct in6_addrpolicy
*pol
;
153 struct policyqueue
*ent
;
156 for (ent
= TAILQ_FIRST(&policyhead
); ent
;
157 ent
= TAILQ_NEXT(ent
, pc_entry
)) {
158 pol
= &ent
->pc_policy
;
160 printf("%-30s %5s %5s %8s\n",
161 "Prefix", "Prec", "Label", "Use");
165 if ((getnameinfo((struct sockaddr
*)&pol
->addr
,
166 sizeof(pol
->addr
), addrbuf
, sizeof(addrbuf
),
167 NULL
, 0, NI_NUMERICHOST
))) {
168 warnx("getnameinfo for prefix address failed");
171 if ((plen
= mask2plen(&pol
->addrmask
)) < 0) {
172 warnx("invalid address mask");
175 addrlen
= strlen(addrbuf
);
176 if (addrlen
+ sizeof("/128") < sizeof(addrbuf
)) {
177 snprintf(&addrbuf
[addrlen
],
178 sizeof(addrbuf
) - addrlen
- 1,
180 printf("%-30s", addrbuf
);
182 printf("%s/%d", addrbuf
, plen
);
183 printf(" %5d %5d %8llu\n", pol
->preced
, pol
->label
,
184 (unsigned long long)pol
->use
);
188 #define SKIP_WHITE(p, emptyok) \
190 while((*(p) == ' ' || *(p) == '\t')) \
192 if ((*(p) == '\0' || (*(p) == '\n')) && !(emptyok)) \
195 #define SKIP_WORD(p) \
197 while(*(p) != ' ' && *(p) != '\t') \
199 if (*(p) == '\0' || *(p) == '\n') \
204 make_policy_fromfile(conf
)
207 char line
[_POSIX2_LINE_MAX
], *cp
;
211 struct in6_addrpolicy pol0
;
212 struct policyqueue
*new;
214 if ((fp
= fopen(conf
, "r")) == NULL
)
215 err(1, "fopen: %s", conf
);
217 while(fgets(line
, sizeof(line
), fp
)) {
221 memset(&pol0
, 0, sizeof(pol0
));
225 if (*cp
== '\n') /* empty line */
230 if (parse_prefix((const char *)addrstr
, &pol0
))
233 /* get precedence value */
236 pol0
.preced
= atoi(cp
);
241 pol0
.label
= atoi(cp
);
243 /* parse succeeded. make a control buffer entry. */
244 if ((new = malloc(sizeof(*new))) == NULL
)
245 errx(1, "malloc failed\n");
246 memset(new, 0, sizeof(*new));
247 new->pc_policy
= pol0
;
248 TAILQ_INSERT_TAIL(&policyhead
, new, pc_entry
);
255 errx(1, "parse failed at line %d", count
);
260 parse_prefix(prefix0
, pol
)
262 struct in6_addrpolicy
*pol
;
265 char *prefix
, *plenstr
;
266 struct addrinfo hints
, *res
;
268 if ((prefix
= strdup(prefix0
)) == NULL
)
269 errx(1, "strdup failed");
271 if ((plenstr
= strchr(prefix
, '/')) == NULL
) {
277 memset(&hints
, 0, sizeof(hints
));
278 hints
.ai_flags
= AI_NUMERICHOST
;
279 hints
.ai_family
= AF_INET6
;
281 if ((e
= getaddrinfo(prefix
, NULL
, &hints
, &res
)) != 0) {
282 warnx("getaddrinfo failed for %s: %s", prefix
,
286 memcpy(&pol
->addr
, res
->ai_addr
, res
->ai_addrlen
);
288 plen
= atoi(plenstr
+ 1);
289 if (plen
< 0 || plen
> 128) {
290 warnx("invalid prefix length: %d", plen
);
294 plen2mask(&pol
->addrmask
, plen
);
302 plen2mask(mask
, plen
)
303 struct sockaddr_in6
*mask
;
306 u_char
*cp
= (unsigned char *)&mask
->sin6_addr
;
308 memset(mask
, 0, sizeof(*mask
));
309 mask
->sin6_family
= AF_INET6
; /* just in case */
310 mask
->sin6_len
= sizeof(*mask
);
312 for(; plen
>= 8; plen
-= 8)
315 *cp
= (0xff << (8 - plen
));
321 struct policyqueue
*ent
;
324 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0)
325 err(1, "socket(UDP)");
327 for (ent
= TAILQ_FIRST(&policyhead
); ent
;
328 ent
= TAILQ_NEXT(ent
, pc_entry
)) {
329 if (ioctl(s
, SIOCAADDRCTL_POLICY
, &ent
->pc_policy
))
330 warn("ioctl(SIOCAADDRCTL_POLICY)");
338 struct sockaddr_in6
*mask
;
340 int masklen
, final
= 0;
344 lim
= (u_char
*)(mask
+ 1);
345 for (p
= (u_char
*)(&mask
->sin6_addr
); p
< lim
; p
++) {
397 add_policy(prefix
, prec
, label
)
398 char *prefix
, *prec
, *label
;
400 struct in6_addrpolicy p
;
403 memset(&p
, 0, sizeof(p
));
405 if (parse_prefix((const char *)prefix
, &p
))
406 errx(1, "bad prefix: %s", prefix
);
407 p
.preced
= atoi(prec
);
408 p
.label
= atoi(label
);
410 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0)
411 err(1, "socket(UDP)");
412 if (ioctl(s
, SIOCAADDRCTL_POLICY
, &p
))
413 err(1, "ioctl(SIOCAADDRCTL_POLICY)");
419 delete_policy(prefix
)
422 struct in6_addrpolicy p
;
425 memset(&p
, 0, sizeof(p
));
427 if (parse_prefix((const char *)prefix
, &p
))
428 errx(1, "bad prefix: %s", prefix
);
430 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0)
431 err(1, "socket(UDP)");
432 if (ioctl(s
, SIOCDADDRCTL_POLICY
, &p
))
433 err(1, "ioctl(SIOCDADDRCTL_POLICY)");
441 struct policyqueue
*ent
;
444 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0)
445 err(1, "socket(UDP)");
447 for (ent
= TAILQ_FIRST(&policyhead
); ent
;
448 ent
= TAILQ_NEXT(ent
, pc_entry
)) {
449 if (ioctl(s
, SIOCDADDRCTL_POLICY
, &ent
->pc_policy
))
450 warn("ioctl(SIOCDADDRCTL_POLICY)");
459 fprintf(stderr
, "usage: ip6addrctl [show]\n");
460 fprintf(stderr
, " ip6addrctl add "
461 "<prefix> <precedence> <label>\n");
462 fprintf(stderr
, " ip6addrctl delete <prefix>\n");
463 fprintf(stderr
, " ip6addrctl flush\n");
464 fprintf(stderr
, " ip6addrctl install <configfile>\n");