~ubuntu-branches/ubuntu/trusty/virtualbox/trusty-proposed

« back to all changes in this revision

Viewing changes to src/VBox/Devices/Network/DrvNAT.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2013-03-07 16:38:36 UTC
  • mfrom: (1.1.13) (3.1.20 experimental)
  • Revision ID: package-import@ubuntu.com-20130307163836-p93jpbgx39tp3gb4
Tags: 4.2.8-dfsg-0ubuntu1
* New upstream release. (Closes: #691148)
  - Fixes compatibility with kernel 3.8. (Closes: #700823; LP: #1101867)
* Switch to my @debian.org email address.
* Move package to contrib as virtualbox 4.2 needs a non-free compiler to
  build the BIOS.
* Build-depend on libdevmapper-dev.
* Refresh patches.
  - Drop 36-fix-ftbfs-xserver-112.patch, cve-2012-3221.patch,
    CVE-2013-0420.patch 37-kcompat-3.6.patch and 38-kcompat-3.7.patch.
* Drop all virtualbox-ose transitional packages.
* Drop the virtualbox-fuse package as vdfuse fails to build with
  virtualbox 4.2.
* Update install files and VBox.sh.
* Bump required kbuild version to 0.1.9998svn2577.
* Fix path to VBoxCreateUSBNode.sh in virtualbox.postinst. (Closes: #700479)
* Add an init script to virtuabox-guest-x11 which loads the vboxvideo
  kernel module. The X Server 1.13 doesn't load it anymore. (Closes: #686994)
* Update man pages. (Closes: #680053)
* Add 36-python-multiarch.patch from Rico Tzschichholz to fix detection of
  python in multiarch paths using pkg-config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 */
5
5
 
6
6
/*
7
 
 * Copyright (C) 2006-2011 Oracle Corporation
 
7
 * Copyright (C) 2006-2012 Oracle Corporation
8
8
 *
9
9
 * This file is part of VirtualBox Open Source Edition (OSE), as
10
10
 * available from http://www.virtualbox.org. This file is free software;
153
153
    /** Polling thread. */
154
154
    PPDMTHREAD              pSlirpThread;
155
155
    /** Queue for NAT-thread-external events. */
156
 
    PRTREQQUEUE             pSlirpReqQueue;
 
156
    RTREQQUEUE              hSlirpReqQueue;
157
157
    /** The guest IP for port-forwarding. */
158
158
    uint32_t                GuestIP;
159
159
    /** Link state set when the VM is suspended. */
160
160
    PDMNETWORKLINKSTATE     enmLinkStateWant;
161
161
 
162
 
#ifdef VBOX_WITH_SLIRP_MT
163
 
    PPDMTHREAD              pGuestThread;
164
 
#endif
165
162
#ifndef RT_OS_WINDOWS
166
163
    /** The write end of the control pipe. */
167
164
    RTPIPE                  hPipeWrite;
184
181
    /** event to wakeup the guest urgent receive thread */
185
182
    RTSEMEVENT              EventUrgRecv;
186
183
    /** Receive Req queue (deliver packets to the guest) */
187
 
    PRTREQQUEUE             pRecvReqQueue;
 
184
    RTREQQUEUE              hRecvReqQueue;
188
185
    /** Receive Urgent Req queue (deliver packets to the guest). */
189
 
    PRTREQQUEUE             pUrgRecvReqQueue;
 
186
    RTREQQUEUE              hUrgRecvReqQueue;
190
187
 
191
188
    /** makes access to device func RecvAvail and Recv atomical. */
192
189
    RTCRITSECT              DevAccessLock;
199
196
    RTCRITSECT              XmitLock;
200
197
} DRVNAT;
201
198
AssertCompileMemberAlignment(DRVNAT, StatNATRecvWakeups, 8);
202
 
/** Pointer the NAT driver instance data. */
 
199
/** Pointer to the NAT driver instance data. */
203
200
typedef DRVNAT *PDRVNAT;
204
201
 
205
202
 
218
215
 
219
216
    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
220
217
    {
221
 
        RTReqProcess(pThis->pRecvReqQueue, 0);
 
218
        RTReqQueueProcess(pThis->hRecvReqQueue, 0);
222
219
        if (ASMAtomicReadU32(&pThis->cPkts) == 0)
223
220
            RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT);
224
221
    }
245
242
 
246
243
    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
247
244
    {
248
 
        RTReqProcess(pThis->pUrgRecvReqQueue, 0);
 
245
        RTReqQueueProcess(pThis->hUrgRecvReqQueue, 0);
249
246
        if (ASMAtomicReadU32(&pThis->cUrgPkts) == 0)
250
247
        {
251
248
            int rc = RTSemEventWait(pThis->EventUrgRecv, RT_INDEFINITE_WAIT);
400
397
            {
401
398
                size_t cbSeg;
402
399
                void  *pvSeg;
403
 
                m = slirp_ext_m_get(pThis->pNATState, pGso->cbHdrs + pGso->cbMaxSeg, &pvSeg, &cbSeg);
 
400
                m = slirp_ext_m_get(pThis->pNATState, pGso->cbHdrsTotal + pGso->cbMaxSeg, &pvSeg, &cbSeg);
404
401
                if (!m)
405
402
                    break;
406
403
 
407
404
#if 1
408
 
                uint32_t cbPayload;
 
405
                uint32_t cbPayload, cbHdrs;
409
406
                uint32_t offPayload = PDMNetGsoCarveSegment(pGso, pbFrame, pSgBuf->cbUsed,
410
 
                                                            iSeg, cSegs, (uint8_t *)pvSeg, &cbPayload);
411
 
                memcpy((uint8_t *)pvSeg + pGso->cbHdrs, pbFrame + offPayload, cbPayload);
 
407
                                                            iSeg, cSegs, (uint8_t *)pvSeg, &cbHdrs, &cbPayload);
 
408
                memcpy((uint8_t *)pvSeg + cbHdrs, pbFrame + offPayload, cbPayload);
412
409
 
413
 
                slirp_input(pThis->pNATState, m, cbPayload + pGso->cbHdrs);
 
410
                slirp_input(pThis->pNATState, m, cbPayload + cbHdrs);
414
411
#else
415
412
                uint32_t cbSegFrame;
416
413
                void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)pbFrame, pSgBuf->cbUsed, abHdrScratch,
533
530
        /* Set an FTM checkpoint as this operation changes the state permanently. */
534
531
        PDMDrvHlpFTSetCheckpoint(pThis->pDrvIns, FTMCHECKPOINTTYPE_NETWORK);
535
532
 
536
 
#ifdef VBOX_WITH_SLIRP_MT
537
 
        PRTREQQUEUE pQueue = (PRTREQQUEUE)slirp_get_queue(pThis->pNATState);
538
 
#else
539
 
        PRTREQQUEUE pQueue = pThis->pSlirpReqQueue;
540
 
#endif
541
 
        rc = RTReqCallEx(pQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
542
 
                         (PFNRT)drvNATSendWorker, 2, pThis, pSgBuf);
 
533
 
 
534
        RTREQQUEUE hQueue = pThis->hSlirpReqQueue;
 
535
 
 
536
        rc = RTReqQueueCallEx(hQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
 
537
                              (PFNRT)drvNATSendWorker, 2, pThis, pSgBuf);
543
538
        if (RT_SUCCESS(rc))
544
539
        {
545
540
            drvNATNotifyNATThread(pThis, "drvNATNetworkUp_SendBuf");
636
631
    }
637
632
 
638
633
    PRTREQ pReq;
639
 
    int rc = RTReqCallEx(pThis->pSlirpReqQueue, &pReq, 0 /*cMillies*/, RTREQFLAGS_VOID,
640
 
                         (PFNRT)drvNATNotifyLinkChangedWorker, 2, pThis, enmLinkState);
 
634
    int rc = RTReqQueueCallEx(pThis->hSlirpReqQueue, &pReq, 0 /*cMillies*/, RTREQFLAGS_VOID,
 
635
                              (PFNRT)drvNATNotifyLinkChangedWorker, 2, pThis, enmLinkState);
641
636
    if (RT_LIKELY(rc == VERR_TIMEOUT))
642
637
    {
643
638
        drvNATNotifyNATThread(pThis, "drvNATNetworkUp_NotifyLinkChanged");
646
641
    }
647
642
    else
648
643
        AssertRC(rc);
649
 
    RTReqFree(pReq);
 
644
    RTReqRelease(pReq);
650
645
}
651
646
 
652
647
static void drvNATNotifyApplyPortForwardCommand(PDRVNAT pThis, bool fRemove,
683
678
                 u16GuestPort));
684
679
    PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkNATCfg);
