Changeset 105202 in vbox
- Timestamp:
- Jul 8, 2024 10:42:06 PM (8 months ago)
- svn:sync-xref-src-repo-rev:
- 163845
- Location:
- trunk/src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvNATlibslirp.cpp
r105201 r105202 35 35 36 36 37 /** *******************************************************************************************************************************38 * Internal Functions * 39 *********************************************************************************************************************************/37 /** 38 * PDM Function Implementations 39 */ 40 40 41 41 /** … … 368 368 { 369 369 RT_NOREF(pszWho); 370 int rc ;370 int rc = 0; 371 371 #ifndef RT_OS_WINDOWS 372 372 /* kick poll() */ 373 373 size_t cbIgnored; 374 374 rc = RTPipeWrite(pThis->hPipeWrite, "", 1, &cbIgnored); 375 #else 376 RT_NOREF(pThis); 375 377 #endif 376 378 AssertRC(rc); … … 452 454 453 455 /** 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 */ 472 static 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 */ 604 static 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 */ 616 static 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 */ 636 static 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 */ 658 static 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 */ 753 static 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 778 static 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 */ 824 static 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 */ 855 static 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 } 467 876 } 468 877 … … 522 931 523 932 /** 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 */ 946 static 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 */ 984 static 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 */ 1001 static 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 */ 1022 static 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 */ 1046 static 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 */ 1072 static 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 */ 1087 static 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 */ 1097 static 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 */ 1105 static DECLCALLBACK(void) drvNAT_UnregisterPoll(int fd, void *opaque) { 1106 RT_NOREF(fd, opaque); 1107 Log4(("Poll unregistered\n")); 1108 } 1109 1110 /** 524 1111 * Callback function to add entry to pollfd array. 525 1112 * … … 533 1120 * @thread ? 534 1121 */ 535 static int drvNAT_addPollCb(int iFd, int iEvents, void *opaque)1122 static DECLCALLBACK(int) drvNAT_AddPollCb(int iFd, int iEvents, void *opaque) 536 1123 { 537 1124 PDRVNAT pThis = (PDRVNAT)opaque; … … 572 1159 * @thread ? 573 1160 */ 574 static int drvNAT_getREventsCb(int idx, void *opaque)1161 static DECLCALLBACK(int) drvNAT_GetREventsCb(int idx, void *opaque) 575 1162 { 576 1163 PDRVNAT pThis = (PDRVNAT)opaque; … … 580 1167 581 1168 /** 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 */ 1165 1171 /** 1166 1172 * Destruct a driver instance. … … 1395 1401 SlirpCb *slirpCallbacks = (struct SlirpCb *)RTMemAlloc(sizeof(SlirpCb)); 1396 1402 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; 1403 1409 slirpCallbacks->register_poll_fd = &drvNAT_RegisterPoll; 1404 1410 slirpCallbacks->unregister_poll_fd = &drvNAT_UnregisterPoll; 1405 slirpCallbacks->notify = & slirpNotifyCb;1411 slirpCallbacks->notify = &drvNAT_NotifyCb; 1406 1412 slirpCallbacks->init_completed = NULL; 1407 1413 slirpCallbacks->timer_new_opaque = NULL; -
trunk/src/VBox/Devices/Network/DrvNATlibslirp.h
r105070 r105202 53 53 #endif 54 54 55 /** @todo r=jack: do we need to externally define inet* functions on win */56 55 #ifdef RT_OS_WINDOWS 57 56 # include <iprt/win/winsock2.h> 58 # ifdef __cplusplus59 extern "C" {60 # endif61 int inet_pton(int,const char *,void *);62 # ifdef __cplusplus63 }64 # endif65 57 # define inet_aton(x, y) inet_pton(2, x, y) 66 58 # define AF_INET6 23 … … 256 248 typedef DRVNAT *PDRVNAT; 257 249 250 /** 251 * PDM Function Implementations 252 */ 258 253 static DECLCALLBACK(int) drvNATRecv(PPDMDRVINS, PPDMTHREAD); 259 254 static DECLCALLBACK(int) drvNATRecvWakeup(PPDMDRVINS, PPDMTHREAD); … … 261 256 static void drvNATFreeSgBuf(PDRVNAT, PPDMSCATTERGATHER); 262 257 static DECLCALLBACK(void) drvNATSendWorker(PDRVNAT, PPDMSCATTERGATHER); 258 static DECLCALLBACK(int) drvNATNetworkUp_BeginXmit(PPDMINETWORKUP, bool); 263 259 static DECLCALLBACK(int) drvNATNetworkUp_AllocBuf(PPDMINETWORKUP, size_t, 264 260 PCPDMNETWORKGSO, PPPDMSCATTERGATHER); 265 261 static DECLCALLBACK(int) drvNATNetworkUp_FreeBuf(PPDMINETWORKUP, PPDMSCATTERGATHER); 266 262 static DECLCALLBACK(int) drvNATNetworkUp_SendBuf(PPDMINETWORKUP, PPDMSCATTERGATHER, bool); 267 static DECLCALLBACK(void) drvNATNetworkUp_EndXmit(PPDMINETWORKUP 263 static DECLCALLBACK(void) drvNATNetworkUp_EndXmit(PPDMINETWORKUP); 268 264 static void drvNATNotifyNATThread(PDRVNAT pThis, const char *); 269 265 static DECLCALLBACK(void) drvNATNetworkUp_SetPromiscuousMode(PPDMINETWORKUP, bool); … … 274 270 static DECLCALLBACK(void *) drvNATQueryInterface(PPDMIBASE, const char *); 275 271 static 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 272 static int drvNATConstructRedir(unsigned, PDRVNAT, PCFGMNODE, PRTNETADDRIPV4); 273 static DECLCALLBACK(void) drvNATNotifyApplyPortForwardCommand(PDRVNAT, bool, bool, const char *, 274 uint16_t, const char *, uint16_t); 275 static DECLCALLBACK(int) drvNATNetworkNatConfigRedirect(PPDMINETWORKNATCONFIG, bool, bool, 276 const char *, uint16_t, const char *, uint16_t); 277 278 /** 279 * Libslirp Utility Functions 280 */ 281 static void drvNAT_UpdateTimeout(uint32_t *, void *); 282 static void drvNAT_CheckTimeout(void *); 283 static int drvNAT_PollEventSlirpToHost(int); 284 static int drvNAT_PollEventHostToSlirp(int); 285 286 /** 287 * Libslirp Callback Functions 288 */ 289 static DECLCALLBACK(ssize_t) drvNAT_SendPacketCb(const void *, size_t, void *); 290 static DECLCALLBACK(void) drvNAT_GuestErrorCb(const char *, void *); 291 static DECLCALLBACK(int64_t) drvNAT_ClockGetNsCb(void *); 292 static DECLCALLBACK(void *) drvNAT_TimerNewCb(SlirpTimerCb, void *, void *); 293 static DECLCALLBACK(void) drvNAT_TimerFreeCb(void *, void *); 294 static DECLCALLBACK(void) drvNAT_TimerModCb(void *, int64_t, void *); 295 static DECLCALLBACK(void) drvNAT_NotifyCb(void *); 296 static DECLCALLBACK(void) drvNAT_RegisterPoll(int, void *); 297 static DECLCALLBACK(void) drvNAT_UnregisterPoll(int, void *); 298 299 static DECLCALLBACK(int) drvNAT_AddPollCb(int, int, void *); 300 static DECLCALLBACK(int) drvNAT_GetREventsCb(int, void *); 301 302 /** 303 * Contructor/Destructor 304 */ 287 305 static DECLCALLBACK(void) drvNATDestruct(PPDMDRVINS); 288 306 static DECLCALLBACK(int) drvNATConstruct(PPDMDRVINS, PCFGMNODE, uint32_t); -
trunk/src/libs/libslirp-4.7.0/src/nathandletable.c
r105101 r105202 43 43 { 44 44 pNATHandleTable = RTMemAlloc(sizeof(RTHANDLETABLE)); 45 int rc = RTHandleTableCreate(pNATHandleTable) 45 int rc = RTHandleTableCreate(pNATHandleTable); 46 46 AssertRC(rc); 47 47 } … … 62 62 63 63 LogFlowFunc(("Creating sock %llu on %p\n", uSocket, (void *)pNATHandleTable)); 64 return RTHandleTableAlloc(*pNATHandleTable, uSocket, pHandle);64 return RTHandleTableAlloc(*pNATHandleTable, (void *)uSocket, pHandle); 65 65 } 66 66
Note:
See TracChangeset
for help on using the changeset viewer.