1 /* $OpenBSD: icmp6.c,v 1.239 2022/04/20 09:38:26 bluhm Exp $ */ 2 /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1982, 1986, 1988, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 62 */ 63 64 #include "carp.h" 65 #include "pf.h" 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/malloc.h> 70 #include <sys/mbuf.h> 71 #include <sys/sysctl.h> 72 #include <sys/protosw.h> 73 #include <sys/socket.h> 74 #include <sys/socketvar.h> 75 #include <sys/time.h> 76 #include <sys/kernel.h> 77 #include <sys/syslog.h> 78 79 #include <net/if.h> 80 #include <net/if_var.h> 81 #include <net/route.h> 82 #include <net/if_dl.h> 83 #include <net/if_types.h> 84 85 #include <netinet/in.h> 86 #include <netinet/ip.h> 87 #include <netinet6/in6_var.h> 88 #include <netinet/ip6.h> 89 #include <netinet6/ip6_var.h> 90 #include <netinet/icmp6.h> 91 #include <netinet6/mld6_var.h> 92 #include <netinet/in_pcb.h> 93 #include <netinet6/nd6.h> 94 #include <netinet6/ip6protosw.h> 95 96 #if NCARP > 0 97 #include <netinet/ip_carp.h> 98 #endif 99 100 #if NPF > 0 101 #include <net/pfvar.h> 102 #endif 103 104 struct cpumem *icmp6counters; 105 106 extern int icmp6errppslim; 107 static int icmp6errpps_count = 0; 108 static struct timeval icmp6errppslim_last; 109 110 /* 111 * List of callbacks to notify when Path MTU changes are made. 112 */ 113 struct icmp6_mtudisc_callback { 114 LIST_ENTRY(icmp6_mtudisc_callback) mc_list; 115 void (*mc_func)(struct sockaddr_in6 *, u_int); 116 }; 117 118 LIST_HEAD(, icmp6_mtudisc_callback) icmp6_mtudisc_callbacks = 119 LIST_HEAD_INITIALIZER(icmp6_mtudisc_callbacks); 120 121 struct rttimer_queue *icmp6_mtudisc_timeout_q; 122 123 /* XXX do these values make any sense? */ 124 static int icmp6_mtudisc_hiwat = 1280; 125 static int icmp6_mtudisc_lowat = 256; 126 127 /* 128 * keep track of # of redirect routes. 129 */ 130 struct rttimer_queue *icmp6_redirect_timeout_q; 131 132 /* XXX experimental, turned off */ 133 static int icmp6_redirect_lowat = -1; 134 135 void icmp6_errcount(int, int); 136 int icmp6_ratelimit(const struct in6_addr *, const int, const int); 137 const char *icmp6_redirect_diag(struct in6_addr *, struct in6_addr *, 138 struct in6_addr *); 139 int icmp6_notify_error(struct mbuf *, int, int, int); 140 void icmp6_mtudisc_timeout(struct rtentry *, struct rttimer *); 141 void icmp6_redirect_timeout(struct rtentry *, struct rttimer *); 142 143 void 144 icmp6_init(void) 145 { 146 mld6_init(); 147 icmp6_mtudisc_timeout_q = rt_timer_queue_create(ip6_mtudisc_timeout); 148 icmp6_redirect_timeout_q = rt_timer_queue_create(icmp6_redirtimeout); 149 icmp6counters = counters_alloc(icp6s_ncounters); 150 } 151 152 void 153 icmp6_errcount(int type, int code) 154 { 155 enum icmp6stat_counters c = icp6s_ounknown; 156 157 switch (type) { 158 case ICMP6_DST_UNREACH: 159 switch (code) { 160 case ICMP6_DST_UNREACH_NOROUTE: 161 c = icp6s_odst_unreach_noroute; 162 break; 163 case ICMP6_DST_UNREACH_ADMIN: 164 c = icp6s_odst_unreach_admin; 165 break; 166 case ICMP6_DST_UNREACH_BEYONDSCOPE: 167 c = icp6s_odst_unreach_beyondscope; 168 break; 169 case ICMP6_DST_UNREACH_ADDR: 170 c = icp6s_odst_unreach_addr; 171 break; 172 case ICMP6_DST_UNREACH_NOPORT: 173 c = icp6s_odst_unreach_noport; 174 break; 175 } 176 break; 177 case ICMP6_PACKET_TOO_BIG: 178 c = icp6s_opacket_too_big; 179 break; 180 case ICMP6_TIME_EXCEEDED: 181 switch (code) { 182 case ICMP6_TIME_EXCEED_TRANSIT: 183 c = icp6s_otime_exceed_transit; 184 break; 185 case ICMP6_TIME_EXCEED_REASSEMBLY: 186 c = icp6s_otime_exceed_reassembly; 187 break; 188 } 189 break; 190 case ICMP6_PARAM_PROB: 191 switch (code) { 192 case ICMP6_PARAMPROB_HEADER: 193 c = icp6s_oparamprob_header; 194 break; 195 case ICMP6_PARAMPROB_NEXTHEADER: 196 c = icp6s_oparamprob_nextheader; 197 break; 198 case ICMP6_PARAMPROB_OPTION: 199 c = icp6s_oparamprob_option; 200 break; 201 } 202 break; 203 case ND_REDIRECT: 204 c = icp6s_oredirect; 205 break; 206 } 207 208 icmp6stat_inc(c); 209 } 210 211 /* 212 * Register a Path MTU Discovery callback. 213 */ 214 void 215 icmp6_mtudisc_callback_register(void (*func)(struct sockaddr_in6 *, u_int)) 216 { 217 struct icmp6_mtudisc_callback *mc; 218 219 LIST_FOREACH(mc, &icmp6_mtudisc_callbacks, mc_list) { 220 if (mc->mc_func == func) 221 return; 222 } 223 224 mc = malloc(sizeof(*mc), M_PCB, M_NOWAIT); 225 if (mc == NULL) 226 panic("%s", __func__); 227 228 mc->mc_func = func; 229 LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks, mc, mc_list); 230 } 231 232 struct mbuf * 233 icmp6_do_error(struct mbuf *m, int type, int code, int param) 234 { 235 struct ip6_hdr *oip6, *nip6; 236 struct icmp6_hdr *icmp6; 237 u_int preplen; 238 int off; 239 int nxt; 240 241 icmp6stat_inc(icp6s_error); 242 243 /* count per-type-code statistics */ 244 icmp6_errcount(type, code); 245 246 if (m->m_len < sizeof(struct ip6_hdr)) { 247 m = m_pullup(m, sizeof(struct ip6_hdr)); 248 if (m == NULL) 249 return (NULL); 250 } 251 oip6 = mtod(m, struct ip6_hdr *); 252 253 /* 254 * If the destination address of the erroneous packet is a multicast 255 * address, or the packet was sent using link-layer multicast, 256 * we should basically suppress sending an error (RFC 2463, Section 257 * 2.4). 258 * We have two exceptions (the item e.2 in that section): 259 * - the Packet Too Big message can be sent for path MTU discovery. 260 * - the Parameter Problem Message that can be allowed an icmp6 error 261 * in the option type field. This check has been done in 262 * ip6_unknown_opt(), so we can just check the type and code. 263 */ 264 if ((m->m_flags & (M_BCAST|M_MCAST) || 265 IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) && 266 (type != ICMP6_PACKET_TOO_BIG && 267 (type != ICMP6_PARAM_PROB || 268 code != ICMP6_PARAMPROB_OPTION))) 269 goto freeit; 270 271 /* 272 * RFC 2463, 2.4 (e.5): source address check. 273 * XXX: the case of anycast source? 274 */ 275 if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) || 276 IN6_IS_ADDR_MULTICAST(&oip6->ip6_src)) 277 goto freeit; 278 279 /* 280 * If we are about to send ICMPv6 against ICMPv6 error/redirect, 281 * don't do it. 282 */ 283 nxt = -1; 284 off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt); 285 if (off >= 0 && nxt == IPPROTO_ICMPV6) { 286 struct icmp6_hdr *icp; 287 288 IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off, 289 sizeof(*icp)); 290 if (icp == NULL) { 291 icmp6stat_inc(icp6s_tooshort); 292 return (NULL); 293 } 294 if (icp->icmp6_type < ICMP6_ECHO_REQUEST || 295 icp->icmp6_type == ND_REDIRECT) { 296 /* 297 * ICMPv6 error 298 * Special case: for redirect (which is 299 * informational) we must not send icmp6 error. 300 */ 301 icmp6stat_inc(icp6s_canterror); 302 goto freeit; 303 } else { 304 /* ICMPv6 informational - send the error */ 305 } 306 } 307 else { 308 /* non-ICMPv6 - send the error */ 309 } 310 311 oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */ 312 313 /* Finally, do rate limitation check. */ 314 if (icmp6_ratelimit(&oip6->ip6_src, type, code)) { 315 icmp6stat_inc(icp6s_toofreq); 316 goto freeit; 317 } 318 319 /* 320 * OK, ICMP6 can be generated. 321 */ 322 323 if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN) 324 m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len); 325 326 preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 327 M_PREPEND(m, preplen, M_DONTWAIT); 328 if (m && m->m_len < preplen) 329 m = m_pullup(m, preplen); 330 if (m == NULL) { 331 nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__)); 332 return (NULL); 333 } 334 335 nip6 = mtod(m, struct ip6_hdr *); 336 nip6->ip6_src = oip6->ip6_src; 337 nip6->ip6_dst = oip6->ip6_dst; 338 339 if (IN6_IS_SCOPE_EMBED(&oip6->ip6_src)) 340 oip6->ip6_src.s6_addr16[1] = 0; 341 if (IN6_IS_SCOPE_EMBED(&oip6->ip6_dst)) 342 oip6->ip6_dst.s6_addr16[1] = 0; 343 344 icmp6 = (struct icmp6_hdr *)(nip6 + 1); 345 icmp6->icmp6_type = type; 346 icmp6->icmp6_code = code; 347 icmp6->icmp6_pptr = htonl((u_int32_t)param); 348 349 /* 350 * icmp6_reflect() is designed to be in the input path. 351 * icmp6_error() can be called from both input and output path, 352 * and if we are in output path rcvif could contain bogus value. 353 * clear m->m_pkthdr.ph_ifidx for safety, we should have enough 354 * scope information in ip header (nip6). 355 */ 356 m->m_pkthdr.ph_ifidx = 0; 357 358 icmp6stat_inc(icp6s_outhist + type); 359 360 return (m); 361 362 freeit: 363 /* 364 * If we can't tell whether or not we can generate ICMP6, free it. 365 */ 366 return (m_freem(m)); 367 } 368 369 /* 370 * Generate an error packet of type error in response to bad IP6 packet. 371 */ 372 void 373 icmp6_error(struct mbuf *m, int type, int code, int param) 374 { 375 struct mbuf *n; 376 377 n = icmp6_do_error(m, type, code, param); 378 if (n != NULL) { 379 /* header order: IPv6 - ICMPv6 */ 380 if (!icmp6_reflect(&n, sizeof(struct ip6_hdr), NULL)) 381 ip6_send(n); 382 } 383 } 384 385 /* 386 * Process a received ICMP6 message. 387 */ 388 int 389 icmp6_input(struct mbuf **mp, int *offp, int proto, int af) 390 { 391 #if NCARP > 0 392 struct ifnet *ifp; 393 #endif 394 struct mbuf *m = *mp, *n; 395 struct ip6_hdr *ip6, *nip6; 396 struct icmp6_hdr *icmp6, *nicmp6; 397 int off = *offp; 398 int icmp6len = m->m_pkthdr.len - *offp; 399 int code, sum, noff; 400 char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN]; 401 402 /* 403 * Locate icmp6 structure in mbuf, and check 404 * that not corrupted and of at least minimum length 405 */ 406 407 ip6 = mtod(m, struct ip6_hdr *); 408 if (icmp6len < sizeof(struct icmp6_hdr)) { 409 icmp6stat_inc(icp6s_tooshort); 410 goto freeit; 411 } 412 413 /* 414 * calculate the checksum 415 */ 416 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6)); 417 if (icmp6 == NULL) { 418 icmp6stat_inc(icp6s_tooshort); 419 return IPPROTO_DONE; 420 } 421 code = icmp6->icmp6_code; 422 423 if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) { 424 nd6log((LOG_ERR, 425 "ICMP6 checksum error(%d|%x) %s\n", 426 icmp6->icmp6_type, sum, 427 inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)))); 428 icmp6stat_inc(icp6s_checksum); 429 goto freeit; 430 } 431 432 #if NPF > 0 433 if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { 434 switch (icmp6->icmp6_type) { 435 /* 436 * These ICMP6 types map to other connections. They must be 437 * delivered to pr_ctlinput() also for diverted connections. 438 */ 439 case ICMP6_DST_UNREACH: 440 case ICMP6_PACKET_TOO_BIG: 441 case ICMP6_TIME_EXCEEDED: 442 case ICMP6_PARAM_PROB: 443 /* 444 * Do not use the divert-to property of the TCP or UDP 445 * rule when doing the PCB lookup for the raw socket. 446 */ 447 m->m_pkthdr.pf.flags &=~ PF_TAG_DIVERTED; 448 break; 449 default: 450 goto raw; 451 } 452 } 453 #endif /* NPF */ 454 455 #if NCARP > 0 456 ifp = if_get(m->m_pkthdr.ph_ifidx); 457 if (ifp == NULL) 458 goto freeit; 459 460 if (icmp6->icmp6_type == ICMP6_ECHO_REQUEST && 461 carp_lsdrop(ifp, m, AF_INET6, ip6->ip6_src.s6_addr32, 462 ip6->ip6_dst.s6_addr32, 1)) { 463 if_put(ifp); 464 goto freeit; 465 } 466 467 if_put(ifp); 468 #endif 469 icmp6stat_inc(icp6s_inhist + icmp6->icmp6_type); 470 471 switch (icmp6->icmp6_type) { 472 case ICMP6_DST_UNREACH: 473 switch (code) { 474 case ICMP6_DST_UNREACH_NOROUTE: 475 code = PRC_UNREACH_NET; 476 break; 477 case ICMP6_DST_UNREACH_ADMIN: 478 code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ 479 break; 480 case ICMP6_DST_UNREACH_ADDR: 481 code = PRC_HOSTDEAD; 482 break; 483 case ICMP6_DST_UNREACH_BEYONDSCOPE: 484 /* I mean "source address was incorrect." */ 485 code = PRC_PARAMPROB; 486 break; 487 case ICMP6_DST_UNREACH_NOPORT: 488 code = PRC_UNREACH_PORT; 489 break; 490 default: 491 goto badcode; 492 } 493 goto deliver; 494 495 case ICMP6_PACKET_TOO_BIG: 496 /* MTU is checked in icmp6_mtudisc_update. */ 497 code = PRC_MSGSIZE; 498 499 /* 500 * Updating the path MTU will be done after examining 501 * intermediate extension headers. 502 */ 503 goto deliver; 504 505 case ICMP6_TIME_EXCEEDED: 506 switch (code) { 507 case ICMP6_TIME_EXCEED_TRANSIT: 508 code = PRC_TIMXCEED_INTRANS; 509 break; 510 case ICMP6_TIME_EXCEED_REASSEMBLY: 511 code = PRC_TIMXCEED_REASS; 512 break; 513 default: 514 goto badcode; 515 } 516 goto deliver; 517 518 case ICMP6_PARAM_PROB: 519 switch (code) { 520 case ICMP6_PARAMPROB_NEXTHEADER: 521 code = PRC_UNREACH_PROTOCOL; 522 break; 523 case ICMP6_PARAMPROB_HEADER: 524 case ICMP6_PARAMPROB_OPTION: 525 code = PRC_PARAMPROB; 526 break; 527 default: 528 goto badcode; 529 } 530 goto deliver; 531 532 case ICMP6_ECHO_REQUEST: 533 if (code != 0) 534 goto badcode; 535 /* 536 * Copy mbuf to send to two data paths: userland socket(s), 537 * and to the querier (echo reply). 538 * m: a copy for socket, n: a copy for querier 539 */ 540 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 541 /* Give up local */ 542 n = m; 543 m = *mp = NULL; 544 goto deliverecho; 545 } 546 /* 547 * If the first mbuf is shared, or the first mbuf is too short, 548 * copy the first part of the data into a fresh mbuf. 549 * Otherwise, we will wrongly overwrite both copies. 550 */ 551 if ((n->m_flags & M_EXT) != 0 || 552 n->m_len < off + sizeof(struct icmp6_hdr)) { 553 struct mbuf *n0 = n; 554 const int maxlen = sizeof(*nip6) + sizeof(*nicmp6); 555 556 /* 557 * Prepare an internal mbuf. m_pullup() doesn't 558 * always copy the length we specified. 559 */ 560 if (maxlen >= MCLBYTES) { 561 /* Give up remote */ 562 m_freem(n0); 563 break; 564 } 565 MGETHDR(n, M_DONTWAIT, n0->m_type); 566 if (n && maxlen >= MHLEN) { 567 MCLGET(n, M_DONTWAIT); 568 if ((n->m_flags & M_EXT) == 0) { 569 m_free(n); 570 n = NULL; 571 } 572 } 573 if (n == NULL) { 574 /* Give up local */ 575 m_freem(n0); 576 n = m; 577 m = *mp = NULL; 578 goto deliverecho; 579 } 580 M_MOVE_PKTHDR(n, n0); 581 /* 582 * Copy IPv6 and ICMPv6 only. 583 */ 584 nip6 = mtod(n, struct ip6_hdr *); 585 bcopy(ip6, nip6, sizeof(struct ip6_hdr)); 586 nicmp6 = (struct icmp6_hdr *)(nip6 + 1); 587 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); 588 noff = sizeof(struct ip6_hdr); 589 n->m_len = noff + sizeof(struct icmp6_hdr); 590 /* 591 * Adjust mbuf. ip6_plen will be adjusted in 592 * ip6_output(). 593 * n->m_pkthdr.len == n0->m_pkthdr.len at this point. 594 */ 595 n->m_pkthdr.len += noff + sizeof(struct icmp6_hdr); 596 n->m_pkthdr.len -= (off + sizeof(struct icmp6_hdr)); 597 m_adj(n0, off + sizeof(struct icmp6_hdr)); 598 n->m_next = n0; 599 } else { 600 deliverecho: 601 IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off, 602 sizeof(*nicmp6)); 603 noff = off; 604 } 605 if (n) { 606 nicmp6->icmp6_type = ICMP6_ECHO_REPLY; 607 nicmp6->icmp6_code = 0; 608 icmp6stat_inc(icp6s_reflect); 609 icmp6stat_inc(icp6s_outhist + ICMP6_ECHO_REPLY); 610 if (!icmp6_reflect(&n, noff, NULL)) 611 ip6_send(n); 612 } 613 if (!m) 614 goto freeit; 615 break; 616 617 case ICMP6_ECHO_REPLY: 618 if (code != 0) 619 goto badcode; 620 break; 621 622 case MLD_LISTENER_QUERY: 623 case MLD_LISTENER_REPORT: 624 if (icmp6len < sizeof(struct mld_hdr)) 625 goto badlen; 626 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 627 /* give up local */ 628 mld6_input(m, off); 629 m = NULL; 630 goto freeit; 631 } 632 mld6_input(n, off); 633 /* m stays. */ 634 break; 635 636 case MLD_LISTENER_DONE: 637 if (icmp6len < sizeof(struct mld_hdr)) /* necessary? */ 638 goto badlen; 639 break; /* nothing to be done in kernel */ 640 641 case MLD_MTRACE_RESP: 642 case MLD_MTRACE: 643 /* XXX: these two are experimental. not officially defined. */ 644 /* XXX: per-interface statistics? */ 645 break; /* just pass it to applications */ 646 647 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */ 648 /* IPv6 Node Information Queries are not supported */ 649 break; 650 case ICMP6_WRUREPLY: 651 break; 652 653 case ND_ROUTER_SOLICIT: 654 case ND_ROUTER_ADVERT: 655 if (code != 0) 656 goto badcode; 657 if ((icmp6->icmp6_type == ND_ROUTER_SOLICIT && icmp6len < 658 sizeof(struct nd_router_solicit)) || 659 (icmp6->icmp6_type == ND_ROUTER_ADVERT && icmp6len < 660 sizeof(struct nd_router_advert))) 661 goto badlen; 662 663 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 664 /* give up local */ 665 nd6_rtr_cache(m, off, icmp6len, 666 icmp6->icmp6_type); 667 m = NULL; 668 goto freeit; 669 } 670 nd6_rtr_cache(n, off, icmp6len, icmp6->icmp6_type); 671 /* m stays. */ 672 break; 673 674 case ND_NEIGHBOR_SOLICIT: 675 if (code != 0) 676 goto badcode; 677 if (icmp6len < sizeof(struct nd_neighbor_solicit)) 678 goto badlen; 679 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 680 /* give up local */ 681 nd6_ns_input(m, off, icmp6len); 682 m = NULL; 683 goto freeit; 684 } 685 nd6_ns_input(n, off, icmp6len); 686 /* m stays. */ 687 break; 688 689 case ND_NEIGHBOR_ADVERT: 690 if (code != 0) 691 goto badcode; 692 if (icmp6len < sizeof(struct nd_neighbor_advert)) 693 goto badlen; 694 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 695 /* give up local */ 696 nd6_na_input(m, off, icmp6len); 697 m = NULL; 698 goto freeit; 699 } 700 nd6_na_input(n, off, icmp6len); 701 /* m stays. */ 702 break; 703 704 case ND_REDIRECT: 705 if (code != 0) 706 goto badcode; 707 if (icmp6len < sizeof(struct nd_redirect)) 708 goto badlen; 709 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 710 /* give up local */ 711 icmp6_redirect_input(m, off); 712 m = NULL; 713 goto freeit; 714 } 715 icmp6_redirect_input(n, off); 716 /* m stays. */ 717 break; 718 719 case ICMP6_ROUTER_RENUMBERING: 720 if (code != ICMP6_ROUTER_RENUMBERING_COMMAND && 721 code != ICMP6_ROUTER_RENUMBERING_RESULT) 722 goto badcode; 723 if (icmp6len < sizeof(struct icmp6_router_renum)) 724 goto badlen; 725 break; 726 727 default: 728 nd6log((LOG_DEBUG, 729 "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%u)\n", 730 icmp6->icmp6_type, 731 inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)), 732 inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst)), 733 m->m_pkthdr.ph_ifidx)); 734 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { 735 /* ICMPv6 error: MUST deliver it by spec... */ 736 code = PRC_NCMDS; 737 /* deliver */ 738 } else { 739 /* ICMPv6 informational: MUST not deliver */ 740 break; 741 } 742 deliver: 743 if (icmp6_notify_error(m, off, icmp6len, code)) { 744 /* In this case, m should've been freed. */ 745 return (IPPROTO_DONE); 746 } 747 break; 748 749 badcode: 750 icmp6stat_inc(icp6s_badcode); 751 break; 752 753 badlen: 754 icmp6stat_inc(icp6s_badlen); 755 break; 756 } 757 758 #if NPF > 0 759 raw: 760 #endif 761 /* deliver the packet to appropriate sockets */ 762 return rip6_input(mp, offp, proto, af); 763 764 freeit: 765 m_freem(m); 766 return IPPROTO_DONE; 767 } 768 769 int 770 icmp6_notify_error(struct mbuf *m, int off, int icmp6len, int code) 771 { 772 struct icmp6_hdr *icmp6; 773 struct ip6_hdr *eip6; 774 u_int32_t notifymtu; 775 struct sockaddr_in6 icmp6src, icmp6dst; 776 777 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) { 778 icmp6stat_inc(icp6s_tooshort); 779 goto freeit; 780 } 781 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 782 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 783 if (icmp6 == NULL) { 784 icmp6stat_inc(icp6s_tooshort); 785 return (-1); 786 } 787 eip6 = (struct ip6_hdr *)(icmp6 + 1); 788 789 /* Detect the upper level protocol */ 790 { 791 void (*ctlfunc)(int, struct sockaddr *, u_int, void *); 792 u_int8_t nxt = eip6->ip6_nxt; 793 int eoff = off + sizeof(struct icmp6_hdr) + 794 sizeof(struct ip6_hdr); 795 struct ip6ctlparam ip6cp; 796 struct in6_addr *finaldst = NULL; 797 int icmp6type = icmp6->icmp6_type; 798 struct ip6_frag *fh; 799 struct ip6_rthdr *rth; 800 struct ip6_rthdr0 *rth0; 801 int rthlen; 802 803 while (1) { /* XXX: should avoid infinite loop explicitly? */ 804 struct ip6_ext *eh; 805 806 switch (nxt) { 807 case IPPROTO_HOPOPTS: 808 case IPPROTO_DSTOPTS: 809 case IPPROTO_AH: 810 IP6_EXTHDR_GET(eh, struct ip6_ext *, m, 811 eoff, sizeof(*eh)); 812 if (eh == NULL) { 813 icmp6stat_inc(icp6s_tooshort); 814 return (-1); 815 } 816 817 if (nxt == IPPROTO_AH) 818 eoff += (eh->ip6e_len + 2) << 2; 819 else 820 eoff += (eh->ip6e_len + 1) << 3; 821 nxt = eh->ip6e_nxt; 822 break; 823 case IPPROTO_ROUTING: 824 /* 825 * When the erroneous packet contains a 826 * routing header, we should examine the 827 * header to determine the final destination. 828 * Otherwise, we can't properly update 829 * information that depends on the final 830 * destination (e.g. path MTU). 831 */ 832 IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m, 833 eoff, sizeof(*rth)); 834 if (rth == NULL) { 835 icmp6stat_inc(icp6s_tooshort); 836 return (-1); 837 } 838 rthlen = (rth->ip6r_len + 1) << 3; 839 /* 840 * XXX: currently there is no 841 * officially defined type other 842 * than type-0. 843 * Note that if the segment left field 844 * is 0, all intermediate hops must 845 * have been passed. 846 */ 847 if (rth->ip6r_segleft && 848 rth->ip6r_type == IPV6_RTHDR_TYPE_0) { 849 int hops; 850 851 IP6_EXTHDR_GET(rth0, 852 struct ip6_rthdr0 *, m, 853 eoff, rthlen); 854 if (rth0 == NULL) { 855 icmp6stat_inc(icp6s_tooshort); 856 return (-1); 857 } 858 /* just ignore a bogus header */ 859 if ((rth0->ip6r0_len % 2) == 0 && 860 (hops = rth0->ip6r0_len/2)) 861 finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1); 862 } 863 eoff += rthlen; 864 nxt = rth->ip6r_nxt; 865 break; 866 case IPPROTO_FRAGMENT: 867 IP6_EXTHDR_GET(fh, struct ip6_frag *, m, 868 eoff, sizeof(*fh)); 869 if (fh == NULL) { 870 icmp6stat_inc(icp6s_tooshort); 871 return (-1); 872 } 873 /* 874 * Data after a fragment header is meaningless 875 * unless it is the first fragment, but 876 * we'll go to the notify label for path MTU 877 * discovery. 878 */ 879 if (fh->ip6f_offlg & IP6F_OFF_MASK) 880 goto notify; 881 882 eoff += sizeof(struct ip6_frag); 883 nxt = fh->ip6f_nxt; 884 break; 885 default: 886 /* 887 * This case includes ESP and the No Next 888 * Header. In such cases going to the notify 889 * label does not have any meaning 890 * (i.e. ctlfunc will be NULL), but we go 891 * anyway since we might have to update 892 * path MTU information. 893 */ 894 goto notify; 895 } 896 } 897 notify: 898 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 899 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 900 if (icmp6 == NULL) { 901 icmp6stat_inc(icp6s_tooshort); 902 return (-1); 903 } 904 905 eip6 = (struct ip6_hdr *)(icmp6 + 1); 906 bzero(&icmp6dst, sizeof(icmp6dst)); 907 icmp6dst.sin6_len = sizeof(struct sockaddr_in6); 908 icmp6dst.sin6_family = AF_INET6; 909 if (finaldst == NULL) 910 icmp6dst.sin6_addr = eip6->ip6_dst; 911 else 912 icmp6dst.sin6_addr = *finaldst; 913 icmp6dst.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, 914 &icmp6dst.sin6_addr); 915 if (in6_embedscope(&icmp6dst.sin6_addr, &icmp6dst, NULL)) { 916 /* should be impossible */ 917 nd6log((LOG_DEBUG, 918 "icmp6_notify_error: in6_embedscope failed\n")); 919 goto freeit; 920 } 921 922 /* 923 * retrieve parameters from the inner IPv6 header, and convert 924 * them into sockaddr structures. 925 */ 926 bzero(&icmp6src, sizeof(icmp6src)); 927 icmp6src.sin6_len = sizeof(struct sockaddr_in6); 928 icmp6src.sin6_family = AF_INET6; 929 icmp6src.sin6_addr = eip6->ip6_src; 930 icmp6src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, 931 &icmp6src.sin6_addr); 932 if (in6_embedscope(&icmp6src.sin6_addr, &icmp6src, NULL)) { 933 /* should be impossible */ 934 nd6log((LOG_DEBUG, 935 "icmp6_notify_error: in6_embedscope failed\n")); 936 goto freeit; 937 } 938 icmp6src.sin6_flowinfo = 939 (eip6->ip6_flow & IPV6_FLOWLABEL_MASK); 940 941 if (finaldst == NULL) 942 finaldst = &eip6->ip6_dst; 943 ip6cp.ip6c_m = m; 944 ip6cp.ip6c_icmp6 = icmp6; 945 ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1); 946 ip6cp.ip6c_off = eoff; 947 ip6cp.ip6c_finaldst = finaldst; 948 ip6cp.ip6c_src = &icmp6src; 949 ip6cp.ip6c_nxt = nxt; 950 #if NPF > 0 951 pf_pkt_addr_changed(m); 952 #endif 953 954 if (icmp6type == ICMP6_PACKET_TOO_BIG) { 955 notifymtu = ntohl(icmp6->icmp6_mtu); 956 ip6cp.ip6c_cmdarg = (void *)¬ifymtu; 957 } 958 959 ctlfunc = inet6sw[ip6_protox[nxt]].pr_ctlinput; 960 if (ctlfunc) 961 (*ctlfunc)(code, sin6tosa(&icmp6dst), 962 m->m_pkthdr.ph_rtableid, &ip6cp); 963 } 964 return (0); 965 966 freeit: 967 m_freem(m); 968 return (-1); 969 } 970 971 void 972 icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated) 973 { 974 unsigned long rtcount; 975 struct icmp6_mtudisc_callback *mc; 976 struct in6_addr *dst = ip6cp->ip6c_finaldst; 977 struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6; 978 struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */ 979 u_int mtu = ntohl(icmp6->icmp6_mtu); 980 struct rtentry *rt = NULL; 981 struct sockaddr_in6 sin6; 982 983 if (mtu < IPV6_MMTU) 984 return; 985 986 /* 987 * allow non-validated cases if memory is plenty, to make traffic 988 * from non-connected pcb happy. 989 */ 990 rtcount = rt_timer_queue_count(icmp6_mtudisc_timeout_q); 991 if (validated) { 992 if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat) 993 return; 994 else if (0 <= icmp6_mtudisc_lowat && 995 rtcount > icmp6_mtudisc_lowat) { 996 /* 997 * XXX nuke a victim, install the new one. 998 */ 999 } 1000 } else { 1001 if (0 <= icmp6_mtudisc_lowat && rtcount > icmp6_mtudisc_lowat) 1002 return; 1003 } 1004 1005 bzero(&sin6, sizeof(sin6)); 1006 sin6.sin6_family = PF_INET6; 1007 sin6.sin6_len = sizeof(struct sockaddr_in6); 1008 sin6.sin6_addr = *dst; 1009 /* XXX normally, this won't happen */ 1010 if (IN6_IS_ADDR_LINKLOCAL(dst)) { 1011 sin6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.ph_ifidx); 1012 } 1013 sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, 1014 &sin6.sin6_addr); 1015 1016 rt = icmp6_mtudisc_clone(&sin6, m->m_pkthdr.ph_rtableid, 0); 1017 1018 if (rt != NULL && ISSET(rt->rt_flags, RTF_HOST) && 1019 !(rt->rt_locks & RTV_MTU) && 1020 (rt->rt_mtu > mtu || rt->rt_mtu == 0)) { 1021 struct ifnet *ifp; 1022 1023 ifp = if_get(rt->rt_ifidx); 1024 if (ifp != NULL && mtu < ifp->if_mtu) { 1025 icmp6stat_inc(icp6s_pmtuchg); 1026 rt->rt_mtu = mtu; 1027 } 1028 if_put(ifp); 1029 } 1030 rtfree(rt); 1031 1032 /* 1033 * Notify protocols that the MTU for this destination 1034 * has changed. 1035 */ 1036 LIST_FOREACH(mc, &icmp6_mtudisc_callbacks, mc_list) 1037 (*mc->mc_func)(&sin6, m->m_pkthdr.ph_rtableid); 1038 } 1039 1040 /* 1041 * Reflect the ip6 packet back to the source. 1042 * OFF points to the icmp6 header, counted from the top of the mbuf. 1043 */ 1044 int 1045 icmp6_reflect(struct mbuf **mp, size_t off, struct sockaddr *sa) 1046 { 1047 struct mbuf *m = *mp; 1048 struct rtentry *rt = NULL; 1049 struct ip6_hdr *ip6; 1050 struct icmp6_hdr *icmp6; 1051 struct in6_addr t, *src = NULL; 1052 struct sockaddr_in6 sa6_src, sa6_dst; 1053 u_int rtableid; 1054 u_int8_t pfflags; 1055 1056 CTASSERT(sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) <= MHLEN); 1057 1058 /* too short to reflect */ 1059 if (off < sizeof(struct ip6_hdr)) { 1060 nd6log((LOG_DEBUG, 1061 "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n", 1062 (u_long)off, (u_long)sizeof(struct ip6_hdr), 1063 __FILE__, __LINE__)); 1064 goto bad; 1065 } 1066 1067 if (m->m_pkthdr.ph_loopcnt++ >= M_MAXLOOP) { 1068 m_freemp(mp); 1069 return (ELOOP); 1070 } 1071 rtableid = m->m_pkthdr.ph_rtableid; 1072 pfflags = m->m_pkthdr.pf.flags; 1073 m_resethdr(m); 1074 m->m_pkthdr.ph_rtableid = rtableid; 1075 m->m_pkthdr.pf.flags = pfflags & PF_TAG_GENERATED; 1076 1077 /* 1078 * If there are extra headers between IPv6 and ICMPv6, strip 1079 * off that header first. 1080 */ 1081 if (off > sizeof(struct ip6_hdr)) { 1082 size_t l; 1083 struct ip6_hdr nip6; 1084 1085 l = off - sizeof(struct ip6_hdr); 1086 m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6); 1087 m_adj(m, l); 1088 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1089 if (m->m_len < l) { 1090 if ((m = *mp = m_pullup(m, l)) == NULL) 1091 return (EMSGSIZE); 1092 } 1093 memcpy(mtod(m, caddr_t), &nip6, sizeof(nip6)); 1094 } else /* off == sizeof(struct ip6_hdr) */ { 1095 size_t l; 1096 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1097 if (m->m_len < l) { 1098 if ((m = *mp = m_pullup(m, l)) == NULL) 1099 return (EMSGSIZE); 1100 } 1101 } 1102 ip6 = mtod(m, struct ip6_hdr *); 1103 ip6->ip6_nxt = IPPROTO_ICMPV6; 1104 icmp6 = (struct icmp6_hdr *)(ip6 + 1); 1105 1106 t = ip6->ip6_dst; 1107 /* 1108 * ip6_input() drops a packet if its src is multicast. 1109 * So, the src is never multicast. 1110 */ 1111 ip6->ip6_dst = ip6->ip6_src; 1112 1113 /* 1114 * XXX: make sure to embed scope zone information, using 1115 * already embedded IDs or the received interface (if any). 1116 * Note that rcvif may be NULL. 1117 * TODO: scoped routing case (XXX). 1118 */ 1119 bzero(&sa6_src, sizeof(sa6_src)); 1120 sa6_src.sin6_family = AF_INET6; 1121 sa6_src.sin6_len = sizeof(sa6_src); 1122 sa6_src.sin6_addr = ip6->ip6_dst; 1123 bzero(&sa6_dst, sizeof(sa6_dst)); 1124 sa6_dst.sin6_family = AF_INET6; 1125 sa6_dst.sin6_len = sizeof(sa6_dst); 1126 sa6_dst.sin6_addr = t; 1127 1128 if (sa == NULL) { 1129 /* 1130 * If the incoming packet was addressed directly to us (i.e. 1131 * unicast), use dst as the src for the reply. The 1132 * IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED case would be VERY rare, 1133 * but is possible (for example) when we encounter an error 1134 * while forwarding procedure destined to a duplicated address 1135 * of ours. 1136 */ 1137 rt = rtalloc(sin6tosa(&sa6_dst), 0, rtableid); 1138 if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) && 1139 !ISSET(ifatoia6(rt->rt_ifa)->ia6_flags, 1140 IN6_IFF_ANYCAST|IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)) { 1141 src = &t; 1142 } 1143 rtfree(rt); 1144 rt = NULL; 1145 sa = sin6tosa(&sa6_src); 1146 } 1147 1148 if (src == NULL) { 1149 struct in6_ifaddr *ia6; 1150 1151 /* 1152 * This case matches to multicasts, our anycast, or unicasts 1153 * that we do not own. Select a source address based on the 1154 * source address of the erroneous packet. 1155 */ 1156 rt = rtalloc(sa, RT_RESOLVE, rtableid); 1157 if (!rtisvalid(rt)) { 1158 char addr[INET6_ADDRSTRLEN]; 1159 1160 nd6log((LOG_DEBUG, 1161 "%s: source can't be determined: dst=%s\n", 1162 __func__, inet_ntop(AF_INET6, &sa6_src.sin6_addr, 1163 addr, sizeof(addr)))); 1164 rtfree(rt); 1165 goto bad; 1166 } 1167 ia6 = in6_ifawithscope(rt->rt_ifa->ifa_ifp, &t, rtableid); 1168 if (ia6 != NULL) 1169 src = &ia6->ia_addr.sin6_addr; 1170 if (src == NULL) 1171 src = &ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr; 1172 } 1173 1174 ip6->ip6_src = *src; 1175 rtfree(rt); 1176 1177 ip6->ip6_flow = 0; 1178 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 1179 ip6->ip6_vfc |= IPV6_VERSION; 1180 ip6->ip6_nxt = IPPROTO_ICMPV6; 1181 ip6->ip6_hlim = ip6_defhlim; 1182 1183 icmp6->icmp6_cksum = 0; 1184 m->m_pkthdr.csum_flags = M_ICMP_CSUM_OUT; 1185 1186 /* 1187 * XXX option handling 1188 */ 1189 1190 m->m_flags &= ~(M_BCAST|M_MCAST); 1191 return (0); 1192 1193 bad: 1194 m_freemp(mp); 1195 return (EHOSTUNREACH); 1196 } 1197 1198 void 1199 icmp6_fasttimo(void) 1200 { 1201 1202 mld6_fasttimeo(); 1203 } 1204 1205 const char * 1206 icmp6_redirect_diag(struct in6_addr *src6, struct in6_addr *dst6, 1207 struct in6_addr *tgt6) 1208 { 1209 static char buf[1024]; /* XXX */ 1210 char src[INET6_ADDRSTRLEN]; 1211 char dst[INET6_ADDRSTRLEN]; 1212 char tgt[INET6_ADDRSTRLEN]; 1213 1214 snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)", 1215 inet_ntop(AF_INET6, src6, src, sizeof(src)), 1216 inet_ntop(AF_INET6, dst6, dst, sizeof(dst)), 1217 inet_ntop(AF_INET6, tgt6, tgt, sizeof(tgt))); 1218 return buf; 1219 } 1220 1221 void 1222 icmp6_redirect_input(struct mbuf *m, int off) 1223 { 1224 struct ifnet *ifp; 1225 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1226 struct nd_redirect *nd_rd; 1227 int icmp6len = ntohs(ip6->ip6_plen); 1228 char *lladdr = NULL; 1229 int lladdrlen = 0; 1230 struct rtentry *rt = NULL; 1231 int is_router; 1232 int is_onlink; 1233 struct in6_addr src6 = ip6->ip6_src; 1234 struct in6_addr redtgt6; 1235 struct in6_addr reddst6; 1236 union nd_opts ndopts; 1237 char addr[INET6_ADDRSTRLEN]; 1238 1239 ifp = if_get(m->m_pkthdr.ph_ifidx); 1240 if (ifp == NULL) 1241 return; 1242 1243 /* XXX if we are router, we don't update route by icmp6 redirect */ 1244 if (ip6_forwarding) 1245 goto freeit; 1246 if (!(ifp->if_xflags & IFXF_AUTOCONF6)) 1247 goto freeit; 1248 1249 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len); 1250 if (nd_rd == NULL) { 1251 icmp6stat_inc(icp6s_tooshort); 1252 if_put(ifp); 1253 return; 1254 } 1255 redtgt6 = nd_rd->nd_rd_target; 1256 reddst6 = nd_rd->nd_rd_dst; 1257 1258 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1259 redtgt6.s6_addr16[1] = htons(ifp->if_index); 1260 if (IN6_IS_ADDR_LINKLOCAL(&reddst6)) 1261 reddst6.s6_addr16[1] = htons(ifp->if_index); 1262 1263 /* validation */ 1264 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) { 1265 nd6log((LOG_ERR, 1266 "ICMP6 redirect sent from %s rejected; " 1267 "must be from linklocal\n", 1268 inet_ntop(AF_INET6, &src6, addr, sizeof(addr)))); 1269 goto bad; 1270 } 1271 if (ip6->ip6_hlim != 255) { 1272 nd6log((LOG_ERR, 1273 "ICMP6 redirect sent from %s rejected; " 1274 "hlim=%d (must be 255)\n", 1275 inet_ntop(AF_INET6, &src6, addr, sizeof(addr)), 1276 ip6->ip6_hlim)); 1277 goto bad; 1278 } 1279 if (IN6_IS_ADDR_MULTICAST(&reddst6)) { 1280 nd6log((LOG_ERR, 1281 "ICMP6 redirect rejected; " 1282 "redirect dst must be unicast: %s\n", 1283 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1284 goto bad; 1285 } 1286 { 1287 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */ 1288 struct sockaddr_in6 sin6; 1289 struct in6_addr *gw6; 1290 1291 bzero(&sin6, sizeof(sin6)); 1292 sin6.sin6_family = AF_INET6; 1293 sin6.sin6_len = sizeof(struct sockaddr_in6); 1294 memcpy(&sin6.sin6_addr, &reddst6, sizeof(reddst6)); 1295 rt = rtalloc(sin6tosa(&sin6), 0, m->m_pkthdr.ph_rtableid); 1296 if (rt) { 1297 if (rt->rt_gateway == NULL || 1298 rt->rt_gateway->sa_family != AF_INET6) { 1299 nd6log((LOG_ERR, 1300 "ICMP6 redirect rejected; no route " 1301 "with inet6 gateway found for redirect dst: %s\n", 1302 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1303 rtfree(rt); 1304 goto bad; 1305 } 1306 1307 gw6 = &(satosin6(rt->rt_gateway)->sin6_addr); 1308 if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) { 1309 nd6log((LOG_ERR, 1310 "ICMP6 redirect rejected; " 1311 "not equal to gw-for-src=%s (must be same): " 1312 "%s\n", 1313 inet_ntop(AF_INET6, gw6, addr, sizeof(addr)), 1314 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1315 rtfree(rt); 1316 goto bad; 1317 } 1318 } else { 1319 nd6log((LOG_ERR, 1320 "ICMP6 redirect rejected; " 1321 "no route found for redirect dst: %s\n", 1322 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1323 goto bad; 1324 } 1325 rtfree(rt); 1326 rt = NULL; 1327 } 1328 1329 is_router = is_onlink = 0; 1330 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1331 is_router = 1; /* router case */ 1332 if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) 1333 is_onlink = 1; /* on-link destination case */ 1334 if (!is_router && !is_onlink) { 1335 nd6log((LOG_ERR, 1336 "ICMP6 redirect rejected; " 1337 "neither router case nor onlink case: %s\n", 1338 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1339 goto bad; 1340 } 1341 /* validation passed */ 1342 1343 icmp6len -= sizeof(*nd_rd); 1344 nd6_option_init(nd_rd + 1, icmp6len, &ndopts); 1345 if (nd6_options(&ndopts) < 0) { 1346 nd6log((LOG_INFO, "icmp6_redirect_input: " 1347 "invalid ND option, rejected: %s\n", 1348 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1349 /* nd6_options have incremented stats */ 1350 goto freeit; 1351 } 1352 1353 if (ndopts.nd_opts_tgt_lladdr) { 1354 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); 1355 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; 1356 } 1357 1358 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 1359 nd6log((LOG_INFO, 1360 "icmp6_redirect_input: lladdrlen mismatch for %s " 1361 "(if %d, icmp6 packet %d): %s\n", 1362 inet_ntop(AF_INET6, &redtgt6, addr, sizeof(addr)), 1363 ifp->if_addrlen, lladdrlen - 2, 1364 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1365 goto bad; 1366 } 1367 1368 /* RFC 2461 8.3 */ 1369 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, 1370 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); 1371 1372 if (!is_onlink) { /* better router case. perform rtredirect. */ 1373 /* perform rtredirect */ 1374 struct sockaddr_in6 sdst; 1375 struct sockaddr_in6 sgw; 1376 struct sockaddr_in6 ssrc; 1377 unsigned long rtcount; 1378 struct rtentry *newrt = NULL; 1379 1380 /* 1381 * do not install redirect route, if the number of entries 1382 * is too much (> hiwat). note that, the node (= host) will 1383 * work just fine even if we do not install redirect route 1384 * (there will be additional hops, though). 1385 */ 1386 rtcount = rt_timer_queue_count(icmp6_redirect_timeout_q); 1387 if (0 <= ip6_maxdynroutes && rtcount >= ip6_maxdynroutes) 1388 goto freeit; 1389 else if (0 <= icmp6_redirect_lowat && 1390 rtcount > icmp6_redirect_lowat) { 1391 /* 1392 * XXX nuke a victim, install the new one. 1393 */ 1394 } 1395 1396 bzero(&sdst, sizeof(sdst)); 1397 bzero(&sgw, sizeof(sgw)); 1398 bzero(&ssrc, sizeof(ssrc)); 1399 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6; 1400 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len = 1401 sizeof(struct sockaddr_in6); 1402 memcpy(&sgw.sin6_addr, &redtgt6, sizeof(struct in6_addr)); 1403 memcpy(&sdst.sin6_addr, &reddst6, sizeof(struct in6_addr)); 1404 memcpy(&ssrc.sin6_addr, &src6, sizeof(struct in6_addr)); 1405 rtredirect(sin6tosa(&sdst), sin6tosa(&sgw), sin6tosa(&ssrc), 1406 &newrt, m->m_pkthdr.ph_rtableid); 1407 if (newrt != NULL && icmp6_redirtimeout > 0) { 1408 rt_timer_add(newrt, icmp6_redirect_timeout, 1409 icmp6_redirect_timeout_q, m->m_pkthdr.ph_rtableid); 1410 } 1411 rtfree(newrt); 1412 } 1413 /* finally update cached route in each socket via pfctlinput */ 1414 { 1415 struct sockaddr_in6 sdst; 1416 1417 bzero(&sdst, sizeof(sdst)); 1418 sdst.sin6_family = AF_INET6; 1419 sdst.sin6_len = sizeof(struct sockaddr_in6); 1420 memcpy(&sdst.sin6_addr, &reddst6, sizeof(struct in6_addr)); 1421 pfctlinput(PRC_REDIRECT_HOST, sin6tosa(&sdst)); 1422 } 1423 1424 freeit: 1425 if_put(ifp); 1426 m_freem(m); 1427 return; 1428 1429 bad: 1430 if_put(ifp); 1431 icmp6stat_inc(icp6s_badredirect); 1432 m_freem(m); 1433 } 1434 1435 void 1436 icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt) 1437 { 1438 struct ifnet *ifp = NULL; 1439 struct in6_addr *ifp_ll6; 1440 struct in6_addr *nexthop; 1441 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */ 1442 struct mbuf *m = NULL; /* newly allocated one */ 1443 struct ip6_hdr *ip6; /* m as struct ip6_hdr */ 1444 struct nd_redirect *nd_rd; 1445 size_t maxlen; 1446 u_char *p; 1447 struct sockaddr_in6 src_sa; 1448 1449 icmp6_errcount(ND_REDIRECT, 0); 1450 1451 /* if we are not router, we don't send icmp6 redirect */ 1452 if (!ip6_forwarding) 1453 goto fail; 1454 1455 /* sanity check */ 1456 if (m0 == NULL || !rtisvalid(rt)) 1457 goto fail; 1458 1459 ifp = if_get(rt->rt_ifidx); 1460 if (ifp == NULL) 1461 goto fail; 1462 1463 /* 1464 * Address check: 1465 * the source address must identify a neighbor, and 1466 * the destination address must not be a multicast address 1467 * [RFC 2461, sec 8.2] 1468 */ 1469 sip6 = mtod(m0, struct ip6_hdr *); 1470 bzero(&src_sa, sizeof(src_sa)); 1471 src_sa.sin6_family = AF_INET6; 1472 src_sa.sin6_len = sizeof(src_sa); 1473 src_sa.sin6_addr = sip6->ip6_src; 1474 /* we don't currently use sin6_scope_id, but eventually use it */ 1475 src_sa.sin6_scope_id = in6_addr2scopeid(ifp->if_index, &sip6->ip6_src); 1476 if (nd6_is_addr_neighbor(&src_sa, ifp) == 0) 1477 goto fail; 1478 if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst)) 1479 goto fail; /* what should we do here? */ 1480 1481 /* rate limit */ 1482 if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0)) 1483 goto fail; 1484 1485 /* 1486 * Since we are going to append up to 1280 bytes (= IPV6_MMTU), 1487 * we almost always ask for an mbuf cluster for simplicity. 1488 * (MHLEN < IPV6_MMTU is almost always true) 1489 */ 1490 #if IPV6_MMTU >= MCLBYTES 1491 # error assumption failed about IPV6_MMTU and MCLBYTES 1492 #endif 1493 MGETHDR(m, M_DONTWAIT, MT_HEADER); 1494 if (m && IPV6_MMTU >= MHLEN) 1495 MCLGET(m, M_DONTWAIT); 1496 if (!m) 1497 goto fail; 1498 m->m_pkthdr.ph_ifidx = 0; 1499 m->m_len = 0; 1500 maxlen = m_trailingspace(m); 1501 maxlen = min(IPV6_MMTU, maxlen); 1502 /* just for safety */ 1503 if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 1504 ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) { 1505 goto fail; 1506 } 1507 1508 { 1509 /* get ip6 linklocal address for ifp(my outgoing interface). */ 1510 struct in6_ifaddr *ia6; 1511 if ((ia6 = in6ifa_ifpforlinklocal(ifp, IN6_IFF_TENTATIVE| 1512 IN6_IFF_DUPLICATED|IN6_IFF_ANYCAST)) == NULL) 1513 goto fail; 1514 ifp_ll6 = &ia6->ia_addr.sin6_addr; 1515 } 1516 1517 /* get ip6 linklocal address for the router. */ 1518 if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) { 1519 struct sockaddr_in6 *sin6; 1520 sin6 = satosin6(rt->rt_gateway); 1521 nexthop = &sin6->sin6_addr; 1522 if (!IN6_IS_ADDR_LINKLOCAL(nexthop)) 1523 nexthop = NULL; 1524 } else 1525 nexthop = NULL; 1526 1527 /* ip6 */ 1528 ip6 = mtod(m, struct ip6_hdr *); 1529 ip6->ip6_flow = 0; 1530 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 1531 ip6->ip6_vfc |= IPV6_VERSION; 1532 /* ip6->ip6_plen will be set later */ 1533 ip6->ip6_nxt = IPPROTO_ICMPV6; 1534 ip6->ip6_hlim = 255; 1535 /* ip6->ip6_src must be linklocal addr for my outgoing if. */ 1536 bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr)); 1537 bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr)); 1538 1539 /* ND Redirect */ 1540 nd_rd = (struct nd_redirect *)(ip6 + 1); 1541 nd_rd->nd_rd_type = ND_REDIRECT; 1542 nd_rd->nd_rd_code = 0; 1543 nd_rd->nd_rd_reserved = 0; 1544 if (rt->rt_flags & RTF_GATEWAY) { 1545 /* 1546 * nd_rd->nd_rd_target must be a link-local address in 1547 * better router cases. 1548 */ 1549 if (!nexthop) 1550 goto fail; 1551 bcopy(nexthop, &nd_rd->nd_rd_target, 1552 sizeof(nd_rd->nd_rd_target)); 1553 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 1554 sizeof(nd_rd->nd_rd_dst)); 1555 } else { 1556 /* make sure redtgt == reddst */ 1557 nexthop = &sip6->ip6_dst; 1558 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target, 1559 sizeof(nd_rd->nd_rd_target)); 1560 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 1561 sizeof(nd_rd->nd_rd_dst)); 1562 } 1563 1564 p = (u_char *)(nd_rd + 1); 1565 1566 { 1567 /* target lladdr option */ 1568 struct rtentry *nrt; 1569 int len; 1570 struct sockaddr_dl *sdl; 1571 struct nd_opt_hdr *nd_opt; 1572 char *lladdr; 1573 1574 len = sizeof(*nd_opt) + ifp->if_addrlen; 1575 len = (len + 7) & ~7; /* round by 8 */ 1576 /* safety check */ 1577 if (len + (p - (u_char *)ip6) > maxlen) 1578 goto nolladdropt; 1579 nrt = nd6_lookup(nexthop, 0, ifp, ifp->if_rdomain); 1580 if ((nrt != NULL) && 1581 (nrt->rt_flags & (RTF_GATEWAY|RTF_LLINFO)) == RTF_LLINFO && 1582 (nrt->rt_gateway->sa_family == AF_LINK) && 1583 (sdl = satosdl(nrt->rt_gateway)) && 1584 sdl->sdl_alen) { 1585 nd_opt = (struct nd_opt_hdr *)p; 1586 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; 1587 nd_opt->nd_opt_len = len >> 3; 1588 lladdr = (char *)(nd_opt + 1); 1589 bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen); 1590 p += len; 1591 } 1592 rtfree(nrt); 1593 } 1594 nolladdropt:; 1595 1596 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 1597 1598 /* just to be safe */ 1599 if (p - (u_char *)ip6 > maxlen) 1600 goto noredhdropt; 1601 1602 { 1603 /* redirected header option */ 1604 int len; 1605 struct nd_opt_rd_hdr *nd_opt_rh; 1606 1607 /* 1608 * compute the maximum size for icmp6 redirect header option. 1609 * XXX room for auth header? 1610 */ 1611 len = maxlen - (p - (u_char *)ip6); 1612 len &= ~7; 1613 1614 /* 1615 * Redirected header option spec (RFC2461 4.6.3) talks nothing 1616 * about padding/truncate rule for the original IP packet. 1617 * From the discussion on IPv6imp in Feb 1999, 1618 * the consensus was: 1619 * - "attach as much as possible" is the goal 1620 * - pad if not aligned (original size can be guessed by 1621 * original ip6 header) 1622 * Following code adds the padding if it is simple enough, 1623 * and truncates if not. 1624 */ 1625 if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) { 1626 /* not enough room, truncate */ 1627 m_adj(m0, (len - sizeof(*nd_opt_rh)) - 1628 m0->m_pkthdr.len); 1629 } else { 1630 /* 1631 * enough room, truncate if not aligned. 1632 * we don't pad here for simplicity. 1633 */ 1634 size_t extra; 1635 1636 extra = m0->m_pkthdr.len % 8; 1637 if (extra) { 1638 /* truncate */ 1639 m_adj(m0, -extra); 1640 } 1641 len = m0->m_pkthdr.len + sizeof(*nd_opt_rh); 1642 } 1643 1644 nd_opt_rh = (struct nd_opt_rd_hdr *)p; 1645 bzero(nd_opt_rh, sizeof(*nd_opt_rh)); 1646 nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER; 1647 nd_opt_rh->nd_opt_rh_len = len >> 3; 1648 p += sizeof(*nd_opt_rh); 1649 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 1650 1651 /* connect m0 to m */ 1652 m->m_pkthdr.len += m0->m_pkthdr.len; 1653 m_cat(m, m0); 1654 m0 = NULL; 1655 } 1656 noredhdropt: 1657 m_freem(m0); 1658 m0 = NULL; 1659 1660 sip6 = mtod(m, struct ip6_hdr *); 1661 if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src)) 1662 sip6->ip6_src.s6_addr16[1] = 0; 1663 if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst)) 1664 sip6->ip6_dst.s6_addr16[1] = 0; 1665 #if 0 1666 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) 1667 ip6->ip6_src.s6_addr16[1] = 0; 1668 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) 1669 ip6->ip6_dst.s6_addr16[1] = 0; 1670 #endif 1671 if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target)) 1672 nd_rd->nd_rd_target.s6_addr16[1] = 0; 1673 if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst)) 1674 nd_rd->nd_rd_dst.s6_addr16[1] = 0; 1675 1676 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 1677 1678 nd_rd->nd_rd_cksum = 0; 1679 m->m_pkthdr.csum_flags = M_ICMP_CSUM_OUT; 1680 1681 /* send the packet to outside... */ 1682 ip6_output(m, NULL, NULL, 0, NULL, NULL); 1683 1684 icmp6stat_inc(icp6s_outhist + ND_REDIRECT); 1685 1686 if_put(ifp); 1687 return; 1688 1689 fail: 1690 if_put(ifp); 1691 m_freem(m); 1692 m_freem(m0); 1693 } 1694 1695 /* 1696 * ICMPv6 socket option processing. 1697 */ 1698 int 1699 icmp6_ctloutput(int op, struct socket *so, int level, int optname, 1700 struct mbuf *m) 1701 { 1702 int error = 0; 1703 struct inpcb *in6p = sotoinpcb(so); 1704 1705 if (level != IPPROTO_ICMPV6) 1706 return EINVAL; 1707 1708 switch (op) { 1709 case PRCO_SETOPT: 1710 switch (optname) { 1711 case ICMP6_FILTER: 1712 { 1713 struct icmp6_filter *p; 1714 1715 if (m == NULL || m->m_len != sizeof(*p)) { 1716 error = EMSGSIZE; 1717 break; 1718 } 1719 p = mtod(m, struct icmp6_filter *); 1720 if (!p || !in6p->inp_icmp6filt) { 1721 error = EINVAL; 1722 break; 1723 } 1724 bcopy(p, in6p->inp_icmp6filt, 1725 sizeof(struct icmp6_filter)); 1726 error = 0; 1727 break; 1728 } 1729 1730 default: 1731 error = ENOPROTOOPT; 1732 break; 1733 } 1734 break; 1735 1736 case PRCO_GETOPT: 1737 switch (optname) { 1738 case ICMP6_FILTER: 1739 { 1740 struct icmp6_filter *p; 1741 1742 if (!in6p->inp_icmp6filt) { 1743 error = EINVAL; 1744 break; 1745 } 1746 m->m_len = sizeof(struct icmp6_filter); 1747 p = mtod(m, struct icmp6_filter *); 1748 bcopy(in6p->inp_icmp6filt, p, 1749 sizeof(struct icmp6_filter)); 1750 error = 0; 1751 break; 1752 } 1753 1754 default: 1755 error = ENOPROTOOPT; 1756 break; 1757 } 1758 break; 1759 } 1760 1761 return (error); 1762 } 1763 1764 /* 1765 * Perform rate limit check. 1766 * Returns 0 if it is okay to send the icmp6 packet. 1767 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate 1768 * limitation. 1769 * 1770 * XXX per-destination/type check necessary? 1771 * 1772 * dst - not used at this moment 1773 * type - not used at this moment 1774 * code - not used at this moment 1775 */ 1776 int 1777 icmp6_ratelimit(const struct in6_addr *dst, const int type, const int code) 1778 { 1779 /* PPS limit */ 1780 if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count, 1781 icmp6errppslim)) 1782 return 1; /* The packet is subject to rate limit */ 1783 return 0; /* okay to send */ 1784 } 1785 1786 struct rtentry * 1787 icmp6_mtudisc_clone(struct sockaddr_in6 *dst, u_int rtableid, int ipsec) 1788 { 1789 struct rtentry *rt; 1790 int error; 1791 1792 rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid); 1793 1794 /* Check if the route is actually usable */ 1795 if (!rtisvalid(rt)) 1796 goto bad; 1797 /* IPsec needs the route only for PMTU, it can use reject for that */ 1798 if (!ipsec && (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE))) 1799 goto bad; 1800 1801 /* 1802 * No PMTU for local routes and permanent neighbors, 1803 * ARP and NDP use the same expire timer as the route. 1804 */ 1805 if (ISSET(rt->rt_flags, RTF_LOCAL) || 1806 (ISSET(rt->rt_flags, RTF_LLINFO) && rt->rt_expire == 0)) 1807 goto bad; 1808 1809 /* If we didn't get a host route, allocate one */ 1810 if ((rt->rt_flags & RTF_HOST) == 0) { 1811 struct rtentry *nrt; 1812 struct rt_addrinfo info; 1813 struct sockaddr_rtlabel sa_rl; 1814 1815 memset(&info, 0, sizeof(info)); 1816 info.rti_ifa = rt->rt_ifa; 1817 info.rti_flags = RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC; 1818 info.rti_info[RTAX_DST] = sin6tosa(dst); 1819 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1820 info.rti_info[RTAX_LABEL] = 1821 rtlabel_id2sa(rt->rt_labelid, &sa_rl); 1822 1823 error = rtrequest(RTM_ADD, &info, rt->rt_priority, &nrt, 1824 rtableid); 1825 if (error) 1826 goto bad; 1827 nrt->rt_rmx = rt->rt_rmx; 1828 rtfree(rt); 1829 rt = nrt; 1830 rtm_send(rt, RTM_ADD, 0, rtableid); 1831 } 1832 error = rt_timer_add(rt, icmp6_mtudisc_timeout, icmp6_mtudisc_timeout_q, 1833 rtableid); 1834 if (error) 1835 goto bad; 1836 1837 return (rt); 1838 bad: 1839 rtfree(rt); 1840 return (NULL); 1841 } 1842 1843 void 1844 icmp6_mtudisc_timeout(struct rtentry *rt, struct rttimer *r) 1845 { 1846 struct ifnet *ifp; 1847 1848 NET_ASSERT_LOCKED(); 1849 1850 ifp = if_get(rt->rt_ifidx); 1851 if (ifp == NULL) 1852 return; 1853 1854 if ((rt->rt_flags & (RTF_DYNAMIC|RTF_HOST)) == (RTF_DYNAMIC|RTF_HOST)) { 1855 rtdeletemsg(rt, ifp, r->rtt_tableid); 1856 } else { 1857 if (!(rt->rt_locks & RTV_MTU)) 1858 rt->rt_mtu = 0; 1859 } 1860 1861 if_put(ifp); 1862 } 1863 1864 void 1865 icmp6_redirect_timeout(struct rtentry *rt, struct rttimer *r) 1866 { 1867 struct ifnet *ifp; 1868 1869 NET_ASSERT_LOCKED(); 1870 1871 ifp = if_get(rt->rt_ifidx); 1872 if (ifp == NULL) 1873 return; 1874 1875 if ((rt->rt_flags & (RTF_DYNAMIC|RTF_HOST)) == (RTF_DYNAMIC|RTF_HOST)) { 1876 rtdeletemsg(rt, ifp, r->rtt_tableid); 1877 } 1878 1879 if_put(ifp); 1880 } 1881 1882 const struct sysctl_bounded_args icmpv6ctl_vars[] = { 1883 { ICMPV6CTL_ND6_DELAY, &nd6_delay, 0, INT_MAX }, 1884 { ICMPV6CTL_ND6_UMAXTRIES, &nd6_umaxtries, 0, INT_MAX }, 1885 { ICMPV6CTL_ND6_MMAXTRIES, &nd6_mmaxtries, 0, INT_MAX }, 1886 { ICMPV6CTL_ERRPPSLIMIT, &icmp6errppslim, -1, 1000 }, 1887 { ICMPV6CTL_ND6_MAXNUDHINT, &nd6_maxnudhint, 0, INT_MAX }, 1888 { ICMPV6CTL_MTUDISC_HIWAT, &icmp6_mtudisc_hiwat, -1, INT_MAX }, 1889 { ICMPV6CTL_MTUDISC_LOWAT, &icmp6_mtudisc_lowat, -1, INT_MAX }, 1890 { ICMPV6CTL_ND6_DEBUG, &nd6_debug, 0, 1 }, 1891 }; 1892 1893 int 1894 icmp6_sysctl_icmp6stat(void *oldp, size_t *oldlenp, void *newp) 1895 { 1896 struct icmp6stat *icmp6stat; 1897 int ret; 1898 1899 CTASSERT(sizeof(*icmp6stat) == icp6s_ncounters * sizeof(uint64_t)); 1900 icmp6stat = malloc(sizeof(*icmp6stat), M_TEMP, M_WAITOK|M_ZERO); 1901 counters_read(icmp6counters, (uint64_t *)icmp6stat, icp6s_ncounters); 1902 ret = sysctl_rdstruct(oldp, oldlenp, newp, 1903 icmp6stat, sizeof(*icmp6stat)); 1904 free(icmp6stat, M_TEMP, sizeof(*icmp6stat)); 1905 1906 return (ret); 1907 } 1908 1909 int 1910 icmp6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1911 void *newp, size_t newlen) 1912 { 1913 int error; 1914 1915 /* All sysctl names at this level are terminal. */ 1916 if (namelen != 1) 1917 return (ENOTDIR); 1918 1919 switch (name[0]) { 1920 case ICMPV6CTL_REDIRTIMEOUT: 1921 NET_LOCK(); 1922 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, 1923 &icmp6_redirtimeout, 0, INT_MAX); 1924 rt_timer_queue_change(icmp6_redirect_timeout_q, 1925 icmp6_redirtimeout); 1926 NET_UNLOCK(); 1927 break; 1928 1929 case ICMPV6CTL_STATS: 1930 error = icmp6_sysctl_icmp6stat(oldp, oldlenp, newp); 1931 break; 1932 1933 default: 1934 NET_LOCK(); 1935 error = sysctl_bounded_arr(icmpv6ctl_vars, 1936 nitems(icmpv6ctl_vars), name, namelen, oldp, oldlenp, newp, 1937 newlen); 1938 NET_UNLOCK(); 1939 break; 1940 } 1941 1942 return (error); 1943 } 1944