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