~ubuntu-branches/ubuntu/natty/virtualbox-ose/natty-updates

« back to all changes in this revision

Viewing changes to src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFlt-solaris.c

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2010-10-15 02:12:28 UTC
  • mfrom: (0.3.10 upstream) (0.4.19 sid)
  • Revision ID: james.westby@ubuntu.com-20101015021228-5e6vbxgtes8mg189
Tags: 3.2.10-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - VirtualBox should go in Accessories, not in System tools.
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Add ubuntu-01-fix-build-gcc45.patch to fix FTBFS due to uninitalized
  variables. Thanks to Lubomir Rintel <lkundrak@v3.sk> for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
215
215
    nochpoll,                       /* c poll */
216
216
    ddi_prop_op,                    /* property ops */
217
217
    &g_VBoxNetFltSolarisStreamTab,
218
 
    D_NEW | D_MP | D_MTQPAIR,       /* compat. flag */
 
218
    D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL, /* compat. flag */
219
219
    CB_REV                          /* revision */
220
220
};
221
221
 
254
254
{
255
255
    DEVICE_NAME,
256
256
    &g_VBoxNetFltSolarisStreamTab,
257
 
    D_NEW | D_MP | D_MTQPAIR
 
257
    D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL
258
258
};
259
259
 
260
260
/**
343
343
    PRTTIMER pIp6Timer;                   /* ipv6 stream poll timer for dynamic ipv6 stream attachment */
344
344
#endif
345
345
    size_t cLoopback;                     /* loopback queue size list */
346
 
    timeout_id_t TimeoutId;               /* timeout id of promisc. req */
 
346
    timeout_id_t volatile TimeoutId;      /* timeout id of promisc. req */
347
347
    PVBOXNETFLTPACKETID pHead;            /* loopback packet identifier head */
348
348
    PVBOXNETFLTPACKETID pTail;            /* loopback packet identifier tail */
349
349
} vboxnetflt_promisc_stream_t;
896
896
 
897
897
    if (pStream->Type == kPromiscStream)
898
898
    {
 
899
        /*
 
900
         * If there are any timeout scheduled, we need to make sure they are cancelled.
 
901
         */
 
902
        vboxnetflt_promisc_stream_t *pPromiscStream = (vboxnetflt_promisc_stream_t *)pStream;
 
903
        timeout_id_t TimeoutId = ASMAtomicReadPtr(&pPromiscStream->TimeoutId);
 
904
        if (TimeoutId)
 
905
        {
 
906
            quntimeout(WR(pPromiscStream->Stream.pReadQueue), TimeoutId);
 
907
            ASMAtomicWritePtr(&pPromiscStream->TimeoutId, NULL);
 
908
        }
 
909
 
899
910
        flushq(pQueue, FLUSHALL);
900
911
        flushq(WR(pQueue), FLUSHALL);
901
912
    }
1298
1309
 
1299
1310
 
1300
1311
/**
1301
 
 * Send fake promiscous mode requests downstream.
 
1312
 * Callback function for qwriter to send promiscuous request messages
 
1313
 * downstream.
1302
1314
 *
1303
 
 * @param   pQueue          Pointer to the read queue.
1304
 
 * @param   fPromisc        Whether to enable promiscous mode or not.
1305
 
 * @param   PromiscLevel    Promiscous level; DL_PROMISC_PHYS/SAP/MULTI.
 
1315
 * @param   pQueue          Pointer to the write queue.
 
1316
 * @param   fPromisc        Whether to send promiscuous ON or OFF requests.
1306
1317
 *
1307
1318
 * @returns VBox status code.
1308
1319
 */
1345
1356
        ((dl_promiscoff_req_t *)pPromiscSapMsg->b_rptr)->dl_level = DL_PROMISC_SAP;
1346
1357
    }
1347
1358
 
1348
 
    qreply(pQueue, pPromiscPhysMsg);
1349
 
    qreply(pQueue, pPromiscSapMsg);
 
1359
    putnext(pQueue, pPromiscPhysMsg);
 
1360
    putnext(pQueue, pPromiscSapMsg);
1350
1361
 
1351
1362
    return VINF_SUCCESS;
1352
1363
}
1353
1364
 
1354
1365
 
1355
 
/*
1356
 
 * Callback wrapper for qtimeout to safely send promiscuous off request.
1357
 
 *
1358
 
 * @param   pvData      Pointer to a vboxnetflt_promisc_params_t structure, will be freed by us.
 
1366
/**
 
1367
 * Callback wrapper for qwriter() to safely send promiscuous requests. This is
 
1368
 * called at the outer perimeter with exclusive lock held.
 
1369
 *
 
1370
 * @param pQueue            Pointer to the write queue.
 
1371
 * @param pMsg              A one byte message indicates a Promisc ON, otherwise
 
1372
 *                          a promiscuous OFF request. See
 
1373
 *                          vboxNetFltSolarisPromiscReqWrap().
 
1374
 */
 
1375
static void vboxNetFltSolarisPromiscReqWrapExcl(queue_t *pQueue, mblk_t *pMsg)
 
1376
{
 
1377
    /*
 
1378
     * Paranoia.
 
1379
     */
 
1380
    AssertReturnVoid(pQueue);
 
1381
    if (RT_UNLIKELY(!pMsg))
 
1382
        LogRel((DEVICE_NAME ":VBoxNetFltSolarisPromiscReqWrapExcl pQueue=%p missing message!\n", pQueue));
 
1383
 
 
1384
    bool fPromisc = (MBLKL(pMsg) == 1);
 
1385
    freemsg(pMsg);
 
1386
    pMsg = NULL;
 
1387
    int rc = vboxNetFltSolarisPromiscReq(pQueue, fPromisc);
 
1388
    if (RT_FAILURE(rc))
 
1389
        LogRel((DEVICE_NAME ":VBoxNetFltSolarisPromiscReqWrapExcl vboxNetFltSolarisPromiscReq failed. rc=%d\n", rc));
 
1390
}
 
