diff options
Diffstat (limited to 'src/VBox/HostDrivers/VBoxNetAdp/freebsd')
3 files changed, 487 insertions, 0 deletions
diff --git a/src/VBox/HostDrivers/VBoxNetAdp/freebsd/Makefile b/src/VBox/HostDrivers/VBoxNetAdp/freebsd/Makefile new file mode 100644 index 00000000..013a223d --- /dev/null +++ b/src/VBox/HostDrivers/VBoxNetAdp/freebsd/Makefile @@ -0,0 +1,54 @@ +# $Id: Makefile $ +## @file +# Makefile for the VirtualBox FreeBSD Host Driver. +# + +# +# Copyright (C) 2006-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +KMOD = vboxnetadp + +CFLAGS += -DRT_OS_FREEBSD -DIN_RING0 -DIN_RT_R0 -DIN_SUP_R0 -DVBOX -DRT_WITH_VBOX -Iinclude -I. -Ir0drv -w -DVBOX_WITH_HARDENING -DVIMAGE + +.if (${MACHINE_ARCH} == "i386") + CFLAGS += -DRT_ARCH_X86 +.elif (${MACHINE_ARCH} == "amd64") + CFLAGS += -DRT_ARCH_AMD64 +.endif + +SRCS = \ + VBoxNetAdp-freebsd.c \ + VBoxNetAdp.c + +SRCS += device_if.h bus_if.h + +.include <bsd.kmod.mk> + diff --git a/src/VBox/HostDrivers/VBoxNetAdp/freebsd/VBoxNetAdp-freebsd.c b/src/VBox/HostDrivers/VBoxNetAdp/freebsd/VBoxNetAdp-freebsd.c new file mode 100644 index 00000000..db5c0b64 --- /dev/null +++ b/src/VBox/HostDrivers/VBoxNetAdp/freebsd/VBoxNetAdp-freebsd.c @@ -0,0 +1,339 @@ +/* $Id: VBoxNetAdp-freebsd.c $ */ +/** @file + * VBoxNetAdp - Virtual Network Adapter Driver (Host), FreeBSD Specific Code. + */ + +/*- + * Copyright (c) 2009 Fredrik Lindberg <fli@shapeshifter.se> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <sys/param.h> +#undef PVM +#include <sys/types.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/kernel.h> +#include <sys/fcntl.h> +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/socket.h> +#include <sys/sockio.h> + +#include <net/if.h> +#include <net/if_var.h> +#include <net/route.h> +#include <net/if_dl.h> +#include <net/if_media.h> +#include <net/if_types.h> +#include <net/ethernet.h> +#include <net/bpf.h> + +#define LOG_GROUP LOG_GROUP_NET_ADP_DRV +#include <VBox/version.h> +#include <iprt/errcore.h> +#include <VBox/log.h> +#include <iprt/initterm.h> +#include <iprt/string.h> +#include <iprt/spinlock.h> +#include <iprt/process.h> +#include <iprt/assert.h> +#include <iprt/uuid.h> +#include <iprt/alloc.h> +#include <iprt/errcore.h> + +#define VBOXNETADP_OS_SPECFIC 1 +#include "../VBoxNetAdpInternal.h" + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 800500 +# include <sys/jail.h> +# include <net/vnet.h> + +# define VBOXCURVNET_SET(arg) CURVNET_SET_QUIET(arg) +# define VBOXCURVNET_SET_FROM_UCRED() VBOXCURVNET_SET(CRED_TO_VNET(curthread->td_ucred)) +# define VBOXCURVNET_RESTORE() CURVNET_RESTORE() + +#else /* !defined(__FreeBSD_version) || __FreeBSD_version < 800500 */ + +# define VBOXCURVNET_SET(arg) +# define VBOXCURVNET_SET_FROM_UCRED() +# define VBOXCURVNET_RESTORE() + +#endif /* !defined(__FreeBSD_version) || __FreeBSD_version < 800500 */ + +static int VBoxNetAdpFreeBSDCtrlioctl(struct cdev *, u_long, caddr_t, int flags, + struct thread *); +static struct cdevsw vboxnetadp_cdevsw = +{ + .d_version = D_VERSION, + .d_ioctl = VBoxNetAdpFreeBSDCtrlioctl, + .d_read = (d_read_t *)nullop, + .d_write = (d_write_t *)nullop, + .d_name = VBOXNETADP_CTL_DEV_NAME, +}; + +static struct cdev *VBoxNetAdpFreeBSDcdev; + +static int VBoxNetAdpFreeBSDModuleEvent(struct module *, int, void *); +static moduledata_t g_VBoxNetAdpFreeBSDModule = { + "vboxnetadp", + VBoxNetAdpFreeBSDModuleEvent, + NULL +}; + +/** Declare the module as a pseudo device. */ +DECLARE_MODULE(vboxnetadp, g_VBoxNetAdpFreeBSDModule, SI_SUB_PSEUDO, SI_ORDER_ANY); +MODULE_VERSION(vboxnetadp, 1); +MODULE_DEPEND(vboxnetadp, vboxdrv, 1, 1, 1); +MODULE_DEPEND(vboxnetadp, vboxnetflt, 1, 1, 1); + +/** + * Module event handler + */ +static int +VBoxNetAdpFreeBSDModuleEvent(struct module *pMod, int enmEventType, void *pvArg) +{ + int rc = 0; + + Log(("VBoxNetAdpFreeBSDModuleEvent\n")); + + switch (enmEventType) + { + case MOD_LOAD: + rc = RTR0Init(0); + if (RT_FAILURE(rc)) + { + Log(("RTR0Init failed %d\n", rc)); + return RTErrConvertToErrno(rc); + } + rc = vboxNetAdpInit(); + if (RT_FAILURE(rc)) + { + RTR0Term(); + Log(("vboxNetAdpInit failed %d\n", rc)); + return RTErrConvertToErrno(rc); + } + /* Create dev node */ + VBoxNetAdpFreeBSDcdev = make_dev(&vboxnetadp_cdevsw, 0, + UID_ROOT, GID_WHEEL, 0600, VBOXNETADP_CTL_DEV_NAME); + + break; + + case MOD_UNLOAD: + vboxNetAdpShutdown(); + destroy_dev(VBoxNetAdpFreeBSDcdev); + RTR0Term(); + break; + case MOD_SHUTDOWN: + case MOD_QUIESCE: + default: + return EOPNOTSUPP; + } + + if (RT_SUCCESS(rc)) + return 0; + return RTErrConvertToErrno(rc); +} + +/** + * Device I/O Control entry point. + */ +static int +VBoxNetAdpFreeBSDCtrlioctl(struct cdev *dev, u_long iCmd, caddr_t data, int flags, struct thread *td) +{ + PVBOXNETADP pAdp; + PVBOXNETADPREQ pReq = (PVBOXNETADPREQ)data; + struct ifnet *ifp; + int rc; + + switch (iCmd) + { + case VBOXNETADP_CTL_ADD: + if ( !(iCmd & IOC_INOUT) /* paranoia*/ + || IOCPARM_LEN(iCmd) < sizeof(*pReq)) + return EINVAL; + + rc = vboxNetAdpCreate(&pAdp, + pReq->szName[0] && RTStrEnd(pReq->szName, RT_MIN(IOCPARM_LEN(iCmd), sizeof(pReq->szName))) ? + pReq->szName : NULL); + if (RT_FAILURE(rc)) + return EINVAL; + + strncpy(pReq->szName, pAdp->szName, sizeof(pReq->szName) - 1); + pReq->szName[sizeof(pReq->szName) - 1] = '\0'; + break; + + case VBOXNETADP_CTL_REMOVE: + if (!RTStrEnd(pReq->szName, RT_MIN(sizeof(pReq->szName), IOCPARM_LEN(iCmd)))) + return EINVAL; + + pAdp = vboxNetAdpFindByName(pReq->szName); + if (!pAdp) + return EINVAL; + + rc = vboxNetAdpDestroy(pAdp); + if (RT_FAILURE(rc)) + return EINVAL; + + break; + + default: + return EINVAL; + } + return 0; +} + +/** + * Initialize device, just set the running flag. + */ +static void VBoxNetAdpFreeBSDNetinit(void *priv) +{ + PVBOXNETADP pThis = priv; + struct ifnet *ifp = pThis->u.s.ifp; + + ifp->if_drv_flags |= IFF_DRV_RUNNING; +} + +/** + * Transmit packets. + * netflt has already done everything for us so we just hand the + * packets to BPF and increment the packet stats. + */ +static void VBoxNetAdpFreeBSDNetstart(struct ifnet *ifp) +{ + PVBOXNETADP pThis = ifp->if_softc; + struct mbuf *m; + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) + return; + + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + { +#if __FreeBSD_version >= 1100036 + if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); +#else + ifp->if_opackets++; +#endif + IFQ_DRV_DEQUEUE(&ifp->if_snd, m); + BPF_MTAP(ifp, m); + m_freem(m); + } + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; +} + +/** + * Interface ioctl handling + */ +static int VBoxNetAdpFreeBSDNetioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + int error = 0; + + switch (cmd) + { + case SIOCSIFFLAGS: + if (ifp->if_flags & IFF_UP) + { + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) + ifp->if_init(ifp->if_softc); + } + else + { + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + } + break; + case SIOCGIFMEDIA: + { + struct ifmediareq *ifmr; + int count; + + ifmr = (struct ifmediareq *)data; + count = ifmr->ifm_count; + ifmr->ifm_count = 1; + ifmr->ifm_status = IFM_AVALID; + ifmr->ifm_active = IFM_ETHER; + ifmr->ifm_status |= IFM_ACTIVE; + ifmr->ifm_current = ifmr->ifm_active; + if (count >= 1) + { + int media = IFM_ETHER; + error = copyout(&media, ifmr->ifm_ulist, sizeof(int)); + } + break; + } + default: + return ether_ioctl(ifp, cmd, data); + } + return error; +} + +int vboxNetAdpOsInit(PVBOXNETADP pThis) +{ + pThis->u.s.ifp = NULL; + return VINF_SUCCESS;; +} + +int vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMac) +{ + struct ifnet *ifp; + + VBOXCURVNET_SET_FROM_UCRED(); + ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) + return VERR_NO_MEMORY; + + if_initname(ifp, VBOXNETADP_NAME, pThis->iUnit); + ifp->if_softc = pThis; + ifp->if_mtu = ETHERMTU; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = VBoxNetAdpFreeBSDNetioctl; + ifp->if_start = VBoxNetAdpFreeBSDNetstart; + ifp->if_init = VBoxNetAdpFreeBSDNetinit; + IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_READY(&ifp->if_snd); + ether_ifattach(ifp, (void *)pMac); + ifp->if_baudrate = 0; + + strncpy(pThis->szName, ifp->if_xname, VBOXNETADP_MAX_NAME_LEN); + pThis->u.s.ifp = ifp; + VBOXCURVNET_RESTORE(); + return 0; +} + +void vboxNetAdpOsDestroy(PVBOXNETADP pThis) +{ + struct ifnet *ifp; + + ifp = pThis->u.s.ifp; + VBOXCURVNET_SET(ifp->if_vnet); + ether_ifdetach(ifp); + if_free(ifp); + VBOXCURVNET_RESTORE(); +} diff --git a/src/VBox/HostDrivers/VBoxNetAdp/freebsd/files_vboxnetadp b/src/VBox/HostDrivers/VBoxNetAdp/freebsd/files_vboxnetadp new file mode 100755 index 00000000..d90ced7b --- /dev/null +++ b/src/VBox/HostDrivers/VBoxNetAdp/freebsd/files_vboxnetadp @@ -0,0 +1,94 @@ +#!/bin/sh +# $Id: files_vboxnetadp $ +## @file +# Shared file between Makefile.kmk and export_modules.sh. +# + +# +# Copyright (C) 2007-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + + +VBOX_VBOXNETADP_SOURCES=" \ + ${PATH_ROOT}/include/iprt/alloc.h=>include/iprt/alloc.h \ + ${PATH_ROOT}/include/iprt/alloca.h=>include/iprt/alloca.h \ + ${PATH_ROOT}/include/iprt/asm.h=>include/iprt/asm.h \ + ${PATH_ROOT}/include/iprt/asm-amd64-x86.h=>include/iprt/asm-amd64-x86.h \ + ${PATH_ROOT}/include/iprt/asm-math.h=>include/iprt/asm-math.h \ + ${PATH_ROOT}/include/iprt/assert.h=>include/iprt/assert.h \ + ${PATH_ROOT}/include/iprt/assertcompile.h=>include/iprt/assertcompile.h \ + ${PATH_ROOT}/include/iprt/avl.h=>include/iprt/avl.h \ + ${PATH_ROOT}/include/iprt/cdefs.h=>include/iprt/cdefs.h \ + ${PATH_ROOT}/include/iprt/cpuset.h=>include/iprt/cpuset.h \ + ${PATH_ROOT}/include/iprt/ctype.h=>include/iprt/ctype.h \ + ${PATH_ROOT}/include/iprt/err.h=>include/iprt/err.h \ + ${PATH_ROOT}/include/iprt/errcore.h=>include/iprt/errcore.h \ + ${PATH_ROOT}/include/iprt/heap.h=>include/iprt/heap.h \ + ${PATH_ROOT}/include/iprt/initterm.h=>include/iprt/initterm.h \ + ${PATH_ROOT}/include/iprt/latin1.h=>include/iprt/latin1.h \ + ${PATH_ROOT}/include/iprt/log.h=>include/iprt/log.h \ + ${PATH_ROOT}/include/iprt/mangling.h=>include/iprt/mangling.h \ + ${PATH_ROOT}/include/iprt/mem.h=>include/iprt/mem.h \ + ${PATH_ROOT}/include/iprt/memobj.h=>include/iprt/memobj.h \ + ${PATH_ROOT}/include/iprt/mp.h=>include/iprt/mp.h \ + ${PATH_ROOT}/include/iprt/param.h=>include/iprt/param.h \ + ${PATH_ROOT}/include/iprt/power.h=>include/iprt/power.h \ + ${PATH_ROOT}/include/iprt/process.h=>include/iprt/process.h \ + ${PATH_ROOT}/include/iprt/semaphore.h=>include/iprt/semaphore.h \ + ${PATH_ROOT}/include/iprt/spinlock.h=>include/iprt/spinlock.h \ + ${PATH_ROOT}/include/iprt/stdarg.h=>include/iprt/stdarg.h \ + ${PATH_ROOT}/include/iprt/stdint.h=>include/iprt/stdint.h \ + ${PATH_ROOT}/include/iprt/string.h=>include/iprt/string.h \ + ${PATH_ROOT}/include/iprt/thread.h=>include/iprt/thread.h \ + ${PATH_ROOT}/include/iprt/time.h=>include/iprt/time.h \ + ${PATH_ROOT}/include/iprt/timer.h=>include/iprt/timer.h \ + ${PATH_ROOT}/include/iprt/types.h=>include/iprt/types.h \ + ${PATH_ROOT}/include/iprt/uni.h=>include/iprt/uni.h \ + ${PATH_ROOT}/include/iprt/utf16.h=>include/iprt/utf16.h \ + ${PATH_ROOT}/include/iprt/uuid.h=>include/iprt/uuid.h \ + ${PATH_ROOT}/include/iprt/x86-helpers.h=>include/iprt/x86-helpers.h \ + ${PATH_ROOT}/include/iprt/nocrt/limits.h=>include/iprt/nocrt/limits.h \ + ${PATH_ROOT}/include/VBox/cdefs.h=>include/VBox/cdefs.h \ + ${PATH_ROOT}/include/VBox/err.h=>include/VBox/err.h \ + ${PATH_ROOT}/include/VBox/log.h=>include/VBox/log.h \ + ${PATH_ROOT}/include/VBox/intnet.h=>include/VBox/intnet.h \ + ${PATH_ROOT}/include/VBox/vmm/stam.h=>include/VBox/vmm/stam.h \ + ${PATH_ROOT}/include/VBox/sup.h=>include/VBox/sup.h \ + ${PATH_ROOT}/include/VBox/types.h=>include/VBox/types.h \ + ${PATH_ROOT}/include/VBox/version.h=>include/VBox/version.h \ + ${PATH_ROOT}/include/VBox/SUPDrvMangling.h=>include/VBox/SUPDrvMangling.h \ + ${PATH_ROOT}/src/VBox/HostDrivers/VBoxNetAdp/freebsd/VBoxNetAdp-freebsd.c=>VBoxNetAdp-freebsd.c \ + ${PATH_ROOT}/src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdp.c=>VBoxNetAdp.c \ + ${PATH_ROOT}/src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdpInternal.h=>VBoxNetAdpInternal.h \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/freebsd/the-freebsd-kernel.h=>r0drv/freebsd/the-freebsd-kernel.h \ + ${PATH_OUT}/version-generated.h=>version-generated.h \ + ${PATH_OUT}/product-generated.h=>product-generated.h \ +" + |