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