ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/* $Id$ */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/** @file
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * VBoxNetFlt - Network Filter Driver (Host), FreeBSD Specific Code.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Copyright (c) 2009 Fredrik Lindberg <fli@shapeshifter.se>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync *
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Permission is hereby granted, free of charge, to any person
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * obtaining a copy of this software and associated documentation
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * files (the "Software"), to deal in the Software without
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * restriction, including without limitation the rights to use,
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * copy, modify, merge, publish, distribute, sublicense, and/or sell
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * copies of the Software, and to permit persons to whom the
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Software is furnished to do so, subject to the following
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * conditions:
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync *
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * The above copyright notice and this permission notice shall be
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * included in all copies or substantial portions of the Software.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync *
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * OTHER DEALINGS IN THE SOFTWARE.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/*******************************************************************************
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync* Header Files *
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync*******************************************************************************/
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/param.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#undef PVM
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/types.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/module.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/systm.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/errno.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/kernel.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/fcntl.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/conf.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/socket.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/sockio.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <sys/syscallsubr.h>
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync#include <sys/queue.h>
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync#include <sys/taskqueue.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <net/if.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <net/if_var.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <net/if_dl.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <net/if_types.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <net/ethernet.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <netgraph/ng_message.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <netgraph/netgraph.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <netgraph/ng_parse.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <VBox/version.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <VBox/err.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <VBox/log.h>
6dd8f5023a9ba7588212331db90059553136fe33vboxsync#include <VBox/intnetinline.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <iprt/initterm.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <iprt/string.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <iprt/spinlock.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <iprt/process.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <iprt/assert.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <iprt/uuid.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <iprt/alloc.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include <iprt/err.h>
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#define VBOXNETFLT_OS_SPECFIC 1
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#include "../VBoxNetFltInternal.h"
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic int vboxnetflt_modevent(struct module *, int, void *);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic ng_constructor_t ng_vboxnetflt_constructor;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic ng_rcvmsg_t ng_vboxnetflt_rcvmsg;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic ng_shutdown_t ng_vboxnetflt_shutdown;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic ng_newhook_t ng_vboxnetflt_newhook;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic ng_rcvdata_t ng_vboxnetflt_rcvdata;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic ng_disconnect_t ng_vboxnetflt_disconnect;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic int ng_vboxnetflt_mod_event(module_t mod, int event, void *data);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/** Netgraph node type */
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync#define NG_VBOXNETFLT_NODE_TYPE "vboxnetflt"
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/** Netgraph message cookie */
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync#define NGM_VBOXNETFLT_COOKIE 0x56424f58
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/** Input netgraph hook name */
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync#define NG_VBOXNETFLT_HOOK_IN "input"
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/** Output netgraph hook name */
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync#define NG_VBOXNETFLT_HOOK_OUT "output"
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/** mbuf tag identifier */
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync#define MTAG_VBOX 0x56424f58
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/** mbuf packet tag */
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync#define PACKET_TAG_VBOX 128
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync#if defined(__FreeBSD_version) && __FreeBSD_version >= 800500
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync# include <sys/jail.h>
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync# include <net/vnet.h>
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync# define VBOXCURVNET_SET(arg) CURVNET_SET_QUIET(arg)
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync# define VBOXCURVNET_SET_FROM_UCRED() VBOXCURVNET_SET(CRED_TO_VNET(curthread->td_ucred))
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync# define VBOXCURVNET_RESTORE() CURVNET_RESTORE()
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync#else /* !defined(__FreeBSD_version) || __FreeBSD_version < 800500 */
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync# define VBOXCURVNET_SET(arg)
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync# define VBOXCURVNET_SET_FROM_UCRED()
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync# define VBOXCURVNET_RESTORE()
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync#endif /* !defined(__FreeBSD_version) || __FreeBSD_version < 800500 */
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Netgraph command list, we don't support any
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * additional commands.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic const struct ng_cmdlist ng_vboxnetflt_cmdlist[] =
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync { 0 }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync};
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Netgraph type definition
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic struct ng_type ng_vboxnetflt_typestruct =
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .version = NG_ABI_VERSION,
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .name = NG_VBOXNETFLT_NODE_TYPE,
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .mod_event = vboxnetflt_modevent,
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .constructor= ng_vboxnetflt_constructor,
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .rcvmsg = ng_vboxnetflt_rcvmsg,
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .shutdown = ng_vboxnetflt_shutdown,
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .newhook = ng_vboxnetflt_newhook,
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .rcvdata = ng_vboxnetflt_rcvdata,
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .disconnect = ng_vboxnetflt_disconnect,
b0a3d0ec5780199a2f379da63c59ccf48f1a73b9vboxsync .cmdlist = ng_vboxnetflt_cmdlist,
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync};
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncNETGRAPH_INIT(vboxnetflt, &ng_vboxnetflt_typestruct);
545f5817b4bf7085bafbc6e5186faa7cabef5102vboxsync
545f5817b4bf7085bafbc6e5186faa7cabef5102vboxsync/*
545f5817b4bf7085bafbc6e5186faa7cabef5102vboxsync * Use vboxnetflt because the kernel module is named vboxnetflt and vboxnetadp
545f5817b4bf7085bafbc6e5186faa7cabef5102vboxsync * depends on this when loading dependencies.
545f5817b4bf7085bafbc6e5186faa7cabef5102vboxsync * NETGRAP_INIT will prefix the given name with ng_ so MODULE_DEPEND needs the
545f5817b4bf7085bafbc6e5186faa7cabef5102vboxsync * prefixed name.
545f5817b4bf7085bafbc6e5186faa7cabef5102vboxsync */
545f5817b4bf7085bafbc6e5186faa7cabef5102vboxsyncMODULE_VERSION(vboxnetflt, 1);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncMODULE_DEPEND(ng_vboxnetflt, vboxdrv, 1, 1, 1);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/**
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * The (common) global data.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic VBOXNETFLTGLOBALS g_VBoxNetFltGlobals;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/**
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Module event handler, called from netgraph subsystem.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic int vboxnetflt_modevent(struct module *pMod, int enmEventType, void *pvArg)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync int rc;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync Log(("VBoxNetFltFreeBSDModuleEvent\n"));
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync switch (enmEventType)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync case MOD_LOAD:
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync rc = RTR0Init(0);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (RT_FAILURE(rc))
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
c366016ffe1788c6847d0a967a954713725cab5evboxsync printf("RTR0Init failed %d\n", rc);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return RTErrConvertToErrno(rc);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync memset(&g_VBoxNetFltGlobals, 0, sizeof(VBOXNETFLTGLOBALS));
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync rc = vboxNetFltInitGlobalsAndIdc(&g_VBoxNetFltGlobals);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (RT_FAILURE(rc))
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
c366016ffe1788c6847d0a967a954713725cab5evboxsync printf("vboxNetFltInitGlobalsAndIdc failed %d\n", rc);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return RTErrConvertToErrno(rc);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /* No MODULE_VERSION in ng_ether so we can't MODULE_DEPEND it */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync kern_kldload(curthread, "ng_ether", NULL);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync break;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync case MOD_UNLOAD:
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync rc = vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltGlobals);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync memset(&g_VBoxNetFltGlobals, 0, sizeof(VBOXNETFLTGLOBALS));
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync RTR0Term();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync break;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync case MOD_SHUTDOWN:
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync case MOD_QUIESCE:
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync default:
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return EOPNOTSUPP;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (RT_SUCCESS(rc))
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return 0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return RTErrConvertToErrno(rc);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Convert from mbufs to vbox scatter-gather data structure
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic void vboxNetFltFreeBSDMBufToSG(PVBOXNETFLTINS pThis, struct mbuf *m, PINTNETSG pSG,
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync unsigned int cSegs, unsigned int segOffset)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync static uint8_t const s_abZero[128] = {0};
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync unsigned int i;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct mbuf *m0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
9127c416edfd6f9266e387f7abd7aa9904eecbc9vboxsync IntNetSgInitTempSegs(pSG, m_length(m, NULL), cSegs, 0 /*cSegsUsed*/);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync for (m0 = m, i = segOffset; m0; m0 = m0->m_next)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (m0->m_len == 0)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync continue;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pSG->aSegs[i].cb = m0->m_len;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pSG->aSegs[i].pv = mtod(m0, uint8_t *);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pSG->aSegs[i].Phys = NIL_RTHCPHYS;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync i++;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#ifdef PADD_RUNT_FRAMES_FROM_HOST
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (pSG->cbTotal < 60)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pSG->aSegs[i].Phys = NIL_RTHCPHYS;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pSG->aSegs[i].pv = (void *)&s_abZero[0];
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pSG->aSegs[i].cb = 60 - pSG->cbTotal;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pSG->cbTotal = 60;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync i++;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#endif
6dd8f5023a9ba7588212331db90059553136fe33vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pSG->cSegsUsed = i;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Convert to mbufs from vbox scatter-gather data structure
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic struct mbuf * vboxNetFltFreeBSDSGMBufFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct mbuf *m;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync int error;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync unsigned int i;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
108e1eed4a717344ddcec74bcae3ea793fda4724vboxsync if (pSG->cbTotal == 0)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (NULL);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (m == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (NULL);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m->m_pkthdr.len = m->m_len = 0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m->m_pkthdr.rcvif = NULL;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync for (i = 0; i < pSG->cSegsUsed; i++)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync error = m_append(m, pSG->aSegs[i].cb, pSG->aSegs[i].pv);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (error == 0)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m_freem(m);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (NULL);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (m);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic int ng_vboxnetflt_constructor(node_p node)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /* Nothing to do */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (EINVAL);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Setup netgraph hooks
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic int ng_vboxnetflt_newhook(node_p node, hook_p hook, const char *name)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (strcmp(name, NG_VBOXNETFLT_HOOK_IN) == 0)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#if __FreeBSD_version >= 800000
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_HOOK_SET_TO_INBOUND(hook);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#endif
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.input = hook;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync else if (strcmp(name, NG_VBOXNETFLT_HOOK_OUT) == 0)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.output = hook;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync else
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (EINVAL);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_HOOK_HI_STACK(hook);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (0);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/**
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Netgraph message processing for node specific messages.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * We don't accept any special messages so this is not used.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic int ng_vboxnetflt_rcvmsg(node_p node, item_p item, hook_p lasthook)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ng_mesg *msg;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync int error = 0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NGI_GET_MSG(item, msg);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (msg->header.typecookie != NGM_VBOXNETFLT_COOKIE)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (EINVAL);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync switch (msg->header.cmd)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync default:
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync error = EINVAL;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (error);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/**
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Handle data on netgraph hooks.
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync * Frames processing is deferred to a taskqueue because this might
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync * be called with non-sleepable locks held and code paths inside
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync * the virtual switch might sleep.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncstatic int ng_vboxnetflt_rcvdata(hook_p hook, item_p item)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync const node_p node = NG_HOOK_NODE(hook);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync struct ifnet *ifp = pThis->u.s.ifp;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct mbuf *m;
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync struct m_tag *mtag;
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync bool fActive;
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_SET(ifp->if_vnet);
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync fActive = vboxNetFltTryRetainBusyActive(pThis);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync NGI_GET_M(item, m);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync NG_FREE_ITEM(item);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync /* Locate tag to see if processing should be skipped for this frame */
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtag = m_tag_locate(m, MTAG_VBOX, PACKET_TAG_VBOX, NULL);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (mtag != NULL)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync {
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync m_tag_unlink(m, mtag);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync m_tag_free(mtag);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync }
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync /*
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync * Handle incoming hook. This is connected to the
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync * input path of the interface, thus handling incoming frames.
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (pThis->u.s.input == hook)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync {
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (mtag != NULL || !fActive)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync {
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync ether_demux(ifp, m);
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync if (fActive)
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync vboxNetFltRelease(pThis, true /*fBusy*/);
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_RESTORE();
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync return (0);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync }
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_lock_spin(&pThis->u.s.inq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync _IF_ENQUEUE(&pThis->u.s.inq, m);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_unlock_spin(&pThis->u.s.inq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync taskqueue_enqueue_fast(taskqueue_fast, &pThis->u.s.tskin);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync }
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync /*
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync * Handle mbufs on the outgoing hook, frames going to the interface
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync else if (pThis->u.s.output == hook)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync {
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (mtag != NULL || !fActive)
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync {
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync int rc = ether_output_frame(ifp, m);
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync if (fActive)
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync vboxNetFltRelease(pThis, true /*fBusy*/);
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_RESTORE();
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync return rc;
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync }
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_lock_spin(&pThis->u.s.outq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync _IF_ENQUEUE(&pThis->u.s.outq, m);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_unlock_spin(&pThis->u.s.outq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync taskqueue_enqueue_fast(taskqueue_fast, &pThis->u.s.tskout);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync else
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync m_freem(m);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync if (fActive)
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync vboxNetFltRelease(pThis, true /*fBusy*/);
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_RESTORE();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return (0);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsyncstatic int ng_vboxnetflt_shutdown(node_p node)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync{
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync bool fActive;
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync /* Prevent node shutdown if we're active */
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync if (pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync return (EBUSY);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync NG_NODE_UNREF(node);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync return (0);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync}
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsyncstatic int ng_vboxnetflt_disconnect(hook_p hook)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync{
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync return (0);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync}
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/**
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync * Input processing task, handles incoming frames
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsyncstatic void vboxNetFltFreeBSDinput(void *arg, int pending)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct mbuf *m, *m0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ifnet *ifp = pThis->u.s.ifp;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync unsigned int cSegs = 0;
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync bool fDropIt = false, fActive;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync PINTNETSG pSG;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_SET(ifp->if_vnet);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync vboxNetFltRetain(pThis, true /* fBusy */);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync for (;;)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_lock_spin(&pThis->u.s.inq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync _IF_DEQUEUE(&pThis->u.s.inq, m);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_unlock_spin(&pThis->u.s.inq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (m == NULL)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync break;
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync for (m0 = m; m0 != NULL; m0 = m0->m_next)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (m0->m_len > 0)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync cSegs++;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#ifdef PADD_RUNT_FRAMES_FROM_HOST
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (m_length(m, NULL) < 60)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync cSegs++;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#endif
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync /* Create a copy and deliver to the virtual switch */
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, NULL /* pvIf */, pSG, INTNETTRUNKDIR_WIRE);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync RTMemTmpFree(pSG);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (fDropIt)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync m_freem(m);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync else
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync ether_demux(ifp, m);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync vboxNetFltRelease(pThis, true /* fBusy */);
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_RESTORE();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/**
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync * Output processing task, handles outgoing frames
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsyncstatic void vboxNetFltFreeBSDoutput(void *arg, int pending)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct mbuf *m, *m0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ifnet *ifp = pThis->u.s.ifp;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync unsigned int cSegs = 0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync bool fDropIt = false, fActive;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync PINTNETSG pSG;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_SET(ifp->if_vnet);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync vboxNetFltRetain(pThis, true /* fBusy */);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync for (;;)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_lock_spin(&pThis->u.s.outq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync _IF_DEQUEUE(&pThis->u.s.outq, m);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_unlock_spin(&pThis->u.s.outq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (m == NULL)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync break;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync for (m0 = m; m0 != NULL; m0 = m0->m_next)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (m0->m_len > 0)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync cSegs++;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#ifdef PADD_RUNT_FRAMES_FROM_HOST
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (m_length(m, NULL) < 60)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync cSegs++;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync#endif
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync /* Create a copy and deliver to the virtual switch */
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
0c05664313a83177e156d6deb64c656fbc26608dvboxsync fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, NULL /* pvIf */, pSG, INTNETTRUNKDIR_HOST);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync RTMemTmpFree(pSG);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync if (fDropIt)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync m_freem(m);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync else
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync ether_output_frame(ifp, m);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync vboxNetFltRelease(pThis, true /* fBusy */);
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_RESTORE();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync/**
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Called to deliver a frame to either the host, the wire or both.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsyncint vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync NOREF(pvIfData);
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync void (*input_f)(struct ifnet *, struct mbuf *);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ifnet *ifp;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct mbuf *m;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct m_tag *mtag;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync bool fActive;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync int error;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
c7ff622115966b69b482bd2896662e40d823b22fvboxsync ifp = ASMAtomicUoReadPtrT(&pThis->u.s.ifp, struct ifnet *);
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_SET(ifp->if_vnet);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (fDst & INTNETTRUNKDIR_WIRE)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m = vboxNetFltFreeBSDSGMBufFromSG(pThis, pSG);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (m == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VERR_NO_MEMORY;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m = m_pullup(m, ETHER_HDR_LEN);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (m == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VERR_NO_MEMORY;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m->m_flags |= M_PKTHDR;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ether_output_frame(ifp, m);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (fDst & INTNETTRUNKDIR_HOST)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m = vboxNetFltFreeBSDSGMBufFromSG(pThis, pSG);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (m == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VERR_NO_MEMORY;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m = m_pullup(m, ETHER_HDR_LEN);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (m == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VERR_NO_MEMORY;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Delivering packets to the host will be captured by the
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * input hook. Tag the packet with a mbuf tag so that we
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * can skip re-delivery of the packet to the guest during
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * input hook processing.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync mtag = m_tag_alloc(MTAG_VBOX, PACKET_TAG_VBOX, 0, M_NOWAIT);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (mtag == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m_freem(m);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VERR_NO_MEMORY;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m_tag_init(m);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m_tag_prepend(m, mtag);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m->m_flags |= M_PKTHDR;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync m->m_pkthdr.rcvif = ifp;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ifp->if_input(ifp, m);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_RESTORE();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VINF_SUCCESS;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsyncstatic bool vboxNetFltFreeBsdIsPromiscuous(PVBOXNETFLTINS pThis)
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync{
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync /** @todo This isn't taking into account that we put the interface in
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync * promiscuous mode. */
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync return (pThis->u.s.flags & IFF_PROMISC) ? true : false;
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync}
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncint vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync char nam[NG_NODESIZ];
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ifnet *ifp;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync node_p node;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_SET_FROM_UCRED();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NOREF(pvContext);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ifp = ifunit(pThis->szName);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (ifp == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VERR_INTNET_FLT_IF_NOT_FOUND;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /* Create a new netgraph node for this instance */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync return VERR_INTERNAL_ERROR;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync
c7ff622115966b69b482bd2896662e40d823b22fvboxsync ASMAtomicUoWritePtr(&pThis->u.s.ifp, ifp);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.node = node;
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync bcopy(IF_LLADDR(ifp), &pThis->u.s.MacAddr, ETHER_ADDR_LEN);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false);
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync /* Initialize deferred input queue */
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync bzero(&pThis->u.s.inq, sizeof(struct ifqueue));
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_init(&pThis->u.s.inq.ifq_mtx, "vboxnetflt inq", NULL, MTX_SPIN);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync TASK_INIT(&pThis->u.s.tskin, 0, vboxNetFltFreeBSDinput, pThis);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync /* Initialize deferred output queue */
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync bzero(&pThis->u.s.outq, sizeof(struct ifqueue));
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_init(&pThis->u.s.outq.ifq_mtx, "vboxnetflt outq", NULL, MTX_SPIN);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync TASK_INIT(&pThis->u.s.tskout, 0, vboxNetFltFreeBSDoutput, pThis);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync RTSpinlockRelease(pThis->hSpinlock);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_NODE_SET_PRIVATE(node, pThis);
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /* Attempt to name it vboxnetflt_<ifname> */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync snprintf(nam, NG_NODESIZ, "vboxnetflt_%s", pThis->szName);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ng_name_node(node, nam);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync /* Report MAC address, promiscuous mode and GSO capabilities. */
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync /** @todo keep these reports up to date, either by polling for changes or
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync * intercept some control flow if possible. */
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync if (vboxNetFltTryRetainBusyNotDisconnected(pThis))
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync {
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync Assert(pThis->pSwitchPort);
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr);
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltFreeBsdIsPromiscuous(pThis));
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST);
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */);
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync vboxNetFltRelease(pThis, true /*fBusy*/);
d61e6f5b11d9031623420bd7ed3013477d8f402dvboxsync }
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_RESTORE();
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VINF_SUCCESS;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncbool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ifnet *ifp, *ifp0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
c7ff622115966b69b482bd2896662e40d823b22fvboxsync ifp = ASMAtomicUoReadPtrT(&pThis->u.s.ifp, struct ifnet *);
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_SET(ifp->if_vnet);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Attempt to check if the interface is still there and re-initialize if
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * something has changed.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ifp0 = ifunit(pThis->szName);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (ifp != ifp0)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, true);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ng_rmnode_self(pThis->u.s.node);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.node = NULL;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
14a377d3ca792413ba2e6a8485a8b132d2b75a1cvboxsync VBOXCURVNET_RESTORE();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (ifp0 != NULL)
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync {
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync vboxNetFltOsDeleteInstance(pThis);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync vboxNetFltOsInitInstance(pThis, NULL);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncvoid vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync taskqueue_drain(taskqueue_fast, &pThis->u.s.tskin);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync taskqueue_drain(taskqueue_fast, &pThis->u.s.tskout);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_destroy(&pThis->u.s.inq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync mtx_destroy(&pThis->u.s.outq.ifq_mtx);
e54b16ce4a8dbf2ade96b5d4c9e59ccea044c817vboxsync
14a377d3ca792413ba2e6a8485a8b132d2b75a1cvboxsync VBOXCURVNET_SET_FROM_UCRED();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (pThis->u.s.node != NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ng_rmnode_self(pThis->u.s.node);
14a377d3ca792413ba2e6a8485a8b132d2b75a1cvboxsync VBOXCURVNET_RESTORE();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.node = NULL;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncint vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.ifp = NULL;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.flags = 0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.node = NULL;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VINF_SUCCESS;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncvoid vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ifnet *ifp;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ifreq ifreq;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync int error;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync node_p node;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ng_mesg *msg;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ngm_connect *con;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync struct ngm_rmhook *rm;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync char path[NG_PATHSIZ];
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync Log(("%s: fActive:%d\n", __func__, fActive));
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
c7ff622115966b69b482bd2896662e40d823b22fvboxsync ifp = ASMAtomicUoReadPtrT(&pThis->u.s.ifp, struct ifnet *);
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_SET(ifp->if_vnet);
c7ff622115966b69b482bd2896662e40d823b22fvboxsync node = ASMAtomicUoReadPtrT(&pThis->u.s.node, node_p);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync memset(&ifreq, 0, sizeof(struct ifreq));
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /* Activate interface */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (fActive)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.flags = ifp->if_flags;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ifpromisc(ifp, 1);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /* ng_ether nodes are named after the interface name */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync snprintf(path, sizeof(path), "%s:", ifp->if_xname);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Send a netgraph connect message to the ng_ether node
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * assigned to the bridged interface. Connecting
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * the hooks 'lower' (ng_ether) to out 'input'.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync sizeof(struct ngm_connect), M_NOWAIT);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (msg == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync con = (struct ngm_connect *)msg->data;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:", ifp->if_xname);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync strlcpy(con->ourhook, "lower", NG_HOOKSIZ);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync strlcpy(con->peerhook, "input", NG_HOOKSIZ);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_SEND_MSG_PATH(error, node, msg, path, 0);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Do the same for the hooks 'upper' (ng_ether) and our
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * 'output' hook.
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_CONNECT,
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync sizeof(struct ngm_connect), M_NOWAIT);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (msg == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync con = (struct ngm_connect *)msg->data;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync snprintf(con->path, NG_PATHSIZ, "vboxnetflt_%s:",
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ifp->if_xname);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync strlcpy(con->ourhook, "upper", sizeof(con->ourhook));
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync strlcpy(con->peerhook, "output", sizeof(con->peerhook));
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_SEND_MSG_PATH(error, node, msg, path, 0);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync else
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync {
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /* De-activate interface */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync pThis->u.s.flags = 0;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync ifpromisc(ifp, 0);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /* Disconnect msgs are addressed to ourself */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync snprintf(path, sizeof(path), "vboxnetflt_%s:", ifp->if_xname);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Send a netgraph message to disconnect our 'input' hook
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync sizeof(struct ngm_rmhook), M_NOWAIT);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (msg == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync rm = (struct ngm_rmhook *)msg->data;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync strlcpy(rm->ourhook, "input", NG_HOOKSIZ);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_SEND_MSG_PATH(error, node, msg, path, 0);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync /*
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync * Send a netgraph message to disconnect our 'output' hook
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync */
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_RMHOOK,
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync sizeof(struct ngm_rmhook), M_NOWAIT);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync if (msg == NULL)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync rm = (struct ngm_rmhook *)msg->data;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync strlcpy(rm->ourhook, "output", NG_HOOKSIZ);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync NG_SEND_MSG_PATH(error, node, msg, path, 0);
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync }
8d73b12275cff467e9a44e417d5bb7a5b7218bfevboxsync VBOXCURVNET_RESTORE();
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncint vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VINF_SUCCESS;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsyncint vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis)
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync{
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync return VINF_SUCCESS;
ba287763fb250c9244e7a7afc1abff9387b94e43vboxsync}
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsyncvoid vboxNetFltPortOsNotifyMacAddress(PVBOXNETFLTINS pThis, void *pvIfData, PCRTMAC pMac)
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync{
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync NOREF(pThis); NOREF(pvIfData); NOREF(pMac);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync}
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsyncint vboxNetFltPortOsConnectInterface(PVBOXNETFLTINS pThis, void *pvIf, void **ppvIfData)
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync{
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync /* Nothing to do */
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync NOREF(pThis); NOREF(pvIf); NOREF(ppvIfData);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync return VINF_SUCCESS;
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync}
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsyncint vboxNetFltPortOsDisconnectInterface(PVBOXNETFLTINS pThis, void *pvIfData)
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync{
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync /* Nothing to do */
586cf6585d0e6aa3bef888eeff116bf82d18cd83vboxsync NOREF(pThis); NOREF(pvIfData);
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync return VINF_SUCCESS;
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync}
69c51855f3b700d7b26a81f1d7dfed523097b7e2vboxsync