1 /* $OpenBSD: icmp6.c,v 1.231 2020/08/01 23:41:56 gnezdo 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 *m, size_t off, struct sockaddr *sa) 1048 { 1049 struct rtentry *rt = NULL; 1050 struct ip6_hdr *ip6; 1051 struct icmp6_hdr *icmp6; 1052 struct in6_addr t, *src = NULL; 1053 struct sockaddr_in6 sa6_src, sa6_dst; 1054 u_int rtableid; 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_freem(m); 1069 return (ELOOP); 1070 } 1071 rtableid = m->m_pkthdr.ph_rtableid; 1072 m_resethdr(m); 1073 m->m_pkthdr.ph_rtableid = rtableid; 1074 1075 /* 1076 * If there are extra headers between IPv6 and ICMPv6, strip 1077 * off that header first. 1078 */ 1079 if (off > sizeof(struct ip6_hdr)) { 1080 size_t l; 1081 struct ip6_hdr nip6; 1082 1083 l = off - sizeof(struct ip6_hdr); 1084 m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6); 1085 m_adj(m, l); 1086 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1087 if (m->m_len < l) { 1088 if ((m = m_pullup(m, l)) == NULL) 1089 return (EMSGSIZE); 1090 } 1091 memcpy(mtod(m, caddr_t), &nip6, sizeof(nip6)); 1092 } else /* off == sizeof(struct ip6_hdr) */ { 1093 size_t l; 1094 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1095 if (m->m_len < l) { 1096 if ((m = m_pullup(m, l)) == NULL) 1097 return (EMSGSIZE); 1098 } 1099 } 1100 ip6 = mtod(m, struct ip6_hdr *); 1101 ip6->ip6_nxt = IPPROTO_ICMPV6; 1102 icmp6 = (struct icmp6_hdr *)(ip6 + 1); 1103 1104 t = ip6->ip6_dst; 1105 /* 1106 * ip6_input() drops a packet if its src is multicast. 1107 * So, the src is never multicast. 1108 */ 1109 ip6->ip6_dst = ip6->ip6_src; 1110 1111 /* 1112 * XXX: make sure to embed scope zone information, using 1113 * already embedded IDs or the received interface (if any). 1114 * Note that rcvif may be NULL. 1115 * TODO: scoped routing case (XXX). 1116 */ 1117 bzero(&sa6_src, sizeof(sa6_src)); 1118 sa6_src.sin6_family = AF_INET6; 1119 sa6_src.sin6_len = sizeof(sa6_src); 1120 sa6_src.sin6_addr = ip6->ip6_dst; 1121 bzero(&sa6_dst, sizeof(sa6_dst)); 1122 sa6_dst.sin6_family = AF_INET6; 1123 sa6_dst.sin6_len = sizeof(sa6_dst); 1124 sa6_dst.sin6_addr = t; 1125 1126 if (sa == NULL) { 1127 /* 1128 * If the incoming packet was addressed directly to us (i.e. 1129 * unicast), use dst as the src for the reply. The 1130 * IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED case would be VERY rare, 1131 * but is possible (for example) when we encounter an error 1132 * while forwarding procedure destined to a duplicated address 1133 * of ours. 1134 */ 1135 rt = rtalloc(sin6tosa(&sa6_dst), 0, rtableid); 1136 if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) && 1137 !ISSET(ifatoia6(rt->rt_ifa)->ia6_flags, 1138 IN6_IFF_ANYCAST|IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)) { 1139 src = &t; 1140 } 1141 rtfree(rt); 1142 rt = NULL; 1143 sa = sin6tosa(&sa6_src); 1144 } 1145 1146 if (src == NULL) { 1147 struct in6_ifaddr *ia6; 1148 1149 /* 1150 * This case matches to multicasts, our anycast, or unicasts 1151 * that we do not own. Select a source address based on the 1152 * source address of the erroneous packet. 1153 */ 1154 rt = rtalloc(sa, RT_RESOLVE, rtableid); 1155 if (!rtisvalid(rt)) { 1156 char addr[INET6_ADDRSTRLEN]; 1157 1158 nd6log((LOG_DEBUG, 1159 "%s: source can't be determined: dst=%s\n", 1160 __func__, inet_ntop(AF_INET6, &sa6_src.sin6_addr, 1161 addr, sizeof(addr)))); 1162 rtfree(rt); 1163 goto bad; 1164 } 1165 ia6 = in6_ifawithscope(rt->rt_ifa->ifa_ifp, &t, rtableid); 1166 if (ia6 != NULL) 1167 src = &ia6->ia_addr.sin6_addr; 1168 if (src == NULL) 1169 src = &ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr; 1170 } 1171 1172 ip6->ip6_src = *src; 1173 rtfree(rt); 1174 1175 ip6->ip6_flow = 0; 1176 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 1177 ip6->ip6_vfc |= IPV6_VERSION; 1178 ip6->ip6_nxt = IPPROTO_ICMPV6; 1179 ip6->ip6_hlim = ip6_defhlim; 1180 1181 icmp6->icmp6_cksum = 0; 1182 m->m_pkthdr.csum_flags = M_ICMP_CSUM_OUT; 1183 1184 /* 1185 * XXX option handling 1186 */ 1187 1188 m->m_flags &= ~(M_BCAST|M_MCAST); 1189 return (0); 1190 1191 bad: 1192 m_freem(m); 1193 return (EHOSTUNREACH); 1194 } 1195 1196 void 1197 icmp6_fasttimo(void) 1198 { 1199 1200 mld6_fasttimeo(); 1201 } 1202 1203 const char * 1204 icmp6_redirect_diag(struct in6_addr *src6, struct in6_addr *dst6, 1205 struct in6_addr *tgt6) 1206 { 1207 static char buf[1024]; /* XXX */ 1208 char src[INET6_ADDRSTRLEN]; 1209 char dst[INET6_ADDRSTRLEN]; 1210 char tgt[INET6_ADDRSTRLEN]; 1211 1212 snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)", 1213 inet_ntop(AF_INET6, src6, src, sizeof(src)), 1214 inet_ntop(AF_INET6, dst6, dst, sizeof(dst)), 1215 inet_ntop(AF_INET6, tgt6, tgt, sizeof(tgt))); 1216 return buf; 1217 } 1218 1219 void 1220 icmp6_redirect_input(struct mbuf *m, int off) 1221 { 1222 struct ifnet *ifp; 1223 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1224 struct nd_redirect *nd_rd; 1225 int icmp6len = ntohs(ip6->ip6_plen); 1226 char *lladdr = NULL; 1227 int lladdrlen = 0; 1228 struct rtentry *rt = NULL; 1229 int is_router; 1230 int is_onlink; 1231 struct in6_addr src6 = ip6->ip6_src; 1232 struct in6_addr redtgt6; 1233 struct in6_addr reddst6; 1234 union nd_opts ndopts; 1235 char addr[INET6_ADDRSTRLEN]; 1236 1237 ifp = if_get(m->m_pkthdr.ph_ifidx); 1238 if (ifp == NULL) 1239 return; 1240 1241 /* XXX if we are router, we don't update route by icmp6 redirect */ 1242 if (ip6_forwarding) 1243 goto freeit; 1244 if (!(ifp->if_xflags & IFXF_AUTOCONF6)) 1245 goto freeit; 1246 1247 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len); 1248 if (nd_rd == NULL) { 1249 icmp6stat_inc(icp6s_tooshort); 1250 if_put(ifp); 1251 return; 1252 } 1253 redtgt6 = nd_rd->nd_rd_target; 1254 reddst6 = nd_rd->nd_rd_dst; 1255 1256 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1257 redtgt6.s6_addr16[1] = htons(ifp->if_index); 1258 if (IN6_IS_ADDR_LINKLOCAL(&reddst6)) 1259 reddst6.s6_addr16[1] = htons(ifp->if_index); 1260 1261 /* validation */ 1262 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) { 1263 nd6log((LOG_ERR, 1264 "ICMP6 redirect sent from %s rejected; " 1265 "must be from linklocal\n", 1266 inet_ntop(AF_INET6, &src6, addr, sizeof(addr)))); 1267 goto bad; 1268 } 1269 if (ip6->ip6_hlim != 255) { 1270 nd6log((LOG_ERR, 1271 "ICMP6 redirect sent from %s rejected; " 1272 "hlim=%d (must be 255)\n", 1273 inet_ntop(AF_INET6, &src6, addr, sizeof(addr)), 1274 ip6->ip6_hlim)); 1275 goto bad; 1276 } 1277 if (IN6_IS_ADDR_MULTICAST(&reddst6)) { 1278 nd6log((LOG_ERR, 1279 "ICMP6 redirect rejected; " 1280 "redirect dst must be unicast: %s\n", 1281 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1282 goto bad; 1283 } 1284 { 1285 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */ 1286 struct sockaddr_in6 sin6; 1287 struct in6_addr *gw6; 1288 1289 bzero(&sin6, sizeof(sin6)); 1290 sin6.sin6_family = AF_INET6; 1291 sin6.sin6_len = sizeof(struct sockaddr_in6); 1292 memcpy(&sin6.sin6_addr, &reddst6, sizeof(reddst6)); 1293 rt = rtalloc(sin6tosa(&sin6), 0, m->m_pkthdr.ph_rtableid); 1294 if (rt) { 1295 if (rt->rt_gateway == NULL || 1296 rt->rt_gateway->sa_family != AF_INET6) { 1297 nd6log((LOG_ERR, 1298 "ICMP6 redirect rejected; no route " 1299 "with inet6 gateway found for redirect dst: %s\n", 1300 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1301 rtfree(rt); 1302 goto bad; 1303 } 1304 1305 gw6 = &(satosin6(rt->rt_gateway)->sin6_addr); 1306 if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) { 1307 nd6log((LOG_ERR, 1308 "ICMP6 redirect rejected; " 1309 "not equal to gw-for-src=%s (must be same): " 1310 "%s\n", 1311 inet_ntop(AF_INET6, gw6, addr, sizeof(addr)), 1312 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1313 rtfree(rt); 1314 goto bad; 1315 } 1316 } else { 1317 nd6log((LOG_ERR, 1318 "ICMP6 redirect rejected; " 1319 "no route found for redirect dst: %s\n", 1320 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1321 goto bad; 1322 } 1323 rtfree(rt); 1324 rt = NULL; 1325 } 1326 1327 is_router = is_onlink = 0; 1328 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1329 is_router = 1; /* router case */ 1330 if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) 1331 is_onlink = 1; /* on-link destination case */ 1332 if (!is_router && !is_onlink) { 1333 nd6log((LOG_ERR, 1334 "ICMP6 redirect rejected; " 1335 "neither router case nor onlink case: %s\n", 1336 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1337 goto bad; 1338 } 1339 /* validation passed */ 1340 1341 icmp6len -= sizeof(*nd_rd); 1342 nd6_option_init(nd_rd + 1, icmp6len, &ndopts); 1343 if (nd6_options(&ndopts) < 0) { 1344 nd6log((LOG_INFO, "icmp6_redirect_input: " 1345 "invalid ND option, rejected: %s\n", 1346 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1347 /* nd6_options have incremented stats */ 1348 goto freeit; 1349 } 1350 1351 if (ndopts.nd_opts_tgt_lladdr) { 1352 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); 1353 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; 1354 } 1355 1356 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 1357 nd6log((LOG_INFO, 1358 "icmp6_redirect_input: lladdrlen mismatch for %s " 1359 "(if %d, icmp6 packet %d): %s\n", 1360 inet_ntop(AF_INET6, &redtgt6, addr, sizeof(addr)), 1361 ifp->if_addrlen, lladdrlen - 2, 1362 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 1363 goto bad; 1364 } 1365 1366 /* RFC 2461 8.3 */ 1367 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, 1368 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); 1369 1370 if (!is_onlink) { /* better router case. perform rtredirect. */ 1371 /* perform rtredirect */ 1372 struct sockaddr_in6 sdst; 1373 struct sockaddr_in6 sgw; 1374 struct sockaddr_in6 ssrc; 1375 unsigned long rtcount; 1376 struct rtentry *newrt = NULL; 1377 1378 /* 1379 * do not install redirect route, if the number of entries 1380 * is too much (> hiwat). note that, the node (= host) will 1381 * work just fine even if we do not install redirect route 1382 * (there will be additional hops, though). 1383 */ 1384 rtcount = rt_timer_queue_count(icmp6_redirect_timeout_q); 1385 if (0 <= ip6_maxdynroutes && rtcount >= ip6_maxdynroutes) 1386 goto freeit; 1387 else if (0 <= icmp6_redirect_lowat && 1388 rtcount > icmp6_redirect_lowat) { 1389 /* 1390 * XXX nuke a victim, install the new one. 1391 */ 1392 } 1393 1394 bzero(&sdst, sizeof(sdst)); 1395 bzero(&sgw, sizeof(sgw)); 1396 bzero(&ssrc, sizeof(ssrc)); 1397 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6; 1398 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len = 1399 sizeof(struct sockaddr_in6); 1400 memcpy(&sgw.sin6_addr, &redtgt6, sizeof(struct in6_addr)); 1401 memcpy(&sdst.sin6_addr, &reddst6, sizeof(struct in6_addr)); 1402 memcpy(&ssrc.sin6_addr, &src6, sizeof(struct in6_addr)); 1403 rtredirect(sin6tosa(&sdst), sin6tosa(&sgw), sin6tosa(&ssrc), 1404 &newrt, m->m_pkthdr.ph_rtableid); 1405 1406 if (newrt) { 1407 (void)rt_timer_add(newrt, icmp6_redirect_timeout, 1408 icmp6_redirect_timeout_q, m->m_pkthdr.ph_rtableid); 1409 rtfree(newrt); 1410 } 1411 } 1412 /* finally update cached route in each socket via pfctlinput */ 1413 { 1414 struct sockaddr_in6 sdst; 1415 1416 bzero(&sdst, sizeof(sdst)); 1417 sdst.sin6_family = AF_INET6; 1418 sdst.sin6_len = sizeof(struct sockaddr_in6); 1419 memcpy(&sdst.sin6_addr, &reddst6, sizeof(struct in6_addr)); 1420 pfctlinput(PRC_REDIRECT_HOST, sin6tosa(&sdst)); 1421 } 1422 1423 freeit: 1424 if_put(ifp); 1425 m_freem(m); 1426 return; 1427 1428 bad: 1429 if_put(ifp); 1430 icmp6stat_inc(icp6s_badredirect); 1431 m_freem(m); 1432 } 1433 1434 void 1435 icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt) 1436 { 1437 struct ifnet *ifp = NULL; 1438 struct in6_addr *ifp_ll6; 1439 struct in6_addr *nexthop; 1440 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */ 1441 struct mbuf *m = NULL; /* newly allocated one */ 1442 struct ip6_hdr *ip6; /* m as struct ip6_hdr */ 1443 struct nd_redirect *nd_rd; 1444 size_t maxlen; 1445 u_char *p; 1446 struct sockaddr_in6 src_sa; 1447 1448 icmp6_errcount(ND_REDIRECT, 0); 1449 1450 /* if we are not router, we don't send icmp6 redirect */ 1451 if (!ip6_forwarding) 1452 goto fail; 1453 1454 /* sanity check */ 1455 if (m0 == NULL || !rtisvalid(rt)) 1456 goto fail; 1457 1458 ifp = if_get(rt->rt_ifidx); 1459 if (ifp == NULL) 1460 goto fail; 1461 1462 /* 1463 * Address check: 1464 * the source address must identify a neighbor, and 1465 * the destination address must not be a multicast address 1466 * [RFC 2461, sec 8.2] 1467 */ 1468 sip6 = mtod(m0, struct ip6_hdr *); 1469 bzero(&src_sa, sizeof(src_sa)); 1470 src_sa.sin6_family = AF_INET6; 1471 src_sa.sin6_len = sizeof(src_sa); 1472 src_sa.sin6_addr = sip6->ip6_src; 1473 /* we don't currently use sin6_scope_id, but eventually use it */ 1474 src_sa.sin6_scope_id = in6_addr2scopeid(ifp->if_index, &sip6->ip6_src); 1475 if (nd6_is_addr_neighbor(&src_sa, ifp) == 0) 1476 goto fail; 1477 if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst)) 1478 goto fail; /* what should we do here? */ 1479 1480 /* rate limit */ 1481 if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0)) 1482 goto fail; 1483 1484 /* 1485 * Since we are going to append up to 1280 bytes (= IPV6_MMTU), 1486 * we almost always ask for an mbuf cluster for simplicity. 1487 * (MHLEN < IPV6_MMTU is almost always true) 1488 */ 1489 #if IPV6_MMTU >= MCLBYTES 1490 # error assumption failed about IPV6_MMTU and MCLBYTES 1491 #endif 1492 MGETHDR(m, M_DONTWAIT, MT_HEADER); 1493 if (m && IPV6_MMTU >= MHLEN) 1494 MCLGET(m, M_DONTWAIT); 1495 if (!m) 1496 goto fail; 1497 m->m_pkthdr.ph_ifidx = 0; 1498 m->m_len = 0; 1499 maxlen = m_trailingspace(m); 1500 maxlen = min(IPV6_MMTU, maxlen); 1501 /* just for safety */ 1502 if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 1503 ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) { 1504 goto fail; 1505 } 1506 1507 { 1508 /* get ip6 linklocal address for ifp(my outgoing interface). */ 1509 struct in6_ifaddr *ia6; 1510 if ((ia6 = in6ifa_ifpforlinklocal(ifp, IN6_IFF_TENTATIVE| 1511 IN6_IFF_DUPLICATED|IN6_IFF_ANYCAST)) == NULL) 1512 goto fail; 1513 ifp_ll6 = &ia6->ia_addr.sin6_addr; 1514 } 1515 1516 /* get ip6 linklocal address for the router. */ 1517 if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) { 1518 struct sockaddr_in6 *sin6; 1519 sin6 = satosin6(rt->rt_gateway); 1520 nexthop = &sin6->sin6_addr; 1521 if (!IN6_IS_ADDR_LINKLOCAL(nexthop)) 1522 nexthop = NULL; 1523 } else 1524 nexthop = NULL; 1525 1526 /* ip6 */ 1527 ip6 = mtod(m, struct ip6_hdr *); 1528 ip6->ip6_flow = 0; 1529 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 1530 ip6->ip6_vfc |= IPV6_VERSION; 1531 /* ip6->ip6_plen will be set later */ 1532 ip6->ip6_nxt = IPPROTO_ICMPV6; 1533 ip6->ip6_hlim = 255; 1534 /* ip6->ip6_src must be linklocal addr for my outgoing if. */ 1535 bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr)); 1536 bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr)); 1537 1538 /* ND Redirect */ 1539 nd_rd = (struct nd_redirect *)(ip6 + 1); 1540 nd_rd->nd_rd_type = ND_REDIRECT; 1541 nd_rd->nd_rd_code = 0; 1542 nd_rd->nd_rd_reserved = 0; 1543 if (rt->rt_flags & RTF_GATEWAY) { 1544 /* 1545 * nd_rd->nd_rd_target must be a link-local address in 1546 * better router cases. 1547 */ 1548 if (!nexthop) 1549 goto fail; 1550 bcopy(nexthop, &nd_rd->nd_rd_target, 1551 sizeof(nd_rd->nd_rd_target)); 1552 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 1553 sizeof(nd_rd->nd_rd_dst)); 1554 } else { 1555 /* make sure redtgt == reddst */ 1556 nexthop = &sip6->ip6_dst; 1557 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target, 1558 sizeof(nd_rd->nd_rd_target)); 1559 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 1560 sizeof(nd_rd->nd_rd_dst)); 1561 } 1562 1563 p = (u_char *)(nd_rd + 1); 1564 1565 { 1566 /* target lladdr option */ 1567 struct rtentry *nrt; 1568 int len; 1569 struct sockaddr_dl *sdl; 1570 struct nd_opt_hdr *nd_opt; 1571 char *lladdr; 1572 1573 len = sizeof(*nd_opt) + ifp->if_addrlen; 1574 len = (len + 7) & ~7; /* round by 8 */ 1575 /* safety check */ 1576 if (len + (p - (u_char *)ip6) > maxlen) 1577 goto nolladdropt; 1578 nrt = nd6_lookup(nexthop, 0, ifp, ifp->if_rdomain); 1579 if ((nrt != NULL) && 1580 (nrt->rt_flags & (RTF_GATEWAY|RTF_LLINFO)) == RTF_LLINFO && 1581 (nrt->rt_gateway->sa_family == AF_LINK) && 1582 (sdl = satosdl(nrt->rt_gateway)) && 1583 sdl->sdl_alen) { 1584 nd_opt = (struct nd_opt_hdr *)p; 1585 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; 1586 nd_opt->nd_opt_len = len >> 3; 1587 lladdr = (char *)(nd_opt + 1); 1588 bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen); 1589 p += len; 1590 } 1591 rtfree(nrt); 1592 } 1593 nolladdropt:; 1594 1595 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 1596 1597 /* just to be safe */ 1598 if (p - (u_char *)ip6 > maxlen) 1599 goto noredhdropt; 1600 1601 { 1602 /* redirected header option */ 1603 int len; 1604 struct nd_opt_rd_hdr *nd_opt_rh; 1605 1606 /* 1607 * compute the maximum size for icmp6 redirect header option. 1608 * XXX room for auth header? 1609 */ 1610 len = maxlen - (p - (u_char *)ip6); 1611 len &= ~7; 1612 1613 /* 1614 * Redirected header option spec (RFC2461 4.6.3) talks nothing 1615 * about padding/truncate rule for the original IP packet. 1616 * From the discussion on IPv6imp in Feb 1999, 1617 * the consensus was: 1618 * - "attach as much as possible" is the goal 1619 * - pad if not aligned (original size can be guessed by 1620 * original ip6 header) 1621 * Following code adds the padding if it is simple enough, 1622 * and truncates if not. 1623 */ 1624 if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) { 1625 /* not enough room, truncate */ 1626 m_adj(m0, (len - sizeof(*nd_opt_rh)) - 1627 m0->m_pkthdr.len); 1628 } else { 1629 /* 1630 * enough room, truncate if not aligned. 1631 * we don't pad here for simplicity. 1632 */ 1633 size_t extra; 1634 1635 extra = m0->m_pkthdr.len % 8; 1636 if (extra) { 1637 /* truncate */ 1638 m_adj(m0, -extra); 1639 } 1640 len = m0->m_pkthdr.len + sizeof(*nd_opt_rh); 1641 } 1642 1643 nd_opt_rh = (struct nd_opt_rd_hdr *)p; 1644 bzero(nd_opt_rh, sizeof(*nd_opt_rh)); 1645 nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER; 1646 nd_opt_rh->nd_opt_rh_len = len >> 3; 1647 p += sizeof(*nd_opt_rh); 1648 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 1649 1650 /* connect m0 to m */ 1651 m->m_pkthdr.len += m0->m_pkthdr.len; 1652 m_cat(m, m0); 1653 m0 = NULL; 1654 } 1655 noredhdropt: 1656 m_freem(m0); 1657 m0 = NULL; 1658 1659 sip6 = mtod(m, struct ip6_hdr *); 1660 if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src)) 1661 sip6->ip6_src.s6_addr16[1] = 0; 1662 if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst)) 1663 sip6->ip6_dst.s6_addr16[1] = 0; 1664 #if 0 1665 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) 1666 ip6->ip6_src.s6_addr16[1] = 0; 1667 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) 1668 ip6->ip6_dst.s6_addr16[1] = 0; 1669 #endif 1670 if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target)) 1671 nd_rd->nd_rd_target.s6_addr16[1] = 0; 1672 if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst)) 1673 nd_rd->nd_rd_dst.s6_addr16[1] = 0; 1674 1675 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 1676 1677 nd_rd->nd_rd_cksum = 0; 1678 m->m_pkthdr.csum_flags = M_ICMP_CSUM_OUT; 1679 1680 /* send the packet to outside... */ 1681 ip6_output(m, NULL, NULL, 0, NULL, NULL); 1682 1683 icmp6stat_inc(icp6s_outhist + ND_REDIRECT); 1684 1685 if_put(ifp); 1686 return; 1687 1688 fail: 1689 if_put(ifp); 1690 m_freem(m); 1691 m_freem(m0); 1692 } 1693 1694 /* 1695 * ICMPv6 socket option processing. 1696 */ 1697 int 1698 icmp6_ctloutput(int op, struct socket *so, int level, int optname, 1699 struct mbuf *m) 1700 { 1701 int error = 0; 1702 struct inpcb *in6p = sotoinpcb(so); 1703 1704 if (level != IPPROTO_ICMPV6) 1705 return EINVAL; 1706 1707 switch (op) { 1708 case PRCO_SETOPT: 1709 switch (optname) { 1710 case ICMP6_FILTER: 1711 { 1712 struct icmp6_filter *p; 1713 1714 if (m == NULL || m->m_len != sizeof(*p)) { 1715 error = EMSGSIZE; 1716 break; 1717 } 1718 p = mtod(m, struct icmp6_filter *); 1719 if (!p || !in6p->inp_icmp6filt) { 1720 error = EINVAL; 1721 break; 1722 } 1723 bcopy(p, in6p->inp_icmp6filt, 1724 sizeof(struct icmp6_filter)); 1725 error = 0; 1726 break; 1727 } 1728 1729 default: 1730 error = ENOPROTOOPT; 1731 break; 1732 } 1733 break; 1734 1735 case PRCO_GETOPT: 1736 switch (optname) { 1737 case ICMP6_FILTER: 1738 { 1739 struct icmp6_filter *p; 1740 1741 if (!in6p->inp_icmp6filt) { 1742 error = EINVAL; 1743 break; 1744 } 1745 m->m_len = sizeof(struct icmp6_filter); 1746 p = mtod(m, struct icmp6_filter *); 1747 bcopy(in6p->inp_icmp6filt, p, 1748 sizeof(struct icmp6_filter)); 1749 error = 0; 1750 break; 1751 } 1752 1753 default: 1754 error = ENOPROTOOPT; 1755 break; 1756 } 1757 break; 1758 } 1759 1760 return (error); 1761 } 1762 1763 /* 1764 * Perform rate limit check. 1765 * Returns 0 if it is okay to send the icmp6 packet. 1766 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate 1767 * limitation. 1768 * 1769 * XXX per-destination/type check necessary? 1770 * 1771 * dst - not used at this moment 1772 * type - not used at this moment 1773 * code - not used at this moment 1774 */ 1775 int 1776 icmp6_ratelimit(const struct in6_addr *dst, const int type, const int code) 1777 { 1778 /* PPS limit */ 1779 if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count, 1780 icmp6errppslim)) 1781 return 1; /* The packet is subject to rate limit */ 1782 return 0; /* okay to send */ 1783 } 1784 1785 struct rtentry * 1786 icmp6_mtudisc_clone(struct sockaddr *dst, u_int rtableid) 1787 { 1788 struct rtentry *rt; 1789 int error; 1790 1791 rt = rtalloc(dst, RT_RESOLVE, rtableid); 1792 1793 /* Check if the route is actually usable */ 1794 if (!rtisvalid(rt) || (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE))) 1795 goto bad; 1796 1797 /* 1798 * No PMTU for local routes and permanent neighbors, 1799 * ARP and NDP use the same expire timer as the route. 1800 */ 1801 if (ISSET(rt->rt_flags, RTF_LOCAL) || 1802 (ISSET(rt->rt_flags, RTF_LLINFO) && rt->rt_expire == 0)) 1803 goto bad; 1804 1805 /* If we didn't get a host route, allocate one */ 1806 if ((rt->rt_flags & RTF_HOST) == 0) { 1807 struct rtentry *nrt; 1808 struct rt_addrinfo info; 1809 struct sockaddr_rtlabel sa_rl; 1810 1811 memset(&info, 0, sizeof(info)); 1812 info.rti_ifa = rt->rt_ifa; 1813 info.rti_flags = RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC; 1814 info.rti_info[RTAX_DST] = dst; 1815 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1816 info.rti_info[RTAX_LABEL] = 1817 rtlabel_id2sa(rt->rt_labelid, &sa_rl); 1818 1819 error = rtrequest(RTM_ADD, &info, rt->rt_priority, &nrt, 1820 rtableid); 1821 if (error) 1822 goto bad; 1823 nrt->rt_rmx = rt->rt_rmx; 1824 rtfree(rt); 1825 rt = nrt; 1826 rtm_send(rt, RTM_ADD, 0, rtableid); 1827 } 1828 error = rt_timer_add(rt, icmp6_mtudisc_timeout, icmp6_mtudisc_timeout_q, 1829 rtableid); 1830 if (error) 1831 goto bad; 1832 1833 return (rt); 1834 bad: 1835 rtfree(rt); 1836 return (NULL); 1837 } 1838 1839 void 1840 icmp6_mtudisc_timeout(struct rtentry *rt, struct rttimer *r) 1841 { 1842 struct ifnet *ifp; 1843 1844 NET_ASSERT_LOCKED(); 1845 1846 ifp = if_get(rt->rt_ifidx); 1847 if (ifp == NULL) 1848 return; 1849 1850 if ((rt->rt_flags & (RTF_DYNAMIC|RTF_HOST)) == (RTF_DYNAMIC|RTF_HOST)) { 1851 rtdeletemsg(rt, ifp, r->rtt_tableid); 1852 } else { 1853 if (!(rt->rt_locks & RTV_MTU)) 1854 rt->rt_mtu = 0; 1855 } 1856 1857 if_put(ifp); 1858 } 1859 1860 void 1861 icmp6_redirect_timeout(struct rtentry *rt, struct rttimer *r) 1862 { 1863 struct ifnet *ifp; 1864 1865 NET_ASSERT_LOCKED(); 1866 1867 ifp = if_get(rt->rt_ifidx); 1868 if (ifp == NULL) 1869 return; 1870 1871 if ((rt->rt_flags & (RTF_DYNAMIC|RTF_HOST)) == (RTF_DYNAMIC|RTF_HOST)) { 1872 rtdeletemsg(rt, ifp, r->rtt_tableid); 1873 } 1874 1875 if_put(ifp); 1876 } 1877 1878 int *icmpv6ctl_vars[ICMPV6CTL_MAXID] = ICMPV6CTL_VARS; 1879 1880 int 1881 icmp6_sysctl_icmp6stat(void *oldp, size_t *oldlenp, void *newp) 1882 { 1883 struct icmp6stat *icmp6stat; 1884 int ret; 1885 1886 CTASSERT(sizeof(*icmp6stat) == icp6s_ncounters * sizeof(uint64_t)); 1887 icmp6stat = malloc(sizeof(*icmp6stat), M_TEMP, M_WAITOK|M_ZERO); 1888 counters_read(icmp6counters, (uint64_t *)icmp6stat, icp6s_ncounters); 1889 ret = sysctl_rdstruct(oldp, oldlenp, newp, 1890 icmp6stat, sizeof(*icmp6stat)); 1891 free(icmp6stat, M_TEMP, sizeof(*icmp6stat)); 1892 1893 return (ret); 1894 } 1895 1896 int 1897 icmp6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 1898 void *newp, size_t newlen) 1899 { 1900 int error; 1901 1902 /* All sysctl names at this level are terminal. */ 1903 if (namelen != 1) 1904 return ENOTDIR; 1905 1906 switch (name[0]) { 1907 1908 case ICMPV6CTL_STATS: 1909 return icmp6_sysctl_icmp6stat(oldp, oldlenp, newp); 1910 default: 1911 NET_LOCK(); 1912 error = sysctl_int_arr(icmpv6ctl_vars, nitems(icmpv6ctl_vars), 1913 name, namelen, oldp, oldlenp, newp, newlen); 1914 NET_UNLOCK(); 1915 return (error); 1916 } 1917 /* NOTREACHED */ 1918 } 1919