VirtualBox

Changeset 105202 in vbox


Ignore:
Timestamp:
Jul 8, 2024 10:42:06 PM (8 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
163845
Message:

Devices/Network: clean and reorganized code, fix win warnings. bugref:10268

Location:
trunk/src
Files:
3 edited

Legend:

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

    r105201 r105202  
    3535
    3636
    37 /*********************************************************************************************************************************
    38 *   Internal Functions                                                                                                           *
    39 *********************************************************************************************************************************/
     37/**
     38 * PDM Function Implementations
     39 */
    4040
    4141/**
     
    368368{
    369369    RT_NOREF(pszWho);
    370     int rc;
     370    int rc = 0;
    371371#ifndef RT_OS_WINDOWS
    372372    /* kick poll() */
    373373    size_t cbIgnored;
    374374    rc = RTPipeWrite(pThis->hPipeWrite, "", 1, &cbIgnored);
     375#else
     376    RT_NOREF(pThis);
    375377#endif
    376378    AssertRC(rc);
     
    452454
    453455/**
    454  * Registers poll. Unused function (other than logging).
    455  */
    456 static void drvNAT_RegisterPoll(int fd, void *opaque) {
    457     RT_NOREF(fd, opaque);
    458     Log4(("Poll registered\n"));
    459 }
    460 
    461 /**
    462  * Unregisters poll. Unused function (other than logging).
    463  */
    464 static void drvNAT_UnregisterPoll(int fd, void *opaque) {
    465     RT_NOREF(fd, opaque);
    466     Log4(("Poll unregistered\n"));
     456 * NAT thread handling the slirp stuff.
     457 *
     458 * The slirp implementation is single-threaded so we execute this enginre in a
     459 * dedicated thread. We take care that this thread does not become the
     460 * bottleneck: If the guest wants to send, a request is enqueued into the
     461 * hSlirpReqQueue and handled asynchronously by this thread.  If this thread
     462 * wants to deliver packets to the guest, it enqueues a request into
     463 * hRecvReqQueue which is later handled by the Recv thread.
     464 *
     465 * @param   pDrvIns     Pointer to PDM driver context.
     466 * @param   pThread     Pointer to calling thread context.
     467 *
     468 * @returns VBox status code
     469 *
     470 * @thread  NAT
     471 */
     472static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
     473{
     474    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     475#ifdef RT_OS_WINDOWS
     476    unsigned int cBreak = 0;
     477#else /* RT_OS_WINDOWS */
     478    unsigned int cPollNegRet = 0;
     479    drvNAT_AddPollCb(RTPipeToNative(pThis->hPipeRead), SLIRP_POLL_IN | SLIRP_POLL_HUP, pThis);
     480    pThis->pNATState->polls[0].fd = RTPipeToNative(pThis->hPipeRead);
     481    pThis->pNATState->polls[0].events = POLLRDNORM | POLLPRI | POLLRDBAND;
     482    pThis->pNATState->polls[0].revents = 0;
     483#endif /* !RT_OS_WINDOWS */
     484
     485    LogFlow(("drvNATAsyncIoThread: pThis=%p\n", pThis));
     486
     487    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     488        return VINF_SUCCESS;
     489
     490    if (pThis->enmLinkStateWant != pThis->enmLinkState)
     491        drvNATNotifyLinkChangedWorker(pThis, pThis->enmLinkStateWant);
     492
     493    /*
     494     * Polling loop.
     495     */
     496    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     497    {
     498        /*
     499         * To prevent concurrent execution of sending/receiving threads
     500         */
     501#ifndef RT_OS_WINDOWS
     502        uint32_t uTimeout = 0;
     503        pThis->pNATState->nsock = 1;
     504
     505        slirp_pollfds_fill(pThis->pNATState->pSlirp, &uTimeout, drvNAT_AddPollCb /* SlirpAddPollCb */, pThis /* opaque */);
     506        drvNAT_UpdateTimeout(&uTimeout, pThis);
     507
     508        int cChangedFDs = poll(pThis->pNATState->polls, pThis->pNATState->nsock, uTimeout /* timeout */);
     509
     510        if (cChangedFDs < 0)
     511        {
     512            if (errno == EINTR)
     513            {
     514                Log2(("NAT: signal was caught while sleep on poll\n"));
     515                /* No error, just process all outstanding requests but don't wait */
     516                cChangedFDs = 0;
     517            }
     518            else if (cPollNegRet++ > 128)
     519            {
     520                LogRel(("NAT: Poll returns (%s) suppressed %d\n", strerror(errno), cPollNegRet));
     521                cPollNegRet = 0;
     522            }
     523        }
     524
     525
     526        slirp_pollfds_poll(pThis->pNATState->pSlirp, cChangedFDs < 0, drvNAT_GetREventsCb /* SlirpGetREventsCb */, pThis /* opaque */);
     527        if (pThis->pNATState->polls[0].revents & (POLLRDNORM|POLLPRI|POLLRDBAND))
     528        {
     529            /* drain the pipe
     530             *
     531             * Note! drvNATSend decoupled so we don't know how many times
     532             * device's thread sends before we've entered multiplex,
     533             * so to avoid false alarm drain pipe here to the very end
     534             *
     535             * @todo: Probably we should counter drvNATSend to count how
     536             * deep pipe has been filed before drain.
     537             *
     538             */
     539            /** @todo XXX: Make it reading exactly we need to drain the
     540             * pipe.*/
     541            char ch;
     542            size_t cbRead;
     543            RTPipeRead(pThis->hPipeRead, &ch, 1, &cbRead);
     544        }
     545
     546        /* process _all_ outstanding requests but don't wait */
     547        RTReqQueueProcess(pThis->hSlirpReqQueue, 0);
     548        drvNAT_CheckTimeout(pThis);
     549
     550#else /* RT_OS_WINDOWS */
     551        uint32_t uTimeout = 0;
     552        pThis->pNATState->nsock = 0;
     553        slirp_pollfds_fill(pThis->pNATState->pSlirp, &uTimeout, drvNAT_AddPollCb /* SlirpAddPollCb */, pThis /* opaque */);
     554        drvNAT_UpdateTimeout(&uTimeout, pThis);
     555
     556        int cChangedFDs = WSAPoll(pThis->pNATState->polls, pThis->pNATState->nsock, uTimeout /* timeout */);
     557        int error = WSAGetLastError();
     558
     559        if (cChangedFDs < 0)
     560        {
     561            LogFlow(("NAT: WSAPoll returned %d (error %d)\n", cChangedFDs, error));
     562            LogFlow(("NSOCK = %d\n", pThis->pNATState->nsock));
     563
     564            if (error == 10022)
     565                RTThreadSleep(100);
     566        }
     567
     568        if (cChangedFDs == 0)
     569        {
     570            /* only check for slow/fast timers */
     571            slirp_pollfds_poll(pThis->pNATState->pSlirp, false /*select error*/, drvNAT_GetREventsCb /* SlirpGetREventsCb */, pThis /* opaque */);
     572            RTReqQueueProcess(pThis->hSlirpReqQueue, 0);
     573            continue;
     574        }
     575        /* poll the sockets in any case */
     576        Log2(("%s: poll\n", __FUNCTION__));
     577        slirp_pollfds_poll(pThis->pNATState->pSlirp, cChangedFDs < 0 /*select error*/, drvNAT_GetREventsCb /* SlirpGetREventsCb */, pThis /* opaque */);
     578
     579        /* process _all_ outstanding requests but don't wait */
     580        RTReqQueueProcess(pThis->hSlirpReqQueue, 0);
     581        drvNAT_CheckTimeout(pThis);
     582# ifdef VBOX_NAT_DELAY_HACK
     583        if (cBreak++ > 128)
     584        {
     585            cBreak = 0;
     586            RTThreadSleep(2);
     587        }
     588# endif
     589#endif /* RT_OS_WINDOWS */
     590    }
     591
     592    return VINF_SUCCESS;
     593}
     594
     595/**
     596 * Unblock the send thread so it can respond to a state change.
     597 *
     598 * @returns VBox status code.
     599 * @param   pDrvIns     The pcnet device instance.
     600 * @param   pThread     The send thread.
     601 *
     602 * @thread  ?
     603 */
     604static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
     605{
     606    RT_NOREF(pThread);
     607    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     608
     609    drvNATNotifyNATThread(pThis, "drvNATAsyncIoWakeup");
     610    return VINF_SUCCESS;
     611}
     612
     613/**
     614 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
     615 */
     616static DECLCALLBACK(void *) drvNATQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     617{
     618    PPDMDRVINS  pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
     619    PDRVNAT     pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     620
     621    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
     622    PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKUP, &pThis->INetworkUp);
     623    PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKNATCONFIG, &pThis->INetworkNATCfg);
     624    return NULL;
     625}
     626
     627/**
     628 * Info handler.
     629 *
     630 * @param   pDrvIns     The PDM driver context.
     631 * @param   pHlp        ....
     632 * @param   pszArgs     Unused.
     633 *
     634 * @thread  any
     635 */
     636static DECLCALLBACK(void) drvNATInfo(PPDMDRVINS pDrvIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
     637{
     638    RT_NOREF(pszArgs);
     639    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
     640    pHlp->pfnPrintf(pHlp, "libslirp Connection Info:\n");
     641    pHlp->pfnPrintf(pHlp, slirp_connection_info(pThis->pNATState->pSlirp));
     642    pHlp->pfnPrintf(pHlp, "libslirp Neighbor Info:\n");
     643    pHlp->pfnPrintf(pHlp, slirp_neighbor_info(pThis->pNATState->pSlirp));
     644    pHlp->pfnPrintf(pHlp, "libslirp Version String: %s \n", slirp_version_string());
     645}
     646
     647/**
     648 * Sets up the redirectors.
     649 *
     650 * @returns VBox status code.
     651 * @param   uInstance       ?
     652 * @param   pThis           ?
     653 * @param   pCfg            The configuration handle.
     654 * @param   pNetwork        Unused.
     655 *
     656 * @thread  ?
     657 */
     658static int drvNATConstructRedir(unsigned iInstance, PDRVNAT pThis, PCFGMNODE pCfg, PRTNETADDRIPV4 pNetwork)
     659{
     660    /** @todo r=jack: rewrite to support IPv6? */
     661    PPDMDRVINS pDrvIns = pThis->pDrvIns;
     662    PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
     663
     664    RT_NOREF(pNetwork); /** @todo figure why pNetwork isn't used */
     665
     666    PCFGMNODE pPFTree = pHlp->pfnCFGMGetChild(pCfg, "PortForwarding");
     667    if (pPFTree == NULL)
     668        return VINF_SUCCESS;
     669
     670    /*
     671     * Enumerate redirections.
     672     */
     673    for (PCFGMNODE pNode = pHlp->pfnCFGMGetFirstChild(pPFTree); pNode; pNode = pHlp->pfnCFGMGetNextChild(pNode))
     674    {
     675        /*
     676         * Validate the port forwarding config.
     677         */
     678        if (!pHlp->pfnCFGMAreValuesValid(pNode, "Name\0Protocol\0UDP\0HostPort\0GuestPort\0GuestIP\0BindIP\0"))
     679            return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
     680                                    N_("Unknown configuration in port forwarding"));
     681
     682        /* protocol type */
     683        bool fUDP;
     684        char szProtocol[32];
     685        int rc;
     686        GET_STRING(rc, pDrvIns, pNode, "Protocol", szProtocol[0], sizeof(szProtocol));
     687        if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     688        {
     689            fUDP = false;
     690            GET_BOOL(rc, pDrvIns, pNode, "UDP", fUDP);
     691        }
     692        else if (RT_SUCCESS(rc))
     693        {
     694            if (!RTStrICmp(szProtocol, "TCP"))
     695                fUDP = false;
     696            else if (!RTStrICmp(szProtocol, "UDP"))
     697                fUDP = true;
     698            else
     699                return PDMDrvHlpVMSetError(pDrvIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
     700                    N_("NAT#%d: Invalid configuration value for \"Protocol\": \"%s\""),
     701                    iInstance, szProtocol);
     702        }
     703        else
     704            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     705                                       N_("NAT#%d: configuration query for \"Protocol\" failed"),
     706                                       iInstance);
     707        /* host port */
     708        int32_t iHostPort;
     709        GET_S32_STRICT(rc, pDrvIns, pNode, "HostPort", iHostPort);
     710
     711        /* guest port */
     712        int32_t iGuestPort;
     713        GET_S32_STRICT(rc, pDrvIns, pNode, "GuestPort", iGuestPort);
     714
     715        /* host address ("BindIP" name is rather unfortunate given "HostPort" to go with it) */
     716        struct in_addr BindIP;
     717        RT_ZERO(BindIP);
     718        GETIP_DEF(rc, pDrvIns, pNode, BindIP, INADDR_ANY);
     719
     720        /* guest address */
     721        struct in_addr GuestIP;
     722        RT_ZERO(GuestIP);
     723        GETIP_DEF(rc, pDrvIns, pNode, GuestIP, INADDR_ANY);
     724
     725        /*
     726         * Call slirp about it.
     727         */
     728        if (slirp_add_hostfwd(pThis->pNATState->pSlirp, fUDP, BindIP,
     729                              iHostPort, GuestIP, iGuestPort) < 0)
     730            return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_SETUP, RT_SRC_POS,
     731                                       N_("NAT#%d: configuration error: failed to set up "
     732                                       "redirection of %d to %d. Probably a conflict with "
     733                                       "existing services or other rules"), iInstance, iHostPort,
     734                                       iGuestPort);
     735    } /* for each redir rule */
     736
     737    return VINF_SUCCESS;
     738}
     739
     740/**
     741 * Applies port forwarding between guest and host.
     742 *
     743 * @param   pThis           Pointer to DRVNAT state for current context.
     744 * @param   fRemove         Flag to remove port forward instead of create.
     745 * @param   fUdp            Flag specifying if UDP. If false, TCP.
     746 * @param   pHostIp         String of host IP address.
     747 * @param   u16HostPort     Host port to forward to.
     748 * @param   pGuestIp        String of guest IP address.
     749 * @param   u16GuestPort    Guest port to forward.
     750 *
     751 * @thread  ?
     752 */
     753static DECLCALLBACK(void) drvNATNotifyApplyPortForwardCommand(PDRVNAT pThis, bool fRemove,
     754                                                              bool fUdp, const char *pHostIp,
     755                                                              uint16_t u16HostPort, const char *pGuestIp, uint16_t u16GuestPort)
     756{
     757    /** @todo r=jack:
     758     * - rewrite for IPv6
     759     * - do we want to lock the guestIp to the VMs IP?
     760     */
     761    struct in_addr guestIp, hostIp;
     762
     763    if (   pHostIp == NULL
     764        || inet_aton(pHostIp, &hostIp) == 0)
     765        hostIp.s_addr = INADDR_ANY;
     766
     767    if (   pGuestIp == NULL
     768        || inet_aton(pGuestIp, &guestIp) == 0)
     769        guestIp.s_addr = pThis->GuestIP;
     770
     771    if (fRemove)
     772        slirp_remove_hostfwd(pThis->pNATState->pSlirp, fUdp, hostIp, u16HostPort);
     773    else
     774        slirp_add_hostfwd(pThis->pNATState->pSlirp, fUdp, hostIp,
     775                          u16HostPort, guestIp, u16GuestPort);
     776}
     777
     778static DECLCALLBACK(int) drvNATNetworkNatConfigRedirect(PPDMINETWORKNATCONFIG pInterface, bool fRemove,
     779                                                        bool fUdp, const char *pHostIp, uint16_t u16HostPort,
     780                                                        const char *pGuestIp, uint16_t u16GuestPort)
     781{
     782    LogFlowFunc(("fRemove=%d, fUdp=%d, pHostIp=%s, u16HostPort=%u, pGuestIp=%s, u16GuestPort=%u\n",
     783                 RT_BOOL(fRemove), RT_BOOL(fUdp), pHostIp, u16HostPort, pGuestIp, u16GuestPort));
     784    PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkNATCfg);
     785    /* Execute the command directly if the VM is not running. */
     786    int rc;
     787    if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING)
     788    {
     789        drvNATNotifyApplyPortForwardCommand(pThis, fRemove, fUdp, pHostIp,
     790                                           u16HostPort, pGuestIp,u16GuestPort);
     791        rc = VINF_SUCCESS;
     792    }
     793    else
     794    {
     795        PRTREQ pReq;
     796        rc = RTReqQueueCallEx(pThis->hSlirpReqQueue, &pReq, 0 /*cMillies*/, RTREQFLAGS_VOID,
     797                              (PFNRT)drvNATNotifyApplyPortForwardCommand, 7, pThis, fRemove,
     798                              fUdp, pHostIp, u16HostPort, pGuestIp, u16GuestPort);
     799        if (rc == VERR_TIMEOUT)
     800        {
     801            drvNATNotifyNATThread(pThis, "drvNATNetworkNatConfigRedirect");
     802            rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);
     803            AssertRC(rc);
     804        }
     805        else
     806            AssertRC(rc);
     807
     808        RTReqRelease(pReq);
     809    }
     810    return rc;
     811}
     812
     813/**
     814 * Libslirp Utility Functions
     815 */
     816/**
     817 * Update the timeout field in given list of Slirp timers.
     818 *
     819 * @param uTimeout  Pointer to timeout value.
     820 * @param opaque    Pointer to NAT State context.
     821 *
     822 * @thread  ?
     823 */
     824static void drvNAT_UpdateTimeout(uint32_t *uTimeout, void *opaque)
     825{
     826    PDRVNAT pThis = (PDRVNAT)opaque;
     827    Assert(pThis);
     828
     829    int64_t currTime = drvNAT_ClockGetNsCb(pThis) / (1000 * 1000);
     830    SlirpTimer *pCurrent = pThis->pNATState->pTimerHead;
     831    while (pCurrent != NULL)
     832    {
     833        if (pCurrent->uTimeExpire != -1)
     834        {
     835            int64_t diff = pCurrent->uTimeExpire - currTime;
     836
     837            if (diff < 0)
     838                diff = 0;
     839
     840            if (diff < *uTimeout)
     841                *uTimeout = diff;
     842        }
     843
     844        pCurrent = pCurrent->next;
     845    }
     846}
     847
     848/**
     849 * Check if timeout has passed in given list of Slirp timers.
     850 *
     851 * @param   opaque  Pointer to NAT State context.
     852 *
     853 * @thread  ?
     854 */
     855static void drvNAT_CheckTimeout(void *opaque)
     856{
     857    PDRVNAT pThis = (PDRVNAT)opaque;
     858    Assert(pThis);
     859
     860    int64_t currTime = drvNAT_ClockGetNsCb(pThis) / (1000 * 1000);
     861    SlirpTimer *pCurrent = pThis->pNATState->pTimerHead;
     862    while (pCurrent != NULL)
     863    {
     864        if (pCurrent->uTimeExpire != -1)
     865        {
     866            int64_t diff = pCurrent->uTimeExpire - currTime;
     867            if (diff <= 0)
     868            {
     869                pCurrent->uTimeExpire = -1;
     870                pCurrent->pHandler(pCurrent->opaque);
     871            }
     872        }
     873
     874        pCurrent = pCurrent->next;
     875    }
    467876}
    468877
     
    522931
    523932/**
     933 * Libslirp Callbacks
     934 */
     935/**
     936 * Callback called by libslirp to send packet into guest.
     937 *
     938 * @param   pBuf    Pointer to packet buffer.
     939 * @param   cb      Size of packet.
     940 * @param   opaque  Pointer to NAT State context.
     941 *
     942 * @returns Size of packet received or -1 on error.
     943 *
     944 * @thread  ?
     945 */
     946static DECLCALLBACK(ssize_t) drvNAT_SendPacketCb(const void *pBuf, size_t cb, void *opaque /* PDRVNAT */)
     947{
     948    char *pNewBuf = (char *)RTMemAlloc(cb);
     949    if (pNewBuf == NULL)
     950        return -1;
     951
     952    memcpy(pNewBuf, pBuf, cb);
     953
     954    PDRVNAT pThis = (PDRVNAT)opaque;
     955    Assert(pThis);
     956
     957    LogFlow(("slirp_output BEGIN %p %d\n", pNewBuf, cb));
     958    Log6(("slirp_output: pNewBuf=%p cb=%#x (pThis=%p)\n"
     959          "%.*Rhxd\n", pNewBuf, cb, pThis, cb, pNewBuf));
     960
     961    /* don't queue new requests when the NAT thread is about to stop */
     962    if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING)
     963        return -1;
     964
     965    ASMAtomicIncU32(&pThis->cPkts);
     966    int rc = RTReqQueueCallEx(pThis->hRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
     967                              (PFNRT)drvNATRecvWorker, 3, pThis, pNewBuf, cb);
     968    AssertRC(rc);
     969    drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread);
     970    drvNATNotifyNATThread(pThis, "drvNAT_SendPacketCb");
     971    STAM_COUNTER_INC(&pThis->StatQueuePktSent);
     972    LogFlowFuncLeave();
     973    return cb;
     974}
     975
     976/**
     977 * Callback called by libslirp on an error from a guest.
     978 *
     979 * @param   pMsg    Error message string.
     980 * @param   opaque  Pointer to NAT State context.
     981 *
     982 * @thread  ?
     983 */
     984static DECLCALLBACK(void) drvNAT_GuestErrorCb(const char *pMsg, void *opaque)
     985{
     986    PDRVNAT pThis = (PDRVNAT)opaque;
     987    Assert(pThis);
     988
     989    PDMDRV_SET_ERROR(pThis->pDrvIns, VERR_PDM_UNKNOWN_DRVREG_VERSION,
     990                            N_("Unknown error: "));
     991    LogRel((pMsg));
     992}
     993
     994/**
     995 * Callback called by libslirp to get the current timestamp in nanoseconds.
     996 *
     997 * @param   opaque  Pointer to NAT State context.
     998 *
     999 * @returns 64-bit signed integer representing time in nanoseconds.
     1000 */
     1001static DECLCALLBACK(int64_t) drvNAT_ClockGetNsCb(void *opaque)
     1002{
     1003    PDRVNAT pThis = (PDRVNAT)opaque;
     1004    Assert(pThis);
     1005
     1006    RT_NOREF(pThis);
     1007
     1008    return (int64_t)RTTimeNanoTS();
     1009}
     1010
     1011/**
     1012 * Callback called by slirp to create a new timer and insert it into the given list.
     1013 *
     1014 * @param   slirpTimeCb     Callback function supplied to the new timer upon timer expiry.
     1015 *                          Called later by the timeout handler.
     1016 * @param   cb_opaque       Opaque object supplied to slirpTimeCb when called. Should be
     1017 *                          Identical to the opaque parameter.
     1018 * @param   opaque          Pointer to NAT State context.
     1019 *
     1020 * @returns Pointer to new timer.
     1021 */
     1022static DECLCALLBACK(void *) drvNAT_TimerNewCb(SlirpTimerCb slirpTimeCb, void *cb_opaque, void *opaque)
     1023{
     1024    PDRVNAT pThis = (PDRVNAT)opaque;
     1025    Assert(pThis);
     1026
     1027    SlirpTimer *pNewTimer = (SlirpTimer *)RTMemAlloc(sizeof(SlirpTimer));
     1028    if (!pNewTimer)
     1029        return NULL;
     1030
     1031    pNewTimer->next = pThis->pNATState->pTimerHead;
     1032    pNewTimer->uTimeExpire = -1;
     1033    pNewTimer->pHandler = slirpTimeCb;
     1034    pNewTimer->opaque = cb_opaque;
     1035    pThis->pNATState->pTimerHead = pNewTimer;
     1036
     1037    return pNewTimer;
     1038}
     1039
     1040/**
     1041 * Callback called by slirp to free a timer.
     1042 *
     1043 * @param   pTimer  Pointer to slirpTimer object to be freed.
     1044 * @param   opaque  Pointer to NAT State context.
     1045 */
     1046static DECLCALLBACK(void) drvNAT_TimerFreeCb(void *pTimer, void *opaque)
     1047{
     1048    PDRVNAT pThis = (PDRVNAT)opaque;
     1049    Assert(pThis);
     1050    SlirpTimer *pCurrent = pThis->pNATState->pTimerHead;
     1051
     1052    while (pCurrent != NULL)
     1053    {
     1054        if (pCurrent == (SlirpTimer *)pTimer)
     1055        {
     1056            SlirpTimer *pTmp = pCurrent->next;
     1057            RTMemFree(pCurrent);
     1058            pCurrent = pTmp;
     1059        }
     1060        else
     1061            pCurrent = pCurrent->next;
     1062    }
     1063}
     1064
     1065/**
     1066 * Callback called by slirp to modify a timer.
     1067 *
     1068 * @param   pTimer      Pointer to slirpTimer object to be modified.
     1069 * @param   expireTime  Signed 64-bit integer representing the new expiry time.
     1070 * @param   opaque      Pointer to NAT State context.
     1071 */
     1072static DECLCALLBACK(void) drvNAT_TimerModCb(void *pTimer, int64_t expireTime, void *opaque)
     1073{
     1074    PDRVNAT pThis = (PDRVNAT)opaque;
     1075    Assert(pThis);
     1076
     1077    RT_NOREF(pThis);
     1078
     1079    ((SlirpTimer *)pTimer)->uTimeExpire = expireTime;
     1080}
     1081
     1082/**
     1083 * Callback called by slirp when there is I/O that needs to happen.
     1084 *
     1085 * @param   opaque  Pointer to NAT State context.
     1086 */
     1087static DECLCALLBACK(void) drvNAT_NotifyCb(void *opaque)
     1088{
     1089    PDRVNAT pThis = (PDRVNAT)opaque;
     1090
     1091    drvNATAsyncIoWakeup(pThis->pDrvIns, NULL);
     1092}
     1093
     1094/**
     1095 * Registers poll. Unused function (other than logging).
     1096 */
     1097static DECLCALLBACK(void) drvNAT_RegisterPoll(int fd, void *opaque) {
     1098    RT_NOREF(fd, opaque);
     1099    Log4(("Poll registered\n"));
     1100}
     1101
     1102/**
     1103 * Unregisters poll. Unused function (other than logging).
     1104 */
     1105static DECLCALLBACK(void) drvNAT_UnregisterPoll(int fd, void *opaque) {
     1106    RT_NOREF(fd, opaque);
     1107    Log4(("Poll unregistered\n"));
     1108}
     1109
     1110/**
    5241111 * Callback function to add entry to pollfd array.
    5251112 *
     
    5331120 * @thread  ?
    5341121 */
    535 static int drvNAT_addPollCb(int iFd, int iEvents, void *opaque)
     1122static DECLCALLBACK(int) drvNAT_AddPollCb(int iFd, int iEvents, void *opaque)
    5361123{
    5371124    PDRVNAT pThis = (PDRVNAT)opaque;
     
    5721159 * @thread  ?
    5731160 */
    574 static int drvNAT_getREventsCb(int idx, void *opaque)
     1161static DECLCALLBACK(int) drvNAT_GetREventsCb(int idx, void *opaque)
    5751162{
    5761163    PDRVNAT pThis = (PDRVNAT)opaque;
     
    5801167
    5811168/**
    582  * NAT thread handling the slirp stuff.
    583  *
    584  * The slirp implementation is single-threaded so we execute this enginre in a
    585  * dedicated thread. We take care that this thread does not become the
    586  * bottleneck: If the guest wants to send, a request is enqueued into the
    587  * hSlirpReqQueue and handled asynchronously by this thread.  If this thread
    588  * wants to deliver packets to the guest, it enqueues a request into
    589  * hRecvReqQueue which is later handled by the Recv thread.
    590  *
    591  * @param   pDrvIns     Pointer to PDM driver context.
    592  * @param   pThread     Pointer to calling thread context.
    593  *
    594  * @returns VBox status code
    595  *
    596  * @thread  NAT
    597  */
    598 static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    599 {
    600     PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
    601 #ifdef RT_OS_WINDOWS
    602     unsigned int cBreak = 0;
    603 #else /* RT_OS_WINDOWS */
    604     unsigned int cPollNegRet = 0;
    605     drvNAT_addPollCb(RTPipeToNative(pThis->hPipeRead), SLIRP_POLL_IN | SLIRP_POLL_HUP, pThis);
    606     pThis->pNATState->polls[0].fd = RTPipeToNative(pThis->hPipeRead);
    607     pThis->pNATState->polls[0].events = POLLRDNORM | POLLPRI | POLLRDBAND;
    608     pThis->pNATState->polls[0].revents = 0;
    609 #endif /* !RT_OS_WINDOWS */
    610 
    611     LogFlow(("drvNATAsyncIoThread: pThis=%p\n", pThis));
    612 
    613     if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    614         return VINF_SUCCESS;
    615 
    616     if (pThis->enmLinkStateWant != pThis->enmLinkState)
    617         drvNATNotifyLinkChangedWorker(pThis, pThis->enmLinkStateWant);
    618 
    619     /*
    620      * Polling loop.
    621      */
    622     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    623     {
    624         /*
    625          * To prevent concurrent execution of sending/receiving threads
    626          */
    627 #ifndef RT_OS_WINDOWS
    628         uint32_t uTimeout = 0;
    629         pThis->pNATState->nsock = 1;
    630 
    631         slirp_pollfds_fill(pThis->pNATState->pSlirp, &uTimeout, drvNAT_addPollCb /* SlirpAddPollCb */, pThis /* opaque */);
    632         slirpUpdateTimeout(&uTimeout, pThis);
    633 
    634         int cChangedFDs = poll(pThis->pNATState->polls, pThis->pNATState->nsock, uTimeout /* timeout */);
    635 
    636         if (cChangedFDs < 0)
    637         {
    638             if (errno == EINTR)
    639             {
    640                 Log2(("NAT: signal was caught while sleep on poll\n"));
    641                 /* No error, just process all outstanding requests but don't wait */
    642                 cChangedFDs = 0;
    643             }
    644             else if (cPollNegRet++ > 128)
    645             {
    646                 LogRel(("NAT: Poll returns (%s) suppressed %d\n", strerror(errno), cPollNegRet));
    647                 cPollNegRet = 0;
    648             }
    649         }
    650 
    651 
    652         slirp_pollfds_poll(pThis->pNATState->pSlirp, cChangedFDs < 0, drvNAT_getREventsCb /* SlirpGetREventsCb */, pThis /* opaque */);
    653         if (pThis->pNATState->polls[0].revents & (POLLRDNORM|POLLPRI|POLLRDBAND))
    654         {
    655             /* drain the pipe
    656              *
    657              * Note! drvNATSend decoupled so we don't know how many times
    658              * device's thread sends before we've entered multiplex,
    659              * so to avoid false alarm drain pipe here to the very end
    660              *
    661              * @todo: Probably we should counter drvNATSend to count how
    662              * deep pipe has been filed before drain.
    663              *
    664              */
    665             /** @todo XXX: Make it reading exactly we need to drain the
    666              * pipe.*/
    667             char ch;
    668             size_t cbRead;
    669             RTPipeRead(pThis->hPipeRead, &ch, 1, &cbRead);
    670         }
    671 
    672         /* process _all_ outstanding requests but don't wait */
    673         RTReqQueueProcess(pThis->hSlirpReqQueue, 0);
    674         slirpCheckTimeout(pThis);
    675 
    676 #else /* RT_OS_WINDOWS */
    677         uint32_t uTimeout = 0;
    678         pThis->pNATState->nsock = 0;
    679         slirp_pollfds_fill(pThis->pNATState->pSlirp, &uTimeout, drvNAT_addPollCb /* SlirpAddPollCb */, pThis /* opaque */);
    680         slirpUpdateTimeout(&uTimeout, pThis);
    681 
    682         int cChangedFDs = WSAPoll(pThis->pNATState->polls, pThis->pNATState->nsock, uTimeout /* timeout */);
    683         int error = WSAGetLastError();
    684 
    685         if (cChangedFDs < 0)
    686         {
    687             LogFlow(("NAT: WSAPoll returned %d (error %d)\n", cChangedFDs, error));
    688             LogFlow(("NSOCK = %d\n", pThis->pNATState->nsock));
    689 
    690             if (error == 10022)
    691                 RTThreadSleep(100);
    692         }
    693 
    694         if (cChangedFDs == 0)
    695         {
    696             /* only check for slow/fast timers */
    697             slirp_pollfds_poll(pThis->pNATState->pSlirp, false /*select error*/, drvNAT_getREventsCb /* SlirpGetREventsCb */, pThis /* opaque */);
    698             RTReqQueueProcess(pThis->hSlirpReqQueue, 0);
    699             continue;
    700         }
    701         /* poll the sockets in any case */
    702         Log2(("%s: poll\n", __FUNCTION__));
    703         slirp_pollfds_poll(pThis->pNATState->pSlirp, cChangedFDs < 0 /*select error*/, drvNAT_getREventsCb /* SlirpGetREventsCb */, pThis /* opaque */);
    704 
    705         /* process _all_ outstanding requests but don't wait */
    706         RTReqQueueProcess(pThis->hSlirpReqQueue, 0);
    707         slirpCheckTimeout(pThis);
    708 # ifdef VBOX_NAT_DELAY_HACK
    709         if (cBreak++ > 128)
    710         {
    711             cBreak = 0;
    712             RTThreadSleep(2);
    713         }
    714 # endif
    715 #endif /* RT_OS_WINDOWS */
    716     }
    717 
    718     return VINF_SUCCESS;
    719 }
    720 
    721 /**
    722  * Unblock the send thread so it can respond to a state change.
    723  *
    724  * @returns VBox status code.
    725  * @param   pDrvIns     The pcnet device instance.
    726  * @param   pThread     The send thread.
    727  *
    728  * @thread  ?
    729  */
    730 static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    731 {
    732     RT_NOREF(pThread);
    733     PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
    734 
    735     drvNATNotifyNATThread(pThis, "drvNATAsyncIoWakeup");
    736     return VINF_SUCCESS;
    737 }
    738 
    739 /**
    740  * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    741  */
    742 static DECLCALLBACK(void *) drvNATQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    743 {
    744     PPDMDRVINS  pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    745     PDRVNAT     pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
    746 
    747     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    748     PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKUP, &pThis->INetworkUp);
    749     PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKNATCONFIG, &pThis->INetworkNATCfg);
    750     return NULL;
    751 }
    752 
    753 /**
    754  * Info handler.
    755  *
    756  * @param   pDrvIns     The PDM driver context.
    757  * @param   pHlp        ....
    758  * @param   pszArgs     Unused.
    759  *
    760  * @thread  any
    761  */
    762 static DECLCALLBACK(void) drvNATInfo(PPDMDRVINS pDrvIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    763 {
    764     RT_NOREF(pszArgs);
    765     PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
    766     pHlp->pfnPrintf(pHlp, "libslirp Connection Info:\n");
    767     pHlp->pfnPrintf(pHlp, slirp_connection_info(pThis->pNATState->pSlirp));
    768     pHlp->pfnPrintf(pHlp, "libslirp Neighbor Info:\n");
    769     pHlp->pfnPrintf(pHlp, slirp_neighbor_info(pThis->pNATState->pSlirp));
    770     pHlp->pfnPrintf(pHlp, "libslirp Version String: %s \n", slirp_version_string());
    771 }
    772 
    773 /**
    774  * Sets up the redirectors.
    775  *
    776  * @returns VBox status code.
    777  * @param   uInstance       ?
    778  * @param   pThis           ?
    779  * @param   pCfg            The configuration handle.
    780  * @param   pNetwork        Unused.
    781  *
    782  * @thread  ?
    783  */
    784 static int drvNATConstructRedir(unsigned iInstance, PDRVNAT pThis, PCFGMNODE pCfg, PRTNETADDRIPV4 pNetwork)
    785 {
    786     /** @todo r=jack: rewrite to support IPv6? */
    787     PPDMDRVINS pDrvIns = pThis->pDrvIns;
    788     PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
    789 
    790     RT_NOREF(pNetwork); /** @todo figure why pNetwork isn't used */
    791 
    792     PCFGMNODE pPFTree = pHlp->pfnCFGMGetChild(pCfg, "PortForwarding");
    793     if (pPFTree == NULL)
    794         return VINF_SUCCESS;
    795 
    796     /*
    797      * Enumerate redirections.
    798      */
    799     for (PCFGMNODE pNode = pHlp->pfnCFGMGetFirstChild(pPFTree); pNode; pNode = pHlp->pfnCFGMGetNextChild(pNode))
    800     {
    801         /*
    802          * Validate the port forwarding config.
    803          */
    804         if (!pHlp->pfnCFGMAreValuesValid(pNode, "Name\0Protocol\0UDP\0HostPort\0GuestPort\0GuestIP\0BindIP\0"))
    805             return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
    806                                     N_("Unknown configuration in port forwarding"));
    807 
    808         /* protocol type */
    809         bool fUDP;
    810         char szProtocol[32];
    811         int rc;
    812         GET_STRING(rc, pDrvIns, pNode, "Protocol", szProtocol[0], sizeof(szProtocol));
    813         if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    814         {
    815             fUDP = false;
    816             GET_BOOL(rc, pDrvIns, pNode, "UDP", fUDP);
    817         }
    818         else if (RT_SUCCESS(rc))
    819         {
    820             if (!RTStrICmp(szProtocol, "TCP"))
    821                 fUDP = false;
    822             else if (!RTStrICmp(szProtocol, "UDP"))
    823                 fUDP = true;
    824             else
    825                 return PDMDrvHlpVMSetError(pDrvIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
    826                     N_("NAT#%d: Invalid configuration value for \"Protocol\": \"%s\""),
    827                     iInstance, szProtocol);
    828         }
    829         else
    830             return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
    831                                        N_("NAT#%d: configuration query for \"Protocol\" failed"),
    832                                        iInstance);
    833         /* host port */
    834         int32_t iHostPort;
    835         GET_S32_STRICT(rc, pDrvIns, pNode, "HostPort", iHostPort);
    836 
    837         /* guest port */
    838         int32_t iGuestPort;
    839         GET_S32_STRICT(rc, pDrvIns, pNode, "GuestPort", iGuestPort);
    840 
    841         /* host address ("BindIP" name is rather unfortunate given "HostPort" to go with it) */
    842         struct in_addr BindIP;
    843         RT_ZERO(BindIP);
    844         GETIP_DEF(rc, pDrvIns, pNode, BindIP, INADDR_ANY);
    845 
    846         /* guest address */
    847         struct in_addr GuestIP;
    848         RT_ZERO(GuestIP);
    849         GETIP_DEF(rc, pDrvIns, pNode, GuestIP, INADDR_ANY);
    850 
    851         /*
    852          * Call slirp about it.
    853          */
    854         if (slirp_add_hostfwd(pThis->pNATState->pSlirp, fUDP, BindIP,
    855                               iHostPort, GuestIP, iGuestPort) < 0)
    856             return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_SETUP, RT_SRC_POS,
    857                                        N_("NAT#%d: configuration error: failed to set up "
    858                                        "redirection of %d to %d. Probably a conflict with "
    859                                        "existing services or other rules"), iInstance, iHostPort,
    860                                        iGuestPort);
    861     } /* for each redir rule */
    862 
    863     return VINF_SUCCESS;
    864 }
    865 
    866 /**
    867  * Applies port forwarding between guest and host.
    868  *
    869  * @param   pThis           Pointer to DRVNAT state for current context.
    870  * @param   fRemove         Flag to remove port forward instead of create.
    871  * @param   fUdp            Flag specifying if UDP. If false, TCP.
    872  * @param   pHostIp         String of host IP address.
    873  * @param   u16HostPort     Host port to forward to.
    874  * @param   pGuestIp        String of guest IP address.
    875  * @param   u16GuestPort    Guest port to forward.
    876  *
    877  * @thread  ?
    878  */
    879 static DECLCALLBACK(void) drvNATNotifyApplyPortForwardCommand(PDRVNAT pThis, bool fRemove,
    880                                                               bool fUdp, const char *pHostIp,
    881                                                               uint16_t u16HostPort, const char *pGuestIp, uint16_t u16GuestPort)
    882 {
    883     /** @todo r=jack:
    884      * - rewrite for IPv6
    885      * - do we want to lock the guestIp to the VMs IP?
    886      */
    887     struct in_addr guestIp, hostIp;
    888 
    889     if (   pHostIp == NULL
    890         || inet_aton(pHostIp, &hostIp) == 0)
    891         hostIp.s_addr = INADDR_ANY;
    892 
    893     if (   pGuestIp == NULL
    894         || inet_aton(pGuestIp, &guestIp) == 0)
    895         guestIp.s_addr = pThis->GuestIP;
    896 
    897     if (fRemove)
    898         slirp_remove_hostfwd(pThis->pNATState->pSlirp, fUdp, hostIp, u16HostPort);
    899     else
    900         slirp_add_hostfwd(pThis->pNATState->pSlirp, fUdp, hostIp,
    901                           u16HostPort, guestIp, u16GuestPort);
    902 }
    903 
    904 static DECLCALLBACK(int) drvNATNetworkNatConfigRedirect(PPDMINETWORKNATCONFIG pInterface, bool fRemove,
    905                                                         bool fUdp, const char *pHostIp, uint16_t u16HostPort,
    906                                                         const char *pGuestIp, uint16_t u16GuestPort)
    907 {
    908     LogFlowFunc(("fRemove=%d, fUdp=%d, pHostIp=%s, u16HostPort=%u, pGuestIp=%s, u16GuestPort=%u\n",
    909                  RT_BOOL(fRemove), RT_BOOL(fUdp), pHostIp, u16HostPort, pGuestIp, u16GuestPort));
    910     PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkNATCfg);
    911     /* Execute the command directly if the VM is not running. */
    912     int rc;
    913     if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING)
    914     {
    915         drvNATNotifyApplyPortForwardCommand(pThis, fRemove, fUdp, pHostIp,
    916                                            u16HostPort, pGuestIp,u16GuestPort);
    917         rc = VINF_SUCCESS;
    918     }
    919     else
    920     {
    921         PRTREQ pReq;
    922         rc = RTReqQueueCallEx(pThis->hSlirpReqQueue, &pReq, 0 /*cMillies*/, RTREQFLAGS_VOID,
    923                               (PFNRT)drvNATNotifyApplyPortForwardCommand, 7, pThis, fRemove,
    924                               fUdp, pHostIp, u16HostPort, pGuestIp, u16GuestPort);
    925         if (rc == VERR_TIMEOUT)
    926         {
    927             drvNATNotifyNATThread(pThis, "drvNATNetworkNatConfigRedirect");
    928             rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);
    929             AssertRC(rc);
    930         }
    931         else
    932             AssertRC(rc);
    933 
    934         RTReqRelease(pReq);
    935     }
    936     return rc;
    937 }
    938 
    939 /**
    940  * Update the timeout field in given list of Slirp timers.
    941  *
    942  * @param uTimeout  Pointer to timeout value.
    943  * @param opaque    Pointer to NAT State context.
    944  *
    945  * @thread  ?
    946  */
    947 static void slirpUpdateTimeout(uint32_t *uTimeout, void *opaque)
    948 {
    949     PDRVNAT pThis = (PDRVNAT)opaque;
    950     Assert(pThis);
    951 
    952     int64_t currTime = slirpClockGetNsCb(pThis) / (1000 * 1000);
    953     SlirpTimer *pCurrent = pThis->pNATState->pTimerHead;
    954     while (pCurrent != NULL)
    955     {
    956         if (pCurrent->uTimeExpire != -1)
    957         {
    958             int64_t diff = pCurrent->uTimeExpire - currTime;
    959 
    960             if (diff < 0)
    961                 diff = 0;
    962 
    963             if (diff < *uTimeout)
    964                 *uTimeout = diff;
    965         }
    966 
    967         pCurrent = pCurrent->next;
    968     }
    969 }
    970 
    971 /**
    972  * Check if timeout has passed in given list of Slirp timers.
    973  *
    974  * @param   opaque  Pointer to NAT State context.
    975  *
    976  * @thread  ?
    977  */
    978 static void slirpCheckTimeout(void *opaque)
    979 {
    980     PDRVNAT pThis = (PDRVNAT)opaque;
    981     Assert(pThis);
    982 
    983     int64_t currTime = slirpClockGetNsCb(pThis) / (1000 * 1000);
    984     SlirpTimer *pCurrent = pThis->pNATState->pTimerHead;
    985     while (pCurrent != NULL)
    986     {
    987         if (pCurrent->uTimeExpire != -1)
    988         {
    989             int64_t diff = pCurrent->uTimeExpire - currTime;
    990             if (diff <= 0)
    991             {
    992                 pCurrent->uTimeExpire = -1;
    993                 pCurrent->pHandler(pCurrent->opaque);
    994             }
    995         }
    996 
    997         pCurrent = pCurrent->next;
    998     }
    999 }
    1000 
    1001 /**
    1002  * CALLBACKS
    1003  */
    1004 
    1005 /**
    1006  * Callback called by libslirp to send packet into guest.
    1007  *
    1008  * @param   pBuf    Pointer to packet buffer.
    1009  * @param   cb      Size of packet.
    1010  * @param   opaque  Pointer to NAT State context.
    1011  *
    1012  * @returns Size of packet received or -1 on error.
    1013  *
    1014  * @thread  ?
    1015  */
    1016 static DECLCALLBACK(ssize_t) slirpSendPacketCb(const void *pBuf, size_t cb, void *opaque /* PDRVNAT */)
    1017 {
    1018     char *pNewBuf = (char *)RTMemAlloc(cb); /** @todo r=aeichner Missing check whether memory was actually allocated */
    1019     if (pNewBuf == NULL)
    1020         return -1;
    1021 
    1022     memcpy(pNewBuf, pBuf, cb);
    1023 
    1024     PDRVNAT pThis = (PDRVNAT)opaque;
    1025     Assert(pThis);
    1026 
    1027     LogFlow(("slirp_output BEGIN %p %d\n", pNewBuf, cb));
    1028     Log6(("slirp_output: pNewBuf=%p cb=%#x (pThis=%p)\n"
    1029           "%.*Rhxd\n", pNewBuf, cb, pThis, cb, pNewBuf));
    1030 
    1031     /* don't queue new requests when the NAT thread is about to stop */
    1032     if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING)
    1033         return -1;
    1034 
    1035     ASMAtomicIncU32(&pThis->cPkts);
    1036     int rc = RTReqQueueCallEx(pThis->hRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
    1037                               (PFNRT)drvNATRecvWorker, 3, pThis, pNewBuf, cb);
    1038     AssertRC(rc);
    1039     drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread);
    1040     drvNATNotifyNATThread(pThis, "slirpSendPacketCb");
    1041     STAM_COUNTER_INC(&pThis->StatQueuePktSent);
    1042     LogFlowFuncLeave();
    1043     return cb;
    1044 }
    1045 
    1046 /**
    1047  * Callback called by libslirp on an error from a guest.
    1048  *
    1049  * @param   pMsg    Error message string.
    1050  * @param   opaque  Pointer to NAT State context.
    1051  *
    1052  * @thread  ?
    1053  */
    1054 static DECLCALLBACK(void) slirpGuestErrorCb(const char *pMsg, void *opaque)
    1055 {
    1056     PDRVNAT pThis = (PDRVNAT)opaque;
    1057     Assert(pThis);
    1058 
    1059     PDMDRV_SET_ERROR(pThis->pDrvIns, VERR_PDM_UNKNOWN_DRVREG_VERSION,
    1060                             N_("Unknown error: "));
    1061     LogRel((pMsg));
    1062 }
    1063 
    1064 /**
    1065  * Callback called by libslirp to get the current timestamp in nanoseconds.
    1066  *
    1067  * @param   opaque  Pointer to NAT State context.
    1068  *
    1069  * @returns 64-bit signed integer representing time in nanoseconds.
    1070  */
    1071 static DECLCALLBACK(int64_t) slirpClockGetNsCb(void *opaque)
    1072 {
    1073     PDRVNAT pThis = (PDRVNAT)opaque;
    1074     Assert(pThis);
    1075 
    1076     RT_NOREF(pThis);
    1077 
    1078     return (int64_t)RTTimeNanoTS();
    1079 }
    1080 
    1081 
    1082 /**
    1083  * Callback called by slirp to create a new timer and insert it into the given list.
    1084  *
    1085  * @param   slirpTimeCb     Callback function supplied to the new timer upon timer expiry.
    1086  *                          Called later by the timeout handler.
    1087  * @param   cb_opaque       Opaque object supplied to slirpTimeCb when called. Should be
    1088  *                          Identical to the opaque parameter.
    1089  * @param   opaque          Pointer to NAT State context.
    1090  *
    1091  * @returns Pointer to new timer.
    1092  */
    1093 static DECLCALLBACK(void *) slirpTimerNewCb(SlirpTimerCb slirpTimeCb, void *cb_opaque, void *opaque)
    1094 {
    1095     PDRVNAT pThis = (PDRVNAT)opaque;
    1096     Assert(pThis);
    1097 
    1098     SlirpTimer *pNewTimer = (SlirpTimer *)RTMemAlloc(sizeof(SlirpTimer));
    1099     if (!pNewTimer)
    1100         return NULL;
    1101 
    1102     pNewTimer->next = pThis->pNATState->pTimerHead;
    1103     pNewTimer->uTimeExpire = -1;
    1104     pNewTimer->pHandler = slirpTimeCb;
    1105     pNewTimer->opaque = cb_opaque;
    1106     pThis->pNATState->pTimerHead = pNewTimer;
    1107 
    1108     return pNewTimer;
    1109 }
    1110 
    1111 /**
    1112  * Callback called by slirp to free a timer.
    1113  *
    1114  * @param   pTimer  Pointer to slirpTimer object to be freed.
    1115  * @param   opaque  Pointer to NAT State context.
    1116  */
    1117 static DECLCALLBACK(void) slirpTimerFreeCb(void *pTimer, void *opaque)
    1118 {
    1119     PDRVNAT pThis = (PDRVNAT)opaque;
    1120     Assert(pThis);
    1121     SlirpTimer *pCurrent = pThis->pNATState->pTimerHead;
    1122 
    1123     while (pCurrent != NULL)
    1124     {
    1125         if (pCurrent == (SlirpTimer *)pTimer)
    1126         {
    1127             SlirpTimer *pTmp = pCurrent->next;
    1128             RTMemFree(pCurrent);
    1129             pCurrent = pTmp;
    1130         }
    1131         else
    1132             pCurrent = pCurrent->next;
    1133     }
    1134 }
    1135 
    1136 /**
    1137  * Callback called by slirp to modify a timer.
    1138  *
    1139  * @param   pTimer      Pointer to slirpTimer object to be modified.
    1140  * @param   expireTime  Signed 64-bit integer representing the new expiry time.
    1141  * @param   opaque      Pointer to NAT State context.
    1142  */
    1143 static DECLCALLBACK(void) slirpTimerModCb(void *pTimer, int64_t expireTime, void *opaque)
    1144 {
    1145     PDRVNAT pThis = (PDRVNAT)opaque;
    1146     Assert(pThis);
    1147 
    1148     RT_NOREF(pThis);
    1149 
    1150     ((SlirpTimer *)pTimer)->uTimeExpire = expireTime;
    1151 }
    1152 
    1153 /**
    1154  * Callback called by slirp when there is I/O that needs to happen.
    1155  *
    1156  * @param   opaque  Pointer to NAT State context.
    1157  */
    1158 static DECLCALLBACK(void) slirpNotifyCb(void *opaque)
    1159 {
    1160     PDRVNAT pThis = (PDRVNAT)opaque;
    1161 
    1162     drvNATAsyncIoWakeup(pThis->pDrvIns, NULL);
    1163 }
    1164 
     1169 * Contructor/Destructor
     1170 */
    11651171/**
    11661172 * Destruct a driver instance.
     
    13951401    SlirpCb *slirpCallbacks = (struct SlirpCb *)RTMemAlloc(sizeof(SlirpCb));
    13961402
    1397     slirpCallbacks->send_packet = &slirpSendPacketCb;
    1398     slirpCallbacks->guest_error = &slirpGuestErrorCb;
    1399     slirpCallbacks->clock_get_ns = &slirpClockGetNsCb;
    1400     slirpCallbacks->timer_new = &slirpTimerNewCb;
    1401     slirpCallbacks->timer_free = &slirpTimerFreeCb;
    1402     slirpCallbacks->timer_mod = &slirpTimerModCb;
     1403    slirpCallbacks->send_packet = &drvNAT_SendPacketCb;
     1404    slirpCallbacks->guest_error = &drvNAT_GuestErrorCb;
     1405    slirpCallbacks->clock_get_ns = &drvNAT_ClockGetNsCb;
     1406    slirpCallbacks->timer_new = &drvNAT_TimerNewCb;
     1407    slirpCallbacks->timer_free = &drvNAT_TimerFreeCb;
     1408    slirpCallbacks->timer_mod = &drvNAT_TimerModCb;
    14031409    slirpCallbacks->register_poll_fd = &drvNAT_RegisterPoll;
    14041410    slirpCallbacks->unregister_poll_fd = &drvNAT_UnregisterPoll;
    1405     slirpCallbacks->notify = &slirpNotifyCb;
     1411    slirpCallbacks->notify = &drvNAT_NotifyCb;
    14061412    slirpCallbacks->init_completed = NULL;
    14071413    slirpCallbacks->timer_new_opaque = NULL;
  • trunk/src/VBox/Devices/Network/DrvNATlibslirp.h

    r105070 r105202  
    5353#endif
    5454
    55 /** @todo r=jack: do we need to externally define inet* functions on win */
    5655#ifdef RT_OS_WINDOWS
    5756# include <iprt/win/winsock2.h>
    58 # ifdef __cplusplus
    59 extern "C" {
    60 # endif
    61 int inet_pton(int,const char *,void *);
    62 # ifdef __cplusplus
    63 }
    64 # endif
    6557# define inet_aton(x, y) inet_pton(2, x, y)
    6658# define AF_INET6 23
     
    256248typedef DRVNAT *PDRVNAT;
    257249
     250/**
     251 * PDM Function Implementations
     252 */
    258253static DECLCALLBACK(int) drvNATRecv(PPDMDRVINS, PPDMTHREAD);
    259254static DECLCALLBACK(int) drvNATRecvWakeup(PPDMDRVINS, PPDMTHREAD);
     
    261256static void drvNATFreeSgBuf(PDRVNAT, PPDMSCATTERGATHER);
    262257static DECLCALLBACK(void) drvNATSendWorker(PDRVNAT, PPDMSCATTERGATHER);
     258static DECLCALLBACK(int) drvNATNetworkUp_BeginXmit(PPDMINETWORKUP, bool);
    263259static DECLCALLBACK(int) drvNATNetworkUp_AllocBuf(PPDMINETWORKUP, size_t,
    264260                                                  PCPDMNETWORKGSO, PPPDMSCATTERGATHER);
    265261static DECLCALLBACK(int) drvNATNetworkUp_FreeBuf(PPDMINETWORKUP, PPDMSCATTERGATHER);
    266262static DECLCALLBACK(int) drvNATNetworkUp_SendBuf(PPDMINETWORKUP, PPDMSCATTERGATHER, bool);
    267 static DECLCALLBACK(void) drvNATNetworkUp_EndXmit(PPDMINETWORKUP );
     263static DECLCALLBACK(void) drvNATNetworkUp_EndXmit(PPDMINETWORKUP);
    268264static void drvNATNotifyNATThread(PDRVNAT pThis, const char *);
    269265static DECLCALLBACK(void) drvNATNetworkUp_SetPromiscuousMode(PPDMINETWORKUP, bool);
     
    274270static DECLCALLBACK(void *) drvNATQueryInterface(PPDMIBASE, const char *);
    275271static DECLCALLBACK(void) drvNATInfo(PPDMDRVINS, PCDBGFINFOHLP, const char *);
    276 
    277 static void slirpUpdateTimeout(uint32_t *, void *);
    278 static void slirpCheckTimeout(void *);
    279 
    280 static DECLCALLBACK(ssize_t) slirpSendPacketCb(const void *, size_t, void *);
    281 static DECLCALLBACK(void) slirpGuestErrorCb(const char *, void *);
    282 static DECLCALLBACK(int64_t) slirpClockGetNsCb(void *);
    283 static DECLCALLBACK(void *) slirpTimerNewCb(SlirpTimerCb, void *, void *);
    284 static DECLCALLBACK(void) slirpTimerFreeCb(void *, void *);
    285 static DECLCALLBACK(void) slirpTimerModCb(void *, int64_t, void *);
    286 
     272static int drvNATConstructRedir(unsigned, PDRVNAT, PCFGMNODE, PRTNETADDRIPV4);
     273static DECLCALLBACK(void) drvNATNotifyApplyPortForwardCommand(PDRVNAT, bool, bool, const char *,
     274                                                              uint16_t, const char *, uint16_t);
     275static DECLCALLBACK(int) drvNATNetworkNatConfigRedirect(PPDMINETWORKNATCONFIG, bool, bool,
     276                                                        const char *, uint16_t, const char *, uint16_t);
     277
     278/**
     279 * Libslirp Utility Functions
     280 */
     281static void drvNAT_UpdateTimeout(uint32_t *, void *);
     282static void drvNAT_CheckTimeout(void *);
     283static int drvNAT_PollEventSlirpToHost(int);
     284static int drvNAT_PollEventHostToSlirp(int);
     285
     286/**
     287 * Libslirp Callback Functions
     288 */
     289static DECLCALLBACK(ssize_t) drvNAT_SendPacketCb(const void *, size_t, void *);
     290static DECLCALLBACK(void) drvNAT_GuestErrorCb(const char *, void *);
     291static DECLCALLBACK(int64_t) drvNAT_ClockGetNsCb(void *);
     292static DECLCALLBACK(void *) drvNAT_TimerNewCb(SlirpTimerCb, void *, void *);
     293static DECLCALLBACK(void) drvNAT_TimerFreeCb(void *, void *);
     294static DECLCALLBACK(void) drvNAT_TimerModCb(void *, int64_t, void *);
     295static DECLCALLBACK(void) drvNAT_NotifyCb(void *);
     296static DECLCALLBACK(void) drvNAT_RegisterPoll(int, void *);
     297static DECLCALLBACK(void) drvNAT_UnregisterPoll(int, void *);
     298
     299static DECLCALLBACK(int) drvNAT_AddPollCb(int, int, void *);
     300static DECLCALLBACK(int) drvNAT_GetREventsCb(int, void *);
     301
     302/**
     303 * Contructor/Destructor
     304 */
    287305static DECLCALLBACK(void) drvNATDestruct(PPDMDRVINS);
    288306static DECLCALLBACK(int) drvNATConstruct(PPDMDRVINS, PCFGMNODE, uint32_t);
  • trunk/src/libs/libslirp-4.7.0/src/nathandletable.c

    r105101 r105202  
    4343    {
    4444        pNATHandleTable = RTMemAlloc(sizeof(RTHANDLETABLE));
    45         int rc = RTHandleTableCreate(pNATHandleTable)
     45        int rc = RTHandleTableCreate(pNATHandleTable);
    4646        AssertRC(rc);
    4747    }
     
    6262
    6363    LogFlowFunc(("Creating sock %llu on %p\n", uSocket, (void *)pNATHandleTable));
    64     return RTHandleTableAlloc(*pNATHandleTable, uSocket, pHandle);
     64    return RTHandleTableAlloc(*pNATHandleTable, (void *)uSocket, pHandle);
    6565}
    6666
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