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