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