]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/ip6_input.c
xnu-1504.9.37.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;
b7266188 640#if MROUTING
1c79356b 641 else if (!ip6_mrouter) {
b7266188
A
642#else
643 else {
644#endif
1c79356b
A
645 ip6stat.ip6s_notmember++;
646 ip6stat.ip6s_cantforward++;
b0d623f7 647 in6_ifstat_inc(ifp, ifs6_in_discard);
1c79356b
A
648 goto bad;
649 }
b0d623f7 650 deliverifp = ifp;
1c79356b
A
651 goto hbhcheck;
652 }
653
b0d623f7
A
654 if (ip6_forward_rt.ro_rt != NULL)
655 RT_LOCK(ip6_forward_rt.ro_rt);
1c79356b
A
656 /*
657 * Unicast check
658 */
9bccf70c 659 if (ip6_forward_rt.ro_rt != NULL &&
b0d623f7 660 (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) &&
9bccf70c 661 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
b0d623f7
A
662 &((struct sockaddr_in6 *)(&ip6_forward_rt.ro_dst))->sin6_addr) &&
663 ip6_forward_rt.ro_rt->generation_id == route_generation) {
9bccf70c 664 ip6stat.ip6s_forward_cachehit++;
b0d623f7 665 } else {
9bccf70c
A
666 struct sockaddr_in6 *dst6;
667
b0d623f7
A
668 if (ip6_forward_rt.ro_rt != NULL) {
669 /* route is down/stale or destination is different */
9bccf70c 670 ip6stat.ip6s_forward_cachemiss++;
b0d623f7 671 RT_UNLOCK(ip6_forward_rt.ro_rt);
9bccf70c 672 rtfree(ip6_forward_rt.ro_rt);
b0d623f7 673 ip6_forward_rt.ro_rt = NULL;
1c79356b 674 }
9bccf70c 675
1c79356b 676 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
9bccf70c
A
677 dst6 = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
678 dst6->sin6_len = sizeof(struct sockaddr_in6);
679 dst6->sin6_family = AF_INET6;
680 dst6->sin6_addr = ip6->ip6_dst;
681#if SCOPEDROUTING
682 ip6_forward_rt.ro_dst.sin6_scope_id =
683 in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst);
684#endif
1c79356b 685
1c79356b 686 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
b0d623f7
A
687 if (ip6_forward_rt.ro_rt != NULL)
688 RT_LOCK(ip6_forward_rt.ro_rt);
1c79356b
A
689 }
690
691#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
692
693 /*
694 * Accept the packet if the forwarding interface to the destination
695 * according to the routing table is the loopback interface,
696 * unless the associated route has a gateway.
697 * Note that this approach causes to accept a packet if there is a
698 * route to the loopback interface for the destination of the packet.
699 * But we think it's even useful in some situations, e.g. when using
700 * a special daemon which wants to intercept the packet.
9bccf70c
A
701 *
702 * XXX: some OSes automatically make a cloned route for the destination
703 * of an outgoing packet. If the outgoing interface of the packet
704 * is a loopback one, the kernel would consider the packet to be
705 * accepted, even if we have no such address assinged on the interface.
706 * We check the cloned flag of the route entry to reject such cases,
707 * assuming that route entries for our own addresses are not made by
708 * cloning (it should be true because in6_addloop explicitly installs
709 * the host route). However, we might have to do an explicit check
710 * while it would be less efficient. Or, should we rather install a
711 * reject route for such a case?
1c79356b 712 */
b0d623f7 713 if (ip6_forward_rt.ro_rt != NULL &&
1c79356b
A
714 (ip6_forward_rt.ro_rt->rt_flags &
715 (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
9bccf70c
A
716#if RTF_WASCLONED
717 !(ip6_forward_rt.ro_rt->rt_flags & RTF_WASCLONED) &&
718#endif
1c79356b
A
719#if 0
720 /*
721 * The check below is redundant since the comparison of
722 * the destination and the key of the rtentry has
723 * already done through looking up the routing table.
724 */
725 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
9bccf70c 726 &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr)
1c79356b
A
727#endif
728 ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
729 struct in6_ifaddr *ia6 =
730 (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
9bccf70c
A
731
732 /*
733 * record address information into m_aux.
734 */
735 (void)ip6_setdstifaddr(m, ia6);
736
737 /*
738 * packets to a tentative, duplicated, or somehow invalid
739 * address must not be accepted.
740 */
1c79356b 741 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
9bccf70c 742 /* this address is ready */
1c79356b
A
743 ours = 1;
744 deliverifp = ia6->ia_ifp; /* correct? */
9bccf70c
A
745 /* Count the packet in the ip address stats */
746#ifndef __APPLE__
747
748 ia6->ia_ifa.if_ipackets++;
749 ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
750#endif
b0d623f7 751 RT_UNLOCK(ip6_forward_rt.ro_rt);
1c79356b
A
752 goto hbhcheck;
753 } else {
b0d623f7 754 RT_UNLOCK(ip6_forward_rt.ro_rt);
9bccf70c
A
755 /* address is not ready, so discard the packet. */
756 nd6log((LOG_INFO,
757 "ip6_input: packet to an unready address %s->%s\n",
758 ip6_sprintf(&ip6->ip6_src),
759 ip6_sprintf(&ip6->ip6_dst)));
9bccf70c 760 goto bad;
1c79356b
A
761 }
762 }
763
764 /*
765 * FAITH(Firewall Aided Internet Translator)
766 */
767#if defined(NFAITH) && 0 < NFAITH
768 if (ip6_keepfaith) {
769 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
770 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
771 /* XXX do we need more sanity checks? */
772 ours = 1;
55e303ae 773 deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /* faith */
b0d623f7 774 RT_UNLOCK(ip6_forward_rt.ro_rt);
1c79356b
A
775 goto hbhcheck;
776 }
777 }
778#endif
b0d623f7
A
779 if (ip6_forward_rt.ro_rt != NULL)
780 RT_UNLOCK(ip6_forward_rt.ro_rt);
1c79356b 781
1c79356b
A
782 /*
783 * Now there is no reason to process the packet if it's not our own
784 * and we're not a router.
785 */
786 if (!ip6_forwarding) {
787 ip6stat.ip6s_cantforward++;
788 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
789 goto bad;
790 }
791
792 hbhcheck:
9bccf70c
A
793 /*
794 * record address information into m_aux, if we don't have one yet.
795 * note that we are unable to record it, if the address is not listed
796 * as our interface address (e.g. multicast addresses, addresses
797 * within FAITH prefixes and such).
798 */
799 if (deliverifp && !ip6_getdstifaddr(m)) {
800 struct in6_ifaddr *ia6;
801
802 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
803 if (ia6) {
804 if (!ip6_setdstifaddr(m, ia6)) {
805 /*
806 * XXX maybe we should drop the packet here,
807 * as we could not provide enough information
808 * to the upper layers.
809 */
810 }
b0d623f7 811 ifafree(&ia6->ia_ifa);
9bccf70c
A
812 }
813 }
814
1c79356b
A
815 /*
816 * Process Hop-by-Hop options header if it's contained.
817 * m may be modified in ip6_hopopts_input().
818 * If a JumboPayload option is included, plen will also be modified.
819 */
820 plen = (u_int32_t)ntohs(ip6->ip6_plen);
821 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
822 struct ip6_hbh *hbh;
823
824 if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
825#if 0 /*touches NULL pointer*/
826 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
827#endif
91447636 828 lck_mtx_unlock(ip6_mutex);
1c79356b
A
829 return; /* m have already been freed */
830 }
9bccf70c 831
1c79356b
A
832 /* adjust pointer */
833 ip6 = mtod(m, struct ip6_hdr *);
9bccf70c
A
834
835 /*
55e303ae 836 * if the payload length field is 0 and the next header field
9bccf70c
A
837 * indicates Hop-by-Hop Options header, then a Jumbo Payload
838 * option MUST be included.
839 */
840 if (ip6->ip6_plen == 0 && plen == 0) {
841 /*
842 * Note that if a valid jumbo payload option is
843 * contained, ip6_hoptops_input() must set a valid
844 * (non-zero) payload length to the variable plen.
845 */
846 ip6stat.ip6s_badoptions++;
847 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
848 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
91447636 849 lck_mtx_unlock(ip6_mutex);
9bccf70c
A
850 icmp6_error(m, ICMP6_PARAM_PROB,
851 ICMP6_PARAMPROB_HEADER,
852 (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
853 return;
854 }
1c79356b
A
855#ifndef PULLDOWN_TEST
856 /* ip6_hopopts_input() ensures that mbuf is contiguous */
857 hbh = (struct ip6_hbh *)(ip6 + 1);
858#else
859 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
860 sizeof(struct ip6_hbh));
861 if (hbh == NULL) {
862 ip6stat.ip6s_tooshort++;
91447636 863 lck_mtx_unlock(ip6_mutex);
1c79356b
A
864 return;
865 }
866#endif
867 nxt = hbh->ip6h_nxt;
868
869 /*
870 * accept the packet if a router alert option is included
871 * and we act as an IPv6 router.
872 */
873 if (rtalert != ~0 && ip6_forwarding)
874 ours = 1;
875 } else
876 nxt = ip6->ip6_nxt;
877
878 /*
879 * Check that the amount of data in the buffers
880 * is as at least much as the IPv6 header would have us expect.
881 * Trim mbufs if longer than we expect.
882 * Drop packet if shorter than we expect.
883 */
884 if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
885 ip6stat.ip6s_tooshort++;
886 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
887 goto bad;
888 }
889 if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
890 if (m->m_len == m->m_pkthdr.len) {
891 m->m_len = sizeof(struct ip6_hdr) + plen;
892 m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
893 } else
894 m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
895 }
896
897 /*
898 * Forward if desirable.
899 */
900 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
901 /*
902 * If we are acting as a multicast router, all
903 * incoming multicast packets are passed to the
904 * kernel-level multicast forwarding function.
905 * The packet is returned (relatively) intact; if
906 * ip6_mforward() returns a non-zero value, the packet
907 * must be discarded, else it may be accepted below.
908 */
b7266188 909#if MROUTING
1c79356b
A
910 if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
911 ip6stat.ip6s_cantforward++;
912 m_freem(m);
91447636 913 lck_mtx_unlock(ip6_mutex);
1c79356b
A
914 return;
915 }
b7266188 916#endif
1c79356b
A
917 if (!ours) {
918 m_freem(m);
91447636 919 lck_mtx_unlock(ip6_mutex);
1c79356b
A
920 return;
921 }
922 } else if (!ours) {
2d21ac55 923 ip6_forward(m, &ip6_forward_rt, 0, 1);
91447636 924 lck_mtx_unlock(ip6_mutex);
1c79356b
A
925 return;
926 }
927
928 ip6 = mtod(m, struct ip6_hdr *);
929
930 /*
931 * Malicious party may be able to use IPv4 mapped addr to confuse
932 * tcp/udp stack and bypass security checks (act as if it was from
933 * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious.
934 *
935 * For SIIT end node behavior, you may want to disable the check.
936 * However, you will become vulnerable to attacks using IPv4 mapped
937 * source.
938 */
939 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
940 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
941 ip6stat.ip6s_badscope++;
942 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
943 goto bad;
944 }
945
946 /*
947 * Tell launch routine the next header
948 */
1c79356b
A
949 ip6stat.ip6s_delivered++;
950 in6_ifstat_inc(deliverifp, ifs6_in_deliver);
91447636
A
951
952 lck_mtx_unlock(ip6_mutex);
953injectit:
1c79356b
A
954 nest = 0;
955
1c79356b 956 while (nxt != IPPROTO_DONE) {
91447636 957 struct ipfilter *filter;
0b4c1975
A
958 int (*pr_input)(struct mbuf **, int *);
959
1c79356b
A
960 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
961 ip6stat.ip6s_toomanyhdr++;
91447636 962 goto badunlocked;
1c79356b
A
963 }
964
965 /*
966 * protection against faulty packet - there should be
967 * more sanity checks in header chain processing.
968 */
9bccf70c 969 if (m->m_pkthdr.len < off) {
1c79356b
A
970 ip6stat.ip6s_tooshort++;
971 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
91447636 972 goto badunlocked;
1c79356b 973 }
9bccf70c
A
974
975#if 0
976 /*
977 * do we need to do it for every header? yeah, other
978 * functions can play with it (like re-allocate and copy).
979 */
980 mhist = ip6_addaux(m);
981 if (mhist && M_TRAILINGSPACE(mhist) >= sizeof(nxt)) {
982 hist = mtod(mhist, caddr_t) + mhist->m_len;
983 bcopy(&nxt, hist, sizeof(nxt));
984 mhist->m_len += sizeof(nxt);
985 } else {
986 ip6stat.ip6s_toomanyhdr++;
987 goto bad;
988 }
989#endif
990
991#if IPSEC
992 /*
993 * enforce IPsec policy checking if we are seeing last header.
994 * note that we do not visit this with protocols with pcb layer
995 * code - like udp/tcp/raw ip.
996 */
91447636 997 if ((ipsec_bypass == 0) && (ip6_protox[nxt]->pr_flags & PR_LASTHDR) != 0) {
91447636 998 if (ipsec6_in_reject(m, NULL)) {
2d21ac55 999 IPSEC_STAT_INCREMENT(ipsec6stat.in_polvio);
91447636 1000 goto badunlocked;
2d21ac55 1001 }
1c79356b
A
1002 }
1003#endif
9bccf70c 1004
91447636 1005 /*
2d21ac55 1006 * Call IP filter
91447636 1007 */
2d21ac55 1008 if (!TAILQ_EMPTY(&ipv6_filters)) {
91447636
A
1009 ipf_ref();
1010 TAILQ_FOREACH(filter, &ipv6_filters, ipf_link) {
1011 if (seen == 0) {
1012 if ((struct ipfilter *)inject_ipfref == filter)
1013 seen = 1;
1014 } else if (filter->ipf_filter.ipf_input) {
1015 errno_t result;
1016
1017 result = filter->ipf_filter.ipf_input(
1018 filter->ipf_filter.cookie, (mbuf_t*)&m, off, nxt);
1019 if (result == EJUSTRETURN) {
1020 ipf_unref();
1021 return;
1022 }
1023 if (result != 0) {
1024 ipf_unref();
1025 m_freem(m);
1026 return;
1027 }
1028 }
1029 }
1030 ipf_unref();
1031 }
0b4c1975
A
1032
1033 if ((pr_input = ip6_protox[nxt]->pr_input) == NULL) {
1034 m_freem(m);
1035 m = NULL;
1036 nxt = IPPROTO_DONE;
1037 } else if (!(ip6_protox[nxt]->pr_flags & PR_PROTOLOCK)) {
91447636 1038 lck_mtx_lock(inet6_domain_mutex);
0b4c1975 1039 nxt = pr_input(&m, &off);
91447636 1040 lck_mtx_unlock(inet6_domain_mutex);
0b4c1975
A
1041 } else {
1042 nxt = pr_input(&m, &off);
91447636 1043 }
1c79356b
A
1044 }
1045 return;
1046 bad:
91447636
A
1047 lck_mtx_unlock(ip6_mutex);
1048 badunlocked:
1c79356b 1049 m_freem(m);
91447636 1050 return;
1c79356b
A
1051}
1052
9bccf70c
A
1053/*
1054 * set/grab in6_ifaddr correspond to IPv6 destination address.
1055 * XXX backward compatibility wrapper
1056 */
2d21ac55
A
1057static struct ip6aux *
1058ip6_setdstifaddr(struct mbuf *m, struct in6_ifaddr *ia6)
9bccf70c 1059{
2d21ac55 1060 struct ip6aux *n;
9bccf70c
A
1061
1062 n = ip6_addaux(m);
1063 if (n)
2d21ac55
A
1064 n->ip6a_dstia6 = ia6;
1065 return (struct ip6aux *)n; /* NULL if failed to set */
9bccf70c
A
1066}
1067
1068struct in6_ifaddr *
1069ip6_getdstifaddr(m)
1070 struct mbuf *m;
1071{
2d21ac55 1072 struct ip6aux *n;
9bccf70c
A
1073
1074 n = ip6_findaux(m);
1075 if (n)
2d21ac55 1076 return n->ip6a_dstia6;
9bccf70c
A
1077 else
1078 return NULL;
1079}
1080
1c79356b
A
1081/*
1082 * Hop-by-Hop options header processing. If a valid jumbo payload option is
1083 * included, the real payload length will be stored in plenp.
1084 */
1085static int
1086ip6_hopopts_input(plenp, rtalertp, mp, offp)
1087 u_int32_t *plenp;
1088 u_int32_t *rtalertp; /* XXX: should be stored more smart way */
1089 struct mbuf **mp;
1090 int *offp;
1091{
9bccf70c 1092 struct mbuf *m = *mp;
1c79356b
A
1093 int off = *offp, hbhlen;
1094 struct ip6_hbh *hbh;
1095 u_int8_t *opt;
1096
1097 /* validation of the length of the header */
1098#ifndef PULLDOWN_TEST
91447636 1099 IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), return -1);
1c79356b
A
1100 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
1101 hbhlen = (hbh->ip6h_len + 1) << 3;
1102
91447636 1103 IP6_EXTHDR_CHECK(m, off, hbhlen, return -1);
1c79356b
A
1104 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
1105#else
1106 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
1107 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
1108 if (hbh == NULL) {
1109 ip6stat.ip6s_tooshort++;
1110 return -1;
1111 }
1112 hbhlen = (hbh->ip6h_len + 1) << 3;
1113 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
1114 hbhlen);
1115 if (hbh == NULL) {
1116 ip6stat.ip6s_tooshort++;
1117 return -1;
1118 }
1119#endif
1120 off += hbhlen;
1121 hbhlen -= sizeof(struct ip6_hbh);
1122 opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
1123
1124 if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
1125 hbhlen, rtalertp, plenp) < 0)
1126 return(-1);
1127
1128 *offp = off;
1129 *mp = m;
1130 return(0);
1131}
1132
1133/*
1134 * Search header for all Hop-by-hop options and process each option.
1135 * This function is separate from ip6_hopopts_input() in order to
1136 * handle a case where the sending node itself process its hop-by-hop
1137 * options header. In such a case, the function is called from ip6_output().
9bccf70c
A
1138 *
1139 * The function assumes that hbh header is located right after the IPv6 header
1140 * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
1141 * opthead + hbhlen is located in continuous memory region.
1c79356b
A
1142 */
1143int
1144ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
1145 struct mbuf *m;
1146 u_int8_t *opthead;
1147 int hbhlen;
1148 u_int32_t *rtalertp;
1149 u_int32_t *plenp;
1150{
1151 struct ip6_hdr *ip6;
1152 int optlen = 0;
1153 u_int8_t *opt = opthead;
1154 u_int16_t rtalert_val;
9bccf70c
A
1155 u_int32_t jumboplen;
1156 const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
1c79356b
A
1157
1158 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
9bccf70c
A
1159 switch (*opt) {
1160 case IP6OPT_PAD1:
1161 optlen = 1;
1162 break;
1163 case IP6OPT_PADN:
1164 if (hbhlen < IP6OPT_MINLEN) {
1165 ip6stat.ip6s_toosmall++;
1166 goto bad;
1167 }
1168 optlen = *(opt + 1) + 2;
1169 break;
1170 case IP6OPT_RTALERT:
1171 /* XXX may need check for alignment */
1172 if (hbhlen < IP6OPT_RTALERT_LEN) {
1173 ip6stat.ip6s_toosmall++;
1174 goto bad;
1175 }
1176 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
1177 /* XXX stat */
91447636 1178 lck_mtx_unlock(ip6_mutex);
9bccf70c
A
1179 icmp6_error(m, ICMP6_PARAM_PROB,
1180 ICMP6_PARAMPROB_HEADER,
1181 erroff + opt + 1 - opthead);
91447636 1182 lck_mtx_lock(ip6_mutex);
9bccf70c
A
1183 return(-1);
1184 }
1185 optlen = IP6OPT_RTALERT_LEN;
1186 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
1187 *rtalertp = ntohs(rtalert_val);
1188 break;
1189 case IP6OPT_JUMBO:
1190 /* XXX may need check for alignment */
1191 if (hbhlen < IP6OPT_JUMBO_LEN) {
1192 ip6stat.ip6s_toosmall++;
1193 goto bad;
1194 }
1195 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
1196 /* XXX stat */
91447636 1197 lck_mtx_unlock(ip6_mutex);
9bccf70c
A
1198 icmp6_error(m, ICMP6_PARAM_PROB,
1199 ICMP6_PARAMPROB_HEADER,
1200 erroff + opt + 1 - opthead);
91447636 1201 lck_mtx_lock(ip6_mutex);
9bccf70c
A
1202 return(-1);
1203 }
1204 optlen = IP6OPT_JUMBO_LEN;
1205
1206 /*
1207 * IPv6 packets that have non 0 payload length
1208 * must not contain a jumbo payload option.
1209 */
1210 ip6 = mtod(m, struct ip6_hdr *);
1211 if (ip6->ip6_plen) {
1212 ip6stat.ip6s_badoptions++;
91447636 1213 lck_mtx_unlock(ip6_mutex);
9bccf70c
A
1214 icmp6_error(m, ICMP6_PARAM_PROB,
1215 ICMP6_PARAMPROB_HEADER,
1216 erroff + opt - opthead);
91447636 1217 lck_mtx_lock(ip6_mutex);
9bccf70c
A
1218 return(-1);
1219 }
1220
1221 /*
1222 * We may see jumbolen in unaligned location, so
1223 * we'd need to perform bcopy().
1224 */
1225 bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
1226 jumboplen = (u_int32_t)htonl(jumboplen);
1227
1228#if 1
1229 /*
1230 * if there are multiple jumbo payload options,
1231 * *plenp will be non-zero and the packet will be
1232 * rejected.
1233 * the behavior may need some debate in ipngwg -
1234 * multiple options does not make sense, however,
1235 * there's no explicit mention in specification.
1236 */
1237 if (*plenp != 0) {
1238 ip6stat.ip6s_badoptions++;
91447636 1239 lck_mtx_unlock(ip6_mutex);
9bccf70c
A
1240 icmp6_error(m, ICMP6_PARAM_PROB,
1241 ICMP6_PARAMPROB_HEADER,
1242 erroff + opt + 2 - opthead);
91447636 1243 lck_mtx_lock(ip6_mutex);
9bccf70c
A
1244 return(-1);
1245 }
1c79356b 1246#endif
9bccf70c
A
1247
1248 /*
1249 * jumbo payload length must be larger than 65535.
1250 */
1251 if (jumboplen <= IPV6_MAXPACKET) {
1252 ip6stat.ip6s_badoptions++;
91447636 1253 lck_mtx_unlock(ip6_mutex);
9bccf70c
A
1254 icmp6_error(m, ICMP6_PARAM_PROB,
1255 ICMP6_PARAMPROB_HEADER,
1256 erroff + opt + 2 - opthead);
91447636 1257 lck_mtx_lock(ip6_mutex);
9bccf70c
A
1258 return(-1);
1259 }
1260 *plenp = jumboplen;
1261
1262 break;
1263 default: /* unknown option */
1264 if (hbhlen < IP6OPT_MINLEN) {
1265 ip6stat.ip6s_toosmall++;
1266 goto bad;
1267 }
1268 optlen = ip6_unknown_opt(opt, m,
91447636
A
1269 erroff + opt - opthead, 1);
1270 if (optlen == -1) {
1271 /* ip6_unknown opt unlocked ip6_mutex */
9bccf70c 1272 return(-1);
91447636 1273 }
9bccf70c
A
1274 optlen += 2;
1275 break;
1c79356b
A
1276 }
1277 }
1278
1279 return(0);
1280
91447636 1281 bad:
1c79356b
A
1282 m_freem(m);
1283 return(-1);
1284}
1285
1286/*
1287 * Unknown option processing.
1288 * The third argument `off' is the offset from the IPv6 header to the option,
1289 * which is necessary if the IPv6 header the and option header and IPv6 header
1290 * is not continuous in order to return an ICMPv6 error.
1291 */
1292int
91447636 1293ip6_unknown_opt(optp, m, off, locked)
1c79356b
A
1294 u_int8_t *optp;
1295 struct mbuf *m;
1296 int off;
91447636 1297 int locked;
1c79356b
A
1298{
1299 struct ip6_hdr *ip6;
1300
9bccf70c
A
1301 switch (IP6OPT_TYPE(*optp)) {
1302 case IP6OPT_TYPE_SKIP: /* ignore the option */
1303 return((int)*(optp + 1));
1304 case IP6OPT_TYPE_DISCARD: /* silently discard */
1305 m_freem(m);
1306 return(-1);
1307 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
1308 ip6stat.ip6s_badoptions++;
91447636
A
1309 if (locked)
1310 lck_mtx_unlock(ip6_mutex);
9bccf70c 1311 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
91447636
A
1312 if (locked)
1313 lck_mtx_lock(ip6_mutex);
9bccf70c
A
1314 return(-1);
1315 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
1316 ip6stat.ip6s_badoptions++;
1317 ip6 = mtod(m, struct ip6_hdr *);
1318 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
1319 (m->m_flags & (M_BCAST|M_MCAST)))
1320 m_freem(m);
91447636
A
1321 else {
1322 if (locked)
1323 lck_mtx_unlock(ip6_mutex);
9bccf70c
A
1324 icmp6_error(m, ICMP6_PARAM_PROB,
1325 ICMP6_PARAMPROB_OPTION, off);
91447636
A
1326 if (locked)
1327 lck_mtx_lock(ip6_mutex);
1328 }
9bccf70c 1329 return(-1);
1c79356b
A
1330 }
1331
1332 m_freem(m); /* XXX: NOTREACHED */
1333 return(-1);
1334}
1335
1336/*
1337 * Create the "control" list for this pcb.
1338 * The function will not modify mbuf chain at all.
1339 *
1340 * with KAME mbuf chain restriction:
1341 * The routine will be called from upper layer handlers like tcp6_input().
1342 * Thus the routine assumes that the caller (tcp6_input) have already
1343 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
1344 * very first mbuf on the mbuf chain.
1345 */
1346void
9bccf70c
A
1347ip6_savecontrol(in6p, mp, ip6, m)
1348 struct inpcb *in6p;
1349 struct mbuf **mp;
1350 struct ip6_hdr *ip6;
1351 struct mbuf *m;
1c79356b 1352{
9bccf70c 1353 int rthdr_exist = 0;
1c79356b 1354
1c79356b 1355#if SO_TIMESTAMP
9bccf70c 1356 if ((in6p->in6p_socket->so_options & SO_TIMESTAMP) != 0) {
1c79356b
A
1357 struct timeval tv;
1358
1359 microtime(&tv);
1360 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1361 SCM_TIMESTAMP, SOL_SOCKET);
1362 if (*mp) {
1c79356b
A
1363 mp = &(*mp)->m_next;
1364 }
1365 }
1366#endif
1367
2d21ac55
A
1368 /* some OSes call this logic with IPv4 packet, for SO_TIMESTAMP */
1369 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION)
1370 return;
1371
1c79356b 1372 /* RFC 2292 sec. 5 */
9bccf70c
A
1373 if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) {
1374 struct in6_pktinfo pi6;
1c79356b
A
1375 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1376 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
1377 pi6.ipi6_addr.s6_addr16[1] = 0;
1378 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
1379 ? m->m_pkthdr.rcvif->if_index
1380 : 0;
9bccf70c
A
1381 *mp = sbcreatecontrol((caddr_t) &pi6,
1382 sizeof(struct in6_pktinfo), IPV6_PKTINFO,
1383 IPPROTO_IPV6);
1384 if (*mp)
1385 mp = &(*mp)->m_next;
1c79356b
A
1386 }
1387
9bccf70c
A
1388 if ((in6p->in6p_flags & IN6P_HOPLIMIT) != 0) {
1389 int hlim = ip6->ip6_hlim & 0xff;
1390 *mp = sbcreatecontrol((caddr_t) &hlim,
1391 sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
1392 if (*mp)
1393 mp = &(*mp)->m_next;
1c79356b
A
1394 }
1395
b0d623f7
A
1396 if ((in6p->in6p_flags & IN6P_TCLASS) != 0) {
1397 u_int32_t flowinfo;
1398 int tclass;
1399
1400 flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
1401 flowinfo >>= 20;
1402
1403 tclass = flowinfo & 0xff;
1404 *mp = sbcreatecontrol((caddr_t) &tclass, sizeof(tclass),
1405 IPV6_TCLASS, IPPROTO_IPV6);
1406 if (*mp)
1407 mp = &(*mp)->m_next;
1408 }
1409
1c79356b 1410 /*
91447636
A
1411 * IPV6_HOPOPTS socket option. Recall that we required super-user
1412 * privilege for the option (see ip6_ctloutput), but it might be too
1413 * strict, since there might be some hop-by-hop options which can be
1414 * returned to normal user.
1c79356b
A
1415 * See RFC 2292 section 6.
1416 */
91447636 1417 if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0) {
1c79356b
A
1418 /*
1419 * Check if a hop-by-hop options header is contatined in the
1420 * received packet, and if so, store the options as ancillary
1421 * data. Note that a hop-by-hop options header must be
1422 * just after the IPv6 header, which fact is assured through
1423 * the IPv6 input processing.
1424 */
91447636 1425 ip6 = mtod(m, struct ip6_hdr *);
1c79356b 1426 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
9bccf70c
A
1427 struct ip6_hbh *hbh;
1428 int hbhlen = 0;
1429#if PULLDOWN_TEST
1c79356b
A
1430 struct mbuf *ext;
1431#endif
1432
1433#ifndef PULLDOWN_TEST
1434 hbh = (struct ip6_hbh *)(ip6 + 1);
1435 hbhlen = (hbh->ip6h_len + 1) << 3;
1436#else
1437 ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
1438 ip6->ip6_nxt);
1439 if (ext == NULL) {
1440 ip6stat.ip6s_tooshort++;
1441 return;
1442 }
1443 hbh = mtod(ext, struct ip6_hbh *);
1444 hbhlen = (hbh->ip6h_len + 1) << 3;
1445 if (hbhlen != ext->m_len) {
1446 m_freem(ext);
1447 ip6stat.ip6s_tooshort++;
1448 return;
1449 }
1450#endif
1451
1c79356b 1452 /*
9bccf70c
A
1453 * XXX: We copy whole the header even if a jumbo
1454 * payload option is included, which option is to
1455 * be removed before returning in the RFC 2292.
1456 * Note: this constraint is removed in 2292bis.
1c79356b 1457 */
9bccf70c
A
1458 *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1459 IPV6_HOPOPTS, IPPROTO_IPV6);
1460 if (*mp)
1461 mp = &(*mp)->m_next;
1462#if PULLDOWN_TEST
1c79356b
A
1463 m_freem(ext);
1464#endif
1465 }
1466 }
1467
1468 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
9bccf70c
A
1469 if ((in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
1470 int proto, off, nxt;
1471
1472 /*
1473 * go through the header chain to see if a routing header is
1474 * contained in the packet. We need this information to store
1475 * destination options headers (if any) properly.
1476 * XXX: performance issue. We should record this info when
1477 * processing extension headers in incoming routine.
1478 * (todo) use m_aux?
1479 */
1480 proto = IPPROTO_IPV6;
1481 off = 0;
1482 nxt = -1;
1483 while (1) {
1484 int newoff;
1485
1486 newoff = ip6_nexthdr(m, off, proto, &nxt);
1487 if (newoff < 0)
1488 break;
1489 if (newoff < off) /* invalid, check for safety */
1490 break;
1491 if ((proto = nxt) == IPPROTO_ROUTING) {
1492 rthdr_exist = 1;
1493 break;
1494 }
1495 off = newoff;
1496 }
1497 }
1498
1499 if ((in6p->in6p_flags &
1500 (IN6P_RTHDR | IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
91447636 1501 ip6 = mtod(m, struct ip6_hdr *);
1c79356b 1502 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
1c79356b
A
1503
1504 /*
1505 * Search for destination options headers or routing
1506 * header(s) through the header chain, and stores each
1507 * header as ancillary data.
1508 * Note that the order of the headers remains in
1509 * the chain of ancillary data.
1510 */
1511 while (1) { /* is explicit loop prevention necessary? */
1512 struct ip6_ext *ip6e = NULL;
1513 int elen;
9bccf70c 1514#if PULLDOWN_TEST
1c79356b
A
1515 struct mbuf *ext = NULL;
1516#endif
1517
1518 /*
1519 * if it is not an extension header, don't try to
1520 * pull it from the chain.
1521 */
1522 switch (nxt) {
1523 case IPPROTO_DSTOPTS:
1524 case IPPROTO_ROUTING:
1525 case IPPROTO_HOPOPTS:
1526 case IPPROTO_AH: /* is it possible? */
1527 break;
1528 default:
1529 goto loopend;
1530 }
1531
1532#ifndef PULLDOWN_TEST
1533 if (off + sizeof(*ip6e) > m->m_len)
1534 goto loopend;
1535 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1536 if (nxt == IPPROTO_AH)
1537 elen = (ip6e->ip6e_len + 2) << 2;
1538 else
1539 elen = (ip6e->ip6e_len + 1) << 3;
1540 if (off + elen > m->m_len)
1541 goto loopend;
1542#else
1543 ext = ip6_pullexthdr(m, off, nxt);
1544 if (ext == NULL) {
1545 ip6stat.ip6s_tooshort++;
1546 return;
1547 }
1548 ip6e = mtod(ext, struct ip6_ext *);
1549 if (nxt == IPPROTO_AH)
1550 elen = (ip6e->ip6e_len + 2) << 2;
1551 else
1552 elen = (ip6e->ip6e_len + 1) << 3;
1553 if (elen != ext->m_len) {
1554 m_freem(ext);
1555 ip6stat.ip6s_tooshort++;
1556 return;
1557 }
1558#endif
1559
1560 switch (nxt) {
1561 case IPPROTO_DSTOPTS:
9bccf70c 1562 if ((in6p->in6p_flags & IN6P_DSTOPTS) == 0)
1c79356b
A
1563 break;
1564
9bccf70c
A
1565 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1566 IPV6_DSTOPTS,
1567 IPPROTO_IPV6);
1568 if (*mp)
1569 mp = &(*mp)->m_next;
1c79356b 1570 break;
1c79356b 1571 case IPPROTO_ROUTING:
1c79356b
A
1572 if (!in6p->in6p_flags & IN6P_RTHDR)
1573 break;
1574
1c79356b
A
1575 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1576 IPV6_RTHDR,
1577 IPPROTO_IPV6);
1c79356b
A
1578 if (*mp)
1579 mp = &(*mp)->m_next;
1580 break;
1c79356b
A
1581 case IPPROTO_HOPOPTS:
1582 case IPPROTO_AH: /* is it possible? */
1583 break;
1584
1585 default:
1586 /*
1587 * other cases have been filtered in the above.
1588 * none will visit this case. here we supply
1589 * the code just in case (nxt overwritten or
1590 * other cases).
1591 */
9bccf70c 1592#if PULLDOWN_TEST
1c79356b
A
1593 m_freem(ext);
1594#endif
1595 goto loopend;
1596
1597 }
1598
1599 /* proceed with the next header. */
1600 off += elen;
1601 nxt = ip6e->ip6e_nxt;
1602 ip6e = NULL;
9bccf70c 1603#if PULLDOWN_TEST
1c79356b
A
1604 m_freem(ext);
1605 ext = NULL;
1606#endif
1607 }
1608 loopend:
9bccf70c 1609 ;
1c79356b
A
1610 }
1611
1c79356b
A
1612}
1613
9bccf70c 1614#if PULLDOWN_TEST
1c79356b
A
1615/*
1616 * pull single extension header from mbuf chain. returns single mbuf that
1617 * contains the result, or NULL on error.
1618 */
1619static struct mbuf *
1620ip6_pullexthdr(m, off, nxt)
1621 struct mbuf *m;
1622 size_t off;
1623 int nxt;
1624{
1625 struct ip6_ext ip6e;
1626 size_t elen;
1627 struct mbuf *n;
1628
9bccf70c 1629#if DIAGNOSTIC
1c79356b
A
1630 switch (nxt) {
1631 case IPPROTO_DSTOPTS:
1632 case IPPROTO_ROUTING:
1633 case IPPROTO_HOPOPTS:
1634 case IPPROTO_AH: /* is it possible? */
1635 break;
1636 default:
1637 printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
1638 }
1639#endif
1640
1641 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1642 if (nxt == IPPROTO_AH)
1643 elen = (ip6e.ip6e_len + 2) << 2;
1644 else
1645 elen = (ip6e.ip6e_len + 1) << 3;
1646
1647 MGET(n, M_DONTWAIT, MT_DATA);
1648 if (n && elen >= MLEN) {
1649 MCLGET(n, M_DONTWAIT);
1650 if ((n->m_flags & M_EXT) == 0) {
1651 m_free(n);
1652 n = NULL;
1653 }
1654 }
1655 if (!n)
1656 return NULL;
1657
1658 n->m_len = 0;
1659 if (elen >= M_TRAILINGSPACE(n)) {
1660 m_free(n);
1661 return NULL;
1662 }
1663
1664 m_copydata(m, off, elen, mtod(n, caddr_t));
1665 n->m_len = elen;
1666 return n;
1667}
1668#endif
1669
1c79356b
A
1670/*
1671 * Get pointer to the previous header followed by the header
1672 * currently processed.
1673 * XXX: This function supposes that
1674 * M includes all headers,
1675 * the next header field and the header length field of each header
1676 * are valid, and
1677 * the sum of each header length equals to OFF.
1678 * Because of these assumptions, this function must be called very
1679 * carefully. Moreover, it will not be used in the near future when
1680 * we develop `neater' mechanism to process extension headers.
1681 */
1682char *
1683ip6_get_prevhdr(m, off)
1684 struct mbuf *m;
1685 int off;
1686{
1687 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1688
1689 if (off == sizeof(struct ip6_hdr))
2d21ac55 1690 return((char *) &ip6->ip6_nxt);
1c79356b
A
1691 else {
1692 int len, nxt;
1693 struct ip6_ext *ip6e = NULL;
1694
1695 nxt = ip6->ip6_nxt;
1696 len = sizeof(struct ip6_hdr);
1697 while (len < off) {
1698 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1699
9bccf70c 1700 switch (nxt) {
1c79356b
A
1701 case IPPROTO_FRAGMENT:
1702 len += sizeof(struct ip6_frag);
1703 break;
1704 case IPPROTO_AH:
1705 len += (ip6e->ip6e_len + 2) << 2;
1706 break;
1707 default:
1708 len += (ip6e->ip6e_len + 1) << 3;
1709 break;
1710 }
1711 nxt = ip6e->ip6e_nxt;
1712 }
1713 if (ip6e)
2d21ac55 1714 return((char *) &ip6e->ip6e_nxt);
1c79356b
A
1715 else
1716 return NULL;
1717 }
1718}
1719
1720/*
1721 * get next header offset. m will be retained.
1722 */
1723int
1724ip6_nexthdr(m, off, proto, nxtp)
1725 struct mbuf *m;
1726 int off;
1727 int proto;
1728 int *nxtp;
1729{
1730 struct ip6_hdr ip6;
1731 struct ip6_ext ip6e;
1732 struct ip6_frag fh;
1733
1734 /* just in case */
1735 if (m == NULL)
1736 panic("ip6_nexthdr: m == NULL");
1737 if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
1738 return -1;
1739
1740 switch (proto) {
1741 case IPPROTO_IPV6:
1742 if (m->m_pkthdr.len < off + sizeof(ip6))
1743 return -1;
1744 m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
1745 if (nxtp)
1746 *nxtp = ip6.ip6_nxt;
1747 off += sizeof(ip6);
1748 return off;
1749
1750 case IPPROTO_FRAGMENT:
1751 /*
1752 * terminate parsing if it is not the first fragment,
1753 * it does not make sense to parse through it.
1754 */
1755 if (m->m_pkthdr.len < off + sizeof(fh))
1756 return -1;
1757 m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
91447636
A
1758 /* IP6F_OFF_MASK = 0xfff8(BigEndian), 0xf8ff(LittleEndian) */
1759 if (fh.ip6f_offlg & IP6F_OFF_MASK)
1c79356b
A
1760 return -1;
1761 if (nxtp)
1762 *nxtp = fh.ip6f_nxt;
1763 off += sizeof(struct ip6_frag);
1764 return off;
1765
1766 case IPPROTO_AH:
1767 if (m->m_pkthdr.len < off + sizeof(ip6e))
1768 return -1;
1769 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1770 if (nxtp)
1771 *nxtp = ip6e.ip6e_nxt;
1772 off += (ip6e.ip6e_len + 2) << 2;
1773 return off;
1774
1775 case IPPROTO_HOPOPTS:
1776 case IPPROTO_ROUTING:
1777 case IPPROTO_DSTOPTS:
1778 if (m->m_pkthdr.len < off + sizeof(ip6e))
1779 return -1;
1780 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1781 if (nxtp)
1782 *nxtp = ip6e.ip6e_nxt;
1783 off += (ip6e.ip6e_len + 1) << 3;
1784 return off;
1785
1786 case IPPROTO_NONE:
1787 case IPPROTO_ESP:
1788 case IPPROTO_IPCOMP:
1789 /* give up */
1790 return -1;
1791
1792 default:
1793 return -1;
1794 }
1795
1796 return -1;
1797}
1798
1799/*
1800 * get offset for the last header in the chain. m will be kept untainted.
1801 */
1802int
1803ip6_lasthdr(m, off, proto, nxtp)
1804 struct mbuf *m;
1805 int off;
1806 int proto;
1807 int *nxtp;
1808{
1809 int newoff;
1810 int nxt;
1811
1812 if (!nxtp) {
1813 nxt = -1;
1814 nxtp = &nxt;
1815 }
1816 while (1) {
1817 newoff = ip6_nexthdr(m, off, proto, nxtp);
1818 if (newoff < 0)
1819 return off;
1820 else if (newoff < off)
1821 return -1; /* invalid */
1822 else if (newoff == off)
1823 return newoff;
1824
1825 off = newoff;
1826 proto = *nxtp;
1827 }
1828}
1829
2d21ac55
A
1830struct ip6aux *
1831ip6_addaux(
1832 struct mbuf *m)
9bccf70c 1833{
2d21ac55
A
1834 struct m_tag *tag;
1835
1836 /* Check if one is already allocated */
1837 tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_INET6, NULL);
1838 if (tag == NULL) {
1839 /* Allocate a tag */
1840 tag = m_tag_alloc(KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_INET6,
b0d623f7
A
1841 sizeof (struct ip6aux), M_DONTWAIT);
1842
2d21ac55
A
1843 /* Attach it to the mbuf */
1844 if (tag) {
1845 m_tag_prepend(m, tag);
55e303ae 1846 }
9bccf70c 1847 }
2d21ac55
A
1848
1849 return tag ? (struct ip6aux*)(tag + 1) : NULL;
9bccf70c
A
1850}
1851
2d21ac55
A
1852struct ip6aux *
1853ip6_findaux(
1854 struct mbuf *m)
9bccf70c 1855{
2d21ac55
A
1856 struct m_tag *tag;
1857
1858 tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_ENCAP, NULL);
1859
1860 return tag ? (struct ip6aux*)(tag + 1) : NULL;
9bccf70c
A
1861}
1862
1863void
2d21ac55
A
1864ip6_delaux(
1865 struct mbuf *m)
9bccf70c 1866{
2d21ac55 1867 struct m_tag *tag;
9bccf70c 1868
2d21ac55
A
1869 tag = m_tag_locate(m, KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_ENCAP, NULL);
1870 if (tag) {
1871 m_tag_delete(m, tag);
1872 }
9bccf70c
A
1873}
1874
1c79356b
A
1875/*
1876 * System control for IP6
1877 */
1878
1879u_char inet6ctlerrmap[PRC_NCMDS] = {
1880 0, 0, 0, 0,
1881 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1882 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1883 EMSGSIZE, EHOSTUNREACH, 0, 0,
1884 0, 0, 0, 0,
1885 ENOPROTOOPT
1886};