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