VBoxNetFlt-solaris.c revision 5479e8692221a59f5ce441db9fe494c6c62601f2
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/* $Id$ */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/** @file
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * VBoxNetFlt - Network Filter Driver (Host), Solaris Specific Code.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/*
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * available from http://www.virtualbox.org. This file is free software;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * General Public License (GPL) as published by the Free Software
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * additional information or have any questions.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/*******************************************************************************
a299266cddc1ae14d76d725a660bb278816bc151vboxsync* Header Files *
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync*******************************************************************************/
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#if defined(DEBUG_ramshankar) && !defined(LOG_ENABLED)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync# define LOG_ENABLED
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#endif
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#include <VBox/log.h>
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#include <VBox/err.h>
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#include <VBox/cdefs.h>
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync#include <VBox/version.h>
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#include <iprt/string.h>
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#include <iprt/initterm.h>
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#include <iprt/assert.h>
54dc8e6c81a07ae54c66e27f210609f2ff529760vboxsync#include <iprt/alloca.h>
739c9e0e5fccb99475b8202ead8fc5665b2fa64cvboxsync#include <iprt/net.h>
e99772f9bf09219c532812c859fbeea513c67e65vboxsync#include <iprt/mem.h>
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#include <iprt/thread.h>
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#include <iprt/spinlock.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <iprt/crc32.h>
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#include <iprt/err.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <inet/ip.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <net/if.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/socket.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/kstr.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/file.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/sockio.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/strsubr.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/pathname.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/t_kuser.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/types.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/dlpi.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/types.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#ifdef VBOX_WITH_NETFLT_SOLARIS_DLPISTYLE2
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync# include <sys/time.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#endif
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/param.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/ethernet.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/stat.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/stream.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/stropts.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/strsun.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/modctl.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/ddi.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/sunddi.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#include <sys/sunldi.h>
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Experimental: Using netinfo interfaces and queuing out packets.
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync * This is for playing better with IPFilter.
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync#undef VBOXNETFLT_SOLARIS_USE_NETINFO
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync#ifdef VBOXNETFLT_SOLARIS_USE_NETINFO
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync# include <sys/neti.h>
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync#endif
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync// Workaround for very strange define in sys/user.h
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync// #define u (curproc->p_user) /* user is now part of proc structure */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync#ifdef u
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#undef u
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync#endif
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync#define VBOXNETFLT_OS_SPECFIC 1
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync#include "../VBoxNetFltInternal.h"
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/*******************************************************************************
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync* Defined Constants And Macros *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync*******************************************************************************/
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#define VBOXSOLQUOTE2(x) #x
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#define VBOXSOLQUOTE(x) VBOXSOLQUOTE2(x)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/** The module name. */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#define DEVICE_NAME "vboxflt"
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/** The module descriptions as seen in 'modinfo'. */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#define DEVICE_DESC_DRV "VirtualBox NetDrv"
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#define DEVICE_DESC_MOD "VirtualBox NetMod"
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#ifdef VBOX_WITH_NETFLT_SOLARIS_DLPISTYLE2
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync# define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#endif
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/** @todo Remove the below hackery once done! */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#if defined(DEBUG_ramshankar) && defined(LOG_ENABLED)
54dc8e6c81a07ae54c66e27f210609f2ff529760vboxsync# undef Log
a299266cddc1ae14d76d725a660bb278816bc151vboxsync# define Log LogRel
a299266cddc1ae14d76d725a660bb278816bc151vboxsync# undef LogFlow
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync# define LogFlow LogRel
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#endif
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/** Maximum loopback packet queue size per interface */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#define VBOXNETFLT_LOOPBACK_SIZE 32
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/*******************************************************************************
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync* Global Functions *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync*******************************************************************************/
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync * Stream Driver hooks.
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pArg, void **ppResult);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd);
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsyncstatic int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd);
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync/**
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync * Stream Module hooks.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsyncstatic int VBoxNetFltSolarisModOpen(queue_t *pQueue, dev_t *pDev, int fFile, int fStream, cred_t *pCred);
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsyncstatic int VBoxNetFltSolarisModClose(queue_t *pQueue, int fFile, cred_t *pCred);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int VBoxNetFltSolarisModReadPut(queue_t *pQueue, mblk_t *pMsg);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsyncstatic int VBoxNetFltSolarisModWritePut(queue_t *pQueue, mblk_t *pMsg);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * OS specific hooks invoked from common VBoxNetFlt ring-0.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/** @todo r=bird: What are these doing here? */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncbool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncvoid vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncbool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncvoid vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncint vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncint vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncvoid vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncint vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncint vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/*******************************************************************************
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync* Structures and Typedefs *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync*******************************************************************************/
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync/**
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync * Streams: module info.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsyncstatic struct module_info g_VBoxNetFltSolarisModInfo =
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync{
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync 0xbad, /* module id */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync DEVICE_NAME,
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync 0, /* min. packet size */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync INFPSZ, /* max. packet size */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync 0, /* hi-water mark */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync 0 /* lo-water mark */
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync};
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Streams: read queue hooks.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic struct qinit g_VBoxNetFltSolarisReadQ =
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBoxNetFltSolarisModReadPut,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync NULL, /* service */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBoxNetFltSolarisModOpen,
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync VBoxNetFltSolarisModClose,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync NULL, /* admin (reserved) */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync &g_VBoxNetFltSolarisModInfo,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync NULL /* module stats */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync};
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Streams: write queue hooks.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsyncstatic struct qinit g_VBoxNetFltSolarisWriteQ =
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VBoxNetFltSolarisModWritePut,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync NULL, /* service */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync NULL, /* open */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync NULL, /* close */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync NULL, /* admin (reserved) */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync &g_VBoxNetFltSolarisModInfo,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync NULL /* module stats */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync};
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync/**
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync * Streams: IO stream tab.
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsyncstatic struct streamtab g_VBoxNetFltSolarisStreamTab =
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync{
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync &g_VBoxNetFltSolarisReadQ,
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync &g_VBoxNetFltSolarisWriteQ,
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync NULL, /* muxread init */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync NULL /* muxwrite init */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync};
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * cb_ops: driver char/block entry points
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic struct cb_ops g_VBoxNetFltSolarisCbOps =
d0445e5c26b62718e727032ae46626f5d5db7ae5vboxsync{
d0445e5c26b62718e727032ae46626f5d5db7ae5vboxsync nulldev, /* cb open */
d0445e5c26b62718e727032ae46626f5d5db7ae5vboxsync nulldev, /* cb close */
d0445e5c26b62718e727032ae46626f5d5db7ae5vboxsync nodev, /* b strategy */
d0445e5c26b62718e727032ae46626f5d5db7ae5vboxsync nodev, /* b dump */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync nodev, /* b print */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync nodev, /* cb read */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync nodev, /* cb write */
d0445e5c26b62718e727032ae46626f5d5db7ae5vboxsync nodev, /* cb ioctl */
d0445e5c26b62718e727032ae46626f5d5db7ae5vboxsync nodev, /* c devmap */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync nodev, /* c mmap */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync nodev, /* c segmap */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync nochpoll, /* c poll */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ddi_prop_op, /* property ops */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync &g_VBoxNetFltSolarisStreamTab,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync D_NEW | D_MP | D_MTQPAIR, /* compat. flag */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync CB_REV /* revision */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync};
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
0d1ceffcc16b8999752140e739adb27132655ee8vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * dev_ops: driver entry/exit and other ops.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic struct dev_ops g_VBoxNetFltSolarisDevOps =
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync DEVO_REV, /* driver build revision */
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync 0, /* ref count */
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync VBoxNetFltSolarisGetInfo,
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync nulldev, /* identify */
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync nulldev, /* probe */
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync VBoxNetFltSolarisAttach,
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync VBoxNetFltSolarisDetach,
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync nodev, /* reset */
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync &g_VBoxNetFltSolarisCbOps,
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync (struct bus_ops *)0,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync nodev /* power */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync};
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync/**
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync * modldrv: export driver specifics to kernel
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync */
d0445e5c26b62718e727032ae46626f5d5db7ae5vboxsyncstatic struct modldrv g_VBoxNetFltSolarisDriver =
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync &mod_driverops, /* extern from kernel */
a8fd9edea57842da84a8bcf265a92eb5e96c9c4bvboxsync DEVICE_DESC_DRV " " VBOX_VERSION_STRING "r" VBOXSOLQUOTE(VBOX_SVN_REV),
a299266cddc1ae14d76d725a660bb278816bc151vboxsync &g_VBoxNetFltSolarisDevOps
a299266cddc1ae14d76d725a660bb278816bc151vboxsync};
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * fmodsw: streams module ops
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
739c9e0e5fccb99475b8202ead8fc5665b2fa64cvboxsyncstatic struct fmodsw g_VBoxNetFltSolarisModOps =
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync DEVICE_NAME,
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync &g_VBoxNetFltSolarisStreamTab,
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync D_NEW | D_MP | D_MTQPAIR
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync};
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * modlstrmod: streams module specifics to kernel
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic struct modlstrmod g_VBoxNetFltSolarisModule =
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync{
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync &mod_strmodops, /* extern from kernel */
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync DEVICE_DESC_MOD " " VBOX_VERSION_STRING "r" VBOXSOLQUOTE(VBOX_SVN_REV),
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync &g_VBoxNetFltSolarisModOps
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync};
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync/**
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync * modlinkage: export install/remove/info to the kernel
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync */
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsyncstatic struct modlinkage g_VBoxNetFltSolarisModLinkage =
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync{
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync MODREV_1, /* loadable module system revision */
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync &g_VBoxNetFltSolarisDriver, /* streams driver framework */
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync &g_VBoxNetFltSolarisModule, /* streams module framework */
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync NULL /* terminate array of linkage structures */
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync};
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsyncstruct vboxnetflt_state_t;
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * vboxnetflt_dladdr_t: DL SAP address format
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsynctypedef struct vboxnetflt_dladdr_t
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync ether_addr_t Mac;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync uint16_t SAP;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync} vboxnetflt_dladdr_t;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#define VBOXNETFLT_DLADDRL sizeof(vboxnetflt_dladdr_t)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * which stream is this?
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsynctypedef enum VBOXNETFLTSTREAMTYPE
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync kUndefined = 0,
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync kIp4Stream = 0x1b,
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync kIp6Stream = 0xcc,
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync kArpStream = 0xab,
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync kPromiscStream = 0xdf
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync} VBOXNETFLTSTREAMTYPE;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * loopback packet identifier
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync */
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsynctypedef struct VBOXNETFLTPACKETID
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync{
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync struct VBOXNETFLTPACKETID *pNext;
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync uint16_t cbPacket;
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync uint16_t Checksum;
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync RTMAC SrcMac;
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync RTMAC DstMac;
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync} VBOXNETFLTPACKETID;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsynctypedef struct VBOXNETFLTPACKETID *PVBOXNETFLTPACKETID;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync * vboxnetflt_stream_t: per-stream data (multiple streams per interface)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsynctypedef struct vboxnetflt_stream_t
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int DevMinor; /* minor device no. (for clone) */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync queue_t *pReadQueue; /* read side queue */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync struct vboxnetflt_stream_t *pNext; /* next stream in list */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync PVBOXNETFLTINS volatile pThis; /* the backend instance */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync VBOXNETFLTSTREAMTYPE Type; /* the type of the stream */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync} vboxnetflt_stream_t;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * vboxnetflt_promisc_stream_t: per-interface dedicated stream data
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsynctypedef struct vboxnetflt_promisc_stream_t
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_stream_t Stream; /* The generic stream */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync bool fPromisc; /* cached promiscous value */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync bool fRawMode; /* whether raw mode request was successful */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync uint32_t ModeReqId; /* track MIOCTLs for swallowing our fake request acknowledgements */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync size_t cLoopback; /* loopback queue size list */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync PVBOXNETFLTPACKETID pHead; /* loopback packet identifier head */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync PVBOXNETFLTPACKETID pTail; /* loopback packet identifier tail */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync} vboxnetflt_promisc_stream_t;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/*******************************************************************************
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync* Internal Functions *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync*******************************************************************************/
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisSetRawMode(vboxnetflt_promisc_stream_t *pPromiscStream);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/* static int vboxNetFltSolarisSetFastMode(queue_t *pQueue); */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisPhysAddrReq(queue_t *pQueue);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic void vboxNetFltSolarisCachePhysAddr(PVBOXNETFLTINS pThis, mblk_t *pPhysAddrAckMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisBindReq(queue_t *pQueue, int SAP);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisNotifyReq(queue_t *pQueue);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisUnitDataToRaw(PVBOXNETFLTINS pThis, mblk_t *pMsg, mblk_t **ppRawMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisRawToUnitData(mblk_t *pMsg, mblk_t **ppDlpiMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic inline void vboxNetFltSolarisInitPacketId(PVBOXNETFLTPACKETID pTag, mblk_t *pMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisQueueLoopback(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic bool vboxNetFltSolarisIsOurMBlk(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStream, queue_t *pQueue, mblk_t *pMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic mblk_t *vboxNetFltSolarisFixChecksums(mblk_t *pMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/*******************************************************************************
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync* Global Variables *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync*******************************************************************************/
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/** Global device info handle. */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic dev_info_t *g_pVBoxNetFltSolarisDip = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync/** The (common) global data. */
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsyncstatic VBOXNETFLTGLOBALS g_VBoxNetFltSolarisGlobals;
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync/** The list of all opened streams. */
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsyncvboxnetflt_stream_t *g_VBoxNetFltSolarisStreams;
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync/** Global mutex protecting open/close. */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsyncstatic RTSEMFASTMUTEX g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync/**
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * g_VBoxNetFltInstance is the current PVBOXNETFLTINS to be associated with the stream being created
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * in ModOpen. This is just shared global data between the dynamic attach and the ModOpen procedure.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsyncPVBOXNETFLTINS volatile g_VBoxNetFltSolarisInstance;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync/** Goes along with the instance to determine type of stream being opened/created. */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsyncVBOXNETFLTSTREAMTYPE volatile g_VBoxNetFltSolarisStreamType;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync/**
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync * Kernel entry points
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsyncint _init(void)
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync{
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync LogFlow((DEVICE_NAME ":_init\n"));
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync /*
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync * Prevent module autounloading.
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync */
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync modctl_t *pModCtl = mod_getctl(&g_VBoxNetFltSolarisModLinkage);
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync if (pModCtl)
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync else
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Initialize IPRT.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int rc = RTR0Init(0);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_SUCCESS(rc))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Initialize Solaris specific globals here.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync g_VBoxNetFltSolarisStreams = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync g_VBoxNetFltSolarisInstance = NULL;
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync int rc = RTSemFastMutexCreate(&g_VBoxNetFltSolarisMtx);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync if (RT_SUCCESS(rc))
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync {
4d41bf71a71dd2c00d0c4e0006571b9e07b484c3vboxsync /*
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync * Initialize the globals and connect to the support driver.
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync *
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync * This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync * for establishing the connect to the support driver.
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync */
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals));
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync rc = vboxNetFltInitGlobalsAndIdc(&g_VBoxNetFltSolarisGlobals);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync if (RT_SUCCESS(rc))
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync {
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync rc = mod_install(&g_VBoxNetFltSolarisModLinkage);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync if (!rc)
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync return rc;
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync LogRel((DEVICE_NAME ":mod_install failed. rc=%d\n", rc));
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync }
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync else
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync LogRel((DEVICE_NAME ":failed to initialize globals.\n"));
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync RTSemFastMutexDestroy(g_VBoxNetFltSolarisMtx);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX;
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync }
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync RTR0Term();
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync }
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync else
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync LogRel((DEVICE_NAME ":failed to initialize IPRT (rc=%d)\n", rc));
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals));
f1cdf99d4db5875ae9e1432c7e4a8222e685a0e3vboxsync return RTErrConvertToErrno(rc);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync}
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncint _fini(void)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int rc;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":_fini\n"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Undo the work done during start (in reverse order).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync rc = vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_FAILURE(rc))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":_fini - busy!\n"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return EBUSY;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (g_VBoxNetFltSolarisMtx != NIL_RTSEMFASTMUTEX)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexDestroy(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTR0Term();
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return mod_remove(&g_VBoxNetFltSolarisModLinkage);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncint _info(struct modinfo *pModInfo)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":_info\n"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int rc = mod_info(&g_VBoxNetFltSolarisModLinkage, pModInfo);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":_info returns %d\n", rc));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return rc;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Attach entry point, to attach a device to the system or resume it.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pDip The module structure instance.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param enmCmd Operation type (attach/resume).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @returns corresponding solaris error code.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync switch (enmCmd)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case DDI_ATTACH:
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int instance = ddi_get_instance(pDip);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int rc = ddi_create_minor_node(pDip, DEVICE_NAME, S_IFCHR, instance, DDI_PSEUDO, CLONE_DEV);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (rc == DDI_SUCCESS)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync g_pVBoxNetFltSolarisDip = pDip;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync ddi_report_dev(pDip);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_SUCCESS;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync else
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisAttach failed to create minor node. rc%d\n", rc));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_FAILURE;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case DDI_RESUME:
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /* Nothing to do here... */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_SUCCESS;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_FAILURE;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Detach entry point, to detach a device to the system or suspend it.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pDip The module structure instance.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param enmCmd Operation type (detach/suspend).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @returns corresponding solaris error code.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync switch (enmCmd)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case DDI_DETACH:
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int instance = ddi_get_instance(pDip);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync ddi_remove_minor_node(pDip, NULL);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_SUCCESS;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case DDI_RESUME:
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /* Nothing to do here... */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_SUCCESS;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_FAILURE;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Info entry point, called by solaris kernel for obtaining driver info.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pDip The module structure instance (do not use).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param enmCmd Information request type.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pvArg Type specific argument.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param ppvResult Where to store the requested info.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @returns corresponding solaris error code.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
ad27e1d5e48ca41245120c331cc88b50464813cevboxsyncstatic int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg, void **ppResult)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisGetInfo pDip=%p enmCmd=%d pArg=%p instance=%d\n", pDip, enmCmd,
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync getminor((dev_t)pvArg)));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync switch (enmCmd)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case DDI_INFO_DEVT2DEVINFO:
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *ppResult = g_pVBoxNetFltSolarisDip;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_SUCCESS;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case DDI_INFO_DEVT2INSTANCE:
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int instance = getminor((dev_t)pvArg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *ppResult = (void *)(uintptr_t)instance;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_SUCCESS;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return DDI_FAILURE;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Stream module open entry point, initializes the queue and allows streams processing.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pQueue Pointer to the read queue (cannot be NULL).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pDev Pointer to the dev_t associated with the driver at the end of the stream.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param fOpenMode Open mode (always 0 for streams driver, thus ignored).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param fStreamMode Stream open mode.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pCred Pointer to user credentials.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @returns corresponding solaris error code.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
a2d2faa1528d1752b2bb4da5469495fe5436e0f0vboxsyncstatic int VBoxNetFltSolarisModOpen(queue_t *pQueue, dev_t *pDev, int fOpenMode, int fStreamMode, cred_t *pCred)
a2d2faa1528d1752b2bb4da5469495fe5436e0f0vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync Assert(pQueue);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModOpen pQueue=%p pDev=%p fOpenMode=%d fStreamMode=%d\n", pQueue, pDev,
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync fOpenMode, fStreamMode));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int rc = RTSemFastMutexRequest(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync AssertRCReturn(rc, rc);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Already open?
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
bb48f1a46f469da79b8d15cae8deee8c199448a0vboxsync if (pQueue->q_ptr)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModOpen invalid open.\n"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexRelease(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return ENOENT;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Check for the VirtualBox instance.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync PVBOXNETFLTINS pThis = g_VBoxNetFltSolarisInstance;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (!pThis)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModOpen failed to get VirtualBox instance.\n"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexRelease(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return ENOENT;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Check VirtualBox stream type.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (g_VBoxNetFltSolarisStreamType == kUndefined)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModOpen failed due to undefined VirtualBox open mode.\n"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexRelease(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return ENOENT;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Get minor number. For clone opens provide a new dev_t.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync minor_t DevMinor = 0;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_stream_t *pStream = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_stream_t **ppPrevStream = &g_VBoxNetFltSolarisStreams;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (fStreamMode == CLONEOPEN)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync for (; (pStream = *ppPrevStream) != NULL; ppPrevStream = &pStream->pNext)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (DevMinor < pStream->DevMinor)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync DevMinor++;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *pDev = makedevice(getmajor(*pDev), DevMinor);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync else
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync DevMinor = getminor(*pDev);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (g_VBoxNetFltSolarisStreamType == kPromiscStream)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_promisc_stream_t *pPromiscStream = RTMemAlloc(sizeof(vboxnetflt_promisc_stream_t));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_UNLIKELY(!pPromiscStream))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModOpen failed to allocate promiscuous stream data.\n"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexRelease(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return ENOMEM;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->fPromisc = false;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->fRawMode = false;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->ModeReqId = 0;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->pHead = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->pTail = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->cLoopback = 0;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pStream = (vboxnetflt_stream_t *)pPromiscStream;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync else
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Allocate & initialize per-stream data. Hook it into the (read and write) queue's module specific data.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pStream = RTMemAlloc(sizeof(vboxnetflt_stream_t));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_UNLIKELY(!pStream))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModOpen failed to allocate stream data.\n"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexRelease(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return ENOMEM;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pStream->DevMinor = DevMinor;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pStream->pReadQueue = pQueue;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Pick up the current global VBOXNETFLTINS instance as
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * the one that we will associate this stream with.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync ASMAtomicUoWritePtr((void * volatile *)&pStream->pThis, pThis);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pStream->Type = g_VBoxNetFltSolarisStreamType;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync switch (pStream->Type)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case kIp4Stream: ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pvIp4Stream, pStream); break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case kIp6Stream: ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pvIp6Stream, pStream); break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case kArpStream: ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pvArpStream, pStream); break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case kPromiscStream: ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.pvPromiscStream, pStream); break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync default: /* Heh. */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync AssertRelease(pStream->Type);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pQueue->q_ptr = pStream;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync WR(pQueue)->q_ptr = pStream;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Link it to the list of streams.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pStream->pNext = *ppPrevStream;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *ppPrevStream = pStream;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Release global lock, & do not hold locks across putnext calls.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexRelease(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync qprocson(pQueue);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Don't hold the spinlocks across putnext calls as it could
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * (and does mostly) re-enter the put procedure on the same thread.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (pStream->Type == kPromiscStream)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_promisc_stream_t *pPromiscStream = (vboxnetflt_promisc_stream_t *)pStream;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Bind to SAP 0 (DL_ETHER).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Note: We don't support DL_TPR (token passing ring) SAP as that is unnecessary asynchronous
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * work to get DL_INFO_REQ acknowledgements and determine SAP based on the Mac Type etc.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Besides TPR doesn't really exist anymore practically as far as I know.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int rc = vboxNetFltSolarisBindReq(pStream->pReadQueue, 0 /* SAP */);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_LIKELY(RT_SUCCESS(rc)))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
f285bb149147cccd6109e5487e744df17c04da82vboxsync * Request the physical address (we cache the acknowledgement).
f285bb149147cccd6109e5487e744df17c04da82vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync rc = vboxNetFltSolarisPhysAddrReq(pStream->pReadQueue);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_LIKELY(RT_SUCCESS(rc)))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Ask for DLPI link notifications, don't bother check for errors here.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxNetFltSolarisNotifyReq(pStream->pReadQueue);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Enable raw mode.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync rc = vboxNetFltSolarisSetRawMode(pPromiscStream);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_FAILURE(rc))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisSetRawMode failed rc=%Rrc.\n", rc));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync else
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisSetRawMode failed rc=%Rrc.\n", rc));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync else
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisBindReq failed rc=%Rrc.\n", rc));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync NOREF(fOpenMode);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync NOREF(pCred);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModOpen returns 0, DevMinor=%d pQueue=%p\n", DevMinor, pStream->pReadQueue));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return 0;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Stream module close entry point, undoes the work done on open and closes the stream.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pQueue Pointer to the read queue (cannot be NULL).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param fOpenMode Open mode (always 0 for streams driver, thus ignored).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pCred Pointer to user credentials.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @returns corresponding solaris error code.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int VBoxNetFltSolarisModClose(queue_t *pQueue, int fOpenMode, cred_t *pCred)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync Assert(pQueue);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModClose pQueue=%p fOpenMode=%d\n", pQueue, fOpenMode));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int rc = RTSemFastMutexRequest(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync AssertRCReturn(rc, rc);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_stream_t *pStream = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_stream_t **ppPrevStream = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Get instance data.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pStream = (vboxnetflt_stream_t *)pQueue->q_ptr;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_UNLIKELY(!pStream))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModClose failed to get stream.\n"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxNetFltRelease(pStream->pThis, false /* fBusy */);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexRelease(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return ENXIO;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (pStream->Type == kPromiscStream)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync flushq(pQueue, FLUSHALL);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync flushq(WR(pQueue), FLUSHALL);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync qprocsoff(pQueue);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (pStream->Type == kPromiscStream)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_promisc_stream_t *pPromiscStream = (vboxnetflt_promisc_stream_t *)pStream;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int rc = RTSemFastMutexRequest(pStream->pThis->u.s.hFastMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync AssertRCReturn(rc, rc);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Free-up loopback buffers.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync PVBOXNETFLTPACKETID pCur = pPromiscStream->pHead;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync while (pCur)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync PVBOXNETFLTPACKETID pNext = pCur->pNext;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTMemFree(pCur);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pCur = pNext;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->pHead = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->pTail = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->cLoopback = 0;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexRelease(pStream->pThis->u.s.hFastMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Unlink it from the list of streams.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync for (ppPrevStream = &g_VBoxNetFltSolarisStreams; (pStream = *ppPrevStream) != NULL; ppPrevStream = &pStream->pNext)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (pStream == (vboxnetflt_stream_t *)pQueue->q_ptr)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *ppPrevStream = pStream->pNext;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Delete the stream.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync switch (pStream->Type)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case kIp4Stream: ASMAtomicUoWritePtr(pStream->pThis->u.s.pvIp4Stream, NULL); break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case kIp6Stream: ASMAtomicUoWritePtr(pStream->pThis->u.s.pvIp6Stream, NULL); break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case kArpStream: ASMAtomicUoWritePtr(pStream->pThis->u.s.pvArpStream, NULL); break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case kPromiscStream: ASMAtomicUoWritePtr(pStream->pThis->u.s.pvPromiscStream, NULL); break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync default: /* Heh. */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync AssertRelease(pStream->Type);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxNetFltRelease(pStream->pThis, false /* fBusy */);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTMemFree(pStream);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pQueue->q_ptr = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync WR(pQueue)->q_ptr = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync NOREF(fOpenMode);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync NOREF(pCred);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSemFastMutexRelease(g_VBoxNetFltSolarisMtx);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return 0;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Read side put procedure for processing messages in the read queue.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * All streams, bound and unbound share this read procedure.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pQueue Pointer to the read queue.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pMsg Pointer to the message.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @returns corresponding solaris error code.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int VBoxNetFltSolarisModReadPut(queue_t *pQueue, mblk_t *pMsg)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (!pMsg)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return 0;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut pQueue=%p pMsg=%p\n", pQueue, pMsg));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync bool fSendUpstream = true;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_stream_t *pStream = pQueue->q_ptr;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync PVBOXNETFLTINS pThis = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * In the unlikely case where VirtualBox crashed and this filter
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * is somehow still in the host stream we must try not to panic the host.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if ( pStream
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync && pStream->Type == kPromiscStream)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync fSendUpstream = false;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pThis = ASMAtomicUoReadPtr((void * volatile *)&pStream->pThis);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_LIKELY(pThis))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Retain the instance if we're filtering regardless of we are active or not
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * The reason being even when we are inactive we reference the instance (e.g
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * the promiscuous OFF acknowledgement case).
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync const bool fActive = ASMAtomicUoReadBool(&pThis->fActive);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxNetFltRetain(pThis, true /* fBusy */);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync RTSpinlockRelease(pThis->hSpinlock, &Tmp);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vboxnetflt_promisc_stream_t *pPromiscStream = (vboxnetflt_promisc_stream_t *)pStream;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync switch (DB_TYPE(pMsg))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync case M_DATA:
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut M_DATA\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if ( fActive
a299266cddc1ae14d76d725a660bb278816bc151vboxsync && pPromiscStream->fRawMode)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync vboxNetFltSolarisRecv(pThis, pStream, pQueue, pMsg);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync break;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync case M_PROTO:
54dc8e6c81a07ae54c66e27f210609f2ff529760vboxsync case M_PCPROTO:
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync union DL_primitives *pPrim = (union DL_primitives *)pMsg->b_rptr;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync t_uscalar_t Prim = pPrim->dl_primitive;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_PCPROTO %d\n", Prim));
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync switch (Prim)
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync {
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync case DL_NOTIFY_IND:
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync {
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync if (MBLKL(pMsg) < DL_NOTIFY_IND_SIZE)
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync {
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: Invalid notification size; expected>=%d got=%d\n",
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync DL_NOTIFY_IND_SIZE, MBLKL(pMsg)));
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync break;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync }
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync dl_notify_ind_t *pNotifyInd = (dl_notify_ind_t *)pMsg->b_rptr;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync switch (pNotifyInd->dl_notification)
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync case DL_NOTE_PHYS_ADDR:
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (pNotifyInd->dl_data != DL_CURR_PHYS_ADDR)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync break;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync size_t cOffset = pNotifyInd->dl_addr_offset;
54dc8e6c81a07ae54c66e27f210609f2ff529760vboxsync size_t cbAddr = pNotifyInd->dl_addr_length;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (!cOffset || !cbAddr)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_NOTE_PHYS_ADDR. Invalid offset/addr.\n"));
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync fSendUpstream = false;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync break;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync bcopy(pMsg->b_rptr + cOffset, &pThis->u.s.Mac, sizeof(pThis->u.s.Mac));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_NOTE_PHYS_ADDR. New Mac=%.*Rhxs\n",
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync sizeof(pThis->u.s.Mac), &pThis->u.s.Mac));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync break;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync case DL_NOTE_LINK_UP:
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync const bool fDisconnected = ASMAtomicUoReadBool(&pThis->fActive);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (fDisconnected)
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync {
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, false);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_NOTE_LINK_UP.\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync break;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync case DL_NOTE_LINK_DOWN:
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync {
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync const bool fDisconnected = ASMAtomicUoReadBool(&pThis->fActive);
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync if (!fDisconnected)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, true);
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_NOTE_LINK_DOWN.\n"));
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync }
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync break;
54dc8e6c81a07ae54c66e27f210609f2ff529760vboxsync }
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync }
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync break;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync case DL_BIND_ACK:
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /*
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Swallow our bind request acknowledgement.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: DL_BIND_ACK. Bound to requested SAP!\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync break;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync case DL_PHYS_ADDR_ACK:
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /*
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Swallow our physical address request acknowledgement.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync vboxNetFltSolarisCachePhysAddr(pThis, pMsg);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync break;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync case DL_OK_ACK:
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /*
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Swallow our fake promiscous request acknowledgement.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync dl_ok_ack_t *pOkAck = (dl_ok_ack_t *)pMsg->b_rptr;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (pOkAck->dl_correct_primitive == DL_PROMISCON_REQ)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_PCPROTO: DL_OK_ACK: fPromisc is ON.\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pPromiscStream->fPromisc = true;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync else if (pOkAck->dl_correct_primitive == DL_PROMISCOFF_REQ)
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_PCPROTO: DL_OK_ACK: fPromisc is OFF.\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pPromiscStream->fPromisc = false;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case M_IOCACK:
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync /*
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Swallow our fake raw/fast path mode request acknowledgement.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync struct iocblk *pIOC = (struct iocblk *)pMsg->b_rptr;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (pIOC->ioc_id == pPromiscStream->ModeReqId)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pPromiscStream->fRawMode = true;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: Mode acknowledgement. RawMode is %s\n",
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->fRawMode ? "ON" : "OFF"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync break;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync case M_IOCNAK:
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /*
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * Swallow our fake raw/fast path mode request not acknowledged.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync struct iocblk *pIOC = (struct iocblk *)pMsg->b_rptr;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (pIOC->ioc_id == pPromiscStream->ModeReqId)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->fRawMode = false;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: WARNING! Mode not acknowledged. RawMode is %s\n",
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->fRawMode ? "ON" : "OFF"));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync break;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync case M_FLUSH:
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync {
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync /*
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * We must support flushing queues.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: M_FLUSH\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (*pMsg->b_rptr & FLUSHR)
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync flushq(pQueue, FLUSHALL);
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync break;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync }
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync vboxNetFltRelease(pThis, true /* fBusy */);
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync }
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync else
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync LogRel((DEVICE_NAME ":VBoxNetFltSolarisModReadPut: Could not find VirtualBox instance!!\n"));
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync }
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync if (fSendUpstream)
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync {
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync /*
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * Don't queue up things here, can cause bad things to happen when the system
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * is under heavy loads and we need to jam across high priority messages which
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * if it's not done properly will end up in an infinite loop.
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync putnext(pQueue, pMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync else
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync {
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync /*
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * We need to free up the message if we don't pass it through.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync freemsg(pMsg);
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync }
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
54dc8e6c81a07ae54c66e27f210609f2ff529760vboxsync return 0;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync}
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync/**
54dc8e6c81a07ae54c66e27f210609f2ff529760vboxsync * Write side put procedure for processing messages in the write queue.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * All streams, bound and unbound share this write procedure.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync *
b8795afd31d95dd5bf668aa9034df0c985080bc0vboxsync * @param pQueue Pointer to the write queue.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * @param pMsg Pointer to the message.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @returns corresponding solaris error code.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int VBoxNetFltSolarisModWritePut(queue_t *pQueue, mblk_t *pMsg)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":VBoxNetFltSolarisModWritePut pQueue=%p pMsg=%p\n", pQueue, pMsg));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync putnext(pQueue, pMsg);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return 0;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Put the stream in raw mode.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @returns VBox status code.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * @param pQueue Pointer to the read queue.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxNetFltSolarisSetRawMode(vboxnetflt_promisc_stream_t *pPromiscStream)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisSetRawMode pPromiscStream=%p\n", pPromiscStream));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync mblk_t *pRawMsg = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pRawMsg = mkiocb(DLIOCRAW);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_UNLIKELY(!pRawMsg))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return VERR_NO_MEMORY;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync queue_t *pQueue = pPromiscStream->Stream.pReadQueue;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (!pQueue)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return VERR_INVALID_POINTER;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync struct iocblk *pIOC = (struct iocblk *)pRawMsg->b_rptr;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPromiscStream->ModeReqId = pIOC->ioc_id;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pIOC->ioc_count = 0;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync qreply(pQueue, pRawMsg);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return VINF_SUCCESS;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#if 0
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * Put the stream back in fast path mode.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync *
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * @returns VBox status code.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * @param pQueue Pointer to the read queue.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsyncstatic int vboxNetFltSolarisSetFastMode(queue_t *pQueue)
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync{
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisSetFastMode pQueue=%p\n", pQueue));
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync mblk_t *pFastMsg = mkiocb(DL_IOC_HDR_INFO);
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync if (RT_UNLIKELY(!pFastMsg))
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync return VERR_NO_MEMORY;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync vboxnetflt_stream_t *pStream = pQueue->q_ptr;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync struct iocblk *pIOC = (struct iocblk *)pFastMsg->b_rptr;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync pStream->ModeReqId = pIOC->ioc_id;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync size_t cbReq = sizeof(dl_unitdata_req_t) + sizeof(vboxnetflt_dladdr_t);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync mblk_t *pDataReqMsg = allocb(cbReq, BPRI_MED);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (RT_UNLIKELY(!pDataReqMsg))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return VERR_NO_MEMORY;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync DB_TYPE(pDataReqMsg) = M_PROTO;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync dl_unitdata_req_t *pDataReq = (dl_unitdata_req_t *)pDataReqMsg->b_rptr;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pDataReq->dl_primitive = DL_UNITDATA_REQ;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pDataReq->dl_dest_addr_length = sizeof(vboxnetflt_dladdr_t);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pDataReq->dl_dest_addr_offset = sizeof(dl_unitdata_req_t);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pDataReq->dl_priority.dl_min = 0;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pDataReq->dl_priority.dl_max = 0;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync bzero(pDataReqMsg->b_rptr + sizeof(dl_unitdata_req_t), sizeof(vboxnetflt_dladdr_t));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pDataReqMsg->b_wptr = pDataReqMsg->b_rptr + cbReq;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync /*
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Link the data format request message into the header ioctl message.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pFastMsg->b_cont = pDataReqMsg;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pIOC->ioc_count = msgdsize(pDataReqMsg);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync qreply(pQueue, pFastMsg);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VINF_SUCCESS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#endif
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Send fake promiscous mode requests downstream.
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pQueue Pointer to the read queue.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param fPromisc Whether to enable promiscous mode or not.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param PromiscLevel Promiscous level; DL_PROMISC_PHYS/SAP/MULTI.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @returns VBox error code.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxNetFltSolarisPromiscReq(queue_t *pQueue, bool fPromisc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisPromiscReq pQueue=%p fPromisc=%d\n", pQueue, fPromisc));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync t_uscalar_t Cmd;
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync size_t cbReq = 0;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (fPromisc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Cmd = DL_PROMISCON_REQ;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync cbReq = DL_PROMISCON_REQ_SIZE;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync else
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync Cmd = DL_PROMISCOFF_REQ;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync cbReq = DL_PROMISCOFF_REQ_SIZE;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync mblk_t *pPromiscPhysMsg = mexchange(NULL, NULL, cbReq, M_PROTO, Cmd);
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync if (RT_UNLIKELY(!pPromiscPhysMsg))
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync return VERR_NO_MEMORY;
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync mblk_t *pPromiscSapMsg = mexchange(NULL, NULL, cbReq, M_PROTO, Cmd);
3b91cdad96393c90c3098e2805621136b20ef1e6vboxsync if (RT_UNLIKELY(!pPromiscSapMsg))
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync {
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync freemsg(pPromiscPhysMsg);
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync return VERR_NO_MEMORY;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (fPromisc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
939e2ecb812c6402abcc63e7d615c5444acfd02evboxsync ((dl_promiscon_req_t *)pPromiscPhysMsg->b_rptr)->dl_level = DL_PROMISC_PHYS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ((dl_promiscon_req_t *)pPromiscSapMsg->b_rptr)->dl_level = DL_PROMISC_SAP;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync else
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ((dl_promiscoff_req_t *)pPromiscPhysMsg->b_rptr)->dl_level = DL_PROMISC_PHYS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync ((dl_promiscoff_req_t *)pPromiscSapMsg->b_rptr)->dl_level = DL_PROMISC_SAP;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync qreply(pQueue, pPromiscPhysMsg);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync qreply(pQueue, pPromiscSapMsg);
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync return VINF_SUCCESS;
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync}
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync * Send a fake physical address request downstream.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @returns VBox status code.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pQueue Pointer to the read queue.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxNetFltSolarisPhysAddrReq(queue_t *pQueue)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisPhysAddrReq pQueue=%p\n", pQueue));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync t_uscalar_t Cmd = DL_PHYS_ADDR_REQ;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync size_t cbReq = DL_PHYS_ADDR_REQ_SIZE;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync mblk_t *pPhysAddrMsg = mexchange(NULL, NULL, cbReq, M_PROTO, Cmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (RT_UNLIKELY(!pPhysAddrMsg))
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VERR_NO_MEMORY;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync dl_phys_addr_req_t *pPhysAddrReq = (dl_phys_addr_req_t *)pPhysAddrMsg->b_rptr;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pPhysAddrReq->dl_addr_type = DL_CURR_PHYS_ADDR;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync qreply(pQueue, pPhysAddrMsg);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VINF_SUCCESS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Cache the MAC address into the VirtualBox instance given a physical
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * address acknowledgement message.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pThis The instance.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pMsg Pointer to the physical address acknowledgement message.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic void vboxNetFltSolarisCachePhysAddr(PVBOXNETFLTINS pThis, mblk_t *pMsg)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisCachePhysAddr pThis=%p pMsg=%p\n", pThis, pMsg));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync AssertCompile(sizeof(RTMAC) == ETHERADDRL);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync dl_phys_addr_ack_t *pPhysAddrAck = (dl_phys_addr_ack_t *)pMsg->b_rptr;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (pPhysAddrAck->dl_addr_length == sizeof(pThis->u.s.Mac))
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync {
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync bcopy(pMsg->b_rptr + pPhysAddrAck->dl_addr_offset, &pThis->u.s.Mac, sizeof(pThis->u.s.Mac));
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisCachePhysAddr: DL_PHYS_ADDR_ACK: Mac=%.*Rhxs\n", sizeof(pThis->u.s.Mac),
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync &pThis->u.s.Mac));
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync }
e45e3ae4a834169539e689759ba6b3ac71bfe40fvboxsync else
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisCachePhysAddr: Invalid address size. expected=%d got=%d\n", ETHERADDRL,
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pPhysAddrAck->dl_addr_length));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Prepare DLPI bind request to a SAP.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @returns VBox status code.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pQueue Pointer to the read queue.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param SAP The SAP to bind the stream to.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsyncstatic int vboxNetFltSolarisBindReq(queue_t *pQueue, int SAP)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisBindReq SAP=%d\n", SAP));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync mblk_t *pBindMsg = mexchange(NULL, NULL, DL_BIND_REQ_SIZE, M_PROTO, DL_BIND_REQ);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (RT_UNLIKELY(!pBindMsg))
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VERR_NO_MEMORY;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync dl_bind_req_t *pBindReq = (dl_bind_req_t *)pBindMsg->b_rptr;
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync pBindReq->dl_sap = SAP;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pBindReq->dl_max_conind = 0;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pBindReq->dl_conn_mgmt = 0;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pBindReq->dl_xidtest_flg = 0;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pBindReq->dl_service_mode = DL_CLDLS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync qreply(pQueue, pBindMsg);
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync return VINF_SUCCESS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Prepare DLPI notifications request.
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync *
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync * @returns VBox status code.
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync * @param pQueue Pointer to the read queue.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxNetFltSolarisNotifyReq(queue_t *pQueue)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisNotifyReq\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync mblk_t *pNotifyMsg = mexchange(NULL, NULL, DL_NOTIFY_REQ_SIZE, M_PROTO, DL_NOTIFY_REQ);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (RT_UNLIKELY(!pNotifyMsg))
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync return VERR_NO_MEMORY;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync dl_notify_req_t *pNotifyReq = (dl_notify_req_t *)pNotifyMsg->b_rptr;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pNotifyReq->dl_notifications = DL_NOTE_LINK_UP | DL_NOTE_LINK_DOWN | DL_NOTE_PHYS_ADDR;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync qreply(pQueue, pNotifyMsg);
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync return VINF_SUCCESS;
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
56689b5c06781615da91826b9f9df665826a0b92vboxsync
56689b5c06781615da91826b9f9df665826a0b92vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Opens the required device and returns the vnode_t associated with it.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * We require this for the funny attach/detach routine.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync * @returns VBox status code.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pszDev The device path.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param ppVNode Where to store the vnode_t pointer associated with the opened device.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param ppVNodeHeld Where to store the vnode_t required during closing of the device.
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync * @param ppUser Open handle required while closing the device.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisOpenDev(char *pszDev, vnode_t **ppVNode, vnode_t **ppVNodeHeld, TIUSER **ppUser)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int rc;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync vnode_t *pVNodeHeld = NULL;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync rc = lookupname(pszDev, UIO_SYSSPACE, FOLLOW, NULLVPP, &pVNodeHeld);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (!rc)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync TIUSER *pUser;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync rc = t_kopen((file_t *)NULL, pVNodeHeld->v_rdev, FREAD | FWRITE, &pUser, kcred);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (!rc)
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync {
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync *ppVNode = pUser->fp->f_vnode;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *ppVNodeHeld = pVNodeHeld;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *ppUser = pUser;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return VINF_SUCCESS;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync }
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync VN_RELE(pVNodeHeld);
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync }
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync return VERR_PATH_NOT_FOUND;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync/**
da0b2d0ebcbeb635e76686254cc10c70faa37ee6vboxsync * Close the device opened using vboxNetFltSolarisOpenDev.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pVNodeHeld Pointer to the held vnode of the device.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pUser Pointer to the file handle.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
230bd8589bba39933ac5ec21482d6186d675e604vboxsyncstatic void vboxNetFltSolarisCloseDev(vnode_t *pVNodeHeld, TIUSER *pUser)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync t_kclose(pUser, 0);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync VN_RELE(pVNodeHeld);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync}
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync#ifdef VBOX_WITH_NETFLT_SOLARIS_DLPISTYLE2
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync/**
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * Set the DLPI style-2 PPA via an attach request.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @returns VBox status code.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param hDevice Layered device handle.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param PPA Physical Point of Attachment (PPA) number.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisAttachReq(ldi_handle_t hDevice, int PPA)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync t_uscalar_t Cmd = DL_ATTACH_REQ;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync size_t cbReq = DL_ATTACH_REQ_SIZE;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync mblk_t *pAttachMsg = mexchange(NULL, NULL, cbReq, M_PROTO, Cmd);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (RT_UNLIKELY(!pAttachMsg))
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync return VERR_NO_MEMORY;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync dl_attach_req_t *pAttachReq = (dl_attach_req_t *)pAttachMsg->b_rptr;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync pAttachReq->dl_ppa = PPA;
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = ldi_putmsg(hDevice, pAttachMsg);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (!rc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = ldi_getmsg(hDevice, &pAttachMsg, NULL);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (!rc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VINF_SUCCESS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync else
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachReq ldi_getmsg failed. rc=%d\n", rc));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync else
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachReq ldi_putmsg failed. rc=%d\n", rc));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VERR_GENERAL_FAILURE;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync#endif
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Get the logical interface flags from the stream.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @returns VBox status code.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param hDevice Layered device handle.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pInterface Pointer to the interface.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxNetFltSolarisGetIfFlags(ldi_handle_t hDevice, struct lifreq *pInterface)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync struct strioctl IOCReq;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int ret;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync IOCReq.ic_cmd = SIOCGLIFFLAGS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync IOCReq.ic_timout = 40;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync IOCReq.ic_len = sizeof(struct lifreq);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync IOCReq.ic_dp = (caddr_t)pInterface;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = ldi_ioctl(hDevice, I_STR, (intptr_t)&IOCReq, FKIOCTL, kcred, &ret);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (!rc)
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync return VINF_SUCCESS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return RTErrConvertFromErrno(rc);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync/**
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync * Sets the multiplexor ID from the interface.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync * @returns VBox status code.
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync * @param pVNode Pointer to the device vnode.
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync * @param pInterface Pointer to the interface.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync */
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsyncstatic int vboxNetFltSolarisSetMuxId(vnode_t *pVNode, struct lifreq *pInterface)
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync{
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync struct strioctl IOCReq;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync int rc;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync int ret;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync IOCReq.ic_cmd = SIOCSLIFMUXID;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync IOCReq.ic_timout = 40;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync IOCReq.ic_len = sizeof(struct lifreq);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync IOCReq.ic_dp = (caddr_t)pInterface;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = strioctl(pVNode, I_STR, (intptr_t)&IOCReq, 0, K_TO_K, kcred, &ret);
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync if (!rc)
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync return VINF_SUCCESS;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync return RTErrConvertFromErrno(rc);
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync}
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync/**
4bcaf5d320bf0d88910212509c37bdd634e0879evboxsync * Get the multiplexor file descriptor of the lower stream.
cec3b04587a02f0dc7d0cc679e9a0de19b730e2cvboxsync *
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync * @returns VBox status code.
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync * @param MuxId The multiplexor ID.
4a4d802b46dfabbfd36e88822ff7b17421120469vboxsync * @param pFd Where to store the lower stream file descriptor.
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync */
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsyncstatic int vboxNetFltSolarisMuxIdToFd(vnode_t *pVNode, int MuxId, int *pFd)
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync{
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync int ret;
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync int rc = strioctl(pVNode, _I_MUXID2FD, (intptr_t)MuxId, 0, K_TO_K, kcred, &ret);
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync if (!rc)
b2c35a7024c4c308b429c81b203b3bcbd44ee60cvboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *pFd = ret;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VINF_SUCCESS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return RTErrConvertFromErrno(rc);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Relinks the lower and the upper IPv4 stream.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync *
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @returns VBox status code.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pVNode Pointer to the device vnode.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param pInterface Pointer to the interface.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param IpMuxFd The IP multiplexor ID.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync * @param ArpMuxFd The ARP multiplexor ID.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisRelinkIp4(vnode_t *pVNode, struct lifreq *pInterface, int IpMuxFd, int ArpMuxFd)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisRelinkIp4: pVNode=%p pInterface=%p IpMuxFd=%d ArpMuxFd=%d\n", pVNode,
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pInterface, IpMuxFd, ArpMuxFd));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int NewIpMuxId;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int NewArpMuxId;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = strioctl(pVNode, I_PLINK, (intptr_t)IpMuxFd, 0, K_TO_K, kcred, &NewIpMuxId);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc2 = strioctl(pVNode, I_PLINK, (intptr_t)ArpMuxFd, 0, K_TO_K, kcred, &NewArpMuxId);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if ( !rc
a299266cddc1ae14d76d725a660bb278816bc151vboxsync && !rc2)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pInterface->lifr_ip_muxid = NewIpMuxId;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pInterface->lifr_arp_muxid = NewArpMuxId;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxNetFltSolarisSetMuxId(pVNode, pInterface);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (RT_SUCCESS(rc))
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VINF_SUCCESS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisRelinkIp4: failed to set new Mux Id.\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync else
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisRelinkIp4: failed to link.\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VERR_GENERAL_FAILURE;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Relinks the lower and the upper IPv6 stream.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @returns VBox status code.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pVNode Pointer to the device vnode.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pInterface Pointer to the interface.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param Ip6MuxFd The IPv6 multiplexor ID.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync */
a299266cddc1ae14d76d725a660bb278816bc151vboxsyncstatic int vboxNetFltSolarisRelinkIp6(vnode_t *pVNode, struct lifreq *pInterface, int Ip6MuxFd)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync{
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisRelinkIp6: pVNode=%p pInterface=%p Ip6MuxFd=%d\n", pVNode, pInterface, Ip6MuxFd));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int NewIp6MuxId;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = strioctl(pVNode, I_PLINK, (intptr_t)Ip6MuxFd, 0, K_TO_K, kcred, &NewIp6MuxId);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (!rc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync pInterface->lifr_ip_muxid = NewIp6MuxId;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync rc = vboxNetFltSolarisSetMuxId(pVNode, pInterface);
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (RT_SUCCESS(rc))
cea38eeef9a0a2060a343a9bf2b82a1f51963b46vboxsync return VINF_SUCCESS;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisRelinkIp6: failed to set new Mux Id.\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync else
a299266cddc1ae14d76d725a660bb278816bc151vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisRelinkIp6: failed to link.\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VERR_GENERAL_FAILURE;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync}
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
a299266cddc1ae14d76d725a660bb278816bc151vboxsync/**
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * Dynamically find the position on the host stack where to attach/detach ourselves.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync *
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @returns VBox status code.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pVNode Pointer to the lower stream vnode.
a299266cddc1ae14d76d725a660bb278816bc151vboxsync * @param pModPos Where to store the module position.
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync */
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsyncstatic int vboxNetFltSolarisDetermineModPos(bool fAttach, vnode_t *pVNode, int *pModPos)
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync{
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogFlow((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: fAttach=%d pVNode=%p pModPos=%p\n", fAttach, pVNode, pModPos));
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync int cMod;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync int rc = strioctl(pVNode, I_LIST, (intptr_t)NULL, 0, K_TO_K, kcred, &cMod);
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync if (!rc)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
a299266cddc1ae14d76d725a660bb278816bc151vboxsync if (cMod < 1)
a299266cddc1ae14d76d725a660bb278816bc151vboxsync {
6578276195b5b6a53ef2fc44f96a3348c516d3f5vboxsync LogRel((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: too few modules on host interface. cMod=%d\n"));
a299266cddc1ae14d76d725a660bb278816bc151vboxsync return VERR_OUT_OF_RANGE;
a299266cddc1ae14d76d725a660bb278816bc151vboxsync }
a299266cddc1ae14d76d725a660bb278816bc151vboxsync
/*
* While attaching we make sure we are at the bottom most of the stack, excepting
* the host driver.
*/
LogFlow((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: cMod=%d\n", cMod));
if (fAttach)
{
*pModPos = cMod - 1;
return VINF_SUCCESS;
}
/*
* Detaching is a bit more complicated; since user could have altered the stack positions
* we take the safe approach by finding our position.
*/
struct str_list StrList;
StrList.sl_nmods = cMod;
StrList.sl_modlist = RTMemAllocZ(cMod * sizeof(struct str_list));
if (RT_UNLIKELY(!StrList.sl_modlist))
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: failed to alloc memory for StrList.\n"));
return VERR_NO_MEMORY;
}
/*
* Get the list of all modules on the stack.
*/
int ret;
rc = strioctl(pVNode, I_LIST, (intptr_t)&StrList, 0, K_TO_K, kcred, &ret);
if (!rc)
{
/*
* Find our filter.
*/
for (int i = 0; i < StrList.sl_nmods; i++)
{
if (!strcmp(DEVICE_NAME, StrList.sl_modlist[i].l_name))
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: Success! Found %s at %d.\n", DEVICE_NAME, i));
*pModPos = i;
RTMemFree(StrList.sl_modlist);
return VINF_SUCCESS;
}
}
LogRel((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: failed to find %s in the host stack.\n"));
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: failed to get module information. rc=%d\n"));
RTMemFree(StrList.sl_modlist);
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisDetermineModPos: failed to get list of modules on host interface. rc=%d\n", rc));
return VERR_GENERAL_FAILURE;
}
#ifdef VBOX_WITH_NETFLT_SOLARIS_DLPISTYLE2
/**
* Opens up the DLPI style 2 link that requires explicit PPA attach
* phase.
*
* @param pThis The instance.
*/
static int vboxNetFltSolarisOpenStyle2(PVBOXNETFLTINS pThis, ldi_ident_t *pDevId)
{
/*
* Strip out PPA from the device name, eg: "ce3".
*/
char *pszDev = RTStrDup(pThis->szName);
char *pszEnd = strchr(pszDev, '\0');
int PPALen = 0;
while (--pszEnd > pszDev)
{
if (!ISDIGIT(*pszEnd))
break;
PPALen++;
}
pszEnd++;
char szDev[128];
RTStrPrintf(szDev, sizeof(szDev), "/dev/%s", pszDev);
RTStrFree(pszDev);
int rc;
long PPA;
if ( pszEnd
&& ddi_strtol(pszEnd, NULL, 10, &PPA) == 0)
{
pszEnd -= PPALen;
*pszEnd = '\0';
/*
* Try open the device as DPLI style 2.
*/
rc = ldi_open_by_name(szDev, FREAD | FWRITE, kcred, &pThis->u.s.hIface, *pDevId);
if (!rc)
{
/*
* Attach the PPA explictly.
*/
rc = dl_attach(pThis->u.s.hIface, (int)PPA, NULL);
if (!rc)
return VINF_SUCCESS;
ldi_close(pThis->u.s.hIface, FREAD | FWRITE, kcred);
LogRel((DEVICE_NAME ":vboxNetFltSolarisOpenStyle2 dl_attach failed. rc=%d\n", rc));
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisOpenStyle2 Failed to open szDev=%s\n", szDev));
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisOpenStyle2 Failed to construct PPA.\n"));
return VERR_INTNET_FLT_IF_FAILED;
}
#endif
/**
* Opens up dedicated stream on top of the interface.
* As a side-effect, the stream gets opened during
* the I_PUSH phase.
*
* @param pThis The instance.
*/
static int vboxNetFltSolarisOpenStream(PVBOXNETFLTINS pThis)
{
ldi_ident_t DevId;
DevId = ldi_ident_from_anon();
int ret;
/** @todo enable and test DLPI style 2.*/
/*
* Try style-1 open first.
*/
char szDev[128];
RTStrPrintf(szDev, sizeof(szDev), "/dev/net/%s", pThis->szName);
int rc = ldi_open_by_name(szDev, FREAD | FWRITE, kcred, &pThis->u.s.hIface, DevId);
if ( rc
&& rc == ENODEV) /* ENODEV is returned when resolvepath fails, not ENOENT */
{
/*
* Fallback to non-ClearView style-1 open.
*/
RTStrPrintf(szDev, sizeof(szDev), "/dev/%s", pThis->szName);
rc = ldi_open_by_name(szDev, FREAD | FWRITE, kcred, &pThis->u.s.hIface, DevId);
}
#ifdef VBOX_WITH_NETFLT_SOLARIS_DLPISTYLE2
if (rc)
{
/*
* Try DLPI style 2.
*/
rc = vboxNetFltSolarisOpenStyle2(pThis, &DevId);
if (RT_FAILURE(rc))
LogRel((DEVICE_NAME ":vboxNetFltSolarisOpenStream vboxNetFltSolarisOpenStyle2 failed. rc=%d\n", rc));
}
#endif
ldi_ident_release(DevId);
if (rc)
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisOpenStream Failed to open '%s' rc=%d pszName='%s'\n", szDev, rc, pThis->szName));
return VERR_INTNET_FLT_IF_FAILED;
}
rc = ldi_ioctl(pThis->u.s.hIface, I_FIND, (intptr_t)DEVICE_NAME, FKIOCTL, kcred, &ret);
if (!rc)
{
if (!ret)
{
g_VBoxNetFltSolarisInstance = pThis;
g_VBoxNetFltSolarisStreamType = kPromiscStream;
rc = ldi_ioctl(pThis->u.s.hIface, I_PUSH, (intptr_t)DEVICE_NAME, FKIOCTL, kcred, &ret);
g_VBoxNetFltSolarisInstance = NULL;
g_VBoxNetFltSolarisStreamType = kUndefined;
if (!rc)
return VINF_SUCCESS;
LogRel((DEVICE_NAME ":vboxNetFltSolarisOpenStream Failed to push filter onto host interface '%s'\n", pThis->szName));
}
else
return VINF_SUCCESS;
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisOpenStream Failed to search for filter in interface '%s'.\n", pThis->szName));
return VERR_INTNET_FLT_IF_FAILED;
}
/**
* Closes the interface, thereby closing the dedicated stream.
*
* @param pThis The instance.
*/
static void vboxNetFltSolarisCloseStream(PVBOXNETFLTINS pThis)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisCloseStream pThis=%p\n"));
vboxNetFltRetain(pThis, false /* fBusy */);
ldi_close(pThis->u.s.hIface, FREAD | FWRITE, kcred);
}
/**
* Dynamically attach under IPv4 and ARP streams on the host stack.
*
* @returns VBox status code.
* @param pThis The instance.
* @param fAttach Is this an attach or detach.
*/
static int vboxNetFltSolarisAttachIp4(PVBOXNETFLTINS pThis, bool fAttach)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachIp4 pThis=%p fAttach=%d\n", pThis, fAttach));
/*
* Statuatory Warning: Hackish code ahead.
*/
char *pszModName = DEVICE_NAME;
struct lifreq Ip4Interface;
bzero(&Ip4Interface, sizeof(Ip4Interface));
Ip4Interface.lifr_addr.ss_family = AF_INET;
strncpy(Ip4Interface.lifr_name, pThis->szName, sizeof(Ip4Interface.lifr_name));
struct strmodconf StrMod;
StrMod.mod_name = pszModName;
StrMod.pos = -1; /* this is filled in later. */
struct strmodconf ArpStrMod;
bcopy(&StrMod, &ArpStrMod, sizeof(StrMod));
int rc;
int rc2;
int ret;
ldi_ident_t DeviceIdent = ldi_ident_from_anon();
ldi_handle_t Ip4DevHandle;
ldi_handle_t ArpDevHandle;
/*
* Open the IP and ARP streams as layered devices.
*/
rc = ldi_open_by_name(IP_DEV_NAME, FREAD | FWRITE, kcred, &Ip4DevHandle, DeviceIdent);
if (rc)
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to open the IP stream on '%s'.\n", pThis->szName));
ldi_ident_release(DeviceIdent);
return VERR_INTNET_FLT_IF_FAILED;
}
rc = ldi_open_by_name("/dev/arp", FREAD | FWRITE, kcred, &ArpDevHandle, DeviceIdent);
if (rc)
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to open the ARP stream on '%s'.\n", pThis->szName));
ldi_ident_release(DeviceIdent);
ldi_close(Ip4DevHandle, FREAD | FWRITE, kcred);
return VERR_INTNET_FLT_IF_FAILED;
}
ldi_ident_release(DeviceIdent);
/*
* Obtain the interface flags from IPv4.
*/
rc = vboxNetFltSolarisGetIfFlags(Ip4DevHandle, &Ip4Interface);
if (RT_SUCCESS(rc))
{
/*
* Open the UDP stream. We sort of cheat here and obtain the vnode so that we can perform
* things that are not possible from the layered interface.
*/
vnode_t *pUdp4VNode = NULL;
vnode_t *pUdp4VNodeHeld = NULL;
TIUSER *pUdp4User = NULL;
rc = vboxNetFltSolarisOpenDev(UDP_DEV_NAME, &pUdp4VNode, &pUdp4VNodeHeld, &pUdp4User);
if (RT_SUCCESS(rc))
{
/*
* Get the multiplexor IDs.
*/
rc = ldi_ioctl(Ip4DevHandle, SIOCGLIFMUXID, (intptr_t)&Ip4Interface, FKIOCTL, kcred, &ret);
if (!rc)
{
/*
* Get the multiplex file descriptor to the lower streams. Generally this is lost
* once a module is I_PLINK, we need to reobtain it for inserting/removing ourselves from the stack.
*/
int Ip4MuxFd;
int ArpMuxFd;
rc = vboxNetFltSolarisMuxIdToFd(pUdp4VNode, Ip4Interface.lifr_ip_muxid, &Ip4MuxFd);
rc2 = vboxNetFltSolarisMuxIdToFd(pUdp4VNode, Ip4Interface.lifr_arp_muxid, &ArpMuxFd);
if ( RT_SUCCESS(rc)
&& RT_SUCCESS(rc2))
{
/*
* We need to I_PUNLINK on these multiplexor IDs before we can start
* operating on the lower stream as insertions are direct operations on the lower stream.
*/
int ret;
rc = strioctl(pUdp4VNode, I_PUNLINK, (intptr_t)Ip4Interface.lifr_ip_muxid, 0, K_TO_K, kcred, &ret);
rc2 = strioctl(pUdp4VNode, I_PUNLINK, (intptr_t)Ip4Interface.lifr_arp_muxid, 0, K_TO_K, kcred, &ret);
if ( !rc
&& !rc2)
{
/*
* Obtain the vnode from the useless userland file descriptor.
*/
file_t *pIpFile = getf(Ip4MuxFd);
file_t *pArpFile = getf(ArpMuxFd);
if ( pIpFile
&& pArpFile
&& pArpFile->f_vnode
&& pIpFile->f_vnode)
{
vnode_t *pIp4VNode = pIpFile->f_vnode;
vnode_t *pArpVNode = pArpFile->f_vnode;
/*
* Find the position on the host stack for attaching/detaching ourselves.
*/
rc = vboxNetFltSolarisDetermineModPos(fAttach, pIp4VNode, &StrMod.pos);
rc2 = vboxNetFltSolarisDetermineModPos(fAttach, pArpVNode, &ArpStrMod.pos);
if ( RT_SUCCESS(rc)
&& RT_SUCCESS(rc2))
{
/*
* Inject/Eject from the host IP stack.
*/
if (!fAttach)
vboxNetFltRetain(pThis, false /* fBusy */);
/*
* Set global data which will be grabbed by ModOpen.
* There is a known (though very unlikely) race here because
* of the inability to pass user data while inserting.
*/
g_VBoxNetFltSolarisInstance = pThis;
g_VBoxNetFltSolarisStreamType = kIp4Stream;
rc = strioctl(pIp4VNode, fAttach ? _I_INSERT : _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K,
kcred, &ret);
g_VBoxNetFltSolarisInstance = NULL;
g_VBoxNetFltSolarisStreamType = kUndefined;
if (!rc)
{
if (!fAttach)
vboxNetFltRetain(pThis, false /* fBusy */);
/*
* Inject/Eject from the host ARP stack.
*/
g_VBoxNetFltSolarisInstance = pThis;
g_VBoxNetFltSolarisStreamType = kArpStream;
rc = strioctl(pArpVNode, fAttach ? _I_INSERT : _I_REMOVE, (intptr_t)&ArpStrMod, 0, K_TO_K,
kcred, &ret);
g_VBoxNetFltSolarisInstance = NULL;
g_VBoxNetFltSolarisStreamType = kUndefined;
if (!rc)
{
/*
* Our job's not yet over; we need to relink the upper and lower streams
* otherwise we've pretty much screwed up the host interface.
*/
rc = vboxNetFltSolarisRelinkIp4(pUdp4VNode, &Ip4Interface, Ip4MuxFd, ArpMuxFd);
if (RT_SUCCESS(rc))
{
/*
* Close the devices ONLY during the return from function case; otherwise
* we end up close twice which is an instant kernel panic.
*/
vboxNetFltSolarisCloseDev(pUdp4VNodeHeld, pUdp4User);
ldi_close(ArpDevHandle, FREAD | FWRITE, kcred);
ldi_close(Ip4DevHandle, FREAD | FWRITE, kcred);
releasef(Ip4MuxFd);
releasef(ArpMuxFd);
LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: Success! %s %s@(IPv4:%d Arp:%d) "
"%s interface %s\n", fAttach ? "Injected" : "Ejected", StrMod.mod_name,
StrMod.pos, ArpStrMod.pos, fAttach ? "to" : "from", pThis->szName));
return VINF_SUCCESS;
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: Relinking failed. Mode=%s rc=%d.\n",
fAttach ? "inject" : "eject", rc));
}
/*
* Try failing gracefully during attach.
*/
if (fAttach)
strioctl(pArpVNode, _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K, kcred, &ret);
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to %s the ARP stack. rc=%d\n",
fAttach ? "inject into" : "eject from", rc));
}
if (fAttach)
strioctl(pIp4VNode, _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K, kcred, &ret);
vboxNetFltSolarisRelinkIp4(pUdp4VNode, &Ip4Interface, Ip4MuxFd, ArpMuxFd);
if (!fAttach)
vboxNetFltRelease(pThis, false /* fBusy */);
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to %s the IP stack. rc=%d\n",
fAttach ? "inject into" : "eject from", rc));
}
g_VBoxNetFltSolarisInstance = NULL;
g_VBoxNetFltSolarisStreamType = kUndefined;
if (!fAttach)
vboxNetFltRelease(pThis, false /* fBusy */);
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to find position. rc=%d rc2=%d\n", rc, rc2));
releasef(Ip4MuxFd);
releasef(ArpMuxFd);
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to get vnode from MuxFd.\n"));
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to unlink upper stream rc=%d rc2=%d.\n", rc, rc2));
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to get MuxFd from MuxId. rc=%d rc2=%d\n", rc, rc2));
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to get Mux Ids. rc=%d\n", rc));
vboxNetFltSolarisCloseDev(pUdp4VNodeHeld, pUdp4User);
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: failed to open UDP. rc=%d\n", rc));
}
else
{
/*
* This would happen for interfaces that are not plumbed.
*/
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp4: Warning: seems '%s' is unplumbed.\n", pThis->szName));
rc = VINF_SUCCESS;
}
ldi_close(ArpDevHandle, FREAD | FWRITE, kcred);
ldi_close(Ip4DevHandle, FREAD | FWRITE, kcred);
if (RT_SUCCESS(rc))
return rc;
return VERR_INTNET_FLT_IF_FAILED;
}
/**
* Dynamically attach under IPv6 on the host stack.
*
* @returns VBox status code.
* @param pThis The instance.
* @param fAttach Is this an attach or detach.
*/
static int vboxNetFltSolarisAttachIp6(PVBOXNETFLTINS pThis, bool fAttach)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachIp6 pThis=%p fAttach=%d\n", pThis, fAttach));
/*
* Statuatory Warning: Hackish code ahead.
*/
char *pszModName = DEVICE_NAME;
struct lifreq Ip6Interface;
bzero(&Ip6Interface, sizeof(Ip6Interface));
Ip6Interface.lifr_addr.ss_family = AF_INET6;
strncpy(Ip6Interface.lifr_name, pThis->szName, sizeof(Ip6Interface.lifr_name));
struct strmodconf StrMod;
StrMod.mod_name = pszModName;
StrMod.pos = -1; /* this is filled in later. */
int rc;
int rc2;
int ret;
ldi_ident_t DeviceIdent = ldi_ident_from_anon();
ldi_handle_t Ip6DevHandle;
ldi_handle_t Udp6DevHandle;
/*
* Open the IPv6 stream as a layered devices.
*/
rc = ldi_open_by_name(IP6_DEV_NAME, FREAD | FWRITE, kcred, &Ip6DevHandle, DeviceIdent);
ldi_ident_release(DeviceIdent);
if (rc)
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to open the IPv6 stream on '%s'.\n", pThis->szName));
return VERR_INTNET_FLT_IF_FAILED;
}
/*
* Obtain the interface flags from IPv6.
*/
rc = vboxNetFltSolarisGetIfFlags(Ip6DevHandle, &Ip6Interface);
if (RT_SUCCESS(rc))
{
/*
* Open the UDP stream. We sort of cheat here and obtain the vnode so that we can perform
* things that are not possible from the layered interface.
*/
vnode_t *pUdp6VNode = NULL;
vnode_t *pUdp6VNodeHeld = NULL;
TIUSER *pUdp6User = NULL;
rc = vboxNetFltSolarisOpenDev(UDP6_DEV_NAME, &pUdp6VNode, &pUdp6VNodeHeld, &pUdp6User);
if (RT_SUCCESS(rc))
{
/*
* Get the multiplexor IDs.
*/
rc = ldi_ioctl(Ip6DevHandle, SIOCGLIFMUXID, (intptr_t)&Ip6Interface, FKIOCTL, kcred, &ret);
if (!rc)
{
/*
* Get the multiplex file descriptor to the lower streams. Generally this is lost
* once a module is I_PLINK, we need to reobtain it for inserting/removing ourselves from the stack.
*/
int Ip6MuxFd;
rc = vboxNetFltSolarisMuxIdToFd(pUdp6VNode, Ip6Interface.lifr_ip_muxid, &Ip6MuxFd);
if (RT_SUCCESS(rc))
{
/*
* We need to I_PUNLINK on these multiplexor IDs before we can start
* operating on the lower stream as insertions are direct operations on the lower stream.
*/
int ret;
rc = strioctl(pUdp6VNode, I_PUNLINK, (intptr_t)Ip6Interface.lifr_ip_muxid, 0, K_TO_K, kcred, &ret);
if (!rc)
{
/*
* Obtain the vnode from the useless userland file descriptor.
*/
file_t *pIpFile = getf(Ip6MuxFd);
if ( pIpFile
&& pIpFile->f_vnode)
{
vnode_t *pIp6VNode = pIpFile->f_vnode;
/*
* Find the position on the host stack for attaching/detaching ourselves.
*/
rc = vboxNetFltSolarisDetermineModPos(fAttach, pIp6VNode, &StrMod.pos);
if (RT_SUCCESS(rc))
{
if (!fAttach)
vboxNetFltRetain(pThis, false /* fBusy */);
/*
* Set global data which will be grabbed by ModOpen.
* There is a known (though very unlikely) race here because
* of the inability to pass user data while inserting.
*/
g_VBoxNetFltSolarisInstance = pThis;
g_VBoxNetFltSolarisStreamType = kIp6Stream;
/*
* Inject/Eject from the host IPv6 stack.
*/
rc = strioctl(pIp6VNode, fAttach ? _I_INSERT : _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K,
kcred, &ret);
if (!rc)
{
g_VBoxNetFltSolarisInstance = NULL;
g_VBoxNetFltSolarisStreamType = kUndefined;
/*
* Our job's not yet over; we need to relink the upper and lower streams
* otherwise we've pretty much screwed up the host interface.
*/
rc = vboxNetFltSolarisRelinkIp6(pUdp6VNode, &Ip6Interface, Ip6MuxFd);
if (RT_SUCCESS(rc))
{
/*
* Close the devices ONLY during the return from function case; otherwise
* we end up close twice which is an instant kernel panic.
*/
vboxNetFltSolarisCloseDev(pUdp6VNodeHeld, pUdp6User);
ldi_close(Ip6DevHandle, FREAD | FWRITE, kcred);
releasef(Ip6MuxFd);
LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: Success! %s %s@(IPv6:%d) "
"%s interface %s\n", fAttach ? "Injected" : "Ejected", StrMod.mod_name,
StrMod.pos, fAttach ? "to" : "from", pThis->szName));
return VINF_SUCCESS;
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: Relinking failed. Mode=%s rc=%d.\n",
fAttach ? "inject" : "eject", rc));
}
if (fAttach)
strioctl(pIp6VNode, _I_REMOVE, (intptr_t)&StrMod, 0, K_TO_K, kcred, &ret);
vboxNetFltSolarisRelinkIp6(pUdp6VNode, &Ip6Interface, Ip6MuxFd);
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to %s the IP stack. rc=%d\n",
fAttach ? "inject into" : "eject from", rc));
if (!fAttach)
vboxNetFltRelease(pThis, false /* fBusy */);
}
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to find position. rc=%d rc2=%d\n", rc, rc2));
releasef(Ip6MuxFd);
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to get vnode from MuxFd.\n"));
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to unlink upper stream rc=%d rc2=%d.\n", rc, rc2));
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to get MuxFd from MuxId. rc=%d rc2=%d\n", rc, rc2));
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to get Mux Ids. rc=%d\n", rc));
vboxNetFltSolarisCloseDev(pUdp6VNodeHeld, pUdp6User);
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to open UDP. rc=%d\n", rc));
}
else
LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachIp6: failed to get IPv6 flags.\n", pThis->szName));
ldi_close(Ip6DevHandle, FREAD | FWRITE, kcred);
if (RT_SUCCESS(rc))
return rc;
return VERR_INTNET_FLT_IF_FAILED;
}
/**
* Wrapper for attaching ourselves to the interface.
*
* @returns VBox status code.
* @param pThis The instance.
*/
static int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis)
{
int rc = vboxNetFltSolarisOpenStream(pThis);
if (RT_SUCCESS(rc))
{
rc = vboxNetFltSolarisAttachIp4(pThis, true /* fAttach */);
if (RT_SUCCESS(rc))
{
vboxNetFltSolarisAttachIp6(pThis, true /* fAttach */);
/* Ignore Ipv6 binding errors as it's optional. */
ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, false);
}
else
vboxNetFltSolarisCloseStream(pThis);
}
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface vboxNetFltSolarisOpenStream failed rc=%Rrc\n", rc));
return rc;
}
/**
* Wrapper for detaching ourselves from the interface.
*
* @returns VBox status code.
* @param pThis The instance.
* @remarks Owns the globals mutex, so re-requesting it anytime during this phase
* would panic the system (e.g. in vboxNetFltSolarisFindInstance).
*/
static int vboxNetFltSolarisDetachFromInterface(PVBOXNETFLTINS pThis)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisDetachFromInterface pThis=%p\n", pThis));
ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, true);
vboxNetFltSolarisCloseStream(pThis);
int rc = vboxNetFltSolarisAttachIp4(pThis, false /* fAttach */);
if (pThis->u.s.pvIp6Stream)
rc = vboxNetFltSolarisAttachIp6(pThis, false /* fAttach */);
return rc;
}
/**
* Create a solaris message block from the SG list.
*
* @returns Solaris message block.
* @param pThis The instance.
* @param pSG Pointer to the scatter-gather list.
*/
static mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG pThis=%p pSG=%p\n"));
mblk_t *pMsg = allocb(pSG->cbTotal, BPRI_MED);
if (RT_UNLIKELY(!pMsg))
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG failed to alloc %d bytes for mblk_t.\n", pSG->cbTotal));
return NULL;
}
/*
* Single buffer copy. Maybe later explore the
* need/possibility for using a mblk_t chain rather.
*/
for (unsigned i = 0; i < pSG->cSegsUsed; i++)
{
if (pSG->aSegs[i].pv)
{
bcopy(pSG->aSegs[i].pv, pMsg->b_wptr, pSG->aSegs[i].cb);
pMsg->b_wptr += pSG->aSegs[i].cb;
}
}
DB_TYPE(pMsg) = M_DATA;
return pMsg;
}
/**
* Calculate the number of segments required for this message block.
*
* @returns Number of segments.
* @param pThis The instance
* @param pMsg Pointer to the data message.
*/
static unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg)
{
unsigned cSegs = 0;
for (mblk_t *pCur = pMsg; pCur; pCur = pCur->b_cont)
if (MBLKL(pCur))
cSegs++;
#ifdef PADD_RUNT_FRAMES_FROM_HOST
if (msgdsize(pMsg) < 60)
cSegs++;
#endif
NOREF(pThis);
return RT_MAX(cSegs, 1);
}
/**
* Initializes an SG list from the given message block.
*
* @returns VBox status code.
* @param pThis The instance.
* @param pMsg Pointer to the data message.
The caller must ensure it's not a control message block.
* @param pSG Pointer to the SG.
* @param cSegs Number of segments in the SG.
* This should match the number in the message block exactly!
* @param fSrc The source of the message.
*/
static int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pThis=%p pMsg=%p pSG=%p cSegs=%d\n", pThis, pMsg, pSG, cSegs));
pSG->pvOwnerData = NULL;
pSG->pvUserData = NULL;
pSG->pvUserData2 = NULL;
pSG->cUsers = 1;
pSG->cbTotal = 0;
pSG->fFlags = INTNETSG_FLAGS_TEMP;
pSG->cSegsAlloc = cSegs;
/*
* Convert the message block to segments.
*/
mblk_t *pCur = pMsg;
unsigned iSeg = 0;
while (pCur)
{
size_t cbSeg = MBLKL(pCur);
if (cbSeg)
{
void *pvSeg = pCur->b_rptr;
pSG->aSegs[iSeg].pv = pvSeg;
pSG->aSegs[iSeg].cb = cbSeg;
pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
pSG->cbTotal += cbSeg;
iSeg++;
}
pCur = pCur->b_cont;
}
pSG->cSegsUsed = iSeg;
#ifdef PADD_RUNT_FRAMES_FROM_HOST
if (pSG->cbTotal < 60 && (fSrc & INTNETTRUNKDIR_HOST))
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pulling up to length.\n"));
static uint8_t const s_abZero[128] = {0};
pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
pSG->aSegs[iSeg].pv = (void *)&s_abZero[0];
pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal;
pSG->cbTotal = 60;
pSG->cSegsUsed++;
}
#endif
LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG iSeg=%d pSG->cbTotal=%d msgdsize=%d\n", iSeg, pSG->cbTotal, msgdsize(pMsg)));
return VINF_SUCCESS;
}
/**
* Converts raw mode M_DATA messages to M_PROTO DL_UNITDATA_IND format.
*
* @returns VBox status code.
* @param pMsg Pointer to the raw message.
* @param pDlpiMsg Where to store the M_PROTO message.
*
* @remarks The original raw message would be no longer valid and will be
* linked as part of the new DLPI message. Callers must take care
* not to use the raw message if this routine is successful.
*/
static int vboxNetFltSolarisRawToUnitData(mblk_t *pMsg, mblk_t **ppDlpiMsg)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisRawToUnitData pMsg=%p\n", pMsg));
if (DB_TYPE(pMsg) != M_DATA)
return VERR_NO_MEMORY;
size_t cbMsg = sizeof(dl_unitdata_ind_t) + 2 * sizeof(vboxnetflt_dladdr_t);
mblk_t *pDlpiMsg = allocb(cbMsg, BPRI_MED);
if (RT_UNLIKELY(!pDlpiMsg))
return VERR_NO_MEMORY;
DB_TYPE(pDlpiMsg) = M_PROTO;
dl_unitdata_ind_t *pDlpiData = (dl_unitdata_ind_t *)pDlpiMsg->b_rptr;
pDlpiData->dl_primitive = DL_UNITDATA_IND;
pDlpiData->dl_dest_addr_length = VBOXNETFLT_DLADDRL;
pDlpiData->dl_dest_addr_offset = sizeof(dl_unitdata_ind_t);
pDlpiData->dl_src_addr_length = VBOXNETFLT_DLADDRL;
pDlpiData->dl_src_addr_offset = VBOXNETFLT_DLADDRL + sizeof(dl_unitdata_ind_t);
PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
vboxnetflt_dladdr_t *pDlAddr = (vboxnetflt_dladdr_t *)(pDlpiMsg->b_rptr + pDlpiData->dl_dest_addr_offset);
pDlAddr->SAP = RT_BE2H_U16(pEthHdr->EtherType);
bcopy(&pEthHdr->DstMac, &pDlAddr->Mac, sizeof(RTMAC));
pDlAddr = (vboxnetflt_dladdr_t *)(pDlpiMsg->b_rptr + pDlpiData->dl_src_addr_offset);
pDlAddr->SAP = RT_BE2H_U16(pEthHdr->EtherType);
bcopy(&pEthHdr->SrcMac, &pDlAddr->Mac, sizeof(RTMAC));
pDlpiMsg->b_wptr = pDlpiMsg->b_rptr + cbMsg;
/* Make the message point to the protocol header */
pMsg->b_rptr += sizeof(RTNETETHERHDR);
pDlpiMsg->b_cont = pMsg;
*ppDlpiMsg = pDlpiMsg;
return VINF_SUCCESS;
}
/**
* Converts DLPI M_PROTO messages to the raw mode M_DATA format.
*
* @returns VBox status code.
* @param pMsg Pointer to the M_PROTO message.
* @param ppRawMsg Where to store the converted message.
*
* @remarks If successful, the original pMsg is no longer valid, it will be deleted.
* Callers must take care not to continue to use pMsg after a successful
* call to this conversion routine.
*/
static int vboxNetFltSolarisUnitDataToRaw(PVBOXNETFLTINS pThis, mblk_t *pMsg, mblk_t **ppRawMsg)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisUnitDataToRaw pMsg=%p\n", pMsg));
if ( !pMsg->b_cont
|| DB_TYPE(pMsg) != M_PROTO)
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisUnitDataToRaw invalid input message.\n"));
return VERR_NET_PROTOCOL_ERROR;
}
/*
* Upstream consumers send/receive packets in the fast path mode.
* We of course need to convert them into raw ethernet frames.
*/
RTNETETHERHDR EthHdr;
union DL_primitives *pPrim = (union DL_primitives *)pMsg->b_rptr;
switch (pPrim->dl_primitive)
{
case DL_UNITDATA_IND:
{
/*
* Receive side.
*/
dl_unitdata_ind_t *pDlpiMsg = (dl_unitdata_ind_t *)pMsg->b_rptr;
bcopy(pMsg->b_rptr + pDlpiMsg->dl_dest_addr_offset, &EthHdr.DstMac, sizeof(EthHdr.DstMac));
bcopy(pMsg->b_rptr + pDlpiMsg->dl_src_addr_offset, &EthHdr.SrcMac, sizeof(EthHdr.SrcMac));
vboxnetflt_dladdr_t *pDLSapAddr = (vboxnetflt_dladdr_t *)(pMsg->b_rptr + pDlpiMsg->dl_dest_addr_offset);
EthHdr.EtherType = RT_H2BE_U16(pDLSapAddr->SAP);
break;
}
case DL_UNITDATA_REQ:
{
/*
* Send side.
*/
dl_unitdata_req_t *pDlpiMsg = (dl_unitdata_req_t *)pMsg->b_rptr;
bcopy(pMsg->b_rptr + pDlpiMsg->dl_dest_addr_offset, &EthHdr.DstMac, sizeof(EthHdr.DstMac));
bcopy(&pThis->u.s.Mac, &EthHdr.SrcMac, sizeof(EthHdr.SrcMac));
vboxnetflt_dladdr_t *pDLSapAddr = (vboxnetflt_dladdr_t *)(pMsg->b_rptr + pDlpiMsg->dl_dest_addr_offset);
EthHdr.EtherType = RT_H2BE_U16(pDLSapAddr->SAP);
break;
}
default:
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisUnitDataToRaw Unknown M_PROTO. This shouldn't be happening!!"));
return VERR_NET_PROTOCOL_ERROR;
}
}
/*
* Let us just link it as a mblk_t chain rather than re-copy the entire message.
* The vboxNetFltSolarisMBlkToSG function will handle chained mblk_t's.
*/
size_t cbLen = sizeof(EthHdr);
mblk_t *pEtherMsg = allocb(cbLen, BPRI_MED);
if (RT_UNLIKELY(!pEtherMsg))
return VERR_NO_MEMORY;
DB_TYPE(pEtherMsg) = M_DATA;
bcopy(&EthHdr, pEtherMsg->b_wptr, sizeof(EthHdr));
pEtherMsg->b_wptr += cbLen;
pEtherMsg->b_cont = pMsg->b_cont;
/*
* Change the chained blocks to type M_DATA.
*/
for (mblk_t *pTmp = pEtherMsg->b_cont; pTmp; pTmp = pTmp->b_cont)
DB_TYPE(pTmp) = M_DATA;
pMsg->b_cont = NULL;
freemsg(pMsg);
*ppRawMsg = pEtherMsg;
return VINF_SUCCESS;
}
/**
* Initializes a packet identifier.
*
* @param pTag Pointer to the packed identifier.
* @param pMsg Pointer to the message to be identified.
*
* @remarks Warning!!! This function assumes 'pMsg' is an unchained message.
*/
static inline void vboxNetFltSolarisInitPacketId(PVBOXNETFLTPACKETID pTag, mblk_t *pMsg)
{
PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr;
size_t cbMsg = MBLKL(pMsg);
pTag->cbPacket = cbMsg;
pTag->Checksum = RTCrc32(pMsg->b_rptr, cbMsg);
bcopy(&pEthHdr->SrcMac, &pTag->SrcMac, sizeof(RTMAC));
bcopy(&pEthHdr->DstMac, &pTag->DstMac, sizeof(RTMAC));
}
/**
* Queues a packet for loopback elimination.
*
* @returns VBox status code.
* @param pThis The instance.
* @param pPromiscStream Pointer to the promiscuous stream.
* @param pMsg Pointer to the message.
*/
static int vboxNetFltSolarisQueueLoopback(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg)
{
Assert(pThis);
Assert(pMsg);
Assert(DB_TYPE(pMsg) == M_DATA);
Assert(pPromiscStream);
LogFlow((DEVICE_NAME ":vboxNetFltSolarisQueueLoopback pThis=%p pPromiscStream=%p pMsg=%p\n", pThis, pPromiscStream, pMsg));
if (RT_UNLIKELY(pMsg->b_cont))
{
/*
* We don't currently make chained messages in on Xmit
* so this only needs to be supported when we do that.
*/
return VERR_NOT_SUPPORTED;
}
size_t cbMsg = MBLKL(pMsg);
if (RT_UNLIKELY(cbMsg < sizeof(RTNETETHERHDR)))
return VERR_NET_MSG_SIZE;
int rc = RTSemFastMutexRequest(pThis->u.s.hFastMtx);
AssertRCReturn(rc, rc);
PVBOXNETFLTPACKETID pCur = NULL;
if (pPromiscStream->cLoopback < VBOXNETFLT_LOOPBACK_SIZE
|| ( pPromiscStream->pHead
&& pPromiscStream->pHead->cbPacket == 0))
{
do
{
if (!pPromiscStream->pHead)
{
pCur = RTMemAlloc(sizeof(VBOXNETFLTPACKETID));
if (RT_UNLIKELY(!pCur))
{
rc = VERR_NO_MEMORY;
break;
}
vboxNetFltSolarisInitPacketId(pCur, pMsg);
pCur->pNext = NULL;
pPromiscStream->pHead = pCur;
pPromiscStream->pTail = pCur;
pPromiscStream->cLoopback++;
LogFlow((DEVICE_NAME ":vboxNetFltSolarisQueueLoopback initialized head. checksum=%u.\n",
pPromiscStream->pHead->Checksum));
break;
}
else if ( pPromiscStream->pHead
&& pPromiscStream->pHead->cbPacket == 0)
{
pCur = pPromiscStream->pHead;
vboxNetFltSolarisInitPacketId(pCur, pMsg);
LogFlow((DEVICE_NAME ":vboxNetFltSolarisQueueLoopback re-used head checksum=%u cLoopback=%d.\n",
pCur->Checksum, pPromiscStream->cLoopback));
break;
}
else
{
pCur = RTMemAlloc(sizeof(VBOXNETFLTPACKETID));
if (RT_UNLIKELY(!pCur))
{
rc = VERR_NO_MEMORY;
break;
}
vboxNetFltSolarisInitPacketId(pCur, pMsg);
pCur->pNext = pPromiscStream->pHead;
pPromiscStream->pHead = pCur;
pPromiscStream->cLoopback++;
LogFlow((DEVICE_NAME ":vboxNetFltSolarisQueueLoopback added head checksum=%u cLoopback=%d.\n", pCur->Checksum,
pPromiscStream->cLoopback));
break;
}
} while (0);
}
else
{
/*
* Maximum loopback queue size reached. Re-use tail as head.
*/
Assert(pPromiscStream->pHead);
Assert(pPromiscStream->pTail);
/*
* Find tail's previous item.
*/
PVBOXNETFLTPACKETID pPrev = NULL;
pCur = pPromiscStream->pHead;
/** @todo consider if this is worth switching to a double linked list... */
while (pCur != pPromiscStream->pTail)
{
pPrev = pCur;
pCur = pCur->pNext;
}
pPromiscStream->pTail = pPrev;
pPromiscStream->pTail->pNext = NULL;
pCur->pNext = pPromiscStream->pHead;
pPromiscStream->pHead = pCur;
vboxNetFltSolarisInitPacketId(pCur, pMsg);
LogFlow((DEVICE_NAME ":vboxNetFltSolarisQueueLoopback recycled tail!! checksum=%u cLoopback=%d\n", pCur->Checksum,
pPromiscStream->cLoopback));
}
RTSemFastMutexRelease(pThis->u.s.hFastMtx);
return rc;
}
/**
* Checks if the packet is enqueued for loopback as our own packet.
*
* @returns If it's our packet, returns true after dequeuing it, otherwise false.
* @param pThis The instance.
* @param pPromiscStream Pointer to the promiscuous stream.
* @param pMsg Pointer to the message.
*/
static bool vboxNetFltSolarisIsOurMBlk(PVBOXNETFLTINS pThis, vboxnetflt_promisc_stream_t *pPromiscStream, mblk_t *pMsg)
{
Assert(pThis);
Assert(pPromiscStream);
Assert(pMsg);
Assert(DB_TYPE(pMsg) == M_DATA);
LogFlow((DEVICE_NAME ":vboxNetFltSolarisIsOurMBlk pThis=%p pMsg=%p\n", pThis, pMsg));
if (pMsg->b_cont)
{
/** Handle this when Xmit makes chained messages */
return false;
}
size_t cbMsg = MBLKL(pMsg);
if (cbMsg < sizeof(RTNETETHERHDR))
return false;
int rc = RTSemFastMutexRequest(pThis->u.s.hFastMtx);
AssertRCReturn(rc, rc);
PVBOXNETFLTPACKETID pPrev = NULL;
PVBOXNETFLTPACKETID pCur = pPromiscStream->pHead;
bool fIsOurPacket = false;
while (pCur)
{
PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr;
if ( pCur->cbPacket != cbMsg
|| pCur->SrcMac.au8[0] != pEthHdr->SrcMac.au8[0]
|| pCur->SrcMac.au8[1] != pEthHdr->SrcMac.au8[1]
|| pCur->SrcMac.au8[2] != pEthHdr->SrcMac.au8[2]
|| pCur->SrcMac.au8[3] != pEthHdr->SrcMac.au8[3]
|| pCur->SrcMac.au8[4] != pEthHdr->SrcMac.au8[4]
|| pCur->SrcMac.au8[5] != pEthHdr->SrcMac.au8[5]
|| pCur->DstMac.au8[0] != pEthHdr->DstMac.au8[0]
|| pCur->DstMac.au8[1] != pEthHdr->DstMac.au8[1]
|| pCur->DstMac.au8[2] != pEthHdr->DstMac.au8[2]
|| pCur->DstMac.au8[3] != pEthHdr->DstMac.au8[3]
|| pCur->DstMac.au8[4] != pEthHdr->DstMac.au8[4]
|| pCur->DstMac.au8[5] != pEthHdr->DstMac.au8[5])
{
pPrev = pCur;
pCur = pCur->pNext;
continue;
}
uint16_t Checksum = RTCrc32(pMsg->b_rptr, cbMsg);
if (pCur->Checksum != Checksum)
{
pPrev = pCur;
pCur = pCur->pNext;
continue;
}
/*
* Yes, it really is our own packet, mark it as handled
* and move it as a "free slot" to the head and return success.
*/
pCur->cbPacket = 0;
if (pPrev)
{
if (!pCur->pNext)
pPromiscStream->pTail = pPrev;
pPrev->pNext = pCur->pNext;
pCur->pNext = pPromiscStream->pHead;
pPromiscStream->pHead = pCur;
}
fIsOurPacket = true;
LogFlow((DEVICE_NAME ":vboxNetFltSolarisIsOurMBlk found packet %p Checksum=%u cLoopback=%d\n", pMsg, Checksum,
pPromiscStream->cLoopback));
break;
}
RTSemFastMutexRelease(pThis->u.s.hFastMtx);
return fIsOurPacket;
}
/**
* Worker for routing messages from the wire or from the host.
*
* @returns VBox status code.
* @param pThis The instance.
* @param pStream Pointer to the stream.
* @param pQueue Pointer to the read queue.
* @param pOrigMsg Pointer to the message.
*/
static int vboxNetFltSolarisRecv(PVBOXNETFLTINS pThis, vboxnetflt_stream_t *pStream, queue_t *pQueue, mblk_t *pMsg)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv pThis=%p pMsg=%p\n", pThis, pMsg));
AssertCompile(sizeof(struct ether_header) == sizeof(RTNETETHERHDR));
Assert(pStream->Type == kPromiscStream);
vboxnetflt_promisc_stream_t *pPromiscStream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvPromiscStream);
if (RT_UNLIKELY(!pPromiscStream))
{
LogRel((DEVICE_NAME ":Promiscuous stream missing!! Failing to receive packet.\n"));
return VERR_INVALID_POINTER;
}
/*
* Don't loopback packets we transmit to the wire.
*/
/** @todo maybe we need not check for loopback for INTNETTRUNKDIR_HOST case? */
if (vboxNetFltSolarisIsOurMBlk(pThis, pPromiscStream, pMsg))
{
LogFlow((DEVICE_NAME ":Avoiding packet loopback.\n"));
return VINF_SUCCESS;
}
/*
* Figure out the source of the packet based on the source Mac address.
*/
uint32_t fSrc = INTNETTRUNKDIR_WIRE;
PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
if (vboxNetFltPortOsIsHostMac(pThis, &pEthHdr->SrcMac))
fSrc = INTNETTRUNKDIR_HOST;
/*
* Afaik; we no longer need to worry about incorrect checksums because we now use
* a dedicated stream and don't intercept packets under IP/ARP which might be doing
* checksum offloading.
*/
#if 0
if (fSrc & INTNETTRUNKDIR_HOST)
{
mblk_t *pCorrectedMsg = vboxNetFltSolarisFixChecksums(pMsg);
if (pCorrectedMsg)
pMsg = pCorrectedMsg;
}
vboxNetFltSolarisAnalyzeMBlk(pMsg);
#endif
/*
* Route all received packets into the internal network.
*/
unsigned cSegs = vboxNetFltSolarisMBlkCalcSGSegs(pThis, pMsg);
PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
int rc = vboxNetFltSolarisMBlkToSG(pThis, pMsg, pSG, cSegs, fSrc);
if (RT_SUCCESS(rc))
pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, fSrc);
else
LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG failed. rc=%d\n", rc));
return VINF_SUCCESS;
}
/**
* Finalize the message to be fed into the internal network.
* Verifies and tries to fix checksums for TCP, UDP and IP.
*
* @returns Corrected message or NULL if no change was required.
* @param pMsg Pointer to the message block.
* This must not be DLPI linked messages, must be M_DATA.
*
* @remarks If this function returns a checksum adjusted message, the
* passed in input message has been freed and should not be
* referenced anymore by the caller.
*/
static mblk_t *vboxNetFltSolarisFixChecksums(mblk_t *pMsg)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisFixChecksums pMsg=%p\n"));
Assert(DB_TYPE(pMsg) == M_DATA);
if (MBLKL(pMsg) < sizeof(RTNETETHERHDR))
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisFixChecksums Packet shorter than ethernet header size!\n"));
return NULL;
}
PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
{
/*
* Check if we have a complete packet or being fed a chain.
*/
size_t cbIpPacket = 0;
mblk_t *pFullMsg = NULL;
if (pMsg->b_cont)
{
LogFlow((DEVICE_NAME ":Chained mblk_t.\n"));
/*
* Handle chain by making a packet copy to verify if the IP checksum is correct.
* Contributions to calculating IP checksums from a chained message block with
* odd/non-pulled up sizes are welcome.
*/
size_t cbFullMsg = msgdsize(pMsg);
mblk_t *pFullMsg = allocb(cbFullMsg, BPRI_MED);
LogFlow((DEVICE_NAME ":msgdsize returns %d\n", cbFullMsg));
if (RT_UNLIKELY(!pFullMsg))
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisFixChecksums failed to alloc new message of %d bytes.\n", cbFullMsg));
return NULL;
}
for (mblk_t *pTmp = pMsg; pTmp; pTmp = pTmp->b_cont)
{
if (DB_TYPE(pTmp) == M_DATA)
{
bcopy(pTmp->b_rptr, pFullMsg->b_wptr, MBLKL(pTmp));
pFullMsg->b_wptr += MBLKL(pTmp);
}
}
DB_TYPE(pFullMsg) = M_DATA;
pEthHdr = (PRTNETETHERHDR)pFullMsg->b_rptr;
cbIpPacket = MBLKL(pFullMsg) - sizeof(RTNETETHERHDR);
}
else
cbIpPacket = MBLKL(pMsg) - sizeof(RTNETETHERHDR);
/*
* Check if the IP checksum is valid.
*/
uint8_t *pbProtocol = (uint8_t *)(pEthHdr + 1);
PRTNETIPV4 pIpHdr = (PRTNETIPV4)pbProtocol;
size_t cbPayload = cbIpPacket - (pIpHdr->ip_hl << 2);
bool fChecksumAdjusted = false;
if (RTNetIPv4IsHdrValid(pIpHdr, cbPayload, cbPayload))
{
pbProtocol += (pIpHdr->ip_hl << 2);
/*
* Fix up TCP/UDP and IP checksums if they're incomplete/invalid.
*/
if (pIpHdr->ip_p == RTNETIPV4_PROT_TCP)
{
PRTNETTCP pTcpHdr = (PRTNETTCP)pbProtocol;
uint16_t TcpChecksum = RTNetIPv4TCPChecksum(pIpHdr, pTcpHdr, NULL);
if (pTcpHdr->th_sum != TcpChecksum)
{
pTcpHdr->th_sum = TcpChecksum;
fChecksumAdjusted = true;
LogFlow((DEVICE_NAME ":fixed TCP checksum.\n"));
}
}
else if (pIpHdr->ip_p == RTNETIPV4_PROT_UDP)
{
PRTNETUDP pUdpHdr = (PRTNETUDP)pbProtocol;
uint16_t UdpChecksum = RTNetIPv4UDPChecksum(pIpHdr, pUdpHdr, pUdpHdr + 1);
if (pUdpHdr->uh_sum != UdpChecksum)
{
pUdpHdr->uh_sum = UdpChecksum;
fChecksumAdjusted = true;
LogFlow((DEVICE_NAME ":Fixed UDP checksum."));
}
}
}
if (fChecksumAdjusted)
{
/*
* If we made a copy and the checksum is corrected on the copy,
* free the original, return the checksum fixed copy.
*/
if (pFullMsg)
{
freemsg(pMsg);
return pFullMsg;
}
return pMsg;
}
/*
* If we made a copy and the checksum is NOT corrected, free the copy,
* and return NULL.
*/
if (pFullMsg)
freemsg(pFullMsg);
return NULL;
}
return NULL;
}
/**
* Simple packet dump, used for internal debugging.
*
* @param pMsg Pointer to the message to analyze and dump.
*/
static void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg)
{
LogFlow((DEVICE_NAME ":vboxNetFltSolarisAnalyzeMBlk pMsg=%p\n", pMsg));
PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr;
uint8_t *pb = pMsg->b_rptr;
if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
{
PRTNETIPV4 pIpHdr = (PRTNETIPV4)(pEthHdr + 1);
size_t cbLen = MBLKL(pMsg) - sizeof(*pEthHdr);
if (!pMsg->b_cont)
{
if (pIpHdr->ip_p == RTNETIPV4_PROT_ICMP)
LogFlow((DEVICE_NAME ":ICMP D=%.6Rhxs S=%.6Rhxs T=%04x\n", pb, pb + 6, RT_BE2H_U16(*(uint16_t *)(pb + 12))));
else if (pIpHdr->ip_p == RTNETIPV4_PROT_TCP)
LogFlow((DEVICE_NAME ":TCP D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6));
else if (pIpHdr->ip_p == RTNETIPV4_PROT_UDP)
{
PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint32_t *)pIpHdr + pIpHdr->ip_hl);
if ( RT_BE2H_U16(pUdpHdr->uh_sport) == 67
&& RT_BE2H_U16(pUdpHdr->uh_dport) == 68)
{
LogRel((DEVICE_NAME ":UDP bootp ack D=%.6Rhxs S=%.6Rhxs UDP_CheckSum=%04x Computex=%04x\n", pb, pb + 6,
RT_BE2H_U16(pUdpHdr->uh_sum), RT_BE2H_U16(RTNetIPv4UDPChecksum(pIpHdr, pUdpHdr, pUdpHdr + 1))));
}
}
}
else
{
LogFlow((DEVICE_NAME ":Chained IP packet. Skipping validity check.\n"));
}
}
else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_VLAN))
{
typedef struct VLANHEADER
{
int Pcp:3;
int Cfi:1;
int Vid:12;
} VLANHEADER;
VLANHEADER *pVlanHdr = (VLANHEADER *)(pMsg->b_rptr + sizeof(RTNETETHERHDR));
LogFlow((DEVICE_NAME ":VLAN Pcp=%d Cfi=%d Id=%d\n", pVlanHdr->Pcp, pVlanHdr->Cfi, pVlanHdr->Vid >> 4));
LogFlow((DEVICE_NAME "%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr));
}
else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP))
{
PRTNETARPHDR pArpHdr = (PRTNETARPHDR)(pEthHdr + 1);
LogFlow((DEVICE_NAME ":ARP Op=%d\n", pArpHdr->ar_oper));
}
else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
{
LogFlow((DEVICE_NAME ":IPv6 D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6));
}
else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_1)
|| pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_2)
|| pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_3))
{
LogFlow((DEVICE_NAME ":IPX packet.\n"));
}
else
{
LogFlow((DEVICE_NAME ":Unknown EtherType=%x D=%.6Rhxs S=%.6Rhxs\n", RT_H2BE_U16(pEthHdr->EtherType), &pEthHdr->DstMac,
&pEthHdr->SrcMac));
/* LogFlow((DEVICE_NAME ":%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr)); */
}
}
/* -=-=-=-=-=- Common Hooks -=-=-=-=-=- */
bool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis)
{
/*
* There is no easy way of obtaining the global host side promiscuous counter.
* Currently we just return false.
*/
return false;
}
void vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac)
{
LogFlow((DEVICE_NAME ":vboxNetFltPortOsGetMacAddress pThis=%p\n", pThis));
*pMac = pThis->u.s.Mac;
}
bool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac)
{
/*
* MAC address change acknowledgements are intercepted on the read side
* hence theoritically we are always update to date with any changes.
*/
return pThis->u.s.Mac.au16[0] == pMac->au16[0]
&& pThis->u.s.Mac.au16[1] == pMac->au16[1]
&& pThis->u.s.Mac.au16[2] == pMac->au16[2];
}
void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
{
LogFlow((DEVICE_NAME ":vboxNetFltPortOsSetActive pThis=%p fActive=%d\n", pThis, fActive));
/*
* Enable/disable promiscuous mode.
*/
vboxnetflt_stream_t *pStream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvPromiscStream);
if (pStream)
{
if (pStream->pReadQueue)
{
int rc = vboxNetFltSolarisPromiscReq(pStream->pReadQueue, fActive);
if (RT_FAILURE(rc))
LogRel((DEVICE_NAME ":vboxNetFltPortOsSetActive failed to request promiscuous mode! rc=%d\n", rc));
}
else
LogRel((DEVICE_NAME ":vboxNetFltPortOsSetActive queue not found!\n"));
}
else
LogRel((DEVICE_NAME ":vboxNetFltPortOsSetActive stream not found!\n"));
}
int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis)
{
LogFlow((DEVICE_NAME ":vboxNetFltOsDisconnectIt pThis=%p\n", pThis));
vboxNetFltSolarisDetachFromInterface(pThis);
if (pThis->u.s.hFastMtx != NIL_RTSEMFASTMUTEX)
{
RTSemFastMutexDestroy(pThis->u.s.hFastMtx);
pThis->u.s.hFastMtx = NIL_RTSEMFASTMUTEX;
}
return VINF_SUCCESS;
}
int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis)
{
/* Nothing to do here. */
return VINF_SUCCESS;
}
void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
{
LogFlow((DEVICE_NAME ":vboxNetFltOsDeleteInstance pThis=%p\n", pThis));
/* Nothing to do here. */
}
int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
{
LogFlow((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p\n"));
/*
* Mutex used for loopback lockouts.
*/
int rc = RTSemFastMutexCreate(&pThis->u.s.hFastMtx);
if (RT_SUCCESS(rc))
{
rc = vboxNetFltSolarisAttachToInterface(pThis);
if (RT_SUCCESS(rc))
return rc;
LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed. rc=%Rrc\n", rc));
RTSemFastMutexDestroy(pThis->u.s.hFastMtx);
pThis->u.s.hFastMtx = NIL_RTSEMFASTMUTEX;
}
else
LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to create mutex. rc=%Rrc\n", rc));
NOREF(pvContext);
return rc;
}
int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
{
/*
* Init. the solaris specific data.
*/
pThis->u.s.pvIp4Stream = NULL;
pThis->u.s.pvIp6Stream = NULL;
pThis->u.s.pvArpStream = NULL;
pThis->u.s.pvPromiscStream = NULL;
pThis->u.s.hFastMtx = NIL_RTSEMFASTMUTEX;
bzero(&pThis->u.s.Mac, sizeof(pThis->u.s.Mac));
return VINF_SUCCESS;
}
bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
{
/*
* We don't support interface rediscovery on Solaris hosts because the
* filter is very tightly bound to the stream.
*/
return false;
}
int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst)
{
LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit pThis=%p pSG=%p fDst=%d\n", pThis, pSG, fDst));
int rc = VINF_SUCCESS;
if (fDst & INTNETTRUNKDIR_WIRE)
{
#ifdef VBOXNETFLT_SOLARIS_USE_NETINFO
/*
* @todo try find a way for IPFilter to accept ethernet frames (currently silently drops them).
*/
mblk_t *pMsg = vboxNetFltSolarisMBlkFromSG(pThis, pSG, fDst);
if (RT_LIKELY(pMsg))
{
PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr;
unsigned uProtocol;
if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
uProtocol = AF_INET6;
else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
uProtocol = AF_INET;
/*
* Queue out using netinfo.
*/
netstack_t *pNetStack = netstack_get_current();
if (pNetStack)
{
net_data_t pNetData = net_lookup_impl(NHF_INET, pNetStack);
if (pNetData)
{
phy_if_t pInterface = net_phylookup(pNetData, pThis->szName);
if (pInterface)
{
net_inject_t InjectData;
InjectData.ni_packet = pMsg;
InjectData.ni_physical = pInterface;
bzero(&InjectData.ni_addr, sizeof(InjectData.ni_addr));
InjectData.ni_addr.ss_family = uProtocol;
/*
* Queue out rather than direct out transmission.
*/
int rc = net_inject(pNetData, NI_QUEUE_OUT, &InjectData);
if (!rc)
rc = VINF_SUCCESS;
else
{
LogRel((DEVICE_NAME ":queuing IP packet for transmission failed. rc=%d\n", rc));
rc = VERR_NET_IO_ERROR;
}
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit failed to lookup physical interface.\n"));
rc = VERR_NET_IO_ERROR;
}
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit failed to get IP hooks.\n"));
rc = VERR_NET_IO_ERROR;
}
netstack_rele(pNetStack);
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit failed to get current net stack.\n"));
rc = VERR_NET_IO_ERROR;
}
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit vboxNetFltSolarisMBlkFromSG failed.\n"));
rc = VERR_NO_MEMORY;
}
#else
vboxnetflt_promisc_stream_t *pPromiscStream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvPromiscStream);
if (RT_LIKELY(pPromiscStream))
{
mblk_t *pMsg = vboxNetFltSolarisMBlkFromSG(pThis, pSG, fDst);
if (RT_LIKELY(pMsg))
{
LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit INTNETTRUNKDIR_WIRE\n"));
vboxNetFltSolarisQueueLoopback(pThis, pPromiscStream, pMsg);
putnext(WR(pPromiscStream->Stream.pReadQueue), pMsg);
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit vboxNetFltSolarisMBlkFromSG failed.\n"));
rc = VERR_NO_MEMORY;
}
}
#endif
}
if (fDst & INTNETTRUNKDIR_HOST)
{
/*
* For unplumbed interfaces we would not be bound to IP or ARP.
* We either bind to both or neither; so atomic reading one should be sufficient.
*/
vboxnetflt_stream_t *pIp4Stream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvIp4Stream);
if (!pIp4Stream)
return rc;
/*
* Create a message block and send it up the host stack (upstream).
*/
mblk_t *pMsg = vboxNetFltSolarisMBlkFromSG(pThis, pSG, fDst);
if (RT_LIKELY(pMsg))
{
PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr;
/*
* Send message up ARP stream.
*/
if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP))
{
LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit INTNETTRUNKDIR_HOST ARP\n"));
vboxnetflt_stream_t *pArpStream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvArpStream);
if (pArpStream)
{
/*
* Construct a DL_UNITDATA_IND style message for ARP as it doesn't understand fast path.
*/
mblk_t *pDlpiMsg;
int rc = vboxNetFltSolarisRawToUnitData(pMsg, &pDlpiMsg);
if (RT_SUCCESS(rc))
{
pMsg = pDlpiMsg;
queue_t *pArpReadQueue = pArpStream->pReadQueue;
putnext(pArpReadQueue, pMsg);
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisRawToUnitData failed!\n"));
freemsg(pMsg);
rc = VERR_NO_MEMORY;
}
}
else
freemsg(pMsg); /* Should really never happen... */
}
else
{
vboxnetflt_stream_t *pIp6Stream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvIp6Stream);
if ( pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6)
&& pIp6Stream)
{
/*
* Send messages up IPv6 stream.
*/
LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit INTNETTRUNKDIR_HOST IPv6\n"));
pMsg->b_rptr += sizeof(RTNETETHERHDR);
queue_t *pIp6ReadQueue = pIp6Stream->pReadQueue;
putnext(pIp6ReadQueue, pMsg);
}
else
{
/*
* Send messages up IPv4 stream.
*/
LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit INTNETTRUNKDIR_HOST IPv4\n"));
pMsg->b_rptr += sizeof(RTNETETHERHDR);
queue_t *pIp4ReadQueue = pIp4Stream->pReadQueue;
putnext(pIp4ReadQueue, pMsg);
}
}
}
else
{
LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG failed.\n"));
rc = VERR_NO_MEMORY;
}
}
return rc;
}