]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/ip6_input.c
xnu-123.5.tar.gz
[apple/xnu.git] / bsd / netinet6 / ip6_input.c
CommitLineData
1c79356b
A
1/* $KAME: ip6_input.c,v 1.75 2000/03/28 23:11:05 itojun 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_input.c 8.2 (Berkeley) 1/4/94
65 */
66#define _IP_VHL
67#ifdef __FreeBSD__
68#include "opt_ip6fw.h"
69#endif
70#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
71#include "opt_inet.h"
72#ifdef __NetBSD__ /*XXX*/
73#include "opt_ipsec.h"
74#endif
75#endif
76
77#include <sys/param.h>
78#include <sys/systm.h>
79#include <sys/malloc.h>
80#include <sys/mbuf.h>
81#include <sys/domain.h>
82#include <sys/protosw.h>
83#include <sys/socket.h>
84#include <sys/socketvar.h>
85#include <sys/errno.h>
86#include <sys/time.h>
87#include <sys/kernel.h>
88#include <sys/syslog.h>
89#if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
90#include <sys/proc.h>
91#endif
92
93#include <net/if.h>
94#include <net/if_types.h>
95#include <net/if_dl.h>
96#include <net/route.h>
97#include <net/netisr.h>
98
99#include <netinet/in.h>
100#include <netinet/in_systm.h>
101#if INET
102#include <netinet/ip.h>
103#include <netinet/ip_icmp.h>
104#endif /*INET*/
105#include <netinet/ip6.h>
106#include <netinet6/in6_var.h>
107#include <netinet6/ip6_var.h>
108#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802) || defined (__APPLE__)
109#include <netinet/in_pcb.h>
110#endif
111#if defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)
112#include <netinet6/in6_pcb.h>
113#endif
114#include <netinet/icmp6.h>
115#include <netinet6/in6_ifattach.h>
116#include <netinet6/nd6.h>
117#include <netinet6/in6_prefix.h>
118
119#if MIP6
120#include <netinet6/mip6.h>
121#endif
122
123#if IPV6FIREWALL
124#include <netinet6/ip6_fw.h>
125#endif
126
127#include <netinet6/ip6protosw.h>
128
129/* we need it for NLOOP. */
130#ifndef __bsdi__
131#include "loop.h"
132#endif
133#include "faith.h"
134#include "gif.h"
135#include "bpfilter.h"
136
137#include <net/net_osdep.h>
138
139extern struct domain inet6domain;
140extern struct ip6protosw inet6sw[];
141#ifdef __bsdi__
142#if _BSDI_VERSION < 199802
143extern struct ifnet loif;
144#else
145extern struct ifnet *loifp;
146#endif
147#endif
148
149struct ip6protosw * ip6_protox[IPPROTO_MAX];
150static int ip6qmaxlen = IFQ_MAXLEN;
151struct in6_ifaddr *in6_ifaddr;
152#if !(defined(__FreeBSD__) && __FreeBSD__ >= 4)
153struct ifqueue ip6intrq;
154#endif
155
156#if defined(__NetBSD__) || defined(__OpenBSD__)
157extern struct ifnet loif[NLOOP];
158#endif
159int ip6_forward_srcrt; /* XXX */
160int ip6_sourcecheck; /* XXX */
161int ip6_sourcecheck_interval; /* XXX */
162#if defined(__FreeBSD__) && __FreeBSD__ >= 4
163const int int6intrq_present = 1;
164#endif
165
166#if IPV6FIREWALL
167/* firewall hooks */
168ip6_fw_chk_t *ip6_fw_chk_ptr;
169ip6_fw_ctl_t *ip6_fw_ctl_ptr;
170#endif
171
172struct ip6stat ip6stat;
173
174static void ip6_init2 __P((void *));
175
176static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
177#if PULLDOWN_TEST
178static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int));
179#endif
180
181#if NATPT
182extern int ip6_protocol_tr;
183
184int natpt_in6 __P((struct mbuf *, struct mbuf **));
185extern void ip_forward __P((struct mbuf *, int));
186#endif
187
188/* Initialize the PF_INET6 domain, and add in the pre-defined protos */
189void
190in6_dinit()
191{ register int i;
192 register struct ip6protosw *pr;
193 register struct domain *dp;
194 static inet6domain_initted = 0;
195 extern int in6_proto_count;
196
197 if (!inet6domain_initted)
198 {
199 dp = &inet6domain;
200
201 for (i=0, pr = &inet6sw[0]; i<in6_proto_count; i++, pr++) {
202 if (net_add_proto(pr, dp))
203 printf("in6_dinit: warning net_add_proto failed for pr=%x proto #%d\n", pr, i);
204
205 }
206 inet6domain_initted = 1;
207 }
208}
209
210#ifdef MIP6
211int (*mip6_new_packet_hook)(struct mbuf *m) = 0;
212int (*mip6_route_optimize_hook)(struct mbuf *m) = 0;
213#endif
214
215/*
216 * IP6 initialization: fill in IP6 protocol switch table.
217 * All protocols not implemented in kernel go to raw IP6 protocol handler.
218 */
219void
220ip6_init()
221{
222 register struct protosw *pr;
223 register int i;
224 struct timeval tv;
225
226 pr = (struct protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
227 if (pr == 0)
228 panic("ip6_init");
229 for (i = 0; i < IPPROTO_MAX; i++)
230 ip6_protox[i] = pr;
231 for (pr = inet6domain.dom_protosw; pr; pr = pr->pr_next) {
232 if(!((unsigned int)pr->pr_domain)) continue; /* If uninitialized, skip */
233 if (pr->pr_domain->dom_family == PF_INET6 &&
234 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) {
235 ip6_protox[pr->pr_protocol] = pr;
236 }
237 }
238
239 ip6intrq.ifq_maxlen = ip6qmaxlen;
240 nd6_init();
241 frag6_init();
242#if IPV6FIREWALL
243 ip6_fw_init();
244#endif
245 /*
246 * in many cases, random() here does NOT return random number
247 * as initialization during bootstrap time occur in fixed order.
248 */
249 microtime(&tv);
250 ip6_flow_seq = random() ^ tv.tv_usec;
251 timeout(ip6_init2, (caddr_t)0, 6 * hz);
252}
253
254static void
255ip6_init2(dummy)
256 void *dummy;
257{
258 int ret;
259#if defined(__bsdi__) && _BSDI_VERSION < 199802
260 struct ifnet *loifp = &loif;
261#endif
262#ifdef __APPLE__
263 boolean_t funnel_state;
264 funnel_state = thread_set_funneled(TRUE);
265#endif
266
267 /* get EUI64 from somewhere */
268 ret = in6_ifattach_getifid(NULL);
269
270 /*
271 * to route local address of p2p link to loopback,
272 * assign loopback address first.
273 */
274 in6_ifattach(&loif[0], IN6_IFT_LOOP, NULL, 0);
275
276#if MIP6
277 /* Initialize the Mobile IPv6 code */
278 mip6_init();
279#endif
280
281#import <gif.h>
282#if NGIF > 0
283 gifattach();
284#endif
285#import <faith.h>
286#if NFAITH > 0
287 faithattach();
288#endif
289
290 /* nd6_timer_init */
291 timeout(nd6_timer, (caddr_t)0, hz);
292 /* router renumbering prefix list maintenance */
293 timeout(in6_rr_timer, (caddr_t)0, hz);
294#ifdef __APPLE__
295 (void) thread_set_funneled(funnel_state);
296#endif
297}
298
299#if __FreeBSD__
300/* cheat */
301SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip6_init2, NULL);
302#endif
303
304/*
305 * IP6 input interrupt handling. Just pass the packet to ip6_input.
306 */
307void
308ip6intr(void)
309{
310 int s;
311 struct mbuf *m;
312
313 for (;;) {
314 s = splimp();
315 IF_DEQUEUE(&ip6intrq, m);
316 splx(s);
317 if (m == 0)
318 return;
319 ip6_input(m);
320 }
321}
322
323NETISR_SET(NETISR_IPV6, ip6intr);
324
325extern struct route_in6 ip6_forward_rt;
326
327void
328ip6_input(m)
329 struct mbuf *m;
330{
331 struct ip6_hdr *ip6;
332 int off = sizeof(struct ip6_hdr), nest;
333 u_int32_t plen;
334 u_int32_t rtalert = ~0;
335 int nxt = 0, ours = 0;
336 struct ifnet *deliverifp = NULL;
337#if defined(__bsdi__) && _BSDI_VERSION < 199802
338 struct ifnet *loifp = &loif;
339#endif
340
341#if IPSEC
342 /*
343 * should the inner packet be considered authentic?
344 * see comment in ah4_input().
345 */
346 if (m) {
347 m->m_flags &= ~M_AUTHIPHDR;
348 m->m_flags &= ~M_AUTHIPDGM;
349 }
350#endif
351
352 /*
353 * mbuf statistics by kazu
354 */
355 if (m->m_flags & M_EXT) {
356 if (m->m_next)
357 ip6stat.ip6s_mext2m++;
358 else
359 ip6stat.ip6s_mext1++;
360 } else {
361 if (m->m_next) {
362 if (m->m_flags & M_LOOP)
363 ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
364 else if (m->m_pkthdr.rcvif->if_index <= 31)
365 ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
366 else
367 ip6stat.ip6s_m2m[0]++;
368 } else
369 ip6stat.ip6s_m1++;
370 }
371
372 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
373 ip6stat.ip6s_total++;
374
375#ifndef PULLDOWN_TEST
376 /* XXX is the line really necessary? */
377 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
378#endif
379
380 if (m->m_len < sizeof(struct ip6_hdr)) {
381 struct ifnet *inifp;
382 inifp = m->m_pkthdr.rcvif;
383 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
384 ip6stat.ip6s_toosmall++;
385 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
386 return;
387 }
388 }
389
390 ip6 = mtod(m, struct ip6_hdr *);
391
392 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
393 ip6stat.ip6s_badvers++;
394 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
395 goto bad;
396 }
397
398 ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
399
400#if IPV6FIREWALL
401 /*
402 * Check with the firewall...
403 */
404 if (ip6_fw_chk_ptr) {
405 u_short port = 0;
406 /* If ipfw says divert, we have to just drop packet */
407 /* use port as a dummy argument */
408 if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
409 m_freem(m);
410 m = NULL;
411 }
412 if (!m)
413 return;
414 }
415#endif
416
417 /*
418 * Scope check
419 */
420 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
421 IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
422 ip6stat.ip6s_badscope++;
423 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
424 goto bad;
425 }
426
427 /*
428 * Don't check IPv4 mapped address here. SIIT assumes that
429 * routers would forward IPv6 native packets with IPv4 mapped
430 * address normally.
431 */
432#if 0
433 /*
434 * Reject packets with IPv4 compatible addresses (auto tunnel).
435 *
436 * The code forbids auto tunnel relay case in RFC1933 (the check is
437 * stronger than RFC1933). We may want to re-enable it if mech-xx
438 * is revised to forbid relaying case.
439 */
440 if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
441 IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
442 ip6stat.ip6s_badscope++;
443 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
444 goto bad;
445 }
446#endif
447 if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
448 IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
449 if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
450 ours = 1;
451 deliverifp = m->m_pkthdr.rcvif;
452 goto hbhcheck;
453 } else {
454 ip6stat.ip6s_badscope++;
455 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
456 goto bad;
457 }
458 }
459
460 if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
461 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
462 ours = 1;
463 deliverifp = m->m_pkthdr.rcvif;
464 goto hbhcheck;
465 }
466 } else {
467 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
468 ip6->ip6_src.s6_addr16[1]
469 = htons(m->m_pkthdr.rcvif->if_index);
470 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
471 ip6->ip6_dst.s6_addr16[1]
472 = htons(m->m_pkthdr.rcvif->if_index);
473 }
474
475 /*
476 * Multicast check
477 */
478 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
479 struct in6_multi *in6m = 0;
480
481 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
482 /*
483 * See if we belong to the destination multicast group on the
484 * arrival interface.
485 */
486 IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
487 if (in6m)
488 ours = 1;
489 else if (!ip6_mrouter) {
490 ip6stat.ip6s_notmember++;
491 ip6stat.ip6s_cantforward++;
492 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
493 goto bad;
494 }
495 deliverifp = m->m_pkthdr.rcvif;
496 goto hbhcheck;
497 }
498
499 /*
500 * Unicast check
501 */
502 if (ip6_forward_rt.ro_rt == 0 ||
503 !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
504 &ip6_forward_rt.ro_dst.sin6_addr)) {
505 if (ip6_forward_rt.ro_rt) {
506 RTFREE(ip6_forward_rt.ro_rt);
507 ip6_forward_rt.ro_rt = 0;
508 }
509 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
510 ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
511 ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
512 ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
513
514#if __FreeBSD__ || defined(__APPLE__)
515 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
516#else
517 rtalloc((struct route *)&ip6_forward_rt);
518#endif
519 }
520
521#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
522
523 /*
524 * Accept the packet if the forwarding interface to the destination
525 * according to the routing table is the loopback interface,
526 * unless the associated route has a gateway.
527 * Note that this approach causes to accept a packet if there is a
528 * route to the loopback interface for the destination of the packet.
529 * But we think it's even useful in some situations, e.g. when using
530 * a special daemon which wants to intercept the packet.
531 */
532 if (ip6_forward_rt.ro_rt &&
533 (ip6_forward_rt.ro_rt->rt_flags &
534 (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
535#if 0
536 /*
537 * The check below is redundant since the comparison of
538 * the destination and the key of the rtentry has
539 * already done through looking up the routing table.
540 */
541 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
542 &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) &&
543#endif
544 ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
545 struct in6_ifaddr *ia6 =
546 (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
547 /* packet to tentative address must not be received */
548 if (ia6->ia6_flags & IN6_IFF_ANYCAST)
549 m->m_flags |= M_ANYCAST6;
550 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
551 /* this interface is ready */
552 ours = 1;
553 deliverifp = ia6->ia_ifp; /* correct? */
554 goto hbhcheck;
555 } else {
556 /* this interface is not ready, fall through */
557 }
558 }
559
560 /*
561 * FAITH(Firewall Aided Internet Translator)
562 */
563#if defined(NFAITH) && 0 < NFAITH
564 if (ip6_keepfaith) {
565 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
566 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
567 /* XXX do we need more sanity checks? */
568 ours = 1;
569 deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/
570 goto hbhcheck;
571 }
572 }
573#endif
574
575#if NATPT
576 /*
577 * NAT-PT (Network Address Translation - Protocol Translation)
578 */
579 if (ip6_protocol_tr)
580 {
581 struct mbuf *m1 = NULL;
582
583 switch (natpt_in6(m, &m1))
584 {
585 case IPPROTO_IP: goto processpacket;
586 case IPPROTO_IPV4: ip_forward(m1, 0); break;
587 case IPPROTO_IPV6: ip6_forward(m1, 0); break;
588 case IPPROTO_MAX: /* discard this packet */
589 default: break;
590
591 case IPPROTO_DONE: /* discard without free */
592 return;
593 }
594
595 if (m != m1)
596 m_freem(m);
597
598 return;
599 }
600
601 processpacket:
602#endif
603
604#if 0
605 {
606 /*
607 * Last resort: check in6_ifaddr for incoming interface.
608 * The code is here until I update the "goto ours hack" code above
609 * working right.
610 */
611 struct ifaddr *ifa;
612 for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
613 ifa;
614 ifa = ifa->ifa_list.tqe_next) {
615 if (ifa->ifa_addr == NULL)
616 continue; /* just for safety */
617 if (ifa->ifa_addr->sa_family != AF_INET6)
618 continue;
619 if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) {
620 ours = 1;
621 deliverifp = ifa->ifa_ifp;
622 goto hbhcheck;
623 }
624 }
625 }
626#endif
627
628 /*
629 * Now there is no reason to process the packet if it's not our own
630 * and we're not a router.
631 */
632 if (!ip6_forwarding) {
633 ip6stat.ip6s_cantforward++;
634 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
635 goto bad;
636 }
637
638 hbhcheck:
639 /*
640 * Process Hop-by-Hop options header if it's contained.
641 * m may be modified in ip6_hopopts_input().
642 * If a JumboPayload option is included, plen will also be modified.
643 */
644 plen = (u_int32_t)ntohs(ip6->ip6_plen);
645 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
646 struct ip6_hbh *hbh;
647
648 if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
649#if 0 /*touches NULL pointer*/
650 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
651#endif
652 return; /* m have already been freed */
653 }
654 /* adjust pointer */
655 ip6 = mtod(m, struct ip6_hdr *);
656#ifndef PULLDOWN_TEST
657 /* ip6_hopopts_input() ensures that mbuf is contiguous */
658 hbh = (struct ip6_hbh *)(ip6 + 1);
659#else
660 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
661 sizeof(struct ip6_hbh));
662 if (hbh == NULL) {
663 ip6stat.ip6s_tooshort++;
664 return;
665 }
666#endif
667 nxt = hbh->ip6h_nxt;
668
669 /*
670 * accept the packet if a router alert option is included
671 * and we act as an IPv6 router.
672 */
673 if (rtalert != ~0 && ip6_forwarding)
674 ours = 1;
675 } else
676 nxt = ip6->ip6_nxt;
677
678 /*
679 * Check that the amount of data in the buffers
680 * is as at least much as the IPv6 header would have us expect.
681 * Trim mbufs if longer than we expect.
682 * Drop packet if shorter than we expect.
683 */
684 if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
685 ip6stat.ip6s_tooshort++;
686 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
687 goto bad;
688 }
689 if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
690 if (m->m_len == m->m_pkthdr.len) {
691 m->m_len = sizeof(struct ip6_hdr) + plen;
692 m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
693 } else
694 m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
695 }
696
697 /*
698 * Forward if desirable.
699 */
700 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
701 /*
702 * If we are acting as a multicast router, all
703 * incoming multicast packets are passed to the
704 * kernel-level multicast forwarding function.
705 * The packet is returned (relatively) intact; if
706 * ip6_mforward() returns a non-zero value, the packet
707 * must be discarded, else it may be accepted below.
708 */
709 if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
710 ip6stat.ip6s_cantforward++;
711 m_freem(m);
712 return;
713 }
714 if (!ours) {
715 m_freem(m);
716 return;
717 }
718 } else if (!ours) {
719 ip6_forward(m, 0);
720 return;
721 }
722
723 ip6 = mtod(m, struct ip6_hdr *);
724
725 /*
726 * Malicious party may be able to use IPv4 mapped addr to confuse
727 * tcp/udp stack and bypass security checks (act as if it was from
728 * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious.
729 *
730 * For SIIT end node behavior, you may want to disable the check.
731 * However, you will become vulnerable to attacks using IPv4 mapped
732 * source.
733 */
734 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
735 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
736 ip6stat.ip6s_badscope++;
737 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
738 goto bad;
739 }
740
741 /*
742 * Tell launch routine the next header
743 */
744#if defined(__NetBSD__) && defined(IFA_STATS)
745 if (IFA_STATS && deliverifp != NULL) {
746 struct in6_ifaddr *ia6;
747 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
748 if (ia6)
749 ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len;
750 }
751#endif
752 ip6stat.ip6s_delivered++;
753 in6_ifstat_inc(deliverifp, ifs6_in_deliver);
754 nest = 0;
755
756#if MIP6
757 /*
758 * Mobile IPv6
759 *
760 * Assume that the received packet shall be processed by MIPv6 when
761 * the destination header has been taken care of. Because of this,
762 * some flags have to be reset for later evaluation.
763 */
764 if (mip6_new_packet_hook)
765 (*mip6_new_packet_hook)(m);
766#endif /* MIP6 */
767
768 while (nxt != IPPROTO_DONE) {
769 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
770 ip6stat.ip6s_toomanyhdr++;
771 goto bad;
772 }
773
774 /*
775 * protection against faulty packet - there should be
776 * more sanity checks in header chain processing.
777 */
778 if (m->m_pkthdr.len == 0 || m->m_pkthdr.len < off) {
779 ip6stat.ip6s_tooshort++;
780 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
781 goto bad;
782 }
783
784#if MIP6
785 if ((nxt != IPPROTO_HOPOPTS) && (nxt != IPPROTO_DSTOPTS) &&
786 (nxt != IPPROTO_ROUTING) && (nxt != IPPROTO_FRAGMENT) &&
787 (nxt != IPPROTO_ESP) && (nxt != IPPROTO_AH)) {
788 if (mip6_route_optimize_hook)
789 (*mip6_route_optimize_hook)(m);
790 }
791#endif
792 nxt = (*ip6_protox[nxt]->pr_input)(&m, &off, nxt);
793 }
794 return;
795 bad:
796 m_freem(m);
797}
798
799/*
800 * Hop-by-Hop options header processing. If a valid jumbo payload option is
801 * included, the real payload length will be stored in plenp.
802 */
803static int
804ip6_hopopts_input(plenp, rtalertp, mp, offp)
805 u_int32_t *plenp;
806 u_int32_t *rtalertp; /* XXX: should be stored more smart way */
807 struct mbuf **mp;
808 int *offp;
809{
810 register struct mbuf *m = *mp;
811 int off = *offp, hbhlen;
812 struct ip6_hbh *hbh;
813 u_int8_t *opt;
814
815 /* validation of the length of the header */
816#ifndef PULLDOWN_TEST
817 IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
818 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
819 hbhlen = (hbh->ip6h_len + 1) << 3;
820
821 IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
822 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
823#else
824 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
825 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
826 if (hbh == NULL) {
827 ip6stat.ip6s_tooshort++;
828 return -1;
829 }
830 hbhlen = (hbh->ip6h_len + 1) << 3;
831 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
832 hbhlen);
833 if (hbh == NULL) {
834 ip6stat.ip6s_tooshort++;
835 return -1;
836 }
837#endif
838 off += hbhlen;
839 hbhlen -= sizeof(struct ip6_hbh);
840 opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
841
842 if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
843 hbhlen, rtalertp, plenp) < 0)
844 return(-1);
845
846 *offp = off;
847 *mp = m;
848 return(0);
849}
850
851/*
852 * Search header for all Hop-by-hop options and process each option.
853 * This function is separate from ip6_hopopts_input() in order to
854 * handle a case where the sending node itself process its hop-by-hop
855 * options header. In such a case, the function is called from ip6_output().
856 */
857int
858ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
859 struct mbuf *m;
860 u_int8_t *opthead;
861 int hbhlen;
862 u_int32_t *rtalertp;
863 u_int32_t *plenp;
864{
865 struct ip6_hdr *ip6;
866 int optlen = 0;
867 u_int8_t *opt = opthead;
868 u_int16_t rtalert_val;
869
870 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
871 switch(*opt) {
872 case IP6OPT_PAD1:
873 optlen = 1;
874 break;
875 case IP6OPT_PADN:
876 if (hbhlen < IP6OPT_MINLEN) {
877 ip6stat.ip6s_toosmall++;
878 goto bad;
879 }
880 optlen = *(opt + 1) + 2;
881 break;
882 case IP6OPT_RTALERT:
883 /* XXX may need check for alignment */
884 if (hbhlen < IP6OPT_RTALERT_LEN) {
885 ip6stat.ip6s_toosmall++;
886 goto bad;
887 }
888 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2)
889 /* XXX: should we discard the packet? */
890 log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
891 *(opt + 1));
892 optlen = IP6OPT_RTALERT_LEN;
893 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
894 *rtalertp = ntohs(rtalert_val);
895 break;
896 case IP6OPT_JUMBO:
897 /* XXX may need check for alignment */
898 if (hbhlen < IP6OPT_JUMBO_LEN) {
899 ip6stat.ip6s_toosmall++;
900 goto bad;
901 }
902 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
903 /* XXX: should we discard the packet? */
904 log(LOG_ERR, "length of jumbopayload opt "
905 "is inconsistent(%d)",
906 *(opt + 1));
907 optlen = IP6OPT_JUMBO_LEN;
908
909 /*
910 * We can simply cast because of the alignment
911 * requirement of the jumbo payload option.
912 */
913#if 0
914 *plenp = ntohl(*(u_int32_t *)(opt + 2));
915#else
916 bcopy(opt + 2, plenp, sizeof(*plenp));
917 *plenp = htonl(*plenp);
918#endif
919 if (*plenp <= IPV6_MAXPACKET) {
920 /*
921 * jumbo payload length must be larger
922 * than 65535
923 */
924 ip6stat.ip6s_badoptions++;
925 icmp6_error(m, ICMP6_PARAM_PROB,
926 ICMP6_PARAMPROB_HEADER,
927 sizeof(struct ip6_hdr) +
928 sizeof(struct ip6_hbh) +
929 opt + 2 - opthead);
930 return(-1);
931 }
932
933 ip6 = mtod(m, struct ip6_hdr *);
934 if (ip6->ip6_plen) {
935 /*
936 * IPv6 packets that have non 0 payload length
937 * must not contain a jumbo paylod option.
938 */
939 ip6stat.ip6s_badoptions++;
940 icmp6_error(m, ICMP6_PARAM_PROB,
941 ICMP6_PARAMPROB_HEADER,
942 sizeof(struct ip6_hdr) +
943 sizeof(struct ip6_hbh) +
944 opt - opthead);
945 return(-1);
946 }
947 break;
948 default: /* unknown option */
949 if (hbhlen < IP6OPT_MINLEN) {
950 ip6stat.ip6s_toosmall++;
951 goto bad;
952 }
953 if ((optlen = ip6_unknown_opt(opt, m,
954 sizeof(struct ip6_hdr) +
955 sizeof(struct ip6_hbh) +
956 opt - opthead)) == -1)
957 return(-1);
958 optlen += 2;
959 break;
960 }
961 }
962
963 return(0);
964
965 bad:
966 m_freem(m);
967 return(-1);
968}
969
970/*
971 * Unknown option processing.
972 * The third argument `off' is the offset from the IPv6 header to the option,
973 * which is necessary if the IPv6 header the and option header and IPv6 header
974 * is not continuous in order to return an ICMPv6 error.
975 */
976int
977ip6_unknown_opt(optp, m, off)
978 u_int8_t *optp;
979 struct mbuf *m;
980 int off;
981{
982 struct ip6_hdr *ip6;
983
984 switch(IP6OPT_TYPE(*optp)) {
985 case IP6OPT_TYPE_SKIP: /* ignore the option */
986 return((int)*(optp + 1));
987 case IP6OPT_TYPE_DISCARD: /* silently discard */
988 m_freem(m);
989 return(-1);
990 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
991 ip6stat.ip6s_badoptions++;
992 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
993 return(-1);
994 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
995 ip6stat.ip6s_badoptions++;
996 ip6 = mtod(m, struct ip6_hdr *);
997 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
998 (m->m_flags & (M_BCAST|M_MCAST)))
999 m_freem(m);
1000 else
1001 icmp6_error(m, ICMP6_PARAM_PROB,
1002 ICMP6_PARAMPROB_OPTION, off);
1003 return(-1);
1004 }
1005
1006 m_freem(m); /* XXX: NOTREACHED */
1007 return(-1);
1008}
1009
1010/*
1011 * Create the "control" list for this pcb.
1012 * The function will not modify mbuf chain at all.
1013 *
1014 * with KAME mbuf chain restriction:
1015 * The routine will be called from upper layer handlers like tcp6_input().
1016 * Thus the routine assumes that the caller (tcp6_input) have already
1017 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
1018 * very first mbuf on the mbuf chain.
1019 */
1020void
1021ip6_savecontrol(in6p, ip6, m, ctl, prevctlp)
1022#if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined(__APPLE__)
1023 register struct inpcb *in6p;
1024#else
1025 register struct in6pcb *in6p;
1026#endif
1027 register struct ip6_hdr *ip6;
1028 register struct mbuf *m;
1029 struct ip6_recvpktopts *ctl, **prevctlp;
1030{
1031 register struct mbuf **mp;
1032 struct cmsghdr *cm = NULL;
1033 struct ip6_recvpktopts *prevctl = NULL;
1034#if HAVE_NRL_INPCB
1035# define in6p_flags inp_flags
1036#endif
1037#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
1038 struct proc *p = current_proc(); /* XXX */
1039#endif
1040#ifdef __bsdi__
1041# define sbcreatecontrol so_cmsg
1042#endif
1043 int privileged = 0;
1044
1045
1046 if (ctl == NULL) /* validity check */
1047 return;
1048 bzero(ctl, sizeof(*ctl)); /* XXX is it really OK? */
1049 mp = &ctl->head;
1050
1051 /*
1052 * If caller wanted to keep history, allocate space to store the
1053 * history at the first time.
1054 */
1055 if (prevctlp) {
1056 if (*prevctlp == NULL) {
1057 MALLOC(prevctl, struct ip6_recvpktopts *,
1058 sizeof(*prevctl), M_IP6OPT, M_NOWAIT);
1059 if (prevctl == NULL) {
1060 printf("ip6_savecontrol: can't allocate "
1061 " enough space for history\n");
1062 return;
1063 }
1064 bzero(prevctl, sizeof(*prevctl));
1065 *prevctlp = prevctl;
1066 }
1067 else
1068 prevctl = *prevctlp;
1069 }
1070
1071#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ == 3)
1072 if (p && !suser(p->p_ucred, &p->p_acflag))
1073 privileged++;
1074#elif defined(__FreeBSD__) && __FreeBSD__ >= 4
1075 if (p && !suser(p))
1076 privileged++;
1077#else
1078#if HAVE_NRL_INPCB
1079 if ((in6p->inp_socket->so_state & SS_PRIV) != 0)
1080 privileged++;
1081#else
1082 if ((in6p->in6p_socket->so_state & SS_PRIV) != 0)
1083 privileged++;
1084#endif
1085#endif
1086
1087#if SO_TIMESTAMP
1088 if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
1089 struct timeval tv;
1090
1091 microtime(&tv);
1092 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1093 SCM_TIMESTAMP, SOL_SOCKET);
1094 if (*mp) {
1095 /* always set regradless of the previous value */
1096 ctl->timestamp = *mp;
1097 mp = &(*mp)->m_next;
1098 }
1099 }
1100#endif
1101
1102 /* RFC 2292 sec. 5 */
1103 if (in6p->in6p_flags & IN6P_PKTINFO) {
1104 struct in6_pktinfo pi6, *prevpi = NULL;
1105 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1106 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
1107 pi6.ipi6_addr.s6_addr16[1] = 0;
1108 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
1109 ? m->m_pkthdr.rcvif->if_index
1110 : 0;
1111 if (prevctl && prevctl->pktinfo) {
1112 cm = mtod(prevctl->pktinfo, struct cmsghdr *);
1113 prevpi = (struct in6_pktinfo *)CMSG_DATA(cm);
1114 }
1115
1116 /*
1117 * Make a new option only if this is the first time or if the
1118 * option value is chaned from last time.
1119 */
1120 if (prevpi == NULL || bcmp(prevpi, &pi6, sizeof(pi6))) {
1121 *mp = sbcreatecontrol((caddr_t) &pi6,
1122 sizeof(struct in6_pktinfo),
1123 IPV6_PKTINFO,
1124 IPPROTO_IPV6);
1125 if (*mp) {
1126 ctl->pktinfo = *mp;
1127 mp = &(*mp)->m_next;
1128 }
1129 }
1130 }
1131
1132 if (in6p->in6p_flags & IN6P_HOPLIMIT) {
1133 int hlim = ip6->ip6_hlim & 0xff, oldhlim = -1;
1134
1135 if (prevctl && prevctl->hlim) {
1136 cm = mtod(prevctl->hlim, struct cmsghdr *);
1137 oldhlim = (*(int *)CMSG_DATA(cm)) & 0xff;
1138 }
1139
1140 if (oldhlim < 0 || hlim != oldhlim) {
1141 *mp = sbcreatecontrol((caddr_t) &hlim,
1142 sizeof(int), IPV6_HOPLIMIT,
1143 IPPROTO_IPV6);
1144 if (*mp) {
1145 ctl->hlim = *mp;
1146 mp = &(*mp)->m_next;
1147 }
1148 }
1149 }
1150
1151 /*
1152 * IPV6_HOPOPTS socket option. We require super-user privilege
1153 * for the option, but it might be too strict, since there might
1154 * be some hop-by-hop options which can be returned to normal user.
1155 * See RFC 2292 section 6.
1156 */
1157 if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
1158 /*
1159 * Check if a hop-by-hop options header is contatined in the
1160 * received packet, and if so, store the options as ancillary
1161 * data. Note that a hop-by-hop options header must be
1162 * just after the IPv6 header, which fact is assured through
1163 * the IPv6 input processing.
1164 */
1165 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1166 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1167 struct ip6_hbh *hbh, *prevhbh = NULL;
1168 int hbhlen = 0, prevhbhlen = 0;
1169#ifdef PULLDOWN_TEST
1170 struct mbuf *ext;
1171#endif
1172
1173#ifndef PULLDOWN_TEST
1174 hbh = (struct ip6_hbh *)(ip6 + 1);
1175 hbhlen = (hbh->ip6h_len + 1) << 3;
1176#else
1177 ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
1178 ip6->ip6_nxt);
1179 if (ext == NULL) {
1180 ip6stat.ip6s_tooshort++;
1181 return;
1182 }
1183 hbh = mtod(ext, struct ip6_hbh *);
1184 hbhlen = (hbh->ip6h_len + 1) << 3;
1185 if (hbhlen != ext->m_len) {
1186 m_freem(ext);
1187 ip6stat.ip6s_tooshort++;
1188 return;
1189 }
1190#endif
1191
1192 if (prevctl && prevctl->hbh) {
1193 cm = mtod(prevctl->hbh, struct cmsghdr *);
1194 prevhbh = (struct ip6_hbh *)CMSG_DATA(cm);
1195 prevhbhlen = (prevhbh->ip6h_len + 1) << 3;
1196 }
1197 /*
1198 * Check if there's difference between the current
1199 * and previous HbH headers.
1200 * XXX: should the next header field be ignored?
1201 */
1202 if (prevhbh == NULL || hbhlen != prevhbhlen ||
1203 bcmp(prevhbh, hbh, hbhlen)) {
1204 /*
1205 * XXX: We copy whole the header even if a
1206 * jumbo payload option is included, which
1207 * option is to be removed before returning
1208 * in the RFC 2292.
1209 * Note: this constraint is removed in
1210 * 2292bis.
1211 */
1212 *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1213 IPV6_HOPOPTS,
1214 IPPROTO_IPV6);
1215 if (*mp) {
1216 ctl->hbh = *mp;
1217 mp = &(*mp)->m_next;
1218 }
1219 }
1220#ifdef PULLDOWN_TEST
1221 m_freem(ext);
1222#endif
1223 }
1224 }
1225
1226 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
1227 if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) {
1228 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1229 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
1230 int rthdr = 0; /* flag if we've passed a routing header */
1231
1232 /*
1233 * Search for destination options headers or routing
1234 * header(s) through the header chain, and stores each
1235 * header as ancillary data.
1236 * Note that the order of the headers remains in
1237 * the chain of ancillary data.
1238 */
1239 while (1) { /* is explicit loop prevention necessary? */
1240 struct ip6_ext *ip6e = NULL;
1241 int elen;
1242#ifdef PULLDOWN_TEST
1243 struct mbuf *ext = NULL;
1244#endif
1245
1246 /*
1247 * if it is not an extension header, don't try to
1248 * pull it from the chain.
1249 */
1250 switch (nxt) {
1251 case IPPROTO_DSTOPTS:
1252 case IPPROTO_ROUTING:
1253 case IPPROTO_HOPOPTS:
1254 case IPPROTO_AH: /* is it possible? */
1255 break;
1256 default:
1257 goto loopend;
1258 }
1259
1260#ifndef PULLDOWN_TEST
1261 if (off + sizeof(*ip6e) > m->m_len)
1262 goto loopend;
1263 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1264 if (nxt == IPPROTO_AH)
1265 elen = (ip6e->ip6e_len + 2) << 2;
1266 else
1267 elen = (ip6e->ip6e_len + 1) << 3;
1268 if (off + elen > m->m_len)
1269 goto loopend;
1270#else
1271 ext = ip6_pullexthdr(m, off, nxt);
1272 if (ext == NULL) {
1273 ip6stat.ip6s_tooshort++;
1274 return;
1275 }
1276 ip6e = mtod(ext, struct ip6_ext *);
1277 if (nxt == IPPROTO_AH)
1278 elen = (ip6e->ip6e_len + 2) << 2;
1279 else
1280 elen = (ip6e->ip6e_len + 1) << 3;
1281 if (elen != ext->m_len) {
1282 m_freem(ext);
1283 ip6stat.ip6s_tooshort++;
1284 return;
1285 }
1286#endif
1287
1288 switch (nxt) {
1289 case IPPROTO_DSTOPTS:
1290 {
1291 struct ip6_dest *prevdest1 = NULL,
1292 *prevdest2 = NULL;
1293 int prevdestlen;
1294
1295 if ((in6p->in6p_flags &
1296 (IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) == 0)
1297 break;
1298
1299 /*
1300 * We also require super-user privilege for
1301 * the option.
1302 * See the comments on IN6_HOPOPTS.
1303 */
1304 if (!privileged)
1305 break;
1306
1307 /*
1308 * Save a dst opt header before a routing
1309 * header if the user wanted.
1310 */
1311 if (rthdr == 0 &&
1312 (in6p->in6p_flags & IN6P_RTHDRDSTOPTS)) {
1313 if (prevctl && prevctl->dest1) {
1314 cm = mtod(prevctl->dest1,
1315 struct cmsghdr *);
1316 prevdest1 = (struct ip6_dest *)CMSG_DATA(cm);
1317 prevdestlen = (prevdest1->ip6d_len + 1) << 3;
1318 }
1319
1320 /*
1321 * If this is the 1st dst opt header
1322 * (that is placed before rthdr)
1323 * we enconter and this header is
1324 * not different from the previous one,
1325 * simply ignore the header.
1326 */
1327 if (ctl->dest1 == NULL &&
1328 (prevdest1 &&
1329 prevdestlen == elen &&
1330 bcmp(ip6e, prevdest1, elen) == 0))
1331 break;
1332
1333 *mp = sbcreatecontrol((caddr_t)ip6e,
1334 elen,
1335 IPV6_RTHDRDSTOPTS,
1336 IPPROTO_IPV6);
1337 if (ctl->dest1 == NULL)
1338 ctl->dest1 = *mp;
1339 if (*mp)
1340 mp = &(*mp)->m_next;
1341 }
1342 /*
1343 * Save a dst opt header after a routing
1344 * header if the user wanted.
1345 */
1346 if (rthdr &&
1347 (in6p->in6p_flags & IN6P_DSTOPTS)) {
1348 if (prevctl && prevctl->dest2) {
1349 cm = mtod(prevctl->dest2,
1350 struct cmsghdr *);
1351 prevdest2 = (struct ip6_dest *)CMSG_DATA(cm);
1352 prevdestlen = (prevdest2->ip6d_len + 1) << 3;
1353 }
1354 /* see the above comment */
1355 if (ctl->dest2 == NULL &&
1356 (prevdest2 &&
1357 prevdestlen == elen &&
1358 bcmp(ip6e, prevdest2, elen) == 0))
1359 break;
1360
1361 *mp = sbcreatecontrol((caddr_t)ip6e,
1362 elen,
1363 IPV6_DSTOPTS,
1364 IPPROTO_IPV6);
1365 if (ctl->dest2 == NULL)
1366 ctl->dest2 = *mp;
1367
1368 if (*mp)
1369 mp = &(*mp)->m_next;
1370 }
1371 break;
1372 }
1373 case IPPROTO_ROUTING:
1374 {
1375 struct ip6_rthdr *prevrth = NULL;
1376 int prevrhlen = 0;
1377
1378 rthdr++;
1379 if (!in6p->in6p_flags & IN6P_RTHDR)
1380 break;
1381
1382 if (prevctl && prevctl->rthdr) {
1383 cm = mtod(prevctl->rthdr,
1384 struct cmsghdr *);
1385 prevrth = (struct ip6_rthdr *)CMSG_DATA(cm);
1386 prevrhlen =
1387 (prevrth->ip6r_len + 1) << 3;
1388 }
1389
1390 /*
1391 * Check if the rthdr should be passed to
1392 * a user. See the comments for dstopt hdr.
1393 */
1394 if (ctl->rthdr == NULL && prevrth &&
1395 prevrhlen == elen &&
1396 bcmp(ip6e, prevrth, elen) == 0)
1397 break;
1398
1399 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1400 IPV6_RTHDR,
1401 IPPROTO_IPV6);
1402 if (ctl->rthdr == NULL)
1403 ctl->rthdr = *mp;
1404 if (*mp)
1405 mp = &(*mp)->m_next;
1406 break;
1407 }
1408 case IPPROTO_HOPOPTS:
1409 case IPPROTO_AH: /* is it possible? */
1410 break;
1411
1412 default:
1413 /*
1414 * other cases have been filtered in the above.
1415 * none will visit this case. here we supply
1416 * the code just in case (nxt overwritten or
1417 * other cases).
1418 */
1419#ifdef PULLDOWN_TEST
1420 m_freem(ext);
1421#endif
1422 goto loopend;
1423
1424 }
1425
1426 /* proceed with the next header. */
1427 off += elen;
1428 nxt = ip6e->ip6e_nxt;
1429 ip6e = NULL;
1430#ifdef PULLDOWN_TEST
1431 m_freem(ext);
1432 ext = NULL;
1433#endif
1434 }
1435 loopend:
1436 }
1437
1438#ifdef __bsdi__
1439# undef sbcreatecontrol
1440#endif
1441#ifdef __OpenBSD__
1442# undef in6p_flags
1443#endif
1444}
1445
1446#ifdef PULLDOWN_TEST
1447/*
1448 * pull single extension header from mbuf chain. returns single mbuf that
1449 * contains the result, or NULL on error.
1450 */
1451static struct mbuf *
1452ip6_pullexthdr(m, off, nxt)
1453 struct mbuf *m;
1454 size_t off;
1455 int nxt;
1456{
1457 struct ip6_ext ip6e;
1458 size_t elen;
1459 struct mbuf *n;
1460
1461#ifdef DIAGNOSTIC
1462 switch (nxt) {
1463 case IPPROTO_DSTOPTS:
1464 case IPPROTO_ROUTING:
1465 case IPPROTO_HOPOPTS:
1466 case IPPROTO_AH: /* is it possible? */
1467 break;
1468 default:
1469 printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
1470 }
1471#endif
1472
1473 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1474 if (nxt == IPPROTO_AH)
1475 elen = (ip6e.ip6e_len + 2) << 2;
1476 else
1477 elen = (ip6e.ip6e_len + 1) << 3;
1478
1479 MGET(n, M_DONTWAIT, MT_DATA);
1480 if (n && elen >= MLEN) {
1481 MCLGET(n, M_DONTWAIT);
1482 if ((n->m_flags & M_EXT) == 0) {
1483 m_free(n);
1484 n = NULL;
1485 }
1486 }
1487 if (!n)
1488 return NULL;
1489
1490 n->m_len = 0;
1491 if (elen >= M_TRAILINGSPACE(n)) {
1492 m_free(n);
1493 return NULL;
1494 }
1495
1496 m_copydata(m, off, elen, mtod(n, caddr_t));
1497 n->m_len = elen;
1498 return n;
1499}
1500#endif
1501
1502/*
1503 * Merge new IPv6 received options to previous ones.
1504 * If a new option is not given, just re-link the option chain.
1505 * If an old option exists but a corresponding new one doesn't, just
1506 * keep the ole option.
1507 * If a new option exists but a corresponding old one doesn't, just
1508 * copy the new option.
1509 * If both new and old options exist, free old one and overwrite the option
1510 * with the new option.
1511 * Otherwise, do nothing for the option.
1512 * XXX: in any case, options that don't follow the recommend order and
1513 * number of extension headers (RFC 2460 Section 4.1) are simply ignored.
1514 * XXX: We assume that each option is stored in a single mbuf.
1515 */
1516#define CLEAN_RECVOPT(old, type) \
1517do { \
1518 if ((old)->type && (old)->type->m_next) { \
1519 (old)->type->m_next = NULL; \
1520 } \
1521} while (0)
1522#define MERGE_RECVOPT(new, old, type) if ((new)->type) {\
1523 if ((old)->type)\
1524 m_free((old)->type);\
1525 (old)->type = m_copy((new)->type, 0, (new)->type->m_len);\
1526 if (((old)->type) && ((old)->type->m_next)) {\
1527 m_freem((old)->type);\
1528 old->type = NULL;\
1529 }\
1530 }
1531#define LINK_RECVOPTS(opt, type, p) if ((opt)->type) {\
1532 *(p) = (opt)->type;\
1533 (p) = &(opt)->type->m_next;\
1534 }
1535
1536static void dump_inputopts __P((char *, struct ip6_recvpktopts *));
1537static void
1538dump_inputopts(str, p)
1539 char *str;
1540 struct ip6_recvpktopts *p;
1541{
1542#if 1
1543 return;
1544#else
1545#define PRINT1(p, name) \
1546do { \
1547 if (p->name) { \
1548 printf(" %s: %p", #name, (p)->name); \
1549 if (p->name->m_next) \
1550 printf("[%p]", (p)->name->m_next); \
1551 } \
1552} while (0)
1553
1554 printf("%s p=%p head=%p", str, p, p->head);
1555 PRINT1(p, hlim);
1556 PRINT1(p, pktinfo);
1557 PRINT1(p, hbh);
1558 PRINT1(p, dest1);
1559 PRINT1(p, dest2);
1560 PRINT1(p, rthdr);
1561 printf("\n");
1562#undef PRINT1
1563#endif
1564}
1565
1566void
1567ip6_update_recvpcbopt(old, new)
1568 struct ip6_recvpktopts *new, *old;
1569{
1570 struct mbuf **mp;
1571
1572 if (old == NULL) {
1573 printf("ip6_update_recvpcbopt: invalid arguments\n");
1574 return;
1575 }
1576
1577 dump_inputopts("old before", old);
1578 if (new)
1579 dump_inputopts("new before", new);
1580
1581#if 0
1582 /*
1583 * cleanup m->m_next linkage. note that we do it in reverse order
1584 * to prevent possible memory leakage.
1585 */
1586 old->head = NULL;
1587 CLEAN_RECVOPT(old, rthdr);
1588 CLEAN_RECVOPT(old, dest2);
1589 CLEAN_RECVOPT(old, dest1);
1590 CLEAN_RECVOPT(old, hbh);
1591 CLEAN_RECVOPT(old, pktinfo);
1592 CLEAN_RECVOPT(old, hlim);
1593#endif
1594
1595 if (new) {
1596 MERGE_RECVOPT(new, old, hlim);
1597 MERGE_RECVOPT(new, old, pktinfo);
1598 MERGE_RECVOPT(new, old, hbh);
1599 MERGE_RECVOPT(new, old, dest1);
1600 MERGE_RECVOPT(new, old, dest2);
1601 MERGE_RECVOPT(new, old, rthdr);
1602 }
1603
1604 dump_inputopts("old middle", old);
1605 if (new)
1606 dump_inputopts("new middle", new);
1607
1608 /* link options */
1609 mp = &old->head;
1610 LINK_RECVOPTS(old, hlim, mp);
1611 LINK_RECVOPTS(old, pktinfo, mp);
1612 LINK_RECVOPTS(old, hbh, mp);
1613 LINK_RECVOPTS(old, dest1, mp);
1614 LINK_RECVOPTS(old, dest2, mp);
1615 LINK_RECVOPTS(old, rthdr, mp);
1616 *mp = NULL;
1617
1618 dump_inputopts("old after", old);
1619 if (new)
1620 dump_inputopts("new after", new);
1621}
1622
1623#undef MERGE_RECVOPT
1624#undef LINK_RECVOPTS
1625
1626void
1627ip6_reset_rcvopt(opts, optname)
1628 struct ip6_recvpktopts *opts;
1629 int optname;
1630{
1631 if (opts == NULL)
1632 return;
1633
1634 switch(optname) {
1635 case IPV6_RECVPKTINFO:
1636 if (opts->pktinfo) m_free(opts->pktinfo);
1637 opts->pktinfo = NULL;
1638 break;
1639 case IPV6_RECVHOPLIMIT:
1640 if (opts->hlim) m_free(opts->hlim);
1641 opts->hlim = NULL;
1642 break;
1643 case IPV6_RECVHOPOPTS:
1644 if (opts->hbh) m_free(opts->hbh);
1645 opts->hbh = NULL;
1646 break;
1647 case IPV6_RECVRTHDRDSTOPTS:
1648 if (opts->dest1) m_free(opts->dest1);
1649 opts->dest1 = NULL;
1650 break;
1651 case IPV6_RECVDSTOPTS:
1652 if (opts->dest2) m_free(opts->dest2);
1653 opts->dest2 = NULL;
1654 break;
1655 case IPV6_RECVRTHDR:
1656 if (opts->rthdr) m_free(opts->rthdr);
1657 opts->rthdr = NULL;
1658 break;
1659 default:
1660 printf("ip6_reset_rcvopt: invalid option name (%d)\n",
1661 optname);
1662 return;
1663 }
1664
1665 ip6_update_recvpcbopt(opts, NULL); /* re-link the option chain */
1666}
1667
1668/*
1669 * Get pointer to the previous header followed by the header
1670 * currently processed.
1671 * XXX: This function supposes that
1672 * M includes all headers,
1673 * the next header field and the header length field of each header
1674 * are valid, and
1675 * the sum of each header length equals to OFF.
1676 * Because of these assumptions, this function must be called very
1677 * carefully. Moreover, it will not be used in the near future when
1678 * we develop `neater' mechanism to process extension headers.
1679 */
1680char *
1681ip6_get_prevhdr(m, off)
1682 struct mbuf *m;
1683 int off;
1684{
1685 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1686
1687 if (off == sizeof(struct ip6_hdr))
1688 return(&ip6->ip6_nxt);
1689 else {
1690 int len, nxt;
1691 struct ip6_ext *ip6e = NULL;
1692
1693 nxt = ip6->ip6_nxt;
1694 len = sizeof(struct ip6_hdr);
1695 while (len < off) {
1696 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1697
1698 switch(nxt) {
1699 case IPPROTO_FRAGMENT:
1700 len += sizeof(struct ip6_frag);
1701 break;
1702 case IPPROTO_AH:
1703 len += (ip6e->ip6e_len + 2) << 2;
1704 break;
1705 default:
1706 len += (ip6e->ip6e_len + 1) << 3;
1707 break;
1708 }
1709 nxt = ip6e->ip6e_nxt;
1710 }
1711 if (ip6e)
1712 return(&ip6e->ip6e_nxt);
1713 else
1714 return NULL;
1715 }
1716}
1717
1718/*
1719 * get next header offset. m will be retained.
1720 */
1721int
1722ip6_nexthdr(m, off, proto, nxtp)
1723 struct mbuf *m;
1724 int off;
1725 int proto;
1726 int *nxtp;
1727{
1728 struct ip6_hdr ip6;
1729 struct ip6_ext ip6e;
1730 struct ip6_frag fh;
1731
1732 /* just in case */
1733 if (m == NULL)
1734 panic("ip6_nexthdr: m == NULL");
1735 if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
1736 return -1;
1737
1738 switch (proto) {
1739 case IPPROTO_IPV6:
1740 if (m->m_pkthdr.len < off + sizeof(ip6))
1741 return -1;
1742 m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
1743 if (nxtp)
1744 *nxtp = ip6.ip6_nxt;
1745 off += sizeof(ip6);
1746 return off;
1747
1748 case IPPROTO_FRAGMENT:
1749 /*
1750 * terminate parsing if it is not the first fragment,
1751 * it does not make sense to parse through it.
1752 */
1753 if (m->m_pkthdr.len < off + sizeof(fh))
1754 return -1;
1755 m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
1756 if ((ntohs(fh.ip6f_offlg) & IP6F_OFF_MASK) != 0)
1757 return -1;
1758 if (nxtp)
1759 *nxtp = fh.ip6f_nxt;
1760 off += sizeof(struct ip6_frag);
1761 return off;
1762
1763 case IPPROTO_AH:
1764 if (m->m_pkthdr.len < off + sizeof(ip6e))
1765 return -1;
1766 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1767 if (nxtp)
1768 *nxtp = ip6e.ip6e_nxt;
1769 off += (ip6e.ip6e_len + 2) << 2;
1770 return off;
1771
1772 case IPPROTO_HOPOPTS:
1773 case IPPROTO_ROUTING:
1774 case IPPROTO_DSTOPTS:
1775 if (m->m_pkthdr.len < off + sizeof(ip6e))
1776 return -1;
1777 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1778 if (nxtp)
1779 *nxtp = ip6e.ip6e_nxt;
1780 off += (ip6e.ip6e_len + 1) << 3;
1781 return off;
1782
1783 case IPPROTO_NONE:
1784 case IPPROTO_ESP:
1785 case IPPROTO_IPCOMP:
1786 /* give up */
1787 return -1;
1788
1789 default:
1790 return -1;
1791 }
1792
1793 return -1;
1794}
1795
1796/*
1797 * get offset for the last header in the chain. m will be kept untainted.
1798 */
1799int
1800ip6_lasthdr(m, off, proto, nxtp)
1801 struct mbuf *m;
1802 int off;
1803 int proto;
1804 int *nxtp;
1805{
1806 int newoff;
1807 int nxt;
1808
1809 if (!nxtp) {
1810 nxt = -1;
1811 nxtp = &nxt;
1812 }
1813 while (1) {
1814 newoff = ip6_nexthdr(m, off, proto, nxtp);
1815 if (newoff < 0)
1816 return off;
1817 else if (newoff < off)
1818 return -1; /* invalid */
1819 else if (newoff == off)
1820 return newoff;
1821
1822 off = newoff;
1823 proto = *nxtp;
1824 }
1825}
1826
1827/*
1828 * System control for IP6
1829 */
1830
1831u_char inet6ctlerrmap[PRC_NCMDS] = {
1832 0, 0, 0, 0,
1833 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1834 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1835 EMSGSIZE, EHOSTUNREACH, 0, 0,
1836 0, 0, 0, 0,
1837 ENOPROTOOPT
1838};
1839
1840#if defined(__NetBSD__) || defined(__OpenBSD__)
1841#include <vm/vm.h>
1842#include <sys/sysctl.h>
1843
1844int
1845ip6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1846 int *name;
1847 u_int namelen;
1848 void *oldp;
1849 size_t *oldlenp;
1850 void *newp;
1851 size_t newlen;
1852{
1853 /* All sysctl names at this level are terminal. */
1854 if (namelen != 1)
1855 return ENOTDIR;
1856
1857 switch (name[0]) {
1858
1859 case IPV6CTL_FORWARDING:
1860 return sysctl_int(oldp, oldlenp, newp, newlen,
1861 &ip6_forwarding);
1862 case IPV6CTL_SENDREDIRECTS:
1863 return sysctl_int(oldp, oldlenp, newp, newlen,
1864 &ip6_sendredirects);
1865 case IPV6CTL_DEFHLIM:
1866 return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_defhlim);
1867 case IPV6CTL_MAXFRAGPACKETS:
1868 return sysctl_int(oldp, oldlenp, newp, newlen,
1869 &ip6_maxfragpackets);
1870 case IPV6CTL_ACCEPT_RTADV:
1871 return sysctl_int(oldp, oldlenp, newp, newlen,
1872 &ip6_accept_rtadv);
1873 case IPV6CTL_KEEPFAITH:
1874 return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_keepfaith);
1875 case IPV6CTL_LOG_INTERVAL:
1876 return sysctl_int(oldp, oldlenp, newp, newlen,
1877 &ip6_log_interval);
1878 case IPV6CTL_HDRNESTLIMIT:
1879 return sysctl_int(oldp, oldlenp, newp, newlen,
1880 &ip6_hdrnestlimit);
1881 case IPV6CTL_DAD_COUNT:
1882 return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_dad_count);
1883 case IPV6CTL_AUTO_FLOWLABEL:
1884 return sysctl_int(oldp, oldlenp, newp, newlen,
1885 &ip6_auto_flowlabel);
1886 case IPV6CTL_DEFMCASTHLIM:
1887 return sysctl_int(oldp, oldlenp, newp, newlen,
1888 &ip6_defmcasthlim);
1889 case IPV6CTL_GIF_HLIM:
1890 return sysctl_int(oldp, oldlenp, newp, newlen,
1891 &ip6_gif_hlim);
1892 case IPV6CTL_KAME_VERSION:
1893 return sysctl_rdstring(oldp, oldlenp, newp, __KAME_VERSION);
1894 case IPV6CTL_USE_DEPRECATED:
1895 return sysctl_int(oldp, oldlenp, newp, newlen,
1896 &ip6_use_deprecated);
1897 case IPV6CTL_RR_PRUNE:
1898 return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_rr_prune);
1899#if defined(__NetBSD__) && !defined(INET6_BINDV6ONLY)
1900 case IPV6CTL_BINDV6ONLY:
1901 return sysctl_int(oldp, oldlenp, newp, newlen,
1902 &ip6_bindv6only);
1903#endif
1904 default:
1905 return EOPNOTSUPP;
1906 }
1907 /* NOTREACHED */
1908}
1909#endif /* __NetBSD__ || __OpenBSD__ */
1910
1911#ifdef __bsdi__
1912int *ip6_sysvars[] = IPV6CTL_VARS;
1913
1914int
1915ip6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1916 int *name;
1917 u_int namelen;
1918 void *oldp;
1919 size_t *oldlenp;
1920 void *newp;
1921 size_t newlen;
1922{
1923 if (name[0] >= IPV6CTL_MAXID)
1924 return (EOPNOTSUPP);
1925
1926 switch (name[0]) {
1927 case IPV6CTL_STATS:
1928 return sysctl_rdtrunc(oldp, oldlenp, newp, &ip6stat,
1929 sizeof(ip6stat));
1930 case IPV6CTL_KAME_VERSION:
1931 return sysctl_rdstring(oldp, oldlenp, newp, __KAME_VERSION);
1932 default:
1933 return (sysctl_int_arr(ip6_sysvars, name, namelen,
1934 oldp, oldlenp, newp, newlen));
1935 }
1936}
1937#endif /* __bsdi__ */