685
680
    PRTREQ pReq;
686
 
    int rc = RTReqCallEx(pThis->pSlirpReqQueue, &pReq, 0 /*cMillies*/, RTREQFLAGS_VOID,
687
 
                         (PFNRT)drvNATNotifyApplyPortForwardCommand, 7, pThis, fRemove,
688
 
                         fUdp, pHostIp, u16HostPort, pGuestIp, u16GuestPort);
 
681
    int rc = RTReqQueueCallEx(pThis->hSlirpReqQueue, &pReq, 0 /*cMillies*/, RTREQFLAGS_VOID,
 
682
                              (PFNRT)drvNATNotifyApplyPortForwardCommand, 7, pThis, fRemove,
 
683
                              fUdp, pHostIp, u16HostPort, pGuestIp, u16GuestPort);
689
684
    if (RT_LIKELY(rc == VERR_TIMEOUT))
690
685
    {
691
686
        drvNATNotifyNATThread(pThis, "drvNATNetworkNatConfig_RedirectRuleCommand");
695
690
    else
696
691
        AssertRC(rc);
697
692
 
698
 
    RTReqFree(pReq);
 
693
    RTReqRelease(pReq);
699
694
    port_forwarding_done:
700
695
    return rc;
701
696
}
706
701
 * The slirp implementation is single-threaded so we execute this enginre in a
