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