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