Deleted Added
full compact
ip6_input.c (78064) ip6_input.c (79106)
1/* $FreeBSD: head/sys/netinet6/ip6_input.c 78064 2001-06-11 12:39:29Z ume $ */
1/* $FreeBSD: head/sys/netinet6/ip6_input.c 79106 2001-07-02 21:02:09Z brooks $ */
2/* $KAME: ip6_input.c,v 1.194 2001/05/27 13:28:35 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1982, 1986, 1988, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Berkeley and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 *
65 * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
66 */
67
68#include "opt_ip6fw.h"
69#include "opt_inet.h"
70#include "opt_inet6.h"
71#include "opt_ipsec.h"
72#include "opt_pfil_hooks.h"
73
74#include <sys/param.h>
75#include <sys/systm.h>
76#include <sys/malloc.h>
77#include <sys/mbuf.h>
78#include <sys/domain.h>
79#include <sys/protosw.h>
80#include <sys/socket.h>
81#include <sys/socketvar.h>
82#include <sys/errno.h>
83#include <sys/time.h>
84#include <sys/kernel.h>
85#include <sys/syslog.h>
86
87#include <net/if.h>
88#include <net/if_types.h>
89#include <net/if_dl.h>
90#include <net/route.h>
91#include <net/netisr.h>
92#include <net/intrq.h>
93#ifdef PFIL_HOOKS
94#include <net/pfil.h>
95#endif
96
97#include <netinet/in.h>
98#include <netinet/in_systm.h>
99#ifdef INET
100#include <netinet/ip.h>
101#include <netinet/ip_icmp.h>
102#endif /*INET*/
103#include <netinet/ip6.h>
104#include <netinet6/in6_var.h>
105#include <netinet6/ip6_var.h>
106#include <netinet/in_pcb.h>
107#include <netinet/icmp6.h>
108#include <netinet6/in6_ifattach.h>
109#include <netinet6/nd6.h>
110#include <netinet6/in6_prefix.h>
111
112#ifdef IPSEC
113#include <netinet6/ipsec.h>
114#ifdef INET6
115#include <netinet6/ipsec6.h>
116#endif
117#endif
118
119#include <netinet6/ip6_fw.h>
120
121#include <netinet6/ip6protosw.h>
122
123#include "faith.h"
2/* $KAME: ip6_input.c,v 1.194 2001/05/27 13:28:35 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1982, 1986, 1988, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Berkeley and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 *
65 * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
66 */
67
68#include "opt_ip6fw.h"
69#include "opt_inet.h"
70#include "opt_inet6.h"
71#include "opt_ipsec.h"
72#include "opt_pfil_hooks.h"
73
74#include <sys/param.h>
75#include <sys/systm.h>
76#include <sys/malloc.h>
77#include <sys/mbuf.h>
78#include <sys/domain.h>
79#include <sys/protosw.h>
80#include <sys/socket.h>
81#include <sys/socketvar.h>
82#include <sys/errno.h>
83#include <sys/time.h>
84#include <sys/kernel.h>
85#include <sys/syslog.h>
86
87#include <net/if.h>
88#include <net/if_types.h>
89#include <net/if_dl.h>
90#include <net/route.h>
91#include <net/netisr.h>
92#include <net/intrq.h>
93#ifdef PFIL_HOOKS
94#include <net/pfil.h>
95#endif
96
97#include <netinet/in.h>
98#include <netinet/in_systm.h>
99#ifdef INET
100#include <netinet/ip.h>
101#include <netinet/ip_icmp.h>
102#endif /*INET*/
103#include <netinet/ip6.h>
104#include <netinet6/in6_var.h>
105#include <netinet6/ip6_var.h>
106#include <netinet/in_pcb.h>
107#include <netinet/icmp6.h>
108#include <netinet6/in6_ifattach.h>
109#include <netinet6/nd6.h>
110#include <netinet6/in6_prefix.h>
111
112#ifdef IPSEC
113#include <netinet6/ipsec.h>
114#ifdef INET6
115#include <netinet6/ipsec6.h>
116#endif
117#endif
118
119#include <netinet6/ip6_fw.h>
120
121#include <netinet6/ip6protosw.h>
122
123#include "faith.h"
124#include "gif.h"
125
126#include <net/net_osdep.h>
127
128extern struct domain inet6domain;
129extern struct ip6protosw inet6sw[];
130
131u_char ip6_protox[IPPROTO_MAX];
132static int ip6qmaxlen = IFQ_MAXLEN;
133struct in6_ifaddr *in6_ifaddr;
134
135extern struct callout in6_tmpaddrtimer_ch;
136
137int ip6_forward_srcrt; /* XXX */
138int ip6_sourcecheck; /* XXX */
139int ip6_sourcecheck_interval; /* XXX */
140const int int6intrq_present = 1;
141
142int ip6_ours_check_algorithm;
143
144
145/* firewall hooks */
146ip6_fw_chk_t *ip6_fw_chk_ptr;
147ip6_fw_ctl_t *ip6_fw_ctl_ptr;
148int ip6_fw_enable = 1;
149
150struct ip6stat ip6stat;
151
152static void ip6_init2 __P((void *));
153static struct mbuf *ip6_setdstifaddr __P((struct mbuf *, struct in6_ifaddr *));
154
155static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
156#ifdef PULLDOWN_TEST
157static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int));
158#endif
159
160
161/*
162 * IP6 initialization: fill in IP6 protocol switch table.
163 * All protocols not implemented in kernel go to raw IP6 protocol handler.
164 */
165void
166ip6_init()
167{
168 struct ip6protosw *pr;
169 int i;
170 struct timeval tv;
171
172#ifdef DIAGNOSTIC
173 if (sizeof(struct protosw) != sizeof(struct ip6protosw))
174 panic("sizeof(protosw) != sizeof(ip6protosw)");
175#endif
176 pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
177 if (pr == 0)
178 panic("ip6_init");
179 for (i = 0; i < IPPROTO_MAX; i++)
180 ip6_protox[i] = pr - inet6sw;
181 for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
182 pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
183 if (pr->pr_domain->dom_family == PF_INET6 &&
184 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
185 ip6_protox[pr->pr_protocol] = pr - inet6sw;
186 ip6intrq.ifq_maxlen = ip6qmaxlen;
187 mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", MTX_DEF);
188 register_netisr(NETISR_IPV6, ip6intr);
189 nd6_init();
190 frag6_init();
191 /*
192 * in many cases, random() here does NOT return random number
193 * as initialization during bootstrap time occur in fixed order.
194 */
195 microtime(&tv);
196 ip6_flow_seq = random() ^ tv.tv_usec;
197 microtime(&tv);
198 ip6_desync_factor = (random() ^ tv.tv_usec) % MAX_TEMP_DESYNC_FACTOR;
199}
200
201static void
202ip6_init2(dummy)
203 void *dummy;
204{
205
206 /*
207 * to route local address of p2p link to loopback,
208 * assign loopback address first.
209 */
210 in6_ifattach(&loif[0], NULL);
211
212 /* nd6_timer_init */
213 callout_init(&nd6_timer_ch, 0);
214 callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL);
215
216 /* router renumbering prefix list maintenance */
217 callout_init(&in6_rr_timer_ch, 0);
218 callout_reset(&in6_rr_timer_ch, hz, in6_rr_timer, NULL);
219
220 /* timer for regeneranation of temporary addresses randomize ID */
221 callout_reset(&in6_tmpaddrtimer_ch,
222 (ip6_temp_preferred_lifetime - ip6_desync_factor -
223 ip6_temp_regen_advance) * hz,
224 in6_tmpaddrtimer, NULL);
225}
226
227/* cheat */
228/* This must be after route_init(), which is now SI_ORDER_THIRD */
229SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
230
231/*
232 * IP6 input interrupt handling. Just pass the packet to ip6_input.
233 */
234void
235ip6intr()
236{
237 int s;
238 struct mbuf *m;
239
240 for (;;) {
241 s = splimp();
242 IF_DEQUEUE(&ip6intrq, m);
243 splx(s);
244 if (m == 0)
245 return;
246 ip6_input(m);
247 }
248}
249
250extern struct route_in6 ip6_forward_rt;
251
252void
253ip6_input(m)
254 struct mbuf *m;
255{
256 struct ip6_hdr *ip6;
257 int off = sizeof(struct ip6_hdr), nest;
258 u_int32_t plen;
259 u_int32_t rtalert = ~0;
260 int nxt, ours = 0;
261 struct ifnet *deliverifp = NULL;
262#ifdef PFIL_HOOKS
263 struct packet_filter_hook *pfh;
264 struct mbuf *m0;
265 int rv;
266#endif /* PFIL_HOOKS */
267
268#ifdef IPSEC
269 /*
270 * should the inner packet be considered authentic?
271 * see comment in ah4_input().
272 */
273 if (m) {
274 m->m_flags &= ~M_AUTHIPHDR;
275 m->m_flags &= ~M_AUTHIPDGM;
276 }
277#endif
278
279 /*
280 * make sure we don't have onion peering information into m_aux.
281 */
282 ip6_delaux(m);
283
284 /*
285 * mbuf statistics by kazu
286 */
287 if (m->m_flags & M_EXT) {
288 if (m->m_next)
289 ip6stat.ip6s_mext2m++;
290 else
291 ip6stat.ip6s_mext1++;
292 } else {
293#define M2MMAX (sizeof(ip6stat.ip6s_m2m)/sizeof(ip6stat.ip6s_m2m[0]))
294 if (m->m_next) {
295 if (m->m_flags & M_LOOP) {
296 ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
297 } else if (m->m_pkthdr.rcvif->if_index < M2MMAX)
298 ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
299 else
300 ip6stat.ip6s_m2m[0]++;
301 } else
302 ip6stat.ip6s_m1++;
303#undef M2MMAX
304 }
305
306 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
307 ip6stat.ip6s_total++;
308
309#ifndef PULLDOWN_TEST
310 /*
311 * L2 bridge code and some other code can return mbuf chain
312 * that does not conform to KAME requirement. too bad.
313 * XXX: fails to join if interface MTU > MCLBYTES. jumbogram?
314 */
315 if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
316 struct mbuf *n;
317
318 MGETHDR(n, M_DONTWAIT, MT_HEADER);
319 if (n)
320 M_COPY_PKTHDR(n, m);
321 if (n && m->m_pkthdr.len > MHLEN) {
322 MCLGET(n, M_DONTWAIT);
323 if ((n->m_flags & M_EXT) == 0) {
324 m_freem(n);
325 n = NULL;
326 }
327 }
328 if (!n) {
329 m_freem(m);
330 return; /*ENOBUFS*/
331 }
332
333 m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
334 n->m_len = m->m_pkthdr.len;
335 m_freem(m);
336 m = n;
337 }
338 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
339#endif
340
341 if (m->m_len < sizeof(struct ip6_hdr)) {
342 struct ifnet *inifp;
343 inifp = m->m_pkthdr.rcvif;
344 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
345 ip6stat.ip6s_toosmall++;
346 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
347 return;
348 }
349 }
350
351 ip6 = mtod(m, struct ip6_hdr *);
352
353 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
354 ip6stat.ip6s_badvers++;
355 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
356 goto bad;
357 }
358
359#ifdef PFIL_HOOKS
360 /*
361 * Run through list of hooks for input packets. If there are any
362 * filters which require that additional packets in the flow are
363 * not fast-forwarded, they must clear the M_CANFASTFWD flag.
364 * Note that filters must _never_ set this flag, as another filter
365 * in the list may have previously cleared it.
366 */
367 m0 = m;
368 pfh = pfil_hook_get(PFIL_IN, &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
369 for (; pfh; pfh = pfh->pfil_link.tqe_next)
370 if (pfh->pfil_func) {
371 rv = pfh->pfil_func(ip6, sizeof(*ip6),
372 m->m_pkthdr.rcvif, 0, &m0);
373 if (rv)
374 return;
375 m = m0;
376 if (m == NULL)
377 return;
378 ip6 = mtod(m, struct ip6_hdr *);
379 }
380#endif /* PFIL_HOOKS */
381
382 ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
383
384 /*
385 * Check with the firewall...
386 */
387 if (ip6_fw_enable && ip6_fw_chk_ptr) {
388 u_short port = 0;
389 /* If ipfw says divert, we have to just drop packet */
390 /* use port as a dummy argument */
391 if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
392 m_freem(m);
393 m = NULL;
394 }
395 if (!m)
396 return;
397 }
398
399 /*
400 * Check against address spoofing/corruption.
401 */
402 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
403 IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
404 /*
405 * XXX: "badscope" is not very suitable for a multicast source.
406 */
407 ip6stat.ip6s_badscope++;
408 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
409 goto bad;
410 }
411 if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
412 IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) &&
413 (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
414 ip6stat.ip6s_badscope++;
415 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
416 goto bad;
417 }
418 /*
419 * The following check is not documented in specs. A malicious
420 * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
421 * and bypass security checks (act as if it was from 127.0.0.1 by using
422 * IPv6 src ::ffff:127.0.0.1). Be cautious.
423 *
424 * This check chokes if we are in an SIIT cloud. As none of BSDs
425 * support IPv4-less kernel compilation, we cannot support SIIT
426 * environment at all. So, it makes more sense for us to reject any
427 * malicious packets for non-SIIT environment, than try to do a
428 * partical support for SIIT environment.
429 */
430 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
431 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
432 ip6stat.ip6s_badscope++;
433 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
434 goto bad;
435 }
436#if 0
437 /*
438 * Reject packets with IPv4 compatible addresses (auto tunnel).
439 *
440 * The code forbids auto tunnel relay case in RFC1933 (the check is
441 * stronger than RFC1933). We may want to re-enable it if mech-xx
442 * is revised to forbid relaying case.
443 */
444 if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
445 IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
446 ip6stat.ip6s_badscope++;
447 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
448 goto bad;
449 }
450#endif
451
452 /* drop packets if interface ID portion is already filled */
453 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
454 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src) &&
455 ip6->ip6_src.s6_addr16[1]) {
456 ip6stat.ip6s_badscope++;
457 goto bad;
458 }
459 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst) &&
460 ip6->ip6_dst.s6_addr16[1]) {
461 ip6stat.ip6s_badscope++;
462 goto bad;
463 }
464 }
465
466 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
467 ip6->ip6_src.s6_addr16[1]
468 = htons(m->m_pkthdr.rcvif->if_index);
469 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
470 ip6->ip6_dst.s6_addr16[1]
471 = htons(m->m_pkthdr.rcvif->if_index);
472
473#if 0 /* this case seems to be unnecessary. (jinmei, 20010401) */
474 /*
475 * We use rt->rt_ifp to determine if the address is ours or not.
476 * If rt_ifp is lo0, the address is ours.
477 * The problem here is, rt->rt_ifp for fe80::%lo0/64 is set to lo0,
478 * so any address under fe80::%lo0/64 will be mistakenly considered
479 * local. The special case is supplied to handle the case properly
480 * by actually looking at interface addresses
481 * (using in6ifa_ifpwithaddr).
482 */
483 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0 &&
484 IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
485 if (!in6ifa_ifpwithaddr(m->m_pkthdr.rcvif, &ip6->ip6_dst)) {
486 icmp6_error(m, ICMP6_DST_UNREACH,
487 ICMP6_DST_UNREACH_ADDR, 0);
488 /* m is already freed */
489 return;
490 }
491
492 ours = 1;
493 deliverifp = m->m_pkthdr.rcvif;
494 goto hbhcheck;
495 }
496#endif
497
498 /*
499 * Multicast check
500 */
501 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
502 struct in6_multi *in6m = 0;
503
504 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
505 /*
506 * See if we belong to the destination multicast group on the
507 * arrival interface.
508 */
509 IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
510 if (in6m)
511 ours = 1;
512 else if (!ip6_mrouter) {
513 ip6stat.ip6s_notmember++;
514 ip6stat.ip6s_cantforward++;
515 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
516 goto bad;
517 }
518 deliverifp = m->m_pkthdr.rcvif;
519 goto hbhcheck;
520 }
521
522 /*
523 * Unicast check
524 */
525 switch (ip6_ours_check_algorithm) {
526 default:
527 /*
528 * XXX: I intentionally broke our indentation rule here,
529 * since this switch-case is just for measurement and
530 * therefore should soon be removed.
531 */
532 if (ip6_forward_rt.ro_rt != NULL &&
533 (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
534 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
535 &((struct sockaddr_in6 *)(&ip6_forward_rt.ro_dst))->sin6_addr))
536 ip6stat.ip6s_forward_cachehit++;
537 else {
538 struct sockaddr_in6 *dst6;
539
540 if (ip6_forward_rt.ro_rt) {
541 /* route is down or destination is different */
542 ip6stat.ip6s_forward_cachemiss++;
543 RTFREE(ip6_forward_rt.ro_rt);
544 ip6_forward_rt.ro_rt = 0;
545 }
546
547 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
548 dst6 = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
549 dst6->sin6_len = sizeof(struct sockaddr_in6);
550 dst6->sin6_family = AF_INET6;
551 dst6->sin6_addr = ip6->ip6_dst;
552#ifdef SCOPEDROUTING
553 ip6_forward_rt.ro_dst.sin6_scope_id =
554 in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst);
555#endif
556
557 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
558 }
559
560#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
561
562 /*
563 * Accept the packet if the forwarding interface to the destination
564 * according to the routing table is the loopback interface,
565 * unless the associated route has a gateway.
566 * Note that this approach causes to accept a packet if there is a
567 * route to the loopback interface for the destination of the packet.
568 * But we think it's even useful in some situations, e.g. when using
569 * a special daemon which wants to intercept the packet.
570 *
571 * XXX: some OSes automatically make a cloned route for the destination
572 * of an outgoing packet. If the outgoing interface of the packet
573 * is a loopback one, the kernel would consider the packet to be
574 * accepted, even if we have no such address assinged on the interface.
575 * We check the cloned flag of the route entry to reject such cases,
576 * assuming that route entries for our own addresses are not made by
577 * cloning (it should be true because in6_addloop explicitly installs
578 * the host route). However, we might have to do an explicit check
579 * while it would be less efficient. Or, should we rather install a
580 * reject route for such a case?
581 */
582 if (ip6_forward_rt.ro_rt &&
583 (ip6_forward_rt.ro_rt->rt_flags &
584 (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
585#ifdef RTF_WASCLONED
586 !(ip6_forward_rt.ro_rt->rt_flags & RTF_WASCLONED) &&
587#endif
588#ifdef RTF_CLONED
589 !(ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
590#endif
591#if 0
592 /*
593 * The check below is redundant since the comparison of
594 * the destination and the key of the rtentry has
595 * already done through looking up the routing table.
596 */
597 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
598 &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr)
599#endif
600 ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
601 struct in6_ifaddr *ia6 =
602 (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
603
604 /*
605 * record address information into m_aux.
606 */
607 (void)ip6_setdstifaddr(m, ia6);
608
609 /*
610 * packets to a tentative, duplicated, or somehow invalid
611 * address must not be accepted.
612 */
613 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
614 /* this address is ready */
615 ours = 1;
616 deliverifp = ia6->ia_ifp; /* correct? */
617 /* Count the packet in the ip address stats */
618 ia6->ia_ifa.if_ipackets++;
619 ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
620 goto hbhcheck;
621 } else {
622 /* address is not ready, so discard the packet. */
623 nd6log((LOG_INFO,
624 "ip6_input: packet to an unready address %s->%s\n",
625 ip6_sprintf(&ip6->ip6_src),
626 ip6_sprintf(&ip6->ip6_dst)));
627
628 goto bad;
629 }
630 }
631 } /* XXX indentation (see above) */
632
633 /*
634 * FAITH(Firewall Aided Internet Translator)
635 */
636#if defined(NFAITH) && 0 < NFAITH
637 if (ip6_keepfaith) {
638 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
639 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
640 /* XXX do we need more sanity checks? */
641 ours = 1;
642 deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/
643 goto hbhcheck;
644 }
645 }
646#endif
647
648 /*
649 * Now there is no reason to process the packet if it's not our own
650 * and we're not a router.
651 */
652 if (!ip6_forwarding) {
653 ip6stat.ip6s_cantforward++;
654 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
655 goto bad;
656 }
657
658 hbhcheck:
659 /*
660 * record address information into m_aux, if we don't have one yet.
661 * note that we are unable to record it, if the address is not listed
662 * as our interface address (e.g. multicast addresses, addresses
663 * within FAITH prefixes and such).
664 */
665 if (deliverifp && !ip6_getdstifaddr(m)) {
666 struct in6_ifaddr *ia6;
667
668 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
669 if (ia6) {
670 if (!ip6_setdstifaddr(m, ia6)) {
671 /*
672 * XXX maybe we should drop the packet here,
673 * as we could not provide enough information
674 * to the upper layers.
675 */
676 }
677 }
678 }
679
680 /*
681 * Process Hop-by-Hop options header if it's contained.
682 * m may be modified in ip6_hopopts_input().
683 * If a JumboPayload option is included, plen will also be modified.
684 */
685 plen = (u_int32_t)ntohs(ip6->ip6_plen);
686 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
687 struct ip6_hbh *hbh;
688
689 if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
690#if 0 /*touches NULL pointer*/
691 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
692#endif
693 return; /* m have already been freed */
694 }
695
696 /* adjust pointer */
697 ip6 = mtod(m, struct ip6_hdr *);
698
699 /*
700 * if the payload length field is 0 and the next header field
701 * indicates Hop-by-Hop Options header, then a Jumbo Payload
702 * option MUST be included.
703 */
704 if (ip6->ip6_plen == 0 && plen == 0) {
705 /*
706 * Note that if a valid jumbo payload option is
707 * contained, ip6_hoptops_input() must set a valid
708 * (non-zero) payload length to the variable plen.
709 */
710 ip6stat.ip6s_badoptions++;
711 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
712 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
713 icmp6_error(m, ICMP6_PARAM_PROB,
714 ICMP6_PARAMPROB_HEADER,
715 (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
716 return;
717 }
718#ifndef PULLDOWN_TEST
719 /* ip6_hopopts_input() ensures that mbuf is contiguous */
720 hbh = (struct ip6_hbh *)(ip6 + 1);
721#else
722 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
723 sizeof(struct ip6_hbh));
724 if (hbh == NULL) {
725 ip6stat.ip6s_tooshort++;
726 return;
727 }
728#endif
729 nxt = hbh->ip6h_nxt;
730
731 /*
732 * accept the packet if a router alert option is included
733 * and we act as an IPv6 router.
734 */
735 if (rtalert != ~0 && ip6_forwarding)
736 ours = 1;
737 } else
738 nxt = ip6->ip6_nxt;
739
740 /*
741 * Check that the amount of data in the buffers
742 * is as at least much as the IPv6 header would have us expect.
743 * Trim mbufs if longer than we expect.
744 * Drop packet if shorter than we expect.
745 */
746 if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
747 ip6stat.ip6s_tooshort++;
748 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
749 goto bad;
750 }
751 if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
752 if (m->m_len == m->m_pkthdr.len) {
753 m->m_len = sizeof(struct ip6_hdr) + plen;
754 m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
755 } else
756 m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
757 }
758
759 /*
760 * Forward if desirable.
761 */
762 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
763 /*
764 * If we are acting as a multicast router, all
765 * incoming multicast packets are passed to the
766 * kernel-level multicast forwarding function.
767 * The packet is returned (relatively) intact; if
768 * ip6_mforward() returns a non-zero value, the packet
769 * must be discarded, else it may be accepted below.
770 */
771 if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
772 ip6stat.ip6s_cantforward++;
773 m_freem(m);
774 return;
775 }
776 if (!ours) {
777 m_freem(m);
778 return;
779 }
780 } else if (!ours) {
781 ip6_forward(m, 0);
782 return;
783 }
784
785 ip6 = mtod(m, struct ip6_hdr *);
786
787 /*
788 * Malicious party may be able to use IPv4 mapped addr to confuse
789 * tcp/udp stack and bypass security checks (act as if it was from
790 * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious.
791 *
792 * For SIIT end node behavior, you may want to disable the check.
793 * However, you will become vulnerable to attacks using IPv4 mapped
794 * source.
795 */
796 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
797 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
798 ip6stat.ip6s_badscope++;
799 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
800 goto bad;
801 }
802
803 /*
804 * Tell launch routine the next header
805 */
806 ip6stat.ip6s_delivered++;
807 in6_ifstat_inc(deliverifp, ifs6_in_deliver);
808 nest = 0;
809
810 while (nxt != IPPROTO_DONE) {
811 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
812 ip6stat.ip6s_toomanyhdr++;
813 goto bad;
814 }
815
816 /*
817 * protection against faulty packet - there should be
818 * more sanity checks in header chain processing.
819 */
820 if (m->m_pkthdr.len < off) {
821 ip6stat.ip6s_tooshort++;
822 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
823 goto bad;
824 }
825
826#if 0
827 /*
828 * do we need to do it for every header? yeah, other
829 * functions can play with it (like re-allocate and copy).
830 */
831 mhist = ip6_addaux(m);
832 if (mhist && M_TRAILINGSPACE(mhist) >= sizeof(nxt)) {
833 hist = mtod(mhist, caddr_t) + mhist->m_len;
834 bcopy(&nxt, hist, sizeof(nxt));
835 mhist->m_len += sizeof(nxt);
836 } else {
837 ip6stat.ip6s_toomanyhdr++;
838 goto bad;
839 }
840#endif
841
842#ifdef IPSEC
843 /*
844 * enforce IPsec policy checking if we are seeing last header.
845 * note that we do not visit this with protocols with pcb layer
846 * code - like udp/tcp/raw ip.
847 */
848 if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
849 ipsec6_in_reject(m, NULL)) {
850 ipsec6stat.in_polvio++;
851 goto bad;
852 }
853#endif
854
855 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
856 }
857 return;
858 bad:
859 m_freem(m);
860}
861
862/*
863 * set/grab in6_ifaddr correspond to IPv6 destination address.
864 * XXX backward compatibility wrapper
865 */
866static struct mbuf *
867ip6_setdstifaddr(m, ia6)
868 struct mbuf *m;
869 struct in6_ifaddr *ia6;
870{
871 struct mbuf *n;
872
873 n = ip6_addaux(m);
874 if (n)
875 mtod(n, struct ip6aux *)->ip6a_dstia6 = ia6;
876 return n; /* NULL if failed to set */
877}
878
879struct in6_ifaddr *
880ip6_getdstifaddr(m)
881 struct mbuf *m;
882{
883 struct mbuf *n;
884
885 n = ip6_findaux(m);
886 if (n)
887 return mtod(n, struct ip6aux *)->ip6a_dstia6;
888 else
889 return NULL;
890}
891
892/*
893 * Hop-by-Hop options header processing. If a valid jumbo payload option is
894 * included, the real payload length will be stored in plenp.
895 */
896static int
897ip6_hopopts_input(plenp, rtalertp, mp, offp)
898 u_int32_t *plenp;
899 u_int32_t *rtalertp; /* XXX: should be stored more smart way */
900 struct mbuf **mp;
901 int *offp;
902{
903 struct mbuf *m = *mp;
904 int off = *offp, hbhlen;
905 struct ip6_hbh *hbh;
906 u_int8_t *opt;
907
908 /* validation of the length of the header */
909#ifndef PULLDOWN_TEST
910 IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
911 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
912 hbhlen = (hbh->ip6h_len + 1) << 3;
913
914 IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
915 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
916#else
917 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
918 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
919 if (hbh == NULL) {
920 ip6stat.ip6s_tooshort++;
921 return -1;
922 }
923 hbhlen = (hbh->ip6h_len + 1) << 3;
924 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
925 hbhlen);
926 if (hbh == NULL) {
927 ip6stat.ip6s_tooshort++;
928 return -1;
929 }
930#endif
931 off += hbhlen;
932 hbhlen -= sizeof(struct ip6_hbh);
933 opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
934
935 if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
936 hbhlen, rtalertp, plenp) < 0)
937 return(-1);
938
939 *offp = off;
940 *mp = m;
941 return(0);
942}
943
944/*
945 * Search header for all Hop-by-hop options and process each option.
946 * This function is separate from ip6_hopopts_input() in order to
947 * handle a case where the sending node itself process its hop-by-hop
948 * options header. In such a case, the function is called from ip6_output().
949 *
950 * The function assumes that hbh header is located right after the IPv6 header
951 * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
952 * opthead + hbhlen is located in continuous memory region.
953 */
954int
955ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
956 struct mbuf *m;
957 u_int8_t *opthead;
958 int hbhlen;
959 u_int32_t *rtalertp;
960 u_int32_t *plenp;
961{
962 struct ip6_hdr *ip6;
963 int optlen = 0;
964 u_int8_t *opt = opthead;
965 u_int16_t rtalert_val;
966 u_int32_t jumboplen;
967 const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
968
969 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
970 switch (*opt) {
971 case IP6OPT_PAD1:
972 optlen = 1;
973 break;
974 case IP6OPT_PADN:
975 if (hbhlen < IP6OPT_MINLEN) {
976 ip6stat.ip6s_toosmall++;
977 goto bad;
978 }
979 optlen = *(opt + 1) + 2;
980 break;
981 case IP6OPT_RTALERT:
982 /* XXX may need check for alignment */
983 if (hbhlen < IP6OPT_RTALERT_LEN) {
984 ip6stat.ip6s_toosmall++;
985 goto bad;
986 }
987 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
988 /* XXX stat */
989 icmp6_error(m, ICMP6_PARAM_PROB,
990 ICMP6_PARAMPROB_HEADER,
991 erroff + opt + 1 - opthead);
992 return(-1);
993 }
994 optlen = IP6OPT_RTALERT_LEN;
995 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
996 *rtalertp = ntohs(rtalert_val);
997 break;
998 case IP6OPT_JUMBO:
999 /* XXX may need check for alignment */
1000 if (hbhlen < IP6OPT_JUMBO_LEN) {
1001 ip6stat.ip6s_toosmall++;
1002 goto bad;
1003 }
1004 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
1005 /* XXX stat */
1006 icmp6_error(m, ICMP6_PARAM_PROB,
1007 ICMP6_PARAMPROB_HEADER,
1008 erroff + opt + 1 - opthead);
1009 return(-1);
1010 }
1011 optlen = IP6OPT_JUMBO_LEN;
1012
1013 /*
1014 * IPv6 packets that have non 0 payload length
1015 * must not contain a jumbo payload option.
1016 */
1017 ip6 = mtod(m, struct ip6_hdr *);
1018 if (ip6->ip6_plen) {
1019 ip6stat.ip6s_badoptions++;
1020 icmp6_error(m, ICMP6_PARAM_PROB,
1021 ICMP6_PARAMPROB_HEADER,
1022 erroff + opt - opthead);
1023 return(-1);
1024 }
1025
1026 /*
1027 * We may see jumbolen in unaligned location, so
1028 * we'd need to perform bcopy().
1029 */
1030 bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
1031 jumboplen = (u_int32_t)htonl(jumboplen);
1032
1033#if 1
1034 /*
1035 * if there are multiple jumbo payload options,
1036 * *plenp will be non-zero and the packet will be
1037 * rejected.
1038 * the behavior may need some debate in ipngwg -
1039 * multiple options does not make sense, however,
1040 * there's no explicit mention in specification.
1041 */
1042 if (*plenp != 0) {
1043 ip6stat.ip6s_badoptions++;
1044 icmp6_error(m, ICMP6_PARAM_PROB,
1045 ICMP6_PARAMPROB_HEADER,
1046 erroff + opt + 2 - opthead);
1047 return(-1);
1048 }
1049#endif
1050
1051 /*
1052 * jumbo payload length must be larger than 65535.
1053 */
1054 if (jumboplen <= IPV6_MAXPACKET) {
1055 ip6stat.ip6s_badoptions++;
1056 icmp6_error(m, ICMP6_PARAM_PROB,
1057 ICMP6_PARAMPROB_HEADER,
1058 erroff + opt + 2 - opthead);
1059 return(-1);
1060 }
1061 *plenp = jumboplen;
1062
1063 break;
1064 default: /* unknown option */
1065 if (hbhlen < IP6OPT_MINLEN) {
1066 ip6stat.ip6s_toosmall++;
1067 goto bad;
1068 }
1069 optlen = ip6_unknown_opt(opt, m,
1070 erroff + opt - opthead);
1071 if (optlen == -1)
1072 return(-1);
1073 optlen += 2;
1074 break;
1075 }
1076 }
1077
1078 return(0);
1079
1080 bad:
1081 m_freem(m);
1082 return(-1);
1083}
1084
1085/*
1086 * Unknown option processing.
1087 * The third argument `off' is the offset from the IPv6 header to the option,
1088 * which is necessary if the IPv6 header the and option header and IPv6 header
1089 * is not continuous in order to return an ICMPv6 error.
1090 */
1091int
1092ip6_unknown_opt(optp, m, off)
1093 u_int8_t *optp;
1094 struct mbuf *m;
1095 int off;
1096{
1097 struct ip6_hdr *ip6;
1098
1099 switch (IP6OPT_TYPE(*optp)) {
1100 case IP6OPT_TYPE_SKIP: /* ignore the option */
1101 return((int)*(optp + 1));
1102 case IP6OPT_TYPE_DISCARD: /* silently discard */
1103 m_freem(m);
1104 return(-1);
1105 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
1106 ip6stat.ip6s_badoptions++;
1107 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
1108 return(-1);
1109 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
1110 ip6stat.ip6s_badoptions++;
1111 ip6 = mtod(m, struct ip6_hdr *);
1112 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
1113 (m->m_flags & (M_BCAST|M_MCAST)))
1114 m_freem(m);
1115 else
1116 icmp6_error(m, ICMP6_PARAM_PROB,
1117 ICMP6_PARAMPROB_OPTION, off);
1118 return(-1);
1119 }
1120
1121 m_freem(m); /* XXX: NOTREACHED */
1122 return(-1);
1123}
1124
1125/*
1126 * Create the "control" list for this pcb.
1127 * The function will not modify mbuf chain at all.
1128 *
1129 * with KAME mbuf chain restriction:
1130 * The routine will be called from upper layer handlers like tcp6_input().
1131 * Thus the routine assumes that the caller (tcp6_input) have already
1132 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
1133 * very first mbuf on the mbuf chain.
1134 */
1135void
1136ip6_savecontrol(in6p, mp, ip6, m)
1137 struct inpcb *in6p;
1138 struct mbuf **mp;
1139 struct ip6_hdr *ip6;
1140 struct mbuf *m;
1141{
1142 struct proc *p = curproc; /* XXX */
1143 int privileged = 0;
1144 int rthdr_exist = 0;
1145
1146
1147 if (p && !suser(p))
1148 privileged++;
1149
1150#ifdef SO_TIMESTAMP
1151 if ((in6p->in6p_socket->so_options & SO_TIMESTAMP) != 0) {
1152 struct timeval tv;
1153
1154 microtime(&tv);
1155 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1156 SCM_TIMESTAMP, SOL_SOCKET);
1157 if (*mp) {
1158 mp = &(*mp)->m_next;
1159 }
1160 }
1161#endif
1162
1163 /* RFC 2292 sec. 5 */
1164 if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) {
1165 struct in6_pktinfo pi6;
1166 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1167 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
1168 pi6.ipi6_addr.s6_addr16[1] = 0;
1169 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
1170 ? m->m_pkthdr.rcvif->if_index
1171 : 0;
1172 *mp = sbcreatecontrol((caddr_t) &pi6,
1173 sizeof(struct in6_pktinfo), IPV6_PKTINFO,
1174 IPPROTO_IPV6);
1175 if (*mp)
1176 mp = &(*mp)->m_next;
1177 }
1178
1179 if ((in6p->in6p_flags & IN6P_HOPLIMIT) != 0) {
1180 int hlim = ip6->ip6_hlim & 0xff;
1181 *mp = sbcreatecontrol((caddr_t) &hlim,
1182 sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
1183 if (*mp)
1184 mp = &(*mp)->m_next;
1185 }
1186
1187 /*
1188 * IPV6_HOPOPTS socket option. We require super-user privilege
1189 * for the option, but it might be too strict, since there might
1190 * be some hop-by-hop options which can be returned to normal user.
1191 * See RFC 2292 section 6.
1192 */
1193 if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0 && privileged) {
1194 /*
1195 * Check if a hop-by-hop options header is contatined in the
1196 * received packet, and if so, store the options as ancillary
1197 * data. Note that a hop-by-hop options header must be
1198 * just after the IPv6 header, which fact is assured through
1199 * the IPv6 input processing.
1200 */
1201 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1202 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1203 struct ip6_hbh *hbh;
1204 int hbhlen = 0;
1205#ifdef PULLDOWN_TEST
1206 struct mbuf *ext;
1207#endif
1208
1209#ifndef PULLDOWN_TEST
1210 hbh = (struct ip6_hbh *)(ip6 + 1);
1211 hbhlen = (hbh->ip6h_len + 1) << 3;
1212#else
1213 ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
1214 ip6->ip6_nxt);
1215 if (ext == NULL) {
1216 ip6stat.ip6s_tooshort++;
1217 return;
1218 }
1219 hbh = mtod(ext, struct ip6_hbh *);
1220 hbhlen = (hbh->ip6h_len + 1) << 3;
1221 if (hbhlen != ext->m_len) {
1222 m_freem(ext);
1223 ip6stat.ip6s_tooshort++;
1224 return;
1225 }
1226#endif
1227
1228 /*
1229 * XXX: We copy whole the header even if a jumbo
1230 * payload option is included, which option is to
1231 * be removed before returning in the RFC 2292.
1232 * Note: this constraint is removed in 2292bis.
1233 */
1234 *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1235 IPV6_HOPOPTS, IPPROTO_IPV6);
1236 if (*mp)
1237 mp = &(*mp)->m_next;
1238#ifdef PULLDOWN_TEST
1239 m_freem(ext);
1240#endif
1241 }
1242 }
1243
1244 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
1245 if ((in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
1246 int proto, off, nxt;
1247
1248 /*
1249 * go through the header chain to see if a routing header is
1250 * contained in the packet. We need this information to store
1251 * destination options headers (if any) properly.
1252 * XXX: performance issue. We should record this info when
1253 * processing extension headers in incoming routine.
1254 * (todo) use m_aux?
1255 */
1256 proto = IPPROTO_IPV6;
1257 off = 0;
1258 nxt = -1;
1259 while (1) {
1260 int newoff;
1261
1262 newoff = ip6_nexthdr(m, off, proto, &nxt);
1263 if (newoff < 0)
1264 break;
1265 if (newoff < off) /* invalid, check for safety */
1266 break;
1267 if ((proto = nxt) == IPPROTO_ROUTING) {
1268 rthdr_exist = 1;
1269 break;
1270 }
1271 off = newoff;
1272 }
1273 }
1274
1275 if ((in6p->in6p_flags &
1276 (IN6P_RTHDR | IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
1277 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1278 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
1279
1280 /*
1281 * Search for destination options headers or routing
1282 * header(s) through the header chain, and stores each
1283 * header as ancillary data.
1284 * Note that the order of the headers remains in
1285 * the chain of ancillary data.
1286 */
1287 while (1) { /* is explicit loop prevention necessary? */
1288 struct ip6_ext *ip6e = NULL;
1289 int elen;
1290#ifdef PULLDOWN_TEST
1291 struct mbuf *ext = NULL;
1292#endif
1293
1294 /*
1295 * if it is not an extension header, don't try to
1296 * pull it from the chain.
1297 */
1298 switch (nxt) {
1299 case IPPROTO_DSTOPTS:
1300 case IPPROTO_ROUTING:
1301 case IPPROTO_HOPOPTS:
1302 case IPPROTO_AH: /* is it possible? */
1303 break;
1304 default:
1305 goto loopend;
1306 }
1307
1308#ifndef PULLDOWN_TEST
1309 if (off + sizeof(*ip6e) > m->m_len)
1310 goto loopend;
1311 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1312 if (nxt == IPPROTO_AH)
1313 elen = (ip6e->ip6e_len + 2) << 2;
1314 else
1315 elen = (ip6e->ip6e_len + 1) << 3;
1316 if (off + elen > m->m_len)
1317 goto loopend;
1318#else
1319 ext = ip6_pullexthdr(m, off, nxt);
1320 if (ext == NULL) {
1321 ip6stat.ip6s_tooshort++;
1322 return;
1323 }
1324 ip6e = mtod(ext, struct ip6_ext *);
1325 if (nxt == IPPROTO_AH)
1326 elen = (ip6e->ip6e_len + 2) << 2;
1327 else
1328 elen = (ip6e->ip6e_len + 1) << 3;
1329 if (elen != ext->m_len) {
1330 m_freem(ext);
1331 ip6stat.ip6s_tooshort++;
1332 return;
1333 }
1334#endif
1335
1336 switch (nxt) {
1337 case IPPROTO_DSTOPTS:
1338 if ((in6p->in6p_flags & IN6P_DSTOPTS) == 0)
1339 break;
1340
1341 /*
1342 * We also require super-user privilege for
1343 * the option.
1344 * See the comments on IN6_HOPOPTS.
1345 */
1346 if (!privileged)
1347 break;
1348
1349 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1350 IPV6_DSTOPTS,
1351 IPPROTO_IPV6);
1352 if (*mp)
1353 mp = &(*mp)->m_next;
1354 break;
1355 case IPPROTO_ROUTING:
1356 if (!in6p->in6p_flags & IN6P_RTHDR)
1357 break;
1358
1359 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1360 IPV6_RTHDR,
1361 IPPROTO_IPV6);
1362 if (*mp)
1363 mp = &(*mp)->m_next;
1364 break;
1365 case IPPROTO_HOPOPTS:
1366 case IPPROTO_AH: /* is it possible? */
1367 break;
1368
1369 default:
1370 /*
1371 * other cases have been filtered in the above.
1372 * none will visit this case. here we supply
1373 * the code just in case (nxt overwritten or
1374 * other cases).
1375 */
1376#ifdef PULLDOWN_TEST
1377 m_freem(ext);
1378#endif
1379 goto loopend;
1380
1381 }
1382
1383 /* proceed with the next header. */
1384 off += elen;
1385 nxt = ip6e->ip6e_nxt;
1386 ip6e = NULL;
1387#ifdef PULLDOWN_TEST
1388 m_freem(ext);
1389 ext = NULL;
1390#endif
1391 }
1392 loopend:
1393 ;
1394 }
1395
1396}
1397
1398#ifdef PULLDOWN_TEST
1399/*
1400 * pull single extension header from mbuf chain. returns single mbuf that
1401 * contains the result, or NULL on error.
1402 */
1403static struct mbuf *
1404ip6_pullexthdr(m, off, nxt)
1405 struct mbuf *m;
1406 size_t off;
1407 int nxt;
1408{
1409 struct ip6_ext ip6e;
1410 size_t elen;
1411 struct mbuf *n;
1412
1413#ifdef DIAGNOSTIC
1414 switch (nxt) {
1415 case IPPROTO_DSTOPTS:
1416 case IPPROTO_ROUTING:
1417 case IPPROTO_HOPOPTS:
1418 case IPPROTO_AH: /* is it possible? */
1419 break;
1420 default:
1421 printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
1422 }
1423#endif
1424
1425 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1426 if (nxt == IPPROTO_AH)
1427 elen = (ip6e.ip6e_len + 2) << 2;
1428 else
1429 elen = (ip6e.ip6e_len + 1) << 3;
1430
1431 MGET(n, M_DONTWAIT, MT_DATA);
1432 if (n && elen >= MLEN) {
1433 MCLGET(n, M_DONTWAIT);
1434 if ((n->m_flags & M_EXT) == 0) {
1435 m_free(n);
1436 n = NULL;
1437 }
1438 }
1439 if (!n)
1440 return NULL;
1441
1442 n->m_len = 0;
1443 if (elen >= M_TRAILINGSPACE(n)) {
1444 m_free(n);
1445 return NULL;
1446 }
1447
1448 m_copydata(m, off, elen, mtod(n, caddr_t));
1449 n->m_len = elen;
1450 return n;
1451}
1452#endif
1453
1454/*
1455 * Get pointer to the previous header followed by the header
1456 * currently processed.
1457 * XXX: This function supposes that
1458 * M includes all headers,
1459 * the next header field and the header length field of each header
1460 * are valid, and
1461 * the sum of each header length equals to OFF.
1462 * Because of these assumptions, this function must be called very
1463 * carefully. Moreover, it will not be used in the near future when
1464 * we develop `neater' mechanism to process extension headers.
1465 */
1466char *
1467ip6_get_prevhdr(m, off)
1468 struct mbuf *m;
1469 int off;
1470{
1471 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1472
1473 if (off == sizeof(struct ip6_hdr))
1474 return(&ip6->ip6_nxt);
1475 else {
1476 int len, nxt;
1477 struct ip6_ext *ip6e = NULL;
1478
1479 nxt = ip6->ip6_nxt;
1480 len = sizeof(struct ip6_hdr);
1481 while (len < off) {
1482 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1483
1484 switch (nxt) {
1485 case IPPROTO_FRAGMENT:
1486 len += sizeof(struct ip6_frag);
1487 break;
1488 case IPPROTO_AH:
1489 len += (ip6e->ip6e_len + 2) << 2;
1490 break;
1491 default:
1492 len += (ip6e->ip6e_len + 1) << 3;
1493 break;
1494 }
1495 nxt = ip6e->ip6e_nxt;
1496 }
1497 if (ip6e)
1498 return(&ip6e->ip6e_nxt);
1499 else
1500 return NULL;
1501 }
1502}
1503
1504/*
1505 * get next header offset. m will be retained.
1506 */
1507int
1508ip6_nexthdr(m, off, proto, nxtp)
1509 struct mbuf *m;
1510 int off;
1511 int proto;
1512 int *nxtp;
1513{
1514 struct ip6_hdr ip6;
1515 struct ip6_ext ip6e;
1516 struct ip6_frag fh;
1517
1518 /* just in case */
1519 if (m == NULL)
1520 panic("ip6_nexthdr: m == NULL");
1521 if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
1522 return -1;
1523
1524 switch (proto) {
1525 case IPPROTO_IPV6:
1526 if (m->m_pkthdr.len < off + sizeof(ip6))
1527 return -1;
1528 m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
1529 if (nxtp)
1530 *nxtp = ip6.ip6_nxt;
1531 off += sizeof(ip6);
1532 return off;
1533
1534 case IPPROTO_FRAGMENT:
1535 /*
1536 * terminate parsing if it is not the first fragment,
1537 * it does not make sense to parse through it.
1538 */
1539 if (m->m_pkthdr.len < off + sizeof(fh))
1540 return -1;
1541 m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
1542 if ((ntohs(fh.ip6f_offlg) & IP6F_OFF_MASK) != 0)
1543 return -1;
1544 if (nxtp)
1545 *nxtp = fh.ip6f_nxt;
1546 off += sizeof(struct ip6_frag);
1547 return off;
1548
1549 case IPPROTO_AH:
1550 if (m->m_pkthdr.len < off + sizeof(ip6e))
1551 return -1;
1552 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1553 if (nxtp)
1554 *nxtp = ip6e.ip6e_nxt;
1555 off += (ip6e.ip6e_len + 2) << 2;
1556 return off;
1557
1558 case IPPROTO_HOPOPTS:
1559 case IPPROTO_ROUTING:
1560 case IPPROTO_DSTOPTS:
1561 if (m->m_pkthdr.len < off + sizeof(ip6e))
1562 return -1;
1563 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1564 if (nxtp)
1565 *nxtp = ip6e.ip6e_nxt;
1566 off += (ip6e.ip6e_len + 1) << 3;
1567 return off;
1568
1569 case IPPROTO_NONE:
1570 case IPPROTO_ESP:
1571 case IPPROTO_IPCOMP:
1572 /* give up */
1573 return -1;
1574
1575 default:
1576 return -1;
1577 }
1578
1579 return -1;
1580}
1581
1582/*
1583 * get offset for the last header in the chain. m will be kept untainted.
1584 */
1585int
1586ip6_lasthdr(m, off, proto, nxtp)
1587 struct mbuf *m;
1588 int off;
1589 int proto;
1590 int *nxtp;
1591{
1592 int newoff;
1593 int nxt;
1594
1595 if (!nxtp) {
1596 nxt = -1;
1597 nxtp = &nxt;
1598 }
1599 while (1) {
1600 newoff = ip6_nexthdr(m, off, proto, nxtp);
1601 if (newoff < 0)
1602 return off;
1603 else if (newoff < off)
1604 return -1; /* invalid */
1605 else if (newoff == off)
1606 return newoff;
1607
1608 off = newoff;
1609 proto = *nxtp;
1610 }
1611}
1612
1613struct mbuf *
1614ip6_addaux(m)
1615 struct mbuf *m;
1616{
1617 struct mbuf *n;
1618
1619#ifdef DIAGNOSTIC
1620 if (sizeof(struct ip6aux) > MHLEN)
1621 panic("assumption failed on sizeof(ip6aux)");
1622#endif
1623 n = m_aux_find(m, AF_INET6, -1);
1624 if (n) {
1625 if (n->m_len < sizeof(struct ip6aux)) {
1626 printf("conflicting use of ip6aux");
1627 return NULL;
1628 }
1629 } else {
1630 n = m_aux_add(m, AF_INET6, -1);
1631 n->m_len = sizeof(struct ip6aux);
1632 bzero(mtod(n, caddr_t), n->m_len);
1633 }
1634 return n;
1635}
1636
1637struct mbuf *
1638ip6_findaux(m)
1639 struct mbuf *m;
1640{
1641 struct mbuf *n;
1642
1643 n = m_aux_find(m, AF_INET6, -1);
1644 if (n && n->m_len < sizeof(struct ip6aux)) {
1645 printf("conflicting use of ip6aux");
1646 n = NULL;
1647 }
1648 return n;
1649}
1650
1651void
1652ip6_delaux(m)
1653 struct mbuf *m;
1654{
1655 struct mbuf *n;
1656
1657 n = m_aux_find(m, AF_INET6, -1);
1658 if (n)
1659 m_aux_delete(m, n);
1660}
1661
1662/*
1663 * System control for IP6
1664 */
1665
1666u_char inet6ctlerrmap[PRC_NCMDS] = {
1667 0, 0, 0, 0,
1668 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1669 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1670 EMSGSIZE, EHOSTUNREACH, 0, 0,
1671 0, 0, 0, 0,
1672 ENOPROTOOPT
1673};
124
125#include <net/net_osdep.h>
126
127extern struct domain inet6domain;
128extern struct ip6protosw inet6sw[];
129
130u_char ip6_protox[IPPROTO_MAX];
131static int ip6qmaxlen = IFQ_MAXLEN;
132struct in6_ifaddr *in6_ifaddr;
133
134extern struct callout in6_tmpaddrtimer_ch;
135
136int ip6_forward_srcrt; /* XXX */
137int ip6_sourcecheck; /* XXX */
138int ip6_sourcecheck_interval; /* XXX */
139const int int6intrq_present = 1;
140
141int ip6_ours_check_algorithm;
142
143
144/* firewall hooks */
145ip6_fw_chk_t *ip6_fw_chk_ptr;
146ip6_fw_ctl_t *ip6_fw_ctl_ptr;
147int ip6_fw_enable = 1;
148
149struct ip6stat ip6stat;
150
151static void ip6_init2 __P((void *));
152static struct mbuf *ip6_setdstifaddr __P((struct mbuf *, struct in6_ifaddr *));
153
154static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
155#ifdef PULLDOWN_TEST
156static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int));
157#endif
158
159
160/*
161 * IP6 initialization: fill in IP6 protocol switch table.
162 * All protocols not implemented in kernel go to raw IP6 protocol handler.
163 */
164void
165ip6_init()
166{
167 struct ip6protosw *pr;
168 int i;
169 struct timeval tv;
170
171#ifdef DIAGNOSTIC
172 if (sizeof(struct protosw) != sizeof(struct ip6protosw))
173 panic("sizeof(protosw) != sizeof(ip6protosw)");
174#endif
175 pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
176 if (pr == 0)
177 panic("ip6_init");
178 for (i = 0; i < IPPROTO_MAX; i++)
179 ip6_protox[i] = pr - inet6sw;
180 for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
181 pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
182 if (pr->pr_domain->dom_family == PF_INET6 &&
183 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
184 ip6_protox[pr->pr_protocol] = pr - inet6sw;
185 ip6intrq.ifq_maxlen = ip6qmaxlen;
186 mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", MTX_DEF);
187 register_netisr(NETISR_IPV6, ip6intr);
188 nd6_init();
189 frag6_init();
190 /*
191 * in many cases, random() here does NOT return random number
192 * as initialization during bootstrap time occur in fixed order.
193 */
194 microtime(&tv);
195 ip6_flow_seq = random() ^ tv.tv_usec;
196 microtime(&tv);
197 ip6_desync_factor = (random() ^ tv.tv_usec) % MAX_TEMP_DESYNC_FACTOR;
198}
199
200static void
201ip6_init2(dummy)
202 void *dummy;
203{
204
205 /*
206 * to route local address of p2p link to loopback,
207 * assign loopback address first.
208 */
209 in6_ifattach(&loif[0], NULL);
210
211 /* nd6_timer_init */
212 callout_init(&nd6_timer_ch, 0);
213 callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL);
214
215 /* router renumbering prefix list maintenance */
216 callout_init(&in6_rr_timer_ch, 0);
217 callout_reset(&in6_rr_timer_ch, hz, in6_rr_timer, NULL);
218
219 /* timer for regeneranation of temporary addresses randomize ID */
220 callout_reset(&in6_tmpaddrtimer_ch,
221 (ip6_temp_preferred_lifetime - ip6_desync_factor -
222 ip6_temp_regen_advance) * hz,
223 in6_tmpaddrtimer, NULL);
224}
225
226/* cheat */
227/* This must be after route_init(), which is now SI_ORDER_THIRD */
228SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
229
230/*
231 * IP6 input interrupt handling. Just pass the packet to ip6_input.
232 */
233void
234ip6intr()
235{
236 int s;
237 struct mbuf *m;
238
239 for (;;) {
240 s = splimp();
241 IF_DEQUEUE(&ip6intrq, m);
242 splx(s);
243 if (m == 0)
244 return;
245 ip6_input(m);
246 }
247}
248
249extern struct route_in6 ip6_forward_rt;
250
251void
252ip6_input(m)
253 struct mbuf *m;
254{
255 struct ip6_hdr *ip6;
256 int off = sizeof(struct ip6_hdr), nest;
257 u_int32_t plen;
258 u_int32_t rtalert = ~0;
259 int nxt, ours = 0;
260 struct ifnet *deliverifp = NULL;
261#ifdef PFIL_HOOKS
262 struct packet_filter_hook *pfh;
263 struct mbuf *m0;
264 int rv;
265#endif /* PFIL_HOOKS */
266
267#ifdef IPSEC
268 /*
269 * should the inner packet be considered authentic?
270 * see comment in ah4_input().
271 */
272 if (m) {
273 m->m_flags &= ~M_AUTHIPHDR;
274 m->m_flags &= ~M_AUTHIPDGM;
275 }
276#endif
277
278 /*
279 * make sure we don't have onion peering information into m_aux.
280 */
281 ip6_delaux(m);
282
283 /*
284 * mbuf statistics by kazu
285 */
286 if (m->m_flags & M_EXT) {
287 if (m->m_next)
288 ip6stat.ip6s_mext2m++;
289 else
290 ip6stat.ip6s_mext1++;
291 } else {
292#define M2MMAX (sizeof(ip6stat.ip6s_m2m)/sizeof(ip6stat.ip6s_m2m[0]))
293 if (m->m_next) {
294 if (m->m_flags & M_LOOP) {
295 ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
296 } else if (m->m_pkthdr.rcvif->if_index < M2MMAX)
297 ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
298 else
299 ip6stat.ip6s_m2m[0]++;
300 } else
301 ip6stat.ip6s_m1++;
302#undef M2MMAX
303 }
304
305 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
306 ip6stat.ip6s_total++;
307
308#ifndef PULLDOWN_TEST
309 /*
310 * L2 bridge code and some other code can return mbuf chain
311 * that does not conform to KAME requirement. too bad.
312 * XXX: fails to join if interface MTU > MCLBYTES. jumbogram?
313 */
314 if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
315 struct mbuf *n;
316
317 MGETHDR(n, M_DONTWAIT, MT_HEADER);
318 if (n)
319 M_COPY_PKTHDR(n, m);
320 if (n && m->m_pkthdr.len > MHLEN) {
321 MCLGET(n, M_DONTWAIT);
322 if ((n->m_flags & M_EXT) == 0) {
323 m_freem(n);
324 n = NULL;
325 }
326 }
327 if (!n) {
328 m_freem(m);
329 return; /*ENOBUFS*/
330 }
331
332 m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
333 n->m_len = m->m_pkthdr.len;
334 m_freem(m);
335 m = n;
336 }
337 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
338#endif
339
340 if (m->m_len < sizeof(struct ip6_hdr)) {
341 struct ifnet *inifp;
342 inifp = m->m_pkthdr.rcvif;
343 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
344 ip6stat.ip6s_toosmall++;
345 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
346 return;
347 }
348 }
349
350 ip6 = mtod(m, struct ip6_hdr *);
351
352 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
353 ip6stat.ip6s_badvers++;
354 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
355 goto bad;
356 }
357
358#ifdef PFIL_HOOKS
359 /*
360 * Run through list of hooks for input packets. If there are any
361 * filters which require that additional packets in the flow are
362 * not fast-forwarded, they must clear the M_CANFASTFWD flag.
363 * Note that filters must _never_ set this flag, as another filter
364 * in the list may have previously cleared it.
365 */
366 m0 = m;
367 pfh = pfil_hook_get(PFIL_IN, &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
368 for (; pfh; pfh = pfh->pfil_link.tqe_next)
369 if (pfh->pfil_func) {
370 rv = pfh->pfil_func(ip6, sizeof(*ip6),
371 m->m_pkthdr.rcvif, 0, &m0);
372 if (rv)
373 return;
374 m = m0;
375 if (m == NULL)
376 return;
377 ip6 = mtod(m, struct ip6_hdr *);
378 }
379#endif /* PFIL_HOOKS */
380
381 ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
382
383 /*
384 * Check with the firewall...
385 */
386 if (ip6_fw_enable && ip6_fw_chk_ptr) {
387 u_short port = 0;
388 /* If ipfw says divert, we have to just drop packet */
389 /* use port as a dummy argument */
390 if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
391 m_freem(m);
392 m = NULL;
393 }
394 if (!m)
395 return;
396 }
397
398 /*
399 * Check against address spoofing/corruption.
400 */
401 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
402 IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
403 /*
404 * XXX: "badscope" is not very suitable for a multicast source.
405 */
406 ip6stat.ip6s_badscope++;
407 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
408 goto bad;
409 }
410 if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
411 IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) &&
412 (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
413 ip6stat.ip6s_badscope++;
414 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
415 goto bad;
416 }
417 /*
418 * The following check is not documented in specs. A malicious
419 * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
420 * and bypass security checks (act as if it was from 127.0.0.1 by using
421 * IPv6 src ::ffff:127.0.0.1). Be cautious.
422 *
423 * This check chokes if we are in an SIIT cloud. As none of BSDs
424 * support IPv4-less kernel compilation, we cannot support SIIT
425 * environment at all. So, it makes more sense for us to reject any
426 * malicious packets for non-SIIT environment, than try to do a
427 * partical support for SIIT environment.
428 */
429 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
430 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
431 ip6stat.ip6s_badscope++;
432 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
433 goto bad;
434 }
435#if 0
436 /*
437 * Reject packets with IPv4 compatible addresses (auto tunnel).
438 *
439 * The code forbids auto tunnel relay case in RFC1933 (the check is
440 * stronger than RFC1933). We may want to re-enable it if mech-xx
441 * is revised to forbid relaying case.
442 */
443 if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
444 IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
445 ip6stat.ip6s_badscope++;
446 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
447 goto bad;
448 }
449#endif
450
451 /* drop packets if interface ID portion is already filled */
452 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
453 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src) &&
454 ip6->ip6_src.s6_addr16[1]) {
455 ip6stat.ip6s_badscope++;
456 goto bad;
457 }
458 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst) &&
459 ip6->ip6_dst.s6_addr16[1]) {
460 ip6stat.ip6s_badscope++;
461 goto bad;
462 }
463 }
464
465 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
466 ip6->ip6_src.s6_addr16[1]
467 = htons(m->m_pkthdr.rcvif->if_index);
468 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
469 ip6->ip6_dst.s6_addr16[1]
470 = htons(m->m_pkthdr.rcvif->if_index);
471
472#if 0 /* this case seems to be unnecessary. (jinmei, 20010401) */
473 /*
474 * We use rt->rt_ifp to determine if the address is ours or not.
475 * If rt_ifp is lo0, the address is ours.
476 * The problem here is, rt->rt_ifp for fe80::%lo0/64 is set to lo0,
477 * so any address under fe80::%lo0/64 will be mistakenly considered
478 * local. The special case is supplied to handle the case properly
479 * by actually looking at interface addresses
480 * (using in6ifa_ifpwithaddr).
481 */
482 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0 &&
483 IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
484 if (!in6ifa_ifpwithaddr(m->m_pkthdr.rcvif, &ip6->ip6_dst)) {
485 icmp6_error(m, ICMP6_DST_UNREACH,
486 ICMP6_DST_UNREACH_ADDR, 0);
487 /* m is already freed */
488 return;
489 }
490
491 ours = 1;
492 deliverifp = m->m_pkthdr.rcvif;
493 goto hbhcheck;
494 }
495#endif
496
497 /*
498 * Multicast check
499 */
500 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
501 struct in6_multi *in6m = 0;
502
503 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
504 /*
505 * See if we belong to the destination multicast group on the
506 * arrival interface.
507 */
508 IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
509 if (in6m)
510 ours = 1;
511 else if (!ip6_mrouter) {
512 ip6stat.ip6s_notmember++;
513 ip6stat.ip6s_cantforward++;
514 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
515 goto bad;
516 }
517 deliverifp = m->m_pkthdr.rcvif;
518 goto hbhcheck;
519 }
520
521 /*
522 * Unicast check
523 */
524 switch (ip6_ours_check_algorithm) {
525 default:
526 /*
527 * XXX: I intentionally broke our indentation rule here,
528 * since this switch-case is just for measurement and
529 * therefore should soon be removed.
530 */
531 if (ip6_forward_rt.ro_rt != NULL &&
532 (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
533 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
534 &((struct sockaddr_in6 *)(&ip6_forward_rt.ro_dst))->sin6_addr))
535 ip6stat.ip6s_forward_cachehit++;
536 else {
537 struct sockaddr_in6 *dst6;
538
539 if (ip6_forward_rt.ro_rt) {
540 /* route is down or destination is different */
541 ip6stat.ip6s_forward_cachemiss++;
542 RTFREE(ip6_forward_rt.ro_rt);
543 ip6_forward_rt.ro_rt = 0;
544 }
545
546 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
547 dst6 = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
548 dst6->sin6_len = sizeof(struct sockaddr_in6);
549 dst6->sin6_family = AF_INET6;
550 dst6->sin6_addr = ip6->ip6_dst;
551#ifdef SCOPEDROUTING
552 ip6_forward_rt.ro_dst.sin6_scope_id =
553 in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst);
554#endif
555
556 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
557 }
558
559#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
560
561 /*
562 * Accept the packet if the forwarding interface to the destination
563 * according to the routing table is the loopback interface,
564 * unless the associated route has a gateway.
565 * Note that this approach causes to accept a packet if there is a
566 * route to the loopback interface for the destination of the packet.
567 * But we think it's even useful in some situations, e.g. when using
568 * a special daemon which wants to intercept the packet.
569 *
570 * XXX: some OSes automatically make a cloned route for the destination
571 * of an outgoing packet. If the outgoing interface of the packet
572 * is a loopback one, the kernel would consider the packet to be
573 * accepted, even if we have no such address assinged on the interface.
574 * We check the cloned flag of the route entry to reject such cases,
575 * assuming that route entries for our own addresses are not made by
576 * cloning (it should be true because in6_addloop explicitly installs
577 * the host route). However, we might have to do an explicit check
578 * while it would be less efficient. Or, should we rather install a
579 * reject route for such a case?
580 */
581 if (ip6_forward_rt.ro_rt &&
582 (ip6_forward_rt.ro_rt->rt_flags &
583 (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
584#ifdef RTF_WASCLONED
585 !(ip6_forward_rt.ro_rt->rt_flags & RTF_WASCLONED) &&
586#endif
587#ifdef RTF_CLONED
588 !(ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
589#endif
590#if 0
591 /*
592 * The check below is redundant since the comparison of
593 * the destination and the key of the rtentry has
594 * already done through looking up the routing table.
595 */
596 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
597 &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr)
598#endif
599 ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
600 struct in6_ifaddr *ia6 =
601 (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
602
603 /*
604 * record address information into m_aux.
605 */
606 (void)ip6_setdstifaddr(m, ia6);
607
608 /*
609 * packets to a tentative, duplicated, or somehow invalid
610 * address must not be accepted.
611 */
612 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
613 /* this address is ready */
614 ours = 1;
615 deliverifp = ia6->ia_ifp; /* correct? */
616 /* Count the packet in the ip address stats */
617 ia6->ia_ifa.if_ipackets++;
618 ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
619 goto hbhcheck;
620 } else {
621 /* address is not ready, so discard the packet. */
622 nd6log((LOG_INFO,
623 "ip6_input: packet to an unready address %s->%s\n",
624 ip6_sprintf(&ip6->ip6_src),
625 ip6_sprintf(&ip6->ip6_dst)));
626
627 goto bad;
628 }
629 }
630 } /* XXX indentation (see above) */
631
632 /*
633 * FAITH(Firewall Aided Internet Translator)
634 */
635#if defined(NFAITH) && 0 < NFAITH
636 if (ip6_keepfaith) {
637 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
638 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
639 /* XXX do we need more sanity checks? */
640 ours = 1;
641 deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/
642 goto hbhcheck;
643 }
644 }
645#endif
646
647 /*
648 * Now there is no reason to process the packet if it's not our own
649 * and we're not a router.
650 */
651 if (!ip6_forwarding) {
652 ip6stat.ip6s_cantforward++;
653 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
654 goto bad;
655 }
656
657 hbhcheck:
658 /*
659 * record address information into m_aux, if we don't have one yet.
660 * note that we are unable to record it, if the address is not listed
661 * as our interface address (e.g. multicast addresses, addresses
662 * within FAITH prefixes and such).
663 */
664 if (deliverifp && !ip6_getdstifaddr(m)) {
665 struct in6_ifaddr *ia6;
666
667 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
668 if (ia6) {
669 if (!ip6_setdstifaddr(m, ia6)) {
670 /*
671 * XXX maybe we should drop the packet here,
672 * as we could not provide enough information
673 * to the upper layers.
674 */
675 }
676 }
677 }
678
679 /*
680 * Process Hop-by-Hop options header if it's contained.
681 * m may be modified in ip6_hopopts_input().
682 * If a JumboPayload option is included, plen will also be modified.
683 */
684 plen = (u_int32_t)ntohs(ip6->ip6_plen);
685 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
686 struct ip6_hbh *hbh;
687
688 if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
689#if 0 /*touches NULL pointer*/
690 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
691#endif
692 return; /* m have already been freed */
693 }
694
695 /* adjust pointer */
696 ip6 = mtod(m, struct ip6_hdr *);
697
698 /*
699 * if the payload length field is 0 and the next header field
700 * indicates Hop-by-Hop Options header, then a Jumbo Payload
701 * option MUST be included.
702 */
703 if (ip6->ip6_plen == 0 && plen == 0) {
704 /*
705 * Note that if a valid jumbo payload option is
706 * contained, ip6_hoptops_input() must set a valid
707 * (non-zero) payload length to the variable plen.
708 */
709 ip6stat.ip6s_badoptions++;
710 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
711 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
712 icmp6_error(m, ICMP6_PARAM_PROB,
713 ICMP6_PARAMPROB_HEADER,
714 (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
715 return;
716 }
717#ifndef PULLDOWN_TEST
718 /* ip6_hopopts_input() ensures that mbuf is contiguous */
719 hbh = (struct ip6_hbh *)(ip6 + 1);
720#else
721 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
722 sizeof(struct ip6_hbh));
723 if (hbh == NULL) {
724 ip6stat.ip6s_tooshort++;
725 return;
726 }
727#endif
728 nxt = hbh->ip6h_nxt;
729
730 /*
731 * accept the packet if a router alert option is included
732 * and we act as an IPv6 router.
733 */
734 if (rtalert != ~0 && ip6_forwarding)
735 ours = 1;
736 } else
737 nxt = ip6->ip6_nxt;
738
739 /*
740 * Check that the amount of data in the buffers
741 * is as at least much as the IPv6 header would have us expect.
742 * Trim mbufs if longer than we expect.
743 * Drop packet if shorter than we expect.
744 */
745 if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
746 ip6stat.ip6s_tooshort++;
747 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
748 goto bad;
749 }
750 if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
751 if (m->m_len == m->m_pkthdr.len) {
752 m->m_len = sizeof(struct ip6_hdr) + plen;
753 m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
754 } else
755 m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
756 }
757
758 /*
759 * Forward if desirable.
760 */
761 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
762 /*
763 * If we are acting as a multicast router, all
764 * incoming multicast packets are passed to the
765 * kernel-level multicast forwarding function.
766 * The packet is returned (relatively) intact; if
767 * ip6_mforward() returns a non-zero value, the packet
768 * must be discarded, else it may be accepted below.
769 */
770 if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
771 ip6stat.ip6s_cantforward++;
772 m_freem(m);
773 return;
774 }
775 if (!ours) {
776 m_freem(m);
777 return;
778 }
779 } else if (!ours) {
780 ip6_forward(m, 0);
781 return;
782 }
783
784 ip6 = mtod(m, struct ip6_hdr *);
785
786 /*
787 * Malicious party may be able to use IPv4 mapped addr to confuse
788 * tcp/udp stack and bypass security checks (act as if it was from
789 * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious.
790 *
791 * For SIIT end node behavior, you may want to disable the check.
792 * However, you will become vulnerable to attacks using IPv4 mapped
793 * source.
794 */
795 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
796 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
797 ip6stat.ip6s_badscope++;
798 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
799 goto bad;
800 }
801
802 /*
803 * Tell launch routine the next header
804 */
805 ip6stat.ip6s_delivered++;
806 in6_ifstat_inc(deliverifp, ifs6_in_deliver);
807 nest = 0;
808
809 while (nxt != IPPROTO_DONE) {
810 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
811 ip6stat.ip6s_toomanyhdr++;
812 goto bad;
813 }
814
815 /*
816 * protection against faulty packet - there should be
817 * more sanity checks in header chain processing.
818 */
819 if (m->m_pkthdr.len < off) {
820 ip6stat.ip6s_tooshort++;
821 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
822 goto bad;
823 }
824
825#if 0
826 /*
827 * do we need to do it for every header? yeah, other
828 * functions can play with it (like re-allocate and copy).
829 */
830 mhist = ip6_addaux(m);
831 if (mhist && M_TRAILINGSPACE(mhist) >= sizeof(nxt)) {
832 hist = mtod(mhist, caddr_t) + mhist->m_len;
833 bcopy(&nxt, hist, sizeof(nxt));
834 mhist->m_len += sizeof(nxt);
835 } else {
836 ip6stat.ip6s_toomanyhdr++;
837 goto bad;
838 }
839#endif
840
841#ifdef IPSEC
842 /*
843 * enforce IPsec policy checking if we are seeing last header.
844 * note that we do not visit this with protocols with pcb layer
845 * code - like udp/tcp/raw ip.
846 */
847 if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
848 ipsec6_in_reject(m, NULL)) {
849 ipsec6stat.in_polvio++;
850 goto bad;
851 }
852#endif
853
854 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
855 }
856 return;
857 bad:
858 m_freem(m);
859}
860
861/*
862 * set/grab in6_ifaddr correspond to IPv6 destination address.
863 * XXX backward compatibility wrapper
864 */
865static struct mbuf *
866ip6_setdstifaddr(m, ia6)
867 struct mbuf *m;
868 struct in6_ifaddr *ia6;
869{
870 struct mbuf *n;
871
872 n = ip6_addaux(m);
873 if (n)
874 mtod(n, struct ip6aux *)->ip6a_dstia6 = ia6;
875 return n; /* NULL if failed to set */
876}
877
878struct in6_ifaddr *
879ip6_getdstifaddr(m)
880 struct mbuf *m;
881{
882 struct mbuf *n;
883
884 n = ip6_findaux(m);
885 if (n)
886 return mtod(n, struct ip6aux *)->ip6a_dstia6;
887 else
888 return NULL;
889}
890
891/*
892 * Hop-by-Hop options header processing. If a valid jumbo payload option is
893 * included, the real payload length will be stored in plenp.
894 */
895static int
896ip6_hopopts_input(plenp, rtalertp, mp, offp)
897 u_int32_t *plenp;
898 u_int32_t *rtalertp; /* XXX: should be stored more smart way */
899 struct mbuf **mp;
900 int *offp;
901{
902 struct mbuf *m = *mp;
903 int off = *offp, hbhlen;
904 struct ip6_hbh *hbh;
905 u_int8_t *opt;
906
907 /* validation of the length of the header */
908#ifndef PULLDOWN_TEST
909 IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
910 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
911 hbhlen = (hbh->ip6h_len + 1) << 3;
912
913 IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
914 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
915#else
916 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
917 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
918 if (hbh == NULL) {
919 ip6stat.ip6s_tooshort++;
920 return -1;
921 }
922 hbhlen = (hbh->ip6h_len + 1) << 3;
923 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
924 hbhlen);
925 if (hbh == NULL) {
926 ip6stat.ip6s_tooshort++;
927 return -1;
928 }
929#endif
930 off += hbhlen;
931 hbhlen -= sizeof(struct ip6_hbh);
932 opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
933
934 if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
935 hbhlen, rtalertp, plenp) < 0)
936 return(-1);
937
938 *offp = off;
939 *mp = m;
940 return(0);
941}
942
943/*
944 * Search header for all Hop-by-hop options and process each option.
945 * This function is separate from ip6_hopopts_input() in order to
946 * handle a case where the sending node itself process its hop-by-hop
947 * options header. In such a case, the function is called from ip6_output().
948 *
949 * The function assumes that hbh header is located right after the IPv6 header
950 * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
951 * opthead + hbhlen is located in continuous memory region.
952 */
953int
954ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
955 struct mbuf *m;
956 u_int8_t *opthead;
957 int hbhlen;
958 u_int32_t *rtalertp;
959 u_int32_t *plenp;
960{
961 struct ip6_hdr *ip6;
962 int optlen = 0;
963 u_int8_t *opt = opthead;
964 u_int16_t rtalert_val;
965 u_int32_t jumboplen;
966 const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
967
968 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
969 switch (*opt) {
970 case IP6OPT_PAD1:
971 optlen = 1;
972 break;
973 case IP6OPT_PADN:
974 if (hbhlen < IP6OPT_MINLEN) {
975 ip6stat.ip6s_toosmall++;
976 goto bad;
977 }
978 optlen = *(opt + 1) + 2;
979 break;
980 case IP6OPT_RTALERT:
981 /* XXX may need check for alignment */
982 if (hbhlen < IP6OPT_RTALERT_LEN) {
983 ip6stat.ip6s_toosmall++;
984 goto bad;
985 }
986 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
987 /* XXX stat */
988 icmp6_error(m, ICMP6_PARAM_PROB,
989 ICMP6_PARAMPROB_HEADER,
990 erroff + opt + 1 - opthead);
991 return(-1);
992 }
993 optlen = IP6OPT_RTALERT_LEN;
994 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
995 *rtalertp = ntohs(rtalert_val);
996 break;
997 case IP6OPT_JUMBO:
998 /* XXX may need check for alignment */
999 if (hbhlen < IP6OPT_JUMBO_LEN) {
1000 ip6stat.ip6s_toosmall++;
1001 goto bad;
1002 }
1003 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
1004 /* XXX stat */
1005 icmp6_error(m, ICMP6_PARAM_PROB,
1006 ICMP6_PARAMPROB_HEADER,
1007 erroff + opt + 1 - opthead);
1008 return(-1);
1009 }
1010 optlen = IP6OPT_JUMBO_LEN;
1011
1012 /*
1013 * IPv6 packets that have non 0 payload length
1014 * must not contain a jumbo payload option.
1015 */
1016 ip6 = mtod(m, struct ip6_hdr *);
1017 if (ip6->ip6_plen) {
1018 ip6stat.ip6s_badoptions++;
1019 icmp6_error(m, ICMP6_PARAM_PROB,
1020 ICMP6_PARAMPROB_HEADER,
1021 erroff + opt - opthead);
1022 return(-1);
1023 }
1024
1025 /*
1026 * We may see jumbolen in unaligned location, so
1027 * we'd need to perform bcopy().
1028 */
1029 bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
1030 jumboplen = (u_int32_t)htonl(jumboplen);
1031
1032#if 1
1033 /*
1034 * if there are multiple jumbo payload options,
1035 * *plenp will be non-zero and the packet will be
1036 * rejected.
1037 * the behavior may need some debate in ipngwg -
1038 * multiple options does not make sense, however,
1039 * there's no explicit mention in specification.
1040 */
1041 if (*plenp != 0) {
1042 ip6stat.ip6s_badoptions++;
1043 icmp6_error(m, ICMP6_PARAM_PROB,
1044 ICMP6_PARAMPROB_HEADER,
1045 erroff + opt + 2 - opthead);
1046 return(-1);
1047 }
1048#endif
1049
1050 /*
1051 * jumbo payload length must be larger than 65535.
1052 */
1053 if (jumboplen <= IPV6_MAXPACKET) {
1054 ip6stat.ip6s_badoptions++;
1055 icmp6_error(m, ICMP6_PARAM_PROB,
1056 ICMP6_PARAMPROB_HEADER,
1057 erroff + opt + 2 - opthead);
1058 return(-1);
1059 }
1060 *plenp = jumboplen;
1061
1062 break;
1063 default: /* unknown option */
1064 if (hbhlen < IP6OPT_MINLEN) {
1065 ip6stat.ip6s_toosmall++;
1066 goto bad;
1067 }
1068 optlen = ip6_unknown_opt(opt, m,
1069 erroff + opt - opthead);
1070 if (optlen == -1)
1071 return(-1);
1072 optlen += 2;
1073 break;
1074 }
1075 }
1076
1077 return(0);
1078
1079 bad:
1080 m_freem(m);
1081 return(-1);
1082}
1083
1084/*
1085 * Unknown option processing.
1086 * The third argument `off' is the offset from the IPv6 header to the option,
1087 * which is necessary if the IPv6 header the and option header and IPv6 header
1088 * is not continuous in order to return an ICMPv6 error.
1089 */
1090int
1091ip6_unknown_opt(optp, m, off)
1092 u_int8_t *optp;
1093 struct mbuf *m;
1094 int off;
1095{
1096 struct ip6_hdr *ip6;
1097
1098 switch (IP6OPT_TYPE(*optp)) {
1099 case IP6OPT_TYPE_SKIP: /* ignore the option */
1100 return((int)*(optp + 1));
1101 case IP6OPT_TYPE_DISCARD: /* silently discard */
1102 m_freem(m);
1103 return(-1);
1104 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
1105 ip6stat.ip6s_badoptions++;
1106 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
1107 return(-1);
1108 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
1109 ip6stat.ip6s_badoptions++;
1110 ip6 = mtod(m, struct ip6_hdr *);
1111 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
1112 (m->m_flags & (M_BCAST|M_MCAST)))
1113 m_freem(m);
1114 else
1115 icmp6_error(m, ICMP6_PARAM_PROB,
1116 ICMP6_PARAMPROB_OPTION, off);
1117 return(-1);
1118 }
1119
1120 m_freem(m); /* XXX: NOTREACHED */
1121 return(-1);
1122}
1123
1124/*
1125 * Create the "control" list for this pcb.
1126 * The function will not modify mbuf chain at all.
1127 *
1128 * with KAME mbuf chain restriction:
1129 * The routine will be called from upper layer handlers like tcp6_input().
1130 * Thus the routine assumes that the caller (tcp6_input) have already
1131 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
1132 * very first mbuf on the mbuf chain.
1133 */
1134void
1135ip6_savecontrol(in6p, mp, ip6, m)
1136 struct inpcb *in6p;
1137 struct mbuf **mp;
1138 struct ip6_hdr *ip6;
1139 struct mbuf *m;
1140{
1141 struct proc *p = curproc; /* XXX */
1142 int privileged = 0;
1143 int rthdr_exist = 0;
1144
1145
1146 if (p && !suser(p))
1147 privileged++;
1148
1149#ifdef SO_TIMESTAMP
1150 if ((in6p->in6p_socket->so_options & SO_TIMESTAMP) != 0) {
1151 struct timeval tv;
1152
1153 microtime(&tv);
1154 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1155 SCM_TIMESTAMP, SOL_SOCKET);
1156 if (*mp) {
1157 mp = &(*mp)->m_next;
1158 }
1159 }
1160#endif
1161
1162 /* RFC 2292 sec. 5 */
1163 if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) {
1164 struct in6_pktinfo pi6;
1165 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1166 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
1167 pi6.ipi6_addr.s6_addr16[1] = 0;
1168 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
1169 ? m->m_pkthdr.rcvif->if_index
1170 : 0;
1171 *mp = sbcreatecontrol((caddr_t) &pi6,
1172 sizeof(struct in6_pktinfo), IPV6_PKTINFO,
1173 IPPROTO_IPV6);
1174 if (*mp)
1175 mp = &(*mp)->m_next;
1176 }
1177
1178 if ((in6p->in6p_flags & IN6P_HOPLIMIT) != 0) {
1179 int hlim = ip6->ip6_hlim & 0xff;
1180 *mp = sbcreatecontrol((caddr_t) &hlim,
1181 sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
1182 if (*mp)
1183 mp = &(*mp)->m_next;
1184 }
1185
1186 /*
1187 * IPV6_HOPOPTS socket option. We require super-user privilege
1188 * for the option, but it might be too strict, since there might
1189 * be some hop-by-hop options which can be returned to normal user.
1190 * See RFC 2292 section 6.
1191 */
1192 if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0 && privileged) {
1193 /*
1194 * Check if a hop-by-hop options header is contatined in the
1195 * received packet, and if so, store the options as ancillary
1196 * data. Note that a hop-by-hop options header must be
1197 * just after the IPv6 header, which fact is assured through
1198 * the IPv6 input processing.
1199 */
1200 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1201 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1202 struct ip6_hbh *hbh;
1203 int hbhlen = 0;
1204#ifdef PULLDOWN_TEST
1205 struct mbuf *ext;
1206#endif
1207
1208#ifndef PULLDOWN_TEST
1209 hbh = (struct ip6_hbh *)(ip6 + 1);
1210 hbhlen = (hbh->ip6h_len + 1) << 3;
1211#else
1212 ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
1213 ip6->ip6_nxt);
1214 if (ext == NULL) {
1215 ip6stat.ip6s_tooshort++;
1216 return;
1217 }
1218 hbh = mtod(ext, struct ip6_hbh *);
1219 hbhlen = (hbh->ip6h_len + 1) << 3;
1220 if (hbhlen != ext->m_len) {
1221 m_freem(ext);
1222 ip6stat.ip6s_tooshort++;
1223 return;
1224 }
1225#endif
1226
1227 /*
1228 * XXX: We copy whole the header even if a jumbo
1229 * payload option is included, which option is to
1230 * be removed before returning in the RFC 2292.
1231 * Note: this constraint is removed in 2292bis.
1232 */
1233 *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1234 IPV6_HOPOPTS, IPPROTO_IPV6);
1235 if (*mp)
1236 mp = &(*mp)->m_next;
1237#ifdef PULLDOWN_TEST
1238 m_freem(ext);
1239#endif
1240 }
1241 }
1242
1243 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
1244 if ((in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
1245 int proto, off, nxt;
1246
1247 /*
1248 * go through the header chain to see if a routing header is
1249 * contained in the packet. We need this information to store
1250 * destination options headers (if any) properly.
1251 * XXX: performance issue. We should record this info when
1252 * processing extension headers in incoming routine.
1253 * (todo) use m_aux?
1254 */
1255 proto = IPPROTO_IPV6;
1256 off = 0;
1257 nxt = -1;
1258 while (1) {
1259 int newoff;
1260
1261 newoff = ip6_nexthdr(m, off, proto, &nxt);
1262 if (newoff < 0)
1263 break;
1264 if (newoff < off) /* invalid, check for safety */
1265 break;
1266 if ((proto = nxt) == IPPROTO_ROUTING) {
1267 rthdr_exist = 1;
1268 break;
1269 }
1270 off = newoff;
1271 }
1272 }
1273
1274 if ((in6p->in6p_flags &
1275 (IN6P_RTHDR | IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
1276 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1277 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
1278
1279 /*
1280 * Search for destination options headers or routing
1281 * header(s) through the header chain, and stores each
1282 * header as ancillary data.
1283 * Note that the order of the headers remains in
1284 * the chain of ancillary data.
1285 */
1286 while (1) { /* is explicit loop prevention necessary? */
1287 struct ip6_ext *ip6e = NULL;
1288 int elen;
1289#ifdef PULLDOWN_TEST
1290 struct mbuf *ext = NULL;
1291#endif
1292
1293 /*
1294 * if it is not an extension header, don't try to
1295 * pull it from the chain.
1296 */
1297 switch (nxt) {
1298 case IPPROTO_DSTOPTS:
1299 case IPPROTO_ROUTING:
1300 case IPPROTO_HOPOPTS:
1301 case IPPROTO_AH: /* is it possible? */
1302 break;
1303 default:
1304 goto loopend;
1305 }
1306
1307#ifndef PULLDOWN_TEST
1308 if (off + sizeof(*ip6e) > m->m_len)
1309 goto loopend;
1310 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1311 if (nxt == IPPROTO_AH)
1312 elen = (ip6e->ip6e_len + 2) << 2;
1313 else
1314 elen = (ip6e->ip6e_len + 1) << 3;
1315 if (off + elen > m->m_len)
1316 goto loopend;
1317#else
1318 ext = ip6_pullexthdr(m, off, nxt);
1319 if (ext == NULL) {
1320 ip6stat.ip6s_tooshort++;
1321 return;
1322 }
1323 ip6e = mtod(ext, struct ip6_ext *);
1324 if (nxt == IPPROTO_AH)
1325 elen = (ip6e->ip6e_len + 2) << 2;
1326 else
1327 elen = (ip6e->ip6e_len + 1) << 3;
1328 if (elen != ext->m_len) {
1329 m_freem(ext);
1330 ip6stat.ip6s_tooshort++;
1331 return;
1332 }
1333#endif
1334
1335 switch (nxt) {
1336 case IPPROTO_DSTOPTS:
1337 if ((in6p->in6p_flags & IN6P_DSTOPTS) == 0)
1338 break;
1339
1340 /*
1341 * We also require super-user privilege for
1342 * the option.
1343 * See the comments on IN6_HOPOPTS.
1344 */
1345 if (!privileged)
1346 break;
1347
1348 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1349 IPV6_DSTOPTS,
1350 IPPROTO_IPV6);
1351 if (*mp)
1352 mp = &(*mp)->m_next;
1353 break;
1354 case IPPROTO_ROUTING:
1355 if (!in6p->in6p_flags & IN6P_RTHDR)
1356 break;
1357
1358 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1359 IPV6_RTHDR,
1360 IPPROTO_IPV6);
1361 if (*mp)
1362 mp = &(*mp)->m_next;
1363 break;
1364 case IPPROTO_HOPOPTS:
1365 case IPPROTO_AH: /* is it possible? */
1366 break;
1367
1368 default:
1369 /*
1370 * other cases have been filtered in the above.
1371 * none will visit this case. here we supply
1372 * the code just in case (nxt overwritten or
1373 * other cases).
1374 */
1375#ifdef PULLDOWN_TEST
1376 m_freem(ext);
1377#endif
1378 goto loopend;
1379
1380 }
1381
1382 /* proceed with the next header. */
1383 off += elen;
1384 nxt = ip6e->ip6e_nxt;
1385 ip6e = NULL;
1386#ifdef PULLDOWN_TEST
1387 m_freem(ext);
1388 ext = NULL;
1389#endif
1390 }
1391 loopend:
1392 ;
1393 }
1394
1395}
1396
1397#ifdef PULLDOWN_TEST
1398/*
1399 * pull single extension header from mbuf chain. returns single mbuf that
1400 * contains the result, or NULL on error.
1401 */
1402static struct mbuf *
1403ip6_pullexthdr(m, off, nxt)
1404 struct mbuf *m;
1405 size_t off;
1406 int nxt;
1407{
1408 struct ip6_ext ip6e;
1409 size_t elen;
1410 struct mbuf *n;
1411
1412#ifdef DIAGNOSTIC
1413 switch (nxt) {
1414 case IPPROTO_DSTOPTS:
1415 case IPPROTO_ROUTING:
1416 case IPPROTO_HOPOPTS:
1417 case IPPROTO_AH: /* is it possible? */
1418 break;
1419 default:
1420 printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
1421 }
1422#endif
1423
1424 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1425 if (nxt == IPPROTO_AH)
1426 elen = (ip6e.ip6e_len + 2) << 2;
1427 else
1428 elen = (ip6e.ip6e_len + 1) << 3;
1429
1430 MGET(n, M_DONTWAIT, MT_DATA);
1431 if (n && elen >= MLEN) {
1432 MCLGET(n, M_DONTWAIT);
1433 if ((n->m_flags & M_EXT) == 0) {
1434 m_free(n);
1435 n = NULL;
1436 }
1437 }
1438 if (!n)
1439 return NULL;
1440
1441 n->m_len = 0;
1442 if (elen >= M_TRAILINGSPACE(n)) {
1443 m_free(n);
1444 return NULL;
1445 }
1446
1447 m_copydata(m, off, elen, mtod(n, caddr_t));
1448 n->m_len = elen;
1449 return n;
1450}
1451#endif
1452
1453/*
1454 * Get pointer to the previous header followed by the header
1455 * currently processed.
1456 * XXX: This function supposes that
1457 * M includes all headers,
1458 * the next header field and the header length field of each header
1459 * are valid, and
1460 * the sum of each header length equals to OFF.
1461 * Because of these assumptions, this function must be called very
1462 * carefully. Moreover, it will not be used in the near future when
1463 * we develop `neater' mechanism to process extension headers.
1464 */
1465char *
1466ip6_get_prevhdr(m, off)
1467 struct mbuf *m;
1468 int off;
1469{
1470 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1471
1472 if (off == sizeof(struct ip6_hdr))
1473 return(&ip6->ip6_nxt);
1474 else {
1475 int len, nxt;
1476 struct ip6_ext *ip6e = NULL;
1477
1478 nxt = ip6->ip6_nxt;
1479 len = sizeof(struct ip6_hdr);
1480 while (len < off) {
1481 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1482
1483 switch (nxt) {
1484 case IPPROTO_FRAGMENT:
1485 len += sizeof(struct ip6_frag);
1486 break;
1487 case IPPROTO_AH:
1488 len += (ip6e->ip6e_len + 2) << 2;
1489 break;
1490 default:
1491 len += (ip6e->ip6e_len + 1) << 3;
1492 break;
1493 }
1494 nxt = ip6e->ip6e_nxt;
1495 }
1496 if (ip6e)
1497 return(&ip6e->ip6e_nxt);
1498 else
1499 return NULL;
1500 }
1501}
1502
1503/*
1504 * get next header offset. m will be retained.
1505 */
1506int
1507ip6_nexthdr(m, off, proto, nxtp)
1508 struct mbuf *m;
1509 int off;
1510 int proto;
1511 int *nxtp;
1512{
1513 struct ip6_hdr ip6;
1514 struct ip6_ext ip6e;
1515 struct ip6_frag fh;
1516
1517 /* just in case */
1518 if (m == NULL)
1519 panic("ip6_nexthdr: m == NULL");
1520 if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
1521 return -1;
1522
1523 switch (proto) {
1524 case IPPROTO_IPV6:
1525 if (m->m_pkthdr.len < off + sizeof(ip6))
1526 return -1;
1527 m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
1528 if (nxtp)
1529 *nxtp = ip6.ip6_nxt;
1530 off += sizeof(ip6);
1531 return off;
1532
1533 case IPPROTO_FRAGMENT:
1534 /*
1535 * terminate parsing if it is not the first fragment,
1536 * it does not make sense to parse through it.
1537 */
1538 if (m->m_pkthdr.len < off + sizeof(fh))
1539 return -1;
1540 m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
1541 if ((ntohs(fh.ip6f_offlg) & IP6F_OFF_MASK) != 0)
1542 return -1;
1543 if (nxtp)
1544 *nxtp = fh.ip6f_nxt;
1545 off += sizeof(struct ip6_frag);
1546 return off;
1547
1548 case IPPROTO_AH:
1549 if (m->m_pkthdr.len < off + sizeof(ip6e))
1550 return -1;
1551 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1552 if (nxtp)
1553 *nxtp = ip6e.ip6e_nxt;
1554 off += (ip6e.ip6e_len + 2) << 2;
1555 return off;
1556
1557 case IPPROTO_HOPOPTS:
1558 case IPPROTO_ROUTING:
1559 case IPPROTO_DSTOPTS:
1560 if (m->m_pkthdr.len < off + sizeof(ip6e))
1561 return -1;
1562 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1563 if (nxtp)
1564 *nxtp = ip6e.ip6e_nxt;
1565 off += (ip6e.ip6e_len + 1) << 3;
1566 return off;
1567
1568 case IPPROTO_NONE:
1569 case IPPROTO_ESP:
1570 case IPPROTO_IPCOMP:
1571 /* give up */
1572 return -1;
1573
1574 default:
1575 return -1;
1576 }
1577
1578 return -1;
1579}
1580
1581/*
1582 * get offset for the last header in the chain. m will be kept untainted.
1583 */
1584int
1585ip6_lasthdr(m, off, proto, nxtp)
1586 struct mbuf *m;
1587 int off;
1588 int proto;
1589 int *nxtp;
1590{
1591 int newoff;
1592 int nxt;
1593
1594 if (!nxtp) {
1595 nxt = -1;
1596 nxtp = &nxt;
1597 }
1598 while (1) {
1599 newoff = ip6_nexthdr(m, off, proto, nxtp);
1600 if (newoff < 0)
1601 return off;
1602 else if (newoff < off)
1603 return -1; /* invalid */
1604 else if (newoff == off)
1605 return newoff;
1606
1607 off = newoff;
1608 proto = *nxtp;
1609 }
1610}
1611
1612struct mbuf *
1613ip6_addaux(m)
1614 struct mbuf *m;
1615{
1616 struct mbuf *n;
1617
1618#ifdef DIAGNOSTIC
1619 if (sizeof(struct ip6aux) > MHLEN)
1620 panic("assumption failed on sizeof(ip6aux)");
1621#endif
1622 n = m_aux_find(m, AF_INET6, -1);
1623 if (n) {
1624 if (n->m_len < sizeof(struct ip6aux)) {
1625 printf("conflicting use of ip6aux");
1626 return NULL;
1627 }
1628 } else {
1629 n = m_aux_add(m, AF_INET6, -1);
1630 n->m_len = sizeof(struct ip6aux);
1631 bzero(mtod(n, caddr_t), n->m_len);
1632 }
1633 return n;
1634}
1635
1636struct mbuf *
1637ip6_findaux(m)
1638 struct mbuf *m;
1639{
1640 struct mbuf *n;
1641
1642 n = m_aux_find(m, AF_INET6, -1);
1643 if (n && n->m_len < sizeof(struct ip6aux)) {
1644 printf("conflicting use of ip6aux");
1645 n = NULL;
1646 }
1647 return n;
1648}
1649
1650void
1651ip6_delaux(m)
1652 struct mbuf *m;
1653{
1654 struct mbuf *n;
1655
1656 n = m_aux_find(m, AF_INET6, -1);
1657 if (n)
1658 m_aux_delete(m, n);
1659}
1660
1661/*
1662 * System control for IP6
1663 */
1664
1665u_char inet6ctlerrmap[PRC_NCMDS] = {
1666 0, 0, 0, 0,
1667 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1668 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1669 EMSGSIZE, EHOSTUNREACH, 0, 0,
1670 0, 0, 0, 0,
1671 ENOPROTOOPT
1672};