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