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