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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "defs.h" 30 #include "tables.h" 31 32 #include <sys/sysmacros.h> 33 34 static boolean_t verify_opt_len(struct nd_opt_hdr *opt, int optlen, 35 struct phyint *pi, struct sockaddr_in6 *from); 36 37 static void incoming_rs(struct phyint *pi, struct nd_router_solicit *rs, 38 int len, struct sockaddr_in6 *from); 39 40 void incoming_ra(struct phyint *pi, struct nd_router_advert *ra, 41 int len, struct sockaddr_in6 *from, boolean_t loopback); 42 static void incoming_prefix_opt(struct phyint *pi, uchar_t *opt, 43 struct sockaddr_in6 *from, boolean_t loopback); 44 static void incoming_prefix_onlink(struct phyint *pi, uchar_t *opt, 45 struct sockaddr_in6 *from, boolean_t loopback); 46 void incoming_prefix_onlink_process(struct prefix *pr, 47 uchar_t *opt); 48 static boolean_t incoming_prefix_addrconf(struct phyint *pi, 49 uchar_t *opt, struct sockaddr_in6 *from, 50 boolean_t loopback); 51 boolean_t incoming_prefix_addrconf_process(struct phyint *pi, 52 struct prefix *pr, uchar_t *opt, 53 struct sockaddr_in6 *from, boolean_t loopback, 54 boolean_t new_prefix); 55 static void incoming_mtu_opt(struct phyint *pi, uchar_t *opt, 56 struct sockaddr_in6 *from); 57 static void incoming_lla_opt(struct phyint *pi, uchar_t *opt, 58 struct sockaddr_in6 *from, int isrouter); 59 60 static void verify_ra_consistency(struct phyint *pi, 61 struct nd_router_advert *ra, 62 int len, struct sockaddr_in6 *from); 63 static void verify_prefix_opt(struct phyint *pi, uchar_t *opt, 64 char *frombuf); 65 static void verify_mtu_opt(struct phyint *pi, uchar_t *opt, 66 char *frombuf); 67 68 static void update_ra_flag(const struct phyint *pi, 69 const struct sockaddr_in6 *from, int isrouter); 70 71 static uint_t ra_flags; /* Global to detect when to trigger DHCP */ 72 73 /* 74 * Return a pointer to the specified option buffer. 75 * If not found return NULL. 76 */ 77 static void * 78 find_ancillary(struct msghdr *msg, int cmsg_type) 79 { 80 struct cmsghdr *cmsg; 81 82 for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; 83 cmsg = CMSG_NXTHDR(msg, cmsg)) { 84 if (cmsg->cmsg_level == IPPROTO_IPV6 && 85 cmsg->cmsg_type == cmsg_type) { 86 return (CMSG_DATA(cmsg)); 87 } 88 } 89 return (NULL); 90 } 91 92 void 93 in_data(struct phyint *pi) 94 { 95 struct sockaddr_in6 from; 96 struct icmp6_hdr *icmp; 97 struct nd_router_solicit *rs; 98 struct nd_router_advert *ra; 99 static uint64_t in_packet[(IP_MAXPACKET + 1)/8]; 100 static uint64_t ancillary_data[(IP_MAXPACKET + 1)/8]; 101 int len; 102 char abuf[INET6_ADDRSTRLEN]; 103 const char *msgbuf; 104 struct msghdr msg; 105 struct iovec iov; 106 uchar_t *opt; 107 uint_t hoplimit; 108 109 iov.iov_base = (char *)in_packet; 110 iov.iov_len = sizeof (in_packet); 111 msg.msg_iov = &iov; 112 msg.msg_iovlen = 1; 113 msg.msg_name = (struct sockaddr *)&from; 114 msg.msg_namelen = sizeof (from); 115 msg.msg_control = ancillary_data; 116 msg.msg_controllen = sizeof (ancillary_data); 117 118 if ((len = recvmsg(pi->pi_sock, &msg, 0)) < 0) { 119 logperror_pi(pi, "in_data: recvfrom"); 120 return; 121 } 122 if (len == 0) 123 return; 124 125 if (inet_ntop(AF_INET6, (void *)&from.sin6_addr, 126 abuf, sizeof (abuf)) == NULL) 127 msgbuf = "Unspecified Router"; 128 else 129 msgbuf = abuf; 130 131 /* Ignore packets > 64k or control buffers that don't fit */ 132 if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { 133 if (debug & D_PKTBAD) { 134 logmsg(LOG_DEBUG, "Truncated message: msg_flags 0x%x " 135 "from %s\n", msg.msg_flags, msgbuf); 136 } 137 return; 138 } 139 140 icmp = (struct icmp6_hdr *)in_packet; 141 142 if (len < ICMP6_MINLEN) { 143 logmsg(LOG_INFO, "Too short ICMP packet: %d bytes " 144 "from %s on %s\n", 145 len, msgbuf, pi->pi_name); 146 return; 147 } 148 149 opt = find_ancillary(&msg, IPV6_HOPLIMIT); 150 if (opt == NULL) { 151 /* Unknown hoplimit - must drop */ 152 logmsg(LOG_INFO, "Unknown hop limit from %s on %s\n", 153 msgbuf, pi->pi_name); 154 return; 155 } 156 hoplimit = *(uint_t *)opt; 157 opt = find_ancillary(&msg, IPV6_RTHDR); 158 if (opt != NULL) { 159 /* Can't allow routing headers in ND messages */ 160 logmsg(LOG_INFO, "ND message with routing header " 161 "from %s on %s\n", 162 msgbuf, pi->pi_name); 163 return; 164 } 165 switch (icmp->icmp6_type) { 166 case ND_ROUTER_SOLICIT: 167 if (!pi->pi_AdvSendAdvertisements) 168 return; 169 if (pi->pi_flags & IFF_NORTEXCH) { 170 if (debug & D_PKTIN) { 171 logmsg(LOG_DEBUG, "Ignore received RS packet " 172 "on %s (no route exchange on interface)\n", 173 pi->pi_name); 174 } 175 return; 176 } 177 178 /* 179 * Assumes that the kernel has verified the AH (if present) 180 * and the ICMP checksum. 181 */ 182 if (hoplimit != IPV6_MAX_HOPS) { 183 logmsg(LOG_DEBUG, "RS hop limit: %d from %s on %s\n", 184 hoplimit, msgbuf, pi->pi_name); 185 return; 186 } 187 188 if (icmp->icmp6_code != 0) { 189 logmsg(LOG_INFO, "RS code: %d from %s on %s\n", 190 icmp->icmp6_code, msgbuf, pi->pi_name); 191 return; 192 } 193 194 if (len < sizeof (struct nd_router_solicit)) { 195 logmsg(LOG_INFO, "RS too short: %d bytes " 196 "from %s on %s\n", 197 len, msgbuf, pi->pi_name); 198 return; 199 } 200 rs = (struct nd_router_solicit *)icmp; 201 if (len > sizeof (struct nd_router_solicit)) { 202 if (!verify_opt_len((struct nd_opt_hdr *)&rs[1], 203 len - sizeof (struct nd_router_solicit), pi, &from)) 204 return; 205 } 206 if (debug & D_PKTIN) { 207 print_route_sol("Received valid solicit from ", pi, 208 rs, len, &from); 209 } 210 incoming_rs(pi, rs, len, &from); 211 break; 212 213 case ND_ROUTER_ADVERT: 214 if (IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr)) { 215 /* 216 * Router advt. must have address! 217 * Logging the news and returning. 218 */ 219 logmsg(LOG_DEBUG, 220 "Router's address unspecified in advertisement\n"); 221 return; 222 } 223 if (pi->pi_flags & IFF_NORTEXCH) { 224 if (debug & D_PKTIN) { 225 logmsg(LOG_DEBUG, "Ignore received RA packet " 226 "on %s (no route exchange on interface)\n", 227 pi->pi_name); 228 } 229 return; 230 } 231 232 /* 233 * Assumes that the kernel has verified the AH (if present) 234 * and the ICMP checksum. 235 */ 236 if (!IN6_IS_ADDR_LINKLOCAL(&from.sin6_addr)) { 237 logmsg(LOG_DEBUG, "RA from %s - not link local on %s\n", 238 msgbuf, pi->pi_name); 239 return; 240 } 241 242 if (hoplimit != IPV6_MAX_HOPS) { 243 logmsg(LOG_INFO, "RA hop limit: %d from %s on %s\n", 244 hoplimit, msgbuf, pi->pi_name); 245 return; 246 } 247 248 if (icmp->icmp6_code != 0) { 249 logmsg(LOG_INFO, "RA code: %d from %s on %s\n", 250 icmp->icmp6_code, msgbuf, pi->pi_name); 251 return; 252 } 253 254 if (len < sizeof (struct nd_router_advert)) { 255 logmsg(LOG_INFO, "RA too short: %d bytes " 256 "from %s on %s\n", 257 len, msgbuf, pi->pi_name); 258 return; 259 } 260 ra = (struct nd_router_advert *)icmp; 261 if (len > sizeof (struct nd_router_advert)) { 262 if (!verify_opt_len((struct nd_opt_hdr *)&ra[1], 263 len - sizeof (struct nd_router_advert), pi, &from)) 264 return; 265 } 266 if (debug & D_PKTIN) { 267 print_route_adv("Received valid advert from ", pi, 268 ra, len, &from); 269 } 270 if (pi->pi_AdvSendAdvertisements) 271 verify_ra_consistency(pi, ra, len, &from); 272 else 273 incoming_ra(pi, ra, len, &from, _B_FALSE); 274 break; 275 } 276 } 277 278 /* 279 * Process a received router solicitation. 280 * Check for source link-layer address option and check if it 281 * is time to advertise. 282 */ 283 static void 284 incoming_rs(struct phyint *pi, struct nd_router_solicit *rs, int len, 285 struct sockaddr_in6 *from) 286 { 287 struct nd_opt_hdr *opt; 288 int optlen; 289 290 /* Process any options */ 291 len -= sizeof (struct nd_router_solicit); 292 opt = (struct nd_opt_hdr *)&rs[1]; 293 while (len >= sizeof (struct nd_opt_hdr)) { 294 optlen = opt->nd_opt_len * 8; 295 switch (opt->nd_opt_type) { 296 case ND_OPT_SOURCE_LINKADDR: 297 incoming_lla_opt(pi, (uchar_t *)opt, 298 from, NDF_ISROUTER_OFF); 299 break; 300 default: 301 break; 302 } 303 opt = (struct nd_opt_hdr *)((char *)opt + optlen); 304 len -= optlen; 305 } 306 /* Simple algorithm: treat unicast and multicast RSs the same */ 307 check_to_advertise(pi, RECEIVED_SOLICIT); 308 } 309 310 /* 311 * Process a received router advertisement. 312 * Called both when packets arrive as well as when we send RAs. 313 * In the latter case 'loopback' is set. 314 */ 315 void 316 incoming_ra(struct phyint *pi, struct nd_router_advert *ra, int len, 317 struct sockaddr_in6 *from, boolean_t loopback) 318 { 319 struct nd_opt_hdr *opt; 320 int optlen; 321 struct lifreq lifr; 322 boolean_t set_needed = _B_FALSE; 323 struct router *dr; 324 uint16_t router_lifetime; 325 uint_t reachable, retrans; 326 boolean_t reachable_time_changed = _B_FALSE; 327 boolean_t slla_opt_present = _B_FALSE; 328 329 if (no_loopback && loopback) 330 return; 331 332 /* 333 * If the interface is FAILED or INACTIVE or OFFLINE, don't 334 * create any addresses on them. in.mpathd assumes that no new 335 * addresses will appear on these. This implies that we 336 * won't create any new prefixes advertised by the router 337 * on FAILED/INACTIVE/OFFLINE interfaces. When the state changes, 338 * the next RA will create the prefix on this interface. 339 */ 340 if (pi->pi_flags & (IFF_FAILED|IFF_INACTIVE|IFF_OFFLINE)) 341 return; 342 343 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 344 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 345 if (ioctl(pi->pi_sock, SIOCGLIFLNKINFO, (char *)&lifr) < 0) { 346 if (errno == ENXIO) 347 return; 348 logperror_pi(pi, "incoming_ra: SIOCGLIFLNKINFO"); 349 return; 350 } 351 if (ra->nd_ra_curhoplimit != CURHOP_UNSPECIFIED && 352 ra->nd_ra_curhoplimit != pi->pi_CurHopLimit) { 353 pi->pi_CurHopLimit = ra->nd_ra_curhoplimit; 354 355 lifr.lifr_ifinfo.lir_maxhops = pi->pi_CurHopLimit; 356 set_needed = _B_TRUE; 357 } 358 359 reachable = ntohl(ra->nd_ra_reachable); 360 if (reachable != 0 && 361 reachable != pi->pi_BaseReachableTime) { 362 pi->pi_BaseReachableTime = reachable; 363 reachable_time_changed = _B_TRUE; 364 } 365 366 if (pi->pi_reach_time_since_random < MIN_REACH_RANDOM_INTERVAL || 367 reachable_time_changed) { 368 phyint_reach_random(pi, _B_FALSE); 369 set_needed = _B_TRUE; 370 } 371 lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime; 372 373 retrans = ntohl(ra->nd_ra_retransmit); 374 if (retrans != 0 && 375 pi->pi_RetransTimer != retrans) { 376 pi->pi_RetransTimer = retrans; 377 lifr.lifr_ifinfo.lir_reachretrans = pi->pi_RetransTimer; 378 set_needed = _B_TRUE; 379 } 380 381 if (set_needed) { 382 if (ioctl(pi->pi_sock, SIOCSLIFLNKINFO, (char *)&lifr) < 0) { 383 logperror_pi(pi, "incoming_ra: SIOCSLIFLNKINFO"); 384 return; 385 } 386 } 387 388 if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) && 389 !(ra_flags & ND_RA_FLAG_MANAGED)) { 390 ra_flags |= ND_RA_FLAG_MANAGED; 391 /* TODO trigger dhcpv6 */ 392 logmsg(LOG_DEBUG, "incoming_ra: trigger dhcp MANAGED\n"); 393 } 394 if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) && 395 !(ra_flags & ND_RA_FLAG_OTHER)) { 396 ra_flags |= ND_RA_FLAG_OTHER; 397 if (!(ra_flags & ND_RA_FLAG_MANAGED)) { 398 /* TODO trigger dhcpv6 for non-address info */ 399 logmsg(LOG_DEBUG, "incoming_ra: trigger dhcp OTHER\n"); 400 } 401 } 402 /* Skip default router code if sent from ourselves */ 403 if (!loopback) { 404 /* Find and update or add default router in list */ 405 dr = router_lookup(pi, from->sin6_addr); 406 router_lifetime = ntohs(ra->nd_ra_router_lifetime); 407 if (dr == NULL) { 408 if (router_lifetime != 0) { 409 dr = router_create(pi, from->sin6_addr, 410 MILLISEC * router_lifetime); 411 timer_schedule(dr->dr_lifetime); 412 } 413 } else { 414 dr->dr_lifetime = MILLISEC * router_lifetime; 415 if (dr->dr_lifetime != 0) 416 timer_schedule(dr->dr_lifetime); 417 if ((dr->dr_lifetime != 0 && !dr->dr_inkernel) || 418 (dr->dr_lifetime == 0 && dr->dr_inkernel)) 419 router_update_k(dr); 420 } 421 } 422 /* Process any options */ 423 len -= sizeof (struct nd_router_advert); 424 opt = (struct nd_opt_hdr *)&ra[1]; 425 while (len >= sizeof (struct nd_opt_hdr)) { 426 optlen = opt->nd_opt_len * 8; 427 switch (opt->nd_opt_type) { 428 case ND_OPT_PREFIX_INFORMATION: 429 incoming_prefix_opt(pi, (uchar_t *)opt, from, 430 loopback); 431 break; 432 case ND_OPT_MTU: 433 incoming_mtu_opt(pi, (uchar_t *)opt, from); 434 break; 435 case ND_OPT_SOURCE_LINKADDR: 436 /* skip lla option if sent from ourselves! */ 437 if (!loopback) { 438 incoming_lla_opt(pi, (uchar_t *)opt, 439 from, NDF_ISROUTER_ON); 440 slla_opt_present = _B_TRUE; 441 } 442 break; 443 default: 444 break; 445 } 446 opt = (struct nd_opt_hdr *)((char *)opt + optlen); 447 len -= optlen; 448 } 449 if (!loopback && !slla_opt_present) 450 update_ra_flag(pi, from, NDF_ISROUTER_ON); 451 /* Stop sending solicitations */ 452 check_to_solicit(pi, SOLICIT_DONE); 453 } 454 455 /* 456 * Process a received prefix option. 457 * Unless addrconf is turned off we process both the addrconf and the 458 * onlink aspects of the prefix option. 459 * 460 * Note that when a flag (onlink or auto) is turned off we do nothing - 461 * the prefix will time out. 462 */ 463 static void 464 incoming_prefix_opt(struct phyint *pi, uchar_t *opt, 465 struct sockaddr_in6 *from, boolean_t loopback) 466 { 467 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 468 boolean_t good_prefix = _B_TRUE; 469 470 if (8 * po->nd_opt_pi_len != sizeof (*po)) { 471 char abuf[INET6_ADDRSTRLEN]; 472 473 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 474 abuf, sizeof (abuf)); 475 logmsg(LOG_INFO, "prefix option from %s on %s wrong size " 476 "(%d bytes)\n", 477 abuf, pi->pi_name, 478 8 * (int)po->nd_opt_pi_len); 479 return; 480 } 481 if (IN6_IS_ADDR_LINKLOCAL(&po->nd_opt_pi_prefix)) { 482 char abuf[INET6_ADDRSTRLEN]; 483 484 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 485 abuf, sizeof (abuf)); 486 logmsg(LOG_INFO, "RA from %s on %s contains link-local prefix " 487 "- ignored\n", 488 abuf, pi->pi_name); 489 return; 490 } 491 if ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) && 492 pi->pi_StatelessAddrConf) { 493 good_prefix = incoming_prefix_addrconf(pi, opt, from, loopback); 494 } 495 if ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) && 496 good_prefix) { 497 incoming_prefix_onlink(pi, opt, from, loopback); 498 } 499 } 500 501 /* 502 * Process prefix options with the onlink flag set. 503 * 504 * If there are no routers ndpd will add an onlink 505 * default route which will allow communication 506 * between neighbors. 507 * 508 * This function needs to loop to find the same prefix multiple times 509 * as if a failover happened earlier, the addresses belonging to 510 * a different interface may be found here on this interface. 511 */ 512 /* ARGSUSED2 */ 513 static void 514 incoming_prefix_onlink(struct phyint *pi, uchar_t *opt, 515 struct sockaddr_in6 *from, boolean_t loopback) 516 { 517 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 518 int plen; 519 struct prefix *pr; 520 uint32_t validtime; /* Without 2 hour rule */ 521 boolean_t found_one = _B_FALSE; 522 523 plen = po->nd_opt_pi_prefix_len; 524 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 525 if (pr->pr_prefix_len == plen && 526 prefix_equal(po->nd_opt_pi_prefix, pr->pr_prefix, plen)) { 527 /* Exclude static prefixes */ 528 if (pr->pr_state & PR_STATIC) 529 continue; 530 found_one = _B_TRUE; 531 incoming_prefix_onlink_process(pr, opt); 532 } 533 } 534 535 validtime = ntohl(po->nd_opt_pi_valid_time); 536 /* 537 * If we have found a matching prefix already or validtime 538 * is zero, we have nothing to do. 539 */ 540 if (validtime == 0 || found_one) 541 return; 542 pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 0); 543 if (pr == NULL) 544 return; 545 incoming_prefix_onlink_process(pr, opt); 546 } 547 548 void 549 incoming_prefix_onlink_process(struct prefix *pr, uchar_t *opt) 550 { 551 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 552 uint32_t validtime; /* Without 2 hour rule */ 553 char abuf[INET6_ADDRSTRLEN]; 554 555 validtime = ntohl(po->nd_opt_pi_valid_time); 556 if (validtime != 0) 557 pr->pr_state |= PR_ONLINK; 558 else 559 pr->pr_state &= ~PR_ONLINK; 560 561 /* 562 * Convert from seconds to milliseconds avoiding overflow. 563 * If the lifetime in the packet is e.g. PREFIX_INFINITY - 1 564 * (4 billion seconds - about 130 years) we will in fact time 565 * out the prefix after 4 billion milliseconds - 46 days). 566 * Thus the longest lifetime (apart from infinity) is 46 days. 567 * Note that this ensures that PREFIX_INFINITY still means "forever". 568 */ 569 if (pr->pr_flags & IFF_TEMPORARY) { 570 pr->pr_OnLinkLifetime = pr->pr_ValidLifetime; 571 } else { 572 if (validtime >= PREFIX_INFINITY / MILLISEC) 573 pr->pr_OnLinkLifetime = PREFIX_INFINITY - 1; 574 else 575 pr->pr_OnLinkLifetime = validtime * MILLISEC; 576 } 577 pr->pr_OnLinkFlag = _B_TRUE; 578 if (debug & (D_PREFIX|D_TMP)) { 579 logmsg(LOG_DEBUG, "incoming_prefix_onlink_process(%s, %s/%u) " 580 "onlink %u state 0x%x, kstate 0x%x\n", 581 pr->pr_name, inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 582 abuf, sizeof (abuf)), pr->pr_prefix_len, 583 pr->pr_OnLinkLifetime, pr->pr_state, pr->pr_kernel_state); 584 } 585 586 if (pr->pr_kernel_state != pr->pr_state) { 587 prefix_update_k(pr); 588 } 589 590 if (pr->pr_OnLinkLifetime != 0) 591 timer_schedule(pr->pr_OnLinkLifetime); 592 } 593 594 /* 595 * Process prefix options with the autonomous flag set. 596 * Returns false if this prefix results in a bad address (duplicate) 597 * This function needs to loop to find the same prefix multiple times 598 * as if a failover happened earlier, the addresses belonging to 599 * a different interface may be found here on this interface. 600 */ 601 /* ARGSUSED2 */ 602 static boolean_t 603 incoming_prefix_addrconf(struct phyint *pi, uchar_t *opt, 604 struct sockaddr_in6 *from, boolean_t loopback) 605 { 606 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 607 int plen; 608 struct prefix *pr; 609 uint32_t validtime, preftime; /* In seconds */ 610 char abuf[INET6_ADDRSTRLEN]; 611 char pbuf[INET6_ADDRSTRLEN]; 612 boolean_t found_pub = _B_FALSE; 613 boolean_t found_tmp = _B_FALSE; 614 boolean_t ret; 615 616 validtime = ntohl(po->nd_opt_pi_valid_time); 617 preftime = ntohl(po->nd_opt_pi_preferred_time); 618 plen = po->nd_opt_pi_prefix_len; 619 620 /* Sanity checks */ 621 if (validtime < preftime) { 622 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 623 abuf, sizeof (abuf)); 624 (void) inet_ntop(AF_INET6, 625 (void *)&po->nd_opt_pi_prefix, 626 pbuf, sizeof (pbuf)); 627 logmsg(LOG_WARNING, "prefix option %s/%u from %s on %s: " 628 "valid %u < pref %u ignored\n", 629 pbuf, plen, abuf, pi->pi_name, 630 validtime, preftime); 631 return (_B_FALSE); 632 } 633 634 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 635 if (pr->pr_prefix_len == plen && 636 prefix_equal(po->nd_opt_pi_prefix, pr->pr_prefix, plen)) { 637 638 /* Exclude static prefixes */ 639 if (pr->pr_state & PR_STATIC) 640 continue; 641 if (pr->pr_flags & IFF_TEMPORARY) { 642 /* 643 * If this address is deprecated and its token 644 * doesn't match the current tmp token, we want 645 * to create a new address with the current 646 * token. So don't count this addr as a match. 647 */ 648 if (!((pr->pr_flags & IFF_DEPRECATED) && 649 !token_equal(pi->pi_tmp_token, 650 pr->pr_address, TMP_TOKEN_BITS))) 651 found_tmp = _B_TRUE; 652 } else { 653 found_pub = _B_TRUE; 654 } 655 (void) incoming_prefix_addrconf_process(pi, pr, opt, 656 from, loopback, _B_FALSE); 657 } 658 } 659 660 /* 661 * If we have found a matching prefix (for public and, if temp addrs 662 * are enabled, for temporary) already or validtime is zero, we have 663 * nothing to do. 664 */ 665 if (validtime == 0 || 666 (found_pub && (!pi->pi_TmpAddrsEnabled || found_tmp))) 667 return (_B_TRUE); 668 669 if (!found_pub) { 670 pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 0); 671 if (pr == NULL) 672 return (_B_TRUE); 673 ret = incoming_prefix_addrconf_process(pi, pr, opt, from, 674 loopback, _B_TRUE); 675 } 676 /* 677 * if processing of the public address failed, 678 * don't bother with the temporary address. 679 */ 680 if (ret == _B_FALSE) 681 return (_B_FALSE); 682 683 if (pi->pi_TmpAddrsEnabled && !found_tmp) { 684 pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 685 IFF_TEMPORARY); 686 if (pr == NULL) 687 return (_B_TRUE); 688 ret = incoming_prefix_addrconf_process(pi, pr, opt, from, 689 loopback, _B_TRUE); 690 } 691 692 return (ret); 693 } 694 695 boolean_t 696 incoming_prefix_addrconf_process(struct phyint *pi, struct prefix *pr, 697 uchar_t *opt, struct sockaddr_in6 *from, boolean_t loopback, 698 boolean_t new_prefix) 699 { 700 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 701 char abuf[INET6_ADDRSTRLEN]; 702 char pbuf[INET6_ADDRSTRLEN]; 703 uint32_t validtime, preftime; /* In seconds */ 704 uint32_t recorded_validtime; /* In seconds */ 705 int plen, dadfails = 0; 706 struct prefix *other_pr; 707 708 validtime = ntohl(po->nd_opt_pi_valid_time); 709 preftime = ntohl(po->nd_opt_pi_preferred_time); 710 plen = po->nd_opt_pi_prefix_len; 711 if (!new_prefix) { 712 /* 713 * Check 2 hour rule on valid lifetime. 714 * Follows: RFC 2462 715 * If we advertised this prefix ourselves we skip 716 * these checks. They are also skipped if we did not 717 * previously do addrconf on this prefix. 718 */ 719 recorded_validtime = pr->pr_ValidLifetime / MILLISEC; 720 721 if (loopback || !(pr->pr_state & PR_AUTO) || 722 validtime >= MIN_VALID_LIFETIME || 723 /* LINTED - statement has no consequent */ 724 validtime >= recorded_validtime) { 725 /* OK */ 726 } else if (recorded_validtime < MIN_VALID_LIFETIME && 727 validtime < recorded_validtime) { 728 /* Ignore the prefix */ 729 (void) inet_ntop(AF_INET6, 730 (void *)&from->sin6_addr, 731 abuf, sizeof (abuf)); 732 (void) inet_ntop(AF_INET6, 733 (void *)&po->nd_opt_pi_prefix, 734 pbuf, sizeof (pbuf)); 735 logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: " 736 "too short valid lifetime %u stored %u " 737 "- ignored\n", 738 pbuf, plen, abuf, pi->pi_name, 739 validtime, recorded_validtime); 740 return (_B_TRUE); 741 } else { 742 /* 743 * If the router clock runs slower than the 744 * host by 1 second over 2 hours then this 745 * test will set the lifetime back to 2 hours 746 * once i.e. a lifetime decrementing in 747 * realtime might cause the prefix to live an 748 * extra 2 hours on the host. 749 */ 750 (void) inet_ntop(AF_INET6, 751 (void *)&from->sin6_addr, 752 abuf, sizeof (abuf)); 753 (void) inet_ntop(AF_INET6, 754 (void *)&po->nd_opt_pi_prefix, 755 pbuf, sizeof (pbuf)); 756 logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: " 757 "valid time %u stored %u rounded up " 758 "to %u\n", 759 pbuf, plen, abuf, pi->pi_name, 760 validtime, recorded_validtime, 761 MIN_VALID_LIFETIME); 762 validtime = MIN_VALID_LIFETIME; 763 } 764 } 765 766 /* 767 * For RFC3041 addresses, need to take token lifetime 768 * into account, too. 769 */ 770 if (pr->pr_flags & IFF_TEMPORARY) { 771 uint_t cur_tpreftime = 772 pi->pi_TmpPreferredLifetime - pi->pi_TmpDesyncFactor; 773 774 if (new_prefix) { 775 validtime = MIN(validtime, pi->pi_TmpValidLifetime); 776 preftime = MIN(preftime, cur_tpreftime); 777 } else { 778 uint_t cur_vexp, cur_pexp, curtime; 779 curtime = getcurrenttime() / MILLISEC; 780 781 cur_vexp = pr->pr_CreateTime + pi->pi_TmpValidLifetime; 782 cur_pexp = pr->pr_CreateTime + cur_tpreftime; 783 if (curtime > cur_vexp) 784 validtime = 0; 785 else if ((curtime + validtime) > cur_vexp) 786 validtime = cur_vexp - curtime; 787 /* 788 * If this is an existing address which was deprecated 789 * because of a bad token, we don't want to update its 790 * preferred lifetime! 791 */ 792 if ((pr->pr_PreferredLifetime == 0) && 793 !token_equal(pr->pr_address, pi->pi_tmp_token, 794 TMP_TOKEN_BITS)) 795 preftime = 0; 796 else if (curtime > cur_pexp) 797 preftime = 0; 798 else if ((curtime + preftime) > cur_pexp) 799 preftime = cur_pexp - curtime; 800 } 801 if ((preftime != 0) && (preftime <= pi->pi_TmpRegenAdvance)) { 802 (void) inet_ntop(AF_INET6, 803 (void *)&from->sin6_addr, 804 abuf, sizeof (abuf)); 805 (void) inet_ntop(AF_INET6, 806 (void *)&po->nd_opt_pi_prefix, 807 pbuf, sizeof (pbuf)); 808 logmsg(LOG_WARNING, "prefix opt %s/%u from %s on %s: " 809 "preferred lifetime(%d) <= TmpRegenAdvance(%d)\n", 810 pbuf, plen, abuf, pi->pi_name, preftime, 811 pi->pi_TmpRegenAdvance); 812 if (new_prefix) 813 prefix_delete(pr); 814 return (_B_TRUE); 815 } 816 } 817 if (debug & D_TMP) 818 logmsg(LOG_DEBUG, "calculated lifetimes(%s, 0x%llx): v %d, " 819 "p %d\n", pr->pr_name, pr->pr_flags, validtime, preftime); 820 821 if (!(pr->pr_state & PR_AUTO)) { 822 int i, tokenlen; 823 in6_addr_t *token; 824 /* 825 * Form a new local address if the lengths match. 826 */ 827 if (pr->pr_flags && IFF_TEMPORARY) { 828 RETRY_TOKEN: 829 if (IN6_IS_ADDR_UNSPECIFIED(&pi->pi_tmp_token)) { 830 if (!tmptoken_create(pi)) { 831 prefix_delete(pr); 832 return (_B_TRUE); 833 } 834 } 835 tokenlen = TMP_TOKEN_BITS; 836 token = &pi->pi_tmp_token; 837 } else { 838 tokenlen = pi->pi_token_length; 839 token = &pi->pi_token; 840 } 841 if (pr->pr_prefix_len + tokenlen != IPV6_ABITS) { 842 (void) inet_ntop(AF_INET6, 843 (void *)&from->sin6_addr, 844 abuf, sizeof (abuf)); 845 (void) inet_ntop(AF_INET6, 846 (void *)&po->nd_opt_pi_prefix, 847 pbuf, sizeof (pbuf)); 848 logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: " 849 "mismatched length %d token length %d\n", 850 pbuf, plen, abuf, pi->pi_name, 851 pr->pr_prefix_len, tokenlen); 852 return (_B_TRUE); 853 } 854 for (i = 0; i < 16; i++) { 855 /* 856 * prefix_create ensures that pr_prefix has all-zero 857 * bits after prefixlen. 858 */ 859 pr->pr_address.s6_addr[i] = pr->pr_prefix.s6_addr[i] | 860 token->s6_addr[i]; 861 } 862 /* 863 * Check if any other physical interface has the same 864 * address configured already 865 */ 866 if ((other_pr = prefix_lookup_addr_match(pr)) != NULL) { 867 /* 868 * Delete this prefix structure as kernel 869 * does not allow duplicated addresses 870 */ 871 872 logmsg(LOG_ERR, "incoming_prefix_addrconf_process: " 873 "Duplicate prefix %s received on interface %s\n", 874 inet_ntop(AF_INET6, 875 (void *)&po->nd_opt_pi_prefix, abuf, 876 sizeof (abuf)), pi->pi_name); 877 logmsg(LOG_ERR, "incoming_prefix_addrconf_process: " 878 "Prefix already exists in interface %s\n", 879 other_pr->pr_physical->pi_name); 880 if (new_prefix) { 881 prefix_delete(pr); 882 return (_B_FALSE); 883 } 884 /* Ignore for addrconf purposes */ 885 validtime = preftime = 0; 886 } 887 if ((pr->pr_flags & IFF_TEMPORARY) && new_prefix) { 888 struct sockaddr_in6 sin6; 889 sin6.sin6_family = AF_INET6; 890 sin6.sin6_addr = pr->pr_address; 891 if (do_dad(pi->pi_name, &sin6) != 0) { 892 /* DAD failed, need a new token */ 893 dadfails++; 894 logmsg(LOG_WARNING, 895 "incoming_prefix_addrconf_process: " 896 "deprecating temporary token %s\n", 897 inet_ntop(AF_INET6, 898 (void *)&pi->pi_tmp_token, abuf, 899 sizeof (abuf))); 900 tmptoken_delete(pi); 901 if (dadfails == MAX_DAD_FAILURES) { 902 logmsg(LOG_ERR, "Too many DAD " 903 "failures; disabling temporary " 904 "addresses on %s\n", pi->pi_name); 905 pi->pi_TmpAddrsEnabled = 0; 906 prefix_delete(pr); 907 return (_B_TRUE); 908 } 909 goto RETRY_TOKEN; 910 } 911 pr->pr_CreateTime = getcurrenttime() / MILLISEC; 912 if (debug & D_TMP) 913 logmsg(LOG_DEBUG, 914 "created tmp addr(%s v %d p %d)\n", 915 pr->pr_name, validtime, preftime); 916 } 917 } 918 919 if (validtime != 0) 920 pr->pr_state |= PR_AUTO; 921 else 922 pr->pr_state &= ~(PR_AUTO|PR_DEPRECATED); 923 if (preftime != 0 || !(pr->pr_state & PR_AUTO)) 924 pr->pr_state &= ~PR_DEPRECATED; 925 else 926 pr->pr_state |= PR_DEPRECATED; 927 928 /* 929 * Convert from seconds to milliseconds avoiding overflow. 930 * If the lifetime in the packet is e.g. PREFIX_INFINITY - 1 931 * (4 billion seconds - about 130 years) we will in fact time 932 * out the prefix after 4 billion milliseconds - 46 days). 933 * Thus the longest lifetime (apart from infinity) is 46 days. 934 * Note that this ensures that PREFIX_INFINITY still means "forever". 935 */ 936 if (validtime >= PREFIX_INFINITY / MILLISEC) 937 pr->pr_ValidLifetime = PREFIX_INFINITY - 1; 938 else 939 pr->pr_ValidLifetime = validtime * MILLISEC; 940 if (preftime >= PREFIX_INFINITY / MILLISEC) 941 pr->pr_PreferredLifetime = PREFIX_INFINITY - 1; 942 else 943 pr->pr_PreferredLifetime = preftime * MILLISEC; 944 pr->pr_AutonomousFlag = _B_TRUE; 945 946 if (debug & D_PREFIX) { 947 logmsg(LOG_DEBUG, "incoming_prefix_addrconf_process(%s, %s/%u) " 948 "valid %u pref %u\n", 949 pr->pr_physical->pi_name, 950 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 951 abuf, sizeof (abuf)), pr->pr_prefix_len, 952 pr->pr_ValidLifetime, pr->pr_PreferredLifetime); 953 } 954 955 if (pr->pr_state & PR_AUTO) { 956 /* Take the min of the two timeouts by calling it twice */ 957 if (pr->pr_ValidLifetime != 0) 958 timer_schedule(pr->pr_ValidLifetime); 959 if (pr->pr_PreferredLifetime != 0) 960 timer_schedule(pr->pr_PreferredLifetime); 961 } 962 if (pr->pr_kernel_state != pr->pr_state) { 963 /* Log a message when an addrconf prefix goes away */ 964 if ((pr->pr_kernel_state & PR_AUTO) && 965 !(pr->pr_state & PR_AUTO)) { 966 char abuf[INET6_ADDRSTRLEN]; 967 968 logmsg(LOG_WARNING, "Address removed due to zero " 969 "valid lifetime %s\n", 970 inet_ntop(AF_INET6, (void *)&pr->pr_address, 971 abuf, sizeof (abuf))); 972 } 973 prefix_update_k(pr); 974 } 975 return (_B_TRUE); 976 } 977 978 /* 979 * Process an MTU option received in a router advertisement. 980 */ 981 static void 982 incoming_mtu_opt(struct phyint *pi, uchar_t *opt, 983 struct sockaddr_in6 *from) 984 { 985 struct nd_opt_mtu *mo = (struct nd_opt_mtu *)opt; 986 struct lifreq lifr; 987 uint32_t mtu; 988 989 if (8 * mo->nd_opt_mtu_len != sizeof (*mo)) { 990 char abuf[INET6_ADDRSTRLEN]; 991 992 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 993 abuf, sizeof (abuf)); 994 logmsg(LOG_INFO, "mtu option from %s on %s wrong size " 995 "(%d bytes)\n", 996 abuf, pi->pi_name, 997 8 * (int)mo->nd_opt_mtu_len); 998 return; 999 } 1000 mtu = ntohl(mo->nd_opt_mtu_mtu); 1001 if (pi->pi_LinkMTU == mtu) 1002 return; /* No change */ 1003 if (mtu > pi->pi_mtu) { 1004 /* Can't exceed physical MTU */ 1005 char abuf[INET6_ADDRSTRLEN]; 1006 1007 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1008 abuf, sizeof (abuf)); 1009 logmsg(LOG_INFO, "mtu option from %s on %s too large " 1010 "MTU %d - %d\n", abuf, pi->pi_name, mtu, pi->pi_mtu); 1011 return; 1012 } 1013 if (mtu < IPV6_MIN_MTU) { 1014 char abuf[INET6_ADDRSTRLEN]; 1015 1016 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1017 abuf, sizeof (abuf)); 1018 logmsg(LOG_INFO, "mtu option from %s on %s too small " 1019 "MTU (%d)\n", abuf, pi->pi_name, mtu); 1020 return; 1021 } 1022 1023 pi->pi_LinkMTU = mtu; 1024 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 1025 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1026 if (ioctl(pi->pi_sock, SIOCGLIFLNKINFO, (char *)&lifr) < 0) { 1027 logperror_pi(pi, "incoming_mtu_opt: SIOCGLIFLNKINFO"); 1028 return; 1029 } 1030 lifr.lifr_ifinfo.lir_maxmtu = pi->pi_LinkMTU; 1031 if (ioctl(pi->pi_sock, SIOCSLIFLNKINFO, (char *)&lifr) < 0) { 1032 logperror_pi(pi, "incoming_mtu_opt: SIOCSLIFLNKINFO"); 1033 return; 1034 } 1035 } 1036 1037 /* 1038 * Process a source link-layer address option received in a router 1039 * advertisement or solicitation. 1040 */ 1041 static void 1042 incoming_lla_opt(struct phyint *pi, uchar_t *opt, 1043 struct sockaddr_in6 *from, int isrouter) 1044 { 1045 struct nd_opt_lla *lo = (struct nd_opt_lla *)opt; 1046 struct lifreq lifr; 1047 struct sockaddr_in6 *sin6; 1048 int max_content_len; 1049 1050 if (pi->pi_hdw_addr_len == 0) 1051 return; 1052 1053 /* 1054 * Can't remove padding since it is link type specific. 1055 * However, we check against the length of our link-layer 1056 * address. 1057 * Note: assumes that all links have a fixed lengh address. 1058 */ 1059 max_content_len = lo->nd_opt_lla_len * 8 - sizeof (struct nd_opt_hdr); 1060 if (max_content_len < pi->pi_hdw_addr_len || 1061 (max_content_len >= 8 && 1062 max_content_len - 7 > pi->pi_hdw_addr_len)) { 1063 char abuf[INET6_ADDRSTRLEN]; 1064 1065 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1066 abuf, sizeof (abuf)); 1067 logmsg(LOG_INFO, "lla option from %s on %s too long with bad " 1068 "physaddr length (%d vs. %d bytes)\n", 1069 abuf, pi->pi_name, 1070 max_content_len, pi->pi_hdw_addr_len); 1071 return; 1072 } 1073 1074 lifr.lifr_nd.lnr_hdw_len = pi->pi_hdw_addr_len; 1075 bcopy((char *)lo->nd_opt_lla_hdw_addr, 1076 (char *)lifr.lifr_nd.lnr_hdw_addr, 1077 lifr.lifr_nd.lnr_hdw_len); 1078 1079 sin6 = (struct sockaddr_in6 *)&lifr.lifr_nd.lnr_addr; 1080 bzero(sin6, sizeof (struct sockaddr_in6)); 1081 sin6->sin6_family = AF_INET6; 1082 sin6->sin6_addr = from->sin6_addr; 1083 1084 /* 1085 * Set IsRouter flag if RA; clear if RS. 1086 */ 1087 lifr.lifr_nd.lnr_state_create = ND_STALE; 1088 lifr.lifr_nd.lnr_state_same_lla = ND_UNCHANGED; 1089 lifr.lifr_nd.lnr_state_diff_lla = ND_STALE; 1090 lifr.lifr_nd.lnr_flags = isrouter; 1091 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 1092 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 1093 if (ioctl(pi->pi_sock, SIOCLIFSETND, (char *)&lifr) < 0) { 1094 logperror_pi(pi, "incoming_lla_opt: SIOCLIFSETND"); 1095 return; 1096 } 1097 } 1098 1099 /* 1100 * Verify the content of the received router advertisement against our 1101 * own configuration as specified in RFC 2461. 1102 */ 1103 static void 1104 verify_ra_consistency(struct phyint *pi, struct nd_router_advert *ra, int len, 1105 struct sockaddr_in6 *from) 1106 { 1107 char frombuf[INET6_ADDRSTRLEN]; 1108 struct nd_opt_hdr *opt; 1109 int optlen; 1110 uint_t reachable, retrans; 1111 boolean_t pktflag, myflag; 1112 1113 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1114 frombuf, sizeof (frombuf)); 1115 1116 if (ra->nd_ra_curhoplimit != 0 && 1117 pi->pi_AdvCurHopLimit != 0 && 1118 ra->nd_ra_curhoplimit != pi->pi_AdvCurHopLimit) { 1119 logmsg(LOG_INFO, "RA from %s on %s inconsistent cur hop " 1120 "limit:\n\treceived %d configuration %d\n", 1121 frombuf, pi->pi_name, 1122 ra->nd_ra_curhoplimit, pi->pi_AdvCurHopLimit); 1123 } 1124 1125 reachable = ntohl(ra->nd_ra_reachable); 1126 if (reachable != 0 && pi->pi_AdvReachableTime != 0 && 1127 reachable != pi->pi_AdvReachableTime) { 1128 logmsg(LOG_INFO, "RA from %s on %s inconsistent reachable " 1129 "time:\n\treceived %d configuration %d\n", 1130 frombuf, pi->pi_name, 1131 reachable, pi->pi_AdvReachableTime); 1132 } 1133 1134 retrans = ntohl(ra->nd_ra_retransmit); 1135 if (retrans != 0 && pi->pi_AdvRetransTimer != 0 && 1136 retrans != pi->pi_AdvRetransTimer) { 1137 logmsg(LOG_INFO, "RA from %s on %s inconsistent retransmit " 1138 "timer:\n\treceived %d configuration %d\n", 1139 frombuf, pi->pi_name, 1140 retrans, pi->pi_AdvRetransTimer); 1141 } 1142 1143 pktflag = ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) != 0); 1144 myflag = (pi->pi_AdvManagedFlag != 0); 1145 if (pktflag != myflag) { 1146 logmsg(LOG_INFO, "RA from %s on %s inconsistent managed " 1147 "flag:\n\treceived %s configuration %s\n", 1148 frombuf, pi->pi_name, 1149 (pktflag ? "ON" : "OFF"), 1150 (myflag ? "ON" : "OFF")); 1151 } 1152 pktflag = ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) != 0); 1153 myflag = (pi->pi_AdvOtherConfigFlag != 0); 1154 if (pktflag != myflag) { 1155 logmsg(LOG_INFO, "RA from %s on %s inconsistent other config " 1156 "flag:\n\treceived %s configuration %s\n", 1157 frombuf, pi->pi_name, 1158 (pktflag ? "ON" : "OFF"), 1159 (myflag ? "ON" : "OFF")); 1160 } 1161 1162 /* Process any options */ 1163 len -= sizeof (struct nd_router_advert); 1164 opt = (struct nd_opt_hdr *)&ra[1]; 1165 while (len >= sizeof (struct nd_opt_hdr)) { 1166 optlen = opt->nd_opt_len * 8; 1167 switch (opt->nd_opt_type) { 1168 case ND_OPT_PREFIX_INFORMATION: 1169 verify_prefix_opt(pi, (uchar_t *)opt, frombuf); 1170 break; 1171 case ND_OPT_MTU: 1172 verify_mtu_opt(pi, (uchar_t *)opt, frombuf); 1173 break; 1174 default: 1175 break; 1176 } 1177 opt = (struct nd_opt_hdr *)((char *)opt + optlen); 1178 len -= optlen; 1179 } 1180 } 1181 1182 /* 1183 * Verify that the lifetimes and onlink/auto flags are consistent 1184 * with our settings. 1185 */ 1186 static void 1187 verify_prefix_opt(struct phyint *pi, uchar_t *opt, char *frombuf) 1188 { 1189 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 1190 int plen; 1191 struct adv_prefix *adv_pr; 1192 uint32_t validtime, preftime; 1193 char prefixbuf[INET6_ADDRSTRLEN]; 1194 int pktflag, myflag; 1195 1196 if (8 * po->nd_opt_pi_len != sizeof (*po)) { 1197 logmsg(LOG_INFO, "RA prefix option from %s on %s wrong size " 1198 "(%d bytes)\n", 1199 frombuf, pi->pi_name, 1200 8 * (int)po->nd_opt_pi_len); 1201 return; 1202 } 1203 if (IN6_IS_ADDR_LINKLOCAL(&po->nd_opt_pi_prefix)) { 1204 logmsg(LOG_INFO, "RA from %s on %s contains link-local " 1205 "prefix - ignored\n", 1206 frombuf, pi->pi_name); 1207 return; 1208 } 1209 plen = po->nd_opt_pi_prefix_len; 1210 adv_pr = adv_prefix_lookup(pi, po->nd_opt_pi_prefix, plen); 1211 if (adv_pr == NULL) 1212 return; 1213 1214 /* Ignore prefixes which we do not advertise */ 1215 if (!adv_pr->adv_pr_AdvAutonomousFlag && !adv_pr->adv_pr_AdvOnLinkFlag) 1216 return; 1217 (void) inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix, 1218 prefixbuf, sizeof (prefixbuf)); 1219 pktflag = ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) != 0); 1220 myflag = (adv_pr->adv_pr_AdvAutonomousFlag != 0); 1221 if (pktflag != myflag) { 1222 logmsg(LOG_INFO, 1223 "RA from %s on %s inconsistent autonumous flag for \n\t" 1224 "prefix %s/%u: received %s configuration %s\n", 1225 frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, 1226 (pktflag ? "ON" : "OFF"), 1227 (myflag ? "ON" : "OFF")); 1228 } 1229 1230 pktflag = ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) != 0); 1231 myflag = (adv_pr->adv_pr_AdvOnLinkFlag != 0); 1232 if (pktflag != myflag) { 1233 logmsg(LOG_INFO, "RA from %s on %s inconsistent on link flag " 1234 "for \n\tprefix %s/%u: received %s configuration %s\n", 1235 frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, 1236 (pktflag ? "ON" : "OFF"), 1237 (myflag ? "ON" : "OFF")); 1238 } 1239 validtime = ntohl(po->nd_opt_pi_valid_time); 1240 preftime = ntohl(po->nd_opt_pi_preferred_time); 1241 1242 /* 1243 * Take into account variation for lifetimes decrementing 1244 * in real time. Allow +/- 10 percent and +/- 10 seconds. 1245 */ 1246 #define LOWER_LIMIT(val) ((val) - (val)/10 - 10) 1247 #define UPPER_LIMIT(val) ((val) + (val)/10 + 10) 1248 if (adv_pr->adv_pr_AdvValidRealTime) { 1249 if (adv_pr->adv_pr_AdvValidExpiration > 0 && 1250 (validtime < 1251 LOWER_LIMIT(adv_pr->adv_pr_AdvValidExpiration) || 1252 validtime > 1253 UPPER_LIMIT(adv_pr->adv_pr_AdvValidExpiration))) { 1254 logmsg(LOG_INFO, "RA from %s on %s inconsistent valid " 1255 "lifetime for\n\tprefix %s/%u: received %d " 1256 "configuration %d\n", 1257 frombuf, pi->pi_name, prefixbuf, 1258 adv_pr->adv_pr_prefix_len, 1259 validtime, adv_pr->adv_pr_AdvValidExpiration); 1260 } 1261 } else { 1262 if (validtime != adv_pr->adv_pr_AdvValidLifetime) { 1263 logmsg(LOG_INFO, "RA from %s on %s inconsistent valid " 1264 "lifetime for\n\tprefix %s/%u: received %d " 1265 "configuration %d\n", 1266 frombuf, pi->pi_name, prefixbuf, 1267 adv_pr->adv_pr_prefix_len, 1268 validtime, adv_pr->adv_pr_AdvValidLifetime); 1269 } 1270 } 1271 1272 if (adv_pr->adv_pr_AdvPreferredRealTime) { 1273 if (adv_pr->adv_pr_AdvPreferredExpiration > 0 && 1274 (preftime < 1275 LOWER_LIMIT(adv_pr->adv_pr_AdvPreferredExpiration) || 1276 preftime > 1277 UPPER_LIMIT(adv_pr->adv_pr_AdvPreferredExpiration))) { 1278 logmsg(LOG_INFO, "RA from %s on %s inconsistent " 1279 "preferred lifetime for\n\tprefix %s/%u: " 1280 "received %d configuration %d\n", 1281 frombuf, pi->pi_name, prefixbuf, 1282 adv_pr->adv_pr_prefix_len, 1283 preftime, adv_pr->adv_pr_AdvPreferredExpiration); 1284 } 1285 } else { 1286 if (preftime != adv_pr->adv_pr_AdvPreferredLifetime) { 1287 logmsg(LOG_INFO, "RA from %s on %s inconsistent " 1288 "preferred lifetime for\n\tprefix %s/%u: " 1289 "received %d configuration %d\n", 1290 frombuf, pi->pi_name, prefixbuf, 1291 adv_pr->adv_pr_prefix_len, 1292 preftime, adv_pr->adv_pr_AdvPreferredLifetime); 1293 } 1294 } 1295 } 1296 1297 /* 1298 * Verify the received MTU against our own configuration. 1299 */ 1300 static void 1301 verify_mtu_opt(struct phyint *pi, uchar_t *opt, char *frombuf) 1302 { 1303 struct nd_opt_mtu *mo = (struct nd_opt_mtu *)opt; 1304 uint32_t mtu; 1305 1306 if (8 * mo->nd_opt_mtu_len != sizeof (*mo)) { 1307 logmsg(LOG_INFO, "mtu option from %s on %s wrong size " 1308 "(%d bytes)\n", 1309 frombuf, pi->pi_name, 1310 8 * (int)mo->nd_opt_mtu_len); 1311 return; 1312 } 1313 mtu = ntohl(mo->nd_opt_mtu_mtu); 1314 if (pi->pi_AdvLinkMTU != 0 && 1315 pi->pi_AdvLinkMTU != mtu) { 1316 logmsg(LOG_INFO, "RA from %s on %s inconsistent MTU: " 1317 "received %d configuration %d\n", 1318 frombuf, pi->pi_name, 1319 mtu, pi->pi_AdvLinkMTU); 1320 } 1321 } 1322 1323 /* 1324 * Verify that all options have a non-zero length and that 1325 * the options fit within the total length of the packet (optlen). 1326 */ 1327 static boolean_t 1328 verify_opt_len(struct nd_opt_hdr *opt, int optlen, 1329 struct phyint *pi, struct sockaddr_in6 *from) 1330 { 1331 while (optlen > 0) { 1332 if (opt->nd_opt_len == 0) { 1333 char abuf[INET6_ADDRSTRLEN]; 1334 1335 (void) inet_ntop(AF_INET6, 1336 (void *)&from->sin6_addr, 1337 abuf, sizeof (abuf)); 1338 1339 logmsg(LOG_INFO, "Zero length option type 0x%x " 1340 "from %s on %s\n", 1341 opt->nd_opt_type, abuf, pi->pi_name); 1342 return (_B_FALSE); 1343 } 1344 optlen -= 8 * opt->nd_opt_len; 1345 if (optlen < 0) { 1346 char abuf[INET6_ADDRSTRLEN]; 1347 1348 (void) inet_ntop(AF_INET6, 1349 (void *)&from->sin6_addr, 1350 abuf, sizeof (abuf)); 1351 1352 logmsg(LOG_INFO, "Too large option: type 0x%x len %u " 1353 "from %s on %s\n", 1354 opt->nd_opt_type, opt->nd_opt_len, 1355 abuf, pi->pi_name); 1356 return (_B_FALSE); 1357 } 1358 opt = (struct nd_opt_hdr *)((char *)opt + 1359 8 * opt->nd_opt_len); 1360 } 1361 return (_B_TRUE); 1362 } 1363 1364 /* 1365 * Update IsRouter Flag for Host turning into a router or vice-versa. 1366 */ 1367 static void 1368 update_ra_flag(const struct phyint *pi, const struct sockaddr_in6 *from, 1369 int isrouter) 1370 { 1371 struct lifreq lifr; 1372 char abuf[INET6_ADDRSTRLEN]; 1373 struct sockaddr_in6 *sin6; 1374 1375 /* check if valid flag is being set */ 1376 if ((isrouter != NDF_ISROUTER_ON) && 1377 (isrouter != NDF_ISROUTER_OFF)) { 1378 logmsg(LOG_ERR, "update_ra_flag: Invalid IsRouter " 1379 "flag %d\n", isrouter); 1380 return; 1381 } 1382 1383 sin6 = (struct sockaddr_in6 *)&lifr.lifr_nd.lnr_addr; 1384 bzero(sin6, sizeof (*sin6)); 1385 sin6->sin6_family = AF_INET6; 1386 sin6->sin6_addr = from->sin6_addr; 1387 1388 (void) strlcpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 1389 1390 if (ioctl(pi->pi_sock, SIOCLIFGETND, (char *)&lifr) < 0) { 1391 if (errno == ESRCH) { 1392 if (debug & D_IFSCAN) { 1393 logmsg(LOG_DEBUG, 1394 "update_ra_flag: SIOCLIFGETND: nce doesn't exist, not setting IFF_ROUTER"); 1395 } 1396 } else { 1397 logperror_pi(pi, "update_ra_flag: SIOCLIFGETND"); 1398 } 1399 } else { 1400 /* 1401 * The lif_nd_req structure has three state values to be used 1402 * when changing/updating nces : 1403 * lnr_state_create, lnr_state_same_lla, and lnr_state_diff_lla. 1404 * 1405 * In this case, we're updating an nce, without changing lla; 1406 * so we set lnr_state_same_lla to ND_UNCHANGED, indicating that 1407 * nce's state should not be affected by our flag change. 1408 * 1409 * The kernel implementation also expects the lnr_state_create 1410 * field be always set, before processing ioctl request for NCE 1411 * update. 1412 * We use the state as STALE, while addressing the possibility 1413 * of NCE deletion when ioctl with SIOCLIFGETND argument 1414 * in earlier step is returned - further in such case we don't 1415 * want to re-create the entry in the reachable state. 1416 */ 1417 lifr.lifr_nd.lnr_state_create = ND_STALE; 1418 lifr.lifr_nd.lnr_state_same_lla = ND_UNCHANGED; 1419 lifr.lifr_nd.lnr_flags = isrouter; 1420 if ((ioctl(pi->pi_sock, SIOCLIFSETND, (char *)&lifr)) < 0) { 1421 logperror_pi(pi, "update_ra_flag: SIOCLIFSETND"); 1422 } else { 1423 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1424 abuf, sizeof (abuf)); 1425 logmsg(LOG_INFO, "update_ra_flag: IsRouter flag " 1426 "updated for %s\n", abuf); 1427 } 1428 } 1429 } 1430