Deleted Added
full compact
ip6_input.c (54263) ip6_input.c (55009)
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 *
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 * $FreeBSD: head/sys/netinet6/ip6_input.c 54263 1999-12-07 17:39:16Z shin $
29 * $FreeBSD: head/sys/netinet6/ip6_input.c 55009 1999-12-22 19:13:38Z shin $
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
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
67#include "opt_ipsec.h"
68
67#include <sys/param.h>
68#include <sys/systm.h>
69#include <sys/malloc.h>
70#include <sys/mbuf.h>
71#include <sys/domain.h>
72#include <sys/protosw.h>
73#include <sys/socket.h>
74#include <sys/socketvar.h>
75#include <sys/errno.h>
76#include <sys/time.h>
77#include <sys/kernel.h>
78#include <sys/syslog.h>
79#include <sys/proc.h>
80
81#include <net/if.h>
82#include <net/if_types.h>
83#include <net/if_dl.h>
84#include <net/route.h>
85#include <net/netisr.h>
86
87#include <netinet/in.h>
88#include <netinet/in_systm.h>
89#include <netinet/ip.h>
90#include <netinet/ip_icmp.h>
91#include <netinet/in_pcb.h>
92#include <netinet6/in6_var.h>
93#include <netinet6/ip6.h>
94#include <netinet6/ip6_var.h>
95#include <netinet6/icmp6.h>
96#include <netinet6/in6_ifattach.h>
97#include <netinet6/nd6.h>
98#include <netinet6/in6_prefix.h>
99
100#ifdef IPV6FIREWALL
101#include <netinet6/ip6_fw.h>
102#endif
103
104#ifdef ALTQ
105#include <netinet/altq_cdnr.h>
106#endif
107
108#include <netinet6/ip6protosw.h>
109
110/* we need it for NLOOP. */
111#include "loop.h"
112
113#include "faith.h"
114#include "gif.h"
115
116#include <net/net_osdep.h>
117
118extern struct domain inet6domain;
119extern struct ip6protosw inet6sw[];
120
121u_char ip6_protox[IPPROTO_MAX];
122static int ip6qmaxlen = IFQ_MAXLEN;
123struct in6_ifaddr *in6_ifaddr;
124struct ifqueue ip6intrq;
125
126int ip6_forward_srcrt; /* XXX */
127int ip6_sourcecheck; /* XXX */
128int ip6_sourcecheck_interval; /* XXX */
129
130#ifdef IPV6FIREWALL
131/* firewall hooks */
132ip6_fw_chk_t *ip6_fw_chk_ptr;
133ip6_fw_ctl_t *ip6_fw_ctl_ptr;
134#endif
135
136struct ip6stat ip6stat;
137
138static void ip6_init2 __P((void *));
139
140static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
141
142#if defined(PTR)
143extern int ip6_protocol_tr;
144
145int ptr_in6 __P((struct mbuf *, struct mbuf **));
146extern void ip_forward __P((struct mbuf *, int));
147#endif
148
149/*
150 * IP6 initialization: fill in IP6 protocol switch table.
151 * All protocols not implemented in kernel go to raw IP6 protocol handler.
152 */
153void
154ip6_init()
155{
156 register struct ip6protosw *pr;
157 register int i;
158 struct timeval tv;
159
160 pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
161 if (pr == 0)
162 panic("ip6_init");
163 for (i = 0; i < IPPROTO_MAX; i++)
164 ip6_protox[i] = pr - inet6sw;
165 for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
166 pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
167 if (pr->pr_domain->dom_family == PF_INET6 &&
168 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
169 ip6_protox[pr->pr_protocol] = pr - inet6sw;
170 ip6intrq.ifq_maxlen = ip6qmaxlen;
171 nd6_init();
172 frag6_init();
173#ifdef IPV6FIREWALL
174 ip6_fw_init();
175#endif
176 /*
177 * in many cases, random() here does NOT return random number
178 * as initialization during bootstrap time occur in fixed order.
179 */
180 microtime(&tv);
181 ip6_flow_seq = random() ^ tv.tv_usec;
182}
183
184static void
185ip6_init2(dummy)
186 void *dummy;
187{
188 int i;
189 int ret;
190
191 /* get EUI64 from somewhere */
192 ret = in6_ifattach_getifid(NULL);
193
194 /*
195 * to route local address of p2p link to loopback,
196 * assign loopback address first.
197 */
198 for (i = 0; i < NLOOP; i++)
199 in6_ifattach(&loif[i], IN6_IFT_LOOP, NULL, 0);
200
201 /* attach pseudo interfaces */
202 if (ret == 0)
203 in6_ifattach_p2p();
204
205 /* nd6_timer_init */
206 timeout(nd6_timer, (caddr_t)0, hz);
207 /* router renumbering prefix list maintenance */
208 timeout(in6_rr_timer, (caddr_t)0, hz);
209}
210
211/* cheat */
69#include <sys/param.h>
70#include <sys/systm.h>
71#include <sys/malloc.h>
72#include <sys/mbuf.h>
73#include <sys/domain.h>
74#include <sys/protosw.h>
75#include <sys/socket.h>
76#include <sys/socketvar.h>
77#include <sys/errno.h>
78#include <sys/time.h>
79#include <sys/kernel.h>
80#include <sys/syslog.h>
81#include <sys/proc.h>
82
83#include <net/if.h>
84#include <net/if_types.h>
85#include <net/if_dl.h>
86#include <net/route.h>
87#include <net/netisr.h>
88
89#include <netinet/in.h>
90#include <netinet/in_systm.h>
91#include <netinet/ip.h>
92#include <netinet/ip_icmp.h>
93#include <netinet/in_pcb.h>
94#include <netinet6/in6_var.h>
95#include <netinet6/ip6.h>
96#include <netinet6/ip6_var.h>
97#include <netinet6/icmp6.h>
98#include <netinet6/in6_ifattach.h>
99#include <netinet6/nd6.h>
100#include <netinet6/in6_prefix.h>
101
102#ifdef IPV6FIREWALL
103#include <netinet6/ip6_fw.h>
104#endif
105
106#ifdef ALTQ
107#include <netinet/altq_cdnr.h>
108#endif
109
110#include <netinet6/ip6protosw.h>
111
112/* we need it for NLOOP. */
113#include "loop.h"
114
115#include "faith.h"
116#include "gif.h"
117
118#include <net/net_osdep.h>
119
120extern struct domain inet6domain;
121extern struct ip6protosw inet6sw[];
122
123u_char ip6_protox[IPPROTO_MAX];
124static int ip6qmaxlen = IFQ_MAXLEN;
125struct in6_ifaddr *in6_ifaddr;
126struct ifqueue ip6intrq;
127
128int ip6_forward_srcrt; /* XXX */
129int ip6_sourcecheck; /* XXX */
130int ip6_sourcecheck_interval; /* XXX */
131
132#ifdef IPV6FIREWALL
133/* firewall hooks */
134ip6_fw_chk_t *ip6_fw_chk_ptr;
135ip6_fw_ctl_t *ip6_fw_ctl_ptr;
136#endif
137
138struct ip6stat ip6stat;
139
140static void ip6_init2 __P((void *));
141
142static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
143
144#if defined(PTR)
145extern int ip6_protocol_tr;
146
147int ptr_in6 __P((struct mbuf *, struct mbuf **));
148extern void ip_forward __P((struct mbuf *, int));
149#endif
150
151/*
152 * IP6 initialization: fill in IP6 protocol switch table.
153 * All protocols not implemented in kernel go to raw IP6 protocol handler.
154 */
155void
156ip6_init()
157{
158 register struct ip6protosw *pr;
159 register int i;
160 struct timeval tv;
161
162 pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
163 if (pr == 0)
164 panic("ip6_init");
165 for (i = 0; i < IPPROTO_MAX; i++)
166 ip6_protox[i] = pr - inet6sw;
167 for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
168 pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
169 if (pr->pr_domain->dom_family == PF_INET6 &&
170 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
171 ip6_protox[pr->pr_protocol] = pr - inet6sw;
172 ip6intrq.ifq_maxlen = ip6qmaxlen;
173 nd6_init();
174 frag6_init();
175#ifdef IPV6FIREWALL
176 ip6_fw_init();
177#endif
178 /*
179 * in many cases, random() here does NOT return random number
180 * as initialization during bootstrap time occur in fixed order.
181 */
182 microtime(&tv);
183 ip6_flow_seq = random() ^ tv.tv_usec;
184}
185
186static void
187ip6_init2(dummy)
188 void *dummy;
189{
190 int i;
191 int ret;
192
193 /* get EUI64 from somewhere */
194 ret = in6_ifattach_getifid(NULL);
195
196 /*
197 * to route local address of p2p link to loopback,
198 * assign loopback address first.
199 */
200 for (i = 0; i < NLOOP; i++)
201 in6_ifattach(&loif[i], IN6_IFT_LOOP, NULL, 0);
202
203 /* attach pseudo interfaces */
204 if (ret == 0)
205 in6_ifattach_p2p();
206
207 /* nd6_timer_init */
208 timeout(nd6_timer, (caddr_t)0, hz);
209 /* router renumbering prefix list maintenance */
210 timeout(in6_rr_timer, (caddr_t)0, hz);
211}
212
213/* cheat */
212SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip6_init2, NULL);
214/* This must be after route_init(), which is now SI_ORDER_THIRD */
215SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
213
214/*
215 * IP6 input interrupt handling. Just pass the packet to ip6_input.
216 */
217void
218ip6intr()
219{
220 int s;
221 struct mbuf *m;
222
223 for (;;) {
224 s = splimp();
225 IF_DEQUEUE(&ip6intrq, m);
226 splx(s);
227 if (m == 0)
228 return;
229 ip6_input(m);
230 }
231}
232
233NETISR_SET(NETISR_IPV6, ip6intr);
234
235extern struct route_in6 ip6_forward_rt;
236
237void
238ip6_input(m)
239 struct mbuf *m;
240{
241 struct ip6_hdr *ip6;
242 int off = sizeof(struct ip6_hdr), nest;
243 u_int32_t plen;
244 u_int32_t rtalert = ~0;
245 int nxt, ours = 0;
246 struct ifnet *deliverifp = NULL;
247
248#ifdef IPSEC
249 /*
250 * should the inner packet be considered authentic?
251 * see comment in ah4_input().
252 */
253 if (m) {
254 m->m_flags &= ~M_AUTHIPHDR;
255 m->m_flags &= ~M_AUTHIPDGM;
256 }
257#endif
258
259 /*
260 * mbuf statistics by kazu
261 */
262 if (m->m_flags & M_EXT) {
263 if (m->m_next)
264 ip6stat.ip6s_mext2m++;
265 else
266 ip6stat.ip6s_mext1++;
267 } else {
268 if (m->m_next) {
269 if (m->m_flags & M_LOOP) {
270 ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
271 } else if (m->m_pkthdr.rcvif->if_index <= 31)
272 ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
273 else
274 ip6stat.ip6s_m2m[0]++;
275 } else
276 ip6stat.ip6s_m1++;
277 }
278
279 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
280 ip6stat.ip6s_total++;
281
282 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
283
284 if (m->m_len < sizeof(struct ip6_hdr)) {
285 struct ifnet *inifp;
286 inifp = m->m_pkthdr.rcvif;
287 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
288 ip6stat.ip6s_toosmall++;
289 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
290 return;
291 }
292 }
293
294 ip6 = mtod(m, struct ip6_hdr *);
295
296 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
297 ip6stat.ip6s_badvers++;
298 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
299 goto bad;
300 }
301
302 ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
303
304#ifdef IPV6FIREWALL
305 /*
306 * Check with the firewall...
307 */
308 if (ip6_fw_chk_ptr) {
309 u_short port = 0;
310 /* If ipfw says divert, we have to just drop packet */
311 /* use port as a dummy argument */
312 if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
313 m_freem(m);
314 m = NULL;
315 }
316 if (!m)
317 return;
318 }
319#endif
320
321#ifdef ALTQ
322 if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
323 /* packet is dropped by traffic conditioner */
324 return;
325 }
326#endif
327
328 /*
329 * Scope check
330 */
331 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
332 IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
333 ip6stat.ip6s_badscope++;
334 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
335 goto bad;
336 }
337 if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
338 IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
339 if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
340 ours = 1;
341 deliverifp = m->m_pkthdr.rcvif;
342 goto hbhcheck;
343 } else {
344 ip6stat.ip6s_badscope++;
345 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
346 goto bad;
347 }
348 }
349
350 if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
351 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
352 ours = 1;
353 deliverifp = m->m_pkthdr.rcvif;
354 goto hbhcheck;
355 }
356 } else {
357 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
358 ip6->ip6_src.s6_addr16[1]
359 = htons(m->m_pkthdr.rcvif->if_index);
360 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
361 ip6->ip6_dst.s6_addr16[1]
362 = htons(m->m_pkthdr.rcvif->if_index);
363 }
364
365#if defined(PTR)
366 /*
367 *
368 */
369 if (ip6_protocol_tr)
370 {
371 struct mbuf *m1 = NULL;
372
373 switch (ptr_in6(m, &m1))
374 {
375 case IPPROTO_IP: goto mcastcheck;
376 case IPPROTO_IPV4: ip_forward(m1, 0); break;
377 case IPPROTO_IPV6: ip6_forward(m1, 0); break;
378 case IPPROTO_MAX: /* discard this packet */
379 default:
380 }
381
382 if (m != m1)
383 m_freem(m);
384
385 return;
386 }
387
388 mcastcheck:
389#endif
390
391 /*
392 * Multicast check
393 */
394 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
395 struct in6_multi *in6m = 0;
396
397 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
398 /*
399 * See if we belong to the destination multicast group on the
400 * arrival interface.
401 */
402 IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
403 if (in6m)
404 ours = 1;
405 else {
406 ip6stat.ip6s_notmember++;
407 ip6stat.ip6s_cantforward++;
408 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
409 goto bad;
410 }
411 deliverifp = m->m_pkthdr.rcvif;
412 goto hbhcheck;
413 }
414
415 /*
416 * Unicast check
417 */
418 if (ip6_forward_rt.ro_rt == 0 ||
419 !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
420 &ip6_forward_rt.ro_dst.sin6_addr)) {
421 if (ip6_forward_rt.ro_rt) {
422 RTFREE(ip6_forward_rt.ro_rt);
423 ip6_forward_rt.ro_rt = 0;
424 }
425 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
426 ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
427 ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
428 ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
429
430 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
431 }
432
433#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
434
435 /*
436 * Accept the packet if the forwarding interface to the destination
437 * according to the routing table is the loopback interface,
438 * unless the associated route has a gateway.
439 * Note that this approach causes to accept a packet if there is a
440 * route to the loopback interface for the destination of the packet.
441 * But we think it's even useful in some situations, e.g. when using
442 * a special daemon which wants to intercept the packet.
443 */
444 if (ip6_forward_rt.ro_rt &&
445 (ip6_forward_rt.ro_rt->rt_flags &
446 (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
447 /*
448 * The comparison of the destination and the key of the rtentry
449 * has already done through looking up the routing table,
450 * so no need to do such a comparison here again.
451 */
452 ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
453 struct in6_ifaddr *ia6 =
454 (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
455 /* packet to tentative address must not be received */
456 if (ia6->ia6_flags & IN6_IFF_ANYCAST)
457 m->m_flags |= M_ANYCAST6;
458 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
459 /* this interface is ready */
460 ours = 1;
461 deliverifp = ia6->ia_ifp; /* correct? */
462 goto hbhcheck;
463 } else {
464 /* this interface is not ready, fall through */
465 }
466 }
467
468 /*
469 * FAITH(Firewall Aided Internet Translator)
470 */
471#if defined(NFAITH) && 0 < NFAITH
472 if (ip6_keepfaith) {
473 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
474 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
475 /* XXX do we need more sanity checks? */
476 ours = 1;
477 deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/
478 goto hbhcheck;
479 }
480 }
481#endif
482
483 /*
484 * Now there is no reason to process the packet if it's not our own
485 * and we're not a router.
486 */
487 if (!ip6_forwarding) {
488 ip6stat.ip6s_cantforward++;
489 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
490 goto bad;
491 }
492
493 hbhcheck:
494 /*
495 * Process Hop-by-Hop options header if it's contained.
496 * m may be modified in ip6_hopopts_input().
497 * If a JumboPayload option is included, plen will also be modified.
498 */
499 plen = (u_int32_t)ntohs(ip6->ip6_plen);
500 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
501 if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
502 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
503 return; /* m have already been freed */
504 }
505 /* adjust pointer */
506 ip6 = mtod(m, struct ip6_hdr *);
507 nxt = ((struct ip6_hbh *)(ip6 + 1))->ip6h_nxt;
508
509 /*
510 * accept the packet if a router alert option is included
511 * and we act as an IPv6 router.
512 */
513 if (rtalert != ~0 && ip6_forwarding)
514 ours = 1;
515 } else
516 nxt = ip6->ip6_nxt;
517
518 /*
519 * Check that the amount of data in the buffers
520 * is as at least much as the IPv6 header would have us expect.
521 * Trim mbufs if longer than we expect.
522 * Drop packet if shorter than we expect.
523 */
524 if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
525 ip6stat.ip6s_tooshort++;
526 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
527 goto bad;
528 }
529 if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
530 if (m->m_len == m->m_pkthdr.len) {
531 m->m_len = sizeof(struct ip6_hdr) + plen;
532 m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
533 } else
534 m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
535 }
536
537 /*
538 * Forward if desirable.
539 */
540 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
541 if (!ours) {
542 m_freem(m);
543 return;
544 }
545 } else if (!ours) {
546 ip6_forward(m, 0);
547 return;
548 }
549
550 /*
551 * Tell launch routine the next header
552 */
553#if defined(__NetBSD__) && defined(IFA_STATS)
554 if (IFA_STATS && deliverifp != NULL) {
555 struct in6_ifaddr *ia6;
556 ip6 = mtod(m, struct ip6_hdr *);
557 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
558 if (ia6)
559 ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len;
560 }
561#endif
562 ip6stat.ip6s_delivered++;
563 in6_ifstat_inc(deliverifp, ifs6_in_deliver);
564 nest = 0;
565 while (nxt != IPPROTO_DONE) {
566 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
567 ip6stat.ip6s_toomanyhdr++;
568 goto bad;
569 }
570
571 /*
572 * protection against faulty packet - there should be
573 * more sanity checks in header chain processing.
574 */
575 if (m->m_pkthdr.len < off) {
576 ip6stat.ip6s_tooshort++;
577 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
578 goto bad;
579 }
580
581 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
582 }
583 return;
584 bad:
585 m_freem(m);
586}
587
588/*
589 * Hop-by-Hop options header processing. If a valid jumbo payload option is
590 * included, the real payload length will be stored in plenp.
591 */
592static int
593ip6_hopopts_input(plenp, rtalertp, mp, offp)
594 u_int32_t *plenp;
595 u_int32_t *rtalertp; /* XXX: should be stored more smart way */
596 struct mbuf **mp;
597 int *offp;
598{
599 register struct mbuf *m = *mp;
600 int off = *offp, hbhlen;
601 struct ip6_hbh *hbh;
602 u_int8_t *opt;
603
604 /* validation of the length of the header */
605 IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
606 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
607 hbhlen = (hbh->ip6h_len + 1) << 3;
608
609 IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
610 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
611 off += hbhlen;
612 hbhlen -= sizeof(struct ip6_hbh);
613 opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
614
615 if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
616 hbhlen, rtalertp, plenp) < 0)
617 return(-1);
618
619 *offp = off;
620 *mp = m;
621 return(0);
622}
623
624/*
625 * Search header for all Hop-by-hop options and process each option.
626 * This function is separate from ip6_hopopts_input() in order to
627 * handle a case where the sending node itself process its hop-by-hop
628 * options header. In such a case, the function is called from ip6_output().
629 */
630int
631ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
632 struct mbuf *m;
633 u_int8_t *opthead;
634 int hbhlen;
635 u_int32_t *rtalertp;
636 u_int32_t *plenp;
637{
638 struct ip6_hdr *ip6;
639 int optlen = 0;
640 u_int8_t *opt = opthead;
641 u_int16_t rtalert_val;
642
643 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
644 switch(*opt) {
645 case IP6OPT_PAD1:
646 optlen = 1;
647 break;
648 case IP6OPT_PADN:
649 if (hbhlen < IP6OPT_MINLEN) {
650 ip6stat.ip6s_toosmall++;
651 goto bad;
652 }
653 optlen = *(opt + 1) + 2;
654 break;
655 case IP6OPT_RTALERT:
656 /* XXX may need check for alignment */
657 if (hbhlen < IP6OPT_RTALERT_LEN) {
658 ip6stat.ip6s_toosmall++;
659 goto bad;
660 }
661 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2)
662 /* XXX: should we discard the packet? */
663 log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
664 *(opt + 1));
665 optlen = IP6OPT_RTALERT_LEN;
666 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
667 *rtalertp = ntohs(rtalert_val);
668 break;
669 case IP6OPT_JUMBO:
670 /* XXX may need check for alignment */
671 if (hbhlen < IP6OPT_JUMBO_LEN) {
672 ip6stat.ip6s_toosmall++;
673 goto bad;
674 }
675 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
676 /* XXX: should we discard the packet? */
677 log(LOG_ERR, "length of jumbopayload opt "
678 "is inconsistent(%d)",
679 *(opt + 1));
680 optlen = IP6OPT_JUMBO_LEN;
681
682 bcopy(opt + 2, plenp, sizeof(*plenp));
683 *plenp = htonl(*plenp);
684 if (*plenp <= IPV6_MAXPACKET) {
685 /*
686 * jumbo payload length must be larger
687 * than 65535
688 */
689 ip6stat.ip6s_badoptions++;
690 icmp6_error(m, ICMP6_PARAM_PROB,
691 ICMP6_PARAMPROB_HEADER,
692 sizeof(struct ip6_hdr) +
693 sizeof(struct ip6_hbh) +
694 opt + 2 - opthead);
695 return(-1);
696 }
697
698 ip6 = mtod(m, struct ip6_hdr *);
699 if (ip6->ip6_plen) {
700 /*
701 * IPv6 packets that have non 0 payload length
702 * must not contain a jumbo paylod option.
703 */
704 ip6stat.ip6s_badoptions++;
705 icmp6_error(m, ICMP6_PARAM_PROB,
706 ICMP6_PARAMPROB_HEADER,
707 sizeof(struct ip6_hdr) +
708 sizeof(struct ip6_hbh) +
709 opt - opthead);
710 return(-1);
711 }
712 break;
713 default: /* unknown option */
714 if (hbhlen < IP6OPT_MINLEN) {
715 ip6stat.ip6s_toosmall++;
716 goto bad;
717 }
718 if ((optlen = ip6_unknown_opt(opt, m,
719 sizeof(struct ip6_hdr) +
720 sizeof(struct ip6_hbh) +
721 opt - opthead)) == -1)
722 return(-1);
723 optlen += 2;
724 break;
725 }
726 }
727
728 return(0);
729
730 bad:
731 m_freem(m);
732 return(-1);
733}
734
735/*
736 * Unknown option processing.
737 * The third argument `off' is the offset from the IPv6 header to the option,
738 * which is necessary if the IPv6 header the and option header and IPv6 header
739 * is not continuous in order to return an ICMPv6 error.
740 */
741int
742ip6_unknown_opt(optp, m, off)
743 u_int8_t *optp;
744 struct mbuf *m;
745 int off;
746{
747 struct ip6_hdr *ip6;
748
749 switch(IP6OPT_TYPE(*optp)) {
750 case IP6OPT_TYPE_SKIP: /* ignore the option */
751 return((int)*(optp + 1));
752 case IP6OPT_TYPE_DISCARD: /* silently discard */
753 m_freem(m);
754 return(-1);
755 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
756 ip6stat.ip6s_badoptions++;
757 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
758 return(-1);
759 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
760 ip6stat.ip6s_badoptions++;
761 ip6 = mtod(m, struct ip6_hdr *);
762 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
763 (m->m_flags & (M_BCAST|M_MCAST)))
764 m_freem(m);
765 else
766 icmp6_error(m, ICMP6_PARAM_PROB,
767 ICMP6_PARAMPROB_OPTION, off);
768 return(-1);
769 }
770
771 m_freem(m); /* XXX: NOTREACHED */
772 return(-1);
773}
774
775/*
776 * Create the "control" list for this pcb
777 */
778void
779ip6_savecontrol(in6p, mp, ip6, m)
780 register struct inpcb *in6p;
781 register struct mbuf **mp;
782 register struct ip6_hdr *ip6;
783 register struct mbuf *m;
784{
785 struct proc *p = curproc; /* XXX */
786 int privileged;
787
788 privileged = 0;
789 if (p && !suser(p))
790 privileged++;
791
792 if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
793 struct timeval tv;
794
795 microtime(&tv);
796 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
797 SCM_TIMESTAMP, SOL_SOCKET);
798 if (*mp)
799 mp = &(*mp)->m_next;
800 }
801 if (in6p->in6p_flags & IN6P_RECVDSTADDR) {
802 *mp = sbcreatecontrol((caddr_t) &ip6->ip6_dst,
803 sizeof(struct in6_addr), IPV6_RECVDSTADDR,
804 IPPROTO_IPV6);
805 if (*mp)
806 mp = &(*mp)->m_next;
807 }
808
809 /* RFC 2292 sec. 5 */
810 if (in6p->in6p_flags & IN6P_PKTINFO) {
811 struct in6_pktinfo pi6;
812 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
813 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
814 pi6.ipi6_addr.s6_addr16[1] = 0;
815 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
816 ? m->m_pkthdr.rcvif->if_index
817 : 0;
818 *mp = sbcreatecontrol((caddr_t) &pi6,
819 sizeof(struct in6_pktinfo), IPV6_PKTINFO,
820 IPPROTO_IPV6);
821 if (*mp)
822 mp = &(*mp)->m_next;
823 }
824 if (in6p->in6p_flags & IN6P_HOPLIMIT) {
825 int hlim = ip6->ip6_hlim & 0xff;
826 *mp = sbcreatecontrol((caddr_t) &hlim,
827 sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
828 if (*mp)
829 mp = &(*mp)->m_next;
830 }
831 /* IN6P_NEXTHOP - for outgoing packet only */
832
833 /*
834 * IPV6_HOPOPTS socket option. We require super-user privilege
835 * for the option, but it might be too strict, since there might
836 * be some hop-by-hop options which can be returned to normal user.
837 * See RFC 2292 section 6.
838 */
839 if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
840 /*
841 * Check if a hop-by-hop options header is contatined in the
842 * received packet, and if so, store the options as ancillary
843 * data. Note that a hop-by-hop options header must be
844 * just after the IPv6 header, which fact is assured through
845 * the IPv6 input processing.
846 */
847 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
848 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
849 struct ip6_hbh *hbh = (struct ip6_hbh *)(ip6 + 1);
850
851 /*
852 * XXX: We copy whole the header even if a jumbo
853 * payload option is included, which option is to
854 * be removed before returning in the RFC 2292.
855 * But it's too painful operation...
856 */
857 *mp = sbcreatecontrol((caddr_t)hbh,
858 (hbh->ip6h_len + 1) << 3,
859 IPV6_HOPOPTS, IPPROTO_IPV6);
860 if (*mp)
861 mp = &(*mp)->m_next;
862 }
863 }
864
865 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
866 if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) {
867 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
868 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);;
869
870 /*
871 * Search for destination options headers or routing
872 * header(s) through the header chain, and stores each
873 * header as ancillary data.
874 * Note that the order of the headers remains in
875 * the chain of ancillary data.
876 */
877 while(1) { /* is explicit loop prevention necessary? */
878 struct ip6_ext *ip6e =
879 (struct ip6_ext *)(mtod(m, caddr_t) + off);
880
881 switch(nxt) {
882 case IPPROTO_DSTOPTS:
883 if (!in6p->in6p_flags & IN6P_DSTOPTS)
884 break;
885
886 /*
887 * We also require super-user privilege for
888 * the option.
889 * See the comments on IN6_HOPOPTS.
890 */
891 if (!privileged)
892 break;
893
894 *mp = sbcreatecontrol((caddr_t)ip6e,
895 (ip6e->ip6e_len + 1) << 3,
896 IPV6_DSTOPTS,
897 IPPROTO_IPV6);
898 if (*mp)
899 mp = &(*mp)->m_next;
900 break;
901
902 case IPPROTO_ROUTING:
903 if (!in6p->in6p_flags & IN6P_RTHDR)
904 break;
905
906 *mp = sbcreatecontrol((caddr_t)ip6e,
907 (ip6e->ip6e_len + 1) << 3,
908 IPV6_RTHDR,
909 IPPROTO_IPV6);
910 if (*mp)
911 mp = &(*mp)->m_next;
912 break;
913
914 case IPPROTO_UDP:
915 case IPPROTO_TCP:
916 case IPPROTO_ICMPV6:
917 default:
918 /*
919 * stop search if we encounter an upper
920 * layer protocol headers.
921 */
922 goto loopend;
923
924 case IPPROTO_HOPOPTS:
925 case IPPROTO_AH: /* is it possible? */
926 break;
927 }
928
929 /* proceed with the next header. */
930 if (nxt == IPPROTO_AH)
931 off += (ip6e->ip6e_len + 2) << 2;
932 else
933 off += (ip6e->ip6e_len + 1) << 3;
934 nxt = ip6e->ip6e_nxt;
935 }
936 loopend:
937 }
938 if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
939 /* to be done */
940 }
941 if ((in6p->in6p_flags & IN6P_DSTOPTS) && privileged) {
942 /* to be done */
943 }
944 /* IN6P_RTHDR - to be done */
945}
946
947/*
948 * Get pointer to the previous header followed by the header
949 * currently processed.
950 * XXX: This function supposes that
951 * M includes all headers,
952 * the next header field and the header length field of each header
953 * are valid, and
954 * the sum of each header length equals to OFF.
955 * Because of these assumptions, this function must be called very
956 * carefully. Moreover, it will not be used in the near future when
957 * we develop `neater' mechanism to process extension headers.
958 */
959char *
960ip6_get_prevhdr(m, off)
961 struct mbuf *m;
962 int off;
963{
964 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
965
966 if (off == sizeof(struct ip6_hdr))
967 return(&ip6->ip6_nxt);
968 else {
969 int len, nxt;
970 struct ip6_ext *ip6e = NULL;
971
972 nxt = ip6->ip6_nxt;
973 len = sizeof(struct ip6_hdr);
974 while (len < off) {
975 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
976
977 switch(nxt) {
978 case IPPROTO_FRAGMENT:
979 len += sizeof(struct ip6_frag);
980 break;
981 case IPPROTO_AH:
982 len += (ip6e->ip6e_len + 2) << 2;
983 break;
984 default:
985 len += (ip6e->ip6e_len + 1) << 3;
986 break;
987 }
988 nxt = ip6e->ip6e_nxt;
989 }
990 if (ip6e)
991 return(&ip6e->ip6e_nxt);
992 else
993 return NULL;
994 }
995}
996
997/*
998 * System control for IP6
999 */
1000
1001u_char inet6ctlerrmap[PRC_NCMDS] = {
1002 0, 0, 0, 0,
1003 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1004 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1005 EMSGSIZE, EHOSTUNREACH, 0, 0,
1006 0, 0, 0, 0,
1007 ENOPROTOOPT
1008};
216
217/*
218 * IP6 input interrupt handling. Just pass the packet to ip6_input.
219 */
220void
221ip6intr()
222{
223 int s;
224 struct mbuf *m;
225
226 for (;;) {
227 s = splimp();
228 IF_DEQUEUE(&ip6intrq, m);
229 splx(s);
230 if (m == 0)
231 return;
232 ip6_input(m);
233 }
234}
235
236NETISR_SET(NETISR_IPV6, ip6intr);
237
238extern struct route_in6 ip6_forward_rt;
239
240void
241ip6_input(m)
242 struct mbuf *m;
243{
244 struct ip6_hdr *ip6;
245 int off = sizeof(struct ip6_hdr), nest;
246 u_int32_t plen;
247 u_int32_t rtalert = ~0;
248 int nxt, ours = 0;
249 struct ifnet *deliverifp = NULL;
250
251#ifdef IPSEC
252 /*
253 * should the inner packet be considered authentic?
254 * see comment in ah4_input().
255 */
256 if (m) {
257 m->m_flags &= ~M_AUTHIPHDR;
258 m->m_flags &= ~M_AUTHIPDGM;
259 }
260#endif
261
262 /*
263 * mbuf statistics by kazu
264 */
265 if (m->m_flags & M_EXT) {
266 if (m->m_next)
267 ip6stat.ip6s_mext2m++;
268 else
269 ip6stat.ip6s_mext1++;
270 } else {
271 if (m->m_next) {
272 if (m->m_flags & M_LOOP) {
273 ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
274 } else if (m->m_pkthdr.rcvif->if_index <= 31)
275 ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
276 else
277 ip6stat.ip6s_m2m[0]++;
278 } else
279 ip6stat.ip6s_m1++;
280 }
281
282 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
283 ip6stat.ip6s_total++;
284
285 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
286
287 if (m->m_len < sizeof(struct ip6_hdr)) {
288 struct ifnet *inifp;
289 inifp = m->m_pkthdr.rcvif;
290 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
291 ip6stat.ip6s_toosmall++;
292 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
293 return;
294 }
295 }
296
297 ip6 = mtod(m, struct ip6_hdr *);
298
299 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
300 ip6stat.ip6s_badvers++;
301 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
302 goto bad;
303 }
304
305 ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
306
307#ifdef IPV6FIREWALL
308 /*
309 * Check with the firewall...
310 */
311 if (ip6_fw_chk_ptr) {
312 u_short port = 0;
313 /* If ipfw says divert, we have to just drop packet */
314 /* use port as a dummy argument */
315 if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
316 m_freem(m);
317 m = NULL;
318 }
319 if (!m)
320 return;
321 }
322#endif
323
324#ifdef ALTQ
325 if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
326 /* packet is dropped by traffic conditioner */
327 return;
328 }
329#endif
330
331 /*
332 * Scope check
333 */
334 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
335 IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
336 ip6stat.ip6s_badscope++;
337 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
338 goto bad;
339 }
340 if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
341 IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
342 if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
343 ours = 1;
344 deliverifp = m->m_pkthdr.rcvif;
345 goto hbhcheck;
346 } else {
347 ip6stat.ip6s_badscope++;
348 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
349 goto bad;
350 }
351 }
352
353 if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
354 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
355 ours = 1;
356 deliverifp = m->m_pkthdr.rcvif;
357 goto hbhcheck;
358 }
359 } else {
360 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
361 ip6->ip6_src.s6_addr16[1]
362 = htons(m->m_pkthdr.rcvif->if_index);
363 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
364 ip6->ip6_dst.s6_addr16[1]
365 = htons(m->m_pkthdr.rcvif->if_index);
366 }
367
368#if defined(PTR)
369 /*
370 *
371 */
372 if (ip6_protocol_tr)
373 {
374 struct mbuf *m1 = NULL;
375
376 switch (ptr_in6(m, &m1))
377 {
378 case IPPROTO_IP: goto mcastcheck;
379 case IPPROTO_IPV4: ip_forward(m1, 0); break;
380 case IPPROTO_IPV6: ip6_forward(m1, 0); break;
381 case IPPROTO_MAX: /* discard this packet */
382 default:
383 }
384
385 if (m != m1)
386 m_freem(m);
387
388 return;
389 }
390
391 mcastcheck:
392#endif
393
394 /*
395 * Multicast check
396 */
397 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
398 struct in6_multi *in6m = 0;
399
400 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
401 /*
402 * See if we belong to the destination multicast group on the
403 * arrival interface.
404 */
405 IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
406 if (in6m)
407 ours = 1;
408 else {
409 ip6stat.ip6s_notmember++;
410 ip6stat.ip6s_cantforward++;
411 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
412 goto bad;
413 }
414 deliverifp = m->m_pkthdr.rcvif;
415 goto hbhcheck;
416 }
417
418 /*
419 * Unicast check
420 */
421 if (ip6_forward_rt.ro_rt == 0 ||
422 !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
423 &ip6_forward_rt.ro_dst.sin6_addr)) {
424 if (ip6_forward_rt.ro_rt) {
425 RTFREE(ip6_forward_rt.ro_rt);
426 ip6_forward_rt.ro_rt = 0;
427 }
428 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
429 ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
430 ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
431 ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
432
433 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
434 }
435
436#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
437
438 /*
439 * Accept the packet if the forwarding interface to the destination
440 * according to the routing table is the loopback interface,
441 * unless the associated route has a gateway.
442 * Note that this approach causes to accept a packet if there is a
443 * route to the loopback interface for the destination of the packet.
444 * But we think it's even useful in some situations, e.g. when using
445 * a special daemon which wants to intercept the packet.
446 */
447 if (ip6_forward_rt.ro_rt &&
448 (ip6_forward_rt.ro_rt->rt_flags &
449 (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
450 /*
451 * The comparison of the destination and the key of the rtentry
452 * has already done through looking up the routing table,
453 * so no need to do such a comparison here again.
454 */
455 ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
456 struct in6_ifaddr *ia6 =
457 (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
458 /* packet to tentative address must not be received */
459 if (ia6->ia6_flags & IN6_IFF_ANYCAST)
460 m->m_flags |= M_ANYCAST6;
461 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
462 /* this interface is ready */
463 ours = 1;
464 deliverifp = ia6->ia_ifp; /* correct? */
465 goto hbhcheck;
466 } else {
467 /* this interface is not ready, fall through */
468 }
469 }
470
471 /*
472 * FAITH(Firewall Aided Internet Translator)
473 */
474#if defined(NFAITH) && 0 < NFAITH
475 if (ip6_keepfaith) {
476 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
477 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
478 /* XXX do we need more sanity checks? */
479 ours = 1;
480 deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/
481 goto hbhcheck;
482 }
483 }
484#endif
485
486 /*
487 * Now there is no reason to process the packet if it's not our own
488 * and we're not a router.
489 */
490 if (!ip6_forwarding) {
491 ip6stat.ip6s_cantforward++;
492 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
493 goto bad;
494 }
495
496 hbhcheck:
497 /*
498 * Process Hop-by-Hop options header if it's contained.
499 * m may be modified in ip6_hopopts_input().
500 * If a JumboPayload option is included, plen will also be modified.
501 */
502 plen = (u_int32_t)ntohs(ip6->ip6_plen);
503 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
504 if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
505 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
506 return; /* m have already been freed */
507 }
508 /* adjust pointer */
509 ip6 = mtod(m, struct ip6_hdr *);
510 nxt = ((struct ip6_hbh *)(ip6 + 1))->ip6h_nxt;
511
512 /*
513 * accept the packet if a router alert option is included
514 * and we act as an IPv6 router.
515 */
516 if (rtalert != ~0 && ip6_forwarding)
517 ours = 1;
518 } else
519 nxt = ip6->ip6_nxt;
520
521 /*
522 * Check that the amount of data in the buffers
523 * is as at least much as the IPv6 header would have us expect.
524 * Trim mbufs if longer than we expect.
525 * Drop packet if shorter than we expect.
526 */
527 if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
528 ip6stat.ip6s_tooshort++;
529 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
530 goto bad;
531 }
532 if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
533 if (m->m_len == m->m_pkthdr.len) {
534 m->m_len = sizeof(struct ip6_hdr) + plen;
535 m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
536 } else
537 m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
538 }
539
540 /*
541 * Forward if desirable.
542 */
543 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
544 if (!ours) {
545 m_freem(m);
546 return;
547 }
548 } else if (!ours) {
549 ip6_forward(m, 0);
550 return;
551 }
552
553 /*
554 * Tell launch routine the next header
555 */
556#if defined(__NetBSD__) && defined(IFA_STATS)
557 if (IFA_STATS && deliverifp != NULL) {
558 struct in6_ifaddr *ia6;
559 ip6 = mtod(m, struct ip6_hdr *);
560 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
561 if (ia6)
562 ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len;
563 }
564#endif
565 ip6stat.ip6s_delivered++;
566 in6_ifstat_inc(deliverifp, ifs6_in_deliver);
567 nest = 0;
568 while (nxt != IPPROTO_DONE) {
569 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
570 ip6stat.ip6s_toomanyhdr++;
571 goto bad;
572 }
573
574 /*
575 * protection against faulty packet - there should be
576 * more sanity checks in header chain processing.
577 */
578 if (m->m_pkthdr.len < off) {
579 ip6stat.ip6s_tooshort++;
580 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
581 goto bad;
582 }
583
584 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
585 }
586 return;
587 bad:
588 m_freem(m);
589}
590
591/*
592 * Hop-by-Hop options header processing. If a valid jumbo payload option is
593 * included, the real payload length will be stored in plenp.
594 */
595static int
596ip6_hopopts_input(plenp, rtalertp, mp, offp)
597 u_int32_t *plenp;
598 u_int32_t *rtalertp; /* XXX: should be stored more smart way */
599 struct mbuf **mp;
600 int *offp;
601{
602 register struct mbuf *m = *mp;
603 int off = *offp, hbhlen;
604 struct ip6_hbh *hbh;
605 u_int8_t *opt;
606
607 /* validation of the length of the header */
608 IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
609 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
610 hbhlen = (hbh->ip6h_len + 1) << 3;
611
612 IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
613 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
614 off += hbhlen;
615 hbhlen -= sizeof(struct ip6_hbh);
616 opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
617
618 if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
619 hbhlen, rtalertp, plenp) < 0)
620 return(-1);
621
622 *offp = off;
623 *mp = m;
624 return(0);
625}
626
627/*
628 * Search header for all Hop-by-hop options and process each option.
629 * This function is separate from ip6_hopopts_input() in order to
630 * handle a case where the sending node itself process its hop-by-hop
631 * options header. In such a case, the function is called from ip6_output().
632 */
633int
634ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
635 struct mbuf *m;
636 u_int8_t *opthead;
637 int hbhlen;
638 u_int32_t *rtalertp;
639 u_int32_t *plenp;
640{
641 struct ip6_hdr *ip6;
642 int optlen = 0;
643 u_int8_t *opt = opthead;
644 u_int16_t rtalert_val;
645
646 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
647 switch(*opt) {
648 case IP6OPT_PAD1:
649 optlen = 1;
650 break;
651 case IP6OPT_PADN:
652 if (hbhlen < IP6OPT_MINLEN) {
653 ip6stat.ip6s_toosmall++;
654 goto bad;
655 }
656 optlen = *(opt + 1) + 2;
657 break;
658 case IP6OPT_RTALERT:
659 /* XXX may need check for alignment */
660 if (hbhlen < IP6OPT_RTALERT_LEN) {
661 ip6stat.ip6s_toosmall++;
662 goto bad;
663 }
664 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2)
665 /* XXX: should we discard the packet? */
666 log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
667 *(opt + 1));
668 optlen = IP6OPT_RTALERT_LEN;
669 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
670 *rtalertp = ntohs(rtalert_val);
671 break;
672 case IP6OPT_JUMBO:
673 /* XXX may need check for alignment */
674 if (hbhlen < IP6OPT_JUMBO_LEN) {
675 ip6stat.ip6s_toosmall++;
676 goto bad;
677 }
678 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
679 /* XXX: should we discard the packet? */
680 log(LOG_ERR, "length of jumbopayload opt "
681 "is inconsistent(%d)",
682 *(opt + 1));
683 optlen = IP6OPT_JUMBO_LEN;
684
685 bcopy(opt + 2, plenp, sizeof(*plenp));
686 *plenp = htonl(*plenp);
687 if (*plenp <= IPV6_MAXPACKET) {
688 /*
689 * jumbo payload length must be larger
690 * than 65535
691 */
692 ip6stat.ip6s_badoptions++;
693 icmp6_error(m, ICMP6_PARAM_PROB,
694 ICMP6_PARAMPROB_HEADER,
695 sizeof(struct ip6_hdr) +
696 sizeof(struct ip6_hbh) +
697 opt + 2 - opthead);
698 return(-1);
699 }
700
701 ip6 = mtod(m, struct ip6_hdr *);
702 if (ip6->ip6_plen) {
703 /*
704 * IPv6 packets that have non 0 payload length
705 * must not contain a jumbo paylod option.
706 */
707 ip6stat.ip6s_badoptions++;
708 icmp6_error(m, ICMP6_PARAM_PROB,
709 ICMP6_PARAMPROB_HEADER,
710 sizeof(struct ip6_hdr) +
711 sizeof(struct ip6_hbh) +
712 opt - opthead);
713 return(-1);
714 }
715 break;
716 default: /* unknown option */
717 if (hbhlen < IP6OPT_MINLEN) {
718 ip6stat.ip6s_toosmall++;
719 goto bad;
720 }
721 if ((optlen = ip6_unknown_opt(opt, m,
722 sizeof(struct ip6_hdr) +
723 sizeof(struct ip6_hbh) +
724 opt - opthead)) == -1)
725 return(-1);
726 optlen += 2;
727 break;
728 }
729 }
730
731 return(0);
732
733 bad:
734 m_freem(m);
735 return(-1);
736}
737
738/*
739 * Unknown option processing.
740 * The third argument `off' is the offset from the IPv6 header to the option,
741 * which is necessary if the IPv6 header the and option header and IPv6 header
742 * is not continuous in order to return an ICMPv6 error.
743 */
744int
745ip6_unknown_opt(optp, m, off)
746 u_int8_t *optp;
747 struct mbuf *m;
748 int off;
749{
750 struct ip6_hdr *ip6;
751
752 switch(IP6OPT_TYPE(*optp)) {
753 case IP6OPT_TYPE_SKIP: /* ignore the option */
754 return((int)*(optp + 1));
755 case IP6OPT_TYPE_DISCARD: /* silently discard */
756 m_freem(m);
757 return(-1);
758 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
759 ip6stat.ip6s_badoptions++;
760 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
761 return(-1);
762 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
763 ip6stat.ip6s_badoptions++;
764 ip6 = mtod(m, struct ip6_hdr *);
765 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
766 (m->m_flags & (M_BCAST|M_MCAST)))
767 m_freem(m);
768 else
769 icmp6_error(m, ICMP6_PARAM_PROB,
770 ICMP6_PARAMPROB_OPTION, off);
771 return(-1);
772 }
773
774 m_freem(m); /* XXX: NOTREACHED */
775 return(-1);
776}
777
778/*
779 * Create the "control" list for this pcb
780 */
781void
782ip6_savecontrol(in6p, mp, ip6, m)
783 register struct inpcb *in6p;
784 register struct mbuf **mp;
785 register struct ip6_hdr *ip6;
786 register struct mbuf *m;
787{
788 struct proc *p = curproc; /* XXX */
789 int privileged;
790
791 privileged = 0;
792 if (p && !suser(p))
793 privileged++;
794
795 if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
796 struct timeval tv;
797
798 microtime(&tv);
799 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
800 SCM_TIMESTAMP, SOL_SOCKET);
801 if (*mp)
802 mp = &(*mp)->m_next;
803 }
804 if (in6p->in6p_flags & IN6P_RECVDSTADDR) {
805 *mp = sbcreatecontrol((caddr_t) &ip6->ip6_dst,
806 sizeof(struct in6_addr), IPV6_RECVDSTADDR,
807 IPPROTO_IPV6);
808 if (*mp)
809 mp = &(*mp)->m_next;
810 }
811
812 /* RFC 2292 sec. 5 */
813 if (in6p->in6p_flags & IN6P_PKTINFO) {
814 struct in6_pktinfo pi6;
815 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
816 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
817 pi6.ipi6_addr.s6_addr16[1] = 0;
818 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
819 ? m->m_pkthdr.rcvif->if_index
820 : 0;
821 *mp = sbcreatecontrol((caddr_t) &pi6,
822 sizeof(struct in6_pktinfo), IPV6_PKTINFO,
823 IPPROTO_IPV6);
824 if (*mp)
825 mp = &(*mp)->m_next;
826 }
827 if (in6p->in6p_flags & IN6P_HOPLIMIT) {
828 int hlim = ip6->ip6_hlim & 0xff;
829 *mp = sbcreatecontrol((caddr_t) &hlim,
830 sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
831 if (*mp)
832 mp = &(*mp)->m_next;
833 }
834 /* IN6P_NEXTHOP - for outgoing packet only */
835
836 /*
837 * IPV6_HOPOPTS socket option. We require super-user privilege
838 * for the option, but it might be too strict, since there might
839 * be some hop-by-hop options which can be returned to normal user.
840 * See RFC 2292 section 6.
841 */
842 if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
843 /*
844 * Check if a hop-by-hop options header is contatined in the
845 * received packet, and if so, store the options as ancillary
846 * data. Note that a hop-by-hop options header must be
847 * just after the IPv6 header, which fact is assured through
848 * the IPv6 input processing.
849 */
850 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
851 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
852 struct ip6_hbh *hbh = (struct ip6_hbh *)(ip6 + 1);
853
854 /*
855 * XXX: We copy whole the header even if a jumbo
856 * payload option is included, which option is to
857 * be removed before returning in the RFC 2292.
858 * But it's too painful operation...
859 */
860 *mp = sbcreatecontrol((caddr_t)hbh,
861 (hbh->ip6h_len + 1) << 3,
862 IPV6_HOPOPTS, IPPROTO_IPV6);
863 if (*mp)
864 mp = &(*mp)->m_next;
865 }
866 }
867
868 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
869 if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) {
870 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
871 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);;
872
873 /*
874 * Search for destination options headers or routing
875 * header(s) through the header chain, and stores each
876 * header as ancillary data.
877 * Note that the order of the headers remains in
878 * the chain of ancillary data.
879 */
880 while(1) { /* is explicit loop prevention necessary? */
881 struct ip6_ext *ip6e =
882 (struct ip6_ext *)(mtod(m, caddr_t) + off);
883
884 switch(nxt) {
885 case IPPROTO_DSTOPTS:
886 if (!in6p->in6p_flags & IN6P_DSTOPTS)
887 break;
888
889 /*
890 * We also require super-user privilege for
891 * the option.
892 * See the comments on IN6_HOPOPTS.
893 */
894 if (!privileged)
895 break;
896
897 *mp = sbcreatecontrol((caddr_t)ip6e,
898 (ip6e->ip6e_len + 1) << 3,
899 IPV6_DSTOPTS,
900 IPPROTO_IPV6);
901 if (*mp)
902 mp = &(*mp)->m_next;
903 break;
904
905 case IPPROTO_ROUTING:
906 if (!in6p->in6p_flags & IN6P_RTHDR)
907 break;
908
909 *mp = sbcreatecontrol((caddr_t)ip6e,
910 (ip6e->ip6e_len + 1) << 3,
911 IPV6_RTHDR,
912 IPPROTO_IPV6);
913 if (*mp)
914 mp = &(*mp)->m_next;
915 break;
916
917 case IPPROTO_UDP:
918 case IPPROTO_TCP:
919 case IPPROTO_ICMPV6:
920 default:
921 /*
922 * stop search if we encounter an upper
923 * layer protocol headers.
924 */
925 goto loopend;
926
927 case IPPROTO_HOPOPTS:
928 case IPPROTO_AH: /* is it possible? */
929 break;
930 }
931
932 /* proceed with the next header. */
933 if (nxt == IPPROTO_AH)
934 off += (ip6e->ip6e_len + 2) << 2;
935 else
936 off += (ip6e->ip6e_len + 1) << 3;
937 nxt = ip6e->ip6e_nxt;
938 }
939 loopend:
940 }
941 if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
942 /* to be done */
943 }
944 if ((in6p->in6p_flags & IN6P_DSTOPTS) && privileged) {
945 /* to be done */
946 }
947 /* IN6P_RTHDR - to be done */
948}
949
950/*
951 * Get pointer to the previous header followed by the header
952 * currently processed.
953 * XXX: This function supposes that
954 * M includes all headers,
955 * the next header field and the header length field of each header
956 * are valid, and
957 * the sum of each header length equals to OFF.
958 * Because of these assumptions, this function must be called very
959 * carefully. Moreover, it will not be used in the near future when
960 * we develop `neater' mechanism to process extension headers.
961 */
962char *
963ip6_get_prevhdr(m, off)
964 struct mbuf *m;
965 int off;
966{
967 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
968
969 if (off == sizeof(struct ip6_hdr))
970 return(&ip6->ip6_nxt);
971 else {
972 int len, nxt;
973 struct ip6_ext *ip6e = NULL;
974
975 nxt = ip6->ip6_nxt;
976 len = sizeof(struct ip6_hdr);
977 while (len < off) {
978 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
979
980 switch(nxt) {
981 case IPPROTO_FRAGMENT:
982 len += sizeof(struct ip6_frag);
983 break;
984 case IPPROTO_AH:
985 len += (ip6e->ip6e_len + 2) << 2;
986 break;
987 default:
988 len += (ip6e->ip6e_len + 1) << 3;
989 break;
990 }
991 nxt = ip6e->ip6e_nxt;
992 }
993 if (ip6e)
994 return(&ip6e->ip6e_nxt);
995 else
996 return NULL;
997 }
998}
999
1000/*
1001 * System control for IP6
1002 */
1003
1004u_char inet6ctlerrmap[PRC_NCMDS] = {
1005 0, 0, 0, 0,
1006 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1007 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1008 EMSGSIZE, EHOSTUNREACH, 0, 0,
1009 0, 0, 0, 0,
1010 ENOPROTOOPT
1011};