1391
 
 
1392
 
 
1393
/**
 
1394
 * Callback wrapper for qtimeout() to safely send promiscuous requests. This is
 
1395
 * called at the inner perimenter with shared lock.
 
1396
 *
 
1397
 * @param pvData            Pointer to vboxnetflt_promisc_params_t. See
 
1398
 *                          vboxNetFltPortOsSetActive().
1359
1399
 */
1360
1400
static void vboxNetFltSolarisPromiscReqWrap(void *pvData)
1361
1401
{
1367
1407
        if (   pPromiscStream
1368
1408
            && pPromiscStream->Stream.pReadQueue)
1369
1409
        {
1370
 
            pPromiscStream->TimeoutId = 0;
1371
 
            vboxNetFltSolarisPromiscReq(pPromiscStream->Stream.pReadQueue, pParams->fPromiscOn);
 
1410
            /*
 
1411
             * Use size of message to indicate to qwriter callback whether it must send
 
1412
             * promiscuous On or Off messages. This is ugly but easier and more efficient than
 
1413
             * scheduling two separate qwriter callbacks with prepared messages to putnext.
 
1414
             */
 
1415
            size_t cbMsg = pParams->fPromiscOn ? 1 : 2;
 
1416
            mblk_t *pMsg = allocb(cbMsg, BPRI_HI);
 
1417
            if (RT_UNLIKELY(!pMsg))
 
1418
            {
 
1419
                LogRel((DEVICE_NAME ":Failed to alloc message of %u bytes\n", cbMsg));
 
1420
                return;
 
1421
            }
 
1422
 
 
1423
            /*
 
1424
             * Move the data pointer so we can use MBLKL, as MBLKSIZE gets the db_lim which is
 
1425
             * always aligned.
 
1426
             */
 
1427
            pMsg->b_wptr += cbMsg;
 
1428
 
 
1429
            /*
 
1430
             * Upgrade inner perimeter lock to exclusive outer perimeter lock and
 
1431
             * then call putnext while we are at the outer perimeter.
 
1432
             */
 
1433
            qwriter(WR(pPromiscStream->Stream.pReadQueue), pMsg, vboxNetFltSolarisPromiscReqWrapExcl, PERIM_OUTER);
 
1434
            ASMAtomicWritePtr(&pPromiscStream->TimeoutId, NULL);
1372
1435
        }
1373
1436
        RTMemFree(pParams);
1374
1437
    }
2021
2084
 
2022
2085
    if (pThis->u.s.hIface)
2023
2086
    {
2024
 
        /*
2025
 
         * If there are any timeout scheduled, we need to make sure they are cancelled.
2026
 
         */
2027
 
        vboxnetflt_promisc_stream_t *pPromiscStream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvPromiscStream);
2028
 
        if (   pPromiscStream
2029
 
            && pPromiscStream->TimeoutId)
2030
 
        {
2031
 
            quntimeout(WR(pPromiscStream->Stream.pReadQueue), pPromiscStream->TimeoutId);
2032
 
        }
2033
 
 
2034
2087
        ldi_close(pThis->u.s.hIface, FREAD | FWRITE, kcred);
2035
2088
        pThis->u.s.hIface = NULL;
2036
2089
    }
3622
3675
    vboxnetflt_promisc_params_t *pData = RTMemAllocZ(sizeof(vboxnetflt_promisc_params_t));
3623
3676
    if (RT_LIKELY(pData))
3624
3677
    {
 
3678
        /*
 
3679
         * See #5262 as to why we need to do all this qtimeout/qwriter tricks.
 
3680
         */
3625
3681
        vboxnetflt_promisc_stream_t *pPromiscStream = ASMAtomicUoReadPtr((void * volatile *)&pThis->u.s.pvPromiscStream);
3626
3682
        if (   pPromiscStream
3627
3683
            && pPromiscStream->Stream.pReadQueue)
3628
3684
        {
3629
3685
            pData->pThis      = pThis;
3630
3686
            pData->fPromiscOn = fActive;
3631
 
            if (pPromiscStream->TimeoutId != 0)
 
3687
            if (ASMAtomicReadPtr(&pPromiscStream->TimeoutId))
3632
3688
                quntimeout(WR(pPromiscStream->Stream.pReadQueue), pPromiscStream->TimeoutId);
3633
 
            pPromiscStream->TimeoutId = qtimeout(WR(pPromiscStream->Stream.pReadQueue), vboxNetFltSolarisPromiscReqWrap, pData, 1 /* ticks */);
3634
 
            return;
 
3689
            timeout_id_t TimeoutId = qtimeout(WR(pPromiscStream->Stream.pReadQueue), vboxNetFltSolarisPromiscReqWrap, pData, 1 /* ticks */);
 
3690
            ASMAtomicWritePtr(&pPromiscStream->TimeoutId, TimeoutId);
 
3691
            return; /* pData will be freed by vboxNetFltSolarisPromiscReqWrap() */
3635
3692
        }
 
3693
        else
 
3694
            LogRel((DEVICE_NAME ":vboxNetFltPortOsSetActive pThis=%p fActive=%d missing stream!\n", pThis, fActive));
3636
3695
        RTMemFree(pData);
3637
3696
    }
3638
3697
    else