707
702
 * dedicated thread. We take care that this thread does not become the
708
703
 * bottleneck: If the guest wants to send, a request is enqueued into the
709
 
 * pSlirpReqQueue and handled asynchronously by this thread.  If this thread
 
704
 * hSlirpReqQueue and handled asynchronously by this thread.  If this thread
710
705
 * wants to deliver packets to the guest, it enqueues a request into
711
 
 * pRecvReqQueue which is later handled by the Recv thread.
 
706
 * hRecvReqQueue which is later handled by the Recv thread.
712
707
 */
713
708
static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
714
709
{
791
786
            }
792
787
        }
793
788
        /* process _all_ outstanding requests but don't wait */
794
 
        RTReqProcess(pThis->pSlirpReqQueue, 0);
 
789
        RTReqQueueProcess(pThis->hSlirpReqQueue, 0);
795
790
        RTMemFree(polls);
796
791
 
797
792
#else /* RT_OS_WINDOWS */
818
813
        Log2(("%s: poll\n", __FUNCTION__));
819
814
        slirp_select_poll(pThis->pNATState, /* fTimeout=*/false, /* fIcmp=*/(dwEvent == WSA_WAIT_EVENT_0));
820
815
        /* process _all_ outstanding requests but don't wait */
821
 
        RTReqProcess(pThis->pSlirpReqQueue, 0);
 
816
        RTReqQueueProcess(pThis->hSlirpReqQueue, 0);
822
817
# ifdef VBOX_NAT_DELAY_HACK
823
818
        if (cBreak++ > 128)
824
819
        {
848
843
    return VINF_SUCCESS;
849
844
}
850
845
 
851
 
#ifdef VBOX_WITH_SLIRP_MT
852
 
 
853
 
