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