VirtualBox

Ignore:
Timestamp:
May 5, 2015 3:28:45 AM (10 years ago)
Author:
vboxsync
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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;
Note: See TracChangeset for help on using the changeset viewer.

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