static DECLCALLBACK(int) drvNATAsyncIoGuest(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
854
 
{
855
 
    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
856
 
 
857
 
    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
858
 
        return VINF_SUCCESS;
859
 
 
860
 
    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
861
 
        slirp_process_queue(pThis->pNATState);
862
 
 
863
 
    return VINF_SUCCESS;
864
 
}
865
 
 
866
 
 
867
 
static DECLCALLBACK(int) drvNATAsyncIoGuestWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
868
 
{
869
 
    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
870
 
 
871
 
    return VINF_SUCCESS;
872
 
}
873
 
 
874
 
#endif /* VBOX_WITH_SLIRP_MT */
875
 
 
876
846
/**
877
847
 * Function called by slirp to check if it's possible to feed incoming data to the network port.
878
848
 * @returns 1 if possible.
902
872
        return;
903
873
 
904
874
    ASMAtomicIncU32(&pThis->cUrgPkts);
905
 
    int rc = RTReqCallEx(pThis->pUrgRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
906
 
                         (PFNRT)drvNATUrgRecvWorker, 4, pThis, pu8Buf, cb, m);
 
875
    int rc = RTReqQueueCallEx(pThis->hUrgRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
 
876
                              (PFNRT)drvNATUrgRecvWorker, 4, pThis, pu8Buf, cb, m);
907
877
    AssertRC(rc);
908
878
    drvNATUrgRecvWakeup(pThis->pDrvIns, pThis->pUrgRecvThread);
909
879
}
915
885
{
916
886
    PDRVNAT pThis = (PDRVNAT)pvUser;
917
887
    Assert(pThis);
 
888
    LogFlowFuncEnter();
918
889
    pThis->pIAboveNet->pfnXmitPending(pThis->pIAboveNet);
 
890
    LogFlowFuncLeave();
919
891
}
920
892
 
921
893
/**
936
908
        return;
937
909
 
938
910
    ASMAtomicIncU32(&pThis->cPkts);
939
 
    int rc = RTReqCallEx(pThis->pRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
940
 
                         (PFNRT)drvNATRecvWorker, 4, pThis, pu8Buf, cb, m);
 
911
    int rc = RTReqQueueCallEx(pThis->hRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
 
912
                              (PFNRT)drvNATRecvWorker, 4, pThis, pu8Buf, cb, m);
941
913
    AssertRC(rc);
942
914
    drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread);
943
915
    STAM_COUNTER_INC(&pThis->StatQueuePktSent);
 
916
    LogFlowFuncLeave();
944
917
}
945
918
 
946
919
 
1019
992
            return PDMDRV_SET_ERROR(pThis->pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
1020
993
                                    N_("Unknown configuration in dns mapping"));
1021
994
        char szHostNameOrPattern[255];
1022
 
        /* fMatch = false used for equal matching, and true if regex is used */
1023
 
        bool fMatch = false;
 
995
        bool fMatch = false;    /* false used for equal matching, and true if wildcard pattern is used. */
1024
996
        RT_ZERO(szHostNameOrPattern);
1025
997
        GET_STRING(rc, pThis, pNode, "HostName", szHostNameOrPattern[0], sizeof(szHostNameOrPattern));
1026
998
        if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1167
1139
        pThis->pNATState = NULL;
1168
1140
    }
1169
1141
 
1170
 
    RTReqDestroyQueue(pThis->pSlirpReqQueue);
1171
 
    pThis->pSlirpReqQueue = NULL;
 
1142
    RTReqQueueDestroy(pThis->hSlirpReqQueue);
 
1143
    pThis->hSlirpReqQueue = NIL_RTREQQUEUE;
1172
1144
 
1173
 
    RTReqDestroyQueue(pThis->pUrgRecvReqQueue);
1174
 
    pThis->pUrgRecvReqQueue = NULL;
 
1145
    RTReqQueueDestroy(pThis->hUrgRecvReqQueue);
 
1146
    pThis->hUrgRecvReqQueue = NIL_RTREQQUEUE;
1175
1147
 
1176
1148
    RTSemEventDestroy(pThis->EventRecv);
1177
1149
    pThis->EventRecv = NIL_RTSEMEVENT;
1224
1196
    pThis->pszTFTPPrefix                = NULL;
1225
1197
    pThis->pszBootFile                  = NULL;
