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