icmp6.c revision 1.26
1/* $NetBSD: icmp6.c,v 1.26 2000/03/01 12:49:44 itojun Exp $ */ 2/* $KAME: icmp6.c,v 1.71 2000/02/28 09:25:42 jinmei Exp $ */ 3 4/* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33/* 34 * Copyright (c) 1982, 1986, 1988, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Berkeley and its contributors. 49 * 4. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 66 */ 67 68#include "opt_inet.h" 69#include "opt_ipsec.h" 70 71#include <sys/param.h> 72#include <sys/systm.h> 73#include <sys/malloc.h> 74#include <sys/mbuf.h> 75#include <sys/protosw.h> 76#include <sys/socket.h> 77#include <sys/socketvar.h> 78#include <sys/time.h> 79#include <sys/kernel.h> 80#include <sys/syslog.h> 81#include <sys/domain.h> 82 83#include <net/if.h> 84#include <net/route.h> 85#include <net/if_dl.h> 86#include <net/if_types.h> 87 88#include <netinet/in.h> 89#include <netinet/in_var.h> 90#include <netinet/ip6.h> 91#include <netinet6/ip6_var.h> 92#include <netinet/icmp6.h> 93#include <netinet6/mld6_var.h> 94#include <netinet6/in6_pcb.h> 95#include <netinet6/nd6.h> 96#include <netinet6/in6_ifattach.h> 97#include <netinet6/ip6protosw.h> 98 99 100#ifdef IPSEC 101#include <netinet6/ipsec.h> 102#include <netkey/key.h> 103#include <netkey/key_debug.h> 104#endif 105 106#include "faith.h" 107 108#include <net/net_osdep.h> 109 110extern struct domain inet6domain; 111 112struct icmp6stat icmp6stat; 113 114extern struct in6pcb rawin6pcb; 115extern struct timeval icmp6errratelim; 116extern int icmp6_nodeinfo; 117static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL; 118extern int pmtu_expire; 119 120static int icmp6_rip6_input __P((struct mbuf **, int)); 121static void icmp6_mtudisc_update __P((struct in6_addr *, struct icmp6_hdr *, 122 struct mbuf *)); 123static int icmp6_ratelimit __P((const struct in6_addr *, const int, const int)); 124static const char *icmp6_redirect_diag __P((struct in6_addr *, 125 struct in6_addr *, struct in6_addr *)); 126static struct mbuf * ni6_input __P((struct mbuf *, int)); 127static int ni6_addrs __P((struct icmp6_nodeinfo *, struct mbuf *, 128 struct ifnet **)); 129static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo *, 130 struct ifnet *, int)); 131static struct rtentry *icmp6_mtudisc_clone __P((struct sockaddr *)); 132static void icmp6_mtudisc_timeout __P((struct rtentry *, struct rttimer *)); 133 134#ifdef COMPAT_RFC1885 135static struct route_in6 icmp6_reflect_rt; 136#endif 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 if (m->m_flags & M_DECRYPTED) { 162 icmp6stat.icp6s_canterror++; 163 goto freeit; 164 } 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 code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ 415 break; 416 case ICMP6_DST_UNREACH_ADDR: 417 code = PRC_HOSTDEAD; 418 break; 419#ifdef COMPAT_RFC1885 420 case ICMP6_DST_UNREACH_NOTNEIGHBOR: 421 code = PRC_UNREACH_SRCFAIL; 422 break; 423#else 424 case ICMP6_DST_UNREACH_BEYONDSCOPE: 425 /* I mean "source address was incorrect." */ 426 code = PRC_PARAMPROB; 427 break; 428#endif 429 case ICMP6_DST_UNREACH_NOPORT: 430 code = PRC_UNREACH_PORT; 431 break; 432 default: 433 goto badcode; 434 } 435 goto deliver; 436 break; 437 438 case ICMP6_PACKET_TOO_BIG: 439 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig); 440 if (code != 0) 441 goto badcode; 442 443 code = PRC_MSGSIZE; 444 445 /* 446 * Updating the path MTU will be done after examining 447 * intermediate extension headers. 448 */ 449 goto deliver; 450 break; 451 452 case ICMP6_TIME_EXCEEDED: 453 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed); 454 switch (code) { 455 case ICMP6_TIME_EXCEED_TRANSIT: 456 case ICMP6_TIME_EXCEED_REASSEMBLY: 457 code += PRC_TIMXCEED_INTRANS; 458 break; 459 default: 460 goto badcode; 461 } 462 goto deliver; 463 break; 464 465 case ICMP6_PARAM_PROB: 466 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob); 467 switch (code) { 468 case ICMP6_PARAMPROB_NEXTHEADER: 469 code = PRC_UNREACH_PROTOCOL; 470 break; 471 case ICMP6_PARAMPROB_HEADER: 472 case ICMP6_PARAMPROB_OPTION: 473 code = PRC_PARAMPROB; 474 break; 475 default: 476 goto badcode; 477 } 478 goto deliver; 479 break; 480 481 case ICMP6_ECHO_REQUEST: 482 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo); 483 if (code != 0) 484 goto badcode; 485 if ((n = m_copy(m, 0, M_COPYALL)) == NULL) { 486 /* Give up remote */ 487 break; 488 } 489 if ((n->m_flags & M_EXT) != 0 490 || n->m_len < off + sizeof(struct icmp6_hdr)) { 491 struct mbuf *n0 = n; 492 const int maxlen = sizeof(*nip6) + sizeof(*nicmp6); 493 494 /* 495 * Prepare an internal mbuf. m_pullup() doesn't 496 * always copy the length we specified. 497 */ 498 if (maxlen >= MCLBYTES) { 499#ifdef DIAGNOSTIC 500 printf("MCLBYTES too small\n"); 501#endif 502 /* Give up remote */ 503 m_freem(n0); 504 break; 505 } 506 MGETHDR(n, M_DONTWAIT, n0->m_type); 507 if (n && maxlen >= MHLEN) { 508 MCLGET(n, M_DONTWAIT); 509 if ((n->m_flags & M_EXT) == 0) { 510 m_free(n); 511 n = NULL; 512 } 513 } 514 if (n == NULL) { 515 /* Give up remote */ 516 m_freem(n0); 517 break; 518 } 519 M_COPY_PKTHDR(n, n0); 520 /* 521 * Copy IPv6 and ICMPv6 only. 522 */ 523 nip6 = mtod(n, struct ip6_hdr *); 524 bcopy(ip6, nip6, sizeof(struct ip6_hdr)); 525 nicmp6 = (struct icmp6_hdr *)(nip6 + 1); 526 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); 527 noff = sizeof(struct ip6_hdr); 528 n->m_pkthdr.len = n->m_len = 529 noff + sizeof(struct icmp6_hdr); 530 /* 531 * Adjust mbuf. ip6_plen will be adjusted in 532 * ip6_output(). 533 */ 534 m_adj(n0, off + sizeof(struct icmp6_hdr)); 535 n->m_pkthdr.len += n0->m_pkthdr.len; 536 n->m_next = n0; 537 n0->m_flags &= ~M_PKTHDR; 538 } else { 539 nip6 = mtod(n, struct ip6_hdr *); 540 nicmp6 = (struct icmp6_hdr *)((caddr_t)nip6 + off); 541 noff = off; 542 } 543 nicmp6->icmp6_type = ICMP6_ECHO_REPLY; 544 nicmp6->icmp6_code = 0; 545 if (n) { 546 icmp6stat.icp6s_reflect++; 547 icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++; 548 icmp6_reflect(n, noff); 549 } 550 break; 551 552 case ICMP6_ECHO_REPLY: 553 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply); 554 if (code != 0) 555 goto badcode; 556 break; 557 558 case MLD6_LISTENER_QUERY: 559 case MLD6_LISTENER_REPORT: 560 if (icmp6len < sizeof(struct mld6_hdr)) 561 goto badlen; 562 if (icmp6->icmp6_type == MLD6_LISTENER_QUERY) /* XXX: ugly... */ 563 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldquery); 564 else 565 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldreport); 566 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 567 /* give up local */ 568 mld6_input(m, off); 569 m = NULL; 570 goto freeit; 571 } 572 mld6_input(n, off); 573 /* m stays. */ 574 break; 575 576 case MLD6_LISTENER_DONE: 577 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mlddone); 578 if (icmp6len < sizeof(struct mld6_hdr)) /* necessary? */ 579 goto badlen; 580 break; /* nothing to be done in kernel */ 581 582 case MLD6_MTRACE_RESP: 583 case MLD6_MTRACE: 584 /* XXX: these two are experimental. not officially defind. */ 585 /* XXX: per-interface statistics? */ 586 break; /* just pass it to applications */ 587 588 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */ 589 { 590 enum { WRU, FQDN } mode; 591 592 if (code != 0) 593 goto badcode; 594 if (!icmp6_nodeinfo) 595 break; 596 597 if (icmp6len == sizeof(struct icmp6_hdr) + 4) 598 mode = WRU; 599 else if (icmp6len >= sizeof(struct icmp6_hdr) + 8) /* XXX */ 600 mode = FQDN; 601 else 602 goto badlen; 603 604 if (mode == FQDN) { 605#ifndef PULLDOWN_TEST 606 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo), 607 IPPROTO_DONE); 608#endif 609 n = m_copy(m, 0, M_COPYALL); 610 if (n) 611 n = ni6_input(n, off); 612 if (n) 613 noff = sizeof(struct ip6_hdr); 614 } else { 615 u_char *p; 616 int maxlen, maxhlen; 617 618 maxlen = sizeof(*nip6) + sizeof(*nicmp6) + 4; 619 if (maxlen >= MCLBYTES) { 620#ifdef DIAGNOSTIC 621 printf("MCLBYTES too small\n"); 622#endif 623 /* Give up remote */ 624 break; 625 } 626 MGETHDR(n, M_DONTWAIT, m->m_type); 627 if (n && maxlen > MHLEN) { 628 MCLGET(n, M_DONTWAIT); 629 if ((n->m_flags & M_EXT) == 0) { 630 m_free(n); 631 n = NULL; 632 } 633 } 634 if (n == NULL) { 635 /* Give up remote */ 636 break; 637 } 638 n->m_len = 0; 639 maxhlen = M_TRAILINGSPACE(n) - maxlen; 640 if (maxhlen > hostnamelen) 641 maxhlen = hostnamelen; 642 /* 643 * Copy IPv6 and ICMPv6 only. 644 */ 645 nip6 = mtod(n, struct ip6_hdr *); 646 bcopy(ip6, nip6, sizeof(struct ip6_hdr)); 647 nicmp6 = (struct icmp6_hdr *)(nip6 + 1); 648 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); 649 p = (u_char *)(nicmp6 + 1); 650 bzero(p, 4); 651 bcopy(hostname, p + 4, maxhlen); 652 noff = sizeof(struct ip6_hdr); 653 M_COPY_PKTHDR(n, m); /* just for recvif */ 654 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) + 655 sizeof(struct icmp6_hdr) + 4 + maxhlen; 656 nicmp6->icmp6_type = ICMP6_WRUREPLY; 657 nicmp6->icmp6_code = 0; 658 } 659#undef hostnamelen 660 if (n) { 661 icmp6stat.icp6s_reflect++; 662 icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++; 663 icmp6_reflect(n, noff); 664 } 665 break; 666 } 667 668 case ICMP6_WRUREPLY: 669 if (code != 0) 670 goto badcode; 671 break; 672 673 case ND_ROUTER_SOLICIT: 674 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit); 675 if (code != 0) 676 goto badcode; 677 if (icmp6len < sizeof(struct nd_router_solicit)) 678 goto badlen; 679 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 680 /* give up local */ 681 nd6_rs_input(m, off, icmp6len); 682 m = NULL; 683 goto freeit; 684 } 685 nd6_rs_input(n, off, icmp6len); 686 /* m stays. */ 687 break; 688 689 case ND_ROUTER_ADVERT: 690 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert); 691 if (code != 0) 692 goto badcode; 693 if (icmp6len < sizeof(struct nd_router_advert)) 694 goto badlen; 695 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 696 /* give up local */ 697 nd6_ra_input(m, off, icmp6len); 698 m = NULL; 699 goto freeit; 700 } 701 nd6_ra_input(n, off, icmp6len); 702 /* m stays. */ 703 break; 704 705 case ND_NEIGHBOR_SOLICIT: 706 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit); 707 if (code != 0) 708 goto badcode; 709 if (icmp6len < sizeof(struct nd_neighbor_solicit)) 710 goto badlen; 711 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 712 /* give up local */ 713 nd6_ns_input(m, off, icmp6len); 714 m = NULL; 715 goto freeit; 716 } 717 nd6_ns_input(n, off, icmp6len); 718 /* m stays. */ 719 break; 720 721 case ND_NEIGHBOR_ADVERT: 722 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert); 723 if (code != 0) 724 goto badcode; 725 if (icmp6len < sizeof(struct nd_neighbor_advert)) 726 goto badlen; 727 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 728 /* give up local */ 729 nd6_na_input(m, off, icmp6len); 730 m = NULL; 731 goto freeit; 732 } 733 nd6_na_input(n, off, icmp6len); 734 /* m stays. */ 735 break; 736 737 case ND_REDIRECT: 738 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect); 739 if (code != 0) 740 goto badcode; 741 if (icmp6len < sizeof(struct nd_redirect)) 742 goto badlen; 743 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 744 /* give up local */ 745 icmp6_redirect_input(m, off); 746 m = NULL; 747 goto freeit; 748 } 749 icmp6_redirect_input(n, off); 750 /* m stays. */ 751 break; 752 753 case ICMP6_ROUTER_RENUMBERING: 754 if (code != ICMP6_ROUTER_RENUMBERING_COMMAND && 755 code != ICMP6_ROUTER_RENUMBERING_RESULT) 756 goto badcode; 757 if (icmp6len < sizeof(struct icmp6_router_renum)) 758 goto badlen; 759 break; 760 761 default: 762 printf("icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n", 763 icmp6->icmp6_type, ip6_sprintf(&ip6->ip6_src), 764 ip6_sprintf(&ip6->ip6_dst), 765 m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0); 766 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { 767 /* ICMPv6 error: MUST deliver it by spec... */ 768 code = PRC_NCMDS; 769 /* deliver */ 770 } else { 771 /* ICMPv6 informational: MUST not deliver */ 772 break; 773 } 774 deliver: 775 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) { 776 icmp6stat.icp6s_tooshort++; 777 goto freeit; 778 } 779#ifndef PULLDOWN_TEST 780 IP6_EXTHDR_CHECK(m, off, 781 sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr), 782 IPPROTO_DONE); 783 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off); 784#else 785 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 786 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 787 if (icmp6 == NULL) { 788 icmp6stat.icp6s_tooshort++; 789 return IPPROTO_DONE; 790 } 791#endif 792 bzero(&icmp6src, sizeof(icmp6src)); 793 icmp6src.sin6_len = sizeof(struct sockaddr_in6); 794 icmp6src.sin6_family = AF_INET6; 795 icmp6src.sin6_addr = ((struct ip6_hdr *)(icmp6 + 1))->ip6_dst; 796 797 /* Detect the upper level protocol */ 798 { 799 void (*ctlfunc) __P((int, struct sockaddr *, void *)); 800 struct ip6_hdr *eip6 = (struct ip6_hdr *)(icmp6 + 1); 801 u_int8_t nxt = eip6->ip6_nxt; 802 int eoff = off + sizeof(struct icmp6_hdr) + 803 sizeof(struct ip6_hdr); 804 struct ip6ctlparam ip6cp; 805 struct in6_addr *finaldst = NULL; 806 int icmp6type = icmp6->icmp6_type; 807 struct ip6_frag *fh; 808 struct ip6_rthdr *rth; 809 struct ip6_rthdr0 *rth0; 810 int rthlen; 811 812 while (1) { /* XXX: should avoid inf. loop explicitly? */ 813 struct ip6_ext *eh; 814 815 switch(nxt) { 816 case IPPROTO_HOPOPTS: 817 case IPPROTO_DSTOPTS: 818 case IPPROTO_AH: 819#ifndef PULLDOWN_TEST 820 IP6_EXTHDR_CHECK(m, 0, eoff + 821 sizeof(struct ip6_ext), 822 IPPROTO_DONE); 823 eh = (struct ip6_ext *)(mtod(m, caddr_t) 824 + eoff); 825#else 826 IP6_EXTHDR_GET(eh, struct ip6_ext *, m, 827 eoff, sizeof(*eh)); 828 if (eh == NULL) { 829 icmp6stat.icp6s_tooshort++; 830 return IPPROTO_DONE; 831 } 832#endif 833 834 if (nxt == IPPROTO_AH) 835 eoff += (eh->ip6e_len + 2) << 2; 836 else 837 eoff += (eh->ip6e_len + 1) << 3; 838 nxt = eh->ip6e_nxt; 839 break; 840 case IPPROTO_ROUTING: 841 /* 842 * When the erroneous packet contains a 843 * routing header, we should examine the 844 * header to determine the final destination. 845 * Otherwise, we can't properly update 846 * information that depends on the final 847 * destination (e.g. path MTU). 848 */ 849#ifndef PULLDOWN_TEST 850 IP6_EXTHDR_CHECK(m, 0, eoff + sizeof(*rth), 851 IPPROTO_DONE); 852 rth = (struct ip6_rthdr *)(mtod(m, caddr_t) 853 + eoff); 854#else 855 IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m, 856 eoff, sizeof(*rth)); 857 if (rth == NULL) { 858 icmp6stat.icp6s_tooshort++; 859 return IPPROTO_DONE; 860 } 861#endif 862 rthlen = (rth->ip6r_len + 1) << 3; 863 /* 864 * XXX: currently there is no 865 * officially defined type other 866 * than type-0. 867 * Note that if the segment left field 868 * is 0, all intermediate hops must 869 * have been passed. 870 */ 871 if (rth->ip6r_segleft && 872 rth->ip6r_type == IPV6_RTHDR_TYPE_0) { 873 int hops; 874 875#ifndef PULLDOWN_TEST 876 IP6_EXTHDR_CHECK(m, 0, eoff + rthlen, 877 IPPROTO_DONE); 878 rth0 = (struct ip6_rthdr0 *)(mtod(m, caddr_t) + eoff); 879#else 880 IP6_EXTHDR_GET(rth0, 881 struct ip6_rthdr0 *, m, 882 eoff, rthlen); 883 if (rth0 == NULL) { 884 icmp6stat.icp6s_tooshort++; 885 return IPPROTO_DONE; 886 } 887#endif 888 /* just ignore a bogus header */ 889 if ((rth0->ip6r0_len % 2) == 0 && 890 (hops = rth0->ip6r0_len/2)) 891 finaldst = (struct in6_addr *)(rth0 + 1) + (hops - 1); 892 } 893 eoff += rthlen; 894 nxt = rth->ip6r_nxt; 895 break; 896 case IPPROTO_FRAGMENT: 897#ifndef PULLDOWN_TEST 898 IP6_EXTHDR_CHECK(m, 0, eoff + 899 sizeof(struct ip6_frag), 900 IPPROTO_DONE); 901 fh = (struct ip6_frag *)(mtod(m, caddr_t) 902 + eoff); 903#else 904 IP6_EXTHDR_GET(fh, struct ip6_frag *, m, 905 eoff, sizeof(*fh)); 906 if (fh == NULL) { 907 icmp6stat.icp6s_tooshort++; 908 return IPPROTO_DONE; 909 } 910#endif 911 /* 912 * Data after a fragment header is meaningless 913 * unless it is the first fragment, but 914 * we'll go to the notify label for path MTU 915 * discovery. 916 */ 917 if (fh->ip6f_offlg & IP6F_OFF_MASK) 918 goto notify; 919 920 eoff += sizeof(struct ip6_frag); 921 nxt = fh->ip6f_nxt; 922 break; 923 default: 924 /* 925 * This case includes ESP and the No Next 926 * Header. In such cases going to the notify 927 * label does not have any meaning 928 * (i.e. ctlfunc will be NULL), but we go 929 * anyway since we might have to update 930 * path MTU information. 931 */ 932 goto notify; 933 } 934 } 935 notify: 936#ifndef PULLDOWN_TEST 937 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off); 938#else 939 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 940 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 941 if (icmp6 == NULL) { 942 icmp6stat.icp6s_tooshort++; 943 return IPPROTO_DONE; 944 } 945#endif 946 if (icmp6type == ICMP6_PACKET_TOO_BIG) { 947 if (finaldst == NULL) 948 finaldst = &((struct ip6_hdr *)(icmp6 + 1))->ip6_dst; 949 icmp6_mtudisc_update(finaldst, icmp6, m); 950 } 951 952 ctlfunc = (void (*) __P((int, struct sockaddr *, void *))) 953 (inet6sw[ip6_protox[nxt]].pr_ctlinput); 954 if (ctlfunc) { 955 ip6cp.ip6c_m = m; 956 ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1); 957 ip6cp.ip6c_off = eoff; 958 (*ctlfunc)(code, (struct sockaddr *)&icmp6src, &ip6cp); 959 } 960 } 961 break; 962 963 badcode: 964 icmp6stat.icp6s_badcode++; 965 break; 966 967 badlen: 968 icmp6stat.icp6s_badlen++; 969 break; 970 } 971 972 icmp6_rip6_input(&m, *offp); 973 return IPPROTO_DONE; 974 975 freeit: 976 m_freem(m); 977 return IPPROTO_DONE; 978} 979 980static void 981icmp6_mtudisc_update(dst, icmp6, m) 982 struct in6_addr *dst; 983 struct icmp6_hdr *icmp6;/* we can assume the validity of the pointer */ 984 struct mbuf *m; /* currently unused but added for scoped addrs */ 985{ 986 u_int mtu = ntohl(icmp6->icmp6_mtu); 987 struct rtentry *rt = NULL; 988 struct sockaddr_in6 sin6; 989 990 bzero(&sin6, sizeof(sin6)); 991 sin6.sin6_family = PF_INET6; 992 sin6.sin6_len = sizeof(struct sockaddr_in6); 993 sin6.sin6_addr = *dst; 994 /* sin6.sin6_scope_id = XXX: should be set if DST is a scoped addr */ 995 rt = rtalloc1((struct sockaddr *)&sin6, 1); /*clone*/ 996 if (!rt || (rt->rt_flags & RTF_HOST) == 0) { 997 if (rt) 998 RTFREE(rt); 999 rt = icmp6_mtudisc_clone((struct sockaddr *)&sin6); 1000 } 1001 1002 if (rt && (rt->rt_flags & RTF_HOST) 1003 && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { 1004 if (mtu < IPV6_MMTU) { 1005 /* xxx */ 1006 rt->rt_rmx.rmx_locks |= RTV_MTU; 1007 } else if (mtu < rt->rt_ifp->if_mtu && 1008 rt->rt_rmx.rmx_mtu > mtu) { 1009 rt->rt_rmx.rmx_mtu = mtu; 1010 } 1011 } 1012 if (rt) 1013 RTFREE(rt); 1014} 1015 1016/* 1017 * Process a Node Information Query 1018 */ 1019#ifndef offsetof /* XXX */ 1020#define offsetof(type, member) ((size_t)(&((type *)0)->member)) 1021#endif 1022 1023static struct mbuf * 1024ni6_input(m, off) 1025 struct mbuf *m; 1026 int off; 1027{ 1028 struct icmp6_nodeinfo *ni6, *nni6; 1029 struct mbuf *n = NULL; 1030 u_int16_t qtype; 1031 int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo); 1032 struct ni_reply_fqdn *fqdn; 1033 int addrs; /* for NI_QTYPE_NODEADDR */ 1034 struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */ 1035 1036#ifndef PULLDOWN_TEST 1037 ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off); 1038#else 1039 IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6)); 1040 if (ni6 == NULL) { 1041 /* m is already reclaimed */ 1042 return NULL; 1043 } 1044#endif 1045 qtype = ntohs(ni6->ni_qtype); 1046 1047 switch(qtype) { 1048 case NI_QTYPE_NOOP: 1049 break; /* no reply data */ 1050 case NI_QTYPE_SUPTYPES: 1051 goto bad; /* xxx: to be implemented */ 1052 break; 1053 case NI_QTYPE_FQDN: 1054 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_name) + 1055 hostnamelen; 1056 break; 1057 case NI_QTYPE_NODEADDR: 1058 addrs = ni6_addrs(ni6, m, &ifp); 1059 if ((replylen += addrs * sizeof(struct in6_addr)) > MCLBYTES) 1060 replylen = MCLBYTES; /* XXX: we'll truncate later */ 1061 1062 break; 1063 default: 1064 /* 1065 * XXX: We must return a reply with the ICMP6 code 1066 * `unknown Qtype' in this case. However we regard the case 1067 * as an FQDN query for backward compatibility. 1068 * Older versions set a random value to this field, 1069 * so it rarely varies in the defined qtypes. 1070 * But the mechanism is not reliable... 1071 * maybe we should obsolete older versions. 1072 */ 1073 qtype = NI_QTYPE_FQDN; 1074 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_name) + 1075 hostnamelen; 1076 break; 1077 } 1078 1079 /* allocate a mbuf to reply. */ 1080 MGETHDR(n, M_DONTWAIT, m->m_type); 1081 if (n == NULL) { 1082 m_freem(m); 1083 return(NULL); 1084 } 1085 M_COPY_PKTHDR(n, m); /* just for recvif */ 1086 if (replylen > MHLEN) { 1087 if (replylen > MCLBYTES) 1088 /* 1089 * XXX: should we try to allocate more? But MCLBYTES is 1090 * probably much larger than IPV6_MMTU... 1091 */ 1092 goto bad; 1093 MCLGET(n, M_DONTWAIT); 1094 if ((n->m_flags & M_EXT) == 0) { 1095 goto bad; 1096 } 1097 } 1098 n->m_pkthdr.len = n->m_len = replylen; 1099 1100 /* copy mbuf header and IPv6 + Node Information base headers */ 1101 bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr)); 1102 nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1); 1103 bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo)); 1104 1105 /* qtype dependent procedure */ 1106 switch (qtype) { 1107 case NI_QTYPE_NOOP: 1108 nni6->ni_flags = 0; 1109 break; 1110 case NI_QTYPE_SUPTYPES: 1111 goto bad; /* xxx: to be implemented */ 1112 break; 1113 case NI_QTYPE_FQDN: 1114 if (hostnamelen > 255) { /* XXX: rare case, but may happen */ 1115 printf("ni6_input: " 1116 "hostname length(%d) is too large for reply\n", 1117 hostnamelen); 1118 goto bad; 1119 } 1120 fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) + 1121 sizeof(struct ip6_hdr) + 1122 sizeof(struct icmp6_nodeinfo)); 1123 nni6->ni_flags = 0; /* XXX: meaningless TTL */ 1124 fqdn->ni_fqdn_ttl = 0; /* ditto. */ 1125 fqdn->ni_fqdn_namelen = hostnamelen; 1126 bcopy(hostname, &fqdn->ni_fqdn_name[0], hostnamelen); 1127 break; 1128 case NI_QTYPE_NODEADDR: 1129 { 1130 int lenlim, copied; 1131 1132 if (n->m_flags & M_EXT) 1133 lenlim = MCLBYTES - sizeof(struct ip6_hdr) - 1134 sizeof(struct icmp6_nodeinfo); 1135 else 1136 lenlim = MHLEN - sizeof(struct ip6_hdr) - 1137 sizeof(struct icmp6_nodeinfo); 1138 copied = ni6_store_addrs(ni6, nni6, ifp, lenlim); 1139 /* XXX: reset mbuf length */ 1140 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) + 1141 sizeof(struct icmp6_nodeinfo) + copied; 1142 break; 1143 } 1144 default: 1145 break; /* XXX impossible! */ 1146 } 1147 1148 nni6->ni_type = ICMP6_NI_REPLY; 1149 nni6->ni_code = ICMP6_NI_SUCESS; 1150 m_freem(m); 1151 return(n); 1152 1153 bad: 1154 m_freem(m); 1155 if (n) 1156 m_freem(n); 1157 return(NULL); 1158} 1159#undef hostnamelen 1160 1161/* 1162 * calculate the number of addresses to be returned in the node info reply. 1163 */ 1164static int 1165ni6_addrs(ni6, m, ifpp) 1166 struct icmp6_nodeinfo *ni6; 1167 struct mbuf *m; 1168 struct ifnet **ifpp; 1169{ 1170 register struct ifnet *ifp; 1171 register struct in6_ifaddr *ifa6; 1172 register struct ifaddr *ifa; 1173 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1174 int addrs = 0, addrsofif, iffound = 0; 1175 1176 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) 1177 { 1178 addrsofif = 0; 1179 for (ifa = ifp->if_addrlist.tqh_first; ifa; 1180 ifa = ifa->ifa_list.tqe_next) 1181 { 1182 if (ifa->ifa_addr->sa_family != AF_INET6) 1183 continue; 1184 ifa6 = (struct in6_ifaddr *)ifa; 1185 1186 if (!(ni6->ni_flags & NI_NODEADDR_FLAG_ALL) && 1187 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, 1188 &ifa6->ia_addr.sin6_addr)) 1189 iffound = 1; 1190 1191 /* 1192 * IPv4-mapped addresses can only be returned by a 1193 * Node Information proxy, since they represent 1194 * addresses of IPv4-only nodes, which perforce do 1195 * not implement this protocol. 1196 * [icmp-name-lookups-05] 1197 * So we don't support NI_NODEADDR_FLAG_COMPAT in 1198 * this function at this moment. 1199 */ 1200 1201 if (ifa6->ia6_flags & IN6_IFF_ANYCAST) 1202 continue; /* we need only unicast addresses */ 1203 1204 if ((ni6->ni_flags & (NI_NODEADDR_FLAG_LINKLOCAL | 1205 NI_NODEADDR_FLAG_SITELOCAL | 1206 NI_NODEADDR_FLAG_GLOBAL)) == 0) 1207 continue; 1208 1209 /* What do we have to do about ::1? */ 1210 switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) { 1211 case IPV6_ADDR_SCOPE_LINKLOCAL: 1212 if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL) 1213 addrsofif++; 1214 break; 1215 case IPV6_ADDR_SCOPE_SITELOCAL: 1216 if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL) 1217 addrsofif++; 1218 break; 1219 case IPV6_ADDR_SCOPE_GLOBAL: 1220 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL) 1221 addrsofif++; 1222 break; 1223 default: 1224 continue; 1225 } 1226 } 1227 if (iffound) { 1228 *ifpp = ifp; 1229 return(addrsofif); 1230 } 1231 1232 addrs += addrsofif; 1233 } 1234 1235 return(addrs); 1236} 1237 1238static int 1239ni6_store_addrs(ni6, nni6, ifp0, resid) 1240 struct icmp6_nodeinfo *ni6, *nni6; 1241 struct ifnet *ifp0; 1242 int resid; 1243{ 1244 register struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&ifnet); 1245 register struct in6_ifaddr *ifa6; 1246 register struct ifaddr *ifa; 1247 int docopy, copied = 0; 1248 u_char *cp = (u_char *)(nni6 + 1); 1249 1250 if (ifp0 == NULL && !(ni6->ni_flags & NI_NODEADDR_FLAG_ALL)) 1251 return(0); /* needless to copy */ 1252 1253 for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) 1254 { 1255 for (ifa = ifp->if_addrlist.tqh_first; ifa; 1256 ifa = ifa->ifa_list.tqe_next) 1257 { 1258 docopy = 0; 1259 1260 if (ifa->ifa_addr->sa_family != AF_INET6) 1261 continue; 1262 ifa6 = (struct in6_ifaddr *)ifa; 1263 1264 if (ifa6->ia6_flags & IN6_IFF_ANYCAST) { 1265 /* just experimental. not in the spec. */ 1266 if (ni6->ni_flags & NI_NODEADDR_FLAG_ANYCAST) 1267 docopy = 1; 1268 else 1269 continue; 1270 } 1271 else { /* unicast address */ 1272 if (ni6->ni_flags & NI_NODEADDR_FLAG_ANYCAST) 1273 continue; 1274 else 1275 docopy = 1; 1276 } 1277 1278 /* What do we have to do about ::1? */ 1279 switch(in6_addrscope(&ifa6->ia_addr.sin6_addr)) { 1280 case IPV6_ADDR_SCOPE_LINKLOCAL: 1281 if (ni6->ni_flags & NI_NODEADDR_FLAG_LINKLOCAL) 1282 docopy = 1; 1283 break; 1284 case IPV6_ADDR_SCOPE_SITELOCAL: 1285 if (ni6->ni_flags & NI_NODEADDR_FLAG_SITELOCAL) 1286 docopy = 1; 1287 break; 1288 case IPV6_ADDR_SCOPE_GLOBAL: 1289 if (ni6->ni_flags & NI_NODEADDR_FLAG_GLOBAL) 1290 docopy = 1; 1291 break; 1292 default: 1293 continue; 1294 } 1295 1296 if (docopy) { 1297 if (resid < sizeof(struct in6_addr)) { 1298 /* 1299 * We give up much more copy. 1300 * Set the truncate flag and return. 1301 */ 1302 nni6->ni_flags |= 1303 NI_NODEADDR_FLAG_TRUNCATE; 1304 return(copied); 1305 } 1306 bcopy(&ifa6->ia_addr.sin6_addr, cp, 1307 sizeof(struct in6_addr)); 1308 /* XXX: KAME link-local hack; remove ifindex */ 1309 if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr)) 1310 ((struct in6_addr *)cp)->s6_addr16[1] = 0; 1311 cp += sizeof(struct in6_addr); 1312 resid -= sizeof(struct in6_addr); 1313 copied += sizeof(struct in6_addr); 1314 } 1315 } 1316 if (ifp0) /* we need search only on the specified IF */ 1317 break; 1318 } 1319 1320 return(copied); 1321} 1322 1323/* 1324 * XXX almost dup'ed code with rip6_input. 1325 */ 1326static int 1327icmp6_rip6_input(mp, off) 1328 struct mbuf **mp; 1329 int off; 1330{ 1331 struct mbuf *m = *mp; 1332 register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1333 register struct in6pcb *in6p; 1334 struct in6pcb *last = NULL; 1335 struct sockaddr_in6 rip6src; 1336 struct icmp6_hdr *icmp6; 1337 struct mbuf *opts = NULL; 1338 1339#ifndef PULLDOWN_TEST 1340 /* this is assumed to be safe. */ 1341 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off); 1342#else 1343 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6)); 1344 if (icmp6 == NULL) { 1345 /* m is already reclaimed */ 1346 return IPPROTO_DONE; 1347 } 1348#endif 1349 1350 bzero(&rip6src, sizeof(rip6src)); 1351 rip6src.sin6_len = sizeof(struct sockaddr_in6); 1352 rip6src.sin6_family = AF_INET6; 1353 rip6src.sin6_addr = ip6->ip6_src; 1354 if (IN6_IS_SCOPE_LINKLOCAL(&rip6src.sin6_addr)) 1355 rip6src.sin6_addr.s6_addr16[1] = 0; 1356 if (m->m_pkthdr.rcvif) { 1357 if (IN6_IS_SCOPE_LINKLOCAL(&rip6src.sin6_addr)) 1358 rip6src.sin6_scope_id = m->m_pkthdr.rcvif->if_index; 1359 else 1360 rip6src.sin6_scope_id = 0; 1361 } else 1362 rip6src.sin6_scope_id = 0; 1363 1364 for (in6p = rawin6pcb.in6p_next; 1365 in6p != &rawin6pcb; in6p = in6p->in6p_next) 1366 { 1367 if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6) 1368 continue; 1369 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 1370 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 1371 continue; 1372 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 1373 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 1374 continue; 1375 if (in6p->in6p_icmp6filt 1376 && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type, 1377 in6p->in6p_icmp6filt)) 1378 continue; 1379 if (last) { 1380 struct mbuf *n; 1381 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 1382 if (last->in6p_flags & IN6P_CONTROLOPTS) 1383 ip6_savecontrol(last, &opts, ip6, n); 1384 /* strip intermediate headers */ 1385 m_adj(n, off); 1386 if (sbappendaddr(&last->in6p_socket->so_rcv, 1387 (struct sockaddr *)&rip6src, 1388 n, opts) == 0) { 1389 /* should notify about lost packet */ 1390 m_freem(n); 1391 if (opts) 1392 m_freem(opts); 1393 } else 1394 sorwakeup(last->in6p_socket); 1395 opts = NULL; 1396 } 1397 } 1398 last = in6p; 1399 } 1400 if (last) { 1401 if (last->in6p_flags & IN6P_CONTROLOPTS) 1402 ip6_savecontrol(last, &opts, ip6, m); 1403 /* strip intermediate headers */ 1404 m_adj(m, off); 1405 if (sbappendaddr(&last->in6p_socket->so_rcv, 1406 (struct sockaddr *)&rip6src, m, opts) == 0) { 1407 m_freem(m); 1408 if (opts) 1409 m_freem(opts); 1410 } else 1411 sorwakeup(last->in6p_socket); 1412 } else { 1413 m_freem(m); 1414 ip6stat.ip6s_delivered--; 1415 } 1416 return IPPROTO_DONE; 1417} 1418 1419/* 1420 * Reflect the ip6 packet back to the source. 1421 * OFF points to the icmp6 header, counted from the top of the mbuf. 1422 */ 1423void 1424icmp6_reflect(m, off) 1425 struct mbuf *m; 1426 size_t off; 1427{ 1428 struct ip6_hdr *ip6; 1429 struct icmp6_hdr *icmp6; 1430 struct in6_ifaddr *ia; 1431 struct in6_addr t, *src = 0; 1432 int plen; 1433 int type, code; 1434 struct ifnet *outif = NULL; 1435#ifdef COMPAT_RFC1885 1436 int mtu = IPV6_MMTU; 1437 struct sockaddr_in6 *sin6 = &icmp6_reflect_rt.ro_dst; 1438#endif 1439 1440 /* too short to reflect */ 1441 if (off < sizeof(struct ip6_hdr)) { 1442 printf("sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n", 1443 (u_long)off, (u_long)sizeof(struct ip6_hdr), 1444 __FILE__, __LINE__); 1445 goto bad; 1446 } 1447 1448 /* 1449 * If there are extra headers between IPv6 and ICMPv6, strip 1450 * off that header first. 1451 */ 1452 if (off > sizeof(struct ip6_hdr)) { 1453 size_t l; 1454 struct ip6_hdr nip6; 1455 1456 l = off - sizeof(struct ip6_hdr); 1457 m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6); 1458 m_adj(m, l); 1459 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1460 if (m->m_len < l) { 1461 if ((m = m_pullup(m, l)) == NULL) 1462 return; 1463 } 1464 bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6)); 1465 } else /* off == sizeof(struct ip6_hdr) */ { 1466 size_t l; 1467 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 1468 if (m->m_len < l) { 1469 if ((m = m_pullup(m, l)) == NULL) 1470 return; 1471 } 1472 } 1473 plen = m->m_pkthdr.len - sizeof(struct ip6_hdr); 1474 ip6 = mtod(m, struct ip6_hdr *); 1475 ip6->ip6_nxt = IPPROTO_ICMPV6; 1476 icmp6 = (struct icmp6_hdr *)(ip6 + 1); 1477 type = icmp6->icmp6_type; /* keep type for statistics */ 1478 code = icmp6->icmp6_code; /* ditto. */ 1479 1480 t = ip6->ip6_dst; 1481 /* 1482 * ip6_input() drops a packet if its src is multicast. 1483 * So, the src is never multicast. 1484 */ 1485 ip6->ip6_dst = ip6->ip6_src; 1486 1487 /* XXX hack for link-local addresses */ 1488 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) 1489 ip6->ip6_dst.s6_addr16[1] = 1490 htons(m->m_pkthdr.rcvif->if_index); 1491 if (IN6_IS_ADDR_LINKLOCAL(&t)) 1492 t.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index); 1493 1494#ifdef COMPAT_RFC1885 1495 /* 1496 * xxx guess MTU 1497 * RFC 1885 requires that echo reply should be truncated if it 1498 * does not fit in with (return) path MTU, but the description was 1499 * removed in the new spec. 1500 */ 1501 if (icmp6_reflect_rt.ro_rt == 0 || 1502 ! (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_dst))) { 1503 if (icmp6_reflect_rt.ro_rt) { 1504 icmp6_reflect_rt.ro_rt = 0; 1505 } 1506 bzero(sin6, sizeof(*sin6)); 1507 sin6->sin6_family = PF_INET6; 1508 sin6->sin6_len = sizeof(struct sockaddr_in6); 1509 sin6->sin6_addr = ip6->ip6_dst; 1510 1511 rtalloc((struct route *)&icmp6_reflect_rt.ro_rt); 1512 } 1513 1514 if (icmp6_reflect_rt.ro_rt == 0) 1515 goto bad; 1516 1517 if ((icmp6_reflect_rt.ro_rt->rt_flags & RTF_HOST) 1518 && mtu < icmp6_reflect_rt.ro_rt->rt_ifp->if_mtu) 1519 mtu = icmp6_reflect_rt.ro_rt->rt_rmx.rmx_mtu; 1520 1521 if (mtu < m->m_pkthdr.len) { 1522 plen -= (m->m_pkthdr.len - mtu); 1523 m_adj(m, mtu - m->m_pkthdr.len); 1524 } 1525#endif 1526 /* 1527 * If the incoming packet was addressed directly to us(i.e. unicast), 1528 * use dst as the src for the reply. 1529 * The IN6_IFF_NOTREADY case would be VERY rare, but is possible when 1530 * (for example) when we encounter an error while forwarding procedure 1531 * destined to a duplicated address of ours. 1532 */ 1533 for (ia = in6_ifaddr; ia; ia = ia->ia_next) 1534 if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) && 1535 (ia->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0) { 1536 src = &t; 1537 break; 1538 } 1539 if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) && (m->m_flags & M_LOOP)) { 1540 /* 1541 * This is the case if the dst is our link-local address 1542 * and the sender is also ourseleves. 1543 */ 1544 src = &t; 1545 } 1546 1547 if (src == 0) 1548 /* 1549 * This case matches to multicasts, our anycast, or unicasts 1550 * that we do not own. Select a source address which has the 1551 * same scope. 1552 * XXX: for (non link-local) multicast addresses, this might 1553 * not be a good choice. 1554 */ 1555 if ((ia = in6_ifawithscope(m->m_pkthdr.rcvif, &t)) != 0) 1556 src = &IA6_SIN6(ia)->sin6_addr; 1557 1558 if (src == 0) 1559 goto bad; 1560 1561 ip6->ip6_src = *src; 1562 1563 ip6->ip6_flow = 0; 1564 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 1565 ip6->ip6_vfc |= IPV6_VERSION; 1566 ip6->ip6_nxt = IPPROTO_ICMPV6; 1567 if (m->m_pkthdr.rcvif) { 1568 /* XXX: This may not be the outgoing interface */ 1569 ip6->ip6_hlim = nd_ifinfo[m->m_pkthdr.rcvif->if_index].chlim; 1570 } 1571 1572 icmp6->icmp6_cksum = 0; 1573 icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6, 1574 sizeof(struct ip6_hdr), plen); 1575 1576 /* 1577 * xxx option handling 1578 */ 1579 1580 m->m_flags &= ~(M_BCAST|M_MCAST); 1581#ifdef IPSEC 1582 /* Don't lookup socket */ 1583 ipsec_setsocket(m, NULL); 1584#endif /*IPSEC*/ 1585 1586#ifdef COMPAT_RFC1885 1587 ip6_output(m, NULL, &icmp6_reflect_rt, 0, NULL, &outif); 1588#else 1589 ip6_output(m, NULL, NULL, 0, NULL, &outif); 1590#endif 1591 if (outif) 1592 icmp6_ifoutstat_inc(outif, type, code); 1593 1594 return; 1595 1596 bad: 1597 m_freem(m); 1598 return; 1599} 1600 1601void 1602icmp6_fasttimo() 1603{ 1604 mld6_fasttimeo(); 1605} 1606 1607static const char * 1608icmp6_redirect_diag(src6, dst6, tgt6) 1609 struct in6_addr *src6; 1610 struct in6_addr *dst6; 1611 struct in6_addr *tgt6; 1612{ 1613 static char buf[1024]; 1614 snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)", 1615 ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6)); 1616 return buf; 1617} 1618 1619void 1620icmp6_redirect_input(m, off) 1621 register struct mbuf *m; 1622 int off; 1623{ 1624 struct ifnet *ifp = m->m_pkthdr.rcvif; 1625 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1626 struct nd_redirect *nd_rd; 1627 int icmp6len = ntohs(ip6->ip6_plen); 1628 char *lladdr = NULL; 1629 int lladdrlen = 0; 1630 u_char *redirhdr = NULL; 1631 int redirhdrlen = 0; 1632 struct rtentry *rt = NULL; 1633 int is_router; 1634 int is_onlink; 1635 struct in6_addr src6 = ip6->ip6_src; 1636 struct in6_addr redtgt6; 1637 struct in6_addr reddst6; 1638 union nd_opts ndopts; 1639 1640 if (!m || !ifp) 1641 return; 1642 1643 /* XXX if we are router, we don't update route by icmp6 redirect */ 1644 if (ip6_forwarding) 1645 goto freeit; 1646 if (!icmp6_rediraccept) 1647 goto freeit; 1648 1649#ifndef PULLDOWN_TEST 1650 IP6_EXTHDR_CHECK(m, off, icmp6len,); 1651 nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off); 1652#else 1653 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len); 1654 if (nd_rd == NULL) { 1655 icmp6stat.icp6s_tooshort++; 1656 return; 1657 } 1658#endif 1659 redtgt6 = nd_rd->nd_rd_target; 1660 reddst6 = nd_rd->nd_rd_dst; 1661 1662 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1663 redtgt6.s6_addr16[1] = htons(ifp->if_index); 1664 if (IN6_IS_ADDR_LINKLOCAL(&reddst6)) 1665 reddst6.s6_addr16[1] = htons(ifp->if_index); 1666 1667 /* validation */ 1668 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) { 1669 log(LOG_ERR, 1670 "ICMP6 redirect sent from %s rejected; " 1671 "must be from linklocal\n", ip6_sprintf(&src6)); 1672 goto freeit; 1673 } 1674 if (ip6->ip6_hlim != 255) { 1675 log(LOG_ERR, 1676 "ICMP6 redirect sent from %s rejected; " 1677 "hlim=%d (must be 255)\n", 1678 ip6_sprintf(&src6), ip6->ip6_hlim); 1679 goto freeit; 1680 } 1681 { 1682 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */ 1683 struct sockaddr_in6 sin6; 1684 struct in6_addr *gw6; 1685 1686 bzero(&sin6, sizeof(sin6)); 1687 sin6.sin6_family = AF_INET6; 1688 sin6.sin6_len = sizeof(struct sockaddr_in6); 1689 bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6)); 1690 rt = rtalloc1((struct sockaddr *)&sin6, 0); 1691 if (rt) { 1692 gw6 = &(((struct sockaddr_in6 *)rt->rt_gateway)->sin6_addr); 1693 if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) { 1694 log(LOG_ERR, 1695 "ICMP6 redirect rejected; " 1696 "not equal to gw-for-src=%s (must be same): " 1697 "%s\n", 1698 ip6_sprintf(gw6), 1699 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)); 1700 RTFREE(rt); 1701 goto freeit; 1702 } 1703 } else { 1704 log(LOG_ERR, 1705 "ICMP6 redirect rejected; " 1706 "no route found for redirect dst: %s\n", 1707 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)); 1708 goto freeit; 1709 } 1710 RTFREE(rt); 1711 rt = NULL; 1712 } 1713 if (IN6_IS_ADDR_MULTICAST(&reddst6)) { 1714 log(LOG_ERR, 1715 "ICMP6 redirect rejected; " 1716 "redirect dst must be unicast: %s\n", 1717 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)); 1718 goto freeit; 1719 } 1720 1721 is_router = is_onlink = 0; 1722 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 1723 is_router = 1; /* router case */ 1724 if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) 1725 is_onlink = 1; /* on-link destination case */ 1726 if (!is_router && !is_onlink) { 1727 log(LOG_ERR, 1728 "ICMP6 redirect rejected; " 1729 "neither router case nor onlink case: %s\n", 1730 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)); 1731 goto freeit; 1732 } 1733 /* validation passed */ 1734 1735 icmp6len -= sizeof(*nd_rd); 1736 nd6_option_init(nd_rd + 1, icmp6len, &ndopts); 1737 if (nd6_options(&ndopts) < 0) { 1738 log(LOG_INFO, "icmp6_redirect_input: " 1739 "invalid ND option, rejected: %s\n", 1740 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)); 1741 goto freeit; 1742 } 1743 1744 if (ndopts.nd_opts_tgt_lladdr) { 1745 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); 1746 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; 1747 } 1748 1749 if (ndopts.nd_opts_rh) { 1750 redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len; 1751 redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */ 1752 } 1753 1754 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 1755 log(LOG_INFO, 1756 "icmp6_redirect_input: lladdrlen mismatch for %s " 1757 "(if %d, icmp6 packet %d): %s\n", 1758 ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2, 1759 icmp6_redirect_diag(&src6, &reddst6, &redtgt6)); 1760 } 1761 1762 /* RFC 2461 8.3 */ 1763 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, 1764 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); 1765 1766 if (!is_onlink) { /* better router case. perform rtredirect. */ 1767 /* perform rtredirect */ 1768 struct sockaddr_in6 sdst; 1769 struct sockaddr_in6 sgw; 1770 struct sockaddr_in6 ssrc; 1771 1772 bzero(&sdst, sizeof(sdst)); 1773 bzero(&sgw, sizeof(sgw)); 1774 bzero(&ssrc, sizeof(ssrc)); 1775 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6; 1776 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len = 1777 sizeof(struct sockaddr_in6); 1778 bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr)); 1779 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); 1780 bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr)); 1781 rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw, 1782 (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST, 1783 (struct sockaddr *)&ssrc, 1784 (struct rtentry **)NULL 1785 ); 1786 } 1787 /* finally update cached route in each socket via pfctlinput */ 1788 { 1789 struct sockaddr_in6 sdst; 1790#if 1 1791#else 1792 struct ip6protosw *pr; 1793#endif 1794 1795 bzero(&sdst, sizeof(sdst)); 1796 sdst.sin6_family = AF_INET6; 1797 sdst.sin6_len = sizeof(struct sockaddr_in6); 1798 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); 1799#if 1 1800 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst); 1801#else 1802 /* 1803 * do not use pfctlinput() here, we have different prototype for 1804 * xx_ctlinput() in ip6proto. 1805 */ 1806 for (pr = (struct ip6protosw *)inet6domain.dom_protosw; 1807 pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; 1808 pr++) { 1809 if (pr->pr_ctlinput) { 1810 (*pr->pr_ctlinput)(PRC_REDIRECT_HOST, 1811 (struct sockaddr *)&sdst, NULL, NULL, 0); 1812 } 1813 } 1814#endif 1815#ifdef IPSEC 1816 key_sa_routechange((struct sockaddr *)&sdst); 1817#endif 1818 } 1819 1820 freeit: 1821 m_freem(m); 1822} 1823 1824void 1825icmp6_redirect_output(m0, rt) 1826 struct mbuf *m0; 1827 struct rtentry *rt; 1828{ 1829 struct ifnet *ifp; /* my outgoing interface */ 1830 struct in6_addr *ifp_ll6; 1831 struct in6_addr *router_ll6; 1832 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */ 1833 struct mbuf *m = NULL; /* newly allocated one */ 1834 struct ip6_hdr *ip6; /* m as struct ip6_hdr */ 1835 struct nd_redirect *nd_rd; 1836 size_t maxlen; 1837 u_char *p; 1838 struct ifnet *outif = NULL; 1839 1840 /* if we are not router, we don't send icmp6 redirect */ 1841 if (!ip6_forwarding || ip6_accept_rtadv) 1842 goto fail; 1843 1844 /* sanity check */ 1845 if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp)) 1846 goto fail; 1847 1848 /* 1849 * Address check: 1850 * the source address must identify a neighbor, and 1851 * the destination address must not be a multicast address 1852 * [RFC 2461, sec 8.2] 1853 */ 1854 sip6 = mtod(m0, struct ip6_hdr *); 1855 if (nd6_is_addr_neighbor(&sip6->ip6_src, ifp) == 0) 1856 goto fail; 1857 if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst)) 1858 goto fail; /* what should we do here? */ 1859 1860 /* rate limit */ 1861 if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0)) 1862 goto fail; 1863 1864 /* 1865 * Since we are going to append up to 1280 bytes (= IPV6_MMTU), 1866 * we almost always ask for an mbuf cluster for simplicity. 1867 * (MHLEN < IPV6_MMTU is almost always true) 1868 */ 1869#if IPV6_MMTU >= MCLBYTES 1870# error assumption failed about IPV6_MMTU and MCLBYTES 1871#endif 1872 MGETHDR(m, M_DONTWAIT, MT_HEADER); 1873 if (m && IPV6_MMTU >= MHLEN) 1874 MCLGET(m, M_DONTWAIT); 1875 if (!m) 1876 goto fail; 1877 maxlen = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN; 1878 maxlen = min(IPV6_MMTU, maxlen); 1879 /* just for safety */ 1880 if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 1881 ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) { 1882 goto fail; 1883 } 1884 1885 { 1886 /* get ip6 linklocal address for ifp(my outgoing interface). */ 1887 struct in6_ifaddr *ia; 1888 if ((ia = in6ifa_ifpforlinklocal(ifp, 1889 IN6_IFF_NOTREADY| 1890 IN6_IFF_ANYCAST)) == NULL) 1891 goto fail; 1892 ifp_ll6 = &ia->ia_addr.sin6_addr; 1893 } 1894 1895 /* get ip6 linklocal address for the router. */ 1896 if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) { 1897 struct sockaddr_in6 *sin6; 1898 sin6 = (struct sockaddr_in6 *)rt->rt_gateway; 1899 router_ll6 = &sin6->sin6_addr; 1900 if (!IN6_IS_ADDR_LINKLOCAL(router_ll6)) 1901 router_ll6 = (struct in6_addr *)NULL; 1902 } else 1903 router_ll6 = (struct in6_addr *)NULL; 1904 1905 /* ip6 */ 1906 ip6 = mtod(m, struct ip6_hdr *); 1907 ip6->ip6_flow = 0; 1908 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 1909 ip6->ip6_vfc |= IPV6_VERSION; 1910 /* ip6->ip6_plen will be set later */ 1911 ip6->ip6_nxt = IPPROTO_ICMPV6; 1912 ip6->ip6_hlim = 255; 1913 /* ip6->ip6_src must be linklocal addr for my outgoing if. */ 1914 bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr)); 1915 bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr)); 1916 1917 /* ND Redirect */ 1918 nd_rd = (struct nd_redirect *)(ip6 + 1); 1919 nd_rd->nd_rd_type = ND_REDIRECT; 1920 nd_rd->nd_rd_code = 0; 1921 nd_rd->nd_rd_reserved = 0; 1922 if (rt->rt_flags & RTF_GATEWAY) { 1923 /* 1924 * nd_rd->nd_rd_target must be a link-local address in 1925 * better router cases. 1926 */ 1927 if (!router_ll6) 1928 goto fail; 1929 bcopy(router_ll6, &nd_rd->nd_rd_target, 1930 sizeof(nd_rd->nd_rd_target)); 1931 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 1932 sizeof(nd_rd->nd_rd_dst)); 1933 } else { 1934 /* make sure redtgt == reddst */ 1935 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target, 1936 sizeof(nd_rd->nd_rd_target)); 1937 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 1938 sizeof(nd_rd->nd_rd_dst)); 1939 } 1940 1941 p = (u_char *)(nd_rd + 1); 1942 1943 if (!router_ll6) 1944 goto nolladdropt; 1945 1946 { 1947 /* target lladdr option */ 1948 struct rtentry *rt_router = NULL; 1949 int len; 1950 struct sockaddr_dl *sdl; 1951 struct nd_opt_hdr *nd_opt; 1952 char *lladdr; 1953 1954 rt_router = nd6_lookup(router_ll6, 0, ifp); 1955 if (!rt_router) 1956 goto nolladdropt; 1957 len = sizeof(*nd_opt) + ifp->if_addrlen; 1958 len = (len + 7) & ~7; /*round by 8*/ 1959 /* safety check */ 1960 if (len + (p - (u_char *)ip6) > maxlen) 1961 goto nolladdropt; 1962 if (!(rt_router->rt_flags & RTF_GATEWAY) && 1963 (rt_router->rt_flags & RTF_LLINFO) && 1964 (rt_router->rt_gateway->sa_family == AF_LINK) && 1965 (sdl = (struct sockaddr_dl *)rt_router->rt_gateway) && 1966 sdl->sdl_alen) { 1967 nd_opt = (struct nd_opt_hdr *)p; 1968 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; 1969 nd_opt->nd_opt_len = len >> 3; 1970 lladdr = (char *)(nd_opt + 1); 1971 bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen); 1972 p += len; 1973 } 1974 } 1975nolladdropt:; 1976 1977 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 1978 1979 /* just to be safe */ 1980 if (m0->m_flags & M_DECRYPTED) 1981 goto noredhdropt; 1982 if (p - (u_char *)ip6 > maxlen) 1983 goto noredhdropt; 1984 1985 { 1986 /* redirected header option */ 1987 int len; 1988 struct nd_opt_rd_hdr *nd_opt_rh; 1989 1990 /* 1991 * compute the maximum size for icmp6 redirect header option. 1992 * XXX room for auth header? 1993 */ 1994 len = maxlen - (p - (u_char *)ip6); 1995 len &= ~7; 1996 1997 /* This is just for simplicity. */ 1998 if (m0->m_pkthdr.len != m0->m_len) { 1999 if (m0->m_next) { 2000 m_freem(m0->m_next); 2001 m0->m_next = NULL; 2002 } 2003 m0->m_pkthdr.len = m0->m_len; 2004 } 2005 2006 /* 2007 * Redirected header option spec (RFC2461 4.6.3) talks nothing 2008 * about padding/truncate rule for the original IP packet. 2009 * From the discussion on IPv6imp in Feb 1999, the consensus was: 2010 * - "attach as much as possible" is the goal 2011 * - pad if not aligned (original size can be guessed by original 2012 * ip6 header) 2013 * Following code adds the padding if it is simple enough, 2014 * and truncates if not. 2015 */ 2016 if (m0->m_next || m0->m_pkthdr.len != m0->m_len) 2017 panic("assumption failed in %s:%d\n", __FILE__, __LINE__); 2018 2019 if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) { 2020 /* not enough room, truncate */ 2021 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh); 2022 } else { 2023 /* enough room, pad or truncate */ 2024 size_t extra; 2025 2026 extra = m0->m_pkthdr.len % 8; 2027 if (extra) { 2028 /* pad if easy enough, truncate if not */ 2029 if (8 - extra <= M_TRAILINGSPACE(m0)) { 2030 /* pad */ 2031 m0->m_len += (8 - extra); 2032 m0->m_pkthdr.len += (8 - extra); 2033 } else { 2034 /* truncate */ 2035 m0->m_pkthdr.len -= extra; 2036 m0->m_len -= extra; 2037 } 2038 } 2039 len = m0->m_pkthdr.len + sizeof(*nd_opt_rh); 2040 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh); 2041 } 2042 2043 nd_opt_rh = (struct nd_opt_rd_hdr *)p; 2044 bzero(nd_opt_rh, sizeof(*nd_opt_rh)); 2045 nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER; 2046 nd_opt_rh->nd_opt_rh_len = len >> 3; 2047 p += sizeof(*nd_opt_rh); 2048 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 2049 2050 /* connect m0 to m */ 2051 m->m_next = m0; 2052 m->m_pkthdr.len = m->m_len + m0->m_len; 2053 } 2054noredhdropt:; 2055 2056 if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src)) 2057 sip6->ip6_src.s6_addr16[1] = 0; 2058 if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst)) 2059 sip6->ip6_dst.s6_addr16[1] = 0; 2060#if 0 2061 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) 2062 ip6->ip6_src.s6_addr16[1] = 0; 2063 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) 2064 ip6->ip6_dst.s6_addr16[1] = 0; 2065#endif 2066 if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target)) 2067 nd_rd->nd_rd_target.s6_addr16[1] = 0; 2068 if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst)) 2069 nd_rd->nd_rd_dst.s6_addr16[1] = 0; 2070 2071 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 2072 2073 nd_rd->nd_rd_cksum = 0; 2074 nd_rd->nd_rd_cksum 2075 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen)); 2076 2077 /* send the packet to outside... */ 2078#ifdef IPSEC 2079 /* Don't lookup socket */ 2080 ipsec_setsocket(m, NULL); 2081#endif /*IPSEC*/ 2082 ip6_output(m, NULL, NULL, 0, NULL, &outif); 2083 if (outif) { 2084 icmp6_ifstat_inc(outif, ifs6_out_msg); 2085 icmp6_ifstat_inc(outif, ifs6_out_redirect); 2086 } 2087 icmp6stat.icp6s_outhist[ND_REDIRECT]++; 2088 2089 return; 2090 2091fail: 2092 if (m) 2093 m_freem(m); 2094 if (m0) 2095 m_freem(m0); 2096} 2097 2098/* 2099 * ICMPv6 socket option processing. 2100 */ 2101int 2102icmp6_ctloutput(op, so, level, optname, mp) 2103 int op; 2104 struct socket *so; 2105 int level, optname; 2106 struct mbuf **mp; 2107{ 2108 register struct in6pcb *in6p = sotoin6pcb(so); 2109 register struct mbuf *m = *mp; 2110 int error = 0; 2111 2112 if (level != IPPROTO_ICMPV6) { 2113 error = EINVAL; 2114 if (op == PRCO_SETOPT && m) 2115 (void)m_free(m); 2116 } else switch(op) { 2117 case PRCO_SETOPT: 2118 switch (optname) { 2119 case ICMP6_FILTER: 2120 { 2121 struct icmp6_filter *p; 2122 2123 p = mtod(m, struct icmp6_filter *); 2124 if (!p || !in6p->in6p_icmp6filt) { 2125 error = EINVAL; 2126 break; 2127 } 2128 bcopy(p, in6p->in6p_icmp6filt, 2129 sizeof(struct icmp6_filter)); 2130 error = 0; 2131 break; 2132 } 2133 2134 default: 2135 error = ENOPROTOOPT; 2136 break; 2137 } 2138 if (m) 2139 (void)m_free(m); 2140 break; 2141 2142 case PRCO_GETOPT: 2143 switch (optname) { 2144 case ICMP6_FILTER: 2145 { 2146 struct icmp6_filter *p; 2147 2148 if (!in6p->in6p_icmp6filt) { 2149 error = EINVAL; 2150 break; 2151 } 2152 *mp = m = m_get(M_WAIT, MT_SOOPTS); 2153 m->m_len = sizeof(struct icmp6_filter); 2154 p = mtod(m, struct icmp6_filter *); 2155 bcopy(in6p->in6p_icmp6filt, p, 2156 sizeof(struct icmp6_filter)); 2157 error = 0; 2158 break; 2159 } 2160 2161 default: 2162 error = ENOPROTOOPT; 2163 break; 2164 } 2165 break; 2166 } 2167 2168 return(error); 2169} 2170 2171/* 2172 * Perform rate limit check. 2173 * Returns 0 if it is okay to send the icmp6 packet. 2174 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate 2175 * limitation. 2176 * 2177 * XXX per-destination/type check necessary? 2178 */ 2179static int 2180icmp6_ratelimit(dst, type, code) 2181 const struct in6_addr *dst; /* not used at this moment */ 2182 const int type; /* not used at this moment */ 2183 const int code; /* not used at this moment */ 2184{ 2185 static struct timeval icmp6errratelim_last; 2186 2187 /* 2188 * ratecheck() returns true if it is okay to send. We return 2189 * true if it is not okay to send. 2190 */ 2191 return (ratecheck(&icmp6errratelim_last, &icmp6errratelim) == 0); 2192} 2193 2194static struct rtentry * 2195icmp6_mtudisc_clone(dst) 2196 struct sockaddr *dst; 2197{ 2198 struct rtentry *rt; 2199 int error; 2200 2201 rt = rtalloc1(dst, 1); 2202 if (rt == 0) 2203 return NULL; 2204 2205 /* If we didn't get a host route, allocate one */ 2206 if ((rt->rt_flags & RTF_HOST) == 0) { 2207 struct rtentry *nrt; 2208 2209 error = rtrequest((int) RTM_ADD, dst, 2210 (struct sockaddr *) rt->rt_gateway, 2211 (struct sockaddr *) 0, 2212 RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt); 2213 if (error) { 2214 rtfree(rt); 2215 rtfree(nrt); 2216 return NULL; 2217 } 2218 nrt->rt_rmx = rt->rt_rmx; 2219 rtfree(rt); 2220 rt = nrt; 2221 } 2222 error = rt_timer_add(rt, icmp6_mtudisc_timeout, 2223 icmp6_mtudisc_timeout_q); 2224 if (error) { 2225 rtfree(rt); 2226 return NULL; 2227 } 2228 2229 return rt; /* caller need to call rtfree() */ 2230} 2231 2232static void 2233icmp6_mtudisc_timeout(rt, r) 2234 struct rtentry *rt; 2235 struct rttimer *r; 2236{ 2237 if (rt == NULL) 2238 panic("icmp6_mtudisc_timeout: bad route to timeout"); 2239 if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) == 2240 (RTF_DYNAMIC | RTF_HOST)) { 2241 rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt), 2242 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); 2243 } else { 2244 if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) { 2245 rt->rt_rmx.rmx_mtu = 0; 2246 } 2247 } 2248} 2249 2250#include <vm/vm.h> 2251#include <sys/sysctl.h> 2252int 2253icmp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 2254 int *name; 2255 u_int namelen; 2256 void *oldp; 2257 size_t *oldlenp; 2258 void *newp; 2259 size_t newlen; 2260{ 2261 2262 /* All sysctl names at this level are terminal. */ 2263 if (namelen != 1) 2264 return ENOTDIR; 2265 2266 switch (name[0]) { 2267 2268 case ICMPV6CTL_REDIRACCEPT: 2269 return sysctl_int(oldp, oldlenp, newp, newlen, 2270 &icmp6_rediraccept); 2271 case ICMPV6CTL_REDIRTIMEOUT: 2272 return sysctl_int(oldp, oldlenp, newp, newlen, 2273 &icmp6_redirtimeout); 2274 case ICMPV6CTL_STATS: 2275 return sysctl_rdstruct(oldp, oldlenp, newp, 2276 &icmp6stat, sizeof(icmp6stat)); 2277 case ICMPV6CTL_ERRRATELIMIT: 2278 { 2279 int rate_usec, error, s; 2280 2281 /* 2282 * The sysctl specifies the rate in usec-between-icmp, 2283 * so we must convert from/to a timeval. 2284 */ 2285 rate_usec = (icmp6errratelim.tv_sec * 1000000) + 2286 icmp6errratelim.tv_usec; 2287 error = sysctl_int(oldp, oldlenp, newp, newlen, &rate_usec); 2288 if (error) 2289 return (error); 2290 s = splsoftnet(); 2291 icmp6errratelim.tv_sec = rate_usec / 1000000; 2292 icmp6errratelim.tv_usec = rate_usec % 1000000; 2293 splx(s); 2294 2295 return (0); 2296 } 2297 case ICMPV6CTL_ND6_PRUNE: 2298 return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_prune); 2299 case ICMPV6CTL_ND6_DELAY: 2300 return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_delay); 2301 case ICMPV6CTL_ND6_UMAXTRIES: 2302 return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_umaxtries); 2303 case ICMPV6CTL_ND6_MMAXTRIES: 2304 return sysctl_int(oldp, oldlenp, newp, newlen, &nd6_mmaxtries); 2305 case ICMPV6CTL_ND6_USELOOPBACK: 2306 return sysctl_int(oldp, oldlenp, newp, newlen, 2307 &nd6_useloopback); 2308 case ICMPV6CTL_NODEINFO: 2309 return sysctl_int(oldp, oldlenp, newp, newlen, &icmp6_nodeinfo); 2310 default: 2311 return ENOPROTOOPT; 2312 } 2313 /* NOTREACHED */ 2314} 2315