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