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