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