VirtualBox

Changeset 55652 in vbox for trunk/src


Ignore:
Timestamp:
May 5, 2015 3:28:45 AM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
100033
Message:

IntNet/NetFlt: blacklist host's L3 addresses when bridging to wifi. Implemented on Linux and OS X for now.

Location:
trunk/src/VBox
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp

    r54868 r55652  
    162162/** Pointer to a const destination table. */
    163163typedef INTNETDSTTAB const *PCINTNETDSTTAB;
    164 
    165 
    166 /** Network layer address type. */
    167 typedef enum INTNETADDRTYPE
    168 {
    169     /** The invalid 0 entry. */
    170     kIntNetAddrType_Invalid = 0,
    171     /** IP version 4. */
    172     kIntNetAddrType_IPv4,
    173     /** IP version 6. */
    174     kIntNetAddrType_IPv6,
    175     /** IPX. */
    176     kIntNetAddrType_IPX,
    177     /** The end of the valid values. */
    178     kIntNetAddrType_End,
    179     /** The usual 32-bit hack. */
    180     kIntNetAddrType_32BitHack = 0x7fffffff
    181 } INTNETADDRTYPE;
    182 /** Pointer to a network layer address type. */
    183 typedef INTNETADDRTYPE *PINTNETADDRTYPE;
    184 
    185164
    186165/**
     
    356335    struct INTNETNETWORK   *pNext;
    357336
    358     /** The spinlock protecting MacTab and INTNETTRUNKIF::aAddrCache.
     337    /** The spinlock protecting MacTab, aAddrBlacklist and INTNETIF::aAddrCache.
    359338     *  Interrupt safe. */
    360339    RTSPINLOCK              hAddrSpinlock;
     
    362341     * This doubles as interface collection. */
    363342    INTNETMACTAB            MacTab;
     343
     344    /** The network layer address cache. (Indexed by type, 0 entry isn't used.
     345     * Contains host addresses.  We don't let guests spoof them. */
     346    INTNETADDRCACHE         aAddrBlacklist[kIntNetAddrType_End];
    364347
    365348    /** Wait for an interface to stop being busy so it can be removed or have its
     
    11681151 * @param   pszMsg          Log message.
    11691152 */
    1170 DECLINLINE(void) intnetR0NetworkAddrCacheDelete(PINTNETNETWORK pNetwork, PCRTNETADDRU pAddr, INTNETADDRTYPE const enmType,
    1171                                                 uint8_t const cbAddr, const char *pszMsg)
    1172 {
    1173     RTSpinlockAcquire(pNetwork->hAddrSpinlock);
    1174 
     1153DECLINLINE(void) intnetR0NetworkAddrCacheDeleteUnlocked(PINTNETNETWORK pNetwork,
     1154                                                        PCRTNETADDRU pAddr, INTNETADDRTYPE enmType,
     1155                                                        uint8_t const cbAddr,
     1156                                                        const char *pszMsg)
     1157{
    11751158    uint32_t iIf = pNetwork->MacTab.cEntries;
    11761159    while (iIf--)
    11771160    {
    11781161        PINTNETIF pIf = pNetwork->MacTab.paEntries[iIf].pIf;
     1162
    11791163        int i = intnetR0IfAddrCacheLookup(&pIf->aAddrCache[enmType], pAddr, cbAddr);
    11801164        if (RT_UNLIKELY(i >= 0))
    11811165            intnetR0IfAddrCacheDeleteIt(pIf, &pIf->aAddrCache[enmType], i, pszMsg);
    11821166    }
     1167}
     1168
     1169
     1170/**
     1171 * Deletes the address from all the interface caches.
     1172 *
     1173 * This is used to remove stale entries that has been reassigned to
     1174 * other machines on the network.
     1175 *
     1176 * @param   pNetwork        The network.
     1177 * @param   pAddr           The address.
     1178 * @param   enmType         The address type.
     1179 * @param   cbAddr          The address size (optimization).
     1180 * @param   pszMsg          Log message.
     1181 */
     1182DECLINLINE(void) intnetR0NetworkAddrCacheDelete(PINTNETNETWORK pNetwork, PCRTNETADDRU pAddr, INTNETADDRTYPE const enmType,
     1183                                                uint8_t const cbAddr, const char *pszMsg)
     1184{
     1185    RTSpinlockAcquire(pNetwork->hAddrSpinlock);
     1186
     1187    intnetR0NetworkAddrCacheDeleteUnlocked(pNetwork, pAddr, enmType, cbAddr, pszMsg);
    11831188
    11841189    RTSpinlockRelease(pNetwork->hAddrSpinlock);
     
    12531258
    12541259/**
     1260 * Look up specified address in the network's blacklist.
     1261 *
     1262 * @param pNetwork      The network.
     1263 * @param enmType       The address type.
     1264 * @param pAddr         The address.
     1265 */
     1266static bool intnetR0NetworkBlacklistLookup(PINTNETNETWORK pNetwork,
     1267                                           PCRTNETADDRU pAddr, INTNETADDRTYPE enmType)
     1268{
     1269    PINTNETADDRCACHE pCache = &pNetwork->aAddrBlacklist[enmType];
     1270
     1271    if (RT_UNLIKELY(pCache->cEntriesAlloc == 0))
     1272        return false;
     1273
     1274    const uint8_t cbAddr = pCache->cbAddress;
     1275    Assert(cbAddr == intnetR0AddrSize(enmType));
     1276
     1277    for (unsigned i = 0; i < pCache->cEntries; ++i)
     1278    {
     1279        uint8_t *pbEntry = pCache->pbEntries + pCache->cbEntry * i;
     1280        if (intnetR0AddrUIsEqualEx((PCRTNETADDRU)pbEntry, pAddr, cbAddr))
     1281            return true;
     1282    }
     1283
     1284    return false;
     1285}
     1286
     1287
     1288/**
     1289 * Deletes specified address from network's blacklist.
     1290 *
     1291 * @param pNetwork      The network.
     1292 * @param enmType       The address type.
     1293 * @param pAddr         The address.
     1294 */
     1295static void intnetR0NetworkBlacklistDelete(PINTNETNETWORK pNetwork,
     1296                                           PCRTNETADDRU pAddr, INTNETADDRTYPE enmType)
     1297{
     1298    PINTNETADDRCACHE pCache = &pNetwork->aAddrBlacklist[enmType];
     1299
     1300    if (RT_UNLIKELY(pCache->cEntriesAlloc == 0))
     1301        return;
     1302
     1303    const uint8_t cbAddr = pCache->cbAddress;
     1304    Assert(cbAddr == intnetR0AddrSize(enmType));
     1305
     1306    for (unsigned i = 0; i < pCache->cEntries; ++i)
     1307    {
     1308        uint8_t *pbEntry = pCache->pbEntries + pCache->cbEntry * i;
     1309        if (!intnetR0AddrUIsEqualEx((PCRTNETADDRU)pbEntry, pAddr, cbAddr))
     1310            continue;
     1311
     1312        --pCache->cEntries;
     1313        memmove(pCache->pbEntries + i * pCache->cbEntry,
     1314                pCache->pbEntries + (i + 1) * pCache->cbEntry,
     1315                (pCache->cEntries - i) * pCache->cbEntry);
     1316        return;
     1317    }
     1318}
     1319
     1320
     1321/**
     1322 * Adds specified address from network's blacklist.
     1323 *
     1324 * @param pNetwork      The network.
     1325 * @param enmType       The address type.
     1326 * @param pAddr         The address.
     1327 */
     1328static void intnetR0NetworkBlacklistAdd(PINTNETNETWORK pNetwork,
     1329                                        PCRTNETADDRU pAddr, INTNETADDRTYPE enmType)
     1330{
     1331    PINTNETADDRCACHE pCache = &pNetwork->aAddrBlacklist[enmType];
     1332
     1333    if (RT_UNLIKELY(pCache->cEntriesAlloc == 0))
     1334        return;
     1335
     1336    const uint8_t cbAddr = pCache->cbAddress;
     1337    Assert(cbAddr == intnetR0AddrSize(enmType));
     1338
     1339    /* lookup */
     1340    for (unsigned i = 0; i < pCache->cEntries; ++i)
     1341    {
     1342        uint8_t *pbEntry = pCache->pbEntries + pCache->cbEntry * i;
     1343        if (RT_UNLIKELY(intnetR0AddrUIsEqualEx((PCRTNETADDRU)pbEntry, pAddr, cbAddr)))
     1344            return; /* already exists */
     1345    }
     1346
     1347    if (pCache->cEntries >= pCache->cEntriesAlloc)
     1348    {
     1349        /* shift */
     1350        memmove(pCache->pbEntries, pCache->pbEntries + pCache->cbEntry,
     1351                pCache->cbEntry * (pCache->cEntries - 1));
     1352        --pCache->cEntries;
     1353    }
     1354
     1355    Assert(pCache->cEntries < pCache->cEntriesAlloc);
     1356
     1357    /* push */
     1358    uint8_t *pbEntry = pCache->pbEntries + pCache->cEntries * pCache->cbEntry;
     1359    memcpy(pbEntry, pAddr, cbAddr);
     1360    memset(pbEntry + pCache->cbAddress, '\0', pCache->cbEntry - cbAddr);
     1361    ++pCache->cEntries;
     1362
     1363    Assert(pCache->cEntries <= pCache->cEntriesAlloc);
     1364}
     1365
     1366
     1367/**
    12551368 * Adds an address to the cache, the caller is responsible for making sure it's
    12561369 * not already in the cache.
     
    12631376 * @param   pszMsg      log message.
    12641377 */
    1265 static void intnetR0IfAddrCacheAddIt(PINTNETIF pIf, PINTNETADDRCACHE pCache, PCRTNETADDRU pAddr, const char *pszMsg)
     1378static void intnetR0IfAddrCacheAddIt(PINTNETIF pIf, INTNETADDRTYPE enmAddrType, PCRTNETADDRU pAddr,
     1379                                     const char *pszMsg)
    12661380{
    12671381    PINTNETNETWORK  pNetwork = pIf->pNetwork;
    12681382    AssertReturnVoid(pNetwork);
     1383
     1384    PINTNETADDRCACHE pCache = &pIf->aAddrCache[enmAddrType];
     1385
     1386    const uint8_t cbAddr = pCache->cbAddress;
     1387    Assert(cbAddr == intnetR0AddrSize(enmAddrType));
     1388
    12691389    RTSpinlockAcquire(pNetwork->hAddrSpinlock);
     1390
     1391    bool fBlacklisted = intnetR0NetworkBlacklistLookup(pNetwork, pAddr, enmAddrType);
     1392    if (fBlacklisted)
     1393    {
     1394        RTSpinlockRelease(pNetwork->hAddrSpinlock);
     1395
     1396#ifdef LOG_ENABLED
     1397        switch (enmAddrType)
     1398        {
     1399            case kIntNetAddrType_IPv4:
     1400                Log(("%s: spoofing attempt for %RTnaipv4\n",
     1401                     __FUNCTION__, pAddr->IPv4));
     1402                break;
     1403            case kIntNetAddrType_IPv6:
     1404                Log(("%s: spoofing attempt for %RTnaipv6\n",
     1405                     __FUNCTION__, &pAddr->IPv6));
     1406                break;
     1407            default:
     1408                Log(("%s: spoofing attempt for %.*Rhxs (type %d)\n",
     1409                     __FUNCTION__, cbAddr, pAddr, enmAddrType));
     1410                break;
     1411        }
     1412#endif
     1413        return;
     1414    }
    12701415
    12711416    if (RT_UNLIKELY(!pCache->cEntriesAlloc))
     
    12921437    memcpy(pbEntry, pAddr, pCache->cbAddress);
    12931438    memset(pbEntry + pCache->cbAddress, '\0', pCache->cbEntry - pCache->cbAddress);
     1439
    12941440#ifdef LOG_ENABLED
    1295     INTNETADDRTYPE enmAddrType = (INTNETADDRTYPE)(uintptr_t)(pCache - &pIf->aAddrCache[0]);
    12961441    switch (enmAddrType)
    12971442    {
     
    13261471 * @param   pszMsg      Log message.
    13271472 */
    1328 static void intnetR0IfAddrCacheAddSlow(PINTNETIF pIf, PINTNETADDRCACHE pCache, PCRTNETADDRU pAddr, uint8_t const cbAddr, const char *pszMsg)
    1329 {
     1473static void intnetR0IfAddrCacheAddSlow(PINTNETIF pIf, INTNETADDRTYPE enmAddrType, PCRTNETADDRU pAddr,
     1474                                       const char *pszMsg)
     1475{
     1476    PINTNETADDRCACHE pCache = &pIf->aAddrCache[enmAddrType];
     1477
     1478    const uint8_t cbAddr = pCache->cbAddress;
     1479    Assert(cbAddr == intnetR0AddrSize(enmAddrType));
     1480
    13301481    /*
    13311482     * Check all but the first and last entries, the caller
     
    13451496     * Not found, add it.
    13461497     */
    1347     intnetR0IfAddrCacheAddIt(pIf, pCache, pAddr, pszMsg);
     1498    intnetR0IfAddrCacheAddIt(pIf, enmAddrType, pAddr, pszMsg);
    13481499}
    13491500
     
    13601511 * @param   pszMsg      Log message.
    13611512 */
    1362 DECLINLINE(void) intnetR0IfAddrCacheAdd(PINTNETIF pIf, PINTNETADDRCACHE pCache, PCRTNETADDRU pAddr,
    1363                                         uint8_t const cbAddr, const char *pszMsg)
    1364 {
    1365     Assert(pCache->cbAddress == cbAddr);
     1513DECLINLINE(void) intnetR0IfAddrCacheAdd(PINTNETIF pIf, INTNETADDRTYPE enmAddrType, PCRTNETADDRU pAddr,
     1514                                        const char *pszMsg)
     1515{
     1516    PINTNETADDRCACHE pCache = &pIf->aAddrCache[enmAddrType];
     1517
     1518    const uint8_t cbAddr = pCache->cbAddress;
     1519    Assert(cbAddr == intnetR0AddrSize(enmAddrType));
    13661520
    13671521    /*
     
    13741528                          && intnetR0AddrUIsEqualEx((PCRTNETADDRU)(pCache->pbEntries + pCache->cbEntry * i), pAddr, cbAddr))) ))
    13751529        return;
    1376     intnetR0IfAddrCacheAddSlow(pIf, pCache, pAddr, cbAddr, pszMsg);
     1530
     1531    intnetR0IfAddrCacheAddSlow(pIf, enmAddrType, pAddr, pszMsg);
    13771532}
    13781533
     
    21502305                if (pMatchingIf)
    21512306                {
    2152                     intnetR0IfAddrCacheAdd(pMatchingIf, &pMatchingIf->aAddrCache[kIntNetAddrType_IPv4],
    2153                                            (PCRTNETADDRU)&pDhcp->bp_yiaddr, sizeof(RTNETADDRIPV4), "DHCP_MT_ACK");
     2307                    intnetR0IfAddrCacheAdd(pMatchingIf, kIntNetAddrType_IPv4,
     2308                                           (PCRTNETADDRU)&pDhcp->bp_yiaddr, "DHCP_MT_ACK");
    21542309                    intnetR0BusyDecIf(pMatchingIf);
    21552310                }
     
    24232578        &&  intnetR0IfAddrCacheLookupLikely(&pIf->aAddrCache[kIntNetAddrType_IPv6], &Addr, sizeof(Addr.IPv6)) < 0)
    24242579    {
    2425         intnetR0IfAddrCacheAddIt(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv6], &Addr, "if/ipv6");
     2580        intnetR0IfAddrCacheAdd(pIf, kIntNetAddrType_IPv6, &Addr, "if/ipv6");
    24262581    }
    24272582}
     
    24692624            return;
    24702625        }
    2471         intnetR0IfAddrCacheAddIt(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, "if/ipv4");
     2626
     2627        intnetR0IfAddrCacheAddIt(pIf, kIntNetAddrType_IPv4, &Addr, "if/ipv4");
    24722628        fValidatedIpHdr = true;
    24732629    }
     
    25452701    if (    !memcmp(&pArpIPv4->ar_sha, &pIf->MacAddr, sizeof(RTMAC))
    25462702        &&  intnetR0IPv4AddrIsGood(pArpIPv4->ar_spa))
    2547         intnetR0IfAddrCacheAdd(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4],
    2548                                (PCRTNETADDRU)&pArpIPv4->ar_spa, sizeof(RTNETADDRIPV4), "if/arp");
     2703    {
     2704        intnetR0IfAddrCacheAdd(pIf, kIntNetAddrType_IPv4, (PCRTNETADDRU)&pArpIPv4->ar_spa, "if/arp");
     2705    }
    25492706}
    25502707
     
    53575514
    53585515
     5516/** @copydoc INTNETTRUNKSWPORT::pfnNotifyHostAddress */
     5517static DECLCALLBACK(void) intnetR0NetworkNotifyHostAddress(PINTNETTRUNKSWPORT pSwitchPort,
     5518                                                           bool fAdded,
     5519                                                           INTNETADDRTYPE enmType, const void *pvAddr)
     5520{
     5521    PINTNETTRUNKIF pTrunkIf = INTNET_SWITCHPORT_2_TRUNKIF(pSwitchPort);
     5522    PINTNETNETWORK pNetwork = pTrunkIf->pNetwork;
     5523    PCRTNETADDRU pAddr = (PCRTNETADDRU)pvAddr;
     5524    uint8_t cbAddr;
     5525
     5526    if (enmType == kIntNetAddrType_IPv4)
     5527    {
     5528        Log(("%s: %s %RTnaipv4\n",
     5529             __FUNCTION__, (fAdded ? "add" : "del"),
     5530             pAddr->IPv4));
     5531        cbAddr = 4;
     5532    }
     5533    else if (enmType == kIntNetAddrType_IPv6)
     5534    {
     5535        Log(("%s: %s %RTnaipv6\n",
     5536             __FUNCTION__, (fAdded ? "add" : "del"),
     5537             pAddr));
     5538        cbAddr = 16;
     5539    }
     5540    else
     5541    {
     5542        Log(("%s: unexpected address type %d\n", __FUNCTION__, enmType));
     5543        return;
     5544    }
     5545
     5546    RTSpinlockAcquire(pNetwork->hAddrSpinlock);
     5547    if (fAdded)         /* one of host interfaces got a new address */
     5548    {
     5549        /* blacklist it to prevent spoofing by guests */
     5550        intnetR0NetworkBlacklistAdd(pNetwork, pAddr, enmType);
     5551
     5552        /* kick out any guest that uses it */
     5553        intnetR0NetworkAddrCacheDeleteUnlocked(pNetwork, pAddr, enmType, cbAddr, "tif/host");
     5554    }
     5555    else                /* address deleted from one of host interfaces */
     5556    {
     5557        /* stop blacklisting it, guests may use it now */
     5558        intnetR0NetworkBlacklistDelete(pNetwork, pAddr, enmType);
     5559    }
     5560    RTSpinlockRelease(pNetwork->hAddrSpinlock);
     5561}
     5562
     5563
    53595564/**
    53605565 * Shutdown the trunk interface.
     
    55205725        pTrunk->SwitchPort.pfnReportGsoCapabilities   = intnetR0TrunkIfPortReportGsoCapabilities;
    55215726        pTrunk->SwitchPort.pfnReportNoPreemptDsts     = intnetR0TrunkIfPortReportNoPreemptDsts;
     5727        if (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
     5728            pTrunk->SwitchPort.pfnNotifyHostAddress   = intnetR0NetworkNotifyHostAddress;
    55225729        pTrunk->SwitchPort.pfnDisconnect              = intnetR0TrunkIfPortDisconnect;
    55235730        pTrunk->SwitchPort.u32VersionEnd              = INTNETTRUNKSWPORT_VERSION;
     
    56505857     */
    56515858    RTSpinlockAcquire(pNetwork->hAddrSpinlock);
     5859
     5860    for (int i = kIntNetAddrType_Invalid + 1; i < kIntNetAddrType_End; i++)
     5861        intnetR0IfAddrCacheDestroy(&pNetwork->aAddrBlacklist[i]);
    56525862
    56535863    uint32_t iIf = pNetwork->MacTab.cEntries;
     
    61126322    if (RT_SUCCESS(rc))
    61136323    {
     6324        for (int i = kIntNetAddrType_Invalid + 1; i < kIntNetAddrType_End && RT_SUCCESS(rc); i++)
     6325            rc = intnetR0IfAddrCacheInit(&pNetwork->aAddrBlacklist[i], (INTNETADDRTYPE)i,
     6326                                         !!(pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE));
     6327    }
     6328    if (RT_SUCCESS(rc))
     6329    {
    61146330        /*
    61156331         * Register the object in the current session and link it into the network list.
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h

    r52394 r55652  
    154154            /** The MAC address of the interface. */
    155155            RTMAC MacAddr;
     156            /** PF_SYSTEM socket to listen for events (XXX: globals?) */
     157            socket_t pSysSock;
    156158            /** @} */
    157159# elif defined(RT_OS_LINUX)
     
    171173            /** The MAC address of the interface. */
    172174            RTMAC MacAddr;
    173             struct notifier_block Notifier;
     175            struct notifier_block Notifier; /* netdevice */
     176            struct notifier_block NotifierIPv4;
     177            struct notifier_block NotifierIPv6;
    174178            struct packet_type    PacketType;
    175179#  ifndef VBOXNETFLT_LINUX_NO_XMIT_QUEUE
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp

    r52618 r55652  
    5252#include <sys/errno.h>
    5353#include <sys/ioccom.h>
     54#include <sys/filio.h>
    5455#include <sys/malloc.h>
    5556#include <sys/proc.h>
     
    6263#include <net/kpi_interfacefilter.h>
    6364RT_C_DECLS_END
     65
     66#include <sys/kpi_socket.h>
    6467#include <net/if.h>
     68#include <net/if_var.h>
     69#include <netinet/in.h>
     70#include <netinet/in_var.h>
     71#include <netinet6/in6_var.h>
    6572
    6673#define VBOXNETFLT_OS_SPECFIC 1
     
    8794static kern_return_t    VBoxNetFltDarwinStart(struct kmod_info *pKModInfo, void *pvData);
    8895static kern_return_t    VBoxNetFltDarwinStop(struct kmod_info *pKModInfo, void *pvData);
     96
     97static void vboxNetFltDarwinSysSockUpcall(socket_t pSysSock, void *pvData, int fWait);
    8998RT_C_DECLS_END
    9099
     
    12941303    if (pIfFilter)
    12951304        iflt_detach(pIfFilter);
     1305
     1306    if (pThis->u.s.pSysSock != NULL)
     1307    {
     1308        sock_close(pThis->u.s.pSysSock);
     1309        pThis->u.s.pSysSock = NULL;
     1310    }
    12961311}
    12971312
     
    13001315{
    13011316    NOREF(pvContext);
    1302     return vboxNetFltDarwinAttachToInterface(pThis, false /* fRediscovery */);
     1317
     1318    int rc = vboxNetFltDarwinAttachToInterface(pThis, false /* fRediscovery */);
     1319    if (RT_FAILURE(rc))
     1320        return rc;
     1321
     1322    if (pThis->pSwitchPort->pfnNotifyHostAddress == NULL)
     1323        return rc;
     1324
     1325    /*
     1326     * XXX: uwe
     1327     *
     1328     * Learn host's IP addresses and set up notifications for changes.
     1329     * To avoid racing, set up notifications first.
     1330     *
     1331     * XXX: This should probably be global, since the only thing
     1332     * specific to ifnet here is its IPv6 link-local address.
     1333     */
     1334    errno_t error;
     1335
     1336    error = sock_socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT,
     1337                        vboxNetFltDarwinSysSockUpcall, pThis,
     1338                        &pThis->u.s.pSysSock);
     1339    if (error != 0)
     1340    {
     1341        LogRel(("sock_socket(SYSPROTO_EVENT): error %d\n", error));
     1342        return rc;
     1343    }
     1344
     1345    int nbio = 1;
     1346    error = sock_ioctl(pThis->u.s.pSysSock, FIONBIO, &nbio);
     1347    if (error != 0)
     1348    {
     1349        LogRel(("FIONBIO: error %d\n", error));
     1350        sock_close(pThis->u.s.pSysSock);
     1351        return rc;
     1352    }
     1353
     1354    if (!sock_isnonblocking(pThis->u.s.pSysSock))
     1355    {
     1356        LogRel(("FIONBIO ok, but socket is blocking?!\n"));
     1357        sock_close(pThis->u.s.pSysSock);
     1358        return rc;       
     1359    }
     1360
     1361    struct kev_request req;
     1362    req.vendor_code = KEV_VENDOR_APPLE;
     1363    req.kev_class = KEV_NETWORK_CLASS;
     1364    req.kev_subclass = KEV_ANY_SUBCLASS; /* need both INET and INET6, so have to request all */
     1365
     1366    error = sock_ioctl(pThis->u.s.pSysSock, SIOCSKEVFILT, &req);
     1367    if (error != 0)
     1368    {
     1369        LogRel(("SIOCSKEVFILT: error %d\n", error));
     1370        sock_close(pThis->u.s.pSysSock);
     1371        return rc;
     1372    }
     1373
     1374    ifnet_t pIfNet = pThis->u.s.pIfNet; /* already retained */
     1375
     1376    ifaddr_t *pIfAddrList;
     1377    error = ifnet_get_address_list(/* all interfaces*/ NULL, &pIfAddrList);
     1378    if (error != 0)
     1379    {
     1380        LogRel(("ifnet_get_address_list: error %d\n", error));
     1381        return rc;
     1382    }
     1383
     1384    for (ifaddr_t *pIfAddr = pIfAddrList; *pIfAddr != NULL; ++pIfAddr)
     1385    {
     1386        ifaddr_t ifa = *pIfAddr;
     1387        sa_family_t family = ifaddr_address_family(ifa);
     1388        struct sockaddr_storage ss;
     1389
     1390        error = ifaddr_address(ifa, (struct sockaddr *)&ss, sizeof(ss));
     1391        if (error != 0)
     1392        {
     1393            LogRel(("getting address family %d: error %d\n", family, error));
     1394            continue;
     1395        }
     1396
     1397        if (family == AF_INET)
     1398        {
     1399            struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
     1400            u_int32_t u32Addr = ntohl(sin->sin_addr.s_addr);
     1401
     1402            if ((u32Addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
     1403                continue;
     1404
     1405            Log(("> inet %RTnaipv4\n", sin->sin_addr.s_addr));
     1406            pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     1407                /* :fAdded */ true, kIntNetAddrType_IPv4, &sin->sin_addr);
     1408        }
     1409        else if (family == AF_INET6)
     1410        {
     1411            struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
     1412
     1413            if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
     1414                continue;
     1415
     1416            /* link-local from other interfaces are out of scope */
     1417            if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && ifaddr_ifnet(ifa) != pIfNet)
     1418                continue;
     1419
     1420            Log(("> inet6 %RTnaipv6\n", &sin6->sin6_addr));
     1421            pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     1422                /* :fAdded */ true, kIntNetAddrType_IPv6, &sin6->sin6_addr);
     1423        }
     1424    }
     1425
     1426    ifnet_free_address_list(pIfAddrList);
     1427
     1428    /*
     1429     * Now that we've got current addresses, check for events that
     1430     * might have happened while we were working.
     1431     */
     1432    vboxNetFltDarwinSysSockUpcall(pThis->u.s.pSysSock, pThis, MBUF_DONTWAIT);
     1433
     1434    return rc;
     1435}
     1436
     1437
     1438static void vboxNetFltDarwinSysSockUpcall(socket_t pSysSock, void *pvData, int fWait)
     1439{
     1440    PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvData;
     1441    errno_t error;
     1442
     1443    NOREF(fWait);
     1444
     1445    if (RT_UNLIKELY(pSysSock != pThis->u.s.pSysSock))
     1446    {
     1447        Log(("vboxNetFltDarwinSysSockUpcall: %p != %p?\n",
     1448             pSysSock, pThis->u.s.pSysSock));
     1449        return;
     1450    }
     1451
     1452    for (;;) {
     1453        mbuf_t m;
     1454        size_t len = sizeof(struct kern_event_msg) - sizeof(u_int32_t)
     1455            + sizeof(struct kev_in6_data);
     1456
     1457        error = sock_receivembuf(pSysSock, NULL, &m, 0, &len);
     1458        if (error == EWOULDBLOCK)
     1459        {
     1460            Log(("vboxNetFltDarwinSysSockUpcall: EWOULDBLOCK - we are done\n"));
     1461            error = 0;
     1462            break;
     1463        }
     1464        else if (error != 0)
     1465        {
     1466            Log(("sock_receivembuf: error %d\n", error));
     1467            break;
     1468        }
     1469
     1470        if (len < sizeof(struct kern_event_msg) - sizeof(u_int32_t))
     1471        {
     1472            Log(("vboxNetFltDarwinSysSockUpcall: %u bytes is too short\n",
     1473                 (unsigned int)len));
     1474            mbuf_freem(m);
     1475            return;
     1476        }
     1477
     1478        struct kern_event_msg *msg = (struct kern_event_msg *)mbuf_data(m);
     1479        if (msg->kev_subclass == KEV_INET_SUBCLASS)
     1480        {
     1481            if (len - (sizeof(struct kern_event_msg) - sizeof(u_int32_t)) < sizeof(struct kev_in_data))
     1482            {
     1483                Log(("vboxNetFltDarwinSysSockUpcall: %u bytes is too short for KEV_INET_SUBCLASS\n",
     1484                     (unsigned int)len));
     1485                mbuf_freem(m);
     1486                return;
     1487            }
     1488
     1489            struct kev_in_data *iev = (struct kev_in_data *)msg->event_data;
     1490            PCRTNETADDRU pAddr = (PCRTNETADDRU)&iev->ia_addr;
     1491            switch (msg->event_code)
     1492            {
     1493                case KEV_INET_NEW_ADDR:
     1494                    Log(("KEV_INET_NEW_ADDR %RTnaipv4\n", pAddr->IPv4));
     1495                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     1496                        /* :fAdded */ true, kIntNetAddrType_IPv4, pAddr);
     1497                    break;
     1498
     1499                case KEV_INET_ADDR_DELETED:
     1500                    Log(("KEV_INET_ADDR_DELETED %RTnaipv4\n", pAddr->IPv4));
     1501                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     1502                        /* :fAdded */ false, kIntNetAddrType_IPv4, &iev->ia_addr);
     1503                    break;
     1504
     1505                default:
     1506                    Log(("KEV INET event %u addr %RTnaipv4\n", msg->event_code, pAddr->IPv4));
     1507                    break;
     1508            }
     1509        }
     1510        else if (msg->kev_subclass == KEV_INET6_SUBCLASS)
     1511        {
     1512            if (len - (sizeof(struct kern_event_msg) - sizeof(u_int32_t)) < sizeof(struct kev_in6_data))
     1513            {
     1514                Log(("vboxNetFltDarwinSysSockUpcall: %u bytes is too short for KEV_INET6_SUBCLASS\n",
     1515                        (unsigned int)len));
     1516                mbuf_freem(m);
     1517                return;
     1518            }
     1519
     1520            struct kev_in6_data *iev6 = (struct kev_in6_data *)msg->event_data;
     1521            PCRTNETADDRU pAddr = (PCRTNETADDRU)&iev6->ia_addr.sin6_addr;
     1522            switch (msg->event_code)
     1523            {
     1524                case KEV_INET6_NEW_USER_ADDR:
     1525                    Log(("KEV_INET6_NEW_USER_ADDR: %RTnaipv6\n", pAddr));
     1526                    goto kev_inet6_new;
     1527
     1528                case KEV_INET6_NEW_LL_ADDR:
     1529                    Log(("KEV_INET6_NEW_LL_ADDR: %RTnaipv6\n", pAddr));
     1530                    /* XXX: uwe: TODO: only interface we are attached to */
     1531                    goto kev_inet6_new;
     1532
     1533                case KEV_INET6_NEW_RTADV_ADDR:
     1534                    Log(("KEV_INET6_NEW_RTADV_ADDR: %RTnaipv6\n", pAddr));
     1535                    goto kev_inet6_new;
     1536
     1537                kev_inet6_new:
     1538                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     1539                        /* :fAdded */ true, kIntNetAddrType_IPv6, pAddr);
     1540                    break;
     1541
     1542                case KEV_INET6_ADDR_DELETED:
     1543                    Log(("KEV_INET6_ADDR_DELETED: %RTnaipv6\n", pAddr));
     1544                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     1545                        /* :fAdded */ false, kIntNetAddrType_IPv6, pAddr);
     1546                    break;
     1547
     1548                default:
     1549                    Log(("KEV INET6 event %u addr %RTnaipv6\n", msg->event_code, pAddr));
     1550                    break;
     1551            }
     1552        }
     1553        else
     1554        {
     1555            Log(("vboxNetFltDarwinSysSockUpcall: subclass %u ignored\n",
     1556                 (unsigned)msg->kev_subclass));
     1557        }
     1558
     1559        mbuf_freem(m);
     1560    }
    13031561}
    13041562
     
    13141572    pThis->u.s.fNeedSetPromiscuous = false;
    13151573    //pThis->u.s.MacAddr = {0};
     1574    pThis->u.s.pSysSock = NULL;
    13161575
    13171576    return VINF_SUCCESS;
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c

    r54461 r55652  
    2828#include <linux/rtnetlink.h>
    2929#include <linux/miscdevice.h>
     30#include <linux/inetdevice.h>
    3031#include <linux/ip.h>
    3132#include <linux/if_vlan.h>
     33#include <net/if_inet6.h>
     34#include <net/addrconf.h>
    3235
    3336#include <VBox/log.h>
     
    18571860}
    18581861
     1862static int vboxNetFltLinuxNotifierIPv4Callback(struct notifier_block *self, unsigned long ulEventType, void *ptr)
     1863{
     1864    PVBOXNETFLTINS     pThis = RT_FROM_MEMBER(self, VBOXNETFLTINS, u.s.NotifierIPv4);
     1865    struct net_device *pDev;
     1866    struct in_ifaddr  *ifa   = (struct in_ifaddr *)ptr;
     1867    int                rc    = NOTIFY_OK;
     1868
     1869    pDev = vboxNetFltLinuxRetainNetDev(pThis);
     1870    Log(("VBoxNetFlt: %s: IPv4 event %s(0x%lx): addr %RTnaipv4 mask %RTnaipv4\n",
     1871         pDev ? netdev_name(pDev) : "<???>",
     1872         vboxNetFltLinuxGetNetDevEventName(ulEventType), ulEventType,
     1873         ifa->ifa_address, ifa->ifa_mask));
     1874
     1875    if (pDev != NULL)
     1876        vboxNetFltLinuxReleaseNetDev(pThis, pDev);
     1877
     1878    if (pThis->pSwitchPort->pfnNotifyHostAddress)
     1879    {
     1880        bool fAdded;
     1881        if (ulEventType == NETDEV_UP)
     1882            fAdded = true;
     1883        else if (ulEventType == NETDEV_DOWN)
     1884            fAdded = false;
     1885        else
     1886            return NOTIFY_OK;
     1887           
     1888        pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort, fAdded,
     1889                                                 kIntNetAddrType_IPv4, &ifa->ifa_local);
     1890    }
     1891
     1892    return rc;
     1893}
     1894
     1895
     1896static int vboxNetFltLinuxNotifierIPv6Callback(struct notifier_block *self, unsigned long ulEventType, void *ptr)
     1897{
     1898    PVBOXNETFLTINS       pThis = RT_FROM_MEMBER(self, VBOXNETFLTINS, u.s.NotifierIPv6);
     1899    struct net_device   *pDev;
     1900    struct inet6_ifaddr *ifa   = (struct inet6_ifaddr *)ptr;
     1901    int                  rc    = NOTIFY_OK;
     1902
     1903    pDev = vboxNetFltLinuxRetainNetDev(pThis);
     1904    Log(("VBoxNetFlt: %s: IPv6 event %s(0x%lx): %RTnaipv6\n",
     1905         pDev ? netdev_name(pDev) : "<???>",
     1906         vboxNetFltLinuxGetNetDevEventName(ulEventType), ulEventType,
     1907         &ifa->addr));
     1908
     1909    if (pDev != NULL)
     1910        vboxNetFltLinuxReleaseNetDev(pThis, pDev);
     1911
     1912    if (pThis->pSwitchPort->pfnNotifyHostAddress)
     1913    {
     1914        bool fAdded;
     1915        if (ulEventType == NETDEV_UP)
     1916            fAdded = true;
     1917        else if (ulEventType == NETDEV_DOWN)
     1918            fAdded = false;
     1919        else
     1920            return NOTIFY_OK;
     1921           
     1922        pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort, fAdded,
     1923                                                 kIntNetAddrType_IPv6, &ifa->addr);
     1924    }
     1925
     1926    return rc;
     1927}
     1928
     1929
    18591930bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
    18601931{
     
    20532124        dev_put(pDev);
    20542125    }
     2126
     2127    unregister_inet6addr_notifier(&pThis->u.s.NotifierIPv6);
     2128    unregister_inetaddr_notifier(&pThis->u.s.NotifierIPv4);
     2129
    20552130    Log(("vboxNetFltOsDeleteInstance: this=%p: Notifier removed.\n", pThis));
    20562131    unregister_netdevice_notifier(&pThis->u.s.Notifier);
     
    20792154        || !try_module_get(THIS_MODULE))
    20802155        return VERR_INTNET_FLT_IF_FAILED;
     2156
     2157    if (pThis->pSwitchPort->pfnNotifyHostAddress)
     2158    {
     2159        struct net *net = dev_net(pThis->u.s.pDev);
     2160        struct net_device *dev;
     2161
     2162        rcu_read_lock();
     2163        for_each_netdev_rcu(net, dev)
     2164        {
     2165            struct in_device *in_dev;
     2166            struct inet6_dev *in6_dev;
     2167
     2168            /*
     2169             * IPv4
     2170             */
     2171            in_dev = __in_dev_get_rcu(dev);
     2172            if (in_dev != NULL)
     2173            {
     2174                for_ifa(in_dev) {
     2175                    if (ifa->ifa_address == htonl(INADDR_LOOPBACK))
     2176                        goto continue_netdev;
     2177
     2178                    Log(("%s: %s: IPv4: addr %RTnaipv4 mask %RTnaipv4\n",
     2179                         __FUNCTION__, netdev_name(dev),
     2180                         ifa->ifa_address, ifa->ifa_mask));
     2181
     2182                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     2183                        /* :fAdded */ true, kIntNetAddrType_IPv4, &ifa->ifa_address);
     2184                } endfor_ifa(in_dev);
     2185            }
     2186
     2187            /*
     2188             * IPv6
     2189             */
     2190            in6_dev = __in6_dev_get(dev);
     2191            if (in6_dev != NULL)
     2192            {
     2193                struct inet6_ifaddr *ifa;
     2194
     2195                read_lock_bh(&in6_dev->lock);
     2196                list_for_each_entry(ifa, &in6_dev->addr_list, if_list)
     2197                {
     2198                    Log(("%s: %s: IPv6: addr %RTnaipv6/%u\n",
     2199                         __FUNCTION__, netdev_name(dev),
     2200                         &ifa->addr, (unsigned)ifa->prefix_len));
     2201
     2202                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
     2203                        /* :fAdded */ true, kIntNetAddrType_IPv6, &ifa->addr);
     2204                }
     2205                read_unlock_bh(&in6_dev->lock);
     2206            }
     2207
     2208          continue_netdev:
     2209            /* continue */;
     2210        }
     2211        rcu_read_unlock();
     2212
     2213        Log(("%s: pfnNotifyHostAddress is set, register notifiers\n", __FUNCTION__));
     2214
     2215        pThis->u.s.NotifierIPv4.notifier_call = vboxNetFltLinuxNotifierIPv4Callback;
     2216        err = register_inetaddr_notifier(&pThis->u.s.NotifierIPv4);
     2217        if (err)
     2218            LogRel(("%s: failed to register IPv4 notifier: error %d\n",
     2219                    __FUNCTION__, err));
     2220
     2221        pThis->u.s.NotifierIPv6.notifier_call = vboxNetFltLinuxNotifierIPv6Callback;
     2222        err = register_inet6addr_notifier(&pThis->u.s.NotifierIPv6);
     2223        if (err)
     2224            LogRel(("%s: failed to register IPv6 notifier: error %d\n",
     2225                    __FUNCTION__, err));
     2226    }
     2227    else
     2228        Log(("%s: uwe: pfnNotifyHostAddress is NULL\n", __FUNCTION__));
    20812229
    20822230    return VINF_SUCCESS;
Note: See TracChangeset for help on using the changeset viewer.

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