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