Bug Summary

File:netinet6/ip6_output.c
Warning:line 659, 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_output.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_output.c
1/* $OpenBSD: ip6_output.c,v 1.282 2023/12/01 15:30:47 bluhm Exp $ */
2/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 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, 1990, 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_output.c 8.3 (Berkeley) 1/21/94
62 */
63
64#include "pf.h"
65
66#include <sys/param.h>
67#include <sys/malloc.h>
68#include <sys/mbuf.h>
69#include <sys/errno.h>
70#include <sys/protosw.h>
71#include <sys/socket.h>
72#include <sys/socketvar.h>
73#include <sys/proc.h>
74#include <sys/systm.h>
75
76#include <net/if.h>
77#include <net/if_var.h>
78#include <net/if_enc.h>
79#include <net/route.h>
80
81#include <netinet/in.h>
82#include <netinet/ip.h>
83#include <netinet/in_pcb.h>
84#include <netinet/udp.h>
85#include <netinet/tcp.h>
86
87#include <netinet/ip_var.h>
88#include <netinet/tcp_timer.h>
89#include <netinet/tcp_var.h>
90#include <netinet/udp_var.h>
91
92#include <netinet6/in6_var.h>
93#include <netinet/ip6.h>
94#include <netinet/icmp6.h>
95#include <netinet6/ip6_var.h>
96#include <netinet6/nd6.h>
97
98#include <crypto/idgen.h>
99
100#if NPF1 > 0
101#include <net/pfvar.h>
102#endif
103
104#ifdef IPSEC1
105#include <netinet/ip_ipsp.h>
106#include <netinet/ip_ah.h>
107#include <netinet/ip_esp.h>
108
109#ifdef ENCDEBUG
110#define DPRINTF(fmt, args...)do { } while (0) \
111 do { \
112 if (encdebug) \
113 printf("%s: " fmt "\n", __func__, ## args); \
114 } while (0)
115#else
116#define DPRINTF(fmt, args...)do { } while (0) \
117 do { } while (0)
118#endif
119#endif /* IPSEC */
120
121struct ip6_exthdrs {
122 struct mbuf *ip6e_ip6;
123 struct mbuf *ip6e_hbh;
124 struct mbuf *ip6e_dest1;
125 struct mbuf *ip6e_rthdr;
126 struct mbuf *ip6e_dest2;
127};
128
129int ip6_pcbopt(int, u_char *, int, struct ip6_pktopts **, int, int);
130int ip6_getpcbopt(struct ip6_pktopts *, int, struct mbuf *);
131int ip6_setpktopt(int, u_char *, int, struct ip6_pktopts *, int, int, int);
132int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *, unsigned int);
133int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf *);
134int ip6_copyexthdr(struct mbuf **, caddr_t, int);
135int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int,
136 struct ip6_frag **);
137int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t);
138int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
139int ip6_getpmtu(struct rtentry *, struct ifnet *, u_long *);
140int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *);
141static __inline u_int16_t __attribute__((__unused__))
142 in6_cksum_phdr(const struct in6_addr *, const struct in6_addr *,
143 u_int32_t, u_int32_t);
144void in6_delayed_cksum(struct mbuf *, u_int8_t);
145
146int ip6_output_ipsec_pmtu_update(struct tdb *, struct route_in6 *,
147 struct in6_addr *, int, int, int);
148
149/* Context for non-repeating IDs */
150struct idgen32_ctx ip6_id_ctx;
151
152/*
153 * IP6 output. The packet in mbuf chain m contains a skeletal IP6
154 * header (with pri, len, nxt, hlim, src, dst).
155 * This function may modify ver and hlim only.
156 * The mbuf chain containing the packet will be freed.
157 * The mbuf opt, if present, will not be freed.
158 *
159 * type of "mtu": rt_mtu is u_long, ifnet.ifr_mtu is int.
160 * We use u_long to hold largest one, * which is rt_mtu.
161 */
162int
163ip6_output(struct mbuf *m, struct ip6_pktopts *opt, struct route_in6 *ro,
164 int flags, struct ip6_moptions *im6o, const u_char seclevel[])
165{
166 struct ip6_hdr *ip6;
167 struct ifnet *ifp = NULL((void *)0);
168 struct mbuf_list ml;
169 int hlen, tlen;
170 struct route_in6 ip6route;
171 struct rtentry *rt = NULL((void *)0);
172 struct sockaddr_in6 *dst, dstsock;
173 int error = 0;
174 u_long mtu;
175 int dontfrag;
176 u_int16_t src_scope, dst_scope;
1
'dst_scope' declared without an initial value
177 u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
178 struct ip6_exthdrs exthdrs;
179 struct in6_addr finaldst;
180 struct route_in6 *ro_pmtu = NULL((void *)0);
181 int hdrsplit = 0;
182 u_int8_t sproto = 0;
183 u_char nextproto;
184#ifdef IPSEC1
185 struct tdb *tdb = NULL((void *)0);
186#endif /* IPSEC */
187
188 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
189 finaldst = ip6->ip6_dst;
190
191#define MAKE_EXTHDR(hp, mp)do { if (hp) { struct ip6_ext *eh = (struct ip6_ext *)(hp); error
= ip6_copyexthdr((mp), (caddr_t)(hp), ((eh)->ip6e_len + 1
) << 3); if (error) goto freehdrs; } } while (0)
\
192 do { \
193 if (hp) { \
194 struct ip6_ext *eh = (struct ip6_ext *)(hp); \
195 error = ip6_copyexthdr((mp), (caddr_t)(hp), \
196 ((eh)->ip6e_len + 1) << 3); \
197 if (error) \
198 goto freehdrs; \
199 } \
200 } while (0)
201
202 bzero(&exthdrs, sizeof(exthdrs))__builtin_bzero((&exthdrs), (sizeof(exthdrs)));
203
204 if (opt) {
2
Assuming 'opt' is null
205 /* Hop-by-Hop options header */
206 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh)do { if (opt->ip6po_hbh) { struct ip6_ext *eh = (struct ip6_ext
*)(opt->ip6po_hbh); error = ip6_copyexthdr((&exthdrs.
ip6e_hbh), (caddr_t)(opt->ip6po_hbh), ((eh)->ip6e_len +
1) << 3); if (error) goto freehdrs; } } while (0)
;
207 /* Destination options header(1st part) */
208 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1)do { if (opt->ip6po_dest1) { struct ip6_ext *eh = (struct ip6_ext
*)(opt->ip6po_dest1); error = ip6_copyexthdr((&exthdrs
.ip6e_dest1), (caddr_t)(opt->ip6po_dest1), ((eh)->ip6e_len
+ 1) << 3); if (error) goto freehdrs; } } while (0)
;
209 /* Routing header */
210 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr)do { if (opt->ip6po_rhinfo.ip6po_rhi_rthdr) { struct ip6_ext
*eh = (struct ip6_ext *)(opt->ip6po_rhinfo.ip6po_rhi_rthdr
); error = ip6_copyexthdr((&exthdrs.ip6e_rthdr), (caddr_t
)(opt->ip6po_rhinfo.ip6po_rhi_rthdr), ((eh)->ip6e_len +
1) << 3); if (error) goto freehdrs; } } while (0)
;
211 /* Destination options header(2nd part) */
212 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2)do { if (opt->ip6po_dest2) { struct ip6_ext *eh = (struct ip6_ext
*)(opt->ip6po_dest2); error = ip6_copyexthdr((&exthdrs
.ip6e_dest2), (caddr_t)(opt->ip6po_dest2), ((eh)->ip6e_len
+ 1) << 3); if (error) goto freehdrs; } } while (0)
;
213 }
214
215#ifdef IPSEC1
216 if (ipsec_in_use || seclevel != NULL((void *)0)) {
3
Assuming 'ipsec_in_use' is 0
4
Assuming 'seclevel' is equal to NULL
5
Taking false branch
217 error = ip6_output_ipsec_lookup(m, seclevel, &tdb);
218 if (error) {
219 /*
220 * -EINVAL is used to indicate that the packet should
221 * be silently dropped, typically because we've asked
222 * key management for an SA.
223 */
224 if (error == -EINVAL22) /* Should silently drop packet */
225 error = 0;
226
227 goto freehdrs;
228 }
229 }
230#endif /* IPSEC */
231
232 /*
233 * Calculate the total length of the extension header chain.
234 * Keep the length of the unfragmentable part for fragmentation.
235 */
236 optlen = 0;
237 if (exthdrs.ip6e_hbh
5.1
Field 'ip6e_hbh' is null
) optlen += exthdrs.ip6e_hbh->m_lenm_hdr.mh_len;
6
Taking false branch
238 if (exthdrs.ip6e_dest1
6.1
Field 'ip6e_dest1' is null
) optlen += exthdrs.ip6e_dest1->m_lenm_hdr.mh_len;
7
Taking false branch
239 if (exthdrs.ip6e_rthdr
7.1
Field 'ip6e_rthdr' is null
) optlen += exthdrs.ip6e_rthdr->m_lenm_hdr.mh_len;
8
Taking false branch
240 unfragpartlen = optlen + sizeof(struct ip6_hdr);
241 /* NOTE: we don't add AH/ESP length here. do that later. */
242 if (exthdrs.ip6e_dest2
8.1
Field 'ip6e_dest2' is null
) optlen += exthdrs.ip6e_dest2->m_lenm_hdr.mh_len;
243
244 /*
245 * If we need IPsec, or there is at least one extension header,
246 * separate IP6 header from the payload.
247 */
248 if ((sproto
8.2
'sproto' is 0
|| optlen
8.3
'optlen' is 0
) && !hdrsplit) {
249 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
250 m = NULL((void *)0);
251 goto freehdrs;
252 }
253 m = exthdrs.ip6e_ip6;
254 hdrsplit++;
255 }
256
257 /* adjust pointer */
258 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
259
260 /* adjust mbuf packet header length */
261 m->m_pkthdrM_dat.MH.MH_pkthdr.len += optlen;
262 plen = m->m_pkthdrM_dat.MH.MH_pkthdr.len - sizeof(*ip6);
263
264 /* If this is a jumbo payload, insert a jumbo payload option. */
265 if (plen > IPV6_MAXPACKET65535) {
9
Assuming 'plen' is <= IPV6_MAXPACKET
266 if (!hdrsplit) {
267 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
268 m = NULL((void *)0);
269 goto freehdrs;
270 }
271 m = exthdrs.ip6e_ip6;
272 hdrsplit++;
273 }
274 /* adjust pointer */
275 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
276 if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
277 goto freehdrs;
278 ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen = 0;
279 } else
280 ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen = htons(plen)(__uint16_t)(__builtin_constant_p(plen) ? (__uint16_t)(((__uint16_t
)(plen) & 0xffU) << 8 | ((__uint16_t)(plen) & 0xff00U
) >> 8) : __swap16md(plen))
;
10
Taking false branch
11
'?' condition is false
281
282 /*
283 * Concatenate headers and fill in next header fields.
284 * Here we have, on "m"
285 * IPv6 payload
286 * and we insert headers accordingly. Finally, we should be getting:
287 * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
288 *
289 * during the header composing process, "m" points to IPv6 header.
290 * "mprev" points to an extension header prior to esp.
291 */
292 {
293 u_char *nexthdrp = &ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
294 struct mbuf *mprev = m;
295
296 /*
297 * we treat dest2 specially. this makes IPsec processing
298 * much easier. the goal here is to make mprev point the
299 * mbuf prior to dest2.
300 *
301 * result: IPv6 dest2 payload
302 * m and mprev will point to IPv6 header.
303 */
304 if (exthdrs.ip6e_dest2
11.1
Field 'ip6e_dest2' is null
) {
12
Taking false branch
305 if (!hdrsplit)
306 panic("%s: assumption failed: hdr not split",
307 __func__);
308 exthdrs.ip6e_dest2->m_nextm_hdr.mh_next = m->m_nextm_hdr.mh_next;
309 m->m_nextm_hdr.mh_next = exthdrs.ip6e_dest2;
310 *mtod(exthdrs.ip6e_dest2, u_char *)((u_char *)((exthdrs.ip6e_dest2)->m_hdr.mh_data)) = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
311 ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_DSTOPTS60;
312 }
313
314#define MAKE_CHAIN(m, mp, p, i)do { if (m) { if (!hdrsplit) panic("assumption failed: hdr not split"
); *((u_char *)(((m))->m_hdr.mh_data)) = *(p); *(p) = (i);
p = ((u_char *)(((m))->m_hdr.mh_data)); (m)->m_hdr.mh_next
= (mp)->m_hdr.mh_next; (mp)->m_hdr.mh_next = (m); (mp)
= (m); } } while (0)
\
315 do {\
316 if (m) {\
317 if (!hdrsplit) \
318 panic("assumption failed: hdr not split"); \
319 *mtod((m), u_char *)((u_char *)(((m))->m_hdr.mh_data)) = *(p);\
320 *(p) = (i);\
321 p = mtod((m), u_char *)((u_char *)(((m))->m_hdr.mh_data));\
322 (m)->m_nextm_hdr.mh_next = (mp)->m_nextm_hdr.mh_next;\
323 (mp)->m_nextm_hdr.mh_next = (m);\
324 (mp) = (m);\
325 }\
326 } while (0)
327 /*
328 * result: IPv6 hbh dest1 rthdr dest2 payload
329 * m will point to IPv6 header. mprev will point to the
330 * extension header prior to dest2 (rthdr in the above case).
331 */
332 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, nexthdrp, IPPROTO_HOPOPTS)do { if (exthdrs.ip6e_hbh) { if (!hdrsplit) panic("assumption failed: hdr not split"
); *((u_char *)(((exthdrs.ip6e_hbh))->m_hdr.mh_data)) = *(
nexthdrp); *(nexthdrp) = (0); nexthdrp = ((u_char *)(((exthdrs
.ip6e_hbh))->m_hdr.mh_data)); (exthdrs.ip6e_hbh)->m_hdr
.mh_next = (mprev)->m_hdr.mh_next; (mprev)->m_hdr.mh_next
= (exthdrs.ip6e_hbh); (mprev) = (exthdrs.ip6e_hbh); } } while
(0)
;
13
Taking false branch
14
Loop condition is false. Exiting loop
333 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, nexthdrp,do { if (exthdrs.ip6e_dest1) { if (!hdrsplit) panic("assumption failed: hdr not split"
); *((u_char *)(((exthdrs.ip6e_dest1))->m_hdr.mh_data)) = *
(nexthdrp); *(nexthdrp) = (60); nexthdrp = ((u_char *)(((exthdrs
.ip6e_dest1))->m_hdr.mh_data)); (exthdrs.ip6e_dest1)->m_hdr
.mh_next = (mprev)->m_hdr.mh_next; (mprev)->m_hdr.mh_next
= (exthdrs.ip6e_dest1); (mprev) = (exthdrs.ip6e_dest1); } } while
(0)
15
Taking false branch
16
Loop condition is false. Exiting loop
334 IPPROTO_DSTOPTS)do { if (exthdrs.ip6e_dest1) { if (!hdrsplit) panic("assumption failed: hdr not split"
); *((u_char *)(((exthdrs.ip6e_dest1))->m_hdr.mh_data)) = *
(nexthdrp); *(nexthdrp) = (60); nexthdrp = ((u_char *)(((exthdrs
.ip6e_dest1))->m_hdr.mh_data)); (exthdrs.ip6e_dest1)->m_hdr
.mh_next = (mprev)->m_hdr.mh_next; (mprev)->m_hdr.mh_next
= (exthdrs.ip6e_dest1); (mprev) = (exthdrs.ip6e_dest1); } } while
(0)
;
335 MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp,do { if (exthdrs.ip6e_rthdr) { if (!hdrsplit) panic("assumption failed: hdr not split"
); *((u_char *)(((exthdrs.ip6e_rthdr))->m_hdr.mh_data)) = *
(nexthdrp); *(nexthdrp) = (43); nexthdrp = ((u_char *)(((exthdrs
.ip6e_rthdr))->m_hdr.mh_data)); (exthdrs.ip6e_rthdr)->m_hdr
.mh_next = (mprev)->m_hdr.mh_next; (mprev)->m_hdr.mh_next
= (exthdrs.ip6e_rthdr); (mprev) = (exthdrs.ip6e_rthdr); } } while
(0)
17
Taking false branch
18
Loop condition is false. Exiting loop
336 IPPROTO_ROUTING)do { if (exthdrs.ip6e_rthdr) { if (!hdrsplit) panic("assumption failed: hdr not split"
); *((u_char *)(((exthdrs.ip6e_rthdr))->m_hdr.mh_data)) = *
(nexthdrp); *(nexthdrp) = (43); nexthdrp = ((u_char *)(((exthdrs
.ip6e_rthdr))->m_hdr.mh_data)); (exthdrs.ip6e_rthdr)->m_hdr
.mh_next = (mprev)->m_hdr.mh_next; (mprev)->m_hdr.mh_next
= (exthdrs.ip6e_rthdr); (mprev) = (exthdrs.ip6e_rthdr); } } while
(0)
;
337 }
338
339 /*
340 * If there is a routing header, replace the destination address field
341 * with the first hop of the routing header.
342 */
343 if (exthdrs.ip6e_rthdr
18.1
Field 'ip6e_rthdr' is null
) {
344 struct ip6_rthdr *rh;
345 struct ip6_rthdr0 *rh0;
346 struct in6_addr *addr;
347
348 rh = (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,((struct ip6_rthdr *)((exthdrs.ip6e_rthdr)->m_hdr.mh_data)
)
349 struct ip6_rthdr *)((struct ip6_rthdr *)((exthdrs.ip6e_rthdr)->m_hdr.mh_data)
)
);
350 switch (rh->ip6r_type) {
351 case IPV6_RTHDR_TYPE_00:
352 rh0 = (struct ip6_rthdr0 *)rh;
353 addr = (struct in6_addr *)(rh0 + 1);
354 ip6->ip6_dst = addr[0];
355 bcopy(&addr[1], &addr[0],
356 sizeof(struct in6_addr) * (rh0->ip6r0_segleft - 1));
357 addr[rh0->ip6r0_segleft - 1] = finaldst;
358 break;
359 default: /* is it possible? */
360 error = EINVAL22;
361 goto bad;
362 }
363 }
364
365 /* Source address validation */
366 if (!(flags & IPV6_UNSPECSRC0x01) &&
19
Assuming the condition is false
367 IN6_IS_ADDR_UNSPECIFIED(&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))
) {
368 /*
369 * XXX: we can probably assume validation in the caller, but
370 * we explicitly check the address here for safety.
371 */
372 error = EOPNOTSUPP45;
373 ip6stat_inc(ip6s_badscope);
374 goto bad;
375 }
376 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)((&ip6->ip6_src)->__u6_addr.__u6_addr8[0] == 0xff)) {
20
Assuming the condition is false
21
Taking false branch
377 error = EOPNOTSUPP45;
378 ip6stat_inc(ip6s_badscope);
379 goto bad;
380 }
381
382 ip6stat_inc(ip6s_localout);
383
384 /*
385 * Route packet.
386 */
387#if NPF1 > 0
388reroute:
389#endif
390
391 /* initialize cached route */
392 if (ro == NULL((void *)0)) {
22
Assuming 'ro' is not equal to NULL
23
Taking false branch
393 ro = &ip6route;
394 bzero((caddr_t)ro, sizeof(*ro))__builtin_bzero(((caddr_t)ro), (sizeof(*ro)));
395 }
396 ro_pmtu = ro;
397 if (opt
23.1
'opt' is null
&& opt->ip6po_rthdrip6po_rhinfo.ip6po_rhi_rthdr)
398 ro = &opt->ip6po_routeip6po_rhinfo.ip6po_rhi_route;
399 dst = &ro->ro_dst;
400
401 /*
402 * if specified, try to fill in the traffic class field.
403 * do not override if a non-zero value is already set.
404 * we check the diffserv field and the ecn field separately.
405 */
406 if (opt
23.2
'opt' is null
&& opt->ip6po_tclass >= 0) {
407 int mask = 0;
408
409 if ((ip6->ip6_flowip6_ctlun.ip6_un1.ip6_un1_flow & htonl(0xfc << 20)(__uint32_t)(__builtin_constant_p(0xfc << 20) ? (__uint32_t
)(((__uint32_t)(0xfc << 20) & 0xff) << 24 | (
(__uint32_t)(0xfc << 20) & 0xff00) << 8 | ((__uint32_t
)(0xfc << 20) & 0xff0000) >> 8 | ((__uint32_t
)(0xfc << 20) & 0xff000000) >> 24) : __swap32md
(0xfc << 20))
) == 0)
410 mask |= 0xfc;
411 if ((ip6->ip6_flowip6_ctlun.ip6_un1.ip6_un1_flow & htonl(0x03 << 20)(__uint32_t)(__builtin_constant_p(0x03 << 20) ? (__uint32_t
)(((__uint32_t)(0x03 << 20) & 0xff) << 24 | (
(__uint32_t)(0x03 << 20) & 0xff00) << 8 | ((__uint32_t
)(0x03 << 20) & 0xff0000) >> 8 | ((__uint32_t
)(0x03 << 20) & 0xff000000) >> 24) : __swap32md
(0x03 << 20))
) == 0)
412 mask |= 0x03;
413 if (mask != 0)
414 ip6->ip6_flowip6_ctlun.ip6_un1.ip6_un1_flow |=
415 htonl((opt->ip6po_tclass & mask) << 20)(__uint32_t)(__builtin_constant_p((opt->ip6po_tclass &
mask) << 20) ? (__uint32_t)(((__uint32_t)((opt->ip6po_tclass
& mask) << 20) & 0xff) << 24 | ((__uint32_t
)((opt->ip6po_tclass & mask) << 20) & 0xff00
) << 8 | ((__uint32_t)((opt->ip6po_tclass & mask
) << 20) & 0xff0000) >> 8 | ((__uint32_t)((opt
->ip6po_tclass & mask) << 20) & 0xff000000) >>
24) : __swap32md((opt->ip6po_tclass & mask) << 20
))
;
416 }
417
418 /* fill in or override the hop limit field, if necessary. */
419 if (opt
23.3
'opt' is null
&& opt->ip6po_hlim != -1)
420 ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim = opt->ip6po_hlim & 0xff;
421 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff)) {
24
Assuming the condition is false
25
Taking false branch
422 if (im6o != NULL((void *)0))
423 ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim = im6o->im6o_hlim;
424 else
425 ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim = ip6_defmcasthlim;
426 }
427
428#ifdef IPSEC1
429 if (tdb
25.1
'tdb' is equal to NULL
!= NULL((void *)0)) {
26
Taking false branch
430 /*
431 * XXX what should we do if ip6_hlim == 0 and the
432 * packet gets tunneled?
433 */
434 /*
435 * if we are source-routing, do not attempt to tunnel the
436 * packet just because ip6_dst is different from what tdb has.
437 * XXX
438 */
439 error = ip6_output_ipsec_send(tdb, m, ro,
440 exthdrs.ip6e_rthdr ? 1 : 0, 0);
441 goto done;
442 }
443#endif /* IPSEC */
444
445 bzero(&dstsock, sizeof(dstsock))__builtin_bzero((&dstsock), (sizeof(dstsock)));
446 dstsock.sin6_family = AF_INET624;
447 dstsock.sin6_addr = ip6->ip6_dst;
448 dstsock.sin6_len = sizeof(dstsock);
449 ro->ro_tableid = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid;
450
451 if (IN6_IS_ADDR_MULTICAST(&dstsock.sin6_addr)((&dstsock.sin6_addr)->__u6_addr.__u6_addr8[0] == 0xff
)
) {
27
Assuming the condition is false
28
Taking false branch
452 struct in6_pktinfo *pi = NULL((void *)0);
453
454 /*
455 * If the caller specify the outgoing interface
456 * explicitly, use it.
457 */
458 if (opt != NULL((void *)0) && (pi = opt->ip6po_pktinfo) != NULL((void *)0))
459 ifp = if_get(pi->ipi6_ifindex);
460
461 if (ifp == NULL((void *)0) && im6o != NULL((void *)0))
462 ifp = if_get(im6o->im6o_ifidx);
463 }
464
465 if (ifp
28.1
'ifp' is equal to NULL
== NULL((void *)0)) {
29
Taking true branch
466 rt = in6_selectroute(&dstsock, opt, ro, ro->ro_tableid);
467 if (rt == NULL((void *)0)) {
30
Assuming 'rt' is not equal to NULL
31
Taking false branch
468 ip6stat_inc(ip6s_noroute);
469 error = EHOSTUNREACH65;
470 goto bad;
471 }
472 if (ISSET(rt->rt_flags, RTF_LOCAL)((rt->rt_flags) & (0x200000)))
32
Assuming the condition is false
33
Taking false branch
473 ifp = if_get(rtable_loindex(m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid));
474 else
475 ifp = if_get(rt->rt_ifidx);
476 /*
477 * We aren't using rtisvalid() here because the UP/DOWN state
478 * machine is broken with some Ethernet drivers like em(4).
479 * As a result we might try to use an invalid cached route
480 * entry while an interface is being detached.
481 */
482 if (ifp == NULL((void *)0)) {
34
Assuming 'ifp' is not equal to NULL
483 ip6stat_inc(ip6s_noroute);
484 error = EHOSTUNREACH65;
485 goto bad;
486 }
487 } else {
488 *dst = dstsock;
489 }
490
491 if (rt
34.1
'rt' is non-null
&& (rt->rt_flags & RTF_GATEWAY0x2) &&
35
Assuming the condition is false
492 !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff))
493 dst = satosin6(rt->rt_gateway);
494
495 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff)) {
36
Assuming the condition is false
37
Taking false branch
496 /* Unicast */
497
498 m->m_flagsm_hdr.mh_flags &= ~(M_BCAST0x0100 | M_MCAST0x0200); /* just in case */
499 } else {
500 /* Multicast */
501
502 m->m_flagsm_hdr.mh_flags = (m->m_flagsm_hdr.mh_flags & ~M_BCAST0x0100) | M_MCAST0x0200;
503
504 /*
505 * Confirm that the outgoing interface supports multicast.
506 */
507 if ((ifp->if_flags & IFF_MULTICAST0x8000) == 0) {
38
Assuming the condition is false
508 ip6stat_inc(ip6s_noroute);
509 error = ENETUNREACH51;
510 goto bad;
511 }
512
513 if ((im6o == NULL((void *)0) || im6o->im6o_loop) &&
39
Assuming 'im6o' is not equal to NULL
40
Assuming field 'im6o_loop' is 0
514 in6_hasmulti(&ip6->ip6_dst, ifp)) {
515 /*
516 * If we belong to the destination multicast group
517 * on the outgoing interface, and the caller did not
518 * forbid loopback, loop back a copy.
519 * Can't defer TCP/UDP checksumming, do the
520 * computation now.
521 */
522 in6_proto_cksum_out(m, NULL((void *)0));
523 ip6_mloopback(ifp, m, dst);
524 }
525#ifdef MROUTING1
526 else {
527 /*
528 * If we are acting as a multicast router, perform
529 * multicast forwarding as if the packet had just
530 * arrived on the interface to which we are about
531 * to send. The multicast forwarding function
532 * recursively calls this function, using the
533 * IPV6_FORWARDING flag to prevent infinite recursion.
534 *
535 * Multicasts that are looped back by ip6_mloopback(),
536 * above, will be forwarded by the ip6_input() routine,
537 * if necessary.
538 */
539 if (ip6_mforwarding && ip6_mrouter[ifp->if_rdomainif_data.ifi_rdomain] &&
41
Assuming 'ip6_mforwarding' is 0
540 (flags & IPV6_FORWARDING0x02) == 0) {
541 if (ip6_mforward(ip6, ifp, m) != 0) {
542 m_freem(m);
543 goto done;
544 }
545 }
546 }
547#endif
548 /*
549 * Multicasts with a hoplimit of zero may be looped back,
550 * above, but must not be transmitted on a network.
551 * Also, multicasts addressed to the loopback interface
552 * are not sent -- the above call to ip6_mloopback() will
553 * loop back a copy if this host actually belongs to the
554 * destination group on the loopback interface.
555 */
556 if (ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK0x8) ||
42
Assuming field 'ip6_un1_hlim' is not equal to 0
43
Assuming the condition is false
557 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))
) {
44
Assuming the condition is false
558 m_freem(m);
559 goto done;
560 }
561 }
562
563 /*
564 * If this packet is going through a loopback interface we won't
565 * be able to restore its scope ID using the interface index.
566 */
567 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))))
) {
45
Assuming the condition is false
46
Assuming the condition is false
47
Assuming the condition is false
568 if (ifp->if_flags & IFF_LOOPBACK0x8)
569 src_scope = ip6->ip6_src.s6_addr16__u6_addr.__u6_addr16[1];
570 ip6->ip6_src.s6_addr16__u6_addr.__u6_addr16[1] = 0;
571 }
572 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))))
) {
48
Assuming the condition is false
49
Assuming the condition is false
50
Assuming the condition is false
573 if (ifp->if_flags & IFF_LOOPBACK0x8)
574 dst_scope = ip6->ip6_dst.s6_addr16__u6_addr.__u6_addr16[1];
575 ip6->ip6_dst.s6_addr16__u6_addr.__u6_addr16[1] = 0;
576 }
577
578 /* Determine path MTU. */
579 if ((error = ip6_getpmtu(ro_pmtu->ro_rt, ifp, &mtu)) != 0)
51
Taking false branch
580 goto bad;
581
582 /*
583 * The caller of this function may specify to use the minimum MTU
584 * in some cases.
585 * An advanced API option (IPV6_USE_MIN_MTU) can also override MTU
586 * setting. The logic is a bit complicated; by default, unicast
587 * packets will follow path MTU while multicast packets will be sent at
588 * the minimum MTU. If IP6PO_MINMTU_ALL is specified, all packets
589 * including unicast ones will be sent at the minimum MTU. Multicast
590 * packets will always be sent at the minimum MTU unless
591 * IP6PO_MINMTU_DISABLE is explicitly specified.
592 * See RFC 3542 for more details.
593 */
594 if (mtu > IPV6_MMTU1280) {
52
Assuming 'mtu' is <= IPV6_MMTU
53
Taking false branch
595 if ((flags & IPV6_MINMTU0x04))
596 mtu = IPV6_MMTU1280;
597 else if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL1)
598 mtu = IPV6_MMTU1280;
599 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)((&ip6->ip6_dst)->__u6_addr.__u6_addr8[0] == 0xff) && (opt == NULL((void *)0) ||
600 opt->ip6po_minmtu != IP6PO_MINMTU_DISABLE0)) {
601 mtu = IPV6_MMTU1280;
602 }
603 }
604
605 /*
606 * If the outgoing packet contains a hop-by-hop options header,
607 * it must be examined and processed even by the source node.
608 * (RFC 2460, section 4.)
609 */
610 if (exthdrs.ip6e_hbh
53.1
Field 'ip6e_hbh' is null
) {
54
Taking false branch
611 struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh, struct ip6_hbh *)((struct ip6_hbh *)((exthdrs.ip6e_hbh)->m_hdr.mh_data));
612 u_int32_t rtalert; /* returned value is ignored */
613 u_int32_t plen = 0; /* no more than 1 jumbo payload option! */
614
615 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = ifp->if_index;
616 if (ip6_process_hopopts(&m, (u_int8_t *)(hbh + 1),
617 ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh),
618 &rtalert, &plen) < 0) {
619 /* m was already freed at this point */
620 error = EINVAL22;/* better error? */
621 goto done;
622 }
623 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = 0;
624 }
625
626#if NPF1 > 0
627 if (pf_test(AF_INET624, PF_OUT, ifp, &m) != PF_PASS) {
55
Assuming the condition is false
56
Taking false branch
628 error = EACCES13;
629 m_freem(m);
630 goto done;
631 }
632 if (m == NULL((void *)0))
57
Assuming 'm' is not equal to NULL
58
Taking false branch
633 goto done;
634 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
635 if ((m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags & (PF_TAG_REROUTE0x20 | PF_TAG_GENERATED0x01)) ==
59
Assuming the condition is false
60
Taking false branch
636 (PF_TAG_REROUTE0x20 | PF_TAG_GENERATED0x01)) {
637 /* already rerun the route lookup, go on */
638 m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags &= ~(PF_TAG_GENERATED0x01 | PF_TAG_REROUTE0x20);
639 } else if (m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags & PF_TAG_REROUTE0x20) {
61
Assuming the condition is false
62
Taking false branch
640 /* tag as generated to skip over pf_test on rerun */
641 m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags |= PF_TAG_GENERATED0x01;
642 finaldst = ip6->ip6_dst;
643 ro = NULL((void *)0);
644 if_put(ifp); /* drop reference since destination changed */
645 ifp = NULL((void *)0);
646 goto reroute;
647 }
648#endif
649
650 /*
651 * If the packet is not going on the wire it can be destined
652 * to any local address. In this case do not clear its scopes
653 * to let ip6_input() find a matching local route.
654 */
655 if (ifp->if_flags & IFF_LOOPBACK0x8) {
63
Assuming the condition is true
656 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))))
)
64
Taking true branch
65
Assuming the condition is false
66
Assuming the condition is false
657 ip6->ip6_src.s6_addr16__u6_addr.__u6_addr16[1] = src_scope;
658 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))))
)
67
Assuming the condition is true
68
Assuming the condition is true
659 ip6->ip6_dst.s6_addr16__u6_addr.__u6_addr16[1] = dst_scope;
69
Assigned value is garbage or undefined
660 }
661
662 /*
663 * Send the packet to the outgoing interface.
664 * If necessary, do IPv6 fragmentation before sending.
665 *
666 * the logic here is rather complex:
667 * 1: normal case (dontfrag == 0)
668 * 1-a: send as is if tlen <= path mtu
669 * 1-b: fragment if tlen > path mtu
670 *
671 * 2: if user asks us not to fragment (dontfrag == 1)
672 * 2-a: send as is if tlen <= interface mtu
673 * 2-b: error if tlen > interface mtu
674 */
675 tlen = ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)((m->M_dat.MH.MH_pkthdr.csum_flags) & (0x8000)) ?
676 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_mss : m->m_pkthdrM_dat.MH.MH_pkthdr.len;
677
678 if (ISSET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)((m->M_dat.MH.MH_pkthdr.csum_flags) & (0x1000))) {
679 CLR(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)((m->M_dat.MH.MH_pkthdr.csum_flags) &= ~(0x1000));
680 dontfrag = 1;
681 } else if (opt && ISSET(opt->ip6po_flags, IP6PO_DONTFRAG)((opt->ip6po_flags) & (0x04)))
682 dontfrag = 1;
683 else
684 dontfrag = 0;
685
686 if (dontfrag && tlen > ifp->if_mtuif_data.ifi_mtu) { /* case 2-b */
687#ifdef IPSEC1
688 if (ip_mtudisc)
689 ipsec_adjust_mtu(m, mtu);
690#endif
691 error = EMSGSIZE40;
692 goto bad;
693 }
694
695 /*
696 * transmit packet without fragmentation
697 */
698 if (dontfrag || tlen <= mtu) { /* case 1-a and 2-a */
699 error = if_output_tso(ifp, &m, sin6tosa(dst), ro->ro_rt,
700 ifp->if_mtuif_data.ifi_mtu);
701 if (error || m == NULL((void *)0))
702 goto done;
703 goto bad; /* should not happen */
704 }
705
706 /*
707 * try to fragment the packet. case 1-b
708 */
709 if (mtu < IPV6_MMTU1280) {
710 /* path MTU cannot be less than IPV6_MMTU */
711 error = EMSGSIZE40;
712 goto bad;
713 } else if (ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen == 0) {
714 /* jumbo payload cannot be fragmented */
715 error = EMSGSIZE40;
716 goto bad;
717 }
718
719 /*
720 * Too large for the destination or interface;
721 * fragment if possible.
722 * Must be able to put at least 8 bytes per fragment.
723 */
724 hlen = unfragpartlen;
725 if (mtu > IPV6_MAXPACKET65535)
726 mtu = IPV6_MAXPACKET65535;
727
728 /*
729 * If we are doing fragmentation, we can't defer TCP/UDP
730 * checksumming; compute the checksum and clear the flag.
731 */
732 in6_proto_cksum_out(m, NULL((void *)0));
733
734 /*
735 * Change the next header field of the last header in the
736 * unfragmentable part.
737 */
738 if (exthdrs.ip6e_rthdr) {
739 nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *)((u_char *)((exthdrs.ip6e_rthdr)->m_hdr.mh_data));
740 *mtod(exthdrs.ip6e_rthdr, u_char *)((u_char *)((exthdrs.ip6e_rthdr)->m_hdr.mh_data)) = IPPROTO_FRAGMENT44;
741 } else if (exthdrs.ip6e_dest1) {
742 nextproto = *mtod(exthdrs.ip6e_dest1, u_char *)((u_char *)((exthdrs.ip6e_dest1)->m_hdr.mh_data));
743 *mtod(exthdrs.ip6e_dest1, u_char *)((u_char *)((exthdrs.ip6e_dest1)->m_hdr.mh_data)) = IPPROTO_FRAGMENT44;
744 } else if (exthdrs.ip6e_hbh) {
745 nextproto = *mtod(exthdrs.ip6e_hbh, u_char *)((u_char *)((exthdrs.ip6e_hbh)->m_hdr.mh_data));
746 *mtod(exthdrs.ip6e_hbh, u_char *)((u_char *)((exthdrs.ip6e_hbh)->m_hdr.mh_data)) = IPPROTO_FRAGMENT44;
747 } else {
748 nextproto = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
749 ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_FRAGMENT44;
750 }
751
752 if ((error = ip6_fragment(m, &ml, hlen, nextproto, mtu)) ||
753 (error = if_output_ml(ifp, &ml, sin6tosa(dst), ro->ro_rt)))
754 goto done;
755 ip6stat_inc(ip6s_fragmented);
756
757done:
758 if (ro == &ip6route && ro->ro_rt) {
759 rtfree(ro->ro_rt);
760 } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) {
761 rtfree(ro_pmtu->ro_rt);
762 }
763 if_put(ifp);
764#ifdef IPSEC1
765 tdb_unref(tdb);
766#endif /* IPSEC */
767 return (error);
768
769freehdrs:
770 m_freem(exthdrs.ip6e_hbh); /* m_freem will check if mbuf is 0 */
771 m_freem(exthdrs.ip6e_dest1);
772 m_freem(exthdrs.ip6e_rthdr);
773 m_freem(exthdrs.ip6e_dest2);
774 /* FALLTHROUGH */
775bad:
776 m_freem(m);
777 goto done;
778}
779
780int
781ip6_fragment(struct mbuf *m0, struct mbuf_list *ml, int hlen, u_char nextproto,
782 u_long mtu)
783{
784 struct ip6_hdr *ip6;
785 u_int32_t id;
786 int tlen, len, off;
787 int error;
788
789 ml_init(ml);
790
791 ip6 = mtod(m0, struct ip6_hdr *)((struct ip6_hdr *)((m0)->m_hdr.mh_data));
792 tlen = m0->m_pkthdrM_dat.MH.MH_pkthdr.len;
793 len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
794 if (len < 8) {
795 error = EMSGSIZE40;
796 goto bad;
797 }
798 id = htonl(ip6_randomid())(__uint32_t)(__builtin_constant_p(ip6_randomid()) ? (__uint32_t
)(((__uint32_t)(ip6_randomid()) & 0xff) << 24 | ((__uint32_t
)(ip6_randomid()) & 0xff00) << 8 | ((__uint32_t)(ip6_randomid
()) & 0xff0000) >> 8 | ((__uint32_t)(ip6_randomid()
) & 0xff000000) >> 24) : __swap32md(ip6_randomid())
)
;
799
800 /*
801 * Loop through length of payload,
802 * make new header and copy data of each part and link onto chain.
803 */
804 for (off = hlen; off < tlen; off += len) {
805 struct mbuf *m;
806 struct mbuf *mlast;
807 struct ip6_hdr *mhip6;
808 struct ip6_frag *ip6f;
809
810 MGETHDR(m, M_DONTWAIT, MT_HEADER)m = m_gethdr((0x0002), (2));
811 if (m == NULL((void *)0)) {
812 error = ENOBUFS55;
813 goto bad;
814 }
815 ml_enqueue(ml, m);
816 if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT0x0002)) != 0)
817 goto bad;
818 m->m_datam_hdr.mh_data += max_linkhdr;
819 mhip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
820 *mhip6 = *ip6;
821 m->m_lenm_hdr.mh_len = sizeof(struct ip6_hdr);
822
823 if ((error = ip6_insertfraghdr(m0, m, hlen, &ip6f)) != 0)
824 goto bad;
825 ip6f->ip6f_offlg = htons((off - hlen) & ~7)(__uint16_t)(__builtin_constant_p((off - hlen) & ~7) ? (__uint16_t
)(((__uint16_t)((off - hlen) & ~7) & 0xffU) << 8
| ((__uint16_t)((off - hlen) & ~7) & 0xff00U) >>
8) : __swap16md((off - hlen) & ~7))
;
826 if (off + len >= tlen)
827 len = tlen - off;
828 else
829 ip6f->ip6f_offlg |= IP6F_MORE_FRAG0x0100;
830
831 m->m_pkthdrM_dat.MH.MH_pkthdr.len = hlen + sizeof(struct ip6_frag) + len;
832 mhip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen = htons(m->m_pkthdr.len -(__uint16_t)(__builtin_constant_p(m->M_dat.MH.MH_pkthdr.len
- sizeof(struct ip6_hdr)) ? (__uint16_t)(((__uint16_t)(m->
M_dat.MH.MH_pkthdr.len - sizeof(struct ip6_hdr)) & 0xffU)
<< 8 | ((__uint16_t)(m->M_dat.MH.MH_pkthdr.len - sizeof
(struct ip6_hdr)) & 0xff00U) >> 8) : __swap16md(m->
M_dat.MH.MH_pkthdr.len - sizeof(struct ip6_hdr)))
833 sizeof(struct ip6_hdr))(__uint16_t)(__builtin_constant_p(m->M_dat.MH.MH_pkthdr.len
- sizeof(struct ip6_hdr)) ? (__uint16_t)(((__uint16_t)(m->
M_dat.MH.MH_pkthdr.len - sizeof(struct ip6_hdr)) & 0xffU)
<< 8 | ((__uint16_t)(m->M_dat.MH.MH_pkthdr.len - sizeof
(struct ip6_hdr)) & 0xff00U) >> 8) : __swap16md(m->
M_dat.MH.MH_pkthdr.len - sizeof(struct ip6_hdr)))
;
834 for (mlast = m; mlast->m_nextm_hdr.mh_next; mlast = mlast->m_nextm_hdr.mh_next)
835 ;
836 mlast->m_nextm_hdr.mh_next = m_copym(m0, off, len, M_DONTWAIT0x0002);
837 if (mlast->m_nextm_hdr.mh_next == NULL((void *)0)) {
838 error = ENOBUFS55;
839 goto bad;
840 }
841
842 ip6f->ip6f_reserved = 0;
843 ip6f->ip6f_ident = id;
844 ip6f->ip6f_nxt = nextproto;
845 }
846
847 ip6stat_add(ip6s_ofragments, ml_len(ml)((ml)->ml_len));
848 m_freem(m0);
849 return (0);
850
851bad:
852 ip6stat_inc(ip6s_odropped);
853 ml_purge(ml);
854 m_freem(m0);
855 return (error);
856}
857
858int
859ip6_copyexthdr(struct mbuf **mp, caddr_t hdr, int hlen)
860{
861 struct mbuf *m;
862
863 if (hlen > MCLBYTES(1 << 11))
864 return (ENOBUFS55); /* XXX */
865
866 MGET(m, M_DONTWAIT, MT_DATA)m = m_get((0x0002), (1));
867 if (!m)
868 return (ENOBUFS55);
869
870 if (hlen > MLEN(256 - sizeof(struct m_hdr))) {
871 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
872 if ((m->m_flagsm_hdr.mh_flags & M_EXT0x0001) == 0) {
873 m_free(m);
874 return (ENOBUFS55);
875 }
876 }
877 m->m_lenm_hdr.mh_len = hlen;
878 if (hdr)
879 memcpy(mtod(m, caddr_t), hdr, hlen)__builtin_memcpy((((caddr_t)((m)->m_hdr.mh_data))), (hdr),
(hlen))
;
880
881 *mp = m;
882 return (0);
883}
884
885/*
886 * Insert jumbo payload option.
887 */
888int
889ip6_insert_jumboopt(struct ip6_exthdrs *exthdrs, u_int32_t plen)
890{
891 struct mbuf *mopt;
892 u_int8_t *optbuf;
893 u_int32_t v;
894
895#define JUMBOOPTLEN 8 /* length of jumbo payload option and padding */
896
897 /*
898 * If there is no hop-by-hop options header, allocate new one.
899 * If there is one but it doesn't have enough space to store the
900 * jumbo payload option, allocate a cluster to store the whole options.
901 * Otherwise, use it to store the options.
902 */
903 if (exthdrs->ip6e_hbh == 0) {
904 MGET(mopt, M_DONTWAIT, MT_DATA)mopt = m_get((0x0002), (1));
905 if (mopt == NULL((void *)0))
906 return (ENOBUFS55);
907 mopt->m_lenm_hdr.mh_len = JUMBOOPTLEN;
908 optbuf = mtod(mopt, u_int8_t *)((u_int8_t *)((mopt)->m_hdr.mh_data));
909 optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */
910 exthdrs->ip6e_hbh = mopt;
911 } else {
912 struct ip6_hbh *hbh;
913
914 mopt = exthdrs->ip6e_hbh;
915 if (m_trailingspace(mopt) < JUMBOOPTLEN) {
916 /*
917 * XXX assumption:
918 * - exthdrs->ip6e_hbh is not referenced from places
919 * other than exthdrs.
920 * - exthdrs->ip6e_hbh is not an mbuf chain.
921 */
922 int oldoptlen = mopt->m_lenm_hdr.mh_len;
923 struct mbuf *n;
924
925 /*
926 * XXX: give up if the whole (new) hbh header does
927 * not fit even in an mbuf cluster.
928 */
929 if (oldoptlen + JUMBOOPTLEN > MCLBYTES(1 << 11))
930 return (ENOBUFS55);
931
932 /*
933 * As a consequence, we must always prepare a cluster
934 * at this point.
935 */
936 MGET(n, M_DONTWAIT, MT_DATA)n = m_get((0x0002), (1));
937 if (n) {
938 MCLGET(n, M_DONTWAIT)(void) m_clget((n), (0x0002), (1 << 11));
939 if ((n->m_flagsm_hdr.mh_flags & M_EXT0x0001) == 0) {
940 m_freem(n);
941 n = NULL((void *)0);
942 }
943 }
944 if (!n)
945 return (ENOBUFS55);
946 n->m_lenm_hdr.mh_len = oldoptlen + JUMBOOPTLEN;
947 memcpy(mtod(n, caddr_t), mtod(mopt, caddr_t),__builtin_memcpy((((caddr_t)((n)->m_hdr.mh_data))), (((caddr_t
)((mopt)->m_hdr.mh_data))), (oldoptlen))
948 oldoptlen)__builtin_memcpy((((caddr_t)((n)->m_hdr.mh_data))), (((caddr_t
)((mopt)->m_hdr.mh_data))), (oldoptlen))
;
949 optbuf = mtod(n, u_int8_t *)((u_int8_t *)((n)->m_hdr.mh_data)) + oldoptlen;
950 m_freem(mopt);
951 mopt = exthdrs->ip6e_hbh = n;
952 } else {
953 optbuf = mtod(mopt, u_int8_t *)((u_int8_t *)((mopt)->m_hdr.mh_data)) + mopt->m_lenm_hdr.mh_len;
954 mopt->m_lenm_hdr.mh_len += JUMBOOPTLEN;
955 }
956 optbuf[0] = IP6OPT_PADN0x01;
957 optbuf[1] = 0;
958
959 /*
960 * Adjust the header length according to the pad and
961 * the jumbo payload option.
962 */
963 hbh = mtod(mopt, struct ip6_hbh *)((struct ip6_hbh *)((mopt)->m_hdr.mh_data));
964 hbh->ip6h_len += (JUMBOOPTLEN >> 3);
965 }
966
967 /* fill in the option. */
968 optbuf[2] = IP6OPT_JUMBO0xC2;
969 optbuf[3] = 4;
970 v = (u_int32_t)htonl(plen + JUMBOOPTLEN)(__uint32_t)(__builtin_constant_p(plen + JUMBOOPTLEN) ? (__uint32_t
)(((__uint32_t)(plen + JUMBOOPTLEN) & 0xff) << 24 |
((__uint32_t)(plen + JUMBOOPTLEN) & 0xff00) << 8 |
((__uint32_t)(plen + JUMBOOPTLEN) & 0xff0000) >> 8
| ((__uint32_t)(plen + JUMBOOPTLEN) & 0xff000000) >>
24) : __swap32md(plen + JUMBOOPTLEN))
;
971 memcpy(&optbuf[4], &v, sizeof(u_int32_t))__builtin_memcpy((&optbuf[4]), (&v), (sizeof(u_int32_t
)))
;
972
973 /* finally, adjust the packet header length */
974 exthdrs->ip6e_ip6->m_pkthdrM_dat.MH.MH_pkthdr.len += JUMBOOPTLEN;
975
976 return (0);
977#undef JUMBOOPTLEN
978}
979
980/*
981 * Insert fragment header and copy unfragmentable header portions.
982 */
983int
984ip6_insertfraghdr(struct mbuf *m0, struct mbuf *m, int hlen,
985 struct ip6_frag **frghdrp)
986{
987 struct mbuf *n, *mlast;
988
989 if (hlen > sizeof(struct ip6_hdr)) {
990 n = m_copym(m0, sizeof(struct ip6_hdr),
991 hlen - sizeof(struct ip6_hdr), M_DONTWAIT0x0002);
992 if (n == NULL((void *)0))
993 return (ENOBUFS55);
994 m->m_nextm_hdr.mh_next = n;
995 } else
996 n = m;
997
998 /* Search for the last mbuf of unfragmentable part. */
999 for (mlast = n; mlast->m_nextm_hdr.mh_next; mlast = mlast->m_nextm_hdr.mh_next)
1000 ;
1001
1002 if ((mlast->m_flagsm_hdr.mh_flags & M_EXT0x0001) == 0 &&
1003 m_trailingspace(mlast) >= sizeof(struct ip6_frag)) {
1004 /* use the trailing space of the last mbuf for fragment hdr */
1005 *frghdrp = (struct ip6_frag *)(mtod(mlast, caddr_t)((caddr_t)((mlast)->m_hdr.mh_data)) +
1006 mlast->m_lenm_hdr.mh_len);
1007 mlast->m_lenm_hdr.mh_len += sizeof(struct ip6_frag);
1008 m->m_pkthdrM_dat.MH.MH_pkthdr.len += sizeof(struct ip6_frag);
1009 } else {
1010 /* allocate a new mbuf for the fragment header */
1011 struct mbuf *mfrg;
1012
1013 MGET(mfrg, M_DONTWAIT, MT_DATA)mfrg = m_get((0x0002), (1));
1014 if (mfrg == NULL((void *)0))
1015 return (ENOBUFS55);
1016 mfrg->m_lenm_hdr.mh_len = sizeof(struct ip6_frag);
1017 *frghdrp = mtod(mfrg, struct ip6_frag *)((struct ip6_frag *)((mfrg)->m_hdr.mh_data));
1018 mlast->m_nextm_hdr.mh_next = mfrg;
1019 }
1020
1021 return (0);
1022}
1023
1024int
1025ip6_getpmtu(struct rtentry *rt, struct ifnet *ifp, u_long *mtup)
1026{
1027 u_int32_t mtu = 0;
1028 int error = 0;
1029
1030 if (rt != NULL((void *)0)) {
1031 mtu = rt->rt_mturt_rmx.rmx_mtu;
1032 if (mtu == 0)
1033 mtu = ifp->if_mtuif_data.ifi_mtu;
1034 else if (mtu < IPV6_MMTU1280) {
1035 /* RFC8021 IPv6 Atomic Fragments Considered Harmful */
1036 mtu = IPV6_MMTU1280;
1037 } else if (mtu > ifp->if_mtuif_data.ifi_mtu) {
1038 /*
1039 * The MTU on the route is larger than the MTU on
1040 * the interface! This shouldn't happen, unless the
1041 * MTU of the interface has been changed after the
1042 * interface was brought up. Change the MTU in the
1043 * route to match the interface MTU (as long as the
1044 * field isn't locked).
1045 */
1046 mtu = ifp->if_mtuif_data.ifi_mtu;
1047 if (!(rt->rt_locksrt_rmx.rmx_locks & RTV_MTU0x1))
1048 rt->rt_mturt_rmx.rmx_mtu = mtu;
1049 }
1050 } else {
1051 mtu = ifp->if_mtuif_data.ifi_mtu;
1052 }
1053
1054 *mtup = mtu;
1055 return (error);
1056}
1057
1058/*
1059 * IP6 socket option processing.
1060 */
1061int
1062ip6_ctloutput(int op, struct socket *so, int level, int optname,
1063 struct mbuf *m)
1064{
1065 int privileged, optdatalen, uproto;
1066 void *optdata;
1067 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
1068 int error, optval;
1069 struct proc *p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
; /* For IPsec and rdomain */
1070 u_int rtableid, rtid = 0;
1071
1072 error = optval = 0;
1073
1074 privileged = (inp->inp_socket->so_state & SS_PRIV0x080);
1075 uproto = (int)so->so_proto->pr_protocol;
1076
1077 if (level != IPPROTO_IPV641)
1078 return (EINVAL22);
1079
1080 rtableid = p->p_p->ps_rtableid;
1081
1082 switch (op) {
1083 case PRCO_SETOPT1:
1084 switch (optname) {
1085 /*
1086 * Use of some Hop-by-Hop options or some
1087 * Destination options, might require special
1088 * privilege. That is, normal applications
1089 * (without special privilege) might be forbidden
1090 * from setting certain options in outgoing packets,
1091 * and might never see certain options in received
1092 * packets. [RFC 2292 Section 6]
1093 * KAME specific note:
1094 * KAME prevents non-privileged users from sending or
1095 * receiving ANY hbh/dst options in order to avoid
1096 * overhead of parsing options in the kernel.
1097 */
1098 case IPV6_RECVHOPOPTS39:
1099 case IPV6_RECVDSTOPTS40:
1100 if (!privileged) {
1101 error = EPERM1;
1102 break;
1103 }
1104 /* FALLTHROUGH */
1105 case IPV6_UNICAST_HOPS4:
1106 case IPV6_MINHOPCOUNT65:
1107 case IPV6_HOPLIMIT47:
1108
1109 case IPV6_RECVPKTINFO36:
1110 case IPV6_RECVHOPLIMIT37:
1111 case IPV6_RECVRTHDR38:
1112 case IPV6_RECVPATHMTU43:
1113 case IPV6_RECVTCLASS57:
1114 case IPV6_V6ONLY27:
1115 case IPV6_AUTOFLOWLABEL59:
1116 case IPV6_RECVDSTPORT64:
1117 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(int)) {
1118 error = EINVAL22;
1119 break;
1120 }
1121 optval = *mtod(m, int *)((int *)((m)->m_hdr.mh_data));
1122 switch (optname) {
1123
1124 case IPV6_UNICAST_HOPS4:
1125 if (optval < -1 || optval >= 256)
1126 error = EINVAL22;
1127 else {
1128 /* -1 = kernel default */
1129 inp->inp_hops = optval;
1130 }
1131 break;
1132
1133 case IPV6_MINHOPCOUNT65:
1134 if (optval < 0 || optval > 255)
1135 error = EINVAL22;
1136 else
1137 inp->inp_ip6_minhliminp_ip_minttl = optval;
1138 break;
1139
1140#define OPTSET(bit) \
1141do { \
1142 if (optval) \
1143 inp->inp_flags |= (bit); \
1144 else \
1145 inp->inp_flags &= ~(bit); \
1146} while (/*CONSTCOND*/ 0)
1147#define OPTBIT(bit)(inp->inp_flags & (bit) ? 1 : 0) (inp->inp_flags & (bit) ? 1 : 0)
1148
1149 case IPV6_RECVPKTINFO36:
1150 OPTSET(IN6P_PKTINFO0x010000);
1151 break;
1152
1153 case IPV6_HOPLIMIT47:
1154 {
1155 struct ip6_pktopts **optp;
1156
1157 optp = &inp->inp_outputopts6;
1158 error = ip6_pcbopt(IPV6_HOPLIMIT47,
1159 (u_char *)&optval, sizeof(optval), optp,
1160 privileged, uproto);
1161 break;
1162 }
1163
1164 case IPV6_RECVHOPLIMIT37:
1165 OPTSET(IN6P_HOPLIMIT0x020000);
1166 break;
1167
1168 case IPV6_RECVHOPOPTS39:
1169 OPTSET(IN6P_HOPOPTS0x040000);
1170 break;
1171
1172 case IPV6_RECVDSTOPTS40:
1173 OPTSET(IN6P_DSTOPTS0x080000);
1174 break;
1175
1176 case IPV6_RECVRTHDR38:
1177 OPTSET(IN6P_RTHDR0x100000);
1178 break;
1179
1180 case IPV6_RECVPATHMTU43:
1181 /*
1182 * We ignore this option for TCP
1183 * sockets.
1184 * (RFC3542 leaves this case
1185 * unspecified.)
1186 */
1187 if (uproto != IPPROTO_TCP6)
1188 OPTSET(IN6P_MTU0x80000000);
1189 break;
1190
1191 case IPV6_V6ONLY27:
1192 /*
1193 * make setsockopt(IPV6_V6ONLY)
1194 * available only prior to bind(2).
1195 * see ipng mailing list, Jun 22 2001.
1196 */
1197 if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(((*(const u_int32_t *)(const void *)(&(&inp->inp_laddru
.iau_addr6)->__u6_addr.__u6_addr8[0]) == 0) && (*(
const u_int32_t *)(const void *)(&(&inp->inp_laddru
.iau_addr6)->__u6_addr.__u6_addr8[4]) == 0) && (*(
const u_int32_t *)(const void *)(&(&inp->inp_laddru
.iau_addr6)->__u6_addr.__u6_addr8[8]) == 0) && (*(
const u_int32_t *)(const void *)(&(&inp->inp_laddru
.iau_addr6)->__u6_addr.__u6_addr8[12]) == 0))
1198 &inp->inp_laddr6)((*(const u_int32_t *)(const void *)(&(&inp->inp_laddru
.iau_addr6)->__u6_addr.__u6_addr8[0]) == 0) && (*(
const u_int32_t *)(const void *)(&(&inp->inp_laddru
.iau_addr6)->__u6_addr.__u6_addr8[4]) == 0) && (*(
const u_int32_t *)(const void *)(&(&inp->inp_laddru
.iau_addr6)->__u6_addr.__u6_addr8[8]) == 0) && (*(
const u_int32_t *)(const void *)(&(&inp->inp_laddru
.iau_addr6)->__u6_addr.__u6_addr8[12]) == 0))
) {
1199 error = EINVAL22;
1200 break;
1201 }
1202 /* No support for IPv4-mapped addresses. */
1203 if (!optval)
1204 error = EINVAL22;
1205 else
1206 error = 0;
1207 break;
1208 case IPV6_RECVTCLASS57:
1209 OPTSET(IN6P_TCLASS0x400000);
1210 break;
1211 case IPV6_AUTOFLOWLABEL59:
1212 OPTSET(IN6P_AUTOFLOWLABEL0x800000);
1213 break;
1214
1215 case IPV6_RECVDSTPORT64:
1216 OPTSET(IN6P_RECVDSTPORT0x200);
1217 break;
1218 }
1219 break;
1220
1221 case IPV6_TCLASS61:
1222 case IPV6_DONTFRAG62:
1223 case IPV6_USE_MIN_MTU42:
1224 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(optval)) {
1225 error = EINVAL22;
1226 break;
1227 }
1228 optval = *mtod(m, int *)((int *)((m)->m_hdr.mh_data));
1229 {
1230 struct ip6_pktopts **optp;
1231 optp = &inp->inp_outputopts6;
1232 error = ip6_pcbopt(optname, (u_char *)&optval,
1233 sizeof(optval), optp, privileged, uproto);
1234 break;
1235 }
1236
1237 case IPV6_PKTINFO46:
1238 case IPV6_HOPOPTS49:
1239 case IPV6_RTHDR51:
1240 case IPV6_DSTOPTS50:
1241 case IPV6_RTHDRDSTOPTS35:
1242 {
1243 /* new advanced API (RFC3542) */
1244 u_char *optbuf;
1245 int optbuflen;
1246 struct ip6_pktopts **optp;
1247
1248 if (m && m->m_nextm_hdr.mh_next) {
1249 error = EINVAL22; /* XXX */
1250 break;
1251 }
1252 if (m) {
1253 optbuf = mtod(m, u_char *)((u_char *)((m)->m_hdr.mh_data));
1254 optbuflen = m->m_lenm_hdr.mh_len;
1255 } else {
1256 optbuf = NULL((void *)0);
1257 optbuflen = 0;
1258 }
1259 optp = &inp->inp_outputopts6;
1260 error = ip6_pcbopt(optname, optbuf, optbuflen, optp,
1261 privileged, uproto);
1262 break;
1263 }
1264#undef OPTSET
1265
1266 case IPV6_MULTICAST_IF9:
1267 case IPV6_MULTICAST_HOPS10:
1268 case IPV6_MULTICAST_LOOP11:
1269 case IPV6_JOIN_GROUP12:
1270 case IPV6_LEAVE_GROUP13:
1271 error = ip6_setmoptions(optname,
1272 &inp->inp_moptions6inp_mou.mou_mo6,
1273 m, inp->inp_rtableid);
1274 break;
1275
1276 case IPV6_PORTRANGE14:
1277 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(int)) {
1278 error = EINVAL22;
1279 break;
1280 }
1281 optval = *mtod(m, int *)((int *)((m)->m_hdr.mh_data));
1282
1283 switch (optval) {
1284 case IPV6_PORTRANGE_DEFAULT0:
1285 inp->inp_flags &= ~(IN6P_LOWPORT0x020);
1286 inp->inp_flags &= ~(IN6P_HIGHPORT0x010);
1287 break;
1288
1289 case IPV6_PORTRANGE_HIGH1:
1290 inp->inp_flags &= ~(IN6P_LOWPORT0x020);
1291 inp->inp_flags |= IN6P_HIGHPORT0x010;
1292 break;
1293
1294 case IPV6_PORTRANGE_LOW2:
1295 inp->inp_flags &= ~(IN6P_HIGHPORT0x010);
1296 inp->inp_flags |= IN6P_LOWPORT0x020;
1297 break;
1298
1299 default:
1300 error = EINVAL22;
1301 break;
1302 }
1303 break;
1304
1305 case IPSEC6_OUTSA56:
1306 error = EINVAL22;
1307 break;
1308
1309 case IPV6_AUTH_LEVEL53:
1310 case IPV6_ESP_TRANS_LEVEL54:
1311 case IPV6_ESP_NETWORK_LEVEL55:
1312 case IPV6_IPCOMP_LEVEL60:
1313#ifndef IPSEC1
1314 error = EINVAL22;
1315#else
1316 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(int)) {
1317 error = EINVAL22;
1318 break;
1319 }
1320 optval = *mtod(m, int *)((int *)((m)->m_hdr.mh_data));
1321
1322 if (optval < IPSEC_LEVEL_BYPASS0x00 ||
1323 optval > IPSEC_LEVEL_UNIQUE0x04) {
1324 error = EINVAL22;
1325 break;
1326 }
1327
1328 switch (optname) {
1329 case IPV6_AUTH_LEVEL53:
1330 if (optval < IPSEC_AUTH_LEVEL_DEFAULT0x01 &&
1331 suser(p)) {
1332 error = EACCES13;
1333 break;
1334 }
1335 inp->inp_seclevel[SL_AUTH0] = optval;
1336 break;
1337
1338 case IPV6_ESP_TRANS_LEVEL54:
1339 if (optval < IPSEC_ESP_TRANS_LEVEL_DEFAULT0x01 &&
1340 suser(p)) {
1341 error = EACCES13;
1342 break;
1343 }
1344 inp->inp_seclevel[SL_ESP_TRANS1] = optval;
1345 break;
1346
1347 case IPV6_ESP_NETWORK_LEVEL55:
1348 if (optval < IPSEC_ESP_NETWORK_LEVEL_DEFAULT0x01 &&
1349 suser(p)) {
1350 error = EACCES13;
1351 break;
1352 }
1353 inp->inp_seclevel[SL_ESP_NETWORK2] = optval;
1354 break;
1355
1356 case IPV6_IPCOMP_LEVEL60:
1357 if (optval < IPSEC_IPCOMP_LEVEL_DEFAULT0x01 &&
1358 suser(p)) {
1359 error = EACCES13;
1360 break;
1361 }
1362 inp->inp_seclevel[SL_IPCOMP3] = optval;
1363 break;
1364 }
1365#endif
1366 break;
1367 case SO_RTABLE0x1021:
1368 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof(u_int)) {
1369 error = EINVAL22;
1370 break;
1371 }
1372 rtid = *mtod(m, u_int *)((u_int *)((m)->m_hdr.mh_data));
1373 if (inp->inp_rtableid == rtid)
1374 break;
1375 /* needs privileges to switch when already set */
1376 if (rtableid != rtid && rtableid != 0 &&
1377 (error = suser(p)) != 0)
1378 break;
1379 /* table must exist */
1380 if (!rtable_exists(rtid)) {
1381 error = EINVAL22;
1382 break;
1383 }
1384 error = in_pcbset_rtableid(inp, rtid);
1385 break;
1386 case IPV6_PIPEX63:
1387 if (m != NULL((void *)0) && m->m_lenm_hdr.mh_len == sizeof(int))
1388 inp->inp_pipex = *mtod(m, int *)((int *)((m)->m_hdr.mh_data));
1389 else
1390 error = EINVAL22;
1391 break;
1392
1393 default:
1394 error = ENOPROTOOPT42;
1395 break;
1396 }
1397 break;
1398
1399 case PRCO_GETOPT0:
1400 switch (optname) {
1401
1402 case IPV6_RECVHOPOPTS39:
1403 case IPV6_RECVDSTOPTS40:
1404 case IPV6_UNICAST_HOPS4:
1405 case IPV6_MINHOPCOUNT65:
1406 case IPV6_RECVPKTINFO36:
1407 case IPV6_RECVHOPLIMIT37:
1408 case IPV6_RECVRTHDR38:
1409 case IPV6_RECVPATHMTU43:
1410
1411 case IPV6_V6ONLY27:
1412 case IPV6_PORTRANGE14:
1413 case IPV6_RECVTCLASS57:
1414 case IPV6_AUTOFLOWLABEL59:
1415 case IPV6_RECVDSTPORT64:
1416 switch (optname) {
1417
1418 case IPV6_RECVHOPOPTS39:
1419 optval = OPTBIT(IN6P_HOPOPTS)(inp->inp_flags & (0x040000) ? 1 : 0);
1420 break;
1421
1422 case IPV6_RECVDSTOPTS40:
1423 optval = OPTBIT(IN6P_DSTOPTS)(inp->inp_flags & (0x080000) ? 1 : 0);
1424 break;
1425
1426 case IPV6_UNICAST_HOPS4:
1427 optval = inp->inp_hops;
1428 break;
1429
1430 case IPV6_MINHOPCOUNT65:
1431 optval = inp->inp_ip6_minhliminp_ip_minttl;
1432 break;
1433
1434 case IPV6_RECVPKTINFO36:
1435 optval = OPTBIT(IN6P_PKTINFO)(inp->inp_flags & (0x010000) ? 1 : 0);
1436 break;
1437
1438 case IPV6_RECVHOPLIMIT37:
1439 optval = OPTBIT(IN6P_HOPLIMIT)(inp->inp_flags & (0x020000) ? 1 : 0);
1440 break;
1441
1442 case IPV6_RECVRTHDR38:
1443 optval = OPTBIT(IN6P_RTHDR)(inp->inp_flags & (0x100000) ? 1 : 0);
1444 break;
1445
1446 case IPV6_RECVPATHMTU43:
1447 optval = OPTBIT(IN6P_MTU)(inp->inp_flags & (0x80000000) ? 1 : 0);
1448 break;
1449
1450 case IPV6_V6ONLY27:
1451 optval = 1;
1452 break;
1453
1454 case IPV6_PORTRANGE14:
1455 {
1456 int flags;
1457 flags = inp->inp_flags;
1458 if (flags & IN6P_HIGHPORT0x010)
1459 optval = IPV6_PORTRANGE_HIGH1;
1460 else if (flags & IN6P_LOWPORT0x020)
1461 optval = IPV6_PORTRANGE_LOW2;
1462 else
1463 optval = 0;
1464 break;
1465 }
1466 case IPV6_RECVTCLASS57:
1467 optval = OPTBIT(IN6P_TCLASS)(inp->inp_flags & (0x400000) ? 1 : 0);
1468 break;
1469
1470 case IPV6_AUTOFLOWLABEL59:
1471 optval = OPTBIT(IN6P_AUTOFLOWLABEL)(inp->inp_flags & (0x800000) ? 1 : 0);
1472 break;
1473
1474 case IPV6_RECVDSTPORT64:
1475 optval = OPTBIT(IN6P_RECVDSTPORT)(inp->inp_flags & (0x200) ? 1 : 0);
1476 break;
1477 }
1478 if (error)
1479 break;
1480 m->m_lenm_hdr.mh_len = sizeof(int);
1481 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = optval;
1482 break;
1483
1484 case IPV6_PATHMTU44:
1485 {
1486 u_long pmtu = 0;
1487 struct ip6_mtuinfo mtuinfo;
1488 struct ifnet *ifp;
1489 struct rtentry *rt;
1490
1491 if (!(so->so_state & SS_ISCONNECTED0x002))
1492 return (ENOTCONN57);
1493
1494 rt = in_pcbrtentry(inp);
1495 if (!rtisvalid(rt))
1496 return (EHOSTUNREACH65);
1497
1498 ifp = if_get(rt->rt_ifidx);
1499 if (ifp == NULL((void *)0))
1500 return (EHOSTUNREACH65);
1501 /*
1502 * XXX: we dot not consider the case of source
1503 * routing, or optional information to specify
1504 * the outgoing interface.
1505 */
1506 error = ip6_getpmtu(rt, ifp, &pmtu);
1507 if_put(ifp);
1508 if (error)
1509 break;
1510 if (pmtu > IPV6_MAXPACKET65535)
1511 pmtu = IPV6_MAXPACKET65535;
1512
1513 bzero(&mtuinfo, sizeof(mtuinfo))__builtin_bzero((&mtuinfo), (sizeof(mtuinfo)));
1514 mtuinfo.ip6m_mtu = (u_int32_t)pmtu;
1515 optdata = (void *)&mtuinfo;
1516 optdatalen = sizeof(mtuinfo);
1517 if (optdatalen > MCLBYTES(1 << 11))
1518 return (EMSGSIZE40); /* XXX */
1519 if (optdatalen > MLEN(256 - sizeof(struct m_hdr)))
1520 MCLGET(m, M_WAIT)(void) m_clget((m), (0x0001), (1 << 11));
1521 m->m_lenm_hdr.mh_len = optdatalen;
1522 bcopy(optdata, mtod(m, void *)((void *)((m)->m_hdr.mh_data)), optdatalen);
1523 break;
1524 }
1525
1526 case IPV6_PKTINFO46:
1527 case IPV6_HOPOPTS49:
1528 case IPV6_RTHDR51:
1529 case IPV6_DSTOPTS50:
1530 case IPV6_RTHDRDSTOPTS35:
1531 case IPV6_TCLASS61:
1532 case IPV6_DONTFRAG62:
1533 case IPV6_USE_MIN_MTU42:
1534 error = ip6_getpcbopt(inp->inp_outputopts6,
1535 optname, m);
1536 break;
1537
1538 case IPV6_MULTICAST_IF9:
1539 case IPV6_MULTICAST_HOPS10:
1540 case IPV6_MULTICAST_LOOP11:
1541 case IPV6_JOIN_GROUP12:
1542 case IPV6_LEAVE_GROUP13:
1543 error = ip6_getmoptions(optname,
1544 inp->inp_moptions6inp_mou.mou_mo6, m);
1545 break;
1546
1547 case IPSEC6_OUTSA56:
1548 error = EINVAL22;
1549 break;
1550
1551 case IPV6_AUTH_LEVEL53:
1552 case IPV6_ESP_TRANS_LEVEL54:
1553 case IPV6_ESP_NETWORK_LEVEL55:
1554 case IPV6_IPCOMP_LEVEL60:
1555#ifndef IPSEC1
1556 m->m_lenm_hdr.mh_len = sizeof(int);
1557 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = IPSEC_LEVEL_NONE0x00;
1558#else
1559 m->m_lenm_hdr.mh_len = sizeof(int);
1560 switch (optname) {
1561 case IPV6_AUTH_LEVEL53:
1562 optval = inp->inp_seclevel[SL_AUTH0];
1563 break;
1564
1565 case IPV6_ESP_TRANS_LEVEL54:
1566 optval =
1567 inp->inp_seclevel[SL_ESP_TRANS1];
1568 break;
1569
1570 case IPV6_ESP_NETWORK_LEVEL55:
1571 optval =
1572 inp->inp_seclevel[SL_ESP_NETWORK2];
1573 break;
1574
1575 case IPV6_IPCOMP_LEVEL60:
1576 optval = inp->inp_seclevel[SL_IPCOMP3];
1577 break;
1578 }
1579 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = optval;
1580#endif
1581 break;
1582 case SO_RTABLE0x1021:
1583 m->m_lenm_hdr.mh_len = sizeof(u_int);
1584 *mtod(m, u_int *)((u_int *)((m)->m_hdr.mh_data)) = inp->inp_rtableid;
1585 break;
1586 case IPV6_PIPEX63:
1587 m->m_lenm_hdr.mh_len = sizeof(int);
1588 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = inp->inp_pipex;
1589 break;
1590
1591 default:
1592 error = ENOPROTOOPT42;
1593 break;
1594 }
1595 break;
1596 }
1597 return (error);
1598}
1599
1600int
1601ip6_raw_ctloutput(int op, struct socket *so, int level, int optname,
1602 struct mbuf *m)
1603{
1604 int error = 0, optval;
1605 const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum)__builtin_offsetof(struct icmp6_hdr, icmp6_cksum);
1606 struct inpcb *inp = sotoinpcb(so)((struct inpcb *)(so)->so_pcb);
1607
1608 if (level != IPPROTO_IPV641)
1609 return (EINVAL22);
1610
1611 switch (optname) {
1612 case IPV6_CHECKSUM26:
1613 /*
1614 * For ICMPv6 sockets, no modification allowed for checksum
1615 * offset, permit "no change" values to help existing apps.
1616 *
1617 * RFC3542 says: "An attempt to set IPV6_CHECKSUM
1618 * for an ICMPv6 socket will fail."
1619 * The current behavior does not meet RFC3542.
1620 */
1621 switch (op) {
1622 case PRCO_SETOPT1:
1623 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(int)) {
1624 error = EINVAL22;
1625 break;
1626 }
1627 optval = *mtod(m, int *)((int *)((m)->m_hdr.mh_data));
1628 if (optval < -1 ||
1629 (optval > 0 && (optval % 2) != 0)) {
1630 /*
1631 * The API assumes non-negative even offset
1632 * values or -1 as a special value.
1633 */
1634 error = EINVAL22;
1635 } else if (so->so_proto->pr_protocol ==
1636 IPPROTO_ICMPV658) {
1637 if (optval != icmp6off)
1638 error = EINVAL22;
1639 } else
1640 inp->inp_cksum6 = optval;
1641 break;
1642
1643 case PRCO_GETOPT0:
1644 if (so->so_proto->pr_protocol == IPPROTO_ICMPV658)
1645 optval = icmp6off;
1646 else
1647 optval = inp->inp_cksum6;
1648
1649 m->m_lenm_hdr.mh_len = sizeof(int);
1650 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = optval;
1651 break;
1652
1653 default:
1654 error = EINVAL22;
1655 break;
1656 }
1657 break;
1658
1659 default:
1660 error = ENOPROTOOPT42;
1661 break;
1662 }
1663
1664 return (error);
1665}
1666
1667/*
1668 * initialize ip6_pktopts. beware that there are non-zero default values in
1669 * the struct.
1670 */
1671void
1672ip6_initpktopts(struct ip6_pktopts *opt)
1673{
1674 bzero(opt, sizeof(*opt))__builtin_bzero((opt), (sizeof(*opt)));
1675 opt->ip6po_hlim = -1; /* -1 means default hop limit */
1676 opt->ip6po_tclass = -1; /* -1 means default traffic class */
1677 opt->ip6po_minmtu = IP6PO_MINMTU_MCASTONLY-1;
1678}
1679
1680int
1681ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt,
1682 int priv, int uproto)
1683{
1684 struct ip6_pktopts *opt;
1685
1686 if (*pktopt == NULL((void *)0)) {
1687 *pktopt = malloc(sizeof(struct ip6_pktopts), M_IP6OPT123,
1688 M_WAITOK0x0001);
1689 ip6_initpktopts(*pktopt);
1690 }
1691 opt = *pktopt;
1692
1693 return (ip6_setpktopt(optname, buf, len, opt, priv, 1, uproto));
1694}
1695
1696int
1697ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct mbuf *m)
1698{
1699 void *optdata = NULL((void *)0);
1700 int optdatalen = 0;
1701 struct ip6_ext *ip6e;
1702 int error = 0;
1703 struct in6_pktinfo null_pktinfo;
1704 int deftclass = 0, on;
1705 int defminmtu = IP6PO_MINMTU_MCASTONLY-1;
1706
1707 switch (optname) {
1708 case IPV6_PKTINFO46:
1709 if (pktopt && pktopt->ip6po_pktinfo)
1710 optdata = (void *)pktopt->ip6po_pktinfo;
1711 else {
1712 /* XXX: we don't have to do this every time... */
1713 bzero(&null_pktinfo, sizeof(null_pktinfo))__builtin_bzero((&null_pktinfo), (sizeof(null_pktinfo)));
1714 optdata = (void *)&null_pktinfo;
1715 }
1716 optdatalen = sizeof(struct in6_pktinfo);
1717 break;
1718 case IPV6_TCLASS61:
1719 if (pktopt && pktopt->ip6po_tclass >= 0)
1720 optdata = (void *)&pktopt->ip6po_tclass;
1721 else
1722 optdata = (void *)&deftclass;
1723 optdatalen = sizeof(int);
1724 break;
1725 case IPV6_HOPOPTS49:
1726 if (pktopt && pktopt->ip6po_hbh) {
1727 optdata = (void *)pktopt->ip6po_hbh;
1728 ip6e = (struct ip6_ext *)pktopt->ip6po_hbh;
1729 optdatalen = (ip6e->ip6e_len + 1) << 3;
1730 }
1731 break;
1732 case IPV6_RTHDR51:
1733 if (pktopt && pktopt->ip6po_rthdrip6po_rhinfo.ip6po_rhi_rthdr) {
1734 optdata = (void *)pktopt->ip6po_rthdrip6po_rhinfo.ip6po_rhi_rthdr;
1735 ip6e = (struct ip6_ext *)pktopt->ip6po_rthdrip6po_rhinfo.ip6po_rhi_rthdr;
1736 optdatalen = (ip6e->ip6e_len + 1) << 3;
1737 }
1738 break;
1739 case IPV6_RTHDRDSTOPTS35:
1740 if (pktopt && pktopt->ip6po_dest1) {
1741 optdata = (void *)pktopt->ip6po_dest1;
1742 ip6e = (struct ip6_ext *)pktopt->ip6po_dest1;
1743 optdatalen = (ip6e->ip6e_len + 1) << 3;
1744 }
1745 break;
1746 case IPV6_DSTOPTS50:
1747 if (pktopt && pktopt->ip6po_dest2) {
1748 optdata = (void *)pktopt->ip6po_dest2;
1749 ip6e = (struct ip6_ext *)pktopt->ip6po_dest2;
1750 optdatalen = (ip6e->ip6e_len + 1) << 3;
1751 }
1752 break;
1753 case IPV6_USE_MIN_MTU42:
1754 if (pktopt)
1755 optdata = (void *)&pktopt->ip6po_minmtu;
1756 else
1757 optdata = (void *)&defminmtu;
1758 optdatalen = sizeof(int);
1759 break;
1760 case IPV6_DONTFRAG62:
1761 if (pktopt && ((pktopt->ip6po_flags) & IP6PO_DONTFRAG0x04))
1762 on = 1;
1763 else
1764 on = 0;
1765 optdata = (void *)&on;
1766 optdatalen = sizeof(on);
1767 break;
1768 default: /* should not happen */
1769#ifdef DIAGNOSTIC1
1770 panic("%s: unexpected option", __func__);
1771#endif
1772 return (ENOPROTOOPT42);
1773 }
1774
1775 if (optdatalen > MCLBYTES(1 << 11))
1776 return (EMSGSIZE40); /* XXX */
1777 if (optdatalen > MLEN(256 - sizeof(struct m_hdr)))
1778 MCLGET(m, M_WAIT)(void) m_clget((m), (0x0001), (1 << 11));
1779 m->m_lenm_hdr.mh_len = optdatalen;
1780 if (optdatalen)
1781 bcopy(optdata, mtod(m, void *)((void *)((m)->m_hdr.mh_data)), optdatalen);
1782
1783 return (error);
1784}
1785
1786void
1787ip6_clearpktopts(struct ip6_pktopts *pktopt, int optname)
1788{
1789 if (optname == -1 || optname == IPV6_PKTINFO46) {
1790 if (pktopt->ip6po_pktinfo)
1791 free(pktopt->ip6po_pktinfo, M_IP6OPT123, 0);
1792 pktopt->ip6po_pktinfo = NULL((void *)0);
1793 }
1794 if (optname == -1 || optname == IPV6_HOPLIMIT47)
1795 pktopt->ip6po_hlim = -1;
1796 if (optname == -1 || optname == IPV6_TCLASS61)
1797 pktopt->ip6po_tclass = -1;
1798 if (optname == -1 || optname == IPV6_HOPOPTS49) {
1799 if (pktopt->ip6po_hbh)
1800 free(pktopt->ip6po_hbh, M_IP6OPT123, 0);
1801 pktopt->ip6po_hbh = NULL((void *)0);
1802 }
1803 if (optname == -1 || optname == IPV6_RTHDRDSTOPTS35) {
1804 if (pktopt->ip6po_dest1)
1805 free(pktopt->ip6po_dest1, M_IP6OPT123, 0);
1806 pktopt->ip6po_dest1 = NULL((void *)0);
1807 }
1808 if (optname == -1 || optname == IPV6_RTHDR51) {
1809 if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
1810 free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT123, 0);
1811 pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL((void *)0);
1812 if (pktopt->ip6po_routeip6po_rhinfo.ip6po_rhi_route.ro_rt) {
1813 rtfree(pktopt->ip6po_routeip6po_rhinfo.ip6po_rhi_route.ro_rt);
1814 pktopt->ip6po_routeip6po_rhinfo.ip6po_rhi_route.ro_rt = NULL((void *)0);
1815 }
1816 }
1817 if (optname == -1 || optname == IPV6_DSTOPTS50) {
1818 if (pktopt->ip6po_dest2)
1819 free(pktopt->ip6po_dest2, M_IP6OPT123, 0);
1820 pktopt->ip6po_dest2 = NULL((void *)0);
1821 }
1822}
1823
1824#define PKTOPT_EXTHDRCPY(type) \
1825do {\
1826 if (src->type) {\
1827 size_t hlen;\
1828 hlen = (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\
1829 dst->type = malloc(hlen, M_IP6OPT123, M_NOWAIT0x0002);\
1830 if (dst->type == NULL((void *)0))\
1831 goto bad;\
1832 memcpy(dst->type, src->type, hlen)__builtin_memcpy((dst->type), (src->type), (hlen));\
1833 }\
1834} while (/*CONSTCOND*/ 0)
1835
1836int
1837copypktopts(struct ip6_pktopts *dst, struct ip6_pktopts *src)
1838{
1839 dst->ip6po_hlim = src->ip6po_hlim;
1840 dst->ip6po_tclass = src->ip6po_tclass;
1841 dst->ip6po_flags = src->ip6po_flags;
1842 if (src->ip6po_pktinfo) {
1843 dst->ip6po_pktinfo = malloc(sizeof(*dst->ip6po_pktinfo),
1844 M_IP6OPT123, M_NOWAIT0x0002);
1845 if (dst->ip6po_pktinfo == NULL((void *)0))
1846 goto bad;
1847 *dst->ip6po_pktinfo = *src->ip6po_pktinfo;
1848 }
1849 PKTOPT_EXTHDRCPY(ip6po_hbh);
1850 PKTOPT_EXTHDRCPY(ip6po_dest1);
1851 PKTOPT_EXTHDRCPY(ip6po_dest2);
1852 PKTOPT_EXTHDRCPY(ip6po_rthdrip6po_rhinfo.ip6po_rhi_rthdr); /* not copy the cached route */
1853 return (0);
1854
1855 bad:
1856 ip6_clearpktopts(dst, -1);
1857 return (ENOBUFS55);
1858}
1859#undef PKTOPT_EXTHDRCPY
1860
1861void
1862ip6_freepcbopts(struct ip6_pktopts *pktopt)
1863{
1864 if (pktopt == NULL((void *)0))
1865 return;
1866
1867 ip6_clearpktopts(pktopt, -1);
1868
1869 free(pktopt, M_IP6OPT123, 0);
1870}
1871
1872/*
1873 * Set the IP6 multicast options in response to user setsockopt().
1874 */
1875int
1876ip6_setmoptions(int optname, struct ip6_moptions **im6op, struct mbuf *m,
1877 unsigned int rtableid)
1878{
1879 int error = 0;
1880 u_int loop, ifindex;
1881 struct ipv6_mreq *mreq;
1882 struct ifnet *ifp;
1883 struct ip6_moptions *im6o = *im6op;
1884 struct in6_multi_mship *imm;
1885 struct proc *p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
; /* XXX */
1886
1887 if (im6o == NULL((void *)0)) {
1888 /*
1889 * No multicast option buffer attached to the pcb;
1890 * allocate one and initialize to default values.
1891 */
1892 im6o = malloc(sizeof(*im6o), M_IPMOPTS53, M_WAITOK0x0001);
1893 if (im6o == NULL((void *)0))
1894 return (ENOBUFS55);
1895 *im6op = im6o;
1896 im6o->im6o_ifidx = 0;
1897 im6o->im6o_hlim = ip6_defmcasthlim;
1898 im6o->im6o_loop = IPV6_DEFAULT_MULTICAST_LOOP1;
1899 LIST_INIT(&im6o->im6o_memberships)do { ((&im6o->im6o_memberships)->lh_first) = ((void
*)0); } while (0)
;
1900 }
1901
1902 switch (optname) {
1903
1904 case IPV6_MULTICAST_IF9:
1905 /*
1906 * Select the interface for outgoing multicast packets.
1907 */
1908 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(u_int)) {
1909 error = EINVAL22;
1910 break;
1911 }
1912 memcpy(&ifindex, mtod(m, u_int *), sizeof(ifindex))__builtin_memcpy((&ifindex), (((u_int *)((m)->m_hdr.mh_data
))), (sizeof(ifindex)))
;
1913 if (ifindex != 0) {
1914 ifp = if_get(ifindex);
1915 if (ifp == NULL((void *)0)) {
1916 error = ENXIO6; /* XXX EINVAL? */
1917 break;
1918 }
1919 if (ifp->if_rdomainif_data.ifi_rdomain != rtable_l2(rtableid) ||
1920 (ifp->if_flags & IFF_MULTICAST0x8000) == 0) {
1921 error = EADDRNOTAVAIL49;
1922 if_put(ifp);
1923 break;
1924 }
1925 if_put(ifp);
1926 }
1927 im6o->im6o_ifidx = ifindex;
1928 break;
1929
1930 case IPV6_MULTICAST_HOPS10:
1931 {
1932 /*
1933 * Set the IP6 hoplimit for outgoing multicast packets.
1934 */
1935 int optval;
1936 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(int)) {
1937 error = EINVAL22;
1938 break;
1939 }
1940 memcpy(&optval, mtod(m, u_int *), sizeof(optval))__builtin_memcpy((&optval), (((u_int *)((m)->m_hdr.mh_data
))), (sizeof(optval)))
;
1941 if (optval < -1 || optval >= 256)
1942 error = EINVAL22;
1943 else if (optval == -1)
1944 im6o->im6o_hlim = ip6_defmcasthlim;
1945 else
1946 im6o->im6o_hlim = optval;
1947 break;
1948 }
1949
1950 case IPV6_MULTICAST_LOOP11:
1951 /*
1952 * Set the loopback flag for outgoing multicast packets.
1953 * Must be zero or one.
1954 */
1955 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(u_int)) {
1956 error = EINVAL22;
1957 break;
1958 }
1959 memcpy(&loop, mtod(m, u_int *), sizeof(loop))__builtin_memcpy((&loop), (((u_int *)((m)->m_hdr.mh_data
))), (sizeof(loop)))
;
1960 if (loop > 1) {
1961 error = EINVAL22;
1962 break;
1963 }
1964 im6o->im6o_loop = loop;
1965 break;
1966
1967 case IPV6_JOIN_GROUP12:
1968 /*
1969 * Add a multicast group membership.
1970 * Group must be a valid IP6 multicast address.
1971 */
1972 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(struct ipv6_mreq)) {
1973 error = EINVAL22;
1974 break;
1975 }
1976 mreq = mtod(m, struct ipv6_mreq *)((struct ipv6_mreq *)((m)->m_hdr.mh_data));
1977 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)((*(const u_int32_t *)(const void *)(&(&mreq->ipv6mr_multiaddr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&mreq->ipv6mr_multiaddr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&mreq->ipv6mr_multiaddr)->__u6_addr.__u6_addr8
[8]) == 0) && (*(const u_int32_t *)(const void *)(&
(&mreq->ipv6mr_multiaddr)->__u6_addr.__u6_addr8[12]
) == 0))
) {
1978 /*
1979 * We use the unspecified address to specify to accept
1980 * all multicast addresses. Only super user is allowed
1981 * to do this.
1982 */
1983 if (suser(p))
1984 {
1985 error = EACCES13;
1986 break;
1987 }
1988 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)((&mreq->ipv6mr_multiaddr)->__u6_addr.__u6_addr8[0]
== 0xff)
) {
1989 error = EINVAL22;
1990 break;
1991 }
1992
1993 /*
1994 * If no interface was explicitly specified, choose an
1995 * appropriate one according to the given multicast address.
1996 */
1997 if (mreq->ipv6mr_interface == 0) {
1998 struct rtentry *rt;
1999 struct sockaddr_in6 dst;
2000
2001 memset(&dst, 0, sizeof(dst))__builtin_memset((&dst), (0), (sizeof(dst)));
2002 dst.sin6_len = sizeof(dst);
2003 dst.sin6_family = AF_INET624;
2004 dst.sin6_addr = mreq->ipv6mr_multiaddr;
2005 rt = rtalloc(sin6tosa(&dst), RT_RESOLVE1, rtableid);
2006 if (rt == NULL((void *)0)) {
2007 error = EADDRNOTAVAIL49;
2008 break;
2009 }
2010 ifp = if_get(rt->rt_ifidx);
2011 rtfree(rt);
2012 } else {
2013 /*
2014 * If the interface is specified, validate it.
2015 */
2016 ifp = if_get(mreq->ipv6mr_interface);
2017 if (ifp == NULL((void *)0)) {
2018 error = ENXIO6; /* XXX EINVAL? */
2019 break;
2020 }
2021 }
2022
2023 /*
2024 * See if we found an interface, and confirm that it
2025 * supports multicast
2026 */
2027 if (ifp == NULL((void *)0) || ifp->if_rdomainif_data.ifi_rdomain != rtable_l2(rtableid) ||
2028 (ifp->if_flags & IFF_MULTICAST0x8000) == 0) {
2029 if_put(ifp);
2030 error = EADDRNOTAVAIL49;
2031 break;
2032 }
2033 /*
2034 * Put interface index into the multicast address,
2035 * if the address has link/interface-local scope.
2036 */
2037 if (IN6_IS_SCOPE_EMBED(&mreq->ipv6mr_multiaddr)(((((&mreq->ipv6mr_multiaddr)->__u6_addr.__u6_addr8
[0] == 0xfe) && (((&mreq->ipv6mr_multiaddr)->
__u6_addr.__u6_addr8[1] & 0xc0) == 0x80))) || ((((&mreq
->ipv6mr_multiaddr)->__u6_addr.__u6_addr8[0] == 0xff) &&
(((&mreq->ipv6mr_multiaddr)->__u6_addr.__u6_addr8[
1] & 0x0f) == 0x02))) || ((((&mreq->ipv6mr_multiaddr
)->__u6_addr.__u6_addr8[0] == 0xff) && (((&mreq
->ipv6mr_multiaddr)->__u6_addr.__u6_addr8[1] & 0x0f
) == 0x01))))
) {
2038 mreq->ipv6mr_multiaddr.s6_addr16__u6_addr.__u6_addr16[1] =
2039 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))
;
2040 }
2041 /*
2042 * See if the membership already exists.
2043 */
2044 LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain)for((imm) = ((&im6o->im6o_memberships)->lh_first); (
imm)!= ((void *)0); (imm) = ((imm)->i6mm_chain.le_next))
2045 if (imm->i6mm_maddr->in6m_ifidxin6m_ifma.ifma_ifidx == ifp->if_index &&
2046 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,(__builtin_memcmp((&(&imm->i6mm_maddr->in6m_sin
.sin6_addr)->__u6_addr.__u6_addr8[0]), (&(&mreq->
ipv6mr_multiaddr)->__u6_addr.__u6_addr8[0]), (sizeof(struct
in6_addr))) == 0)
2047 &mreq->ipv6mr_multiaddr)(__builtin_memcmp((&(&imm->i6mm_maddr->in6m_sin
.sin6_addr)->__u6_addr.__u6_addr8[0]), (&(&mreq->
ipv6mr_multiaddr)->__u6_addr.__u6_addr8[0]), (sizeof(struct
in6_addr))) == 0)
)
2048 break;
2049 if (imm != NULL((void *)0)) {
2050 if_put(ifp);
2051 error = EADDRINUSE48;
2052 break;
2053 }
2054 /*
2055 * Everything looks good; add a new record to the multicast
2056 * address list for the given interface.
2057 */
2058 imm = in6_joingroup(ifp, &mreq->ipv6mr_multiaddr, &error);
2059 if_put(ifp);
2060 if (!imm)
2061 break;
2062 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain)do { if (((imm)->i6mm_chain.le_next = (&im6o->im6o_memberships
)->lh_first) != ((void *)0)) (&im6o->im6o_memberships
)->lh_first->i6mm_chain.le_prev = &(imm)->i6mm_chain
.le_next; (&im6o->im6o_memberships)->lh_first = (imm
); (imm)->i6mm_chain.le_prev = &(&im6o->im6o_memberships
)->lh_first; } while (0)
;
2063 break;
2064
2065 case IPV6_LEAVE_GROUP13:
2066 /*
2067 * Drop a multicast group membership.
2068 * Group must be a valid IP6 multicast address.
2069 */
2070 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(struct ipv6_mreq)) {
2071 error = EINVAL22;
2072 break;
2073 }
2074 mreq = mtod(m, struct ipv6_mreq *)((struct ipv6_mreq *)((m)->m_hdr.mh_data));
2075 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)((*(const u_int32_t *)(const void *)(&(&mreq->ipv6mr_multiaddr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&mreq->ipv6mr_multiaddr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&mreq->ipv6mr_multiaddr)->__u6_addr.__u6_addr8
[8]) == 0) && (*(const u_int32_t *)(const void *)(&
(&mreq->ipv6mr_multiaddr)->__u6_addr.__u6_addr8[12]
) == 0))
) {
2076 if (suser(p)) {
2077 error = EACCES13;
2078 break;
2079 }
2080 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)((&mreq->ipv6mr_multiaddr)->__u6_addr.__u6_addr8[0]
== 0xff)
) {
2081 error = EINVAL22;
2082 break;
2083 }
2084
2085 /*
2086 * Put interface index into the multicast address,
2087 * if the address has link-local scope.
2088 */
2089 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)(((&mreq->ipv6mr_multiaddr)->__u6_addr.__u6_addr8[0
] == 0xff) && (((&mreq->ipv6mr_multiaddr)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))
) {
2090 mreq->ipv6mr_multiaddr.s6_addr16__u6_addr.__u6_addr16[1] =
2091 htons(mreq->ipv6mr_interface)(__uint16_t)(__builtin_constant_p(mreq->ipv6mr_interface) ?
(__uint16_t)(((__uint16_t)(mreq->ipv6mr_interface) & 0xffU
) << 8 | ((__uint16_t)(mreq->ipv6mr_interface) &
0xff00U) >> 8) : __swap16md(mreq->ipv6mr_interface)
)
;
2092 }
2093
2094 /*
2095 * If an interface address was specified, get a pointer
2096 * to its ifnet structure.
2097 */
2098 if (mreq->ipv6mr_interface == 0)
2099 ifp = NULL((void *)0);
2100 else {
2101 ifp = if_get(mreq->ipv6mr_interface);
2102 if (ifp == NULL((void *)0)) {
2103 error = ENXIO6; /* XXX EINVAL? */
2104 break;
2105 }
2106 }
2107
2108 /*
2109 * Find the membership in the membership list.
2110 */
2111 LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain)for((imm) = ((&im6o->im6o_memberships)->lh_first); (
imm)!= ((void *)0); (imm) = ((imm)->i6mm_chain.le_next))
{
2112 if ((ifp == NULL((void *)0) ||
2113 imm->i6mm_maddr->in6m_ifidxin6m_ifma.ifma_ifidx == ifp->if_index) &&
2114 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,(__builtin_memcmp((&(&imm->i6mm_maddr->in6m_sin
.sin6_addr)->__u6_addr.__u6_addr8[0]), (&(&mreq->
ipv6mr_multiaddr)->__u6_addr.__u6_addr8[0]), (sizeof(struct
in6_addr))) == 0)
2115 &mreq->ipv6mr_multiaddr)(__builtin_memcmp((&(&imm->i6mm_maddr->in6m_sin
.sin6_addr)->__u6_addr.__u6_addr8[0]), (&(&mreq->
ipv6mr_multiaddr)->__u6_addr.__u6_addr8[0]), (sizeof(struct
in6_addr))) == 0)
)
2116 break;
2117 }
2118
2119 if_put(ifp);
2120
2121 if (imm == NULL((void *)0)) {
2122 /* Unable to resolve interface */
2123 error = EADDRNOTAVAIL49;
2124 break;
2125 }
2126 /*
2127 * Give up the multicast address record to which the
2128 * membership points.
2129 */
2130 LIST_REMOVE(imm, i6mm_chain)do { if ((imm)->i6mm_chain.le_next != ((void *)0)) (imm)->
i6mm_chain.le_next->i6mm_chain.le_prev = (imm)->i6mm_chain
.le_prev; *(imm)->i6mm_chain.le_prev = (imm)->i6mm_chain
.le_next; ((imm)->i6mm_chain.le_prev) = ((void *)-1); ((imm
)->i6mm_chain.le_next) = ((void *)-1); } while (0)
;
2131 in6_leavegroup(imm);
2132 break;
2133
2134 default:
2135 error = EOPNOTSUPP45;
2136 break;
2137 }
2138
2139 /*
2140 * If all options have default values, no need to keep the option
2141 * structure.
2142 */
2143 if (im6o->im6o_ifidx == 0 &&
2144 im6o->im6o_hlim == ip6_defmcasthlim &&
2145 im6o->im6o_loop == IPV6_DEFAULT_MULTICAST_LOOP1 &&
2146 LIST_EMPTY(&im6o->im6o_memberships)(((&im6o->im6o_memberships)->lh_first) == ((void *)
0))
) {
2147 free(*im6op, M_IPMOPTS53, sizeof(**im6op));
2148 *im6op = NULL((void *)0);
2149 }
2150
2151 return (error);
2152}
2153
2154/*
2155 * Return the IP6 multicast options in response to user getsockopt().
2156 */
2157int
2158ip6_getmoptions(int optname, struct ip6_moptions *im6o, struct mbuf *m)
2159{
2160 u_int *hlim, *loop, *ifindex;
2161
2162 switch (optname) {
2163 case IPV6_MULTICAST_IF9:
2164 ifindex = mtod(m, u_int *)((u_int *)((m)->m_hdr.mh_data));
2165 m->m_lenm_hdr.mh_len = sizeof(u_int);
2166 if (im6o == NULL((void *)0) || im6o->im6o_ifidx == 0)
2167 *ifindex = 0;
2168 else
2169 *ifindex = im6o->im6o_ifidx;
2170 return (0);
2171
2172 case IPV6_MULTICAST_HOPS10:
2173 hlim = mtod(m, u_int *)((u_int *)((m)->m_hdr.mh_data));
2174 m->m_lenm_hdr.mh_len = sizeof(u_int);
2175 if (im6o == NULL((void *)0))
2176 *hlim = ip6_defmcasthlim;
2177 else
2178 *hlim = im6o->im6o_hlim;
2179 return (0);
2180
2181 case IPV6_MULTICAST_LOOP11:
2182 loop = mtod(m, u_int *)((u_int *)((m)->m_hdr.mh_data));
2183 m->m_lenm_hdr.mh_len = sizeof(u_int);
2184 if (im6o == NULL((void *)0))
2185 *loop = ip6_defmcasthlim;
2186 else
2187 *loop = im6o->im6o_loop;
2188 return (0);
2189
2190 default:
2191 return (EOPNOTSUPP45);
2192 }
2193}
2194
2195/*
2196 * Discard the IP6 multicast options.
2197 */
2198void
2199ip6_freemoptions(struct ip6_moptions *im6o)
2200{
2201 struct in6_multi_mship *imm;
2202
2203 if (im6o == NULL((void *)0))
2204 return;
2205
2206 while (!LIST_EMPTY(&im6o->im6o_memberships)(((&im6o->im6o_memberships)->lh_first) == ((void *)
0))
) {
2207 imm = LIST_FIRST(&im6o->im6o_memberships)((&im6o->im6o_memberships)->lh_first);
2208 LIST_REMOVE(imm, i6mm_chain)do { if ((imm)->i6mm_chain.le_next != ((void *)0)) (imm)->
i6mm_chain.le_next->i6mm_chain.le_prev = (imm)->i6mm_chain
.le_prev; *(imm)->i6mm_chain.le_prev = (imm)->i6mm_chain
.le_next; ((imm)->i6mm_chain.le_prev) = ((void *)-1); ((imm
)->i6mm_chain.le_next) = ((void *)-1); } while (0)
;
2209 in6_leavegroup(imm);
2210 }
2211 free(im6o, M_IPMOPTS53, sizeof(*im6o));
2212}
2213
2214/*
2215 * Set IPv6 outgoing packet options based on advanced API.
2216 */
2217int
2218ip6_setpktopts(struct mbuf *control, struct ip6_pktopts *opt,
2219 struct ip6_pktopts *stickyopt, int priv, int uproto)
2220{
2221 u_int clen;
2222 struct cmsghdr *cm = 0;
2223 caddr_t cmsgs;
2224 int error;
2225
2226 if (control == NULL((void *)0) || opt == NULL((void *)0))
2227 return (EINVAL22);
2228
2229 ip6_initpktopts(opt);
2230 if (stickyopt) {
2231 int error;
2232
2233 /*
2234 * If stickyopt is provided, make a local copy of the options
2235 * for this particular packet, then override them by ancillary
2236 * objects.
2237 * XXX: copypktopts() does not copy the cached route to a next
2238 * hop (if any). This is not very good in terms of efficiency,
2239 * but we can allow this since this option should be rarely
2240 * used.
2241 */
2242 if ((error = copypktopts(opt, stickyopt)) != 0)
2243 return (error);
2244 }
2245
2246 /*
2247 * XXX: Currently, we assume all the optional information is stored
2248 * in a single mbuf.
2249 */
2250 if (control->m_nextm_hdr.mh_next)
2251 return (EINVAL22);
2252
2253 clen = control->m_lenm_hdr.mh_len;
2254 cmsgs = mtod(control, caddr_t)((caddr_t)((control)->m_hdr.mh_data));
2255 do {
2256 if (clen < CMSG_LEN(0)((((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1)) + (0))
)
2257 return (EINVAL22);
2258 cm = (struct cmsghdr *)cmsgs;
2259 if (cm->cmsg_len < CMSG_LEN(0)((((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1)) + (0))
|| cm->cmsg_len > clen ||
2260 CMSG_ALIGN(cm->cmsg_len)(((unsigned long)(cm->cmsg_len) + (sizeof(long) - 1)) &
~(sizeof(long) - 1))
> clen)
2261 return (EINVAL22);
2262 if (cm->cmsg_level == IPPROTO_IPV641) {
2263 error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm)((unsigned char *)(cm) + (((unsigned long)(sizeof(struct cmsghdr
)) + (sizeof(long) - 1)) &~(sizeof(long) - 1)))
,
2264 cm->cmsg_len - CMSG_LEN(0)((((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1)) + (0))
, opt, priv, 0, uproto);
2265 if (error)
2266 return (error);
2267 }
2268
2269 clen -= CMSG_ALIGN(cm->cmsg_len)(((unsigned long)(cm->cmsg_len) + (sizeof(long) - 1)) &
~(sizeof(long) - 1))
;
2270 cmsgs += CMSG_ALIGN(cm->cmsg_len)(((unsigned long)(cm->cmsg_len) + (sizeof(long) - 1)) &
~(sizeof(long) - 1))
;
2271 } while (clen);
2272
2273 return (0);
2274}
2275
2276/*
2277 * Set a particular packet option, as a sticky option or an ancillary data
2278 * item. "len" can be 0 only when it's a sticky option.
2279 */
2280int
2281ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt,
2282 int priv, int sticky, int uproto)
2283{
2284 int minmtupolicy;
2285
2286 switch (optname) {
2287 case IPV6_PKTINFO46:
2288 {
2289 struct ifnet *ifp = NULL((void *)0);
2290 struct in6_pktinfo *pktinfo;
2291
2292 if (len != sizeof(struct in6_pktinfo))
2293 return (EINVAL22);
2294
2295 pktinfo = (struct in6_pktinfo *)buf;
2296
2297 /*
2298 * An application can clear any sticky IPV6_PKTINFO option by
2299 * doing a "regular" setsockopt with ipi6_addr being
2300 * in6addr_any and ipi6_ifindex being zero.
2301 * [RFC 3542, Section 6]
2302 */
2303 if (opt->ip6po_pktinfo &&
2304 pktinfo->ipi6_ifindex == 0 &&
2305 IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)((*(const u_int32_t *)(const void *)(&(&pktinfo->ipi6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&pktinfo->ipi6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&pktinfo->ipi6_addr)->__u6_addr.__u6_addr8
[8]) == 0) && (*(const u_int32_t *)(const void *)(&
(&pktinfo->ipi6_addr)->__u6_addr.__u6_addr8[12]) ==
0))
) {
2306 ip6_clearpktopts(opt, optname);
2307 break;
2308 }
2309
2310 if (uproto == IPPROTO_TCP6 &&
2311 sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)((*(const u_int32_t *)(const void *)(&(&pktinfo->ipi6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&pktinfo->ipi6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&pktinfo->ipi6_addr)->__u6_addr.__u6_addr8
[8]) == 0) && (*(const u_int32_t *)(const void *)(&
(&pktinfo->ipi6_addr)->__u6_addr.__u6_addr8[12]) ==
0))
) {
2312 return (EINVAL22);
2313 }
2314
2315 if (pktinfo->ipi6_ifindex) {
2316 ifp = if_get(pktinfo->ipi6_ifindex);
2317 if (ifp == NULL((void *)0))
2318 return (ENXIO6);
2319 if_put(ifp);
2320 }
2321
2322 /*
2323 * We store the address anyway, and let in6_selectsrc()
2324 * validate the specified address. This is because ipi6_addr
2325 * may not have enough information about its scope zone, and
2326 * we may need additional information (such as outgoing
2327 * interface or the scope zone of a destination address) to
2328 * disambiguate the scope.
2329 * XXX: the delay of the validation may confuse the
2330 * application when it is used as a sticky option.
2331 */
2332 if (opt->ip6po_pktinfo == NULL((void *)0)) {
2333 opt->ip6po_pktinfo = malloc(sizeof(*pktinfo),
2334 M_IP6OPT123, M_NOWAIT0x0002);
2335 if (opt->ip6po_pktinfo == NULL((void *)0))
2336 return (ENOBUFS55);
2337 }
2338 bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo));
2339 break;
2340 }
2341
2342 case IPV6_HOPLIMIT47:
2343 {
2344 int *hlimp;
2345
2346 /*
2347 * RFC 3542 deprecated the usage of sticky IPV6_HOPLIMIT
2348 * to simplify the ordering among hoplimit options.
2349 */
2350 if (sticky)
2351 return (ENOPROTOOPT42);
2352
2353 if (len != sizeof(int))
2354 return (EINVAL22);
2355 hlimp = (int *)buf;
2356 if (*hlimp < -1 || *hlimp > 255)
2357 return (EINVAL22);
2358
2359 opt->ip6po_hlim = *hlimp;
2360 break;
2361 }
2362
2363 case IPV6_TCLASS61:
2364 {
2365 int tclass;
2366
2367 if (len != sizeof(int))
2368 return (EINVAL22);
2369 tclass = *(int *)buf;
2370 if (tclass < -1 || tclass > 255)
2371 return (EINVAL22);
2372
2373 opt->ip6po_tclass = tclass;
2374 break;
2375 }
2376 case IPV6_HOPOPTS49:
2377 {
2378 struct ip6_hbh *hbh;
2379 int hbhlen;
2380
2381 /*
2382 * XXX: We don't allow a non-privileged user to set ANY HbH
2383 * options, since per-option restriction has too much
2384 * overhead.
2385 */
2386 if (!priv)
2387 return (EPERM1);
2388
2389 if (len == 0) {
2390 ip6_clearpktopts(opt, IPV6_HOPOPTS49);
2391 break; /* just remove the option */
2392 }
2393
2394 /* message length validation */
2395 if (len < sizeof(struct ip6_hbh))
2396 return (EINVAL22);
2397 hbh = (struct ip6_hbh *)buf;
2398 hbhlen = (hbh->ip6h_len + 1) << 3;
2399 if (len != hbhlen)
2400 return (EINVAL22);
2401
2402 /* turn off the previous option, then set the new option. */
2403 ip6_clearpktopts(opt, IPV6_HOPOPTS49);
2404 opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT123, M_NOWAIT0x0002);
2405 if (opt->ip6po_hbh == NULL((void *)0))
2406 return (ENOBUFS55);
2407 memcpy(opt->ip6po_hbh, hbh, hbhlen)__builtin_memcpy((opt->ip6po_hbh), (hbh), (hbhlen));
2408
2409 break;
2410 }
2411
2412 case IPV6_DSTOPTS50:
2413 case IPV6_RTHDRDSTOPTS35:
2414 {
2415 struct ip6_dest *dest, **newdest = NULL((void *)0);
2416 int destlen;
2417
2418 if (!priv) /* XXX: see the comment for IPV6_HOPOPTS */
2419 return (EPERM1);
2420
2421 if (len == 0) {
2422 ip6_clearpktopts(opt, optname);
2423 break; /* just remove the option */
2424 }
2425
2426 /* message length validation */
2427 if (len < sizeof(struct ip6_dest))
2428 return (EINVAL22);
2429 dest = (struct ip6_dest *)buf;
2430 destlen = (dest->ip6d_len + 1) << 3;
2431 if (len != destlen)
2432 return (EINVAL22);
2433 /*
2434 * Determine the position that the destination options header
2435 * should be inserted; before or after the routing header.
2436 */
2437 switch (optname) {
2438 case IPV6_RTHDRDSTOPTS35:
2439 newdest = &opt->ip6po_dest1;
2440 break;
2441 case IPV6_DSTOPTS50:
2442 newdest = &opt->ip6po_dest2;
2443 break;
2444 }
2445
2446 /* turn off the previous option, then set the new option. */
2447 ip6_clearpktopts(opt, optname);
2448 *newdest = malloc(destlen, M_IP6OPT123, M_NOWAIT0x0002);
2449 if (*newdest == NULL((void *)0))
2450 return (ENOBUFS55);
2451 memcpy(*newdest, dest, destlen)__builtin_memcpy((*newdest), (dest), (destlen));
2452
2453 break;
2454 }
2455
2456 case IPV6_RTHDR51:
2457 {
2458 struct ip6_rthdr *rth;
2459 int rthlen;
2460
2461 if (len == 0) {
2462 ip6_clearpktopts(opt, IPV6_RTHDR51);
2463 break; /* just remove the option */
2464 }
2465
2466 /* message length validation */
2467 if (len < sizeof(struct ip6_rthdr))
2468 return (EINVAL22);
2469 rth = (struct ip6_rthdr *)buf;
2470 rthlen = (rth->ip6r_len + 1) << 3;
2471 if (len != rthlen)
2472 return (EINVAL22);
2473
2474 switch (rth->ip6r_type) {
2475 case IPV6_RTHDR_TYPE_00:
2476 if (rth->ip6r_len == 0) /* must contain one addr */
2477 return (EINVAL22);
2478 if (rth->ip6r_len % 2) /* length must be even */
2479 return (EINVAL22);
2480 if (rth->ip6r_len / 2 != rth->ip6r_segleft)
2481 return (EINVAL22);
2482 break;
2483 default:
2484 return (EINVAL22); /* not supported */
2485 }
2486 /* turn off the previous option */
2487 ip6_clearpktopts(opt, IPV6_RTHDR51);
2488 opt->ip6po_rthdrip6po_rhinfo.ip6po_rhi_rthdr = malloc(rthlen, M_IP6OPT123, M_NOWAIT0x0002);
2489 if (opt->ip6po_rthdrip6po_rhinfo.ip6po_rhi_rthdr == NULL((void *)0))
2490 return (ENOBUFS55);
2491 memcpy(opt->ip6po_rthdr, rth, rthlen)__builtin_memcpy((opt->ip6po_rhinfo.ip6po_rhi_rthdr), (rth
), (rthlen))
;
2492 break;
2493 }
2494
2495 case IPV6_USE_MIN_MTU42:
2496 if (len != sizeof(int))
2497 return (EINVAL22);
2498 minmtupolicy = *(int *)buf;
2499 if (minmtupolicy != IP6PO_MINMTU_MCASTONLY-1 &&
2500 minmtupolicy != IP6PO_MINMTU_DISABLE0 &&
2501 minmtupolicy != IP6PO_MINMTU_ALL1) {
2502 return (EINVAL22);
2503 }
2504 opt->ip6po_minmtu = minmtupolicy;
2505 break;
2506
2507 case IPV6_DONTFRAG62:
2508 if (len != sizeof(int))
2509 return (EINVAL22);
2510
2511 if (uproto == IPPROTO_TCP6 || *(int *)buf == 0) {
2512 /*
2513 * we ignore this option for TCP sockets.
2514 * (RFC3542 leaves this case unspecified.)
2515 */
2516 opt->ip6po_flags &= ~IP6PO_DONTFRAG0x04;
2517 } else
2518 opt->ip6po_flags |= IP6PO_DONTFRAG0x04;
2519 break;
2520
2521 default:
2522 return (ENOPROTOOPT42);
2523 } /* end of switch */
2524
2525 return (0);
2526}
2527
2528/*
2529 * Routine called from ip6_output() to loop back a copy of an IP6 multicast
2530 * packet to the input queue of a specified interface.
2531 */
2532void
2533ip6_mloopback(struct ifnet *ifp, struct mbuf *m, struct sockaddr_in6 *dst)
2534{
2535 struct mbuf *copym;
2536 struct ip6_hdr *ip6;
2537
2538 /*
2539 * Duplicate the packet.
2540 */
2541 copym = m_copym(m, 0, M_COPYALL1000000000, M_NOWAIT0x0002);
2542 if (copym == NULL((void *)0))
2543 return;
2544
2545 /*
2546 * Make sure to deep-copy IPv6 header portion in case the data
2547 * is in an mbuf cluster, so that we can safely override the IPv6
2548 * header portion later.
2549 */
2550 if ((copym->m_flagsm_hdr.mh_flags & M_EXT0x0001) != 0 ||
2551 copym->m_lenm_hdr.mh_len < sizeof(struct ip6_hdr)) {
2552 copym = m_pullup(copym, sizeof(struct ip6_hdr));
2553 if (copym == NULL((void *)0))
2554 return;
2555 }
2556
2557#ifdef DIAGNOSTIC1
2558 if (copym->m_lenm_hdr.mh_len < sizeof(*ip6)) {
2559 m_freem(copym);
2560 return;
2561 }
2562#endif
2563
2564 ip6 = mtod(copym, struct ip6_hdr *)((struct ip6_hdr *)((copym)->m_hdr.mh_data));
2565 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))))
)
2566 ip6->ip6_src.s6_addr16__u6_addr.__u6_addr16[1] = 0;
2567 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))))
)
2568 ip6->ip6_dst.s6_addr16__u6_addr.__u6_addr16[1] = 0;
2569
2570 if_input_local(ifp, copym, dst->sin6_family);
2571}
2572
2573/*
2574 * Chop IPv6 header off from the payload.
2575 */
2576int
2577ip6_splithdr(struct mbuf *m, struct ip6_exthdrs *exthdrs)
2578{
2579 struct mbuf *mh;
2580 struct ip6_hdr *ip6;
2581
2582 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
2583 if (m->m_lenm_hdr.mh_len > sizeof(*ip6)) {
2584 MGET(mh, M_DONTWAIT, MT_HEADER)mh = m_get((0x0002), (2));
2585 if (mh == NULL((void *)0)) {
2586 m_freem(m);
2587 return ENOBUFS55;
2588 }
2589 M_MOVE_PKTHDR(mh, m)do { (mh)->m_hdr.mh_flags = ((mh)->m_hdr.mh_flags &
(0x0001 | 0x0008)); (mh)->m_hdr.mh_flags |= (m)->m_hdr
.mh_flags & (0x0002|0x0004|0x0010|0x0100|0x0200|0x0400|0x4000
| 0x0800|0x0040|0x1000|0x8000|0x0020|0x2000); do { ((mh))->
M_dat.MH.MH_pkthdr = ((m))->M_dat.MH.MH_pkthdr; ((m))->
m_hdr.mh_flags &= ~0x0002; { ((&((m))->M_dat.MH.MH_pkthdr
.ph_tags)->slh_first) = ((void *)0); }; ((m))->M_dat.MH
.MH_pkthdr.pf.statekey = ((void *)0); } while ( 0); if (((mh)
->m_hdr.mh_flags & 0x0001) == 0) (mh)->m_hdr.mh_data
= (mh)->M_dat.MH.MH_dat.MH_databuf; } while ( 0)
;
2590 m_align(mh, sizeof(*ip6));
2591 m->m_lenm_hdr.mh_len -= sizeof(*ip6);
2592 m->m_datam_hdr.mh_data += sizeof(*ip6);
2593 mh->m_nextm_hdr.mh_next = m;
2594 m = mh;
2595 m->m_lenm_hdr.mh_len = sizeof(*ip6);
2596 bcopy((caddr_t)ip6, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), sizeof(*ip6));
2597 }
2598 exthdrs->ip6e_ip6 = m;
2599 return 0;
2600}
2601
2602u_int32_t
2603ip6_randomid(void)
2604{
2605 return idgen32(&ip6_id_ctx);
2606}
2607
2608void
2609ip6_randomid_init(void)
2610{
2611 idgen32_init(&ip6_id_ctx);
2612}
2613
2614/*
2615 * Compute significant parts of the IPv6 checksum pseudo-header
2616 * for use in a delayed TCP/UDP checksum calculation.
2617 */
2618static __inline u_int16_t __attribute__((__unused__))
2619in6_cksum_phdr(const struct in6_addr *src, const struct in6_addr *dst,
2620 u_int32_t len, u_int32_t nxt)
2621{
2622 u_int32_t sum = 0;
2623 const u_int16_t *w;
2624
2625 w = (const u_int16_t *) src;
2626 sum += w[0];
2627 if (!IN6_IS_SCOPE_EMBED(src)(((((src)->__u6_addr.__u6_addr8[0] == 0xfe) && (((
src)->__u6_addr.__u6_addr8[1] & 0xc0) == 0x80))) || ((
((src)->__u6_addr.__u6_addr8[0] == 0xff) && (((src
)->__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((src
)->__u6_addr.__u6_addr8[0] == 0xff) && (((src)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x01))))
)
2628 sum += w[1];
2629 sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
2630 sum += w[6]; sum += w[7];
2631
2632 w = (const u_int16_t *) dst;
2633 sum += w[0];
2634 if (!IN6_IS_SCOPE_EMBED(dst)(((((dst)->__u6_addr.__u6_addr8[0] == 0xfe) && (((
dst)->__u6_addr.__u6_addr8[1] & 0xc0) == 0x80))) || ((
((dst)->__u6_addr.__u6_addr8[0] == 0xff) && (((dst
)->__u6_addr.__u6_addr8[1] & 0x0f) == 0x02))) || ((((dst
)->__u6_addr.__u6_addr8[0] == 0xff) && (((dst)->
__u6_addr.__u6_addr8[1] & 0x0f) == 0x01))))
)
2635 sum += w[1];
2636 sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
2637 sum += w[6]; sum += w[7];
2638
2639 sum += (u_int16_t)(len >> 16) + (u_int16_t)(len /*& 0xffff*/);
2640
2641 sum += (u_int16_t)(nxt >> 16) + (u_int16_t)(nxt /*& 0xffff*/);
2642
2643 sum = (u_int16_t)(sum >> 16) + (u_int16_t)(sum /*& 0xffff*/);
2644
2645 if (sum > 0xffff)
2646 sum -= 0xffff;
2647
2648 return (sum);
2649}
2650
2651/*
2652 * Process a delayed payload checksum calculation.
2653 */
2654void
2655in6_delayed_cksum(struct mbuf *m, u_int8_t nxt)
2656{
2657 int nxtp, offset;
2658 u_int16_t csum;
2659
2660 offset = ip6_lasthdr(m, 0, IPPROTO_IPV641, &nxtp);
2661 if (offset <= 0 || nxtp != nxt)
2662 /* If the desired next protocol isn't found, punt. */
2663 return;
2664 csum = (u_int16_t)(in6_cksum(m, 0, offset, m->m_pkthdrM_dat.MH.MH_pkthdr.len - offset));
2665
2666 switch (nxt) {
2667 case IPPROTO_TCP6:
2668 offset += offsetof(struct tcphdr, th_sum)__builtin_offsetof(struct tcphdr, th_sum);
2669 break;
2670
2671 case IPPROTO_UDP17:
2672 offset += offsetof(struct udphdr, uh_sum)__builtin_offsetof(struct udphdr, uh_sum);
2673 if (csum == 0)
2674 csum = 0xffff;
2675 break;
2676
2677 case IPPROTO_ICMPV658:
2678 offset += offsetof(struct icmp6_hdr, icmp6_cksum)__builtin_offsetof(struct icmp6_hdr, icmp6_cksum);
2679 break;
2680 }
2681
2682 if ((offset + sizeof(u_int16_t)) > m->m_lenm_hdr.mh_len)
2683 m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT0x0002);
2684 else
2685 *(u_int16_t *)(mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)) + offset) = csum;
2686}
2687
2688void
2689in6_proto_cksum_out(struct mbuf *m, struct ifnet *ifp)
2690{
2691 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
2692
2693 /* some hw and in6_delayed_cksum need the pseudo header cksum */
2694 if (m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags &
2695 (M_TCP_CSUM_OUT0x0002|M_UDP_CSUM_OUT0x0004|M_ICMP_CSUM_OUT0x0200)) {
2696 int nxt, offset;
2697 u_int16_t csum;
2698
2699 offset = ip6_lasthdr(m, 0, IPPROTO_IPV641, &nxt);
2700 if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)((m->M_dat.MH.MH_pkthdr.csum_flags) & (0x8000)) &&
2701 in_ifcap_cksum(m, ifp, IFCAP_TSOv60x00002000)) {
2702 csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
2703 htonl(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
, htonl(nxt)(__uint32_t)(__builtin_constant_p(nxt) ? (__uint32_t)(((__uint32_t
)(nxt) & 0xff) << 24 | ((__uint32_t)(nxt) & 0xff00
) << 8 | ((__uint32_t)(nxt) & 0xff0000) >> 8 |
((__uint32_t)(nxt) & 0xff000000) >> 24) : __swap32md
(nxt))
);
2704 } else {
2705 csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
2706 htonl(m->m_pkthdr.len - offset)(__uint32_t)(__builtin_constant_p(m->M_dat.MH.MH_pkthdr.len
- offset) ? (__uint32_t)(((__uint32_t)(m->M_dat.MH.MH_pkthdr
.len - offset) & 0xff) << 24 | ((__uint32_t)(m->
M_dat.MH.MH_pkthdr.len - offset) & 0xff00) << 8 | (
(__uint32_t)(m->M_dat.MH.MH_pkthdr.len - offset) & 0xff0000
) >> 8 | ((__uint32_t)(m->M_dat.MH.MH_pkthdr.len - offset
) & 0xff000000) >> 24) : __swap32md(m->M_dat.MH.
MH_pkthdr.len - offset))
, htonl(nxt)(__uint32_t)(__builtin_constant_p(nxt) ? (__uint32_t)(((__uint32_t
)(nxt) & 0xff) << 24 | ((__uint32_t)(nxt) & 0xff00
) << 8 | ((__uint32_t)(nxt) & 0xff0000) >> 8 |
((__uint32_t)(nxt) & 0xff000000) >> 24) : __swap32md
(nxt))
);
2707 }
2708 if (nxt == IPPROTO_TCP6)
2709 offset += offsetof(struct tcphdr, th_sum)__builtin_offsetof(struct tcphdr, th_sum);
2710 else if (nxt == IPPROTO_UDP17)
2711 offset += offsetof(struct udphdr, uh_sum)__builtin_offsetof(struct udphdr, uh_sum);
2712 else if (nxt == IPPROTO_ICMPV658)
2713 offset += offsetof(struct icmp6_hdr, icmp6_cksum)__builtin_offsetof(struct icmp6_hdr, icmp6_cksum);
2714 if ((offset + sizeof(u_int16_t)) > m->m_lenm_hdr.mh_len)
2715 m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT0x0002);
2716 else
2717 *(u_int16_t *)(mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)) + offset) = csum;
2718 }
2719
2720 if (m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags & M_TCP_CSUM_OUT0x0002) {
2721 if (!ifp || !(ifp->if_capabilitiesif_data.ifi_capabilities & IFCAP_CSUM_TCPv60x00000080) ||
2722 ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_TCP6 ||
2723 ifp->if_bridgeidx != 0) {
2724 tcpstat_inc(tcps_outswcsum);
2725 in6_delayed_cksum(m, IPPROTO_TCP6);
2726 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags &= ~M_TCP_CSUM_OUT0x0002; /* Clear */
2727 }
2728 } else if (m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags & M_UDP_CSUM_OUT0x0004) {
2729 if (!ifp || !(ifp->if_capabilitiesif_data.ifi_capabilities & IFCAP_CSUM_UDPv60x00000100) ||
2730 ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_UDP17 ||
2731 ifp->if_bridgeidx != 0) {
2732 udpstat_inc(udps_outswcsum);
2733 in6_delayed_cksum(m, IPPROTO_UDP17);
2734 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT0x0004; /* Clear */
2735 }
2736 } else if (m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags & M_ICMP_CSUM_OUT0x0200) {
2737 in6_delayed_cksum(m, IPPROTO_ICMPV658);
2738 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT0x0200; /* Clear */
2739 }
2740}
2741
2742#ifdef IPSEC1
2743int
2744ip6_output_ipsec_lookup(struct mbuf *m, const u_char seclevel[],
2745 struct tdb **tdbout)
2746{
2747 struct tdb *tdb;
2748 struct m_tag *mtag;
2749 struct tdb_ident *tdbi;
2750 int error;
2751
2752 /*
2753 * Check if there was an outgoing SA bound to the flow
2754 * from a transport protocol.
2755 */
2756
2757 /* Do we have any pending SAs to apply ? */
2758 error = ipsp_spd_lookup(m, AF_INET624, sizeof(struct ip6_hdr),
2759 IPSP_DIRECTION_OUT0x2, NULL((void *)0), seclevel, &tdb, NULL((void *)0));
2760 if (error || tdb == NULL((void *)0)) {
2761 *tdbout = NULL((void *)0);
2762 return error;
2763 }
2764 /* Loop detection */
2765 for (mtag = m_tag_first(m); mtag != NULL((void *)0); mtag = m_tag_next(m, mtag)) {
2766 if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE0x0002)
2767 continue;
2768 tdbi = (struct tdb_ident *)(mtag + 1);
2769 if (tdbi->spi == tdb->tdb_spi &&
2770 tdbi->proto == tdb->tdb_sproto &&
2771 tdbi->rdomain == tdb->tdb_rdomain &&
2772 !memcmp(&tdbi->dst, &tdb->tdb_dst,__builtin_memcmp((&tdbi->dst), (&tdb->tdb_dst),
(sizeof(union sockaddr_union)))
2773 sizeof(union sockaddr_union))__builtin_memcmp((&tdbi->dst), (&tdb->tdb_dst),
(sizeof(union sockaddr_union)))
) {
2774 /* no IPsec needed */
2775 tdb_unref(tdb);
2776 *tdbout = NULL((void *)0);
2777 return 0;
2778 }
2779 }
2780 *tdbout = tdb;
2781 return 0;
2782}
2783
2784int
2785ip6_output_ipsec_pmtu_update(struct tdb *tdb, struct route_in6 *ro,
2786 struct in6_addr *dst, int ifidx, int rtableid, int transportmode)
2787{
2788 struct rtentry *rt = NULL((void *)0);
2789 int rt_mtucloned = 0;
2790
2791 /* Find a host route to store the mtu in */
2792 if (ro != NULL((void *)0))
2793 rt = ro->ro_rt;
2794 /* but don't add a PMTU route for transport mode SAs */
2795 if (transportmode)
2796 rt = NULL((void *)0);
2797 else if (rt == NULL((void *)0) || (rt->rt_flags & RTF_HOST0x4) == 0) {
2798 struct sockaddr_in6 sin6;
2799 int error;
2800
2801 memset(&sin6, 0, sizeof(sin6))__builtin_memset((&sin6), (0), (sizeof(sin6)));
2802 sin6.sin6_family = AF_INET624;
2803 sin6.sin6_len = sizeof(sin6);
2804 sin6.sin6_addr = *dst;
2805 sin6.sin6_scope_id = in6_addr2scopeid(ifidx, dst);
2806 error = in6_embedscope(dst, &sin6, NULL((void *)0), NULL((void *)0));
2807 if (error) {
2808 /* should be impossible */
2809 return error;
2810 }
2811 rt = icmp6_mtudisc_clone(&sin6, rtableid, 1);
2812 rt_mtucloned = 1;
2813 }
2814 DPRINTF("spi %08x mtu %d rt %p cloned %d",do { } while (0)
2815 ntohl(tdb->tdb_spi), tdb->tdb_mtu, rt, rt_mtucloned)do { } while (0);
2816 if (rt != NULL((void *)0)) {
2817 rt->rt_mturt_rmx.rmx_mtu = tdb->tdb_mtu;
2818 if (ro != NULL((void *)0) && ro->ro_rt != NULL((void *)0)) {
2819 rtfree(ro->ro_rt);
2820 ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst), RT_RESOLVE1,
2821 rtableid);
2822 }
2823 if (rt_mtucloned)
2824 rtfree(rt);
2825 }
2826 return 0;
2827}
2828
2829int
2830ip6_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct route_in6 *ro,
2831 int tunalready, int fwd)
2832{
2833 struct mbuf_list ml;
2834 struct ifnet *encif = NULL((void *)0);
2835 struct ip6_hdr *ip6;
2836 struct in6_addr dst;
2837 u_int len;
2838 int error, ifidx, rtableid, tso = 0;
2839
2840#if NPF1 > 0
2841 /*
2842 * Packet filter
2843 */
2844 if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL((void *)0) ||
2845 pf_test(AF_INET624, fwd ? PF_FWD : PF_OUT, encif, &m) != PF_PASS) {
2846 m_freem(m);
2847 return EACCES13;
2848 }
2849 if (m == NULL((void *)0))
2850 return 0;
2851 /*
2852 * PF_TAG_REROUTE handling or not...
2853 * Packet is entering IPsec so the routing is
2854 * already overruled by the IPsec policy.
2855 * Until now the change was not reconsidered.
2856 * What's the behaviour?
2857 */
2858#endif
2859
2860 /* Check if we can chop the TCP packet */
2861 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
2862 if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)((m->M_dat.MH.MH_pkthdr.csum_flags) & (0x8000)) &&
2863 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_mss <= tdb->tdb_mtu) {
2864 tso = 1;
2865 len = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_mss;
2866 } else
2867 len = sizeof(struct ip6_hdr) + 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))
;
2868
2869 /* Check if we are allowed to fragment */
2870 dst = ip6->ip6_dst;
2871 ifidx = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx;
2872 rtableid = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid;
2873 if (ip_mtudisc && tdb->tdb_mtu &&
2874 len > tdb->tdb_mtu && tdb->tdb_mtutimeout > gettime()) {
2875 int transportmode;
2876
2877 transportmode = (tdb->tdb_dst.sa.sa_family == AF_INET624) &&
2878 (IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr, &dst)(__builtin_memcmp((&(&tdb->tdb_dst.sin6.sin6_addr)
->__u6_addr.__u6_addr8[0]), (&(&dst)->__u6_addr
.__u6_addr8[0]), (sizeof(struct in6_addr))) == 0)
);
2879 error = ip6_output_ipsec_pmtu_update(tdb, ro, &dst, ifidx,
2880 rtableid, transportmode);
2881 if (error) {
2882 ipsecstat_inc(ipsec_odrops);
2883 tdbstat_inc(tdb, tdb_odrops);
2884 m_freem(m);
2885 return error;
2886 }
2887 ipsec_adjust_mtu(m, tdb->tdb_mtu);
2888 m_freem(m);
2889 return EMSGSIZE40;
2890 }
2891 /* propagate don't fragment for v6-over-v6 */
2892 if (ip_mtudisc)
2893 SET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)((m->M_dat.MH.MH_pkthdr.csum_flags) |= (0x1000));
2894
2895 /*
2896 * Clear these -- they'll be set in the recursive invocation
2897 * as needed.
2898 */
2899 m->m_flagsm_hdr.mh_flags &= ~(M_BCAST0x0100 | M_MCAST0x0200);
2900
2901 if (tso) {
2902 error = tcp_chopper(m, &ml, encif, len);
2903 if (error)
2904 goto done;
2905 } else {
2906 CLR(m->m_pkthdr.csum_flags, M_TCP_TSO)((m->M_dat.MH.MH_pkthdr.csum_flags) &= ~(0x8000));
2907 in6_proto_cksum_out(m, encif);
2908 ml_init(&ml);
2909 ml_enqueue(&ml, m);
2910 }
2911
2912 KERNEL_LOCK()_kernel_lock();
2913 while ((m = ml_dequeue(&ml)) != NULL((void *)0)) {
2914 /* Callee frees mbuf */
2915 error = ipsp_process_packet(m, tdb, AF_INET624, tunalready);
2916 if (error)
2917 break;
2918 }
2919 KERNEL_UNLOCK()_kernel_unlock();
2920 done:
2921 if (error) {
2922 ml_purge(&ml);
2923 ipsecstat_inc(ipsec_odrops);
2924 tdbstat_inc(tdb, tdb_odrops);
2925 }
2926 if (!error && tso)
2927 tcpstat_inc(tcps_outswtso);
2928 if (ip_mtudisc && error == EMSGSIZE40)
2929 ip6_output_ipsec_pmtu_update(tdb, ro, &dst, ifidx, rtableid, 0);
2930 return error;
2931}
2932#endif /* IPSEC */