~ubuntu-branches/ubuntu/vivid/virtualbox-ose/vivid

« back to all changes in this revision

Viewing changes to src/VBox/HostDrivers/VBoxNetAdp/darwin/VBoxNetAdp-darwin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-10-13 23:06:00 UTC
  • mfrom: (0.3.2 upstream) (0.1.12 sid)
  • Revision ID: james.westby@ubuntu.com-20091013230600-xhu2pwizq0wo63l9
Tags: 3.0.8-dfsg-1ubuntu1
* Merge from debian unstable (LP: #444812), remaining changes:
  - Enable DKMS support on virtualbox host and guest modules (LP: #267097)
    - Drop virtualbox-ose{-guest,}-modules-* package templates
    - Recommend *-source instead of *-modules packages
    - Replace error messages related to missing/mismatched
      kernel module accordingly
  - Autoload kernel module
    - LOAD_VBOXDRV_MODULE=1 in virtualbox-ose.default
  - Disable update action
    - patches/u01-disable-update-action.dpatch
  - Virtualbox should go in Accessories, not in System tools (LP: #288590)
    - virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add apport hook
    - virtualbox-ose.files/source_virtualbox-ose.py
    - virtualbox-ose.install
  - Add launchpad integration
    - control
    - lpi-bug.xpm
    - patches/u02-lp-integration.dpatch
* Try to remove existing dkms modules before adding the new modules
  (LP: #434503)
  - debian/virtualbox-ose-source.postinst
  - debian/virtualbox-ose-guest-source.postinst
* Don't fail if dkms modules have already been removed
  - debian/virtualbox-ose-source.prerm
  - debian/virtualbox-ose-guest-source.prerm

Show diffs side-by-side

added added

removed removed

Lines of Context:
123
123
/**
124
124
 * The (common) global data.
125
125
 */
126
 
#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
127
 
static VBOXNETADPGLOBALS g_VBoxNetAdpGlobals;
128
 
 
129
 
#else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
130
 
 
131
126
static int   g_nCtlDev = -1; /* Major dev number */
132
127
static void *g_hCtlDev = 0;  /* FS dev handle */
133
128
 
152
147
    /*.d_type     = */0
153
148
};
154
149
 
155
 
/**
156
 
 * Generate a suitable MAC address.
157
 
 *
158
 
 * @param   pThis       The instance.
159
 
 * @param   pMac        Where to return the MAC address.
160
 
 */
161
 
DECLHIDDEN(void) vboxNetAdpComposeMACAddress(PVBOXNETADP pThis, PRTMAC pMac)
162
 
{
163
 
#if 0 /* Use a locally administered version of the OUI we use for the guest NICs. */
164
 
    pMac->au8[0] = 0x08 | 2;
165
 
    pMac->au8[1] = 0x00;
166
 
    pMac->au8[2] = 0x27;
167
 
#else /* this is what \0vb comes down to. It seems to be unassigned atm. */
168
 
    pMac->au8[0] = 0;
169
 
    pMac->au8[1] = 0x76;
170
 
    pMac->au8[2] = 0x62;
171
 
#endif
172
 
 
173
 
    pMac->au8[3] = 0; /* pThis->uUnit >> 16; */
174
 
    pMac->au8[4] = 0; /* pThis->uUnit >> 8; */
175
 
    pMac->au8[5] = pThis->uUnit;
176
 
}
177
 
 
178
 
#endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */
179
 
 
180
 
 
181
150
 
182
151
 
183
152
static void vboxNetAdpDarwinComposeUUID(PVBOXNETADP pThis, PRTUUID pUuid)
191
160
    vboxNetAdpComposeMACAddress(pThis, (PRTMAC)pUuid->Gen.au8Node);
192
161
}
193
162
 
194
 
#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
195
 
/**
196
 
 * Reads and retains the host interface handle.
197
 
 *
198
 
 * @returns The handle, NULL if detached.
199
 
 * @param   pThis
200
 
 */
201
 
DECLINLINE(ifnet_t) vboxNetAdpDarwinRetainIfNet(PVBOXNETADP pThis)
202
 
{
203
 
    if (pThis->u.s.pIface)
204
 
        ifnet_reference(pThis->u.s.pIface);
205
 
 
206
 
    return pThis->u.s.pIface;
207
 
}
208
 
 
209
 
 
210
 
/**
211
 
 * Release the host interface handle previously retained
212
 
 * by vboxNetAdpDarwinRetainIfNet.
213
 
 *
214
 
 * @param   pThis           The instance.
215
 
 * @param   pIfNet          The vboxNetAdpDarwinRetainIfNet return value, NULL is fine.
216
 
 */
217
 
DECLINLINE(void) vboxNetAdpDarwinReleaseIfNet(PVBOXNETADP pThis, ifnet_t pIfNet)
218
 
{
219
 
    NOREF(pThis);
220
 
    if (pIfNet)
221
 
        ifnet_release(pIfNet);
222
 
}
223
 
 
224
 
/**
225
 
 * Internal worker that create a darwin mbuf for a (scatter/)gather list.
226
 
 *
227
 
 * Taken from VBoxNetAdp-darwin.cpp.
228
 
 *
229
 
 * @returns Pointer to the mbuf.
230
 
 * @param   pThis           The instance.
231
 
 * @param   pSG             The (scatter/)gather list.
232
 
 */
233
 
static mbuf_t vboxNetAdpDarwinMBufFromSG(PVBOXNETADP pThis, PINTNETSG pSG)
234
 
{
235
 
    /// @todo future? mbuf_how_t How = preemtion enabled ? MBUF_DONTWAIT : MBUF_WAITOK;
236
 
    mbuf_how_t How = MBUF_WAITOK;
237
 
 
238
 
    /*
239
 
     * We can't make use of the physical addresses on darwin because the way the
240
 
     * mbuf / cluster stuffe works (see mbuf_data_to_physical and mcl_to_paddr).
241
 
     * So, because we're lazy, we will ASSUME that all SGs coming from INTNET
242
 
     * will only contain one single segment.
243
 
     */
244
 
    Assert(pSG->cSegsUsed == 1);
245
 
    Assert(pSG->cbTotal == pSG->aSegs[0].cb);
246
 
    Assert(pSG->cbTotal > 0);
247
 
 
248
 
    /*
249
 
     * We need some way of getting back to our instance data when
250
 
     * the mbuf is freed, so use pvUserData for this.
251
 
     *  -- this is not relevant anylonger! --
252
 
     */
253
 
    Assert(!pSG->pvUserData || pSG->pvUserData == pThis);
254
 
    Assert(!pSG->pvUserData2);
255
 
    pSG->pvUserData = pThis;
256
 
 
257
 
    /*
258
 
     * Allocate a packet and copy over the data.
259
 
     *
260
 
     * Using mbuf_attachcluster() here would've been nice but there are two
261
 
     * issues with it: (1) it's 10.5.x only, and (2) the documentation indicates
262
 
     * that it's not supposed to be used for really external buffers. The 2nd
263
 
     * point might be argued against considering that the only m_clattach user
264
 
     * is mallocs memory for the ext mbuf and not doing what's stated in the docs.
265
 
     * However, it's hard to tell if these m_clattach buffers actually makes it
266
 
     * to the NICs or not, and even if they did, the NIC would need the physical
267
 
     * addresses for the pages they contain and might end up copying the data
268
 
     * to a new mbuf anyway.
269
 
     *
270
 
     * So, in the end it's better to just do it the simple way that will work
271
 
     * 100%, even if it involes some extra work (alloc + copy) we really wished
272
 
     * to avoid.
273
 
     */
274
 
    mbuf_t pPkt = NULL;
275
 
    errno_t err = mbuf_allocpacket(How, pSG->cbTotal, NULL, &pPkt);
276
 
    if (!err)
277
 
    {
278
 
        /* Skip zero sized memory buffers (paranoia). */
279
 
        mbuf_t pCur = pPkt;
280
 
        while (pCur && !mbuf_maxlen(pCur))
281
 
            pCur = mbuf_next(pCur);
282
 
        Assert(pCur);
283
 
 
284
 
        /* Set the required packet header attributes. */
285
 
        mbuf_pkthdr_setlen(pPkt, pSG->cbTotal);
286
 
        mbuf_pkthdr_setheader(pPkt, mbuf_data(pCur));
287
 
 
288
 
        /* Special case the single buffer copy. */
289
 
        if (    mbuf_next(pCur)
290
 
            &&  mbuf_maxlen(pCur) >= pSG->cbTotal)
291
 
        {
292
 
            mbuf_setlen(pCur, pSG->cbTotal);
293
 
            memcpy(mbuf_data(pCur), pSG->aSegs[0].pv, pSG->cbTotal);
294
 
        }
295
 
        else
296
 
        {
297
 
            /* Multi buffer copying. */
298
 
            size_t         cbSrc = pSG->cbTotal;
299
 
            uint8_t const *pbSrc = (uint8_t const *)pSG->aSegs[0].pv;
300
 
            while (cbSrc > 0 && pCur)
301
 
            {
302
 
                size_t cb = mbuf_maxlen(pCur);
303
 
                if (cbSrc < cb)
304
 
                    cb = cbSrc;
305
 
                mbuf_setlen(pCur, cb);
306
 
                memcpy(mbuf_data(pCur), pbSrc, cb);
307
 
 
308
 
                /* advance */
309
 
                pbSrc += cb;
310
 
                cbSrc -= cb;
311
 
                pCur = mbuf_next(pCur);
312
 
            }
313
 
        }
314
 
        if (!err)
315
 
            return pPkt;
316
 
 
317
 
        mbuf_freem(pPkt);
318
 
    }
319
 
    else
320
 
        AssertMsg(err == ENOMEM || err == EWOULDBLOCK, ("err=%d\n", err));
321
 
    pSG->pvUserData = NULL;
322
 
 
323
 
    return NULL;
324
 
}
325
 
 
326
 
 
327
 
/**
328
 
 * Calculates the number of segments required to represent the mbuf.
329
 
 *
330
 
 * Taken from VBoxNetAdp-darwin.cpp.
331
 
 *
332
 
 * @returns Number of segments.
333
 
 * @param   pThis               The instance.
334
 
 * @param   pMBuf               The mbuf.
335
 
 * @param   pvFrame             The frame pointer, optional.
336
 
 */
337
 
DECLINLINE(unsigned) vboxNetAdpDarwinMBufCalcSGSegs(PVBOXNETADP pThis, mbuf_t pMBuf, void *pvFrame)
338
 
{
339
 
    NOREF(pThis);
340
 
 
341
 
    /*
342
 
     * Count the buffers in the chain.
343
 
     */
344
 
    unsigned cSegs = 0;
345
 
    for (mbuf_t pCur = pMBuf; pCur; pCur = mbuf_next(pCur))
346
 
        if (mbuf_len(pCur))
347
 
            cSegs++;
348
 
        else if (   !cSegs
349
 
                 && pvFrame
350
 
                 && (uintptr_t)pvFrame - (uintptr_t)mbuf_datastart(pMBuf) < mbuf_maxlen(pMBuf))
351
 
            cSegs++;
352
 
 
353
 
#ifdef PADD_RUNT_FRAMES_FROM_HOST
354
 
    /*
355
 
     * Add one buffer if the total is less than the ethernet minimum 60 bytes.
356
 
     * This may allocate a segment too much if the ethernet header is separated,
357
 
     * but that shouldn't harm us much.
358
 
     */
359
 
    if (mbuf_pkthdr_len(pMBuf) < 60)
360
 
        cSegs++;
361
 
#endif
362
 
 
363
 
#ifdef VBOXNETFLT_DARWIN_TEST_SEG_SIZE
364
 
    /* maximize the number of segments. */
365
 
    cSegs = RT_MAX(VBOXNETFLT_DARWIN_MAX_SEGS - 1, cSegs);
366
 
#endif
367
 
 
368
 
    return cSegs ? cSegs : 1;
369
 
}
370
 
 
371
 
 
372
 
/**
373
 
 * Initializes a SG list from an mbuf.
374
 
 *
375
 
 * Taken from VBoxNetAdp-darwin.cpp.
376
 
 *
377
 
 * @returns Number of segments.
378
 
 * @param   pThis               The instance.
379
 
 * @param   pMBuf               The mbuf.
380
 
 * @param   pSG                 The SG.
381
 
 * @param   pvFrame             The frame pointer, optional.
382
 
 * @param   cSegs               The number of segments allocated for the SG.
383
 
 *                              This should match the number in the mbuf exactly!
384
 
 * @param   fSrc                The source of the frame.
385
 
 */
386
 
DECLINLINE(void) vboxNetAdpDarwinMBufToSG(PVBOXNETADP pThis, mbuf_t pMBuf, void *pvFrame, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc)
387
 
{
388
 
    NOREF(pThis);
389
 
 
390
 
    pSG->pvOwnerData = NULL;
391
 
    pSG->pvUserData = NULL;
392
 
    pSG->pvUserData2 = NULL;
393
 
    pSG->cUsers = 1;
394
 
    pSG->fFlags = INTNETSG_FLAGS_TEMP;
395
 
    pSG->cSegsAlloc = cSegs;
396
 
 
397
 
    /*
398
 
     * Walk the chain and convert the buffers to segments.
399
 
     */
400
 
    unsigned iSeg = 0;
401
 
    pSG->cbTotal = 0;
402
 
    for (mbuf_t pCur = pMBuf; pCur; pCur = mbuf_next(pCur))
403
 
    {
404
 
        size_t cbSeg = mbuf_len(pCur);
405
 
        if (cbSeg)
406
 
        {
407
 
            void *pvSeg = mbuf_data(pCur);
408
 
 
409
 
            /* deal with pvFrame */
410
 
            if (!iSeg && pvFrame && pvFrame != pvSeg)
411
 
            {
412
 
                void     *pvStart   = mbuf_datastart(pMBuf);
413
 
                uintptr_t offSeg    = (uintptr_t)pvSeg - (uintptr_t)pvStart;
414
 
                uintptr_t offSegEnd = offSeg + cbSeg;
415
 
                Assert(pvStart && pvSeg && offSeg < mbuf_maxlen(pMBuf) && offSegEnd <= mbuf_maxlen(pMBuf)); NOREF(offSegEnd);
416
 
                uintptr_t offFrame  = (uintptr_t)pvFrame - (uintptr_t)pvStart;
417
 
                if (RT_LIKELY(offFrame < offSeg))
418
 
                {
419
 
                    pvSeg = pvFrame;
420
 
                    cbSeg += offSeg - offFrame;
421
 
                }
422
 
                else
423
 
                    AssertMsgFailed(("pvFrame=%p pvStart=%p pvSeg=%p offSeg=%p cbSeg=%#zx offSegEnd=%p offFrame=%p maxlen=%#zx\n",
424
 
                                     pvFrame, pvStart, pvSeg, offSeg, cbSeg, offSegEnd, offFrame, mbuf_maxlen(pMBuf)));
425
 
                pvFrame = NULL;
426
 
            }
427
 
 
428
 
            AssertBreak(iSeg < cSegs);
429
 
            pSG->cbTotal += cbSeg;
430
 
            pSG->aSegs[iSeg].cb = cbSeg;
431
 
            pSG->aSegs[iSeg].pv = pvSeg;
432
 
            pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
433
 
            iSeg++;
434
 
        }
435
 
        /* The pvFrame might be in a now empty buffer. */
436
 
        else if (   !iSeg
437
 
                 && pvFrame
438
 
                 && (uintptr_t)pvFrame - (uintptr_t)mbuf_datastart(pMBuf) < mbuf_maxlen(pMBuf))
439
 
        {
440
 
            cbSeg = (uintptr_t)mbuf_datastart(pMBuf) + mbuf_maxlen(pMBuf) - (uintptr_t)pvFrame;
441
 
            pSG->cbTotal += cbSeg;
442
 
            pSG->aSegs[iSeg].cb = cbSeg;
443
 
            pSG->aSegs[iSeg].pv = pvFrame;
444
 
            pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
445
 
            iSeg++;
446
 
            pvFrame = NULL;
447
 
        }
448
 
    }
449
 
 
450
 
    Assert(iSeg && iSeg <= cSegs);
451
 
    pSG->cSegsUsed = iSeg;
452
 
 
453
 
#ifdef PADD_RUNT_FRAMES_FROM_HOST
454
 
    /*
455
 
     * Add a trailer if the frame is too small.
456
 
     *
457
 
     * Since we're getting to the packet before it is framed, it has not
458
 
     * yet been padded. The current solution is to add a segment pointing
459
 
     * to a buffer containing all zeros and pray that works for all frames...
460
 
     */
461
 
    if (pSG->cbTotal < 60 && (fSrc & INTNETTRUNKDIR_HOST))
462
 
    {
463
 
        AssertReturnVoid(iSeg < cSegs);
464
 
 
465
 
        static uint8_t const s_abZero[128] = {0};
466
 
        pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
467
 
        pSG->aSegs[iSeg].pv = (void *)&s_abZero[0];
468
 
        pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal;
469
 
        pSG->cbTotal = 60;
470
 
        pSG->cSegsUsed++;
471
 
    }
472
 
#endif
473
 
 
474
 
#ifdef VBOXNETFLT_DARWIN_TEST_SEG_SIZE
475
 
    /*
476
 
     * Redistribute the segments.
477
 
     */
478
 
    if (pSG->cSegsUsed < pSG->cSegsAlloc)
479
 
    {
480
 
        /* copy the segments to the end. */
481
 
        int iSrc = pSG->cSegsUsed;
482
 
        int iDst = pSG->cSegsAlloc;
483
 
        while (iSrc > 0)
484
 
        {
485
 
            iDst--;
486
 
            iSrc--;
487
 
            pSG->aSegs[iDst] = pSG->aSegs[iSrc];
488
 
        }
489
 
 
490
 
        /* create small segments from the start. */
491
 
        pSG->cSegsUsed = pSG->cSegsAlloc;
492
 
        iSrc = iDst;
493
 
        iDst = 0;
494
 
        while (     iDst < iSrc
495
 
               &&   iDst < pSG->cSegsAlloc)
496
 
        {
497
 
            pSG->aSegs[iDst].Phys = NIL_RTHCPHYS;
498
 
            pSG->aSegs[iDst].pv = pSG->aSegs[iSrc].pv;
499
 
            pSG->aSegs[iDst].cb = RT_MIN(pSG->aSegs[iSrc].cb, VBOXNETFLT_DARWIN_TEST_SEG_SIZE);
500
 
            if (pSG->aSegs[iDst].cb != pSG->aSegs[iSrc].cb)
501
 
            {
502
 
                pSG->aSegs[iSrc].cb -= pSG->aSegs[iDst].cb;
503
 
                pSG->aSegs[iSrc].pv = (uint8_t *)pSG->aSegs[iSrc].pv + pSG->aSegs[iDst].cb;
504
 
            }
505
 
            else if (++iSrc >= pSG->cSegsAlloc)
506
 
            {
507
 
                pSG->cSegsUsed = iDst + 1;
508
 
                break;
509
 
            }
510
 
            iDst++;
511
 
        }
512
 
    }
513
 
#endif
514
 
 
515
 
    AssertMsg(!pvFrame, ("pvFrame=%p pMBuf=%p iSeg=%d\n", pvFrame, pMBuf, iSeg));
516
 
}
517
 
 
518
 
#endif /* VBOXANETADP_DO_NOT_USE_NETFLT */
519
163
static errno_t vboxNetAdpDarwinOutput(ifnet_t pIface, mbuf_t pMBuf)
520
164
{
521
 
#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
522
 
    PVBOXNETADP pThis = VBOXNETADP_FROM_IFACE(pIface);
523
 
    Assert(pThis);
524
 
    if (vboxNetAdpPrepareToReceive(pThis))
525
 
    {
526
 
        unsigned cSegs = vboxNetAdpDarwinMBufCalcSGSegs(pThis, pMBuf, NULL);
527
 
        if (cSegs < VBOXNETADP_DARWIN_MAX_SEGS)
528
 
        {
529
 
            PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
530
 
            vboxNetAdpDarwinMBufToSG(pThis, pMBuf, NULL, pSG, cSegs, INTNETTRUNKDIR_HOST);
531
 
            vboxNetAdpReceive(pThis, pSG);
532
 
        }
533
 
        else
534
 
            vboxNetAdpCancelReceive(pThis);
535
 
    }
536
 
#endif /* VBOXANETADP_DO_NOT_USE_NETFLT */
537
165
    mbuf_freem_list(pMBuf);
538
166
    return 0;
539
167
}
585
213
}
586
214
 
587
215
 
588
 
#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
589
 
 
590
 
int  vboxNetAdpPortOsXmit(PVBOXNETADP pThis, PINTNETSG pSG, uint32_t fDst)
591
 
{
592
 
    int rc = VINF_SUCCESS;
593
 
    ifnet_t pIfNet = vboxNetAdpDarwinRetainIfNet(pThis); // Really need a wrapper?
594
 
    if (pIfNet)
595
 
    {
596
 
        /*
597
 
         * Create a mbuf for the gather list and push it onto the host stack.
598
 
         */
599
 
        mbuf_t pMBuf = vboxNetAdpDarwinMBufFromSG(pThis, pSG);
600
 
        if (pMBuf)
601
 
        {
602
 
            /* This is what IONetworkInterface::inputPacket does. */
603
 
            unsigned const cbEthHdr = 14;
604
 
            mbuf_pkthdr_setheader(pMBuf, mbuf_data(pMBuf));
605
 
            mbuf_pkthdr_setlen(pMBuf, mbuf_pkthdr_len(pMBuf) - cbEthHdr);
606
 
            mbuf_setdata(pMBuf, (uint8_t *)mbuf_data(pMBuf) + cbEthHdr, mbuf_len(pMBuf) - cbEthHdr);
607
 
            mbuf_pkthdr_setrcvif(pMBuf, pIfNet); /* will crash without this. */
608
 
 
609
 
            Log(("vboxNetAdpPortOsXmit: calling ifnet_input()\n"));
610
 
            errno_t err = ifnet_input(pIfNet, pMBuf, NULL);
611
 
            if (err)
612
 
                rc = RTErrConvertFromErrno(err);
613
 
        }
614
 
        else
615
 
        {
616
 
            Log(("vboxNetAdpPortOsXmit: failed to convert SG to mbuf.\n"));
617
 
            rc = VERR_NO_MEMORY;
618
 
        }
619
 
 
620
 
        vboxNetAdpDarwinReleaseIfNet(pThis, pIfNet);
621
 
    }
622
 
    else
623
 
        Log(("vboxNetAdpPortOsXmit: failed to retain the interface.\n"));
624
 
 
625
 
    return rc;
626
 
}
627
 
 
628
 
bool vboxNetAdpPortOsIsPromiscuous(PVBOXNETADP pThis)
629
 
{
630
 
    uint16_t fIf = 0;
631
 
    ifnet_t pIfNet = vboxNetAdpDarwinRetainIfNet(pThis);
632
 
    if (pIfNet)
633
 
    {
634
 
        /* gather the data */
635
 
        fIf = ifnet_flags(pIfNet);
636
 
        vboxNetAdpDarwinReleaseIfNet(pThis, pIfNet);
637
 
    }
638
 
    return fIf & IFF_PROMISC;
639
 
}
640
 
 
641
 
 
642
 
void vboxNetAdpPortOsGetMacAddress(PVBOXNETADP pThis, PRTMAC pMac)
643
 
{
644
 
    *pMac = pThis->u.s.Mac;
645
 
}
646
 
 
647
 
 
648
 
bool vboxNetAdpPortOsIsHostMac(PVBOXNETADP pThis, PCRTMAC pMac)
649
 
{
650
 
    /* ASSUMES that the MAC address never changes. */
651
 
    return pThis->u.s.Mac.au16[0] == pMac->au16[0]
652
 
        && pThis->u.s.Mac.au16[1] == pMac->au16[1]
653
 
        && pThis->u.s.Mac.au16[2] == pMac->au16[2];
654
 
}
655
 
 
656
 
int vboxNetAdpOsDisconnectIt(PVBOXNETADP pThis)
657
 
{
658
 
    /* Nothing to do here. */
659
 
    return VINF_SUCCESS;
660
 
}
661
 
 
662
 
 
663
 
int  vboxNetAdpOsConnectIt(PVBOXNETADP pThis)
664
 
{
665
 
    /* Nothing to do here. */
666
 
    return VINF_SUCCESS;
667
 
}
668
 
#else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
669
 
//VBOXNETADP g_vboxnet0;
670
 
VBOXNETADP g_aAdapters[VBOXNETADP_MAX_INSTANCES];
671
 
 
672
 
#endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */
673
 
 
674
 
 
675
 
 
676
216
int vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMACAddress)
677
217
{
678
218
    int rc;
782
322
    pThis->u.s.hEvtDetached = NIL_RTSEMEVENT;
783
323
}
784
324
 
