VirtualBox

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

Last change on this file since 40107 was 35950, checked in by vboxsync, 14 years ago

netflt: FreeBSD build fix by Howard Su

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 KB
Line 
1/* $Id: VBoxNetAdp-freebsd.c 35950 2011-02-14 07:46:18Z vboxsync $ */
2/** @file
3 * VBoxNetAdp - Virtual Network Adapter Driver (Host), FreeBSD Specific Code.
4 */
5
6/*-
7 * Copyright (c) 2009 Fredrik Lindberg <fli@shapeshifter.se>
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* Header Files *
33*******************************************************************************/
34#include <sys/param.h>
35#undef PVM
36#include <sys/types.h>
37#include <sys/module.h>
38#include <sys/systm.h>
39#include <sys/errno.h>
40#include <sys/kernel.h>
41#include <sys/fcntl.h>
42#include <sys/conf.h>
43#include <sys/uio.h>
44#include <sys/socket.h>
45#include <sys/sockio.h>
46
47#include <net/if.h>
48#include <net/if_var.h>
49#include <net/route.h>
50#include <net/if_dl.h>
51#include <net/if_types.h>
52#include <net/ethernet.h>
53#include <net/bpf.h>
54
55#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
56#include <VBox/version.h>
57#include <VBox/err.h>
58#include <VBox/log.h>
59#include <iprt/initterm.h>
60#include <iprt/string.h>
61#include <iprt/spinlock.h>
62#include <iprt/process.h>
63#include <iprt/assert.h>
64#include <iprt/uuid.h>
65#include <iprt/alloc.h>
66#include <iprt/err.h>
67
68#define VBOXNETADP_OS_SPECFIC 1
69#include "../VBoxNetAdpInternal.h"
70
71static int VBoxNetAdpFreeBSDCtrlioctl(struct cdev *, u_long, caddr_t, int flags,
72 struct thread *);
73static struct cdevsw vboxnetadp_cdevsw =
74{
75 .d_version = D_VERSION,
76 .d_ioctl = VBoxNetAdpFreeBSDCtrlioctl,
77 .d_read = (d_read_t *)nullop,
78 .d_write = (d_write_t *)nullop,
79 .d_name = VBOXNETADP_CTL_DEV_NAME,
80};
81
82static struct cdev *VBoxNetAdpFreeBSDcdev;
83
84static int VBoxNetAdpFreeBSDModuleEvent(struct module *, int, void *);
85static moduledata_t g_VBoxNetAdpFreeBSDModule = {
86 "vboxnetadp",
87 VBoxNetAdpFreeBSDModuleEvent,
88 NULL
89};
90
91/** Declare the module as a pseudo device. */
92DECLARE_MODULE(vboxnetadp, g_VBoxNetAdpFreeBSDModule, SI_SUB_PSEUDO, SI_ORDER_ANY);
93MODULE_VERSION(vboxnetadp, 1);
94MODULE_DEPEND(vboxnetadp, vboxdrv, 1, 1, 1);
95MODULE_DEPEND(vboxnetadp, vboxnetflt, 1, 1, 1);
96
97/**
98 * Module event handler
99 */
100static int
101VBoxNetAdpFreeBSDModuleEvent(struct module *pMod, int enmEventType, void *pvArg)
102{
103 int rc = 0;
104
105 Log(("VBoxNetAdpFreeBSDModuleEvent\n"));
106
107 switch (enmEventType)
108 {
109 case MOD_LOAD:
110 rc = RTR0Init(0);
111 if (RT_FAILURE(rc))
112 {
113 Log(("RTR0Init failed %d\n", rc));
114 return RTErrConvertToErrno(rc);
115 }
116 rc = vboxNetAdpInit();
117 if (RT_FAILURE(rc))
118 {
119 RTR0Term();
120 Log(("vboxNetAdpInit failed %d\n", rc));
121 return RTErrConvertToErrno(rc);
122 }
123 /* Create dev node */
124 VBoxNetAdpFreeBSDcdev = make_dev(&vboxnetadp_cdevsw, 0,
125 UID_ROOT, GID_WHEEL, 0600, VBOXNETADP_CTL_DEV_NAME);
126
127 break;
128
129 case MOD_UNLOAD:
130 vboxNetAdpShutdown();
131 destroy_dev(VBoxNetAdpFreeBSDcdev);
132 RTR0Term();
133 break;
134 case MOD_SHUTDOWN:
135 case MOD_QUIESCE:
136 default:
137 return EOPNOTSUPP;
138 }
139
140 if (RT_SUCCESS(rc))
141 return 0;
142 return RTErrConvertToErrno(rc);
143}
144
145/**
146 * Device I/O Control entry point.
147 */
148static int
149VBoxNetAdpFreeBSDCtrlioctl(struct cdev *dev, u_long iCmd, caddr_t data, int flags, struct thread *td)
150{
151 PVBOXNETADP pAdp;
152 PVBOXNETADPREQ pReq = (PVBOXNETADPREQ)data;
153 struct ifnet *ifp;
154 int rc;
155
156 switch (iCmd)
157 {
158 case VBOXNETADP_CTL_ADD:
159 if ( !(iCmd & IOC_INOUT) /* paranoia*/
160 || IOCPARM_LEN(iCmd) < sizeof(*pReq))
161 return EINVAL;
162
163 rc = vboxNetAdpCreate(&pAdp,
164 pReq->szName[0] && RTStrEnd(pReq->szName, RT_MIN(IOCPARM_LEN(iCmd), sizeof(pReq->szName))) ?
165 pReq->szName : NULL);
166 if (RT_FAILURE(rc))
167 return EINVAL;
168
169 strncpy(pReq->szName, pAdp->szName, sizeof(pReq->szName) - 1);
170 pReq->szName[sizeof(pReq->szName) - 1] = '\0';
171 break;
172
173 case VBOXNETADP_CTL_REMOVE:
174 if (!RTStrEnd(pReq->szName, RT_MIN(sizeof(pReq->szName), IOCPARM_LEN(iCmd))))
175 return EINVAL;
176
177 pAdp = vboxNetAdpFindByName(pReq->szName);
178 if (!pAdp)
179 return EINVAL;
180
181 rc = vboxNetAdpDestroy(pAdp);
182 if (RT_FAILURE(rc))
183 return EINVAL;
184
185 break;
186
187 default:
188 return EINVAL;
189 }
190 return 0;
191}
192
193/**
194 * Initialize device, just set the running flag.
195 */
196static void VBoxNetAdpFreeBSDNetinit(void *priv)
197{
198 PVBOXNETADP pThis = priv;
199 struct ifnet *ifp = pThis->u.s.ifp;
200
201 ifp->if_drv_flags |= IFF_DRV_RUNNING;
202}
203
204/**
205 * Transmit packets.
206 * netflt has already done everything for us so we just hand the
207 * packets to BPF and increment the packet stats.
208 */
209static void VBoxNetAdpFreeBSDNetstart(struct ifnet *ifp)
210{
211 PVBOXNETADP pThis = ifp->if_softc;
212 struct mbuf *m;
213
214 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING)
215 return;
216
217 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
218 while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
219 {
220 ifp->if_opackets++;
221 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
222 BPF_MTAP(ifp, m);
223 m_freem(m);
224 }
225 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
226}
227
228/**
229 * Interface ioctl handling
230 */
231static int VBoxNetAdpFreeBSDNetioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
232{
233 switch (cmd)
234 {
235 case SIOCSIFFLAGS:
236 if (ifp->if_flags & IFF_UP)
237 {
238 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
239 ifp->if_init(ifp->if_softc);
240 }
241 else
242 {
243 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
244 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
245 }
246 break;
247 default:
248 return ether_ioctl(ifp, cmd, data);
249 }
250 return 0;
251}
252
253int vboxNetAdpOsInit(PVBOXNETADP pThis)
254{
255 pThis->u.s.ifp = NULL;
256 return VINF_SUCCESS;;
257}
258
259int vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMac)
260{
261 struct ifnet *ifp;
262
263 ifp = if_alloc(IFT_ETHER);
264 if (ifp == NULL)
265 return VERR_NO_MEMORY;
266
267 if_initname(ifp, VBOXNETADP_NAME, pThis->iUnit);
268 ifp->if_softc = pThis;
269 ifp->if_mtu = ETHERMTU;
270 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
271 ifp->if_ioctl = VBoxNetAdpFreeBSDNetioctl;
272 ifp->if_start = VBoxNetAdpFreeBSDNetstart;
273 ifp->if_init = VBoxNetAdpFreeBSDNetinit;
274 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
275 ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
276 IFQ_SET_READY(&ifp->if_snd);
277 ether_ifattach(ifp, (void *)pMac);
278 ifp->if_baudrate = 0;
279
280 strncpy(pThis->szName, ifp->if_xname, VBOXNETADP_MAX_NAME_LEN);
281 pThis->u.s.ifp = ifp;
282 return 0;
283}
284
285void vboxNetAdpOsDestroy(PVBOXNETADP pThis)
286{
287 struct ifnet *ifp;
288
289 ifp = pThis->u.s.ifp;
290 ether_ifdetach(ifp);
291 if_free(ifp);
292}
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