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