785
 
int vboxNetAdpCreate (PVBOXNETADP *ppNew)
786
 
{
787
 
    int rc;
788
 
    unsigned i;
789
 
    for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
790
 
    {
791
 
        PVBOXNETADP pThis = &g_aAdapters[i];
792
 
 
793
 
        if (ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Transitional, kVBoxNetAdpState_Invalid))
794
 
        {
795
 
            /* Found an empty slot -- use it. */
796
 
            Log(("vboxNetAdpCreate: found empty slot: %d\n", i));
797
 
            RTMAC Mac;
798
 
            vboxNetAdpComposeMACAddress(pThis, &Mac);
799
 
            rc = vboxNetAdpOsCreate(pThis, &Mac);
800
 
            if (RT_SUCCESS(rc))
801
 
            {
802
 
                *ppNew = pThis;
803
 
                ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Active);
804
 
            }
805
 
            else
806
 
            {
807
 
                ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Invalid);
808
 
                Log(("vboxNetAdpCreate: vboxNetAdpOsCreate failed with '%Rrc'.\n", rc));
809
 
            }
810
 
            return rc;
811
 
        }
812
 
    }
813
 
    Log(("vboxNetAdpCreate: no empty slots!\n"));
814
 
 
815
 
    /* All slots in adapter array are busy. */
