Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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