12df34251SHajimu UMEMOTO /* $KAME: ip6addrctl.c,v 1.3 2003/12/16 08:14:28 suz Exp $ */ 2f71d0e11SHajimu UMEMOTO 38a16b7a1SPedro F. Giffuni /*- 48a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 58a16b7a1SPedro F. Giffuni * 6f71d0e11SHajimu UMEMOTO * Copyright (C) 2001 WIDE Project. 7f71d0e11SHajimu UMEMOTO * All rights reserved. 8f71d0e11SHajimu UMEMOTO * 9f71d0e11SHajimu UMEMOTO * Redistribution and use in source and binary forms, with or without 10f71d0e11SHajimu UMEMOTO * modification, are permitted provided that the following conditions 11f71d0e11SHajimu UMEMOTO * are met: 12f71d0e11SHajimu UMEMOTO * 1. Redistributions of source code must retain the above copyright 13f71d0e11SHajimu UMEMOTO * notice, this list of conditions and the following disclaimer. 14f71d0e11SHajimu UMEMOTO * 2. Redistributions in binary form must reproduce the above copyright 15f71d0e11SHajimu UMEMOTO * notice, this list of conditions and the following disclaimer in the 16f71d0e11SHajimu UMEMOTO * documentation and/or other materials provided with the distribution. 17f71d0e11SHajimu UMEMOTO * 3. Neither the name of the project nor the names of its contributors 18f71d0e11SHajimu UMEMOTO * may be used to endorse or promote products derived from this software 19f71d0e11SHajimu UMEMOTO * without specific prior written permission. 20f71d0e11SHajimu UMEMOTO * 21f71d0e11SHajimu UMEMOTO * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22f71d0e11SHajimu UMEMOTO * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23f71d0e11SHajimu UMEMOTO * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24f71d0e11SHajimu UMEMOTO * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25f71d0e11SHajimu UMEMOTO * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26f71d0e11SHajimu UMEMOTO * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27f71d0e11SHajimu UMEMOTO * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28f71d0e11SHajimu UMEMOTO * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29f71d0e11SHajimu UMEMOTO * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30f71d0e11SHajimu UMEMOTO * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31f71d0e11SHajimu UMEMOTO * SUCH DAMAGE. 32f71d0e11SHajimu UMEMOTO */ 33f71d0e11SHajimu UMEMOTO 34f71d0e11SHajimu UMEMOTO #include <sys/types.h> 35f71d0e11SHajimu UMEMOTO #include <sys/socket.h> 36f71d0e11SHajimu UMEMOTO #include <sys/queue.h> 37f71d0e11SHajimu UMEMOTO #include <sys/param.h> 38f71d0e11SHajimu UMEMOTO #include <sys/ioctl.h> 39*6dcdd79aSZhenlei Huang #ifdef JAIL 40*6dcdd79aSZhenlei Huang #include <sys/jail.h> 41*6dcdd79aSZhenlei Huang #endif 42f71d0e11SHajimu UMEMOTO #include <sys/sysctl.h> 43f71d0e11SHajimu UMEMOTO 44f71d0e11SHajimu UMEMOTO #include <net/if.h> 45f71d0e11SHajimu UMEMOTO 46f71d0e11SHajimu UMEMOTO #include <netinet/in.h> 47f71d0e11SHajimu UMEMOTO #include <netinet6/in6_var.h> 48f71d0e11SHajimu UMEMOTO 49f71d0e11SHajimu UMEMOTO #include <stdlib.h> 50f71d0e11SHajimu UMEMOTO #include <netdb.h> 51*6dcdd79aSZhenlei Huang #ifdef JAIL 52*6dcdd79aSZhenlei Huang #include <jail.h> 53*6dcdd79aSZhenlei Huang #endif 54f71d0e11SHajimu UMEMOTO #include <stdio.h> 55f71d0e11SHajimu UMEMOTO #include <unistd.h> 56f71d0e11SHajimu UMEMOTO #include <limits.h> 57f71d0e11SHajimu UMEMOTO #include <string.h> 58f71d0e11SHajimu UMEMOTO #include <err.h> 59f71d0e11SHajimu UMEMOTO 60*6dcdd79aSZhenlei Huang #ifdef JAIL 61*6dcdd79aSZhenlei Huang static char *jailname; 62*6dcdd79aSZhenlei Huang #endif 63f71d0e11SHajimu UMEMOTO static char *configfile; 64f71d0e11SHajimu UMEMOTO 65f71d0e11SHajimu UMEMOTO struct policyqueue { 66f71d0e11SHajimu UMEMOTO TAILQ_ENTRY(policyqueue) pc_entry; 67f71d0e11SHajimu UMEMOTO struct in6_addrpolicy pc_policy; 68f71d0e11SHajimu UMEMOTO }; 69f71d0e11SHajimu UMEMOTO TAILQ_HEAD(policyhead, policyqueue); 707bb9ba61SZhenlei Huang static struct policyhead policyhead = TAILQ_HEAD_INITIALIZER(policyhead); 71f71d0e11SHajimu UMEMOTO 72a9cce232SAlfonso Gregory static void usage(void) __dead2; 73*6dcdd79aSZhenlei Huang static void attach_jail(void); 74784bddbcSKevin Lo static void get_policy(void); 75784bddbcSKevin Lo static void dump_policy(void); 76784bddbcSKevin Lo static int mask2plen(struct sockaddr_in6 *); 77784bddbcSKevin Lo static int parse_prefix(const char *, struct in6_addrpolicy *); 78784bddbcSKevin Lo static void make_policy_fromfile(char *); 79784bddbcSKevin Lo static void plen2mask(struct sockaddr_in6 *, int); 80784bddbcSKevin Lo static void set_policy(void); 81784bddbcSKevin Lo static void add_policy(char *, char *, char *); 82784bddbcSKevin Lo static void delete_policy(char *); 8345442869SEitan Adler static void flush_policy(void); 84f71d0e11SHajimu UMEMOTO 85f71d0e11SHajimu UMEMOTO int 8645442869SEitan Adler main(int argc, char *argv[]) 87f71d0e11SHajimu UMEMOTO { 88*6dcdd79aSZhenlei Huang int ch; 89*6dcdd79aSZhenlei Huang 90*6dcdd79aSZhenlei Huang while ((ch = getopt(argc, argv, "j:")) != -1) { 91*6dcdd79aSZhenlei Huang switch (ch) { 92*6dcdd79aSZhenlei Huang case 'j': 93*6dcdd79aSZhenlei Huang #ifdef JAIL 94*6dcdd79aSZhenlei Huang if ((jailname = optarg) == NULL) 95*6dcdd79aSZhenlei Huang usage(); 96*6dcdd79aSZhenlei Huang #else 97*6dcdd79aSZhenlei Huang errx(1, "not built with jail support"); 98*6dcdd79aSZhenlei Huang #endif 99*6dcdd79aSZhenlei Huang break; 100*6dcdd79aSZhenlei Huang default: 101*6dcdd79aSZhenlei Huang usage(); 102*6dcdd79aSZhenlei Huang } 103*6dcdd79aSZhenlei Huang } 104*6dcdd79aSZhenlei Huang argc -= optind; 105*6dcdd79aSZhenlei Huang argv += optind; 106*6dcdd79aSZhenlei Huang 107*6dcdd79aSZhenlei Huang if (argc == 0 || (argc == 1 && strcasecmp(argv[0], "show") == 0)) { 108*6dcdd79aSZhenlei Huang attach_jail(); 109f71d0e11SHajimu UMEMOTO get_policy(); 110f71d0e11SHajimu UMEMOTO dump_policy(); 111*6dcdd79aSZhenlei Huang } else if (strcasecmp(argv[0], "add") == 0) { 112*6dcdd79aSZhenlei Huang if (argc != 4) 113f71d0e11SHajimu UMEMOTO usage(); 114*6dcdd79aSZhenlei Huang attach_jail(); 115*6dcdd79aSZhenlei Huang add_policy(argv[1], argv[2], argv[3]); 116*6dcdd79aSZhenlei Huang } else if (strcasecmp(argv[0], "delete") == 0) { 11713ce55b6SZhenlei Huang if (argc != 2) 11813ce55b6SZhenlei Huang usage(); 119*6dcdd79aSZhenlei Huang attach_jail(); 120*6dcdd79aSZhenlei Huang delete_policy(argv[1]); 121*6dcdd79aSZhenlei Huang } else if (strcasecmp(argv[0], "flush") == 0) { 122*6dcdd79aSZhenlei Huang if (argc != 1) 123*6dcdd79aSZhenlei Huang usage(); 124*6dcdd79aSZhenlei Huang attach_jail(); 125f71d0e11SHajimu UMEMOTO get_policy(); 126f71d0e11SHajimu UMEMOTO flush_policy(); 127*6dcdd79aSZhenlei Huang } else if (strcasecmp(argv[0], "install") == 0) { 128*6dcdd79aSZhenlei Huang if (argc != 2) 129f71d0e11SHajimu UMEMOTO usage(); 130*6dcdd79aSZhenlei Huang configfile = argv[1]; 131f71d0e11SHajimu UMEMOTO make_policy_fromfile(configfile); 132*6dcdd79aSZhenlei Huang attach_jail(); 133f71d0e11SHajimu UMEMOTO set_policy(); 134f71d0e11SHajimu UMEMOTO } else 135f71d0e11SHajimu UMEMOTO usage(); 136f71d0e11SHajimu UMEMOTO 137f71d0e11SHajimu UMEMOTO exit(0); 138f71d0e11SHajimu UMEMOTO } 139f71d0e11SHajimu UMEMOTO 140f71d0e11SHajimu UMEMOTO static void 141*6dcdd79aSZhenlei Huang attach_jail(void) 142*6dcdd79aSZhenlei Huang { 143*6dcdd79aSZhenlei Huang #ifdef JAIL 144*6dcdd79aSZhenlei Huang int jid; 145*6dcdd79aSZhenlei Huang 146*6dcdd79aSZhenlei Huang if (jailname == NULL) 147*6dcdd79aSZhenlei Huang return; 148*6dcdd79aSZhenlei Huang 149*6dcdd79aSZhenlei Huang jid = jail_getid(jailname); 150*6dcdd79aSZhenlei Huang if (jid == -1) 151*6dcdd79aSZhenlei Huang errx(1, "jail not found"); 152*6dcdd79aSZhenlei Huang if (jail_attach(jid) != 0) 153*6dcdd79aSZhenlei Huang errx(1, "cannot attach to jail"); 154*6dcdd79aSZhenlei Huang #endif 155*6dcdd79aSZhenlei Huang } 156*6dcdd79aSZhenlei Huang 157*6dcdd79aSZhenlei Huang static void 15845442869SEitan Adler get_policy(void) 159f71d0e11SHajimu UMEMOTO { 160f71d0e11SHajimu UMEMOTO int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY }; 161f71d0e11SHajimu UMEMOTO size_t l; 16245442869SEitan Adler struct in6_addrpolicy *buf; 163f71d0e11SHajimu UMEMOTO struct in6_addrpolicy *pol, *ep; 164f71d0e11SHajimu UMEMOTO 165d42456e1SMarcelo Araujo if (sysctl(mib, nitems(mib), NULL, &l, NULL, 0) < 0) { 166f71d0e11SHajimu UMEMOTO err(1, "sysctl(IPV6CTL_ADDRCTLPOLICY)"); 167f71d0e11SHajimu UMEMOTO /* NOTREACHED */ 168f71d0e11SHajimu UMEMOTO } 1692df34251SHajimu UMEMOTO if (l == 0) { 1702df34251SHajimu UMEMOTO printf("no source-address-selection policy is installed\n"); 1712df34251SHajimu UMEMOTO return; 1722df34251SHajimu UMEMOTO } 173f71d0e11SHajimu UMEMOTO if ((buf = malloc(l)) == NULL) { 174f71d0e11SHajimu UMEMOTO errx(1, "malloc failed"); 175f71d0e11SHajimu UMEMOTO /* NOTREACHED */ 176f71d0e11SHajimu UMEMOTO } 177d42456e1SMarcelo Araujo if (sysctl(mib, nitems(mib), buf, &l, NULL, 0) < 0) { 178f71d0e11SHajimu UMEMOTO err(1, "sysctl(IPV6CTL_ADDRCTLPOLICY)"); 179f71d0e11SHajimu UMEMOTO /* NOTREACHED */ 180f71d0e11SHajimu UMEMOTO } 181f71d0e11SHajimu UMEMOTO 18245442869SEitan Adler ep = buf + l/sizeof(*buf); 18345442869SEitan Adler for (pol = buf; pol + 1 <= ep; pol++) { 184f71d0e11SHajimu UMEMOTO struct policyqueue *new; 185f71d0e11SHajimu UMEMOTO 186f71d0e11SHajimu UMEMOTO if ((new = malloc(sizeof(*new))) == NULL) 187f71d0e11SHajimu UMEMOTO errx(1, "malloc failed\n"); 188f71d0e11SHajimu UMEMOTO new->pc_policy = *pol; 189f71d0e11SHajimu UMEMOTO TAILQ_INSERT_TAIL(&policyhead, new, pc_entry); 190f71d0e11SHajimu UMEMOTO } 191f71d0e11SHajimu UMEMOTO 192f71d0e11SHajimu UMEMOTO free(buf); 193f71d0e11SHajimu UMEMOTO } 194f71d0e11SHajimu UMEMOTO 195f71d0e11SHajimu UMEMOTO static void 19645442869SEitan Adler dump_policy(void) 197f71d0e11SHajimu UMEMOTO { 198f71d0e11SHajimu UMEMOTO size_t addrlen; 199f71d0e11SHajimu UMEMOTO char addrbuf[NI_MAXHOST]; 200f71d0e11SHajimu UMEMOTO struct in6_addrpolicy *pol; 201f71d0e11SHajimu UMEMOTO struct policyqueue *ent; 202f71d0e11SHajimu UMEMOTO int plen, first = 1; 203f71d0e11SHajimu UMEMOTO 204f71d0e11SHajimu UMEMOTO for (ent = TAILQ_FIRST(&policyhead); ent; 205f71d0e11SHajimu UMEMOTO ent = TAILQ_NEXT(ent, pc_entry)) { 206f71d0e11SHajimu UMEMOTO pol = &ent->pc_policy; 207f71d0e11SHajimu UMEMOTO if (first) { 208f71d0e11SHajimu UMEMOTO printf("%-30s %5s %5s %8s\n", 209f71d0e11SHajimu UMEMOTO "Prefix", "Prec", "Label", "Use"); 210f71d0e11SHajimu UMEMOTO first = 0; 211f71d0e11SHajimu UMEMOTO } 212f71d0e11SHajimu UMEMOTO 213f71d0e11SHajimu UMEMOTO if ((getnameinfo((struct sockaddr *)&pol->addr, 214f71d0e11SHajimu UMEMOTO sizeof(pol->addr), addrbuf, sizeof(addrbuf), 215f71d0e11SHajimu UMEMOTO NULL, 0, NI_NUMERICHOST))) { 216f71d0e11SHajimu UMEMOTO warnx("getnameinfo for prefix address failed"); 217f71d0e11SHajimu UMEMOTO continue; 218f71d0e11SHajimu UMEMOTO } 219f71d0e11SHajimu UMEMOTO if ((plen = mask2plen(&pol->addrmask)) < 0) { 220f71d0e11SHajimu UMEMOTO warnx("invalid address mask"); 221f71d0e11SHajimu UMEMOTO continue; 222f71d0e11SHajimu UMEMOTO } 223f71d0e11SHajimu UMEMOTO addrlen = strlen(addrbuf); 224f71d0e11SHajimu UMEMOTO if (addrlen + sizeof("/128") < sizeof(addrbuf)) { 225f71d0e11SHajimu UMEMOTO snprintf(&addrbuf[addrlen], 226f71d0e11SHajimu UMEMOTO sizeof(addrbuf) - addrlen - 1, 227f71d0e11SHajimu UMEMOTO "/%d", plen); 228f71d0e11SHajimu UMEMOTO printf("%-30s", addrbuf); 229f71d0e11SHajimu UMEMOTO } else /* XXX */ 230f71d0e11SHajimu UMEMOTO printf("%s/%d", addrbuf, plen); 231f71d0e11SHajimu UMEMOTO printf(" %5d %5d %8llu\n", pol->preced, pol->label, 232f71d0e11SHajimu UMEMOTO (unsigned long long)pol->use); 233f71d0e11SHajimu UMEMOTO } 234f71d0e11SHajimu UMEMOTO } 235f71d0e11SHajimu UMEMOTO 236f71d0e11SHajimu UMEMOTO #define SKIP_WHITE(p, emptyok) \ 237f71d0e11SHajimu UMEMOTO do { \ 238f71d0e11SHajimu UMEMOTO while((*(p) == ' ' || *(p) == '\t')) \ 239f71d0e11SHajimu UMEMOTO (p)++; \ 240f71d0e11SHajimu UMEMOTO if ((*(p) == '\0' || (*(p) == '\n')) && !(emptyok)) \ 241f71d0e11SHajimu UMEMOTO goto bad; \ 242f71d0e11SHajimu UMEMOTO } while (0); 243f71d0e11SHajimu UMEMOTO #define SKIP_WORD(p) \ 244f71d0e11SHajimu UMEMOTO do { \ 245f71d0e11SHajimu UMEMOTO while(*(p) != ' ' && *(p) != '\t') \ 246f71d0e11SHajimu UMEMOTO (p)++; \ 247f71d0e11SHajimu UMEMOTO if (*(p) == '\0' || *(p) == '\n') \ 248f71d0e11SHajimu UMEMOTO goto bad; \ 249f71d0e11SHajimu UMEMOTO } while (0); 250f71d0e11SHajimu UMEMOTO 251f71d0e11SHajimu UMEMOTO static void 25245442869SEitan Adler make_policy_fromfile(char *conf) 253f71d0e11SHajimu UMEMOTO { 254f71d0e11SHajimu UMEMOTO char line[_POSIX2_LINE_MAX], *cp; 255f71d0e11SHajimu UMEMOTO char *addrstr; 256f71d0e11SHajimu UMEMOTO FILE *fp; 257f71d0e11SHajimu UMEMOTO int count = 0; 258f71d0e11SHajimu UMEMOTO struct in6_addrpolicy pol0; 259f71d0e11SHajimu UMEMOTO struct policyqueue *new; 260f71d0e11SHajimu UMEMOTO 261f71d0e11SHajimu UMEMOTO if ((fp = fopen(conf, "r")) == NULL) 262f71d0e11SHajimu UMEMOTO err(1, "fopen: %s", conf); 263f71d0e11SHajimu UMEMOTO 264f71d0e11SHajimu UMEMOTO while(fgets(line, sizeof(line), fp)) { 265f71d0e11SHajimu UMEMOTO count++; 266f71d0e11SHajimu UMEMOTO cp = line; 267f71d0e11SHajimu UMEMOTO 268f71d0e11SHajimu UMEMOTO memset(&pol0, 0, sizeof(pol0)); 269f71d0e11SHajimu UMEMOTO 270f71d0e11SHajimu UMEMOTO /* get prefix */ 271f71d0e11SHajimu UMEMOTO SKIP_WHITE(cp, 1); 272f71d0e11SHajimu UMEMOTO if (*cp == '\n') /* empty line */ 273f71d0e11SHajimu UMEMOTO continue; 274f71d0e11SHajimu UMEMOTO if (*cp == '#') 275f71d0e11SHajimu UMEMOTO continue; 276f71d0e11SHajimu UMEMOTO addrstr = cp; 277f71d0e11SHajimu UMEMOTO if (parse_prefix((const char *)addrstr, &pol0)) 278f71d0e11SHajimu UMEMOTO goto bad; 279f71d0e11SHajimu UMEMOTO 280f71d0e11SHajimu UMEMOTO /* get precedence value */ 281f71d0e11SHajimu UMEMOTO SKIP_WORD(cp); 282f71d0e11SHajimu UMEMOTO SKIP_WHITE(cp, 0); 283f71d0e11SHajimu UMEMOTO pol0.preced = atoi(cp); 284f71d0e11SHajimu UMEMOTO 285f71d0e11SHajimu UMEMOTO /* get label */ 286f71d0e11SHajimu UMEMOTO SKIP_WORD(cp); 287f71d0e11SHajimu UMEMOTO SKIP_WHITE(cp, 0); 288f71d0e11SHajimu UMEMOTO pol0.label = atoi(cp); 289f71d0e11SHajimu UMEMOTO 290f71d0e11SHajimu UMEMOTO /* parse succeeded. make a control buffer entry. */ 291f71d0e11SHajimu UMEMOTO if ((new = malloc(sizeof(*new))) == NULL) 292f71d0e11SHajimu UMEMOTO errx(1, "malloc failed\n"); 293f71d0e11SHajimu UMEMOTO memset(new, 0, sizeof(*new)); 294f71d0e11SHajimu UMEMOTO new->pc_policy = pol0; 295f71d0e11SHajimu UMEMOTO TAILQ_INSERT_TAIL(&policyhead, new, pc_entry); 296f71d0e11SHajimu UMEMOTO } 297f71d0e11SHajimu UMEMOTO 298f71d0e11SHajimu UMEMOTO fclose(fp); 299f71d0e11SHajimu UMEMOTO return; 300f71d0e11SHajimu UMEMOTO 301f71d0e11SHajimu UMEMOTO bad: 302f71d0e11SHajimu UMEMOTO errx(1, "parse failed at line %d", count); 303f71d0e11SHajimu UMEMOTO /* NOTREACHED */ 304f71d0e11SHajimu UMEMOTO } 305f71d0e11SHajimu UMEMOTO 306f71d0e11SHajimu UMEMOTO static int 30745442869SEitan Adler parse_prefix(const char *prefix0, struct in6_addrpolicy *pol) 308f71d0e11SHajimu UMEMOTO { 309f71d0e11SHajimu UMEMOTO int e = 0, plen; 310f71d0e11SHajimu UMEMOTO char *prefix, *plenstr; 311f71d0e11SHajimu UMEMOTO struct addrinfo hints, *res; 312f71d0e11SHajimu UMEMOTO 313f71d0e11SHajimu UMEMOTO if ((prefix = strdup(prefix0)) == NULL) 314f71d0e11SHajimu UMEMOTO errx(1, "strdup failed"); 315f71d0e11SHajimu UMEMOTO 316f71d0e11SHajimu UMEMOTO if ((plenstr = strchr(prefix, '/')) == NULL) { 317f71d0e11SHajimu UMEMOTO e = -1; 318f71d0e11SHajimu UMEMOTO goto end; 319f71d0e11SHajimu UMEMOTO } 320f71d0e11SHajimu UMEMOTO *plenstr = '\0'; 321f71d0e11SHajimu UMEMOTO 322f71d0e11SHajimu UMEMOTO memset(&hints, 0, sizeof(hints)); 323f71d0e11SHajimu UMEMOTO hints.ai_flags = AI_NUMERICHOST; 324f71d0e11SHajimu UMEMOTO hints.ai_family = AF_INET6; 325f71d0e11SHajimu UMEMOTO 326f71d0e11SHajimu UMEMOTO if ((e = getaddrinfo(prefix, NULL, &hints, &res)) != 0) { 327f71d0e11SHajimu UMEMOTO warnx("getaddrinfo failed for %s: %s", prefix, 328f71d0e11SHajimu UMEMOTO gai_strerror(e)); 329f71d0e11SHajimu UMEMOTO goto end; 330f71d0e11SHajimu UMEMOTO } 331f71d0e11SHajimu UMEMOTO memcpy(&pol->addr, res->ai_addr, res->ai_addrlen); 332f71d0e11SHajimu UMEMOTO freeaddrinfo(res); 333f71d0e11SHajimu UMEMOTO plen = atoi(plenstr + 1); 334f71d0e11SHajimu UMEMOTO if (plen < 0 || plen > 128) { 335f71d0e11SHajimu UMEMOTO warnx("invalid prefix length: %d", plen); 336f71d0e11SHajimu UMEMOTO e = -1; 337f71d0e11SHajimu UMEMOTO goto end; 338f71d0e11SHajimu UMEMOTO } 339f71d0e11SHajimu UMEMOTO plen2mask(&pol->addrmask, plen); 340f71d0e11SHajimu UMEMOTO 341f71d0e11SHajimu UMEMOTO end: 342f71d0e11SHajimu UMEMOTO free(prefix); 343f71d0e11SHajimu UMEMOTO return(e); 344f71d0e11SHajimu UMEMOTO } 345f71d0e11SHajimu UMEMOTO 346f71d0e11SHajimu UMEMOTO static void 34745442869SEitan Adler plen2mask(struct sockaddr_in6 *mask, int plen) 348f71d0e11SHajimu UMEMOTO { 34945442869SEitan Adler u_char *cp = (unsigned char *)&mask->sin6_addr; 350f71d0e11SHajimu UMEMOTO 351f71d0e11SHajimu UMEMOTO memset(mask, 0, sizeof(*mask)); 352f71d0e11SHajimu UMEMOTO mask->sin6_family = AF_INET6; /* just in case */ 353f71d0e11SHajimu UMEMOTO mask->sin6_len = sizeof(*mask); 354f71d0e11SHajimu UMEMOTO 355f71d0e11SHajimu UMEMOTO for(; plen >= 8; plen -= 8) 356f71d0e11SHajimu UMEMOTO *cp++ = 0xff; 357f71d0e11SHajimu UMEMOTO if (plen > 0) 358f71d0e11SHajimu UMEMOTO *cp = (0xff << (8 - plen)); 359f71d0e11SHajimu UMEMOTO } 360f71d0e11SHajimu UMEMOTO 361f71d0e11SHajimu UMEMOTO static void 36245442869SEitan Adler set_policy(void) 363f71d0e11SHajimu UMEMOTO { 364f71d0e11SHajimu UMEMOTO struct policyqueue *ent; 365f71d0e11SHajimu UMEMOTO int s; 366f71d0e11SHajimu UMEMOTO 367f71d0e11SHajimu UMEMOTO if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) 368f71d0e11SHajimu UMEMOTO err(1, "socket(UDP)"); 369f71d0e11SHajimu UMEMOTO 370f71d0e11SHajimu UMEMOTO for (ent = TAILQ_FIRST(&policyhead); ent; 371f71d0e11SHajimu UMEMOTO ent = TAILQ_NEXT(ent, pc_entry)) { 372f71d0e11SHajimu UMEMOTO if (ioctl(s, SIOCAADDRCTL_POLICY, &ent->pc_policy)) 373f71d0e11SHajimu UMEMOTO warn("ioctl(SIOCAADDRCTL_POLICY)"); 374f71d0e11SHajimu UMEMOTO } 375f71d0e11SHajimu UMEMOTO 376f71d0e11SHajimu UMEMOTO close(s); 377f71d0e11SHajimu UMEMOTO } 378f71d0e11SHajimu UMEMOTO 379f71d0e11SHajimu UMEMOTO static int 38045442869SEitan Adler mask2plen(struct sockaddr_in6 *mask) 381f71d0e11SHajimu UMEMOTO { 382f71d0e11SHajimu UMEMOTO int masklen, final = 0; 383f71d0e11SHajimu UMEMOTO u_char *p, *lim; 384f71d0e11SHajimu UMEMOTO 385f71d0e11SHajimu UMEMOTO masklen = 0; 386f71d0e11SHajimu UMEMOTO lim = (u_char *)(mask + 1); 387f71d0e11SHajimu UMEMOTO for (p = (u_char *)(&mask->sin6_addr); p < lim; p++) { 388f71d0e11SHajimu UMEMOTO if (final && *p) { 389f71d0e11SHajimu UMEMOTO goto bad; 390f71d0e11SHajimu UMEMOTO } 391f71d0e11SHajimu UMEMOTO 392f71d0e11SHajimu UMEMOTO switch (*p & 0xff) { 393f71d0e11SHajimu UMEMOTO case 0xff: 394f71d0e11SHajimu UMEMOTO masklen += 8; 395f71d0e11SHajimu UMEMOTO break; 396f71d0e11SHajimu UMEMOTO case 0xfe: 397f71d0e11SHajimu UMEMOTO masklen += 7; 398f71d0e11SHajimu UMEMOTO final++; 399f71d0e11SHajimu UMEMOTO break; 400f71d0e11SHajimu UMEMOTO case 0xfc: 401f71d0e11SHajimu UMEMOTO masklen += 6; 402f71d0e11SHajimu UMEMOTO final++; 403f71d0e11SHajimu UMEMOTO break; 404f71d0e11SHajimu UMEMOTO case 0xf8: 405f71d0e11SHajimu UMEMOTO masklen += 5; 406f71d0e11SHajimu UMEMOTO final++; 407f71d0e11SHajimu UMEMOTO break; 408f71d0e11SHajimu UMEMOTO case 0xf0: 409f71d0e11SHajimu UMEMOTO masklen += 4; 410f71d0e11SHajimu UMEMOTO final++; 411f71d0e11SHajimu UMEMOTO break; 412f71d0e11SHajimu UMEMOTO case 0xe0: 413f71d0e11SHajimu UMEMOTO masklen += 3; 414f71d0e11SHajimu UMEMOTO final++; 415f71d0e11SHajimu UMEMOTO break; 416f71d0e11SHajimu UMEMOTO case 0xc0: 417f71d0e11SHajimu UMEMOTO masklen += 2; 418f71d0e11SHajimu UMEMOTO final++; 419f71d0e11SHajimu UMEMOTO break; 420f71d0e11SHajimu UMEMOTO case 0x80: 421f71d0e11SHajimu UMEMOTO masklen += 1; 422f71d0e11SHajimu UMEMOTO final++; 423f71d0e11SHajimu UMEMOTO break; 424f71d0e11SHajimu UMEMOTO case 0x00: 425f71d0e11SHajimu UMEMOTO final++; 426f71d0e11SHajimu UMEMOTO break; 427f71d0e11SHajimu UMEMOTO default: 428f71d0e11SHajimu UMEMOTO goto bad; 429f71d0e11SHajimu UMEMOTO break; 430f71d0e11SHajimu UMEMOTO } 431f71d0e11SHajimu UMEMOTO } 432f71d0e11SHajimu UMEMOTO return(masklen); 433f71d0e11SHajimu UMEMOTO 434f71d0e11SHajimu UMEMOTO bad: 435f71d0e11SHajimu UMEMOTO return(-1); 436f71d0e11SHajimu UMEMOTO } 437f71d0e11SHajimu UMEMOTO 438f71d0e11SHajimu UMEMOTO static void 43945442869SEitan Adler add_policy(char *prefix, char *prec, char *label) 440f71d0e11SHajimu UMEMOTO { 441f71d0e11SHajimu UMEMOTO struct in6_addrpolicy p; 442f71d0e11SHajimu UMEMOTO int s; 443f71d0e11SHajimu UMEMOTO 444f71d0e11SHajimu UMEMOTO memset(&p, 0, sizeof(p)); 445f71d0e11SHajimu UMEMOTO 446f71d0e11SHajimu UMEMOTO if (parse_prefix((const char *)prefix, &p)) 447f71d0e11SHajimu UMEMOTO errx(1, "bad prefix: %s", prefix); 448f71d0e11SHajimu UMEMOTO p.preced = atoi(prec); 449f71d0e11SHajimu UMEMOTO p.label = atoi(label); 450f71d0e11SHajimu UMEMOTO 451f71d0e11SHajimu UMEMOTO if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) 452f71d0e11SHajimu UMEMOTO err(1, "socket(UDP)"); 453f71d0e11SHajimu UMEMOTO if (ioctl(s, SIOCAADDRCTL_POLICY, &p)) 454f71d0e11SHajimu UMEMOTO err(1, "ioctl(SIOCAADDRCTL_POLICY)"); 455f71d0e11SHajimu UMEMOTO 456f71d0e11SHajimu UMEMOTO close(s); 457f71d0e11SHajimu UMEMOTO } 458f71d0e11SHajimu UMEMOTO 459f71d0e11SHajimu UMEMOTO static void 46045442869SEitan Adler delete_policy(char *prefix) 461f71d0e11SHajimu UMEMOTO { 462f71d0e11SHajimu UMEMOTO struct in6_addrpolicy p; 463f71d0e11SHajimu UMEMOTO int s; 464f71d0e11SHajimu UMEMOTO 465f71d0e11SHajimu UMEMOTO memset(&p, 0, sizeof(p)); 466f71d0e11SHajimu UMEMOTO 467f71d0e11SHajimu UMEMOTO if (parse_prefix((const char *)prefix, &p)) 468f71d0e11SHajimu UMEMOTO errx(1, "bad prefix: %s", prefix); 469f71d0e11SHajimu UMEMOTO 470f71d0e11SHajimu UMEMOTO if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) 471f71d0e11SHajimu UMEMOTO err(1, "socket(UDP)"); 472f71d0e11SHajimu UMEMOTO if (ioctl(s, SIOCDADDRCTL_POLICY, &p)) 473f71d0e11SHajimu UMEMOTO err(1, "ioctl(SIOCDADDRCTL_POLICY)"); 474f71d0e11SHajimu UMEMOTO 475f71d0e11SHajimu UMEMOTO close(s); 476f71d0e11SHajimu UMEMOTO } 477f71d0e11SHajimu UMEMOTO 478f71d0e11SHajimu UMEMOTO static void 47945442869SEitan Adler flush_policy(void) 480f71d0e11SHajimu UMEMOTO { 481f71d0e11SHajimu UMEMOTO struct policyqueue *ent; 482f71d0e11SHajimu UMEMOTO int s; 483f71d0e11SHajimu UMEMOTO 484f71d0e11SHajimu UMEMOTO if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) 485f71d0e11SHajimu UMEMOTO err(1, "socket(UDP)"); 486f71d0e11SHajimu UMEMOTO 487f71d0e11SHajimu UMEMOTO for (ent = TAILQ_FIRST(&policyhead); ent; 488f71d0e11SHajimu UMEMOTO ent = TAILQ_NEXT(ent, pc_entry)) { 489f71d0e11SHajimu UMEMOTO if (ioctl(s, SIOCDADDRCTL_POLICY, &ent->pc_policy)) 490f71d0e11SHajimu UMEMOTO warn("ioctl(SIOCDADDRCTL_POLICY)"); 491f71d0e11SHajimu UMEMOTO } 492f71d0e11SHajimu UMEMOTO 493f71d0e11SHajimu UMEMOTO close(s); 494f71d0e11SHajimu UMEMOTO } 495f71d0e11SHajimu UMEMOTO 496f71d0e11SHajimu UMEMOTO static void 49745442869SEitan Adler usage(void) 498f71d0e11SHajimu UMEMOTO { 499*6dcdd79aSZhenlei Huang fprintf(stderr, "usage: ip6addrctl [-j jail] [show]\n"); 500*6dcdd79aSZhenlei Huang fprintf(stderr, " ip6addrctl [-j jail] add " 501f71d0e11SHajimu UMEMOTO "<prefix> <precedence> <label>\n"); 502*6dcdd79aSZhenlei Huang fprintf(stderr, " ip6addrctl [-j jail] delete <prefix>\n"); 503*6dcdd79aSZhenlei Huang fprintf(stderr, " ip6addrctl [-j jail] flush\n"); 504*6dcdd79aSZhenlei Huang fprintf(stderr, " ip6addrctl [-j jail] install <configfile>\n"); 505f71d0e11SHajimu UMEMOTO 506f71d0e11SHajimu UMEMOTO exit(1); 507f71d0e11SHajimu UMEMOTO } 508