816
 
    return VERR_OUT_OF_RESOURCES;
817
 
}
818
 
 
819
 
int vboxNetAdpDestroy (PVBOXNETADP pThis)
820
 
{
821
 
    int rc = VINF_SUCCESS;
822
 
 
823
 
    if (!ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Transitional, kVBoxNetAdpState_Active))
824
 
        return VERR_INTNET_FLT_IF_BUSY;
825
 
 
826
 
    vboxNetAdpOsDestroy(pThis);
827
 
 
828
 
    ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Invalid);
829
 
 
830
 
    return rc;
831
 
}
832
 
 
833
325
/**
834
326
 * Device open. Called on open /dev/vboxnetctl
835
327
 *
866
358
 */
867
359
static int VBoxNetAdpDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess)
868
360
{
869
 
    int rc = VINF_SUCCESS;
870
361
    uint32_t cbReq = IOCPARM_LEN(iCmd);
871
362
    PVBOXNETADPREQ pReq = (PVBOXNETADPREQ)pData;
 
363
    int rc;
872
364
 
873
365
    Log(("VBoxNetAdpDarwinIOCtl: param len %#x; iCmd=%#lx\n", cbReq, iCmd));
874
366
    switch (IOCBASECMD(iCmd))
875
367
    {
876
368
        case IOCBASECMD(VBOXNETADP_CTL_ADD):
877
 
            if ((IOC_DIRMASK & iCmd) == IOC_OUT)
878
 
            {
879
 
                PVBOXNETADP pNew;
880
 
                rc = vboxNetAdpCreate(&pNew);
881
 
                if (RT_SUCCESS(rc))
882
 
                {
883
 
                    if (cbReq < sizeof(VBOXNETADPREQ))
884
 
                    {
885
 
                        OSDBGPRINT(("VBoxNetAdpDarwinIOCtl: param len %#x < req size %#x; iCmd=%#lx\n", cbReq, sizeof(VBOXNETADPREQ), iCmd));
886
 
                        return EINVAL;
887
 
                    }
888
 
                    strncpy(pReq->szName, pNew->szName, sizeof(pReq->szName));
889
 
                }
890
 
            }
 
369
        {
 
370
            if (   (IOC_DIRMASK & iCmd) != IOC_OUT
 
371
                || cbReq < sizeof(VBOXNETADPREQ))
 
372
                return EINVAL;
 
373
 
 
374
            PVBOXNETADP pNew;
 
375
            rc = vboxNetAdpCreate(&pNew);
 
376
            if (RT_FAILURE(rc))
 
377
                return EINVAL;
 
378
 
 
379
            Assert(strlen(pReq->szName) < sizeof(pReq->szName));
 
380
            strncpy(pReq->szName, pNew->szName, sizeof(pReq->szName) - 1);
 
381
            pReq->szName[sizeof(pReq->szName) - 1] = '\0';
 
382
            Log(("VBoxNetAdpDarwinIOCtl: Added '%s'\n", pReq->szName));
891
383
            break;
 
384
        }
892
385
 
893
386
        case IOCBASECMD(VBOXNETADP_CTL_REMOVE):
894
 
            for (unsigned i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
895
 
            {
896
 
                PVBOXNETADP pThis = &g_aAdapters[i];
897
 
                rc = VERR_NOT_FOUND;
898
 
                if (strncmp(pThis->szName, pReq->szName, VBOXNETADP_MAX_NAME_LEN) == 0)
899
 
                    if (ASMAtomicReadU32((uint32_t volatile *)&pThis->enmState) == kVBoxNetAdpState_Active)
900
 
                    {
901
 
                        rc = vboxNetAdpDestroy(pThis);
902
 
                        break;
903
 
                    }
904
 
            }
 
387
        {
 
388
            if (!memchr(pReq->szName, '\0', RT_MIN(cbReq, sizeof(pReq->szName))))
 
389
                return EINVAL;
 
390
 
 
391
            PVBOXNETADP pAdp = vboxNetAdpFindByName(pReq->szName);
 
392
            if (!pAdp)
 
393
                return EINVAL;
 
394
 
 
395
            rc = vboxNetAdpDestroy(pAdp);
 
396
            if (RT_FAILURE(rc))
 
397
                return EINVAL;
 
398
            Log(("VBoxNetAdpDarwinIOCtl: Removed %s\n", pReq->szName));
905
399
            break;
 
400
        }
 
401
 
906
402
        default:
907
403
            OSDBGPRINT(("VBoxNetAdpDarwinIOCtl: unknown command %x.\n", IOCBASECMD(iCmd)));
908
 
            rc = VERR_INVALID_PARAMETER;
909
 
            break;
 
404
            return EINVAL;
910
405
    }
911
406
 
912
 
    return RT_SUCCESS(rc) ? 0 : EINVAL;
 
407
    return 0;
913
408
}
914
409
 
915
410
int  vboxNetAdpOsInit(PVBOXNETADP pThis)
917
412
    /*
918
413
     * Init the darwin specific members.
919
414
     */
920
 
    pThis->enmState = kVBoxNetAdpState_Invalid;
921
415
    pThis->u.s.pIface = NULL;
922
416
    pThis->u.s.hEvtDetached = NIL_RTSEMEVENT;
923
417
    memset(pThis->u.s.aAttachedFamilies, 0, sizeof(pThis->u.s.aAttachedFamilies));
940
434
    if (RT_SUCCESS(rc))
941
435
    {
942
436
        Log(("VBoxNetAdpDarwinStart\n"));
943
 
        /*
944
 
         * Initialize the globals and connect to the support driver.
945
 
         *
946
 
         * This will call back vboxNetAdpOsOpenSupDrv (and maybe vboxNetAdpOsCloseSupDrv)
947
 
         * for establishing the connect to the support driver.
948
 
         */
949
 
#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
950
 
        memset(&g_VBoxNetAdpGlobals, 0, sizeof(g_VBoxNetAdpGlobals));
951
 
        rc = vboxNetAdpInitGlobals(&g_VBoxNetAdpGlobals);
952
 
#else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
953
 
        for (unsigned i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
954
 
        {
955
 
            g_aAdapters[i].uUnit = i;
956
 
            vboxNetAdpOsInit(&g_aAdapters[i]);
957
 
        }
958
 
 
959
 
        PVBOXNETADP pVboxnet0;
960
 
        rc = vboxNetAdpCreate(&pVboxnet0);
 
437
        rc = vboxNetAdpInit();
961
438
        if (RT_SUCCESS(rc))
962
439
        {
963
440
            g_nCtlDev = cdevsw_add(-1, &g_ChDev);
978
455
            }
979
456
        }
980
457
 
981
 
#endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */
982
458
        if (RT_SUCCESS(rc))
983
459
        {
984
460
            LogRel(("VBoxAdpDrv: version " VBOX_VERSION_STRING " r%d\n", VBOX_SVN_REV));
991
467
    else
992
468
        printf("VBoxAdpDrv: failed to initialize IPRT (rc=%d)\n", rc);
993
469
 
994
 
#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
995
 
    memset(&g_VBoxNetAdpGlobals, 0, sizeof(g_VBoxNetAdpGlobals));
996
 
#endif /* VBOXANETADP_DO_NOT_USE_NETFLT */
997
470
    return KMOD_RETURN_FAILURE;
998
471
}
999
472
 
1005
478
{
1006
479
    Log(("VBoxNetAdpDarwinStop\n"));
1007
480
 
1008
 
    /*
1009
 
     * Refuse to unload if anyone is currently using the filter driver.
1010
 
     * This is important as I/O kit / xnu will to be able to do usage
1011
 
     * tracking for us!
1012
 
     */
1013
 
#ifdef VBOXANETADP_DO_NOT_USE_NETFLT
1014
 
    int rc = vboxNetAdpTryDeleteGlobals(&g_VBoxNetAdpGlobals);
1015
 
    if (RT_FAILURE(rc))
1016
 
    {
1017
 
        Log(("VBoxNetAdpDarwinStop - failed, busy.\n"));
1018
 
        return KMOD_RETURN_FAILURE;
1019
 
    }
1020
 
 
1021
 
    /*
1022
 
     * Undo the work done during start (in reverse order).
1023
 
     */
1024
 
    memset(&g_VBoxNetAdpGlobals, 0, sizeof(g_VBoxNetAdpGlobals));
1025
 
#else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
1026
 
    /* Remove virtual adapters */
1027
 
    for (unsigned i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
1028
 
        vboxNetAdpDestroy(&g_aAdapters[i]);
 
481
    vboxNetAdpShutdown();
1029
482
    /* Remove control device */
1030
483
    devfs_remove(g_hCtlDev);
1031
484
    cdevsw_remove(g_nCtlDev, &g_ChDev);
1032
 
#endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */
1033
485
 
1034
486
    RTR0Term();
1035
487