1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1990, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 2019 Andrey V. Elsukov <ae@FreeBSD.org>
7 * Copyright (c) 2025 Gleb Smirnoff <glebius@FreeBSD.org>
8 *
9 * This code is derived from the Stanford/CMU enet packet filter,
10 * (net/enet.c) distributed as part of 4.3BSD, and code contributed
11 * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
12 * Berkeley Laboratory.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/mbuf.h>
40 #include <sys/socket.h>
41 #include <net/bpf.h>
42 #include <net/bpfdesc.h>
43 #include <net/if.h>
44 #include <net/if_var.h>
45 #include <net/if_private.h>
46 #include <net/if_types.h>
47 #include <net/route.h>
48
49 /* We need to know all the ifnets we support. */
50 #include <net/if_dl.h>
51 #include <net/ethernet.h>
52 #include <net/firewire.h>
53 #include <net/if_pflog.h>
54 #include <net/if_pfsync.h>
55
56 #include <security/mac/mac_framework.h>
57
58 static int
bpf_ifnet_write(void * arg,struct mbuf * m,struct mbuf * mc,int flags)59 bpf_ifnet_write(void *arg, struct mbuf *m, struct mbuf *mc, int flags)
60 {
61 struct ifnet *ifp = arg;
62 struct route ro = {};
63 struct sockaddr dst = {
64 .sa_family = AF_UNSPEC,
65 };
66 u_int hlen;
67 int error;
68
69 NET_EPOCH_ASSERT();
70
71 if (__predict_false((ifp->if_flags & IFF_UP) == 0)) {
72 m_freem(m);
73 m_freem(mc);
74 return (ENETDOWN);
75 }
76
77 switch (ifp->if_type) {
78 /* DLT_RAW */
79 case IFT_MBIM: /* umb(4) */
80 case IFT_OTHER: /* uhso(4), usie */
81 hlen = 0;
82 break;
83
84 /* DLT_ENC */
85 case IFT_ENC:
86 hlen = 12; /* XXXGL: sizeof(struct enchdr); */
87 break;
88
89 /* DLT_EN10MB */
90 case IFT_ETHER: /* if_ethersubr.c */
91 case IFT_L2VLAN: /* vlan(4) */
92 case IFT_BRIDGE: /* if_bridge(4) */
93 case IFT_IEEE8023ADLAG: /* lagg(4) */
94 case IFT_INFINIBAND: /* if_infiniband.c */
95 {
96 struct ether_header *eh;
97
98 eh = mtod(m, struct ether_header *);
99 if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
100 if (bcmp(ifp->if_broadcastaddr, eh->ether_dhost,
101 ETHER_ADDR_LEN) == 0)
102 m->m_flags |= M_BCAST;
103 else
104 m->m_flags |= M_MCAST;
105 }
106 if (!(flags & BPFD_HDRCMPLT)) {
107 memcpy(eh->ether_shost, IF_LLADDR(ifp),
108 sizeof(eh->ether_shost));
109 }
110 hlen = ETHER_HDR_LEN;
111 break;
112 }
113 /* DLT_APPLE_IP_OVER_IEEE1394 */
114 case IFT_IEEE1394: /* fwip(4) */
115 hlen = sizeof(struct fw_hwaddr);
116 break;
117
118 /* DLT_NULL */
119 case IFT_GIF: /* gif(4) */
120 case IFT_LOOP: /* lo(4), disc(4) */
121 case IFT_PARA: /* plip(4), iic */
122 case IFT_PPP: /* tun(4) */
123 case IFT_PROPVIRTUAL: /* ng_iface(4) */
124 case IFT_WIREGUARD: /* wg(4) */
125 case IFT_STF: /* stf(4) */
126 case IFT_TUNNEL: /* ipsec(4), me(4), gre(4), ovpn(4) */
127 hlen = sizeof(uint32_t);
128 break;
129
130 /* DLT_PFLOG */
131 case IFT_PFLOG:
132 hlen = PFLOG_HDRLEN;
133 break;
134
135 /* DLT_PFSYNC */
136 case IFT_PFSYNC:
137 hlen = PFSYNC_HDRLEN;
138 break;
139
140 default:
141 hlen = 0; /* pacify compiler */
142 KASSERT(0, ("%s: ifp %p type %u not supported", __func__,
143 ifp, ifp->if_type));
144 }
145
146 if (__predict_false(hlen > m->m_len)) {
147 m_freem(m);
148 m_freem(mc);
149 return (EMSGSIZE);
150 };
151
152 if (hlen != 0) {
153 bcopy(mtod(m, const void *), &dst.sa_data, hlen);
154 ro.ro_prepend = (char *)&dst.sa_data;
155 ro.ro_plen = hlen;
156 ro.ro_flags = RT_HAS_HEADER;
157 m->m_pkthdr.len -= hlen;
158 m->m_len -= hlen;
159 m->m_data += hlen;
160 };
161
162 CURVNET_SET(ifp->if_vnet);
163 error = ifp->if_output(ifp, m, &dst, &ro);
164 if (error != 0) {
165 m_freem(mc);
166 } else if (mc != NULL) {
167 mc->m_pkthdr.rcvif = ifp;
168 (void)ifp->if_input(ifp, mc);
169 }
170 CURVNET_RESTORE();
171
172 return (error);
173 }
174
175 static bool
bpf_ifnet_chkdir(void * arg,const struct mbuf * m,int dir)176 bpf_ifnet_chkdir(void *arg, const struct mbuf *m, int dir)
177 {
178 struct ifnet *ifp = arg;
179 struct ifnet *rcvif = m_rcvif(m);
180
181 return ((dir == BPF_D_IN && ifp != rcvif) ||
182 (dir == BPF_D_OUT && ifp == rcvif));
183 }
184
185 uint32_t
bpf_ifnet_wrsize(void * arg)186 bpf_ifnet_wrsize(void *arg)
187 {
188 struct ifnet *ifp = arg;
189
190 return (ifp->if_mtu);
191 }
192
193 int
bpf_ifnet_promisc(void * arg,bool on)194 bpf_ifnet_promisc(void *arg, bool on)
195 {
196 struct ifnet *ifp = arg;
197 int error;
198
199 CURVNET_SET(ifp->if_vnet);
200 if ((error = ifpromisc(ifp, on ? 1 : 0)) != 0)
201 if_printf(ifp, "%s: ifpromisc failed (%d)\n", __func__, error);
202 CURVNET_RESTORE();
203
204 return (error);
205 }
206
207 #ifdef MAC
208 static int
bpf_ifnet_mac_check_receive(void * arg,struct bpf_d * d)209 bpf_ifnet_mac_check_receive(void *arg, struct bpf_d *d)
210 {
211 struct ifnet *ifp = arg;
212
213 return (mac_bpfdesc_check_receive(d, ifp));
214 }
215 #endif
216
217 static const struct bif_methods bpf_ifnet_methods = {
218 .bif_chkdir = bpf_ifnet_chkdir,
219 .bif_promisc = bpf_ifnet_promisc,
220 .bif_wrsize = bpf_ifnet_wrsize,
221 .bif_write = bpf_ifnet_write,
222 #ifdef MAC
223 .bif_mac_check_receive = bpf_ifnet_mac_check_receive,
224 #endif
225 };
226
227 /*
228 * Attach an interface to bpf. dlt is the link layer type; hdrlen is the
229 * fixed size of the link header (variable length headers not yet supported).
230 * Legacy KPI to be obsoleted soon.
231 */
232 void
bpfattach(struct ifnet * ifp,u_int dlt,u_int hdrlen)233 bpfattach(struct ifnet *ifp, u_int dlt, u_int hdrlen)
234 {
235
236 ifp->if_bpf = bpf_attach(ifp->if_xname, dlt, hdrlen,
237 &bpf_ifnet_methods, ifp);
238 if_ref(ifp);
239 if (bootverbose && IS_DEFAULT_VNET(curvnet))
240 if_printf(ifp, "bpf attached\n");
241 }
242
243 /*
244 * The dead_bpf_if is an ugly plug against races at ifnet destroy time that
245 * still exist and are not properly covered by epoch(9).
246 * Legacy KPI to be obsoleted soon.
247 */
248 void
bpfdetach(struct ifnet * ifp)249 bpfdetach(struct ifnet *ifp)
250 {
251 static const struct bpfd_list dead_bpf_if = CK_LIST_HEAD_INITIALIZER();
252 struct bpf_if *bif;
253
254 bif = ifp->if_bpf;
255 ifp->if_bpf = __DECONST(struct bpf_if *, &dead_bpf_if);
256 bpf_detach(bif);
257 if_rele(ifp);
258 }
259