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 2007 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 cannot derive the lifetime from 1196 * the kernel, thus it is set to 1 week. 1197 * Ignore the prefix if the interface is not IFF_UP. 1198 * If it's from DHCPv6, then we set the netmask. 1199 */ 1200 int 1201 prefix_init_from_k(struct prefix *pr) 1202 { 1203 struct lifreq lifr; 1204 struct sockaddr_in6 *sin6; 1205 int sock = pr->pr_physical->pi_sock; 1206 1207 (void) strncpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name)); 1208 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1209 if (ioctl(sock, SIOCGLIFADDR, (char *)&lifr) < 0) { 1210 logperror_pr(pr, "prefix_init_from_k: ioctl (get addr)"); 1211 goto error; 1212 } 1213 if (lifr.lifr_addr.ss_family != AF_INET6) { 1214 logmsg(LOG_ERR, "ignoring interface %s: not AF_INET6\n", 1215 pr->pr_name); 1216 goto error; 1217 } 1218 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1219 pr->pr_address = sin6->sin6_addr; 1220 1221 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 1222 logperror_pr(pr, "prefix_init_from_k: ioctl (get flags)"); 1223 goto error; 1224 } 1225 pr->pr_flags = lifr.lifr_flags; 1226 1227 /* 1228 * If this is a DHCPv6 interface, then we control the netmask. 1229 */ 1230 if (lifr.lifr_flags & IFF_DHCPRUNNING) { 1231 struct phyint *pi = pr->pr_physical; 1232 struct prefix *pr2; 1233 1234 pr->pr_prefix_len = IPV6_ABITS; 1235 if (!(lifr.lifr_flags & IFF_UP) || 1236 IN6_IS_ADDR_UNSPECIFIED(&pr->pr_address) || 1237 IN6_IS_ADDR_LINKLOCAL(&pr->pr_address)) { 1238 if (debug & D_DHCP) 1239 logmsg(LOG_DEBUG, "prefix_init_from_k: " 1240 "ignoring DHCP %s not ready\n", 1241 pr->pr_name); 1242 return (0); 1243 } 1244 1245 for (pr2 = pi->pi_prefix_list; pr2 != NULL; 1246 pr2 = pr2->pr_next) { 1247 /* 1248 * Examine any non-static (autoconfigured) prefixes as 1249 * well as existing DHCP-controlled prefixes for valid 1250 * prefix length information. 1251 */ 1252 if (pr2->pr_prefix_len != IPV6_ABITS && 1253 (!(pr2->pr_state & PR_STATIC) || 1254 (pr2->pr_flags & IFF_DHCPRUNNING)) && 1255 prefix_equal(pr->pr_prefix, pr2->pr_prefix, 1256 pr2->pr_prefix_len)) { 1257 pr->pr_prefix_len = pr2->pr_prefix_len; 1258 break; 1259 } 1260 } 1261 if (pr2 == NULL) { 1262 if (debug & D_DHCP) 1263 logmsg(LOG_DEBUG, "prefix_init_from_k: no " 1264 "saved mask for DHCP %s; need to " 1265 "resolicit\n", pr->pr_name); 1266 (void) check_to_solicit(pi, RESTART_INIT_SOLICIT); 1267 } else { 1268 if (debug & D_DHCP) 1269 logmsg(LOG_DEBUG, "prefix_init_from_k: using " 1270 "%s mask for DHCP %s\n", 1271 pr2->pr_name[0] == '\0' ? "saved" : 1272 pr2->pr_name, pr->pr_name); 1273 prefix_update_dhcp(pr); 1274 } 1275 } else { 1276 if (ioctl(sock, SIOCGLIFSUBNET, (char *)&lifr) < 0) { 1277 logperror_pr(pr, 1278 "prefix_init_from_k: ioctl (get subnet)"); 1279 goto error; 1280 } 1281 if (lifr.lifr_subnet.ss_family != AF_INET6) { 1282 logmsg(LOG_ERR, 1283 "ignoring interface %s: not AF_INET6\n", 1284 pr->pr_name); 1285 goto error; 1286 } 1287 /* 1288 * Guard against the prefix having non-zero bits after the 1289 * prefix len bits. 1290 */ 1291 sin6 = (struct sockaddr_in6 *)&lifr.lifr_subnet; 1292 pr->pr_prefix_len = lifr.lifr_addrlen; 1293 prefix_set(&pr->pr_prefix, sin6->sin6_addr, pr->pr_prefix_len); 1294 1295 if (pr->pr_prefix_len != IPV6_ABITS && 1296 (pr->pr_flags & IFF_UP) && 1297 IN6_ARE_ADDR_EQUAL(&pr->pr_address, &pr->pr_prefix)) { 1298 char abuf[INET6_ADDRSTRLEN]; 1299 1300 logmsg(LOG_ERR, "ingoring interface %s: it appears to " 1301 "be configured with an invalid interface id " 1302 "(%s/%u)\n", 1303 pr->pr_name, 1304 inet_ntop(AF_INET6, (void *)&pr->pr_address, 1305 abuf, sizeof (abuf)), pr->pr_prefix_len); 1306 goto error; 1307 } 1308 } 1309 pr->pr_kernel_state = 0; 1310 if (pr->pr_prefix_len != IPV6_ABITS) 1311 pr->pr_kernel_state |= PR_ONLINK; 1312 if (!(pr->pr_flags & (IFF_NOLOCAL | IFF_DHCPRUNNING))) 1313 pr->pr_kernel_state |= PR_AUTO; 1314 if ((pr->pr_flags & IFF_DEPRECATED) && (pr->pr_kernel_state & PR_AUTO)) 1315 pr->pr_kernel_state |= PR_DEPRECATED; 1316 if (!(pr->pr_flags & IFF_ADDRCONF)) { 1317 /* Prevent ndpd from stepping on this prefix */ 1318 pr->pr_kernel_state |= PR_STATIC; 1319 } 1320 pr->pr_state = pr->pr_kernel_state; 1321 /* Adjust pr_prefix_len based if PR_AUTO is set */ 1322 if (pr->pr_state & PR_AUTO) { 1323 pr->pr_prefix_len = 1324 IPV6_ABITS - pr->pr_physical->pi_token_length; 1325 prefix_set(&pr->pr_prefix, pr->pr_prefix, pr->pr_prefix_len); 1326 } 1327 1328 /* Can't extract lifetimes from the kernel - use 1 week */ 1329 pr->pr_ValidLifetime = NDP_PREFIX_DEFAULT_LIFETIME; 1330 pr->pr_PreferredLifetime = NDP_PREFIX_DEFAULT_LIFETIME; 1331 pr->pr_OnLinkLifetime = NDP_PREFIX_DEFAULT_LIFETIME; 1332 1333 /* 1334 * If this is a temp addr, the creation time needs to be set. 1335 * Though it won't be entirely accurate, the current time is 1336 * an okay approximation. 1337 */ 1338 if (pr->pr_flags & IFF_TEMPORARY) 1339 pr->pr_CreateTime = getcurrenttime() / MILLISEC; 1340 1341 if (pr->pr_kernel_state == 0) 1342 pr->pr_name[0] = '\0'; 1343 return (0); 1344 1345 error: 1346 /* Pretend that the prefix does not exist in the kernel */ 1347 pr->pr_kernel_state = 0; 1348 pr->pr_name[0] = '\0'; 1349 return (-1); 1350 } 1351 1352 /* 1353 * Delete (unlink and free) and remove from kernel if the prefix 1354 * was added by in.ndpd (i.e. PR_STATIC is not set). 1355 * Handles delete of things that have not yet been inserted in the list 1356 * i.e. pr_physical is NULL. 1357 */ 1358 void 1359 prefix_delete(struct prefix *pr) 1360 { 1361 struct phyint *pi; 1362 char abuf[INET6_ADDRSTRLEN]; 1363 1364 if (debug & D_PREFIX) { 1365 logmsg(LOG_DEBUG, "prefix_delete(%s, %s, %s/%u)\n", 1366 pr->pr_physical->pi_name, pr->pr_name, 1367 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1368 abuf, sizeof (abuf)), pr->pr_prefix_len); 1369 } 1370 /* Remove non-static prefixes from the kernel. */ 1371 pr->pr_state &= PR_STATIC; 1372 pi = pr->pr_physical; 1373 if (pr->pr_kernel_state != pr->pr_state) 1374 prefix_update_k(pr); 1375 1376 if (pr->pr_prev == NULL) { 1377 if (pi != NULL) 1378 pi->pi_prefix_list = pr->pr_next; 1379 } else { 1380 pr->pr_prev->pr_next = pr->pr_next; 1381 } 1382 if (pr->pr_next != NULL) 1383 pr->pr_next->pr_prev = pr->pr_prev; 1384 pr->pr_next = pr->pr_prev = NULL; 1385 free(pr); 1386 } 1387 1388 /* 1389 * Toggle one or more IFF_ flags for a prefix. Turn on 'onflags' and 1390 * turn off 'offflags'. 1391 */ 1392 static int 1393 prefix_modify_flags(struct prefix *pr, uint64_t onflags, uint64_t offflags) 1394 { 1395 struct lifreq lifr; 1396 struct phyint *pi = pr->pr_physical; 1397 uint64_t old_flags; 1398 char abuf[INET6_ADDRSTRLEN]; 1399 1400 if (debug & D_PREFIX) { 1401 logmsg(LOG_DEBUG, "prefix_modify_flags(%s, %s, %s/%u) " 1402 "flags %llx on %llx off %llx\n", 1403 pr->pr_physical->pi_name, 1404 pr->pr_name, 1405 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1406 abuf, sizeof (abuf)), pr->pr_prefix_len, 1407 pr->pr_flags, onflags, offflags); 1408 } 1409 /* Assumes that only the PR_STATIC link-local matches the pi_name */ 1410 if (!(pr->pr_state & PR_STATIC) && 1411 strcmp(pr->pr_name, pi->pi_name) == 0) { 1412 logmsg(LOG_ERR, "prefix_modify_flags(%s, on %llx, off %llx): " 1413 "name matches interface name\n", 1414 pi->pi_name, onflags, offflags); 1415 return (-1); 1416 } 1417 1418 (void) strncpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name)); 1419 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1420 if (ioctl(pi->pi_sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 1421 logperror_pr(pr, "prefix_modify_flags: SIOCGLIFFLAGS"); 1422 logmsg(LOG_ERR, "prefix_modify_flags(%s, %s) old 0x%llx " 1423 "on 0x%llx off 0x%llx\n", 1424 pr->pr_physical->pi_name, 1425 pr->pr_name, 1426 pr->pr_flags, onflags, offflags); 1427 return (-1); 1428 } 1429 old_flags = lifr.lifr_flags; 1430 lifr.lifr_flags |= onflags; 1431 lifr.lifr_flags &= ~offflags; 1432 pr->pr_flags = lifr.lifr_flags; 1433 if (ioctl(pi->pi_sock, SIOCSLIFFLAGS, (char *)&lifr) < 0) { 1434 logperror_pr(pr, "prefix_modify_flags: SIOCSLIFFLAGS"); 1435 logmsg(LOG_ERR, "prefix_modify_flags(%s, %s) old 0x%llx " 1436 "new 0x%llx on 0x%llx off 0x%llx\n", 1437 pr->pr_physical->pi_name, 1438 pr->pr_name, 1439 old_flags, lifr.lifr_flags, onflags, offflags); 1440 return (-1); 1441 } 1442 return (0); 1443 } 1444 1445 /* 1446 * Update the subnet mask for this interface under DHCPv6 control. 1447 */ 1448 void 1449 prefix_update_dhcp(struct prefix *pr) 1450 { 1451 struct lifreq lifr; 1452 1453 (void) memset(&lifr, 0, sizeof (lifr)); 1454 (void) strlcpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name)); 1455 lifr.lifr_addr.ss_family = AF_INET6; 1456 prefix_set(&((struct sockaddr_in6 *)&lifr.lifr_addr)->sin6_addr, 1457 pr->pr_address, pr->pr_prefix_len); 1458 lifr.lifr_addrlen = pr->pr_prefix_len; 1459 /* 1460 * Ignore ENXIO, as the dhcpagent process is responsible for plumbing 1461 * and unplumbing these. 1462 */ 1463 if (ioctl(pr->pr_physical->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) == 1464 -1 && errno != ENXIO) 1465 logperror_pr(pr, "prefix_update_dhcp: ioctl (set subnet)"); 1466 } 1467 1468 /* 1469 * Make the kernel state match what is in the prefix structure. 1470 * This includes creating the prefix (allocating a new interface name) 1471 * as well as setting the local address and on-link subnet prefix 1472 * and controlling the IFF_ADDRCONF and IFF_DEPRECATED flags. 1473 */ 1474 void 1475 prefix_update_k(struct prefix *pr) 1476 { 1477 struct lifreq lifr; 1478 char abuf[INET6_ADDRSTRLEN]; 1479 char buf1[PREFIX_STATESTRLEN], buf2[PREFIX_STATESTRLEN]; 1480 struct phyint *pi = pr->pr_physical; 1481 struct sockaddr_in6 *sin6; 1482 1483 if (debug & D_PREFIX) { 1484 logmsg(LOG_DEBUG, "prefix_update_k(%s, %s, %s/%u) " 1485 "from %s to %s\n", pr->pr_physical->pi_name, pr->pr_name, 1486 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1487 abuf, sizeof (abuf)), pr->pr_prefix_len, 1488 prefix_print_state(pr->pr_kernel_state, buf1, 1489 sizeof (buf1)), 1490 prefix_print_state(pr->pr_state, buf2, sizeof (buf2))); 1491 } 1492 1493 if (pr->pr_kernel_state == pr->pr_state) 1494 return; /* No changes */ 1495 1496 /* Skip static prefixes */ 1497 if (pr->pr_state & PR_STATIC) 1498 return; 1499 1500 if (pr->pr_kernel_state == 0) { 1501 uint64_t onflags; 1502 /* 1503 * Create a new logical interface name and store in pr_name. 1504 * Set IFF_ADDRCONF. Do not set an address (yet). 1505 */ 1506 if (pr->pr_name[0] != '\0') { 1507 /* Name already set! */ 1508 logmsg(LOG_ERR, "prefix_update_k(%s, %s, %s/%u) " 1509 "from %s to %s name is already allocated\n", 1510 pr->pr_physical->pi_name, pr->pr_name, 1511 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1512 abuf, sizeof (abuf)), pr->pr_prefix_len, 1513 prefix_print_state(pr->pr_kernel_state, buf1, 1514 sizeof (buf1)), 1515 prefix_print_state(pr->pr_state, buf2, 1516 sizeof (buf2))); 1517 return; 1518 } 1519 1520 (void) strncpy(lifr.lifr_name, pi->pi_name, 1521 sizeof (lifr.lifr_name)); 1522 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1523 lifr.lifr_addr.ss_family = AF_UNSPEC; 1524 if (ioctl(pi->pi_sock, SIOCLIFADDIF, (char *)&lifr) < 0) { 1525 logperror_pr(pr, "prefix_update_k: SIOCLIFADDIF"); 1526 return; 1527 } 1528 (void) strncpy(pr->pr_name, lifr.lifr_name, 1529 sizeof (pr->pr_name)); 1530 pr->pr_name[sizeof (pr->pr_name) - 1] = '\0'; 1531 if (debug & D_PREFIX) { 1532 logmsg(LOG_DEBUG, "prefix_update_k: new name %s\n", 1533 pr->pr_name); 1534 } 1535 /* 1536 * The IFF_TEMPORARY flag might have already been set; if 1537 * so, it needs to be or'd into the flags we're turning on. 1538 * But be careful, we might be re-creating a manually 1539 * removed interface, in which case we don't want to try 1540 * to set *all* the flags we might have in our copy of the 1541 * flags yet. 1542 */ 1543 onflags = IFF_ADDRCONF; 1544 if (pr->pr_flags & IFF_TEMPORARY) 1545 onflags |= IFF_TEMPORARY; 1546 if (prefix_modify_flags(pr, onflags, 0) == -1) 1547 return; 1548 } 1549 if ((pr->pr_state & (PR_ONLINK|PR_AUTO)) == 0) { 1550 /* Remove the interface */ 1551 if (prefix_modify_flags(pr, 0, IFF_UP|IFF_DEPRECATED) == -1) 1552 return; 1553 (void) strncpy(lifr.lifr_name, pr->pr_name, 1554 sizeof (lifr.lifr_name)); 1555 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1556 1557 if (debug & D_PREFIX) { 1558 logmsg(LOG_DEBUG, "prefix_update_k: remove name %s\n", 1559 pr->pr_name); 1560 } 1561 1562 /* 1563 * Assumes that only the PR_STATIC link-local matches 1564 * the pi_name 1565 */ 1566 if (!(pr->pr_state & PR_STATIC) && 1567 strcmp(pr->pr_name, pi->pi_name) == 0) { 1568 logmsg(LOG_ERR, "prefix_update_k(%s): " 1569 "name matches if\n", pi->pi_name); 1570 return; 1571 } 1572 1573 /* Remove logical interface based on pr_name */ 1574 lifr.lifr_addr.ss_family = AF_UNSPEC; 1575 if (ioctl(pi->pi_sock, SIOCLIFREMOVEIF, (char *)&lifr) < 0) { 1576 logperror_pr(pr, "prefix_update_k: SIOCLIFREMOVEIF"); 1577 } 1578 pr->pr_kernel_state = 0; 1579 pr->pr_name[0] = '\0'; 1580 return; 1581 } 1582 if ((pr->pr_state & PR_AUTO) && !(pr->pr_kernel_state & PR_AUTO)) { 1583 /* 1584 * Set local address and set the prefix length to 128. 1585 * Turn off IFF_NOLOCAL in case it was set. 1586 * Turn on IFF_UP. 1587 */ 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 sin6->sin6_addr = pr->pr_address; 1595 if (debug & D_PREFIX) { 1596 logmsg(LOG_DEBUG, "prefix_update_k(%s) set addr %s " 1597 "for PR_AUTO on\n", 1598 pr->pr_name, 1599 inet_ntop(AF_INET6, (void *)&pr->pr_address, 1600 abuf, sizeof (abuf))); 1601 } 1602 if (ioctl(pi->pi_sock, SIOCSLIFADDR, (char *)&lifr) < 0) { 1603 logperror_pr(pr, "prefix_update_k: SIOCSLIFADDR"); 1604 return; 1605 } 1606 if (pr->pr_state & PR_ONLINK) { 1607 sin6->sin6_addr = pr->pr_prefix; 1608 lifr.lifr_addrlen = pr->pr_prefix_len; 1609 } else { 1610 sin6->sin6_addr = pr->pr_address; 1611 lifr.lifr_addrlen = IPV6_ABITS; 1612 } 1613 if (debug & D_PREFIX) { 1614 logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet " 1615 "%s/%u for PR_AUTO on\n", pr->pr_name, 1616 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, 1617 abuf, sizeof (abuf)), lifr.lifr_addrlen); 1618 } 1619 if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) { 1620 logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET"); 1621 return; 1622 } 1623 /* 1624 * For ptp interfaces, create a destination based on 1625 * prefix and prefix len together with the remote token 1626 * extracted from the remote pt-pt address. This is used by 1627 * ip to choose a proper source for outgoing packets. 1628 */ 1629 if (pi->pi_flags & IFF_POINTOPOINT) { 1630 int i; 1631 1632 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1633 bzero(sin6, sizeof (struct sockaddr_in6)); 1634 sin6->sin6_family = AF_INET6; 1635 sin6->sin6_addr = pr->pr_prefix; 1636 for (i = 0; i < 16; i++) { 1637 sin6->sin6_addr.s6_addr[i] |= 1638 pi->pi_dst_token.s6_addr[i]; 1639 } 1640 if (debug & D_PREFIX) { 1641 logmsg(LOG_DEBUG, "prefix_update_k(%s) " 1642 "set dstaddr %s for PR_AUTO on\n", 1643 pr->pr_name, inet_ntop(AF_INET6, 1644 (void *)&sin6->sin6_addr, 1645 abuf, sizeof (abuf))); 1646 } 1647 if (ioctl(pi->pi_sock, SIOCSLIFDSTADDR, 1648 (char *)&lifr) < 0) { 1649 logperror_pr(pr, 1650 "prefix_update_k: SIOCSLIFDSTADDR"); 1651 return; 1652 } 1653 } 1654 if (prefix_modify_flags(pr, IFF_UP, IFF_NOLOCAL) == -1) 1655 return; 1656 pr->pr_kernel_state |= PR_AUTO; 1657 if (pr->pr_state & PR_ONLINK) 1658 pr->pr_kernel_state |= PR_ONLINK; 1659 else 1660 pr->pr_kernel_state &= ~PR_ONLINK; 1661 } 1662 if (!(pr->pr_state & PR_AUTO) && (pr->pr_kernel_state & PR_AUTO)) { 1663 /* Turn on IFF_NOLOCAL and set the local address to all zero */ 1664 if (prefix_modify_flags(pr, IFF_NOLOCAL, 0) == -1) 1665 return; 1666 (void) strncpy(lifr.lifr_name, pr->pr_name, 1667 sizeof (lifr.lifr_name)); 1668 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1669 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1670 bzero(sin6, sizeof (struct sockaddr_in6)); 1671 sin6->sin6_family = AF_INET6; 1672 if (debug & D_PREFIX) { 1673 logmsg(LOG_DEBUG, "prefix_update_k(%s) set addr %s " 1674 "for PR_AUTO off\n", pr->pr_name, 1675 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, 1676 abuf, sizeof (abuf))); 1677 } 1678 if (ioctl(pi->pi_sock, SIOCSLIFADDR, (char *)&lifr) < 0) { 1679 logperror_pr(pr, "prefix_update_k: SIOCSLIFADDR"); 1680 return; 1681 } 1682 pr->pr_kernel_state &= ~PR_AUTO; 1683 } 1684 if ((pr->pr_state & PR_DEPRECATED) && 1685 !(pr->pr_kernel_state & PR_DEPRECATED) && 1686 (pr->pr_kernel_state & PR_AUTO)) { 1687 /* Only applies if PR_AUTO */ 1688 if (prefix_modify_flags(pr, IFF_DEPRECATED, 0) == -1) 1689 return; 1690 pr->pr_kernel_state |= PR_DEPRECATED; 1691 } 1692 if (!(pr->pr_state & PR_DEPRECATED) && 1693 (pr->pr_kernel_state & PR_DEPRECATED)) { 1694 if (prefix_modify_flags(pr, 0, IFF_DEPRECATED) == -1) 1695 return; 1696 pr->pr_kernel_state &= ~PR_DEPRECATED; 1697 } 1698 if ((pr->pr_state & PR_ONLINK) && !(pr->pr_kernel_state & PR_ONLINK)) { 1699 /* Set the subnet and set IFF_UP */ 1700 (void) strncpy(lifr.lifr_name, pr->pr_name, 1701 sizeof (lifr.lifr_name)); 1702 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1703 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1704 bzero(sin6, sizeof (struct sockaddr_in6)); 1705 sin6->sin6_family = AF_INET6; 1706 sin6->sin6_addr = pr->pr_prefix; 1707 lifr.lifr_addrlen = pr->pr_prefix_len; 1708 if (debug & D_PREFIX) { 1709 logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet " 1710 "%s/%d for PR_ONLINK on\n", pr->pr_name, 1711 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, 1712 abuf, sizeof (abuf)), lifr.lifr_addrlen); 1713 } 1714 if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) { 1715 logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET"); 1716 return; 1717 } 1718 /* 1719 * If we've previously marked the interface "up" while 1720 * processing the PR_AUTO flag -- via incoming_prefix_addrconf 1721 * -- then there's no need to set it "up" again. We're done; 1722 * just set PR_ONLINK to indicate that we've set the subnet. 1723 */ 1724 if (!(pr->pr_state & PR_AUTO) && 1725 prefix_modify_flags(pr, IFF_UP | IFF_NOLOCAL, 0) == -1) 1726 return; 1727 pr->pr_kernel_state |= PR_ONLINK; 1728 } 1729 if (!(pr->pr_state & PR_ONLINK) && (pr->pr_kernel_state & PR_ONLINK)) { 1730 /* Set the prefixlen to 128 */ 1731 (void) strncpy(lifr.lifr_name, pr->pr_name, 1732 sizeof (lifr.lifr_name)); 1733 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1734 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 1735 bzero(sin6, sizeof (struct sockaddr_in6)); 1736 sin6->sin6_family = AF_INET6; 1737 sin6->sin6_addr = pr->pr_address; 1738 lifr.lifr_addrlen = IPV6_ABITS; 1739 if (debug & D_PREFIX) { 1740 logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet " 1741 "%s/%d for PR_ONLINK off\n", pr->pr_name, 1742 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, 1743 abuf, sizeof (abuf)), lifr.lifr_addrlen); 1744 } 1745 if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) { 1746 logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET"); 1747 return; 1748 } 1749 pr->pr_kernel_state &= ~PR_ONLINK; 1750 } 1751 } 1752 1753 /* 1754 * Called with the number of millseconds elapsed since the last call. 1755 * Determines if any timeout event has occurred and 1756 * returns the number of milliseconds until the next timeout event. 1757 * Returns TIMER_INFINITY for "never". 1758 */ 1759 uint_t 1760 prefix_timer(struct prefix *pr, uint_t elapsed) 1761 { 1762 uint_t next = TIMER_INFINITY; 1763 char abuf[INET6_ADDRSTRLEN]; 1764 1765 if (debug & (D_PREFIX|D_TMP)) { 1766 logmsg(LOG_DEBUG, "prefix_timer(%s, %s/%u, %d) " 1767 "valid %d pref %d onlink %d\n", 1768 pr->pr_name, 1769 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1770 abuf, sizeof (abuf)), pr->pr_prefix_len, 1771 elapsed, pr->pr_ValidLifetime, pr->pr_PreferredLifetime, 1772 pr->pr_OnLinkLifetime); 1773 } 1774 1775 /* Exclude static prefixes */ 1776 if (pr->pr_state & PR_STATIC) 1777 return (next); 1778 1779 if (pr->pr_AutonomousFlag && 1780 (pr->pr_PreferredLifetime != PREFIX_INFINITY)) { 1781 if (pr->pr_PreferredLifetime <= elapsed) { 1782 pr->pr_PreferredLifetime = 0; 1783 } else { 1784 pr->pr_PreferredLifetime -= elapsed; 1785 if (pr->pr_PreferredLifetime < next) 1786 next = pr->pr_PreferredLifetime; 1787 } 1788 } 1789 if (pr->pr_AutonomousFlag && 1790 (pr->pr_ValidLifetime != PREFIX_INFINITY)) { 1791 if (pr->pr_ValidLifetime <= elapsed) { 1792 pr->pr_ValidLifetime = 0; 1793 } else { 1794 pr->pr_ValidLifetime -= elapsed; 1795 if (pr->pr_ValidLifetime < next) 1796 next = pr->pr_ValidLifetime; 1797 } 1798 } 1799 if (pr->pr_OnLinkFlag && 1800 (pr->pr_OnLinkLifetime != PREFIX_INFINITY)) { 1801 if (pr->pr_OnLinkLifetime <= elapsed) { 1802 pr->pr_OnLinkLifetime = 0; 1803 } else { 1804 pr->pr_OnLinkLifetime -= elapsed; 1805 if (pr->pr_OnLinkLifetime < next) 1806 next = pr->pr_OnLinkLifetime; 1807 } 1808 } 1809 if (pr->pr_AutonomousFlag && pr->pr_ValidLifetime == 0) 1810 pr->pr_state &= ~(PR_AUTO|PR_DEPRECATED); 1811 if (pr->pr_AutonomousFlag && pr->pr_PreferredLifetime == 0 && 1812 (pr->pr_state & PR_AUTO)) { 1813 pr->pr_state |= PR_DEPRECATED; 1814 if (debug & D_TMP) 1815 logmsg(LOG_WARNING, "prefix_timer: deprecated " 1816 "prefix(%s)\n", pr->pr_name); 1817 } 1818 if (pr->pr_OnLinkFlag && pr->pr_OnLinkLifetime == 0) 1819 pr->pr_state &= ~PR_ONLINK; 1820 1821 if (pr->pr_state != pr->pr_kernel_state) { 1822 /* Might cause prefix to be deleted! */ 1823 1824 /* Log a message when an addrconf prefix goes away */ 1825 if ((pr->pr_kernel_state & PR_AUTO) && 1826 !(pr->pr_state & PR_AUTO)) { 1827 char abuf[INET6_ADDRSTRLEN]; 1828 1829 logmsg(LOG_WARNING, 1830 "Address removed due to timeout %s\n", 1831 inet_ntop(AF_INET6, (void *)&pr->pr_address, 1832 abuf, sizeof (abuf))); 1833 } 1834 prefix_update_k(pr); 1835 } 1836 1837 return (next); 1838 } 1839 1840 static char * 1841 prefix_print_state(int state, char *buf, int buflen) 1842 { 1843 char *cp; 1844 int cplen = buflen; 1845 1846 cp = buf; 1847 cp[0] = '\0'; 1848 1849 if (state & PR_ONLINK) { 1850 if (strlcat(cp, "ONLINK ", cplen) >= cplen) 1851 return (buf); 1852 cp += strlen(cp); 1853 cplen = buflen - (cp - buf); 1854 } 1855 if (state & PR_AUTO) { 1856 if (strlcat(cp, "AUTO ", cplen) >= cplen) 1857 return (buf); 1858 cp += strlen(cp); 1859 cplen = buflen - (cp - buf); 1860 } 1861 if (state & PR_DEPRECATED) { 1862 if (strlcat(cp, "DEPRECATED ", cplen) >= cplen) 1863 return (buf); 1864 cp += strlen(cp); 1865 cplen = buflen - (cp - buf); 1866 } 1867 if (state & PR_STATIC) { 1868 if (strlcat(cp, "STATIC ", cplen) >= cplen) 1869 return (buf); 1870 cp += strlen(cp); 1871 cplen = buflen - (cp - buf); 1872 } 1873 return (buf); 1874 } 1875 1876 static void 1877 prefix_print(struct prefix *pr) 1878 { 1879 char abuf[INET6_ADDRSTRLEN]; 1880 char buf1[PREFIX_STATESTRLEN], buf2[PREFIX_STATESTRLEN]; 1881 1882 logmsg(LOG_DEBUG, "Prefix name: %s prefix %s/%u state %s " 1883 "kernel_state %s\n", pr->pr_name, 1884 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, abuf, sizeof (abuf)), 1885 pr->pr_prefix_len, 1886 prefix_print_state(pr->pr_state, buf2, sizeof (buf2)), 1887 prefix_print_state(pr->pr_kernel_state, buf1, sizeof (buf1))); 1888 logmsg(LOG_DEBUG, "\tAddress: %s flags %llx in_use %d\n", 1889 inet_ntop(AF_INET6, (void *)&pr->pr_address, abuf, sizeof (abuf)), 1890 pr->pr_flags, pr->pr_in_use); 1891 logmsg(LOG_DEBUG, "\tValidLifetime %u PreferredLifetime %u " 1892 "OnLinkLifetime %u\n", pr->pr_ValidLifetime, 1893 pr->pr_PreferredLifetime, pr->pr_OnLinkLifetime); 1894 logmsg(LOG_DEBUG, "\tOnLink %d Auto %d\n", 1895 pr->pr_OnLinkFlag, pr->pr_AutonomousFlag); 1896 logmsg(LOG_DEBUG, "\n"); 1897 } 1898 1899 /* 1900 * Does the address formed by pr->pr_prefix and pi->pi_token match 1901 * pr->pr_address. It does not match if a failover has happened 1902 * earlier (done by in.mpathd) from a different pi. Should not 1903 * be called for onlink prefixes. 1904 */ 1905 boolean_t 1906 prefix_token_match(struct phyint *pi, struct prefix *pr, uint64_t flags) 1907 { 1908 int i; 1909 in6_addr_t addr, *token; 1910 1911 if (flags & IFF_TEMPORARY) 1912 token = &pi->pi_tmp_token; 1913 else 1914 token = &pi->pi_token; 1915 for (i = 0; i < 16; i++) { 1916 /* 1917 * prefix_create ensures that pr_prefix has all-zero 1918 * bits after prefixlen. 1919 */ 1920 addr.s6_addr[i] = pr->pr_prefix.s6_addr[i] | token->s6_addr[i]; 1921 } 1922 if (IN6_ARE_ADDR_EQUAL(&pr->pr_address, &addr)) { 1923 return (_B_TRUE); 1924 } else { 1925 return (_B_FALSE); 1926 } 1927 } 1928 1929 /* 1930 * Lookup advertisement prefix structure that matches the prefix and 1931 * prefix length. 1932 * Assumes that the bits after prefixlen might not be zero. 1933 */ 1934 struct adv_prefix * 1935 adv_prefix_lookup(struct phyint *pi, struct in6_addr prefix, int prefixlen) 1936 { 1937 struct adv_prefix *adv_pr; 1938 char abuf[INET6_ADDRSTRLEN]; 1939 1940 if (debug & D_PREFIX) { 1941 logmsg(LOG_DEBUG, "adv_prefix_lookup(%s, %s/%u)\n", 1942 pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix, 1943 abuf, sizeof (abuf)), prefixlen); 1944 } 1945 1946 for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL; 1947 adv_pr = adv_pr->adv_pr_next) { 1948 if (adv_pr->adv_pr_prefix_len == prefixlen && 1949 prefix_equal(prefix, adv_pr->adv_pr_prefix, prefixlen)) 1950 return (adv_pr); 1951 } 1952 return (NULL); 1953 } 1954 1955 /* 1956 * Initialize a new advertisement prefix. 1957 */ 1958 struct adv_prefix * 1959 adv_prefix_create(struct phyint *pi, struct in6_addr prefix, int prefixlen) 1960 { 1961 struct adv_prefix *adv_pr; 1962 char abuf[INET6_ADDRSTRLEN]; 1963 1964 if (debug & D_PREFIX) { 1965 logmsg(LOG_DEBUG, "adv_prefix_create(%s, %s/%u)\n", 1966 pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix, 1967 abuf, sizeof (abuf)), prefixlen); 1968 } 1969 adv_pr = (struct adv_prefix *)calloc(sizeof (struct adv_prefix), 1); 1970 if (adv_pr == NULL) { 1971 logmsg(LOG_ERR, "adv_prefix_create: calloc\n"); 1972 return (NULL); 1973 } 1974 /* 1975 * The prefix might have non-zero bits after the prefix len bits. 1976 * Force them to be zero. 1977 */ 1978 prefix_set(&adv_pr->adv_pr_prefix, prefix, prefixlen); 1979 adv_pr->adv_pr_prefix_len = prefixlen; 1980 adv_prefix_insert(pi, adv_pr); 1981 return (adv_pr); 1982 } 1983 1984 /* Insert in linked list */ 1985 static void 1986 adv_prefix_insert(struct phyint *pi, struct adv_prefix *adv_pr) 1987 { 1988 adv_pr->adv_pr_next = pi->pi_adv_prefix_list; 1989 adv_pr->adv_pr_prev = NULL; 1990 if (pi->pi_adv_prefix_list != NULL) 1991 pi->pi_adv_prefix_list->adv_pr_prev = adv_pr; 1992 pi->pi_adv_prefix_list = adv_pr; 1993 adv_pr->adv_pr_physical = pi; 1994 } 1995 1996 /* 1997 * Delete (unlink and free) from our tables. There should be 1998 * a corresponding "struct prefix *" which will clean up the kernel 1999 * if necessary. adv_prefix is just used for sending out advertisements. 2000 */ 2001 static void 2002 adv_prefix_delete(struct adv_prefix *adv_pr) 2003 { 2004 struct phyint *pi; 2005 char abuf[INET6_ADDRSTRLEN]; 2006 2007 if (debug & D_PREFIX) { 2008 logmsg(LOG_DEBUG, "adv_prefix_delete(%s, %s/%u)\n", 2009 adv_pr->adv_pr_physical->pi_name, 2010 inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix, 2011 abuf, sizeof (abuf)), adv_pr->adv_pr_prefix_len); 2012 } 2013 pi = adv_pr->adv_pr_physical; 2014 2015 if (adv_pr->adv_pr_prev == NULL) { 2016 if (pi != NULL) 2017 pi->pi_adv_prefix_list = adv_pr->adv_pr_next; 2018 } else { 2019 adv_pr->adv_pr_prev->adv_pr_next = adv_pr->adv_pr_next; 2020 } 2021 if (adv_pr->adv_pr_next != NULL) 2022 adv_pr->adv_pr_next->adv_pr_prev = adv_pr->adv_pr_prev; 2023 adv_pr->adv_pr_next = adv_pr->adv_pr_prev = NULL; 2024 free(adv_pr); 2025 } 2026 2027 /* 2028 * Called with the number of millseconds elapsed since the last call. 2029 * Determines if any timeout event has occurred and 2030 * returns the number of milliseconds until the next timeout event. 2031 * Returns TIMER_INFINITY for "never". 2032 */ 2033 uint_t 2034 adv_prefix_timer(struct adv_prefix *adv_pr, uint_t elapsed) 2035 { 2036 int seconds_elapsed = (elapsed + 500) / 1000; /* Rounded */ 2037 char abuf[INET6_ADDRSTRLEN]; 2038 2039 if (debug & D_PREFIX) { 2040 logmsg(LOG_DEBUG, "adv_prefix_timer(%s, %s/%u, %d)\n", 2041 adv_pr->adv_pr_physical->pi_name, 2042 inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix, 2043 abuf, sizeof (abuf)), adv_pr->adv_pr_prefix_len, 2044 elapsed); 2045 } 2046 2047 /* Decrement Expire time left for real-time lifetimes */ 2048 if (adv_pr->adv_pr_AdvValidRealTime) { 2049 if (adv_pr->adv_pr_AdvValidExpiration > seconds_elapsed) 2050 adv_pr->adv_pr_AdvValidExpiration -= seconds_elapsed; 2051 else 2052 adv_pr->adv_pr_AdvValidExpiration = 0; 2053 } 2054 if (adv_pr->adv_pr_AdvPreferredRealTime) { 2055 if (adv_pr->adv_pr_AdvPreferredExpiration > seconds_elapsed) { 2056 adv_pr->adv_pr_AdvPreferredExpiration -= 2057 seconds_elapsed; 2058 } else { 2059 adv_pr->adv_pr_AdvPreferredExpiration = 0; 2060 } 2061 } 2062 return (TIMER_INFINITY); 2063 } 2064 2065 static void 2066 adv_prefix_print(struct adv_prefix *adv_pr) 2067 { 2068 print_prefixlist(adv_pr->adv_pr_config); 2069 } 2070 2071 /* Lookup router on its link-local IPv6 address */ 2072 struct router * 2073 router_lookup(struct phyint *pi, struct in6_addr addr) 2074 { 2075 struct router *dr; 2076 char abuf[INET6_ADDRSTRLEN]; 2077 2078 if (debug & D_ROUTER) { 2079 logmsg(LOG_DEBUG, "router_lookup(%s, %s)\n", pi->pi_name, 2080 inet_ntop(AF_INET6, (void *)&addr, 2081 abuf, sizeof (abuf))); 2082 } 2083 2084 for (dr = pi->pi_router_list; dr != NULL; dr = dr->dr_next) { 2085 if (bcmp((char *)&addr, (char *)&dr->dr_address, 2086 sizeof (addr)) == 0) 2087 return (dr); 2088 } 2089 return (NULL); 2090 } 2091 2092 /* 2093 * Create a default router entry. 2094 * The lifetime parameter is in seconds. 2095 */ 2096 struct router * 2097 router_create(struct phyint *pi, struct in6_addr addr, uint_t lifetime) 2098 { 2099 struct router *dr; 2100 char abuf[INET6_ADDRSTRLEN]; 2101 2102 if (debug & D_ROUTER) { 2103 logmsg(LOG_DEBUG, "router_create(%s, %s, %u)\n", pi->pi_name, 2104 inet_ntop(AF_INET6, (void *)&addr, 2105 abuf, sizeof (abuf)), lifetime); 2106 } 2107 2108 dr = (struct router *)calloc(sizeof (struct router), 1); 2109 if (dr == NULL) { 2110 logmsg(LOG_ERR, "router_create: out of memory\n"); 2111 return (NULL); 2112 } 2113 dr->dr_address = addr; 2114 dr->dr_lifetime = lifetime; 2115 router_insert(pi, dr); 2116 if (dr->dr_lifetime != 0) 2117 router_add_k(dr); 2118 return (dr); 2119 } 2120 2121 /* Insert in linked list */ 2122 static void 2123 router_insert(struct phyint *pi, struct router *dr) 2124 { 2125 dr->dr_next = pi->pi_router_list; 2126 dr->dr_prev = NULL; 2127 if (pi->pi_router_list != NULL) 2128 pi->pi_router_list->dr_prev = dr; 2129 pi->pi_router_list = dr; 2130 dr->dr_physical = pi; 2131 } 2132 2133 /* 2134 * Delete (unlink and free). 2135 * Handles delete of things that have not yet been inserted in the list 2136 * i.e. dr_physical is NULL. 2137 */ 2138 static void 2139 router_delete(struct router *dr) 2140 { 2141 struct phyint *pi; 2142 char abuf[INET6_ADDRSTRLEN]; 2143 2144 if (debug & D_ROUTER) { 2145 logmsg(LOG_DEBUG, "router_delete(%s, %s, %u)\n", 2146 dr->dr_physical->pi_name, 2147 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2148 abuf, sizeof (abuf)), dr->dr_lifetime); 2149 } 2150 pi = dr->dr_physical; 2151 if (dr->dr_inkernel && (pi->pi_kernel_state & PI_PRESENT)) 2152 router_delete_k(dr); 2153 2154 if (dr->dr_prev == NULL) { 2155 if (pi != NULL) 2156 pi->pi_router_list = dr->dr_next; 2157 } else { 2158 dr->dr_prev->dr_next = dr->dr_next; 2159 } 2160 if (dr->dr_next != NULL) 2161 dr->dr_next->dr_prev = dr->dr_prev; 2162 dr->dr_next = dr->dr_prev = NULL; 2163 free(dr); 2164 } 2165 2166 /* 2167 * Update the kernel to match dr_lifetime 2168 */ 2169 void 2170 router_update_k(struct router *dr) 2171 { 2172 char abuf[INET6_ADDRSTRLEN]; 2173 2174 if (debug & D_ROUTER) { 2175 logmsg(LOG_DEBUG, "router_update_k(%s, %s, %u)\n", 2176 dr->dr_physical->pi_name, 2177 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2178 abuf, sizeof (abuf)), dr->dr_lifetime); 2179 } 2180 2181 if (dr->dr_lifetime == 0 && dr->dr_inkernel) { 2182 /* Log a message when last router goes away */ 2183 if (dr->dr_physical->pi_num_k_routers == 1) { 2184 logmsg(LOG_WARNING, 2185 "Last default router (%s) removed on %s\n", 2186 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2187 abuf, sizeof (abuf)), dr->dr_physical->pi_name); 2188 } 2189 router_delete(dr); 2190 } else if (dr->dr_lifetime != 0 && !dr->dr_inkernel) 2191 router_add_k(dr); 2192 } 2193 2194 2195 /* 2196 * Called with the number of millseconds elapsed since the last call. 2197 * Determines if any timeout event has occurred and 2198 * returns the number of milliseconds until the next timeout event. 2199 * Returns TIMER_INFINITY for "never". 2200 */ 2201 uint_t 2202 router_timer(struct router *dr, uint_t elapsed) 2203 { 2204 uint_t next = TIMER_INFINITY; 2205 char abuf[INET6_ADDRSTRLEN]; 2206 2207 if (debug & D_ROUTER) { 2208 logmsg(LOG_DEBUG, "router_timer(%s, %s, %u, %d)\n", 2209 dr->dr_physical->pi_name, 2210 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2211 abuf, sizeof (abuf)), dr->dr_lifetime, elapsed); 2212 } 2213 if (dr->dr_lifetime <= elapsed) { 2214 dr->dr_lifetime = 0; 2215 } else { 2216 dr->dr_lifetime -= elapsed; 2217 if (dr->dr_lifetime < next) 2218 next = dr->dr_lifetime; 2219 } 2220 2221 if (dr->dr_lifetime == 0) { 2222 /* Log a message when last router goes away */ 2223 if (dr->dr_physical->pi_num_k_routers == 1) { 2224 logmsg(LOG_WARNING, 2225 "Last default router (%s) timed out on %s\n", 2226 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2227 abuf, sizeof (abuf)), dr->dr_physical->pi_name); 2228 } 2229 router_delete(dr); 2230 } 2231 return (next); 2232 } 2233 2234 /* 2235 * Add a default route to the kernel (unless the lifetime is zero) 2236 * Handles onlink default routes. 2237 */ 2238 static void 2239 router_add_k(struct router *dr) 2240 { 2241 struct phyint *pi = dr->dr_physical; 2242 char abuf[INET6_ADDRSTRLEN]; 2243 int rlen; 2244 2245 if (debug & D_ROUTER) { 2246 logmsg(LOG_DEBUG, "router_add_k(%s, %s, %u)\n", 2247 dr->dr_physical->pi_name, 2248 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2249 abuf, sizeof (abuf)), dr->dr_lifetime); 2250 } 2251 2252 rta_gateway->sin6_addr = dr->dr_address; 2253 2254 rta_ifp->sdl_index = if_nametoindex(pi->pi_name); 2255 if (rta_ifp->sdl_index == 0) { 2256 logperror_pi(pi, "router_add_k: if_nametoindex"); 2257 return; 2258 } 2259 2260 rt_msg->rtm_flags = RTF_GATEWAY; 2261 rt_msg->rtm_type = RTM_ADD; 2262 rt_msg->rtm_seq = ++rtmseq; 2263 rlen = write(rtsock, rt_msg, rt_msg->rtm_msglen); 2264 if (rlen < 0) { 2265 if (errno != EEXIST) { 2266 logperror_pi(pi, "router_add_k: RTM_ADD"); 2267 return; 2268 } 2269 } else if (rlen < rt_msg->rtm_msglen) { 2270 logmsg(LOG_ERR, "router_add_k: write to routing socket got " 2271 "only %d for rlen (interface %s)\n", rlen, pi->pi_name); 2272 return; 2273 } 2274 dr->dr_inkernel = _B_TRUE; 2275 pi->pi_num_k_routers++; 2276 } 2277 2278 /* 2279 * Delete a route from the kernel. 2280 * Handles onlink default routes. 2281 */ 2282 static void 2283 router_delete_k(struct router *dr) 2284 { 2285 struct phyint *pi = dr->dr_physical; 2286 char abuf[INET6_ADDRSTRLEN]; 2287 int rlen; 2288 2289 if (debug & D_ROUTER) { 2290 logmsg(LOG_DEBUG, "router_delete_k(%s, %s, %u)\n", 2291 dr->dr_physical->pi_name, 2292 inet_ntop(AF_INET6, (void *)&dr->dr_address, 2293 abuf, sizeof (abuf)), dr->dr_lifetime); 2294 } 2295 2296 rta_gateway->sin6_addr = dr->dr_address; 2297 2298 rta_ifp->sdl_index = if_nametoindex(pi->pi_name); 2299 if (rta_ifp->sdl_index == 0) { 2300 logperror_pi(pi, "router_delete_k: if_nametoindex"); 2301 return; 2302 } 2303 2304 rt_msg->rtm_flags = RTF_GATEWAY; 2305 rt_msg->rtm_type = RTM_DELETE; 2306 rt_msg->rtm_seq = ++rtmseq; 2307 rlen = write(rtsock, rt_msg, rt_msg->rtm_msglen); 2308 if (rlen < 0) { 2309 if (errno != ESRCH) { 2310 logperror_pi(pi, "router_delete_k: RTM_DELETE"); 2311 } 2312 } else if (rlen < rt_msg->rtm_msglen) { 2313 logmsg(LOG_ERR, "router_delete_k: write to routing socket got " 2314 "only %d for rlen (interface %s)\n", rlen, pi->pi_name); 2315 } 2316 dr->dr_inkernel = _B_FALSE; 2317 pi->pi_num_k_routers--; 2318 } 2319 2320 2321 static void 2322 router_print(struct router *dr) 2323 { 2324 char abuf[INET6_ADDRSTRLEN]; 2325 2326 logmsg(LOG_DEBUG, "Router %s on %s inkernel %d lifetime %u\n", 2327 inet_ntop(AF_INET6, (void *)&dr->dr_address, abuf, sizeof (abuf)), 2328 dr->dr_physical->pi_name, dr->dr_inkernel, dr->dr_lifetime); 2329 } 2330 2331 2332 void 2333 phyint_print_all(void) 2334 { 2335 struct phyint *pi; 2336 2337 for (pi = phyints; pi != NULL; pi = pi->pi_next) { 2338 phyint_print(pi); 2339 } 2340 } 2341 2342 void 2343 phyint_cleanup(pi) 2344 struct phyint *pi; 2345 { 2346 pi->pi_state = 0; 2347 pi->pi_kernel_state = 0; 2348 2349 if (pi->pi_AdvSendAdvertisements) { 2350 check_to_advertise(pi, ADV_OFF); 2351 } else { 2352 check_to_solicit(pi, SOLICIT_OFF); 2353 } 2354 2355 while (pi->pi_router_list) 2356 router_delete(pi->pi_router_list); 2357 (void) poll_remove(pi->pi_sock); 2358 (void) close(pi->pi_sock); 2359 pi->pi_sock = -1; 2360 } 2361