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