1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include "defs.h" 29 #include "tables.h" 30 31 #include <time.h> 32 #include <inet/ip6.h> 33 34 struct phyint *phyints = NULL; 35 36 static void phyint_print(struct phyint *pi); 37 static void phyint_insert(struct phyint *pi); 38 39 static boolean_t tmptoken_isvalid(struct in6_addr *token); 40 41 static void prefix_print(struct prefix *pr); 42 static void prefix_insert(struct phyint *pi, struct prefix *pr); 43 static char *prefix_print_state(int state, char *buf, int buflen); 44 static void prefix_set(struct in6_addr *prefix, struct in6_addr addr, 45 int bits); 46 47 static void adv_prefix_print(struct adv_prefix *adv_pr); 48 static void adv_prefix_insert(struct phyint *pi, struct adv_prefix *adv_pr); 49 static void adv_prefix_delete(struct adv_prefix *adv_pr); 50 51 static void router_print(struct router *dr); 52 static void router_insert(struct phyint *pi, struct router *dr); 53 static void router_delete(struct router *dr); 54 static void router_add_k(struct router *dr); 55 static void router_delete_k(struct router *dr); 56 57 static int rtmseq; /* rtm_seq sequence number */ 58 59 /* 1 week in ms */ 60 #define NDP_PREFIX_DEFAULT_LIFETIME (7*24*60*60*1000) 61 struct phyint * 62 phyint_lookup(char *name) 63 { 64 struct phyint *pi; 65 66 if (debug & D_PHYINT) 67 logmsg(LOG_DEBUG, "phyint_lookup(%s)\n", name); 68 69 for (pi = phyints; pi != NULL; pi = pi->pi_next) { 70 if (strcmp(pi->pi_name, name) == 0) 71 break; 72 } 73 return (pi); 74 } 75 76 struct phyint * 77 phyint_lookup_on_index(uint_t ifindex) 78 { 79 struct phyint *pi; 80 81 if (debug & D_PHYINT) 82 logmsg(LOG_DEBUG, "phyint_lookup_on_index(%d)\n", ifindex); 83 84 for (pi = phyints; pi != NULL; pi = pi->pi_next) { 85 if (pi->pi_index == ifindex) 86 break; 87 } 88 return (pi); 89 } 90 91 struct phyint * 92 phyint_create(char *name) 93 { 94 struct phyint *pi; 95 int i; 96 97 if (debug & D_PHYINT) 98 logmsg(LOG_DEBUG, "phyint_create(%s)\n", name); 99 100 pi = (struct phyint *)calloc(sizeof (struct phyint), 1); 101 if (pi == NULL) { 102 logmsg(LOG_ERR, "phyint_create: out of memory\n"); 103 return (NULL); 104 } 105 (void) strncpy(pi->pi_name, name, sizeof (pi->pi_name)); 106 pi->pi_name[sizeof (pi->pi_name) - 1] = '\0'; 107 108 /* 109 * Copy the defaults from the defaults array. 110 * Do not copy the cf_notdefault fields since these have not 111 * been explicitly set for the phyint. 112 */ 113 for (i = 0; i < I_IFSIZE; i++) 114 pi->pi_config[i].cf_value = ifdefaults[i].cf_value; 115 116 /* 117 * TmpDesyncFactor is used to desynchronize temporary token 118 * generation among systems; the actual preferred lifetime value 119 * of a temporary address will be (TmpPreferredLifetime - 120 * TmpDesyncFactor). It's a random value, with a user-configurable 121 * maximum value. The value is constant throughout the lifetime 122 * of the in.ndpd process, but can change if the daemon is restarted, 123 * per RFC3041. 124 */ 125 if (pi->pi_TmpMaxDesyncFactor != 0) { 126 time_t seed = time(NULL); 127 srand((uint_t)seed); 128 pi->pi_TmpDesyncFactor = rand() % pi->pi_TmpMaxDesyncFactor; 129 /* we actually want [1,max], not [0,(max-1)] */ 130 pi->pi_TmpDesyncFactor++; 131 } 132 pi->pi_TmpRegenCountdown = TIMER_INFINITY; 133 134 pi->pi_sock = -1; 135 if (phyint_init_from_k(pi) == -1) { 136 if (pi->pi_group_name != NULL) 137 free(pi->pi_group_name); 138 free(pi); 139 return (NULL); 140 } 141 phyint_insert(pi); 142 if (pi->pi_sock != -1) { 143 if (poll_add(pi->pi_sock) == -1) { 144 phyint_delete(pi); 145 return (NULL); 146 } 147 } 148 return (pi); 149 } 150 151 /* Insert in linked list */ 152 static void 153 phyint_insert(struct phyint *pi) 154 { 155 /* Insert in list */ 156 pi->pi_next = phyints; 157 pi->pi_prev = NULL; 158 if (phyints) 159 phyints->pi_prev = pi; 160 phyints = pi; 161 } 162 163 /* 164 * Initialize both the phyint data structure and the pi_sock for 165 * sending and receving on the interface. 166 * Extract information from the kernel (if present) and set pi_kernel_state. 167 */ 168 int 169 phyint_init_from_k(struct phyint *pi) 170 { 171 struct ipv6_mreq v6mcastr; 172 struct lifreq lifr; 173 int fd; 174 boolean_t newsock; 175 uint_t ttl; 176 struct sockaddr_in6 *sin6; 177 178 if (debug & D_PHYINT) 179 logmsg(LOG_DEBUG, "phyint_init_from_k(%s)\n", pi->pi_name); 180 181 start_over: 182 183 if (pi->pi_sock < 0) { 184 pi->pi_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 185 if (pi->pi_sock < 0) { 186 logperror_pi(pi, "phyint_init_from_k: socket"); 187 return (-1); 188 } 189 newsock = _B_TRUE; 190 } else { 191 newsock = _B_FALSE; 192 } 193 fd = pi->pi_sock; 194 195 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 196 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 197 if (ioctl(fd, SIOCGLIFINDEX, (char *)&lifr) < 0) { 198 if (errno == ENXIO) { 199 if (newsock) { 200 (void) close(pi->pi_sock); 201 pi->pi_sock = -1; 202 } 203 if (debug & D_PHYINT) { 204 logmsg(LOG_DEBUG, "phyint_init_from_k(%s): " 205 "not exist\n", pi->pi_name); 206 } 207 return (0); 208 } 209 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFINDEX"); 210 goto error; 211 } 212 213 if (!newsock && (pi->pi_index != lifr.lifr_index)) { 214 /* 215 * Interface has been re-plumbed, lets open a new socket. 216 * This situation can occur if plumb/unplumb are happening 217 * quite frequently. 218 */ 219 220 phyint_cleanup(pi); 221 goto start_over; 222 } 223 224 pi->pi_index = lifr.lifr_index; 225 226 if (ioctl(fd, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 227 logperror_pi(pi, "phyint_init_from_k: ioctl (get flags)"); 228 goto error; 229 } 230 pi->pi_flags = lifr.lifr_flags; 231 232 /* 233 * If the link local interface is not up yet or it's IFF_UP 234 * and the flag is set to IFF_NOLOCAL as Duplicate Address 235 * Detection is in progress. 236 * IFF_NOLOCAL is "normal" on other prefixes. 237 */ 238 239 if (!(pi->pi_flags & IFF_UP) || (pi->pi_flags & IFF_NOLOCAL)) { 240 if (newsock) { 241 (void) close(pi->pi_sock); 242 pi->pi_sock = -1; 243 } 244 if (debug & D_PHYINT) { 245 logmsg(LOG_DEBUG, "phyint_init_from_k(%s): " 246 "not IFF_UP\n", pi->pi_name); 247 } 248 return (0); 249 } 250 pi->pi_kernel_state |= PI_PRESENT; 251 252 bzero(lifr.lifr_groupname, sizeof (lifr.lifr_groupname)); 253 if (ioctl(fd, SIOCGLIFGROUPNAME, (caddr_t)&lifr) < 0) { 254 logperror_pi(pi, "phyint_init_from_k: ioctl (get group name)"); 255 goto error; 256 } 257 258 if (lifr.lifr_groupname != NULL && strlen(lifr.lifr_groupname) != 0) { 259 if (pi->pi_group_name == NULL) { 260 pi->pi_group_name = malloc( 261 sizeof (lifr.lifr_groupname)); 262 if (pi->pi_group_name == NULL) { 263 logperror_pi(pi, "phyint_init_from_k:" 264 " malloc(group name)"); 265 goto error; 266 } 267 } 268 /* 269 * Size of the group name can only be LIFNAMESZ -1 characters 270 * which is ensured by kernel. Thus, we don't need strncpy. 271 */ 272 (void) strncpy(pi->pi_group_name, lifr.lifr_groupname, 273 sizeof (lifr.lifr_name)); 274 pi->pi_group_name[sizeof (pi->pi_group_name) - 1] = '\0'; 275 } else if (pi->pi_group_name != NULL) { 276 free(pi->pi_group_name); 277 pi->pi_group_name = NULL; 278 } 279 280 if (ioctl(fd, SIOCGLIFMTU, (caddr_t)&lifr) < 0) { 281 logperror_pi(pi, "phyint_init_from_k: ioctl (get mtu)"); 282 goto error; 283 } 284 pi->pi_mtu = lifr.lifr_mtu; 285 286 if (ioctl(fd, SIOCGLIFADDR, (char *)&lifr) < 0) { 287 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFADDR"); 288 goto error; 289 } 290 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 291 pi->pi_ifaddr = sin6->sin6_addr; 292 293 if (ioctl(fd, SIOCGLIFTOKEN, (char *)&lifr) < 0) { 294 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFTOKEN"); 295 goto error; 296 } 297 /* Ignore interface if the token is all zeros */ 298 sin6 = (struct sockaddr_in6 *)&lifr.lifr_token; 299 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 300 logmsg(LOG_ERR, "ignoring interface %s: zero token\n", 301 pi->pi_name); 302 goto error; 303 } 304 pi->pi_token = sin6->sin6_addr; 305 pi->pi_token_length = lifr.lifr_addrlen; 306 307 /* 308 * Guess a remote token for POINTOPOINT by looking at 309 * the link-local destination address. 310 */ 311 if (pi->pi_flags & IFF_POINTOPOINT) { 312 if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifr) < 0) { 313 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFDSTADDR"); 314 goto error; 315 } 316 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 317 if (sin6->sin6_family != AF_INET6 || 318 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 319 !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 320 pi->pi_dst_token = in6addr_any; 321 } else { 322 pi->pi_dst_token = sin6->sin6_addr; 323 /* Clear link-local prefix (first 10 bits) */ 324 pi->pi_dst_token.s6_addr[0] = 0; 325 pi->pi_dst_token.s6_addr[1] &= 0x3f; 326 } 327 } else { 328 pi->pi_dst_token = in6addr_any; 329 } 330 331 /* Get link-layer address */ 332 if (!(pi->pi_flags & IFF_MULTICAST) || 333 (pi->pi_flags & IFF_POINTOPOINT)) { 334 pi->pi_hdw_addr_len = 0; 335 } else { 336 sin6 = (struct sockaddr_in6 *)&lifr.lifr_nd.lnr_addr; 337 bzero(sin6, sizeof (struct sockaddr_in6)); 338 sin6->sin6_family = AF_INET6; 339 sin6->sin6_addr = pi->pi_ifaddr; 340 341 if (ioctl(fd, SIOCLIFGETND, (char *)&lifr) < 0) { 342 logperror_pi(pi, "phyint_init_from_k: SIOCLIFGETND"); 343 goto error; 344 } 345 346 pi->pi_hdw_addr_len = lifr.lifr_nd.lnr_hdw_len; 347 348 if (lifr.lifr_nd.lnr_hdw_len != 0) { 349 bcopy((char *)lifr.lifr_nd.lnr_hdw_addr, 350 (char *)pi->pi_hdw_addr, 351 lifr.lifr_nd.lnr_hdw_len); 352 } 353 } 354 355 if (newsock) { 356 icmp6_filter_t filter; 357 int on = 1; 358 359 /* Set default values */ 360 pi->pi_LinkMTU = pi->pi_mtu; 361 pi->pi_CurHopLimit = 0; 362 pi->pi_BaseReachableTime = ND_REACHABLE_TIME; 363 phyint_reach_random(pi, _B_FALSE); 364 pi->pi_RetransTimer = ND_RETRANS_TIMER; 365 366 /* Setup socket for transmission and reception */ 367 if (setsockopt(fd, IPPROTO_IPV6, 368 IPV6_BOUND_IF, (char *)&pi->pi_index, 369 sizeof (pi->pi_index)) < 0) { 370 logperror_pi(pi, "phyint_init_from_k: setsockopt " 371 "IPV6_BOUND_IF"); 372 goto error; 373 } 374 375 ttl = IPV6_MAX_HOPS; 376 if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 377 (char *)&ttl, sizeof (ttl)) < 0) { 378 logperror_pi(pi, "phyint_init_from_k: setsockopt " 379 "IPV6_UNICAST_HOPS"); 380 goto error; 381 } 382 383 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 384 (char *)&ttl, sizeof (ttl)) < 0) { 385 logperror_pi(pi, "phyint_init_from_k: setsockopt " 386 "IPV6_MULTICAST_HOPS"); 387 goto error; 388 } 389 390 v6mcastr.ipv6mr_multiaddr = all_nodes_mcast; 391 v6mcastr.ipv6mr_interface = pi->pi_index; 392 if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, 393 (char *)&v6mcastr, sizeof (v6mcastr)) < 0) { 394 logperror_pi(pi, "phyint_init_from_k: " 395 "setsockopt IPV6_JOIN_GROUP"); 396 goto error; 397 } 398 pi->pi_state |= PI_JOINED_ALLNODES; 399 pi->pi_kernel_state |= PI_JOINED_ALLNODES; 400 401 /* 402 * Filter out so that we only receive router advertisements and 403 * router solicitations. 404 */ 405 ICMP6_FILTER_SETBLOCKALL(&filter); 406 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); 407 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter); 408 409 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, 410 (char *)&filter, sizeof (filter)) < 0) { 411 logperror_pi(pi, "phyint_init_from_k: setsockopt " 412 "ICMP6_FILTER"); 413 goto error; 414 } 415 416 /* Enable receipt of ancillary data */ 417 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, 418 (char *)&on, sizeof (on)) < 0) { 419 logperror_pi(pi, "phyint_init_from_k: setsockopt " 420 "IPV6_RECVHOPLIMIT"); 421 goto error; 422 } 423 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVRTHDR, 424 (char *)&on, sizeof (on)) < 0) { 425 logperror_pi(pi, "phyint_init_from_k: setsockopt " 426 "IPV6_RECVRTHDR"); 427 goto error; 428 } 429 } 430 431 if (pi->pi_AdvSendAdvertisements && 432 !(pi->pi_kernel_state & PI_JOINED_ALLROUTERS)) { 433 v6mcastr.ipv6mr_multiaddr = all_routers_mcast; 434 v6mcastr.ipv6mr_interface = pi->pi_index; 435 if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, 436 (char *)&v6mcastr, sizeof (v6mcastr)) < 0) { 437 logperror_pi(pi, "phyint_init_from_k: setsockopt " 438 "IPV6_JOIN_GROUP"); 439 goto error; 440 } 441 pi->pi_state |= PI_JOINED_ALLROUTERS; 442 pi->pi_kernel_state |= PI_JOINED_ALLROUTERS; 443 } 444 /* 445 * If not already set, set the IFF_ROUTER interface flag based on 446 * AdvSendAdvertisements. Note that this will also enable IPv6 447 * forwarding on the interface. We don't clear IFF_ROUTER if we're 448 * not advertising on an interface, because we could still be 449 * forwarding on those interfaces. 450 */ 451 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 452 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 453 if (ioctl(fd, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 454 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFFLAGS"); 455 goto error; 456 } 457 if (!(lifr.lifr_flags & IFF_ROUTER) && pi->pi_AdvSendAdvertisements) { 458 lifr.lifr_flags |= IFF_ROUTER; 459 460 if (ioctl(fd, SIOCSLIFFLAGS, (char *)&lifr) < 0) { 461 logperror_pi(pi, "phyint_init_from_k: SIOCSLIFFLAGS"); 462 goto error; 463 } 464 pi->pi_flags = lifr.lifr_flags; 465 } 466 467 /* Set linkinfo parameters */ 468 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 469 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 470 lifr.lifr_ifinfo.lir_maxhops = pi->pi_CurHopLimit; 471 lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime; 472 lifr.lifr_ifinfo.lir_reachretrans = pi->pi_RetransTimer; 473 /* Setting maxmtu to 0 means that we're leaving the MTU alone */ 474 lifr.lifr_ifinfo.lir_maxmtu = 0; 475 if (ioctl(fd, SIOCSLIFLNKINFO, (char *)&lifr) < 0) { 476 logperror_pi(pi, "phyint_init_from_k: SIOCSLIFLNKINFO"); 477 goto error; 478 } 479 if (debug & D_PHYINT) { 480 logmsg(LOG_DEBUG, "phyint_init_from_k(%s): done\n", 481 pi->pi_name); 482 } 483 return (0); 484 485 error: 486 /* Pretend the interface does not exist in the kernel */ 487 pi->pi_kernel_state &= ~PI_PRESENT; 488 if (newsock) { 489 (void) close(pi->pi_sock); 490 pi->pi_sock = -1; 491 } 492 return (-1); 493 } 494 495 /* 496 * Delete (unlink and free). 497 * Handles delete of things that have not yet been inserted in the list. 498 */ 499 void 500 phyint_delete(struct phyint *pi) 501 { 502 if (debug & D_PHYINT) 503 logmsg(LOG_DEBUG, "phyint_delete(%s)\n", pi->pi_name); 504 505 while (pi->pi_router_list) 506 router_delete(pi->pi_router_list); 507 while (pi->pi_prefix_list) 508 prefix_delete(pi->pi_prefix_list); 509 while (pi->pi_adv_prefix_list) 510 adv_prefix_delete(pi->pi_adv_prefix_list); 511 512 if (pi->pi_sock != -1) { 513 (void) poll_remove(pi->pi_sock); 514 if (close(pi->pi_sock) < 0) { 515 logperror_pi(pi, "phyint_delete: close"); 516 } 517 pi->pi_sock = -1; 518 } 519 520 if (pi->pi_prev == NULL) { 521 if (phyints == pi) 522 phyints = pi->pi_next; 523 } else { 524 pi->pi_prev->pi_next = pi->pi_next; 525 } 526 if (pi->pi_next != NULL) 527 pi->pi_next->pi_prev = pi->pi_prev; 528 pi->pi_next = pi->pi_prev = NULL; 529 if (pi->pi_group_name != NULL) 530 free(pi->pi_group_name); 531 free(pi); 532 } 533 534 /* 535 * Called with the number of millseconds elapsed since the last call. 536 * Determines if any timeout event has occurred and 537 * returns the number of milliseconds until the next timeout event 538 * for the phyint iself (excluding prefixes and routers). 539 * Returns TIMER_INFINITY for "never". 540 */ 541 uint_t 542 phyint_timer(struct phyint *pi, uint_t elapsed) 543 { 544 uint_t next = TIMER_INFINITY; 545 546 if (pi->pi_AdvSendAdvertisements) { 547 if (pi->pi_adv_state != NO_ADV) { 548 int old_state = pi->pi_adv_state; 549 550 if (debug & (D_STATE|D_PHYINT)) { 551 logmsg(LOG_DEBUG, "phyint_timer ADV(%s) " 552 "state %d\n", pi->pi_name, (int)old_state); 553 } 554 next = advertise_event(pi, ADV_TIMER, elapsed); 555 if (debug & D_STATE) { 556 logmsg(LOG_DEBUG, "phyint_timer ADV(%s) " 557 "state %d -> %d\n", 558 pi->pi_name, (int)old_state, 559 (int)pi->pi_adv_state); 560 } 561 } 562 } else { 563 if (pi->pi_sol_state != NO_SOLICIT) { 564 int old_state = pi->pi_sol_state; 565 566 if (debug & (D_STATE|D_PHYINT)) { 567 logmsg(LOG_DEBUG, "phyint_timer SOL(%s) " 568 "state %d\n", pi->pi_name, (int)old_state); 569 } 570 next = solicit_event(pi, SOL_TIMER, elapsed); 571 if (debug & D_STATE) { 572 logmsg(LOG_DEBUG, "phyint_timer SOL(%s) " 573 "state %d -> %d\n", 574 pi->pi_name, (int)old_state, 575 (int)pi->pi_sol_state); 576 } 577 } 578 } 579 580 /* 581 * If the phyint has been unplumbed, we don't want to call 582 * phyint_reach_random. We will be in the NO_ADV or NO_SOLICIT state. 583 */ 584 if ((pi->pi_AdvSendAdvertisements && (pi->pi_adv_state != NO_ADV)) || 585 (!pi->pi_AdvSendAdvertisements && 586 (pi->pi_sol_state != NO_SOLICIT))) { 587 pi->pi_reach_time_since_random += elapsed; 588 if (pi->pi_reach_time_since_random >= MAX_REACH_RANDOM_INTERVAL) 589 phyint_reach_random(pi, _B_TRUE); 590 } 591 592 return (next); 593 } 594 595 static void 596 phyint_print(struct phyint *pi) 597 { 598 struct prefix *pr; 599 struct adv_prefix *adv_pr; 600 struct router *dr; 601 char abuf[INET6_ADDRSTRLEN]; 602 char llabuf[BUFSIZ]; 603 604 logmsg(LOG_DEBUG, "Phyint %s index %d state %x, kernel %x, " 605 "num routers %d\n", 606 pi->pi_name, pi->pi_index, pi->pi_state, pi->pi_kernel_state, 607 pi->pi_num_k_routers); 608 logmsg(LOG_DEBUG, "\taddress: %s flags %x\n", 609 inet_ntop(AF_INET6, (void *)&pi->pi_ifaddr, 610 abuf, sizeof (abuf)), pi->pi_flags); 611 logmsg(LOG_DEBUG, "\tsock %d mtu %d hdw_addr len %d <%s>\n", 612 pi->pi_sock, pi->pi_mtu, pi->pi_hdw_addr_len, 613 ((pi->pi_hdw_addr_len != 0) ? 614 fmt_lla(llabuf, sizeof (llabuf), pi->pi_hdw_addr, 615 pi->pi_hdw_addr_len) : "none")); 616 logmsg(LOG_DEBUG, "\ttoken: len %d %s\n", 617 pi->pi_token_length, 618 inet_ntop(AF_INET6, (void *)&pi->pi_token, 619 abuf, sizeof (abuf))); 620 if (pi->pi_TmpAddrsEnabled) { 621 logmsg(LOG_DEBUG, "\ttmp_token: %s\n", 622 inet_ntop(AF_INET6, (void *)&pi->pi_tmp_token, 623 abuf, sizeof (abuf))); 624 logmsg(LOG_DEBUG, "\ttmp config: pref %d valid %d " 625 "maxdesync %d desync %d regen %d\n", 626 pi->pi_TmpPreferredLifetime, pi->pi_TmpValidLifetime, 627 pi->pi_TmpMaxDesyncFactor, pi->pi_TmpDesyncFactor, 628 pi->pi_TmpRegenAdvance); 629 } 630 if (pi->pi_flags & IFF_POINTOPOINT) { 631 logmsg(LOG_DEBUG, "\tdst_token: %s\n", 632 inet_ntop(AF_INET6, (void *)&pi->pi_dst_token, 633 abuf, sizeof (abuf))); 634 } 635 logmsg(LOG_DEBUG, "\tLinkMTU %d CurHopLimit %d " 636 "BaseReachableTime %d\n\tReachableTime %d RetransTimer %d\n", 637 pi->pi_LinkMTU, pi->pi_CurHopLimit, pi->pi_BaseReachableTime, 638 pi->pi_ReachableTime, pi->pi_RetransTimer); 639 if (!pi->pi_AdvSendAdvertisements) { 640 /* Solicit state */ 641 logmsg(LOG_DEBUG, "\tSOLICIT: time_left %d state %d count %d\n", 642 pi->pi_sol_time_left, pi->pi_sol_state, pi->pi_sol_count); 643 } else { 644 /* Advertise state */ 645 logmsg(LOG_DEBUG, "\tADVERT: time_left %d state %d count %d " 646 "since last %d\n", 647 pi->pi_adv_time_left, pi->pi_adv_state, pi->pi_adv_count, 648 pi->pi_adv_time_since_sent); 649 print_iflist(pi->pi_config); 650 } 651 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) 652 prefix_print(pr); 653 654 for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL; 655 adv_pr = adv_pr->adv_pr_next) { 656 adv_prefix_print(adv_pr); 657 } 658 659 for (dr = pi->pi_router_list; dr != NULL; dr = dr->dr_next) 660 router_print(dr); 661 662 logmsg(LOG_DEBUG, "\n"); 663 } 664 665 /* 666 * Randomize pi->pi_ReachableTime. 667 * Done periodically when there are no RAs and at a maximum frequency when 668 * RA's arrive. 669 * Assumes that caller has determined that it is time to generate 670 * a new random ReachableTime. 671 */ 672 void 673 phyint_reach_random(struct phyint *pi, boolean_t set_needed) 674 { 675 pi->pi_ReachableTime = GET_RANDOM( 676 (int)(ND_MIN_RANDOM_FACTOR * pi->pi_BaseReachableTime), 677 (int)(ND_MAX_RANDOM_FACTOR * pi->pi_BaseReachableTime)); 678 if (set_needed) { 679 struct lifreq lifr; 680 681 (void) strncpy(lifr.lifr_name, pi->pi_name, 682 sizeof (lifr.lifr_name)); 683 pi->pi_name[sizeof (pi->pi_name) - 1] = '\0'; 684 if (ioctl(pi->pi_sock, SIOCGLIFLNKINFO, (char *)&lifr) < 0) { 685 logperror_pi(pi, 686 "phyint_reach_random: SIOCGLIFLNKINFO"); 687 return; 688 } 689 lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime; 690 if (ioctl(pi->pi_sock, SIOCSLIFLNKINFO, (char *)&lifr) < 0) { 691 logperror_pi(pi, 692 "phyint_reach_random: SIOCSLIFLNKINFO"); 693 return; 694 } 695 } 696 pi->pi_reach_time_since_random = 0; 697 } 698 699 /* 700 * Validate a temporary token against a list of known bad values. 701 * Currently assumes that token is 8 bytes long! Current known 702 * bad values include 0, reserved anycast tokens (RFC 2526), tokens 703 * used by ISATAP (draft-ietf-ngtrans-isatap-N), any token already 704 * assigned to this interface, or any token for which the global 705 * bit is set. 706 * 707 * Called by tmptoken_create(). 708 * 709 * Return _B_TRUE if token is valid (no match), _B_FALSE if not. 710 */ 711 static boolean_t 712 tmptoken_isvalid(struct in6_addr *token) 713 { 714 struct phyint *pi; 715 struct in6_addr mask; 716 struct in6_addr isatap = { 0, 0, 0, 0, 0, 0, 0, 0, \ 717 0, 0, 0x5e, 0xfe, 0, 0, 0, 0 }; 718 struct in6_addr anycast = { 0, 0, 0, 0, \ 719 0, 0, 0, 0, \ 720 0xfd, 0xff, 0xff, 0xff, \ 721 0xff, 0xff, 0xff, 0x80 }; 722 723 if (IN6_IS_ADDR_UNSPECIFIED(token)) 724 return (_B_FALSE); 725 726 if (token->s6_addr[8] & 0x2) 727 return (_B_FALSE); 728 729 (void) memcpy(&mask, token, sizeof (mask)); 730 mask._S6_un._S6_u32[3] = 0; 731 if (IN6_ARE_ADDR_EQUAL(&isatap, token)) 732 return (_B_FALSE); 733 734 mask._S6_un._S6_u32[3] = token->_S6_un._S6_u32[3] & 0xffffff80; 735 if (IN6_ARE_ADDR_EQUAL(&anycast, token)) 736 return (_B_FALSE); 737 738 for (pi = phyints; pi != NULL; pi = pi->pi_next) { 739 if (((pi->pi_token_length == TMP_TOKEN_BITS) && 740 IN6_ARE_ADDR_EQUAL(&pi->pi_token, token)) || 741 IN6_ARE_ADDR_EQUAL(&pi->pi_tmp_token, token)) 742 return (_B_FALSE); 743 } 744 745 /* none of our tests failed, must be a good one! */ 746 return (_B_TRUE); 747 } 748 749 /* 750 * Generate a temporary token and set up its timer 751 * 752 * Called from incoming_prefix_addrconf_process() (when token is first 753 * needed) and from tmptoken_timer() (when current token expires). 754 * 755 * Returns _B_TRUE if a token was successfully generated, _B_FALSE if not. 756 */ 757 boolean_t 758 tmptoken_create(struct phyint *pi) 759 { 760 int fd, i = 0, max_tries = 15; 761 struct in6_addr token; 762 uint32_t *tokenp = &(token._S6_un._S6_u32[2]); 763 char buf[INET6_ADDRSTRLEN]; 764 765 if ((fd = open("/dev/urandom", O_RDONLY)) == -1) { 766 perror("open /dev/urandom"); 767 goto no_token; 768 } 769 770 bzero((char *)&token, sizeof (token)); 771 do { 772 if (read(fd, (void *)tokenp, TMP_TOKEN_BYTES) == -1) { 773 perror("read /dev/urandom"); 774 (void) close(fd); 775 goto no_token; 776 } 777 778 /* 779 * Assume EUI-64 formatting, and thus 64-bit 780 * token len; need to clear global bit. 781 */ 782 token.s6_addr[8] &= 0xfd; 783 784 i++; 785 786 } while (!tmptoken_isvalid(&token) && i < max_tries); 787 788 (void) close(fd); 789 790 if (i == max_tries) { 791 no_token: 792 logmsg(LOG_WARNING, "tmptoken_create(%s): failed to create " 793 "token; disabling temporary addresses on %s\n", 794 pi->pi_name, pi->pi_name); 795 pi->pi_TmpAddrsEnabled = 0; 796 return (_B_FALSE); 797 } 798 799 pi->pi_tmp_token = token; 800 801 if (debug & D_TMP) 802 logmsg(LOG_DEBUG, "tmptoken_create(%s): created temporary " 803 "token %s\n", pi->pi_name, 804 inet_ntop(AF_INET6, &pi->pi_tmp_token, buf, sizeof (buf))); 805 806 pi->pi_TmpRegenCountdown = (pi->pi_TmpPreferredLifetime - 807 pi->pi_TmpDesyncFactor - pi->pi_TmpRegenAdvance) * MILLISEC; 808 if (pi->pi_TmpRegenCountdown != 0) 809 timer_schedule(pi->pi_TmpRegenCountdown); 810 811 return (_B_TRUE); 812 } 813 814 /* 815 * Delete a temporary token. This is outside the normal timeout process, 816 * so mark any existing addresses based on this token DEPRECATED and set 817 * their preferred lifetime to 0. Don't tamper with valid lifetime, that 818 * will be used to eventually remove the address. Also reset the current 819 * pi_tmp_token value to 0. 820 * 821 * Called from incoming_prefix_addrconf_process() if DAD fails on a temp 822 * addr. 823 */ 824 void 825 tmptoken_delete(struct phyint *pi) 826 { 827 struct prefix *pr; 828 829 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 830 if (!(pr->pr_flags & IFF_TEMPORARY) || 831 (pr->pr_flags & IFF_DEPRECATED) || 832 (!token_equal(pr->pr_address, pi->pi_tmp_token, 833 TMP_TOKEN_BITS))) { 834 continue; 835 } 836 pr->pr_PreferredLifetime = 0; 837 pr->pr_state |= PR_DEPRECATED; 838 prefix_update_k(pr); 839 } 840 841 (void) memset(&pi->pi_tmp_token, 0, sizeof (pi->pi_tmp_token)); 842 } 843 844 /* 845 * Called from run_timeouts() with the number of milliseconds elapsed 846 * since the last call. Determines if any timeout event has occurred 847 * and returns the number of milliseconds until the next timeout event 848 * for the tmp token. Returns TIMER_INFINITY for "never". 849 */ 850 uint_t 851 tmptoken_timer(struct phyint *pi, uint_t elapsed) 852 { 853 struct nd_opt_prefix_info opt; 854 struct sockaddr_in6 sin6; 855 struct prefix *pr, *newpr; 856 857 if (debug & D_TMP) { 858 logmsg(LOG_DEBUG, "tmptoken_timer(%s, %d) regencountdown %d\n", 859 pi->pi_name, (int)elapsed, pi->pi_TmpRegenCountdown); 860 } 861 if (!pi->pi_TmpAddrsEnabled || 862 (pi->pi_TmpRegenCountdown == TIMER_INFINITY)) 863 return (TIMER_INFINITY); 864 865 if (pi->pi_TmpRegenCountdown > elapsed) { 866 pi->pi_TmpRegenCountdown -= elapsed; 867 return (pi->pi_TmpRegenCountdown); 868 } 869 870 /* 871 * Tmp token timer has expired. Start by generating a new token. 872 * If we can't get a new token, tmp addrs are disabled on this 873 * interface, so there's no need to continue, or to set a timer. 874 */ 875 if (!tmptoken_create(pi)) 876 return (TIMER_INFINITY); 877 878 /* 879 * Now that we have a new token, walk the list of prefixes to 880 * find which ones need a corresponding tmp addr generated. 881 */ 882 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 883 884 if (!(pr->pr_state & PR_AUTO) || pr->pr_state & PR_STATIC || 885 pr->pr_state & PR_DEPRECATED || 886 pr->pr_flags & IFF_TEMPORARY) 887 continue; 888 889 newpr = prefix_create(pi, pr->pr_prefix, pr->pr_prefix_len, 890 IFF_TEMPORARY); 891 if (newpr == NULL) { 892 char pbuf[INET6_ADDRSTRLEN]; 893 char tbuf[INET6_ADDRSTRLEN]; 894 (void) inet_ntop(AF_INET6, &pr->pr_prefix, pbuf, 895 sizeof (pbuf)); 896 (void) inet_ntop(AF_INET6, &pi->pi_tmp_token, tbuf, 897 sizeof (tbuf)); 898 logmsg(LOG_ERR, "can't create new tmp addr " 899 "(%s, %s, %s)\n", pi->pi_name, pbuf, tbuf); 900 continue; 901 } 902 903 /* 904 * We want to use incoming_prefix_*_process() functions to 905 * set up the new tmp addr, so cobble together a prefix 906 * info option struct based on the existing prefix to pass 907 * in. The lifetimes will be based on the current time 908 * remaining. 909 * 910 * The "from" param is only used for messages; pass in 911 * ::0 for that. 912 */ 913 opt.nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; 914 opt.nd_opt_pi_len = sizeof (opt) / 8; 915 opt.nd_opt_pi_prefix_len = pr->pr_prefix_len; 916 opt.nd_opt_pi_flags_reserved = ND_OPT_PI_FLAG_AUTO; 917 opt.nd_opt_pi_valid_time = 918 htonl(pr->pr_ValidLifetime / 1000); 919 opt.nd_opt_pi_preferred_time = 920 htonl(pr->pr_PreferredLifetime / 1000); 921 if (pr->pr_state & PR_ONLINK) 922 opt.nd_opt_pi_flags_reserved &= ND_OPT_PI_FLAG_ONLINK; 923 opt.nd_opt_pi_prefix = pr->pr_prefix; 924 925 (void) memset(&sin6, 0, sizeof (sin6)); 926 927 if (!incoming_prefix_addrconf_process(pi, newpr, 928 (uchar_t *)&opt, &sin6, _B_FALSE, _B_TRUE)) { 929 char pbuf[INET6_ADDRSTRLEN]; 930 char tbuf[INET6_ADDRSTRLEN]; 931 (void) inet_ntop(AF_INET6, &pr->pr_prefix, pbuf, 932 sizeof (pbuf)); 933 (void) inet_ntop(AF_INET6, &pi->pi_tmp_token, tbuf, 934 sizeof (tbuf)); 935 logmsg(LOG_ERR, "can't create new tmp addr " 936 "(%s, %s, %s)\n", pi->pi_name, pbuf, tbuf); 937 continue; 938 } 939 940 if (pr->pr_state & PR_ONLINK) { 941 incoming_prefix_onlink_process(newpr, (uchar_t *)&opt); 942 } 943 } 944 945 /* 946 * appropriate timers were scheduled when 947 * the token and addresses were created. 948 */ 949 return (TIMER_INFINITY); 950 } 951 952 /* 953 * tlen specifies the token length in bits. Compares the lower 954 * tlen bits of the two addresses provided and returns _B_TRUE if 955 * they match, _B_FALSE if not. Also returns _B_FALSE for invalid 956 * values of tlen. 957 */ 958 boolean_t 959 token_equal(struct in6_addr t1, struct in6_addr t2, int tlen) 960 { 961 uchar_t mask; 962 int j, abytes, tbytes, tbits; 963 964 if (tlen < 0 || tlen > IPV6_ABITS) 965 return (_B_FALSE); 966 967 abytes = IPV6_ABITS >> 3; 968 tbytes = tlen >> 3; 969 tbits = tlen & 7; 970 971 for (j = abytes - 1; j >= abytes - tbytes; j--) 972 if (t1.s6_addr[j] != t2.s6_addr[j]) 973 return (_B_FALSE); 974 975 if (tbits == 0) 976 return (_B_TRUE); 977 978 /* We only care about the tbits rightmost bits */ 979 mask = 0xff >> (8 - tbits); 980 if ((t1.s6_addr[j] & mask) != (t2.s6_addr[j] & mask)) 981 return (_B_FALSE); 982 983 return (_B_TRUE); 984 } 985 986 /* 987 * Lookup prefix structure that matches the prefix and prefix length. 988 * Assumes that the bits after prefixlen might not be zero. 989 */ 990 static struct prefix * 991 prefix_lookup(struct phyint *pi, struct in6_addr prefix, int prefixlen) 992 { 993 struct prefix *pr; 994 char abuf[INET6_ADDRSTRLEN]; 995 996 if (debug & D_PREFIX) { 997 logmsg(LOG_DEBUG, "prefix_lookup(%s, %s/%u)\n", pi->pi_name, 998 inet_ntop(AF_INET6, (void *)&prefix, 999 abuf, sizeof (abuf)), prefixlen); 1000 } 1001 1002 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 1003 if (pr->pr_prefix_len == prefixlen && 1004 prefix_equal(prefix, pr->pr_prefix, prefixlen)) 1005 return (pr); 1006 } 1007 return (NULL); 1008 } 1009 1010 /* 1011 * Compare two prefixes that have the same prefix length. 1012 * Fails if the prefix length is unreasonable. 1013 */ 1014 boolean_t 1015 prefix_equal(struct in6_addr p1, struct in6_addr p2, int plen) 1016 { 1017 uchar_t mask; 1018 int j, pbytes, pbits; 1019 1020 if (plen < 0 || plen > IPV6_ABITS) 1021 return (_B_FALSE); 1022 1023 pbytes = plen >> 3; 1024 pbits = plen & 7; 1025 1026 for (j = 0; j < pbytes; j++) 1027 if (p1.s6_addr[j] != p2.s6_addr[j]) 1028 return (_B_FALSE); 1029 1030 if (pbits == 0) 1031 return (_B_TRUE); 1032 1033 /* Make the N leftmost bits one */ 1034 mask = 0xff << (8 - pbits); 1035 if ((p1.s6_addr[j] & mask) != (p2.s6_addr[j] & mask)) 1036 return (_B_FALSE); 1037 1038 return (_B_TRUE); 1039 } 1040 1041 /* 1042 * Set a prefix from an address and a prefix length. 1043 * Force all the bits after the prefix length to be zero. 1044 */ 1045 void 1046 prefix_set(struct in6_addr *prefix, struct in6_addr addr, int prefix_len) 1047 { 1048 uchar_t mask; 1049 int j; 1050 1051 if (prefix_len < 0 || prefix_len > IPV6_ABITS) 1052 return; 1053 1054 bzero((char *)prefix, sizeof (*prefix)); 1055 1056 for (j = 0; prefix_len > 8; prefix_len -= 8, j++) 1057 prefix->s6_addr[j] = addr.s6_addr[j]; 1058 1059 /* Make the N leftmost bits one */ 1060 mask = 0xff << (8 - prefix_len); 1061 prefix->s6_addr[j] = addr.s6_addr[j] & mask; 1062 } 1063 1064 /* 1065 * Lookup a prefix based on the kernel's interface name. 1066 */ 1067 struct prefix * 1068 prefix_lookup_name(struct phyint *pi, char *name) 1069 { 1070 struct prefix *pr; 1071 1072 if (debug & D_PREFIX) { 1073 logmsg(LOG_DEBUG, "prefix_lookup_name(%s, %s)\n", 1074 pi->pi_name, name); 1075 } 1076 if (name[0] == '\0') 1077 return (NULL); 1078 1079 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 1080 if (strcmp(name, pr->pr_name) == 0) 1081 return (pr); 1082 } 1083 return (NULL); 1084 } 1085 1086 /* 1087 * Search the phyints list to make sure that this new prefix does 1088 * not already exist in any other physical interfaces that have 1089 * the same address as this one 1090 */ 1091 struct prefix * 1092 prefix_lookup_addr_match(struct prefix *pr) 1093 { 1094 char abuf[INET6_ADDRSTRLEN]; 1095 struct phyint *pi; 1096 struct prefix *otherpr = NULL; 1097 struct in6_addr prefix; 1098 int prefixlen; 1099 1100 if (debug & D_PREFIX) { 1101 logmsg(LOG_DEBUG, "prefix_lookup_addr_match(%s/%u)\n", 1102 inet_ntop(AF_INET6, (void *)&pr->pr_address, 1103 abuf, sizeof (abuf)), pr->pr_prefix_len); 1104 } 1105 prefix = pr->pr_prefix; 1106 prefixlen = pr->pr_prefix_len; 1107 for (pi = phyints; pi != NULL; pi = pi->pi_next) { 1108 otherpr = prefix_lookup(pi, prefix, prefixlen); 1109 if (otherpr == pr) 1110 continue; 1111 if (otherpr != NULL && (otherpr->pr_state & PR_AUTO) && 1112 IN6_ARE_ADDR_EQUAL(&pr->pr_address, 1113 &otherpr->pr_address)) 1114 return (otherpr); 1115 } 1116 return (NULL); 1117 } 1118 1119 /* 1120 * Initialize a new prefix without setting lifetimes etc. 1121 */ 1122 struct prefix * 1123 prefix_create(struct phyint *pi, struct in6_addr prefix, int prefixlen, 1124 uint64_t flags) 1125 { 1126 struct prefix *pr; 1127 char abuf[INET6_ADDRSTRLEN]; 1128 1129 if (debug & D_PREFIX) { 1130 logmsg(LOG_DEBUG, "prefix_create(%s, %s/%u, 0x%llx)\n", 1131 pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix, 1132 abuf, sizeof (abuf)), prefixlen, flags); 1133 } 1134 pr = (struct prefix *)calloc(sizeof (struct prefix), 1); 1135 if (pr == NULL) { 1136 logmsg(LOG_ERR, "prefix_create: out of memory\n"); 1137 return (NULL); 1138 } 1139 /* 1140 * The prefix might have non-zero bits after the prefix len bits. 1141 * Force them to be zero. 1142 */ 1143 prefix_set(&pr->pr_prefix, prefix, prefixlen); 1144 pr->pr_prefix_len = prefixlen; 1145 pr->pr_PreferredLifetime = PREFIX_INFINITY; 1146 pr->pr_ValidLifetime = PREFIX_INFINITY; 1147 pr->pr_OnLinkLifetime = PREFIX_INFINITY; 1148 pr->pr_kernel_state = 0; 1149 pr->pr_flags |= flags; 1150 prefix_insert(pi, pr); 1151 return (pr); 1152 } 1153 1154 /* 1155 * Create a new named prefix. Caller should use prefix_init_from_k 1156 * to initialize the content. 1157 */ 1158 struct prefix * 1159 prefix_create_name(struct phyint *pi, char *name) 1160 { 1161 struct prefix *pr; 1162 1163 if (debug & D_PREFIX) { 1164 logmsg(LOG_DEBUG, "prefix_create_name(%s, %s)\n", 1165 pi->pi_name, name); 1166 } 1167 pr = (struct prefix *)calloc(sizeof (struct prefix), 1); 1168 if (pr == NULL) { 1169 logmsg(LOG_ERR, "prefix_create_name: out of memory\n"); 1170 return (NULL); 1171 } 1172 (void) strncpy(pr->pr_name, name, sizeof (pr->pr_name)); 1173 pr->pr_name[sizeof (pr->pr_name) - 1] = '\0'; 1174 prefix_insert(pi, pr); 1175 return (pr); 1176 } 1177 1178 /* Insert in linked list */ 1179 static void 1180 prefix_insert(struct phyint *pi, struct prefix *pr) 1181 { 1182 pr->pr_next = pi->pi_prefix_list; 1183 pr->pr_prev = NULL; 1184 if (pi->pi_prefix_list != NULL) 1185 pi->pi_prefix_list->pr_prev = pr; 1186 pi->pi_prefix_list = pr; 1187 pr->pr_physical = pi; 1188 } 1189 1190 /* 1191 * Initialize the prefix from the content of the kernel. 1192 * If IFF_ADDRCONF is set we treat it as PR_AUTO (i.e. an addrconf 1193 * prefix). However, we not derive the lifetimes from 1194 * the kernel thus they are set to 1 week. 1195 * Ignore the prefix if the interface is not IFF_UP. 1196 */ 1197 int 1198 prefix_init_from_k(struct prefix *pr) 1199 { 1200 struct lifreq lifr; 1201 struct sockaddr_in6 *sin6; 1202 int sock = pr->pr_physical->pi_sock; 1203 1204 (void) strncpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name)); 1205 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1206 if (ioctl(sock, SIOCGLIFADDR, (char *)&lifr) < 0) { 1207 logperror_pr(pr, "prefix_init_from_k: ioctl (get addr)"); 1208 goto error; 1209 } 1210 if (lifr.lifr_addr.ss_family != AF_INET6) { 1211 logmsg(LOG_ERR, "ignoring interface %s: not AF_INET6\n", 1212 pr->pr_name); 1213 goto error; 1214 } 1215 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1216 pr->pr_address = sin6->sin6_addr; 1217 1218 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 1219 logperror_pr(pr, "prefix_init_from_k: ioctl (get flags)"); 1220 goto error; 1221 } 1222 pr->pr_flags = lifr.lifr_flags; 1223 1224 if (ioctl(sock, SIOCGLIFSUBNET, (char *)&lifr) < 0) { 1225 logperror_pr(pr, "prefix_init_from_k: ioctl (get subnet)"); 1226 goto error; 1227 } 1228 if (lifr.lifr_subnet.ss_family != AF_INET6) { 1229 logmsg(LOG_ERR, "ignoring interface %s: not AF_INET6\n", 1230 pr->pr_name); 1231 goto error; 1232 } 1233 /* 1234 * Guard against the prefix having non-zero bits after the prefix 1235 * len bits. 1236 */ 1237 sin6 = (struct sockaddr_in6 *)&lifr.lifr_subnet; 1238 pr->pr_prefix_len = lifr.lifr_addrlen; 1239 prefix_set(&pr->pr_prefix, sin6->sin6_addr, pr->pr_prefix_len); 1240 1241 if (pr->pr_prefix_len != IPV6_ABITS && (pr->pr_flags & IFF_UP) && 1242 IN6_ARE_ADDR_EQUAL(&pr->pr_address, &pr->pr_prefix)) { 1243 char abuf[INET6_ADDRSTRLEN]; 1244 1245 logmsg(LOG_ERR, "ingoring interface %s: it appears to be " 1246 "configured with an invalid interface id (%s/%u)\n", 1247 pr->pr_name, 1248 inet_ntop(AF_INET6, (void *)&pr->pr_address, 1249 abuf, sizeof (abuf)), pr->pr_prefix_len); 1250 goto error; 1251 } 1252 pr->pr_kernel_state = 0; 1253 if (pr->pr_prefix_len != IPV6_ABITS) 1254 pr->pr_kernel_state |= PR_ONLINK; 1255 if (!(pr->pr_flags & IFF_NOLOCAL)) 1256 pr->pr_kernel_state |= PR_AUTO; 1257 if ((pr->pr_flags & IFF_DEPRECATED) && (pr->pr_kernel_state & PR_AUTO)) 1258 pr->pr_kernel_state |= PR_DEPRECATED; 1259 if (!(pr->pr_flags & IFF_ADDRCONF)) { 1260 /* Prevent ndpd from stepping on this prefix */ 1261 pr->pr_kernel_state |= PR_STATIC; 1262 } 1263 pr->pr_state = pr->pr_kernel_state; 1264 /* Adjust pr_prefix_len based if PR_AUTO is set */ 1265 if (pr->pr_state & PR_AUTO) { 1266 pr->pr_prefix_len = 1267 IPV6_ABITS - pr->pr_physical->pi_token_length; 1268 prefix_set(&pr->pr_prefix, pr->pr_prefix, pr->pr_prefix_len); 1269 } 1270 1271 /* Can't extract lifetimes from the kernel - use 1 week */ 1272 pr->pr_ValidLifetime = NDP_PREFIX_DEFAULT_LIFETIME; 1273 pr->pr_PreferredLifetime = NDP_PREFIX_DEFAULT_LIFETIME; 1274 pr->pr_OnLinkLifetime = NDP_PREFIX_DEFAULT_LIFETIME; 1275 1276 /* 1277 * If this is a temp addr, the creation time needs to be set. 1278 * Though it won't be entirely accurate, the current time is 1279 * an okay approximation. 1280 */ 1281 if (pr->pr_flags & IFF_TEMPORARY) 1282 pr->pr_CreateTime = getcurrenttime() / MILLISEC; 1283 1284 if (pr->pr_kernel_state == 0) 1285 pr->pr_name[0] = '\0'; 1286 return (0); 1287 1288 error: 1289 /* Pretend that the prefix does not exist in the kernel */ 1290 pr->pr_kernel_state = 0; 1291 pr->pr_name[0] = '\0'; 1292 return (-1); 1293 } 1294 1295 /* 1296 * Delete (unlink and free) and remove from kernel if the prefix 1297 * was added by in.ndpd (i.e. PR_STATIC is not set). 1298 * Handles delete of things that have not yet been inserted in the list 1299 * i.e. pr_physical is NULL. 1300 */ 1301 void 1302 prefix_delete(struct prefix *pr) 1303 { 1304 struct phyint *pi; 1305 char abuf[INET6_ADDRSTRLEN]; 1306 1307 if (debug & D_PREFIX) { 1308 logmsg(LOG_DEBUG, "prefix_delete(%s, %s, %s/%u)\n", 1309 pr->pr_physical->pi_name, pr->pr_name, 1310 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1311 abuf, sizeof (abuf)), pr->pr_prefix_len); 1312 } 1313 /* Remove non-static prefixes from the kernel. */ 1314 pr->pr_state &= PR_STATIC; 1315 pi = pr->pr_physical; 1316 if (pr->pr_kernel_state != pr->pr_state) 1317 prefix_update_k(pr); 1318 1319 if (pr->pr_prev == NULL) { 1320 if (pi != NULL) 1321 pi->pi_prefix_list = pr->pr_next; 1322 } else { 1323 pr->pr_prev->pr_next = pr->pr_next; 1324 } 1325 if (pr->pr_next != NULL) 1326 pr->pr_next->pr_prev = pr->pr_prev; 1327 pr->pr_next = pr->pr_prev = NULL; 1328 free(pr); 1329 } 1330 1331 /* 1332 * Toggle one or more IFF_ flags for a prefix. Turn on 'onflags' and 1333 * turn off 'offflags'. 1334 */ 1335 static int 1336 prefix_modify_flags(struct prefix *pr, uint64_t onflags, uint64_t offflags) 1337 { 1338 struct lifreq lifr; 1339 struct phyint *pi = pr->pr_physical; 1340 uint64_t old_flags; 1341 char abuf[INET6_ADDRSTRLEN]; 1342 1343 if (debug & D_PREFIX) { 1344 logmsg(LOG_DEBUG, "prefix_modify_flags(%s, %s, %s/%u) " 1345 "flags %llx on %llx off %llx\n", 1346 pr->pr_physical->pi_name, 1347 pr->pr_name, 1348 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1349 abuf, sizeof (abuf)), pr->pr_prefix_len, 1350 pr->pr_flags, onflags, offflags); 1351 } 1352 /* Assumes that only the PR_STATIC link-local matches the pi_name */ 1353 if (!(pr->pr_state & PR_STATIC) && 1354 strcmp(pr->pr_name, pi->pi_name) == 0) { 1355 logmsg(LOG_ERR, "prefix_modify_flags(%s, on %llx, off %llx): " 1356 "name matches interface name\n", 1357 pi->pi_name, onflags, offflags); 1358 return (-1); 1359 } 1360 1361 (void) strncpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name)); 1362 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1363 if (ioctl(pi->pi_sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 1364 logperror_pr(pr, "prefix_modify_flags: SIOCGLIFFLAGS"); 1365 logmsg(LOG_ERR, "prefix_modify_flags(%s, %s) old 0x%llx " 1366 "on 0x%llx off 0x%llx\n", 1367 pr->pr_physical->pi_name, 1368 pr->pr_name, 1369 pr->pr_flags, onflags, offflags); 1370 return (-1); 1371 } 1372 old_flags = lifr.lifr_flags; 1373 lifr.lifr_flags |= onflags; 1374 lifr.lifr_flags &= ~offflags; 1375 pr->pr_flags = lifr.lifr_flags; 1376 if (ioctl(pi->pi_sock, SIOCSLIFFLAGS, (char *)&lifr) < 0) { 1377 logperror_pr(pr, "prefix_modify_flags: SIOCSLIFFLAGS"); 1378 logmsg(LOG_ERR, "prefix_modify_flags(%s, %s) old 0x%llx " 1379 "new 0x%llx on 0x%llx off 0x%llx\n", 1380 pr->pr_physical->pi_name, 1381 pr->pr_name, 1382 old_flags, lifr.lifr_flags, onflags, offflags); 1383 return (-1); 1384 } 1385 return (0); 1386 } 1387 1388 /* 1389 * Make the kernel state match what is in the prefix structure. 1390 * This includes creating the prefix (allocating a new interface name) 1391 * as well as setting the local address and on-link subnet prefix 1392 * and controlling the IFF_ADDRCONF and IFF_DEPRECATED flags. 1393 */ 1394 void 1395 prefix_update_k(struct prefix *pr) 1396 { 1397 struct lifreq lifr; 1398 char abuf[INET6_ADDRSTRLEN]; 1399 char buf1[PREFIX_STATESTRLEN], buf2[PREFIX_STATESTRLEN]; 1400 struct phyint *pi = pr->pr_physical; 1401 struct sockaddr_in6 *sin6; 1402 1403 if (debug & D_PREFIX) { 1404 logmsg(LOG_DEBUG, "prefix_update_k(%s, %s, %s/%u) " 1405 "from %s to %s\n", pr->pr_physical->pi_name, pr->pr_name, 1406 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1407 abuf, sizeof (abuf)), pr->pr_prefix_len, 1408 prefix_print_state(pr->pr_kernel_state, buf1, 1409 sizeof (buf1)), 1410 prefix_print_state(pr->pr_state, buf2, sizeof (buf2))); 1411 } 1412 1413 if (pr->pr_kernel_state == pr->pr_state) 1414 return; /* No changes */ 1415 1416 /* Skip static prefixes */ 1417 if (pr->pr_state & PR_STATIC) 1418 return; 1419 1420 if (pr->pr_kernel_state == 0) { 1421 uint64_t onflags; 1422 /* 1423 * Create a new logical interface name and store in pr_name. 1424 * Set IFF_ADDRCONF. Do not set an address (yet). 1425 */ 1426 if (pr->pr_name[0] != '\0') { 1427 /* Name already set! */ 1428 logmsg(LOG_ERR, "prefix_update_k(%s, %s, %s/%u) " 1429 "from %s to %s name is already allocated\n", 1430 pr->pr_physical->pi_name, pr->pr_name, 1431 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1432 abuf, sizeof (abuf)), pr->pr_prefix_len, 1433 prefix_print_state(pr->pr_kernel_state, buf1, 1434 sizeof (buf1)), 1435 prefix_print_state(pr->pr_state, buf2, 1436 sizeof (buf2))); 1437 return; 1438 } 1439 1440 (void) strncpy(lifr.lifr_name, pi->pi_name, 1441 sizeof (lifr.lifr_name)); 1442 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1443 lifr.lifr_addr.ss_family = AF_UNSPEC; 1444 if (ioctl(pi->pi_sock, SIOCLIFADDIF, (char *)&lifr) < 0) { 1445 logperror_pr(pr, "prefix_update_k: SIOCLIFADDIF"); 1446 return; 1447 } 1448 (void) strncpy(pr->pr_name, lifr.lifr_name, 1449 sizeof (pr->pr_name)); 1450 pr->pr_name[sizeof (pr->pr_name) - 1] = '\0'; 1451 if (debug & D_PREFIX) { 1452 logmsg(LOG_DEBUG, "prefix_update_k: new name %s\n", 1453 pr->pr_name); 1454 } 1455 /* 1456 * The IFF_TEMPORARY flag might have already been set; if 1457 * so, it needs to be or'd into the flags we're turning on. 1458 * But be careful, we might be re-creating a manually 1459 * removed interface, in which case we don't want to try 1460 * to set *all* the flags we might have in our copy of the 1461 * flags yet. 1462 */ 1463 onflags = IFF_ADDRCONF; 1464 if (pr->pr_flags & IFF_TEMPORARY) 1465 onflags |= IFF_TEMPORARY; 1466 if (prefix_modify_flags(pr, onflags, 0) == -1) 1467 return; 1468 } 1469 if ((pr->pr_state & (PR_ONLINK|PR_AUTO)) == 0) { 1470 /* Remove the interface */ 1471 if (prefix_modify_flags(pr, 0, IFF_UP|IFF_DEPRECATED) == -1) 1472 return; 1473 (void) strncpy(lifr.lifr_name, pr->pr_name, 1474 sizeof (lifr.lifr_name)); 1475 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1476 1477 if (debug & D_PREFIX) { 1478 logmsg(LOG_DEBUG, "prefix_update_k: remove name %s\n", 1479 pr->pr_name); 1480 } 1481 1482 /* 1483 * Assumes that only the PR_STATIC link-local matches 1484 * the pi_name 1485 */ 1486 if (!(pr->pr_state & PR_STATIC) && 1487 strcmp(pr->pr_name, pi->pi_name) == 0) { 1488 logmsg(LOG_ERR, "prefix_update_k(%s): " 1489 "name matches if\n", pi->pi_name); 1490 return; 1491 } 1492 1493 /* Remove logical interface based on pr_name */ 1494 lifr.lifr_addr.ss_family = AF_UNSPEC; 1495 if (ioctl(pi->pi_sock, SIOCLIFREMOVEIF, (char *)&lifr) < 0) { 1496 logperror_pr(pr, "prefix_update_k: SIOCLIFREMOVEIF"); 1497 } 1498 pr->pr_kernel_state = 0; 1499 pr->pr_name[0] = '\0'; 1500 return; 1501 } 1502 if ((pr->pr_state & PR_AUTO) && !(pr->pr_kernel_state & PR_AUTO)) { 1503 /* 1504 * Set local address and set the prefix length to 128. 1505 * Turn off IFF_NOLOCAL in case it was set. 1506 * Turn on IFF_UP. 1507 */ 1508 (void) strncpy(lifr.lifr_name, pr->pr_name, 1509 sizeof (lifr.lifr_name)); 1510 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1511 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1512 bzero(sin6, sizeof (struct sockaddr_in6)); 1513 sin6->sin6_family = AF_INET6; 1514 sin6->sin6_addr = pr->pr_address; 1515 if (debug & D_PREFIX) { 1516 logmsg(LOG_DEBUG, "prefix_update_k(%s) set addr %s " 1517 "for PR_AUTO on\n", 1518 pr->pr_name, 1519 inet_ntop(AF_INET6, (void *)&pr->pr_address, 1520 abuf, sizeof (abuf))); 1521 } 1522 if (ioctl(pi->pi_sock, SIOCSLIFADDR, (char *)&lifr) < 0) { 1523 logperror_pr(pr, "prefix_update_k: SIOCSLIFADDR"); 1524 return; 1525 } 1526 if (pr->pr_state & PR_ONLINK) { 1527 sin6->sin6_addr = pr->pr_prefix; 1528 lifr.lifr_addrlen = pr->pr_prefix_len; 1529 } else { 1530 sin6->sin6_addr = pr->pr_address; 1531 lifr.lifr_addrlen = IPV6_ABITS; 1532 } 1533 if (debug & D_PREFIX) { 1534 logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet " 1535 "%s/%u for PR_AUTO on\n", pr->pr_name, 1536 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, 1537 abuf, sizeof (abuf)), lifr.lifr_addrlen); 1538 } 1539 if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) { 1540 logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET"); 1541 return; 1542 } 1543 /* 1544 * For ptp interfaces, create a destination based on 1545 * prefix and prefix len together with the remote token 1546 * extracted from the remote pt-pt address. This is used by 1547 * ip to choose a proper source for outgoing packets. 1548 */ 1549 if (pi->pi_flags & IFF_POINTOPOINT) { 1550 int i; 1551 1552 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1553 bzero(sin6, sizeof (struct sockaddr_in6)); 1554 sin6->sin6_family = AF_INET6; 1555 sin6->sin6_addr = pr->pr_prefix; 1556 for (i = 0; i < 16; i++) { 1557 sin6->sin6_addr.s6_addr[i] |= 1558 pi->pi_dst_token.s6_addr[i]; 1559 } 1560 if (debug & D_PREFIX) { 1561 logmsg(LOG_DEBUG, "prefix_update_k(%s) " 1562 "set dstaddr %s for PR_AUTO on\n", 1563 pr->pr_name, inet_ntop(AF_INET6, 1564 (void *)&sin6->sin6_addr, 1565 abuf, sizeof (abuf))); 1566 } 1567 if (ioctl(pi->pi_sock, SIOCSLIFDSTADDR, 1568 (char *)&lifr) < 0) { 1569 logperror_pr(pr, 1570 "prefix_update_k: SIOCSLIFDSTADDR"); 1571 return; 1572 } 1573 } 1574 if (prefix_modify_flags(pr, IFF_UP, IFF_NOLOCAL) == -1) 1575 return; 1576 pr->pr_kernel_state |= PR_AUTO; 1577 if (pr->pr_state & PR_ONLINK) 1578 pr->pr_kernel_state |= PR_ONLINK; 1579 else 1580 pr->pr_kernel_state &= ~PR_ONLINK; 1581 } 1582 if (!(pr->pr_state & PR_AUTO) && (pr->pr_kernel_state & PR_AUTO)) { 1583 /* Turn on IFF_NOLOCAL and set the local address to all zero */ 1584 if (prefix_modify_flags(pr, IFF_NOLOCAL, 0) == -1) 1585 return; 1586 (void) strncpy(lifr.lifr_name, pr->pr_name, 1587 sizeof (lifr.lifr_name)); 1588 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1589 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1590 bzero(sin6, sizeof (struct sockaddr_in6)); 1591 sin6->sin6_family = AF_INET6; 1592 if (debug & D_PREFIX) { 1593 logmsg(LOG_DEBUG, "prefix_update_k(%s) set addr %s " 1594 "for PR_AUTO off\n", pr->pr_name, 1595 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, 1596 abuf, sizeof (abuf))); 1597 } 1598 if (ioctl(pi->pi_sock, SIOCSLIFADDR, (char *)&lifr) < 0) { 1599 logperror_pr(pr, "prefix_update_k: SIOCSLIFADDR"); 1600 return; 1601 } 1602 pr->pr_kernel_state &= ~PR_AUTO; 1603 } 1604 if ((pr->pr_state & PR_DEPRECATED) && 1605 !(pr->pr_kernel_state & PR_DEPRECATED) && 1606 (pr->pr_kernel_state & PR_AUTO)) { 1607 /* Only applies if PR_AUTO */ 1608 if (prefix_modify_flags(pr, IFF_DEPRECATED, 0) == -1) 1609 return; 1610 pr->pr_kernel_state |= PR_DEPRECATED; 1611 } 1612 if (!(pr->pr_state & PR_DEPRECATED) && 1613 (pr->pr_kernel_state & PR_DEPRECATED)) { 1614 if (prefix_modify_flags(pr, 0, IFF_DEPRECATED) == -1) 1615 return; 1616 pr->pr_kernel_state &= ~PR_DEPRECATED; 1617 } 1618 if ((pr->pr_state & PR_ONLINK) && !(pr->pr_kernel_state & PR_ONLINK)) { 1619 /* Set the subnet and set IFF_UP */ 1620 (void) strncpy(lifr.lifr_name, pr->pr_name, 1621 sizeof (lifr.lifr_name)); 1622 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1623 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1624 bzero(sin6, sizeof (struct sockaddr_in6)); 1625 sin6->sin6_family = AF_INET6; 1626 sin6->sin6_addr = pr->pr_prefix; 1627 lifr.lifr_addrlen = pr->pr_prefix_len; 1628 if (debug & D_PREFIX) { 1629 logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet " 1630 "%s/%d for PR_ONLINK on\n", pr->pr_name, 1631 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, 1632 abuf, sizeof (abuf)), lifr.lifr_addrlen); 1633 } 1634 if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) { 1635 logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET"); 1636 return; 1637 } 1638 if (!(pr->pr_state & PR_AUTO)) { 1639 if (prefix_modify_flags(pr, IFF_NOLOCAL, 0) == -1) 1640 return; 1641 } 1642 if (prefix_modify_flags(pr, IFF_UP, 0) == -1) 1643 return; 1644 pr->pr_kernel_state |= PR_ONLINK; 1645 } 1646 if (!(pr->pr_state & PR_ONLINK) && (pr->pr_kernel_state & PR_ONLINK)) { 1647 /* Set the prefixlen to 128 */ 1648 (void) strncpy(lifr.lifr_name, pr->pr_name, 1649 sizeof (lifr.lifr_name)); 1650 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1651 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1652 bzero(sin6, sizeof (struct sockaddr_in6)); 1653 sin6->sin6_family = AF_INET6; 1654 sin6->sin6_addr = pr->pr_address; 1655 lifr.lifr_addrlen = IPV6_ABITS; 1656 if (debug & D_PREFIX) { 1657 logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet " 1658 "%s/%d for PR_ONLINK off\n", pr->pr_name, 1659 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, 1660 abuf, sizeof (abuf)), lifr.lifr_addrlen); 1661 } 1662 if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) { 1663 logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET"); 1664 return; 1665 } 1666 pr->pr_kernel_state &= ~PR_ONLINK; 1667 } 1668 } 1669 1670 /* 1671 * Called with the number of millseconds elapsed since the last call. 1672 * Determines if any timeout event has occurred and 1673 * returns the number of milliseconds until the next timeout event. 1674 * Returns TIMER_INFINITY for "never". 1675 */ 1676 uint_t 1677 prefix_timer(struct prefix *pr, uint_t elapsed) 1678 { 1679 uint_t next = TIMER_INFINITY; 1680 char abuf[INET6_ADDRSTRLEN]; 1681 1682 if (debug & (D_PREFIX|D_TMP)) { 1683 logmsg(LOG_DEBUG, "prefix_timer(%s, %s/%u, %d) " 1684 "valid %d pref %d onlink %d\n", 1685 pr->pr_name, 1686 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1687 abuf, sizeof (abuf)), pr->pr_prefix_len, 1688 elapsed, pr->pr_ValidLifetime, pr->pr_PreferredLifetime, 1689 pr->pr_OnLinkLifetime); 1690 } 1691 1692 /* Exclude static prefixes */ 1693 if (pr->pr_state & PR_STATIC) 1694 return (next); 1695 1696 if (pr->pr_AutonomousFlag && 1697 (pr->pr_PreferredLifetime != PREFIX_INFINITY)) { 1698 if (pr->pr_PreferredLifetime <= elapsed) { 1699 pr->pr_PreferredLifetime = 0; 1700 } else { 1701 pr->pr_PreferredLifetime -= elapsed; 1702 if (pr->pr_PreferredLifetime < next) 1703 next = pr->pr_PreferredLifetime; 1704 } 1705 } 1706 if (pr->pr_AutonomousFlag && 1707 (pr->pr_ValidLifetime != PREFIX_INFINITY)) { 1708 if (pr->pr_ValidLifetime <= elapsed) { 1709 pr->pr_ValidLifetime = 0; 1710 } else { 1711 pr->pr_ValidLifetime -= elapsed; 1712 if (pr->pr_ValidLifetime < next) 1713 next = pr->pr_ValidLifetime; 1714 } 1715 } 1716 if (pr->pr_OnLinkFlag && 1717 (pr->pr_OnLinkLifetime != PREFIX_INFINITY)) { 1718 if (pr->pr_OnLinkLifetime <= elapsed) { 1719 pr->pr_OnLinkLifetime = 0; 1720 } else { 1721 pr->pr_OnLinkLifetime -= elapsed; 1722 if (pr->pr_OnLinkLifetime < next) 1723 next = pr->pr_OnLinkLifetime; 1724 } 1725 } 1726 if (pr->pr_AutonomousFlag && pr->pr_ValidLifetime == 0) 1727 pr->pr_state &= ~(PR_AUTO|PR_DEPRECATED); 1728 if (pr->pr_AutonomousFlag && pr->pr_PreferredLifetime == 0 && 1729 (pr->pr_state & PR_AUTO)) { 1730 pr->pr_state |= PR_DEPRECATED; 1731 if (debug & D_TMP) 1732 logmsg(LOG_WARNING, "prefix_timer: deprecated " 1733 "prefix(%s)\n", pr->pr_name); 1734 } 1735 if (pr->pr_OnLinkFlag && pr->pr_OnLinkLifetime == 0) 1736 pr->pr_state &= ~PR_ONLINK; 1737 1738 if (pr->pr_state != pr->pr_kernel_state) { 1739 /* Might cause prefix to be deleted! */ 1740 1741 /* Log a message when an addrconf prefix goes away */ 1742 if ((pr->pr_kernel_state & PR_AUTO) && 1743 !(pr->pr_state & PR_AUTO)) { 1744 char abuf[INET6_ADDRSTRLEN]; 1745 1746 logmsg(LOG_WARNING, 1747 "Address removed due to timeout %s\n", 1748 inet_ntop(AF_INET6, (void *)&pr->pr_address, 1749 abuf, sizeof (abuf))); 1750 } 1751 prefix_update_k(pr); 1752 } 1753 1754 return (next); 1755 } 1756 1757 static char * 1758 prefix_print_state(int state, char *buf, int buflen) 1759 { 1760 char *cp; 1761 int cplen = buflen; 1762 1763 cp = buf; 1764 cp[0] = '\0'; 1765 1766 if (state & PR_ONLINK) { 1767 if (strlcat(cp, "ONLINK ", cplen) >= cplen) 1768 return (buf); 1769 cp += strlen(cp); 1770 cplen = buflen - (cp - buf); 1771 } 1772 if (state & PR_AUTO) { 1773 if (strlcat(cp, "AUTO ", cplen) >= cplen) 1774 return (buf); 1775 cp += strlen(cp); 1776 cplen = buflen - (cp - buf); 1777 } 1778 if (state & PR_DEPRECATED) { 1779 if (strlcat(cp, "DEPRECATED ", cplen) >= cplen) 1780 return (buf); 1781 cp += strlen(cp); 1782 cplen = buflen - (cp - buf); 1783 } 1784 if (state & PR_STATIC) { 1785 if (strlcat(cp, "STATIC ", cplen) >= cplen) 1786 return (buf); 1787 cp += strlen(cp); 1788 cplen = buflen - (cp - buf); 1789 } 1790 return (buf); 1791 } 1792 1793 static void 1794 prefix_print(struct prefix *pr) 1795 { 1796 char abuf[INET6_ADDRSTRLEN]; 1797 char buf1[PREFIX_STATESTRLEN], buf2[PREFIX_STATESTRLEN]; 1798 1799 logmsg(LOG_DEBUG, "Prefix name: %s prefix %s/%u state %s " 1800 "kernel_state %s\n", pr->pr_name, 1801 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, abuf, sizeof (abuf)), 1802 pr->pr_prefix_len, 1803 prefix_print_state(pr->pr_state, buf2, sizeof (buf2)), 1804 prefix_print_state(pr->pr_kernel_state, buf1, sizeof (buf1))); 1805 logmsg(LOG_DEBUG, "\tAddress: %s flags %llx in_use %d\n", 1806 inet_ntop(AF_INET6, (void *)&pr->pr_address, abuf, sizeof (abuf)), 1807 pr->pr_flags, pr->pr_in_use); 1808 logmsg(LOG_DEBUG, "\tValidLifetime %u PreferredLifetime %u " 1809 "OnLinkLifetime %u\n", pr->pr_ValidLifetime, 1810 pr->pr_PreferredLifetime, pr->pr_OnLinkLifetime); 1811 logmsg(LOG_DEBUG, "\tOnLink %d Auto %d\n", 1812 pr->pr_OnLinkFlag, pr->pr_AutonomousFlag); 1813 logmsg(LOG_DEBUG, "\n"); 1814 } 1815 1816 /* 1817 * Does the address formed by pr->pr_prefix and pi->pi_token match 1818 * pr->pr_address. It does not match if a failover has happened 1819 * earlier (done by in.mpathd) from a different pi. Should not 1820 * be called for onlink prefixes. 1821 */ 1822 boolean_t 1823 prefix_token_match(struct phyint *pi, struct prefix *pr, uint64_t flags) 1824 { 1825 int i; 1826 in6_addr_t addr, *token; 1827 1828 if (flags & IFF_TEMPORARY) 1829 token = &pi->pi_tmp_token; 1830 else 1831 token = &pi->pi_token; 1832 for (i = 0; i < 16; i++) { 1833 /* 1834 * prefix_create ensures that pr_prefix has all-zero 1835 * bits after prefixlen. 1836 */ 1837 addr.s6_addr[i] = pr->pr_prefix.s6_addr[i] | token->s6_addr[i]; 1838 } 1839 if (IN6_ARE_ADDR_EQUAL(&pr->pr_address, &addr)) { 1840 return (_B_TRUE); 1841 } else { 1842 return (_B_FALSE); 1843 } 1844 } 1845 1846 /* 1847 * Lookup advertisement prefix structure that matches the prefix and 1848 * prefix length. 1849 * Assumes that the bits after prefixlen might not be zero. 1850 */ 1851 struct adv_prefix * 1852 adv_prefix_lookup(struct phyint *pi, struct in6_addr prefix, int prefixlen) 1853 { 1854 struct adv_prefix *adv_pr; 1855 char abuf[INET6_ADDRSTRLEN]; 1856 1857 if (debug & D_PREFIX) { 1858 logmsg(LOG_DEBUG, "adv_prefix_lookup(%s, %s/%u)\n", 1859 pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix, 1860 abuf, sizeof (abuf)), prefixlen); 1861 } 1862 1863 for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL; 1864 adv_pr = adv_pr->adv_pr_next) { 1865 if (adv_pr->adv_pr_prefix_len == prefixlen && 1866 prefix_equal(prefix, adv_pr->adv_pr_prefix, prefixlen)) 1867 return (adv_pr); 1868 } 1869 return (NULL); 1870 } 1871 1872 /* 1873 * Initialize a new advertisement prefix. 1874 */ 1875 struct adv_prefix * 1876 adv_prefix_create(struct phyint *pi, struct in6_addr prefix, int prefixlen) 1877 { 1878 struct adv_prefix *adv_pr; 1879 char abuf[INET6_ADDRSTRLEN]; 1880 1881 if (debug & D_PREFIX) { 1882 logmsg(LOG_DEBUG, "adv_prefix_create(%s, %s/%u)\n", 1883 pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix, 1884 abuf, sizeof (abuf)), prefixlen); 1885 } 1886 adv_pr = (struct adv_prefix *)calloc(sizeof (struct adv_prefix), 1); 1887 if (adv_pr == NULL) { 1888 logmsg(LOG_ERR, "adv_prefix_create: calloc\n"); 1889 return (NULL); 1890 } 1891 /* 1892 * The prefix might have non-zero bits after the prefix len bits. 1893 * Force them to be zero. 1894 */ 1895 prefix_set(&adv_pr->adv_pr_prefix, prefix, prefixlen); 1896 adv_pr->adv_pr_prefix_len = prefixlen; 1897 adv_prefix_insert(pi, adv_pr); 1898 return (adv_pr); 1899 } 1900 1901 /* Insert in linked list */ 1902 static void 1903 adv_prefix_insert(struct phyint *pi, struct adv_prefix *adv_pr) 1904 { 1905 adv_pr->adv_pr_next = pi->pi_adv_prefix_list; 1906 adv_pr->adv_pr_prev = NULL; 1907 if (pi->pi_adv_prefix_list != NULL) 1908 pi->pi_adv_prefix_list->adv_pr_prev = adv_pr; 1909 pi->pi_adv_prefix_list = adv_pr; 1910 adv_pr->adv_pr_physical = pi; 1911 } 1912 1913 /* 1914 * Delete (unlink and free) from our tables. There should be 1915 * a corresponding "struct prefix *" which will clean up the kernel 1916 * if necessary. adv_prefix is just used for sending out advertisements. 1917 */ 1918 static void 1919 adv_prefix_delete(struct adv_prefix *adv_pr) 1920 { 1921 struct phyint *pi; 1922 char abuf[INET6_ADDRSTRLEN]; 1923 1924 if (debug & D_PREFIX) { 1925 logmsg(LOG_DEBUG, "adv_prefix_delete(%s, %s/%u)\n", 1926 adv_pr->adv_pr_physical->pi_name, 1927 inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix, 1928 abuf, sizeof (abuf)), adv_pr->adv_pr_prefix_len); 1929 } 1930 pi = adv_pr->adv_pr_physical; 1931 1932 if (adv_pr->adv_pr_prev == NULL) { 1933 if (pi != NULL) 1934 pi->pi_adv_prefix_list = adv_pr->adv_pr_next; 1935 } else { 1936 adv_pr->adv_pr_prev->adv_pr_next = adv_pr->adv_pr_next; 1937 } 1938 if (adv_pr->adv_pr_next != NULL) 1939 adv_pr->adv_pr_next->adv_pr_prev = adv_pr->adv_pr_prev; 1940 adv_pr->adv_pr_next = adv_pr->adv_pr_prev = NULL; 1941 free(adv_pr); 1942 } 1943 1944 /* 1945 * Called with the number of millseconds elapsed since the last call. 1946 * Determines if any timeout event has occurred and 1947 * returns the number of milliseconds until the next timeout event. 1948 * Returns TIMER_INFINITY for "never". 1949 */ 1950 uint_t 1951 adv_prefix_timer(struct adv_prefix *adv_pr, uint_t elapsed) 1952 { 1953 int seconds_elapsed = (elapsed + 500) / 1000; /* Rounded */ 1954 char abuf[INET6_ADDRSTRLEN]; 1955 1956 if (debug & D_PREFIX) { 1957 logmsg(LOG_DEBUG, "adv_prefix_timer(%s, %s/%u, %d)\n", 1958 adv_pr->adv_pr_physical->pi_name, 1959 inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix, 1960 abuf, sizeof (abuf)), adv_pr->adv_pr_prefix_len, 1961 elapsed); 1962 } 1963 1964 /* Decrement Expire time left for real-time lifetimes */ 1965 if (adv_pr->adv_pr_AdvValidRealTime) { 1966 if (adv_pr->adv_pr_AdvValidExpiration > seconds_elapsed) 1967 adv_pr->adv_pr_AdvValidExpiration -= seconds_elapsed; 1968 else 1969 adv_pr->adv_pr_AdvValidExpiration = 0; 1970 } 1971 if (adv_pr->adv_pr_AdvPreferredRealTime) { 1972 if (adv_pr->adv_pr_AdvPreferredExpiration > seconds_elapsed) { 1973 adv_pr->adv_pr_AdvPreferredExpiration -= 1974 seconds_elapsed; 1975 } else { 1976 adv_pr->adv_pr_AdvPreferredExpiration = 0; 1977 } 1978 } 1979 return (TIMER_INFINITY); 1980 } 1981 1982 static void 1983 adv_prefix_print(struct adv_prefix *adv_pr) 1984 { 1985 print_prefixlist(adv_pr->adv_pr_config); 1986 } 1987 1988 /* Lookup router on its link-local IPv6 address */ 1989 struct router * 1990 router_lookup(struct phyint *pi, struct in6_addr addr) 1991 { 1992 struct router *dr; 1993 char abuf[INET6_ADDRSTRLEN]; 1994 1995 if (debug & D_ROUTER) { 1996 logmsg(LOG_DEBUG, "router_lookup(%s, %s)\n", pi->pi_name, 1997 inet_ntop(AF_INET6, (void *)&addr, 1998 abuf, sizeof (abuf))); 1999 } 2000 2001 for (dr = pi->pi_router_list; dr != NULL; dr = dr->dr_next) { 2002 if (bcmp((char *)&addr, (char *)&dr->dr_address, 2003 sizeof (addr)) == 0) 2004 return (dr); 2005 } 2006 return (NULL); 2007 } 2008 2009 /* 2010 * Create a default router entry. 2011 * The lifetime parameter is in seconds. 2012 */ 2013 struct router * 2014 router_create(struct phyint *pi, struct in6_addr addr, uint_t lifetime) 2015 { 2016 struct router *dr; 2017 char abuf[INET6_ADDRSTRLEN]; 2018 2019 if (debug & D_ROUTER) { 2020 logmsg(LOG_DEBUG, "router_create(%s, %s, %u)\n", pi->pi_name, 2021 inet_ntop(AF_INET6, (void *)&addr, 2022 abuf, sizeof (abuf)), lifetime); 2023 } 2024 2025 dr = (struct router *)calloc(sizeof (struct router), 1); 2026 if (dr == NULL) { 2027 logmsg(LOG_ERR, "router_create: out of memory\n"); 2028 return (NULL); 2029 } 2030 dr->dr_address = addr; 2031 dr->dr_lifetime = lifetime; 2032 router_insert(pi, dr); 2033 if (dr->dr_lifetime != 0) 2034 router_add_k(dr); 2035 return (dr); 2036 } 2037 2038 /* Insert in linked list */ 2039 static void 2040 router_insert(struct phyint *pi, struct router *dr) 2041 { 2042 dr->dr_next = pi->pi_router_list; 2043 dr->dr_prev = NULL; 2044 if (pi->pi_router_list != NULL) 2045 pi->pi_router_list->dr_prev = dr; 2046 pi->pi_router_list = dr; 2047 dr->dr_physical = pi; 2048 } 2049 2050 /* 2051 * Delete (unlink and free). 2052 * Handles delete of things that have not yet been inserted in the list 2053 * i.e. dr_physical is NULL. 2054 */ 2055 static void 2056 router_delete(struct router *dr) 2057 { 2058 struct phyint *pi; 2059 char abuf[INET6_ADDRSTRLEN]; 2060 2061 if (debug & D_ROUTER) { 2062 logmsg(LOG_DEBUG, "router_delete(%s, %s, %u)\n", 2063 dr->dr_physical->pi_name, 2064 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2065 abuf, sizeof (abuf)), dr->dr_lifetime); 2066 } 2067 pi = dr->dr_physical; 2068 if (dr->dr_inkernel && (pi->pi_kernel_state & PI_PRESENT)) 2069 router_delete_k(dr); 2070 2071 if (dr->dr_prev == NULL) { 2072 if (pi != NULL) 2073 pi->pi_router_list = dr->dr_next; 2074 } else { 2075 dr->dr_prev->dr_next = dr->dr_next; 2076 } 2077 if (dr->dr_next != NULL) 2078 dr->dr_next->dr_prev = dr->dr_prev; 2079 dr->dr_next = dr->dr_prev = NULL; 2080 free(dr); 2081 } 2082 2083 /* 2084 * Update the kernel to match dr_lifetime 2085 */ 2086 void 2087 router_update_k(struct router *dr) 2088 { 2089 char abuf[INET6_ADDRSTRLEN]; 2090 2091 if (debug & D_ROUTER) { 2092 logmsg(LOG_DEBUG, "router_update_k(%s, %s, %u)\n", 2093 dr->dr_physical->pi_name, 2094 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2095 abuf, sizeof (abuf)), dr->dr_lifetime); 2096 } 2097 2098 if (dr->dr_lifetime == 0 && dr->dr_inkernel) { 2099 /* Log a message when last router goes away */ 2100 if (dr->dr_physical->pi_num_k_routers == 1) { 2101 logmsg(LOG_WARNING, 2102 "Last default router (%s) removed on %s\n", 2103 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2104 abuf, sizeof (abuf)), dr->dr_physical->pi_name); 2105 } 2106 router_delete(dr); 2107 } else if (dr->dr_lifetime != 0 && !dr->dr_inkernel) 2108 router_add_k(dr); 2109 } 2110 2111 2112 /* 2113 * Called with the number of millseconds elapsed since the last call. 2114 * Determines if any timeout event has occurred and 2115 * returns the number of milliseconds until the next timeout event. 2116 * Returns TIMER_INFINITY for "never". 2117 */ 2118 uint_t 2119 router_timer(struct router *dr, uint_t elapsed) 2120 { 2121 uint_t next = TIMER_INFINITY; 2122 char abuf[INET6_ADDRSTRLEN]; 2123 2124 if (debug & D_ROUTER) { 2125 logmsg(LOG_DEBUG, "router_timer(%s, %s, %u, %d)\n", 2126 dr->dr_physical->pi_name, 2127 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2128 abuf, sizeof (abuf)), dr->dr_lifetime, elapsed); 2129 } 2130 if (dr->dr_lifetime <= elapsed) { 2131 dr->dr_lifetime = 0; 2132 } else { 2133 dr->dr_lifetime -= elapsed; 2134 if (dr->dr_lifetime < next) 2135 next = dr->dr_lifetime; 2136 } 2137 2138 if (dr->dr_lifetime == 0) { 2139 /* Log a message when last router goes away */ 2140 if (dr->dr_physical->pi_num_k_routers == 1) { 2141 logmsg(LOG_WARNING, 2142 "Last default router (%s) timed out on %s\n", 2143 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2144 abuf, sizeof (abuf)), dr->dr_physical->pi_name); 2145 } 2146 router_delete(dr); 2147 } 2148 return (next); 2149 } 2150 2151 /* 2152 * Add a default route to the kernel (unless the lifetime is zero) 2153 * Handles onlink default routes. 2154 */ 2155 static void 2156 router_add_k(struct router *dr) 2157 { 2158 struct phyint *pi = dr->dr_physical; 2159 char abuf[INET6_ADDRSTRLEN]; 2160 int rlen; 2161 2162 if (debug & D_ROUTER) { 2163 logmsg(LOG_DEBUG, "router_add_k(%s, %s, %u)\n", 2164 dr->dr_physical->pi_name, 2165 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2166 abuf, sizeof (abuf)), dr->dr_lifetime); 2167 } 2168 2169 rta_gateway->sin6_addr = dr->dr_address; 2170 2171 rta_ifp->sdl_index = if_nametoindex(pi->pi_name); 2172 if (rta_ifp->sdl_index == 0) { 2173 logperror_pi(pi, "router_add_k: if_nametoindex"); 2174 return; 2175 } 2176 2177 rt_msg->rtm_flags = RTF_GATEWAY; 2178 rt_msg->rtm_type = RTM_ADD; 2179 rt_msg->rtm_seq = ++rtmseq; 2180 rlen = write(rtsock, rt_msg, rt_msg->rtm_msglen); 2181 if (rlen < 0) { 2182 if (errno != EEXIST) { 2183 logperror_pi(pi, "router_add_k: RTM_ADD"); 2184 return; 2185 } 2186 } else if (rlen < rt_msg->rtm_msglen) { 2187 logmsg(LOG_ERR, "router_add_k: write to routing socket got " 2188 "only %d for rlen (interface %s)\n", rlen, pi->pi_name); 2189 return; 2190 } 2191 dr->dr_inkernel = _B_TRUE; 2192 pi->pi_num_k_routers++; 2193 } 2194 2195 /* 2196 * Delete a route from the kernel. 2197 * Handles onlink default routes. 2198 */ 2199 static void 2200 router_delete_k(struct router *dr) 2201 { 2202 struct phyint *pi = dr->dr_physical; 2203 char abuf[INET6_ADDRSTRLEN]; 2204 int rlen; 2205 2206 if (debug & D_ROUTER) { 2207 logmsg(LOG_DEBUG, "router_delete_k(%s, %s, %u)\n", 2208 dr->dr_physical->pi_name, 2209 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2210 abuf, sizeof (abuf)), dr->dr_lifetime); 2211 } 2212 2213 rta_gateway->sin6_addr = dr->dr_address; 2214 2215 rta_ifp->sdl_index = if_nametoindex(pi->pi_name); 2216 if (rta_ifp->sdl_index == 0) { 2217 logperror_pi(pi, "router_delete_k: if_nametoindex"); 2218 return; 2219 } 2220 2221 rt_msg->rtm_flags = RTF_GATEWAY; 2222 rt_msg->rtm_type = RTM_DELETE; 2223 rt_msg->rtm_seq = ++rtmseq; 2224 rlen = write(rtsock, rt_msg, rt_msg->rtm_msglen); 2225 if (rlen < 0) { 2226 if (errno != ESRCH) { 2227 logperror_pi(pi, "router_delete_k: RTM_DELETE"); 2228 } 2229 } else if (rlen < rt_msg->rtm_msglen) { 2230 logmsg(LOG_ERR, "router_delete_k: write to routing socket got " 2231 "only %d for rlen (interface %s)\n", rlen, pi->pi_name); 2232 } 2233 dr->dr_inkernel = _B_FALSE; 2234 pi->pi_num_k_routers--; 2235 } 2236 2237 2238 static void 2239 router_print(struct router *dr) 2240 { 2241 char abuf[INET6_ADDRSTRLEN]; 2242 2243 logmsg(LOG_DEBUG, "Router %s on %s inkernel %d lifetime %u\n", 2244 inet_ntop(AF_INET6, (void *)&dr->dr_address, abuf, sizeof (abuf)), 2245 dr->dr_physical->pi_name, dr->dr_inkernel, dr->dr_lifetime); 2246 } 2247 2248 2249 void 2250 phyint_print_all(void) 2251 { 2252 struct phyint *pi; 2253 2254 for (pi = phyints; pi != NULL; pi = pi->pi_next) { 2255 phyint_print(pi); 2256 } 2257 } 2258 2259 void 2260 phyint_cleanup(pi) 2261 struct phyint *pi; 2262 { 2263 pi->pi_state = 0; 2264 pi->pi_kernel_state = 0; 2265 2266 if (pi->pi_AdvSendAdvertisements) { 2267 check_to_advertise(pi, ADV_OFF); 2268 } else { 2269 check_to_solicit(pi, SOLICIT_OFF); 2270 } 2271 2272 while (pi->pi_router_list) 2273 router_delete(pi->pi_router_list); 2274 (void) poll_remove(pi->pi_sock); 2275 (void) close(pi->pi_sock); 2276 pi->pi_sock = -1; 2277 } 2278