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 2009 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 bzero(&lifr, sizeof (lifr)); 387 (void) strlcpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 388 389 if (ra->nd_ra_curhoplimit != CURHOP_UNSPECIFIED && 390 ra->nd_ra_curhoplimit != pi->pi_CurHopLimit) { 391 pi->pi_CurHopLimit = ra->nd_ra_curhoplimit; 392 lifr.lifr_ifinfo.lir_maxhops = pi->pi_CurHopLimit; 393 set_needed = _B_TRUE; 394 } 395 396 reachable = ntohl(ra->nd_ra_reachable); 397 if (reachable != 0 && 398 reachable != pi->pi_BaseReachableTime) { 399 pi->pi_BaseReachableTime = reachable; 400 reachable_time_changed = _B_TRUE; 401 } 402 403 if (pi->pi_reach_time_since_random < MIN_REACH_RANDOM_INTERVAL || 404 reachable_time_changed) { 405 phyint_reach_random(pi, _B_FALSE); 406 set_needed = _B_TRUE; 407 } 408 lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime; 409 410 retrans = ntohl(ra->nd_ra_retransmit); 411 if (retrans != 0 && 412 pi->pi_RetransTimer != retrans) { 413 pi->pi_RetransTimer = retrans; 414 lifr.lifr_ifinfo.lir_reachretrans = pi->pi_RetransTimer; 415 set_needed = _B_TRUE; 416 } 417 418 if (set_needed) { 419 if (ioctl(pi->pi_sock, SIOCSLIFLNKINFO, (char *)&lifr) < 0) { 420 logperror_pi(pi, "incoming_ra: SIOCSLIFLNKINFO"); 421 return; 422 } 423 } 424 425 /* 426 * If the "managed" flag is set, then just assume that the "other" flag 427 * is set as well. It's not legal to get addresses alone without 428 * getting other data. 429 */ 430 if (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) 431 ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; 432 433 /* 434 * If either the "managed" or "other" bits have turned on, then it's 435 * now time to invoke DHCP. If only the "other" bit is set, then don't 436 * get addresses via DHCP; only "other" data. If "managed" is set, 437 * then we must always get both addresses and "other" data. 438 */ 439 if (pi->pi_StatefulAddrConf && 440 (ra->nd_ra_flags_reserved & ~pi->pi_ra_flags & 441 (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))) { 442 if (debug & D_DHCP) { 443 logmsg(LOG_DEBUG, 444 "incoming_ra: trigger dhcp %s on %s\n", 445 (ra->nd_ra_flags_reserved & ~pi->pi_ra_flags & 446 ND_RA_FLAG_MANAGED) ? "MANAGED" : "OTHER", 447 pi->pi_name); 448 } 449 pi->pi_ra_flags |= ra->nd_ra_flags_reserved; 450 start_dhcp(pi); 451 } 452 453 /* Skip default router code if sent from ourselves */ 454 if (!loopback) { 455 /* Find and update or add default router in list */ 456 dr = router_lookup(pi, from->sin6_addr); 457 router_lifetime = ntohs(ra->nd_ra_router_lifetime); 458 if (dr == NULL) { 459 if (router_lifetime != 0) { 460 dr = router_create(pi, from->sin6_addr, 461 MILLISEC * router_lifetime); 462 timer_schedule(dr->dr_lifetime); 463 } 464 } else { 465 dr->dr_lifetime = MILLISEC * router_lifetime; 466 if (dr->dr_lifetime != 0) 467 timer_schedule(dr->dr_lifetime); 468 if ((dr->dr_lifetime != 0 && !dr->dr_inkernel) || 469 (dr->dr_lifetime == 0 && dr->dr_inkernel)) 470 router_update_k(dr); 471 } 472 } 473 /* Process any options */ 474 len -= sizeof (struct nd_router_advert); 475 opt = (struct nd_opt_hdr *)&ra[1]; 476 while (len >= sizeof (struct nd_opt_hdr)) { 477 optlen = opt->nd_opt_len * 8; 478 switch (opt->nd_opt_type) { 479 case ND_OPT_PREFIX_INFORMATION: 480 incoming_prefix_opt(pi, (uchar_t *)opt, from, 481 loopback); 482 break; 483 case ND_OPT_MTU: 484 incoming_mtu_opt(pi, (uchar_t *)opt, from); 485 break; 486 case ND_OPT_SOURCE_LINKADDR: 487 /* skip lla option if sent from ourselves! */ 488 if (!loopback) { 489 incoming_lla_opt(pi, (uchar_t *)opt, 490 from, NDF_ISROUTER_ON); 491 slla_opt_present = _B_TRUE; 492 } 493 break; 494 default: 495 break; 496 } 497 opt = (struct nd_opt_hdr *)((char *)opt + optlen); 498 len -= optlen; 499 } 500 if (!loopback && !slla_opt_present) 501 update_ra_flag(pi, from, NDF_ISROUTER_ON); 502 /* Stop sending solicitations */ 503 check_to_solicit(pi, SOLICIT_DONE); 504 } 505 506 /* 507 * Process a received prefix option. 508 * Unless addrconf is turned off we process both the addrconf and the 509 * onlink aspects of the prefix option. 510 * 511 * Note that when a flag (onlink or auto) is turned off we do nothing - 512 * the prefix will time out. 513 */ 514 static void 515 incoming_prefix_opt(struct phyint *pi, uchar_t *opt, 516 struct sockaddr_in6 *from, boolean_t loopback) 517 { 518 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 519 boolean_t good_prefix = _B_TRUE; 520 521 if (8 * po->nd_opt_pi_len != sizeof (*po)) { 522 char abuf[INET6_ADDRSTRLEN]; 523 524 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 525 abuf, sizeof (abuf)); 526 logmsg(LOG_INFO, "prefix option from %s on %s wrong size " 527 "(%d bytes)\n", 528 abuf, pi->pi_name, 529 8 * (int)po->nd_opt_pi_len); 530 return; 531 } 532 if (IN6_IS_ADDR_LINKLOCAL(&po->nd_opt_pi_prefix)) { 533 char abuf[INET6_ADDRSTRLEN]; 534 535 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 536 abuf, sizeof (abuf)); 537 logmsg(LOG_INFO, "RA from %s on %s contains link-local prefix " 538 "- ignored\n", 539 abuf, pi->pi_name); 540 return; 541 } 542 if ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) && 543 pi->pi_StatelessAddrConf) { 544 good_prefix = incoming_prefix_addrconf(pi, opt, from, loopback); 545 } 546 if ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) && 547 good_prefix) { 548 incoming_prefix_onlink(pi, opt); 549 } 550 if (pi->pi_StatefulAddrConf) 551 incoming_prefix_stateful(pi, opt); 552 } 553 554 /* 555 * Process prefix options with the onlink flag set. 556 * 557 * If there are no routers ndpd will add an onlink 558 * default route which will allow communication 559 * between neighbors. 560 * 561 * This function needs to loop to find the same prefix multiple times 562 * as if a failover happened earlier, the addresses belonging to 563 * a different interface may be found here on this interface. 564 */ 565 static void 566 incoming_prefix_onlink(struct phyint *pi, uchar_t *opt) 567 { 568 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 569 int plen; 570 struct prefix *pr; 571 uint32_t validtime; /* Without 2 hour rule */ 572 boolean_t found_one = _B_FALSE; 573 574 plen = po->nd_opt_pi_prefix_len; 575 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 576 if (pr->pr_prefix_len == plen && 577 prefix_equal(po->nd_opt_pi_prefix, pr->pr_prefix, plen)) { 578 /* Exclude static prefixes */ 579 if (pr->pr_state & PR_STATIC) 580 continue; 581 found_one = _B_TRUE; 582 incoming_prefix_onlink_process(pr, opt); 583 } 584 } 585 586 validtime = ntohl(po->nd_opt_pi_valid_time); 587 /* 588 * If we have found a matching prefix already or validtime 589 * is zero, we have nothing to do. 590 */ 591 if (validtime == 0 || found_one) 592 return; 593 pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 0); 594 if (pr == NULL) 595 return; 596 incoming_prefix_onlink_process(pr, opt); 597 } 598 599 void 600 incoming_prefix_onlink_process(struct prefix *pr, uchar_t *opt) 601 { 602 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 603 uint32_t validtime; /* Without 2 hour rule */ 604 char abuf[INET6_ADDRSTRLEN]; 605 606 validtime = ntohl(po->nd_opt_pi_valid_time); 607 if (validtime != 0) 608 pr->pr_state |= PR_ONLINK; 609 else 610 pr->pr_state &= ~PR_ONLINK; 611 612 /* 613 * Convert from seconds to milliseconds avoiding overflow. 614 * If the lifetime in the packet is e.g. PREFIX_INFINITY - 1 615 * (4 billion seconds - about 130 years) we will in fact time 616 * out the prefix after 4 billion milliseconds - 46 days). 617 * Thus the longest lifetime (apart from infinity) is 46 days. 618 * Note that this ensures that PREFIX_INFINITY still means "forever". 619 */ 620 if (pr->pr_flags & IFF_TEMPORARY) { 621 pr->pr_OnLinkLifetime = pr->pr_ValidLifetime; 622 } else { 623 if (validtime >= PREFIX_INFINITY / MILLISEC) 624 pr->pr_OnLinkLifetime = PREFIX_INFINITY - 1; 625 else 626 pr->pr_OnLinkLifetime = validtime * MILLISEC; 627 } 628 pr->pr_OnLinkFlag = _B_TRUE; 629 if (debug & (D_PREFIX|D_TMP)) { 630 logmsg(LOG_DEBUG, "incoming_prefix_onlink_process(%s, %s/%u) " 631 "onlink %u state 0x%x, kstate 0x%x\n", 632 pr->pr_name, inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 633 abuf, sizeof (abuf)), pr->pr_prefix_len, 634 pr->pr_OnLinkLifetime, pr->pr_state, pr->pr_kernel_state); 635 } 636 637 if (pr->pr_kernel_state != pr->pr_state) { 638 prefix_update_k(pr); 639 } 640 641 if (pr->pr_OnLinkLifetime != 0) 642 timer_schedule(pr->pr_OnLinkLifetime); 643 } 644 645 /* 646 * Process all prefix options by locating the DHCPv6-configured interfaces, and 647 * applying the netmasks as needed. 648 */ 649 static void 650 incoming_prefix_stateful(struct phyint *pi, uchar_t *opt) 651 { 652 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 653 struct prefix *pr; 654 boolean_t foundpref; 655 char abuf[INET6_ADDRSTRLEN]; 656 657 /* Make sure it's a valid prefix. */ 658 if (ntohl(po->nd_opt_pi_valid_time) == 0) { 659 if (debug & D_DHCP) 660 logmsg(LOG_DEBUG, "incoming_prefix_stateful: ignoring " 661 "prefix with no valid time\n"); 662 return; 663 } 664 665 if (debug & D_DHCP) 666 logmsg(LOG_DEBUG, "incoming_prefix_stateful(%s, %s/%d)\n", 667 pi->pi_name, inet_ntop(AF_INET6, 668 (void *)&po->nd_opt_pi_prefix, abuf, sizeof (abuf)), 669 po->nd_opt_pi_prefix_len); 670 foundpref = _B_FALSE; 671 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 672 if (prefix_equal(po->nd_opt_pi_prefix, pr->pr_prefix, 673 po->nd_opt_pi_prefix_len)) { 674 if ((pr->pr_flags & IFF_DHCPRUNNING) && 675 pr->pr_prefix_len != po->nd_opt_pi_prefix_len) { 676 pr->pr_prefix_len = po->nd_opt_pi_prefix_len; 677 if (pr->pr_flags & IFF_UP) { 678 if (debug & D_DHCP) 679 logmsg(LOG_DEBUG, 680 "incoming_prefix_stateful:" 681 " set mask on DHCP %s\n", 682 pr->pr_name); 683 prefix_update_dhcp(pr); 684 } 685 } 686 if (pr->pr_prefix_len == po->nd_opt_pi_prefix_len && 687 (!(pr->pr_state & PR_STATIC) || 688 (pr->pr_flags & IFF_DHCPRUNNING))) 689 foundpref = _B_TRUE; 690 } 691 } 692 /* 693 * If there's no matching DHCPv6 prefix present, then create an empty 694 * one so that we'll be able to configure it later. 695 */ 696 if (!foundpref) { 697 pr = prefix_create(pi, po->nd_opt_pi_prefix, 698 po->nd_opt_pi_prefix_len, IFF_DHCPRUNNING); 699 if (pr != NULL) { 700 pr->pr_state = PR_STATIC; 701 if (debug & D_DHCP) 702 logmsg(LOG_DEBUG, 703 "incoming_prefix_stateful: created dummy " 704 "prefix for later\n"); 705 } 706 } 707 } 708 709 /* 710 * Process prefix options with the autonomous flag set. 711 * Returns false if this prefix results in a bad address (duplicate) 712 * This function needs to loop to find the same prefix multiple times 713 * as if a failover happened earlier, the addresses belonging to 714 * a different interface may be found here on this interface. 715 */ 716 static boolean_t 717 incoming_prefix_addrconf(struct phyint *pi, uchar_t *opt, 718 struct sockaddr_in6 *from, boolean_t loopback) 719 { 720 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 721 int plen; 722 struct prefix *pr; 723 uint32_t validtime, preftime; /* In seconds */ 724 char abuf[INET6_ADDRSTRLEN]; 725 char pbuf[INET6_ADDRSTRLEN]; 726 boolean_t found_pub = _B_FALSE; 727 boolean_t found_tmp = _B_FALSE; 728 boolean_t ret; 729 730 validtime = ntohl(po->nd_opt_pi_valid_time); 731 preftime = ntohl(po->nd_opt_pi_preferred_time); 732 plen = po->nd_opt_pi_prefix_len; 733 734 /* Sanity checks */ 735 if (validtime < preftime) { 736 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 737 abuf, sizeof (abuf)); 738 (void) inet_ntop(AF_INET6, 739 (void *)&po->nd_opt_pi_prefix, 740 pbuf, sizeof (pbuf)); 741 logmsg(LOG_WARNING, "prefix option %s/%u from %s on %s: " 742 "valid %u < pref %u ignored\n", 743 pbuf, plen, abuf, pi->pi_name, 744 validtime, preftime); 745 return (_B_FALSE); 746 } 747 748 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 749 if (pr->pr_prefix_len == plen && 750 prefix_equal(po->nd_opt_pi_prefix, pr->pr_prefix, plen)) { 751 752 /* Exclude static prefixes and DHCP */ 753 if ((pr->pr_state & PR_STATIC) || 754 (pr->pr_flags & IFF_DHCPRUNNING)) 755 continue; 756 if (pr->pr_flags & IFF_TEMPORARY) { 757 /* 758 * If this address is deprecated and its token 759 * doesn't match the current tmp token, we want 760 * to create a new address with the current 761 * token. So don't count this addr as a match. 762 */ 763 if (!((pr->pr_flags & IFF_DEPRECATED) && 764 !token_equal(pi->pi_tmp_token, 765 pr->pr_address, TMP_TOKEN_BITS))) 766 found_tmp = _B_TRUE; 767 } else { 768 found_pub = _B_TRUE; 769 } 770 (void) incoming_prefix_addrconf_process(pi, pr, opt, 771 from, loopback, _B_FALSE); 772 } 773 } 774 775 /* 776 * If we have found a matching prefix (for public and, if temp addrs 777 * are enabled, for temporary) already or validtime is zero, we have 778 * nothing to do. 779 */ 780 if (validtime == 0 || 781 (found_pub && (!pi->pi_TmpAddrsEnabled || found_tmp))) 782 return (_B_TRUE); 783 784 if (!found_pub) { 785 pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 0); 786 if (pr == NULL) 787 return (_B_TRUE); 788 ret = incoming_prefix_addrconf_process(pi, pr, opt, from, 789 loopback, _B_TRUE); 790 } 791 /* 792 * if processing of the public address failed, 793 * don't bother with the temporary address. 794 */ 795 if (ret == _B_FALSE) 796 return (_B_FALSE); 797 798 if (pi->pi_TmpAddrsEnabled && !found_tmp) { 799 pr = prefix_create(pi, po->nd_opt_pi_prefix, plen, 800 IFF_TEMPORARY); 801 if (pr == NULL) 802 return (_B_TRUE); 803 ret = incoming_prefix_addrconf_process(pi, pr, opt, from, 804 loopback, _B_TRUE); 805 } 806 807 return (ret); 808 } 809 810 boolean_t 811 incoming_prefix_addrconf_process(struct phyint *pi, struct prefix *pr, 812 uchar_t *opt, struct sockaddr_in6 *from, boolean_t loopback, 813 boolean_t new_prefix) 814 { 815 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 816 char abuf[INET6_ADDRSTRLEN]; 817 char pbuf[INET6_ADDRSTRLEN]; 818 uint32_t validtime, preftime; /* In seconds */ 819 uint32_t recorded_validtime; /* In seconds */ 820 int plen; 821 struct prefix *other_pr; 822 823 validtime = ntohl(po->nd_opt_pi_valid_time); 824 preftime = ntohl(po->nd_opt_pi_preferred_time); 825 plen = po->nd_opt_pi_prefix_len; 826 if (!new_prefix) { 827 /* 828 * Check 2 hour rule on valid lifetime. 829 * Follows: RFC 2462 830 * If we advertised this prefix ourselves we skip 831 * these checks. They are also skipped if we did not 832 * previously do addrconf on this prefix. 833 */ 834 recorded_validtime = pr->pr_ValidLifetime / MILLISEC; 835 836 if (loopback || !(pr->pr_state & PR_AUTO) || 837 validtime >= MIN_VALID_LIFETIME || 838 /* LINTED - statement has no consequent */ 839 validtime >= recorded_validtime) { 840 /* OK */ 841 } else if (recorded_validtime < MIN_VALID_LIFETIME && 842 validtime < recorded_validtime) { 843 /* Ignore the prefix */ 844 (void) inet_ntop(AF_INET6, 845 (void *)&from->sin6_addr, 846 abuf, sizeof (abuf)); 847 (void) inet_ntop(AF_INET6, 848 (void *)&po->nd_opt_pi_prefix, 849 pbuf, sizeof (pbuf)); 850 logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: " 851 "too short valid lifetime %u stored %u " 852 "- ignored\n", 853 pbuf, plen, abuf, pi->pi_name, 854 validtime, recorded_validtime); 855 return (_B_TRUE); 856 } else { 857 /* 858 * If the router clock runs slower than the 859 * host by 1 second over 2 hours then this 860 * test will set the lifetime back to 2 hours 861 * once i.e. a lifetime decrementing in 862 * realtime might cause the prefix to live an 863 * extra 2 hours on the host. 864 */ 865 (void) inet_ntop(AF_INET6, 866 (void *)&from->sin6_addr, 867 abuf, sizeof (abuf)); 868 (void) inet_ntop(AF_INET6, 869 (void *)&po->nd_opt_pi_prefix, 870 pbuf, sizeof (pbuf)); 871 logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: " 872 "valid time %u stored %u rounded up " 873 "to %u\n", 874 pbuf, plen, abuf, pi->pi_name, 875 validtime, recorded_validtime, 876 MIN_VALID_LIFETIME); 877 validtime = MIN_VALID_LIFETIME; 878 } 879 } 880 881 /* 882 * For RFC3041 addresses, need to take token lifetime 883 * into account, too. 884 */ 885 if (pr->pr_flags & IFF_TEMPORARY) { 886 uint_t cur_tpreftime = 887 pi->pi_TmpPreferredLifetime - pi->pi_TmpDesyncFactor; 888 889 if (new_prefix) { 890 validtime = MIN(validtime, pi->pi_TmpValidLifetime); 891 preftime = MIN(preftime, cur_tpreftime); 892 } else { 893 uint_t cur_vexp, cur_pexp, curtime; 894 curtime = getcurrenttime() / MILLISEC; 895 896 cur_vexp = pr->pr_CreateTime + pi->pi_TmpValidLifetime; 897 cur_pexp = pr->pr_CreateTime + cur_tpreftime; 898 if (curtime > cur_vexp) 899 validtime = 0; 900 else if ((curtime + validtime) > cur_vexp) 901 validtime = cur_vexp - curtime; 902 /* 903 * If this is an existing address which was deprecated 904 * because of a bad token, we don't want to update its 905 * preferred lifetime! 906 */ 907 if ((pr->pr_PreferredLifetime == 0) && 908 !token_equal(pr->pr_address, pi->pi_tmp_token, 909 TMP_TOKEN_BITS)) 910 preftime = 0; 911 else if (curtime > cur_pexp) 912 preftime = 0; 913 else if ((curtime + preftime) > cur_pexp) 914 preftime = cur_pexp - curtime; 915 } 916 if ((preftime != 0) && (preftime <= pi->pi_TmpRegenAdvance)) { 917 (void) inet_ntop(AF_INET6, 918 (void *)&from->sin6_addr, 919 abuf, sizeof (abuf)); 920 (void) inet_ntop(AF_INET6, 921 (void *)&po->nd_opt_pi_prefix, 922 pbuf, sizeof (pbuf)); 923 logmsg(LOG_WARNING, "prefix opt %s/%u from %s on %s: " 924 "preferred lifetime(%d) <= TmpRegenAdvance(%d)\n", 925 pbuf, plen, abuf, pi->pi_name, preftime, 926 pi->pi_TmpRegenAdvance); 927 if (new_prefix) 928 prefix_delete(pr); 929 return (_B_TRUE); 930 } 931 } 932 if (debug & D_TMP) 933 logmsg(LOG_DEBUG, "calculated lifetimes(%s, 0x%llx): v %d, " 934 "p %d\n", pr->pr_name, pr->pr_flags, validtime, preftime); 935 936 if (!(pr->pr_state & PR_AUTO)) { 937 int i, tokenlen; 938 in6_addr_t *token; 939 /* 940 * Form a new local address if the lengths match. 941 */ 942 if (pr->pr_flags && IFF_TEMPORARY) { 943 if (IN6_IS_ADDR_UNSPECIFIED(&pi->pi_tmp_token)) { 944 if (!tmptoken_create(pi)) { 945 prefix_delete(pr); 946 return (_B_TRUE); 947 } 948 } 949 tokenlen = TMP_TOKEN_BITS; 950 token = &pi->pi_tmp_token; 951 } else { 952 tokenlen = pi->pi_token_length; 953 token = &pi->pi_token; 954 } 955 if (pr->pr_prefix_len + tokenlen != IPV6_ABITS) { 956 (void) inet_ntop(AF_INET6, 957 (void *)&from->sin6_addr, 958 abuf, sizeof (abuf)); 959 (void) inet_ntop(AF_INET6, 960 (void *)&po->nd_opt_pi_prefix, 961 pbuf, sizeof (pbuf)); 962 logmsg(LOG_INFO, "prefix option %s/%u from %s on %s: " 963 "mismatched length %d token length %d\n", 964 pbuf, plen, abuf, pi->pi_name, 965 pr->pr_prefix_len, tokenlen); 966 return (_B_TRUE); 967 } 968 for (i = 0; i < 16; i++) { 969 /* 970 * prefix_create ensures that pr_prefix has all-zero 971 * bits after prefixlen. 972 */ 973 pr->pr_address.s6_addr[i] = pr->pr_prefix.s6_addr[i] | 974 token->s6_addr[i]; 975 } 976 /* 977 * Check if any other physical interface has the same 978 * address configured already 979 */ 980 if ((other_pr = prefix_lookup_addr_match(pr)) != NULL) { 981 /* 982 * Delete this prefix structure as kernel 983 * does not allow duplicated addresses 984 */ 985 logmsg(LOG_ERR, "incoming_prefix_addrconf_process: " 986 "Duplicate prefix %s received on interface %s\n", 987 inet_ntop(AF_INET6, &po->nd_opt_pi_prefix, abuf, 988 sizeof (abuf)), pi->pi_name); 989 logmsg(LOG_ERR, "incoming_prefix_addrconf_process: " 990 "Prefix already exists in interface %s\n", 991 other_pr->pr_physical->pi_name); 992 if (new_prefix) { 993 prefix_delete(pr); 994 return (_B_FALSE); 995 } 996 /* Ignore for addrconf purposes */ 997 validtime = preftime = 0; 998 } 999 if ((pr->pr_flags & IFF_TEMPORARY) && new_prefix) { 1000 pr->pr_CreateTime = getcurrenttime() / MILLISEC; 1001 if (debug & D_TMP) 1002 logmsg(LOG_DEBUG, 1003 "created tmp addr(%s v %d p %d)\n", 1004 pr->pr_name, validtime, preftime); 1005 } 1006 } 1007 1008 if (validtime != 0) 1009 pr->pr_state |= PR_AUTO; 1010 else 1011 pr->pr_state &= ~(PR_AUTO|PR_DEPRECATED); 1012 if (preftime != 0 || !(pr->pr_state & PR_AUTO)) 1013 pr->pr_state &= ~PR_DEPRECATED; 1014 else 1015 pr->pr_state |= PR_DEPRECATED; 1016 1017 /* 1018 * Convert from seconds to milliseconds avoiding overflow. 1019 * If the lifetime in the packet is e.g. PREFIX_INFINITY - 1 1020 * (4 billion seconds - about 130 years) we will in fact time 1021 * out the prefix after 4 billion milliseconds - 46 days). 1022 * Thus the longest lifetime (apart from infinity) is 46 days. 1023 * Note that this ensures that PREFIX_INFINITY still means "forever". 1024 */ 1025 if (validtime >= PREFIX_INFINITY / MILLISEC) 1026 pr->pr_ValidLifetime = PREFIX_INFINITY - 1; 1027 else 1028 pr->pr_ValidLifetime = validtime * MILLISEC; 1029 if (preftime >= PREFIX_INFINITY / MILLISEC) 1030 pr->pr_PreferredLifetime = PREFIX_INFINITY - 1; 1031 else 1032 pr->pr_PreferredLifetime = preftime * MILLISEC; 1033 pr->pr_AutonomousFlag = _B_TRUE; 1034 1035 if (debug & D_PREFIX) { 1036 logmsg(LOG_DEBUG, "incoming_prefix_addrconf_process(%s, %s/%u) " 1037 "valid %u pref %u\n", 1038 pr->pr_physical->pi_name, 1039 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, 1040 abuf, sizeof (abuf)), pr->pr_prefix_len, 1041 pr->pr_ValidLifetime, pr->pr_PreferredLifetime); 1042 } 1043 1044 if (pr->pr_state & PR_AUTO) { 1045 /* Take the min of the two timeouts by calling it twice */ 1046 if (pr->pr_ValidLifetime != 0) 1047 timer_schedule(pr->pr_ValidLifetime); 1048 if (pr->pr_PreferredLifetime != 0) 1049 timer_schedule(pr->pr_PreferredLifetime); 1050 } 1051 if (pr->pr_kernel_state != pr->pr_state) { 1052 /* Log a message when an addrconf prefix goes away */ 1053 if ((pr->pr_kernel_state & PR_AUTO) && 1054 !(pr->pr_state & PR_AUTO)) { 1055 char abuf[INET6_ADDRSTRLEN]; 1056 1057 logmsg(LOG_WARNING, "Address removed due to zero " 1058 "valid lifetime %s\n", 1059 inet_ntop(AF_INET6, (void *)&pr->pr_address, 1060 abuf, sizeof (abuf))); 1061 } 1062 prefix_update_k(pr); 1063 } 1064 return (_B_TRUE); 1065 } 1066 1067 /* 1068 * Process an MTU option received in a router advertisement. 1069 */ 1070 static void 1071 incoming_mtu_opt(struct phyint *pi, uchar_t *opt, 1072 struct sockaddr_in6 *from) 1073 { 1074 struct nd_opt_mtu *mo = (struct nd_opt_mtu *)opt; 1075 struct lifreq lifr; 1076 uint32_t mtu; 1077 1078 if (8 * mo->nd_opt_mtu_len != sizeof (*mo)) { 1079 char abuf[INET6_ADDRSTRLEN]; 1080 1081 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1082 abuf, sizeof (abuf)); 1083 logmsg(LOG_INFO, "mtu option from %s on %s wrong size " 1084 "(%d bytes)\n", 1085 abuf, pi->pi_name, 1086 8 * (int)mo->nd_opt_mtu_len); 1087 return; 1088 } 1089 mtu = ntohl(mo->nd_opt_mtu_mtu); 1090 if (pi->pi_LinkMTU == mtu) 1091 return; /* No change */ 1092 if (mtu > pi->pi_mtu) { 1093 /* Can't exceed physical MTU */ 1094 char abuf[INET6_ADDRSTRLEN]; 1095 1096 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1097 abuf, sizeof (abuf)); 1098 logmsg(LOG_INFO, "mtu option from %s on %s too large " 1099 "MTU %d - %d\n", abuf, pi->pi_name, mtu, pi->pi_mtu); 1100 return; 1101 } 1102 if (mtu < IPV6_MIN_MTU) { 1103 char abuf[INET6_ADDRSTRLEN]; 1104 1105 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1106 abuf, sizeof (abuf)); 1107 logmsg(LOG_INFO, "mtu option from %s on %s too small " 1108 "MTU (%d)\n", abuf, pi->pi_name, mtu); 1109 return; 1110 } 1111 1112 pi->pi_LinkMTU = mtu; 1113 bzero(&lifr, sizeof (lifr)); 1114 (void) strlcpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 1115 lifr.lifr_ifinfo.lir_maxmtu = pi->pi_LinkMTU; 1116 if (ioctl(pi->pi_sock, SIOCSLIFLNKINFO, (char *)&lifr) < 0) { 1117 logperror_pi(pi, "incoming_mtu_opt: SIOCSLIFLNKINFO"); 1118 return; 1119 } 1120 } 1121 1122 /* 1123 * Process a source link-layer address option received in a router 1124 * advertisement or solicitation. 1125 */ 1126 static void 1127 incoming_lla_opt(struct phyint *pi, uchar_t *opt, 1128 struct sockaddr_in6 *from, int isrouter) 1129 { 1130 struct nd_opt_lla *lo = (struct nd_opt_lla *)opt; 1131 struct lifreq lifr; 1132 struct sockaddr_in6 *sin6; 1133 int max_content_len; 1134 1135 /* 1136 * Get our link-layer address length. We may not have one, in which 1137 * case we can just bail. 1138 */ 1139 if (phyint_get_lla(pi, &lifr) != 0) 1140 return; 1141 1142 /* 1143 * Can't remove padding since it is link type specific. 1144 * However, we check against the length of our link-layer address. 1145 * Note: assumes that all links have a fixed length address. 1146 */ 1147 max_content_len = lo->nd_opt_lla_len * 8 - sizeof (struct nd_opt_hdr); 1148 if (max_content_len < lifr.lifr_nd.lnr_hdw_len || 1149 (max_content_len >= 8 && 1150 max_content_len - 7 > lifr.lifr_nd.lnr_hdw_len)) { 1151 char abuf[INET6_ADDRSTRLEN]; 1152 1153 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1154 abuf, sizeof (abuf)); 1155 logmsg(LOG_INFO, "lla option from %s on %s too long with bad " 1156 "physaddr length (%d vs. %d bytes)\n", abuf, pi->pi_name, 1157 max_content_len, lifr.lifr_nd.lnr_hdw_len); 1158 return; 1159 } 1160 1161 bcopy(lo->nd_opt_lla_hdw_addr, lifr.lifr_nd.lnr_hdw_addr, 1162 lifr.lifr_nd.lnr_hdw_len); 1163 1164 sin6 = (struct sockaddr_in6 *)&lifr.lifr_nd.lnr_addr; 1165 bzero(sin6, sizeof (struct sockaddr_in6)); 1166 sin6->sin6_family = AF_INET6; 1167 sin6->sin6_addr = from->sin6_addr; 1168 1169 /* 1170 * Set IsRouter flag if RA; clear if RS. 1171 */ 1172 lifr.lifr_nd.lnr_state_create = ND_STALE; 1173 lifr.lifr_nd.lnr_state_same_lla = ND_UNCHANGED; 1174 lifr.lifr_nd.lnr_state_diff_lla = ND_STALE; 1175 lifr.lifr_nd.lnr_flags = isrouter; 1176 (void) strlcpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 1177 if (ioctl(pi->pi_sock, SIOCLIFSETND, (char *)&lifr) < 0) { 1178 logperror_pi(pi, "incoming_lla_opt: SIOCLIFSETND"); 1179 return; 1180 } 1181 } 1182 1183 /* 1184 * Verify the content of the received router advertisement against our 1185 * own configuration as specified in RFC 2461. 1186 */ 1187 static void 1188 verify_ra_consistency(struct phyint *pi, struct nd_router_advert *ra, int len, 1189 struct sockaddr_in6 *from) 1190 { 1191 char frombuf[INET6_ADDRSTRLEN]; 1192 struct nd_opt_hdr *opt; 1193 int optlen; 1194 uint_t reachable, retrans; 1195 boolean_t pktflag, myflag; 1196 1197 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1198 frombuf, sizeof (frombuf)); 1199 1200 if (ra->nd_ra_curhoplimit != 0 && 1201 pi->pi_AdvCurHopLimit != 0 && 1202 ra->nd_ra_curhoplimit != pi->pi_AdvCurHopLimit) { 1203 logmsg(LOG_INFO, "RA from %s on %s inconsistent cur hop " 1204 "limit:\n\treceived %d configuration %d\n", 1205 frombuf, pi->pi_name, 1206 ra->nd_ra_curhoplimit, pi->pi_AdvCurHopLimit); 1207 } 1208 1209 reachable = ntohl(ra->nd_ra_reachable); 1210 if (reachable != 0 && pi->pi_AdvReachableTime != 0 && 1211 reachable != pi->pi_AdvReachableTime) { 1212 logmsg(LOG_INFO, "RA from %s on %s inconsistent reachable " 1213 "time:\n\treceived %d configuration %d\n", 1214 frombuf, pi->pi_name, 1215 reachable, pi->pi_AdvReachableTime); 1216 } 1217 1218 retrans = ntohl(ra->nd_ra_retransmit); 1219 if (retrans != 0 && pi->pi_AdvRetransTimer != 0 && 1220 retrans != pi->pi_AdvRetransTimer) { 1221 logmsg(LOG_INFO, "RA from %s on %s inconsistent retransmit " 1222 "timer:\n\treceived %d configuration %d\n", 1223 frombuf, pi->pi_name, 1224 retrans, pi->pi_AdvRetransTimer); 1225 } 1226 1227 pktflag = ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) != 0); 1228 myflag = (pi->pi_AdvManagedFlag != 0); 1229 if (pktflag != myflag) { 1230 logmsg(LOG_INFO, "RA from %s on %s inconsistent managed " 1231 "flag:\n\treceived %s configuration %s\n", 1232 frombuf, pi->pi_name, 1233 (pktflag ? "ON" : "OFF"), 1234 (myflag ? "ON" : "OFF")); 1235 } 1236 pktflag = ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) != 0); 1237 myflag = (pi->pi_AdvOtherConfigFlag != 0); 1238 if (pktflag != myflag) { 1239 logmsg(LOG_INFO, "RA from %s on %s inconsistent other config " 1240 "flag:\n\treceived %s configuration %s\n", 1241 frombuf, pi->pi_name, 1242 (pktflag ? "ON" : "OFF"), 1243 (myflag ? "ON" : "OFF")); 1244 } 1245 1246 /* Process any options */ 1247 len -= sizeof (struct nd_router_advert); 1248 opt = (struct nd_opt_hdr *)&ra[1]; 1249 while (len >= sizeof (struct nd_opt_hdr)) { 1250 optlen = opt->nd_opt_len * 8; 1251 switch (opt->nd_opt_type) { 1252 case ND_OPT_PREFIX_INFORMATION: 1253 verify_prefix_opt(pi, (uchar_t *)opt, frombuf); 1254 break; 1255 case ND_OPT_MTU: 1256 verify_mtu_opt(pi, (uchar_t *)opt, frombuf); 1257 break; 1258 default: 1259 break; 1260 } 1261 opt = (struct nd_opt_hdr *)((char *)opt + optlen); 1262 len -= optlen; 1263 } 1264 } 1265 1266 /* 1267 * Verify that the lifetimes and onlink/auto flags are consistent 1268 * with our settings. 1269 */ 1270 static void 1271 verify_prefix_opt(struct phyint *pi, uchar_t *opt, char *frombuf) 1272 { 1273 struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; 1274 int plen; 1275 struct adv_prefix *adv_pr; 1276 uint32_t validtime, preftime; 1277 char prefixbuf[INET6_ADDRSTRLEN]; 1278 int pktflag, myflag; 1279 1280 if (8 * po->nd_opt_pi_len != sizeof (*po)) { 1281 logmsg(LOG_INFO, "RA prefix option from %s on %s wrong size " 1282 "(%d bytes)\n", 1283 frombuf, pi->pi_name, 1284 8 * (int)po->nd_opt_pi_len); 1285 return; 1286 } 1287 if (IN6_IS_ADDR_LINKLOCAL(&po->nd_opt_pi_prefix)) { 1288 logmsg(LOG_INFO, "RA from %s on %s contains link-local " 1289 "prefix - ignored\n", 1290 frombuf, pi->pi_name); 1291 return; 1292 } 1293 plen = po->nd_opt_pi_prefix_len; 1294 adv_pr = adv_prefix_lookup(pi, po->nd_opt_pi_prefix, plen); 1295 if (adv_pr == NULL) 1296 return; 1297 1298 /* Ignore prefixes which we do not advertise */ 1299 if (!adv_pr->adv_pr_AdvAutonomousFlag && !adv_pr->adv_pr_AdvOnLinkFlag) 1300 return; 1301 (void) inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix, 1302 prefixbuf, sizeof (prefixbuf)); 1303 pktflag = ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) != 0); 1304 myflag = (adv_pr->adv_pr_AdvAutonomousFlag != 0); 1305 if (pktflag != myflag) { 1306 logmsg(LOG_INFO, 1307 "RA from %s on %s inconsistent autonomous flag for \n\t" 1308 "prefix %s/%u: received %s configuration %s\n", 1309 frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, 1310 (pktflag ? "ON" : "OFF"), 1311 (myflag ? "ON" : "OFF")); 1312 } 1313 1314 pktflag = ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) != 0); 1315 myflag = (adv_pr->adv_pr_AdvOnLinkFlag != 0); 1316 if (pktflag != myflag) { 1317 logmsg(LOG_INFO, "RA from %s on %s inconsistent on link flag " 1318 "for \n\tprefix %s/%u: received %s configuration %s\n", 1319 frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, 1320 (pktflag ? "ON" : "OFF"), 1321 (myflag ? "ON" : "OFF")); 1322 } 1323 validtime = ntohl(po->nd_opt_pi_valid_time); 1324 preftime = ntohl(po->nd_opt_pi_preferred_time); 1325 1326 /* 1327 * Take into account variation for lifetimes decrementing 1328 * in real time. Allow +/- 10 percent and +/- 10 seconds. 1329 */ 1330 #define LOWER_LIMIT(val) ((val) - (val)/10 - 10) 1331 #define UPPER_LIMIT(val) ((val) + (val)/10 + 10) 1332 if (adv_pr->adv_pr_AdvValidRealTime) { 1333 if (adv_pr->adv_pr_AdvValidExpiration > 0 && 1334 (validtime < 1335 LOWER_LIMIT(adv_pr->adv_pr_AdvValidExpiration) || 1336 validtime > 1337 UPPER_LIMIT(adv_pr->adv_pr_AdvValidExpiration))) { 1338 logmsg(LOG_INFO, "RA from %s on %s inconsistent valid " 1339 "lifetime for\n\tprefix %s/%u: received %d " 1340 "configuration %d\n", 1341 frombuf, pi->pi_name, prefixbuf, 1342 adv_pr->adv_pr_prefix_len, 1343 validtime, adv_pr->adv_pr_AdvValidExpiration); 1344 } 1345 } else { 1346 if (validtime != adv_pr->adv_pr_AdvValidLifetime) { 1347 logmsg(LOG_INFO, "RA from %s on %s inconsistent valid " 1348 "lifetime for\n\tprefix %s/%u: received %d " 1349 "configuration %d\n", 1350 frombuf, pi->pi_name, prefixbuf, 1351 adv_pr->adv_pr_prefix_len, 1352 validtime, adv_pr->adv_pr_AdvValidLifetime); 1353 } 1354 } 1355 1356 if (adv_pr->adv_pr_AdvPreferredRealTime) { 1357 if (adv_pr->adv_pr_AdvPreferredExpiration > 0 && 1358 (preftime < 1359 LOWER_LIMIT(adv_pr->adv_pr_AdvPreferredExpiration) || 1360 preftime > 1361 UPPER_LIMIT(adv_pr->adv_pr_AdvPreferredExpiration))) { 1362 logmsg(LOG_INFO, "RA from %s on %s inconsistent " 1363 "preferred lifetime for\n\tprefix %s/%u: " 1364 "received %d configuration %d\n", 1365 frombuf, pi->pi_name, prefixbuf, 1366 adv_pr->adv_pr_prefix_len, 1367 preftime, adv_pr->adv_pr_AdvPreferredExpiration); 1368 } 1369 } else { 1370 if (preftime != adv_pr->adv_pr_AdvPreferredLifetime) { 1371 logmsg(LOG_INFO, "RA from %s on %s inconsistent " 1372 "preferred lifetime for\n\tprefix %s/%u: " 1373 "received %d configuration %d\n", 1374 frombuf, pi->pi_name, prefixbuf, 1375 adv_pr->adv_pr_prefix_len, 1376 preftime, adv_pr->adv_pr_AdvPreferredLifetime); 1377 } 1378 } 1379 } 1380 1381 /* 1382 * Verify the received MTU against our own configuration. 1383 */ 1384 static void 1385 verify_mtu_opt(struct phyint *pi, uchar_t *opt, char *frombuf) 1386 { 1387 struct nd_opt_mtu *mo = (struct nd_opt_mtu *)opt; 1388 uint32_t mtu; 1389 1390 if (8 * mo->nd_opt_mtu_len != sizeof (*mo)) { 1391 logmsg(LOG_INFO, "mtu option from %s on %s wrong size " 1392 "(%d bytes)\n", 1393 frombuf, pi->pi_name, 1394 8 * (int)mo->nd_opt_mtu_len); 1395 return; 1396 } 1397 mtu = ntohl(mo->nd_opt_mtu_mtu); 1398 if (pi->pi_AdvLinkMTU != 0 && 1399 pi->pi_AdvLinkMTU != mtu) { 1400 logmsg(LOG_INFO, "RA from %s on %s inconsistent MTU: " 1401 "received %d configuration %d\n", 1402 frombuf, pi->pi_name, 1403 mtu, pi->pi_AdvLinkMTU); 1404 } 1405 } 1406 1407 /* 1408 * Verify that all options have a non-zero length and that 1409 * the options fit within the total length of the packet (optlen). 1410 */ 1411 static boolean_t 1412 verify_opt_len(struct nd_opt_hdr *opt, int optlen, 1413 struct phyint *pi, struct sockaddr_in6 *from) 1414 { 1415 while (optlen > 0) { 1416 if (opt->nd_opt_len == 0) { 1417 char abuf[INET6_ADDRSTRLEN]; 1418 1419 (void) inet_ntop(AF_INET6, 1420 (void *)&from->sin6_addr, 1421 abuf, sizeof (abuf)); 1422 1423 logmsg(LOG_INFO, "Zero length option type 0x%x " 1424 "from %s on %s\n", 1425 opt->nd_opt_type, abuf, pi->pi_name); 1426 return (_B_FALSE); 1427 } 1428 optlen -= 8 * opt->nd_opt_len; 1429 if (optlen < 0) { 1430 char abuf[INET6_ADDRSTRLEN]; 1431 1432 (void) inet_ntop(AF_INET6, 1433 (void *)&from->sin6_addr, 1434 abuf, sizeof (abuf)); 1435 1436 logmsg(LOG_INFO, "Too large option: type 0x%x len %u " 1437 "from %s on %s\n", 1438 opt->nd_opt_type, opt->nd_opt_len, 1439 abuf, pi->pi_name); 1440 return (_B_FALSE); 1441 } 1442 opt = (struct nd_opt_hdr *)((char *)opt + 1443 8 * opt->nd_opt_len); 1444 } 1445 return (_B_TRUE); 1446 } 1447 1448 /* 1449 * Update IsRouter Flag for Host turning into a router or vice-versa. 1450 */ 1451 static void 1452 update_ra_flag(const struct phyint *pi, const struct sockaddr_in6 *from, 1453 int isrouter) 1454 { 1455 struct lifreq lifr; 1456 char abuf[INET6_ADDRSTRLEN]; 1457 struct sockaddr_in6 *sin6; 1458 1459 /* check if valid flag is being set */ 1460 if ((isrouter != NDF_ISROUTER_ON) && 1461 (isrouter != NDF_ISROUTER_OFF)) { 1462 logmsg(LOG_ERR, "update_ra_flag: Invalid IsRouter " 1463 "flag %d\n", isrouter); 1464 return; 1465 } 1466 1467 sin6 = (struct sockaddr_in6 *)&lifr.lifr_nd.lnr_addr; 1468 bzero(sin6, sizeof (*sin6)); 1469 sin6->sin6_family = AF_INET6; 1470 sin6->sin6_addr = from->sin6_addr; 1471 1472 (void) strlcpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name)); 1473 1474 if (ioctl(pi->pi_sock, SIOCLIFGETND, (char *)&lifr) < 0) { 1475 if (errno == ESRCH) { 1476 if (debug & D_IFSCAN) { 1477 logmsg(LOG_DEBUG, 1478 "update_ra_flag: SIOCLIFGETND: nce doesn't exist, not setting IFF_ROUTER"); 1479 } 1480 } else { 1481 logperror_pi(pi, "update_ra_flag: SIOCLIFGETND"); 1482 } 1483 } else { 1484 /* 1485 * The lif_nd_req structure has three state values to be used 1486 * when changing/updating nces : 1487 * lnr_state_create, lnr_state_same_lla, and lnr_state_diff_lla. 1488 * 1489 * In this case, we're updating an nce, without changing lla; 1490 * so we set lnr_state_same_lla to ND_UNCHANGED, indicating that 1491 * nce's state should not be affected by our flag change. 1492 * 1493 * The kernel implementation also expects the lnr_state_create 1494 * field be always set, before processing ioctl request for NCE 1495 * update. 1496 * We use the state as STALE, while addressing the possibility 1497 * of NCE deletion when ioctl with SIOCLIFGETND argument 1498 * in earlier step is returned - further in such case we don't 1499 * want to re-create the entry in the reachable state. 1500 */ 1501 lifr.lifr_nd.lnr_state_create = ND_STALE; 1502 lifr.lifr_nd.lnr_state_same_lla = ND_UNCHANGED; 1503 lifr.lifr_nd.lnr_flags = isrouter; 1504 if ((ioctl(pi->pi_sock, SIOCLIFSETND, (char *)&lifr)) < 0) { 1505 logperror_pi(pi, "update_ra_flag: SIOCLIFSETND"); 1506 } else { 1507 (void) inet_ntop(AF_INET6, (void *)&from->sin6_addr, 1508 abuf, sizeof (abuf)); 1509 logmsg(LOG_INFO, "update_ra_flag: IsRouter flag " 1510 "updated for %s\n", abuf); 1511 } 1512 } 1513 } 1514