Annotation of src/sys/netinet6/ip6_input.c, Revision 1.1.2.3
1.1.2.1 itojun 1: /*
2: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the project nor the names of its contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * Copyright (c) 1982, 1986, 1988, 1993
32: * The Regents of the University of California. All rights reserved.
33: *
34: * Redistribution and use in source and binary forms, with or without
35: * modification, are permitted provided that the following conditions
36: * are met:
37: * 1. Redistributions of source code must retain the above copyright
38: * notice, this list of conditions and the following disclaimer.
39: * 2. Redistributions in binary form must reproduce the above copyright
40: * notice, this list of conditions and the following disclaimer in the
41: * documentation and/or other materials provided with the distribution.
42: * 3. All advertising materials mentioning features or use of this software
43: * must display the following acknowledgement:
44: * This product includes software developed by the University of
45: * California, Berkeley and its contributors.
46: * 4. Neither the name of the University nor the names of its contributors
47: * may be used to endorse or promote products derived from this software
48: * without specific prior written permission.
49: *
50: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60: * SUCH DAMAGE.
61: *
62: * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
63: */
64:
65: #ifdef __FreeBSD__
66: #include "opt_ip6fw.h"
67: #endif
68: #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
69: #include "opt_inet.h"
1.1.2.3 ! itojun 70: #ifdef __NetBSD__ /*XXX*/
! 71: #include "opt_ipsec.h"
! 72: #endif
1.1.2.1 itojun 73: #endif
74:
75: #include <sys/param.h>
76: #include <sys/systm.h>
77: #include <sys/malloc.h>
78: #include <sys/mbuf.h>
79: #include <sys/domain.h>
80: #include <sys/protosw.h>
81: #include <sys/socket.h>
82: #include <sys/socketvar.h>
83: #include <sys/errno.h>
84: #include <sys/time.h>
85: #include <sys/kernel.h>
86: #include <sys/syslog.h>
1.1.2.3 ! itojun 87: #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
1.1.2.1 itojun 88: #include <sys/proc.h>
89: #endif
90:
91: #include <net/if.h>
92: #include <net/if_types.h>
93: #include <net/if_dl.h>
94: #include <net/route.h>
95: #include <net/netisr.h>
96:
97: #include <netinet/in.h>
98: #include <netinet/in_systm.h>
1.1.2.3 ! itojun 99: #ifdef INET
! 100: #include <netinet/ip.h>
! 101: #include <netinet/ip_icmp.h>
! 102: #endif /*INET*/
! 103: #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)
! 104: #include <netinet/in_pcb.h>
! 105: #endif
! 106: #include <netinet6/in6_var.h>
1.1.2.1 itojun 107: #include <netinet6/ip6.h>
1.1.2.3 ! itojun 108: #if !((defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802))
1.1.2.1 itojun 109: #include <netinet6/in6_pcb.h>
110: #endif
111: #include <netinet6/ip6_var.h>
112: #include <netinet6/icmp6.h>
113: #include <netinet6/in6_ifattach.h>
114: #include <netinet6/nd6.h>
1.1.2.3 ! itojun 115: #include <netinet6/in6_prefix.h>
1.1.2.1 itojun 116:
1.1.2.3 ! itojun 117: #ifdef IPV6FIREWALL
! 118: #include <netinet6/ip6_fw.h>
! 119: #endif
! 120:
! 121: #ifdef ALTQ
! 122: #include <netinet/altq_cdnr.h>
! 123: #endif
1.1.2.1 itojun 124:
125: #include <netinet6/ip6protosw.h>
126:
127: /* we need it for NLOOP. */
1.1.2.3 ! itojun 128: #ifndef __bsdi__
1.1.2.1 itojun 129: #include "loop.h"
1.1.2.3 ! itojun 130: #endif
1.1.2.1 itojun 131: #include "faith.h"
132:
133: #include "gif.h"
134: #include "bpfilter.h"
135:
1.1.2.3 ! itojun 136: #include <net/net_osdep.h>
! 137:
! 138: #ifdef __OpenBSD__ /*KAME IPSEC*/
! 139: #undef IPSEC
! 140: #endif
! 141:
1.1.2.1 itojun 142: extern struct domain inet6domain;
143: extern struct ip6protosw inet6sw[];
1.1.2.3 ! itojun 144: #if (defined(__bsdi__) && _BSDI_VERSION < 199802) || defined(__OpenBSD__)
1.1.2.1 itojun 145: extern struct ifnet loif;
146: #endif
1.1.2.3 ! itojun 147: #if defined(__bsdi__) && _BSDI_VERSION >= 199802
! 148: extern struct ifnet *loifp;
! 149: #endif
1.1.2.1 itojun 150:
151: u_char ip6_protox[IPPROTO_MAX];
152: static int ip6qmaxlen = IFQ_MAXLEN;
153: struct in6_ifaddr *in6_ifaddr;
154: struct ifqueue ip6intrq;
155:
156: #ifdef __NetBSD__
157: extern struct ifnet loif[NLOOP];
1.1.2.3 ! itojun 158: #endif
1.1.2.1 itojun 159: int ip6_forward_srcrt; /* XXX */
160: int ip6_sourcecheck; /* XXX */
161: int ip6_sourcecheck_interval; /* XXX */
1.1.2.3 ! itojun 162:
! 163: #ifdef IPV6FIREWALL
! 164: /* firewall hooks */
! 165: ip6_fw_chk_t *ip6_fw_chk_ptr;
! 166: ip6_fw_ctl_t *ip6_fw_ctl_ptr;
1.1.2.1 itojun 167: #endif
168:
169: struct ip6stat ip6stat;
170:
171: static void ip6_init2 __P((void *));
172:
1.1.2.3 ! itojun 173: static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
! 174:
! 175: #if defined(PTR)
! 176: extern int ip6_protocol_tr;
! 177:
! 178: int ptr_in6 __P((struct mbuf *, struct mbuf **));
! 179: extern void ip_forward __P((struct mbuf *, int));
! 180: #endif
1.1.2.1 itojun 181:
182: /*
183: * IP6 initialization: fill in IP6 protocol switch table.
184: * All protocols not implemented in kernel go to raw IP6 protocol handler.
185: */
186: void
187: ip6_init()
188: {
189: register struct ip6protosw *pr;
190: register int i;
191: struct timeval tv;
192:
193: pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
194: if (pr == 0)
195: panic("ip6_init");
196: for (i = 0; i < IPPROTO_MAX; i++)
197: ip6_protox[i] = pr - inet6sw;
198: for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
199: pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
200: if (pr->pr_domain->dom_family == PF_INET6 &&
201: pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
202: ip6_protox[pr->pr_protocol] = pr - inet6sw;
203: ip6intrq.ifq_maxlen = ip6qmaxlen;
204: nd6_init();
205: frag6_init();
1.1.2.3 ! itojun 206: #ifdef IPV6FIREWALL
! 207: ip6_fw_init();
! 208: #endif
1.1.2.1 itojun 209: /*
210: * in many cases, random() here does NOT return random number
211: * as initialization during bootstrap time occur in fixed order.
212: */
213: microtime(&tv);
214: ip6_flow_seq = random() ^ tv.tv_usec;
215:
1.1.2.3 ! itojun 216: #ifndef __FreeBSD__
1.1.2.1 itojun 217: ip6_init2((void *)0);
1.1.2.3 ! itojun 218: #endif
1.1.2.1 itojun 219: }
220:
221: static void
222: ip6_init2(dummy)
223: void *dummy;
224: {
1.1.2.3 ! itojun 225: #if !(defined(__bsdi__) || defined(__OpenBSD__))
1.1.2.1 itojun 226: int i;
1.1.2.3 ! itojun 227: #endif
! 228: int ret;
! 229: #if (defined(__bsdi__) && _BSDI_VERSION < 199802) || defined(__OpenBSD__)
! 230: struct ifnet *loifp = &loif;
! 231: #endif
! 232:
! 233: /* get EUI64 from somewhere */
! 234: ret = in6_ifattach_getifid(NULL);
1.1.2.1 itojun 235:
236: /*
237: * to route local address of p2p link to loopback,
238: * assign loopback address first.
239: */
1.1.2.3 ! itojun 240: #if defined(__bsdi__) || defined(__OpenBSD__)
! 241: in6_ifattach(loifp, IN6_IFT_LOOP, NULL, 0);
! 242: #else
1.1.2.1 itojun 243: for (i = 0; i < NLOOP; i++)
244: in6_ifattach(&loif[i], IN6_IFT_LOOP, NULL, 0);
1.1.2.3 ! itojun 245: #endif
1.1.2.1 itojun 246:
1.1.2.3 ! itojun 247: /* attach pseudo interfaces */
! 248: if (ret == 0)
1.1.2.1 itojun 249: in6_ifattach_p2p();
250:
251: /* nd6_timer_init */
252: timeout(nd6_timer, (caddr_t)0, hz);
1.1.2.3 ! itojun 253: /* router renumbering prefix list maintenance */
! 254: timeout(in6_rr_timer, (caddr_t)0, hz);
1.1.2.1 itojun 255: }
256:
257: #ifdef __FreeBSD__
258: /* cheat */
259: SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip6_init2, NULL);
260: #endif
261:
262: /*
263: * IP6 input interrupt handling. Just pass the packet to ip6_input.
264: */
265: void
266: ip6intr()
267: {
268: int s;
269: struct mbuf *m;
270:
271: for (;;) {
272: s = splimp();
273: IF_DEQUEUE(&ip6intrq, m);
274: splx(s);
275: if (m == 0)
276: return;
277: ip6_input(m);
278: }
279: }
280:
281: #ifdef __FreeBSD__
282: NETISR_SET(NETISR_IPV6, ip6intr);
283: #endif
284:
285: extern struct route_in6 ip6_forward_rt;
286:
287: void
288: ip6_input(m)
289: struct mbuf *m;
290: {
1.1.2.3 ! itojun 291: struct ip6_hdr *ip6;
1.1.2.1 itojun 292: int off = sizeof(struct ip6_hdr), nest;
293: u_int32_t plen;
1.1.2.3 ! itojun 294: u_int32_t rtalert = ~0;
1.1.2.1 itojun 295: int nxt, ours = 0;
1.1.2.3 ! itojun 296: struct ifnet *deliverifp = NULL;
! 297: #if (defined(__bsdi__) && _BSDI_VERSION < 199802) || defined(__OpenBSD__)
! 298: struct ifnet *loifp = &loif;
! 299: #endif
1.1.2.1 itojun 300:
301: #ifdef IPSEC
302: /*
303: * should the inner packet be considered authentic?
304: * see comment in ah4_input().
305: */
306: if (m) {
307: m->m_flags &= ~M_AUTHIPHDR;
308: m->m_flags &= ~M_AUTHIPDGM;
309: }
310: #endif
1.1.2.3 ! itojun 311:
1.1.2.1 itojun 312: /*
313: * mbuf statistics by kazu
314: */
315: if (m->m_flags & M_EXT) {
316: if (m->m_next)
317: ip6stat.ip6s_mext2m++;
318: else
319: ip6stat.ip6s_mext1++;
320: } else {
321: if (m->m_next) {
1.1.2.3 ! itojun 322: if (m->m_flags & M_LOOP) {
! 323: #if defined(__bsdi__) || defined(__OpenBSD__)
! 324: ip6stat.ip6s_m2m[loifp->if_index]++; /*XXX*/
! 325: #else
1.1.2.1 itojun 326: ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
1.1.2.3 ! itojun 327: #endif
! 328: }
1.1.2.1 itojun 329: else if (m->m_pkthdr.rcvif->if_index <= 31)
330: ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
331: else
332: ip6stat.ip6s_m2m[0]++;
333: } else
334: ip6stat.ip6s_m1++;
335: }
336:
1.1.2.3 ! itojun 337: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
1.1.2.1 itojun 338: ip6stat.ip6s_total++;
339:
1.1.2.3 ! itojun 340: #ifndef PULLDOWN_TEST
! 341: /* XXX is the line really necessary? */
! 342: IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
! 343: #endif
! 344:
! 345: if (m->m_len < sizeof(struct ip6_hdr)) {
! 346: struct ifnet *inifp;
! 347: inifp = m->m_pkthdr.rcvif;
! 348: if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
! 349: ip6stat.ip6s_toosmall++;
! 350: in6_ifstat_inc(inifp, ifs6_in_hdrerr);
! 351: return;
! 352: }
1.1.2.1 itojun 353: }
354:
355: ip6 = mtod(m, struct ip6_hdr *);
356:
357: if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
358: ip6stat.ip6s_badvers++;
1.1.2.3 ! itojun 359: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
1.1.2.1 itojun 360: goto bad;
361: }
362:
363: ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
364:
1.1.2.3 ! itojun 365: #ifdef IPV6FIREWALL
! 366: /*
! 367: * Check with the firewall...
! 368: */
! 369: if (ip6_fw_chk_ptr) {
! 370: u_short port = 0;
! 371: /* If ipfw says divert, we have to just drop packet */
! 372: /* use port as a dummy argument */
! 373: if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
! 374: m_freem(m);
! 375: m = NULL;
! 376: }
! 377: if (!m)
! 378: return;
! 379: }
! 380: #endif
! 381:
! 382: #ifdef ALTQ
! 383: if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
! 384: /* packet is dropped by traffic conditioner */
! 385: return;
! 386: }
! 387: #endif
! 388:
1.1.2.1 itojun 389: /*
390: * Scope check
391: */
392: if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
393: IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
394: ip6stat.ip6s_badscope++;
1.1.2.3 ! itojun 395: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
1.1.2.1 itojun 396: goto bad;
397: }
398: if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
399: IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
400: if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
401: ours = 1;
1.1.2.3 ! itojun 402: deliverifp = m->m_pkthdr.rcvif;
1.1.2.1 itojun 403: goto hbhcheck;
404: } else {
405: ip6stat.ip6s_badscope++;
1.1.2.3 ! itojun 406: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
1.1.2.1 itojun 407: goto bad;
408: }
409: }
410:
411: if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
412: if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
413: ours = 1;
1.1.2.3 ! itojun 414: deliverifp = m->m_pkthdr.rcvif;
1.1.2.1 itojun 415: goto hbhcheck;
416: }
417: } else {
418: if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
419: ip6->ip6_src.s6_addr16[1]
420: = htons(m->m_pkthdr.rcvif->if_index);
421: if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
422: ip6->ip6_dst.s6_addr16[1]
423: = htons(m->m_pkthdr.rcvif->if_index);
424: }
425:
1.1.2.3 ! itojun 426: #if defined(PTR)
! 427: /*
! 428: *
! 429: */
! 430: if (ip6_protocol_tr)
! 431: {
! 432: struct mbuf *m1 = NULL;
! 433:
! 434: switch (ptr_in6(m, &m1))
! 435: {
! 436: case IPPROTO_IP: goto mcastcheck;
! 437: case IPPROTO_IPV4: ip_forward(m1, 0); break;
! 438: case IPPROTO_IPV6: ip6_forward(m1, 0); break;
! 439: case IPPROTO_MAX: /* discard this packet */
! 440: default:
! 441: }
! 442:
! 443: if (m != m1)
! 444: m_freem(m);
! 445:
! 446: return;
! 447: }
! 448:
! 449: mcastcheck:
! 450: #endif
! 451:
1.1.2.1 itojun 452: /*
453: * Multicast check
454: */
455: if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
456: struct in6_multi *in6m = 0;
1.1.2.3 ! itojun 457:
! 458: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
1.1.2.1 itojun 459: /*
460: * See if we belong to the destination multicast group on the
461: * arrival interface.
462: */
463: IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
464: if (in6m)
465: ours = 1;
466: else if (!ip6_mrouter) {
467: ip6stat.ip6s_notmember++;
468: ip6stat.ip6s_cantforward++;
1.1.2.3 ! itojun 469: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
1.1.2.1 itojun 470: goto bad;
471: }
1.1.2.3 ! itojun 472: deliverifp = m->m_pkthdr.rcvif;
1.1.2.1 itojun 473: goto hbhcheck;
474: }
475:
476: /*
477: * Unicast check
478: */
479: if (ip6_forward_rt.ro_rt == 0 ||
480: !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
481: &ip6_forward_rt.ro_dst.sin6_addr)) {
482: if (ip6_forward_rt.ro_rt) {
483: RTFREE(ip6_forward_rt.ro_rt);
484: ip6_forward_rt.ro_rt = 0;
485: }
486: bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
487: ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
488: ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
489: ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
490:
491: #if defined(__bsdi__) || defined(__NetBSD__)
492: rtalloc((struct route *)&ip6_forward_rt);
493: #endif
494: #ifdef __FreeBSD__
495: rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
496: #endif
497: }
498:
499: #define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
500:
501: /*
502: * Accept the packet if the forwarding interface to the destination
503: * according to the routing table is the loopback interface,
504: * unless the associated route has a gateway.
505: * Note that this approach causes to accept a packet if there is a
506: * route to the loopback interface for the destination of the packet.
507: * But we think it's even useful in some situations, e.g. when using
508: * a special daemon which wants to intercept the packet.
509: */
510: if (ip6_forward_rt.ro_rt &&
511: (ip6_forward_rt.ro_rt->rt_flags &
512: (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
513: #if 0
514: /*
515: * The check below is redundant since the comparison of
516: * the destination and the key of the rtentry has
517: * already done through looking up the routing table.
518: */
519: IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
520: &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) &&
521: #endif
1.1.2.3 ! itojun 522: ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
1.1.2.1 itojun 523: struct in6_ifaddr *ia6 =
524: (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
525: /* packet to tentative address must not be received */
526: if (ia6->ia6_flags & IN6_IFF_ANYCAST)
527: m->m_flags |= M_ANYCAST6;
528: if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
529: /* this interface is ready */
530: ours = 1;
1.1.2.3 ! itojun 531: deliverifp = ia6->ia_ifp; /* correct? */
1.1.2.1 itojun 532: goto hbhcheck;
533: } else {
534: /* this interface is not ready, fall through */
535: }
536: }
537:
538: /*
539: * FAITH(Firewall Aided Internet Translator)
540: */
541: #if defined(NFAITH) && 0 < NFAITH
542: if (ip6_keepfaith) {
543: if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
544: && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
545: /* XXX do we need more sanity checks? */
546: ours = 1;
1.1.2.3 ! itojun 547: deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/
1.1.2.1 itojun 548: goto hbhcheck;
549: }
550: }
551: #endif
552:
1.1.2.3 ! itojun 553: #ifdef __OpenBSD__
! 554: {
! 555: /*
! 556: * Last resort: check in6_ifaddr for incoming interface.
! 557: * The code is here until I update the "goto ours hack" code above
! 558: * working right.
! 559: */
! 560: struct ifaddr *ifa;
! 561: for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
! 562: ifa;
! 563: ifa = ifa->ifa_list.tqe_next) {
! 564: if (ifa->ifa_addr == NULL)
! 565: continue; /* just for safety */
! 566: if (ifa->ifa_addr->sa_family != AF_INET6)
! 567: continue;
! 568: if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) {
! 569: ours = 1;
! 570: deliverifp = ifa->ifa_ifp;
! 571: goto hbhcheck;
! 572: }
! 573: }
! 574: }
! 575: #endif
1.1.2.1 itojun 576: /*
577: * Now there is no reason to process the packet if it's not our own
578: * and we're not a router.
579: */
580: if (!ip6_forwarding) {
581: ip6stat.ip6s_cantforward++;
1.1.2.3 ! itojun 582: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
1.1.2.1 itojun 583: goto bad;
584: }
585:
586: hbhcheck:
587: /*
588: * Process Hop-by-Hop options header if it's contained.
589: * m may be modified in ip6_hopopts_input().
590: * If a JumboPayload option is included, plen will also be modified.
591: */
592: plen = (u_int32_t)ntohs(ip6->ip6_plen);
593: if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1.1.2.3 ! itojun 594: struct ip6_hbh *hbh;
! 595:
! 596: if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
! 597: #if 0 /*touches NULL pointer*/
! 598: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
! 599: #endif
1.1.2.1 itojun 600: return; /* m have already been freed */
1.1.2.3 ! itojun 601: }
1.1.2.1 itojun 602: /* adjust pointer */
603: ip6 = mtod(m, struct ip6_hdr *);
1.1.2.3 ! itojun 604: #ifndef PULLDOWN_TEST
! 605: /* ip6_hopopts_input() ensures that mbuf is contiguous */
! 606: hbh = (struct ip6_hbh *)(ip6 + 1);
! 607: #else
! 608: IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
! 609: sizeof(struct ip6_hbh));
! 610: if (hbh == NULL) {
! 611: ip6stat.ip6s_tooshort++;
! 612: return;
! 613: }
! 614: #endif
! 615: nxt = hbh->ip6h_nxt;
1.1.2.1 itojun 616:
617: /*
618: * accept the packet if a router alert option is included
619: * and we act as an IPv6 router.
620: */
1.1.2.3 ! itojun 621: if (rtalert != ~0 && ip6_forwarding)
1.1.2.1 itojun 622: ours = 1;
623: } else
624: nxt = ip6->ip6_nxt;
625:
626: /*
627: * Check that the amount of data in the buffers
628: * is as at least much as the IPv6 header would have us expect.
629: * Trim mbufs if longer than we expect.
630: * Drop packet if shorter than we expect.
631: */
632: if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
633: ip6stat.ip6s_tooshort++;
1.1.2.3 ! itojun 634: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
1.1.2.1 itojun 635: goto bad;
636: }
637: if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
638: if (m->m_len == m->m_pkthdr.len) {
639: m->m_len = sizeof(struct ip6_hdr) + plen;
640: m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
641: } else
642: m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
643: }
644:
645: /*
646: * Forward if desirable.
647: */
648: if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
649: /*
650: * If we are acting as a multicast router, all
651: * incoming multicast packets are passed to the
652: * kernel-level multicast forwarding function.
653: * The packet is returned (relatively) intact; if
654: * ip6_mforward() returns a non-zero value, the packet
655: * must be discarded, else it may be accepted below.
656: */
657: if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
658: ip6stat.ip6s_cantforward++;
659: m_freem(m);
660: return;
661: }
662: if (!ours) {
663: m_freem(m);
664: return;
665: }
666: }
667: else if (!ours) {
668: ip6_forward(m, 0);
669: return;
670: }
671:
672: /*
673: * Tell launch routine the next header
674: */
1.1.2.3 ! itojun 675: #if defined(__NetBSD__) && defined(IFA_STATS)
! 676: if (IFA_STATS && deliverifp != NULL) {
! 677: struct in6_ifaddr *ia6;
! 678: ip6 = mtod(m, struct ip6_hdr *);
! 679: ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
! 680: if (ia6)
! 681: ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len;
! 682: }
! 683: #endif
1.1.2.1 itojun 684: ip6stat.ip6s_delivered++;
1.1.2.3 ! itojun 685: in6_ifstat_inc(deliverifp, ifs6_in_deliver);
1.1.2.1 itojun 686: nest = 0;
687: while (nxt != IPPROTO_DONE) {
688: if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
689: ip6stat.ip6s_toomanyhdr++;
690: goto bad;
691: }
1.1.2.3 ! itojun 692:
! 693: /*
! 694: * protection against faulty packet - there should be
! 695: * more sanity checks in header chain processing.
! 696: */
! 697: if (m->m_pkthdr.len < off) {
! 698: ip6stat.ip6s_tooshort++;
! 699: in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
! 700: goto bad;
! 701: }
! 702:
1.1.2.1 itojun 703: nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
704: }
705: return;
706: bad:
707: m_freem(m);
708: }
709:
710: /*
711: * Hop-by-Hop options header processing. If a valid jumbo payload option is
712: * included, the real payload length will be stored in plenp.
713: */
714: static int
715: ip6_hopopts_input(plenp, rtalertp, mp, offp)
716: u_int32_t *plenp;
1.1.2.3 ! itojun 717: u_int32_t *rtalertp; /* XXX: should be stored more smart way */
1.1.2.1 itojun 718: struct mbuf **mp;
719: int *offp;
720: {
721: register struct mbuf *m = *mp;
722: int off = *offp, hbhlen;
723: struct ip6_hbh *hbh;
724: u_int8_t *opt;
725:
726: /* validation of the length of the header */
1.1.2.3 ! itojun 727: #ifndef PULLDOWN_TEST
1.1.2.1 itojun 728: IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
729: hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
730: hbhlen = (hbh->ip6h_len + 1) << 3;
731:
732: IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
733: hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
1.1.2.3 ! itojun 734: #else
! 735: IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
! 736: sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
! 737: if (hbh == NULL) {
! 738: ip6stat.ip6s_tooshort++;
! 739: return -1;
! 740: }
! 741: hbhlen = (hbh->ip6h_len + 1) << 3;
! 742: IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
! 743: hbhlen);
! 744: if (hbh == NULL) {
! 745: ip6stat.ip6s_tooshort++;
! 746: return -1;
! 747: }
! 748: #endif
1.1.2.1 itojun 749: off += hbhlen;
750: hbhlen -= sizeof(struct ip6_hbh);
751: opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
752:
753: if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
754: hbhlen, rtalertp, plenp) < 0)
755: return(-1);
756:
757: *offp = off;
758: *mp = m;
759: return(0);
760: }
761:
762: /*
763: * Search header for all Hop-by-hop options and process each option.
764: * This function is separate from ip6_hopopts_input() in order to
765: * handle a case where the sending node itself process its hop-by-hop
766: * options header. In such a case, the function is called from ip6_output().
767: */
768: int
769: ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
770: struct mbuf *m;
771: u_int8_t *opthead;
772: int hbhlen;
1.1.2.3 ! itojun 773: u_int32_t *rtalertp;
1.1.2.1 itojun 774: u_int32_t *plenp;
775: {
776: struct ip6_hdr *ip6;
777: int optlen = 0;
778: u_int8_t *opt = opthead;
779: u_int16_t rtalert_val;
780:
781: for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
782: switch(*opt) {
783: case IP6OPT_PAD1:
784: optlen = 1;
785: break;
786: case IP6OPT_PADN:
787: if (hbhlen < IP6OPT_MINLEN) {
788: ip6stat.ip6s_toosmall++;
789: goto bad;
790: }
791: optlen = *(opt + 1) + 2;
792: break;
793: case IP6OPT_RTALERT:
1.1.2.3 ! itojun 794: /* XXX may need check for alignment */
1.1.2.1 itojun 795: if (hbhlen < IP6OPT_RTALERT_LEN) {
796: ip6stat.ip6s_toosmall++;
797: goto bad;
798: }
799: if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2)
800: /* XXX: should we discard the packet? */
801: log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
802: *(opt + 1));
803: optlen = IP6OPT_RTALERT_LEN;
804: bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
805: *rtalertp = ntohs(rtalert_val);
806: break;
807: case IP6OPT_JUMBO:
1.1.2.3 ! itojun 808: /* XXX may need check for alignment */
1.1.2.1 itojun 809: if (hbhlen < IP6OPT_JUMBO_LEN) {
810: ip6stat.ip6s_toosmall++;
811: goto bad;
812: }
813: if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
814: /* XXX: should we discard the packet? */
815: log(LOG_ERR, "length of jumbopayload opt "
816: "is inconsistent(%d)",
817: *(opt + 1));
818: optlen = IP6OPT_JUMBO_LEN;
819:
820: /*
821: * We can simply cast because of the alignment
822: * requirement of the jumbo payload option.
823: */
1.1.2.3 ! itojun 824: #if 0
1.1.2.1 itojun 825: *plenp = ntohl(*(u_int32_t *)(opt + 2));
1.1.2.3 ! itojun 826: #else
! 827: bcopy(opt + 2, plenp, sizeof(*plenp));
! 828: *plenp = htonl(*plenp);
! 829: #endif
1.1.2.1 itojun 830: if (*plenp <= IPV6_MAXPACKET) {
831: /*
832: * jumbo payload length must be larger
833: * than 65535
834: */
835: ip6stat.ip6s_badoptions++;
836: icmp6_error(m, ICMP6_PARAM_PROB,
837: ICMP6_PARAMPROB_HEADER,
838: sizeof(struct ip6_hdr) +
839: sizeof(struct ip6_hbh) +
840: opt + 2 - opthead);
841: return(-1);
842: }
843:
844: ip6 = mtod(m, struct ip6_hdr *);
845: if (ip6->ip6_plen) {
846: /*
847: * IPv6 packets that have non 0 payload length
848: * must not contain a jumbo paylod option.
849: */
850: ip6stat.ip6s_badoptions++;
851: icmp6_error(m, ICMP6_PARAM_PROB,
852: ICMP6_PARAMPROB_HEADER,
853: sizeof(struct ip6_hdr) +
854: sizeof(struct ip6_hbh) +
855: opt - opthead);
856: return(-1);
857: }
858: break;
859: default: /* unknown option */
860: if (hbhlen < IP6OPT_MINLEN) {
861: ip6stat.ip6s_toosmall++;
862: goto bad;
863: }
864: if ((optlen = ip6_unknown_opt(opt, m,
865: sizeof(struct ip6_hdr) +
866: sizeof(struct ip6_hbh) +
867: opt - opthead)) == -1)
868: return(-1);
869: optlen += 2;
870: break;
871: }
872: }
873:
874: return(0);
875:
876: bad:
877: m_freem(m);
878: return(-1);
879: }
880:
881: /*
882: * Unknown option processing.
883: * The third argument `off' is the offset from the IPv6 header to the option,
884: * which is necessary if the IPv6 header the and option header and IPv6 header
885: * is not continuous in order to return an ICMPv6 error.
886: */
887: int
888: ip6_unknown_opt(optp, m, off)
889: u_int8_t *optp;
890: struct mbuf *m;
891: int off;
892: {
893: struct ip6_hdr *ip6;
894:
895: switch(IP6OPT_TYPE(*optp)) {
896: case IP6OPT_TYPE_SKIP: /* ignore the option */
897: return((int)*(optp + 1));
898: case IP6OPT_TYPE_DISCARD: /* silently discard */
899: m_freem(m);
900: return(-1);
901: case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
902: ip6stat.ip6s_badoptions++;
903: icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
904: return(-1);
905: case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
906: ip6stat.ip6s_badoptions++;
907: ip6 = mtod(m, struct ip6_hdr *);
908: if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
909: (m->m_flags & (M_BCAST|M_MCAST)))
910: m_freem(m);
911: else
912: icmp6_error(m, ICMP6_PARAM_PROB,
913: ICMP6_PARAMPROB_OPTION, off);
914: return(-1);
915: }
916:
917: m_freem(m); /* XXX: NOTREACHED */
918: return(-1);
919: }
920:
921: /*
1.1.2.3 ! itojun 922: * Create the "control" list for this pcb.
! 923: *
! 924: * The routine will be called from upper layer handlers like tcp6_input().
! 925: * Thus the routine assumes that the caller (tcp6_input) have already
! 926: * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
! 927: * very first mbuf on the mbuf chain.
! 928: * We may want to add some infinite loop prevention or sanity checks for safety.
! 929: * (This applies only when you are using KAME mbuf chain restriction, i.e.
! 930: * you are using IP6_EXTHDR_CHECK() not m_pulldown())
1.1.2.1 itojun 931: */
932: void
933: ip6_savecontrol(in6p, mp, ip6, m)
1.1.2.3 ! itojun 934: #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(HAVE_NRL_INPCB)
! 935: register struct inpcb *in6p;
! 936: #else
1.1.2.1 itojun 937: register struct in6pcb *in6p;
1.1.2.3 ! itojun 938: #endif
1.1.2.1 itojun 939: register struct mbuf **mp;
940: register struct ip6_hdr *ip6;
941: register struct mbuf *m;
942: {
1.1.2.3 ! itojun 943: #ifdef HAVE_NRL_INPCB
! 944: # define in6p_flags inp_flags
! 945: #endif
! 946: #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
1.1.2.1 itojun 947: struct proc *p = curproc; /* XXX */
948: #endif
949: #ifdef __bsdi__
950: # define sbcreatecontrol so_cmsg
951: #endif
1.1.2.3 ! itojun 952: int privileged;
1.1.2.1 itojun 953:
1.1.2.3 ! itojun 954: privileged = 0;
! 955: #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
! 956: if (p && !suser(p->p_ucred, &p->p_acflag))
! 957: privileged++;
! 958: #else
! 959: #ifdef HAVE_NRL_INPCB
! 960: if ((in6p->inp_socket->so_state & SS_PRIV) != 0)
! 961: privileged++;
! 962: #else
! 963: if ((in6p->in6p_socket->so_state & SS_PRIV) != 0)
! 964: privileged++;
! 965: #endif
! 966: #endif
! 967:
! 968: #ifdef SO_TIMESTAMP
1.1.2.1 itojun 969: if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
970: struct timeval tv;
971:
972: microtime(&tv);
973: *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
974: SCM_TIMESTAMP, SOL_SOCKET);
975: if (*mp)
976: mp = &(*mp)->m_next;
977: }
1.1.2.3 ! itojun 978: #endif
1.1.2.1 itojun 979: if (in6p->in6p_flags & IN6P_RECVDSTADDR) {
980: *mp = sbcreatecontrol((caddr_t) &ip6->ip6_dst,
981: sizeof(struct in6_addr), IPV6_RECVDSTADDR,
982: IPPROTO_IPV6);
983: if (*mp)
984: mp = &(*mp)->m_next;
985: }
986:
987: #ifdef noyet
988: /* options were tossed above */
989: if (in6p->in6p_flags & IN6P_RECVOPTS)
990: /* broken */
991: /* ip6_srcroute doesn't do what we want here, need to fix */
992: if (in6p->in6p_flags & IPV6P_RECVRETOPTS)
993: /* broken */
994: #endif
995:
996: /* RFC 2292 sec. 5 */
997: if (in6p->in6p_flags & IN6P_PKTINFO) {
998: struct in6_pktinfo pi6;
999: bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1000: if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
1001: pi6.ipi6_addr.s6_addr16[1] = 0;
1002: pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
1003: ? m->m_pkthdr.rcvif->if_index
1004: : 0;
1005: *mp = sbcreatecontrol((caddr_t) &pi6,
1006: sizeof(struct in6_pktinfo), IPV6_PKTINFO,
1007: IPPROTO_IPV6);
1008: if (*mp)
1009: mp = &(*mp)->m_next;
1010: }
1011: if (in6p->in6p_flags & IN6P_HOPLIMIT) {
1012: int hlim = ip6->ip6_hlim & 0xff;
1013: *mp = sbcreatecontrol((caddr_t) &hlim,
1014: sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
1015: if (*mp)
1016: mp = &(*mp)->m_next;
1017: }
1018: /* IN6P_NEXTHOP - for outgoing packet only */
1019:
1020: /*
1021: * IPV6_HOPOPTS socket option. We require super-user privilege
1022: * for the option, but it might be too strict, since there might
1023: * be some hop-by-hop options which can be returned to normal user.
1024: * See RFC 2292 section 6.
1025: */
1.1.2.3 ! itojun 1026: if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
1.1.2.1 itojun 1027: /*
1028: * Check if a hop-by-hop options header is contatined in the
1029: * received packet, and if so, store the options as ancillary
1030: * data. Note that a hop-by-hop options header must be
1031: * just after the IPv6 header, which fact is assured through
1032: * the IPv6 input processing.
1033: */
1034: struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1035: if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1.1.2.3 ! itojun 1036: struct ip6_hbh *hbh;
! 1037: int hbhlen;
! 1038:
! 1039: #ifndef PULLDOWN_TEST
! 1040: hbh = (struct ip6_hbh *)(ip6 + 1);
! 1041: hbhlen = (hbh->ip6h_len + 1) << 3;
! 1042: #else
! 1043: IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
! 1044: sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
! 1045: if (hbh == NULL) {
! 1046: ip6stat.ip6s_tooshort++;
! 1047: return;
! 1048: }
! 1049: hbhlen = (hbh->ip6h_len + 1) << 3;
! 1050: IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
! 1051: sizeof(struct ip6_hdr), hbhlen);
! 1052: if (hbh == NULL) {
! 1053: ip6stat.ip6s_tooshort++;
! 1054: return;
! 1055: }
! 1056: #endif
1.1.2.1 itojun 1057:
1058: /*
1059: * XXX: We copy whole the header even if a jumbo
1060: * payload option is included, which option is to
1061: * be removed before returning in the RFC 2292.
1062: * But it's too painful operation...
1063: */
1.1.2.3 ! itojun 1064: *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1.1.2.1 itojun 1065: IPV6_HOPOPTS, IPPROTO_IPV6);
1066: if (*mp)
1067: mp = &(*mp)->m_next;
1068: }
1069: }
1070:
1071: /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
1072: if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) {
1073: struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1074: int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);;
1075:
1076: /*
1077: * Search for destination options headers or routing
1078: * header(s) through the header chain, and stores each
1079: * header as ancillary data.
1080: * Note that the order of the headers remains in
1081: * the chain of ancillary data.
1082: */
1083: while(1) { /* is explicit loop prevention necessary? */
1.1.2.3 ! itojun 1084: struct ip6_ext *ip6e;
! 1085: int elen;
! 1086:
! 1087: #ifndef PULLDOWN_TEST
! 1088: ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
! 1089: if (nxt == IPPROTO_AH)
! 1090: elen = (ip6e->ip6e_len + 2) << 2;
! 1091: else
! 1092: elen = (ip6e->ip6e_len + 1) << 3;
! 1093: #else
! 1094: IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off,
! 1095: sizeof(struct ip6_ext));
! 1096: if (ip6e == NULL) {
! 1097: ip6stat.ip6s_tooshort++;
! 1098: return;
! 1099: }
! 1100: if (nxt == IPPROTO_AH)
! 1101: elen = (ip6e->ip6e_len + 2) << 2;
! 1102: else
! 1103: elen = (ip6e->ip6e_len + 1) << 3;
! 1104: IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off, elen);
! 1105: if (ip6e == NULL) {
! 1106: ip6stat.ip6s_tooshort++;
! 1107: return;
! 1108: }
! 1109: #endif
1.1.2.1 itojun 1110:
1111: switch(nxt) {
1112: case IPPROTO_DSTOPTS:
1113: if (!in6p->in6p_flags & IN6P_DSTOPTS)
1114: break;
1115:
1116: /*
1117: * We also require super-user privilege for
1118: * the option.
1119: * See the comments on IN6_HOPOPTS.
1120: */
1.1.2.3 ! itojun 1121: if (!privileged)
1.1.2.1 itojun 1122: break;
1123:
1.1.2.3 ! itojun 1124: *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1.1.2.1 itojun 1125: IPV6_DSTOPTS,
1126: IPPROTO_IPV6);
1127: if (*mp)
1128: mp = &(*mp)->m_next;
1129: break;
1130:
1131: case IPPROTO_ROUTING:
1132: if (!in6p->in6p_flags & IN6P_RTHDR)
1133: break;
1134:
1.1.2.3 ! itojun 1135: *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1.1.2.1 itojun 1136: IPV6_RTHDR,
1137: IPPROTO_IPV6);
1138: if (*mp)
1139: mp = &(*mp)->m_next;
1140: break;
1141:
1142: case IPPROTO_UDP:
1143: case IPPROTO_TCP:
1144: case IPPROTO_ICMPV6:
1145: default:
1146: /*
1147: * stop search if we encounter an upper
1148: * layer protocol headers.
1149: */
1150: goto loopend;
1151:
1152: case IPPROTO_HOPOPTS:
1153: case IPPROTO_AH: /* is it possible? */
1154: break;
1155: }
1156:
1157: /* proceed with the next header. */
1.1.2.3 ! itojun 1158: off += elen;
1.1.2.1 itojun 1159: nxt = ip6e->ip6e_nxt;
1160: }
1161: loopend:
1162: }
1.1.2.3 ! itojun 1163: if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
1.1.2.1 itojun 1164: /* to be done */
1165: }
1.1.2.3 ! itojun 1166: if ((in6p->in6p_flags & IN6P_DSTOPTS) && privileged) {
1.1.2.1 itojun 1167: /* to be done */
1168: }
1169: /* IN6P_RTHDR - to be done */
1170:
1171: #ifdef __bsdi__
1172: # undef sbcreatecontrol
1173: #endif
1.1.2.3 ! itojun 1174: #ifdef __OpenBSD__
! 1175: # undef in6p_flags
! 1176: #endif
1.1.2.1 itojun 1177: }
1178:
1179: /*
1180: * Get pointer to the previous header followed by the header
1181: * currently processed.
1182: * XXX: This function supposes that
1183: * M includes all headers,
1184: * the next header field and the header length field of each header
1185: * are valid, and
1186: * the sum of each header length equals to OFF.
1187: * Because of these assumptions, this function must be called very
1188: * carefully. Moreover, it will not be used in the near future when
1189: * we develop `neater' mechanism to process extension headers.
1190: */
1191: char *
1192: ip6_get_prevhdr(m, off)
1193: struct mbuf *m;
1194: int off;
1195: {
1196: struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1197:
1198: if (off == sizeof(struct ip6_hdr))
1199: return(&ip6->ip6_nxt);
1200: else {
1201: int len, nxt;
1202: struct ip6_ext *ip6e = NULL;
1203:
1204: nxt = ip6->ip6_nxt;
1205: len = sizeof(struct ip6_hdr);
1206: while (len < off) {
1207: ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1208:
1209: switch(nxt) {
1210: case IPPROTO_FRAGMENT:
1211: len += sizeof(struct ip6_frag);
1212: break;
1213: case IPPROTO_AH:
1214: len += (ip6e->ip6e_len + 2) << 2;
1215: break;
1216: default:
1217: len += (ip6e->ip6e_len + 1) << 3;
1218: break;
1219: }
1220: nxt = ip6e->ip6e_nxt;
1221: }
1222: if (ip6e)
1223: return(&ip6e->ip6e_nxt);
1224: else
1225: return NULL;
1226: }
1227: }
1228:
1229: /*
1230: * System control for IP6
1231: */
1232:
1233: u_char inet6ctlerrmap[PRC_NCMDS] = {
1234: 0, 0, 0, 0,
1235: 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1236: EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1237: EMSGSIZE, EHOSTUNREACH, 0, 0,
1238: 0, 0, 0, 0,
1239: ENOPROTOOPT
1240: };
1241:
1.1.2.3 ! itojun 1242: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.1.2.1 itojun 1243: #include <vm/vm.h>
1244: #include <sys/sysctl.h>
1245:
1246: int
1247: ip6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1248: int *name;
1249: u_int namelen;
1250: void *oldp;
1251: size_t *oldlenp;
1252: void *newp;
1253: size_t newlen;
1254: {
1255: /* All sysctl names at this level are terminal. */
1256: if (namelen != 1)
1257: return ENOTDIR;
1258:
1259: switch (name[0]) {
1260:
1261: case IPV6CTL_FORWARDING:
1262: return sysctl_int(oldp, oldlenp, newp, newlen,
1263: &ip6_forwarding);
1264: case IPV6CTL_SENDREDIRECTS:
1265: return sysctl_int(oldp, oldlenp, newp, newlen,
1266: &ip6_sendredirects);
1267: case IPV6CTL_DEFHLIM:
1268: return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_defhlim);
1269: case IPV6CTL_MAXFRAGPACKETS:
1270: return sysctl_int(oldp, oldlenp, newp, newlen,
1271: &ip6_maxfragpackets);
1272: case IPV6CTL_ACCEPT_RTADV:
1273: return sysctl_int(oldp, oldlenp, newp, newlen,
1274: &ip6_accept_rtadv);
1275: case IPV6CTL_KEEPFAITH:
1276: return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_keepfaith);
1277: case IPV6CTL_LOG_INTERVAL:
1278: return sysctl_int(oldp, oldlenp, newp, newlen,
1279: &ip6_log_interval);
1280: case IPV6CTL_HDRNESTLIMIT:
1281: return sysctl_int(oldp, oldlenp, newp, newlen,
1282: &ip6_hdrnestlimit);
1283: case IPV6CTL_DAD_COUNT:
1284: return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_dad_count);
1285: case IPV6CTL_AUTO_FLOWLABEL:
1286: return sysctl_int(oldp, oldlenp, newp, newlen,
1287: &ip6_auto_flowlabel);
1288: case IPV6CTL_DEFMCASTHLIM:
1289: return sysctl_int(oldp, oldlenp, newp, newlen,
1290: &ip6_defmcasthlim);
1291: case IPV6CTL_GIF_HLIM:
1292: return sysctl_int(oldp, oldlenp, newp, newlen,
1293: &ip6_gif_hlim);
1294: case IPV6CTL_KAME_VERSION:
1295: return sysctl_rdstring(oldp, oldlenp, newp, __KAME_VERSION);
1.1.2.3 ! itojun 1296: case IPV6CTL_USE_DEPRECATED:
! 1297: return sysctl_int(oldp, oldlenp, newp, newlen,
! 1298: &ip6_use_deprecated);
1.1.2.1 itojun 1299: default:
1300: return EOPNOTSUPP;
1301: }
1302: /* NOTREACHED */
1303: }
1.1.2.3 ! itojun 1304: #endif /* __NetBSD__ || __OpenBSD__ */
! 1305:
! 1306: #ifdef __bsdi__
! 1307: int *ip6_sysvars[] = IPV6CTL_VARS;
! 1308:
! 1309: int
! 1310: ip6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
! 1311: int *name;
! 1312: u_int namelen;
! 1313: void *oldp;
! 1314: size_t *oldlenp;
! 1315: void *newp;
! 1316: size_t newlen;
! 1317: {
! 1318: if (name[0] >= IPV6CTL_MAXID)
! 1319: return (EOPNOTSUPP);
! 1320:
! 1321: switch (name[0]) {
! 1322: case IPV6CTL_STATS:
! 1323: return sysctl_rdtrunc(oldp, oldlenp, newp, &ip6stat,
! 1324: sizeof(ip6stat));
! 1325: case IPV6CTL_KAME_VERSION:
! 1326: return sysctl_rdstring(oldp, oldlenp, newp, __KAME_VERSION);
! 1327: default:
! 1328: return (sysctl_int_arr(ip6_sysvars, name, namelen,
! 1329: oldp, oldlenp, newp, newlen));
! 1330: }
! 1331: }
! 1332: #endif /* __bsdi__ */
CVSweb <webmaster@jp.NetBSD.org>