1 1.39 msaitoh /* $NetBSD: af_inet6.c,v 1.39 2019/08/16 10:33:17 msaitoh Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /* 4 1.1 thorpej * Copyright (c) 1983, 1993 5 1.1 thorpej * The Regents of the University of California. All rights reserved. 6 1.1 thorpej * 7 1.1 thorpej * Redistribution and use in source and binary forms, with or without 8 1.1 thorpej * modification, are permitted provided that the following conditions 9 1.1 thorpej * are met: 10 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 11 1.1 thorpej * notice, this list of conditions and the following disclaimer. 12 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 14 1.1 thorpej * documentation and/or other materials provided with the distribution. 15 1.1 thorpej * 3. Neither the name of the University nor the names of its contributors 16 1.1 thorpej * may be used to endorse or promote products derived from this software 17 1.1 thorpej * without specific prior written permission. 18 1.1 thorpej * 19 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 thorpej * SUCH DAMAGE. 30 1.1 thorpej */ 31 1.1 thorpej 32 1.1 thorpej #include <sys/cdefs.h> 33 1.1 thorpej #ifndef lint 34 1.39 msaitoh __RCSID("$NetBSD: af_inet6.c,v 1.39 2019/08/16 10:33:17 msaitoh Exp $"); 35 1.1 thorpej #endif /* not lint */ 36 1.1 thorpej 37 1.39 msaitoh #include <sys/param.h> 38 1.39 msaitoh #include <sys/ioctl.h> 39 1.1 thorpej #include <sys/socket.h> 40 1.1 thorpej 41 1.39 msaitoh #include <net/if.h> 42 1.1 thorpej #include <netinet/in.h> 43 1.1 thorpej #include <netinet/in_var.h> 44 1.1 thorpej #include <netinet6/nd6.h> 45 1.1 thorpej 46 1.1 thorpej #include <err.h> 47 1.1 thorpej #include <errno.h> 48 1.1 thorpej #include <ifaddrs.h> 49 1.1 thorpej #include <netdb.h> 50 1.1 thorpej #include <string.h> 51 1.1 thorpej #include <stdlib.h> 52 1.1 thorpej #include <stdio.h> 53 1.5 christos #include <util.h> 54 1.1 thorpej 55 1.8 dyoung #include "env.h" 56 1.22 dyoung #include "extern.h" 57 1.8 dyoung #include "parse.h" 58 1.1 thorpej #include "extern.h" 59 1.13 dyoung #include "af_inetany.h" 60 1.27 pooka #include "prog_ops.h" 61 1.1 thorpej 62 1.22 dyoung static void in6_constructor(void) __attribute__((constructor)); 63 1.37 roy static void in6_alias(struct ifaddrs *, prop_dictionary_t, prop_dictionary_t); 64 1.22 dyoung static void in6_commit_address(prop_dictionary_t, prop_dictionary_t); 65 1.22 dyoung 66 1.22 dyoung static int setia6eui64_impl(prop_dictionary_t, struct in6_aliasreq *); 67 1.22 dyoung static int setia6flags_impl(prop_dictionary_t, struct in6_aliasreq *); 68 1.22 dyoung static int setia6pltime_impl(prop_dictionary_t, struct in6_aliasreq *); 69 1.22 dyoung static int setia6vltime_impl(prop_dictionary_t, struct in6_aliasreq *); 70 1.22 dyoung 71 1.22 dyoung static int setia6lifetime(prop_dictionary_t, int64_t, time_t *, uint32_t *); 72 1.22 dyoung 73 1.22 dyoung static void in6_status(prop_dictionary_t, prop_dictionary_t, bool); 74 1.32 roy static bool in6_addr_tentative(struct ifaddrs *ifa); 75 1.34 roy static bool in6_addr_tentative_or_detached(struct ifaddrs *ifa); 76 1.22 dyoung 77 1.23 dyoung static struct usage_func usage; 78 1.22 dyoung static cmdloop_branch_t branch[2]; 79 1.22 dyoung 80 1.12 dyoung static const struct kwinst ia6flagskw[] = { 81 1.12 dyoung IFKW("anycast", IN6_IFF_ANYCAST) 82 1.12 dyoung , IFKW("deprecated", IN6_IFF_DEPRECATED) 83 1.12 dyoung }; 84 1.12 dyoung 85 1.12 dyoung static struct pinteger parse_pltime = PINTEGER_INITIALIZER(&parse_pltime, 86 1.15 dyoung "pltime", 0, NULL, "pltime", &command_root.pb_parser); 87 1.12 dyoung 88 1.12 dyoung static struct pinteger parse_vltime = PINTEGER_INITIALIZER(&parse_vltime, 89 1.15 dyoung "vltime", 0, NULL, "vltime", &command_root.pb_parser); 90 1.12 dyoung 91 1.12 dyoung static const struct kwinst inet6kw[] = { 92 1.12 dyoung {.k_word = "pltime", .k_nextparser = &parse_pltime.pi_parser} 93 1.12 dyoung , {.k_word = "vltime", .k_nextparser = &parse_vltime.pi_parser} 94 1.14 dyoung , {.k_word = "eui64", .k_key = "eui64", .k_type = KW_T_BOOL, 95 1.15 dyoung .k_bool = true, .k_nextparser = &command_root.pb_parser} 96 1.12 dyoung }; 97 1.12 dyoung 98 1.15 dyoung struct pkw ia6flags = PKW_INITIALIZER(&ia6flags, "ia6flags", NULL, 99 1.12 dyoung "ia6flag", ia6flagskw, __arraycount(ia6flagskw), &command_root.pb_parser); 100 1.12 dyoung struct pkw inet6 = PKW_INITIALIZER(&inet6, "IPv6 keywords", NULL, 101 1.12 dyoung NULL, inet6kw, __arraycount(inet6kw), NULL); 102 1.12 dyoung 103 1.22 dyoung static struct afswtch in6af = { 104 1.22 dyoung .af_name = "inet6", .af_af = AF_INET6, .af_status = in6_status, 105 1.32 roy .af_addr_commit = in6_commit_address, 106 1.34 roy .af_addr_tentative = in6_addr_tentative, 107 1.34 roy .af_addr_tentative_or_detached = in6_addr_tentative_or_detached 108 1.22 dyoung }; 109 1.8 dyoung 110 1.1 thorpej static int 111 1.1 thorpej prefix(void *val, int size) 112 1.1 thorpej { 113 1.1 thorpej u_char *pname = (u_char *)val; 114 1.1 thorpej int byte, bit, plen = 0; 115 1.1 thorpej 116 1.1 thorpej for (byte = 0; byte < size; byte++, plen += 8) 117 1.1 thorpej if (pname[byte] != 0xff) 118 1.1 thorpej break; 119 1.1 thorpej if (byte == size) 120 1.1 thorpej return (plen); 121 1.1 thorpej for (bit = 7; bit != 0; bit--, plen++) 122 1.1 thorpej if (!(pname[byte] & (1 << bit))) 123 1.1 thorpej break; 124 1.1 thorpej for (; bit != 0; bit--) 125 1.1 thorpej if (pname[byte] & (1 << bit)) 126 1.1 thorpej return(0); 127 1.1 thorpej byte++; 128 1.1 thorpej for (; byte < size; byte++) 129 1.1 thorpej if (pname[byte]) 130 1.1 thorpej return(0); 131 1.1 thorpej return (plen); 132 1.1 thorpej } 133 1.1 thorpej 134 1.8 dyoung int 135 1.8 dyoung setia6flags_impl(prop_dictionary_t env, struct in6_aliasreq *ifra) 136 1.1 thorpej { 137 1.10 dyoung int64_t ia6flag; 138 1.1 thorpej 139 1.10 dyoung if (!prop_dictionary_get_int64(env, "ia6flag", &ia6flag)) { 140 1.8 dyoung errno = ENOENT; 141 1.8 dyoung return -1; 142 1.8 dyoung } 143 1.8 dyoung 144 1.8 dyoung if (ia6flag < 0) { 145 1.8 dyoung ia6flag = -ia6flag; 146 1.8 dyoung ifra->ifra_flags &= ~ia6flag; 147 1.1 thorpej } else 148 1.8 dyoung ifra->ifra_flags |= ia6flag; 149 1.8 dyoung return 0; 150 1.8 dyoung } 151 1.8 dyoung 152 1.8 dyoung int 153 1.8 dyoung setia6pltime_impl(prop_dictionary_t env, struct in6_aliasreq *ifra) 154 1.1 thorpej { 155 1.10 dyoung int64_t pltime; 156 1.8 dyoung 157 1.10 dyoung if (!prop_dictionary_get_int64(env, "pltime", &pltime)) { 158 1.8 dyoung errno = ENOENT; 159 1.8 dyoung return -1; 160 1.8 dyoung } 161 1.1 thorpej 162 1.10 dyoung return setia6lifetime(env, pltime, 163 1.8 dyoung &ifra->ifra_lifetime.ia6t_preferred, 164 1.8 dyoung &ifra->ifra_lifetime.ia6t_pltime); 165 1.8 dyoung } 166 1.8 dyoung 167 1.8 dyoung int 168 1.8 dyoung setia6vltime_impl(prop_dictionary_t env, struct in6_aliasreq *ifra) 169 1.1 thorpej { 170 1.10 dyoung int64_t vltime; 171 1.8 dyoung 172 1.10 dyoung if (!prop_dictionary_get_int64(env, "vltime", &vltime)) { 173 1.8 dyoung errno = ENOENT; 174 1.8 dyoung return -1; 175 1.8 dyoung } 176 1.1 thorpej 177 1.10 dyoung return setia6lifetime(env, vltime, 178 1.8 dyoung &ifra->ifra_lifetime.ia6t_expire, 179 1.8 dyoung &ifra->ifra_lifetime.ia6t_vltime); 180 1.8 dyoung } 181 1.8 dyoung 182 1.8 dyoung static int 183 1.8 dyoung setia6lifetime(prop_dictionary_t env, int64_t val, time_t *timep, 184 1.8 dyoung uint32_t *ivalp) 185 1.1 thorpej { 186 1.8 dyoung time_t t; 187 1.8 dyoung int af; 188 1.8 dyoung 189 1.8 dyoung if ((af = getaf(env)) == -1 || af != AF_INET6) { 190 1.8 dyoung errx(EXIT_FAILURE, 191 1.8 dyoung "inet6 address lifetime not allowed for the AF"); 192 1.8 dyoung } 193 1.1 thorpej 194 1.1 thorpej t = time(NULL); 195 1.8 dyoung *timep = t + val; 196 1.8 dyoung *ivalp = val; 197 1.8 dyoung return 0; 198 1.1 thorpej } 199 1.1 thorpej 200 1.8 dyoung int 201 1.8 dyoung setia6eui64_impl(prop_dictionary_t env, struct in6_aliasreq *ifra) 202 1.1 thorpej { 203 1.14 dyoung char buf[2][80]; 204 1.1 thorpej struct ifaddrs *ifap, *ifa; 205 1.1 thorpej const struct sockaddr_in6 *sin6 = NULL; 206 1.1 thorpej const struct in6_addr *lladdr = NULL; 207 1.1 thorpej struct in6_addr *in6; 208 1.8 dyoung const char *ifname; 209 1.14 dyoung bool doit = false; 210 1.8 dyoung int af; 211 1.1 thorpej 212 1.14 dyoung if (!prop_dictionary_get_bool(env, "eui64", &doit) || !doit) { 213 1.14 dyoung errno = ENOENT; 214 1.14 dyoung return -1; 215 1.14 dyoung } 216 1.14 dyoung 217 1.8 dyoung if ((ifname = getifname(env)) == NULL) 218 1.8 dyoung return -1; 219 1.8 dyoung 220 1.8 dyoung af = getaf(env); 221 1.8 dyoung if (af != AF_INET6) { 222 1.8 dyoung errx(EXIT_FAILURE, 223 1.8 dyoung "eui64 address modifier not allowed for the AF"); 224 1.8 dyoung } 225 1.39 msaitoh in6 = &ifra->ifra_addr.sin6_addr; 226 1.14 dyoung if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) { 227 1.14 dyoung union { 228 1.14 dyoung struct sockaddr_in6 sin6; 229 1.14 dyoung struct sockaddr sa; 230 1.14 dyoung } any = {.sin6 = {.sin6_family = AF_INET6}}; 231 1.14 dyoung memcpy(&any.sin6.sin6_addr, &in6addr_any, 232 1.14 dyoung sizeof(any.sin6.sin6_addr)); 233 1.14 dyoung (void)sockaddr_snprintf(buf[0], sizeof(buf[0]), "%a%%S", 234 1.14 dyoung &any.sa); 235 1.14 dyoung (void)sockaddr_snprintf(buf[1], sizeof(buf[1]), "%a%%S", 236 1.14 dyoung (const struct sockaddr *)&ifra->ifra_addr); 237 1.14 dyoung errx(EXIT_FAILURE, "interface index is already filled, %s | %s", 238 1.14 dyoung buf[0], buf[1]); 239 1.14 dyoung } 240 1.1 thorpej if (getifaddrs(&ifap) != 0) 241 1.1 thorpej err(EXIT_FAILURE, "getifaddrs"); 242 1.1 thorpej for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 243 1.1 thorpej if (ifa->ifa_addr->sa_family == AF_INET6 && 244 1.8 dyoung strcmp(ifa->ifa_name, ifname) == 0) { 245 1.1 thorpej sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; 246 1.1 thorpej if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 247 1.1 thorpej lladdr = &sin6->sin6_addr; 248 1.1 thorpej break; 249 1.1 thorpej } 250 1.1 thorpej } 251 1.1 thorpej } 252 1.26 dyoung if (lladdr == NULL) 253 1.39 msaitoh errx(EXIT_FAILURE, "could not determine link local address"); 254 1.1 thorpej 255 1.39 msaitoh memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8); 256 1.1 thorpej 257 1.1 thorpej freeifaddrs(ifap); 258 1.8 dyoung return 0; 259 1.8 dyoung } 260 1.8 dyoung 261 1.1 thorpej /* XXX not really an alias */ 262 1.1 thorpej void 263 1.37 roy in6_alias(struct ifaddrs *ifa, prop_dictionary_t env, prop_dictionary_t oenv) 264 1.1 thorpej { 265 1.1 thorpej struct sockaddr_in6 *sin6; 266 1.1 thorpej char hbuf[NI_MAXHOST]; 267 1.1 thorpej u_int32_t scopeid; 268 1.24 dyoung const int niflag = Nflag ? 0 : NI_NUMERICHOST; 269 1.37 roy char fbuf[1024]; 270 1.1 thorpej 271 1.37 roy sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 272 1.29 christos inet6_getscopeid(sin6, INET6_IS_ADDR_LINKLOCAL); 273 1.1 thorpej scopeid = sin6->sin6_scope_id; 274 1.18 dyoung if (getnameinfo((const struct sockaddr *)sin6, sin6->sin6_len, 275 1.1 thorpej hbuf, sizeof(hbuf), NULL, 0, niflag)) 276 1.1 thorpej strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */ 277 1.1 thorpej printf("\tinet6 %s", hbuf); 278 1.37 roy inet6_putscopeid(sin6, INET6_IS_ADDR_LINKLOCAL); 279 1.1 thorpej 280 1.38 roy sin6 = (struct sockaddr_in6 *)ifa->ifa_netmask; 281 1.38 roy printf("/%d", prefix(&sin6->sin6_addr, sizeof(struct in6_addr))); 282 1.38 roy 283 1.37 roy if (ifa->ifa_flags & IFF_POINTOPOINT) { 284 1.37 roy sin6 = (struct sockaddr_in6 *)ifa->ifa_dstaddr; 285 1.29 christos inet6_getscopeid(sin6, INET6_IS_ADDR_LINKLOCAL); 286 1.1 thorpej hbuf[0] = '\0'; 287 1.1 thorpej if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 288 1.1 thorpej hbuf, sizeof(hbuf), NULL, 0, niflag)) 289 1.1 thorpej strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */ 290 1.1 thorpej printf(" -> %s", hbuf); 291 1.1 thorpej } 292 1.1 thorpej 293 1.37 roy (void)snprintb(fbuf, sizeof(fbuf), IN6_IFFBITS, ifa->ifa_addrflags); 294 1.37 roy printf(" flags %s", fbuf); 295 1.1 thorpej 296 1.1 thorpej if (scopeid) 297 1.1 thorpej printf(" scopeid 0x%x", scopeid); 298 1.1 thorpej 299 1.22 dyoung if (get_flag('L')) { 300 1.37 roy int s; 301 1.37 roy struct in6_ifreq ifr6; 302 1.1 thorpej struct in6_addrlifetime *lifetime; 303 1.37 roy 304 1.37 roy if ((s = getsock(AF_INET6)) == -1) { 305 1.37 roy if (errno == EAFNOSUPPORT) 306 1.37 roy return; 307 1.37 roy err(EXIT_FAILURE, "socket"); 308 1.37 roy } 309 1.37 roy 310 1.37 roy memset(&ifr6, 0, sizeof(ifr6)); 311 1.37 roy estrlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name)); 312 1.37 roy memcpy(&ifr6.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); 313 1.1 thorpej lifetime = &ifr6.ifr_ifru.ifru_lifetime; 314 1.27 pooka if (prog_ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) == -1) { 315 1.1 thorpej if (errno != EADDRNOTAVAIL) 316 1.1 thorpej warn("SIOCGIFALIFETIME_IN6"); 317 1.1 thorpej } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) { 318 1.1 thorpej time_t t = time(NULL); 319 1.1 thorpej printf(" pltime "); 320 1.1 thorpej if (lifetime->ia6t_preferred) { 321 1.19 dyoung printf("%lu", 322 1.19 dyoung (unsigned long)(lifetime->ia6t_preferred - 323 1.19 dyoung MIN(t, lifetime->ia6t_preferred))); 324 1.1 thorpej } else 325 1.1 thorpej printf("infty"); 326 1.1 thorpej 327 1.1 thorpej printf(" vltime "); 328 1.1 thorpej if (lifetime->ia6t_expire) { 329 1.19 dyoung printf("%lu", 330 1.19 dyoung (unsigned long)(lifetime->ia6t_expire - 331 1.19 dyoung MIN(t, lifetime->ia6t_expire))); 332 1.1 thorpej } else 333 1.1 thorpej printf("infty"); 334 1.1 thorpej } 335 1.1 thorpej } 336 1.1 thorpej } 337 1.1 thorpej 338 1.22 dyoung static void 339 1.9 dyoung in6_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force) 340 1.1 thorpej { 341 1.1 thorpej struct ifaddrs *ifap, *ifa; 342 1.8 dyoung const char *ifname; 343 1.25 dyoung bool printprefs = false; 344 1.8 dyoung 345 1.8 dyoung if ((ifname = getifname(env)) == NULL) 346 1.8 dyoung err(EXIT_FAILURE, "%s: getifname", __func__); 347 1.1 thorpej 348 1.1 thorpej if (getifaddrs(&ifap) != 0) 349 1.1 thorpej err(EXIT_FAILURE, "getifaddrs"); 350 1.25 dyoung printprefs = ifa_any_preferences(ifname, ifap, AF_INET6); 351 1.1 thorpej for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 352 1.8 dyoung if (strcmp(ifname, ifa->ifa_name) != 0) 353 1.1 thorpej continue; 354 1.1 thorpej if (ifa->ifa_addr->sa_family != AF_INET6) 355 1.1 thorpej continue; 356 1.37 roy in6_alias(ifa, env, oenv); 357 1.25 dyoung if (printprefs) 358 1.25 dyoung ifa_print_preference(ifa->ifa_name, ifa->ifa_addr); 359 1.25 dyoung printf("\n"); 360 1.1 thorpej } 361 1.1 thorpej freeifaddrs(ifap); 362 1.1 thorpej } 363 1.1 thorpej 364 1.13 dyoung static int 365 1.22 dyoung in6_pre_aifaddr(prop_dictionary_t env, const struct afparam *param) 366 1.13 dyoung { 367 1.14 dyoung struct in6_aliasreq *ifra = param->req.buf; 368 1.13 dyoung 369 1.13 dyoung setia6eui64_impl(env, ifra); 370 1.13 dyoung setia6vltime_impl(env, ifra); 371 1.13 dyoung setia6pltime_impl(env, ifra); 372 1.13 dyoung setia6flags_impl(env, ifra); 373 1.29 christos inet6_putscopeid(&ifra->ifra_addr, INET6_IS_ADDR_LINKLOCAL); 374 1.29 christos inet6_putscopeid(&ifra->ifra_dstaddr, INET6_IS_ADDR_LINKLOCAL); 375 1.13 dyoung 376 1.13 dyoung return 0; 377 1.13 dyoung } 378 1.13 dyoung 379 1.22 dyoung static void 380 1.13 dyoung in6_commit_address(prop_dictionary_t env, prop_dictionary_t oenv) 381 1.13 dyoung { 382 1.14 dyoung struct in6_ifreq in6_ifr = { 383 1.13 dyoung .ifr_addr = { 384 1.13 dyoung .sin6_family = AF_INET6, 385 1.20 dyoung .sin6_len = sizeof(in6_ifr.ifr_addr), 386 1.13 dyoung .sin6_addr = { 387 1.13 dyoung .s6_addr = 388 1.13 dyoung {0xff, 0xff, 0xff, 0xff, 389 1.13 dyoung 0xff, 0xff, 0xff, 0xff} 390 1.13 dyoung } 391 1.13 dyoung } 392 1.13 dyoung }; 393 1.13 dyoung static struct sockaddr_in6 in6_defmask = { 394 1.20 dyoung .sin6_family = AF_INET6, 395 1.20 dyoung .sin6_len = sizeof(in6_defmask), 396 1.13 dyoung .sin6_addr = { 397 1.13 dyoung .s6_addr = {0xff, 0xff, 0xff, 0xff, 398 1.13 dyoung 0xff, 0xff, 0xff, 0xff} 399 1.13 dyoung } 400 1.13 dyoung }; 401 1.13 dyoung 402 1.14 dyoung struct in6_aliasreq in6_ifra = { 403 1.13 dyoung .ifra_prefixmask = { 404 1.20 dyoung .sin6_family = AF_INET6, 405 1.20 dyoung .sin6_len = sizeof(in6_ifra.ifra_prefixmask), 406 1.13 dyoung .sin6_addr = { 407 1.13 dyoung .s6_addr = 408 1.13 dyoung {0xff, 0xff, 0xff, 0xff, 409 1.13 dyoung 0xff, 0xff, 0xff, 0xff}}}, 410 1.13 dyoung .ifra_lifetime = { 411 1.13 dyoung .ia6t_pltime = ND6_INFINITE_LIFETIME 412 1.13 dyoung , .ia6t_vltime = ND6_INFINITE_LIFETIME 413 1.13 dyoung } 414 1.13 dyoung }; 415 1.13 dyoung struct afparam in6param = { 416 1.13 dyoung .req = BUFPARAM(in6_ifra) 417 1.13 dyoung , .dgreq = BUFPARAM(in6_ifr) 418 1.13 dyoung , .name = { 419 1.13 dyoung {.buf = in6_ifr.ifr_name, 420 1.13 dyoung .buflen = sizeof(in6_ifr.ifr_name)}, 421 1.13 dyoung {.buf = in6_ifra.ifra_name, 422 1.13 dyoung .buflen = sizeof(in6_ifra.ifra_name)} 423 1.13 dyoung } 424 1.13 dyoung , .dgaddr = BUFPARAM(in6_ifr.ifr_addr) 425 1.13 dyoung , .addr = BUFPARAM(in6_ifra.ifra_addr) 426 1.13 dyoung , .dst = BUFPARAM(in6_ifra.ifra_dstaddr) 427 1.13 dyoung , .brd = BUFPARAM(in6_ifra.ifra_broadaddr) 428 1.13 dyoung , .mask = BUFPARAM(in6_ifra.ifra_prefixmask) 429 1.13 dyoung , .aifaddr = IFADDR_PARAM(SIOCAIFADDR_IN6) 430 1.13 dyoung , .difaddr = IFADDR_PARAM(SIOCDIFADDR_IN6) 431 1.13 dyoung , .gifaddr = IFADDR_PARAM(SIOCGIFADDR_IN6) 432 1.13 dyoung , .defmask = BUFPARAM(in6_defmask) 433 1.13 dyoung , .pre_aifaddr = in6_pre_aifaddr 434 1.13 dyoung }; 435 1.13 dyoung commit_address(env, oenv, &in6param); 436 1.13 dyoung } 437 1.22 dyoung 438 1.32 roy static bool 439 1.34 roy in6_addr_flags(struct ifaddrs *ifa, int flags) 440 1.32 roy { 441 1.32 roy int s; 442 1.32 roy struct in6_ifreq ifr; 443 1.32 roy 444 1.32 roy if ((s = getsock(AF_INET6)) == -1) 445 1.32 roy err(EXIT_FAILURE, "%s: getsock", __func__); 446 1.32 roy memset(&ifr, 0, sizeof(ifr)); 447 1.35 riastrad estrlcpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name)); 448 1.32 roy ifr.ifr_addr = *(struct sockaddr_in6 *)ifa->ifa_addr; 449 1.33 roy if (prog_ioctl(s, SIOCGIFAFLAG_IN6, &ifr) == -1) 450 1.32 roy err(EXIT_FAILURE, "SIOCGIFAFLAG_IN6"); 451 1.34 roy return ifr.ifr_ifru.ifru_flags6 & flags ? true : false; 452 1.34 roy } 453 1.34 roy 454 1.34 roy static bool 455 1.34 roy in6_addr_tentative(struct ifaddrs *ifa) 456 1.34 roy { 457 1.34 roy 458 1.34 roy return in6_addr_flags(ifa, IN6_IFF_TENTATIVE); 459 1.34 roy } 460 1.34 roy 461 1.34 roy static bool 462 1.34 roy in6_addr_tentative_or_detached(struct ifaddrs *ifa) 463 1.34 roy { 464 1.34 roy 465 1.34 roy return in6_addr_flags(ifa, IN6_IFF_TENTATIVE | IN6_IFF_DETACHED); 466 1.32 roy } 467 1.32 roy 468 1.22 dyoung static void 469 1.23 dyoung in6_usage(prop_dictionary_t env) 470 1.23 dyoung { 471 1.23 dyoung fprintf(stderr, 472 1.23 dyoung "\t[ anycast | -anycast ] [ deprecated | -deprecated ]\n" 473 1.30 roy "\t[ pltime n ] [ vltime n ] " 474 1.23 dyoung "[ eui64 ]\n"); 475 1.23 dyoung } 476 1.23 dyoung 477 1.23 dyoung static void 478 1.22 dyoung in6_constructor(void) 479 1.22 dyoung { 480 1.22 dyoung if (register_flag('L') != 0) 481 1.22 dyoung err(EXIT_FAILURE, __func__); 482 1.22 dyoung register_family(&in6af); 483 1.23 dyoung usage_func_init(&usage, in6_usage); 484 1.23 dyoung register_usage(&usage); 485 1.22 dyoung cmdloop_branch_init(&branch[0], &ia6flags.pk_parser); 486 1.22 dyoung cmdloop_branch_init(&branch[1], &inet6.pk_parser); 487 1.22 dyoung register_cmdloop_branch(&branch[0]); 488 1.22 dyoung register_cmdloop_branch(&branch[1]); 489 1.22 dyoung } 490