1226
1198
    pThis->pszNextServer                = NULL;
1227
 
    pThis->pSlirpReqQueue               = NULL;
1228
 
    pThis->pUrgRecvReqQueue             = NULL;
 
1199
    pThis->hSlirpReqQueue               = NIL_RTREQQUEUE;
 
1200
    pThis->hUrgRecvReqQueue             = NIL_RTREQQUEUE;
1229
1201
    pThis->EventRecv                    = NIL_RTSEMEVENT;
1230
1202
    pThis->EventUrgRecv                 = NIL_RTSEMEVENT;
1231
1203
 
1319
1291
        char *pszBindIP = NULL;
1320
1292
        GET_STRING_ALLOC(rc, pThis, pCfg, "BindIP", pszBindIP);
1321
1293
        rc = slirp_set_binding_address(pThis->pNATState, pszBindIP);
1322
 
        if (rc != 0)
 
1294
        if (rc != 0 && pszBindIP && *pszBindIP)
1323
1295
            LogRel(("NAT: value of BindIP has been ignored\n"));
1324
1296
 
1325
1297
        if(pszBindIP != NULL)
1362
1334
             * engine after we loaded a guest state.
1363
1335
             */
1364
1336
            rc = PDMDrvHlpSSMRegisterLoadDone(pDrvIns, drvNATLoadDone);
1365
 
            AssertRCReturn(rc, rc);
1366
 
 
1367
 
            rc = RTReqCreateQueue(&pThis->pSlirpReqQueue);
1368
 
            if (RT_FAILURE(rc))
1369
 
            {
1370
 
                LogRel(("NAT: Can't create request queue\n"));
1371
 
                return rc;
1372
 
            }
1373
 
 
1374
 
            rc = RTReqCreateQueue(&pThis->pRecvReqQueue);
1375
 
            if (RT_FAILURE(rc))
1376
 
            {
1377
 
                LogRel(("NAT: Can't create request queue\n"));
1378
 
                return rc;
1379
 
            }
1380
 
 
1381
 
            rc = RTReqCreateQueue(&pThis->pUrgRecvReqQueue);
1382
 
            if (RT_FAILURE(rc))
1383
 
            {
1384
 
                LogRel(("NAT: Can't create request queue\n"));
1385
 
                return rc;
1386
 
            }
 
1337
            AssertLogRelRCReturn(rc, rc);
 
1338
 
 
1339
            rc = RTReqQueueCreate(&pThis->hSlirpReqQueue);
 
1340
            AssertLogRelRCReturn(rc, rc);
 
1341
 
 
1342
            rc = RTReqQueueCreate(&pThis->hRecvReqQueue);
 
1343
            AssertLogRelRCReturn(rc, rc);
 
1344
 
 
1345
            rc = RTReqQueueCreate(&pThis->hUrgRecvReqQueue);
 
1346
            AssertLogRelRCReturn(rc, rc);
1387
1347
 
1388
1348
            rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvNATRecv,
1389
1349
                                       drvNATRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATRX");
1428
1388
                                       drvNATAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "NAT");
1429
1389
            AssertRCReturn(rc, rc);
1430
1390
 
1431
 
#ifdef VBOX_WITH_SLIRP_MT
1432
 
            rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pGuestThread, pThis, drvNATAsyncIoGuest,
1433
 
                                       drvNATAsyncIoGuestWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATGUEST");
1434
 
            AssertRCReturn(rc, rc);
1435
 
#endif
1436
 
 
1437
1391
            pThis->enmLinkState = pThis->enmLinkStateWant = PDMNETWORKLINKSTATE_UP;
1438
1392
 
1439
1393
            /* might return VINF_NAT_DNS */
1474
1428
    /* fClass. */
1475
1429
    PDM_DRVREG_CLASS_NETWORK,
1476
1430
    /* cMaxInstances */
1477
 
    16,
 
1431
    ~0U,
1478
1432
    /* cbInstance */
1479
1433
    sizeof(DRVNAT),
1480
1434
    /* pfnConstruct */