VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFltBow-solaris.c@ 25312

Last change on this file since 25312 was 25312, checked in by vboxsync, 15 years ago

Solaris/VBoxBow: bits.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.9 KB
Line 
1/* $Id: VBoxNetFltBow-solaris.c 25312 2009-12-10 17:36:44Z vboxsync $ */
2/** @file
3 * VBoxNetFlt - Network Filter Driver (Host), Solaris Specific Code.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
26#include <VBox/log.h>
27#include <VBox/cdefs.h>
28#include <VBox/version.h>
29#include <iprt/initterm.h>
30#include <iprt/alloca.h>
31#include <iprt/assert.h>
32#include <iprt/err.h>
33#include <iprt/net.h>
34#include <iprt/spinlock.h>
35
36#include <sys/modctl.h>
37#include <sys/conf.h>
38#include <sys/stat.h>
39#include <sys/ddi.h>
40#include <sys/gld.h>
41#include <sys/sunddi.h>
42#include <sys/strsubr.h>
43#include <sys/dlpi.h>
44#include <sys/mac.h>
45#include <sys/strsun.h>
46
47#include "include/mac_provider.h"
48#include "include/mac_client.h"
49#include "include/mac_client_priv.h"
50
51#define VBOXNETFLT_OS_SPECFIC 1
52#include "../VBoxNetFltInternal.h"
53
54/*******************************************************************************
55* Defined Constants And Macros *
56*******************************************************************************/
57/** The module name. */
58#define DEVICE_NAME "vboxflt"
59/** The module descriptions as seen in 'modinfo'. */
60#define DEVICE_DESC_DRV "VirtualBox NetBow"
61/** Debugging switch for using symbols in kmdb */
62# define LOCAL static
63
64#define DEBUG_ramshankar
65#if defined(DEBUG_ramshankar)
66# undef Log
67# define Log LogRel
68# undef LogFlow
69# define LogFlow LogRel
70# undef LOCAL
71# define LOCAL
72#endif
73
74
75/*******************************************************************************
76* Kernel Entry Hooks *
77*******************************************************************************/
78LOCAL int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd);
79LOCAL int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd);
80LOCAL int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pArg, void **ppResult);
81
82
83/*******************************************************************************
84* Structures and Typedefs *
85*******************************************************************************/
86/**
87 * cb_ops: for drivers that support char/block entry points
88 */
89static struct cb_ops g_VBoxNetFltSolarisCbOps =
90{
91 nulldev, /* c open */
92 nulldev, /* c close */
93 nodev, /* b strategy */
94 nodev, /* b dump */
95 nodev, /* b print */
96 nodev, /* c read */
97 nodev, /* c write*/
98 nodev, /* c ioctl*/
99 nodev, /* c devmap */
100 nodev, /* c mmap */
101 nodev, /* c segmap */
102 nochpoll, /* c poll */
103 ddi_prop_op, /* property ops */
104 NULL, /* streamtab */
105 D_NEW | D_MP, /* compat. flag */
106 CB_REV, /* revision */
107 nodev, /* c aread */
108 nodev /* c awrite */
109};
110
111/**
112 * dev_ops: for driver device operations
113 */
114static struct dev_ops g_VBoxNetFltSolarisDevOps =
115{
116 DEVO_REV, /* driver build revision */
117 0, /* ref count */
118 VBoxNetFltSolarisGetInfo,
119 nulldev, /* identify */
120 nulldev, /* probe */
121 VBoxNetFltSolarisAttach,
122 VBoxNetFltSolarisDetach,
123 nodev, /* reset */
124 &g_VBoxNetFltSolarisCbOps,
125 NULL, /* bus ops */
126 nodev, /* power */
127 ddi_quiesce_not_needed
128};
129
130/**
131 * modldrv: export driver specifics to the kernel
132 */
133static struct modldrv g_VBoxNetFltSolarisModule =
134{
135 &mod_driverops, /* extern from kernel */
136 DEVICE_DESC_DRV " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV),
137 &g_VBoxNetFltSolarisDevOps
138};
139
140/**
141 * modlinkage: export install/remove/info to the kernel
142 */
143static struct modlinkage g_VBoxNetFltSolarisModLinkage =
144{
145 MODREV_1,
146 &g_VBoxNetFltSolarisModule,
147 NULL,
148};
149
150
151/*******************************************************************************
152* Global Variables *
153*******************************************************************************/
154/** Global Device handle we only support one instance. */
155static dev_info_t *g_pVBoxNetFltSolarisDip = NULL;
156/** Global Mutex (actually an rw lock). */
157static RTSEMFASTMUTEX g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX;
158/** The (common) global data. */
159static VBOXNETFLTGLOBALS g_VBoxNetFltSolarisGlobals;
160
161
162/*******************************************************************************
163* Internal Function *
164*******************************************************************************/
165LOCAL mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst);
166LOCAL unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg);
167LOCAL int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc);
168
169LOCAL int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis, bool fRediscovery);
170LOCAL int vboxNetFltSolarisDetachFromInterface(PVBOXNETFLTINS pThis);
171LOCAL void vboxNetFltSolarisRecv(void *pvData, mac_resource_handle_t hResource, mblk_t *pMsg, boolean_t fLoopback);
172
173
174/**
175 * Kernel entry points
176 */
177int _init(void)
178{
179 LogFlow((DEVICE_NAME ":_init\n"));
180
181 /*
182 * Prevent module autounloading.
183 */
184 modctl_t *pModCtl = mod_getctl(&g_VBoxNetFltSolarisModLinkage);
185 if (pModCtl)
186 pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
187 else
188 LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));
189
190 /*
191 * Initialize IPRT.
192 */
193 int rc = RTR0Init(0);
194 if (RT_SUCCESS(rc))
195 {
196 /*
197 * Initialize Solaris specific globals here.
198 */
199 rc = RTSemFastMutexCreate(&g_VBoxNetFltSolarisMtx);
200 if (RT_SUCCESS(rc))
201 {
202 /*
203 * Initialize the globals and connect to the support driver.
204 *
205 * This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
206 * for establishing the connect to the support driver.
207 */
208 memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals));
209 rc = vboxNetFltInitGlobalsAndIdc(&g_VBoxNetFltSolarisGlobals);
210 if (RT_SUCCESS(rc))
211 {
212 rc = mod_install(&g_VBoxNetFltSolarisModLinkage);
213 if (!rc)
214 return rc;
215
216 LogRel((DEVICE_NAME ":mod_install failed. rc=%d\n", rc));
217 vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals);
218 }
219 else
220 LogRel((DEVICE_NAME ":failed to initialize globals.\n"));
221
222 RTSemFastMutexDestroy(g_VBoxNetFltSolarisMtx);
223 g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX;
224 }
225
226 RTR0Term();
227 }
228 else
229 LogRel((DEVICE_NAME ":failed to initialize IPRT (rc=%d)\n", rc));
230
231 memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals));
232 return RTErrConvertToErrno(rc);
233}
234
235
236int _fini(void)
237{
238 int rc;
239 LogFlow((DEVICE_NAME ":_fini\n"));
240
241 /*
242 * Undo the work done during start (in reverse order).
243 */
244 rc = vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals);
245 if (RT_FAILURE(rc))
246 {
247 LogRel((DEVICE_NAME ":_fini - busy!\n"));
248 return EBUSY;
249 }
250
251 rc = mod_remove(&g_VBoxNetFltSolarisModLinkage);
252 if (!rc)
253 {
254 if (g_VBoxNetFltSolarisMtx != NIL_RTSEMFASTMUTEX)
255 {
256 RTSemFastMutexDestroy(g_VBoxNetFltSolarisMtx);
257 g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX;
258 }
259
260 RTR0Term();
261 }
262
263 return rc;
264}
265
266
267int _info(struct modinfo *pModInfo)
268{
269 LogFlow((DEVICE_NAME ":_info\n"));
270
271 int rc = mod_info(&g_VBoxNetFltSolarisModLinkage, pModInfo);
272
273 LogFlow((DEVICE_NAME ":_info returns %d\n", rc));
274 return rc;
275}
276
277
278/**
279 * Attach entry point, to attach a device to the system or resume it.
280 *
281 * @param pDip The module structure instance.
282 * @param enmCmd Operation type (attach/resume).
283 *
284 * @returns corresponding solaris error code.
285 */
286LOCAL int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
287{
288 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd));
289
290 switch (enmCmd)
291 {
292 case DDI_ATTACH:
293 {
294 int instance = ddi_get_instance(pDip);
295 int rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME, S_IFCHR, instance, DDI_PSEUDO, 0, "none", "none", 0666);
296 if (rc == DDI_SUCCESS)
297 {
298 g_pVBoxNetFltSolarisDip = pDip;
299 ddi_report_dev(pDip);
300 return DDI_SUCCESS;
301 }
302 else
303 LogRel((DEVICE_NAME ":VBoxNetFltSolarisAttach failed to create minor node. rc=%d\n", rc));
304 return DDI_FAILURE;
305 }
306
307 case DDI_RESUME:
308 {
309 /* Nothing to do here... */
310 return DDI_SUCCESS;
311 }
312
313 /* case DDI_PM_RESUME: */
314 default:
315 return DDI_FAILURE;
316 }
317}
318
319
320/**
321 * Detach entry point, to detach a device to the system or suspend it.
322 *
323 * @param pDip The module structure instance.
324 * @param enmCmd Operation type (detach/suspend).
325 *
326 * @returns corresponding solaris error code.
327 */
328LOCAL int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
329{
330 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd));
331
332 switch (enmCmd)
333 {
334 case DDI_DETACH:
335 {
336 ddi_remove_minor_node(pDip, NULL);
337 return DDI_SUCCESS;
338 }
339
340 case DDI_RESUME:
341 {
342 /* Nothing to do here... */
343 return DDI_SUCCESS;
344 }
345
346 /* case DDI_PM_SUSPEND: */
347 /* case DDI_HOT_PLUG_DETACH: */
348 default:
349 return DDI_FAILURE;
350 }
351}
352
353
354/**
355 * Info entry point, called by solaris kernel for obtaining driver info.
356 *
357 * @param pDip The module structure instance (do not use).
358 * @param enmCmd Information request type.
359 * @param pvArg Type specific argument.
360 * @param ppvResult Where to store the requested info.
361 *
362 * @returns corresponding solaris error code.
363 */
364LOCAL int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg, void **ppResult)
365{
366 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisGetInfo pDip=%p enmCmd=%d pArg=%p instance=%d\n", pDip, enmCmd, getminor((dev_t)pvArg)));
367
368 switch (enmCmd)
369 {
370 case DDI_INFO_DEVT2DEVINFO:
371 {
372 *ppResult = g_pVBoxNetFltSolarisDip;
373 return DDI_SUCCESS;
374 }
375
376 case DDI_INFO_DEVT2INSTANCE:
377 {
378 int instance = getminor((dev_t)pvArg);
379 *ppResult = (void *)(uintptr_t)instance;
380 return DDI_SUCCESS;
381 }
382 }
383
384 return DDI_FAILURE;
385}
386
387
388/**
389 * Create a solaris message block from the SG list.
390 *
391 * @param pThis The instance.
392 * @param pSG Pointer to the scatter-gather list.
393 *
394 * @returns Solaris message block.
395 */
396LOCAL mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst)
397{
398 LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG pThis=%p pSG=%p\n", pThis, pSG));
399
400 mblk_t *pMsg = allocb(pSG->cbTotal, BPRI_HI);
401 if (RT_UNLIKELY(!pMsg))
402 {
403 LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG failed to alloc %d bytes for mblk_t.\n", pSG->cbTotal));
404 return NULL;
405 }
406
407 /*
408 * Single buffer copy. Maybe later explore the
409 * need/possibility for using a mblk_t chain rather.
410 */
411 for (unsigned i = 0; i < pSG->cSegsUsed; i++)
412 {
413 if (pSG->aSegs[i].pv)
414 {
415 bcopy(pSG->aSegs[i].pv, pMsg->b_wptr, pSG->aSegs[i].cb);
416 pMsg->b_wptr += pSG->aSegs[i].cb;
417 }
418 }
419 DB_TYPE(pMsg) = M_DATA;
420 return pMsg;
421}
422
423
424/**
425 * Calculate the number of segments required for this message block.
426 *
427 * @param pThis The instance
428 * @param pMsg Pointer to the data message.
429 *
430 * @returns Number of segments.
431 */
432LOCAL unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg)
433{
434 unsigned cSegs = 0;
435 for (mblk_t *pCur = pMsg; pCur; pCur = pCur->b_cont)
436 if (MBLKL(pCur))
437 cSegs++;
438
439#ifdef PADD_RUNT_FRAMES_FROM_HOST
440 if (msgdsize(pMsg) < 60)
441 cSegs++;
442#endif
443
444 NOREF(pThis);
445 return RT_MAX(cSegs, 1);
446}
447
448
449/**
450 * Initializes an SG list from the given message block.
451 *
452 * @param pThis The instance.
453 * @param pMsg Pointer to the data message.
454 The caller must ensure it's not a control message block.
455 * @param pSG Pointer to the SG.
456 * @param cSegs Number of segments in the SG.
457 * This should match the number in the message block exactly!
458 * @param fSrc The source of the message.
459 *
460 * @returns VBox status code.
461 */
462LOCAL int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc)
463{
464 LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pThis=%p pMsg=%p pSG=%p cSegs=%d\n", pThis, pMsg, pSG, cSegs));
465
466 pSG->pvOwnerData = NULL;
467 pSG->pvUserData = NULL;
468 pSG->pvUserData2 = NULL;
469 pSG->cUsers = 1;
470 pSG->cbTotal = 0;
471 pSG->fFlags = INTNETSG_FLAGS_TEMP;
472 pSG->cSegsAlloc = cSegs;
473
474 /*
475 * Convert the message block to segments.
476 */
477 mblk_t *pCur = pMsg;
478 unsigned iSeg = 0;
479 while (pCur)
480 {
481 size_t cbSeg = MBLKL(pCur);
482 if (cbSeg)
483 {
484 void *pvSeg = pCur->b_rptr;
485 pSG->aSegs[iSeg].pv = pvSeg;
486 pSG->aSegs[iSeg].cb = cbSeg;
487 pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
488 pSG->cbTotal += cbSeg;
489 iSeg++;
490 }
491 pCur = pCur->b_cont;
492 }
493 pSG->cSegsUsed = iSeg;
494
495#ifdef PADD_RUNT_FRAMES_FROM_HOST
496 if (pSG->cbTotal < 60 && (fSrc & INTNETTRUNKDIR_HOST))
497 {
498 LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pulling up to length.\n"));
499
500 static uint8_t const s_abZero[128] = {0};
501 pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
502 pSG->aSegs[iSeg].pv = (void *)&s_abZero[0];
503 pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal;
504 pSG->cbTotal = 60;
505 pSG->cSegsUsed++;
506 }
507#endif
508
509 LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG iSeg=%d pSG->cbTotal=%d msgdsize=%d\n", iSeg, pSG->cbTotal, msgdsize(pMsg)));
510 return VINF_SUCCESS;
511}
512
513
514/**
515 * Simple packet dump, used for internal debugging.
516 *
517 * @param pMsg Pointer to the message to analyze and dump.
518 */
519static void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg)
520{
521 LogFlow((DEVICE_NAME ":vboxNetFltSolarisAnalyzeMBlk pMsg=%p\n", pMsg));
522
523 PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr;
524 uint8_t *pb = pMsg->b_rptr;
525 if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
526 {
527 PRTNETIPV4 pIpHdr = (PRTNETIPV4)(pEthHdr + 1);
528 if (!pMsg->b_cont)
529 {
530 if (pIpHdr->ip_p == RTNETIPV4_PROT_ICMP)
531 LogFlow((DEVICE_NAME ":ICMP D=%.6Rhxs S=%.6Rhxs T=%04x\n", pb, pb + 6, RT_BE2H_U16(*(uint16_t *)(pb + 12))));
532 else if (pIpHdr->ip_p == RTNETIPV4_PROT_TCP)
533 LogFlow((DEVICE_NAME ":TCP D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6));
534 else if (pIpHdr->ip_p == RTNETIPV4_PROT_UDP)
535 {
536 PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint32_t *)pIpHdr + pIpHdr->ip_hl);
537 if ( RT_BE2H_U16(pUdpHdr->uh_sport) == 67
538 && RT_BE2H_U16(pUdpHdr->uh_dport) == 68)
539 {
540 LogRel((DEVICE_NAME ":UDP bootp ack D=%.6Rhxs S=%.6Rhxs UDP_CheckSum=%04x Computex=%04x\n", pb, pb + 6,
541 RT_BE2H_U16(pUdpHdr->uh_sum), RT_BE2H_U16(RTNetIPv4UDPChecksum(pIpHdr, pUdpHdr, pUdpHdr + 1))));
542 }
543 }
544 }
545 else
546 {
547 LogFlow((DEVICE_NAME ":Chained IP packet. Skipping validity check.\n"));
548 }
549 }
550 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_VLAN))
551 {
552 typedef struct VLANHEADER
553 {
554 int Pcp:3;
555 int Cfi:1;
556 int Vid:12;
557 } VLANHEADER;
558
559 VLANHEADER *pVlanHdr = (VLANHEADER *)(pMsg->b_rptr + sizeof(RTNETETHERHDR));
560 LogFlow((DEVICE_NAME ":VLAN Pcp=%d Cfi=%d Id=%d\n", pVlanHdr->Pcp, pVlanHdr->Cfi, pVlanHdr->Vid >> 4));
561 LogFlow((DEVICE_NAME "%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr));
562 }
563 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP))
564 {
565 PRTNETARPHDR pArpHdr = (PRTNETARPHDR)(pEthHdr + 1);
566 LogFlow((DEVICE_NAME ":ARP Op=%d\n", pArpHdr->ar_oper));
567 }
568 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
569 {
570 LogFlow((DEVICE_NAME ":IPv6 D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6));
571 }
572 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_1)
573 || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_2)
574 || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_3))
575 {
576 LogFlow((DEVICE_NAME ":IPX packet.\n"));
577 }
578 else
579 {
580 LogFlow((DEVICE_NAME ":Unknown EtherType=%x D=%.6Rhxs S=%.6Rhxs\n", RT_H2BE_U16(pEthHdr->EtherType), &pEthHdr->DstMac,
581 &pEthHdr->SrcMac));
582 /* LogFlow((DEVICE_NAME ":%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr)); */
583 }
584}
585
586/**
587 * Receive (rx) entry point.
588 *
589 * @param pvData Private data.
590 * @param hResource The resource handle.
591 * @param pMsg The packet.
592 * @param fLoopback Whether this is a loopback packet or not.
593 */
594
595LOCAL void vboxNetFltSolarisRecv(void *pvData, mac_resource_handle_t hResource, mblk_t *pMsg, boolean_t fLoopback)
596{
597 LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv pvData=%p pMsg=%p fLoopback=%d\n", pvData, pMsg, fLoopback));
598
599 PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvData;
600 AssertPtrReturnVoid(pThis);
601 AssertPtrReturnVoid(pMsg);
602
603 /*
604 * Active? Retain the instance and increment the busy counter.
605 */
606 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
607 RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
608 const bool fActive = ASMAtomicUoReadBool(&pThis->fActive);
609 if (fActive)
610 vboxNetFltRetain(pThis, true /* fBusy */);
611 RTSpinlockRelease(pThis->hSpinlock, &Tmp);
612 if (!fActive)
613 return;
614
615 uint32_t fSrc = INTNETTRUNKDIR_WIRE;
616 PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
617 if (vboxNetFltPortOsIsHostMac(pThis, &pEthHdr->SrcMac))
618 fSrc = INTNETTRUNKDIR_HOST;
619
620 vboxNetFltSolarisAnalyzeMBlk(pMsg);
621
622 /*
623 * Route all received packets into the internal network.
624 */
625 unsigned cSegs = vboxNetFltSolarisMBlkCalcSGSegs(pThis, pMsg);
626 PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
627 int rc = vboxNetFltSolarisMBlkToSG(pThis, pMsg, pSG, cSegs, fSrc);
628 if (RT_SUCCESS(rc))
629 pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, fSrc);
630 else
631 LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG failed. rc=%d\n", rc));
632
633 vboxNetFltRelease(pThis, true /* fBusy */);
634 freemsgchain(pMsg);
635
636 NOREF(hResource);
637}
638
639
640/**
641 * Attach to the network interface.
642 *
643 * @param pThis The VM connection instance.
644 * @param fRediscovery Whether this is a rediscovery attempt after disconnect.
645 *
646 * @returns corresponding VBox error code.
647 */
648LOCAL int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis, bool fRediscovery)
649{
650 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
651
652 /*
653 * Open the underlying interface (lower MAC) and get it's handle.
654 */
655 int rc = mac_open_by_linkname(pThis->szName, &pThis->u.s.hInterface);
656 if (RT_LIKELY(!rc))
657 {
658 const mac_info_t *pMacInfo = mac_info(pThis->u.s.hInterface);
659 if (RT_LIKELY(pMacInfo))
660 {
661 if ( pMacInfo->mi_media == DL_ETHER
662 && pMacInfo->mi_nativemedia == DL_ETHER)
663 {
664 /*
665 * Obtain the MAC address of the interface.
666 */
667 AssertCompile(sizeof(RTMAC) == ETHERADDRL);
668 mac_unicast_primary_get(pThis->u.s.hInterface, (uint8_t *)&pThis->u.s.Mac.au8);
669
670 LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface MAC address of %s is %.*Rhxs\n", pThis->szName,
671 sizeof(pThis->u.s.Mac), &pThis->u.s.Mac));
672
673 /** @todo Obtain the MTU size using mac_sdu_get() */
674 /** @todo Obtain capabilities (hardware checksum etc.) using mac_capab_get() */
675
676 /*
677 * Open a client connection to the lower MAC interface.
678 */
679 rc = mac_client_open(pThis->u.s.hInterface, &pThis->u.s.hClient,
680 NULL /* name of this client */,
681 MAC_OPEN_FLAGS_USE_DATALINK_NAME | /* client name same as underlying NIC */
682 MAC_OPEN_FLAGS_MULTI_PRIMARY /* allow multiple primary unicasts */
683 );
684 if (RT_LIKELY(!rc))
685 {
686 /*
687 * Set a unicast address for this client and the packet receive callback.
688 * We want to use the primary unicast address of the underlying interface hence we pass NULL.
689 * Also we don't really set the RX function here, this is done when we activate promiscuous mode.
690 */
691 mac_diag_t MacDiag;
692 rc = mac_unicast_add_set_rx(pThis->u.s.hClient, NULL /* MAC Address */,
693 MAC_UNICAST_PRIMARY | MAC_UNICAST_STRIP_DISABLE |
694 MAC_UNICAST_DISABLE_TX_VID_CHECK | MAC_UNICAST_NODUPCHECK,
695 &pThis->u.s.hUnicast, 0 /* VLAN id */, &MacDiag, NULL /* pfnRecv */, pThis);
696 if (!rc)
697 {
698 LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface successfully attached over '%s'\n", pThis->szName));
699 return VINF_SUCCESS;
700 }
701 else
702 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to set client MAC address over link '%s' rc=%d\n",
703 pThis->szName, rc));
704
705 mac_client_close(pThis->u.s.hClient, 0 /* fFlags */);
706 pThis->u.s.hClient = NULL;
707 }
708 else
709 {
710 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to create client over link '%s' rc=%d\n",
711 pThis->szName, rc));
712 }
713 }
714 else
715 {
716 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface media type incompatible: %d %d\n", pMacInfo->mi_media,
717 pMacInfo->mi_nativemedia));
718 rc = EPROTO;
719 }
720 }
721 else
722 {
723 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to obtain info for link '%s'\n", pThis->szName));
724 rc = ENXIO;
725 }
726
727 mac_close(pThis->u.s.hInterface);
728 }
729 else
730 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to open link '%s' rc=%d\n", pThis->szName, rc));
731
732 return RTErrConvertFromErrno(rc);
733}
734
735
736
737/**
738 * Detach from the network interface.
739 *
740 * @param pThis The VM connection instance.
741 * @returns corresponding VBox error code.
742 */
743LOCAL int vboxNetFltSolarisDetachFromInterface(PVBOXNETFLTINS pThis)
744{
745 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
746
747 if (pThis->u.s.hPromiscuous)
748 {
749 mac_promisc_remove(pThis->u.s.hPromiscuous);
750 pThis->u.s.hPromiscuous = NULL;
751 }
752
753 if (pThis->u.s.hClient)
754 {
755 if (pThis->u.s.hUnicast)
756 {
757 mac_unicast_remove(pThis->u.s.hClient, pThis->u.s.hUnicast);
758 pThis->u.s.hUnicast = NULL;
759 }
760
761 mac_rx_clear(pThis->u.s.hClient);
762
763 mac_client_close(pThis->u.s.hClient, 0 /* fFlags */);
764 pThis->u.s.hClient = NULL;
765 }
766
767 if (pThis->u.s.hInterface)
768 {
769 mac_close(pThis->u.s.hInterface);
770 pThis->u.s.hInterface = NULL;
771 }
772}
773
774
775/* -=-=-=-=-=- Common Hooks -=-=-=-=-=- */
776bool vboxNetFltPortOsIsPromiscuous(PVBOXNETFLTINS pThis)
777{
778 LogFlow((DEVICE_NAME ":vboxNetFltPortOsIsPromiscuous pThis=%p\n", pThis));
779 return pThis->u.s.hPromiscuous ? true : false;
780}
781
782
783void vboxNetFltPortOsGetMacAddress(PVBOXNETFLTINS pThis, PRTMAC pMac)
784{
785 LogFlow((DEVICE_NAME ":vboxNetFltPortOsGetMacAddress pThis=%p\n", pThis));
786 NOREF(pThis); NOREF(pMac);
787 return;
788}
789
790
791bool vboxNetFltPortOsIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac)
792{
793 /** @todo What happens when the MAC address of the underlying NIC changes?? */
794 return pThis->u.s.Mac.au16[0] == pMac->au16[0]
795 && pThis->u.s.Mac.au16[1] == pMac->au16[1]
796 && pThis->u.s.Mac.au16[2] == pMac->au16[2];
797}
798
799
800void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
801{
802 LogFlow((DEVICE_NAME ":vboxNetFltPortOsSetActive pThis=%p fActive=%d\n", pThis, fActive));
803
804 if (fActive)
805 {
806 /*
807 * Activate promiscuous mode.
808 */
809 if (!pThis->u.s.hPromiscuous)
810 {
811 int rc = mac_promisc_add(pThis->u.s.hClient, MAC_CLIENT_PROMISC_ALL, vboxNetFltSolarisRecv, pThis, &pThis->u.s.hPromiscuous,
812 MAC_PROMISC_FLAGS_NO_TX_LOOP);
813 if (rc)
814 LogRel((DEVICE_NAME ":vboxNetFltPortOsSetActive cannot enable promiscuous mode for '%s' rc=%d\n", pThis->szName, rc));
815 }
816 }
817 else
818 {
819 /*
820 * Deactivate promiscuous mode.
821 */
822 if (pThis->u.s.hPromiscuous)
823 {
824 mac_promisc_remove(pThis->u.s.hPromiscuous);
825 pThis->u.s.hPromiscuous = NULL;
826 }
827 }
828}
829
830
831int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis)
832{
833 LogFlow((DEVICE_NAME ":vboxNetFltOsDisconnectIt pThis=%p\n", pThis));
834 return vboxNetFltSolarisDetachFromInterface(pThis);
835}
836
837
838int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis)
839{
840 LogFlow((DEVICE_NAME ":vboxNetFltOsConnectIt pThis=%p\n", pThis));
841 return vboxNetFltSolarisAttachToInterface(pThis, false /* fRediscovery */);
842}
843
844
845void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
846{
847 LogFlow((DEVICE_NAME ":vboxNetFltOsDeleteInstance pThis=%p\n", pThis));
848}
849
850
851int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
852{
853 LogFlow((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p pvContext=%p\n", pThis, pvContext));
854
855 return VINF_SUCCESS;
856}
857
858
859int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
860{
861 /*
862 * Init. the solaris specific data.
863 */
864 pThis->u.s.hInterface = NULL;
865 pThis->u.s.hClient = NULL;
866 pThis->u.s.hUnicast = NULL;
867 pThis->u.s.hPromiscuous = NULL;
868 bzero(&pThis->u.s.Mac, sizeof(pThis->u.s.Mac));
869 return VINF_SUCCESS;
870}
871
872
873bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
874{
875 /*
876 * @todo Think about this.
877 */
878 return false;
879}
880
881
882int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst)
883{
884 /*
885 * Xmit the packet down the interface (tx)
886 */
887 int rc = VERR_INVALID_HANDLE;
888 if (RT_LIKELY(pThis->u.s.hClient))
889 {
890 mblk_t *pMsg = vboxNetFltSolarisMBlkFromSG(pThis, pSG, fDst);
891 if (RT_LIKELY(pMsg))
892 {
893 LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit pThis=%p cbData=%d\n", pThis, MBLKL(pMsg)));
894
895 mac_tx(pThis->u.s.hClient, pMsg, 0 /* Hint */, MAC_DROP_ON_NO_DESC, NULL /* return message */);
896 return VINF_SUCCESS;
897 }
898 else
899 {
900 LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit no memory for allocating Xmit packet.\n"));
901 rc = VERR_NO_MEMORY;
902 }
903 }
904 else
905 LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit missing client.\n"));
906
907 return rc;
908}
909
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette