1 /* $OpenBSD: icmp6.c,v 1.233 2020/10/28 17:27:35 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 #include <sys/domain.h> 79 80 #include <net/if.h> 81 #include <net/if_var.h> 82 #include <net/route.h> 83 #include <net/if_dl.h> 84 #include <net/if_types.h> 85 86 #include <netinet/in.h> 87 #include <netinet/ip.h> 88 #include <netinet6/in6_var.h> 89 #include <netinet/ip6.h> 90 #include <netinet6/ip6_var.h> 91 #include <netinet/icmp6.h> 92 #include <netinet6/mld6_var.h> 93 #include <netinet/in_pcb.h> 94 #include <netinet6/nd6.h> 95 #include <netinet6/ip6protosw.h> 96 97 #if NCARP > 0 98 #include <netinet/ip_carp.h> 99 #endif 100 101 #if NPF > 0 102 #include <net/pfvar.h> 103 #endif 104 105 struct cpumem *icmp6counters; 106 107 extern int icmp6errppslim; 108 static int icmp6errpps_count = 0; 109 static struct timeval icmp6errppslim_last; 110 111 /* 112 * List of callbacks to notify when Path MTU changes are made. 113 */ 114 struct icmp6_mtudisc_callback { 115 LIST_ENTRY(icmp6_mtudisc_callback) mc_list; 116 void (*mc_func)(struct sockaddr_in6 *, u_int); 117 }; 118 119 LIST_HEAD(, icmp6_mtudisc_callback) icmp6_mtudisc_callbacks = 120 LIST_HEAD_INITIALIZER(icmp6_mtudisc_callbacks); 121 122 struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL; 123 124 /* XXX do these values make any sense? */ 125 static int icmp6_mtudisc_hiwat = 1280; 126 static int icmp6_mtudisc_lowat = 256; 127 128 /* 129 * keep track of # of redirect routes. 130 */ 131 static struct rttimer_queue *icmp6_redirect_timeout_q = NULL; 132 133 /* XXX experimental, turned off */ 134 static int icmp6_redirect_lowat = -1; 135 136 void icmp6_errcount(int, int); 137 int icmp6_ratelimit(const struct in6_addr *, const int, const int); 138 const char *icmp6_redirect_diag(struct in6_addr *, struct in6_addr *, 139 struct in6_addr *); 140 int icmp6_notify_error(struct mbuf *, int, int, int); 141 struct rtentry *icmp6_mtudisc_clone(struct sockaddr *, u_int); 142 void icmp6_mtudisc_timeout(struct rtentry *, struct rttimer *); 143 void icmp6_redirect_timeout(struct rtentry *, struct rttimer *); 144 145 void 146 icmp6_init(void) 147 { 148 mld6_init(); 149 icmp6_mtudisc_timeout_q = rt_timer_queue_create(ip6_mtudisc_timeout); 150 icmp6_redirect_timeout_q = rt_timer_queue_create(icmp6_redirtimeout); 151 icmp6counters = counters_alloc(icp6s_ncounters); 152 } 153 154 void 155 icmp6_errcount(int type, int code) 156 { 157 enum icmp6stat_counters c = icp6s_ounknown; 158 159 switch (type) { 160 case ICMP6_DST_UNREACH: 161 switch (code) { 162 case ICMP6_DST_UNREACH_NOROUTE: 163 c = icp6s_odst_unreach_noroute; 164 break; 165 case ICMP6_DST_UNREACH_ADMIN: 166 c = icp6s_odst_unreach_admin; 167 break; 168 case ICMP6_DST_UNREACH_BEYONDSCOPE: 169 c = icp6s_odst_unreach_beyondscope; 170 break; 171 case ICMP6_DST_UNREACH_ADDR: 172 c = icp6s_odst_unreach_addr; 173 break; 174 case ICMP6_DST_UNREACH_NOPORT: 175 c = icp6s_odst_unreach_noport; 176 break; 177 } 178 break; 179 case ICMP6_PACKET_TOO_BIG: 180 c = icp6s_opacket_too_big; 181 break; 182 case ICMP6_TIME_EXCEEDED: 183 switch (code) { 184 case ICMP6_TIME_EXCEED_TRANSIT: 185 c = icp6s_otime_exceed_transit; 186 break; 187 case ICMP6_TIME_EXCEED_REASSEMBLY: 188 c = icp6s_otime_exceed_reassembly; 189 break; 190 } 191 break; 192 case ICMP6_PARAM_PROB: 193 switch (code) { 194 case ICMP6_PARAMPROB_HEADER: 195 c = icp6s_oparamprob_header; 196 break; 197 case ICMP6_PARAMPROB_NEXTHEADER: 198 c = icp6s_oparamprob_nextheader; 199 break; 200 case ICMP6_PARAMPROB_OPTION: 201 c = icp6s_oparamprob_option; 202 break; 203 } 204 break; 205 case ND_REDIRECT: 206 c = icp6s_oredirect; 207 break; 208 } 209 210 icmp6stat_inc(c); 211 } 212 213 /* 214 * Register a Path MTU Discovery callback. 215 */ 216 void 217 icmp6_mtudisc_callback_register(void (*func)(struct sockaddr_in6 *, u_int)) 218 { 219 struct icmp6_mtudisc_callback *mc; 220 221 LIST_FOREACH(mc, &icmp6_mtudisc_callbacks, mc_list) { 222 if (mc->mc_func == func) 223 return; 224 } 225 226 mc = malloc(sizeof(*mc), M_PCB, M_NOWAIT); 227 if (mc == NULL) 228 panic("%s", __func__); 229 230 mc->mc_func = func; 231 LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks, mc, mc_list); 232 } 233 234 struct mbuf * 235 icmp6_do_error(struct mbuf *m, int type, int code, int param) 236 { 237 struct ip6_hdr *oip6, *nip6; 238 struct icmp6_hdr *icmp6; 239 u_int preplen; 240 int off; 241 int nxt; 242 243 icmp6stat_inc(icp6s_error); 244 245 /* count per-type-code statistics */ 246 icmp6_errcount(type, code); 247 248 if (m->m_len < sizeof(struct ip6_hdr)) { 249 m = m_pullup(m, sizeof(struct ip6_hdr)); 250 if (m == NULL) 251 return (NULL); 252 } 253 oip6 = mtod(m, struct ip6_hdr *); 254 255 /* 256 * If the destination address of the erroneous packet is a multicast 257 * address, or the packet was sent using link-layer multicast, 258 * we should basically suppress sending an error (RFC 2463, Section 259 * 2.4). 260 * We have two exceptions (the item e.2 in that section): 261 * - the Packet Too Big message can be sent for path MTU discovery. 262 * - the Parameter Problem Message that can be allowed an icmp6 error 263 * in the option type field. This check has been done in 264 * ip6_unknown_opt(), so we can just check the type and code. 265 */ 266 if ((m->m_flags & (M_BCAST|M_MCAST) || 267 IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) && 268 (type != ICMP6_PACKET_TOO_BIG && 269 (type != ICMP6_PARAM_PROB || 270 code != ICMP6_PARAMPROB_OPTION))) 271 goto freeit; 272 273 /* 274 * RFC 2463, 2.4 (e.5): source address check. 275 * XXX: the case of anycast source? 276 */ 277 if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) || 278 IN6_IS_ADDR_MULTICAST(&oip6->ip6_src)) 279 goto freeit; 280 281 /* 282 * If we are about to send ICMPv6 against ICMPv6 error/redirect, 283 * don't do it. 284 */ 285 nxt = -1; 286 off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt); 287 if (off >= 0 && nxt == IPPROTO_ICMPV6) { 288 struct icmp6_hdr *icp; 289 290 IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off, 291 sizeof(*icp)); 292 if (icp == NULL) { 293 icmp6stat_inc(icp6s_tooshort); 294 return (NULL); 295 } 296 if (icp->icmp6_type < ICMP6_ECHO_REQUEST || 297 icp->icmp6_type == ND_REDIRECT) { 298 /* 299 * ICMPv6 error 300 * Special case: for redirect (which is 301 * informational) we must not send icmp6 error. 302 */ 303 icmp6stat_inc(icp6s_canterror); 304 goto freeit; 305 } else { 306 /* ICMPv6 informational - send the error */ 307 } 308 } 309 else { 310 /* non-ICMPv6 - send the error */ 311 } 312 313 oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */ 314 315 /* Finally, do rate limitation check. */ 316 if (icmp6_ratelimit(&oip6->ip6_src, type, code)) { 317 icmp6stat_inc(icp6s_toofreq); 318 goto freeit; 319 } 320 321 /* 322 * OK, ICMP6 can be generated. 323 */ 324 325 if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN) 326 m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len); 327 328 preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 329 M_PREPEND(m, preplen, M_DONTWAIT); 330 if (m && m->m_len < preplen) 331 m = m_pullup(m, preplen); 332 if (m == NULL) { 333 nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__)); 334 return (NULL); 335 } 336 337 nip6 = mtod(m, struct ip6_hdr *); 338 nip6->ip6_src = oip6->ip6_src; 339 nip6->ip6_dst = oip6->ip6_dst; 340 341 if (IN6_IS_SCOPE_EMBED(&oip6->ip6_src)) 342 oip6->ip6_src.s6_addr16[1] = 0; 343 if (IN6_IS_SCOPE_EMBED(&oip6->ip6_dst)) 344 oip6->ip6_dst.s6_addr16[1] = 0; 345 346 icmp6 = (struct icmp6_hdr *)(nip6 + 1); 347 icmp6->icmp6_type = type; 348 icmp6->icmp6_code = code; 349 icmp6->icmp6_pptr = htonl((u_int32_t)param); 350 351 /* 352 * icmp6_reflect() is designed to be in the input path. 353 * icmp6_error() can be called from both input and outut path, 354 * and if we are in output path rcvif could contain bogus value. 355 * clear m->m_pkthdr.ph_ifidx for safety, we should have enough 356 * scope information in ip header (nip6). 357 */ 358 m->m_pkthdr.ph_ifidx = 0; 359 360 icmp6stat_inc(icp6s_outhist + type); 361 362 return (m); 363 364 freeit: 365 /* 366 * If we can't tell wheter or not we can generate ICMP6, free it. 367 */ 368 return (m_freem(m)); 369 } 370 371 /* 372 * Generate an error packet of type error in response to bad IP6 packet. 373 */ 374 void 375 icmp6_error(struct mbuf *m, int type, int code, int param) 376 { 377 struct mbuf *n; 378 379 n = icmp6_do_error(m, type, code, param); 380 if (n != NULL) { 381 /* header order: IPv6 - ICMPv6 */ 382 if (!icmp6_reflect(&n, sizeof(struct ip6_hdr), NULL)) 383 ip6_send(n); 384 } 385 } 386 387 /* 388 * Process a received ICMP6 message. 389 */ 390 int 391 icmp6_input(struct mbuf **mp, int *offp, int proto, int af) 392 { 393 #if NCARP > 0 394 struct ifnet *ifp; 395 #endif 396 struct mbuf *m = *mp, *n; 397 struct ip6_hdr *ip6, *nip6; 398 struct icmp6_hdr *icmp6, *nicmp6; 399 int off = *offp; 400 int icmp6len = m->m_pkthdr.len - *offp; 401 int code, sum, noff; 402 char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN]; 403 404 /* 405 * Locate icmp6 structure in mbuf, and check 406 * that not corrupted and of at least minimum length 407 */ 408 409 ip6 = mtod(m, struct ip6_hdr *); 410 if (icmp6len < sizeof(struct icmp6_hdr)) { 411 icmp6stat_inc(icp6s_tooshort); 412 goto freeit; 413 } 414 415 /* 416 * calculate the checksum 417 */ 418 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6)); 419 if (icmp6 == NULL) { 420 icmp6stat_inc(icp6s_tooshort); 421 return IPPROTO_DONE; 422 } 423 code = icmp6->icmp6_code; 424 425 if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) { 426 nd6log((LOG_ERR, 427 "ICMP6 checksum error(%d|%x) %s\n", 428 icmp6->icmp6_type, sum, 429 inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)))); 430 icmp6stat_inc(icp6s_checksum); 431 goto freeit; 432 } 433 434 #if NPF > 0 435 if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { 436 switch (icmp6->icmp6_type) { 437 /* 438 * These ICMP6 types map to other connections. They must be 439 * delivered to pr_ctlinput() also for diverted connections. 440 */ 441 case ICMP6_DST_UNREACH: 442 case ICMP6_PACKET_TOO_BIG: 443 case ICMP6_TIME_EXCEEDED: 444 case ICMP6_PARAM_PROB: 445 /* 446 * Do not use the divert-to property of the TCP or UDP 447 * rule when doing the PCB lookup for the raw socket. 448 */ 449 m->m_pkthdr.pf.flags &=~ PF_TAG_DIVERTED; 450 break; 451 default: 452 goto raw; 453 } 454 } 455 #endif /* NPF */ 456 457 #if NCARP > 0 458 ifp = if_get(m->m_pkthdr.ph_ifidx); 459 if (ifp == NULL) 460 goto freeit; 461 462 if (icmp6->icmp6_type == ICMP6_ECHO_REQUEST && 463 carp_lsdrop(ifp, m, AF_INET6, ip6->ip6_src.s6_addr32, 464 ip6->ip6_dst.s6_addr32, 1)) { 465 if_put(ifp); 466 goto freeit; 467 } 468 469 if_put(ifp); 470 #endif 471 icmp6stat_inc(icp6s_inhist + icmp6->icmp6_type); 472 473 switch (icmp6->icmp6_type) { 474 case ICMP6_DST_UNREACH: 475 switch (code) { 476 case ICMP6_DST_UNREACH_NOROUTE: 477 code = PRC_UNREACH_NET; 478 break; 479 case ICMP6_DST_UNREACH_ADMIN: 480 code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ 481 break; 482 case ICMP6_DST_UNREACH_ADDR: 483 code = PRC_HOSTDEAD; 484 break; 485 case ICMP6_DST_UNREACH_BEYONDSCOPE: 486 /* I mean "source address was incorrect." */ 487 code = PRC_PARAMPROB; 488 break; 489 case ICMP6_DST_UNREACH_NOPORT: 490 code = PRC_UNREACH_PORT; 491 break; 492 default: 493 goto badcode; 494 } 495 goto deliver; 496 497 case ICMP6_PACKET_TOO_BIG: 498 /* MTU is checked in icmp6_mtudisc_update. */ 499 code = PRC_MSGSIZE; 500 501 /* 502 * Updating the path MTU will be done after examining 503 * intermediate extension headers. 504 */ 505 goto deliver; 506 507 case ICMP6_TIME_EXCEEDED: 508 switch (code) { 509 case ICMP6_TIME_EXCEED_TRANSIT: 510 code = PRC_TIMXCEED_INTRANS; 511 break; 512 case ICMP6_TIME_EXCEED_REASSEMBLY: 513 code = PRC_TIMXCEED_REASS; 514 break; 515 default: 516 goto badcode; 517 } 518 goto deliver; 519 520 case ICMP6_PARAM_PROB: 521 switch (code) { 522 case ICMP6_PARAMPROB_NEXTHEADER: 523 code = PRC_UNREACH_PROTOCOL; 524 break; 525 case ICMP6_PARAMPROB_HEADER: 526 case ICMP6_PARAMPROB_OPTION: 527 code = PRC_PARAMPROB; 528 break; 529 default: 530 goto badcode; 531 } 532 goto deliver; 533 534 case ICMP6_ECHO_REQUEST: 535 if (code != 0) 536 goto badcode; 537 /* 538 * Copy mbuf to send to two data paths: userland socket(s), 539 * and to the querier (echo reply). 540 * m: a copy for socket, n: a copy for querier 541 */ 542 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 543 /* Give up local */ 544 n = m; 545 m = *mp = NULL; 546 goto deliverecho; 547 } 548 /* 549 * If the first mbuf is shared, or the first mbuf is too short, 550 * copy the first part of the data into a fresh mbuf. 551 * Otherwise, we will wrongly overwrite both copies. 552 */ 553 if ((n->m_flags & M_EXT) != 0 || 554 n->m_len < off + sizeof(struct icmp6_hdr)) { 555 struct mbuf *n0 = n; 556 const int maxlen = sizeof(*nip6) + sizeof(*nicmp6); 557 558 /* 559 * Prepare an internal mbuf. m_pullup() doesn't 560 * always copy the length we specified. 561 */ 562 if (maxlen >= MCLBYTES) { 563 /* Give up remote */ 564 m_freem(n0); 565 break; 566 } 567 MGETHDR(n, M_DONTWAIT, n0->m_type); 568 if (n && maxlen >= MHLEN) { 569 MCLGET(n, M_DONTWAIT); 570 if ((n->m_flags & M_EXT) == 0) { 571 m_free(n); 572 n = NULL; 573 } 574 } 575 if (n == NULL) { 576 /* Give up local */ 577 m_freem(n0); 578 n = m; 579 m = *mp = NULL; 580 goto deliverecho; 581 } 582 M_MOVE_PKTHDR(n, n0); 583 /* 584 * Copy IPv6 and ICMPv6 only. 585 */ 586 nip6 = mtod(n, struct ip6_hdr *); 587 bcopy(ip6, nip6, sizeof(struct ip6_hdr)); 588 nicmp6 = (struct icmp6_hdr *)(nip6 + 1); 589 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); 590 noff = sizeof(struct ip6_hdr); 591 n->m_len = noff + sizeof(struct icmp6_hdr); 592 /* 593 * Adjust mbuf. ip6_plen will be adjusted in 594 * ip6_output(). 595 * n->m_pkthdr.len == n0->m_pkthdr.len at this point. 596 */ 597 n->m_pkthdr.len += noff + sizeof(struct icmp6_hdr); 598 n->m_pkthdr.len -= (off + sizeof(struct icmp6_hdr)); 599 m_adj(n0, off + sizeof(struct icmp6_hdr)); 600 n->m_next = n0; 601 } else { 602 deliverecho: 603 IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off, 604 sizeof(*nicmp6)); 605 noff = off; 606 } 607 if (n) { 608 nicmp6->icmp6_type = ICMP6_ECHO_REPLY; 609 nicmp6->icmp6_code = 0; 610 icmp6stat_inc(icp6s_reflect); 611 icmp6stat_inc(icp6s_outhist + ICMP6_ECHO_REPLY); 612 if (!icmp6_reflect(&n, noff, NULL)) 613 ip6_send(n); 614 } 615 if (!m) 616 goto freeit; 617 break; 618 619 case ICMP6_ECHO_REPLY: 620 if (code != 0) 621 goto badcode; 622 break; 623 624 case MLD_LISTENER_QUERY: 625 case MLD_LISTENER_REPORT: 626 if (icmp6len < sizeof(struct mld_hdr)) 627 goto badlen; 628 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 629 /* give up local */ 630 mld6_input(m, off); 631 m = NULL; 632 goto freeit; 633 } 634 mld6_input(n, off); 635 /* m stays. */ 636 break; 637 638 case MLD_LISTENER_DONE: 639 if (icmp6len < sizeof(struct mld_hdr)) /* necessary? */ 640 goto badlen; 641 break; /* nothing to be done in kernel */ 642 643 case MLD_MTRACE_RESP: 644 case MLD_MTRACE: 645 /* XXX: these two are experimental. not officially defined. */ 646 /* XXX: per-interface statistics? */ 647 break; /* just pass it to applications */ 648 649 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */ 650 /* IPv6 Node Information Queries are not supported */ 651 break; 652 case ICMP6_WRUREPLY: 653 break; 654 655 case ND_ROUTER_SOLICIT: 656 case ND_ROUTER_ADVERT: 657 if (code != 0) 658 goto badcode; 659 if ((icmp6->icmp6_type == ND_ROUTER_SOLICIT && icmp6len < 660 sizeof(struct nd_router_solicit)) || 661 (icmp6->icmp6_type == ND_ROUTER_ADVERT && icmp6len < 662 sizeof(struct nd_router_advert))) 663 goto badlen; 664 665 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 666 /* give up local */ 667 nd6_rtr_cache(m, off, icmp6len, 668 icmp6->icmp6_type); 669 m = NULL; 670 goto freeit; 671 } 672 nd6_rtr_cache(n, off, icmp6len, icmp6->icmp6_type); 673 /* m stays. */ 674 break; 675 676 case ND_NEIGHBOR_SOLICIT: 677 if (code != 0) 678 goto badcode; 679 if (icmp6len < sizeof(struct nd_neighbor_solicit)) 680 goto badlen; 681 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 682 /* give up local */ 683 nd6_ns_input(m, off, icmp6len); 684 m = NULL; 685 goto freeit; 686 } 687 nd6_ns_input(n, off, icmp6len); 688 /* m stays. */ 689 break; 690 691 case ND_NEIGHBOR_ADVERT: 692 if (code != 0) 693 goto badcode; 694 if (icmp6len < sizeof(struct nd_neighbor_advert)) 695 goto badlen; 696 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 697 /* give up local */ 698 nd6_na_input(m, off, icmp6len); 699 m = NULL; 700 goto freeit; 701 } 702 nd6_na_input(n, off, icmp6len); 703 /* m stays. */ 704 break; 705 706 case ND_REDIRECT: 707 if (code != 0) 708 goto badcode; 709 if (icmp6len < sizeof(struct nd_redirect)) 710 goto badlen; 711 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 712 /* give up local */ 713 icmp6_redirect_input(m, off); 714 m = NULL; 715 goto freeit; 716 } 717 icmp6_redirect_input(n, off); 718 /* m stays. */ 719 break; 720 721 case ICMP6_ROUTER_RENUMBERING: 722 if (code != ICMP6_ROUTER_RENUMBERING_COMMAND && 723 code != ICMP6_ROUTER_RENUMBERING_RESULT) 724 goto badcode; 725 if (icmp6len < sizeof(struct icmp6_router_renum)) 726 goto badlen; 727 break; 728 729 default: 730 nd6log((LOG_DEBUG, 731 "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%u)\n", 732 icmp6->icmp6_type, 733 inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)), 734 inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst)), 735 m->m_pkthdr.ph_ifidx)); 736 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { 737 /* ICMPv6 error: MUST deliver it by spec... */ 738 code = PRC_NCMDS; 739 /* deliver */ 740 } else { 741 /* ICMPv6 informational: MUST not deliver */ 742 break; 743 } 744 deliver: 745 if (icmp6_notify_error(m, off, icmp6len, code)) { 746 /* In this case, m should've been freed. */ 747 return (IPPROTO_DONE); 748 } 749 break; 750 751 badcode: 752 icmp6stat_inc(icp6s_badcode); 753 break; 754 755 badlen: 756 icmp6stat_inc(icp6s_badlen); 757 break; 758 } 759 760 #if NPF > 0 761 raw: 762 #endif 763 /* deliver the packet to appropriate sockets */ 764 return rip6_input(mp, offp, proto, af); 765 766 freeit: 767 m_freem(m); 768 return IPPROTO_DONE; 769 } 770 771 int 772 icmp6_notify_error(struct mbuf *m, int off, int icmp6len, int code) 773 { 774 struct icmp6_hdr *icmp6; 775 struct ip6_hdr *eip6; 776 u_int32_t notifymtu; 777 struct sockaddr_in6 icmp6src, icmp6dst; 778 779 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) { 780 icmp6stat_inc(icp6s_tooshort); 781 goto freeit; 782 } 783 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 784 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 785 if (icmp6 == NULL) { 786 icmp6stat_inc(icp6s_tooshort); 787 return (-1); 788 } 789 eip6 = (struct ip6_hdr *)(icmp6 + 1); 790 791 /* Detect the upper level protocol */ 792 { 793 void (*ctlfunc)(int, struct sockaddr *, u_int, void *); 794 u_int8_t nxt = eip6->ip6_nxt; 795 int eoff = off + sizeof(struct icmp6_hdr) + 796 sizeof(struct ip6_hdr); 797 struct ip6ctlparam ip6cp; 798 struct in6_addr *finaldst = NULL; 799 int icmp6type = icmp6->icmp6_type; 800 struct ip6_frag *fh; 801 struct ip6_rthdr *rth; 802 struct ip6_rthdr0 *rth0; 803 int rthlen; 804 805 while (1) { /* XXX: should avoid infinite loop explicitly? */ 806 struct ip6_ext *eh; 807 808 switch (nxt) { 809 case IPPROTO_HOPOPTS: 810 case IPPROTO_DSTOPTS: 811 case IPPROTO_AH: 812 IP6_EXTHDR_GET(eh, struct ip6_ext *, m, 813 eoff, sizeof(*eh)); 814 if (eh == NULL) { 815 icmp6stat_inc(icp6s_tooshort); 816 return (-1); 817 } 818 819 if (nxt == IPPROTO_AH) 820 eoff += (eh->ip6e_len + 2) << 2; 821 else 822 eoff += (eh->ip6e_len + 1) << 3; 823 nxt = eh->ip6e_nxt; 824 break; 825 case IPPROTO_ROUTING: 826 /* 827 * When the erroneous packet contains a 828 * routing header, we should examine the 829 * header to determine the final destination. 830 * Otherwise, we can't properly update 831 * information that depends on the final 832 * destination (e.g. path MTU). 833 */ 834 IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m, 835 eoff, sizeof(*rth)); 836 if (rth == NULL) { 837 icmp6stat_inc(icp6s_tooshort); 838 return (-1); 839 } 840 rthlen = (rth->ip6r_len + 1) << 3; 841 /* 842 * XXX: currently there is no 843 * officially defined type other 844 * than type-0. 845 * Note that if the segment left field 846 * is 0, all intermediate hops must 847 * have been passed. 848 */ 849 if (rth->ip6r_segleft && 850 rth->ip6r_type == IPV6_RTHDR_TYPE_0) { 851 int hops; 852 853 IP6_EXTHDR_GET(rth0, 854 struct ip6_rthdr0 *, m, 855 eoff, rthlen); 856 if (rth0 == NULL) { 857 icmp6stat_inc(icp6s_tooshort); 858 return (-1); 859 } 860 /* just ignore a bogus header */ 861 if ((rth0->ip6r0_len % 2) == 0 && 862 (hops = rth0->ip6r0_len/2)) 863 finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1); 864 } 865 eoff += rthlen; 866 nxt = rth->ip6r_nxt; 867 break; 868 case IPPROTO_FRAGMENT: 869 IP6_EXTHDR_GET(fh, struct ip6_frag *, m, 870 eoff, sizeof(*fh)); 871 if (fh == NULL) { 872 icmp6stat_inc(icp6s_tooshort); 873 return (-1); 874 } 875 /* 876 * Data after a fragment header is meaningless 877 * unless it is the first fragment, but 878 * we'll go to the notify label for path MTU 879 * discovery. 880 */ 881 if (fh->ip6f_offlg & IP6F_OFF_MASK) 882 goto notify; 883 884 eoff += sizeof(struct ip6_frag); 885 nxt = fh->ip6f_nxt; 886 break; 887 default: 888 /* 889 * This case includes ESP and the No Next 890 * Header. In such cases going to the notify 891 * label does not have any meaning 892 * (i.e. ctlfunc will be NULL), but we go 893 * anyway since we might have to update 894 * path MTU information. 895 */ 896 goto notify; 897 } 898 } 899 notify: 900 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 901 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 902 if (icmp6 == NULL) { 903 icmp6stat_inc(icp6s_tooshort); 904 return (-1); 905 } 906 907 eip6 = (struct ip6_hdr *)(icmp6 + 1); 908 bzero(&icmp6dst, sizeof(icmp6dst)); 909 icmp6dst.sin6_len = sizeof(struct sockaddr_in6); 910 icmp6dst.sin6_family = AF_INET6; 911 if (finaldst == NULL) 912 icmp6dst.sin6_addr = eip6->ip6_dst; 913 else 914 icmp6dst.sin6_addr = *finaldst; 915 icmp6dst.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, 916 &icmp6dst.sin6_addr); 917 if (in6_embedscope(&icmp6dst.sin6_addr, &icmp6dst, NULL)) { 918 /* should be impossbile */ 919 nd6log((LOG_DEBUG, 920 "icmp6_notify_error: in6_embedscope failed\n")); 921 goto freeit; 922 } 923 924 /* 925 * retrieve parameters from the inner IPv6 header, and convert 926 * them into sockaddr structures. 927 */ 928 bzero(&icmp6src, sizeof(icmp6src)); 929 icmp6src.sin6_len = sizeof(struct sockaddr_in6); 930 icmp6src.sin6_family = AF_INET6; 931 icmp6src.sin6_addr = eip6->ip6_src; 932 icmp6src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, 933 &icmp6src.sin6_addr); 934 if (in6_embedscope(&icmp6src.sin6_addr, &icmp6src, NULL)) { 935 /* should be impossbile */ 936 nd6log((LOG_DEBUG, 937 "icmp6_notify_error: in6_embedscope failed\n")); 938 goto freeit; 939 } 940 icmp6src.sin6_flowinfo = 941 (eip6->ip6_flow & IPV6_FLOWLABEL_MASK); 942 943 if (finaldst == NULL) 944 finaldst = &eip6->ip6_dst; 945 ip6cp.ip6c_m = m; 946 ip6cp.ip6c_icmp6 = icmp6; 947 ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1); 948 ip6cp.ip6c_off = eoff; 949 ip6cp.ip6c_finaldst = finaldst; 950 ip6cp.ip6c_src = &icmp6src; 951 ip6cp.ip6c_nxt = nxt; 952 #if NPF > 0 953 pf_pkt_addr_changed(m); 954 #endif 955 956 if (icmp6type == ICMP6_PACKET_TOO_BIG) { 957 notifymtu = ntohl(icmp6->icmp6_mtu); 958 ip6cp.ip6c_cmdarg = (void *)¬ifymtu; 959 } 960 961 ctlfunc = inet6sw[ip6_protox[nxt]].pr_ctlinput; 962 if (ctlfunc) 963 (*ctlfunc)(code, sin6tosa(&icmp6dst), 964 m->m_pkthdr.ph_rtableid, &ip6cp); 965 } 966 return (0); 967 968 freeit: 969 m_freem(m); 970 return (-1); 971 } 972 973 void 974 icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated) 975 { 976 unsigned long rtcount; 977 struct icmp6_mtudisc_callback *mc; 978 struct in6_addr *dst = ip6cp->ip6c_finaldst; 979 struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6; 980 struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */ 981 u_int mtu = ntohl(icmp6->icmp6_mtu); 982 struct rtentry *rt = NULL; 983 struct sockaddr_in6 sin6; 984 985 if (mtu < IPV6_MMTU) 986 return; 987 988 /* 989 * allow non-validated cases if memory is plenty, to make traffic 990 * from non-connected pcb happy. 991 */ 992 rtcount = rt_timer_queue_count(icmp6_mtudisc_timeout_q); 993 if (validated) { 994 if (0 <= icmp6_mtudisc_hiwat && rtcount > icmp6_mtudisc_hiwat) 995 return; 996 else if (0 <= icmp6_mtudisc_lowat && 997 rtcount > icmp6_mtudisc_lowat) { 998 /* 999 * XXX nuke a victim, install the new one. 1000 */ 1001 } 1002 } else { 1003 if (0 <= icmp6_mtudisc_lowat && rtcount > icmp6_mtudisc_lowat) 1004 return; 1005 } 1006 1007 bzero(&sin6, sizeof(sin6)); 1008 sin6.sin6_family = PF_INET6; 1009 sin6.sin6_len = sizeof(struct sockaddr_in6); 1010 sin6.sin6_addr = *dst; 1011 /* XXX normally, this won't happen */ 1012 if (IN6_IS_ADDR_LINKLOCAL(dst)) { 1013 sin6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.ph_ifidx); 1014 } 1015 sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, 1016 &sin6.sin6_addr); 1017 1018 rt = icmp6_mtudisc_clone(sin6tosa(&sin6), m->m_pkthdr.ph_rtableid); 1019 1020 if (rt != NULL && ISSET(rt->rt_flags, RTF_HOST) && 1021 !(rt->rt_locks & RTV_MTU) && 1022 (rt->rt_mtu > mtu || rt->rt_mtu == 0)) { 1023 struct ifnet *ifp; 1024 1025 ifp = if_get(rt->rt_ifidx); 1026 if (ifp != NULL && mtu < ifp->if_mtu) { 1027 icmp6stat_inc(icp6s_pmtuchg); 1028 rt->rt_mtu = mtu; 1029 } 1030 if_put(ifp); 1031 } 1032 rtfree(rt); 1033 1034 /* 1035 * Notify protocols that the MTU for this destination 1036 * has changed. 1037 */ 1038 LIST_FOREACH(mc, &icmp6_mtudisc_callbacks, mc_list) 1039 (*mc->mc_func)(&sin6, m->m_pkthdr.ph_rtableid); 1040 } 1041 1042 /* 1043 * Reflect the ip6 packet back to the source. 1044 * OFF points to the icmp6 header, counted from the top of the mbuf. 1045 */ 1046 int 1047 icmp6_reflect(struct mbuf **mp, size_t off, struct sockaddr *sa) 1048 { 1049 struct mbuf *m = *mp; 1050 struct rtentry *rt = NULL; 1051 struct ip6_hdr *ip6; 1052 struct icmp6_hdr *icmp6; 1053 struct in6_addr t, *src = NULL; 1054 struct sockaddr_in6 sa6_src, sa6_dst; 1055 u_int rtableid; 1056 1057 CTASSERT(sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) <= MHLEN); 1058 1059 /* too short to reflect */ 1060 if (off < sizeof(struct ip6_hdr)) { 1061 nd6log((LOG_DEBUG, 1062 "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n", 1063 (u_long)off, (u_long)sizeof(struct ip6_hdr), 1064 __FILE__, __LINE__)); 1065 goto bad; 1066 } 1067 1068 if (m->m_pkthdr.ph_loopcnt++ >= M_MAXLOOP) { 1069 m_freemp(mp); 1070 return (ELOOP); 1071 } 1072 rtableid = m->m_pkthdr.ph_rtableid; 1073 m_resethdr(m); 1074 m->m_pkthdr.ph_rtableid = rtableid; 1075 1076 /* 1077 * If there are extra headers between IPv6 and ICMPv6, strip 1078 * off that header first. 1079 */ 1080 if (off > sizeof(struct ip6_hdr)) { 1081 size_t l; 1082 struct ip6_hdr nip6; 1083 1084 l = off - sizeof(struct ip6_hdr); 1085 m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6); 1086 m_adj(m, l); 1087 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1088 if (m->m_len < l) { 1089 if ((m = *mp = m_pullup(m, l)) == NULL) 1090 return (EMSGSIZE); 1091 } 1092 memcpy(mtod(m, caddr_t), &nip6, sizeof(nip6)); 1093 } else /* off == sizeof(struct ip6_hdr) */ { 1094 size_t l; 1095 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1096 if (m->m_len < l) { 1097 if ((m = *mp = m_pullup(m, l)) == NULL) 1098 return (EMSGSIZE); 1099 } 1100 } 1101 ip6 = mtod(m, struct ip6_hdr *); 1102 ip6->ip6_nxt = IPPROTO_ICMPV6; 1103 icmp6 = (struct icmp6_hdr *)(ip6 + 1); 1104 1105 t = ip6->ip6_dst; 1106 /* 1107 * ip6_input() drops a packet if its src is multicast. 1108 * So, the src is never multicast. 1109 */ 1110 ip6->ip6_dst = ip6->ip6_src; 1111 1112 /* 1113 * XXX: make sure to embed scope zone information, using 1114 * already embedded IDs or the received interface (if any). 1115 * Note that rcvif may be NULL. 1116 * TODO: scoped routing case (XXX). 1117 */ 1118 bzero(&sa6_src, sizeof(sa6_src)); 1119 sa6_src.sin6_family = AF_INET6; 1120 sa6_src.sin6_len = sizeof(sa6_src); 1121 sa6_src.sin6_addr = ip6->ip6_dst; 1122 bzero(&sa6_dst, sizeof(sa6_dst)); 1123 sa6_dst.sin6_family = AF_INET6; 1124 sa6_dst.sin6_len = sizeof(sa6_dst); 1125 sa6_dst.sin6_addr = t; 1126 1127 if (sa == NULL) { 1128 /* 1129 * If the incoming packet was addressed directly to us (i.e. 1130 * unicast), use dst as the src for the reply. The 1131 * IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED case would be VERY rare, 1132 * but is possible (for example) when we encounter an error 1133 * while forwarding procedure destined to a duplicated address 1134 * of ours. 1135 */ 1136 rt = rtalloc(sin6tosa(&sa6_dst), 0, rtableid); 1137 if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) && 1138 !ISSET(ifatoia6(rt->rt_ifa)->ia6_flags, 1139 IN6_IFF_ANYCAST|IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)) { 1140 src = &t; 1141 } 1142 rtfree(rt); 1143 rt = NULL; 1144 sa = sin6tosa(&sa6_src); 1145 } 1146 1147 if (src == NULL) { 1148 struct in6_ifaddr *ia6; 1149 1150 /* 1151 * This case matches to multicasts, our anycast, or unicasts 1152 * that we do not own. Select a source address based on the 1153 * source address of the erroneous packet. 1154 */ 1155 rt = rtalloc(sa, RT_RESOLVE, rtableid); 1156 if (!rtisvalid(rt)) { 1157 char addr[INET6_ADDRSTRLEN]; 1158 1159 nd6log((LOG_DEBUG, 1160 "%s: source can't be determined: dst=%s\n", 1161 __func__, inet_ntop(AF_INET6, &sa6_src.sin6_addr, 1162 addr, sizeof(addr)))); 1163 rtfree(rt); 1164 goto bad; 1165 } 1166 ia6 = in6_ifawithscope(rt->rt_ifa->ifa_ifp, &t, rtableid); 1167 if (ia6 != NULL) 1168 src = &ia6->ia_addr.sin6_addr; 1169 if (src == NULL) 1170 src = &ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr; 1171 } 1172 1173 ip6->ip6_src = *src; 1174 rtfree(rt); 1175 1176 ip6->ip6_flow = 0; 1177 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 1178 ip6->ip6_vfc |= IPV6_VERSION; 1179 ip6->ip6_nxt = IPPROTO_ICMPV6; 1180 ip6->ip6_hlim = ip6_defhlim; 1181 1182 icmp6->icmp6_cksum = 0; 1183 m->m_pkthdr.csum_flags = M_ICMP_CSUM_OUT; 1184 1185 /* 1186 * XXX option handling 1187 */ 1188 1189 m->m_flags &= ~(M_BCAST|M_MCAST); 1190 return (0); 1191 1192 bad: 1193 m_freemp(mp); 1194 return (EHOSTUNREACH); 1195 } 1196 1197 void 1198 icmp6_fasttimo(void) 1199 { 1200 1201 mld6_fasttimeo(); 1202 } 1203 1204 const char * 1205 icmp6_redirect_diag(struct in6_addr *src6, struct in6_addr *dst6, 1206 struct in6_addr *tgt6) 1207 { 1208 static char buf[1024]; /* XXX */ 1209 char src[INET6_ADDRSTRLEN]; 1210 char dst[INET6_ADDRSTRLEN]; 1211 char tgt[INET6_ADDRSTRLEN]; 1212 1213 snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)", 1214 inet_ntop(AF_INET6, src6, src, sizeof(src)), 1215 inet_ntop(AF_INET6, dst6, dst, sizeof(dst)), 1216 inet_ntop(AF_INET6, tgt6, tgt, sizeof(tgt))); 1217 return buf; 1218 } 1219 1220 void 1221 icmp6_redirect_input(struct mbuf *m, int off) 1222 { 1223 struct ifnet *ifp; 1224 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1225 struct nd_redirect *nd_rd; 1226 int icmp6len = ntohs(ip6->ip6_plen); 1227 char *lladdr = NULL; 1228 int lladdrlen = 0; 1229 struct rtentry *rt = NULL; 1230 int is_router; 1231 int is_onlink; 1232 struct in6_addr src6 = ip6->ip6_src; 1233 struct in6_addr redtgt6; 1234 struct in6_addr reddst6; 1235 union nd_opts ndopts; 1236 char addr[INET6_ADDRSTRLEN]; 1237 1238 ifp = if_get(m->m_pkthdr.ph_ifidx); 1239 if (ifp == NULL) 1240 return; 1241 1242 /* XXX if we are router, we don't update route by icmp6 redirect */ 1243 if (ip6_forwarding) 1244 goto freeit; 1245 if (!(ifp->if_xflags & IFXF_AUTOCONF6)) 1246 goto freeit; 1247 1248 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len); 1249 if (nd_rd == NULL) { 1250 icmp6stat_inc(icp6s_tooshort); 1251 if_put(ifp); 1252 return; 1253 } 1254 redtgt6 = nd_rd->nd_rd_target; 1255 reddst6 = nd_rd->nd_rd_dst; 1256 1257 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1258 redtgt6.s6_addr16[1] = htons(ifp->if_index); 1259 if (IN6_IS_ADDR_LINKLOCAL(&reddst6)) 1260 reddst6.s6_addr16[1] = htons(ifp->if_index); 1261 1262 /* validation */ 1263 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) { 1264 nd6log((LOG_ERR, 1265 "ICMP6 redirect sent from %s rejected; " 1266 "must be from linklocal\n", 1267 inet_ntop(AF_INET6, &src6, addr, sizeof(addr)))); 1268 goto bad; 1269 } 1270 if (ip6->ip6_hlim != 255) { 1271 nd6log((LOG_ERR, 1272 "ICMP6 redirect sent from %s rejected; " 1273 "hlim=%d (must be 255)\n", 1274 inet_ntop(AF_INET6, &src6, addr, sizeof(addr)), 1275 ip6->ip6_hlim)); 1276 goto bad; 1277 } 1278 if (IN6_IS_ADDR_MULTICAST(&reddst6)) { 1279 nd6log((LOG_ERR, 1280 "ICMP6 redirect rejected; " 1281 "redirect dst must be unicast: %s\n", 1282 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1283 goto bad; 1284 } 1285 { 1286 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */ 1287 struct sockaddr_in6 sin6; 1288 struct in6_addr *gw6; 1289 1290 bzero(&sin6, sizeof(sin6)); 1291 sin6.sin6_family = AF_INET6; 1292 sin6.sin6_len = sizeof(struct sockaddr_in6); 1293 memcpy(&sin6.sin6_addr, &reddst6, sizeof(reddst6)); 1294 rt = rtalloc(sin6tosa(&sin6), 0, m->m_pkthdr.ph_rtableid); 1295 if (rt) { 1296 if (rt->rt_gateway == NULL || 1297 rt->rt_gateway->sa_family != AF_INET6) { 1298 nd6log((LOG_ERR, 1299 "ICMP6 redirect rejected; no route " 1300 "with inet6 gateway found for redirect dst: %s\n", 1301 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1302 rtfree(rt); 1303 goto bad; 1304 } 1305 1306 gw6 = &(satosin6(rt->rt_gateway)->sin6_addr); 1307 if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) { 1308 nd6log((LOG_ERR, 1309 "ICMP6 redirect rejected; " 1310 "not equal to gw-for-src=%s (must be same): " 1311 "%s\n", 1312 inet_ntop(AF_INET6, gw6, addr, sizeof(addr)), 1313 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1314 rtfree(rt); 1315 goto bad; 1316 } 1317 } else { 1318 nd6log((LOG_ERR, 1319 "ICMP6 redirect rejected; " 1320 "no route found for redirect dst: %s\n", 1321 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1322 goto bad; 1323 } 1324 rtfree(rt); 1325 rt = NULL; 1326 } 1327 1328 is_router = is_onlink = 0; 1329 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1330 is_router = 1; /* router case */ 1331 if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) 1332 is_onlink = 1; /* on-link destination case */ 1333 if (!is_router && !is_onlink) { 1334 nd6log((LOG_ERR, 1335 "ICMP6 redirect rejected; " 1336 "neither router case nor onlink case: %s\n", 1337 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1338 goto bad; 1339 } 1340 /* validation passed */ 1341 1342 icmp6len -= sizeof(*nd_rd); 1343 nd6_option_init(nd_rd + 1, icmp6len, &ndopts); 1344 if (nd6_options(&ndopts) < 0) { 1345 nd6log((LOG_INFO, "icmp6_redirect_input: " 1346 "invalid ND option, rejected: %s\n", 1347 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1348 /* nd6_options have incremented stats */ 1349 goto freeit; 1350 } 1351 1352 if (ndopts.nd_opts_tgt_lladdr) { 1353 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); 1354 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; 1355 } 1356 1357 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 1358 nd6log((LOG_INFO, 1359 "icmp6_redirect_input: lladdrlen mismatch for %s " 1360 "(if %d, icmp6 packet %d): %s\n", 1361 inet_ntop(AF_INET6, &redtgt6, addr, sizeof(addr)), 1362 ifp->if_addrlen, lladdrlen - 2, 1363 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1364 goto bad; 1365 } 1366 1367 /* RFC 2461 8.3 */ 1368 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, 1369 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); 1370 1371 if (!is_onlink) { /* better router case. perform rtredirect. */ 1372 /* perform rtredirect */ 1373 struct sockaddr_in6 sdst; 1374 struct sockaddr_in6 sgw; 1375 struct sockaddr_in6 ssrc; 1376 unsigned long rtcount; 1377 struct rtentry *newrt = NULL; 1378 1379 /* 1380 * do not install redirect route, if the number of entries 1381 * is too much (> hiwat). note that, the node (= host) will 1382 * work just fine even if we do not install redirect route 1383 * (there will be additional hops, though). 1384 */ 1385 rtcount = rt_timer_queue_count(icmp6_redirect_timeout_q); 1386 if (0 <= ip6_maxdynroutes && rtcount >= ip6_maxdynroutes) 1387 goto freeit; 1388 else if (0 <= icmp6_redirect_lowat && 1389 rtcount > icmp6_redirect_lowat) { 1390 /* 1391 * XXX nuke a victim, install the new one. 1392 */ 1393 } 1394 1395 bzero(&sdst, sizeof(sdst)); 1396 bzero(&sgw, sizeof(sgw)); 1397 bzero(&ssrc, sizeof(ssrc)); 1398 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6; 1399 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len = 1400 sizeof(struct sockaddr_in6); 1401 memcpy(&sgw.sin6_addr, &redtgt6, sizeof(struct in6_addr)); 1402 memcpy(&sdst.sin6_addr, &reddst6, sizeof(struct in6_addr)); 1403 memcpy(&ssrc.sin6_addr, &src6, sizeof(struct in6_addr)); 1404 rtredirect(sin6tosa(&sdst), sin6tosa(&sgw), sin6tosa(&ssrc), 1405 &newrt, m->m_pkthdr.ph_rtableid); 1406 1407 if (newrt) { 1408 (void)rt_timer_add(newrt, icmp6_redirect_timeout, 1409 icmp6_redirect_timeout_q, m->m_pkthdr.ph_rtableid); 1410 rtfree(newrt); 1411 } 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 *dst, u_int rtableid) 1788 { 1789 struct rtentry *rt; 1790 int error; 1791 1792 rt = rtalloc(dst, RT_RESOLVE, rtableid); 1793 1794 /* Check if the route is actually usable */ 1795 if (!rtisvalid(rt) || (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE))) 1796 goto bad; 1797 1798 /* 1799 * No PMTU for local routes and permanent neighbors, 1800 * ARP and NDP use the same expire timer as the route. 1801 */ 1802 if (ISSET(rt->rt_flags, RTF_LOCAL) || 1803 (ISSET(rt->rt_flags, RTF_LLINFO) && rt->rt_expire == 0)) 1804 goto bad; 1805 1806 /* If we didn't get a host route, allocate one */ 1807 if ((rt->rt_flags & RTF_HOST) == 0) { 1808 struct rtentry *nrt; 1809 struct rt_addrinfo info; 1810 struct sockaddr_rtlabel sa_rl; 1811 1812 memset(&info, 0, sizeof(info)); 1813 info.rti_ifa = rt->rt_ifa; 1814 info.rti_flags = RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC; 1815 info.rti_info[RTAX_DST] = dst; 1816 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1817 info.rti_info[RTAX_LABEL] = 1818 rtlabel_id2sa(rt->rt_labelid, &sa_rl); 1819 1820 error = rtrequest(RTM_ADD, &info, rt->rt_priority, &nrt, 1821 rtableid); 1822 if (error) 1823 goto bad; 1824 nrt->rt_rmx = rt->rt_rmx; 1825 rtfree(rt); 1826 rt = nrt; 1827 rtm_send(rt, RTM_ADD, 0, rtableid); 1828 } 1829 error = rt_timer_add(rt, icmp6_mtudisc_timeout, icmp6_mtudisc_timeout_q, 1830 rtableid); 1831 if (error) 1832 goto bad; 1833 1834 return (rt); 1835 bad: 1836 rtfree(rt); 1837 return (NULL); 1838 } 1839 1840 void 1841 icmp6_mtudisc_timeout(struct rtentry *rt, struct rttimer *r) 1842 { 1843 struct ifnet *ifp; 1844 1845 NET_ASSERT_LOCKED(); 1846 1847 ifp = if_get(rt->rt_ifidx); 1848 if (ifp == NULL) 1849 return; 1850 1851 if ((rt->rt_flags & (RTF_DYNAMIC|RTF_HOST)) == (RTF_DYNAMIC|RTF_HOST)) { 1852 rtdeletemsg(rt, ifp, r->rtt_tableid); 1853 } else { 1854 if (!(rt->rt_locks & RTV_MTU)) 1855 rt->rt_mtu = 0; 1856 } 1857 1858 if_put(ifp); 1859 } 1860 1861 void 1862 icmp6_redirect_timeout(struct rtentry *rt, struct rttimer *r) 1863 { 1864 struct ifnet *ifp; 1865 1866 NET_ASSERT_LOCKED(); 1867 1868 ifp = if_get(rt->rt_ifidx); 1869 if (ifp == NULL) 1870 return; 1871 1872 if ((rt->rt_flags & (RTF_DYNAMIC|RTF_HOST)) == (RTF_DYNAMIC|RTF_HOST)) { 1873 rtdeletemsg(rt, ifp, r->rtt_tableid); 1874 } 1875 1876 if_put(ifp); 1877 } 1878 1879 const struct sysctl_bounded_args icmpv6ctl_vars[] = { 1880 { ICMPV6CTL_REDIRTIMEOUT, &icmp6_redirtimeout, 0, INT_MAX }, 1881 { ICMPV6CTL_ND6_DELAY, &nd6_delay, 0, INT_MAX }, 1882 { ICMPV6CTL_ND6_UMAXTRIES, &nd6_umaxtries, 0, INT_MAX }, 1883 { ICMPV6CTL_ND6_MMAXTRIES, &nd6_mmaxtries, 0, INT_MAX }, 1884 { ICMPV6CTL_ERRPPSLIMIT, &icmp6errppslim, -1, 1000 }, 1885 { ICMPV6CTL_ND6_MAXNUDHINT, &nd6_maxnudhint, 0, INT_MAX }, 1886 { ICMPV6CTL_MTUDISC_HIWAT, &icmp6_mtudisc_hiwat, -1, INT_MAX }, 1887 { ICMPV6CTL_MTUDISC_LOWAT, &icmp6_mtudisc_lowat, -1, INT_MAX }, 1888 { ICMPV6CTL_ND6_DEBUG, &nd6_debug, 0, 1 }, 1889 }; 1890 1891 int 1892 icmp6_sysctl_icmp6stat(void *oldp, size_t *oldlenp, void *newp) 1893 { 1894 struct icmp6stat *icmp6stat; 1895 int ret; 1896 1897 CTASSERT(sizeof(*icmp6stat) == icp6s_ncounters * sizeof(uint64_t)); 1898 icmp6stat = malloc(sizeof(*icmp6stat), M_TEMP, M_WAITOK|M_ZERO); 1899 counters_read(icmp6counters, (uint64_t *)icmp6stat, icp6s_ncounters); 1900 ret = sysctl_rdstruct(oldp, oldlenp, newp, 1901 icmp6stat, sizeof(*icmp6stat)); 1902 free(icmp6stat, M_TEMP, sizeof(*icmp6stat)); 1903 1904 return (ret); 1905 } 1906 1907 int 1908 icmp6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1909 void *newp, size_t newlen) 1910 { 1911 int error; 1912 1913 /* All sysctl names at this level are terminal. */ 1914 if (namelen != 1) 1915 return ENOTDIR; 1916 1917 switch (name[0]) { 1918 1919 case ICMPV6CTL_STATS: 1920 return icmp6_sysctl_icmp6stat(oldp, oldlenp, newp); 1921 default: 1922 NET_LOCK(); 1923 error = sysctl_bounded_arr(icmpv6ctl_vars, 1924 nitems(icmpv6ctl_vars), name, namelen, oldp, oldlenp, newp, 1925 newlen); 1926 NET_UNLOCK(); 1927 return (error); 1928 } 1929 /* NOTREACHED */ 1930 } 1931