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