1 /* $NetBSD: icmp6.c,v 1.11 1999/10/01 10:16:16 itojun Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1982, 1986, 1988, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 65 */ 66 67 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__) 68 #include "opt_inet.h" 69 #ifdef __NetBSD__ /*XXX*/ 70 #include "opt_ipsec.h" 71 #endif 72 #endif 73 74 #include <sys/param.h> 75 #include <sys/systm.h> 76 #include <sys/malloc.h> 77 #include <sys/mbuf.h> 78 #include <sys/protosw.h> 79 #include <sys/socket.h> 80 #include <sys/socketvar.h> 81 #include <sys/time.h> 82 #include <sys/kernel.h> 83 #include <sys/syslog.h> 84 85 #include <net/if.h> 86 #include <net/route.h> 87 #include <net/if_dl.h> 88 #include <net/if_types.h> 89 90 #include <netinet/in.h> 91 #include <netinet/in_var.h> 92 #include <netinet6/ip6.h> 93 #include <netinet6/ip6_var.h> 94 #include <netinet6/icmp6.h> 95 #include <netinet6/mld6_var.h> 96 #if !defined(__FreeBSD__) || __FreeBSD__ < 3 97 #include <netinet6/in6_pcb.h> 98 #else 99 #include <netinet/in_pcb.h> 100 #endif 101 #include <netinet6/nd6.h> 102 #include <netinet6/in6_ifattach.h> 103 #include <netinet6/ip6protosw.h> 104 105 #ifdef IPSEC 106 #include <netkey/key.h> 107 #include <netkey/key_debug.h> 108 #endif 109 110 #include "faith.h" 111 112 extern struct ip6protosw inet6sw[]; 113 extern u_char ip6_protox[]; 114 115 struct icmp6stat icmp6stat; 116 117 #if !defined(__FreeBSD__) || __FreeBSD__ < 3 118 extern struct in6pcb rawin6pcb; 119 #else 120 extern struct inpcbhead ripcb; 121 #endif 122 extern u_int icmp6errratelim; 123 #ifdef __NetBSD__ 124 static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL; 125 extern int pmtu_expire; 126 #endif 127 128 static int icmp6_rip6_input __P((struct mbuf **, int)); 129 static int icmp6_ratelimit __P((const struct in6_addr *, const int, const int)); 130 static void icmp6_redirect_diag __P((int, struct in6_addr *, struct in6_addr *, 131 struct in6_addr *)); 132 static struct mbuf * ni6_input __P((struct mbuf *, int)); 133 static int ni6_addrs __P((struct icmp6_nodeinfo *, struct mbuf *, 134 struct ifnet **)); 135 static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo *, 136 struct ifnet *, int)); 137 #ifdef __NetBSD__ 138 static struct rtentry *icmp6_mtudisc_clone __P((struct sockaddr *)); 139 static void icmp6_mtudisc_timeout __P((struct rtentry *, struct rttimer *)); 140 #endif 141 142 #ifdef COMPAT_RFC1885 143 static struct route_in6 icmp6_reflect_rt; 144 #endif 145 static struct timeval icmp6_nextsend = {0, 0}; 146 147 void 148 icmp6_init() 149 { 150 mld6_init(); 151 #ifdef __NetBSD__ 152 icmp6_mtudisc_timeout_q = rt_timer_queue_create(pmtu_expire); 153 #endif 154 } 155 156 /* 157 * Generate an error packet of type error in response to bad IP6 packet. 158 */ 159 void 160 icmp6_error(m, type, code, param) 161 struct mbuf *m; 162 int type, code, param; 163 { 164 struct ip6_hdr *oip6, *nip6; 165 struct icmp6_hdr *icmp6; 166 u_int prep; 167 int off; 168 u_char nxt; 169 170 icmp6stat.icp6s_error++; 171 172 if (m->m_flags & M_DECRYPTED) 173 goto freeit; 174 175 oip6 = mtod(m, struct ip6_hdr *); 176 177 /* 178 * Multicast destination check. For unrecognized option errors, 179 * this check has already done in ip6_unknown_opt(), so we can 180 * check only for other errors. 181 */ 182 if ((m->m_flags & (M_BCAST|M_MCAST) || 183 IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) && 184 (type != ICMP6_PACKET_TOO_BIG && 185 (type != ICMP6_PARAM_PROB || 186 code != ICMP6_PARAMPROB_OPTION))) 187 goto freeit; 188 189 /* Source address check. XXX: the case of anycast source? */ 190 if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) || 191 IN6_IS_ADDR_MULTICAST(&oip6->ip6_src)) 192 goto freeit; 193 194 /* 195 * If the erroneous packet is also an ICMP error, discard it. 196 */ 197 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), ); 198 off = sizeof(struct ip6_hdr); 199 nxt = oip6->ip6_nxt; 200 while(1) { /* XXX: should avoid inf. loop explicitly? */ 201 struct ip6_ext *ip6e; 202 struct icmp6_hdr *icp; 203 204 switch(nxt) { 205 case IPPROTO_IPV6: 206 case IPPROTO_IPV4: 207 case IPPROTO_UDP: 208 case IPPROTO_TCP: 209 case IPPROTO_ESP: 210 case IPPROTO_FRAGMENT: 211 /* 212 * ICMPv6 error must not be fragmented. 213 * XXX: but can we trust the sender? 214 */ 215 default: 216 /* What if unknown header followed by ICMP error? */ 217 goto generate; 218 case IPPROTO_ICMPV6: 219 IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), ); 220 icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off); 221 if (icp->icmp6_type < ICMP6_ECHO_REQUEST 222 || icp->icmp6_type == ND_REDIRECT) { 223 /* 224 * ICMPv6 error 225 * Special case: for redirect (which is 226 * informational) we must not send icmp6 error. 227 */ 228 icmp6stat.icp6s_canterror++; 229 goto freeit; 230 } else { 231 /* ICMPv6 informational */ 232 goto generate; 233 } 234 case IPPROTO_HOPOPTS: 235 case IPPROTO_DSTOPTS: 236 case IPPROTO_ROUTING: 237 case IPPROTO_AH: 238 IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct ip6_ext), ); 239 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off); 240 if (nxt == IPPROTO_AH) 241 off += (ip6e->ip6e_len + 2) << 2; 242 else 243 off += (ip6e->ip6e_len + 1) << 3; 244 nxt = ip6e->ip6e_nxt; 245 break; 246 } 247 } 248 249 freeit: 250 /* 251 * If we can't tell wheter or not we can generate ICMP6, free it. 252 */ 253 m_freem(m); 254 return; 255 256 generate: 257 oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */ 258 259 /* Finally, do rate limitation check. */ 260 if (icmp6_ratelimit(&oip6->ip6_src, type, code)) { 261 icmp6stat.icp6s_toofreq++; 262 goto freeit; 263 } 264 265 /* 266 * OK, ICMP6 can be generated. 267 */ 268 269 if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN) 270 m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len); 271 272 prep = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 273 M_PREPEND(m, prep, M_DONTWAIT); 274 if (m && m->m_len < prep) 275 m = m_pullup(m, prep); 276 if (m == NULL) { 277 printf("ENOBUFS in icmp6_error %d\n", __LINE__); 278 return; 279 } 280 281 nip6 = mtod(m, struct ip6_hdr *); 282 nip6->ip6_src = oip6->ip6_src; 283 nip6->ip6_dst = oip6->ip6_dst; 284 285 if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src)) 286 oip6->ip6_src.s6_addr16[1] = 0; 287 if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst)) 288 oip6->ip6_dst.s6_addr16[1] = 0; 289 290 icmp6 = (struct icmp6_hdr *)(nip6 + 1); 291 icmp6->icmp6_type = type; 292 icmp6->icmp6_code = code; 293 icmp6->icmp6_pptr = htonl((u_int32_t)param); 294 295 icmp6stat.icp6s_outhist[type]++; 296 icmp6_reflect(m, sizeof(struct ip6_hdr)); /*header order: IPv6 - ICMPv6*/ 297 } 298 299 /* 300 * Process a received ICMP6 message. 301 */ 302 int 303 icmp6_input(mp, offp, proto) 304 struct mbuf **mp; 305 int *offp, proto; 306 { 307 struct mbuf *m = *mp, *n; 308 struct ip6_hdr *ip6, *nip6; 309 struct icmp6_hdr *icmp6, *nicmp6; 310 int off = *offp; 311 int icmp6len = m->m_pkthdr.len - *offp; 312 int code, sum, noff; 313 struct sockaddr_in6 icmp6src; 314 315 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), IPPROTO_DONE); 316 /* m might change if M_LOOP. So, call mtod after this */ 317 318 /* 319 * Locate icmp6 structure in mbuf, and check 320 * that not corrupted and of at least minimum length 321 */ 322 323 ip6 = mtod(m, struct ip6_hdr *); 324 if (icmp6len < sizeof(struct icmp6_hdr)) { 325 icmp6stat.icp6s_tooshort++; 326 goto freeit; 327 } 328 329 /* 330 * calculate the checksum 331 */ 332 333 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off); 334 code = icmp6->icmp6_code; 335 336 if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) { 337 log(LOG_ERR, 338 "ICMP6 checksum error(%d|%x) %s\n", 339 icmp6->icmp6_type, 340 sum, 341 ip6_sprintf(&ip6->ip6_src)); 342 icmp6stat.icp6s_checksum++; 343 goto freeit; 344 } 345 346 #if defined(NFAITH) && 0 < NFAITH 347 if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) { 348 /* 349 * Deliver very specific ICMP6 type only. 350 * This is important to deilver TOOBIG. Otherwise PMTUD 351 * will not work. 352 */ 353 switch (icmp6->icmp6_type) { 354 case ICMP6_DST_UNREACH: 355 case ICMP6_PACKET_TOO_BIG: 356 case ICMP6_TIME_EXCEEDED: 357 break; 358 default: 359 goto freeit; 360 } 361 } 362 #endif 363 364 #ifdef IPSEC 365 /* drop it if it does not match the default policy */ 366 if (ipsec6_in_reject(m, NULL)) { 367 ipsecstat.in_polvio++; 368 goto freeit; 369 } 370 #endif 371 372 icmp6stat.icp6s_inhist[icmp6->icmp6_type]++; 373 374 switch (icmp6->icmp6_type) { 375 376 case ICMP6_DST_UNREACH: 377 switch (code) { 378 case ICMP6_DST_UNREACH_NOROUTE: 379 code = PRC_UNREACH_NET; 380 break; 381 case ICMP6_DST_UNREACH_ADMIN: 382 case ICMP6_DST_UNREACH_ADDR: 383 code = PRC_UNREACH_HOST; 384 break; 385 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 386 code = PRC_UNREACH_SRCFAIL; 387 break; 388 case ICMP6_DST_UNREACH_NOPORT: 389 code = PRC_UNREACH_PORT; 390 break; 391 default: 392 goto badcode; 393 } 394 goto deliver; 395 break; 396 397 case ICMP6_PACKET_TOO_BIG: 398 if (code != 0) 399 goto badcode; 400 { 401 u_int mtu = ntohl(icmp6->icmp6_mtu); 402 struct rtentry *rt; 403 struct sockaddr_in6 sin6; 404 #ifdef __bsdi__ 405 struct route_in6 ro6; 406 #endif 407 408 code = PRC_MSGSIZE; 409 bzero(&sin6, sizeof(sin6)); 410 sin6.sin6_family = PF_INET6; 411 sin6.sin6_len = sizeof(struct sockaddr_in6); 412 sin6.sin6_addr = ((struct ip6_hdr *)(icmp6 + 1))->ip6_dst; 413 #ifdef __NetBSD__ 414 rt = rtalloc1((struct sockaddr *)&sin6, 1); /*clone*/ 415 if (!rt || (rt->rt_flags & RTF_HOST) == 0) { 416 if (rt) 417 RTFREE(rt); 418 rt = icmp6_mtudisc_clone((struct sockaddr *)&sin6); 419 } 420 #endif 421 #ifdef __FreeBSD__ 422 rt = rtalloc1((struct sockaddr *)&sin6, 0, 423 RTF_CLONING | RTF_PRCLONING); 424 #endif /*__FreeBSD__*/ 425 #ifdef __bsdi__ 426 bcopy(&sin6, &ro6.ro_dst, sizeof(struct sockaddr_in6)); 427 ro6.ro_rt = 0; 428 rtcalloc((struct route *)&ro6); 429 rt = ro6.ro_rt; 430 #endif /*__bsdi__*/ 431 432 if (rt && (rt->rt_flags & RTF_HOST) 433 && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { 434 if (mtu < IPV6_MMTU) { 435 /* xxx */ 436 rt->rt_rmx.rmx_locks |= RTV_MTU; 437 } else if (mtu < rt->rt_ifp->if_mtu && 438 rt->rt_rmx.rmx_mtu > mtu) { 439 rt->rt_rmx.rmx_mtu = mtu; 440 } 441 } 442 if (rt) 443 RTFREE(rt); 444 445 goto deliver; 446 } 447 break; 448 449 case ICMP6_TIME_EXCEEDED: 450 switch (code) { 451 case ICMP6_TIME_EXCEED_TRANSIT: 452 case ICMP6_TIME_EXCEED_REASSEMBLY: 453 code += PRC_TIMXCEED_INTRANS; 454 break; 455 default: 456 goto badcode; 457 } 458 goto deliver; 459 break; 460 461 case ICMP6_PARAM_PROB: 462 switch (code) { 463 case ICMP6_PARAMPROB_NEXTHEADER: 464 code = PRC_UNREACH_PROTOCOL; 465 break; 466 case ICMP6_PARAMPROB_HEADER: 467 case ICMP6_PARAMPROB_OPTION: 468 code = PRC_PARAMPROB; 469 break; 470 default: 471 goto badcode; 472 } 473 goto deliver; 474 break; 475 476 case ICMP6_ECHO_REQUEST: 477 if (code != 0) 478 goto badcode; 479 if ((n = m_copy(m, 0, M_COPYALL)) == NULL) { 480 /* Give up remote */ 481 break; 482 } 483 if (n->m_flags & M_EXT) { 484 int gap, move; 485 struct mbuf *n0 = n; 486 487 /* 488 * Prepare an internal mbuf. m_pullup() doesn't 489 * always copy the length we specified. 490 */ 491 MGETHDR(n, M_DONTWAIT, n0->m_type); 492 if (n == NULL) { 493 /* Give up remote */ 494 m_freem(n0); 495 break; 496 } 497 M_COPY_PKTHDR(n, n0); 498 n0->m_flags &= ~M_PKTHDR; 499 n->m_next = n0; 500 /* 501 * Copy IPv6 and ICMPv6 only. 502 */ 503 nip6 = mtod(n, struct ip6_hdr *); 504 bcopy(ip6, nip6, sizeof(struct ip6_hdr)); 505 nicmp6 = (struct icmp6_hdr *)(nip6 + 1); 506 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); 507 /* 508 * Adjust mbuf. ip6_plen will be adjusted. 509 */ 510 noff = sizeof(struct ip6_hdr); 511 n->m_len = noff + sizeof(struct icmp6_hdr); 512 move = off + sizeof(struct icmp6_hdr); 513 n0->m_len -= move; 514 n0->m_data += move; 515 gap = off - noff; 516 n->m_pkthdr.len -= gap; 517 } else { 518 nip6 = mtod(n, struct ip6_hdr *); 519 nicmp6 = (struct icmp6_hdr *)((caddr_t)nip6 + off); 520 noff = off; 521 } 522 nicmp6->icmp6_type = ICMP6_ECHO_REPLY; 523 nicmp6->icmp6_code = 0; 524 if (n) { 525 icmp6stat.icp6s_reflect++; 526 icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++; 527 icmp6_reflect(n, noff); 528 } 529 break; 530 531 case ICMP6_ECHO_REPLY: 532 if (code != 0) 533 goto badcode; 534 break; 535 536 case MLD6_LISTENER_QUERY: 537 case MLD6_LISTENER_REPORT: 538 if (icmp6len < sizeof(struct mld6_hdr)) 539 goto badlen; 540 IP6_EXTHDR_CHECK(m, off, icmp6len, IPPROTO_DONE); 541 mld6_input(m, off); 542 /* m stays. */ 543 break; 544 545 case MLD6_LISTENER_DONE: 546 if (icmp6len < sizeof(struct mld6_hdr)) 547 goto badlen; 548 break; /* nothing to be done in kernel */ 549 550 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */ 551 { 552 enum { WRU, FQDN } mode; 553 554 if (code != 0) 555 goto badcode; 556 if (icmp6len == sizeof(struct icmp6_hdr) + 4) 557 mode = WRU; 558 else if (icmp6len >= sizeof(struct icmp6_hdr) + 8) /* XXX */ 559 mode = FQDN; 560 else 561 goto badlen; 562 563 #ifdef __FreeBSD__ 564 #define hostnamelen strlen(hostname) 565 #endif 566 if (mode == FQDN) { 567 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo), 568 IPPROTO_DONE); 569 n = ni6_input(m, off); 570 noff = sizeof(struct ip6_hdr); 571 } 572 else { 573 u_char *p; 574 575 MGETHDR(n, M_DONTWAIT, m->m_type); 576 if (n == NULL) { 577 /* Give up remote */ 578 break; 579 } 580 /* 581 * Copy IPv6 and ICMPv6 only. 582 */ 583 nip6 = mtod(n, struct ip6_hdr *); 584 bcopy(ip6, nip6, sizeof(struct ip6_hdr)); 585 nicmp6 = (struct icmp6_hdr *)(nip6 + 1); 586 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); 587 p = (u_char *)(nicmp6 + 1); 588 bzero(p, 4); 589 bcopy(hostname, p + 4, hostnamelen); 590 noff = sizeof(struct ip6_hdr); 591 M_COPY_PKTHDR(n, m); /* just for recvif */ 592 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) + 593 sizeof(struct icmp6_hdr) + 4 + hostnamelen; 594 nicmp6->icmp6_type = ICMP6_WRUREPLY; 595 nicmp6->icmp6_code = 0; 596 } 597 #undef hostnamelen 598 if (n) { 599 icmp6stat.icp6s_reflect++; 600 icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++; 601 icmp6_reflect(n, noff); 602 } 603 break; 604 } 605 606 case ICMP6_WRUREPLY: 607 if (code != 0) 608 goto badcode; 609 break; 610 611 case ND_ROUTER_SOLICIT: 612 if (code != 0) 613 goto badcode; 614 if (icmp6len < sizeof(struct nd_router_solicit)) 615 goto badlen; 616 IP6_EXTHDR_CHECK(m, off, icmp6len, IPPROTO_DONE); 617 nd6_rs_input(m, off, icmp6len); 618 /* m stays. */ 619 break; 620 621 case ND_ROUTER_ADVERT: 622 if (code != 0) 623 goto badcode; 624 if (icmp6len < sizeof(struct nd_router_advert)) 625 goto badlen; 626 IP6_EXTHDR_CHECK(m, off, icmp6len, IPPROTO_DONE); 627 nd6_ra_input(m, off, icmp6len); 628 /* m stays. */ 629 break; 630 631 case ND_NEIGHBOR_SOLICIT: 632 if (code != 0) 633 goto badcode; 634 if (icmp6len < sizeof(struct nd_neighbor_solicit)) 635 goto badlen; 636 IP6_EXTHDR_CHECK(m, off, icmp6len, IPPROTO_DONE); 637 nd6_ns_input(m, off, icmp6len); 638 /* m stays. */ 639 break; 640 641 case ND_NEIGHBOR_ADVERT: 642 if (code != 0) 643 goto badcode; 644 if (icmp6len < sizeof(struct nd_neighbor_advert)) 645 goto badlen; 646 IP6_EXTHDR_CHECK(m, off, icmp6len, IPPROTO_DONE); 647 nd6_na_input(m, off, icmp6len); 648 /* m stays. */ 649 break; 650 651 case ND_REDIRECT: 652 if (code != 0) 653 goto badcode; 654 if (icmp6len < sizeof(struct nd_redirect)) 655 goto badlen; 656 icmp6_redirect_input(m, off); 657 /* m stays. */ 658 break; 659 660 case ICMP6_ROUTER_RENUMBERING: 661 if (code != ICMP6_ROUTER_RENUMBERING_COMMAND && 662 code != ICMP6_ROUTER_RENUMBERING_RESULT) 663 goto badcode; 664 if (icmp6len < sizeof(struct icmp6_router_renum)) 665 goto badlen; 666 break; 667 668 default: 669 printf("icmp6_input: unknown type %d\n", icmp6->icmp6_type); 670 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { 671 /* ICMPv6 error: MUST deliver it by spec... */ 672 code = PRC_NCMDS; 673 /* deliver */ 674 } else { 675 /* ICMPv6 informational: MUST not deliver */ 676 break; 677 } 678 deliver: 679 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) { 680 icmp6stat.icp6s_tooshort++; 681 goto freeit; 682 } 683 IP6_EXTHDR_CHECK(m, off, 684 sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr), 685 IPPROTO_DONE); 686 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off); 687 bzero(&icmp6src, sizeof(icmp6src)); 688 icmp6src.sin6_len = sizeof(struct sockaddr_in6); 689 icmp6src.sin6_family = AF_INET6; 690 icmp6src.sin6_addr = ((struct ip6_hdr *)(icmp6 + 1))->ip6_dst; 691 692 /* Detect the upper level protocol */ 693 { 694 void (*ctlfunc) __P((int, struct sockaddr *, 695 struct ip6_hdr *, 696 struct mbuf *, int)); /* XXX */ 697 struct ip6_hdr *eip6 = (struct ip6_hdr *)(icmp6 + 1); 698 u_int8_t nxt = eip6->ip6_nxt; 699 int eoff = off + sizeof(struct icmp6_hdr) + 700 sizeof(struct ip6_hdr); 701 702 while (1) { /* XXX: should avoid inf. loop explicitly? */ 703 struct ip6_ext *eh; 704 705 switch(nxt) { 706 case IPPROTO_ESP: 707 case IPPROTO_NONE: 708 goto passit; 709 case IPPROTO_HOPOPTS: 710 case IPPROTO_DSTOPTS: 711 case IPPROTO_ROUTING: 712 case IPPROTO_AH: 713 case IPPROTO_FRAGMENT: 714 IP6_EXTHDR_CHECK(m, 0, eoff + 715 sizeof(struct ip6_ext), 716 IPPROTO_DONE); 717 eh = (struct ip6_ext *)(mtod(m, caddr_t) 718 + eoff); 719 if (nxt == IPPROTO_AH) 720 eoff += (eh->ip6e_len + 2) << 2; 721 else if (nxt == IPPROTO_FRAGMENT) 722 eoff += sizeof(struct ip6_frag); 723 else 724 eoff += (eh->ip6e_len + 1) << 3; 725 nxt = eh->ip6e_nxt; 726 break; 727 default: 728 goto notify; 729 } 730 } 731 notify: 732 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off); 733 ctlfunc = (void (*) __P((int, struct sockaddr *, 734 struct ip6_hdr *, 735 struct mbuf *, int))) 736 (inet6sw[ip6_protox[nxt]].pr_ctlinput); 737 if (ctlfunc) 738 (*ctlfunc)(code, (struct sockaddr *)&icmp6src, 739 (struct ip6_hdr *)(icmp6 + 1), 740 m, eoff); 741 } 742 break; 743 744 badcode: 745 icmp6stat.icp6s_badcode++; 746 break; 747 748 badlen: 749 icmp6stat.icp6s_badlen++; 750 break; 751 } 752 753 passit: 754 icmp6_rip6_input(&m, *offp); 755 return IPPROTO_DONE; 756 757 freeit: 758 m_freem(m); 759 return IPPROTO_DONE; 760 } 761 762 /* 763 * Process a Node Information Query 764 */ 765 #ifdef __FreeBSD__ 766 #define hostnamelen strlen(hostname) 767 #endif 768 #ifndef offsetof /* XXX */ 769 #define offsetof(type, member) ((size_t)(&((type *)0)->member)) 770 #endif 771 772 static struct mbuf * 773 ni6_input(m, off) 774 struct mbuf *m; 775 int off; 776 { 777 struct icmp6_nodeinfo *ni6 = 778 (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off), *nni6; 779 struct mbuf *n = NULL; 780 u_int16_t qtype = ntohs(ni6->ni_qtype); 781 int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo); 782 struct ni_reply_fqdn *fqdn; 783 int addrs; /* for NI_QTYPE_NODEADDR */ 784 struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */ 785 786 switch(qtype) { 787 case NI_QTYPE_NOOP: 788 break; /* no reply data */ 789 case NI_QTYPE_SUPTYPES: 790 goto bad; /* xxx: to be implemented */ 791 break; 792 case NI_QTYPE_FQDN: 793 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_name) + 794 hostnamelen; 795 break; 796 case NI_QTYPE_NODEADDR: 797 addrs = ni6_addrs(ni6, m, &ifp); 798 if ((replylen += addrs * sizeof(struct in6_addr)) > MCLBYTES) 799 replylen = MCLBYTES; /* XXX: we'll truncate later */ 800 801 break; 802 default: 803 /* 804 * XXX: We must return a reply with the ICMP6 code 805 * `unknown Qtype' in this case. However we regard the case 806 * as an FQDN query for backward compatibility. 807 * Older versions set a random value to this field, 808 * so it rarely varies in the defined qtypes. 809 * But the mechanism is not reliable... 810 * maybe we should obsolete older versions. 811 */ 812 qtype = NI_QTYPE_FQDN; 813 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_name) + 814 hostnamelen; 815 break; 816 } 817 818 /* allocate a mbuf to reply. */ 819 MGETHDR(n, M_DONTWAIT, m->m_type); 820 if (n == NULL) 821 return(NULL); 822 M_COPY_PKTHDR(n, m); /* just for recvif */ 823 if (replylen > MHLEN) { 824 if (replylen > MCLBYTES) 825 /* 826 * XXX: should we try to allocate more? But MCLBYTES is 827 * probably much larger than IPV6_MMTU... 828 */ 829 goto bad; 830 MCLGET(n, M_DONTWAIT); 831 if ((n->m_flags & M_EXT) == 0) { 832 goto bad; 833 } 834 } 835 n->m_pkthdr.len = n->m_len = replylen; 836 837 /* copy mbuf header and IPv6 + Node Information base headers */ 838 bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr)); 839 nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1); 840 bcopy(mtod(m, caddr_t) + off, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo)); 841 842 /* qtype dependent procedure */ 843 switch (qtype) { 844 case NI_QTYPE_NOOP: 845 nni6->ni_flags = 0; 846 break; 847 case NI_QTYPE_SUPTYPES: 848 goto bad; /* xxx: to be implemented */ 849 break; 850 case NI_QTYPE_FQDN: 851 if (hostnamelen > 255) { /* XXX: rare case, but may happen */ 852 printf("ni6_input: " 853 "hostname length(%d) is too large for reply\n", 854 hostnamelen); 855 goto bad; 856 } 857 fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) + 858 sizeof(struct ip6_hdr) + 859 sizeof(struct icmp6_nodeinfo)); 860 nni6->ni_flags = 0; /* XXX: meaningless TTL */ 861 fqdn->ni_fqdn_ttl = 0; /* ditto. */ 862 fqdn->ni_fqdn_namelen = hostnamelen; 863 bcopy(hostname, &fqdn->ni_fqdn_name[0], hostnamelen); 864 break; 865 case NI_QTYPE_NODEADDR: 866 { 867 int lenlim, copied; 868 869 if (n->m_flags & M_EXT) 870 lenlim = MCLBYTES - sizeof(struct ip6_hdr) - 871 sizeof(struct icmp6_nodeinfo); 872 else 873 lenlim = MHLEN - sizeof(struct ip6_hdr) - 874 sizeof(struct icmp6_nodeinfo); 875 copied = ni6_store_addrs(ni6, nni6, ifp, lenlim); 876 /* XXX: reset mbuf length */ 877 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) + 878 sizeof(struct icmp6_nodeinfo) + copied; 879 break; 880 } 881 default: 882 break; /* XXX impossible! */ 883 } 884 885 nni6->ni_type = ICMP6_NI_REPLY; 886 nni6->ni_code = ICMP6_NI_SUCESS; 887 return(n); 888 889 bad: 890 if (n) 891 m_freem(n); 892 return(NULL); 893 } 894 #undef hostnamelen 895 896 /* 897 * calculate the number of addresses to be returned in the node info reply. 898 */ 899 static int 900 ni6_addrs(ni6, m, ifpp) 901 struct icmp6_nodeinfo *ni6; 902 struct mbuf *m; 903 struct ifnet **ifpp; 904 { 905 register struct ifnet *ifp; 906 register struct in6_ifaddr *ifa6; 907 register struct ifaddr *ifa; 908 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 909 int addrs = 0, addrsofif, iffound = 0; 910 911 #ifdef __NetBSD__ 912 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) 913 #else 914 for (ifp = ifnet; ifp; ifp = ifp->if_next) 915 #endif 916 { 917 addrsofif = 0; 918 #ifdef __NetBSD__ 919 for (ifa = ifp->if_addrlist.tqh_first; ifa; 920 ifa = ifa->ifa_list.tqe_next) 921 #else 922 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 923 #endif 924 { 925 if (ifa->ifa_addr->sa_family != AF_INET6) 926 continue; 927 ifa6 = (struct in6_ifaddr *)ifa; 928 929 if (!(ni6->ni_flags & NI_NODEADDR_FLAG_ALL) && 930 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, 931 &ifa6->ia_addr.sin6_addr)) 932 iffound = 1; 933 934 if (ifa6->ia6_flags & IN6_IFF_ANYCAST) 935 continue; /* we need only unicast addresses */ 936 937 if ((ni6->ni_flags & (NI_NODEADDR_FLAG_LINKLOCAL | 938 NI_NODEADDR_FLAG_SITELOCAL | 939 NI_NODEADDR_FLAG_GLOBAL)) == 0) 940 continue; 941 942 /* What do we have to do about ::1? */ 943 switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) { 944 case IPV6_ADDR_SCOPE_LINKLOCAL: 945 if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL) 946 addrsofif++; 947 break; 948 case IPV6_ADDR_SCOPE_SITELOCAL: 949 if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL) 950 addrsofif++; 951 break; 952 case IPV6_ADDR_SCOPE_GLOBAL: 953 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL) 954 addrsofif++; 955 break; 956 default: 957 continue; 958 } 959 } 960 if (iffound) { 961 *ifpp = ifp; 962 return(addrsofif); 963 } 964 965 addrs += addrsofif; 966 } 967 968 return(addrs); 969 } 970 971 static int 972 ni6_store_addrs(ni6, nni6, ifp0, resid) 973 struct icmp6_nodeinfo *ni6, *nni6; 974 struct ifnet *ifp0; 975 int resid; 976 { 977 #ifdef __NetBSD__ 978 register struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&ifnet); 979 #else 980 register struct ifnet *ifp = ifp0 ? ifp0 : ifnet; 981 #endif 982 register struct in6_ifaddr *ifa6; 983 register struct ifaddr *ifa; 984 int docopy, copied = 0; 985 u_char *cp = (u_char *)(nni6 + 1); 986 987 if (ifp0 == NULL && !(ni6->ni_flags & NI_NODEADDR_FLAG_ALL)) 988 return(0); /* needless to copy */ 989 990 #ifdef __NetBSD__ 991 for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) 992 #else 993 for (; ifp; ifp = ifp->if_next) 994 #endif 995 { 996 #ifdef __NetBSD__ 997 for (ifa = ifp->if_addrlist.tqh_first; ifa; 998 ifa = ifa->ifa_list.tqe_next) 999 #else 1000 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 1001 #endif 1002 { 1003 docopy = 0; 1004 1005 if (ifa->ifa_addr->sa_family != AF_INET6) 1006 continue; 1007 ifa6 = (struct in6_ifaddr *)ifa; 1008 1009 if (ifa6->ia6_flags & IN6_IFF_ANYCAST) 1010 continue; /* we need only unicast addresses */ 1011 1012 /* What do we have to do about ::1? */ 1013 switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) { 1014 case IPV6_ADDR_SCOPE_LINKLOCAL: 1015 if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL) 1016 docopy = 1; 1017 break; 1018 case IPV6_ADDR_SCOPE_SITELOCAL: 1019 if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL) 1020 docopy = 1; 1021 break; 1022 case IPV6_ADDR_SCOPE_GLOBAL: 1023 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL) 1024 docopy = 1; 1025 break; 1026 default: 1027 continue; 1028 } 1029 1030 if (docopy) { 1031 if (resid < sizeof(struct in6_addr)) { 1032 /* 1033 * We give up much more copy. 1034 * Set the truncate flag and return. 1035 */ 1036 nni6->ni_flags |= 1037 NI_NODEADDR_FLAG_TRUNCATE; 1038 return(copied); 1039 } 1040 bcopy(&ifa6->ia_addr.sin6_addr, cp, 1041 sizeof(struct in6_addr)); 1042 /* XXX: KAME link-local hack; remove ifindex */ 1043 if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr)) 1044 ((struct in6_addr *)cp)->s6_addr16[1] = 0; 1045 cp += sizeof(struct in6_addr); 1046 resid -= sizeof(struct in6_addr); 1047 copied += sizeof(struct in6_addr); 1048 } 1049 } 1050 if (ifp0) /* we need search only on the specified IF */ 1051 break; 1052 } 1053 1054 return(copied); 1055 } 1056 1057 /* 1058 * XXX almost dup'ed code with rip6_input. 1059 */ 1060 static int 1061 icmp6_rip6_input(mp, off) 1062 struct mbuf **mp; 1063 int off; 1064 { 1065 struct mbuf *m = *mp; 1066 register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1067 register struct in6pcb *in6p; 1068 struct in6pcb *last = NULL; 1069 struct sockaddr_in6 rip6src; 1070 struct icmp6_hdr *icmp6; 1071 struct mbuf *opts = NULL; 1072 1073 /* this is assumed to be safe. */ 1074 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off); 1075 1076 bzero(&rip6src, sizeof(rip6src)); 1077 rip6src.sin6_len = sizeof(struct sockaddr_in6); 1078 rip6src.sin6_family = AF_INET6; 1079 rip6src.sin6_addr = ip6->ip6_src; 1080 if (IN6_IS_SCOPE_LINKLOCAL(&rip6src.sin6_addr)) 1081 rip6src.sin6_addr.s6_addr16[1] = 0; 1082 if (m->m_pkthdr.rcvif) { 1083 if (IN6_IS_SCOPE_LINKLOCAL(&rip6src.sin6_addr)) 1084 rip6src.sin6_scope_id = m->m_pkthdr.rcvif->if_index; 1085 else 1086 rip6src.sin6_scope_id = 0; 1087 } else 1088 rip6src.sin6_scope_id = 0; 1089 1090 #if !defined(__FreeBSD__) || __FreeBSD__ < 3 1091 for (in6p = rawin6pcb.in6p_next; 1092 in6p != &rawin6pcb; in6p = in6p->in6p_next) 1093 #else 1094 LIST_FOREACH(in6p, &ripcb, inp_list) 1095 #endif 1096 { 1097 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 1098 if ((in6p->inp_vflag & INP_IPV6) == NULL) 1099 continue; 1100 #endif 1101 if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6) 1102 continue; 1103 if (!IN6_IS_ADDR_ANY(&in6p->in6p_laddr) && 1104 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 1105 continue; 1106 if (!IN6_IS_ADDR_ANY(&in6p->in6p_faddr) && 1107 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 1108 continue; 1109 if (in6p->in6p_icmp6filt 1110 && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type, 1111 in6p->in6p_icmp6filt)) 1112 continue; 1113 if (last) { 1114 struct mbuf *n; 1115 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 1116 if (last->in6p_flags & IN6P_CONTROLOPTS) 1117 ip6_savecontrol(last, &opts, ip6, n); 1118 /* strip intermediate headers */ 1119 m_adj(n, off); 1120 if (sbappendaddr(&last->in6p_socket->so_rcv, 1121 (struct sockaddr *)&rip6src, 1122 n, opts) == 0) { 1123 /* should notify about lost packet */ 1124 m_freem(n); 1125 if (opts) 1126 m_freem(opts); 1127 } else 1128 sorwakeup(last->in6p_socket); 1129 opts = NULL; 1130 } 1131 } 1132 last = in6p; 1133 } 1134 if (last) { 1135 if (last->in6p_flags & IN6P_CONTROLOPTS) 1136 ip6_savecontrol(last, &opts, ip6, m); 1137 /* strip intermediate headers */ 1138 m_adj(m, off); 1139 if (sbappendaddr(&last->in6p_socket->so_rcv, 1140 (struct sockaddr *)&rip6src, m, opts) == 0) { 1141 m_freem(m); 1142 if (opts) 1143 m_freem(opts); 1144 } else 1145 sorwakeup(last->in6p_socket); 1146 } else { 1147 m_freem(m); 1148 ip6stat.ip6s_delivered--; 1149 } 1150 return IPPROTO_DONE; 1151 } 1152 1153 /* 1154 * Reflect the ip6 packet back to the source. 1155 * The caller MUST check if the destination is multicast or not. 1156 * This function is usually called with a unicast destination which 1157 * can be safely the source of the reply packet. But some exceptions 1158 * exist(e.g. ECHOREPLY, PATCKET_TOOBIG, "10" in OPTION type). 1159 * ``off'' points to the icmp6 header, counted from the top of the mbuf. 1160 */ 1161 void 1162 icmp6_reflect(m, off) 1163 struct mbuf *m; 1164 size_t off; 1165 { 1166 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1167 struct icmp6_hdr *icmp6; 1168 struct in6_ifaddr *ia; 1169 struct in6_addr t, *src = 0; 1170 int plen = m->m_pkthdr.len - sizeof(struct ip6_hdr); 1171 #ifdef COMPAT_RFC1885 1172 int mtu = IPV6_MMTU; 1173 struct sockaddr_in6 *sin6 = &icmp6_reflect_rt.ro_dst; 1174 #endif 1175 1176 /* 1177 * If there are extra headers between IPv6 and ICMPv6, strip 1178 * off that header first. 1179 */ 1180 if (off != sizeof(struct ip6_hdr)) { 1181 size_t siz; 1182 1183 /* sanity checks */ 1184 if (off < sizeof(struct ip6_hdr)) { 1185 printf("sanity fail: off=%x, sizeof(ip6)=%x in %s:%d\n", 1186 (unsigned int)off, 1187 (unsigned int)sizeof(struct ip6_hdr), 1188 __FILE__, __LINE__); 1189 goto bad; 1190 } 1191 siz = off - sizeof(struct ip6_hdr); 1192 if (plen < siz) { 1193 printf("sanity fail: siz=%x, payloadlen=%x in %s:%d\n", 1194 (unsigned int)siz, plen, __FILE__, __LINE__); 1195 goto bad; 1196 } 1197 IP6_EXTHDR_CHECK(m, 0, off, /*nothing*/); 1198 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), /*nothing*/); 1199 1200 bcopy((caddr_t)ip6, 1201 (caddr_t)(mtod(m, u_char *) + siz), 1202 sizeof(struct ip6_hdr)); 1203 m->m_data += siz; 1204 m->m_len -= siz; 1205 m->m_pkthdr.len -= siz; 1206 ip6 = mtod(m, struct ip6_hdr *); 1207 ip6->ip6_nxt = IPPROTO_ICMPV6; 1208 plen -= siz; 1209 } 1210 1211 icmp6 = (struct icmp6_hdr *)(ip6 + 1); 1212 1213 t = ip6->ip6_dst; 1214 /* 1215 * ip6_input() drops a packet if its src is multicast. 1216 * So, the src is never multicast. 1217 */ 1218 ip6->ip6_dst = ip6->ip6_src; 1219 1220 /* XXX hack for link-local addresses */ 1221 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) 1222 ip6->ip6_dst.s6_addr16[1] = 1223 htons(m->m_pkthdr.rcvif->if_index); 1224 if (IN6_IS_ADDR_LINKLOCAL(&t)) 1225 t.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index); 1226 1227 #ifdef COMPAT_RFC1885 1228 /* 1229 * xxx guess MTU 1230 * RFC 1885 requires that echo reply should be truncated if it 1231 * does not fit in with (return) path MTU, but the description was 1232 * removed in the new spec. 1233 */ 1234 if (icmp6_reflect_rt.ro_rt == 0 || 1235 ! (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_dst))) { 1236 if (icmp6_reflect_rt.ro_rt) { 1237 #ifdef __FreeBSD__ 1238 RTFREE(icmp6_reflect_rt.ro_rt); 1239 #endif 1240 #ifdef __bsdi__ 1241 rtfree(icmp6_reflect_rt.ro_rt); 1242 #endif 1243 icmp6_reflect_rt.ro_rt = 0; 1244 } 1245 bzero(sin6, sizeof(*sin6)); 1246 sin6->sin6_family = PF_INET6; 1247 sin6->sin6_len = sizeof(struct sockaddr_in6); 1248 sin6->sin6_addr = ip6->ip6_dst; 1249 1250 #ifdef __FreeBSD__ 1251 rtalloc_ign((struct route *)&icmp6_reflect_rt.ro_rt, 1252 RTF_PRCLONING); 1253 #else 1254 rtalloc((struct route *)&icmp6_reflect_rt.ro_rt); 1255 #endif 1256 } 1257 1258 if (icmp6_reflect_rt.ro_rt == 0) 1259 goto bad; 1260 1261 if ((icmp6_reflect_rt.ro_rt->rt_flags & RTF_HOST) 1262 && mtu < icmp6_reflect_rt.ro_rt->rt_ifp->if_mtu) 1263 mtu = icmp6_reflect_rt.ro_rt->rt_rmx.rmx_mtu; 1264 1265 if (mtu < m->m_pkthdr.len) { 1266 plen -= (m->m_pkthdr.len - mtu); 1267 m_adj(m, mtu - m->m_pkthdr.len); 1268 } 1269 #endif 1270 /* 1271 * If the incoming packet was addressed directly to us(i.e. unicast), 1272 * use dst as the src for the reply. 1273 */ 1274 for (ia = in6_ifaddr; ia; ia = ia->ia_next) 1275 if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) && 1276 (ia->ia6_flags & IN6_IFF_ANYCAST) == 0) { 1277 src = &t; 1278 break; 1279 } 1280 if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) && (m->m_flags & M_LOOP)) { 1281 /* 1282 * This is the case if the dst is our link-local address 1283 * and the sender is also ourseleves. 1284 */ 1285 src = &t; 1286 } 1287 1288 if (src == 0) 1289 /* 1290 * We have not multicast routing yet. So this case matches 1291 * to our multicast, our anycast or not to our unicast. 1292 * Select a source address which has the same scope. 1293 */ 1294 if ((ia = in6_ifawithscope(m->m_pkthdr.rcvif, &t)) != 0) 1295 src = &IA6_SIN6(ia)->sin6_addr; 1296 1297 if (src == 0) 1298 goto bad; 1299 1300 ip6->ip6_src = *src; 1301 1302 ip6->ip6_flow = 0; 1303 ip6->ip6_vfc = IPV6_VERSION; 1304 ip6->ip6_nxt = IPPROTO_ICMPV6; 1305 if (m->m_pkthdr.rcvif) { 1306 /* XXX: This may not be the outgoing interface */ 1307 ip6->ip6_hlim = nd_ifinfo[m->m_pkthdr.rcvif->if_index].chlim; 1308 } 1309 1310 icmp6->icmp6_cksum = 0; 1311 icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6, 1312 sizeof(struct ip6_hdr), plen); 1313 1314 /* 1315 * xxx option handling 1316 */ 1317 1318 m->m_flags &= ~(M_BCAST|M_MCAST); 1319 #ifdef IPSEC 1320 m->m_pkthdr.rcvif = NULL; 1321 #endif /*IPSEC*/ 1322 1323 #ifdef COMPAT_RFC1885 1324 ip6_output(m, NULL, &icmp6_reflect_rt, 0, NULL); 1325 #else 1326 ip6_output(m, NULL, NULL, 0, NULL); 1327 #endif 1328 1329 return; 1330 1331 bad: 1332 m_freem(m); 1333 return; 1334 } 1335 1336 void 1337 icmp6_fasttimo() 1338 { 1339 mld6_fasttimeo(); 1340 } 1341 1342 static void 1343 icmp6_redirect_diag(level, src6, dst6, tgt6) 1344 int level; 1345 struct in6_addr *src6; 1346 struct in6_addr *dst6; 1347 struct in6_addr *tgt6; 1348 { 1349 log(level, "ICMP6 redirect: src=%s dst=%s tgt=%s\n", 1350 ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6)); 1351 } 1352 1353 void 1354 icmp6_redirect_input(m, off) 1355 register struct mbuf *m; 1356 int off; 1357 { 1358 struct ifnet *ifp = m->m_pkthdr.rcvif; 1359 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1360 struct nd_redirect *nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off); 1361 int icmp6len = ntohs(ip6->ip6_plen); 1362 char *lladdr = NULL; 1363 int lladdrlen = 0; 1364 u_char *redirhdr = NULL; 1365 int redirhdrlen = 0; 1366 struct rtentry *rt = NULL; 1367 int is_router; 1368 int is_onlink; 1369 struct in6_addr src6 = ip6->ip6_src; 1370 struct in6_addr redtgt6 = nd_rd->nd_rd_target; 1371 struct in6_addr reddst6 = nd_rd->nd_rd_dst; 1372 union nd_opts ndopts; 1373 1374 if (!m || !ifp) 1375 return; 1376 1377 /* XXX if we are router, we don't update route by icmp6 redirect */ 1378 if (ip6_forwarding) 1379 return; 1380 if (!icmp6_rediraccept) 1381 return; 1382 1383 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1384 redtgt6.s6_addr16[1] = htons(ifp->if_index); 1385 if (IN6_IS_ADDR_LINKLOCAL(&reddst6)) 1386 reddst6.s6_addr16[1] = htons(ifp->if_index); 1387 1388 /* validation */ 1389 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) { 1390 log(LOG_ERR, 1391 "ICMP6 redirect sent from %s rejected; " 1392 "must be from linklocal\n", ip6_sprintf(&src6)); 1393 return; 1394 } 1395 if (ip6->ip6_hlim != 255) { 1396 log(LOG_ERR, 1397 "ICMP6 redirect sent from %s rejected; " 1398 "hlim=%d (must be 255)\n", 1399 ip6_sprintf(&src6), ip6->ip6_hlim); 1400 return; 1401 } 1402 { 1403 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */ 1404 struct sockaddr_in6 sin6; 1405 struct in6_addr *gw6; 1406 1407 bzero(&sin6, sizeof(sin6)); 1408 sin6.sin6_family = AF_INET6; 1409 sin6.sin6_len = sizeof(struct sockaddr_in6); 1410 bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6)); 1411 rt = rtalloc1((struct sockaddr *)&sin6, 0 1412 #ifdef __FreeBSD__ 1413 , 0UL 1414 #endif 1415 ); 1416 if (rt) { 1417 gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr); 1418 if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) { 1419 icmp6_redirect_diag(LOG_ERR, &src6, &reddst6, &redtgt6); 1420 log(LOG_ERR, 1421 "ICMP6 redirect sent from %s rejected; " 1422 "not equal to gw for src=%s (must be same)\n", 1423 ip6_sprintf(&src6), ip6_sprintf(gw6)); 1424 RTFREE(rt); 1425 return; 1426 } 1427 } else { 1428 icmp6_redirect_diag(LOG_ERR, &src6, &reddst6, &redtgt6); 1429 log(LOG_ERR, 1430 "ICMP6 redirect sent from %s rejected; " 1431 "no route found for redirect dst\n", 1432 ip6_sprintf(&src6)); 1433 return; 1434 } 1435 RTFREE(rt); 1436 rt = NULL; 1437 } 1438 if (IN6_IS_ADDR_MULTICAST(&reddst6)) { 1439 icmp6_redirect_diag(LOG_ERR, &src6, &reddst6, &redtgt6); 1440 log(LOG_ERR, 1441 "ICMP6 redirect sent from %s rejected; " 1442 "redirect dst must be unicast\n", 1443 ip6_sprintf(&src6)); 1444 return; 1445 } 1446 1447 is_router = is_onlink = 0; 1448 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1449 is_router = 1; /* router case */ 1450 if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) 1451 is_onlink = 1; /* on-link destination case */ 1452 if (!is_router && !is_onlink) { 1453 icmp6_redirect_diag(LOG_ERR, &src6, &reddst6, &redtgt6); 1454 log(LOG_ERR, 1455 "ICMP6 redirect sent from %s rejected; " 1456 "neither router case nor onlink case\n", 1457 ip6_sprintf(&src6)); 1458 return; 1459 } 1460 /* validation passed */ 1461 1462 icmp6len -= sizeof(*nd_rd); 1463 nd6_option_init(nd_rd + 1, icmp6len, &ndopts); 1464 if (nd6_options(&ndopts) < 0) { 1465 icmp6_redirect_diag(LOG_INFO, &src6, &reddst6, &redtgt6); 1466 log(LOG_INFO, "icmp6_redirect_input: " 1467 "invalid ND option, rejected\n"); 1468 return; 1469 } 1470 1471 if (ndopts.nd_opts_tgt_lladdr) { 1472 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); 1473 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; 1474 } 1475 1476 if (ndopts.nd_opts_rh) { 1477 redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len; 1478 redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */ 1479 } 1480 1481 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 1482 icmp6_redirect_diag(LOG_INFO, &src6, &reddst6, &redtgt6); 1483 log(LOG_INFO, 1484 "icmp6_redirect_input: lladdrlen mismatch for %s " 1485 "(if %d, icmp6 packet %d)\n", 1486 ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2); 1487 } 1488 1489 /* RFC 2461 8.3 */ 1490 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, 1491 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); 1492 1493 if (!is_onlink) { /* better router case. perform rtredirect. */ 1494 /* perform rtredirect */ 1495 struct sockaddr_in6 sdst; 1496 struct sockaddr_in6 sgw; 1497 struct sockaddr_in6 ssrc; 1498 #ifdef __bsdi__ 1499 extern int icmp_redirtimeout; /*XXX*/ 1500 #endif 1501 1502 bzero(&sdst, sizeof(sdst)); 1503 bzero(&sgw, sizeof(sgw)); 1504 bzero(&ssrc, sizeof(ssrc)); 1505 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6; 1506 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len = 1507 sizeof(struct sockaddr_in6); 1508 bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr)); 1509 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); 1510 bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr)); 1511 rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw, 1512 (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST, 1513 (struct sockaddr *)&ssrc, 1514 #if defined(__FreeBSD__) || defined(__NetBSD__) 1515 (struct rtentry **)NULL 1516 #elif defined(__bsdi__) 1517 icmp_redirtimeout /*XXX*/ 1518 #endif /*__FreeBSD__, __NetBSD__, __bsdi__*/ 1519 ); 1520 } 1521 /* finally update cached route in each socket via pfctlinput */ 1522 { 1523 struct sockaddr_in6 sdst; 1524 1525 bzero(&sdst, sizeof(sdst)); 1526 sdst.sin6_family = AF_INET6; 1527 sdst.sin6_len = sizeof(struct sockaddr_in6); 1528 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); 1529 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst); 1530 #ifdef IPSEC 1531 key_sa_routechange((struct sockaddr *)&sdst); 1532 #endif 1533 } 1534 } 1535 1536 void 1537 icmp6_redirect_output(m0, rt) 1538 struct mbuf *m0; 1539 struct rtentry *rt; 1540 { 1541 struct ifnet *ifp; /* my outgoing interface */ 1542 struct in6_addr *ifp_ll6; 1543 struct in6_addr *router_ll6; 1544 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */ 1545 struct mbuf *m = NULL; /* newly allocated one */ 1546 struct ip6_hdr *ip6; /* m as struct ip6_hdr */ 1547 struct nd_redirect *nd_rd; 1548 size_t maxlen; 1549 u_char *p; 1550 1551 /* if we are not router, we don't send icmp6 redirect */ 1552 if (!ip6_forwarding || ip6_accept_rtadv) 1553 goto fail; 1554 1555 /* sanity check */ 1556 if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp)) 1557 goto fail; 1558 1559 /* 1560 * Address check: 1561 * the source address must identify a neighbor, and 1562 * the destination address must not be a multicast address 1563 * [RFC 2461, sec 8.2] 1564 */ 1565 sip6 = mtod(m0, struct ip6_hdr *); 1566 if (nd6_is_addr_neighbor(&sip6->ip6_src, ifp) == 0) 1567 goto fail; 1568 if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst)) 1569 goto fail; /* what should we do here? */ 1570 1571 /* rate limit */ 1572 if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0)) 1573 goto fail; 1574 1575 /* 1576 * Since we are going to append up to 1280 bytes (= IPV6_MMTU), 1577 * we almost always ask for an mbuf cluster for simplicity. 1578 * (MHLEN < IPV6_MMTU is almost always true) 1579 */ 1580 MGETHDR(m, M_DONTWAIT, MT_HEADER); 1581 if (!m) 1582 goto fail; 1583 if (MHLEN < IPV6_MMTU) 1584 MCLGET(m, M_DONTWAIT); 1585 maxlen = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN; 1586 maxlen = min(IPV6_MMTU, maxlen); 1587 /* just for safety */ 1588 if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) 1589 goto fail; 1590 1591 { 1592 /* get ip6 linklocal address for ifp(my outgoing interface). */ 1593 struct in6_ifaddr *ia = in6ifa_ifpforlinklocal(ifp); 1594 if (ia == NULL) 1595 goto fail; 1596 ifp_ll6 = &ia->ia_addr.sin6_addr; 1597 } 1598 1599 /* get ip6 linklocal address for the router. */ 1600 if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) { 1601 struct sockaddr_in6 *sin6; 1602 sin6 = (struct sockaddr_in6 *)rt->rt_gateway; 1603 router_ll6 = &sin6->sin6_addr; 1604 if (!IN6_IS_ADDR_LINKLOCAL(router_ll6)) 1605 router_ll6 = (struct in6_addr *)NULL; 1606 } else 1607 router_ll6 = (struct in6_addr *)NULL; 1608 1609 /* ip6 */ 1610 ip6 = mtod(m, struct ip6_hdr *); 1611 ip6->ip6_flow = 0; 1612 ip6->ip6_vfc = IPV6_VERSION; 1613 /* ip6->ip6_plen will be set later */ 1614 ip6->ip6_nxt = IPPROTO_ICMPV6; 1615 ip6->ip6_hlim = 255; 1616 /* ip6->ip6_src must be linklocal addr for my outgoing if. */ 1617 bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr)); 1618 bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr)); 1619 1620 /* ND Redirect */ 1621 nd_rd = (struct nd_redirect *)(ip6 + 1); 1622 nd_rd->nd_rd_type = ND_REDIRECT; 1623 nd_rd->nd_rd_code = 0; 1624 nd_rd->nd_rd_reserved = 0; 1625 if (rt->rt_flags & RTF_GATEWAY) { 1626 /* 1627 * nd_rd->nd_rd_target must be a link-local address in 1628 * better router cases. 1629 */ 1630 if (!router_ll6) 1631 goto fail; 1632 bcopy(router_ll6, &nd_rd->nd_rd_target, 1633 sizeof(nd_rd->nd_rd_target)); 1634 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 1635 sizeof(nd_rd->nd_rd_dst)); 1636 } else { 1637 /* make sure redtgt == reddst */ 1638 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target, 1639 sizeof(nd_rd->nd_rd_target)); 1640 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 1641 sizeof(nd_rd->nd_rd_dst)); 1642 } 1643 1644 p = (u_char *)(nd_rd + 1); 1645 1646 if (!router_ll6) 1647 goto nolladdropt; 1648 1649 { 1650 /* target lladdr option */ 1651 struct rtentry *rt_router = NULL; 1652 int len; 1653 struct sockaddr_dl *sdl; 1654 struct nd_opt_hdr *nd_opt; 1655 char *lladdr; 1656 1657 rt_router = nd6_lookup(router_ll6, 0, ifp); 1658 if (!rt_router) 1659 goto nolladdropt; 1660 if (!(rt_router->rt_flags & RTF_GATEWAY) 1661 && (rt_router->rt_flags & RTF_LLINFO) 1662 && (rt_router->rt_gateway->sa_family == AF_LINK) 1663 && (sdl = (struct sockaddr_dl *)rt_router->rt_gateway)) { 1664 nd_opt = (struct nd_opt_hdr *)p; 1665 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; 1666 len = 2 + ifp->if_addrlen; 1667 len = (len + 7) & ~7; /*round by 8*/ 1668 nd_opt->nd_opt_len = len >> 3; 1669 p += len; 1670 lladdr = (char *)(nd_opt + 1); 1671 bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen); 1672 } 1673 } 1674 nolladdropt:; 1675 1676 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 1677 1678 /* just to be safe */ 1679 if (m0->m_flags & M_DECRYPTED) 1680 goto noredhdropt; 1681 1682 { 1683 /* redirected header option */ 1684 int len; 1685 struct nd_opt_rd_hdr *nd_opt_rh; 1686 1687 /* 1688 * compute the maximum size for icmp6 redirect header option. 1689 * XXX room for auth header? 1690 */ 1691 len = maxlen - (p - (u_char *)ip6); 1692 len &= ~7; 1693 1694 /* This is just for simplicity. */ 1695 if (m0->m_pkthdr.len != m0->m_len) { 1696 if (m0->m_next) { 1697 m_freem(m0->m_next); 1698 m0->m_next = NULL; 1699 } 1700 m0->m_pkthdr.len = m0->m_len; 1701 } 1702 1703 /* 1704 * Redirected header option spec (RFC2461 4.6.3) talks nothing 1705 * about padding/trancate rule for the original IP packet. 1706 * From the discussion on IPv6imp in Feb 1999, the consensus was: 1707 * - "attach as much as possible" is the goal 1708 * - pad if not aligned (original size can be guessed by original 1709 * ip6 header) 1710 * Following code adds the padding if it is simple enough, 1711 * and truncates if not. 1712 */ 1713 if (m0->m_next || m0->m_pkthdr.len != m0->m_len) 1714 panic("assumption failed in %s:%d\n", __FILE__, __LINE__); 1715 1716 if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) { 1717 /* not enough room, truncate */ 1718 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh); 1719 } else { 1720 /* enough room, pad or truncate */ 1721 size_t extra; 1722 1723 extra = m0->m_pkthdr.len % 8; 1724 if (extra) { 1725 /* pad if easy enough, truncate if not */ 1726 if (8 - extra <= M_TRAILINGSPACE(m0)) { 1727 /* pad */ 1728 m0->m_len += (8 - extra); 1729 m0->m_pkthdr.len += (8 - extra); 1730 } else { 1731 /* truncate */ 1732 m0->m_pkthdr.len -= extra; 1733 m0->m_len -= extra; 1734 } 1735 } 1736 len = m0->m_pkthdr.len + sizeof(*nd_opt_rh); 1737 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh); 1738 } 1739 1740 nd_opt_rh = (struct nd_opt_rd_hdr *)p; 1741 bzero(nd_opt_rh, sizeof(*nd_opt_rh)); 1742 nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER; 1743 nd_opt_rh->nd_opt_rh_len = len >> 3; 1744 p += sizeof(*nd_opt_rh); 1745 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 1746 1747 /* connect m0 to m */ 1748 m->m_next = m0; 1749 m->m_pkthdr.len = m->m_len + m0->m_len; 1750 } 1751 noredhdropt:; 1752 1753 if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src)) 1754 sip6->ip6_src.s6_addr16[1] = 0; 1755 if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst)) 1756 sip6->ip6_dst.s6_addr16[1] = 0; 1757 #if 0 1758 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) 1759 ip6->ip6_src.s6_addr16[1] = 0; 1760 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) 1761 ip6->ip6_dst.s6_addr16[1] = 0; 1762 #endif 1763 if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target)) 1764 nd_rd->nd_rd_target.s6_addr16[1] = 0; 1765 if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst)) 1766 nd_rd->nd_rd_dst.s6_addr16[1] = 0; 1767 1768 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 1769 1770 nd_rd->nd_rd_cksum = 0; 1771 nd_rd->nd_rd_cksum 1772 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen)); 1773 1774 /* send the packet to outside... */ 1775 #ifdef IPSEC 1776 m->m_pkthdr.rcvif = NULL; 1777 #endif /*IPSEC*/ 1778 ip6_output(m, NULL, NULL, 0, NULL); 1779 icmp6stat.icp6s_outhist[ND_REDIRECT]++; 1780 1781 return; 1782 1783 fail: 1784 if (m) 1785 m_freem(m); 1786 if (m0) 1787 m_freem(m0); 1788 } 1789 1790 /* 1791 * ICMPv6 socket option processing. 1792 */ 1793 int 1794 icmp6_ctloutput(op, so, level, optname, mp) 1795 int op; 1796 struct socket *so; 1797 int level, optname; 1798 struct mbuf **mp; 1799 { 1800 register struct in6pcb *in6p = sotoin6pcb(so); 1801 register struct mbuf *m = *mp; 1802 int error = 0; 1803 1804 if (level != IPPROTO_ICMPV6) { 1805 error = EINVAL; 1806 if (op == PRCO_SETOPT && m) 1807 (void)m_free(m); 1808 } else switch(op) { 1809 case PRCO_SETOPT: 1810 switch (optname) { 1811 case ICMP6_FILTER: 1812 { 1813 struct icmp6_filter *p; 1814 1815 p = mtod(m, struct icmp6_filter *); 1816 if (!p || !in6p->in6p_icmp6filt) { 1817 error = EINVAL; 1818 break; 1819 } 1820 bcopy(p, in6p->in6p_icmp6filt, 1821 sizeof(struct icmp6_filter)); 1822 error = 0; 1823 break; 1824 } 1825 1826 default: 1827 error = ENOPROTOOPT; 1828 break; 1829 } 1830 if (m) 1831 (void)m_free(m); 1832 break; 1833 1834 case PRCO_GETOPT: 1835 switch (optname) { 1836 case ICMP6_FILTER: 1837 { 1838 struct icmp6_filter *p; 1839 1840 p = mtod(m, struct icmp6_filter *); 1841 if (!p || !in6p->in6p_icmp6filt) { 1842 error = EINVAL; 1843 break; 1844 } 1845 bcopy(in6p->in6p_icmp6filt, p, 1846 sizeof(struct icmp6_filter)); 1847 error = 0; 1848 break; 1849 } 1850 1851 default: 1852 error = ENOPROTOOPT; 1853 break; 1854 } 1855 break; 1856 } 1857 1858 return(error); 1859 } 1860 1861 /* 1862 * Perform rate limit check. 1863 * Returns 0 if it is okay to send the icmp6 packet. 1864 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate 1865 * limitation. 1866 * 1867 * XXX per-destination/type check necessary? 1868 */ 1869 static int 1870 icmp6_ratelimit(dst, type, code) 1871 const struct in6_addr *dst; /* not used at this moment */ 1872 const int type; /* not used at this moment */ 1873 const int code; /* not used at this moment */ 1874 { 1875 struct timeval tp; 1876 long sec_diff, usec_diff; 1877 1878 /* If we are not doing rate limitation, it is always okay to send */ 1879 if (!icmp6errratelim) 1880 return 0; 1881 1882 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 1883 microtime(&tp); 1884 tp.tv_sec = time_second; 1885 #else 1886 tp = time; 1887 #endif 1888 if (tp.tv_sec < icmp6_nextsend.tv_sec 1889 || (tp.tv_sec == icmp6_nextsend.tv_sec 1890 && tp.tv_usec < icmp6_nextsend.tv_usec)) { 1891 /* The packet is subject to rate limit */ 1892 return 1; 1893 } 1894 sec_diff = icmp6errratelim / 1000000; 1895 usec_diff = icmp6errratelim % 1000000; 1896 icmp6_nextsend.tv_sec = tp.tv_sec + sec_diff; 1897 if ((tp.tv_usec = tp.tv_usec + usec_diff) >= 1000000) { 1898 icmp6_nextsend.tv_sec++; 1899 icmp6_nextsend.tv_usec -= 1000000; 1900 } 1901 1902 /* it is okay to send this */ 1903 return 0; 1904 } 1905 1906 #ifdef __NetBSD__ 1907 static struct rtentry * 1908 icmp6_mtudisc_clone(dst) 1909 struct sockaddr *dst; 1910 { 1911 struct rtentry *rt; 1912 int error; 1913 1914 rt = rtalloc1(dst, 1); 1915 if (rt == 0) 1916 return NULL; 1917 1918 /* If we didn't get a host route, allocate one */ 1919 if ((rt->rt_flags & RTF_HOST) == 0) { 1920 struct rtentry *nrt; 1921 1922 error = rtrequest((int) RTM_ADD, dst, 1923 (struct sockaddr *) rt->rt_gateway, 1924 (struct sockaddr *) 0, 1925 RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt); 1926 if (error) { 1927 rtfree(rt); 1928 rtfree(nrt); 1929 return NULL; 1930 } 1931 nrt->rt_rmx = rt->rt_rmx; 1932 rtfree(rt); 1933 rt = nrt; 1934 } 1935 error = rt_timer_add(rt, icmp6_mtudisc_timeout, 1936 icmp6_mtudisc_timeout_q); 1937 if (error) { 1938 rtfree(rt); 1939 return NULL; 1940 } 1941 1942 return rt; /* caller need to call rtfree() */ 1943 } 1944 1945 static void 1946 icmp6_mtudisc_timeout(rt, r) 1947 struct rtentry *rt; 1948 struct rttimer *r; 1949 { 1950 if (rt == NULL) 1951 panic("icmp6_mtudisc_timeout: bad route to timeout"); 1952 if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) == 1953 (RTF_DYNAMIC | RTF_HOST)) { 1954 rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt), 1955 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); 1956 } else { 1957 if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) { 1958 rt->rt_rmx.rmx_mtu = 0; 1959 } 1960 } 1961 } 1962 #endif /*__NetBSD__*/ 1963 1964 #ifdef __bsdi__ 1965 void 1966 icmp6_mtuexpire(rt, rtt) 1967 struct rtentry *rt; 1968 struct rttimer *rtt; 1969 { 1970 rt->rt_flags |= RTF_PROBEMTU; 1971 Free(rtt); 1972 } 1973 1974 int *icmp6_sysvars[] = ICMPV6CTL_VARS; 1975 1976 int 1977 icmp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 1978 int *name; 1979 u_int namelen; 1980 void *oldp; 1981 size_t *oldlenp; 1982 void *newp; 1983 size_t newlen; 1984 { 1985 if (name[0] >= ICMPV6CTL_MAXID) 1986 return (EOPNOTSUPP); 1987 switch (name[0]) { 1988 #if 0 1989 ICMPV6CTL_ND6_PRUNE: 1990 ICMPV6CTL_ND6_DELAY: 1991 ICMPV6CTL_ND6_UMAXTRIES: 1992 ICMPV6CTL_ND6_MMAXTRIES: 1993 ICMPV6CTL_ND6_USELOOPBACK: 1994 ICMPV6CTL_ND6_PROXYALL: 1995 /* need to check the value. */ 1996 #endif 1997 case ICMPV6CTL_STATS: 1998 return sysctl_rdtrunc(oldp, oldlenp, newp, &icmp6stat, 1999 sizeof(icmp6stat)); 2000 2001 default: 2002 return (sysctl_int_arr(icmp6_sysvars, name, namelen, 2003 oldp, oldlenp, newp, newlen)); 2004 } 2005 } 2006 #endif /*__bsdi__*/ 2007 2008 #ifdef __NetBSD__ 2009 #include <vm/vm.h> 2010 #include <sys/sysctl.h> 2011 int 2012 icmp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 2013 int *name; 2014 u_int namelen; 2015 void *oldp; 2016 size_t *oldlenp; 2017 void *newp; 2018 size_t newlen; 2019 { 2020 2021 /* All sysctl names at this level are terminal. */ 2022 if (namelen != 1) 2023 return ENOTDIR; 2024 2025 switch (name[0]) { 2026 2027 case ICMPV6CTL_REDIRACCEPT: 2028 return sysctl_int(oldp, oldlenp, newp, newlen, 2029 &icmp6_rediraccept); 2030 case ICMPV6CTL_REDIRTIMEOUT: 2031 return sysctl_int(oldp, oldlenp, newp, newlen, 2032 &icmp6_redirtimeout); 2033 case ICMPV6CTL_STATS: 2034 return sysctl_rdstruct(oldp, oldlenp, newp, 2035 &icmp6stat, sizeof(icmp6stat)); 2036 case ICMPV6CTL_ERRRATELIMIT: 2037 return sysctl_int(oldp, oldlenp, newp, newlen, 2038 &icmp6errratelim); 2039 case ICMPV6CTL_ND6_PRUNE: 2040 return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_prune); 2041 case ICMPV6CTL_ND6_DELAY: 2042 return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_delay); 2043 case ICMPV6CTL_ND6_UMAXTRIES: 2044 return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_umaxtries); 2045 case ICMPV6CTL_ND6_MMAXTRIES: 2046 return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_mmaxtries); 2047 case ICMPV6CTL_ND6_USELOOPBACK: 2048 return sysctl_int(oldp, oldlenp, newp, newlen, 2049 &nd6_useloopback); 2050 case ICMPV6CTL_ND6_PROXYALL: 2051 return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_proxyall); 2052 default: 2053 return ENOPROTOOPT; 2054 } 2055 /* NOTREACHED */ 2056 } 2057 #endif /* __NetBSD__ */ 2058