Bug Summary

File:netinet6/ip6_input.c
Warning:line 427, column 30
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ip6_input.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/netinet6/ip6_input.c
1/* $OpenBSD: ip6_input.c,v 1.257 2023/12/03 20:36:24 bluhm Exp $ */
2/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1982, 1986, 1988, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
62 */
63
64#include "pf.h"
65#include "carp.h"
66
67#include <sys/param.h>
68#include <sys/systm.h>
69#include <sys/mbuf.h>
70#include <sys/domain.h>
71#include <sys/sysctl.h>
72#include <sys/protosw.h>
73#include <sys/socket.h>
74#include <sys/socketvar.h>
75#include <sys/errno.h>
76#include <sys/time.h>
77#include <sys/timeout.h>
78#include <sys/kernel.h>
79#include <sys/syslog.h>
80#include <sys/task.h>
81
82#include <net/if.h>
83#include <net/if_var.h>
84#include <net/if_types.h>
85#include <net/route.h>
86#include <net/netisr.h>
87
88#include <netinet/in.h>
89
90#include <netinet/ip.h>
91
92#include <netinet/in_pcb.h>
93#include <netinet/ip_var.h>
94#include <netinet6/in6_var.h>
95#include <netinet6/in6_ifattach.h>
96#include <netinet/ip6.h>
97#include <netinet6/ip6_var.h>
98#include <netinet/icmp6.h>
99#include <netinet6/nd6.h>
100
101#include "gif.h"
102#include "bpfilter.h"
103
104#ifdef MROUTING1
105#include <netinet6/ip6_mroute.h>
106#endif
107
108#if NPF1 > 0
109#include <net/pfvar.h>
110#endif
111
112#if NCARP1 > 0
113#include <netinet/ip_carp.h>
114#endif
115
116struct niqueue ip6intrq = NIQUEUE_INITIALIZER(IPQ_MAXLEN, NETISR_IPV6){ { { ((void *)0), ((((0x4)) > 0x0 && ((0x4)) <
0x9) ? 0x9 : ((0x4))), 0x0 }, { ((void *)0), ((void *)0), 0 }
, ((2048)), 0 }, (24) }
;
117
118struct cpumem *ip6counters;
119
120uint8_t ip6_soiikey[IP6_SOIIKEY_LEN16];
121
122int ip6_ours(struct mbuf **, int *, int, int);
123int ip6_check_rh0hdr(struct mbuf *, int *);
124int ip6_hbhchcheck(struct mbuf **, int *, int *);
125int ip6_hopopts_input(struct mbuf **, int *, u_int32_t *, u_int32_t *);
126struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
127int ip6_sysctl_soiikey(void *, size_t *, void *, size_t);
128
129static struct mbuf_queue ip6send_mq;
130
131static void ip6_send_dispatch(void *);
132static struct task ip6send_task =
133 TASK_INITIALIZER(ip6_send_dispatch, &ip6send_mq){{ ((void *)0), ((void *)0) }, (ip6_send_dispatch), (&ip6send_mq
), 0 }
;
134
135/*
136 * IP6 initialization: fill in IP6 protocol switch table.
137 * All protocols not implemented in kernel go to raw IP6 protocol handler.
138 */
139void
140ip6_init(void)
141{
142 const struct protosw *pr;
143 int i;
144
145 pr = pffindproto(PF_INET624, IPPROTO_RAW255, SOCK_RAW3);
146 if (pr == NULL((void *)0))
147 panic("%s", __func__);
148 for (i = 0; i < IPPROTO_MAX256; i++)
149 ip6_protox[i] = pr - inet6sw;
150 for (pr = inet6domain.dom_protosw;
151 pr < inet6domain.dom_protoswNPROTOSW; pr++)
152 if (pr->pr_domain->dom_family == PF_INET624 &&
153 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW255 &&
154 pr->pr_protocol < IPPROTO_MAX256)
155 ip6_protox[pr->pr_protocol] = pr - inet6sw;
156 ip6_randomid_init();
157 nd6_init();
158 frag6_init();
159
160 mq_init(&ip6send_mq, 64, IPL_SOFTNET0x2);
161
162 ip6counters = counters_alloc(ip6s_ncounters);
163#ifdef MROUTING1
164 rt_timer_queue_init(&ip6_mrouterq, MCAST_EXPIRE_TIMEOUT30,
165 &mf6c_expire_route);
166#endif
167}
168
169struct ip6_offnxt {
170 int ion_off;
171 int ion_nxt;
172};
173
174/*
175 * Enqueue packet for local delivery. Queuing is used as a boundary
176 * between the network layer (input/forward path) running with
177 * NET_LOCK_SHARED() and the transport layer needing it exclusively.
178 */
179int
180ip6_ours(struct mbuf **mp, int *offp, int nxt, int af)
181{
182 /* ip6_hbhchcheck() may be run before, then off and nxt are set */
183 if (*offp == 0) {
184 nxt = ip6_hbhchcheck(mp, offp, NULL((void *)0));
185 if (nxt == IPPROTO_DONE257)
186 return IPPROTO_DONE257;
187 }
188
189 /* We are already in a IPv4/IPv6 local deliver loop. */
190 if (af != AF_UNSPEC0)
191 return nxt;
192
193 /* save values for later, use after dequeue */
194 if (*offp != sizeof(struct ip6_hdr)) {
195 struct m_tag *mtag;
196 struct ip6_offnxt *ion;
197
198 /* mbuf tags are expensive, but only used for header options */
199 mtag = m_tag_get(PACKET_TAG_IP6_OFFNXT0x8000, sizeof(*ion),
200 M_NOWAIT0x0002);
201 if (mtag == NULL((void *)0)) {
202 ip6stat_inc(ip6s_idropped);
203 m_freemp(mp);
204 return IPPROTO_DONE257;
205 }
206 ion = (struct ip6_offnxt *)(mtag + 1);
207 ion->ion_off = *offp;
208 ion->ion_nxt = nxt;
209
210 m_tag_prepend(*mp, mtag);
211 }
212
213 niq_enqueue(&ip6intrq, *mp);
214 *mp = NULL((void *)0);
215 return IPPROTO_DONE257;
216}
217
218/*
219 * Dequeue and process locally delivered packets.
220 * This is called with exclusive NET_LOCK().
221 */
222void
223ip6intr(void)
224{
225 struct mbuf *m;
226
227 while ((m = niq_dequeue(&ip6intrq)mq_dequeue(&(&ip6intrq)->ni_q)) != NULL((void *)0)) {
228 struct m_tag *mtag;
229 int off, nxt;
230
231#ifdef DIAGNOSTIC1
232 if ((m->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002) == 0)
233 panic("ip6intr no HDR");
234#endif
235 mtag = m_tag_find(m, PACKET_TAG_IP6_OFFNXT0x8000, NULL((void *)0));
236 if (mtag != NULL((void *)0)) {
237 struct ip6_offnxt *ion;
238
239 ion = (struct ip6_offnxt *)(mtag + 1);
240 off = ion->ion_off;
241 nxt = ion->ion_nxt;
242
243 m_tag_delete(m, mtag);
244 } else {
245 struct ip6_hdr *ip6;
246
247 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
248 off = sizeof(struct ip6_hdr);
249 nxt = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
250 }
251 nxt = ip_deliver(&m, &off, nxt, AF_INET624);
252 KASSERT(nxt == IPPROTO_DONE)((nxt == 257) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/netinet6/ip6_input.c"
, 252, "nxt == IPPROTO_DONE"))
;
253 }
254}
255
256void
257ipv6_input(struct ifnet *ifp, struct mbuf *m)
258{
259 int off, nxt;
260
261 off = 0;
262 nxt = ip6_input_if(&m, &off, IPPROTO_IPV641, AF_UNSPEC0, ifp);
263 KASSERT(nxt == IPPROTO_DONE)((nxt == 257) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/netinet6/ip6_input.c"
, 263, "nxt == IPPROTO_DONE"))
;
264}
265
266struct mbuf *
267ipv6_check(struct ifnet *ifp, struct mbuf *m)
268{
269 struct ip6_hdr *ip6;
270
271 if (m->m_lenm_hdr.mh_len < sizeof(*ip6)) {
272 m = m_pullup(m, sizeof(*ip6));
273 if (m == NULL((void *)0)) {
274 ip6stat_inc(ip6s_toosmall);
275 return (NULL((void *)0));
276 }
277 }
278
279 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
280
281 if ((ip6->ip6_vfcip6_ctlun.ip6_un2_vfc & IPV6_VERSION_MASK0xf0) != IPV6_VERSION0x60) {
282 ip6stat_inc(ip6s_badvers);
283 goto bad;
284 }
285
286 /*
287 * Check against address spoofing/corruption.
288 */
289 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)((&ip6->ip6_src)->__u6_addr.__u6_addr8[0] == 0xff) ||
290 IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)((*(const u_int32_t *)(const void *)(&(&ip6->ip6_dst
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_dst)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&ip6->ip6_dst)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&ip6->ip6_dst
)->__u6_addr.__u6_addr8[12]) == 0))
) {
291 /*
292 * XXX: "badscope" is not very suitable for a multicast source.
293 */
294 ip6stat_inc(ip6s_badscope);
295 goto bad;
296 }
297 if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src)((*(const u_int32_t *)(const void *)(&(&ip6->ip6_src
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_src)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&ip6->ip6_src)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&ip6->ip6_src
)->__u6_addr.__u6_addr8[12]) == (__uint32_t)(__builtin_constant_p
(1) ? (__uint32_t)(((__uint32_t)(1) & 0xff) << 24 |
((__uint32_t)(1) & 0xff00) << 8 | ((__uint32_t)(1)
& 0xff0000) >> 8 | ((__uint32_t)(1) & 0xff000000
) >> 24) : __swap32md(1))))
||
298 IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)((*(const u_int32_t *)(const void *)(&(&ip6->ip6_dst
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_dst)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&ip6->ip6_dst)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&ip6->ip6_dst
)->__u6_addr.__u6_addr8[12]) == (__uint32_t)(__builtin_constant_p
(1) ? (__uint32_t)(((__uint32_t)(1) & 0xff) << 24 |
((__uint32_t)(1) & 0xff00) << 8 | ((__uint32_t)(1)
& 0xff0000) >> 8 | ((__uint32_t)(1) & 0xff000000
) >> 24) : __swap32md(1))))
) &&
299 (ifp->if_flags & IFF_LOOPBACK0x8) == 0) {
300 ip6stat_inc(ip6s_badscope);
301 goto bad;
302 }
303 /* Drop packets if interface ID portion is already filled. */
304 if (((IN6_IS_SCOPE_EMBED(&ip6->ip6_src)(((((&ip6->ip6_src)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&ip6->ip6_src)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))) || ((((&ip6->ip6_src)->__u6_addr
.__u6_addr8[0] == 0xff) && (((&ip6->ip6_src)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((&ip6
->ip6_src)->__u6_addr.__u6_addr8[0] == 0xff) &&
(((&ip6->ip6_src)->__u6_addr.__u6_addr8[1] & 0x0f
) == 0x01))))
&& ip6->ip6_src.s6_addr16__u6_addr.__u6_addr16[1]) ||
305 (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)(((((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&ip6->ip6_dst)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))) || ((((&ip6->ip6_dst)->__u6_addr
.__u6_addr8[0] == 0xff) && (((&ip6->ip6_dst)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((&ip6
->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff) &&
(((&ip6->ip6_dst)->__u6_addr.__u6_addr8[1] & 0x0f
) == 0x01))))
&& ip6->ip6_dst.s6_addr16__u6_addr.__u6_addr16[1])) &&
306 (ifp->if_flags & IFF_LOOPBACK0x8) == 0) {
307 ip6stat_inc(ip6s_badscope);
308 goto bad;
309 }
310 if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)(((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff)
&& (((&ip6->ip6_dst)->__u6_addr.__u6_addr8
[1] & 0x0f) == 0x01))
&&
311 !(m->m_flagsm_hdr.mh_flags & M_LOOP0x0040)) {
312 /*
313 * In this case, the packet should come from the loopback
314 * interface. However, we cannot just check the if_flags,
315 * because ip6_mloopback() passes the "actual" interface
316 * as the outgoing/incoming interface.
317 */
318 ip6stat_inc(ip6s_badscope);
319 goto bad;
320 }
321
322 /*
323 * The following check is not documented in specs. A malicious
324 * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
325 * and bypass security checks (act as if it was from 127.0.0.1 by using
326 * IPv6 src ::ffff:127.0.0.1). Be cautious.
327 *
328 * This check chokes if we are in an SIIT cloud. As none of BSDs
329 * support IPv4-less kernel compilation, we cannot support SIIT
330 * environment at all. So, it makes more sense for us to reject any
331 * malicious packets for non-SIIT environment, than try to do a
332 * partial support for SIIT environment.
333 */
334 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src)((*(const u_int32_t *)(const void *)(&(&ip6->ip6_src
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_src)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&ip6->ip6_src)->__u6_addr.__u6_addr8[8]) == (__uint32_t
)(__builtin_constant_p(0x0000ffff) ? (__uint32_t)(((__uint32_t
)(0x0000ffff) & 0xff) << 24 | ((__uint32_t)(0x0000ffff
) & 0xff00) << 8 | ((__uint32_t)(0x0000ffff) & 0xff0000
) >> 8 | ((__uint32_t)(0x0000ffff) & 0xff000000) >>
24) : __swap32md(0x0000ffff))))
||
335 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)((*(const u_int32_t *)(const void *)(&(&ip6->ip6_dst
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_dst)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&ip6->ip6_dst)->__u6_addr.__u6_addr8[8]) == (__uint32_t
)(__builtin_constant_p(0x0000ffff) ? (__uint32_t)(((__uint32_t
)(0x0000ffff) & 0xff) << 24 | ((__uint32_t)(0x0000ffff
) & 0xff00) << 8 | ((__uint32_t)(0x0000ffff) & 0xff0000
) >> 8 | ((__uint32_t)(0x0000ffff) & 0xff000000) >>
24) : __swap32md(0x0000ffff))))
) {
336 ip6stat_inc(ip6s_badscope);
337 goto bad;
338 }
339
340 /*
341 * Reject packets with IPv4 compatible addresses (auto tunnel).
342 *
343 * The code forbids automatic tunneling as per RFC4213.
344 */
345 if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src)((*(const u_int32_t *)(const void *)(&(&ip6->ip6_src
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_src)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&ip6->ip6_src)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&ip6->ip6_src
)->__u6_addr.__u6_addr8[12]) != 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_src)->__u6_addr.__u6_addr8
[12]) != (__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(
((__uint32_t)(1) & 0xff) << 24 | ((__uint32_t)(1) &
0xff00) << 8 | ((__uint32_t)(1) & 0xff0000) >>
8 | ((__uint32_t)(1) & 0xff000000) >> 24) : __swap32md
(1))))
||
346 IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)((*(const u_int32_t *)(const void *)(&(&ip6->ip6_dst
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_dst)->__u6_addr.__u6_addr8
[4]) == 0) && (*(const u_int32_t *)(const void *)(&
(&ip6->ip6_dst)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&ip6->ip6_dst
)->__u6_addr.__u6_addr8[12]) != 0) && (*(const u_int32_t
*)(const void *)(&(&ip6->ip6_dst)->__u6_addr.__u6_addr8
[12]) != (__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(
((__uint32_t)(1) & 0xff) << 24 | ((__uint32_t)(1) &
0xff00) << 8 | ((__uint32_t)(1) & 0xff0000) >>
8 | ((__uint32_t)(1) & 0xff000000) >> 24) : __swap32md
(1))))
) {
347 ip6stat_inc(ip6s_badscope);
348 goto bad;
349 }
350
351 return (m);
352bad:
353 m_freem(m);
354 return (NULL((void *)0));
355}
356
357int
358ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
359{
360 struct mbuf *m;
361 struct ip6_hdr *ip6;
362 struct sockaddr_in6 sin6;
363 struct rtentry *rt = NULL((void *)0);
364 int ours = 0;
365 u_int16_t src_scope, dst_scope;
1
'dst_scope' declared without an initial value
366#if NPF1 > 0
367 struct in6_addr odst;
368#endif
369 int srcrt = 0;
370
371 KASSERT(*offp == 0)((*offp == 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/netinet6/ip6_input.c"
, 371, "*offp == 0"))
;
2
Assuming the condition is true
3
'?' condition is true
372
373 ip6stat_inc(ip6s_total);
374
375 m = *mp = ipv6_check(ifp, *mp);
376 if (m
3.1
'm' is not equal to NULL
== NULL((void *)0))
4
Taking false branch
377 goto bad;
378
379 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
380
381#if NCARP1 > 0
382 if (carp_lsdrop(ifp, m, AF_INET624, ip6->ip6_src.s6_addr32__u6_addr.__u6_addr32,
7
Assuming the condition is false
8
Taking false branch
383 ip6->ip6_dst.s6_addr32__u6_addr.__u6_addr32, (ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt == IPPROTO_ICMPV658 ? 0 : 1)))
5
Assuming field 'ip6_un1_nxt' is not equal to IPPROTO_ICMPV6
6
'?' condition is false
384 goto bad;
385#endif
386 ip6stat_inc(ip6s_nxthist + ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt);
387
388 /*
389 * If the packet has been received on a loopback interface it
390 * can be destined to any local address, not necessarily to
391 * an address configured on `ifp'.
392 */
393 if (ifp->if_flags & IFF_LOOPBACK0x8) {
9
Assuming the condition is false
10
Taking false branch
394 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)(((((&ip6->ip6_src)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&ip6->ip6_src)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))) || ((((&ip6->ip6_src)->__u6_addr
.__u6_addr8[0] == 0xff) && (((&ip6->ip6_src)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((&ip6
->ip6_src)->__u6_addr.__u6_addr8[0] == 0xff) &&
(((&ip6->ip6_src)->__u6_addr.__u6_addr8[1] & 0x0f
) == 0x01))))
) {
395 src_scope = ip6->ip6_src.s6_addr16__u6_addr.__u6_addr16[1];
396 ip6->ip6_src.s6_addr16__u6_addr.__u6_addr16[1] = 0;
397 }
398 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)(((((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&ip6->ip6_dst)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))) || ((((&ip6->ip6_dst)->__u6_addr
.__u6_addr8[0] == 0xff) && (((&ip6->ip6_dst)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((&ip6
->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff) &&
(((&ip6->ip6_dst)->__u6_addr.__u6_addr8[1] & 0x0f
) == 0x01))))
) {
399 dst_scope = ip6->ip6_dst.s6_addr16__u6_addr.__u6_addr16[1];
400 ip6->ip6_dst.s6_addr16__u6_addr.__u6_addr16[1] = 0;
401 }
402 }
403
404#if NPF1 > 0
405 /*
406 * Packet filter
407 */
408 odst = ip6->ip6_dst;
409 if (pf_test(AF_INET624, PF_IN, ifp, mp) != PF_PASS)
11
Assuming the condition is false
12
Taking false branch
410 goto bad;
411 m = *mp;
412 if (m == NULL((void *)0))
13
Assuming 'm' is not equal to NULL
14
Taking false branch
413 goto bad;
414
415 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
416 srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)(__builtin_memcmp((&(&odst)->__u6_addr.__u6_addr8[
0]), (&(&ip6->ip6_dst)->__u6_addr.__u6_addr8[0]
), (sizeof(struct in6_addr))) == 0)
;
15
Assuming the condition is false
417#endif
418
419 /*
420 * Without embedded scope ID we cannot find link-local
421 * addresses in the routing table.
422 */
423 if (ifp->if_flags & IFF_LOOPBACK0x8) {
16
Assuming the condition is true
424 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)(((((&ip6->ip6_src)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&ip6->ip6_src)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))) || ((((&ip6->ip6_src)->__u6_addr
.__u6_addr8[0] == 0xff) && (((&ip6->ip6_src)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((&ip6
->ip6_src)->__u6_addr.__u6_addr8[0] == 0xff) &&
(((&ip6->ip6_src)->__u6_addr.__u6_addr8[1] & 0x0f
) == 0x01))))
)
17
Taking true branch
18
Assuming the condition is false
19
Assuming the condition is false
425 ip6->ip6_src.s6_addr16__u6_addr.__u6_addr16[1] = src_scope;
426 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)(((((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&ip6->ip6_dst)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))) || ((((&ip6->ip6_dst)->__u6_addr
.__u6_addr8[0] == 0xff) && (((&ip6->ip6_dst)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((&ip6
->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff) &&
(((&ip6->ip6_dst)->__u6_addr.__u6_addr8[1] & 0x0f
) == 0x01))))
)
20
Assuming the condition is true
21
Assuming the condition is true
427 ip6->ip6_dst.s6_addr16__u6_addr.__u6_addr16[1] = dst_scope;
22
Assigned value is garbage or undefined
428 } else {
429 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)(((((&ip6->ip6_src)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&ip6->ip6_src)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))) || ((((&ip6->ip6_src)->__u6_addr
.__u6_addr8[0] == 0xff) && (((&ip6->ip6_src)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((&ip6
->ip6_src)->__u6_addr.__u6_addr8[0] == 0xff) &&
(((&ip6->ip6_src)->__u6_addr.__u6_addr8[1] & 0x0f
) == 0x01))))
)
430 ip6->ip6_src.s6_addr16__u6_addr.__u6_addr16[1] = htons(ifp->if_index)(__uint16_t)(__builtin_constant_p(ifp->if_index) ? (__uint16_t
)(((__uint16_t)(ifp->if_index) & 0xffU) << 8 | (
(__uint16_t)(ifp->if_index) & 0xff00U) >> 8) : __swap16md
(ifp->if_index))
;
431 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)(((((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&ip6->ip6_dst)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))) || ((((&ip6->ip6_dst)->__u6_addr
.__u6_addr8[0] == 0xff) && (((&ip6->ip6_dst)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((&ip6
->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff) &&
(((&ip6->ip6_dst)->__u6_addr.__u6_addr8[1] & 0x0f
) == 0x01))))
)
432 ip6->ip6_dst.s6_addr16__u6_addr.__u6_addr16[1] = htons(ifp->if_index)(__uint16_t)(__builtin_constant_p(ifp->if_index) ? (__uint16_t
)(((__uint16_t)(ifp->if_index) & 0xffU) << 8 | (
(__uint16_t)(ifp->if_index) & 0xff00U) >> 8) : __swap16md
(ifp->if_index))
;
433 }
434
435 /*
436 * Be more secure than RFC5095 and scan for type 0 routing headers.
437 * If pf has already scanned the header chain, do not do it twice.
438 */
439 if (!(m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags & PF_TAG_PROCESSED0x80) &&
440 ip6_check_rh0hdr(m, offp)) {
441 ip6stat_inc(ip6s_badoptions);
442 icmp6_error(m, ICMP6_PARAM_PROB4, ICMP6_PARAMPROB_HEADER0, *offp);
443 m = *mp = NULL((void *)0);
444 goto bad;
445 }
446
447#if NPF1 > 0
448 if (pf_ouraddr(m) == 1) {
449 nxt = ip6_ours(mp, offp, nxt, af);
450 goto out;
451 }
452#endif
453
454 /*
455 * Multicast check
456 */
457 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff)) {
458 /*
459 * Make sure M_MCAST is set. It should theoretically
460 * already be there, but let's play safe because upper
461 * layers check for this flag.
462 */
463 m->m_flagsm_hdr.mh_flags |= M_MCAST0x0200;
464
465 /*
466 * See if we belong to the destination multicast group on the
467 * arrival interface.
468 */
469 if (in6_hasmulti(&ip6->ip6_dst, ifp))
470 ours = 1;
471
472#ifdef MROUTING1
473 if (ip6_mforwarding && ip6_mrouter[ifp->if_rdomainif_data.ifi_rdomain]) {
474 int error;
475
476 nxt = ip6_hbhchcheck(&m, offp, &ours);
477 if (nxt == IPPROTO_DONE257)
478 goto out;
479
480 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
481
482 /*
483 * If we are acting as a multicast router, all
484 * incoming multicast packets are passed to the
485 * kernel-level multicast forwarding function.
486 * The packet is returned (relatively) intact; if
487 * ip6_mforward() returns a non-zero value, the packet
488 * must be discarded, else it may be accepted below.
489 */
490 KERNEL_LOCK()_kernel_lock();
491 error = ip6_mforward(ip6, ifp, m);
492 KERNEL_UNLOCK()_kernel_unlock();
493 if (error) {
494 ip6stat_inc(ip6s_cantforward);
495 goto bad;
496 }
497
498 if (ours) {
499 if (af == AF_UNSPEC0)
500 nxt = ip6_ours(mp, offp, nxt, af);
501 goto out;
502 }
503 goto bad;
504 }
505#endif
506 if (!ours) {
507 ip6stat_inc(ip6s_notmember);
508 if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)(((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff)
&& (((&ip6->ip6_dst)->__u6_addr.__u6_addr8
[1] & 0x0f) == 0x02))
)
509 ip6stat_inc(ip6s_cantforward);
510 goto bad;
511 }
512 nxt = ip6_ours(mp, offp, nxt, af);
513 goto out;
514 }
515
516
517 /*
518 * Unicast check
519 */
520 memset(&sin6, 0, sizeof(struct sockaddr_in6))__builtin_memset((&sin6), (0), (sizeof(struct sockaddr_in6
)))
;
521 sin6.sin6_len = sizeof(struct sockaddr_in6);
522 sin6.sin6_family = AF_INET624;
523 sin6.sin6_addr = ip6->ip6_dst;
524 rt = rtalloc_mpath(sin6tosa(&sin6), &ip6->ip6_src.s6_addr32__u6_addr.__u6_addr32[0],
525 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid);
526
527 /*
528 * Accept the packet if the route to the destination is marked
529 * as local.
530 */
531 if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL)((rt->rt_flags) & (0x200000))) {
532 struct in6_ifaddr *ia6 = ifatoia6(rt->rt_ifa);
533
534 if (ip6_forwarding == 0 && rt->rt_ifidx != ifp->if_index &&
535 !((ifp->if_flags & IFF_LOOPBACK0x8) ||
536 (ifp->if_typeif_data.ifi_type == IFT_ENC0xf4) ||
537 (m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST0x04))) {
538 /* received on wrong interface */
539#if NCARP1 > 0
540 struct ifnet *out_if;
541
542 /*
543 * Virtual IPs on carp interfaces need to be checked
544 * also against the parent interface and other carp
545 * interfaces sharing the same parent.
546 */
547 out_if = if_get(rt->rt_ifidx);
548 if (!(out_if && carp_strict_addr_chk(out_if, ifp))) {
549 ip6stat_inc(ip6s_wrongif);
550 if_put(out_if);
551 goto bad;
552 }
553 if_put(out_if);
554#else
555 ip6stat_inc(ip6s_wrongif);
556 goto bad;
557#endif
558 }
559 /*
560 * packets to a tentative, duplicated, or somehow invalid
561 * address must not be accepted.
562 */
563 if ((ia6->ia6_flags & (IN6_IFF_TENTATIVE0x02|IN6_IFF_DUPLICATED0x04))) {
564 char src[INET6_ADDRSTRLEN46], dst[INET6_ADDRSTRLEN46];
565
566 inet_ntop(AF_INET624, &ip6->ip6_src, src, sizeof(src));
567 inet_ntop(AF_INET624, &ip6->ip6_dst, dst, sizeof(dst));
568 /* address is not ready, so discard the packet. */
569 nd6log((LOG_INFO,do { if (nd6_debug) log (6, "%s: packet to an unready address %s->%s\n"
, __func__, src, dst); } while (0)
570 "%s: packet to an unready address %s->%s\n",do { if (nd6_debug) log (6, "%s: packet to an unready address %s->%s\n"
, __func__, src, dst); } while (0)
571 __func__, src, dst))do { if (nd6_debug) log (6, "%s: packet to an unready address %s->%s\n"
, __func__, src, dst); } while (0)
;
572
573 goto bad;
574 } else {
575 nxt = ip6_ours(mp, offp, nxt, af);
576 goto out;
577 }
578 }
579
580#if NCARP1 > 0
581 if (ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt == IPPROTO_ICMPV658 &&
582 carp_lsdrop(ifp, m, AF_INET624, ip6->ip6_src.s6_addr32__u6_addr.__u6_addr32,
583 ip6->ip6_dst.s6_addr32__u6_addr.__u6_addr32, 1))
584 goto bad;
585#endif
586 /*
587 * Now there is no reason to process the packet if it's not our own
588 * and we're not a router.
589 */
590 if (!ip6_forwarding) {
591 ip6stat_inc(ip6s_cantforward);
592 goto bad;
593 }
594
595 nxt = ip6_hbhchcheck(&m, offp, &ours);
596 if (nxt == IPPROTO_DONE257)
597 goto out;
598
599 if (ours) {
600 if (af == AF_UNSPEC0)
601 nxt = ip6_ours(mp, offp, nxt, af);
602 goto out;
603 }
604
605#ifdef IPSEC1
606 if (ipsec_in_use) {
607 int rv;
608
609 rv = ipsec_forward_check(m, *offp, AF_INET624);
610 if (rv != 0) {
611 ip6stat_inc(ip6s_cantforward);
612 goto bad;
613 }
614 /*
615 * Fall through, forward packet. Outbound IPsec policy
616 * checking will occur in ip6_forward().
617 */
618 }
619#endif /* IPSEC */
620
621 ip6_forward(m, rt, srcrt);
622 *mp = NULL((void *)0);
623 return IPPROTO_DONE257;
624 bad:
625 nxt = IPPROTO_DONE257;
626 m_freemp(mp);
627 out:
628 rtfree(rt);
629 return nxt;
630}
631
632/* On error free mbuf and return IPPROTO_DONE. */
633int
634ip6_hbhchcheck(struct mbuf **mp, int *offp, int *oursp)
635{
636 struct ip6_hdr *ip6;
637 u_int32_t plen, rtalert = ~0;
638 int nxt;
639
640 ip6 = mtod(*mp, struct ip6_hdr *)((struct ip6_hdr *)((*mp)->m_hdr.mh_data));
641
642 /*
643 * Process Hop-by-Hop options header if it's contained.
644 * m may be modified in ip6_hopopts_input().
645 * If a JumboPayload option is included, plen will also be modified.
646 */
647 plen = (u_int32_t)ntohs(ip6->ip6_plen)(__uint16_t)(__builtin_constant_p(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen
) ? (__uint16_t)(((__uint16_t)(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen
) & 0xffU) << 8 | ((__uint16_t)(ip6->ip6_ctlun.ip6_un1
.ip6_un1_plen) & 0xff00U) >> 8) : __swap16md(ip6->
ip6_ctlun.ip6_un1.ip6_un1_plen))
;
648 *offp = sizeof(struct ip6_hdr);
649 if (ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt == IPPROTO_HOPOPTS0) {
650 struct ip6_hbh *hbh;
651
652 if (ip6_hopopts_input(mp, offp, &plen, &rtalert))
653 goto bad; /* m have already been freed */
654
655 /* adjust pointer */
656 ip6 = mtod(*mp, struct ip6_hdr *)((struct ip6_hdr *)((*mp)->m_hdr.mh_data));
657
658 /*
659 * if the payload length field is 0 and the next header field
660 * indicates Hop-by-Hop Options header, then a Jumbo Payload
661 * option MUST be included.
662 */
663 if (ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen == 0 && plen == 0) {
664 /*
665 * Note that if a valid jumbo payload option is
666 * contained, ip6_hopopts_input() must set a valid
667 * (non-zero) payload length to the variable plen.
668 */
669 ip6stat_inc(ip6s_badoptions);
670 icmp6_error(*mp, ICMP6_PARAM_PROB4,
671 ICMP6_PARAMPROB_HEADER0,
672 (caddr_t)&ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen - (caddr_t)ip6);
673 goto bad;
674 }
675 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, *mp,do { struct mbuf *t; int tmp; if ((*mp)->m_hdr.mh_len >=
(sizeof(struct ip6_hdr)) + (sizeof(struct ip6_hbh))) (hbh) =
(struct ip6_hbh *)(((caddr_t)(((*mp))->m_hdr.mh_data)) + (
sizeof(struct ip6_hdr))); else { t = m_pulldown((*mp), (sizeof
(struct ip6_hdr)), (sizeof(struct ip6_hbh)), &tmp); if (t
) { if (t->m_hdr.mh_len < tmp + (sizeof(struct ip6_hbh)
)) panic("m_pulldown malfunction"); (hbh) = (struct ip6_hbh *
)(((caddr_t)((t)->m_hdr.mh_data)) + tmp); } else { (hbh) =
(struct ip6_hbh *)((void *)0); (*mp) = ((void *)0); } } } while
( 0)
676 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh))do { struct mbuf *t; int tmp; if ((*mp)->m_hdr.mh_len >=
(sizeof(struct ip6_hdr)) + (sizeof(struct ip6_hbh))) (hbh) =
(struct ip6_hbh *)(((caddr_t)(((*mp))->m_hdr.mh_data)) + (
sizeof(struct ip6_hdr))); else { t = m_pulldown((*mp), (sizeof
(struct ip6_hdr)), (sizeof(struct ip6_hbh)), &tmp); if (t
) { if (t->m_hdr.mh_len < tmp + (sizeof(struct ip6_hbh)
)) panic("m_pulldown malfunction"); (hbh) = (struct ip6_hbh *
)(((caddr_t)((t)->m_hdr.mh_data)) + tmp); } else { (hbh) =
(struct ip6_hbh *)((void *)0); (*mp) = ((void *)0); } } } while
( 0)
;
677 if (hbh == NULL((void *)0)) {
678 ip6stat_inc(ip6s_tooshort);
679 goto bad;
680 }
681 nxt = hbh->ip6h_nxt;
682
683 /*
684 * accept the packet if a router alert option is included
685 * and we act as an IPv6 router.
686 */
687 if (rtalert != ~0 && ip6_forwarding && oursp != NULL((void *)0))
688 *oursp = 1;
689 } else
690 nxt = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
691
692 /*
693 * Check that the amount of data in the buffers
694 * is as at least much as the IPv6 header would have us expect.
695 * Trim mbufs if longer than we expect.
696 * Drop packet if shorter than we expect.
697 */
698 if ((*mp)->m_pkthdrM_dat.MH.MH_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
699 ip6stat_inc(ip6s_tooshort);
700 m_freemp(mp);
701 goto bad;
702 }
703 if ((*mp)->m_pkthdrM_dat.MH.MH_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
704 if ((*mp)->m_lenm_hdr.mh_len == (*mp)->m_pkthdrM_dat.MH.MH_pkthdr.len) {
705 (*mp)->m_lenm_hdr.mh_len = sizeof(struct ip6_hdr) + plen;
706 (*mp)->m_pkthdrM_dat.MH.MH_pkthdr.len = sizeof(struct ip6_hdr) + plen;
707 } else {
708 m_adj((*mp), sizeof(struct ip6_hdr) + plen -
709 (*mp)->m_pkthdrM_dat.MH.MH_pkthdr.len);
710 }
711 }
712
713 return nxt;
714 bad:
715 return IPPROTO_DONE257;
716}
717
718/* scan packet for RH0 routing header. Mostly stolen from pf.c:pf_test() */
719int
720ip6_check_rh0hdr(struct mbuf *m, int *offp)
721{
722 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
723 struct ip6_rthdr rthdr;
724 struct ip6_ext opt6;
725 u_int8_t proto = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
726 int done = 0, lim, off, rh_cnt = 0;
727
728 off = ((caddr_t)ip6 - m->m_datam_hdr.mh_data) + sizeof(struct ip6_hdr);
729 lim = min(m->m_pkthdrM_dat.MH.MH_pkthdr.len, ntohs(ip6->ip6_plen)(__uint16_t)(__builtin_constant_p(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen
) ? (__uint16_t)(((__uint16_t)(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen
) & 0xffU) << 8 | ((__uint16_t)(ip6->ip6_ctlun.ip6_un1
.ip6_un1_plen) & 0xff00U) >> 8) : __swap16md(ip6->
ip6_ctlun.ip6_un1.ip6_un1_plen))
+ sizeof(*ip6));
730 do {
731 switch (proto) {
732 case IPPROTO_ROUTING43:
733 if (rh_cnt++) {
734 /* more than one rh header present */
735 *offp = off;
736 return (1);
737 }
738
739 if (off + sizeof(rthdr) > lim) {
740 /* packet to short to make sense */
741 *offp = off;
742 return (1);
743 }
744
745 m_copydata(m, off, sizeof(rthdr), &rthdr);
746
747 if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_00) {
748 *offp = off +
749 offsetof(struct ip6_rthdr, ip6r_type)__builtin_offsetof(struct ip6_rthdr, ip6r_type);
750 return (1);
751 }
752
753 off += (rthdr.ip6r_len + 1) * 8;
754 proto = rthdr.ip6r_nxt;
755 break;
756 case IPPROTO_AH51:
757 case IPPROTO_HOPOPTS0:
758 case IPPROTO_DSTOPTS60:
759 /* get next header and header length */
760 if (off + sizeof(opt6) > lim) {
761 /*
762 * Packet to short to make sense, we could
763 * reject the packet but as a router we
764 * should not do that so forward it.
765 */
766 return (0);
767 }
768
769 m_copydata(m, off, sizeof(opt6), &opt6);
770
771 if (proto == IPPROTO_AH51)
772 off += (opt6.ip6e_len + 2) * 4;
773 else
774 off += (opt6.ip6e_len + 1) * 8;
775 proto = opt6.ip6e_nxt;
776 break;
777 case IPPROTO_FRAGMENT44:
778 default:
779 /* end of header stack */
780 done = 1;
781 break;
782 }
783 } while (!done);
784
785 return (0);
786}
787
788/*
789 * Hop-by-Hop options header processing. If a valid jumbo payload option is
790 * included, the real payload length will be stored in plenp.
791 * On error free mbuf and return -1.
792 *
793 * rtalertp - XXX: should be stored in a more smart way
794 */
795int
796ip6_hopopts_input(struct mbuf **mp, int *offp, u_int32_t *plenp,
797 u_int32_t *rtalertp)
798{
799 int off = *offp, hbhlen;
800 struct ip6_hbh *hbh;
801
802 /* validation of the length of the header */
803 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, *mp,do { struct mbuf *t; int tmp; if ((*mp)->m_hdr.mh_len >=
(sizeof(struct ip6_hdr)) + (sizeof(struct ip6_hbh))) (hbh) =
(struct ip6_hbh *)(((caddr_t)(((*mp))->m_hdr.mh_data)) + (
sizeof(struct ip6_hdr))); else { t = m_pulldown((*mp), (sizeof
(struct ip6_hdr)), (sizeof(struct ip6_hbh)), &tmp); if (t
) { if (t->m_hdr.mh_len < tmp + (sizeof(struct ip6_hbh)
)) panic("m_pulldown malfunction"); (hbh) = (struct ip6_hbh *
)(((caddr_t)((t)->m_hdr.mh_data)) + tmp); } else { (hbh) =
(struct ip6_hbh *)((void *)0); (*mp) = ((void *)0); } } } while
( 0)
804 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh))do { struct mbuf *t; int tmp; if ((*mp)->m_hdr.mh_len >=
(sizeof(struct ip6_hdr)) + (sizeof(struct ip6_hbh))) (hbh) =
(struct ip6_hbh *)(((caddr_t)(((*mp))->m_hdr.mh_data)) + (
sizeof(struct ip6_hdr))); else { t = m_pulldown((*mp), (sizeof
(struct ip6_hdr)), (sizeof(struct ip6_hbh)), &tmp); if (t
) { if (t->m_hdr.mh_len < tmp + (sizeof(struct ip6_hbh)
)) panic("m_pulldown malfunction"); (hbh) = (struct ip6_hbh *
)(((caddr_t)((t)->m_hdr.mh_data)) + tmp); } else { (hbh) =
(struct ip6_hbh *)((void *)0); (*mp) = ((void *)0); } } } while
( 0)
;
805 if (hbh == NULL((void *)0)) {
806 ip6stat_inc(ip6s_tooshort);
807 return -1;
808 }
809 hbhlen = (hbh->ip6h_len + 1) << 3;
810 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, *mp, sizeof(struct ip6_hdr),do { struct mbuf *t; int tmp; if ((*mp)->m_hdr.mh_len >=
(sizeof(struct ip6_hdr)) + (hbhlen)) (hbh) = (struct ip6_hbh
*)(((caddr_t)(((*mp))->m_hdr.mh_data)) + (sizeof(struct ip6_hdr
))); else { t = m_pulldown((*mp), (sizeof(struct ip6_hdr)), (
hbhlen), &tmp); if (t) { if (t->m_hdr.mh_len < tmp +
(hbhlen)) panic("m_pulldown malfunction"); (hbh) = (struct ip6_hbh
*)(((caddr_t)((t)->m_hdr.mh_data)) + tmp); } else { (hbh)
= (struct ip6_hbh *)((void *)0); (*mp) = ((void *)0); } } } while
( 0)
811 hbhlen)do { struct mbuf *t; int tmp; if ((*mp)->m_hdr.mh_len >=
(sizeof(struct ip6_hdr)) + (hbhlen)) (hbh) = (struct ip6_hbh
*)(((caddr_t)(((*mp))->m_hdr.mh_data)) + (sizeof(struct ip6_hdr
))); else { t = m_pulldown((*mp), (sizeof(struct ip6_hdr)), (
hbhlen), &tmp); if (t) { if (t->m_hdr.mh_len < tmp +
(hbhlen)) panic("m_pulldown malfunction"); (hbh) = (struct ip6_hbh
*)(((caddr_t)((t)->m_hdr.mh_data)) + tmp); } else { (hbh)
= (struct ip6_hbh *)((void *)0); (*mp) = ((void *)0); } } } while
( 0)
;
812 if (hbh == NULL((void *)0)) {
813 ip6stat_inc(ip6s_tooshort);
814 return -1;
815 }
816 off += hbhlen;
817 hbhlen -= sizeof(struct ip6_hbh);
818
819 if (ip6_process_hopopts(mp, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
820 hbhlen, rtalertp, plenp) < 0)
821 return (-1);
822
823 *offp = off;
824 return (0);
825}
826
827/*
828 * Search header for all Hop-by-hop options and process each option.
829 * This function is separate from ip6_hopopts_input() in order to
830 * handle a case where the sending node itself process its hop-by-hop
831 * options header. In such a case, the function is called from ip6_output().
832 * On error free mbuf and return -1.
833 *
834 * The function assumes that hbh header is located right after the IPv6 header
835 * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
836 * opthead + hbhlen is located in continuous memory region.
837 */
838int
839ip6_process_hopopts(struct mbuf **mp, u_int8_t *opthead, int hbhlen,
840 u_int32_t *rtalertp, u_int32_t *plenp)
841{
842 struct ip6_hdr *ip6;
843 int optlen = 0;
844 u_int8_t *opt = opthead;
845 u_int16_t rtalert_val;
846 u_int32_t jumboplen;
847 const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
848
849 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
850 switch (*opt) {
851 case IP6OPT_PAD10x00:
852 optlen = 1;
853 break;
854 case IP6OPT_PADN0x01:
855 if (hbhlen < IP6OPT_MINLEN2) {
856 ip6stat_inc(ip6s_toosmall);
857 goto bad;
858 }
859 optlen = *(opt + 1) + 2;
860 break;
861 case IP6OPT_ROUTER_ALERT0x05:
862 /* XXX may need check for alignment */
863 if (hbhlen < IP6OPT_RTALERT_LEN4) {
864 ip6stat_inc(ip6s_toosmall);
865 goto bad;
866 }
867 if (*(opt + 1) != IP6OPT_RTALERT_LEN4 - 2) {
868 /* XXX stat */
869 icmp6_error(*mp, ICMP6_PARAM_PROB4,
870 ICMP6_PARAMPROB_HEADER0,
871 erroff + opt + 1 - opthead);
872 return (-1);
873 }
874 optlen = IP6OPT_RTALERT_LEN4;
875 memcpy((caddr_t)&rtalert_val, (caddr_t)(opt + 2), 2)__builtin_memcpy(((caddr_t)&rtalert_val), ((caddr_t)(opt +
2)), (2))
;
876 *rtalertp = ntohs(rtalert_val)(__uint16_t)(__builtin_constant_p(rtalert_val) ? (__uint16_t)
(((__uint16_t)(rtalert_val) & 0xffU) << 8 | ((__uint16_t
)(rtalert_val) & 0xff00U) >> 8) : __swap16md(rtalert_val
))
;
877 break;
878 case IP6OPT_JUMBO0xC2:
879 /* XXX may need check for alignment */
880 if (hbhlen < IP6OPT_JUMBO_LEN6) {
881 ip6stat_inc(ip6s_toosmall);
882 goto bad;
883 }
884 if (*(opt + 1) != IP6OPT_JUMBO_LEN6 - 2) {
885 /* XXX stat */
886 icmp6_error(*mp, ICMP6_PARAM_PROB4,
887 ICMP6_PARAMPROB_HEADER0,
888 erroff + opt + 1 - opthead);
889 return (-1);
890 }
891 optlen = IP6OPT_JUMBO_LEN6;
892
893 /*
894 * IPv6 packets that have non 0 payload length
895 * must not contain a jumbo payload option.
896 */
897 ip6 = mtod(*mp, struct ip6_hdr *)((struct ip6_hdr *)((*mp)->m_hdr.mh_data));
898 if (ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen) {
899 ip6stat_inc(ip6s_badoptions);
900 icmp6_error(*mp, ICMP6_PARAM_PROB4,
901 ICMP6_PARAMPROB_HEADER0,
902 erroff + opt - opthead);
903 return (-1);
904 }
905
906 /*
907 * We may see jumbolen in unaligned location, so
908 * we'd need to perform memcpy().
909 */
910 memcpy(&jumboplen, opt + 2, sizeof(jumboplen))__builtin_memcpy((&jumboplen), (opt + 2), (sizeof(jumboplen
)))
;
911 jumboplen = (u_int32_t)htonl(jumboplen)(__uint32_t)(__builtin_constant_p(jumboplen) ? (__uint32_t)((
(__uint32_t)(jumboplen) & 0xff) << 24 | ((__uint32_t
)(jumboplen) & 0xff00) << 8 | ((__uint32_t)(jumboplen
) & 0xff0000) >> 8 | ((__uint32_t)(jumboplen) &
0xff000000) >> 24) : __swap32md(jumboplen))
;
912
913#if 1
914 /*
915 * if there are multiple jumbo payload options,
916 * *plenp will be non-zero and the packet will be
917 * rejected.
918 * the behavior may need some debate in ipngwg -
919 * multiple options does not make sense, however,
920 * there's no explicit mention in specification.
921 */
922 if (*plenp != 0) {
923 ip6stat_inc(ip6s_badoptions);
924 icmp6_error(*mp, ICMP6_PARAM_PROB4,
925 ICMP6_PARAMPROB_HEADER0,
926 erroff + opt + 2 - opthead);
927 return (-1);
928 }
929#endif
930
931 /*
932 * jumbo payload length must be larger than 65535.
933 */
934 if (jumboplen <= IPV6_MAXPACKET65535) {
935 ip6stat_inc(ip6s_badoptions);
936 icmp6_error(*mp, ICMP6_PARAM_PROB4,
937 ICMP6_PARAMPROB_HEADER0,
938 erroff + opt + 2 - opthead);
939 return (-1);
940 }
941 *plenp = jumboplen;
942
943 break;
944 default: /* unknown option */
945 if (hbhlen < IP6OPT_MINLEN2) {
946 ip6stat_inc(ip6s_toosmall);
947 goto bad;
948 }
949 optlen = ip6_unknown_opt(mp, opt,
950 erroff + opt - opthead);
951 if (optlen == -1)
952 return (-1);
953 optlen += 2;
954 break;
955 }
956 }
957
958 return (0);
959
960 bad:
961 m_freemp(mp);
962 return (-1);
963}
964
965/*
966 * Unknown option processing.
967 * The third argument `off' is the offset from the IPv6 header to the option,
968 * which allows returning an ICMPv6 error even if the IPv6 header and the
969 * option header are not continuous.
970 * On error free mbuf and return -1.
971 */
972int
973ip6_unknown_opt(struct mbuf **mp, u_int8_t *optp, int off)
974{
975 struct ip6_hdr *ip6;
976
977 switch (IP6OPT_TYPE(*optp)((*optp) & 0xC0)) {
978 case IP6OPT_TYPE_SKIP0x00: /* ignore the option */
979 return ((int)*(optp + 1));
980 case IP6OPT_TYPE_DISCARD0x40: /* silently discard */
981 m_freemp(mp);
982 return (-1);
983 case IP6OPT_TYPE_FORCEICMP0x80: /* send ICMP even if multicasted */
984 ip6stat_inc(ip6s_badoptions);
985 icmp6_error(*mp, ICMP6_PARAM_PROB4, ICMP6_PARAMPROB_OPTION2, off);
986 return (-1);
987 case IP6OPT_TYPE_ICMP0xC0: /* send ICMP if not multicasted */
988 ip6stat_inc(ip6s_badoptions);
989 ip6 = mtod(*mp, struct ip6_hdr *)((struct ip6_hdr *)((*mp)->m_hdr.mh_data));
990 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff) ||
991 ((*mp)->m_flagsm_hdr.mh_flags & (M_BCAST0x0100|M_MCAST0x0200)))
992 m_freemp(mp);
993 else
994 icmp6_error(*mp, ICMP6_PARAM_PROB4,
995 ICMP6_PARAMPROB_OPTION2, off);
996 return (-1);
997 }
998
999 m_freemp(mp); /* XXX: NOTREACHED */
1000 return (-1);
1001}
1002
1003/*
1004 * Create the "control" list for this pcb.
1005 *
1006 * The routine will be called from upper layer handlers like udp_input().
1007 * Thus the routine assumes that the caller (udp_input) have already
1008 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
1009 * very first mbuf on the mbuf chain.
1010 * We may want to add some infinite loop prevention or sanity checks for safety.
1011 * (This applies only when you are using KAME mbuf chain restriction, i.e.
1012 * you are using IP6_EXTHDR_CHECK() not m_pulldown())
1013 */
1014void
1015ip6_savecontrol(struct inpcb *inp, struct mbuf *m, struct mbuf **mp)
1016{
1017 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
1018
1019 if (inp->inp_socket->so_options & SO_TIMESTAMP0x0800) {
1020 struct timeval tv;
1021
1022 m_microtime(m, &tv);
1023 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1024 SCM_TIMESTAMP0x04, SOL_SOCKET0xffff);
1025 if (*mp)
1026 mp = &(*mp)->m_nextm_hdr.mh_next;
1027 }
1028
1029 /* RFC 2292 sec. 5 */
1030 if ((inp->inp_flags & IN6P_PKTINFO0x010000) != 0) {
1031 struct in6_pktinfo pi6;
1032 memcpy(&pi6.ipi6_addr, &ip6->ip6_dst, sizeof(struct in6_addr))__builtin_memcpy((&pi6.ipi6_addr), (&ip6->ip6_dst)
, (sizeof(struct in6_addr)))
;
1033 if (IN6_IS_SCOPE_EMBED(&pi6.ipi6_addr)(((((&pi6.ipi6_addr)->__u6_addr.__u6_addr8[0] == 0xfe)
&& (((&pi6.ipi6_addr)->__u6_addr.__u6_addr8[1
] & 0xc0) == 0x80))) || ((((&pi6.ipi6_addr)->__u6_addr
.__u6_addr8[0] == 0xff) && (((&pi6.ipi6_addr)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((&pi6
.ipi6_addr)->__u6_addr.__u6_addr8[0] == 0xff) && (
((&pi6.ipi6_addr)->__u6_addr.__u6_addr8[1] & 0x0f)
== 0x01))))
)
1034 pi6.ipi6_addr.s6_addr16__u6_addr.__u6_addr16[1] = 0;
1035 pi6.ipi6_ifindex = m ? m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx : 0;
1036 *mp = sbcreatecontrol((caddr_t) &pi6,
1037 sizeof(struct in6_pktinfo),
1038 IPV6_PKTINFO46, IPPROTO_IPV641);
1039 if (*mp)
1040 mp = &(*mp)->m_nextm_hdr.mh_next;
1041 }
1042
1043 if ((inp->inp_flags & IN6P_HOPLIMIT0x020000) != 0) {
1044 int hlim = ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim & 0xff;
1045 *mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int),
1046 IPV6_HOPLIMIT47, IPPROTO_IPV641);
1047 if (*mp)
1048 mp = &(*mp)->m_nextm_hdr.mh_next;
1049 }
1050
1051 if ((inp->inp_flags & IN6P_TCLASS0x400000) != 0) {
1052 u_int32_t flowinfo;
1053 int tclass;
1054
1055 flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK)(__uint32_t)(__builtin_constant_p(ip6->ip6_ctlun.ip6_un1.ip6_un1_flow
& 0xffffff0f) ? (__uint32_t)(((__uint32_t)(ip6->ip6_ctlun
.ip6_un1.ip6_un1_flow & 0xffffff0f) & 0xff) << 24
| ((__uint32_t)(ip6->ip6_ctlun.ip6_un1.ip6_un1_flow &
0xffffff0f) & 0xff00) << 8 | ((__uint32_t)(ip6->
ip6_ctlun.ip6_un1.ip6_un1_flow & 0xffffff0f) & 0xff0000
) >> 8 | ((__uint32_t)(ip6->ip6_ctlun.ip6_un1.ip6_un1_flow
& 0xffffff0f) & 0xff000000) >> 24) : __swap32md
(ip6->ip6_ctlun.ip6_un1.ip6_un1_flow & 0xffffff0f))
;
1056 flowinfo >>= 20;
1057
1058 tclass = flowinfo & 0xff;
1059 *mp = sbcreatecontrol((caddr_t)&tclass, sizeof(tclass),
1060 IPV6_TCLASS61, IPPROTO_IPV641);
1061 if (*mp)
1062 mp = &(*mp)->m_nextm_hdr.mh_next;
1063 }
1064
1065 /*
1066 * IPV6_HOPOPTS socket option. Recall that we required super-user
1067 * privilege for the option (see ip6_ctloutput), but it might be too
1068 * strict, since there might be some hop-by-hop options which can be
1069 * returned to normal user.
1070 * See also RFC 2292 section 6 (or RFC 3542 section 8).
1071 */
1072 if ((inp->inp_flags & IN6P_HOPOPTS0x040000) != 0) {
1073 /*
1074 * Check if a hop-by-hop options header is contained in the
1075 * received packet, and if so, store the options as ancillary
1076 * data. Note that a hop-by-hop options header must be
1077 * just after the IPv6 header, which is assured through the
1078 * IPv6 input processing.
1079 */
1080 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
1081 if (ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt == IPPROTO_HOPOPTS0) {
1082 struct ip6_hbh *hbh;
1083 int hbhlen = 0;
1084 struct mbuf *ext;
1085
1086 ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
1087 ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt);
1088 if (ext == NULL((void *)0)) {
1089 ip6stat_inc(ip6s_tooshort);
1090 return;
1091 }
1092 hbh = mtod(ext, struct ip6_hbh *)((struct ip6_hbh *)((ext)->m_hdr.mh_data));
1093 hbhlen = (hbh->ip6h_len + 1) << 3;
1094 if (hbhlen != ext->m_lenm_hdr.mh_len) {
1095 m_freem(ext);
1096 ip6stat_inc(ip6s_tooshort);
1097 return;
1098 }
1099
1100 /*
1101 * XXX: We copy the whole header even if a
1102 * jumbo payload option is included, the option which
1103 * is to be removed before returning according to
1104 * RFC2292.
1105 * Note: this constraint is removed in RFC3542.
1106 */
1107 *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1108 IPV6_HOPOPTS49,
1109 IPPROTO_IPV641);
1110 if (*mp)
1111 mp = &(*mp)->m_nextm_hdr.mh_next;
1112 m_freem(ext);
1113 }
1114 }
1115
1116 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
1117 if ((inp->inp_flags & (IN6P_RTHDR0x100000 | IN6P_DSTOPTS0x080000)) != 0) {
1118 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
1119 int nxt = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt, off = sizeof(struct ip6_hdr);
1120
1121 /*
1122 * Search for destination options headers or routing
1123 * header(s) through the header chain, and stores each
1124 * header as ancillary data.
1125 * Note that the order of the headers remains in
1126 * the chain of ancillary data.
1127 */
1128 while (1) { /* is explicit loop prevention necessary? */
1129 struct ip6_ext *ip6e = NULL((void *)0);
1130 int elen;
1131 struct mbuf *ext = NULL((void *)0);
1132
1133 /*
1134 * if it is not an extension header, don't try to
1135 * pull it from the chain.
1136 */
1137 switch (nxt) {
1138 case IPPROTO_DSTOPTS60:
1139 case IPPROTO_ROUTING43:
1140 case IPPROTO_HOPOPTS0:
1141 case IPPROTO_AH51: /* is it possible? */
1142 break;
1143 default:
1144 goto loopend;
1145 }
1146
1147 ext = ip6_pullexthdr(m, off, nxt);
1148 if (ext == NULL((void *)0)) {
1149 ip6stat_inc(ip6s_tooshort);
1150 return;
1151 }
1152 ip6e = mtod(ext, struct ip6_ext *)((struct ip6_ext *)((ext)->m_hdr.mh_data));
1153 if (nxt == IPPROTO_AH51)
1154 elen = (ip6e->ip6e_len + 2) << 2;
1155 else
1156 elen = (ip6e->ip6e_len + 1) << 3;
1157 if (elen != ext->m_lenm_hdr.mh_len) {
1158 m_freem(ext);
1159 ip6stat_inc(ip6s_tooshort);
1160 return;
1161 }
1162
1163 switch (nxt) {
1164 case IPPROTO_DSTOPTS60:
1165 if (!(inp->inp_flags & IN6P_DSTOPTS0x080000))
1166 break;
1167
1168 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1169 IPV6_DSTOPTS50,
1170 IPPROTO_IPV641);
1171 if (*mp)
1172 mp = &(*mp)->m_nextm_hdr.mh_next;
1173 break;
1174
1175 case IPPROTO_ROUTING43:
1176 if (!(inp->inp_flags & IN6P_RTHDR0x100000))
1177 break;
1178
1179 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1180 IPV6_RTHDR51,
1181 IPPROTO_IPV641);
1182 if (*mp)
1183 mp = &(*mp)->m_nextm_hdr.mh_next;
1184 break;
1185
1186 case IPPROTO_HOPOPTS0:
1187 case IPPROTO_AH51: /* is it possible? */
1188 break;
1189
1190 default:
1191 /*
1192 * other cases have been filtered in the above.
1193 * none will visit this case. here we supply
1194 * the code just in case (nxt overwritten or
1195 * other cases).
1196 */
1197 m_freem(ext);
1198 goto loopend;
1199
1200 }
1201
1202 /* proceed with the next header. */
1203 off += elen;
1204 nxt = ip6e->ip6e_nxt;
1205 ip6e = NULL((void *)0);
1206 m_freem(ext);
1207 ext = NULL((void *)0);
1208 }
1209loopend:
1210 ;
1211 }
1212}
1213
1214/*
1215 * pull single extension header from mbuf chain. returns single mbuf that
1216 * contains the result, or NULL on error.
1217 */
1218struct mbuf *
1219ip6_pullexthdr(struct mbuf *m, size_t off, int nxt)
1220{
1221 struct ip6_ext ip6e;
1222 size_t elen;
1223 struct mbuf *n;
1224
1225#ifdef DIAGNOSTIC1
1226 switch (nxt) {
1227 case IPPROTO_DSTOPTS60:
1228 case IPPROTO_ROUTING43:
1229 case IPPROTO_HOPOPTS0:
1230 case IPPROTO_AH51: /* is it possible? */
1231 break;
1232 default:
1233 printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
1234 }
1235#endif
1236
1237 if (off + sizeof(ip6e) > m->m_pkthdrM_dat.MH.MH_pkthdr.len)
1238 return NULL((void *)0);
1239
1240 m_copydata(m, off, sizeof(ip6e), &ip6e);
1241 if (nxt == IPPROTO_AH51)
1242 elen = (ip6e.ip6e_len + 2) << 2;
1243 else
1244 elen = (ip6e.ip6e_len + 1) << 3;
1245
1246 if (off + elen > m->m_pkthdrM_dat.MH.MH_pkthdr.len)
1247 return NULL((void *)0);
1248
1249 MGET(n, M_DONTWAIT, MT_DATA)n = m_get((0x0002), (1));
1250 if (n && elen >= MLEN(256 - sizeof(struct m_hdr))) {
1251 MCLGET(n, M_DONTWAIT)(void) m_clget((n), (0x0002), (1 << 11));
1252 if ((n->m_flagsm_hdr.mh_flags & M_EXT0x0001) == 0) {
1253 m_free(n);
1254 n = NULL((void *)0);
1255 }
1256 }
1257 if (n == NULL((void *)0)) {
1258 ip6stat_inc(ip6s_idropped);
1259 return NULL((void *)0);
1260 }
1261
1262 n->m_lenm_hdr.mh_len = 0;
1263 if (elen >= m_trailingspace(n)) {
1264 m_free(n);
1265 return NULL((void *)0);
1266 }
1267
1268 m_copydata(m, off, elen, mtod(n, caddr_t)((caddr_t)((n)->m_hdr.mh_data)));
1269 n->m_lenm_hdr.mh_len = elen;
1270 return n;
1271}
1272
1273/*
1274 * Get offset to the previous header followed by the header
1275 * currently processed.
1276 */
1277int
1278ip6_get_prevhdr(struct mbuf *m, int off)
1279{
1280 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
1281
1282 if (off == sizeof(struct ip6_hdr)) {
1283 return offsetof(struct ip6_hdr, ip6_nxt)__builtin_offsetof(struct ip6_hdr, ip6_ctlun.ip6_un1.ip6_un1_nxt
)
;
1284 } else if (off < sizeof(struct ip6_hdr)) {
1285 panic("%s: off < sizeof(struct ip6_hdr)", __func__);
1286 } else {
1287 int len, nlen, nxt;
1288 struct ip6_ext ip6e;
1289
1290 nxt = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
1291 len = sizeof(struct ip6_hdr);
1292 nlen = 0;
1293 while (len < off) {
1294 m_copydata(m, len, sizeof(ip6e), &ip6e);
1295
1296 switch (nxt) {
1297 case IPPROTO_FRAGMENT44:
1298 nlen = sizeof(struct ip6_frag);
1299 break;
1300 case IPPROTO_AH51:
1301 nlen = (ip6e.ip6e_len + 2) << 2;
1302 break;
1303 default:
1304 nlen = (ip6e.ip6e_len + 1) << 3;
1305 break;
1306 }
1307 len += nlen;
1308 nxt = ip6e.ip6e_nxt;
1309 }
1310
1311 return (len - nlen);
1312 }
1313}
1314
1315/*
1316 * get next header offset. m will be retained.
1317 */
1318int
1319ip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp)
1320{
1321 struct ip6_hdr ip6;
1322 struct ip6_ext ip6e;
1323 struct ip6_frag fh;
1324
1325 /* just in case */
1326 if (m == NULL((void *)0))
1327 panic("%s: m == NULL", __func__);
1328 if ((m->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002) == 0 || m->m_pkthdrM_dat.MH.MH_pkthdr.len < off)
1329 return -1;
1330
1331 switch (proto) {
1332 case IPPROTO_IPV641:
1333 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < off + sizeof(ip6))
1334 return -1;
1335 m_copydata(m, off, sizeof(ip6), &ip6);
1336 if (nxtp)
1337 *nxtp = ip6.ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
1338 off += sizeof(ip6);
1339 return off;
1340
1341 case IPPROTO_FRAGMENT44:
1342 /*
1343 * terminate parsing if it is not the first fragment,
1344 * it does not make sense to parse through it.
1345 */
1346 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < off + sizeof(fh))
1347 return -1;
1348 m_copydata(m, off, sizeof(fh), &fh);
1349 if ((fh.ip6f_offlg & IP6F_OFF_MASK0xf8ff) != 0)
1350 return -1;
1351 if (nxtp)
1352 *nxtp = fh.ip6f_nxt;
1353 off += sizeof(struct ip6_frag);
1354 return off;
1355
1356 case IPPROTO_AH51:
1357 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < off + sizeof(ip6e))
1358 return -1;
1359 m_copydata(m, off, sizeof(ip6e), &ip6e);
1360 if (nxtp)
1361 *nxtp = ip6e.ip6e_nxt;
1362 off += (ip6e.ip6e_len + 2) << 2;
1363 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < off)
1364 return -1;
1365 return off;
1366
1367 case IPPROTO_HOPOPTS0:
1368 case IPPROTO_ROUTING43:
1369 case IPPROTO_DSTOPTS60:
1370 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < off + sizeof(ip6e))
1371 return -1;
1372 m_copydata(m, off, sizeof(ip6e), &ip6e);
1373 if (nxtp)
1374 *nxtp = ip6e.ip6e_nxt;
1375 off += (ip6e.ip6e_len + 1) << 3;
1376 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < off)
1377 return -1;
1378 return off;
1379
1380 case IPPROTO_NONE59:
1381 case IPPROTO_ESP50:
1382 case IPPROTO_IPCOMP108:
1383 /* give up */
1384 return -1;
1385
1386 default:
1387 return -1;
1388 }
1389
1390 return -1;
1391}
1392
1393/*
1394 * get offset for the last header in the chain. m will be kept untainted.
1395 */
1396int
1397ip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp)
1398{
1399 int newoff;
1400 int nxt;
1401
1402 if (!nxtp) {
1403 nxt = -1;
1404 nxtp = &nxt;
1405 }
1406 while (1) {
1407 newoff = ip6_nexthdr(m, off, proto, nxtp);
1408 if (newoff < 0)
1409 return off;
1410 else if (newoff < off)
1411 return -1; /* invalid */
1412 else if (newoff == off)
1413 return newoff;
1414
1415 off = newoff;
1416 proto = *nxtp;
1417 }
1418}
1419
1420/*
1421 * System control for IP6
1422 */
1423
1424const u_char inet6ctlerrmap[PRC_NCMDS21] = {
1425 0, 0, 0, 0,
1426 0, EMSGSIZE40, EHOSTDOWN64, EHOSTUNREACH65,
1427 EHOSTUNREACH65, EHOSTUNREACH65, ECONNREFUSED61, ECONNREFUSED61,
1428 EMSGSIZE40, EHOSTUNREACH65, 0, 0,
1429 0, 0, 0, 0,
1430 ENOPROTOOPT42
1431};
1432
1433#ifdef MROUTING1
1434extern int ip6_mrtproto;
1435#endif
1436
1437const struct sysctl_bounded_args ipv6ctl_vars[] = {
1438 { IPV6CTL_DAD_PENDING49, &ip6_dad_pending, SYSCTL_INT_READONLY1,0 },
1439#ifdef MROUTING1
1440 { IPV6CTL_MRTPROTO8, &ip6_mrtproto, SYSCTL_INT_READONLY1,0 },
1441#endif
1442 { IPV6CTL_FORWARDING1, &ip6_forwarding, 0, 1 },
1443 { IPV6CTL_SENDREDIRECTS2, &ip6_sendredirects, 0, 1 },
1444 { IPV6CTL_DEFHLIM3, &ip6_defhlim, 0, 255 },
1445 { IPV6CTL_MAXFRAGPACKETS9, &ip6_maxfragpackets, 0, 1000 },
1446 { IPV6CTL_LOG_INTERVAL14, &ip6_log_interval, 0, INT_MAX0x7fffffff },
1447 { IPV6CTL_HDRNESTLIMIT15, &ip6_hdrnestlimit, 0, 100 },
1448 { IPV6CTL_DAD_COUNT16, &ip6_dad_count, 0, 10 },
1449 { IPV6CTL_AUTO_FLOWLABEL17, &ip6_auto_flowlabel, 0, 1 },
1450 { IPV6CTL_DEFMCASTHLIM18, &ip6_defmcasthlim, 0, 255 },
1451 { IPV6CTL_USE_DEPRECATED21, &ip6_use_deprecated, 0, 1 },
1452 { IPV6CTL_MAXFRAGS41, &ip6_maxfrags, 0, 1000 },
1453 { IPV6CTL_MFORWARDING42, &ip6_mforwarding, 0, 1 },
1454 { IPV6CTL_MULTIPATH43, &ip6_multipath, 0, 1 },
1455 { IPV6CTL_MCAST_PMTU44, &ip6_mcast_pmtu, 0, 1 },
1456 { IPV6CTL_NEIGHBORGCTHRESH45, &ip6_neighborgcthresh, -1, 5 * 2048 },
1457 { IPV6CTL_MAXDYNROUTES48, &ip6_maxdynroutes, -1, 5 * 4096 },
1458};
1459
1460int
1461ip6_sysctl_ip6stat(void *oldp, size_t *oldlenp, void *newp)
1462{
1463 struct ip6stat *ip6stat;
1464 int ret;
1465
1466 CTASSERT(sizeof(*ip6stat) == (ip6s_ncounters * sizeof(uint64_t)))extern char _ctassert[(sizeof(*ip6stat) == (ip6s_ncounters * sizeof
(uint64_t))) ? 1 : -1 ] __attribute__((__unused__))
;
1467
1468 ip6stat = malloc(sizeof(*ip6stat), M_TEMP127, M_WAITOK0x0001);
1469 counters_read(ip6counters, (uint64_t *)ip6stat, ip6s_ncounters, NULL((void *)0));
1470 ret = sysctl_rdstruct(oldp, oldlenp, newp,
1471 ip6stat, sizeof(*ip6stat));
1472 free(ip6stat, M_TEMP127, sizeof(*ip6stat));
1473
1474 return (ret);
1475}
1476
1477int
1478ip6_sysctl_soiikey(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1479{
1480 uint8_t oldkey[IP6_SOIIKEY_LEN16];
1481 int error;
1482
1483 error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
1484 if (error != 0)
1485 return (error);
1486
1487 memcpy(oldkey, ip6_soiikey, sizeof(oldkey))__builtin_memcpy((oldkey), (ip6_soiikey), (sizeof(oldkey)));
1488
1489 error = sysctl_struct(oldp, oldlenp, newp, newlen, ip6_soiikey,
1490 sizeof(ip6_soiikey));
1491
1492 return (error);
1493}
1494
1495int
1496ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1497 void *newp, size_t newlen)
1498{
1499#ifdef MROUTING1
1500 extern struct mrt6stat mrt6stat;
1501#endif
1502 int error;
1503
1504 /* Almost all sysctl names at this level are terminal. */
1505 if (namelen != 1 && name[0] != IPV6CTL_IFQUEUE51)
1506 return (ENOTDIR20);
1507
1508 switch (name[0]) {
1509 case IPV6CTL_STATS6:
1510 return (ip6_sysctl_ip6stat(oldp, oldlenp, newp));
1511#ifdef MROUTING1
1512 case IPV6CTL_MRTSTATS7:
1513 if (newp != NULL((void *)0))
1514 return (EPERM1);
1515 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1516 error = sysctl_struct(oldp, oldlenp, newp, newlen,
1517 &mrt6stat, sizeof(mrt6stat));
1518 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1519 return (error);
1520 case IPV6CTL_MRTMIF52:
1521 if (newp)
1522 return (EPERM1);
1523 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1524 error = mrt6_sysctl_mif(oldp, oldlenp);
1525 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1526 return (error);
1527 case IPV6CTL_MRTMFC53:
1528 if (newp)
1529 return (EPERM1);
1530 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1531 error = mrt6_sysctl_mfc(oldp, oldlenp);
1532 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1533 return (error);
1534#else
1535 case IPV6CTL_MRTSTATS7:
1536 case IPV6CTL_MRTPROTO8:
1537 case IPV6CTL_MRTMIF52:
1538 case IPV6CTL_MRTMFC53:
1539 return (EOPNOTSUPP45);
1540#endif
1541 case IPV6CTL_MTUDISCTIMEOUT50:
1542 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1543 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
1544 &ip6_mtudisc_timeout, 0, INT_MAX0x7fffffff);
1545 rt_timer_queue_change(&icmp6_mtudisc_timeout_q,
1546 ip6_mtudisc_timeout);
1547 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1548 return (error);
1549 case IPV6CTL_IFQUEUE51:
1550 return (sysctl_niq(name + 1, namelen - 1,sysctl_mq((name + 1), (namelen - 1), (oldp), (oldlenp), (newp
), (newlen), &(&ip6intrq)->ni_q)
1551 oldp, oldlenp, newp, newlen, &ip6intrq)sysctl_mq((name + 1), (namelen - 1), (oldp), (oldlenp), (newp
), (newlen), &(&ip6intrq)->ni_q)
);
1552 case IPV6CTL_SOIIKEY54:
1553 return (ip6_sysctl_soiikey(oldp, oldlenp, newp, newlen));
1554 default:
1555 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1556 error = sysctl_bounded_arr(ipv6ctl_vars, nitems(ipv6ctl_vars)(sizeof((ipv6ctl_vars)) / sizeof((ipv6ctl_vars)[0])),
1557 name, namelen, oldp, oldlenp, newp, newlen);
1558 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1559 return (error);
1560 }
1561 /* NOTREACHED */
1562}
1563
1564void
1565ip6_send_dispatch(void *xmq)
1566{
1567 struct mbuf_queue *mq = xmq;
1568 struct mbuf *m;
1569 struct mbuf_list ml;
1570
1571 mq_delist(mq, &ml);
1572 if (ml_empty(&ml)((&ml)->ml_len == 0))
1573 return;
1574
1575 NET_LOCK_SHARED()do { rw_enter_read(&netlock); } while (0);
1576 while ((m = ml_dequeue(&ml)) != NULL((void *)0)) {
1577 ip6_output(m, NULL((void *)0), NULL((void *)0), 0, NULL((void *)0), NULL((void *)0));
1578 }
1579 NET_UNLOCK_SHARED()do { rw_exit_read(&netlock); } while (0);
1580}
1581
1582void
1583ip6_send(struct mbuf *m)
1584{
1585 mq_enqueue(&ip6send_mq, m);
1586 task_add(net_tq(0), &ip6send_task);
1587}