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