VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetAdp/freebsd/VBoxNetAdp-freebsd.c@ 79846

Last change on this file since 79846 was 77124, checked in by vboxsync, 6 years ago

VBoxNetAdp,VBoxNetFlt: FreeBSD build fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1/* $Id: VBoxNetAdp-freebsd.c 77124 2019-02-01 15:35:59Z vboxsync $ */
2/** @file
3 * VBoxNetAdp - Virtual Network Adapter Driver (Host), FreeBSD Specific Code.
4 */
5
6/*-
7 * Copyright (c) 2009 Fredrik Lindberg <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#include <sys/param.h>
36#undef PVM
37#include <sys/types.h>
38#include <sys/module.h>
39#include <sys/systm.h>
40#include <sys/errno.h>
41#include <sys/kernel.h>
42#include <sys/fcntl.h>
43#include <sys/conf.h>
44#include <sys/uio.h>
45#include <sys/socket.h>
46#include <sys/sockio.h>
47
48#include <net/if.h>
49#include <net/if_var.h>
50#include <net/route.h>
51#include <net/if_dl.h>
52#include <net/if_media.h>
53#include <net/if_types.h>
54#include <net/ethernet.h>
55#include <net/bpf.h>
56
57#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
58#include <VBox/version.h>
59#include <iprt/errcore.h>
60#include <VBox/log.h>
61#include <iprt/initterm.h>
62#include <iprt/string.h>
63#include <iprt/spinlock.h>
64#include <iprt/process.h>
65#include <iprt/assert.h>
66#include <iprt/uuid.h>
67#include <iprt/alloc.h>
68#include <iprt/errcore.h>
69
70#define VBOXNETADP_OS_SPECFIC 1
71#include "../VBoxNetAdpInternal.h"
72
73#if defined(__FreeBSD_version) && __FreeBSD_version >= 800500
74# include <sys/jail.h>
75# include <net/vnet.h>
76
77# define VBOXCURVNET_SET(arg) CURVNET_SET_QUIET(arg)
78# define VBOXCURVNET_SET_FROM_UCRED() VBOXCURVNET_SET(CRED_TO_VNET(curthread->td_ucred))
79# define VBOXCURVNET_RESTORE() CURVNET_RESTORE()
80
81#else /* !defined(__FreeBSD_version) || __FreeBSD_version < 800500 */
82
83# define VBOXCURVNET_SET(arg)
84# define VBOXCURVNET_SET_FROM_UCRED()
85# define VBOXCURVNET_RESTORE()
86
87#endif /* !defined(__FreeBSD_version) || __FreeBSD_version < 800500 */
88
89static int VBoxNetAdpFreeBSDCtrlioctl(struct cdev *, u_long, caddr_t, int flags,
90 struct thread *);
91static struct cdevsw vboxnetadp_cdevsw =
92{
93 .d_version = D_VERSION,
94 .d_ioctl = VBoxNetAdpFreeBSDCtrlioctl,
95 .d_read = (d_read_t *)nullop,
96 .d_write = (d_write_t *)nullop,
97 .d_name = VBOXNETADP_CTL_DEV_NAME,
98};
99
100static struct cdev *VBoxNetAdpFreeBSDcdev;
101
102static int VBoxNetAdpFreeBSDModuleEvent(struct module *, int, void *);
103static moduledata_t g_VBoxNetAdpFreeBSDModule = {
104 "vboxnetadp",
105 VBoxNetAdpFreeBSDModuleEvent,
106 NULL
107};
108
109/** Declare the module as a pseudo device. */
110DECLARE_MODULE(vboxnetadp, g_VBoxNetAdpFreeBSDModule, SI_SUB_PSEUDO, SI_ORDER_ANY);
111MODULE_VERSION(vboxnetadp, 1);
112MODULE_DEPEND(vboxnetadp, vboxdrv, 1, 1, 1);
113MODULE_DEPEND(vboxnetadp, vboxnetflt, 1, 1, 1);
114
115/**
116 * Module event handler
117 */
118static int
119VBoxNetAdpFreeBSDModuleEvent(struct module *pMod, int enmEventType, void *pvArg)
120{
121 int rc = 0;
122
123 Log(("VBoxNetAdpFreeBSDModuleEvent\n"));
124
125 switch (enmEventType)
126 {
127 case MOD_LOAD:
128 rc = RTR0Init(0);
129 if (RT_FAILURE(rc))
130 {
131 Log(("RTR0Init failed %d\n", rc));
132 return RTErrConvertToErrno(rc);
133 }
134 rc = vboxNetAdpInit();
135 if (RT_FAILURE(rc))
136 {
137 RTR0Term();
138 Log(("vboxNetAdpInit failed %d\n", rc));
139 return RTErrConvertToErrno(rc);
140 }
141 /* Create dev node */
142 VBoxNetAdpFreeBSDcdev = make_dev(&vboxnetadp_cdevsw, 0,
143 UID_ROOT, GID_WHEEL, 0600, VBOXNETADP_CTL_DEV_NAME);
144
145 break;
146
147 case MOD_UNLOAD:
148 vboxNetAdpShutdown();
149 destroy_dev(VBoxNetAdpFreeBSDcdev);
150 RTR0Term();
151 break;
152 case MOD_SHUTDOWN:
153 case MOD_QUIESCE:
154 default:
155 return EOPNOTSUPP;
156 }
157
158 if (RT_SUCCESS(rc))
159 return 0;
160 return RTErrConvertToErrno(rc);
161}
162
163/**
164 * Device I/O Control entry point.
165 */
166static int
167VBoxNetAdpFreeBSDCtrlioctl(struct cdev *dev, u_long iCmd, caddr_t data, int flags, struct thread *td)
168{
169 PVBOXNETADP pAdp;
170 PVBOXNETADPREQ pReq = (PVBOXNETADPREQ)data;
171 struct ifnet *ifp;
172 int rc;
173
174 switch (iCmd)
175 {
176 case VBOXNETADP_CTL_ADD:
177 if ( !(iCmd & IOC_INOUT) /* paranoia*/
178 || IOCPARM_LEN(iCmd) < sizeof(*pReq))
179 return EINVAL;
180
181 rc = vboxNetAdpCreate(&pAdp,
182 pReq->szName[0] && RTStrEnd(pReq->szName, RT_MIN(IOCPARM_LEN(iCmd), sizeof(pReq->szName))) ?
183 pReq->szName : NULL);
184 if (RT_FAILURE(rc))
185 return EINVAL;
186
187 strncpy(pReq->szName, pAdp->szName, sizeof(pReq->szName) - 1);
188 pReq->szName[sizeof(pReq->szName) - 1] = '\0';
189 break;
190
191 case VBOXNETADP_CTL_REMOVE:
192 if (!RTStrEnd(pReq->szName, RT_MIN(sizeof(pReq->szName), IOCPARM_LEN(iCmd))))
193 return EINVAL;
194
195 pAdp = vboxNetAdpFindByName(pReq->szName);
196 if (!pAdp)
197 return EINVAL;
198
199 rc = vboxNetAdpDestroy(pAdp);
200 if (RT_FAILURE(rc))
201 return EINVAL;
202
203 break;
204
205 default:
206 return EINVAL;
207 }
208 return 0;
209}
210
211/**
212 * Initialize device, just set the running flag.
213 */
214static void VBoxNetAdpFreeBSDNetinit(void *priv)
215{
216 PVBOXNETADP pThis = priv;
217 struct ifnet *ifp = pThis->u.s.ifp;
218
219 ifp->if_drv_flags |= IFF_DRV_RUNNING;
220}
221
222/**
223 * Transmit packets.
224 * netflt has already done everything for us so we just hand the
225 * packets to BPF and increment the packet stats.
226 */
227static void VBoxNetAdpFreeBSDNetstart(struct ifnet *ifp)
228{
229 PVBOXNETADP pThis = ifp->if_softc;
230 struct mbuf *m;
231
232 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING)
233 return;
234
235 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
236 while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
237 {
238#if __FreeBSD_version >= 1100036
239 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
240#else
241 ifp->if_opackets++;
242#endif
243 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
244 BPF_MTAP(ifp, m);
245 m_freem(m);
246 }
247 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
248}
249
250/**
251 * Interface ioctl handling
252 */
253static int VBoxNetAdpFreeBSDNetioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
254{
255 int error = 0;
256
257 switch (cmd)
258 {
259 case SIOCSIFFLAGS:
260 if (ifp->if_flags & IFF_UP)
261 {
262 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
263 ifp->if_init(ifp->if_softc);
264 }
265 else
266 {
267 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
268 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
269 }
270 break;
271 case SIOCGIFMEDIA:
272 {
273 struct ifmediareq *ifmr;
274 int count;
275
276 ifmr = (struct ifmediareq *)data;
277 count = ifmr->ifm_count;
278 ifmr->ifm_count = 1;
279 ifmr->ifm_status = IFM_AVALID;
280 ifmr->ifm_active = IFM_ETHER;
281 ifmr->ifm_status |= IFM_ACTIVE;
282 ifmr->ifm_current = ifmr->ifm_active;
283 if (count >= 1)
284 {
285 int media = IFM_ETHER;
286 error = copyout(&media, ifmr->ifm_ulist, sizeof(int));
287 }
288 break;
289 }
290 default:
291 return ether_ioctl(ifp, cmd, data);
292 }
293 return error;
294}
295
296int vboxNetAdpOsInit(PVBOXNETADP pThis)
297{
298 pThis->u.s.ifp = NULL;
299 return VINF_SUCCESS;;
300}
301
302int vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMac)
303{
304 struct ifnet *ifp;
305
306 VBOXCURVNET_SET_FROM_UCRED();
307 ifp = if_alloc(IFT_ETHER);
308 if (ifp == NULL)
309 return VERR_NO_MEMORY;
310
311 if_initname(ifp, VBOXNETADP_NAME, pThis->iUnit);
312 ifp->if_softc = pThis;
313 ifp->if_mtu = ETHERMTU;
314 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
315 ifp->if_ioctl = VBoxNetAdpFreeBSDNetioctl;
316 ifp->if_start = VBoxNetAdpFreeBSDNetstart;
317 ifp->if_init = VBoxNetAdpFreeBSDNetinit;
318 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
319 ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
320 IFQ_SET_READY(&ifp->if_snd);
321 ether_ifattach(ifp, (void *)pMac);
322 ifp->if_baudrate = 0;
323
324 strncpy(pThis->szName, ifp->if_xname, VBOXNETADP_MAX_NAME_LEN);
325 pThis->u.s.ifp = ifp;
326 VBOXCURVNET_RESTORE();
327 return 0;
328}
329
330void vboxNetAdpOsDestroy(PVBOXNETADP pThis)
331{
332 struct ifnet *ifp;
333
334 ifp = pThis->u.s.ifp;
335 VBOXCURVNET_SET(ifp->if_vnet);
336 ether_ifdetach(ifp);
337 if_free(ifp);
338 VBOXCURVNET_RESTORE();
339}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette