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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include "defs.h" 28 #include "tables.h" 29 30 #include <sys/sysmacros.h> 31 32 #include <dhcpagent_ipc.h> 33 #include <dhcpagent_util.h> 34 35 static boolean_t verify_opt_len(struct nd_opt_hdr *opt, int optlen, 36 struct phyint *pi, struct sockaddr_in6 *from); 37 38 static void incoming_rs(struct phyint *pi, struct nd_router_solicit *rs, 39 int len, struct sockaddr_in6 *from); 40 41 void incoming_ra(struct phyint *pi, struct nd_router_advert *ra, 42 int len, struct sockaddr_in6 *from, boolean_t loopback); 43 static void incoming_prefix_opt(struct phyint *pi, uchar_t *opt, 44 struct sockaddr_in6 *from, boolean_t loopback); 45 static void incoming_prefix_onlink(struct phyint *pi, uchar_t *opt); 46 void incoming_prefix_onlink_process(struct prefix *pr, 47 uchar_t *opt); 48 static void incoming_prefix_stateful(struct phyint *, uchar_t *); 49 static boolean_t incoming_prefix_addrconf(struct phyint *pi, 50 uchar_t *opt, struct sockaddr_in6 *from, 51 boolean_t loopback); 52 boolean_t incoming_prefix_addrconf_process(struct phyint *pi, 53 struct prefix *pr, uchar_t *opt, 54 struct sockaddr_in6 *from, boolean_t loopback, 55 boolean_t new_prefix); 56 static void incoming_mtu_opt(struct phyint *pi, uchar_t *opt, 57 struct sockaddr_in6 *from); 58 static void incoming_lla_opt(struct phyint *pi, uchar_t *opt, 59 struct sockaddr_in6 *from, int isrouter); 60 61 static void verify_ra_consistency(struct phyint *pi, 62 struct nd_router_advert *ra, 63 int len, struct sockaddr_in6 *from); 64 static void verify_prefix_opt(struct phyint *pi, uchar_t *opt, 65 char *frombuf); 66 static void verify_mtu_opt(struct phyint *pi, uchar_t *opt, 67 char *frombuf); 68 69 static void update_ra_flag(const struct phyint *pi, 70 const struct sockaddr_in6 *from, int isrouter); 71 72 /* 73 * Return a pointer to the specified option buffer. 74 * If not found return NULL. 75 */ 76 static void * 77 find_ancillary(struct msghdr *msg, int cmsg_type) 78 { 79 struct cmsghdr *cmsg; 80 81 for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; 82 cmsg = CMSG_NXTHDR(msg, cmsg)) { 83 if (cmsg->cmsg_level == IPPROTO_IPV6 && 84 cmsg->cmsg_type == cmsg_type) { 85 return (CMSG_DATA(cmsg)); 86 } 87 } 88 return (NULL); 89 } 90 91 void 92 in_data(struct phyint *pi) 93 { 94 struct sockaddr_in6 from; 95 struct icmp6_hdr *icmp; 96 struct nd_router_solicit *rs; 97 struct nd_router_advert *ra; 98 static uint64_t in_packet[(IP_MAXPACKET + 1)/8]; 99 static uint64_t ancillary_data[(IP_MAXPACKET + 1)/8]; 100 int len; 101 char abuf[INET6_ADDRSTRLEN]; 102 const char *msgbuf; 103 struct msghdr msg; 104 struct iovec iov; 105 uchar_t *opt; 106 uint_t hoplimit; 107 108 iov.iov_base = (char *)in_packet; 109 iov.iov_len = sizeof (in_packet); 110 msg.msg_iov = &iov; 111 msg.msg_iovlen = 1; 112 msg.msg_name = (struct sockaddr *)&from; 113 msg.msg_namelen = sizeof (from); 114 msg.msg_control = ancillary_data; 115 msg.msg_controllen = sizeof (ancillary_data); 116 117 if ((len = recvmsg(pi->pi_sock, &msg, 0)) < 0) { 118 logperror_pi(pi, "in_data: recvfrom"); 119 return; 120 } 121 if (len == 0) 122 return; 123 124 if (inet_ntop(AF_INET6, (void *)&from.sin6_addr, 125 abuf, sizeof (abuf)) == NULL) 126 msgbuf = "Unspecified Router"; 127 else 128 msgbuf = abuf; 129 130 /* Ignore packets > 64k or control buffers that don't fit */ 131 if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { 132 if (debug & D_PKTBAD) { 133 logmsg(LOG_DEBUG, "Truncated message: msg_flags 0x%x " 134 "from %s\n", msg.msg_flags, msgbuf); 135 } 136 return; 137 } 138 139 icmp = (struct icmp6_hdr *)in_packet; 140 141 if (len < ICMP6_MINLEN) { 142 logmsg(LOG_INFO, "Too short ICMP packet: %d bytes " 143 "from %s on %s\n", 144 len, msgbuf, pi->pi_name); 145 return; 146 } 147 148 opt = find_ancillary(&msg, IPV6_HOPLIMIT); 149 if (opt == NULL) { 150 /* Unknown hoplimit - must drop */ 151 logmsg(LOG_INFO, "Unknown hop limit from %s on %s\n", 152 msgbuf, pi->pi_name); 153 return; 154 } 155 hoplimit = *(uint_t *)opt; 156 opt = find_ancillary(&msg, IPV6_RTHDR); 157 if (opt != NULL) { 158 /* Can't allow routing headers in ND messages */ 159 logmsg(LOG_INFO, "ND message with routing header " 160 "from %s on %s\n", 161 msgbuf, pi->pi_name); 162 return; 163 } 164 switch (icmp->icmp6_type) { 165 case ND_ROUTER_SOLICIT: 166 if (!pi->pi_AdvSendAdvertisements) 167 return; 168 if (pi->pi_flags & IFF_NORTEXCH) { 169 if (debug & D_PKTIN) { 170 logmsg(LOG_DEBUG, "Ignore received RS packet " 171 "on %s (no route exchange on interface)\n", 172 pi->pi_name); 173 } 174 return; 175 } 176 177 /* 178 * Assumes that the kernel has verified the AH (if present) 179 * and the ICMP checksum. 180 */ 181 if (hoplimit != IPV6_MAX_HOPS) { 182 logmsg(LOG_DEBUG, "RS hop limit: %d from %s on %s\n", 183 hoplimit, msgbuf, pi->pi_name); 184 return; 185 } 186 187 if (icmp->icmp6_code != 0) { 188 logmsg(LOG_INFO, "RS code: %d from %s on %s\n", 189 icmp->icmp6_code, msgbuf, pi->pi_name); 190 return; 191 } 192 193 if (len < sizeof (struct nd_router_solicit)) { 194 logmsg(LOG_INFO, "RS too short: %d bytes " 195 "from %s on %s\n", 196 len, msgbuf, pi->pi_name); 197 return; 198 } 199 rs = (struct nd_router_solicit *)icmp; 200 if (len > sizeof (struct nd_router_solicit)) { 201 if (!verify_opt_len((struct nd_opt_hdr *)&rs[1], 202 len - sizeof (struct nd_router_solicit), pi, &from)) 203 return; 204 } 205 if (debug & D_PKTIN) { 206 print_route_sol("Received valid solicit from ", pi, 207 rs, len, &from); 208 } 209 incoming_rs(pi, rs, len, &from); 210 break; 211 212 case ND_ROUTER_ADVERT: 213 if (IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr)) { 214 /* 215 * Router advt. must have address! 216 * Logging the news and returning. 217 */ 218 logmsg(LOG_DEBUG, 219 "Router's address unspecified in advertisement\n"); 220 return; 221 } 222 if (pi->pi_flags & IFF_NORTEXCH) { 223 if (debug & D_PKTIN) { 224 logmsg(LOG_DEBUG, "Ignore received RA packet " 225 "on %s (no route exchange on interface)\n", 226 pi->pi_name); 227 } 228 return; 229 } 230 231 /* 232 * Assumes that the kernel has verified the AH (if present) 233 * and the ICMP checksum. 234 */ 235 if (!IN6_IS_ADDR_LINKLOCAL(&from.sin6_addr)) { 236 logmsg(LOG_DEBUG, "RA from %s - not link local on %s\n", 237 msgbuf, pi->pi_name); 238 return; 239 } 240 241 if (hoplimit != IPV6_MAX_HOPS) { 242 logmsg(LOG_INFO, "RA hop limit: %d from %s on %s\n", 243 hoplimit, msgbuf, pi->pi_name); 244 return; 245 } 246 247 if (icmp->icmp6_code != 0) { 248 logmsg(LOG_INFO, "RA code: %d from %s on %s\n", 249 icmp->icmp6_code, msgbuf, pi->pi_name); 250 return; 251 } 252 253 if (len < sizeof (struct nd_router_advert)) { 254 logmsg(LOG_INFO, "RA too short: %d bytes " 255 "from %s on %s\n", 256 len, msgbuf, pi->pi_name); 257 return; 258 } 259 ra = (struct nd_router_advert *)icmp; 260 if (len > sizeof (struct nd_router_advert)) { 261 if (!verify_opt_len((struct nd_opt_hdr *)&ra[1], 262 len - sizeof (struct nd_router_advert), pi, &from)) 263 return; 264 } 265 if (debug & D_PKTIN) { 266 print_route_adv("Received valid advert from ", pi, 267 ra, len, &from); 268 } 269 if (pi->pi_AdvSendAdvertisements) 270 verify_ra_consistency(pi, ra, len, &from); 271 else 272 incoming_ra(pi, ra, len, &from, _B_FALSE); 273 break; 274 } 275 } 276 277 /* 278 * Process a received router solicitation. 279 * Check for source link-layer address option and check if it 280 * is time to advertise. 281 */ 282 static void 283 incoming_rs(struct phyint *pi, struct nd_router_solicit *rs, int len, 284 struct sockaddr_in6 *from) 285 { 286 struct nd_opt_hdr *opt; 287 int optlen; 288 289 /* Process any options */ 290 len -= sizeof (struct nd_router_solicit); 291 opt = (struct nd_opt_hdr *)&rs[1]; 292 while (len >= sizeof (struct nd_opt_hdr)) { 293 optlen = opt->nd_opt_len * 8; 294 switch (opt->nd_opt_type) { 295 case ND_OPT_SOURCE_LINKADDR: 296 incoming_lla_opt(pi, (uchar_t *)opt, 297 from, NDF_ISROUTER_OFF); 298 break; 299 default: 300 break; 301 } 302 opt = (struct nd_opt_hdr *)((char *)opt + optlen); 303 len -= optlen; 304 } 305 /* Simple algorithm: treat unicast and multicast RSs the same */ 306 check_to_advertise(pi, RECEIVED_SOLICIT); 307 } 308 309 /* 310 * Start up DHCPv6 on a given physical interface. Does not wait for a message 311 * to be returned from the daemon. 312 */ 313 void 314 start_dhcp(struct phyint *pi) 315 { 316 dhcp_ipc_request_t *request; 317 dhcp_ipc_reply_t *reply = NULL; 318 int error; 319 int type; 320 321 if (dhcp_start_agent(DHCP_IPC_MAX_WAIT) == -1) { 322 logmsg(LOG_ERR, "start_dhcp: unable to start %s\n", 323 DHCP_AGENT_PATH); 324 /* make sure we try again next time there's a chance */ 325 pi->pi_ra_flags &= ~ND_RA_FLAG_MANAGED & ~ND_RA_FLAG_OTHER; 326 return; 327 } 328 329 type = (pi->pi_ra_flags & ND_RA_FLAG_MANAGED) ? DHCP_START : 330 DHCP_INFORM; 331 332 request = dhcp_ipc_alloc_request(type | DHCP_V6, pi->pi_name, NULL, 0, 333 DHCP_TYPE_NONE); 334 if (request == NULL) { 335 logmsg(LOG_ERR, "start_dhcp: out of memory\n"); 336 /* make sure we try again next time there's a chance */ 337 pi->pi_ra_flags &= ~ND_RA_FLAG_MANAGED & ~ND_RA_FLAG_OTHER; 338 return; 339 } 340 341 error = dhcp_ipc_make_request(request, &reply, 0); 342 free(request); 343 if (error != 0) { 344 logmsg(LOG_ERR, "start_dhcp: err: %s: %s\n", pi->pi_name, 345 dhcp_ipc_strerror(error)); 346 return; 347 } 348 349 error = reply->return_code; 350 free(reply); 351 352 /* 353 * Timeout is considered to be "success" because we don't wait for DHCP 354 * to do its exchange. 355 */ 356 if (error != DHCP_IPC_SUCCESS && error != DHCP_IPC_E_RUNNING && 357 error != DHCP_IPC_E_TIMEOUT) { 358 logmsg(LOG_ERR, "start_dhcp: ret: %s: %s\n", pi->pi_name, 359 dhcp_ipc_strerror(error)); 360 return; 361 } 362 } 363 364 /* 365 * Process a received router advertisement. 366 * Called both when packets arrive as well as when we send RAs. 367 * In the latter case 'loopback' is set. 368 */ 369 void 370 incoming_ra(struct phyint *pi, struct nd_router_advert *ra, int len, 371 struct sockaddr_in6 *from, boolean_t loopback) 372 { 373 struct nd_opt_hdr *opt; 374 int optlen; 375 struct lifreq lifr; 376 boolean_t set_needed = _B_FALSE; 377 struct router *dr; 378 uint16_t router_lifetime; 379 uint_t reachable, retrans; 380 boolean_t reachable_time_changed = _B_FALSE; 381 boolean_t slla_opt_present = _B_FALSE; 382 383 if (no_loopback && loopback) 384 return; 385 386 /* 387 * If the interface is FAILED or INACTIVE or OFFLINE, don't 388 * create any addresses on them. in.mpathd assumes that no new 389 * addresses will appear on these. This implies that we 390 * won't create any new prefixes advertised by the router 391 * on FAILED/INACTIVE/OFFLINE interfaces. When the state changes, 392 * the next RA will create the prefix on this interface. 393 */ 394 if (pi->pi_flags & (IFF_FAILED|IFF_INACTIVE|IFF_OFFLINE)) 395 return; 396 397 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 398 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 399 if (ioctl(pi->pi_sock, SIOCGLIFLNKINFO, (char *)&lifr) < 0) { 400 if (errno == ENXIO) 401 return; 402 logperror_pi(pi, "incoming_ra: SIOCGLIFLNKINFO"); 403 return; 404 } 405 if (ra->nd_ra_curhoplimit != CURHOP_UNSPECIFIED && 406 ra->nd_ra_curhoplimit != pi->pi_CurHopLimit) { 407 pi->pi_CurHopLimit = ra->nd_ra_curhoplimit; 408 409 lifr.lifr_ifinfo.lir_maxhops = pi->pi_CurHopLimit; 410 set_needed = _B_TRUE; 411 } 412 413 reachable = ntohl(ra->nd_ra_reachable); 414 if (reachable != 0 && 415 reachable != pi->pi_BaseReachableTime) { 416 pi->pi_BaseReachableTime = reachable; 417 reachable_time_changed = _B_TRUE; 418 } 419 420 if (pi->pi_reach_time_since_random < MIN_REACH_RANDOM_INTERVAL || 421 reachable_time_changed) { 422 phyint_reach_random(pi, _B_FALSE); 423 set_needed = _B_TRUE; 424 } 425 lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime; 426 427 retrans = ntohl(ra->nd_ra_retransmit); 428 if (retrans != 0 && 429 pi->pi_RetransTimer != retrans) { 430 pi->pi_RetransTimer = retrans; 431 lifr.lifr_ifinfo.lir_reachretrans = pi->pi_RetransTimer; 432 set_needed = _B_TRUE; 433 } 434 435 if (set_needed) { 436 if (ioctl(pi->pi_sock, SIOCSLIFLNKINFO, (char *)&lifr) < 0) { 437 logperror_pi(pi, "incoming_ra: SIOCSLIFLNKINFO"); 438 return; 439 } 440 } 441 442 /* 443 * If the "managed" flag is set, then just assume that the "other" flag 444 * is set as well. It's not legal to get addresses alone without 445 * getting other data. 446 */ 447 if (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) 448 ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; 449 450 /* 451 * If either the "managed" or "other" bits have turned on, then it's 452 * now time to invoke DHCP. If only the "other" bit is set, then don't 453 * get addresses via DHCP; only "other" data. If "managed" is set, 454 * then we must always get both addresses and "other" data. 455 */ 456 if (pi->pi_StatefulAddrConf && 457 (ra->nd_ra_flags_reserved & ~pi->pi_ra_flags & 458 (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))) { 459 if (debug & D_DHCP) { 460 logmsg(LOG_DEBUG, 461 "incoming_ra: trigger dhcp %s on %s\n", 462 (ra->nd_ra_flags_reserved & ~pi->pi_ra_flags & 463 ND_RA_FLAG_MANAGED) ? "MANAGED" : "OTHER", 464 pi->pi_name); 465 } 466 pi->pi_ra_flags |= ra->nd_ra_flags_reserved; 467 start_dhcp(pi); 468 } 469 470 /* Skip default router code if sent from ourselves */ 471 if (!loopback) { 472 /* Find and update or add default router in list */ 473 dr = router_lookup(pi, from->sin6_addr); 474 router_lifetime = ntohs(ra->nd_ra_router_lifetime); 475 if (dr == NULL) { 476 if (router_lifetime != 0) { 477 dr = router_create(pi, from->sin6_addr, 478 MILLISEC * router_lifetime); 479 timer_schedule(dr->dr_lifetime); 480 } 481 } else { 482 dr->dr_lifetime = MILLISEC * router_lifetime; 483 if (dr->dr_lifetime != 0) 484 timer_schedule(dr->dr_lifetime); 485 if ((dr->dr_lifetime != 0 && !dr->dr_inkernel) || 486 (dr->dr_lifetime == 0 && dr->dr_inkernel)) 487 router_update_k(dr); 488 } 489 } 490 /* Process any options */ 491 len -= sizeof (struct nd_router_advert); 492 opt = (struct nd_opt_hdr *)&ra[1]; 493 while (len >= sizeof (struct nd_opt_hdr)) { 494 optlen = opt->nd_opt_len * 8; 495 switch (opt->nd_opt_type) { 496 case ND_OPT_PREFIX_INFORMATION: 497 incoming_prefix_opt(pi, (uchar_t *)opt, from, 498 loopback); 499 break; 500 case ND_OPT_MTU: 501 incoming_mtu_opt(pi, (uchar_t *)opt, from); 502 break; 503 case ND_OPT_SOURCE_LINKADDR: 504 /* skip lla option if sent from ourselves! */ 505 if (!loopback) { 506 incoming_lla_opt(pi, (uchar_t *)opt, 507 from, NDF_ISROUTER_ON); 508 slla_opt_present = _B_TRUE; 509 } 510 break; 511 default: 512 break; 513 } 514 opt = (struct nd_opt_hdr *)((char *)opt + optlen); 515 len -= optlen; 516 } 517 if (!loopback && !slla_opt_present) 518 update_ra_flag(pi, from, NDF_ISROUTER_ON); 519 /* Stop sending solicitations */ 520 check_to_solicit(pi, SOLICIT_DONE); 521 } 522 523 /* 524 * Process a received prefix option. 525 * Unless addrconf is turned off we process both the addrconf and the 526 * onlink aspects of the prefix option. 527 * 528 * Note that when a flag (onlink or auto) is turned off we do nothing - 529 * the prefix will time out. 530 */ 531 static void 532 incoming_prefix_opt(struct phyint *pi, uchar_t *opt, 533 struct sockaddr_in6 *from, boolean_t loopback) 534 { 535 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 536 boolean_t good_prefix = _B_TRUE; 537 538 if (8 * po->nd_opt_pi_len != sizeof (*po)) { 539 char abuf[INET6_ADDRSTRLEN]; 540 541 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 542 abuf, sizeof (abuf)); 543 logmsg(LOG_INFO, "prefix option from %s on %s wrong size " 544 "(%d bytes)\n", 545 abuf, pi->pi_name, 546 8 * (int)po->nd_opt_pi_len); 547 return; 548 } 549 if (IN6_IS_ADDR_LINKLOCAL(&po->nd_opt_pi_prefix)) { 550 char abuf[INET6_ADDRSTRLEN]; 551 552 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 553 abuf, sizeof (abuf)); 554 logmsg(LOG_INFO, "RA from %s on %s contains link-local prefix " 555 "- ignored\n", 556 abuf, pi->pi_name); 557 return; 558 } 559 if ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) && 560 pi->pi_StatelessAddrConf) { 561 good_prefix = incoming_prefix_addrconf(pi, opt, from, loopback); 562 } 563 if ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) && 564 good_prefix) { 565 incoming_prefix_onlink(pi, opt); 566 } 567 if (pi->pi_StatefulAddrConf) 568 incoming_prefix_stateful(pi, opt); 569 } 570 571 /* 572 * Process prefix options with the onlink flag set. 573 * 574 * If there are no routers ndpd will add an onlink 575 * default route which will allow communication 576 * between neighbors. 577 * 578 * This function needs to loop to find the same prefix multiple times 579 * as if a failover happened earlier, the addresses belonging to 580 * a different interface may be found here on this interface. 581 */ 582 static void 583 incoming_prefix_onlink(struct phyint *pi, uchar_t *opt) 584 { 585 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 586 int plen; 587 struct prefix *pr; 588 uint32_t validtime; /* Without 2 hour rule */ 589 boolean_t found_one = _B_FALSE; 590 591 plen = po->nd_opt_pi_prefix_len; 592 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 593 if (pr->pr_prefix_len == plen && 594 prefix_equal(po->nd_opt_pi_prefix, pr->pr_prefix, plen)) { 595 /* Exclude static prefixes */ 596 if (pr->pr_state & PR_STATIC) 597 continue; 598 found_one = _B_TRUE; 599 incoming_prefix_onlink_process(pr, opt); 600 } 601 } 602 603 validtime = ntohl(po->nd_opt_pi_valid_time); 604 /* 605 * If we have found a matching prefix already or validtime 606 * is zero, we have nothing to do. 607 */ 608 if (validtime == 0 || found_one) 609 return; 610 pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 0); 611 if (pr == NULL) 612 return; 613 incoming_prefix_onlink_process(pr, opt); 614 } 615 616 void 617 incoming_prefix_onlink_process(struct prefix *pr, uchar_t *opt) 618 { 619 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 620 uint32_t validtime; /* Without 2 hour rule */ 621 char abuf[INET6_ADDRSTRLEN]; 622 623 validtime = ntohl(po->nd_opt_pi_valid_time); 624 if (validtime != 0) 625 pr->pr_state |= PR_ONLINK; 626 else 627 pr->pr_state &= ~PR_ONLINK; 628 629 /* 630 * Convert from seconds to milliseconds avoiding overflow. 631 * If the lifetime in the packet is e.g. PREFIX_INFINITY - 1 632 * (4 billion seconds - about 130 years) we will in fact time 633 * out the prefix after 4 billion milliseconds - 46 days). 634 * Thus the longest lifetime (apart from infinity) is 46 days. 635 * Note that this ensures that PREFIX_INFINITY still means "forever". 636 */ 637 if (pr->pr_flags & IFF_TEMPORARY) { 638 pr->pr_OnLinkLifetime = pr->pr_ValidLifetime; 639 } else { 640 if (validtime >= PREFIX_INFINITY / MILLISEC) 641 pr->pr_OnLinkLifetime = PREFIX_INFINITY - 1; 642 else 643 pr->pr_OnLinkLifetime = validtime * MILLISEC; 644 } 645 pr->pr_OnLinkFlag = _B_TRUE; 646 if (debug & (D_PREFIX|D_TMP)) { 647 logmsg(LOG_DEBUG, "incoming_prefix_onlink_process(%s, %s/%u) " 648 "onlink %u state 0x%x, kstate 0x%x\n", 649 pr->pr_name, inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 650 abuf, sizeof (abuf)), pr->pr_prefix_len, 651 pr->pr_OnLinkLifetime, pr->pr_state, pr->pr_kernel_state); 652 } 653 654 if (pr->pr_kernel_state != pr->pr_state) { 655 prefix_update_k(pr); 656 } 657 658 if (pr->pr_OnLinkLifetime != 0) 659 timer_schedule(pr->pr_OnLinkLifetime); 660 } 661 662 /* 663 * Process all prefix options by locating the DHCPv6-configured interfaces, and 664 * applying the netmasks as needed. 665 */ 666 static void 667 incoming_prefix_stateful(struct phyint *pi, uchar_t *opt) 668 { 669 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 670 struct prefix *pr; 671 boolean_t foundpref; 672 char abuf[INET6_ADDRSTRLEN]; 673 674 /* Make sure it's a valid prefix. */ 675 if (ntohl(po->nd_opt_pi_valid_time) == 0) { 676 if (debug & D_DHCP) 677 logmsg(LOG_DEBUG, "incoming_prefix_stateful: ignoring " 678 "prefix with no valid time\n"); 679 return; 680 } 681 682 if (debug & D_DHCP) 683 logmsg(LOG_DEBUG, "incoming_prefix_stateful(%s, %s/%d)\n", 684 pi->pi_name, inet_ntop(AF_INET6, 685 (void *)&po->nd_opt_pi_prefix, abuf, sizeof (abuf)), 686 po->nd_opt_pi_prefix_len); 687 foundpref = _B_FALSE; 688 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 689 if (prefix_equal(po->nd_opt_pi_prefix, pr->pr_prefix, 690 po->nd_opt_pi_prefix_len)) { 691 if ((pr->pr_flags & IFF_DHCPRUNNING) && 692 pr->pr_prefix_len != po->nd_opt_pi_prefix_len) { 693 pr->pr_prefix_len = po->nd_opt_pi_prefix_len; 694 if (pr->pr_flags & IFF_UP) { 695 if (debug & D_DHCP) 696 logmsg(LOG_DEBUG, 697 "incoming_prefix_stateful:" 698 " set mask on DHCP %s\n", 699 pr->pr_name); 700 prefix_update_dhcp(pr); 701 } 702 } 703 if (pr->pr_prefix_len == po->nd_opt_pi_prefix_len && 704 (!(pr->pr_state & PR_STATIC) || 705 (pr->pr_flags & IFF_DHCPRUNNING))) 706 foundpref = _B_TRUE; 707 } 708 } 709 /* 710 * If there's no matching DHCPv6 prefix present, then create an empty 711 * one so that we'll be able to configure it later. 712 */ 713 if (!foundpref) { 714 pr = prefix_create(pi, po->nd_opt_pi_prefix, 715 po->nd_opt_pi_prefix_len, IFF_DHCPRUNNING); 716 if (pr != NULL) { 717 pr->pr_state = PR_STATIC; 718 if (debug & D_DHCP) 719 logmsg(LOG_DEBUG, 720 "incoming_prefix_stateful: created dummy " 721 "prefix for later\n"); 722 } 723 } 724 } 725 726 /* 727 * Process prefix options with the autonomous flag set. 728 * Returns false if this prefix results in a bad address (duplicate) 729 * This function needs to loop to find the same prefix multiple times 730 * as if a failover happened earlier, the addresses belonging to 731 * a different interface may be found here on this interface. 732 */ 733 static boolean_t 734 incoming_prefix_addrconf(struct phyint *pi, uchar_t *opt, 735 struct sockaddr_in6 *from, boolean_t loopback) 736 { 737 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 738 int plen; 739 struct prefix *pr; 740 uint32_t validtime, preftime; /* In seconds */ 741 char abuf[INET6_ADDRSTRLEN]; 742 char pbuf[INET6_ADDRSTRLEN]; 743 boolean_t found_pub = _B_FALSE; 744 boolean_t found_tmp = _B_FALSE; 745 boolean_t ret; 746 747 validtime = ntohl(po->nd_opt_pi_valid_time); 748 preftime = ntohl(po->nd_opt_pi_preferred_time); 749 plen = po->nd_opt_pi_prefix_len; 750 751 /* Sanity checks */ 752 if (validtime < preftime) { 753 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 754 abuf, sizeof (abuf)); 755 (void) inet_ntop(AF_INET6, 756 (void *)&po->nd_opt_pi_prefix, 757 pbuf, sizeof (pbuf)); 758 logmsg(LOG_WARNING, "prefix option %s/%u from %s on %s: " 759 "valid %u < pref %u ignored\n", 760 pbuf, plen, abuf, pi->pi_name, 761 validtime, preftime); 762 return (_B_FALSE); 763 } 764 765 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 766 if (pr->pr_prefix_len == plen && 767 prefix_equal(po->nd_opt_pi_prefix, pr->pr_prefix, plen)) { 768 769 /* Exclude static prefixes and DHCP */ 770 if ((pr->pr_state & PR_STATIC) || 771 (pr->pr_flags & IFF_DHCPRUNNING)) 772 continue; 773 if (pr->pr_flags & IFF_TEMPORARY) { 774 /* 775 * If this address is deprecated and its token 776 * doesn't match the current tmp token, we want 777 * to create a new address with the current 778 * token. So don't count this addr as a match. 779 */ 780 if (!((pr->pr_flags & IFF_DEPRECATED) && 781 !token_equal(pi->pi_tmp_token, 782 pr->pr_address, TMP_TOKEN_BITS))) 783 found_tmp = _B_TRUE; 784 } else { 785 found_pub = _B_TRUE; 786 } 787 (void) incoming_prefix_addrconf_process(pi, pr, opt, 788 from, loopback, _B_FALSE); 789 } 790 } 791 792 /* 793 * If we have found a matching prefix (for public and, if temp addrs 794 * are enabled, for temporary) already or validtime is zero, we have 795 * nothing to do. 796 */ 797 if (validtime == 0 || 798 (found_pub && (!pi->pi_TmpAddrsEnabled || found_tmp))) 799 return (_B_TRUE); 800 801 if (!found_pub) { 802 pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 0); 803 if (pr == NULL) 804 return (_B_TRUE); 805 ret = incoming_prefix_addrconf_process(pi, pr, opt, from, 806 loopback, _B_TRUE); 807 } 808 /* 809 * if processing of the public address failed, 810 * don't bother with the temporary address. 811 */ 812 if (ret == _B_FALSE) 813 return (_B_FALSE); 814 815 if (pi->pi_TmpAddrsEnabled && !found_tmp) { 816 pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 817 IFF_TEMPORARY); 818 if (pr == NULL) 819 return (_B_TRUE); 820 ret = incoming_prefix_addrconf_process(pi, pr, opt, from, 821 loopback, _B_TRUE); 822 } 823 824 return (ret); 825 } 826 827 boolean_t 828 incoming_prefix_addrconf_process(struct phyint *pi, struct prefix *pr, 829 uchar_t *opt, struct sockaddr_in6 *from, boolean_t loopback, 830 boolean_t new_prefix) 831 { 832 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 833 char abuf[INET6_ADDRSTRLEN]; 834 char pbuf[INET6_ADDRSTRLEN]; 835 uint32_t validtime, preftime; /* In seconds */ 836 uint32_t recorded_validtime; /* In seconds */ 837 int plen; 838 struct prefix *other_pr; 839 840 validtime = ntohl(po->nd_opt_pi_valid_time); 841 preftime = ntohl(po->nd_opt_pi_preferred_time); 842 plen = po->nd_opt_pi_prefix_len; 843 if (!new_prefix) { 844 /* 845 * Check 2 hour rule on valid lifetime. 846 * Follows: RFC 2462 847 * If we advertised this prefix ourselves we skip 848 * these checks. They are also skipped if we did not 849 * previously do addrconf on this prefix. 850 */ 851 recorded_validtime = pr->pr_ValidLifetime / MILLISEC; 852 853 if (loopback || !(pr->pr_state & PR_AUTO) || 854 validtime >= MIN_VALID_LIFETIME || 855 /* LINTED - statement has no consequent */ 856 validtime >= recorded_validtime) { 857 /* OK */ 858 } else if (recorded_validtime < MIN_VALID_LIFETIME && 859 validtime < recorded_validtime) { 860 /* Ignore the prefix */ 861 (void) inet_ntop(AF_INET6, 862 (void *)&from->sin6_addr, 863 abuf, sizeof (abuf)); 864 (void) inet_ntop(AF_INET6, 865 (void *)&po->nd_opt_pi_prefix, 866 pbuf, sizeof (pbuf)); 867 logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: " 868 "too short valid lifetime %u stored %u " 869 "- ignored\n", 870 pbuf, plen, abuf, pi->pi_name, 871 validtime, recorded_validtime); 872 return (_B_TRUE); 873 } else { 874 /* 875 * If the router clock runs slower than the 876 * host by 1 second over 2 hours then this 877 * test will set the lifetime back to 2 hours 878 * once i.e. a lifetime decrementing in 879 * realtime might cause the prefix to live an 880 * extra 2 hours on the host. 881 */ 882 (void) inet_ntop(AF_INET6, 883 (void *)&from->sin6_addr, 884 abuf, sizeof (abuf)); 885 (void) inet_ntop(AF_INET6, 886 (void *)&po->nd_opt_pi_prefix, 887 pbuf, sizeof (pbuf)); 888 logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: " 889 "valid time %u stored %u rounded up " 890 "to %u\n", 891 pbuf, plen, abuf, pi->pi_name, 892 validtime, recorded_validtime, 893 MIN_VALID_LIFETIME); 894 validtime = MIN_VALID_LIFETIME; 895 } 896 } 897 898 /* 899 * For RFC3041 addresses, need to take token lifetime 900 * into account, too. 901 */ 902 if (pr->pr_flags & IFF_TEMPORARY) { 903 uint_t cur_tpreftime = 904 pi->pi_TmpPreferredLifetime - pi->pi_TmpDesyncFactor; 905 906 if (new_prefix) { 907 validtime = MIN(validtime, pi->pi_TmpValidLifetime); 908 preftime = MIN(preftime, cur_tpreftime); 909 } else { 910 uint_t cur_vexp, cur_pexp, curtime; 911 curtime = getcurrenttime() / MILLISEC; 912 913 cur_vexp = pr->pr_CreateTime + pi->pi_TmpValidLifetime; 914 cur_pexp = pr->pr_CreateTime + cur_tpreftime; 915 if (curtime > cur_vexp) 916 validtime = 0; 917 else if ((curtime + validtime) > cur_vexp) 918 validtime = cur_vexp - curtime; 919 /* 920 * If this is an existing address which was deprecated 921 * because of a bad token, we don't want to update its 922 * preferred lifetime! 923 */ 924 if ((pr->pr_PreferredLifetime == 0) && 925 !token_equal(pr->pr_address, pi->pi_tmp_token, 926 TMP_TOKEN_BITS)) 927 preftime = 0; 928 else if (curtime > cur_pexp) 929 preftime = 0; 930 else if ((curtime + preftime) > cur_pexp) 931 preftime = cur_pexp - curtime; 932 } 933 if ((preftime != 0) && (preftime <= pi->pi_TmpRegenAdvance)) { 934 (void) inet_ntop(AF_INET6, 935 (void *)&from->sin6_addr, 936 abuf, sizeof (abuf)); 937 (void) inet_ntop(AF_INET6, 938 (void *)&po->nd_opt_pi_prefix, 939 pbuf, sizeof (pbuf)); 940 logmsg(LOG_WARNING, "prefix opt %s/%u from %s on %s: " 941 "preferred lifetime(%d) <= TmpRegenAdvance(%d)\n", 942 pbuf, plen, abuf, pi->pi_name, preftime, 943 pi->pi_TmpRegenAdvance); 944 if (new_prefix) 945 prefix_delete(pr); 946 return (_B_TRUE); 947 } 948 } 949 if (debug & D_TMP) 950 logmsg(LOG_DEBUG, "calculated lifetimes(%s, 0x%llx): v %d, " 951 "p %d\n", pr->pr_name, pr->pr_flags, validtime, preftime); 952 953 if (!(pr->pr_state & PR_AUTO)) { 954 int i, tokenlen; 955 in6_addr_t *token; 956 /* 957 * Form a new local address if the lengths match. 958 */ 959 if (pr->pr_flags && IFF_TEMPORARY) { 960 if (IN6_IS_ADDR_UNSPECIFIED(&pi->pi_tmp_token)) { 961 if (!tmptoken_create(pi)) { 962 prefix_delete(pr); 963 return (_