1/* 2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* $FreeBSD: src/sys/netinet6/icmp6.c,v 1.6.2.6 2001/07/10 09:44:16 ume Exp $ */ 30/* $KAME: icmp6.c,v 1.211 2001/04/04 05:56:20 itojun Exp $ */ 31 32/* 33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 34 * 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. Neither the name of the project nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 */ 60 61/* 62 * Copyright (c) 1982, 1986, 1988, 1993 63 * The Regents of the University of California. All rights reserved. 64 * 65 * Redistribution and use in source and binary forms, with or without 66 * modification, are permitted provided that the following conditions 67 * are met: 68 * 1. Redistributions of source code must retain the above copyright 69 * notice, this list of conditions and the following disclaimer. 70 * 2. Redistributions in binary form must reproduce the above copyright 71 * notice, this list of conditions and the following disclaimer in the 72 * documentation and/or other materials provided with the distribution. 73 * 3. All advertising materials mentioning features or use of this software 74 * must display the following acknowledgement: 75 * This product includes software developed by the University of 76 * California, Berkeley and its contributors. 77 * 4. Neither the name of the University nor the names of its contributors 78 * may be used to endorse or promote products derived from this software 79 * without specific prior written permission. 80 * 81 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 82 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 84 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 86 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 87 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 88 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 89 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 90 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 91 * SUCH DAMAGE. 92 * 93 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 94 */ 95 96 97#include <sys/param.h> 98#include <sys/systm.h> 99#include <sys/lock.h> 100#include <sys/malloc.h> 101#include <sys/mcache.h> 102#include <sys/mbuf.h> 103#include <sys/protosw.h> 104#include <sys/socket.h> 105#include <sys/socketvar.h> 106#include <sys/time.h> 107#include <sys/kernel.h> 108#include <sys/syslog.h> 109#include <sys/domain.h> 110#include <sys/kauth.h> 111 112#include <net/if.h> 113#include <net/route.h> 114#include <net/if_dl.h> 115#include <net/if_types.h> 116 117#include <netinet/in.h> 118#include <netinet/in_var.h> 119#include <netinet/ip6.h> 120#include <netinet6/ip6_var.h> 121#include <netinet/icmp6.h> 122#include <netinet6/mld6_var.h> 123#include <netinet/in_pcb.h> 124#include <netinet6/in6_pcb.h> 125#include <netinet6/in6_var.h> 126#include <netinet6/nd6.h> 127#include <netinet6/in6_ifattach.h> 128#include <netinet6/ip6protosw.h> 129#include <netinet6/scope6_var.h> 130 131#if IPSEC 132#include <netinet6/ipsec.h> 133#include <netkey/key.h> 134 135extern int ipsec_bypass; 136#endif 137 138#include <net/net_osdep.h> 139 140extern struct ip6protosw *ip6_protox[]; 141 142extern uint32_t rip_sendspace; 143extern uint32_t rip_recvspace; 144 145struct icmp6stat icmp6stat; 146 147extern struct inpcbhead ripcb; 148extern int icmp6errppslim; 149static int icmp6errpps_count = 0; 150static struct timeval icmp6errppslim_last; 151extern int icmp6_nodeinfo; 152extern struct inpcbinfo ripcbinfo; 153 154static void icmp6_errcount(struct icmp6errstat *, int, int); 155static int icmp6_rip6_input(struct mbuf **, int); 156static int icmp6_ratelimit(const struct in6_addr *, const int, const int); 157static const char *icmp6_redirect_diag(struct in6_addr *, 158 struct in6_addr *, struct in6_addr *); 159static struct mbuf *ni6_input(struct mbuf *, int); 160static struct mbuf *ni6_nametodns(const char *, int, int); 161static int ni6_dnsmatch(const char *, int, const char *, int); 162static int ni6_addrs(struct icmp6_nodeinfo *, 163 struct ifnet **, char *); 164static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *, 165 struct ifnet *, int); 166static int icmp6_notify_error(struct mbuf *, int, int, int); 167 168 169 170void 171icmp6_init(struct ip6protosw *pp, struct domain *dp) 172{ 173#pragma unused(dp) 174 static int icmp6_initialized = 0; 175 176 /* Also called from ip6_init() without pp */ 177 VERIFY(pp == NULL || 178 (pp->pr_flags & (PR_INITIALIZED|PR_ATTACHED)) == PR_ATTACHED); 179 180 /* This gets called by more than one protocols, so initialize once */ 181 if (!icmp6_initialized) { 182 icmp6_initialized = 1; 183 mld_init(); 184 } 185} 186 187static void 188icmp6_errcount(stat, type, code) 189 struct icmp6errstat *stat; 190 int type, code; 191{ 192 switch (type) { 193 case ICMP6_DST_UNREACH: 194 switch (code) { 195 case ICMP6_DST_UNREACH_NOROUTE: 196 stat->icp6errs_dst_unreach_noroute++; 197 return; 198 case ICMP6_DST_UNREACH_ADMIN: 199 stat->icp6errs_dst_unreach_admin++; 200 return; 201 case ICMP6_DST_UNREACH_BEYONDSCOPE: 202 stat->icp6errs_dst_unreach_beyondscope++; 203 return; 204 case ICMP6_DST_UNREACH_ADDR: 205 stat->icp6errs_dst_unreach_addr++; 206 return; 207 case ICMP6_DST_UNREACH_NOPORT: 208 stat->icp6errs_dst_unreach_noport++; 209 return; 210 } 211 break; 212 case ICMP6_PACKET_TOO_BIG: 213 stat->icp6errs_packet_too_big++; 214 return; 215 case ICMP6_TIME_EXCEEDED: 216 switch (code) { 217 case ICMP6_TIME_EXCEED_TRANSIT: 218 stat->icp6errs_time_exceed_transit++; 219 return; 220 case ICMP6_TIME_EXCEED_REASSEMBLY: 221 stat->icp6errs_time_exceed_reassembly++; 222 return; 223 } 224 break; 225 case ICMP6_PARAM_PROB: 226 switch (code) { 227 case ICMP6_PARAMPROB_HEADER: 228 stat->icp6errs_paramprob_header++; 229 return; 230 case ICMP6_PARAMPROB_NEXTHEADER: 231 stat->icp6errs_paramprob_nextheader++; 232 return; 233 case ICMP6_PARAMPROB_OPTION: 234 stat->icp6errs_paramprob_option++; 235 return; 236 } 237 break; 238 case ND_REDIRECT: 239 stat->icp6errs_redirect++; 240 return; 241 } 242 stat->icp6errs_unknown++; 243} 244 245/* 246 * A wrapper function for icmp6_error() necessary when the erroneous packet 247 * may not contain enough scope zone information. 248 */ 249void 250icmp6_error2(struct mbuf *m, int type, int code, int param, 251 struct ifnet *ifp) 252{ 253 struct ip6_hdr *ip6; 254 255 if (ifp == NULL) 256 return; 257 258#ifndef PULLDOWN_TEST 259 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr),return ); 260#else 261 if (m->m_len < sizeof(struct ip6_hdr)) { 262 m = m_pullup(m, sizeof(struct ip6_hdr)); 263 if (m == NULL) 264 return; 265 } 266#endif 267 268 ip6 = mtod(m, struct ip6_hdr *); 269 270 if (in6_setscope(&ip6->ip6_src, ifp, NULL) != 0) 271 return; 272 if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0) 273 return; 274 275 icmp6_error(m, type, code, param); 276} 277 278/* 279 * Generate an error packet of type error in response to bad IP6 packet. 280 */ 281void 282icmp6_error(struct mbuf *m, int type, int code, int param) 283{ 284 struct ip6_hdr *oip6, *nip6; 285 struct icmp6_hdr *icmp6; 286 u_int preplen; 287 int off; 288 int nxt; 289 290 icmp6stat.icp6s_error++; 291 292 /* count per-type-code statistics */ 293 icmp6_errcount(&icmp6stat.icp6s_outerrhist, type, code); 294 295#ifdef M_DECRYPTED /*not openbsd*/ 296 if (m->m_flags & M_DECRYPTED) { 297 icmp6stat.icp6s_canterror++; 298 goto freeit; 299 } 300#endif 301 302#ifndef PULLDOWN_TEST 303 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), return); 304#else 305 if (m->m_len < sizeof(struct ip6_hdr)) { 306 m = m_pullup(m, sizeof(struct ip6_hdr)); 307 if (m == NULL) 308 return; 309 } 310#endif 311 oip6 = mtod(m, struct ip6_hdr *); 312 313 /* 314 * If the destination address of the erroneous packet is a multicast 315 * address, or the packet was sent using link-layer multicast, 316 * we should basically suppress sending an error (RFC 2463, Section 317 * 2.4). 318 * We have two exceptions (the item e.2 in that section): 319 * - the Pakcet Too Big message can be sent for path MTU discovery. 320 * - the Parameter Problem Message that can be allowed an icmp6 error 321 * in the option type field. This check has been done in 322 * ip6_unknown_opt(), so we can just check the type and code. 323 */ 324 if ((m->m_flags & (M_BCAST|M_MCAST) || 325 IN6_IS_ADDR_MULTICAST(&oip6->ip6_dst)) && 326 (type != ICMP6_PACKET_TOO_BIG && 327 (type != ICMP6_PARAM_PROB || 328 code != ICMP6_PARAMPROB_OPTION))) 329 goto freeit; 330 331 /* 332 * RFC 2463, 2.4 (e.5): source address check. 333 * XXX: the case of anycast source? 334 */ 335 if (IN6_IS_ADDR_UNSPECIFIED(&oip6->ip6_src) || 336 IN6_IS_ADDR_MULTICAST(&oip6->ip6_src)) 337 goto freeit; 338 339 /* 340 * If we are about to send ICMPv6 against ICMPv6 error/redirect, 341 * don't do it. 342 */ 343 nxt = -1; 344 off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt); 345 if (off >= 0 && nxt == IPPROTO_ICMPV6) { 346 struct icmp6_hdr *icp; 347 348#ifndef PULLDOWN_TEST 349 IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), return); 350 icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off); 351#else 352 IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off, 353 sizeof(*icp)); 354 if (icp == NULL) { 355 icmp6stat.icp6s_tooshort++; 356 return; 357 } 358#endif 359 if (icp->icmp6_type < ICMP6_ECHO_REQUEST || 360 icp->icmp6_type == ND_REDIRECT) { 361 /* 362 * ICMPv6 error 363 * Special case: for redirect (which is 364 * informational) we must not send icmp6 error. 365 */ 366 icmp6stat.icp6s_canterror++; 367 goto freeit; 368 } else { 369 /* ICMPv6 informational - send the error */ 370 } 371 } else { 372 /* non-ICMPv6 - send the error */ 373 } 374 375 oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */ 376 377 /* Finally, do rate limitation check. */ 378 if (icmp6_ratelimit(&oip6->ip6_src, type, code)) { 379 icmp6stat.icp6s_toofreq++; 380 goto freeit; 381 } 382 383 /* 384 * OK, ICMP6 can be generated. 385 */ 386 387 if (m->m_pkthdr.len >= ICMPV6_PLD_MAXLEN) 388 m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len); 389 390 preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 391 M_PREPEND(m, preplen, M_DONTWAIT); 392 if (m && m->m_len < preplen) 393 m = m_pullup(m, preplen); 394 if (m == NULL) { 395 nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__)); 396 return; 397 } 398 399 nip6 = mtod(m, struct ip6_hdr *); 400 nip6->ip6_src = oip6->ip6_src; 401 nip6->ip6_dst = oip6->ip6_dst; 402 403 in6_clearscope(&oip6->ip6_src); 404 in6_clearscope(&oip6->ip6_dst); 405 406 icmp6 = (struct icmp6_hdr *)(nip6 + 1); 407 icmp6->icmp6_type = type; 408 icmp6->icmp6_code = code; 409 icmp6->icmp6_pptr = htonl((u_int32_t)param); 410 411 /* 412 * icmp6_reflect() is designed to be in the input path. 413 * icmp6_error() can be called from both input and output path, 414 * and if we are in output path rcvif could contain bogus value. 415 * clear m->m_pkthdr.rcvif for safety, we should have enough scope 416 * information in ip header (nip6). 417 */ 418 m->m_pkthdr.rcvif = NULL; 419 420 icmp6stat.icp6s_outhist[type]++; 421 icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */ 422 423 return; 424 425 freeit: 426 /* 427 * If we can't tell whether or not we can generate ICMP6, free it. 428 */ 429 m_freem(m); 430} 431 432/* 433 * Process a received ICMP6 message. 434 */ 435int 436icmp6_input(struct mbuf **mp, int *offp, int proto) 437{ 438#pragma unused(proto) 439 struct mbuf *m = *mp, *n; 440 struct ifnet *ifp; 441 struct ip6_hdr *ip6, *nip6; 442 struct icmp6_hdr *icmp6, *nicmp6; 443 int off = *offp; 444 int icmp6len = m->m_pkthdr.len - *offp; 445 int code, sum, noff, proxy = 0; 446 447 ifp = m->m_pkthdr.rcvif; 448 449#ifndef PULLDOWN_TEST 450 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), return IPPROTO_DONE); 451 /* m might change if M_LOOP. So, call mtod after this */ 452#endif 453 454 /* Expect 32-bit aligned data pointer on strict-align platforms */ 455 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); 456 457 /* 458 * Locate icmp6 structure in mbuf, and check 459 * that not corrupted and of at least minimum length 460 */ 461 ip6 = mtod(m, struct ip6_hdr *); 462 if (icmp6len < sizeof(struct icmp6_hdr)) { 463 icmp6stat.icp6s_tooshort++; 464 goto freeit; 465 } 466 467#ifndef PULLDOWN_TEST 468 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off); 469#else 470 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6)); 471 if (icmp6 == NULL) { 472 icmp6stat.icp6s_tooshort++; 473 return IPPROTO_DONE; 474 } 475#endif 476 code = icmp6->icmp6_code; 477 478 /* Apply rate limit before checksum validation. */ 479 if (icmp6_ratelimit(&ip6->ip6_dst, icmp6->icmp6_type, code)) { 480 icmp6stat.icp6s_toofreq++; 481 goto freeit; 482 } 483 484 /* 485 * Check multicast group membership. 486 * Note: SSM filters are not applied for ICMPv6 traffic. 487 */ 488 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 489 struct in6_multi *inm; 490 491 in6_multihead_lock_shared(); 492 IN6_LOOKUP_MULTI(&ip6->ip6_dst, ifp, inm); 493 in6_multihead_lock_done(); 494 495 if (inm == NULL) { 496 /* 497 * Don't discard if this is a Neighbor Solicitation 498 * that needs to be proxied (see check down below.) 499 */ 500 if (!(m->m_pkthdr.pkt_flags & PKTF_PROXY_DST)) { 501 ip6stat.ip6s_notmember++; 502 in6_ifstat_inc(m->m_pkthdr.rcvif, 503 ifs6_in_discard); 504 goto freeit; 505 } 506 } else { 507 IN6M_REMREF(inm); 508 } 509 } 510 511 /* 512 * calculate the checksum 513 */ 514 if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) { 515 nd6log((LOG_ERR, 516 "ICMP6 checksum error(%d|%x) %s\n", 517 icmp6->icmp6_type, sum, ip6_sprintf(&ip6->ip6_src))); 518 icmp6stat.icp6s_checksum++; 519 goto freeit; 520 } 521 522 if (m->m_pkthdr.pkt_flags & PKTF_PROXY_DST) { 523 /* 524 * This is the special case of proxying NS (dst is either 525 * solicited-node multicast or unicast); process it locally 526 * but don't deliver it to sockets. It practically lets us 527 * steer the packet to nd6_prproxy_ns_input, where more 528 * specific tests and actions will be taken. 529 */ 530 switch (icmp6->icmp6_type) { 531 case ND_NEIGHBOR_SOLICIT: 532 proxy = 1; 533 break; 534 default: 535 goto freeit; 536 } 537 } 538 539 icmp6stat.icp6s_inhist[icmp6->icmp6_type]++; 540 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg); 541 if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK) 542 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error); 543 544 switch (icmp6->icmp6_type) { 545 case ICMP6_DST_UNREACH: 546 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach); 547 switch (code) { 548 case ICMP6_DST_UNREACH_NOROUTE: 549 code = PRC_UNREACH_NET; 550 break; 551 case ICMP6_DST_UNREACH_ADMIN: 552 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_adminprohib); 553 code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ 554 break; 555 case ICMP6_DST_UNREACH_ADDR: 556 code = PRC_HOSTDEAD; 557 break; 558 case ICMP6_DST_UNREACH_BEYONDSCOPE: 559 /* I mean "source address was incorrect." */ 560 code = PRC_PARAMPROB; 561 break; 562 case ICMP6_DST_UNREACH_NOPORT: 563 code = PRC_UNREACH_PORT; 564 break; 565 default: 566 goto badcode; 567 } 568 goto deliver; 569 break; 570 571 case ICMP6_PACKET_TOO_BIG: 572 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig); 573 574 code = PRC_MSGSIZE; 575 576 /* 577 * Updating the path MTU will be done after examining 578 * intermediate extension headers. 579 */ 580 goto deliver; 581 break; 582 583 case ICMP6_TIME_EXCEEDED: 584 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed); 585 switch (code) { 586 case ICMP6_TIME_EXCEED_TRANSIT: 587 code = PRC_TIMXCEED_INTRANS; 588 break; 589 case ICMP6_TIME_EXCEED_REASSEMBLY: 590 code = PRC_TIMXCEED_REASS; 591 break; 592 default: 593 goto badcode; 594 } 595 goto deliver; 596 break; 597 598 case ICMP6_PARAM_PROB: 599 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob); 600 switch (code) { 601 case ICMP6_PARAMPROB_NEXTHEADER: 602 code = PRC_UNREACH_PROTOCOL; 603 break; 604 case ICMP6_PARAMPROB_HEADER: 605 case ICMP6_PARAMPROB_OPTION: 606 code = PRC_PARAMPROB; 607 break; 608 default: 609 goto badcode; 610 } 611 goto deliver; 612 break; 613 614 case ICMP6_ECHO_REQUEST: 615 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo); 616 if (code != 0) 617 goto badcode; 618 619 if ((n = m_copy(m, 0, M_COPYALL)) == NULL) { 620 /* Give up remote */ 621 goto rate_limit_checked; 622 break; 623 } 624 if ((n->m_flags & M_EXT) != 0 625 || n->m_len < off + sizeof(struct icmp6_hdr)) { 626 struct mbuf *n0 = n; 627 const int maxlen = sizeof(*nip6) + sizeof(*nicmp6); 628 629 /* 630 * Prepare an internal mbuf. m_pullup() doesn't 631 * always copy the length we specified. 632 */ 633 if (maxlen >= MCLBYTES) { 634 /* Give up remote */ 635 m_freem(n0); 636 goto rate_limit_checked; 637 break; 638 } 639 MGETHDR(n, M_DONTWAIT, n0->m_type); /* MAC-OK */ 640 if (n && maxlen >= MHLEN) { 641 MCLGET(n, M_DONTWAIT); 642 if ((n->m_flags & M_EXT) == 0) { 643 m_free(n); 644 n = NULL; 645 } 646 } 647 if (n == NULL) { 648 /* Give up remote */ 649 m_freem(n0); 650 goto rate_limit_checked; 651 break; 652 } 653 M_COPY_PKTHDR(n, n0); 654 /* 655 * Copy IPv6 and ICMPv6 only. 656 */ 657 nip6 = mtod(n, struct ip6_hdr *); 658 bcopy(ip6, nip6, sizeof(struct ip6_hdr)); 659 nicmp6 = (struct icmp6_hdr *)(nip6 + 1); 660 bcopy(icmp6, nicmp6, sizeof(struct icmp6_hdr)); 661 noff = sizeof(struct ip6_hdr); 662 n->m_pkthdr.len = n->m_len = 663 noff + sizeof(struct icmp6_hdr); 664 /* 665 * Adjust mbuf. ip6_plen will be adjusted in 666 * ip6_output(). 667 */ 668 m_adj(n0, off + sizeof(struct icmp6_hdr)); 669 n->m_pkthdr.len += n0->m_pkthdr.len; 670 n->m_next = n0; 671 n0->m_flags &= ~M_PKTHDR; 672 } else { 673 nip6 = mtod(n, struct ip6_hdr *); 674 IP6_EXTHDR_GET(nicmp6, struct icmp6_hdr *, n, off, 675 sizeof(*nicmp6)); 676 noff = off; 677 } 678 if(nicmp6 == NULL) 679 panic("nicmp6 is NULL in %s, which isn't good!\n", __FUNCTION__); 680 else { 681 nicmp6->icmp6_type = ICMP6_ECHO_REPLY; 682 nicmp6->icmp6_code = 0; 683 } 684 if (n) { 685 icmp6stat.icp6s_reflect++; 686 icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++; 687 icmp6_reflect(n, noff); 688 } 689 goto rate_limit_checked; 690 break; 691 692 case ICMP6_ECHO_REPLY: 693 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply); 694 if (code != 0) 695 goto badcode; 696 break; 697 698 case MLD_LISTENER_QUERY: 699 case MLD_LISTENER_REPORT: 700 701 if (icmp6len < sizeof(struct mld_hdr)) 702 goto badlen; 703 if (icmp6->icmp6_type == MLD_LISTENER_QUERY) /* XXX: ugly... */ 704 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldquery); 705 else 706 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mldreport); 707 708 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 709 /* give up local */ 710 if (mld_input(m, off, icmp6len) == IPPROTO_DONE) 711 m = NULL; 712 goto freeit; 713 } 714 if (mld_input(n, off, icmp6len) != IPPROTO_DONE) 715 m_freem(n); 716 /* m stays. */ 717 goto rate_limit_checked; 718 break; 719 720 case MLD_LISTENER_DONE: 721 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mlddone); 722 if (icmp6len < sizeof(struct mld_hdr)) /* necessary? */ 723 goto badlen; 724 break; /* nothing to be done in kernel */ 725 726 case MLD_MTRACE_RESP: 727 case MLD_MTRACE: 728 /* XXX: these two are experimental. not officially defined. */ 729 /* XXX: per-interface statistics? */ 730 break; /* just pass it to applications */ 731 732 case ICMP6_NI_QUERY: 733 if (!icmp6_nodeinfo) 734 break; 735//### LD 10/20 Check fbsd differences here. Not sure we're more advanced or not. 736 /* By RFC 4620 refuse to answer queries from global scope addresses */ 737 if ((icmp6_nodeinfo & 8) != 8 && in6_addrscope(&ip6->ip6_src) == IPV6_ADDR_SCOPE_GLOBAL) 738 break; 739 740 if (icmp6len < sizeof(struct icmp6_nodeinfo)) 741 goto badlen; 742 743#ifndef PULLDOWN_TEST 744 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo), 745 return IPPROTO_DONE); 746#endif 747 748 n = m_copy(m, 0, M_COPYALL); 749 if (n) 750 n = ni6_input(n, off); 751 if (n) { 752 noff = sizeof(struct ip6_hdr); 753 icmp6stat.icp6s_reflect++; 754 icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++; 755 icmp6_reflect(n, noff); 756 } 757 goto rate_limit_checked; 758 break; 759 760 case ICMP6_WRUREPLY: 761 if (code != 0) 762 goto badcode; 763 break; 764 765 case ND_ROUTER_SOLICIT: 766 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit); 767 if (code != 0) 768 goto badcode; 769 if (icmp6len < sizeof(struct nd_router_solicit)) 770 goto badlen; 771 772 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 773 /* give up local */ 774 nd6_rs_input(m, off, icmp6len); 775 m = NULL; 776 goto freeit; 777 } 778 nd6_rs_input(n, off, icmp6len); 779 /* m stays. */ 780 goto rate_limit_checked; 781 break; 782 783 case ND_ROUTER_ADVERT: 784 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert); 785 if (code != 0) 786 goto badcode; 787 if (icmp6len < sizeof(struct nd_router_advert)) 788 goto badlen; 789 790 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 791 /* give up local */ 792 nd6_ra_input(m, off, icmp6len); 793 m = NULL; 794 goto freeit; 795 } 796 nd6_ra_input(n, off, icmp6len); 797 /* m stays. */ 798 goto rate_limit_checked; 799 break; 800 801 case ND_NEIGHBOR_SOLICIT: 802 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit); 803 if (code != 0) 804 goto badcode; 805 if (icmp6len < sizeof(struct nd_neighbor_solicit)) 806 goto badlen; 807 808 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 809 /* give up local */ 810 nd6_ns_input(m, off, icmp6len); 811 m = NULL; 812 goto freeit; 813 } 814 nd6_ns_input(n, off, icmp6len); 815 /* m stays. */ 816 goto rate_limit_checked; 817 break; 818 819 case ND_NEIGHBOR_ADVERT: 820 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert); 821 if (code != 0) 822 goto badcode; 823 if (icmp6len < sizeof(struct nd_neighbor_advert)) 824 goto badlen; 825 826 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 827 /* give up local */ 828 nd6_na_input(m, off, icmp6len); 829 m = NULL; 830 goto freeit; 831 } 832 nd6_na_input(n, off, icmp6len); 833 /* m stays. */ 834 goto rate_limit_checked; 835 break; 836 837 case ND_REDIRECT: 838 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect); 839 if (code != 0) 840 goto badcode; 841 if (icmp6len < sizeof(struct nd_redirect)) 842 goto badlen; 843 844 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 845 /* give up local */ 846 icmp6_redirect_input(m, off); 847 m = NULL; 848 goto freeit; 849 } 850 icmp6_redirect_input(n, off); 851 /* m stays. */ 852 goto rate_limit_checked; 853 break; 854 855 case ICMP6_ROUTER_RENUMBERING: 856 if (code != ICMP6_ROUTER_RENUMBERING_COMMAND && 857 code != ICMP6_ROUTER_RENUMBERING_RESULT) 858 goto badcode; 859 if (icmp6len < sizeof(struct icmp6_router_renum)) 860 goto badlen; 861 break; 862 863 default: 864 nd6log((LOG_DEBUG, 865 "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n", 866 icmp6->icmp6_type, ip6_sprintf(&ip6->ip6_src), 867 ip6_sprintf(&ip6->ip6_dst), 868 m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0)); 869 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { 870 /* ICMPv6 error: MUST deliver it by spec... */ 871 code = PRC_NCMDS; 872 /* deliver */ 873 } else { 874 /* ICMPv6 informational: MUST not deliver */ 875 goto rate_limit_checked; 876 break; 877 } 878 deliver: 879 if (icmp6_notify_error(m, off, icmp6len, code)) { 880 /* In this case, m should've been freed. */ 881 return(IPPROTO_DONE); 882 } 883 break; 884 885 badcode: 886 icmp6stat.icp6s_badcode++; 887 break; 888 889 badlen: 890 icmp6stat.icp6s_badlen++; 891 break; 892 } 893 894rate_limit_checked: 895 /* deliver the packet to appropriate sockets (unless proxying) */ 896 if (!proxy) { 897 icmp6_rip6_input(&m, *offp); 898 return IPPROTO_DONE; 899 } 900 901freeit: 902 m_freem(m); 903 return IPPROTO_DONE; 904} 905 906static int 907icmp6_notify_error(m, off, icmp6len, code) 908 struct mbuf *m; 909 int off, icmp6len, code; 910{ 911 struct icmp6_hdr *icmp6; 912 struct ip6_hdr *eip6; 913 u_int32_t notifymtu; 914 struct sockaddr_in6 icmp6src, icmp6dst; 915 916 if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) { 917 icmp6stat.icp6s_tooshort++; 918 goto freeit; 919 } 920#ifndef PULLDOWN_TEST 921 IP6_EXTHDR_CHECK(m, off, 922 sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr), 923 return -1); 924 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off); 925#else 926 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 927 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 928 if (icmp6 == NULL) { 929 icmp6stat.icp6s_tooshort++; 930 return(-1); 931 } 932#endif 933 eip6 = (struct ip6_hdr *)(icmp6 + 1); 934 935 /* Detect the upper level protocol */ 936 { 937 void (*ctlfunc)(int, struct sockaddr *, void *); 938 u_int8_t nxt = eip6->ip6_nxt; 939 int eoff = off + sizeof(struct icmp6_hdr) + 940 sizeof(struct ip6_hdr); 941 struct ip6ctlparam ip6cp; 942 struct in6_addr *finaldst = NULL; 943 int icmp6type = icmp6->icmp6_type; 944 struct ip6_frag *fh; 945 struct ip6_rthdr *rth; 946 struct ip6_rthdr0 *rth0; 947 int rthlen; 948 949 while (1) { /* XXX: should avoid infinite loop explicitly? */ 950 struct ip6_ext *eh; 951 952 switch (nxt) { 953 case IPPROTO_HOPOPTS: 954 case IPPROTO_DSTOPTS: 955 case IPPROTO_AH: 956#ifndef PULLDOWN_TEST 957 IP6_EXTHDR_CHECK(m, 0, eoff + 958 sizeof(struct ip6_ext), 959 return -1); 960 eh = (struct ip6_ext *)(mtod(m, caddr_t) 961 + eoff); 962#else 963 IP6_EXTHDR_GET(eh, struct ip6_ext *, m, 964 eoff, sizeof(*eh)); 965 if (eh == NULL) { 966 icmp6stat.icp6s_tooshort++; 967 return(-1); 968 } 969#endif 970 971 if (nxt == IPPROTO_AH) 972 eoff += (eh->ip6e_len + 2) << 2; 973 else 974 eoff += (eh->ip6e_len + 1) << 3; 975 nxt = eh->ip6e_nxt; 976 break; 977 case IPPROTO_ROUTING: 978 /* 979 * When the erroneous packet contains a 980 * routing header, we should examine the 981 * header to determine the final destination. 982 * Otherwise, we can't properly update 983 * information that depends on the final 984 * destination (e.g. path MTU). 985 */ 986#ifndef PULLDOWN_TEST 987 IP6_EXTHDR_CHECK(m, 0, eoff + sizeof(*rth), 988 return -1); 989 rth = (struct ip6_rthdr *)(mtod(m, caddr_t) 990 + eoff); 991#else 992 IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m, 993 eoff, sizeof(*rth)); 994 if (rth == NULL) { 995 icmp6stat.icp6s_tooshort++; 996 return(-1); 997 } 998#endif 999 rthlen = (rth->ip6r_len + 1) << 3; 1000 /* 1001 * XXX: currently there is no 1002 * officially defined type other 1003 * than type-0. 1004 * Note that if the segment left field 1005 * is 0, all intermediate hops must 1006 * have been passed. 1007 */ 1008 if (rth->ip6r_segleft && 1009 rth->ip6r_type == IPV6_RTHDR_TYPE_0) { 1010 int hops; 1011 1012#ifndef PULLDOWN_TEST 1013 IP6_EXTHDR_CHECK(m, 0, eoff + rthlen, 1014 return -1); 1015 rth0 = (struct ip6_rthdr0 *)(mtod(m, caddr_t) + eoff); 1016#else 1017 IP6_EXTHDR_GET(rth0, 1018 struct ip6_rthdr0 *, m, 1019 eoff, rthlen); 1020 if (rth0 == NULL) { 1021 icmp6stat.icp6s_tooshort++; 1022 return(-1); 1023 } 1024#endif 1025 /* just ignore a bogus header */ 1026 if ((rth0->ip6r0_len % 2) == 0 && 1027 (hops = rth0->ip6r0_len/2)) 1028 finaldst = (struct in6_addr *)(void *)(rth0 + 1) + (hops - 1); 1029 } 1030 eoff += rthlen; 1031 nxt = rth->ip6r_nxt; 1032 break; 1033 case IPPROTO_FRAGMENT: 1034#ifndef PULLDOWN_TEST 1035 IP6_EXTHDR_CHECK(m, 0, eoff + 1036 sizeof(struct ip6_frag), 1037 return -1); 1038 fh = (struct ip6_frag *)(mtod(m, caddr_t) 1039 + eoff); 1040#else 1041 IP6_EXTHDR_GET(fh, struct ip6_frag *, m, 1042 eoff, sizeof(*fh)); 1043 if (fh == NULL) { 1044 icmp6stat.icp6s_tooshort++; 1045 return (-1); 1046 } 1047#endif 1048 /* 1049 * Data after a fragment header is meaningless 1050 * unless it is the first fragment, but 1051 * we'll go to the notify label for path MTU 1052 * discovery. 1053 */ 1054 if (fh->ip6f_offlg & IP6F_OFF_MASK) 1055 goto notify; 1056 1057 eoff += sizeof(struct ip6_frag); 1058 nxt = fh->ip6f_nxt; 1059 break; 1060 default: 1061 /* 1062 * This case includes ESP and the No Next 1063 * Header. In such cases going to the notify 1064 * label does not have any meaning 1065 * (i.e. ctlfunc will be NULL), but we go 1066 * anyway since we might have to update 1067 * path MTU information. 1068 */ 1069 goto notify; 1070 } 1071 } 1072 notify: 1073#ifndef PULLDOWN_TEST 1074 icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off); 1075#else 1076 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, 1077 sizeof(*icmp6) + sizeof(struct ip6_hdr)); 1078 if (icmp6 == NULL) { 1079 icmp6stat.icp6s_tooshort++; 1080 return (-1); 1081 } 1082#endif 1083 1084 /* 1085 * retrieve parameters from the inner IPv6 header, and convert 1086 * them into sockaddr structures. 1087 * XXX: there is no guarantee that the source or destination 1088 * addresses of the inner packet are in the same scope as 1089 * the addresses of the icmp packet. But there is no other 1090 * way to determine the zone. 1091 */ 1092 eip6 = (struct ip6_hdr *)(icmp6 + 1); 1093 1094 bzero(&icmp6dst, sizeof(icmp6dst)); 1095 icmp6dst.sin6_len = sizeof(struct sockaddr_in6); 1096 icmp6dst.sin6_family = AF_INET6; 1097 if (finaldst == NULL) 1098 icmp6dst.sin6_addr = eip6->ip6_dst; 1099 else 1100 icmp6dst.sin6_addr = *finaldst; 1101 if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL)) 1102 goto freeit; 1103 bzero(&icmp6src, sizeof(icmp6src)); 1104 icmp6src.sin6_len = sizeof(struct sockaddr_in6); 1105 icmp6src.sin6_family = AF_INET6; 1106 icmp6src.sin6_addr = eip6->ip6_src; 1107 if (in6_setscope(&icmp6src.sin6_addr, m->m_pkthdr.rcvif, NULL)) 1108 goto freeit; 1109 icmp6src.sin6_flowinfo = 1110 (eip6->ip6_flow & IPV6_FLOWLABEL_MASK); 1111 1112 if (finaldst == NULL) 1113 finaldst = &eip6->ip6_dst; 1114 ip6cp.ip6c_m = m; 1115 ip6cp.ip6c_icmp6 = icmp6; 1116 ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1); 1117 ip6cp.ip6c_off = eoff; 1118 ip6cp.ip6c_finaldst = finaldst; 1119 ip6cp.ip6c_src = &icmp6src; 1120 ip6cp.ip6c_nxt = nxt; 1121 1122 if (icmp6type == ICMP6_PACKET_TOO_BIG) { 1123 notifymtu = ntohl(icmp6->icmp6_mtu); 1124 ip6cp.ip6c_cmdarg = (void *)¬ifymtu; 1125 icmp6_mtudisc_update(&ip6cp, 1); /*XXX*/ 1126 } 1127 1128 ctlfunc = (void (*)(int, struct sockaddr *, void *)) 1129 (ip6_protox[nxt]->pr_ctlinput); 1130 if (ctlfunc) { 1131 (void) (*ctlfunc)(code, (struct sockaddr *)&icmp6dst, 1132 &ip6cp); 1133 } 1134 } 1135 return(0); 1136 1137freeit: 1138 m_freem(m); 1139 return(-1); 1140} 1141 1142void 1143icmp6_mtudisc_update(ip6cp, validated) 1144 struct ip6ctlparam *ip6cp; 1145 int validated; 1146{ 1147 struct in6_addr *dst = ip6cp->ip6c_finaldst; 1148 struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6; 1149 struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */ 1150 u_int mtu = ntohl(icmp6->icmp6_mtu); 1151 struct rtentry *rt = NULL; 1152 struct sockaddr_in6 sin6; 1153 /* 1154 * we reject ICMPv6 too big with abnormally small value. 1155 * XXX what is the good definition of "abnormally small"? 1156 */ 1157 if (mtu < sizeof(struct ip6_hdr) + sizeof(struct ip6_frag) + 8) 1158 return; 1159 1160 if (!validated) 1161 return; 1162 1163 /* 1164 * In case the suggested mtu is less than IPV6_MMTU, we 1165 * only need to remember that it was for above mentioned 1166 * "alwaysfrag" case. 1167 * Try to be as close to the spec as possible. 1168 */ 1169 if (mtu < IPV6_MMTU) 1170 mtu = IPV6_MMTU - 8; 1171 1172 bzero(&sin6, sizeof(sin6)); 1173 sin6.sin6_family = PF_INET6; 1174 sin6.sin6_len = sizeof(struct sockaddr_in6); 1175 sin6.sin6_addr = *dst; 1176 /* XXX normally, this won't happen */ 1177 if (IN6_IS_ADDR_LINKLOCAL(dst)) { 1178 sin6.sin6_addr.s6_addr16[1] = 1179 htons(m->m_pkthdr.rcvif->if_index); 1180 } 1181 /* sin6.sin6_scope_id = XXX: should be set if DST is a scoped addr */ 1182 rt = rtalloc1_scoped((struct sockaddr *)&sin6, 0, 1183 RTF_CLONING | RTF_PRCLONING, m->m_pkthdr.rcvif->if_index); 1184 if (rt != NULL) { 1185 RT_LOCK(rt); 1186 if ((rt->rt_flags & RTF_HOST) && 1187 !(rt->rt_rmx.rmx_locks & RTV_MTU) && 1188 mtu < IN6_LINKMTU(rt->rt_ifp) && 1189 rt->rt_rmx.rmx_mtu > mtu) { 1190 icmp6stat.icp6s_pmtuchg++; 1191 rt->rt_rmx.rmx_mtu = mtu; 1192 } 1193 RT_UNLOCK(rt); 1194 rtfree(rt); 1195 } 1196} 1197 1198/* 1199 * Process a Node Information Query packet, based on 1200 * draft-ietf-ipngwg-icmp-name-lookups-07. 1201 * 1202 * Spec incompatibilities: 1203 * - IPv6 Subject address handling 1204 * - IPv4 Subject address handling support missing 1205 * - Proxy reply (answer even if it's not for me) 1206 * - joins NI group address at in6_ifattach() time only, does not cope 1207 * with hostname changes by sethostname(3) 1208 */ 1209#define hostnamelen strlen(hostname) 1210static struct mbuf * 1211ni6_input(m, off) 1212 struct mbuf *m; 1213 int off; 1214{ 1215 struct icmp6_nodeinfo *ni6, *nni6; 1216 struct mbuf *n = NULL; 1217 u_int16_t qtype; 1218 int subjlen; 1219 int replylen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo); 1220 struct ni_reply_fqdn *fqdn; 1221 int addrs; /* for NI_QTYPE_NODEADDR */ 1222 struct ifnet *ifp = NULL; /* for NI_QTYPE_NODEADDR */ 1223 struct sockaddr_in6 sin6; /* double meaning; ip6_dst and subjectaddr */ 1224 struct sockaddr_in6 sin6_d; /* XXX: we should retrieve this from m_aux */ 1225 struct ip6_hdr *ip6; 1226 int oldfqdn = 0; /* if 1, return pascal string (03 draft) */ 1227 char *subj = NULL; 1228 1229 ip6 = mtod(m, struct ip6_hdr *); 1230#ifndef PULLDOWN_TEST 1231 ni6 = (struct icmp6_nodeinfo *)(mtod(m, caddr_t) + off); 1232#else 1233 IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6)); 1234 if (ni6 == NULL) { 1235 /* m is already reclaimed */ 1236 return (NULL); 1237 } 1238#endif 1239 1240 /* 1241 * Validate IPv6 source address. 1242 * The default configuration MUST be to refuse answering queries from 1243 * global-scope addresses according to RFC4602. 1244 * Notes: 1245 * - it's not very clear what "refuse" means; this implementation 1246 * simply drops it. 1247 * - it's not very easy to identify global-scope (unicast) addresses 1248 * since there are many prefixes for them. It should be safer 1249 * and in practice sufficient to check "all" but loopback and 1250 * link-local (note that site-local unicast was deprecated and 1251 * ULA is defined as global scope-wise) 1252 */ 1253 if ((icmp6_nodeinfo & ICMP6_NODEINFO_GLOBALOK) == 0 && 1254 !IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) && 1255 !IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) 1256 goto bad; 1257 1258 /* 1259 * Validate IPv6 destination address. 1260 * 1261 * The Responder must discard the Query without further processing 1262 * unless it is one of the Responder's unicast or anycast addresses, or 1263 * a link-local scope multicast address which the Responder has joined. 1264 * [RFC4602, Section 5.] 1265 */ 1266 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 1267 if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) 1268 goto bad; 1269 /* else it's a link-local multicast, fine */ 1270 } else { /* unicast or anycast */ 1271 uint32_t ia6_flags; 1272 1273 if (ip6_getdstifaddr_info(m, NULL, &ia6_flags) != 0) 1274 goto bad; /* XXX impossible */ 1275 1276 if ((ia6_flags & IN6_IFF_TEMPORARY) && 1277 !(icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) { 1278 nd6log((LOG_DEBUG, "ni6_input: ignore node info to " 1279 "a temporary address in %s:%d", 1280 __FILE__, __LINE__)); 1281 goto bad; 1282 } 1283 } 1284 1285 /* validate query Subject field. */ 1286 qtype = ntohs(ni6->ni_qtype); 1287 subjlen = m->m_pkthdr.len - off - sizeof(struct icmp6_nodeinfo); 1288 switch (qtype) { 1289 case NI_QTYPE_NOOP: 1290 case NI_QTYPE_SUPTYPES: 1291 /* 07 draft */ 1292 if (ni6->ni_code == ICMP6_NI_SUBJ_FQDN && subjlen == 0) 1293 break; 1294 /* FALLTHROUGH */ 1295 case NI_QTYPE_FQDN: 1296 case NI_QTYPE_NODEADDR: 1297 case NI_QTYPE_IPV4ADDR: 1298 switch (ni6->ni_code) { 1299 case ICMP6_NI_SUBJ_IPV6: 1300#if ICMP6_NI_SUBJ_IPV6 != 0 1301 case 0: 1302#endif 1303 /* 1304 * backward compatibility - try to accept 03 draft 1305 * format, where no Subject is present. 1306 */ 1307 if (qtype == NI_QTYPE_FQDN && ni6->ni_code == 0 && 1308 subjlen == 0) { 1309 oldfqdn++; 1310 break; 1311 } 1312#if ICMP6_NI_SUBJ_IPV6 != 0 1313 if (ni6->ni_code != ICMP6_NI_SUBJ_IPV6) 1314 goto bad; 1315#endif 1316 1317 if (subjlen != sizeof(struct in6_addr)) 1318 goto bad; 1319 1320 /* 1321 * Validate Subject address. 1322 * 1323 * Not sure what exactly "address belongs to the node" 1324 * means in the spec, is it just unicast, or what? 1325 * 1326 * At this moment we consider Subject address as 1327 * "belong to the node" if the Subject address equals 1328 * to the IPv6 destination address; validation for 1329 * IPv6 destination address should have done enough 1330 * check for us. 1331 * 1332 * We do not do proxy at this moment. 1333 */ 1334 /* m_pulldown instead of copy? */ 1335 m_copydata(m, off + sizeof(struct icmp6_nodeinfo), 1336 subjlen, (caddr_t)&sin6.sin6_addr); 1337 sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif, 1338 &sin6.sin6_addr); 1339 in6_embedscope(&sin6.sin6_addr, &sin6, NULL, NULL, 1340 NULL); 1341 bzero(&sin6_d, sizeof(sin6_d)); 1342 sin6_d.sin6_family = AF_INET6; /* not used, actually */ 1343 sin6_d.sin6_len = sizeof(sin6_d); /* ditto */ 1344 sin6_d.sin6_addr = ip6->ip6_dst; 1345 sin6_d.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif, 1346 &ip6->ip6_dst); 1347 in6_embedscope(&sin6_d.sin6_addr, &sin6_d, NULL, NULL, 1348 NULL); 1349 subj = (char *)&sin6; 1350 if (SA6_ARE_ADDR_EQUAL(&sin6, &sin6_d)) 1351 break; 1352 1353 /* 1354 * XXX if we are to allow other cases, we should really 1355 * be careful about scope here. 1356 * basically, we should disallow queries toward IPv6 1357 * destination X with subject Y, 1358 * if scope(X) > scope(Y). 1359 * if we allow scope(X) > scope(Y), it will result in 1360 * information leakage across scope boundary. 1361 */ 1362 goto bad; 1363 1364 case ICMP6_NI_SUBJ_FQDN: 1365 /* 1366 * Validate Subject name with gethostname(3). 1367 * 1368 * The behavior may need some debate, since: 1369 * - we are not sure if the node has FQDN as 1370 * hostname (returned by gethostname(3)). 1371 * - the code does wildcard match for truncated names. 1372 * however, we are not sure if we want to perform 1373 * wildcard match, if gethostname(3) side has 1374 * truncated hostname. 1375 */ 1376 n = ni6_nametodns(hostname, hostnamelen, 0); 1377 if (!n || n->m_next || n->m_len == 0) 1378 goto bad; 1379 IP6_EXTHDR_GET(subj, char *, m, 1380 off + sizeof(struct icmp6_nodeinfo), subjlen); 1381 if (subj == NULL) 1382 goto bad; 1383 if (!ni6_dnsmatch(subj, subjlen, mtod(n, const char *), 1384 n->m_len)) { 1385 goto bad; 1386 } 1387 m_freem(n); 1388 n = NULL; 1389 break; 1390 1391 case ICMP6_NI_SUBJ_IPV4: /* XXX: to be implemented? */ 1392 default: 1393 goto bad; 1394 } 1395 break; 1396 } 1397 1398 /* refuse based on configuration. XXX ICMP6_NI_REFUSED? */ 1399 switch (qtype) { 1400 case NI_QTYPE_FQDN: 1401 if ((icmp6_nodeinfo & ICMP6_NODEINFO_FQDNOK) == 0) 1402 goto bad; 1403 break; 1404 case NI_QTYPE_NODEADDR: 1405 case NI_QTYPE_IPV4ADDR: 1406 if ((icmp6_nodeinfo & ICMP6_NODEINFO_NODEADDROK) == 0) 1407 goto bad; 1408 break; 1409 } 1410 1411 /* guess reply length */ 1412 switch (qtype) { 1413 case NI_QTYPE_NOOP: 1414 break; /* no reply data */ 1415 case NI_QTYPE_SUPTYPES: 1416 replylen += sizeof(u_int32_t); 1417 break; 1418 case NI_QTYPE_FQDN: 1419 /* XXX will append an mbuf */ 1420 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen); 1421 break; 1422 case NI_QTYPE_NODEADDR: 1423 addrs = ni6_addrs(ni6, &ifp, subj); 1424 if ((replylen += addrs * (sizeof(struct in6_addr) + 1425 sizeof(u_int32_t))) > MCLBYTES) 1426 replylen = MCLBYTES; /* XXX: will truncate pkt later */ 1427 break; 1428 case NI_QTYPE_IPV4ADDR: 1429 /* unsupported - should respond with unknown Qtype? */ 1430 break; 1431 default: 1432 /* 1433 * XXX: We must return a reply with the ICMP6 code 1434 * `unknown Qtype' in this case. However we regard the case 1435 * as an FQDN query for backward compatibility. 1436 * Older versions set a random value to this field, 1437 * so it rarely varies in the defined qtypes. 1438 * But the mechanism is not reliable... 1439 * maybe we should obsolete older versions. 1440 */ 1441 qtype = NI_QTYPE_FQDN; 1442 /* XXX will append an mbuf */ 1443 replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen); 1444 oldfqdn++; 1445 break; 1446 } 1447 1448 /* allocate an mbuf to reply. */ 1449 MGETHDR(n, M_DONTWAIT, m->m_type); /* MAC-OK */ 1450 if (n == NULL) { 1451 m_freem(m); 1452 if (ifp != NULL) 1453 ifnet_release(ifp); 1454 return (NULL); 1455 } 1456 M_COPY_PKTHDR(n, m); /* just for recvif */ 1457 if (replylen > MHLEN) { 1458 if (replylen > MCLBYTES) { 1459 /* 1460 * XXX: should we try to allocate more? But MCLBYTES 1461 * is probably much larger than IPV6_MMTU... 1462 */ 1463 goto bad; 1464 } 1465 MCLGET(n, M_DONTWAIT); 1466 if ((n->m_flags & M_EXT) == 0) { 1467 goto bad; 1468 } 1469 } 1470 n->m_pkthdr.len = n->m_len = replylen; 1471 1472 /* copy mbuf header and IPv6 + Node Information base headers */ 1473 bcopy(mtod(m, caddr_t), mtod(n, caddr_t), sizeof(struct ip6_hdr)); 1474 nni6 = (struct icmp6_nodeinfo *)(mtod(n, struct ip6_hdr *) + 1); 1475 bcopy((caddr_t)ni6, (caddr_t)nni6, sizeof(struct icmp6_nodeinfo)); 1476 1477 /* qtype dependent procedure */ 1478 switch (qtype) { 1479 case NI_QTYPE_NOOP: 1480 nni6->ni_code = ICMP6_NI_SUCCESS; 1481 nni6->ni_flags = 0; 1482 break; 1483 case NI_QTYPE_SUPTYPES: 1484 { 1485 u_int32_t v; 1486 nni6->ni_code = ICMP6_NI_SUCCESS; 1487 nni6->ni_flags = htons(0x0000); /* raw bitmap */ 1488 /* supports NOOP, SUPTYPES, FQDN, and NODEADDR */ 1489 v = (u_int32_t)htonl(0x0000000f); 1490 bcopy(&v, nni6 + 1, sizeof(u_int32_t)); 1491 break; 1492 } 1493 case NI_QTYPE_FQDN: 1494 nni6->ni_code = ICMP6_NI_SUCCESS; 1495 fqdn = (struct ni_reply_fqdn *)(mtod(n, caddr_t) + 1496 sizeof(struct ip6_hdr) + 1497 sizeof(struct icmp6_nodeinfo)); 1498 nni6->ni_flags = 0; /* XXX: meaningless TTL */ 1499 fqdn->ni_fqdn_ttl = 0; /* ditto. */ 1500 /* 1501 * XXX do we really have FQDN in variable "hostname"? 1502 */ 1503 n->m_next = ni6_nametodns(hostname, hostnamelen, oldfqdn); 1504 if (n->m_next == NULL) 1505 goto bad; 1506 /* XXX we assume that n->m_next is not a chain */ 1507 if (n->m_next->m_next != NULL) 1508 goto bad; 1509 n->m_pkthdr.len += n->m_next->m_len; 1510 break; 1511 case NI_QTYPE_NODEADDR: 1512 { 1513 int lenlim, copied; 1514 1515 nni6->ni_code = ICMP6_NI_SUCCESS; 1516 n->m_pkthdr.len = n->m_len = 1517 sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo); 1518 lenlim = M_TRAILINGSPACE(n); 1519 copied = ni6_store_addrs(ni6, nni6, ifp, lenlim); 1520 /* XXX: reset mbuf length */ 1521 n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) + 1522 sizeof(struct icmp6_nodeinfo) + copied; 1523 break; 1524 } 1525 default: 1526 break; /* XXX impossible! */ 1527 } 1528 1529 nni6->ni_type = ICMP6_NI_REPLY; 1530 m_freem(m); 1531 if (ifp != NULL) 1532 ifnet_release(ifp); 1533 return (n); 1534 1535bad: 1536 m_freem(m); 1537 if (n) 1538 m_freem(n); 1539 if (ifp != NULL) 1540 ifnet_release(ifp); 1541 return (NULL); 1542} 1543#undef hostnamelen 1544 1545/* 1546 * make a mbuf with DNS-encoded string. no compression support. 1547 * 1548 * XXX names with less than 2 dots (like "foo" or "foo.section") will be 1549 * treated as truncated name (two \0 at the end). this is a wild guess. 1550 */ 1551static struct mbuf * 1552ni6_nametodns(name, namelen, old) 1553 const char *name; 1554 int namelen; 1555 int old; /* return pascal string if non-zero */ 1556{ 1557 struct mbuf *m; 1558 char *cp, *ep; 1559 const char *p, *q; 1560 int i, len, nterm; 1561 1562 if (old) 1563 len = namelen + 1; 1564 else 1565 len = MCLBYTES; 1566 1567 /* because MAXHOSTNAMELEN is usually 256, we use cluster mbuf */ 1568 MGET(m, M_DONTWAIT, MT_DATA); 1569 if (m && len > MLEN) { 1570 MCLGET(m, M_DONTWAIT); 1571 if ((m->m_flags & M_EXT) == 0) 1572 goto fail; 1573 } 1574 if (!m) 1575 goto fail; 1576 m->m_next = NULL; 1577 1578 if (old) { 1579 m->m_len = len; 1580 *mtod(m, char *) = namelen; 1581 bcopy(name, mtod(m, char *) + 1, namelen); 1582 return m; 1583 } else { 1584 m->m_len = 0; 1585 cp = mtod(m, char *); 1586 ep = mtod(m, char *) + M_TRAILINGSPACE(m); 1587 1588 /* if not certain about my name, return empty buffer */ 1589 if (namelen == 0) 1590 return m; 1591 1592 /* 1593 * guess if it looks like shortened hostname, or FQDN. 1594 * shortened hostname needs two trailing "\0". 1595 */ 1596 i = 0; 1597 for (p = name; p < name + namelen; p++) { 1598 if (*p && *p == '.') 1599 i++; 1600 } 1601 if (i < 2) 1602 nterm = 2; 1603 else 1604 nterm = 1; 1605 1606 p = name; 1607 while (cp < ep && p < name + namelen) { 1608 i = 0; 1609 for (q = p; q < name + namelen && *q && *q != '.'; q++) 1610 i++; 1611 /* result does not fit into mbuf */ 1612 if (cp + i + 1 >= ep) 1613 goto fail; 1614 /* 1615 * DNS label length restriction, RFC1035 page 8. 1616 * "i == 0" case is included here to avoid returning 1617 * 0-length label on "foo..bar". 1618 */ 1619 if (i <= 0 || i >= 64) 1620 goto fail; 1621 *cp++ = i; 1622 bcopy(p, cp, i); 1623 cp += i; 1624 p = q; 1625 if (p < name + namelen && *p == '.') 1626 p++; 1627 } 1628 /* termination */ 1629 if (cp + nterm >= ep) 1630 goto fail; 1631 while (nterm-- > 0) 1632 *cp++ = '\0'; 1633 m->m_len = cp - mtod(m, char *); 1634 return m; 1635 } 1636 1637 panic("should not reach here"); 1638 /* NOTREACHED */ 1639 1640 fail: 1641 if (m) 1642 m_freem(m); 1643 return NULL; 1644} 1645 1646/* 1647 * check if two DNS-encoded string matches. takes care of truncated 1648 * form (with \0\0 at the end). no compression support. 1649 * XXX upper/lowercase match (see RFC2065) 1650 */ 1651static int 1652ni6_dnsmatch(a, alen, b, blen) 1653 const char *a; 1654 int alen; 1655 const char *b; 1656 int blen; 1657{ 1658 const char *a0, *b0; 1659 int l; 1660 1661 /* simplest case - need validation? */ 1662 if (alen == blen && bcmp(a, b, alen) == 0) 1663 return 1; 1664 1665 a0 = a; 1666 b0 = b; 1667 1668 /* termination is mandatory */ 1669 if (alen < 2 || blen < 2) 1670 return 0; 1671 if (a0[alen - 1] != '\0' || b0[blen - 1] != '\0') 1672 return 0; 1673 alen--; 1674 blen--; 1675 1676 while (a - a0 < alen && b - b0 < blen) { 1677 if (a - a0 + 1 > alen || b - b0 + 1 > blen) 1678 return 0; 1679 1680 if ((signed char)a[0] < 0 || (signed char)b[0] < 0) 1681 return 0; 1682 /* we don't support compression yet */ 1683 if (a[0] >= 64 || b[0] >= 64) 1684 return 0; 1685 1686 /* truncated case */ 1687 if (a[0] == 0 && a - a0 == alen - 1) 1688 return 1; 1689 if (b[0] == 0 && b - b0 == blen - 1) 1690 return 1; 1691 if (a[0] == 0 || b[0] == 0) 1692 return 0; 1693 1694 if (a[0] != b[0]) 1695 return 0; 1696 l = a[0]; 1697 if (a - a0 + 1 + l > alen || b - b0 + 1 + l > blen) 1698 return 0; 1699 if (bcmp(a + 1, b + 1, l) != 0) 1700 return 0; 1701 1702 a += 1 + l; 1703 b += 1 + l; 1704 } 1705 1706 if (a - a0 == alen && b - b0 == blen) 1707 return 1; 1708 else 1709 return 0; 1710} 1711 1712/* 1713 * calculate the number of addresses to be returned in the node info reply. 1714 */ 1715static int 1716ni6_addrs(ni6, ifpp, subj) 1717 struct icmp6_nodeinfo *ni6; 1718 struct ifnet **ifpp; 1719 char *subj; 1720{ 1721 struct ifnet *ifp; 1722 struct in6_ifaddr *ifa6; 1723 struct ifaddr *ifa; 1724 struct sockaddr_in6 *subj_ip6 = NULL; /* XXX pedant */ 1725 int addrs = 0, addrsofif, iffound = 0; 1726 int niflags = ni6->ni_flags; 1727 1728 if (ifpp != NULL) 1729 *ifpp = NULL; 1730 1731 if ((niflags & NI_NODEADDR_FLAG_ALL) == 0) { 1732 switch (ni6->ni_code) { 1733 case ICMP6_NI_SUBJ_IPV6: 1734 if (subj == NULL) /* must be impossible... */ 1735 return(0); 1736 subj_ip6 = (struct sockaddr_in6 *)(void *)subj; 1737 break; 1738 default: 1739 /* 1740 * XXX: we only support IPv6 subject address for 1741 * this Qtype. 1742 */ 1743 return (0); 1744 } 1745 } 1746 1747 ifnet_head_lock_shared(); 1748 TAILQ_FOREACH(ifp, &ifnet_head, if_list) { 1749 addrsofif = 0; 1750 ifnet_lock_shared(ifp); 1751 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) 1752 { 1753 IFA_LOCK(ifa); 1754 if (ifa->ifa_addr->sa_family != AF_INET6) { 1755 IFA_UNLOCK(ifa); 1756 continue; 1757 } 1758 ifa6 = (struct in6_ifaddr *)ifa; 1759 1760 if ((niflags & NI_NODEADDR_FLAG_ALL) == 0 && 1761 IN6_ARE_ADDR_EQUAL(&subj_ip6->sin6_addr, 1762 &ifa6->ia_addr.sin6_addr)) 1763 iffound = 1; 1764 1765 /* 1766 * IPv4-mapped addresses can only be returned by a 1767 * Node Information proxy, since they represent 1768 * addresses of IPv4-only nodes, which perforce do 1769 * not implement this protocol. 1770 * [icmp-name-lookups-07, Section 5.4] 1771 * So we don't support NI_NODEADDR_FLAG_COMPAT in 1772 * this function at this moment. 1773 */ 1774 1775 /* What do we have to do about ::1? */ 1776 switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) { 1777 case IPV6_ADDR_SCOPE_LINKLOCAL: 1778 if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0) { 1779 IFA_UNLOCK(ifa); 1780 continue; 1781 } 1782 break; 1783 case IPV6_ADDR_SCOPE_SITELOCAL: 1784 if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0) { 1785 IFA_UNLOCK(ifa); 1786 continue; 1787 } 1788 break; 1789 case IPV6_ADDR_SCOPE_GLOBAL: 1790 if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0) { 1791 IFA_UNLOCK(ifa); 1792 continue; 1793 } 1794 break; 1795 default: 1796 IFA_UNLOCK(ifa); 1797 continue; 1798 } 1799 1800 /* 1801 * check if anycast is okay. 1802 * XXX: just experimental. not in the spec. 1803 */ 1804 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 && 1805 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0) { 1806 IFA_UNLOCK(ifa); 1807 continue; /* we need only unicast addresses */ 1808 } 1809 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 && 1810 (icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) { 1811 IFA_UNLOCK(ifa); 1812 continue; 1813 } 1814 addrsofif++; /* count the address */ 1815 IFA_UNLOCK(ifa); 1816 } 1817 ifnet_lock_done(ifp); 1818 if (iffound) { 1819 if (ifpp != NULL) { 1820 *ifpp = ifp; 1821 ifnet_reference(ifp); 1822 } 1823 ifnet_head_done(); 1824 return(addrsofif); 1825 } 1826 1827 addrs += addrsofif; 1828 } 1829 ifnet_head_done(); 1830 1831 return (addrs); 1832} 1833 1834static int 1835ni6_store_addrs(ni6, nni6, ifp0, resid) 1836 struct icmp6_nodeinfo *ni6, *nni6; 1837 struct ifnet *ifp0; 1838 int resid; 1839{ 1840 struct ifnet *ifp = ifp0; 1841 struct in6_ifaddr *ifa6; 1842 struct ifaddr *ifa; 1843 struct ifnet *ifp_dep = NULL; 1844 int copied = 0, allow_deprecated = 0; 1845 u_char *cp = (u_char *)(nni6 + 1); 1846 int niflags = ni6->ni_flags; 1847 u_int32_t ltime; 1848 uint64_t now = net_uptime(); 1849 1850 if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL)) 1851 return (0); /* needless to copy */ 1852 1853 again: 1854 1855 ifnet_head_lock_shared(); 1856 if (ifp == NULL) 1857 ifp = TAILQ_FIRST(&ifnet_head); 1858 1859 for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) { 1860 ifnet_lock_shared(ifp); 1861 for (ifa = ifp->if_addrlist.tqh_first; ifa; 1862 ifa = ifa->ifa_list.tqe_next) { 1863 struct in6_addrlifetime_i *lt; 1864 1865 IFA_LOCK(ifa); 1866 if (ifa->ifa_addr->sa_family != AF_INET6) { 1867 IFA_UNLOCK(ifa); 1868 continue; 1869 } 1870 ifa6 = (struct in6_ifaddr *)ifa; 1871 1872 if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) != 0 && 1873 allow_deprecated == 0) { 1874 /* 1875 * prefererred address should be put before 1876 * deprecated addresses. 1877 */ 1878 1879 /* record the interface for later search */ 1880 if (ifp_dep == NULL) 1881 ifp_dep = ifp; 1882 1883 IFA_UNLOCK(ifa); 1884 continue; 1885 } else if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) == 0 && 1886 allow_deprecated != 0) { 1887 IFA_UNLOCK(ifa); 1888 continue; /* we now collect deprecated addrs */ 1889 } 1890 /* What do we have to do about ::1? */ 1891 switch (in6_addrscope(&ifa6->ia_addr.sin6_addr)) { 1892 case IPV6_ADDR_SCOPE_LINKLOCAL: 1893 if ((niflags & NI_NODEADDR_FLAG_LINKLOCAL) == 0) { 1894 IFA_UNLOCK(ifa); 1895 continue; 1896 } 1897 break; 1898 case IPV6_ADDR_SCOPE_SITELOCAL: 1899 if ((niflags & NI_NODEADDR_FLAG_SITELOCAL) == 0) { 1900 IFA_UNLOCK(ifa); 1901 continue; 1902 } 1903 break; 1904 case IPV6_ADDR_SCOPE_GLOBAL: 1905 if ((niflags & NI_NODEADDR_FLAG_GLOBAL) == 0) { 1906 IFA_UNLOCK(ifa); 1907 continue; 1908 } 1909 break; 1910 default: 1911 IFA_UNLOCK(ifa); 1912 continue; 1913 } 1914 1915 /* 1916 * check if anycast is okay. 1917 * XXX: just experimental. not in the spec. 1918 */ 1919 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0 && 1920 (niflags & NI_NODEADDR_FLAG_ANYCAST) == 0) { 1921 IFA_UNLOCK(ifa); 1922 continue; 1923 } 1924 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0 && 1925 (icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK) == 0) { 1926 IFA_UNLOCK(ifa); 1927 continue; 1928 } 1929 1930 /* now we can copy the address */ 1931 if (resid < sizeof(struct in6_addr) + 1932 sizeof(u_int32_t)) { 1933 IFA_UNLOCK(ifa); 1934 /* 1935 * We give up much more copy. 1936 * Set the truncate flag and return. 1937 */ 1938 nni6->ni_flags |= 1939 NI_NODEADDR_FLAG_TRUNCATE; 1940 ifnet_lock_done(ifp); 1941 ifnet_head_done(); 1942 return(copied); 1943 } 1944 1945 /* 1946 * Set the TTL of the address. 1947 * The TTL value should be one of the following 1948 * according to the specification: 1949 * 1950 * 1. The remaining lifetime of a DHCP lease on the 1951 * address, or 1952 * 2. The remaining Valid Lifetime of a prefix from 1953 * which the address was derived through Stateless 1954 * Autoconfiguration. 1955 * 1956 * Note that we currently do not support stateful 1957 * address configuration by DHCPv6, so the former 1958 * case can't happen. 1959 */ 1960 lt = &ifa6->ia6_lifetime; 1961 if (lt->ia6ti_expire == 0) { 1962 ltime = ND6_INFINITE_LIFETIME; 1963 } else { 1964 if (lt->ia6ti_expire > now) 1965 ltime = htonl(lt->ia6ti_expire - now); 1966 else 1967 ltime = 0; 1968 } 1969 1970 bcopy(<ime, cp, sizeof(u_int32_t)); 1971 cp += sizeof(u_int32_t); 1972 1973 /* copy the address itself */ 1974 bcopy(&ifa6->ia_addr.sin6_addr, cp, 1975 sizeof(struct in6_addr)); 1976 /* XXX: KAME link-local hack; remove ifindex */ 1977 if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr)) 1978 ((struct in6_addr *)(void *)cp)->s6_addr16[1] = 0; 1979 cp += sizeof(struct in6_addr); 1980 1981 resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t)); 1982 copied += (sizeof(struct in6_addr) + 1983 sizeof(u_int32_t)); 1984 IFA_UNLOCK(ifa); 1985 } 1986 ifnet_lock_done(ifp); 1987 if (ifp0) /* we need search only on the specified IF */ 1988 break; 1989 } 1990 ifnet_head_done(); 1991 1992 if (allow_deprecated == 0 && ifp_dep != NULL) { 1993 ifp = ifp_dep; 1994 allow_deprecated = 1; 1995 1996 goto again; 1997 } 1998 1999 return(copied); 2000} 2001 2002/* 2003 * XXX almost dup'ed code with rip6_input. 2004 */ 2005static int 2006icmp6_rip6_input(mp, off) 2007 struct mbuf **mp; 2008 int off; 2009{ 2010 struct mbuf *m = *mp; 2011 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 2012 struct in6pcb *in6p; 2013 struct in6pcb *last = NULL; 2014 struct sockaddr_in6 rip6src; 2015 struct icmp6_hdr *icmp6; 2016 struct mbuf *opts = NULL; 2017 int ret = 0; 2018 struct ifnet *ifp = m->m_pkthdr.rcvif; 2019 2020#ifndef PULLDOWN_TEST 2021 /* this is assumed to be safe. */ 2022 icmp6 = (struct icmp6_hdr *)((caddr_t)ip6 + off); 2023#else 2024 IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6)); 2025 if (icmp6 == NULL) { 2026 /* m is already reclaimed */ 2027 return IPPROTO_DONE; 2028 } 2029#endif 2030 2031 /* 2032 * XXX: the address may have embedded scope zone ID, which should be 2033 * hidden from applications. 2034 */ 2035 bzero(&rip6src, sizeof(rip6src)); 2036 rip6src.sin6_family = AF_INET6; 2037 rip6src.sin6_len = sizeof(struct sockaddr_in6); 2038 rip6src.sin6_addr = ip6->ip6_src; 2039 if (sa6_recoverscope(&rip6src, TRUE)) 2040 return (IPPROTO_DONE); 2041 2042 lck_rw_lock_shared(ripcbinfo.ipi_lock); 2043 LIST_FOREACH(in6p, &ripcb, inp_list) 2044 { 2045 if ((in6p->inp_vflag & INP_IPV6) == 0) 2046 continue; 2047 if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6) 2048 continue; 2049 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) && 2050 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) 2051 continue; 2052 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && 2053 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) 2054 continue; 2055 if (in6p->in6p_icmp6filt 2056 && ICMP6_FILTER_WILLBLOCK(icmp6->icmp6_type, 2057 in6p->in6p_icmp6filt)) 2058 continue; 2059 2060 if (inp_restricted(in6p, ifp)) 2061 continue; 2062 2063 if (ifp != NULL && IFNET_IS_CELLULAR(ifp) && 2064 (in6p->in6p_flags & INP_NO_IFT_CELLULAR)) 2065 continue; 2066 2067 if (last) { 2068 struct mbuf *n; 2069 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 2070 if ((last->in6p_flags & INP_CONTROLOPTS) != 0 || 2071 (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 || 2072 (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0) { 2073 ret = ip6_savecontrol(last, n, &opts); 2074 if (ret != 0) { 2075 m_freem(n); 2076 m_freem(opts); 2077 last = in6p; 2078 continue; 2079 } 2080 } 2081 /* strip intermediate headers */ 2082 m_adj(n, off); 2083 so_recv_data_stat(last->in6p_socket, m, 0); 2084 if (sbappendaddr(&last->in6p_socket->so_rcv, 2085 (struct sockaddr *)&rip6src, 2086 n, opts, NULL) != 0) { 2087 sorwakeup(last->in6p_socket); 2088 } 2089 opts = NULL; 2090 } 2091 } 2092 last = in6p; 2093 } 2094 if (last) { 2095 if ((last->in6p_flags & INP_CONTROLOPTS) != 0 || 2096 (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 || 2097 (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0) { 2098 ret = ip6_savecontrol(last, m, &opts); 2099 if (ret != 0) { 2100 goto error; 2101 } 2102 } 2103 /* strip intermediate headers */ 2104 m_adj(m, off); 2105 so_recv_data_stat(last->in6p_socket, m, 0); 2106 if (sbappendaddr(&last->in6p_socket->so_rcv, 2107 (struct sockaddr *)&rip6src, m, opts, NULL) != 0) { 2108 sorwakeup(last->in6p_socket); 2109 } 2110 } else { 2111 goto error; 2112 } 2113 lck_rw_done(ripcbinfo.ipi_lock); 2114 return IPPROTO_DONE; 2115 2116error: 2117 lck_rw_done(ripcbinfo.ipi_lock); 2118 m_freem(m); 2119 m_freem(opts); 2120 ip6stat.ip6s_delivered--; 2121 return IPPROTO_DONE; 2122} 2123 2124/* 2125 * Reflect the ip6 packet back to the source. 2126 * OFF points to the icmp6 header, counted from the top of the mbuf. 2127 */ 2128void 2129icmp6_reflect(m, off) 2130 struct mbuf *m; 2131 size_t off; 2132{ 2133 struct mbuf *m_ip6hdr = m; 2134 struct ip6_hdr *ip6; 2135 struct icmp6_hdr *icmp6; 2136 struct in6_ifaddr *ia; 2137 struct in6_addr t, src_storage, *src = 0; 2138 int plen; 2139 int type, code; 2140 struct ifnet *outif = NULL; 2141 struct sockaddr_in6 sa6_src, sa6_dst; 2142 struct nd_ifinfo *ndi; 2143 u_int32_t oflow; 2144 struct ip6_out_args ip6oa = { IFSCOPE_NONE, { 0 }, 2145 IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR, 0 }; 2146 2147 if (!(m->m_pkthdr.pkt_flags & PKTF_LOOP) && m->m_pkthdr.rcvif != NULL) { 2148 ip6oa.ip6oa_boundif = m->m_pkthdr.rcvif->if_index; 2149 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF; 2150 } 2151 2152 /* too short to reflect */ 2153 if (off < sizeof(struct ip6_hdr)) { 2154 nd6log((LOG_DEBUG, 2155 "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n", 2156 (u_int32_t)off, (u_int32_t)sizeof(struct ip6_hdr), 2157 __FILE__, __LINE__)); 2158 goto bad; 2159 } 2160 2161 /* 2162 * If there are extra headers between IPv6 and ICMPv6, strip 2163 * off that header first. 2164 */ 2165 if (off > sizeof(struct ip6_hdr)) { 2166 size_t l; 2167 struct ip6_hdr nip6; 2168 2169 l = off - sizeof(struct ip6_hdr); 2170 m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6); 2171 m_adj(m, l); 2172 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 2173 if (m->m_len < l) { 2174 if ((m_ip6hdr = m_pulldown(m, 0, l, NULL)) == NULL) 2175 return; 2176 } 2177 bcopy((caddr_t)&nip6, mtod(m, caddr_t), sizeof(nip6)); 2178 } else /* off == sizeof(struct ip6_hdr) */ { 2179 size_t l; 2180 l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr); 2181 if (m->m_len < l) { 2182 if ((m_ip6hdr = m_pulldown(m, 0, l, NULL)) == NULL) 2183 return; 2184 } 2185 } 2186 plen = m->m_pkthdr.len - sizeof(struct ip6_hdr); 2187 ip6 = mtod(m_ip6hdr, struct ip6_hdr *); 2188 ip6->ip6_nxt = IPPROTO_ICMPV6; 2189 icmp6 = (struct icmp6_hdr *)(ip6 + 1); 2190 type = icmp6->icmp6_type; /* keep type for statistics */ 2191 code = icmp6->icmp6_code; /* ditto. */ 2192 2193 t = ip6->ip6_dst; 2194 /* 2195 * ip6_input() drops a packet if its src is multicast. 2196 * So, the src is never multicast. 2197 */ 2198 ip6->ip6_dst = ip6->ip6_src; 2199 2200 /* 2201 * XXX: make sure to embed scope zone information, using 2202 * already embedded IDs or the received interface (if any). 2203 * Note that rcvif may be NULL. 2204 */ 2205 bzero(&sa6_src, sizeof(sa6_src)); 2206 sa6_src.sin6_family = AF_INET6; 2207 sa6_src.sin6_len = sizeof(sa6_src); 2208 sa6_src.sin6_addr = ip6->ip6_dst; 2209 in6_recoverscope(&sa6_src, &ip6->ip6_dst, m->m_pkthdr.rcvif); 2210 in6_embedscope(&ip6->ip6_dst, &sa6_src, NULL, NULL, NULL); 2211 bzero(&sa6_dst, sizeof(sa6_dst)); 2212 sa6_dst.sin6_family = AF_INET6; 2213 sa6_dst.sin6_len = sizeof(sa6_dst); 2214 sa6_dst.sin6_addr = t; 2215 in6_recoverscope(&sa6_dst, &t, m->m_pkthdr.rcvif); 2216 in6_embedscope(&t, &sa6_dst, NULL, NULL, NULL); 2217 2218 /* 2219 * If the incoming packet was addressed directly to us(i.e. unicast), 2220 * use dst as the src for the reply. 2221 * The IN6_IFF_NOTREADY case should be VERY rare, but is possible 2222 * (for example) when we encounter an error while forwarding procedure 2223 * destined to a duplicated address of ours. 2224 * Note that ip6_getdstifaddr() may fail if we are in an error handling 2225 * procedure of an outgoing packet of our own, in which case we need 2226 * to search in the ifaddr list. 2227 */ 2228 lck_rw_lock_shared(&in6_ifaddr_rwlock); 2229 for (ia = in6_ifaddrs; ia; ia = ia->ia_next) { 2230 IFA_LOCK(&ia->ia_ifa); 2231 if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) && 2232 (ia->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0) { 2233 IFA_UNLOCK(&ia->ia_ifa); 2234 src = &t; 2235 break; 2236 } 2237 IFA_UNLOCK(&ia->ia_ifa); 2238 } 2239 lck_rw_done(&in6_ifaddr_rwlock); 2240 if (ia == NULL && IN6_IS_ADDR_LINKLOCAL(&t) && 2241 ((m->m_flags & M_LOOP) || (m->m_pkthdr.pkt_flags & PKTF_LOOP))) { 2242 /* 2243 * This is the case if the dst is our link-local address 2244 * and the sender is also ourselves. Here we test for both 2245 * M_LOOP and PKTF_LOOP, since the former may have been set 2246 * in ip6_output() and that we get here as part of callling 2247 * ip6_process_hopopts(). See comments in <sys/mbuf.h> 2248 */ 2249 src = &t; 2250 } 2251 2252 if (src == NULL) { 2253 int e; 2254 struct sockaddr_in6 sin6; 2255 struct route_in6 ro; 2256 2257 /* 2258 * This case matches to multicasts, our anycast, or unicasts 2259 * that we do not own. Select a source address based on the 2260 * source address of the erroneous packet. 2261 */ 2262 bzero(&sin6, sizeof(sin6)); 2263 sin6.sin6_family = AF_INET6; 2264 sin6.sin6_len = sizeof(sin6); 2265 sin6.sin6_addr = ip6->ip6_dst; /* zone ID should be embedded */ 2266 2267 bzero(&ro, sizeof(ro)); 2268 /* 2269 * in6_selectsrc() might return outif with its reference held 2270 * even in the error case, so we always need to release it 2271 * if non-NULL. 2272 */ 2273 src = in6_selectsrc(&sin6, NULL, NULL, &ro, &outif, 2274 &src_storage, ip6oa.ip6oa_boundif, &e); 2275 ROUTE_RELEASE(&ro); 2276 if (src == NULL) { 2277 nd6log((LOG_DEBUG, 2278 "icmp6_reflect: source can't be determined: " 2279 "dst=%s, error=%d\n", 2280 ip6_sprintf(&sa6_src.sin6_addr), e)); 2281 goto bad; 2282 } 2283 } 2284 oflow = ip6->ip6_flow; /* Save for later */ 2285 ip6->ip6_src = *src; 2286 ip6->ip6_flow = 0; 2287 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 2288 ip6->ip6_vfc |= IPV6_VERSION; 2289 if (icmp6->icmp6_type == ICMP6_ECHO_REPLY && icmp6->icmp6_code == 0) { 2290 ip6->ip6_flow |= (oflow & htonl(0x0ff00000)); 2291 } 2292 ip6->ip6_nxt = IPPROTO_ICMPV6; 2293 lck_rw_lock_shared(nd_if_rwlock); 2294 if (outif != NULL && (ndi = ND_IFINFO(outif)) != NULL && 2295 ndi->initialized) { 2296 lck_mtx_lock(&ndi->lock); 2297 ip6->ip6_hlim = ndi->chlim; 2298 lck_mtx_unlock(&ndi->lock); 2299 } 2300 if (m->m_pkthdr.rcvif != NULL && 2301 (ndi = ND_IFINFO(m->m_pkthdr.rcvif)) != NULL && 2302 ndi->initialized) { 2303 /* XXX: This may not be the outgoing interface */ 2304 lck_mtx_lock(&ndi->lock); 2305 ip6->ip6_hlim = ndi->chlim; 2306 lck_mtx_unlock(&ndi->lock); 2307 } else { 2308 ip6->ip6_hlim = ip6_defhlim; 2309 } 2310 lck_rw_done(nd_if_rwlock); 2311 /* Use the same traffic class as in the request to match IPv4 */ 2312 icmp6->icmp6_cksum = 0; 2313 icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6, 2314 sizeof(struct ip6_hdr), plen); 2315 2316 /* 2317 * XXX option handling 2318 */ 2319 2320 m->m_flags &= ~(M_BCAST|M_MCAST); 2321#if IPSEC 2322 /* Don't lookup socket */ 2323 if (ipsec_bypass == 0) 2324 (void)ipsec_setsocket(m, NULL); 2325#endif /*IPSEC*/ 2326 2327 if (outif != NULL) { 2328 ifnet_release(outif); 2329 outif = NULL; 2330 } 2331 m->m_pkthdr.rcvif = NULL; 2332 m->m_pkthdr.csum_data = 0; 2333 m->m_pkthdr.csum_flags = 0; 2334 ip6_output(m, NULL, NULL, IPV6_OUTARGS, NULL, &outif, &ip6oa); 2335 if (outif != NULL) { 2336 icmp6_ifoutstat_inc(outif, type, code); 2337 ifnet_release(outif); 2338 } 2339 return; 2340 2341bad: 2342 m_freem(m); 2343 if (outif != NULL) 2344 ifnet_release(outif); 2345 return; 2346} 2347 2348static const char * 2349icmp6_redirect_diag(src6, dst6, tgt6) 2350 struct in6_addr *src6; 2351 struct in6_addr *dst6; 2352 struct in6_addr *tgt6; 2353{ 2354 static char buf[1024]; 2355 snprintf(buf, sizeof(buf), "(src=%s dst=%s tgt=%s)", 2356 ip6_sprintf(src6), ip6_sprintf(dst6), ip6_sprintf(tgt6)); 2357 return buf; 2358} 2359 2360void 2361icmp6_redirect_input(m, off) 2362 struct mbuf *m; 2363 int off; 2364{ 2365 struct ifnet *ifp = m->m_pkthdr.rcvif; 2366 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 2367 struct nd_redirect *nd_rd; 2368 int icmp6len = ntohs(ip6->ip6_plen); 2369 char *lladdr = NULL; 2370 int lladdrlen = 0; 2371 u_char *redirhdr = NULL; 2372 int redirhdrlen = 0; 2373 struct rtentry *rt = NULL; 2374 int is_router; 2375 int is_onlink; 2376 struct in6_addr src6 = ip6->ip6_src; 2377 struct in6_addr redtgt6; 2378 struct in6_addr reddst6; 2379 union nd_opts ndopts; 2380 2381 if (!m || !ifp) 2382 return; 2383 2384 /* 2385 * If we are an advertising router on this interface, 2386 * don't update route by icmp6 redirect. 2387 */ 2388 if (ifp->if_eflags & IFEF_IPV6_ROUTER) 2389 goto freeit; 2390 if (!icmp6_rediraccept) 2391 goto freeit; 2392 2393#ifndef PULLDOWN_TEST 2394 IP6_EXTHDR_CHECK(m, off, icmp6len, return); 2395 nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off); 2396#else 2397 IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len); 2398 if (nd_rd == NULL) { 2399 icmp6stat.icp6s_tooshort++; 2400 return; 2401 } 2402#endif 2403 redtgt6 = nd_rd->nd_rd_target; 2404 reddst6 = nd_rd->nd_rd_dst; 2405 2406 if (in6_setscope(&redtgt6, m->m_pkthdr.rcvif, NULL) || 2407 in6_setscope(&reddst6, m->m_pkthdr.rcvif, NULL)) { 2408 goto freeit; 2409 } 2410 2411 /* validation */ 2412 if (!IN6_IS_ADDR_LINKLOCAL(&src6)) { 2413 nd6log((LOG_ERR, 2414 "ICMP6 redirect sent from %s rejected; " 2415 "must be from linklocal\n", ip6_sprintf(&src6))); 2416 goto bad; 2417 } 2418 if (ip6->ip6_hlim != 255) { 2419 nd6log((LOG_ERR, 2420 "ICMP6 redirect sent from %s rejected; " 2421 "hlim=%d (must be 255)\n", 2422 ip6_sprintf(&src6), ip6->ip6_hlim)); 2423 goto bad; 2424 } 2425 { 2426 /* ip6->ip6_src must be equal to gw for icmp6->icmp6_reddst */ 2427 struct sockaddr_in6 sin6; 2428 struct in6_addr *gw6; 2429 2430 bzero(&sin6, sizeof(sin6)); 2431 sin6.sin6_family = AF_INET6; 2432 sin6.sin6_len = sizeof(struct sockaddr_in6); 2433 bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6)); 2434 rt = rtalloc1_scoped((struct sockaddr *)&sin6, 0, 0, ifp->if_index); 2435 if (rt) { 2436 RT_LOCK(rt); 2437 if (rt->rt_gateway == NULL || 2438 rt->rt_gateway->sa_family != AF_INET6) { 2439 nd6log((LOG_ERR, 2440 "ICMP6 redirect rejected; no route " 2441 "with inet6 gateway found for redirect dst: %s\n", 2442 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2443 RT_UNLOCK(rt); 2444 rtfree(rt); 2445 goto bad; 2446 } 2447 2448 gw6 = &(((struct sockaddr_in6 *)(void *) 2449 rt->rt_gateway)->sin6_addr); 2450 if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) { 2451 nd6log((LOG_ERR, 2452 "ICMP6 redirect rejected; " 2453 "not equal to gw-for-src=%s (must be same): " 2454 "%s\n", 2455 ip6_sprintf(gw6), 2456 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2457 RT_UNLOCK(rt); 2458 rtfree(rt); 2459 goto bad; 2460 } 2461 } else { 2462 nd6log((LOG_ERR, 2463 "ICMP6 redirect rejected; " 2464 "no route found for redirect dst: %s\n", 2465 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2466 goto bad; 2467 } 2468 RT_UNLOCK(rt); 2469 rtfree(rt); 2470 rt = NULL; 2471 } 2472 if (IN6_IS_ADDR_MULTICAST(&reddst6)) { 2473 nd6log((LOG_ERR, 2474 "ICMP6 redirect rejected; " 2475 "redirect dst must be unicast: %s\n", 2476 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2477 goto bad; 2478 } 2479 2480 is_router = is_onlink = 0; 2481 if (IN6_IS_ADDR_LINKLOCAL(&redtgt6)) 2482 is_router = 1; /* router case */ 2483 if (bcmp(&redtgt6, &reddst6, sizeof(redtgt6)) == 0) 2484 is_onlink = 1; /* on-link destination case */ 2485 if (!is_router && !is_onlink) { 2486 nd6log((LOG_ERR, 2487 "ICMP6 redirect rejected; " 2488 "neither router case nor onlink case: %s\n", 2489 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2490 goto bad; 2491 } 2492 /* validation passed */ 2493 2494 icmp6len -= sizeof(*nd_rd); 2495 nd6_option_init(nd_rd + 1, icmp6len, &ndopts); 2496 if (nd6_options(&ndopts) < 0) { 2497 nd6log((LOG_INFO, "icmp6_redirect_input: " 2498 "invalid ND option, rejected: %s\n", 2499 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2500 /* nd6_options have incremented stats */ 2501 goto freeit; 2502 } 2503 2504 if (ndopts.nd_opts_tgt_lladdr) { 2505 lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); 2506 lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; 2507 } 2508 2509 if (ndopts.nd_opts_rh) { 2510 redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len; 2511 redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */ 2512 } 2513 2514 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { 2515 nd6log((LOG_INFO, 2516 "icmp6_redirect_input: lladdrlen mismatch for %s " 2517 "(if %d, icmp6 packet %d): %s\n", 2518 ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2, 2519 icmp6_redirect_diag(&src6, &reddst6, &redtgt6))); 2520 goto bad; 2521 } 2522 2523 /* RFC 2461 8.3 */ 2524 nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, 2525 is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); 2526 2527 if (!is_onlink) { /* better router case. perform rtredirect. */ 2528 /* perform rtredirect */ 2529 struct sockaddr_in6 sdst; 2530 struct sockaddr_in6 sgw; 2531 struct sockaddr_in6 ssrc; 2532 2533 bzero(&sdst, sizeof(sdst)); 2534 bzero(&sgw, sizeof(sgw)); 2535 bzero(&ssrc, sizeof(ssrc)); 2536 sdst.sin6_family = sgw.sin6_family = ssrc.sin6_family = AF_INET6; 2537 sdst.sin6_len = sgw.sin6_len = ssrc.sin6_len = 2538 sizeof(struct sockaddr_in6); 2539 bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr)); 2540 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); 2541 bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr)); 2542 rtredirect(ifp, (struct sockaddr *)&sdst, 2543 (struct sockaddr *)&sgw, NULL, RTF_GATEWAY | RTF_HOST, 2544 (struct sockaddr *)&ssrc, NULL); 2545 } 2546 /* finally update cached route in each socket via pfctlinput */ 2547 { 2548 struct sockaddr_in6 sdst; 2549 2550 bzero(&sdst, sizeof(sdst)); 2551 sdst.sin6_family = AF_INET6; 2552 sdst.sin6_len = sizeof(struct sockaddr_in6); 2553 bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); 2554 2555 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst); 2556#if IPSEC 2557 key_sa_routechange((struct sockaddr *)&sdst); 2558#endif 2559 } 2560 2561 freeit: 2562 m_freem(m); 2563 return; 2564 2565 bad: 2566 icmp6stat.icp6s_badredirect++; 2567 m_freem(m); 2568} 2569 2570void 2571icmp6_redirect_output(m0, rt) 2572 struct mbuf *m0; 2573 struct rtentry *rt; 2574{ 2575 struct ifnet *ifp; /* my outgoing interface */ 2576 struct in6_addr ifp_ll6; 2577 struct in6_addr *router_ll6; 2578 struct ip6_hdr *sip6; /* m0 as struct ip6_hdr */ 2579 struct mbuf *m = NULL; /* newly allocated one */ 2580 struct ip6_hdr *ip6; /* m as struct ip6_hdr */ 2581 struct nd_redirect *nd_rd; 2582 size_t maxlen; 2583 u_char *p; 2584 struct ifnet *outif = NULL; 2585 struct sockaddr_in6 src_sa; 2586 struct ip6_out_args ip6oa = { IFSCOPE_NONE, { 0 }, 2587 IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR, 0 }; 2588 2589 icmp6_errcount(&icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0); 2590 2591 if (rt != NULL) 2592 RT_LOCK(rt); 2593 2594 /* sanity check */ 2595 if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp)) 2596 goto fail; 2597 2598 /* 2599 * If we are not a router to begin with, or not an advertising 2600 * router on this interface, don't send icmp6 redirect. 2601 */ 2602 if (!ip6_forwarding || !(ifp->if_eflags & IFEF_IPV6_ROUTER)) 2603 goto fail; 2604 2605 /* 2606 * Address check: 2607 * the source address must identify a neighbor, and 2608 * the destination address must not be a multicast address 2609 * [RFC 2461, sec 8.2] 2610 */ 2611 sip6 = mtod(m0, struct ip6_hdr *); 2612 bzero(&src_sa, sizeof(src_sa)); 2613 src_sa.sin6_family = AF_INET6; 2614 src_sa.sin6_len = sizeof(src_sa); 2615 src_sa.sin6_addr = sip6->ip6_src; 2616 /* we don't currently use sin6_scope_id, but eventually use it */ 2617 src_sa.sin6_scope_id = in6_addr2scopeid(ifp, &sip6->ip6_src); 2618 RT_UNLOCK(rt); 2619 if (nd6_is_addr_neighbor(&src_sa, ifp, 0) == 0) { 2620 /* already unlocked */ 2621 rt = NULL; 2622 goto fail; 2623 } 2624 RT_LOCK(rt); 2625 if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst)) 2626 goto fail; /* what should we do here? */ 2627 2628 /* rate limit */ 2629 if (icmp6_ratelimit(&sip6->ip6_src, ND_REDIRECT, 0)) 2630 goto fail; 2631 2632 /* 2633 * Since we are going to append up to 1280 bytes (= IPV6_MMTU), 2634 * we almost always ask for an mbuf cluster for simplicity. 2635 * (MHLEN < IPV6_MMTU is almost always true) 2636 */ 2637#if IPV6_MMTU >= MCLBYTES 2638# error assumption failed about IPV6_MMTU and MCLBYTES 2639#endif 2640 MGETHDR(m, M_DONTWAIT, MT_HEADER); /* MAC-OK */ 2641 if (m && IPV6_MMTU >= MHLEN) 2642 MCLGET(m, M_DONTWAIT); 2643 if (!m) 2644 goto fail; 2645 m->m_pkthdr.rcvif = NULL; 2646 m->m_len = 0; 2647 maxlen = M_TRAILINGSPACE(m); 2648 maxlen = min(IPV6_MMTU, maxlen); 2649 /* just for safety */ 2650 if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 2651 ((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) { 2652 goto fail; 2653 } 2654 2655 { 2656 /* get ip6 linklocal address for ifp(my outgoing interface). */ 2657 struct in6_ifaddr *ia; 2658 if ((ia = in6ifa_ifpforlinklocal(ifp, 2659 IN6_IFF_NOTREADY| 2660 IN6_IFF_ANYCAST)) == NULL) 2661 goto fail; 2662 IFA_LOCK(&ia->ia_ifa); 2663 ifp_ll6 = ia->ia_addr.sin6_addr; 2664 IFA_UNLOCK(&ia->ia_ifa); 2665 IFA_REMREF(&ia->ia_ifa); 2666 } 2667 2668 /* get ip6 linklocal address for the router. */ 2669 if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) { 2670 struct sockaddr_in6 *sin6; 2671 sin6 = (struct sockaddr_in6 *)(void *)rt->rt_gateway; 2672 router_ll6 = &sin6->sin6_addr; 2673 if (!IN6_IS_ADDR_LINKLOCAL(router_ll6)) 2674 router_ll6 = (struct in6_addr *)NULL; 2675 } else 2676 router_ll6 = (struct in6_addr *)NULL; 2677 2678 /* ip6 */ 2679 ip6 = mtod(m, struct ip6_hdr *); 2680 ip6->ip6_flow = 0; 2681 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 2682 ip6->ip6_vfc |= IPV6_VERSION; 2683 /* ip6->ip6_plen will be set later */ 2684 ip6->ip6_nxt = IPPROTO_ICMPV6; 2685 ip6->ip6_hlim = 255; 2686 /* ip6->ip6_src must be linklocal addr for my outgoing if. */ 2687 bcopy(&ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr)); 2688 bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr)); 2689 2690 /* ND Redirect */ 2691 nd_rd = (struct nd_redirect *)(ip6 + 1); 2692 nd_rd->nd_rd_type = ND_REDIRECT; 2693 nd_rd->nd_rd_code = 0; 2694 nd_rd->nd_rd_reserved = 0; 2695 if (rt->rt_flags & RTF_GATEWAY) { 2696 /* 2697 * nd_rd->nd_rd_target must be a link-local address in 2698 * better router cases. 2699 */ 2700 if (!router_ll6) 2701 goto fail; 2702 bcopy(router_ll6, &nd_rd->nd_rd_target, 2703 sizeof(nd_rd->nd_rd_target)); 2704 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 2705 sizeof(nd_rd->nd_rd_dst)); 2706 } else { 2707 /* make sure redtgt == reddst */ 2708 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_target, 2709 sizeof(nd_rd->nd_rd_target)); 2710 bcopy(&sip6->ip6_dst, &nd_rd->nd_rd_dst, 2711 sizeof(nd_rd->nd_rd_dst)); 2712 } 2713 RT_UNLOCK(rt); 2714 rt = NULL; 2715 2716 p = (u_char *)(nd_rd + 1); 2717 2718 if (!router_ll6) 2719 goto nolladdropt; 2720 2721 { 2722 /* target lladdr option */ 2723 struct rtentry *rt_router = NULL; 2724 int len; 2725 struct sockaddr_dl *sdl; 2726 struct nd_opt_hdr *nd_opt; 2727 char *lladdr; 2728 2729 /* Callee returns a locked route upon success */ 2730 rt_router = nd6_lookup(router_ll6, 0, ifp, 0); 2731 if (!rt_router) 2732 goto nolladdropt; 2733 RT_LOCK_ASSERT_HELD(rt_router); 2734 len = sizeof(*nd_opt) + ifp->if_addrlen; 2735 len = (len + 7) & ~7; /* round by 8 */ 2736 /* safety check */ 2737 if (len + (p - (u_char *)ip6) > maxlen) { 2738 RT_REMREF_LOCKED(rt_router); 2739 RT_UNLOCK(rt_router); 2740 goto nolladdropt; 2741 } 2742 2743 if (!(rt_router->rt_flags & RTF_GATEWAY) && 2744 (rt_router->rt_flags & RTF_LLINFO) && 2745 (rt_router->rt_gateway->sa_family == AF_LINK) && 2746 (sdl = (struct sockaddr_dl *)(void *) 2747 rt_router->rt_gateway) && sdl->sdl_alen) { 2748 nd_opt = (struct nd_opt_hdr *)p; 2749 nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; 2750 nd_opt->nd_opt_len = len >> 3; 2751 lladdr = (char *)(nd_opt + 1); 2752 bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen); 2753 p += len; 2754 } 2755 RT_REMREF_LOCKED(rt_router); 2756 RT_UNLOCK(rt_router); 2757 } 2758 2759nolladdropt:; 2760 2761 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 2762 2763 /* just to be safe */ 2764#ifdef M_DECRYPTED /*not openbsd*/ 2765 if (m0->m_flags & M_DECRYPTED) 2766 goto noredhdropt; 2767#endif 2768 if (p - (u_char *)ip6 > maxlen) 2769 goto noredhdropt; 2770 2771 { 2772 /* redirected header option */ 2773 int len; 2774 struct nd_opt_rd_hdr *nd_opt_rh; 2775 2776 /* 2777 * compute the maximum size for icmp6 redirect header option. 2778 * XXX room for auth header? 2779 */ 2780 len = maxlen - (p - (u_char *)ip6); 2781 len &= ~7; 2782 2783 /* This is just for simplicity. */ 2784 if (m0->m_pkthdr.len != m0->m_len) { 2785 if (m0->m_next) { 2786 m_freem(m0->m_next); 2787 m0->m_next = NULL; 2788 } 2789 m0->m_pkthdr.len = m0->m_len; 2790 } 2791 2792 /* 2793 * Redirected header option spec (RFC2461 4.6.3) talks nothing 2794 * about padding/truncate rule for the original IP packet. 2795 * From the discussion on IPv6imp in Feb 1999, the consensus was: 2796 * - "attach as much as possible" is the goal 2797 * - pad if not aligned (original size can be guessed by original 2798 * ip6 header) 2799 * Following code adds the padding if it is simple enough, 2800 * and truncates if not. 2801 */ 2802 if (m0->m_next || m0->m_pkthdr.len != m0->m_len) 2803 panic("assumption failed in %s:%d\n", __FILE__, __LINE__); 2804 2805 if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) { 2806 /* not enough room, truncate */ 2807 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh); 2808 } else { 2809 /* enough room, pad or truncate */ 2810 size_t extra; 2811 2812 extra = m0->m_pkthdr.len % 8; 2813 if (extra) { 2814 /* pad if easy enough, truncate if not */ 2815 if (8 - extra <= M_TRAILINGSPACE(m0)) { 2816 /* pad */ 2817 m0->m_len += (8 - extra); 2818 m0->m_pkthdr.len += (8 - extra); 2819 } else { 2820 /* truncate */ 2821 m0->m_pkthdr.len -= extra; 2822 m0->m_len -= extra; 2823 } 2824 } 2825 len = m0->m_pkthdr.len + sizeof(*nd_opt_rh); 2826 m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh); 2827 } 2828 2829 nd_opt_rh = (struct nd_opt_rd_hdr *)p; 2830 bzero(nd_opt_rh, sizeof(*nd_opt_rh)); 2831 nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER; 2832 nd_opt_rh->nd_opt_rh_len = len >> 3; 2833 p += sizeof(*nd_opt_rh); 2834 m->m_pkthdr.len = m->m_len = p - (u_char *)ip6; 2835 2836 /* connect m0 to m */ 2837 m->m_next = m0; 2838 m->m_pkthdr.len = m->m_len + m0->m_len; 2839 } 2840noredhdropt:; 2841 2842 /* XXX: clear embedded link IDs in the inner header */ 2843 in6_clearscope(&sip6->ip6_src); 2844 in6_clearscope(&sip6->ip6_dst); 2845 in6_clearscope(&nd_rd->nd_rd_target); 2846 in6_clearscope(&nd_rd->nd_rd_dst); 2847 2848 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 2849 2850 nd_rd->nd_rd_cksum = 0; 2851 nd_rd->nd_rd_cksum 2852 = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), ntohs(ip6->ip6_plen)); 2853 2854 /* send the packet to outside... */ 2855#if IPSEC 2856 /* Don't lookup socket */ 2857 if (ipsec_bypass == 0) 2858 (void)ipsec_setsocket(m, NULL); 2859#endif /*IPSEC*/ 2860 2861 ip6oa.ip6oa_boundif = ifp->if_index; 2862 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF; 2863 2864 ip6_output(m, NULL, NULL, IPV6_OUTARGS, NULL, &outif, &ip6oa); 2865 if (outif) { 2866 icmp6_ifstat_inc(outif, ifs6_out_msg); 2867 icmp6_ifstat_inc(outif, ifs6_out_redirect); 2868 ifnet_release(outif); 2869 } 2870 icmp6stat.icp6s_outhist[ND_REDIRECT]++; 2871 2872 return; 2873 2874fail: 2875 if (rt != NULL) 2876 RT_UNLOCK(rt); 2877 if (m) 2878 m_freem(m); 2879 if (m0) 2880 m_freem(m0); 2881} 2882 2883/* 2884 * ICMPv6 socket option processing. 2885 */ 2886int 2887icmp6_ctloutput(so, sopt) 2888 struct socket *so; 2889 struct sockopt *sopt; 2890{ 2891 int error = 0; 2892 int optlen; 2893 struct inpcb *inp = sotoinpcb(so); 2894 int level, op, optname; 2895 2896 if (sopt) { 2897 level = sopt->sopt_level; 2898 op = sopt->sopt_dir; 2899 optname = sopt->sopt_name; 2900 optlen = sopt->sopt_valsize; 2901 } else 2902 level = op = optname = optlen = 0; 2903 2904 if (level != IPPROTO_ICMPV6) { 2905 return EINVAL; 2906 } 2907 2908 switch (op) { 2909 case PRCO_SETOPT: 2910 switch (optname) { 2911 case ICMP6_FILTER: 2912 { 2913 struct icmp6_filter *p; 2914 2915 if (optlen != 0 && optlen != sizeof(*p)) { 2916 error = EMSGSIZE; 2917 break; 2918 } 2919 if (inp->in6p_icmp6filt == NULL) { 2920 error = EINVAL; 2921 break; 2922 } 2923 2924 if (optlen == 0) { 2925 /* According to RFC 3542, an installed filter can be 2926 * cleared by issuing a setsockopt for ICMP6_FILTER 2927 * with a zero length. 2928 */ 2929 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt); 2930 } else { 2931 error = sooptcopyin(sopt, inp->in6p_icmp6filt, optlen, 2932 optlen); 2933 } 2934 break; 2935 } 2936 2937 default: 2938 error = ENOPROTOOPT; 2939 break; 2940 } 2941 break; 2942 2943 case PRCO_GETOPT: 2944 switch (optname) { 2945 case ICMP6_FILTER: 2946 { 2947 if (inp->in6p_icmp6filt == NULL) { 2948 error = EINVAL; 2949 break; 2950 } 2951 error = sooptcopyout(sopt, inp->in6p_icmp6filt, 2952 min(sizeof(struct icmp6_filter), optlen)); 2953 break; 2954 } 2955 2956 default: 2957 error = ENOPROTOOPT; 2958 break; 2959 } 2960 break; 2961 } 2962 2963 return(error); 2964} 2965 2966/* 2967 * ICMPv6 socket datagram option processing. 2968 */ 2969int 2970icmp6_dgram_ctloutput(struct socket *so, struct sockopt *sopt) 2971{ 2972 if (kauth_cred_issuser(so->so_cred)) 2973 return icmp6_ctloutput(so, sopt); 2974 2975 if (sopt->sopt_level == IPPROTO_ICMPV6) { 2976 switch (sopt->sopt_name) { 2977 case ICMP6_FILTER: 2978 return icmp6_ctloutput(so, sopt); 2979 default: 2980 return EPERM; 2981 } 2982 } 2983 2984 if (sopt->sopt_level != IPPROTO_IPV6) 2985 return EINVAL; 2986 2987 switch (sopt->sopt_name) { 2988 case IPV6_UNICAST_HOPS: 2989 case IPV6_CHECKSUM: 2990 case IPV6_V6ONLY: 2991 case IPV6_USE_MIN_MTU: 2992 case IPV6_RECVRTHDR: 2993 case IPV6_RECVPKTINFO: 2994 case IPV6_RECVHOPLIMIT: 2995 case IPV6_PATHMTU: 2996 case IPV6_PKTINFO: 2997 case IPV6_HOPLIMIT: 2998 case IPV6_HOPOPTS: 2999 case IPV6_DSTOPTS: 3000 case IPV6_MULTICAST_IF: 3001 case IPV6_MULTICAST_HOPS: 3002 case IPV6_MULTICAST_LOOP: 3003 case IPV6_JOIN_GROUP: 3004 case IPV6_LEAVE_GROUP: 3005 case IPV6_PORTRANGE: 3006 case IPV6_IPSEC_POLICY: 3007 case IPV6_RECVTCLASS: 3008 case IPV6_TCLASS: 3009 case IPV6_2292PKTOPTIONS: 3010 case IPV6_2292PKTINFO: 3011 case IPV6_2292HOPLIMIT: 3012 case IPV6_2292HOPOPTS: 3013 case IPV6_2292DSTOPTS: 3014 case IPV6_2292RTHDR: 3015 case IPV6_BOUND_IF: 3016 case IPV6_NO_IFT_CELLULAR: 3017 3018 return ip6_ctloutput(so, sopt); 3019 3020 default: 3021 return EPERM; 3022 } 3023} 3024 3025__private_extern__ int 3026icmp6_dgram_send(struct socket *so, int flags, struct mbuf *m, 3027 struct sockaddr *nam, struct mbuf *control, struct proc *p) 3028{ 3029#pragma unused(flags, p) 3030 int error = 0; 3031 struct inpcb *inp = sotoinpcb(so); 3032 struct sockaddr_in6 tmp; 3033 struct sockaddr_in6 *dst = (struct sockaddr_in6 *)(void *)nam; 3034 struct icmp6_hdr *icmp6; 3035 3036 if (inp == NULL || (inp->inp_flags2 & INP2_WANT_FLOW_DIVERT)) { 3037 error = (inp == NULL ? EINVAL : EPROTOTYPE); 3038 goto bad; 3039 } 3040 3041 if (kauth_cred_issuser(so->so_cred)) 3042 return (rip6_output(m, so, SIN6(nam), control, 0)); 3043 3044 /* always copy sockaddr to avoid overwrites */ 3045 if (so->so_state & SS_ISCONNECTED) { 3046 if (nam != NULL) { 3047 error = EISCONN; 3048 goto bad; 3049 } 3050 /* XXX */ 3051 bzero(&tmp, sizeof(tmp)); 3052 tmp.sin6_family = AF_INET6; 3053 tmp.sin6_len = sizeof(struct sockaddr_in6); 3054 bcopy(&inp->in6p_faddr, &tmp.sin6_addr, 3055 sizeof(struct in6_addr)); 3056 dst = &tmp; 3057 } else { 3058 if (nam == NULL) { 3059 error = ENOTCONN; 3060 goto bad; 3061 } 3062 tmp = *(struct sockaddr_in6 *)(void *)nam; 3063 dst = &tmp; 3064 } 3065 3066 /* 3067 * For an ICMPv6 packet, we should know its type and code 3068 */ 3069 if (SOCK_PROTO(so) == IPPROTO_ICMPV6) { 3070 if (m->m_len < sizeof(struct icmp6_hdr) && 3071 (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) { 3072 error = ENOBUFS; 3073 goto bad; 3074 } 3075 icmp6 = mtod(m, struct icmp6_hdr *); 3076 3077 /* 3078 * Allow only to send echo request and node information request 3079 * See RFC 2463 for Echo Request Message format 3080 */ 3081 if ((icmp6->icmp6_type == ICMP6_ECHO_REQUEST && 3082 icmp6->icmp6_code == 0) || 3083 (icmp6->icmp6_type == ICMP6_NI_QUERY && 3084 (icmp6->icmp6_code == ICMP6_NI_SUBJ_IPV6 || 3085 icmp6->icmp6_code == ICMP6_NI_SUBJ_FQDN))) { 3086 /* Good */ 3087 ; 3088 } else { 3089 error = EPERM; 3090 goto bad; 3091 } 3092 } 3093 3094#if ENABLE_DEFAULT_SCOPE 3095 if (dst->sin6_scope_id == 0) { /* not change if specified */ 3096 dst->sin6_scope_id = scope6_addr2default(&dst->sin6_addr); 3097 } 3098#endif 3099 3100 return (rip6_output(m, so, dst, control, 0)); 3101bad: 3102 VERIFY(error != 0); 3103 3104 if (m != NULL) 3105 m_freem(m); 3106 if (control != NULL) 3107 m_freem(control); 3108 3109 return (error); 3110} 3111 3112/* Like rip6_attach but without root privilege enforcement */ 3113__private_extern__ int 3114icmp6_dgram_attach(struct socket *so, int proto, struct proc *p) 3115{ 3116 struct inpcb *inp; 3117 int error; 3118 3119 inp = sotoinpcb(so); 3120 if (inp) 3121 panic("icmp6_dgram_attach"); 3122 3123 if (proto != IPPROTO_ICMPV6) 3124 return EINVAL; 3125 3126 error = soreserve(so, rip_sendspace, rip_recvspace); 3127 if (error) 3128 return error; 3129 error = in_pcballoc(so, &ripcbinfo, p); 3130 if (error) 3131 return error; 3132 inp = (struct inpcb *)so->so_pcb; 3133 inp->inp_vflag |= INP_IPV6; 3134 inp->in6p_ip6_nxt = IPPROTO_ICMPV6; 3135 inp->in6p_hops = -1; /* use kernel default */ 3136 inp->in6p_cksum = -1; 3137 MALLOC(inp->in6p_icmp6filt, struct icmp6_filter *, 3138 sizeof(struct icmp6_filter), M_PCB, M_WAITOK); 3139 if (inp->in6p_icmp6filt == NULL) 3140 return (ENOMEM); 3141 ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt); 3142 return 0; 3143} 3144 3145 3146/* 3147 * Perform rate limit check. 3148 * Returns 0 if it is okay to send the icmp6 packet. 3149 * Returns 1 if the router SHOULD NOT send this icmp6 packet due to rate 3150 * limitation. 3151 * 3152 * XXX per-destination/type check necessary? 3153 */ 3154static int 3155icmp6_ratelimit( 3156 __unused const struct in6_addr *dst, /* not used at this moment */ 3157 __unused const int type, /* not used at this moment */ 3158 __unused const int code) /* not used at this moment */ 3159{ 3160 int ret; 3161 3162 ret = 0; /* okay to send */ 3163 3164 /* PPS limit */ 3165 if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count, 3166 icmp6errppslim)) { 3167 /* The packet is subject to rate limit */ 3168 ret++; 3169 } 3170 3171 return ret; 3172} 3173