VirtualBox

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

Last change on this file since 36564 was 36377, checked in by vboxsync, 14 years ago

Solaris/VBoxNetFltBow: remove unneeded headers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.1 KB
Line 
1/* $Id: VBoxNetFltBow-solaris.c 36377 2011-03-23 17:05:21Z vboxsync $ */
2/** @file
3 * VBoxNetFlt - Network Filter Driver (Host), Solaris Specific Code.
4 */
5
6/*
7 * Copyright (C) 2008 Oracle Corporation
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
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
22#include <VBox/log.h>
23#include <VBox/err.h>
24#include <VBox/intnetinline.h>
25#include <VBox/version.h>
26#include <iprt/initterm.h>
27#include <iprt/alloca.h>
28#include <iprt/assert.h>
29#include <iprt/err.h>
30#include <iprt/string.h>
31#include <iprt/rand.h>
32#include <iprt/net.h>
33#include <iprt/spinlock.h>
34#include <iprt/mem.h>
35
36#include <sys/types.h>
37#include <sys/modctl.h>
38#include <sys/conf.h>
39#include <sys/stat.h>
40#include <sys/ddi.h>
41#include <sys/gld.h>
42#include <sys/sunddi.h>
43#include <sys/strsubr.h>
44#include <sys/dlpi.h>
45#include <sys/dls_mgmt.h>
46#include <sys/mac.h>
47#include <sys/strsun.h>
48#include <sys/sunddi.h>
49
50#include <sys/vnic_mgmt.h>
51#include <sys/mac_client.h>
52#include <sys/mac_provider.h>
53#include <sys/dls.h>
54
55
56#define VBOXNETFLT_OS_SPECFIC 1
57#include "../VBoxNetFltInternal.h"
58
59/*******************************************************************************
60* Defined Constants And Macros *
61*******************************************************************************/
62/** The module name. */
63#define DEVICE_NAME "vboxflt"
64/** The module descriptions as seen in 'modinfo'. */
65#define DEVICE_DESC_DRV "VirtualBox NetBow"
66/** The dynamically created VNIC name */
67#define VBOXFLT_VNIC_NAME "vboxvnic"
68/** Debugging switch for using symbols in kmdb */
69# define LOCAL static
70/** VBOXNETFLTVNIC::u32Magic */
71# define VBOXNETFLTVNIC_MAGIC 0x0ddfaced
72
73#if defined(DEBUG_ramshankar)
74# undef Log
75# define Log LogRel
76# undef LogFlow
77# define LogFlow LogRel
78# undef LOCAL
79# define LOCAL
80#endif
81
82/** VLAN tag masking, should probably be in IPRT? */
83#define VLAN_ID(vlan) (((vlan) >> 0) & 0x0fffu)
84#define VLAN_CFI(vlan) (((vlan) >> 12) & 0x0001u)
85#define VLAN_PRI(vlan) (((vlan) >> 13) & 0x0007u)
86#define VLAN_TAG(pri,cfi,vid) (((pri) << 13) | ((cfi) << 12) | ((vid) << 0))
87
88typedef struct VLANHEADER
89{
90 uint16_t Type;
91 uint16_t Data;
92} VLANHEADER;
93typedef struct VLANHEADER *PVLANHEADER;
94
95
96/*******************************************************************************
97* Kernel Entry Hooks *
98*******************************************************************************/
99LOCAL int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd);
100LOCAL int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd);
101LOCAL int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pArg, void **ppResult);
102
103
104/*******************************************************************************
105* Structures and Typedefs *
106*******************************************************************************/
107/**
108 * cb_ops: for drivers that support char/block entry points
109 */
110static struct cb_ops g_VBoxNetFltSolarisCbOps =
111{
112 nulldev, /* c open */
113 nulldev, /* c close */
114 nodev, /* b strategy */
115 nodev, /* b dump */
116 nodev, /* b print */
117 nodev, /* c read */
118 nodev, /* c write*/
119 nodev, /* c ioctl*/
120 nodev, /* c devmap */
121 nodev, /* c mmap */
122 nodev, /* c segmap */
123 nochpoll, /* c poll */
124 ddi_prop_op, /* property ops */
125 NULL, /* streamtab */
126 D_NEW | D_MP, /* compat. flag */
127 CB_REV, /* revision */
128 nodev, /* c aread */
129 nodev /* c awrite */
130};
131
132/**
133 * dev_ops: for driver device operations
134 */
135static struct dev_ops g_VBoxNetFltSolarisDevOps =
136{
137 DEVO_REV, /* driver build revision */
138 0, /* ref count */
139 VBoxNetFltSolarisGetInfo,
140 nulldev, /* identify */
141 nulldev, /* probe */
142 VBoxNetFltSolarisAttach,
143 VBoxNetFltSolarisDetach,
144 nodev, /* reset */
145 &g_VBoxNetFltSolarisCbOps,
146 NULL, /* bus ops */
147 nodev, /* power */
148 ddi_quiesce_not_needed
149};
150
151/**
152 * modldrv: export driver specifics to the kernel
153 */
154static struct modldrv g_VBoxNetFltSolarisModule =
155{
156 &mod_driverops, /* extern from kernel */
157 DEVICE_DESC_DRV " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV),
158 &g_VBoxNetFltSolarisDevOps
159};
160
161/**
162 * modlinkage: export install/remove/info to the kernel
163 */
164static struct modlinkage g_VBoxNetFltSolarisModLinkage =
165{
166 MODREV_1,
167 {
168 &g_VBoxNetFltSolarisModule,
169 NULL,
170 }
171};
172
173/**
174 * VBOXNETFLTVNIC: Per-VNIC instance data.
175 */
176typedef struct VBOXNETFLTVNIC
177{
178 uint32_t u32Magic; /* Magic number (VBOXNETFLTVNIC_MAGIC) */
179 bool fCreated; /* Whether we created the VNIC or not */
180 void *pvIf; /* The VirtualBox interface */
181 mac_handle_t hInterface; /* The lower MAC handle */
182 datalink_id_t hLinkId; /* The link ID */
183 mac_client_handle_t hClient; /* Client handle */
184 mac_unicast_handle_t hUnicast; /* Unicast address handle */
185 mac_promisc_handle_t hPromiscuous; /* Promiscuous handle */
186 char szName[128]; /* The VNIC name */
187 list_node_t hNode; /* Handle to the next VNIC in the list */
188} VBOXNETFLTVNIC;
189typedef struct VBOXNETFLTVNIC *PVBOXNETFLTVNIC;
190
191
192/*******************************************************************************
193* Global Variables *
194*******************************************************************************/
195/** Global Device handle we only support one instance. */
196static dev_info_t *g_pVBoxNetFltSolarisDip = NULL;
197/** Global Mutex (actually an rw lock). */
198static RTSEMFASTMUTEX g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX;
199/** The (common) global data. */
200static VBOXNETFLTGLOBALS g_VBoxNetFltSolarisGlobals;
201
202
203/*******************************************************************************
204* Internal Functions *
205*******************************************************************************/
206LOCAL mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst);
207LOCAL unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg);
208LOCAL int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc);
209LOCAL void vboxNetFltSolarisRecv(void *pvData, mac_resource_handle_t hResource, mblk_t *pMsg, boolean_t fLoopback);
210LOCAL void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg);
211LOCAL void vboxNetFltSolarisReportInfo(PVBOXNETFLTINS pThis);
212LOCAL int vboxNetFltSolarisInitVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC pVNIC);
213LOCAL PVBOXNETFLTVNIC vboxNetFltSolarisAllocVNIC(void);
214LOCAL void vboxNetFltSolarisFreeVNIC(PVBOXNETFLTVNIC pVNIC);
215LOCAL void vboxNetFltSolarisDestroyVNIC(PVBOXNETFLTVNIC pVNIC);
216LOCAL int vboxNetFltSolarisCreateVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC *ppVNIC);
217
218
219/**
220 * Kernel entry points
221 */
222int _init(void)
223{
224 LogFlow((DEVICE_NAME ":_init\n"));
225
226 /*
227 * Prevent module autounloading.
228 */
229 modctl_t *pModCtl = mod_getctl(&g_VBoxNetFltSolarisModLinkage);
230 if (pModCtl)
231 pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
232 else
233 LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));
234
235 /*
236 * Initialize IPRT.
237 */
238 int rc = RTR0Init(0);
239 if (RT_SUCCESS(rc))
240 {
241 /*
242 * Initialize Solaris specific globals here.
243 */
244 rc = RTSemFastMutexCreate(&g_VBoxNetFltSolarisMtx);
245 if (RT_SUCCESS(rc))
246 {
247 /*
248 * Initialize the globals and connect to the support driver.
249 *
250 * This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
251 * for establishing the connect to the support driver.
252 */
253 memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals));
254 rc = vboxNetFltInitGlobalsAndIdc(&g_VBoxNetFltSolarisGlobals);
255 if (RT_SUCCESS(rc))
256 {
257 rc = mod_install(&g_VBoxNetFltSolarisModLinkage);
258 if (!rc)
259 return rc;
260
261 LogRel((DEVICE_NAME ":mod_install failed. rc=%d\n", rc));
262 vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals);
263 }
264 else
265 LogRel((DEVICE_NAME ":failed to initialize globals.\n"));
266
267 RTSemFastMutexDestroy(g_VBoxNetFltSolarisMtx);
268 g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX;
269 }
270
271 RTR0Term();
272 }
273 else
274 LogRel((DEVICE_NAME ":failed to initialize IPRT (rc=%d)\n", rc));
275
276 memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals));
277 return RTErrConvertToErrno(rc);
278}
279
280
281int _fini(void)
282{
283 int rc;
284 LogFlow((DEVICE_NAME ":_fini\n"));
285
286 /*
287 * Undo the work done during start (in reverse order).
288 */
289 rc = vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals);
290 if (RT_FAILURE(rc))
291 {
292 LogRel((DEVICE_NAME ":_fini - busy!\n"));
293 return EBUSY;
294 }
295
296 rc = mod_remove(&g_VBoxNetFltSolarisModLinkage);
297 if (!rc)
298 {
299 if (g_VBoxNetFltSolarisMtx != NIL_RTSEMFASTMUTEX)
300 {
301 RTSemFastMutexDestroy(g_VBoxNetFltSolarisMtx);
302 g_VBoxNetFltSolarisMtx = NIL_RTSEMFASTMUTEX;
303 }
304
305 RTR0Term();
306 }
307
308 return rc;
309}
310
311
312int _info(struct modinfo *pModInfo)
313{
314 LogFlow((DEVICE_NAME ":_info\n"));
315
316 int rc = mod_info(&g_VBoxNetFltSolarisModLinkage, pModInfo);
317
318 LogFlow((DEVICE_NAME ":_info returns %d\n", rc));
319 return rc;
320}
321
322
323/**
324 * Attach entry point, to attach a device to the system or resume it.
325 *
326 * @param pDip The module structure instance.
327 * @param enmCmd Operation type (attach/resume).
328 *
329 * @returns corresponding solaris error code.
330 */
331LOCAL int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
332{
333 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd));
334
335 switch (enmCmd)
336 {
337 case DDI_ATTACH:
338 {
339 int instance = ddi_get_instance(pDip);
340 int rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME, S_IFCHR, instance, DDI_PSEUDO, 0, "none", "none", 0666);
341 if (rc == DDI_SUCCESS)
342 {
343 g_pVBoxNetFltSolarisDip = pDip;
344 ddi_report_dev(pDip);
345 return DDI_SUCCESS;
346 }
347 else
348 LogRel((DEVICE_NAME ":VBoxNetFltSolarisAttach failed to create minor node. rc=%d\n", rc));
349 return DDI_FAILURE;
350 }
351
352 case DDI_RESUME:
353 {
354 /* Nothing to do here... */
355 return DDI_SUCCESS;
356 }
357
358 /* case DDI_PM_RESUME: */
359 default:
360 return DDI_FAILURE;
361 }
362}
363
364
365/**
366 * Detach entry point, to detach a device to the system or suspend it.
367 *
368 * @param pDip The module structure instance.
369 * @param enmCmd Operation type (detach/suspend).
370 *
371 * @returns corresponding solaris error code.
372 */
373LOCAL int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
374{
375 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd));
376
377 switch (enmCmd)
378 {
379 case DDI_DETACH:
380 {
381 ddi_remove_minor_node(pDip, NULL);
382 return DDI_SUCCESS;
383 }
384
385 case DDI_RESUME:
386 {
387 /* Nothing to do here... */
388 return DDI_SUCCESS;
389 }
390
391 /* case DDI_PM_SUSPEND: */
392 /* case DDI_HOT_PLUG_DETACH: */
393 default:
394 return DDI_FAILURE;
395 }
396}
397
398
399/**
400 * Info entry point, called by solaris kernel for obtaining driver info.
401 *
402 * @param pDip The module structure instance (do not use).
403 * @param enmCmd Information request type.
404 * @param pvArg Type specific argument.
405 * @param ppvResult Where to store the requested info.
406 *
407 * @returns corresponding solaris error code.
408 */
409LOCAL int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg, void **ppResult)
410{
411 LogFlow((DEVICE_NAME ":VBoxNetFltSolarisGetInfo pDip=%p enmCmd=%d pArg=%p instance=%d\n", pDip, enmCmd, getminor((dev_t)pvArg)));
412
413 switch (enmCmd)
414 {
415 case DDI_INFO_DEVT2DEVINFO:
416 {
417 *ppResult = g_pVBoxNetFltSolarisDip;
418 return DDI_SUCCESS;
419 }
420
421 case DDI_INFO_DEVT2INSTANCE:
422 {
423 int instance = getminor((dev_t)pvArg);
424 *ppResult = (void *)(uintptr_t)instance;
425 return DDI_SUCCESS;
426 }
427 }
428
429 return DDI_FAILURE;
430}
431
432
433/**
434 * Create a solaris message block from the SG list.
435 *
436 * @param pThis The instance.
437 * @param pSG Pointer to the scatter-gather list.
438 *
439 * @returns Solaris message block.
440 */
441LOCAL mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst)
442{
443 LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG pThis=%p pSG=%p\n", pThis, pSG));
444
445 mblk_t *pMsg = allocb(pSG->cbTotal, BPRI_HI);
446 if (RT_UNLIKELY(!pMsg))
447 {
448 LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG failed to alloc %d bytes for mblk_t.\n", pSG->cbTotal));
449 return NULL;
450 }
451
452 /*
453 * Single buffer copy. Maybe later explore the
454 * need/possibility for using a mblk_t chain rather.
455 */
456 for (unsigned i = 0; i < pSG->cSegsUsed; i++)
457 {
458 if (pSG->aSegs[i].pv)
459 {
460 bcopy(pSG->aSegs[i].pv, pMsg->b_wptr, pSG->aSegs[i].cb);
461 pMsg->b_wptr += pSG->aSegs[i].cb;
462 }
463 }
464 DB_TYPE(pMsg) = M_DATA;
465 return pMsg;
466}
467
468
469/**
470 * Calculate the number of segments required for this message block.
471 *
472 * @param pThis The instance
473 * @param pMsg Pointer to the data message.
474 *
475 * @returns Number of segments.
476 */
477LOCAL unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg)
478{
479 unsigned cSegs = 0;
480 for (mblk_t *pCur = pMsg; pCur; pCur = pCur->b_cont)
481 if (MBLKL(pCur))
482 cSegs++;
483
484#ifdef PADD_RUNT_FRAMES_FROM_HOST
485 if (msgdsize(pMsg) < 60)
486 cSegs++;
487#endif
488
489 NOREF(pThis);
490 return RT_MAX(cSegs, 1);
491}
492
493
494/**
495 * Initializes an SG list from the given message block.
496 *
497 * @param pThis The instance.
498 * @param pMsg Pointer to the data message.
499 The caller must ensure it's not a control message block.
500 * @param pSG Pointer to the SG.
501 * @param cSegs Number of segments in the SG.
502 * This should match the number in the message block exactly!
503 * @param fSrc The source of the message.
504 *
505 * @returns VBox status code.
506 */
507LOCAL int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc)
508{
509 LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pThis=%p pMsg=%p pSG=%p cSegs=%d\n", pThis, pMsg, pSG, cSegs));
510
511 /*
512 * Convert the message block to segments. Works cbTotal and sets cSegsUsed.
513 */
514 IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, cSegs, 0 /*cSegsUsed*/);
515 mblk_t *pCur = pMsg;
516 unsigned iSeg = 0;
517 while (pCur)
518 {
519 size_t cbSeg = MBLKL(pCur);
520 if (cbSeg)
521 {
522 void *pvSeg = pCur->b_rptr;
523 pSG->aSegs[iSeg].pv = pvSeg;
524 pSG->aSegs[iSeg].cb = cbSeg;
525 pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
526 pSG->cbTotal += cbSeg;
527 iSeg++;
528 }
529 pCur = pCur->b_cont;
530 }
531 pSG->cSegsUsed = iSeg;
532
533#ifdef PADD_RUNT_FRAMES_FROM_HOST
534 if (pSG->cbTotal < 60 && (fSrc & INTNETTRUNKDIR_HOST))
535 {
536 LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pulling up to length.\n"));
537
538 static uint8_t const s_abZero[128] = {0};
539 pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
540 pSG->aSegs[iSeg].pv = (void *)&s_abZero[0];
541 pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal;
542 pSG->cbTotal = 60;
543 pSG->cSegsUsed++;
544 Assert(iSeg + 1 < cSegs);
545 }
546#endif
547
548 LogFlow((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG iSeg=%d pSG->cbTotal=%d msgdsize=%d\n", iSeg, pSG->cbTotal, msgdsize(pMsg)));
549 return VINF_SUCCESS;
550}
551
552
553/**
554 * Simple packet dump, used for internal debugging.
555 *
556 * @param pMsg Pointer to the message to analyze and dump.
557 */
558LOCAL void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg)
559{
560 LogFlowFunc((DEVICE_NAME ":vboxNetFltSolarisAnalyzeMBlk pMsg=%p\n", pMsg));
561
562 PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr;
563 uint8_t *pb = pMsg->b_rptr;
564 if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
565 {
566 PRTNETIPV4 pIpHdr = (PRTNETIPV4)(pEthHdr + 1);
567 if (!pMsg->b_cont)
568 {
569 if (pIpHdr->ip_p == RTNETIPV4_PROT_ICMP)
570 LogRel((DEVICE_NAME ":ICMP D=%.6Rhxs S=%.6Rhxs T=%04x\n", pb, pb + 6, RT_BE2H_U16(*(uint16_t *)(pb + 12))));
571 else if (pIpHdr->ip_p == RTNETIPV4_PROT_TCP)
572 LogRel((DEVICE_NAME ":TCP D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6));
573 else if (pIpHdr->ip_p == RTNETIPV4_PROT_UDP)
574 {
575 PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint32_t *)pIpHdr + pIpHdr->ip_hl);
576 if ( RT_BE2H_U16(pUdpHdr->uh_sport) == 67
577 && RT_BE2H_U16(pUdpHdr->uh_dport) == 68)
578 {
579 LogRel((DEVICE_NAME ":UDP bootp ack D=%.6Rhxs S=%.6Rhxs UDP_CheckSum=%04x Computex=%04x\n", pb, pb + 6,
580 RT_BE2H_U16(pUdpHdr->uh_sum), RT_BE2H_U16(RTNetIPv4UDPChecksum(pIpHdr, pUdpHdr, pUdpHdr + 1))));
581 }
582 }
583 }
584 else
585 {
586 LogFlow((DEVICE_NAME ":Chained IP packet. Skipping validity check.\n"));
587 }
588 }
589 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_VLAN))
590 {
591 PVLANHEADER pVlanHdr = (PVLANHEADER)(pMsg->b_rptr + sizeof(RTNETETHERHDR) - sizeof(pEthHdr->EtherType));
592 LogRel((DEVICE_NAME ":VLAN Pcp=%u Cfi=%u Id=%u\n", VLAN_PRI(RT_BE2H_U16(pVlanHdr->Data)), VLAN_CFI(RT_BE2H_U16(pVlanHdr->Data)), VLAN_ID(RT_BE2H_U16(pVlanHdr->Data))));
593 LogRel((DEVICE_NAME "%.*Rhxd\n", sizeof(VLANHEADER), pVlanHdr));
594 }
595 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP))
596 {
597 PRTNETARPHDR pArpHdr = (PRTNETARPHDR)(pEthHdr + 1);
598 LogRel((DEVICE_NAME ":ARP Op=%d\n", pArpHdr->ar_oper));
599 }
600 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
601 {
602 LogRel((DEVICE_NAME ":IPv6 D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6));
603 }
604 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_1)
605 || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_2)
606 || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_3))
607 {
608 LogRel((DEVICE_NAME ":IPX packet.\n"));
609 }
610 else
611 {
612 LogRel((DEVICE_NAME ":Unknown EtherType=%x D=%.6Rhxs S=%.6Rhxs\n", RT_H2BE_U16(pEthHdr->EtherType), &pEthHdr->DstMac,
613 &pEthHdr->SrcMac));
614 /* LogFlow((DEVICE_NAME ":%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr)); */
615 }
616}
617
618
619/**
620 * Helper.
621 */
622DECLINLINE(bool) vboxNetFltPortSolarisIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac)
623{
624 return pThis->u.s.MacAddr.au16[0] == pMac->au16[0]
625 && pThis->u.s.MacAddr.au16[1] == pMac->au16[1]
626 && pThis->u.s.MacAddr.au16[2] == pMac->au16[2];
627}
628
629
630/**
631 * Receive (rx) entry point.
632 *
633 * @param pvData Private data.
634 * @param hResource The resource handle.
635 * @param pMsg The packet.
636 * @param fLoopback Whether this is a loopback packet or not.
637 */
638LOCAL void vboxNetFltSolarisRecv(void *pvData, mac_resource_handle_t hResource, mblk_t *pMsg, boolean_t fLoopback)
639{
640 LogFlow((DEVICE_NAME ":vboxNetFltSolarisRecv pvData=%p pMsg=%p fLoopback=%d cbData=%d\n", pvData, pMsg, fLoopback, pMsg ? MBLKL(pMsg) : 0));
641
642 PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvData;
643 AssertPtrReturnVoid(pThis);
644 AssertPtrReturnVoid(pMsg);
645
646 /*
647 * Active? Retain the instance and increment the busy counter.
648 */
649 if (!vboxNetFltTryRetainBusyActive(pThis))
650 return;
651
652 uint32_t fSrc = INTNETTRUNKDIR_WIRE;
653 PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
654 if ( MBLKL(pMsg) >= sizeof(RTNETETHERHDR)
655 && vboxNetFltPortSolarisIsHostMac(pThis, &pEthHdr->SrcMac))
656 fSrc = INTNETTRUNKDIR_HOST;
657
658 /*
659 * Route all received packets into the internal network.
660 */
661 uint16_t cFailed = 0;
662 for (mblk_t *pCurMsg = pMsg; pCurMsg != NULL; pCurMsg = pCurMsg->b_next)
663 {
664 unsigned cSegs = vboxNetFltSolarisMBlkCalcSGSegs(pThis, pCurMsg);
665 PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
666 int rc = vboxNetFltSolarisMBlkToSG(pThis, pMsg, pSG, cSegs, fSrc);
667 if (RT_SUCCESS(rc))
668 pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, NULL, pSG, fSrc);
669 else
670 cFailed++;
671 }
672 vboxNetFltRelease(pThis, true /* fBusy */);
673
674 if (RT_UNLIKELY(cFailed))
675 LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG failed for %u packets.\n", cFailed));
676
677 freemsgchain(pMsg);
678
679 NOREF(hResource);
680}
681
682
683/**
684 * Report capabilities and MAC address to IntNet.
685 *
686 * @param pThis The instance.
687 * @remarks Retains the instance while doing it's job.
688 */
689LOCAL void vboxNetFltSolarisReportInfo(PVBOXNETFLTINS pThis)
690{
691 if (!pThis->u.s.fReportedInfo)
692 {
693 if (vboxNetFltTryRetainBusyNotDisconnected(pThis))
694 {
695 Assert(pThis->pSwitchPort);
696 LogFlow((DEVICE_NAME ":vboxNetFltSolarisInitVNIC phys mac %.6Rhxs\n", &pThis->u.s.MacAddr));
697 pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr);
698 pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, false); /** @todo Promisc */
699 pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST);
700 pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */);
701 pThis->u.s.fReportedInfo = true;
702 vboxNetFltRelease(pThis, true /*fBusy*/);
703 }
704 }
705}
706
707
708/**
709 * Initialize a VNIC.
710 *
711 * @param pThis The instance.
712 * @param pVNIC Pointer to the VNIC.
713 *
714 * @returns Solaris error code (errno).
715 */
716LOCAL int vboxNetFltSolarisInitVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC pVNIC)
717{
718 /*
719 * Some paranoia.
720 */
721 AssertReturn(pThis, VERR_INVALID_PARAMETER);
722 AssertReturn(pVNIC, VERR_INVALID_PARAMETER);
723 AssertReturn(pVNIC->hInterface, VERR_INVALID_POINTER);
724 AssertReturn(pVNIC->hLinkId, VERR_INVALID_POINTER);
725 AssertReturn(!pVNIC->hClient, VERR_INVALID_HANDLE);
726
727 int rc = mac_client_open(pVNIC->hInterface, &pVNIC->hClient,
728 NULL, /* name of this client */
729 MAC_OPEN_FLAGS_USE_DATALINK_NAME | /* client name same as underlying NIC */
730 MAC_OPEN_FLAGS_MULTI_PRIMARY /* allow multiple primary unicasts */
731 );
732 if (RT_LIKELY(!rc))
733 {
734 /*
735 * Set the RX callback.
736 */
737 mac_diag_t Diag = MAC_DIAG_NONE;
738 rc = mac_unicast_add_set_rx(pVNIC->hClient,
739 NULL /* MAC address, use existing VNIC address */,
740 MAC_UNICAST_PRIMARY | /* Use Primary address of the VNIC */
741 MAC_UNICAST_NODUPCHECK, /* Don't fail for conflicting MAC/VLAN-id combinations */
742 &pVNIC->hUnicast,
743 0 /* VLAN-id */,
744 &Diag,
745 vboxNetFltSolarisRecv, /* RX callback */
746 pThis /* callback private data */
747 );
748 if (RT_LIKELY(!rc))
749 {
750 if (!pThis->u.s.fReportedInfo)
751 {
752 /*
753 * Obtain the MAC address of the underlying physical interface.
754 */
755 mac_handle_t hLowerMac = mac_get_lower_mac_handle(pVNIC->hInterface);
756 if (RT_LIKELY(hLowerMac))
757 {
758 mac_unicast_primary_get(hLowerMac, (uint8_t *)pThis->u.s.MacAddr.au8);
759 vboxNetFltSolarisReportInfo(pThis);
760 }
761 else
762 {
763 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNIC failed to get lower MAC handle for '%s'\n", pThis->szName));
764 rc = ENODEV;
765 }
766 }
767
768 if (!rc)
769 {
770 Assert(pVNIC->hClient);
771 Assert(pVNIC->hInterface);
772 Assert(pVNIC->hLinkId);
773 LogFlow((DEVICE_NAME ":vboxNetFltSolarisInitVNIC successfully initialized VNIC '%s'\n", pVNIC->szName));
774 return 0;
775 }
776
777 mac_unicast_remove(pVNIC->hClient, pVNIC->hUnicast);
778 mac_rx_clear(pVNIC->hClient);
779 pVNIC->hUnicast = NULL;
780 }
781 else
782 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNIC failed to set RX callback. rc=%d Diag=%d\n", rc, Diag));
783
784 mac_client_close(pVNIC->hClient, 0 /* flags */);
785 pVNIC->hClient = NULL;
786 }
787 else
788 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNIC failed to open mac client for '%s' rc=%d\n", pThis->szName, rc));
789
790 return RTErrConvertFromErrno(rc);
791}
792
793
794/**
795 * Allocate a VNIC structure.
796 *
797 * @returns An allocated VNIC structure or NULL in case of errors.
798 */
799LOCAL PVBOXNETFLTVNIC vboxNetFltSolarisAllocVNIC(void)
800{
801 PVBOXNETFLTVNIC pVNIC = RTMemAlloc(sizeof(VBOXNETFLTVNIC));
802 if (RT_UNLIKELY(!pVNIC))
803 return NULL;
804
805 pVNIC->u32Magic = VBOXNETFLTVNIC_MAGIC;
806 pVNIC->fCreated = false;
807 pVNIC->pvIf = NULL;
808 pVNIC->hInterface = NULL;
809 pVNIC->hLinkId = DATALINK_INVALID_LINKID;
810 pVNIC->hClient = NULL;
811 pVNIC->hUnicast = NULL;
812 pVNIC->hPromiscuous = NULL;
813 RT_ZERO(pVNIC->szName);
814 list_link_init(&pVNIC->hNode);
815 return pVNIC;
816}
817
818
819/**
820 * Frees an allocated VNIC.
821 *
822 * @param pVNIC Pointer to the VNIC.
823 */
824LOCAL void vboxNetFltSolarisFreeVNIC(PVBOXNETFLTVNIC pVNIC)
825{
826 if (pVNIC)
827 RTMemFree(pVNIC);
828}
829
830
831/**
832 * Destroy a created VNIC if it was created by us, or just
833 * de-initializes the VNIC freeing up resources handles.
834 *
835 * @param pVNIC Pointer to the VNIC.
836 */
837LOCAL void vboxNetFltSolarisDestroyVNIC(PVBOXNETFLTVNIC pVNIC)
838{
839 if (pVNIC)
840 {
841 if (pVNIC->hPromiscuous)
842 {
843 mac_promisc_remove(pVNIC->hPromiscuous);
844 pVNIC->hPromiscuous = NULL;
845 }
846
847 if (pVNIC->hClient)
848 {
849 if (pVNIC->hUnicast)
850 {
851 mac_unicast_remove(pVNIC->hClient, pVNIC->hUnicast);
852 pVNIC->hUnicast = NULL;
853 }
854
855 mac_rx_clear(pVNIC->hClient);
856
857 mac_client_close(pVNIC->hClient, 0 /* fFlags */);
858 pVNIC->hClient = NULL;
859 }
860
861 if (pVNIC->hInterface)
862 {
863 mac_close(pVNIC->hInterface);
864 pVNIC->hInterface = NULL;
865 }
866
867 if (pVNIC->fCreated)
868 {
869 vnic_delete(pVNIC->hLinkId, 0 /* Flags */);
870 pVNIC->hLinkId = DATALINK_INVALID_LINKID;
871 pVNIC->fCreated = false;
872 }
873 }
874}
875
876
877/**
878 * Create a non-persistent VNIC over the given interface.
879 *
880 * @param pThis The VM connection instance.
881 * @param ppVNIC Where to store the created VNIC.
882 *
883 * @returns corresponding VBox error code.
884 */
885LOCAL int vboxNetFltSolarisCreateVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC *ppVNIC)
886{
887 LogFlow((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC pThis=%p\n", pThis));
888
889 AssertReturn(pThis, VERR_INVALID_POINTER);
890 AssertReturn(ppVNIC, VERR_INVALID_POINTER);
891
892 PVBOXNETFLTVNIC pVNIC = vboxNetFltSolarisAllocVNIC();
893 if (RT_UNLIKELY(!pVNIC))
894 return VERR_NO_MEMORY;
895
896 AssertCompile(sizeof(pVNIC->szName) > sizeof(VBOXFLT_VNIC_NAME) + 64);
897 RTStrPrintf(pVNIC->szName, sizeof(pVNIC->szName), "%s%RU64", VBOXFLT_VNIC_NAME, pThis->u.s.uInstance);
898
899 /*
900 * Set a random MAC address for now. It will be changed to the VM interface's
901 * MAC address later, see vboxNetFltPortOsNotifyMacAddress().
902 */
903 RTMAC GuestMac;
904 GuestMac.au8[0] = 0x08;
905 GuestMac.au8[1] = 0x00;
906 GuestMac.au8[2] = 0x27;
907 RTRandBytes(&GuestMac.au8[3], 3);
908
909 AssertCompile(sizeof(RTMAC) <= MAXMACADDRLEN);
910
911 vnic_mac_addr_type_t AddrType = VNIC_MAC_ADDR_TYPE_FIXED;
912 vnic_ioc_diag_t Diag = VNIC_IOC_DIAG_NONE;
913 int MacSlot = 0;
914 int MacLen = sizeof(GuestMac);
915 uint32_t fFlags = 0;
916
917 int rc = vnic_create(pVNIC->szName, pThis->szName, &AddrType, &MacLen, GuestMac.au8, &MacSlot, 0 /* Mac-Prefix Length */, 0 /* VLAN-ID */,
918 fFlags, &pVNIC->hLinkId, &Diag, NULL /* Reserved */);
919 if (!rc)
920 {
921 pVNIC->fCreated = true;
922
923 /*
924 * Now try opening the created VNIC.
925 */
926 rc = mac_open_by_linkid(pVNIC->hLinkId, &pVNIC->hInterface);
927 if (!rc)
928 {
929 rc = vboxNetFltSolarisInitVNIC(pThis, pVNIC);
930 if (RT_LIKELY(!rc))
931 {
932 pThis->u.s.uInstance++;
933 LogFlow((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC successfully created VNIC '%s' over '%s'\n", pVNIC->szName, pThis->szName));
934 *ppVNIC = pVNIC;
935 return VINF_SUCCESS;
936 }
937 else
938 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC vboxNetFltSolarisInitVNIC failed. rc=%d\n", rc));
939
940 mac_close(pVNIC->hInterface);
941 pVNIC->hInterface = NULL;
942 }
943 else
944 {
945 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to open VNIC '%s' over '%s'. rc=%d\n", pVNIC->szName,
946 pThis->szName, rc));
947 }
948
949 vboxNetFltSolarisDestroyVNIC(pVNIC);
950 rc = VERR_OPEN_FAILED;
951 }
952 else
953 {
954 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to create VNIC '%s' over '%s' rc=%d Diag=%d\n", pVNIC->szName,
955 pThis->szName, rc, Diag));
956 rc = VERR_INTNET_FLT_VNIC_CREATE_FAILED;
957 }
958
959 vboxNetFltSolarisFreeVNIC(pVNIC);
960
961 return rc;
962}
963
964
965/* -=-=-=-=-=- Common Hooks -=-=-=-=-=- */
966
967
968void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
969{
970 LogFlow((DEVICE_NAME ":vboxNetFltPortOsSetActive pThis=%p fActive=%d\n", pThis, fActive));
971#if 0
972 if (fActive)
973 {
974 /*
975 * Activate promiscuous mode.
976 */
977 if (!pThis->u.s.hPromiscuous)
978 {
979 int rc = mac_promisc_add(pThis->u.s.hClient, MAC_CLIENT_PROMISC_ALL, vboxNetFltSolarisRecv, pThis, &pThis->u.s.hPromiscuous,
980 MAC_PROMISC_FLAGS_NO_TX_LOOP);
981 if (rc)
982 LogRel((DEVICE_NAME ":vboxNetFltPortOsSetActive cannot enable promiscuous mode for '%s' rc=%d\n", pThis->szName, rc));
983 }
984 }
985 else
986 {
987 /*
988 * Deactivate promiscuous mode.
989 */
990 if (pThis->u.s.hPromiscuous)
991 {
992 mac_promisc_remove(pThis->u.s.hPromiscuous);
993 pThis->u.s.hPromiscuous = NULL;
994 }
995 }
996#endif
997}
998
999
1000int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis)
1001{
1002 LogFlow((DEVICE_NAME ":vboxNetFltOsDisconnectIt pThis=%p\n", pThis));
1003 return VINF_SUCCESS;
1004}
1005
1006
1007int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis)
1008{
1009 LogFlow((DEVICE_NAME ":vboxNetFltOsConnectIt pThis=%p\n", pThis));
1010 return VINF_SUCCESS;
1011}
1012
1013
1014void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
1015{
1016 LogFlow((DEVICE_NAME ":vboxNetFltOsDeleteInstance pThis=%p\n", pThis));
1017
1018 /*
1019 * Destroy all managed VNICs. If a VNIC was passed to us, there
1020 * will be only 1 item in the list, otherwise as many interfaces
1021 * that were somehow not destroyed using DisconnectInterface() will be
1022 * present.
1023 */
1024 PVBOXNETFLTVNIC pVNIC = NULL;
1025 while ((pVNIC = list_remove_head(&pThis->u.s.hVNICs)) != NULL)
1026 {
1027 vboxNetFltSolarisDestroyVNIC(pVNIC);
1028 vboxNetFltSolarisFreeVNIC(pVNIC);
1029 }
1030
1031 list_destroy(&pThis->u.s.hVNICs);
1032}
1033
1034
1035int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
1036{
1037 LogFlow((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p pvContext=%p\n", pThis, pvContext));
1038
1039 /*
1040 * Figure out if the interface is a VNIC or a physical/etherstub/whatever NIC.
1041 */
1042 mac_handle_t hInterface;
1043 int rc = mac_open_by_linkname(pThis->szName, &hInterface);
1044 if (RT_LIKELY(!rc))
1045 {
1046 rc = mac_is_vnic(hInterface);
1047 if (!rc)
1048 {
1049 /*
1050 * This is NOT a VNIC. Just pretend success for now.
1051 * We will create a VNIC per VM interface later, see vboxNetFltPortOsConnectInterface().
1052 */
1053 pThis->u.s.fIsVNIC = false;
1054 mac_unicast_primary_get(hInterface, pThis->u.s.MacAddr.au8);
1055 vboxNetFltSolarisReportInfo(pThis);
1056 mac_close(hInterface);
1057 return VINF_SUCCESS;
1058 }
1059
1060 pThis->u.s.fIsVNIC = true;
1061
1062 PVBOXNETFLTVNIC pVNIC = vboxNetFltSolarisAllocVNIC();
1063 if (RT_LIKELY(pVNIC))
1064 {
1065 pVNIC->fCreated = false;
1066 pVNIC->hInterface = hInterface;
1067
1068 /*
1069 * Obtain the data link ID for this VNIC, it's needed for modifying the MAC address among other things.
1070 */
1071 rc = dls_mgmt_get_linkid(pThis->szName, &pVNIC->hLinkId);
1072 if (RT_LIKELY(!rc))
1073 {
1074 /*
1075 * Initialize the VNIC and add it to the list of managed VNICs.
1076 */
1077 RTStrPrintf(pVNIC->szName, sizeof(pVNIC->szName), "%s", pThis->szName);
1078 rc = vboxNetFltSolarisInitVNIC(pThis, pVNIC);
1079 if (!rc)
1080 {
1081 list_insert_head(&pThis->u.s.hVNICs, pVNIC);
1082 return VINF_SUCCESS;
1083 }
1084 else
1085 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance vboxNetFltSolarisInitVNIC failed. rc=%d\n", rc));
1086 }
1087 else
1088 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to get link id for '%s'. rc=%d\n", pThis->szName, rc));
1089
1090 vboxNetFltSolarisFreeVNIC(pVNIC);
1091 }
1092 else
1093 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to allocate VNIC private data.\n"));
1094
1095 mac_close(hInterface);
1096 }
1097 else
1098 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to open link '%s'! rc=%d\n", pThis->szName, rc));
1099
1100 return RTErrConvertFromErrno(rc);
1101}
1102
1103
1104int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
1105{
1106 /*
1107 * Init. the solaris specific data.
1108 */
1109 pThis->u.s.fIsVNIC = false;
1110 list_create(&pThis->u.s.hVNICs, sizeof(VBOXNETFLTVNIC), offsetof(VBOXNETFLTVNIC, hNode));
1111 pThis->u.s.uInstance = 0;
1112 pThis->u.s.pvVNIC = NULL;
1113 bzero(&pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr));
1114 pThis->u.s.fReportedInfo = false;
1115 return VINF_SUCCESS;
1116}
1117
1118
1119bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
1120{
1121 /*
1122 * @todo Think about this.
1123 */
1124 return false;
1125}
1126
1127
1128int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
1129{
1130 /*
1131 * Validate parameters.
1132 */
1133 PVBOXNETFLTVNIC pVNIC = pvIfData;
1134 AssertMsgReturn(VALID_PTR(pVNIC) && pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC,
1135 ("Invalid pvIfData=%p magic=%#x (expected %#x)\n", pvIfData, pVNIC ? pVNIC->u32Magic : 0, VBOXNETFLTVNIC_MAGIC),
1136 VERR_INVALID_PARAMETER);
1137
1138 /*
1139 * Xmit the packet down the appropriate VNIC interface.
1140 */
1141 int rc = VINF_SUCCESS;
1142 mblk_t *pMsg = vboxNetFltSolarisMBlkFromSG(pThis, pSG, fDst);
1143 if (RT_LIKELY(pMsg))
1144 {
1145 LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit pThis=%p cbData=%d\n", pThis, MBLKL(pMsg)));
1146
1147 mac_tx_cookie_t pXmitCookie = mac_tx(pVNIC->hClient, pMsg, 0 /* Hint */, MAC_DROP_ON_NO_DESC, NULL /* return message */);
1148 if (RT_LIKELY(!pXmitCookie))
1149 return VINF_SUCCESS;
1150
1151 pMsg = NULL;
1152 rc = VERR_NET_IO_ERROR;
1153 LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit Xmit failed pVNIC=%p.\n", pVNIC));
1154 }
1155 else
1156 {
1157 LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit no memory for allocating Xmit packet.\n"));
1158 rc = VERR_NO_MEMORY;
1159 }
1160
1161 return rc;
1162}
1163
1164
1165void vboxNetFltPortOsNotifyMacAddress(PVBOXNETFLTINS pThis, void *pvIfData, PCRTMAC pMac)
1166{
1167 LogFlow((DEVICE_NAME ":vboxNetFltPortOSNotifyMacAddress %s %.6Rhxs\n", pThis->szName, pMac));
1168
1169 /*
1170 * Validate parameters.
1171 */
1172 PVBOXNETFLTVNIC pVNIC = pvIfData;
1173 AssertMsgReturnVoid(VALID_PTR(pVNIC) && pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC,
1174 ("Invalid pvIfData=%p magic=%#x (expected %#x)\n", pvIfData, pVNIC ? pVNIC->u32Magic : 0, VBOXNETFLTVNIC_MAGIC));
1175 AssertMsgReturnVoid(pVNIC->hLinkId != DATALINK_INVALID_LINKID,
1176 ("Invalid hLinkId pVNIC=%p magic=%#x\n", pVNIC, pVNIC->u32Magic));
1177
1178 /*
1179 * Set the MAC address of the VNIC to the one used by the VM interface.
1180 */
1181 uchar_t au8GuestMac[MAXMACADDRLEN];
1182 bcopy(pMac->au8, au8GuestMac, sizeof(RTMAC));
1183
1184 vnic_mac_addr_type_t AddrType = VNIC_MAC_ADDR_TYPE_FIXED;
1185 vnic_ioc_diag_t Diag = VNIC_IOC_DIAG_NONE;
1186 int MacSlot = 0;
1187 int MacLen = sizeof(RTMAC);
1188
1189 int rc = vnic_modify_addr(pVNIC->hLinkId, &AddrType, &MacLen, au8GuestMac, &MacSlot, 0 /* Mac-Prefix Length */, &Diag);
1190 if (RT_UNLIKELY(rc))
1191 LogRel((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress failed! rc=%d Diag=%d\n", rc, Diag));
1192}
1193
1194
1195int vboxNetFltPortOsConnectInterface(PVBOXNETFLTINS pThis, void *pvIf, void **ppvIfData)
1196{
1197 LogFlow((DEVICE_NAME ":vboxNetFltPortOsConnectInterface pThis=%p pvIf=%p\n", pThis, pvIf));
1198
1199 int rc = VINF_SUCCESS;
1200
1201 /*
1202 * If the underlying interface is not a VNIC, we need to create
1203 * a VNIC per guest NIC.
1204 */
1205 if (!pThis->u.s.fIsVNIC)
1206 {
1207 PVBOXNETFLTVNIC pVNIC = NULL;
1208 rc = vboxNetFltSolarisCreateVNIC(pThis, &pVNIC);
1209 if (RT_SUCCESS(rc))
1210 {
1211 /*
1212 * VM Interface<->VNIC association so that we can Xmit/Recv on the right ones.
1213 */
1214 pVNIC->pvIf = pvIf;
1215 *ppvIfData = pVNIC;
1216
1217 /*
1218 * Add the created VNIC to the list of VNICs we manage.
1219 */
1220 list_insert_tail(&pThis->u.s.hVNICs, pVNIC);
1221 LogFlow((DEVICE_NAME ":vboxNetFltPortOsConnectInterface successfully created VNIC '%s'.\n", pVNIC->szName));
1222 return VINF_SUCCESS;
1223 }
1224 else
1225 LogRel((DEVICE_NAME ":vboxNetFltPortOsConnectInterface failed to create VNIC rc=%d\n", rc));
1226 }
1227 else
1228 {
1229 PVBOXNETFLTVNIC pVNIC = list_head(&pThis->u.s.hVNICs);
1230 if (RT_LIKELY(pVNIC))
1231 {
1232 *ppvIfData = pVNIC;
1233 LogFlow((DEVICE_NAME ":vboxNetFltPortOsConnectInterface set VNIC '%s' private data\n", pVNIC->szName));
1234 }
1235 else
1236 {
1237 LogRel((DEVICE_NAME ":vboxNetFltPortOsConnectInterface huh!? Missing VNIC!\n"));
1238 return VERR_GENERAL_FAILURE;
1239 }
1240 }
1241
1242 return rc;
1243}
1244
1245
1246int vboxNetFltPortOsDisconnectInterface(PVBOXNETFLTINS pThis, void *pvIfData)
1247{
1248 LogFlow((DEVICE_NAME ":vboxNetFltPortOsDisconnectInterface pThis=%p\n", pThis));
1249
1250 PVBOXNETFLTVNIC pVNIC = pvIfData;
1251 AssertMsgReturn(VALID_PTR(pVNIC) && pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC,
1252 ("Invalid pvIfData=%p magic=%#x (expected %#x)\n", pvIfData, pVNIC ? pVNIC->u32Magic : 0, VBOXNETFLTVNIC_MAGIC),
1253 VERR_INVALID_POINTER);
1254
1255 /*
1256 * If the underlying interface is not a VNIC, we need to delete the created VNIC.
1257 */
1258 if (!pThis->u.s.fIsVNIC)
1259 {
1260 /*
1261 * Remove the VNIC from the list, destroy and free it.
1262 */
1263 list_remove(&pThis->u.s.hVNICs, pVNIC);
1264 LogFlow((DEVICE_NAME ":vboxNetFltPortOsDisconnectInterface destroying pVNIC=%p\n", pVNIC));
1265 vboxNetFltSolarisDestroyVNIC(pVNIC);
1266 vboxNetFltSolarisFreeVNIC(pVNIC);
1267 }
1268
1269 return VINF_SUCCESS;
1270}
1271
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