VirtualBox

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

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

Solaris/VBoxNetFltBow: dynamic VNIC creation and management.

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