VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c@ 23832

最後變更 在這個檔案從23832是 23526,由 vboxsync 提交於 15 年 前

HostDrivers/FreeBSD: Use the same method to build the kernel drivers as Linux.

To build the kernel drivers go into out/freebsd.{amd64,x86}/{release,debug}/bin/src
after the build and execute make. make load will load the kernel drivers.
The old way is only used for syntax checking and the resulting modules may not even load anymore.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 19.2 KB
 
1/* $Id: VBoxNetFlt-freebsd.c 23526 2009-10-03 17:55:49Z vboxsync $ */
2/** @file
3 * VBoxNetFlt - Network Filter 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* 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/socket.h>
44#include <sys/sockio.h>
45#include <sys/syscallsubr.h>
46
47#include <net/if.h>
48#include <net/if_var.h>
49#include <net/if_dl.h>
50#include <net/if_types.h>
51#include <net/ethernet.h>
52
53#include <netgraph/ng_message.h>
54#include <netgraph/netgraph.h>
55#include <netgraph/ng_parse.h>
56
57#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
58#include <VBox/version.h>
59#include <VBox/err.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/err.h>
69
70#define VBOXNETFLT_OS_SPECFIC 1
71#include "../VBoxNetFltInternal.h"
72
73static int vboxnetflt_modevent(struct module *, int, void *);
74static ng_constructor_t ng_vboxnetflt_constructor;
75static ng_rcvmsg_t ng_vboxnetflt_rcvmsg;
76static ng_shutdown_t ng_vboxnetflt_shutdown;
77static ng_newhook_t ng_vboxnetflt_newhook;
78static ng_rcvdata_t ng_vboxnetflt_rcvdata;
79static ng_disconnect_t ng_vboxnetflt_disconnect;
80static int ng_vboxnetflt_mod_event(module_t mod, int event, void *data);
81static int ng_vboxnetflt_rcv_in(hook_p node, item_p item);
82static int ng_vboxnetflt_rcv_out(hook_p node, item_p item);
83
84/** Netgraph node type */
85#define NG_VBOXNETFLT_NODE_TYPE "vboxnetflt"
86/** Netgraph message cookie */
87#define NGM_VBOXNETFLT_COOKIE 0x56424f58
88
89/** Input netgraph hook name */
90#define NG_VBOXNETFLT_HOOK_IN "input"
91/** Output netgraph hook name */
92#define NG_VBOXNETFLT_HOOK_OUT "output"
93
94/** mbuf tag identifier */
95#define MTAG_VBOX 0x56424f58
96/** mbuf packet tag */
97#define PACKET_TAG_VBOX 128
98
99/*
100 * Netgraph command list, we don't support any
101 * additional commands.
102 */
103static const struct ng_cmdlist ng_vboxnetflt_cmdlist[] =
104{
105 { 0 }
106};
107
108/*
109 * Netgraph type definition
110 */
111static struct ng_type ng_vboxnetflt_typestruct =
112{
113 .version = NG_ABI_VERSION,
114 .name = NG_VBOXNETFLT_NODE_TYPE,
115 .mod_event = vboxnetflt_modevent,
116 .constructor = ng_vboxnetflt_constructor,
117 .rcvmsg = ng_vboxnetflt_rcvmsg,
118 .shutdown = ng_vboxnetflt_shutdown,
119 .newhook = ng_vboxnetflt_newhook,
120 .rcvdata = ng_vboxnetflt_rcvdata,
121 .disconnect = ng_vboxnetflt_disconnect,
122 .cmdlist = ng_vboxnetflt_cmdlist,
123};
124NETGRAPH_INIT(vboxnetflt, &ng_vboxnetflt_typestruct);
125MODULE_VERSION(ng_vboxnetflt, 1);
126MODULE_DEPEND(ng_vboxnetflt, vboxdrv, 1, 1, 1);
127
128/**
129 * The (common) global data.
130 */
131static VBOXNETFLTGLOBALS g_VBoxNetFltGlobals;
132
133/**
134 * Module event handler, called from netgraph subsystem.
135 */
136static int vboxnetflt_modevent(struct module *pMod, int enmEventType, void *pvArg)
137{
138 int rc;
139
140 Log(("VBoxNetFltFreeBSDModuleEvent\n"));
141
142 switch (enmEventType)
143 {
144 case MOD_LOAD:
145 rc = RTR0Init(0);
146 if (RT_FAILURE(rc))
147 {
148 printf("RTR0Init failed %d\n", rc);
149 return RTErrConvertToErrno(rc);
150 }
151
152 memset(&g_VBoxNetFltGlobals, 0, sizeof(VBOXNETFLTGLOBALS));
153 rc = vboxNetFltInitGlobalsAndIdc(&g_VBoxNetFltGlobals);
154 if (RT_FAILURE(rc))
155 {
156 printf("vboxNetFltInitGlobalsAndIdc failed %d\n", rc);
157 return RTErrConvertToErrno(rc);
158 }
159 /* No MODULE_VERSION in ng_ether so we can't MODULE_DEPEND it */
160 kern_kldload(curthread, "ng_ether", NULL);
161 break;
162
163 case MOD_UNLOAD:
164 rc = vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltGlobals);
165 memset(&g_VBoxNetFltGlobals, 0, sizeof(VBOXNETFLTGLOBALS));
166 RTR0Term();
167 break;
168
169 case MOD_SHUTDOWN:
170 case MOD_QUIESCE:
171 default:
172 return EOPNOTSUPP;
173 }
174
175 if (RT_SUCCESS(rc))
176 return 0;
177 return RTErrConvertToErrno(rc);
178}
179
180/*
181 * Convert from mbufs to vbox scatter-gather data structure
182 */
183static void vboxNetFltFreeBSDMBufToSG(PVBOXNETFLTINS pThis, struct mbuf *m, PINTNETSG pSG,
184 unsigned int cSegs, unsigned int segOffset)
185{
186 static uint8_t const s_abZero[128] = {0};
187 unsigned int i;
188 struct mbuf *m0;
189
190 pSG->cbTotal = m_length(m, NULL);
191 pSG->pvOwnerData = NULL;
192 pSG->pvUserData = NULL;
193 pSG->pvUserData2 = NULL;
194 pSG->cUsers = 1;
195 pSG->fFlags = INTNETSG_FLAGS_TEMP;
196 pSG->cSegsAlloc = cSegs;
197
198 for (m0 = m, i = segOffset; m0; m0 = m0->m_next)
199 {
200 if (m0->m_len == 0)
201 continue;
202
203 pSG->aSegs[i].cb = m0->m_len;
204 pSG->aSegs[i].pv = mtod(m0, uint8_t *);
205 pSG->aSegs[i].Phys = NIL_RTHCPHYS;
206 i++;
207 }
208
209#ifdef PADD_RUNT_FRAMES_FROM_HOST
210 if (pSG->cbTotal < 60)
211 {
212 pSG->aSegs[i].Phys = NIL_RTHCPHYS;
213 pSG->aSegs[i].pv = (void *)&s_abZero[0];
214 pSG->aSegs[i].cb = 60 - pSG->cbTotal;
215 pSG->cbTotal = 60;
216 i++;
217 }
218#endif
219 pSG->cSegsUsed = i;
220}
221
222/*
223 * Convert to mbufs from vbox scatter-gather data structure
224 */
225static struct mbuf * vboxNetFltFreeBSDSGMBufFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG)
226{
227 struct mbuf *m;
228 int error;
229 unsigned int i;
230
231 if (pSG->cbTotal == 0 || pSG->aSegs[0].cb == 0)
232 return (NULL);
233
234 m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
235 if (m == NULL)
236 return (NULL);
237
238 m->m_pkthdr.len = m->m_len = 0;
239 m->m_pkthdr.rcvif = NULL;
240
241 for (i = 0; i < pSG->cSegsUsed; i++)
242 {
243 error = m_append(m, pSG->aSegs[i].cb, pSG->aSegs[i].pv);
244 if (error == 0)
245 {
246 m_freem(m);
247 return (NULL);
248 }
249 }
250 return (m);
251}
252
253
254static int ng_vboxnetflt_constructor(node_p node)
255{
256 /* Nothing to do */
257 return (EINVAL);
258}
259
260/*
261 * Setup netgraph hooks
262 */
263static int ng_vboxnetflt_newhook(node_p node, hook_p hook, const char *name)
264{
265 PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
266
267 if (strcmp(name, NG_VBOXNETFLT_HOOK_IN) == 0)
268 {
269#if __FreeBSD_version >= 800000
270 NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_in);
271 NG_HOOK_SET_TO_INBOUND(hook);
272#endif
273 pThis->u.s.input = hook;
274 }
275 else if (strcmp(name, NG_VBOXNETFLT_HOOK_OUT) == 0)
276 {
277#if __FreeBSD_version >= 800000
278 NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_out);
279#endif
280 pThis->u.s.output = hook;
281 }
282 else
283 return (EINVAL);
284
285 NG_HOOK_HI_STACK(hook);
286 return (0);
287}
288
289/**
290 * Netgraph message processing for node specific messages.
291 * We don't accept any special messages so this is not used.
292 */
293static int ng_vboxnetflt_rcvmsg(node_p node, item_p item, hook_p lasthook)
294{
295 PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
296 struct ng_mesg *msg;
297 int error = 0;
298
299 NGI_GET_MSG(item, msg);
300 if (msg->header.typecookie != NGM_VBOXNETFLT_COOKIE)
301 return (EINVAL);
302
303 switch (msg->header.cmd)
304 {
305 default:
306 error = EINVAL;
307 }
308 return (error);
309}
310
311/**
312 * Handle data on netgraph hooks.
313 */
314static int ng_vboxnetflt_rcvdata(hook_p hook, item_p item)
315{
316 const node_p node = NG_HOOK_NODE(hook);
317 PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
318 struct mbuf *m;
319
320 if (pThis->u.s.input == hook)
321 return ng_vboxnetflt_rcv_in(hook, item);
322 else if (pThis->u.s.output == hook)
323 return ng_vboxnetflt_rcv_out(hook, item);
324 else
325 {
326 NGI_GET_M(item, m);
327 NG_FREE_ITEM(item);
328 }
329 return (0);
330}
331
332/**
333 * Handle incoming hook. This is connected to the
334 * input path of the interface, thus handling incoming frames.
335 */
336static int ng_vboxnetflt_rcv_in(hook_p hook, item_p item)
337{
338 struct mbuf *m, *m0;
339 struct m_tag *mtag;
340 const node_p node = NG_HOOK_NODE(hook);
341 PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
342 struct ifnet *ifp = pThis->u.s.ifp;
343 bool fActive, fDropIt = false;
344 unsigned int cSegs = 0;
345 PINTNETSG pSG;
346
347 NGI_GET_M(item, m);
348 NG_FREE_ITEM(item);
349
350 fActive = ASMAtomicUoReadBool(&pThis->fActive);
351 if (!fActive)
352 goto out;
353
354 mtag = m_tag_locate(m, MTAG_VBOX, PACKET_TAG_VBOX, NULL);
355 if (mtag != NULL)
356 {
357 m_tag_unlink(m, mtag);
358 m_tag_free(mtag);
359 goto out;
360 }
361 vboxNetFltRetain(pThis, true /* fBusy */);
362
363 for (m0 = m; m0 != NULL; m0 = m0->m_next)
364 {
365 if (m0->m_len > 0)
366 cSegs++;
367 }
368
369#ifdef PADD_RUNT_FRAMES_FROM_HOST
370 if (m_length(m, NULL) < 60)
371 cSegs++;
372#endif
373
374 /* Create a copy of the mbuf and hand it to the virtual switch */
375 pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
376 vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
377 fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_WIRE);
378 RTMemTmpFree(pSG);
379 vboxNetFltRelease(pThis, true /* fBusy */);
380
381out:
382 /* Only deliver it to the host stack if the destination weren't a guest */
383 if (fDropIt)
384 {
385 m_freem(m);
386 return (0);
387 }
388 ether_demux(ifp, m);
389 return (0);
390}
391
392/**
393 * Handle mbufs on the outgoing hook, frames going to the interface
394 */
395static int ng_vboxnetflt_rcv_out(hook_p hook, item_p item)
396{
397 struct mbuf *m, *m0;
398 struct m_tag *mtag;
399 const node_p node = NG_HOOK_NODE(hook);
400 PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
401 struct ifnet *ifp = pThis->u.s.ifp;
402 unsigned int cSegs = 0;
403 bool fDropIt = false, fActive;
404 PINTNETSG pSG;
405
406 NGI_GET_M(item, m);
407 NG_FREE_ITEM(item);
408
409 fActive = ASMAtomicUoReadBool(&pThis->fActive);
410 if (!fActive)
411 return ether_output_frame(ifp, m);
412
413 vboxNetFltRetain(pThis, true /* fBusy */);
414 /* Pass directly to interface if the packet originated from us */
415 mtag = m_tag_locate(m, MTAG_VBOX, PACKET_TAG_VBOX, NULL);
416 if (mtag != NULL)
417 {
418 m_tag_unlink(m, mtag);
419 m_tag_free(mtag);
420 goto out;
421 }
422
423 for (m0 = m; m0 != NULL; m0 = m0->m_next)
424 {
425 if (m0->m_len > 0)
426 cSegs++;
427 }
428
429#ifdef PADD_RUNT_FRAMES_FROM_HOST
430 if (m_length(m, NULL) < 60)
431 cSegs++;
432#endif
433 /* Create a copy and deliver to the virtual switch */
434 pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
435 vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
436 fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST);
437 RTMemTmpFree(pSG);
438
439out:
440 vboxNetFltRelease(pThis, true /* fBusy */);
441 if (fDropIt)
442 {
443 m_freem(m);
444 return (0);
445 }
446
447 return ether_output_frame(ifp, m);
448}
449
450static int ng_vboxnetflt_shutdown(node_p node)
451{
452 PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
453 bool fActive;
454
455 /* Prevent node shutdown if we're active */
456 fActive = ASMAtomicUoReadBool(&pThis->fActive);
457 if (fActive)
458 return (EBUSY);
459 NG_NODE_UNREF(node);
460 return (0);
461}
462
463static int ng_vboxnetflt_disconnect(hook_p hook)
464{
465 return (0);
466}
467
468/**
469 * Called to deliver a frame to either the host, the wire or both.
470 */
471int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst)
472{
473 void (*input_f)(struct ifnet *, struct mbuf *);
474 struct ifnet *ifp;
475 struct mbuf *m;
476 struct m_tag *mtag;
477 bool fActive;
478 int error;
479
480 ifp = (void *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.ifp);
481
482 if (fDst & INTNETTRUNKDIR_WIRE)
483 {
484 m = vboxNetFltFreeBSDSGMBufFromSG(pThis, pSG);
485 if (m == NULL)
486 return VERR_NO_MEMORY;
487 m = m_pullup(m, ETHER_HDR_LEN);
488 if (m == NULL)
489 return VERR_NO_MEMORY;
490
491 m->m_flags |= M_PKTHDR;
492 ether_output_frame(ifp, m);
493 }
494
495 if (fDst & INTNETTRUNKDIR_HOST)
496 {
497 m = vboxNetFltFreeBSDSGMBufFromSG(pThis, pSG);
498 if (m == NULL)
499 return VERR_NO_MEMORY;
500 m = m_pullup(m, ETHER_HDR_LEN);
501 if (m == NULL)
502 return VERR_NO_MEMORY;
503 /*
504 * Delivering packets to the host will be captured by the
505 * input hook. Tag the packet with a mbuf tag so that we
506 * can skip re-delivery of the packet to the guest during
507 * input hook processing.
508 */
509 mtag = m_tag_alloc(MTAG_VBOX, PACKET_TAG_VBOX, 0, M_NOWAIT);
510 if (mtag == NULL)
511 {
512 m_freem(m);
513 return VERR_NO_MEMORY;
514 }
515
516 m_tag_init(m);
517 m_tag_prepend(m, mtag);
518 m->m_flags |= M_PKTHDR;
519 m->m_pkthdr.rcvif = ifp;
520 ifp->if_input(ifp, m);
521 }
522 return VINF_SUCCESS;
523}
524
525int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
526{
527 char nam[NG_NODESIZ];
528 struct ifnet *ifp;
529 node_p node;
530 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
531
532 NOREF(pvContext);
533 ifp = ifunit(pThis->szName);
534 if (ifp == NULL)
535 return VERR_INTNET_FLT_IF_NOT_FOUND;
536
537 /* Create a new netgraph node for this instance */
538 if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0)
539 return VERR_INTERNAL_ERROR;
540
541 RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
542 ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.ifp, ifp);
543 pThis->u.s.node = node;
544 bcopy(IF_LLADDR(ifp), &pThis->u.s.Mac, ETHER_ADDR_LEN);
545 ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false);
546 RTSpinlockRelease(pThis->hSpinlock, &Tmp);
547
548 NG_NODE_SET_PRIVATE(node, pThis);
549 /* Attempt to name it vboxnetflt_<ifname> */
550 snprintf(nam, NG_NODESIZ, "vboxnetflt_%s", pThis->szName);
551 ng_name_node(node, nam);
552
553 return VINF_SUCCESS;
554}
555
556bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
557{
558 struct ifnet *ifp, *ifp0;
559
560 ifp = (struct ifnet *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.ifp);
561 /*
562 * Attempt to check if the interface is still there and re-initialize if
563 * something has changed.
564 */
565 ifp0 = ifunit(pThis->szName);
566 if (ifp != ifp0)
567 {
568 ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, true);
569 ng_rmnode_self(pThis->u.s.node);
570 pThis->u.s.node = NULL;
571 }
572
573 if (ifp0 != NULL)
574 vboxNetFltOsInitInstance(pThis, NULL);
575
576 return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
577}
578
579void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
580{
581
582 if (pThis->u.s.node != NULL)
583 ng_rmnode_self(pThis->u.s.node);
584 pThis->u.s.node = NULL;
585}
586
587int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
588{
589
590 pThis->u.s.ifp = NULL;
591 pThis->u.s.flags = 0;
592 pThis->u.s.node = NULL;
593 return VINF_SUCCESS;
594}
595
596void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
597{
598 struct ifnet *ifp;
599 struct ifreq ifreq;
600 int error;
601 node_p node;
602 struct ng_mesg *msg;
603 struct ngm_connect *con;
604 struct ngm_rmhook *rm;
605 char path[NG_PATHSIZ];
606
607 Log(("%s: fActive:%d\n", __func__, fActive));
608
609 ifp = (struct ifnet *)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.ifp);
610 node = (node_p)ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.node);
611
612 memset(&ifreq, 0, sizeof(struct ifreq));
613 /* Activate interface */
614 if (fActive)
615 {
616 pThis->u.s.flags = ifp->if_flags;
617 ifpromisc(ifp, 1);
618
619 /* ng_ether nodes are named after the interface name */
620 snprintf(path, sizeof(path), "%s:", ifp->if_xname);
621
622 /*
623 * Send a netgraph connect message to the ng_ether node
624 * assigned to the bridged interface. Connecting
625 * the hooks 'lower' (ng_ether) to out 'input'.
626 */
627 NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
628 sizeof(struct ngm_connect), M_NOWAIT);
629 if (msg == NULL)
630 return;
631 con = (struct ngm_connect *)msg->data;
632 snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:", ifp->if_xname);
633 strlcpy(con->ourhook, "lower", NG_HOOKSIZ);
634 strlcpy(con->peerhook, "input", NG_HOOKSIZ);
635 NG_SEND_MSG_PATH(error, node, msg, path, 0);
636
637 /*
638 * Do the same for the hooks 'upper' (ng_ether) and our
639 * 'output' hook.
640 */
641 NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
642 sizeof(struct ngm_connect), M_NOWAIT);
643 if (msg == NULL)
644 return;
645 con = (struct ngm_connect *)msg->data;
646 snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:",
647 ifp->if_xname);
648 strlcpy(con->ourhook, "upper", sizeof(con->ourhook));
649 strlcpy(con->peerhook, "output", sizeof(con->peerhook));
650 NG_SEND_MSG_PATH(error, node, msg, path, 0);
651 }
652 else
653 {
654 /* De-activate interface */
655 pThis->u.s.flags = 0;
656 ifpromisc(ifp, 0);
657
658 /* Disconnect msgs are addressed to ourself */
659 snprintf(path, sizeof(path), "vboxnetflt_%s:", ifp->if_xname);
660
661 /*
662 * Send a netgraph message to disconnect our 'input' hook
663 */
664 NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
665 sizeof(struct ngm_rmhook), M_NOWAIT);
666 if (msg == NULL)
667 return;
668 rm = (struct ngm_rmhook *)msg->data;
669 strlcpy(rm->ourhook, "input", NG_HOOKSIZ);
670 NG_SEND_MSG_PATH(error, node, msg, path, 0);
671
672 /*
673 * Send a netgraph message to disconnect our 'output' hook
674 */
675 NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
676 sizeof(struct ngm_rmhook), M_NOWAIT);
677 if (msg == NULL)
678 return;
679 rm = (struct ngm_rmhook *)msg->data;
680 strlcpy(rm->ourhook, "output", NG_HOOKSIZ);
681 NG_SEND_MSG_PATH(error, node, msg, path, 0);
682 }
683}
684
685bool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis)
686{
687 return (pThis->u.s.flags & IFF_PROMISC) ? true : false;
688}
689
690void vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac)
691{
692 *pMac = pThis->u.s.Mac;
693}
694
695bool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac)
696{
697 return pThis->u.s.Mac.au16[0] == pMac->au16[0]
698 && pThis->u.s.Mac.au16[1] == pMac->au16[1]
699 && pThis->u.s.Mac.au16[2] == pMac->au16[2];
700}
701
702int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis)
703{
704 return VINF_SUCCESS;
705}
706
707int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis)
708{
709 return VINF_SUCCESS;
710}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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