VirtualBox

Changeset 87449 in vbox for trunk/src/VBox/NetworkServices


Ignore:
Timestamp:
Jan 27, 2021 1:05:45 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
142467
Message:

NAT/Net: Refactor some more. Move the code to create raw sockets out
of main into their own methods, call them during initialization. Get
rid of the now unused global pointer to the singleton nat object
(where we need the back-reference, we have it via a callback cookie).
Do not allocate the singleton dynamically.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/NetworkServices/NAT/VBoxNetLwipNAT.cpp

    r87400 r87449  
    167167
    168168
    169   public:
    170     VBoxNetLwipNAT(SOCKET icmpsock4, SOCKET icmpsock6);
     169public:
     170    VBoxNetLwipNAT();
    171171    virtual ~VBoxNetLwipNAT();
    172172
     
    179179
    180180    virtual int init();
     181    virtual int run();
     182
     183private:
     184    void createRawSock4();
     185    void createRawSock6();
    181186
    182187    static DECLCALLBACK(void) onLwipTcpIpInit(void *arg);
    183188    static DECLCALLBACK(void) onLwipTcpIpFini(void *arg);
    184189    static err_t netifInit(netif *pNetif) RT_NOTHROW_PROTO;
    185 
    186     virtual int run();
    187190
    188191    HRESULT HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent);
     
    205208INTNETSEG VBoxNetLwipNAT::aXmitSeg[64];
    206209
    207 static VBoxNetLwipNAT *g_pLwipNat;
    208 
    209 
    210 
    211 VBoxNetLwipNAT::VBoxNetLwipNAT(SOCKET icmpsock4, SOCKET icmpsock6)
     210
     211
     212VBoxNetLwipNAT::VBoxNetLwipNAT()
    212213  : VBoxNetBaseService("VBoxNetNAT", "nat-network")
    213214{
     
    216217    m_ProxyOptions.ipv6_enabled = 0;
    217218    m_ProxyOptions.ipv6_defroute = 0;
    218     m_ProxyOptions.icmpsock4 = icmpsock4;
    219     m_ProxyOptions.icmpsock6 = icmpsock6;
     219    m_ProxyOptions.icmpsock4 = INVALID_SOCKET;
     220    m_ProxyOptions.icmpsock6 = INVALID_SOCKET;
    220221    m_ProxyOptions.tftp_root = NULL;
    221222    m_ProxyOptions.src4 = NULL;
     
    376377
    377378    /*
    378      * Bind outgoing connections to the specified IP.
     379     * IPv4 source address, if configured.
    379380     */
    380     com::Bstr bstrSourceIpX;
    381 
    382     /* IPv4 */
     381    com::Bstr bstrSourceIp4;
    383382    com::Bstr bstrSourceIp4Key = com::BstrFmt("NAT/%s/SourceIp4", networkName.c_str());
    384     hrc = virtualbox->GetExtraData(bstrSourceIp4Key.raw(), bstrSourceIpX.asOutParam());
    385     if (SUCCEEDED(hrc) && bstrSourceIpX.isNotEmpty())
     383    hrc = virtualbox->GetExtraData(bstrSourceIp4Key.raw(), bstrSourceIp4.asOutParam());
     384    if (SUCCEEDED(hrc) && bstrSourceIp4.isNotEmpty())
    386385    {
    387386        RTNETADDRIPV4 addr;
    388         rc = RTNetStrToIPv4Addr(com::Utf8Str(bstrSourceIpX).c_str(), &addr);
     387        rc = RTNetStrToIPv4Addr(com::Utf8Str(bstrSourceIp4).c_str(), &addr);
    389388        if (RT_SUCCESS(rc))
    390389        {
     
    398397        {
    399398            LogRel(("Failed to parse \"%s\" IPv4 source address specification\n",
    400                     com::Utf8Str(bstrSourceIpX).c_str()));
    401         }
    402 
    403         bstrSourceIpX.setNull();
    404     }
    405 
    406     /* IPv6 */
    407     com::Bstr bstrSourceIp6Key = com::BstrFmt("NAT/%s/SourceIp6", networkName.c_str());
    408     hrc = virtualbox->GetExtraData(bstrSourceIp6Key.raw(), bstrSourceIpX.asOutParam());
    409     if (SUCCEEDED(hrc) && bstrSourceIpX.isNotEmpty())
    410     {
    411         RTNETADDRIPV6 addr;
    412         char *pszZone = NULL;
    413         rc = RTNetStrToIPv6Addr(com::Utf8Str(bstrSourceIpX).c_str(), &addr, &pszZone);
    414         if (RT_SUCCESS(rc))
    415         {
    416             memcpy(&m_src6.sin6_addr, &addr, sizeof(addr));
    417             m_ProxyOptions.src6 = &m_src6;
    418 
    419             LogRel(("Will use %RTnaipv6 as IPv6 source address\n",
    420                     &m_src6.sin6_addr));
    421         }
    422         else
    423         {
    424             LogRel(("Failed to parse \"%s\" IPv6 source address specification\n",
    425                     com::Utf8Str(bstrSourceIpX).c_str()));
    426         }
    427 
    428         bstrSourceIpX.setNull();
    429     }
     399                    com::Utf8Str(bstrSourceIp4).c_str()));
     400        }
     401    }
     402
     403    /*
     404     * IPv6 source address, if configured.
     405     */
     406    if (fIPv6Enabled)
     407    {
     408        com::Bstr bstrSourceIp6;
     409        com::Bstr bstrSourceIp6Key = com::BstrFmt("NAT/%s/SourceIp6", networkName.c_str());
     410        hrc = virtualbox->GetExtraData(bstrSourceIp6Key.raw(), bstrSourceIp6.asOutParam());
     411        if (SUCCEEDED(hrc) && bstrSourceIp6.isNotEmpty())
     412        {
     413            RTNETADDRIPV6 addr;
     414            char *pszZone = NULL;
     415            rc = RTNetStrToIPv6Addr(com::Utf8Str(bstrSourceIp6).c_str(), &addr, &pszZone);
     416            if (RT_SUCCESS(rc))
     417            {
     418                memcpy(&m_src6.sin6_addr, &addr, sizeof(addr));
     419                m_ProxyOptions.src6 = &m_src6;
     420
     421                LogRel(("Will use %RTnaipv6 as IPv6 source address\n",
     422                        &m_src6.sin6_addr));
     423            }
     424            else
     425            {
     426                LogRel(("Failed to parse \"%s\" IPv6 source address specification\n",
     427                        com::Utf8Str(bstrSourceIp6).c_str()));
     428            }
     429        }
     430    }
     431
     432
     433    createRawSock4();
     434    if (fIPv6Enabled)
     435        createRawSock6();
    430436
    431437
     
    481487    LogFlowFuncLeaveRC(rc);
    482488    return rc;
     489}
     490
     491
     492/**
     493 * Create raw IPv4 socket for sending and snooping ICMP.
     494 */
     495void VBoxNetLwipNAT::createRawSock4()
     496{
     497    SOCKET icmpsock4 = INVALID_SOCKET;
     498
     499#ifndef RT_OS_DARWIN
     500    const int icmpstype = SOCK_RAW;
     501#else
     502    /* on OS X it's not privileged */
     503    const int icmpstype = SOCK_DGRAM;
     504#endif
     505
     506    icmpsock4 = socket(AF_INET, icmpstype, IPPROTO_ICMP);
     507    if (icmpsock4 == INVALID_SOCKET)
     508    {
     509        perror("IPPROTO_ICMP");
     510#ifdef VBOX_RAWSOCK_DEBUG_HELPER
     511        icmpsock4 = getrawsock(AF_INET);
     512#endif
     513    }
     514
     515    if (icmpsock4 != INVALID_SOCKET)
     516    {
     517#ifdef ICMP_FILTER              //  Linux specific
     518        struct icmp_filter flt = {
     519            ~(uint32_t)(
     520                  (1U << ICMP_ECHOREPLY)
     521                | (1U << ICMP_DEST_UNREACH)
     522                | (1U << ICMP_TIME_EXCEEDED)
     523            )
     524        };
     525
     526        int status = setsockopt(icmpsock4, SOL_RAW, ICMP_FILTER,
     527                                &flt, sizeof(flt));
     528        if (status < 0)
     529        {
     530            perror("ICMP_FILTER");
     531        }
     532#endif
     533    }
     534
     535    m_ProxyOptions.icmpsock4 = icmpsock4;
     536}
     537
     538
     539/**
     540 * Create raw IPv6 socket for sending and snooping ICMP6.
     541 */
     542void VBoxNetLwipNAT::createRawSock6()
     543{
     544    SOCKET icmpsock6 = INVALID_SOCKET;
     545
     546#ifndef RT_OS_DARWIN
     547    const int icmpstype = SOCK_RAW;
     548#else
     549    /* on OS X it's not privileged */
     550    const int icmpstype = SOCK_DGRAM;
     551#endif
     552
     553    icmpsock6 = socket(AF_INET6, icmpstype, IPPROTO_ICMPV6);
     554    if (icmpsock6 == INVALID_SOCKET)
     555    {
     556        perror("IPPROTO_ICMPV6");
     557#ifdef VBOX_RAWSOCK_DEBUG_HELPER
     558        icmpsock6 = getrawsock(AF_INET6);
     559#endif
     560    }
     561
     562    if (icmpsock6 != INVALID_SOCKET)
     563    {
     564#ifdef ICMP6_FILTER             // Windows doesn't support RFC 3542 API
     565        /*
     566         * XXX: We do this here for now, not in pxping.c, to avoid
     567         * name clashes between lwIP and system headers.
     568         */
     569        struct icmp6_filter flt;
     570        ICMP6_FILTER_SETBLOCKALL(&flt);
     571
     572        ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &flt);
     573
     574        ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &flt);
     575        ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &flt);
     576        ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &flt);
     577        ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &flt);
     578
     579        int status = setsockopt(icmpsock6, IPPROTO_ICMPV6, ICMP6_FILTER,
     580                                &flt, sizeof(flt));
     581        if (status < 0)
     582        {
     583            perror("ICMP6_FILTER");
     584        }
     585#endif
     586    }
     587
     588    m_ProxyOptions.icmpsock6 = icmpsock6;
    483589}
    484590
     
    9221028
    9231029/**
    924  * Fetch port-forwarding rules from the API.
     1030 * Read the list of host's resolvers via the API.
     1031 *
     1032 * Called during initialization and in response to the
     1033 * VBoxEventType_OnHostNameResolutionConfigurationChange event.
     1034 */
     1035const char **VBoxNetLwipNAT::getHostNameservers()
     1036{
     1037    if (m_host.isNull())
     1038        return NULL;
     1039
     1040    com::SafeArray<BSTR> aNameServers;
     1041    HRESULT hrc = m_host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(aNameServers));
     1042    if (FAILED(hrc))
     1043        return NULL;
     1044
     1045    const size_t cNameServers = aNameServers.size();
     1046    if (cNameServers == 0)
     1047        return NULL;
     1048
     1049    const char **ppcszNameServers =
     1050        (const char **)RTMemAllocZ(sizeof(char *) * (cNameServers + 1));
     1051    if (ppcszNameServers == NULL)
     1052        return NULL;
     1053
     1054    size_t idxLast = 0;
     1055    for (size_t i = 0; i < cNameServers; ++i)
     1056    {
     1057        com::Utf8Str strNameServer(aNameServers[i]);
     1058        ppcszNameServers[idxLast] = RTStrDup(strNameServer.c_str());
     1059        if (ppcszNameServers[idxLast] != NULL)
     1060            ++idxLast;
     1061    }
     1062
     1063    if (idxLast == 0)
     1064    {
     1065        RTMemFree(ppcszNameServers);
     1066        return NULL;
     1067    }
     1068
     1069    return ppcszNameServers;
     1070}
     1071
     1072
     1073/**
     1074 * Fetch port-forwarding rules via the API.
    9251075 *
    9261076 * Reads the initial sets of rules from VBoxSVC.  The rules will be
     
    10511201                natPf.Pfr.szPfrName));
    10521202    return VERR_IGNORED;
    1053 }
    1054 
    1055 
    1056 const char **VBoxNetLwipNAT::getHostNameservers()
    1057 {
    1058     if (m_host.isNull())
    1059         return NULL;
    1060 
    1061     com::SafeArray<BSTR> aNameServers;
    1062     HRESULT hrc = m_host->COMGETTER(NameServers)(ComSafeArrayAsOutParam(aNameServers));
    1063     if (FAILED(hrc))
    1064         return NULL;
    1065 
    1066     const size_t cNameServers = aNameServers.size();
    1067     if (cNameServers == 0)
    1068         return NULL;
    1069 
    1070     const char **ppcszNameServers =
    1071         (const char **)RTMemAllocZ(sizeof(char *) * (cNameServers + 1));
    1072     if (ppcszNameServers == NULL)
    1073         return NULL;
    1074 
    1075     size_t idxLast = 0;
    1076     for (size_t i = 0; i < cNameServers; ++i)
    1077     {
    1078         com::Utf8Str strNameServer(aNameServers[i]);
    1079         ppcszNameServers[idxLast] = RTStrDup(strNameServer.c_str());
    1080         if (ppcszNameServers[idxLast] != NULL)
    1081             ++idxLast;
    1082     }
    1083 
    1084     if (idxLast == 0)
    1085     {
    1086         RTMemFree(ppcszNameServers);
    1087         return NULL;
    1088     }
    1089 
    1090     return ppcszNameServers;
    10911203}
    10921204
     
    13661478    {
    13671479        fprintf(stderr, "wsastartup: failed (%d)\n", err);
    1368         return 1;
     1480        return RTEXITCODE_INIT;
    13691481    }
    13701482#endif
     
    13821494            if (RT_SUCCESS(vrc))
    13831495            {
    1384                 return RTMsgErrorExit(RTEXITCODE_FAILURE,
     1496                return RTMsgErrorExit(RTEXITCODE_INIT,
    13851497                                      "Failed to initialize COM: %s: %Rhrf",
    13861498                                      szHome, hrc);
     
    13881500        }
    13891501#endif  // VBOX_WITH_XPCOM
    1390         return RTMsgErrorExit(RTEXITCODE_FAILURE,
     1502        return RTMsgErrorExit(RTEXITCODE_INIT,
    13911503                              "Failed to initialize COM: %Rhrf", hrc);
    13921504    }
    13931505
    1394 
    1395     SOCKET icmpsock4 = INVALID_SOCKET;
    1396     SOCKET icmpsock6 = INVALID_SOCKET;
    1397 #ifndef RT_OS_DARWIN
    1398     const int icmpstype = SOCK_RAW;
    1399 #else
    1400     /* on OS X it's not privileged */
    1401     const int icmpstype = SOCK_DGRAM;
    1402 #endif
    1403 
    1404     icmpsock4 = socket(AF_INET, icmpstype, IPPROTO_ICMP);
    1405     if (icmpsock4 == INVALID_SOCKET)
    1406     {
    1407         perror("IPPROTO_ICMP");
    1408 #ifdef VBOX_RAWSOCK_DEBUG_HELPER
    1409         icmpsock4 = getrawsock(AF_INET);
    1410 #endif
    1411     }
    1412 
    1413     if (icmpsock4 != INVALID_SOCKET)
    1414     {
    1415 #ifdef ICMP_FILTER              //  Linux specific
    1416         struct icmp_filter flt = {
    1417             ~(uint32_t)(
    1418                   (1U << ICMP_ECHOREPLY)
    1419                 | (1U << ICMP_DEST_UNREACH)
    1420                 | (1U << ICMP_TIME_EXCEEDED)
    1421             )
    1422         };
    1423 
    1424         int status = setsockopt(icmpsock4, SOL_RAW, ICMP_FILTER,
    1425                                 &flt, sizeof(flt));
    1426         if (status < 0)
    1427         {
    1428             perror("ICMP_FILTER");
    1429         }
    1430 #endif
    1431     }
    1432 
    1433     icmpsock6 = socket(AF_INET6, icmpstype, IPPROTO_ICMPV6);
    1434     if (icmpsock6 == INVALID_SOCKET)
    1435     {
    1436         perror("IPPROTO_ICMPV6");
    1437 #ifdef VBOX_RAWSOCK_DEBUG_HELPER
    1438         icmpsock6 = getrawsock(AF_INET6);
    1439 #endif
    1440     }
    1441 
    1442     if (icmpsock6 != INVALID_SOCKET)
    1443     {
    1444 #ifdef ICMP6_FILTER             // Windows doesn't support RFC 3542 API
    1445         /*
    1446          * XXX: We do this here for now, not in pxping.c, to avoid
    1447          * name clashes between lwIP and system headers.
    1448          */
    1449         struct icmp6_filter flt;
    1450         ICMP6_FILTER_SETBLOCKALL(&flt);
    1451 
    1452         ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &flt);
    1453 
    1454         ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &flt);
    1455         ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &flt);
    1456         ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &flt);
    1457         ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &flt);
    1458 
    1459         int status = setsockopt(icmpsock6, IPPROTO_ICMPV6, ICMP6_FILTER,
    1460                                 &flt, sizeof(flt));
    1461         if (status < 0)
    1462         {
    1463             perror("ICMP6_FILTER");
    1464         }
    1465 #endif
    1466     }
    1467 
    1468 
    1469     g_pLwipNat = new VBoxNetLwipNAT(icmpsock4, icmpsock6);
     1506    VBoxNetLwipNAT NAT;
    14701507
    14711508    Log2(("NAT: initialization\n"));
    1472     rc = g_pLwipNat->parseArgs(argc - 1, argv + 1);
     1509    rc = NAT.parseArgs(argc - 1, argv + 1);
    14731510    rc = (rc == 0) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /* XXX: FIXME */
    14741511
    14751512    if (RT_SUCCESS(rc))
    1476         rc = g_pLwipNat->init();
     1513        rc = NAT.init();
    14771514
    14781515    if (RT_SUCCESS(rc))
    1479         g_pLwipNat->run();
    1480 
    1481     delete g_pLwipNat;
    1482     return 0;
     1516        NAT.run();
     1517
     1518    return RTEXITCODE_SUCCESS;
    14831519}
    14841520
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