Bug Summary

File:net/if_vxlan.c
Warning:line 677, column 4
Value stored to 'sc_cand' is never read

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 if_vxlan.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/net/if_vxlan.c
1/* $OpenBSD: if_vxlan.c,v 1.83 2022/01/10 14:07:59 jan Exp $ */
2
3/*
4 * Copyright (c) 2013 Reyk Floeter <reyk@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include "bpfilter.h"
20#include "vxlan.h"
21#include "vlan.h"
22#include "pf.h"
23#include "bridge.h"
24
25#include <sys/param.h>
26#include <sys/systm.h>
27#include <sys/mbuf.h>
28#include <sys/socket.h>
29#include <sys/sockio.h>
30#include <sys/ioctl.h>
31
32#include <net/if.h>
33#include <net/if_var.h>
34#include <net/if_media.h>
35#include <net/route.h>
36
37#if NBPFILTER1 > 0
38#include <net/bpf.h>
39#endif
40
41#include <netinet/in.h>
42#include <netinet/in_var.h>
43#include <netinet/if_ether.h>
44#include <netinet/ip.h>
45#include <netinet/ip_var.h>
46#include <netinet/udp.h>
47#include <netinet/udp_var.h>
48#include <netinet/in_pcb.h>
49
50#if NPF1 > 0
51#include <net/pfvar.h>
52#endif
53
54#if NBRIDGE1 > 0
55#include <net/if_bridge.h>
56#endif
57
58#include <net/if_vxlan.h>
59
60struct vxlan_softc {
61 struct arpcom sc_ac;
62 struct ifmedia sc_media;
63
64 struct ip_moptions sc_imo;
65 struct task sc_atask;
66 struct task sc_ltask;
67 struct task sc_dtask;
68
69 struct sockaddr_storage sc_src;
70 struct sockaddr_storage sc_dst;
71 in_port_t sc_dstport;
72 u_int sc_rdomain;
73 int64_t sc_vnetid;
74 uint16_t sc_df;
75 u_int8_t sc_ttl;
76 int sc_txhprio;
77
78 struct task sc_sendtask;
79
80 LIST_ENTRY(vxlan_softc)struct { struct vxlan_softc *le_next; struct vxlan_softc **le_prev
; }
sc_entry;
81};
82
83void vxlanattach(int);
84int vxlanioctl(struct ifnet *, u_long, caddr_t);
85void vxlanstart(struct ifnet *);
86int vxlan_clone_create(struct if_clone *, int);
87int vxlan_clone_destroy(struct ifnet *);
88void vxlan_multicast_cleanup(struct ifnet *);
89int vxlan_multicast_join(struct ifnet *, struct sockaddr *,
90 struct sockaddr *);
91int vxlan_media_change(struct ifnet *);
92void vxlan_media_status(struct ifnet *, struct ifmediareq *);
93int vxlan_config(struct ifnet *, struct sockaddr *, struct sockaddr *);
94int vxlan_output(struct ifnet *, struct mbuf *);
95void vxlan_addr_change(void *);
96void vxlan_if_change(void *);
97void vxlan_link_change(void *);
98void vxlan_send_dispatch(void *);
99
100int vxlan_sockaddr_cmp(struct sockaddr *, struct sockaddr *);
101uint16_t vxlan_sockaddr_port(struct sockaddr *);
102
103struct if_clone vxlan_cloner =
104 IF_CLONE_INITIALIZER("vxlan", vxlan_clone_create, vxlan_clone_destroy){ .ifc_list = { ((void *)0), ((void *)0) }, .ifc_name = "vxlan"
, .ifc_namelen = sizeof("vxlan") - 1, .ifc_create = vxlan_clone_create
, .ifc_destroy = vxlan_clone_destroy, }
;
105
106int vxlan_enable = 0;
107u_long vxlan_tagmask;
108
109#define VXLAN_TAGHASHSIZE32 32
110#define VXLAN_TAGHASH(tag)((unsigned int)tag & vxlan_tagmask) ((unsigned int)tag & vxlan_tagmask)
111LIST_HEAD(vxlan_taghash, vxlan_softc)struct vxlan_taghash { struct vxlan_softc *lh_first; } *vxlan_tagh, vxlan_any;
112
113void
114vxlanattach(int count)
115{
116 /* Regular vxlan interfaces with a VNI */
117 if ((vxlan_tagh = hashinit(VXLAN_TAGHASHSIZE32, M_DEVBUF2, M_NOWAIT0x0002,
118 &vxlan_tagmask)) == NULL((void *)0))
119 panic("vxlanattach: hashinit");
120
121 /* multipoint-to-multipoint interfaces that accept any VNI */
122 LIST_INIT(&vxlan_any)do { ((&vxlan_any)->lh_first) = ((void *)0); } while (
0)
;
123
124 if_clone_attach(&vxlan_cloner);
125}
126
127int
128vxlan_clone_create(struct if_clone *ifc, int unit)
129{
130 struct ifnet *ifp;
131 struct vxlan_softc *sc;
132
133 sc = malloc(sizeof(*sc), M_DEVBUF2, M_WAITOK0x0001|M_ZERO0x0008);
134 sc->sc_imo.imo_membership = mallocarray(IP_MIN_MEMBERSHIPS15,
135 sizeof(struct in_multi *), M_IPMOPTS53, M_WAITOK0x0001|M_ZERO0x0008);
136 sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS15;
137 sc->sc_dstport = htons(VXLAN_PORT)(__uint16_t)(__builtin_constant_p(4789) ? (__uint16_t)(((__uint16_t
)(4789) & 0xffU) << 8 | ((__uint16_t)(4789) & 0xff00U
) >> 8) : __swap16md(4789))
;
138 sc->sc_vnetid = VXLAN_VNI_UNSET0x01ffffff;
139 sc->sc_txhprio = IFQ_TOS2PRIO(IPTOS_PREC_ROUTINE)((0x00) >> 5); /* 0 */
140 sc->sc_df = htons(0)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t
)(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U
) >> 8) : __swap16md(0))
;
141 task_set(&sc->sc_atask, vxlan_addr_change, sc);
142 task_set(&sc->sc_ltask, vxlan_link_change, sc);
143 task_set(&sc->sc_dtask, vxlan_if_change, sc);
144 task_set(&sc->sc_sendtask, vxlan_send_dispatch, sc);
145
146 ifp = &sc->sc_ac.ac_if;
147 snprintf(ifp->if_xname, sizeof ifp->if_xname, "vxlan%d", unit);
148 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
149 ether_fakeaddr(ifp);
150
151 ifp->if_softc = sc;
152 ifp->if_ioctl = vxlanioctl;
153 ifp->if_start = vxlanstart;
154
155 ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN65435;
156 ifp->if_capabilitiesif_data.ifi_capabilities = IFCAP_VLAN_MTU0x00000010;
157 ifp->if_xflags = IFXF_CLONED0x2;
158
159 ifmedia_init(&sc->sc_media, 0, vxlan_media_change,
160 vxlan_media_status);
161 ifmedia_add(&sc->sc_media, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL, 0, NULL((void *)0));
162 ifmedia_set(&sc->sc_media, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL);
163
164 if_counters_alloc(ifp);
165 if_attach(ifp);
166 ether_ifattach(ifp);
167
168#if 0
169 /*
170 * Instead of using a decreased MTU of 1450 bytes, prefer
171 * to use the default Ethernet-size MTU of 1500 bytes and to
172 * increase the MTU of the outer transport interfaces to
173 * at least 1550 bytes. The following is disabled by default.
174 */
175 ifp->if_mtuif_data.ifi_mtu = ETHERMTU(1518 - ((6 * 2) + 2) - 4) - sizeof(struct ether_header);
176 ifp->if_mtuif_data.ifi_mtu -= sizeof(struct vxlanudphdr) + sizeof(struct ipovly);
177#endif
178
179 LIST_INSERT_HEAD(&vxlan_tagh[VXLAN_TAGHASH(0)], sc, sc_entry)do { if (((sc)->sc_entry.le_next = (&vxlan_tagh[((unsigned
int)0 & vxlan_tagmask)])->lh_first) != ((void *)0)) (
&vxlan_tagh[((unsigned int)0 & vxlan_tagmask)])->lh_first
->sc_entry.le_prev = &(sc)->sc_entry.le_next; (&
vxlan_tagh[((unsigned int)0 & vxlan_tagmask)])->lh_first
= (sc); (sc)->sc_entry.le_prev = &(&vxlan_tagh[((
unsigned int)0 & vxlan_tagmask)])->lh_first; } while (
0)
;
180 vxlan_enable++;
181
182 return (0);
183}
184
185int
186vxlan_clone_destroy(struct ifnet *ifp)
187{
188 struct vxlan_softc *sc = ifp->if_softc;
189
190 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
191 vxlan_multicast_cleanup(ifp);
192 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
193
194 vxlan_enable--;
195 LIST_REMOVE(sc, sc_entry)do { if ((sc)->sc_entry.le_next != ((void *)0)) (sc)->sc_entry
.le_next->sc_entry.le_prev = (sc)->sc_entry.le_prev; *(
sc)->sc_entry.le_prev = (sc)->sc_entry.le_next; ((sc)->
sc_entry.le_prev) = ((void *)-1); ((sc)->sc_entry.le_next)
= ((void *)-1); } while (0)
;
196
197 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY((uint64_t) -1));
198 ether_ifdetach(ifp);
199 if_detach(ifp);
200
201 if (!task_del(net_tq(ifp->if_index), &sc->sc_sendtask))
202 taskq_barrier(net_tq(ifp->if_index));
203
204 free(sc->sc_imo.imo_membership, M_IPMOPTS53,
205 sc->sc_imo.imo_max_memberships * sizeof(struct in_multi *));
206 free(sc, M_DEVBUF2, sizeof(*sc));
207
208 return (0);
209}
210
211void
212vxlan_multicast_cleanup(struct ifnet *ifp)
213{
214 struct vxlan_softc *sc = (struct vxlan_softc *)ifp->if_softc;
215 struct ip_moptions *imo = &sc->sc_imo;
216 struct ifnet *mifp;
217
218 mifp = if_get(imo->imo_ifidx);
219 if (mifp != NULL((void *)0)) {
220 if_addrhook_del(mifp, &sc->sc_atask);
221 if_linkstatehook_del(mifp, &sc->sc_ltask);
222 if_detachhook_del(mifp, &sc->sc_dtask);
223
224 if_put(mifp);
225 }
226
227 if (imo->imo_num_memberships > 0) {
228 in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
229 imo->imo_ifidx = 0;
230 }
231}
232
233int
234vxlan_multicast_join(struct ifnet *ifp, struct sockaddr *src,
235 struct sockaddr *dst)
236{
237 struct vxlan_softc *sc = ifp->if_softc;
238 struct ip_moptions *imo = &sc->sc_imo;
239 struct sockaddr_in *src4, *dst4;
240#ifdef INET61
241 struct sockaddr_in6 *dst6;
242#endif /* INET6 */
243 struct ifaddr *ifa;
244 struct ifnet *mifp;
245
246 switch (dst->sa_family) {
247 case AF_INET2:
248 dst4 = satosin(dst);
249 if (!IN_MULTICAST(dst4->sin_addr.s_addr)(((u_int32_t)(dst4->sin_addr.s_addr) & ((u_int32_t) (__uint32_t
)(__builtin_constant_p((u_int32_t)(0xf0000000)) ? (__uint32_t
)(((__uint32_t)((u_int32_t)(0xf0000000)) & 0xff) <<
24 | ((__uint32_t)((u_int32_t)(0xf0000000)) & 0xff00) <<
8 | ((__uint32_t)((u_int32_t)(0xf0000000)) & 0xff0000) >>
8 | ((__uint32_t)((u_int32_t)(0xf0000000)) & 0xff000000)
>> 24) : __swap32md((u_int32_t)(0xf0000000))))) == ((u_int32_t
) (__uint32_t)(__builtin_constant_p((u_int32_t)(0xe0000000)) ?
(__uint32_t)(((__uint32_t)((u_int32_t)(0xe0000000)) & 0xff
) << 24 | ((__uint32_t)((u_int32_t)(0xe0000000)) & 0xff00
) << 8 | ((__uint32_t)((u_int32_t)(0xe0000000)) & 0xff0000
) >> 8 | ((__uint32_t)((u_int32_t)(0xe0000000)) & 0xff000000
) >> 24) : __swap32md((u_int32_t)(0xe0000000)))))
)
250 return (0);
251 break;
252#ifdef INET61
253 case AF_INET624:
254 dst6 = satosin6(dst);
255 if (!IN6_IS_ADDR_MULTICAST(&dst6->sin6_addr)((&dst6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xff
)
)
256 return (0);
257
258 /* Multicast mode is currently not supported for IPv6 */
259 return (EAFNOSUPPORT47);
260#endif /* INET6 */
261 default:
262 return (EAFNOSUPPORT47);
263 }
264
265 src4 = satosin(src);
266 dst4 = satosin(dst);
267
268 if (src4->sin_addr.s_addr == INADDR_ANY((u_int32_t) (__uint32_t)(__builtin_constant_p((u_int32_t)(0x00000000
)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000000)) &
0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000000)) &
0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000000)) &
0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000000)
) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000000
))))
||
269 IN_MULTICAST(src4->sin_addr.s_addr)(((u_int32_t)(src4->sin_addr.s_addr) & ((u_int32_t) (__uint32_t
)(__builtin_constant_p((u_int32_t)(0xf0000000)) ? (__uint32_t
)(((__uint32_t)((u_int32_t)(0xf0000000)) & 0xff) <<
24 | ((__uint32_t)((u_int32_t)(0xf0000000)) & 0xff00) <<
8 | ((__uint32_t)((u_int32_t)(0xf0000000)) & 0xff0000) >>
8 | ((__uint32_t)((u_int32_t)(0xf0000000)) & 0xff000000)
>> 24) : __swap32md((u_int32_t)(0xf0000000))))) == ((u_int32_t
) (__uint32_t)(__builtin_constant_p((u_int32_t)(0xe0000000)) ?
(__uint32_t)(((__uint32_t)((u_int32_t)(0xe0000000)) & 0xff
) << 24 | ((__uint32_t)((u_int32_t)(0xe0000000)) & 0xff00
) << 8 | ((__uint32_t)((u_int32_t)(0xe0000000)) & 0xff0000
) >> 8 | ((__uint32_t)((u_int32_t)(0xe0000000)) & 0xff000000
) >> 24) : __swap32md((u_int32_t)(0xe0000000)))))
)
270 return (EINVAL22);
271 if ((ifa = ifa_ifwithaddr(src, sc->sc_rdomain)) == NULL((void *)0) ||
272 (mifp = ifa->ifa_ifp) == NULL((void *)0) ||
273 (mifp->if_flags & IFF_MULTICAST0x8000) == 0)
274 return (EADDRNOTAVAIL49);
275
276 if ((imo->imo_membership[0] =
277 in_addmulti(&dst4->sin_addr, mifp)) == NULL((void *)0))
278 return (ENOBUFS55);
279
280 imo->imo_num_memberships++;
281 imo->imo_ifidx = mifp->if_index;
282 if (sc->sc_ttl > 0)
283 imo->imo_ttl = sc->sc_ttl;
284 else
285 imo->imo_ttl = IP_DEFAULT_MULTICAST_TTL1;
286 imo->imo_loop = 0;
287
288 /*
289 * Use interface hooks to track any changes on the interface
290 * that is used to send out the tunnel traffic as multicast.
291 */
292 if_addrhook_add(mifp, &sc->sc_atask);
293 if_linkstatehook_add(mifp, &sc->sc_ltask);
294 if_detachhook_add(mifp, &sc->sc_dtask);
295
296 return (0);
297}
298
299void
300vxlanstart(struct ifnet *ifp)
301{
302 struct vxlan_softc *sc = (struct vxlan_softc *)ifp->if_softc;
303
304 task_add(net_tq(ifp->if_index), &sc->sc_sendtask);
305}
306
307void
308vxlan_send_dispatch(void *xsc)
309{
310 struct vxlan_softc *sc = xsc;
311 struct ifnet *ifp = &sc->sc_ac.ac_if;
312 struct mbuf *m;
313 struct mbuf_list ml;
314
315 ml_init(&ml);
316 for (;;) {
317 m = ifq_dequeue(&ifp->if_snd);
318 if (m == NULL((void *)0))
319 break;
320
321#if NBPFILTER1 > 0
322 if (ifp->if_bpf)
323 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
324#endif
325
326 ml_enqueue(&ml, m);
327 }
328
329 if (ml_empty(&ml)((&ml)->ml_len == 0))
330 return;
331
332 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
333 while ((m = ml_dequeue(&ml)) != NULL((void *)0)) {
334 vxlan_output(ifp, m);
335 }
336 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
337}
338
339
340int
341vxlan_config(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
342{
343 struct vxlan_softc *sc = (struct vxlan_softc *)ifp->if_softc;
344 int reset = 0, error, af;
345 socklen_t slen;
346 in_port_t port;
347 struct vxlan_taghash *tagh;
348
349 if (src != NULL((void *)0) && dst != NULL((void *)0)) {
350 if ((af = src->sa_family) != dst->sa_family)
351 return (EAFNOSUPPORT47);
352 } else {
353 /* Reset current configuration */
354 af = sc->sc_src.ss_family;
355 src = sstosa(&sc->sc_src);
356 dst = sstosa(&sc->sc_dst);
357 reset = 1;
358 }
359
360 switch (af) {
361 case AF_INET2:
362 slen = sizeof(struct sockaddr_in);
363 break;
364#ifdef INET61
365 case AF_INET624:
366 slen = sizeof(struct sockaddr_in6);
367 break;
368#endif /* INET6 */
369 default:
370 return (EAFNOSUPPORT47);
371 }
372
373 if (src->sa_len != slen || dst->sa_len != slen)
374 return (EINVAL22);
375
376 vxlan_multicast_cleanup(ifp);
377
378 /* returns without error if multicast is not configured */
379 if ((error = vxlan_multicast_join(ifp, src, dst)) != 0)
380 return (error);
381
382 if ((port = vxlan_sockaddr_port(dst)) != 0)
383 sc->sc_dstport = port;
384
385 if (!reset) {
386 bzero(&sc->sc_src, sizeof(sc->sc_src))__builtin_bzero((&sc->sc_src), (sizeof(sc->sc_src))
)
;
387 bzero(&sc->sc_dst, sizeof(sc->sc_dst))__builtin_bzero((&sc->sc_dst), (sizeof(sc->sc_dst))
)
;
388 memcpy(&sc->sc_src, src, src->sa_len)__builtin_memcpy((&sc->sc_src), (src), (src->sa_len
))
;
389 memcpy(&sc->sc_dst, dst, dst->sa_len)__builtin_memcpy((&sc->sc_dst), (dst), (dst->sa_len
))
;
390 }
391
392 if (sc->sc_vnetid == VXLAN_VNI_ANY-1ULL) {
393 /*
394 * If the interface accepts any VNI, put it into a separate
395 * list that is not part of the main hash.
396 */
397 tagh = &vxlan_any;
398 } else
399 tagh = &vxlan_tagh[VXLAN_TAGHASH(sc->sc_vnetid)((unsigned int)sc->sc_vnetid & vxlan_tagmask)];
400
401 LIST_REMOVE(sc, sc_entry)do { if ((sc)->sc_entry.le_next != ((void *)0)) (sc)->sc_entry
.le_next->sc_entry.le_prev = (sc)->sc_entry.le_prev; *(
sc)->sc_entry.le_prev = (sc)->sc_entry.le_next; ((sc)->
sc_entry.le_prev) = ((void *)-1); ((sc)->sc_entry.le_next)
= ((void *)-1); } while (0)
;
402 LIST_INSERT_HEAD(tagh, sc, sc_entry)do { if (((sc)->sc_entry.le_next = (tagh)->lh_first) !=
((void *)0)) (tagh)->lh_first->sc_entry.le_prev = &
(sc)->sc_entry.le_next; (tagh)->lh_first = (sc); (sc)->
sc_entry.le_prev = &(tagh)->lh_first; } while (0)
;
403
404 return (0);
405}
406
407int
408vxlanioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
409{
410 struct vxlan_softc *sc = (struct vxlan_softc *)ifp->if_softc;
411 struct ifreq *ifr = (struct ifreq *)data;
412 struct if_laddrreq *lifr = (struct if_laddrreq *)data;
413 int error = 0;
414
415 switch (cmd) {
416 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
417 ifp->if_flags |= IFF_UP0x1;
418 /* FALLTHROUGH */
419
420 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
421 if (ifp->if_flags & IFF_UP0x1) {
422 ifp->if_flags |= IFF_RUNNING0x40;
423 } else {
424 ifp->if_flags &= ~IFF_RUNNING0x40;
425 }
426 break;
427
428 case SIOCADDMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((49)))
:
429 case SIOCDELMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((50)))
:
430 break;
431
432 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
433 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
434 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
435 break;
436
437 case SIOCSLIFPHYADDR((unsigned long)0x80000000 | ((sizeof(struct if_laddrreq) &
0x1fff) << 16) | ((('i')) << 8) | ((74)))
:
438 error = vxlan_config(ifp,
439 sstosa(&lifr->addr),
440 sstosa(&lifr->dstaddr));
441 break;
442
443 case SIOCDIFPHYADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((73)))
:
444 vxlan_multicast_cleanup(ifp);
445 bzero(&sc->sc_src, sizeof(sc->sc_src))__builtin_bzero((&sc->sc_src), (sizeof(sc->sc_src))
)
;
446 bzero(&sc->sc_dst, sizeof(sc->sc_dst))__builtin_bzero((&sc->sc_dst), (sizeof(sc->sc_dst))
)
;
447 sc->sc_dstport = htons(VXLAN_PORT)(__uint16_t)(__builtin_constant_p(4789) ? (__uint16_t)(((__uint16_t
)(4789) & 0xffU) << 8 | ((__uint16_t)(4789) & 0xff00U
) >> 8) : __swap16md(4789))
;
448 break;
449
450 case SIOCGLIFPHYADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct if_laddrreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((75)))
:
451 if (sc->sc_dst.ss_family == AF_UNSPEC0) {
452 error = EADDRNOTAVAIL49;
453 break;
454 }
455 bzero(&lifr->addr, sizeof(lifr->addr))__builtin_bzero((&lifr->addr), (sizeof(lifr->addr))
)
;
456 bzero(&lifr->dstaddr, sizeof(lifr->dstaddr))__builtin_bzero((&lifr->dstaddr), (sizeof(lifr->dstaddr
)))
;
457 memcpy(&lifr->addr, &sc->sc_src, sc->sc_src.ss_len)__builtin_memcpy((&lifr->addr), (&sc->sc_src), (
sc->sc_src.ss_len))
;
458 memcpy(&lifr->dstaddr, &sc->sc_dst, sc->sc_dst.ss_len)__builtin_memcpy((&lifr->dstaddr), (&sc->sc_dst
), (sc->sc_dst.ss_len))
;
459 break;
460
461 case SIOCSLIFPHYRTABLE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((161)))
:
462 if (ifr->ifr_rdomainidifr_ifru.ifru_metric < 0 ||
463 ifr->ifr_rdomainidifr_ifru.ifru_metric > RT_TABLEID_MAX255 ||
464 !rtable_exists(ifr->ifr_rdomainidifr_ifru.ifru_metric)) {
465 error = EINVAL22;
466 break;
467 }
468 sc->sc_rdomain = ifr->ifr_rdomainidifr_ifru.ifru_metric;
469 (void)vxlan_config(ifp, NULL((void *)0), NULL((void *)0));
470 break;
471
472 case SIOCGLIFPHYRTABLE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((162)))
:
473 ifr->ifr_rdomainidifr_ifru.ifru_metric = sc->sc_rdomain;
474 break;
475
476 case SIOCSLIFPHYTTL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((168)))
:
477 if (ifr->ifr_ttlifr_ifru.ifru_metric < 0 || ifr->ifr_ttlifr_ifru.ifru_metric > 0xff) {
478 error = EINVAL22;
479 break;
480 }
481 if (sc->sc_ttl == (u_int8_t)ifr->ifr_ttlifr_ifru.ifru_metric)
482 break;
483 sc->sc_ttl = (u_int8_t)(ifr->ifr_ttlifr_ifru.ifru_metric);
484 (void)vxlan_config(ifp, NULL((void *)0), NULL((void *)0));
485 break;
486
487 case SIOCGLIFPHYTTL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((169)))
:
488 ifr->ifr_ttlifr_ifru.ifru_metric = (int)sc->sc_ttl;
489 break;
490
491 case SIOCSLIFPHYDF((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((193)))
:
492 /* commit */
493 sc->sc_df = ifr->ifr_dfifr_ifru.ifru_metric ? htons(IP_DF)(__uint16_t)(__builtin_constant_p(0x4000) ? (__uint16_t)(((__uint16_t
)(0x4000) & 0xffU) << 8 | ((__uint16_t)(0x4000) &
0xff00U) >> 8) : __swap16md(0x4000))
: htons(0)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t
)(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U
) >> 8) : __swap16md(0))
;
494 break;
495 case SIOCGLIFPHYDF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((194)))
:
496 ifr->ifr_dfifr_ifru.ifru_metric = sc->sc_df ? 1 : 0;
497 break;
498
499 case SIOCSTXHPRIO((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((197)))
:
500 if (ifr->ifr_hdrprioifr_ifru.ifru_metric == IF_HDRPRIO_PACKET-1)
501 ; /* fall through */
502 else if (ifr->ifr_hdrprioifr_ifru.ifru_metric < IF_HDRPRIO_MIN0 ||
503 ifr->ifr_hdrprioifr_ifru.ifru_metric > IF_HDRPRIO_MAX8 - 1) {
504 error = EINVAL22;
505 break;
506 }
507
508 sc->sc_txhprio = ifr->ifr_hdrprioifr_ifru.ifru_metric;
509 break;
510 case SIOCGTXHPRIO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((198)))
:
511 ifr->ifr_hdrprioifr_ifru.ifru_metric = sc->sc_txhprio;
512 break;
513
514 case SIOCSVNETID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((166)))
:
515 if (sc->sc_vnetid == ifr->ifr_vnetidifr_ifru.ifru_vnetid)
516 break;
517
518 if ((ifr->ifr_vnetidifr_ifru.ifru_vnetid != VXLAN_VNI_ANY-1ULL) &&
519 (ifr->ifr_vnetidifr_ifru.ifru_vnetid > VXLAN_VNI_MAX0x00ffffff ||
520 ifr->ifr_vnetidifr_ifru.ifru_vnetid < VXLAN_VNI_MIN0x00000000)) {
521 error = EINVAL22;
522 break;
523 }
524
525 sc->sc_vnetid = (int)ifr->ifr_vnetidifr_ifru.ifru_vnetid;
526 (void)vxlan_config(ifp, NULL((void *)0), NULL((void *)0));
527 break;
528
529 case SIOCGVNETID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((167)))
:
530 if ((sc->sc_vnetid != VXLAN_VNI_ANY-1ULL) &&
531 (sc->sc_vnetid > VXLAN_VNI_MAX0x00ffffff ||
532 sc->sc_vnetid < VXLAN_VNI_MIN0x00000000)) {
533 error = EADDRNOTAVAIL49;
534 break;
535 }
536
537 ifr->ifr_vnetidifr_ifru.ifru_vnetid = sc->sc_vnetid;
538 break;
539
540 case SIOCDVNETID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((175)))
:
541 sc->sc_vnetid = VXLAN_VNI_UNSET0x01ffffff;
542 (void)vxlan_config(ifp, NULL((void *)0), NULL((void *)0));
543 break;
544
545 default:
546 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
547 break;
548 }
549
550 return (error);
551}
552
553int
554vxlan_media_change(struct ifnet *ifp)
555{
556 return (0);
557}
558
559void
560vxlan_media_status(struct ifnet *ifp, struct ifmediareq *imr)
561{
562 imr->ifm_status = IFM_AVALID0x0000000000000001ULL | IFM_ACTIVE0x0000000000000002ULL;
563}
564
565int
566vxlan_sockaddr_cmp(struct sockaddr *srcsa, struct sockaddr *dstsa)
567{
568 struct sockaddr_in *src4, *dst4;
569#ifdef INET61
570 struct sockaddr_in6 *src6, *dst6;
571#endif /* INET6 */
572
573 if (srcsa->sa_family != dstsa->sa_family)
574 return (1);
575
576 switch (dstsa->sa_family) {
577 case AF_INET2:
578 src4 = satosin(srcsa);
579 dst4 = satosin(dstsa);
580 if (src4->sin_addr.s_addr == dst4->sin_addr.s_addr)
581 return (0);
582 break;
583#ifdef INET61
584 case AF_INET624:
585 src6 = satosin6(srcsa);
586 dst6 = satosin6(dstsa);
587 if (IN6_ARE_ADDR_EQUAL(&src6->sin6_addr, &dst6->sin6_addr)(__builtin_memcmp((&(&src6->sin6_addr)->__u6_addr
.__u6_addr8[0]), (&(&dst6->sin6_addr)->__u6_addr
.__u6_addr8[0]), (sizeof(struct in6_addr))) == 0)
&&
588 src6->sin6_scope_id == dst6->sin6_scope_id)
589 return (0);
590 break;
591#endif /* INET6 */
592 }
593
594 return (1);
595}
596
597uint16_t
598vxlan_sockaddr_port(struct sockaddr *sa)
599{
600 struct sockaddr_in *sin4;
601#ifdef INET61
602 struct sockaddr_in6 *sin6;
603#endif /* INET6 */
604
605 switch (sa->sa_family) {
606 case AF_INET2:
607 sin4 = satosin(sa);
608 return (sin4->sin_port);
609#ifdef INET61
610 case AF_INET624:
611 sin6 = satosin6(sa);
612 return (sin6->sin6_port);
613#endif /* INET6 */
614 default:
615 break;
616 }
617
618 return (0);
619}
620
621int
622vxlan_lookup(struct mbuf *m, struct udphdr *uh, int iphlen,
623 struct sockaddr *srcsa, struct sockaddr *dstsa)
624{
625 struct vxlan_softc *sc = NULL((void *)0), *sc_cand = NULL((void *)0);
626 struct vxlan_header v;
627 int vni;
628 struct ifnet *ifp;
629 int skip;
630#if NBRIDGE1 > 0
631 struct bridge_tunneltag *brtag;
632#endif
633 struct mbuf *n;
634 int off;
635
636 /* XXX Should verify the UDP port first before copying the packet */
637 skip = iphlen + sizeof(*uh);
638 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len - skip < sizeof(v))
639 return (0);
640 m_copydata(m, skip, sizeof(v), &v);
641 skip += sizeof(v);
642
643 if (v.vxlan_flags & htonl(VXLAN_RESERVED1)(__uint32_t)(__builtin_constant_p(0xf7ffffff) ? (__uint32_t)(
((__uint32_t)(0xf7ffffff) & 0xff) << 24 | ((__uint32_t
)(0xf7ffffff) & 0xff00) << 8 | ((__uint32_t)(0xf7ffffff
) & 0xff0000) >> 8 | ((__uint32_t)(0xf7ffffff) &
0xff000000) >> 24) : __swap32md(0xf7ffffff))
||
644 v.vxlan_id & htonl(VXLAN_RESERVED2)(__uint32_t)(__builtin_constant_p(0x000000ff) ? (__uint32_t)(
((__uint32_t)(0x000000ff) & 0xff) << 24 | ((__uint32_t
)(0x000000ff) & 0xff00) << 8 | ((__uint32_t)(0x000000ff
) & 0xff0000) >> 8 | ((__uint32_t)(0x000000ff) &
0xff000000) >> 24) : __swap32md(0x000000ff))
)
645 return (0);
646
647 vni = ntohl(v.vxlan_id)(__uint32_t)(__builtin_constant_p(v.vxlan_id) ? (__uint32_t)(
((__uint32_t)(v.vxlan_id) & 0xff) << 24 | ((__uint32_t
)(v.vxlan_id) & 0xff00) << 8 | ((__uint32_t)(v.vxlan_id
) & 0xff0000) >> 8 | ((__uint32_t)(v.vxlan_id) &
0xff000000) >> 24) : __swap32md(v.vxlan_id))
>> VXLAN_VNI_S8;
648 if ((v.vxlan_flags & htonl(VXLAN_FLAGS_VNI)(__uint32_t)(__builtin_constant_p(0x08000000) ? (__uint32_t)(
((__uint32_t)(0x08000000) & 0xff) << 24 | ((__uint32_t
)(0x08000000) & 0xff00) << 8 | ((__uint32_t)(0x08000000
) & 0xff0000) >> 8 | ((__uint32_t)(0x08000000) &
0xff000000) >> 24) : __swap32md(0x08000000))
) == 0) {
649 if (vni != 0)
650 return (0);
651
652 vni = VXLAN_VNI_UNSET0x01ffffff;
653 }
654
655 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
656 /* First search for a vxlan(4) interface with the packet's VNI */
657 LIST_FOREACH(sc, &vxlan_tagh[VXLAN_TAGHASH(vni)], sc_entry)for((sc) = ((&vxlan_tagh[((unsigned int)vni & vxlan_tagmask
)])->lh_first); (sc)!= ((void *)0); (sc) = ((sc)->sc_entry
.le_next))
{
658 if ((uh->uh_dport == sc->sc_dstport) &&
659 vni == sc->sc_vnetid &&
660 sc->sc_rdomain == rtable_l2(m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid)) {
661 sc_cand = sc;
662 if (vxlan_sockaddr_cmp(srcsa, sstosa(&sc->sc_dst)) == 0)
663 goto found;
664 }
665 }
666
667 /*
668 * Now loop through all the vxlan(4) interfaces that are configured
669 * to accept any VNI and operating in multipoint-to-multipoint mode
670 * that is used in combination with bridge(4) or switch(4).
671 * If a vxlan(4) interface has been found for the packet's VNI, this
672 * code is not reached as the other interface is more specific.
673 */
674 LIST_FOREACH(sc, &vxlan_any, sc_entry)for((sc) = ((&vxlan_any)->lh_first); (sc)!= ((void *)0
); (sc) = ((sc)->sc_entry.le_next))
{
675 if ((uh->uh_dport == sc->sc_dstport) &&
676 (sc->sc_rdomain == rtable_l2(m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid))) {
677 sc_cand = sc;
Value stored to 'sc_cand' is never read
678 goto found;
679 }
680 }
681
682 if (sc_cand) {
683 sc = sc_cand;
684 goto found;
685 }
686
687 /* not found */
688 return (0);
689
690 found:
691 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < skip + sizeof(struct ether_header)) {
692 m_freem(m);
693 return (EINVAL22);
694 }
695
696 m_adj(m, skip);
697 ifp = &sc->sc_ac.ac_if;
698
699#if NBRIDGE1 > 0
700 /* Store the tunnel src/dst IP and vni for the bridge or switch */
701 if ((ifp->if_bridgeidx != 0 || ifp->if_switchport != NULL((void *)0)) &&
702 srcsa->sa_family != AF_UNSPEC0 &&
703 ((brtag = bridge_tunneltag(m)) != NULL((void *)0))) {
704 memcpy(&brtag->brtag_peer.sa, srcsa, srcsa->sa_len)__builtin_memcpy((&brtag->brtag_peer.sa), (srcsa), (srcsa
->sa_len))
;
705 memcpy(&brtag->brtag_local.sa, dstsa, dstsa->sa_len)__builtin_memcpy((&brtag->brtag_local.sa), (dstsa), (dstsa
->sa_len))
;
706 brtag->brtag_id = vni;
707 }
708#endif
709
710 m->m_flagsm_hdr.mh_flags &= ~(M_BCAST0x0100|M_MCAST0x0200);
711
712#if NPF1 > 0
713 pf_pkt_addr_changed(m);
714#endif
715 if ((m->m_lenm_hdr.mh_len < sizeof(struct ether_header)) &&
716 (m = m_pullup(m, sizeof(struct ether_header))) == NULL((void *)0))
717 return (ENOBUFS55);
718
719 n = m_getptr(m, sizeof(struct ether_header), &off);
720 if (n == NULL((void *)0)) {
721 m_freem(m);
722 return (EINVAL22);
723 }
724 if (!ALIGNED_POINTER(mtod(n, caddr_t) + off, uint32_t)1) {
725 n = m_dup_pkt(m, ETHER_ALIGN2, M_NOWAIT0x0002);
726 /* Dispose of the original mbuf chain */
727 m_freem(m);
728 if (n == NULL((void *)0))
729 return (ENOBUFS55);
730 m = n;
731 }
732
733 if_vinput(ifp, m);
734
735 /* success */
736 return (1);
737}
738
739struct mbuf *
740vxlan_encap4(struct ifnet *ifp, struct mbuf *m,
741 struct sockaddr *src, struct sockaddr *dst)
742{
743 struct vxlan_softc *sc = (struct vxlan_softc *)ifp->if_softc;
744 struct ip *ip;
745
746 /*
747 * Remove multicast and broadcast flags or encapsulated packet
748 * ends up as multicast or broadcast packet.
749 */
750 m->m_flagsm_hdr.mh_flags &= ~(M_BCAST0x0100|M_MCAST0x0200);
751
752 M_PREPEND(m, sizeof(*ip), M_DONTWAIT)(m) = m_prepend((m), (sizeof(*ip)), (0x0002));
753 if (m == NULL((void *)0))
754 return (NULL((void *)0));
755
756 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
757 ip->ip_v = IPVERSION4;
758 ip->ip_hl = sizeof(struct ip) >> 2;
759 ip->ip_id = htons(ip_randomid())(__uint16_t)(__builtin_constant_p(ip_randomid()) ? (__uint16_t
)(((__uint16_t)(ip_randomid()) & 0xffU) << 8 | ((__uint16_t
)(ip_randomid()) & 0xff00U) >> 8) : __swap16md(ip_randomid
()))
;
760 ip->ip_off = sc->sc_df;
761 ip->ip_p = IPPROTO_UDP17;
762 ip->ip_tos = IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ?((sc->sc_txhprio == -1 ? m->M_dat.MH.MH_pkthdr.pf.prio :
sc->sc_txhprio) << 5)
763 m->m_pkthdr.pf.prio : sc->sc_txhprio)((sc->sc_txhprio == -1 ? m->M_dat.MH.MH_pkthdr.pf.prio :
sc->sc_txhprio) << 5)
;
764 ip->ip_len = htons(m->m_pkthdr.len)(__uint16_t)(__builtin_constant_p(m->M_dat.MH.MH_pkthdr.len
) ? (__uint16_t)(((__uint16_t)(m->M_dat.MH.MH_pkthdr.len) &
0xffU) << 8 | ((__uint16_t)(m->M_dat.MH.MH_pkthdr.len
) & 0xff00U) >> 8) : __swap16md(m->M_dat.MH.MH_pkthdr
.len))
;
765
766 ip->ip_src = satosin(src)->sin_addr;
767 ip->ip_dst = satosin(dst)->sin_addr;
768
769 if (sc->sc_ttl > 0)
770 ip->ip_ttl = sc->sc_ttl;
771 else
772 ip->ip_ttl = IPDEFTTL64;
773
774 return (m);
775}
776
777#ifdef INET61
778struct mbuf *
779vxlan_encap6(struct ifnet *ifp, struct mbuf *m,
780 struct sockaddr *src, struct sockaddr *dst)
781{
782 struct vxlan_softc *sc = (struct vxlan_softc *)ifp->if_softc;
783 struct ip6_hdr *ip6;
784 struct in6_addr *in6a;
785 uint32_t flow;
786
787 /*
788 * Remove multicast and broadcast flags or encapsulated packet
789 * ends up as multicast or broadcast packet.
790 */
791 m->m_flagsm_hdr.mh_flags &= ~(M_BCAST0x0100|M_MCAST0x0200);
792
793 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT)(m) = m_prepend((m), (sizeof(struct ip6_hdr)), (0x0002));
794 if (m == NULL((void *)0))
795 return (NULL((void *)0));
796
797 flow = (uint32_t)IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ?((sc->sc_txhprio == -1 ? m->M_dat.MH.MH_pkthdr.pf.prio :
sc->sc_txhprio) << 5)
798 m->m_pkthdr.pf.prio : sc->sc_txhprio)((sc->sc_txhprio == -1 ? m->M_dat.MH.MH_pkthdr.pf.prio :
sc->sc_txhprio) << 5)
<< 20;
799
800 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
801 ip6->ip6_flowip6_ctlun.ip6_un1.ip6_un1_flow = htonl(flow)(__uint32_t)(__builtin_constant_p(flow) ? (__uint32_t)(((__uint32_t
)(flow) & 0xff) << 24 | ((__uint32_t)(flow) & 0xff00
) << 8 | ((__uint32_t)(flow) & 0xff0000) >> 8
| ((__uint32_t)(flow) & 0xff000000) >> 24) : __swap32md
(flow))
;
802 ip6->ip6_vfcip6_ctlun.ip6_un2_vfc &= ~IPV6_VERSION_MASK0xf0;
803 ip6->ip6_vfcip6_ctlun.ip6_un2_vfc |= IPV6_VERSION0x60;
804 ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP17;
805 ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr))(__uint16_t)(__builtin_constant_p(m->M_dat.MH.MH_pkthdr.len
- sizeof(struct ip6_hdr)) ? (__uint16_t)(((__uint16_t)(m->
M_dat.MH.MH_pkthdr.len - sizeof(struct ip6_hdr)) & 0xffU)
<< 8 | ((__uint16_t)(m->M_dat.MH.MH_pkthdr.len - sizeof
(struct ip6_hdr)) & 0xff00U) >> 8) : __swap16md(m->
M_dat.MH.MH_pkthdr.len - sizeof(struct ip6_hdr)))
;
806 if (in6_embedscope(&ip6->ip6_src, satosin6(src), NULL((void *)0)) != 0)
807 goto drop;
808 if (in6_embedscope(&ip6->ip6_dst, satosin6(dst), NULL((void *)0)) != 0)
809 goto drop;
810
811 if (sc->sc_ttl > 0)
812 ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim = sc->sc_ttl;
813 else
814 ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim = ip6_defhlim;
815
816 if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(src)->sin6_addr)((*(const u_int32_t *)(const void *)(&(&satosin6(src)
->sin6_addr)->__u6_addr.__u6_addr8[0]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&satosin6(src)
->sin6_addr)->__u6_addr.__u6_addr8[4]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&satosin6(src)
->sin6_addr)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&satosin6(src)
->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))
) {
817 if (in6_selectsrc(&in6a, satosin6(dst), NULL((void *)0),
818 sc->sc_rdomain) != 0)
819 goto drop;
820
821 ip6->ip6_src = *in6a;
822 }
823
824 if (sc->sc_df)
825 SET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)((m->M_dat.MH.MH_pkthdr.csum_flags) |= (0x1000));
826
827 /*
828 * The UDP checksum of VXLAN packets should be set to zero,
829 * but the IPv6 UDP checksum is not optional. There is an RFC 6539
830 * to relax the IPv6 UDP checksum requirement for tunnels, but it
831 * is currently not supported by most implementations.
832 */
833 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_UDP_CSUM_OUT0x0004;
834
835 return (m);
836
837drop:
838 m_freem(m);
839 return (NULL((void *)0));
840}
841#endif /* INET6 */
842
843int
844vxlan_output(struct ifnet *ifp, struct mbuf *m)
845{
846 struct vxlan_softc *sc = (struct vxlan_softc *)ifp->if_softc;
847 struct vxlanudphdr *vu;
848 struct sockaddr *src, *dst;
849#if NBRIDGE1 > 0
850 struct bridge_tunneltag *brtag;
851#endif
852 int error, af;
853 uint32_t tag;
854 struct mbuf *m0;
855
856 /* VXLAN header, needs new mbuf because of alignment issues */
857 MGET(m0, M_DONTWAIT, m->m_type)m0 = m_get((0x0002), (m->m_hdr.mh_type));
858 if (m0 == NULL((void *)0)) {
859 ifp->if_oerrorsif_data.ifi_oerrors++;
860 return (ENOBUFS55);
861 }
862 M_MOVE_PKTHDR(m0, m)do { (m0)->m_hdr.mh_flags = ((m0)->m_hdr.mh_flags &
(0x0001 | 0x0008)); (m0)->m_hdr.mh_flags |= (m)->m_hdr
.mh_flags & (0x0002|0x0004|0x0010|0x0100|0x0200|0x0400|0x4000
| 0x0800|0x0040|0x1000|0x8000|0x0020|0x2000); do { ((m0))->
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 (((m0)
->m_hdr.mh_flags & 0x0001) == 0) (m0)->m_hdr.mh_data
= (m0)->M_dat.MH.MH_dat.MH_databuf; } while ( 0)
;
863 m0->m_nextm_hdr.mh_next = m;
864 m = m0;
865 m_align(m, sizeof(*vu));
866 m->m_lenm_hdr.mh_len = sizeof(*vu);
867 m->m_pkthdrM_dat.MH.MH_pkthdr.len += sizeof(*vu);
868
869 src = sstosa(&sc->sc_src);
870 dst = sstosa(&sc->sc_dst);
871 af = src->sa_family;
872
873 vu = mtod(m, struct vxlanudphdr *)((struct vxlanudphdr *)((m)->m_hdr.mh_data));
874 vu->vu_u.uh_sport = sc->sc_dstport;
875 vu->vu_u.uh_dport = sc->sc_dstport;
876 vu->vu_u.uh_ulen = htons(m->m_pkthdr.len)(__uint16_t)(__builtin_constant_p(m->M_dat.MH.MH_pkthdr.len
) ? (__uint16_t)(((__uint16_t)(m->M_dat.MH.MH_pkthdr.len) &
0xffU) << 8 | ((__uint16_t)(m->M_dat.MH.MH_pkthdr.len
) & 0xff00U) >> 8) : __swap16md(m->M_dat.MH.MH_pkthdr
.len))
;
877 vu->vu_u.uh_sum = 0;
878 tag = sc->sc_vnetid;
879
880#if NBRIDGE1 > 0
881 if ((brtag = bridge_tunnel(m)) != NULL((void *)0)) {
882 dst = &brtag->brtag_peer.sa;
883
884 /* If accepting any VNI, source ip address is from brtag */
885 if (sc->sc_vnetid == VXLAN_VNI_ANY-1ULL) {
886 src = &brtag->brtag_local.sa;
887 tag = (uint32_t)brtag->brtag_id;
888 af = src->sa_family;
889 }
890
891 if (dst->sa_family != af) {
892 ifp->if_oerrorsif_data.ifi_oerrors++;
893 m_freem(m);
894 return (EINVAL22);
895 }
896 } else
897#endif
898 if (sc->sc_vnetid == VXLAN_VNI_ANY-1ULL) {
899 /*
900 * If accepting any VNI, build the vxlan header only by
901 * bridge_tunneltag or drop packet if the tag does not exist.
902 */
903 ifp->if_oerrorsif_data.ifi_oerrors++;
904 m_freem(m);
905 return (ENETUNREACH51);
906 }
907
908 if (sc->sc_vnetid != VXLAN_VNI_UNSET0x01ffffff) {
909 vu->vu_v.vxlan_flags = htonl(VXLAN_FLAGS_VNI)(__uint32_t)(__builtin_constant_p(0x08000000) ? (__uint32_t)(
((__uint32_t)(0x08000000) & 0xff) << 24 | ((__uint32_t
)(0x08000000) & 0xff00) << 8 | ((__uint32_t)(0x08000000
) & 0xff0000) >> 8 | ((__uint32_t)(0x08000000) &
0xff000000) >> 24) : __swap32md(0x08000000))
;
910 vu->vu_v.vxlan_id = htonl(tag << VXLAN_VNI_S)(__uint32_t)(__builtin_constant_p(tag << 8) ? (__uint32_t
)(((__uint32_t)(tag << 8) & 0xff) << 24 | ((__uint32_t
)(tag << 8) & 0xff00) << 8 | ((__uint32_t)(tag
<< 8) & 0xff0000) >> 8 | ((__uint32_t)(tag <<
8) & 0xff000000) >> 24) : __swap32md(tag << 8
))
;
911 } else {
912 vu->vu_v.vxlan_flags = htonl(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
;
913 vu->vu_v.vxlan_id = htonl(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
;
914 }
915
916 switch (af) {
917 case AF_INET2:
918 m = vxlan_encap4(ifp, m, src, dst);
919 break;
920#ifdef INET61
921 case AF_INET624:
922 m = vxlan_encap6(ifp, m, src, dst);
923 break;
924#endif /* INET6 */
925 default:
926 m_freem(m);
927 m = NULL((void *)0);
928 }
929
930 if (m == NULL((void *)0)) {
931 ifp->if_oerrorsif_data.ifi_oerrors++;
932 return (ENOBUFS55);
933 }
934
935#if NBRIDGE1 > 0
936 if (brtag != NULL((void *)0))
937 bridge_tunneluntag(m);
938#endif
939
940 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid = sc->sc_rdomain;
941
942#if NPF1 > 0
943 pf_pkt_addr_changed(m);
944#endif
945
946 switch (af) {
947 case AF_INET2:
948 error = ip_output(m, NULL((void *)0), NULL((void *)0), IP_RAWOUTPUT0x2,
949 &sc->sc_imo, NULL((void *)0), 0);
950 break;
951#ifdef INET61
952 case AF_INET624:
953 error = ip6_output(m, NULL((void *)0), NULL((void *)0), IPV6_MINMTU0x04, NULL((void *)0), NULL((void *)0));
954 break;
955#endif /* INET6 */
956 default:
957 m_freem(m);
958 error = EAFNOSUPPORT47;
959 }
960
961 if (error)
962 ifp->if_oerrorsif_data.ifi_oerrors++;
963
964 return (error);
965}
966
967void
968vxlan_addr_change(void *arg)
969{
970 struct vxlan_softc *sc = arg;
971 struct ifnet *ifp = &sc->sc_ac.ac_if;
972 int error;
973
974 /*
975 * Reset the configuration after resume or any possible address
976 * configuration changes.
977 */
978 if ((error = vxlan_config(ifp, NULL((void *)0), NULL((void *)0)))) {
979 /*
980 * The source address of the tunnel can temporarily disappear,
981 * after a link state change when running the DHCP client,
982 * so keep it configured.
983 */
984 }
985}
986
987void
988vxlan_if_change(void *arg)
989{
990 struct vxlan_softc *sc = arg;
991 struct ifnet *ifp = &sc->sc_ac.ac_if;
992
993 /*
994 * Reset the configuration after the parent interface disappeared.
995 */
996 vxlan_multicast_cleanup(ifp);
997 memset(&sc->sc_src, 0, sizeof(sc->sc_src))__builtin_memset((&sc->sc_src), (0), (sizeof(sc->sc_src
)))
;
998 memset(&sc->sc_dst, 0, sizeof(sc->sc_dst))__builtin_memset((&sc->sc_dst), (0), (sizeof(sc->sc_dst
)))
;
999 sc->sc_dstport = htons(VXLAN_PORT)(__uint16_t)(__builtin_constant_p(4789) ? (__uint16_t)(((__uint16_t
)(4789) & 0xffU) << 8 | ((__uint16_t)(4789) & 0xff00U
) >> 8) : __swap16md(4789))
;
1000}
1001
1002void
1003vxlan_link_change(void *arg)
1004{
1005 struct vxlan_softc *sc = arg;
1006 struct ifnet *ifp = &sc->sc_ac.ac_if;
1007
1008 /*
1009 * The machine might have lost its multicast associations after
1010 * link state changes. This fixes a problem with VMware after
1011 * suspend/resume of the host or guest.
1012 */
1013 (void)vxlan_config(ifp, NULL((void *)0), NULL((void *)0));
1014}