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