VirtualBox

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

Last change on this file since 57718 was 57358, checked in by vboxsync, 10 years ago

*: scm cleanup run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 57.3 KB
Line 
1/* $Id: VBoxNetFltBow-solaris.c 57358 2015-08-14 15:16:38Z vboxsync $ */
2/** @file
3 * VBoxNetFlt - Network Filter Driver (Host), Solaris Specific Code.
4 */
5
6/*
7 * Copyright (C) 2008-2015 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
32#include <VBox/log.h>
33#include <VBox/err.h>
34#include <VBox/intnetinline.h>
35#include <VBox/version.h>
36#include <iprt/initterm.h>
37#include <iprt/alloca.h>
38#include <iprt/assert.h>
39#include <iprt/err.h>
40#include <iprt/string.h>
41#include <iprt/rand.h>
42#include <iprt/net.h>
43#include <iprt/spinlock.h>
44#include <iprt/mem.h>
45
46#include <sys/types.h>
47#include <sys/modctl.h>
48#include <sys/conf.h>
49#include <sys/stat.h>
50#include <sys/ddi.h>
51#include <sys/gld.h>
52#include <sys/sunddi.h>
53#include <sys/strsubr.h>
54#include <sys/dlpi.h>
55#include <sys/dls_mgmt.h>
56#include <sys/mac.h>
57#include <sys/strsun.h>
58
59#include <sys/vnic_mgmt.h>
60#include <sys/mac_client.h>
61#include <sys/mac_provider.h>
62#include <sys/dls.h>
63#include <sys/dld.h>
64#include <sys/cred.h>
65
66
67#define VBOXNETFLT_OS_SPECFIC 1
68#include "../VBoxNetFltInternal.h"
69
70
71/*********************************************************************************************************************************
72* Defined Constants And Macros *
73*********************************************************************************************************************************/
74/** The module name. */
75#define DEVICE_NAME "vboxbow"
76/** The module descriptions as seen in 'modinfo'. */
77#define DEVICE_DESC_DRV "VirtualBox NetBow"
78/** The dynamically created VNIC name (hardcoded in NetIf-solaris.cpp).
79 * @todo move this define into a common header. */
80#define VBOXBOW_VNIC_NAME "vboxvnic"
81/** The VirtualBox VNIC template name (hardcoded in NetIf-solaris.cpp).
82 * @todo move this define into a common header. */
83#define VBOXBOW_VNIC_TEMPLATE_NAME "vboxvnic_template"
84/** Debugging switch for using symbols in kmdb */
85# define LOCAL static
86/** VBOXNETFLTVNIC::u32Magic */
87# define VBOXNETFLTVNIC_MAGIC 0x0ddfaced
88
89/** VLAN tag masking, should probably be in IPRT? */
90#define VLAN_ID(vlan) (((vlan) >> 0) & 0x0fffu)
91#define VLAN_CFI(vlan) (((vlan) >> 12) & 0x0001u)
92#define VLAN_PRI(vlan) (((vlan) >> 13) & 0x0007u)
93#define VLAN_TAG(pri,cfi,vid) (((pri) << 13) | ((cfi) << 12) | ((vid) << 0))
94
95typedef struct VLANHEADER
96{
97 uint16_t Type;
98 uint16_t Data;
99} VLANHEADER;
100typedef struct VLANHEADER *PVLANHEADER;
101
102/* Private: from sys/vlan.h */
103#ifndef VLAN_ID_NONE
104# define VLAN_ID_NONE 0
105#endif
106
107/* Private: from sys/param.h */
108#ifndef MAXLINKNAMESPECIFIER
109# define MAXLINKNAMESPECIFIER 96 /* MAXLINKNAMELEN + ZONENAME_MAX */
110#endif
111
112/* Private: from sys/mac_client_priv.h, mac client function prototypes. */
113extern uint16_t mac_client_vid(mac_client_handle_t hClient);
114extern void mac_client_get_resources(mac_client_handle_t hClient, mac_resource_props_t *pResources);
115extern int mac_client_set_resources(mac_client_handle_t hClient, mac_resource_props_t *pResources);
116
117
118/*********************************************************************************************************************************
119* Kernel Entry Hooks *
120*********************************************************************************************************************************/
121LOCAL int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd);
122LOCAL int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd);
123LOCAL int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pArg, void **ppResult);
124
125
126/*********************************************************************************************************************************
127* Structures and Typedefs *
128*********************************************************************************************************************************/
129/**
130 * cb_ops: for drivers that support char/block entry points
131 */
132static struct cb_ops g_VBoxNetFltSolarisCbOps =
133{
134 nulldev, /* c open */
135 nulldev, /* c close */
136 nodev, /* b strategy */
137 nodev, /* b dump */
138 nodev, /* b print */
139 nodev, /* c read */
140 nodev, /* c write*/
141 nodev, /* c ioctl*/
142 nodev, /* c devmap */
143 nodev, /* c mmap */
144 nodev, /* c segmap */
145 nochpoll, /* c poll */
146 ddi_prop_op, /* property ops */
147 NULL, /* streamtab */
148 D_NEW | D_MP, /* compat. flag */
149 CB_REV, /* revision */
150 nodev, /* c aread */
151 nodev /* c awrite */
152};
153
154/**
155 * dev_ops: for driver device operations
156 */
157static struct dev_ops g_VBoxNetFltSolarisDevOps =
158{
159 DEVO_REV, /* driver build revision */
160 0, /* ref count */
161 VBoxNetFltSolarisGetInfo,
162 nulldev, /* identify */
163 nulldev, /* probe */
164 VBoxNetFltSolarisAttach,
165 VBoxNetFltSolarisDetach,
166 nodev, /* reset */
167 &g_VBoxNetFltSolarisCbOps,
168 NULL, /* bus ops */
169 nodev, /* power */
170 ddi_quiesce_not_needed
171};
172
173/**
174 * modldrv: export driver specifics to the kernel
175 */
176static struct modldrv g_VBoxNetFltSolarisModule =
177{
178 &mod_driverops, /* extern from kernel */
179 DEVICE_DESC_DRV " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV),
180 &g_VBoxNetFltSolarisDevOps
181};
182
183/**
184 * modlinkage: export install/remove/info to the kernel
185 */
186static struct modlinkage g_VBoxNetFltSolarisModLinkage =
187{
188 MODREV_1,
189 {
190 &g_VBoxNetFltSolarisModule,
191 NULL,
192 }
193};
194
195/*
196 * VBOXNETFLTVNICTEMPLATE: VNIC template information.
197 */
198typedef struct VBOXNETFLTVNICTEMPLATE
199{
200 /** The name of link on which the VNIC template is created on. */
201 char szLinkName[MAXNAMELEN];
202 /** The VLAN Id (can be VLAN_ID_NONE). */
203 uint16_t uVLANId;
204 /** Resources (bandwidth, CPU bindings, flow priority etc.) */
205 mac_resource_props_t Resources;
206} VBOXNETFLTVNICTEMPLATE;
207typedef struct VBOXNETFLTVNICTEMPLATE *PVBOXNETFLTVNICTEMPLATE;
208
209/**
210 * VBOXNETFLTVNIC: Per-VNIC instance data.
211 */
212typedef struct VBOXNETFLTVNIC
213{
214 /** Magic number (VBOXNETFLTVNIC_MAGIC). */
215 uint32_t u32Magic;
216 /** Whether we created the VNIC or not. */
217 bool fCreated;
218 /** Pointer to the VNIC template if any. */
219 PVBOXNETFLTVNICTEMPLATE pVNICTemplate;
220 /** Pointer to the VirtualBox interface instance. */
221 void *pvIf;
222 /** The MAC handle. */
223 mac_handle_t hInterface;
224 /** The VNIC link ID. */
225 datalink_id_t hLinkId;
226 /** The MAC client handle */
227 mac_client_handle_t hClient;
228 /** The unicast address handle. */
229 mac_unicast_handle_t hUnicast;
230 /** The promiscuous handle. */
231 mac_promisc_handle_t hPromisc;
232 /* The VNIC name. */
233 char szName[MAXLINKNAMESPECIFIER];
234 /** Handle to the next VNIC in the list. */
235 list_node_t hNode;
236} VBOXNETFLTVNIC;
237typedef struct VBOXNETFLTVNIC *PVBOXNETFLTVNIC;
238
239
240/*********************************************************************************************************************************
241* Global Variables *
242*********************************************************************************************************************************/
243/** Global Device handle we only support one instance. */
244static dev_info_t *g_pVBoxNetFltSolarisDip = NULL;
245/** The (common) global data. */
246static VBOXNETFLTGLOBALS g_VBoxNetFltSolarisGlobals;
247/** Global next-free VNIC Id (never decrements). */
248static volatile uint64_t g_VBoxNetFltSolarisVNICId;
249
250
251/*********************************************************************************************************************************
252* Internal Functions *
253*********************************************************************************************************************************/
254LOCAL mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst);
255LOCAL unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg);
256LOCAL int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc);
257LOCAL void vboxNetFltSolarisRecv(void *pvData, mac_resource_handle_t hResource, mblk_t *pMsg, boolean_t fLoopback);
258//LOCAL void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg);
259LOCAL int vboxNetFltSolarisReportInfo(PVBOXNETFLTINS pThis, mac_handle_t hInterface, bool fIsVNIC);
260LOCAL int vboxNetFltSolarisInitVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC pVNIC);
261LOCAL int vboxNetFltSolarisInitVNICTemplate(PVBOXNETFLTINS pThis, PVBOXNETFLTVNICTEMPLATE pVNICTemplate);
262LOCAL PVBOXNETFLTVNIC vboxNetFltSolarisAllocVNIC(void);
263LOCAL void vboxNetFltSolarisFreeVNIC(PVBOXNETFLTVNIC pVNIC);
264LOCAL void vboxNetFltSolarisDestroyVNIC(PVBOXNETFLTVNIC pVNIC);
265LOCAL int vboxNetFltSolarisCreateVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC *ppVNIC);
266LOCAL inline int vboxNetFltSolarisGetLinkId(const char *pszMacName, datalink_id_t *pLinkId);
267
268/**
269 * Kernel entry points
270 */
271int _init(void)
272{
273 Log((DEVICE_NAME ":_init\n"));
274
275 /*
276 * Prevent module autounloading.
277 */
278 modctl_t *pModCtl = mod_getctl(&g_VBoxNetFltSolarisModLinkage);
279 if (pModCtl)
280 pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
281 else
282 cmn_err(CE_NOTE, ":failed to disable autounloading!\n");
283
284 /*
285 * Initialize IPRT.
286 */
287 int rc = RTR0Init(0);
288 if (RT_SUCCESS(rc))
289 {
290 /*
291 * Initialize the globals and connect to the support driver.
292 *
293 * This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
294 * for establishing the connect to the support driver.
295 */
296 memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals));
297 rc = vboxNetFltInitGlobalsAndIdc(&g_VBoxNetFltSolarisGlobals);
298 if (RT_SUCCESS(rc))
299 {
300 rc = mod_install(&g_VBoxNetFltSolarisModLinkage);
301 if (!rc)
302 return rc;
303
304 LogRel((DEVICE_NAME ":mod_install failed. rc=%d\n", rc));
305 vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals);
306 }
307 else
308 LogRel((DEVICE_NAME ":failed to initialize globals.\n"));
309
310 RTR0Term();
311 }
312 else
313 cmn_err(CE_NOTE, "failed to initialize IPRT (rc=%d)\n", rc);
314
315 memset(&g_VBoxNetFltSolarisGlobals, 0, sizeof(g_VBoxNetFltSolarisGlobals));
316 return RTErrConvertToErrno(rc);
317}
318
319
320int _fini(void)
321{
322 int rc;
323 Log((DEVICE_NAME ":_fini\n"));
324
325 /*
326 * Undo the work done during start (in reverse order).
327 */
328 rc = vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltSolarisGlobals);
329 if (RT_FAILURE(rc))
330 {
331 LogRel((DEVICE_NAME ":_fini - busy!\n"));
332 return EBUSY;
333 }
334
335 rc = mod_remove(&g_VBoxNetFltSolarisModLinkage);
336 if (!rc)
337 RTR0Term();
338
339 return rc;
340}
341
342
343int _info(struct modinfo *pModInfo)
344{
345 /* _info() can be called before _init() so RTR0Init() might not be called at this point. */
346 int rc = mod_info(&g_VBoxNetFltSolarisModLinkage, pModInfo);
347 return rc;
348}
349
350
351/**
352 * Attach entry point, to attach a device to the system or resume it.
353 *
354 * @param pDip The module structure instance.
355 * @param enmCmd Operation type (attach/resume).
356 *
357 * @returns corresponding solaris error code.
358 */
359LOCAL int VBoxNetFltSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
360{
361 Log((DEVICE_NAME ":VBoxNetFltSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd));
362
363 switch (enmCmd)
364 {
365 case DDI_ATTACH:
366 {
367 g_pVBoxNetFltSolarisDip = pDip;
368 return DDI_SUCCESS;
369 }
370
371 case DDI_RESUME:
372 {
373 /* Nothing to do here... */
374 return DDI_SUCCESS;
375 }
376
377 /* case DDI_PM_RESUME: */
378 default:
379 return DDI_FAILURE;
380 }
381}
382
383
384/**
385 * Detach entry point, to detach a device to the system or suspend it.
386 *
387 * @param pDip The module structure instance.
388 * @param enmCmd Operation type (detach/suspend).
389 *
390 * @returns corresponding solaris error code.
391 */
392LOCAL int VBoxNetFltSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
393{
394 Log((DEVICE_NAME ":VBoxNetFltSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd));
395
396 switch (enmCmd)
397 {
398 case DDI_DETACH:
399 {
400 return DDI_SUCCESS;
401 }
402
403 case DDI_RESUME:
404 {
405 /* Nothing to do here... */
406 return DDI_SUCCESS;
407 }
408
409 /* case DDI_PM_SUSPEND: */
410 /* case DDI_HOT_PLUG_DETACH: */
411 default:
412 return DDI_FAILURE;
413 }
414}
415
416
417/**
418 * Info entry point, called by solaris kernel for obtaining driver info.
419 *
420 * @param pDip The module structure instance (do not use).
421 * @param enmCmd Information request type.
422 * @param pvArg Type specific argument.
423 * @param ppvResult Where to store the requested info.
424 *
425 * @returns corresponding solaris error code.
426 */
427LOCAL int VBoxNetFltSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg, void **ppResult)
428{
429 Log((DEVICE_NAME ":VBoxNetFltSolarisGetInfo pDip=%p enmCmd=%d pArg=%p instance=%d\n", pDip, enmCmd, getminor((dev_t)pvArg)));
430
431 switch (enmCmd)
432 {
433 case DDI_INFO_DEVT2DEVINFO:
434 {
435 *ppResult = g_pVBoxNetFltSolarisDip;
436 return DDI_SUCCESS;
437 }
438
439 case DDI_INFO_DEVT2INSTANCE:
440 {
441 int instance = getminor((dev_t)pvArg);
442 *ppResult = (void *)(uintptr_t)instance;
443 return DDI_SUCCESS;
444 }
445 }
446
447 return DDI_FAILURE;
448}
449
450
451/**
452 * Create a solaris message block from the SG list.
453 *
454 * @param pThis The instance.
455 * @param pSG Pointer to the scatter-gather list.
456 *
457 * @returns Solaris message block.
458 */
459LOCAL inline mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst)
460{
461 Log((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG pThis=%p pSG=%p\n", pThis, pSG));
462
463 mblk_t *pMsg = allocb(pSG->cbTotal, BPRI_HI);
464 if (RT_UNLIKELY(!pMsg))
465 {
466 LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkFromSG failed to alloc %d bytes for mblk_t.\n", pSG->cbTotal));
467 return NULL;
468 }
469
470 /*
471 * Single buffer copy. Maybe later explore the
472 * need/possibility for using a mblk_t chain rather.
473 */
474 for (unsigned i = 0; i < pSG->cSegsUsed; i++)
475 {
476 if (pSG->aSegs[i].pv)
477 {
478 bcopy(pSG->aSegs[i].pv, pMsg->b_wptr, pSG->aSegs[i].cb);
479 pMsg->b_wptr += pSG->aSegs[i].cb;
480 }
481 }
482 return pMsg;
483}
484
485
486/**
487 * Calculate the number of segments required for this message block.
488 *
489 * @param pThis The instance
490 * @param pMsg Pointer to the data message.
491 *
492 * @returns Number of segments.
493 */
494LOCAL unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg)
495{
496 unsigned cSegs = 0;
497 for (mblk_t *pCur = pMsg; pCur; pCur = pCur->b_cont)
498 if (MBLKL(pCur))
499 cSegs++;
500
501#ifdef PADD_RUNT_FRAMES_FROM_HOST
502 if (msgdsize(pMsg) < 60)
503 cSegs++;
504#endif
505
506 NOREF(pThis);
507 return RT_MAX(cSegs, 1);
508}
509
510
511/**
512 * Initializes an SG list from the given message block.
513 *
514 * @param pThis The instance.
515 * @param pMsg Pointer to the data message.
516 The caller must ensure it's not a control message block.
517 * @param pSG Pointer to the SG.
518 * @param cSegs Number of segments in the SG.
519 * This should match the number in the message block exactly!
520 * @param fSrc The source of the message.
521 *
522 * @returns VBox status code.
523 */
524LOCAL int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc)
525{
526 Log((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pThis=%p pMsg=%p pSG=%p cSegs=%d\n", pThis, pMsg, pSG, cSegs));
527
528 /*
529 * Convert the message block to segments. Works cbTotal and sets cSegsUsed.
530 */
531 IntNetSgInitTempSegs(pSG, 0 /*cbTotal*/, cSegs, 0 /*cSegsUsed*/);
532 mblk_t *pCur = pMsg;
533 unsigned iSeg = 0;
534 while (pCur)
535 {
536 size_t cbSeg = MBLKL(pCur);
537 if (cbSeg)
538 {
539 void *pvSeg = pCur->b_rptr;
540 pSG->aSegs[iSeg].pv = pvSeg;
541 pSG->aSegs[iSeg].cb = cbSeg;
542 pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
543 pSG->cbTotal += cbSeg;
544 iSeg++;
545 }
546 pCur = pCur->b_cont;
547 }
548 pSG->cSegsUsed = iSeg;
549
550#ifdef PADD_RUNT_FRAMES_FROM_HOST
551 if (pSG->cbTotal < 60 && (fSrc & INTNETTRUNKDIR_HOST))
552 {
553 Log((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG pulling up to length.\n"));
554
555 static uint8_t const s_abZero[128] = {0};
556 pSG->aSegs[iSeg].Phys = NIL_RTHCPHYS;
557 pSG->aSegs[iSeg].pv = (void *)&s_abZero[0];
558 pSG->aSegs[iSeg].cb = 60 - pSG->cbTotal;
559 pSG->cbTotal = 60;
560 pSG->cSegsUsed++;
561 Assert(iSeg + 1 < cSegs);
562 }
563#endif
564
565 Log((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG iSeg=%d pSG->cbTotal=%d msgdsize=%d\n", iSeg, pSG->cbTotal, msgdsize(pMsg)));
566 return VINF_SUCCESS;
567}
568
569
570#if 0
571/**
572 * Simple packet dump, used for internal debugging.
573 *
574 * @param pMsg Pointer to the message to analyze and dump.
575 */
576LOCAL void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg)
577{
578 LogFunc((DEVICE_NAME ":vboxNetFltSolarisAnalyzeMBlk pMsg=%p\n", pMsg));
579
580 PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pMsg->b_rptr;
581 uint8_t *pb = pMsg->b_rptr;
582 if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
583 {
584 PRTNETIPV4 pIpHdr = (PRTNETIPV4)(pEthHdr + 1);
585 if (!pMsg->b_cont)
586 {
587 if (pIpHdr->ip_p == RTNETIPV4_PROT_ICMP)
588 LogRel((DEVICE_NAME ":ICMP D=%.6Rhxs S=%.6Rhxs T=%04x\n", pb, pb + 6, RT_BE2H_U16(*(uint16_t *)(pb + 12))));
589 else if (pIpHdr->ip_p == RTNETIPV4_PROT_TCP)
590 LogRel((DEVICE_NAME ":TCP D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6));
591 else if (pIpHdr->ip_p == RTNETIPV4_PROT_UDP)
592 {
593 PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint32_t *)pIpHdr + pIpHdr->ip_hl);
594 if ( RT_BE2H_U16(pUdpHdr->uh_sport) == 67
595 && RT_BE2H_U16(pUdpHdr->uh_dport) == 68)
596 {
597 LogRel((DEVICE_NAME ":UDP bootp ack D=%.6Rhxs S=%.6Rhxs UDP_CheckSum=%04x Computex=%04x\n", pb, pb + 6,
598 RT_BE2H_U16(pUdpHdr->uh_sum), RT_BE2H_U16(RTNetIPv4UDPChecksum(pIpHdr, pUdpHdr, pUdpHdr + 1))));
599 }
600 }
601 }
602 else
603 {
604 Log((DEVICE_NAME ":Chained IP packet. Skipping validity check.\n"));
605 }
606 }
607 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_VLAN))
608 {
609 PVLANHEADER pVlanHdr = (PVLANHEADER)(pMsg->b_rptr + sizeof(RTNETETHERHDR) - sizeof(pEthHdr->EtherType));
610 LogRel((DEVICE_NAME ":VLAN Pcp=%u Cfi=%u Id=%u\n", VLAN_PRI(RT_BE2H_U16(pVlanHdr->Data)),
611 VLAN_CFI(RT_BE2H_U16(pVlanHdr->Data)), VLAN_ID(RT_BE2H_U16(pVlanHdr->Data))));
612 LogRel((DEVICE_NAME "%.*Rhxd\n", sizeof(VLANHEADER), pVlanHdr));
613 }
614 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP))
615 {
616 PRTNETARPHDR pArpHdr = (PRTNETARPHDR)(pEthHdr + 1);
617 LogRel((DEVICE_NAME ":ARP Op=%d\n", pArpHdr->ar_oper));
618 }
619 else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
620 {
621 LogRel((DEVICE_NAME ":IPv6 D=%.6Rhxs S=%.6Rhxs\n", pb, pb + 6));
622 }
623 else if ( pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_1)
624 || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_2)
625 || pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPX_3))
626 {
627 LogRel((DEVICE_NAME ":IPX packet.\n"));
628 }
629 else
630 {
631 LogRel((DEVICE_NAME ":Unknown EtherType=%x D=%.6Rhxs S=%.6Rhxs\n", RT_H2BE_U16(pEthHdr->EtherType), &pEthHdr->DstMac,
632 &pEthHdr->SrcMac));
633 /* Log((DEVICE_NAME ":%.*Rhxd\n", MBLKL(pMsg), pMsg->b_rptr)); */
634 }
635}
636#endif
637
638
639/**
640 * Helper.
641 */
642DECLINLINE(bool) vboxNetFltPortSolarisIsHostMac(PVBOXNETFLTINS pThis, PCRTMAC pMac)
643{
644 return pThis->u.s.MacAddr.au16[0] == pMac->au16[0]
645 && pThis->u.s.MacAddr.au16[1] == pMac->au16[1]
646 && pThis->u.s.MacAddr.au16[2] == pMac->au16[2];
647}
648
649
650/**
651 * Receive (rx) entry point.
652 *
653 * @param pvData Private data.
654 * @param hResource The resource handle.
655 * @param pMsg The packet.
656 * @param fLoopback Whether this is a loopback packet or not.
657 */
658LOCAL void vboxNetFltSolarisRecv(void *pvData, mac_resource_handle_t hResource, mblk_t *pMsg, boolean_t fLoopback)
659{
660 Log((DEVICE_NAME ":vboxNetFltSolarisRecv pvData=%p pMsg=%p fLoopback=%d cbData=%d\n", pvData, pMsg, fLoopback,
661 pMsg ? MBLKL(pMsg) : 0));
662
663 PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvData;
664 AssertPtrReturnVoid(pThis);
665 AssertPtrReturnVoid(pMsg);
666
667 /*
668 * Active? Retain the instance and increment the busy counter.
669 */
670 if (!vboxNetFltTryRetainBusyActive(pThis))
671 {
672 freemsgchain(pMsg);
673 return;
674 }
675
676 uint32_t fSrc = INTNETTRUNKDIR_WIRE;
677 PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pMsg->b_rptr;
678 if ( MBLKL(pMsg) >= sizeof(RTNETETHERHDR)
679 && vboxNetFltPortSolarisIsHostMac(pThis, &pEthHdr->SrcMac))
680 fSrc = INTNETTRUNKDIR_HOST;
681
682 /*
683 * Route all received packets into the internal network.
684 */
685 uint16_t cFailed = 0;
686 for (mblk_t *pCurMsg = pMsg; pCurMsg != NULL; pCurMsg = pCurMsg->b_next)
687 {
688 unsigned cSegs = vboxNetFltSolarisMBlkCalcSGSegs(pThis, pCurMsg);
689 PINTNETSG pSG = (PINTNETSG)alloca(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
690 int rc = vboxNetFltSolarisMBlkToSG(pThis, pMsg, pSG, cSegs, fSrc);
691 if (RT_SUCCESS(rc))
692 pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, NULL, pSG, fSrc);
693 else
694 cFailed++;
695 }
696 vboxNetFltRelease(pThis, true /* fBusy */);
697
698 if (RT_UNLIKELY(cFailed))
699 LogRel((DEVICE_NAME ":vboxNetFltSolarisMBlkToSG failed for %u packets.\n", cFailed));
700
701 freemsgchain(pMsg);
702
703 NOREF(hResource);
704}
705
706
707#if 0
708/**
709 * MAC layer link notification hook.
710 *
711 * @param pvArg Opaque pointer to the instance.
712 * @param Type Notification Type.
713 *
714 * @remarks This hook will be invoked for various changes to the underlying
715 * interface even when VMs aren't running so don't do any funky stuff
716 * here.
717 */
718LOCAL void vboxNetFltSolarisLinkNotify(void *pvArg, mac_notify_type_t Type)
719{
720 LogRel((DEVICE_NAME ":vboxNetFltSolarisLinkNotify pvArg=%p Type=%d\n", pvArg, Type));
721
722 PVBOXNETFLTINS pThis = pvArg;
723 AssertReturnVoid(VALID_PTR(pThis));
724 AssertReturnVoid(pThis->u.s.hInterface);
725
726 switch (Type)
727 {
728 case MAC_NOTE_LINK:
729 {
730 LogRel((DEVICE_NAME ":vboxNetFltSolarisLinkNotify link state change\n"));
731 link_state_t hLinkState = mac_stat_get(pThis->u.s.hInterface, MAC_STAT_LINK_STATE);
732 bool fDisconnectedFromHost = hLinkState == LINK_STATE_UP ? false : true;
733 if (fDisconnectedFromHost != ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost))
734 {
735 ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, fDisconnectedFromHost);
736 LogRel((DEVICE_NAME ":vboxNetFltSolarisLinkNotify link state change: new state=%s\n",
737 fDisconnectedFromHost ? "DOWN" : "UP"));
738 }
739 break;
740 }
741
742 default:
743 return;
744 }
745}
746#endif
747
748
749/**
750 * Report capabilities and MAC address to IntNet after obtaining the MAC address
751 * of the underlying interface for a VNIC or the current interface if it's a
752 * physical/ether-stub interface.
753 *
754 * @param pThis The instance.
755 * @param hInterface The Interface handle.
756 * @param fIsVNIC Whether this interface handle corresponds to a VNIC
757 * or not.
758 *
759 * @remarks Retains the instance while doing it's job.
760 * @returns VBox status code.
761 */
762LOCAL int vboxNetFltSolarisReportInfo(PVBOXNETFLTINS pThis, mac_handle_t hInterface, bool fIsVNIC)
763{
764 mac_handle_t hLowerMac = NULL;
765 if (!fIsVNIC)
766 hLowerMac = hInterface;
767 else
768 {
769 hLowerMac = mac_get_lower_mac_handle(hInterface);
770 if (RT_UNLIKELY(!hLowerMac))
771 {
772 LogRel((DEVICE_NAME ":vboxNetFltSolarisReportInfo failed to get lower MAC handle for '%s'\n", pThis->szName));
773 return VERR_INVALID_HANDLE;
774 }
775 }
776
777 pThis->u.s.hInterface = hLowerMac;
778
779#if 0
780 /*
781 * Try setup link notification hooks, this might fail if mac_no_notification()
782 * doesn't support it. We won't bother using the private function since link notification
783 * isn't critical for us and ignore failures.
784 */
785 pThis->u.s.hNotify = mac_notify_add(hLowerMac, vboxNetFltSolarisLinkNotify, pThis);
786 if (!pThis->u.s.hNotify)
787 LogRel((DEVICE_NAME ":vboxNetFltSolarisReportInfo Warning! Failed to setup link notification hook.\n"));
788#endif
789
790 mac_unicast_primary_get(hLowerMac, (uint8_t *)pThis->u.s.MacAddr.au8);
791 if (vboxNetFltTryRetainBusyNotDisconnected(pThis))
792 {
793 Assert(pThis->pSwitchPort);
794 Log((DEVICE_NAME ":vboxNetFltSolarisReportInfo phys mac %.6Rhxs\n", &pThis->u.s.MacAddr));
795 pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr);
796 pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, false); /** @todo Promisc */
797 pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST);
798 pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */);
799 vboxNetFltRelease(pThis, true /*fBusy*/);
800 return VINF_SUCCESS;
801 }
802 else
803 LogRel((DEVICE_NAME ":vboxNetFltSolarisReportInfo failed to retain interface. pThis=%p\n", pThis));
804
805 return VERR_INTNET_FLT_IF_BUSY;
806}
807
808
809/**
810 * Initialize a VNIC, optionally from a template.
811 *
812 * @param pThis The instance.
813 * @param pVNIC Pointer to the VNIC.
814 * @param pVNICTemplate Pointer to the VNIC template initialize from, can be
815 * NULL.
816 *
817 * @returns VBox status code.
818 */
819LOCAL int vboxNetFltSolarisInitVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC pVNIC)
820{
821 /*
822 * Some paranoia.
823 */
824 AssertReturn(pThis, VERR_INVALID_PARAMETER);
825 AssertReturn(pVNIC, VERR_INVALID_PARAMETER);
826 AssertReturn(pVNIC->hInterface, VERR_INVALID_POINTER);
827 AssertReturn(pVNIC->hLinkId != DATALINK_INVALID_LINKID, VERR_INVALID_HANDLE);
828 AssertReturn(!pVNIC->hClient, VERR_INVALID_POINTER);
829
830 int rc = mac_client_open(pVNIC->hInterface, &pVNIC->hClient,
831 NULL, /* name of this client */
832 MAC_OPEN_FLAGS_USE_DATALINK_NAME | /* client name same as underlying NIC */
833 MAC_OPEN_FLAGS_MULTI_PRIMARY /* allow multiple primary unicasts */
834 );
835 if (RT_LIKELY(!rc))
836 {
837 if (pVNIC->pVNICTemplate)
838 rc = mac_client_set_resources(pVNIC->hClient, &pVNIC->pVNICTemplate->Resources);
839
840 if (RT_LIKELY(!rc))
841 {
842 Log((DEVICE_NAME ":vboxNetFltSolarisInitVNIC succesfully initialized VNIC.\n"));
843 return VINF_SUCCESS;
844 }
845 else
846 {
847 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNIC mac_client_set_resources failed. rc=%d\n", rc));
848 rc = VERR_INTNET_FLT_VNIC_INIT_FAILED;
849 }
850
851 mac_client_close(pVNIC->hClient, 0 /* flags */);
852 pVNIC->hClient = NULL;
853 }
854 else
855 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNIC failed to open mac client for '%s' rc=%d\n", pThis->szName, rc));
856
857 return VERR_INTNET_FLT_VNIC_OPEN_FAILED;
858}
859
860
861
862/**
863 * Get the underlying link name for a VNIC (template).
864 *
865 * @return VBox status code.
866 * @param hVNICMacHandle The handle to the VNIC.
867 * @param pszLowerLinkName Where to store the lower-mac linkname, must be
868 * at least MAXLINKNAMELEN in size.
869 */
870LOCAL int vboxNetFltSolarisGetLowerLinkName(mac_handle_t hVNICMacHandle, char *pszLowerLinkName)
871{
872 Assert(mac_is_vnic(hVNICMacHandle));
873 mac_handle_t hPhysLinkHandle = mac_get_lower_mac_handle(hVNICMacHandle);
874 if (RT_LIKELY(hPhysLinkHandle))
875 {
876 datalink_id_t PhysLinkId;
877 const char *pszMacName = mac_name(hPhysLinkHandle);
878 int rc = vboxNetFltSolarisGetLinkId(pszMacName, &PhysLinkId);
879 if (RT_SUCCESS(rc))
880 {
881 rc = dls_mgmt_get_linkinfo(PhysLinkId, pszLowerLinkName, NULL /*class*/, NULL /*media*/, NULL /*flags*/);
882 if (RT_LIKELY(!rc))
883 return VINF_SUCCESS;
884
885 LogRel((DEVICE_NAME ":vboxNetFltSolarisGetLowerLinkName failed to get link info. pszMacName=%s pszLowerLinkName=%s\n",
886 pszMacName, pszLowerLinkName));
887 return VERR_INTNET_FLT_LOWER_LINK_INFO_NOT_FOUND;
888 }
889
890 LogRel((DEVICE_NAME ":vboxNetFltSolarisGetLowerLinkName failed to get link id. pszMacName=%s pszLowerLinkName=%s\n",
891 pszMacName, pszLowerLinkName));
892 return VERR_INTNET_FLT_LOWER_LINK_ID_NOT_FOUND;
893 }
894
895 LogRel((DEVICE_NAME ":vboxNetFltSolarisGetLowerLinkName failed to get lower-mac. pszLowerLinkName=%s\n", pszLowerLinkName));
896 return VERR_INTNET_FLT_LOWER_LINK_OPEN_FAILED;
897}
898
899
900/**
901 * Initializes the VNIC template. This involves opening the template VNIC to
902 * retreive info. like the VLAN Id, underlying MAC address etc.
903 *
904 * @param pThis The VM connection instance.
905 * @param pVNICTemplate Pointer to a VNIC template to initialize.
906 *
907 * @returns VBox status code.
908 */
909LOCAL int vboxNetFltSolarisInitVNICTemplate(PVBOXNETFLTINS pThis, PVBOXNETFLTVNICTEMPLATE pVNICTemplate)
910{
911 Log((DEVICE_NAME ":vboxNetFltSolarisInitVNICTemplate pThis=%p pVNICTemplate=%p\n", pThis, pVNICTemplate));
912
913 AssertReturn(pVNICTemplate, VERR_INVALID_PARAMETER);
914 AssertReturn(pThis->u.s.fIsVNICTemplate == true, VERR_INVALID_STATE);
915
916 /*
917 * Get the VNIC template's datalink ID.
918 */
919 datalink_id_t VNICLinkId;
920 int rc = vboxNetFltSolarisGetLinkId(pThis->szName, &VNICLinkId);
921 if (RT_SUCCESS(rc))
922 {
923 /*
924 * Open the VNIC to obtain a MAC handle so as to retreive the VLAN ID.
925 */
926 mac_handle_t hInterface;
927 rc = mac_open_by_linkid(VNICLinkId, &hInterface);
928 if (!rc)
929 {
930 /*
931 * Get the underlying linkname.
932 */
933 AssertCompile(sizeof(pVNICTemplate->szLinkName) >= MAXLINKNAMELEN);
934 rc = vboxNetFltSolarisGetLowerLinkName(hInterface, pVNICTemplate->szLinkName);
935 if (RT_SUCCESS(rc))
936 {
937 /*
938 * Now open the VNIC template to retrieve the VLAN Id & resources.
939 */
940 mac_client_handle_t hClient;
941 rc = mac_client_open(hInterface, &hClient,
942 NULL, /* name of this client */
943 MAC_OPEN_FLAGS_USE_DATALINK_NAME | /* client name same as underlying NIC */
944 MAC_OPEN_FLAGS_MULTI_PRIMARY /* allow multiple primary unicasts */
945 );
946 if (RT_LIKELY(!rc))
947 {
948 pVNICTemplate->uVLANId = mac_client_vid(hClient);
949 mac_client_get_resources(hClient, &pVNICTemplate->Resources);
950 mac_client_close(hClient, 0 /* fFlags */);
951 mac_close(hInterface);
952
953 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNICTemplate successfully init. VNIC template. szLinkName=%s "
954 "VLAN Id=%u\n", pVNICTemplate->szLinkName, pVNICTemplate->uVLANId));
955 return VINF_SUCCESS;
956 }
957 else
958 {
959 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNICTemplate failed to open VNIC template. rc=%d\n", rc));
960 rc = VERR_INTNET_FLT_IF_FAILED;
961 }
962 }
963 else
964 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNICTemplate failed to get lower linkname for VNIC template '%s'.\n",
965 pThis->szName));
966
967 mac_close(hInterface);
968 }
969 else
970 {
971 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNICTemplate failed to open by link ID. rc=%d\n", rc));
972 rc = VERR_INTNET_FLT_IF_FAILED;
973 }
974 }
975 else
976 LogRel((DEVICE_NAME ":vboxNetFltSolarisInitVNICTemplate failed to get VNIC template link Id. rc=%d\n", rc));
977
978 return rc;
979}
980
981
982/**
983 * Allocate a VNIC structure.
984 *
985 * @returns An allocated VNIC structure or NULL in case of errors.
986 */
987LOCAL PVBOXNETFLTVNIC vboxNetFltSolarisAllocVNIC(void)
988{
989 PVBOXNETFLTVNIC pVNIC = RTMemAllocZ(sizeof(VBOXNETFLTVNIC));
990 if (RT_UNLIKELY(!pVNIC))
991 return NULL;
992
993 pVNIC->u32Magic = VBOXNETFLTVNIC_MAGIC;
994 pVNIC->fCreated = false;
995 pVNIC->pVNICTemplate = NULL;
996 pVNIC->pvIf = NULL;
997 pVNIC->hInterface = NULL;
998 pVNIC->hLinkId = DATALINK_INVALID_LINKID;
999 pVNIC->hClient = NULL;
1000 pVNIC->hUnicast = NULL;
1001 pVNIC->hPromisc = NULL;
1002 RT_ZERO(pVNIC->szName);
1003 list_link_init(&pVNIC->hNode);
1004 return pVNIC;
1005}
1006
1007
1008/**
1009 * Frees an allocated VNIC.
1010 *
1011 * @param pVNIC Pointer to the VNIC.
1012 */
1013LOCAL inline void vboxNetFltSolarisFreeVNIC(PVBOXNETFLTVNIC pVNIC)
1014{
1015 RTMemFree(pVNIC);
1016}
1017
1018
1019/**
1020 * Destroy a created VNIC if it was created by us, or just
1021 * de-initializes the VNIC freeing up resources handles.
1022 *
1023 * @param pVNIC Pointer to the VNIC.
1024 */
1025LOCAL void vboxNetFltSolarisDestroyVNIC(PVBOXNETFLTVNIC pVNIC)
1026{
1027 AssertPtrReturnVoid(pVNIC);
1028 AssertMsgReturnVoid(pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC, ("pVNIC=%p u32Magic=%#x\n", pVNIC, pVNIC->u32Magic));
1029 if (pVNIC)
1030 {
1031 if (pVNIC->hClient)
1032 {
1033#if 0
1034 if (pVNIC->hUnicast)
1035 {
1036 mac_unicast_remove(pVNIC->hClient, pVNIC->hUnicast);
1037 pVNIC->hUnicast = NULL;
1038 }
1039#endif
1040
1041 if (pVNIC->hPromisc)
1042 {
1043 mac_promisc_remove(pVNIC->hPromisc);
1044 pVNIC->hPromisc = NULL;
1045 }
1046
1047 mac_rx_clear(pVNIC->hClient);
1048
1049 mac_client_close(pVNIC->hClient, 0 /* fFlags */);
1050 pVNIC->hClient = NULL;
1051 }
1052
1053 if (pVNIC->hInterface)
1054 {
1055 mac_close(pVNIC->hInterface);
1056 pVNIC->hInterface = NULL;
1057 }
1058
1059 if (pVNIC->fCreated)
1060 {
1061 vnic_delete(pVNIC->hLinkId, 0 /* Flags */);
1062 pVNIC->hLinkId = DATALINK_INVALID_LINKID;
1063 pVNIC->fCreated = false;
1064 }
1065
1066 if (pVNIC->pVNICTemplate)
1067 {
1068 RTMemFree(pVNIC->pVNICTemplate);
1069 pVNIC->pVNICTemplate = NULL;
1070 }
1071 }
1072}
1073
1074
1075/**
1076 * Create a non-persistent VNIC over the given interface.
1077 *
1078 * @param pThis The VM connection instance.
1079 * @param ppVNIC Where to store the created VNIC.
1080 *
1081 * @returns VBox status code.
1082 */
1083LOCAL int vboxNetFltSolarisCreateVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC *ppVNIC)
1084{
1085 Log((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC pThis=%p\n", pThis));
1086
1087 AssertReturn(pThis, VERR_INVALID_POINTER);
1088 AssertReturn(ppVNIC, VERR_INVALID_POINTER);
1089
1090 int rc = VERR_INVALID_STATE;
1091 PVBOXNETFLTVNIC pVNIC = vboxNetFltSolarisAllocVNIC();
1092 if (RT_UNLIKELY(!pVNIC))
1093 return VERR_NO_MEMORY;
1094
1095 /*
1096 * Set a random MAC address for now. It will be changed to the VM interface's
1097 * MAC address later, see vboxNetFltPortOsNotifyMacAddress().
1098 */
1099 RTMAC GuestMac;
1100 GuestMac.au8[0] = 0x08;
1101 GuestMac.au8[1] = 0x00;
1102 GuestMac.au8[2] = 0x27;
1103 RTRandBytes(&GuestMac.au8[3], 3);
1104
1105 AssertCompile(sizeof(RTMAC) <= MAXMACADDRLEN);
1106
1107 const char *pszLinkName = pThis->szName;
1108 uint16_t uVLANId = VLAN_ID_NONE;
1109 vnic_mac_addr_type_t AddrType = VNIC_MAC_ADDR_TYPE_FIXED;
1110 vnic_ioc_diag_t Diag = VNIC_IOC_DIAG_NONE;
1111 int MacSlot = 0;
1112 int MacLen = sizeof(GuestMac);
1113 uint32_t fFlags = 0;
1114
1115 if (pThis->u.s.fIsVNICTemplate)
1116 {
1117 pVNIC->pVNICTemplate = RTMemAllocZ(sizeof(VBOXNETFLTVNICTEMPLATE));
1118 if (RT_UNLIKELY(!pVNIC->pVNICTemplate))
1119 {
1120 vboxNetFltSolarisFreeVNIC(pVNIC);
1121 return VERR_NO_MEMORY;
1122 }
1123
1124 /*
1125 * Initialize the VNIC template.
1126 */
1127 rc = vboxNetFltSolarisInitVNICTemplate(pThis, pVNIC->pVNICTemplate);
1128 if (RT_FAILURE(rc))
1129 {
1130 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to initialize VNIC from VNIC template. rc=%Rrc\n", rc));
1131 vboxNetFltSolarisFreeVNIC(pVNIC);
1132 return rc;
1133 }
1134
1135 pszLinkName = pVNIC->pVNICTemplate->szLinkName;
1136 uVLANId = pVNIC->pVNICTemplate->uVLANId;
1137#if 0
1138 /*
1139 * Required only if we're creating a VLAN interface & not a VNIC with a VLAN Id.
1140 */
1141 if (uVLANId != VLAN_ID_NONE)
1142 fFlags |= MAC_VLAN;
1143#endif
1144 Log((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC pThis=%p VLAN Id=%u\n", pThis, uVLANId));
1145 }
1146
1147 /*
1148 * Make sure the dynamic VNIC we're creating doesn't already exists, if so pick a new instance.
1149 * This is to avoid conflicts with users manually creating VNICs whose name starts with VBOXBOW_VNIC_NAME.
1150 */
1151 do
1152 {
1153 AssertCompile(sizeof(pVNIC->szName) > sizeof(VBOXBOW_VNIC_NAME "18446744073709551615" /* UINT64_MAX */));
1154 RTStrPrintf(pVNIC->szName, sizeof(pVNIC->szName), "%s%RU64", VBOXBOW_VNIC_NAME, g_VBoxNetFltSolarisVNICId);
1155 mac_handle_t hTmpMacHandle;
1156 rc = mac_open_by_linkname(pVNIC->szName, &hTmpMacHandle);
1157 if (rc)
1158 break;
1159 mac_close(hTmpMacHandle);
1160 ASMAtomicIncU64(&g_VBoxNetFltSolarisVNICId);
1161 } while (1);
1162
1163 /*
1164 * Create the VNIC under 'pszLinkName', which can be the one from the VNIC template or can
1165 * be a physical interface.
1166 */
1167 rc = vnic_create(pVNIC->szName, pszLinkName, &AddrType, &MacLen, GuestMac.au8, &MacSlot, 0 /* Mac-Prefix Length */, uVLANId,
1168 fFlags, &pVNIC->hLinkId, &Diag, NULL /* Reserved */);
1169 if (!rc)
1170 {
1171 pVNIC->fCreated = true;
1172 ASMAtomicIncU64(&g_VBoxNetFltSolarisVNICId);
1173
1174 /*
1175 * Now try opening the created VNIC.
1176 */
1177 rc = mac_open_by_linkid(pVNIC->hLinkId, &pVNIC->hInterface);
1178 if (!rc)
1179 {
1180 /*
1181 * Initialize the VNIC from the physical interface or the VNIC template.
1182 */
1183 rc = vboxNetFltSolarisInitVNIC(pThis, pVNIC);
1184 if (RT_SUCCESS(rc))
1185 {
1186 Log((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC created VNIC '%s' over '%s' with random mac %.6Rhxs\n",
1187 pVNIC->szName, pszLinkName, &GuestMac));
1188 *ppVNIC = pVNIC;
1189 return VINF_SUCCESS;
1190 }
1191
1192 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC vboxNetFltSolarisInitVNIC failed. rc=%d\n", rc));
1193 mac_close(pVNIC->hInterface);
1194 pVNIC->hInterface = NULL;
1195 }
1196 else
1197 {
1198 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC logrel failed to open VNIC '%s' over '%s'. rc=%d\n", pVNIC->szName,
1199 pThis->szName, rc));
1200 rc = VERR_INTNET_FLT_VNIC_LINK_ID_NOT_FOUND;
1201 }
1202
1203 vboxNetFltSolarisDestroyVNIC(pVNIC);
1204 }
1205 else
1206 {
1207 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to create VNIC '%s' over '%s' rc=%d Diag=%d\n", pVNIC->szName,
1208 pszLinkName, rc, Diag));
1209 rc = VERR_INTNET_FLT_VNIC_CREATE_FAILED;
1210 }
1211
1212 vboxNetFltSolarisFreeVNIC(pVNIC);
1213
1214 return rc;
1215}
1216
1217
1218/**
1219 * Wrapper for getting the datalink ID given the MAC name.
1220 *
1221 * @param pszMacName The MAC name.
1222 * @param pLinkId Where to store the datalink ID.
1223 *
1224 * @returns VBox status code.
1225 */
1226LOCAL inline int vboxNetFltSolarisGetLinkId(const char *pszMacName, datalink_id_t *pLinkId)
1227{
1228 /*
1229 * dls_mgmt_get_linkid() requires to be in a state to answer upcalls. We should always use this
1230 * first before resorting to other means to retrieve the MAC name.
1231 */
1232 int rc = dls_mgmt_get_linkid(pszMacName, pLinkId);
1233 if (rc)
1234 rc = dls_devnet_macname2linkid(pszMacName, pLinkId);
1235
1236 if (RT_LIKELY(!rc))
1237 return VINF_SUCCESS;
1238
1239 LogRel((DEVICE_NAME ":vboxNetFltSolarisGetLinkId failed for '%s'. rc=%d\n", pszMacName, rc));
1240 return RTErrConvertFromErrno(rc);
1241}
1242
1243
1244/**
1245 * Set the promiscuous mode RX hook.
1246 *
1247 * @param pThis The VM connection instance.
1248 * @param pVNIC Pointer to the VNIC.
1249 *
1250 * @returns VBox status code.
1251 */
1252LOCAL inline int vboxNetFltSolarisSetPromisc(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC pVNIC)
1253{
1254 int rc = VINF_SUCCESS;
1255 if (!pVNIC->hPromisc)
1256 {
1257 rc = mac_promisc_add(pVNIC->hClient, MAC_CLIENT_PROMISC_FILTERED, vboxNetFltSolarisRecv, pThis, &pVNIC->hPromisc,
1258 MAC_PROMISC_FLAGS_NO_TX_LOOP | MAC_PROMISC_FLAGS_VLAN_TAG_STRIP | MAC_PROMISC_FLAGS_NO_PHYS);
1259 if (RT_UNLIKELY(rc))
1260 LogRel((DEVICE_NAME ":vboxNetFltSolarisSetPromisc failed. rc=%d\n", rc));
1261 rc = RTErrConvertFromErrno(rc);
1262 }
1263 return rc;
1264}
1265
1266
1267/**
1268 * Clear the promiscuous mode RX hook.
1269 *
1270 * @param pThis The VM connection instance.
1271 * @param pVNIC Pointer to the VNIC.
1272 */
1273LOCAL inline void vboxNetFltSolarisRemovePromisc(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC pVNIC)
1274{
1275 if (pVNIC->hPromisc)
1276 {
1277 mac_promisc_remove(pVNIC->hPromisc);
1278 pVNIC->hPromisc = NULL;
1279 }
1280}
1281
1282
1283/* -=-=-=-=-=- Common Hooks -=-=-=-=-=- */
1284
1285
1286void vboxNetFltPortOsSetActive(PVBOXNETFLTINS pThis, bool fActive)
1287{
1288 Log((DEVICE_NAME ":vboxNetFltPortOsSetActive pThis=%p fActive=%d\n", pThis, fActive));
1289
1290 /*
1291 * Reactivate/quiesce the interface.
1292 */
1293 PVBOXNETFLTVNIC pVNIC = list_head(&pThis->u.s.hVNICs);
1294 if (fActive)
1295 {
1296 for (; pVNIC != NULL; pVNIC = list_next(&pThis->u.s.hVNICs, pVNIC))
1297 if (pVNIC->hClient)
1298 {
1299#if 0
1300 mac_rx_set(pVNIC->hClient, vboxNetFltSolarisRecv, pThis);
1301#endif
1302 vboxNetFltSolarisSetPromisc(pThis, pVNIC);
1303 }
1304 }
1305 else
1306 {
1307 for (; pVNIC != NULL; pVNIC = list_next(&pThis->u.s.hVNICs, pVNIC))
1308 if (pVNIC->hClient)
1309 {
1310#if 0
1311 mac_rx_clear(pVNIC->hClient);
1312#endif
1313 vboxNetFltSolarisRemovePromisc(pThis, pVNIC);
1314 }
1315 }
1316}
1317
1318
1319int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis)
1320{
1321 Log((DEVICE_NAME ":vboxNetFltOsDisconnectIt pThis=%p\n", pThis));
1322 return VINF_SUCCESS;
1323}
1324
1325
1326int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis)
1327{
1328 Log((DEVICE_NAME ":vboxNetFltOsConnectIt pThis=%p\n", pThis));
1329 return VINF_SUCCESS;
1330}
1331
1332
1333void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
1334{
1335 Log((DEVICE_NAME ":vboxNetFltOsDeleteInstance pThis=%p\n", pThis));
1336
1337 if (pThis->u.s.hNotify)
1338 mac_notify_remove(pThis->u.s.hNotify, B_TRUE /* Wait */);
1339
1340 /*
1341 * Destroy all managed VNICs. If a VNIC was passed to us, there
1342 * will be only 1 item in the list, otherwise as many interfaces
1343 * that were somehow not destroyed using DisconnectInterface() will be
1344 * present.
1345 */
1346 PVBOXNETFLTVNIC pVNIC = NULL;
1347 while ((pVNIC = list_remove_head(&pThis->u.s.hVNICs)) != NULL)
1348 {
1349 vboxNetFltSolarisDestroyVNIC(pVNIC);
1350 vboxNetFltSolarisFreeVNIC(pVNIC);
1351 }
1352
1353 list_destroy(&pThis->u.s.hVNICs);
1354}
1355
1356
1357int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext)
1358{
1359 Log((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p pvContext=%p\n", pThis, pvContext));
1360
1361 /*
1362 * Figure out if the interface is a VNIC or a physical/etherstub/whatever NIC, then
1363 * do the actual VNIC creation if necessary in vboxNetFltPortOsConnectInterface().
1364 */
1365 mac_handle_t hInterface;
1366 int rc = mac_open_by_linkname(pThis->szName, &hInterface);
1367 if (RT_LIKELY(!rc))
1368 {
1369 rc = mac_is_vnic(hInterface);
1370 if (!rc)
1371 {
1372 Log((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p physical interface '%s' detected.\n", pThis, pThis->szName));
1373 pThis->u.s.fIsVNIC = false;
1374 }
1375 else
1376 {
1377 pThis->u.s.fIsVNIC = true;
1378 if (RTStrNCmp(pThis->szName, VBOXBOW_VNIC_TEMPLATE_NAME, sizeof(VBOXBOW_VNIC_TEMPLATE_NAME) - 1) == 0)
1379 {
1380 Log((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p VNIC template '%s' detected.\n", pThis, pThis->szName));
1381 pThis->u.s.fIsVNICTemplate = true;
1382 }
1383 }
1384
1385 if ( pThis->u.s.fIsVNIC
1386 && !pThis->u.s.fIsVNICTemplate)
1387 Log((DEVICE_NAME ":vboxNetFltOsInitInstance pThis=%p VNIC '%s' detected.\n", pThis, pThis->szName));
1388
1389 /*
1390 * Report info. (host MAC address, promiscuous, GSO capabilities etc.) to IntNet.
1391 */
1392 rc = vboxNetFltSolarisReportInfo(pThis, hInterface, pThis->u.s.fIsVNIC);
1393 if (RT_FAILURE(rc))
1394 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to report info. rc=%d\n", rc));
1395
1396 mac_close(hInterface);
1397 }
1398 else
1399 {
1400 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to open link '%s'! rc=%d\n", pThis->szName, rc));
1401 rc = VERR_INTNET_FLT_IF_FAILED;
1402 }
1403
1404 return rc;
1405}
1406
1407
1408int vboxNetFltOsPreInitInstance(PVBOXNETFLTINS pThis)
1409{
1410 /*
1411 * Init. the solaris specific data.
1412 */
1413 pThis->u.s.fIsVNIC = false;
1414 pThis->u.s.fIsVNICTemplate = false;
1415 list_create(&pThis->u.s.hVNICs, sizeof(VBOXNETFLTVNIC), offsetof(VBOXNETFLTVNIC, hNode));
1416 pThis->u.s.hNotify = NULL;
1417 RT_ZERO(pThis->u.s.MacAddr);
1418 return VINF_SUCCESS;
1419}
1420
1421
1422bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
1423{
1424 /*
1425 * @todo Think about this.
1426 */
1427 return false;
1428}
1429
1430
1431int vboxNetFltPortOsXmit(PVBOXNETFLTINS pThis, void *pvIfData, PINTNETSG pSG, uint32_t fDst)
1432{
1433 /*
1434 * Validate parameters.
1435 */
1436 PVBOXNETFLTVNIC pVNIC = pvIfData;
1437 AssertReturn(VALID_PTR(pVNIC), VERR_INVALID_POINTER);
1438 AssertMsgReturn(pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC,
1439 ("Invalid magic=%#x (expected %#x)\n", pVNIC->u32Magic, VBOXNETFLTVNIC_MAGIC),
1440 VERR_INVALID_MAGIC);
1441
1442 /*
1443 * Xmit the packet down the appropriate VNIC interface.
1444 */
1445 int rc = VINF_SUCCESS;
1446 mblk_t *pMsg = vboxNetFltSolarisMBlkFromSG(pThis, pSG, fDst);
1447 if (RT_LIKELY(pMsg))
1448 {
1449 Log((DEVICE_NAME ":vboxNetFltPortOsXmit pThis=%p cbData=%d\n", pThis, MBLKL(pMsg)));
1450
1451 mac_tx_cookie_t pXmitCookie = mac_tx(pVNIC->hClient, pMsg, 0 /* Hint */, MAC_DROP_ON_NO_DESC, NULL /* return message */);
1452 if (RT_LIKELY(!pXmitCookie))
1453 return VINF_SUCCESS;
1454
1455 pMsg = NULL;
1456 rc = VERR_NET_IO_ERROR;
1457 LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit Xmit failed pVNIC=%p.\n", pVNIC));
1458 }
1459 else
1460 {
1461 LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit no memory for allocating Xmit packet.\n"));
1462 rc = VERR_NO_MEMORY;
1463 }
1464
1465 return rc;
1466}
1467
1468
1469void vboxNetFltPortOsNotifyMacAddress(PVBOXNETFLTINS pThis, void *pvIfData, PCRTMAC pMac)
1470{
1471 Log((DEVICE_NAME ":vboxNetFltPortOSNotifyMacAddress pszIf=%s pszVNIC=%s MAC=%.6Rhxs\n", pThis->szName,
1472 ((PVBOXNETFLTVNIC)pvIfData)->szName, pMac));
1473
1474 /*
1475 * Validate parameters.
1476 */
1477 PVBOXNETFLTVNIC pVNIC = pvIfData;
1478 AssertMsgReturnVoid(VALID_PTR(pVNIC) && pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC,
1479 ("Invalid pVNIC=%p magic=%#x (expected %#x)\n", pvIfData,
1480 VALID_PTR(pVNIC) ? pVNIC->u32Magic : 0, VBOXNETFLTVNIC_MAGIC));
1481 AssertMsgReturnVoid(pVNIC->hLinkId != DATALINK_INVALID_LINKID,
1482 ("Invalid hLinkId pVNIC=%p magic=%#x\n", pVNIC, pVNIC->u32Magic));
1483
1484 /*
1485 * Set the MAC address of the VNIC to the one used by the VM interface.
1486 */
1487 uchar_t au8GuestMac[MAXMACADDRLEN];
1488 bcopy(pMac->au8, au8GuestMac, sizeof(RTMAC));
1489
1490 vnic_mac_addr_type_t AddrType = VNIC_MAC_ADDR_TYPE_FIXED;
1491 vnic_ioc_diag_t Diag = VNIC_IOC_DIAG_NONE;
1492 int MacSlot = 0;
1493 int MacLen = sizeof(RTMAC);
1494
1495 int rc = vnic_modify_addr(pVNIC->hLinkId, &AddrType, &MacLen, au8GuestMac, &MacSlot, 0 /* Mac-Prefix Length */, &Diag);
1496 if (RT_LIKELY(!rc))
1497 {
1498 /*
1499 * Remove existing unicast address, promisc. and the RX hook.
1500 */
1501#if 0
1502 if (pVNIC->hUnicast)
1503 {
1504 mac_rx_clear(pVNIC->hClient);
1505 mac_unicast_remove(pVNIC->hClient, pVNIC->hUnicast);
1506 pVNIC->hUnicast = NULL;
1507 }
1508#endif
1509
1510 if (pVNIC->hPromisc)
1511 {
1512 mac_promisc_remove(pVNIC->hPromisc);
1513 pVNIC->hPromisc = NULL;
1514 }
1515
1516 mac_diag_t MacDiag = MAC_DIAG_NONE;
1517 /* uint16_t uVLANId = pVNIC->pVNICTemplate ? pVNIC->pVNICTemplate->uVLANId : 0; */
1518#if 0
1519 rc = mac_unicast_add(pVNIC->hClient, NULL, MAC_UNICAST_PRIMARY, &pVNIC->hUnicast, 0 /* VLAN Id */, &MacDiag);
1520#endif
1521 if (RT_LIKELY(!rc))
1522 {
1523 rc = vboxNetFltSolarisSetPromisc(pThis, pVNIC);
1524#if 0
1525 if (RT_SUCCESS(rc))
1526 {
1527 /*
1528 * Set the RX receive function.
1529 * This shouldn't be necessary as vboxNetFltPortOsSetActive() will be invoked after this, but in the future,
1530 * if the guest NIC changes MAC address this may not be followed by a vboxNetFltPortOsSetActive() call,
1531 * so set it here anyway.
1532 */
1533 mac_rx_set(pVNIC->hClient, vboxNetFltSolarisRecv, pThis);
1534 Log((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress successfully added unicast address %.6Rhxs\n", pMac));
1535 }
1536 else
1537 LogRel((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress failed to set promiscuous mode. rc=%d\n", rc));
1538 mac_unicast_remove(pVNIC->hClient, pVNIC->hUnicast);
1539 pVNIC->hUnicast = NULL;
1540#endif
1541 }
1542 else
1543 {
1544 LogRel((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress failed to add primary unicast address. rc=%d Diag=%d\n", rc,
1545 MacDiag));
1546 }
1547 }
1548 else
1549 {
1550 /*
1551 * They really ought to use EEXIST, but I'm afraid this error comes from the VNIC device driver directly.
1552 * Sequence: vnic_modify_addr()->mac_unicast_primary_set()->mac_update_macaddr() which uses a function pointer
1553 * to the MAC driver (calls mac_vnic_unicast_set() in our case). Documented here if the error code should change we know
1554 * where to look.
1555 */
1556 if (rc == ENOTSUP)
1557 {
1558 LogRel((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress: failed! a VNIC with mac %.6Rhxs probably already exists.",
1559 pMac, rc));
1560 LogRel((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress: This NIC cannot establish connection. szName=%s szVNIC=%s\n",
1561 pThis->szName, pVNIC->szName));
1562 }
1563 else
1564 LogRel((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress failed! mac %.6Rhxs rc=%d Diag=%d\n", pMac, rc, Diag));
1565 }
1566}
1567
1568
1569int vboxNetFltPortOsConnectInterface(PVBOXNETFLTINS pThis, void *pvIf, void **ppvIfData)
1570{
1571 Log((DEVICE_NAME ":vboxNetFltPortOsConnectInterface pThis=%p pvIf=%p\n", pThis, pvIf));
1572
1573 int rc = VINF_SUCCESS;
1574
1575 /*
1576 * If the underlying interface is a physical interface or a VNIC template, we need to create
1577 * a VNIC per guest NIC.
1578 */
1579 if ( !pThis->u.s.fIsVNIC
1580 || pThis->u.s.fIsVNICTemplate)
1581 {
1582 PVBOXNETFLTVNIC pVNIC = NULL;
1583 rc = vboxNetFltSolarisCreateVNIC(pThis, &pVNIC);
1584 if (RT_SUCCESS(rc))
1585 {
1586 /*
1587 * VM Interface<->VNIC association so that we can Xmit/Recv on the right ones.
1588 */
1589 pVNIC->pvIf = pvIf;
1590 *ppvIfData = pVNIC;
1591
1592 /*
1593 * Add the created VNIC to the list of VNICs we manage.
1594 */
1595 list_insert_tail(&pThis->u.s.hVNICs, pVNIC);
1596 return VINF_SUCCESS;
1597 }
1598 else
1599 LogRel((DEVICE_NAME ":vboxNetFltPortOsConnectInterface failed to create VNIC rc=%d\n", rc));
1600 }
1601 else
1602 {
1603 /*
1604 * This is a VNIC passed to us, use it directly.
1605 */
1606 PVBOXNETFLTVNIC pVNIC = vboxNetFltSolarisAllocVNIC();
1607 if (RT_LIKELY(pVNIC))
1608 {
1609 pVNIC->fCreated = false;
1610
1611 rc = mac_open_by_linkname(pThis->szName, &pVNIC->hInterface);
1612 if (!rc)
1613 {
1614 /*
1615 * Obtain the data link ID for this VNIC, it's needed for modifying the MAC address among other things.
1616 */
1617 rc = vboxNetFltSolarisGetLinkId(pThis->szName, &pVNIC->hLinkId);
1618 if (RT_SUCCESS(rc))
1619 {
1620 /*
1621 * Initialize the VNIC and add it to the list of managed VNICs.
1622 */
1623 RTStrPrintf(pVNIC->szName, sizeof(pVNIC->szName), "%s", pThis->szName);
1624 rc = vboxNetFltSolarisInitVNIC(pThis, pVNIC);
1625 if (!rc)
1626 {
1627 pVNIC->pvIf = pvIf;
1628 *ppvIfData = pVNIC;
1629 list_insert_head(&pThis->u.s.hVNICs, pVNIC);
1630 return VINF_SUCCESS;
1631 }
1632 else
1633 LogRel((DEVICE_NAME ":vboxNetFltPortOsConnectInterface failed to initialize VNIC. rc=%d\n", rc));
1634 }
1635 else
1636 {
1637 LogRel((DEVICE_NAME ":vboxNetFltPortOsConnectInterface failed to get link id for '%s'. rc=%d\n",
1638 pThis->szName, rc));
1639 }
1640 }
1641 else
1642 {
1643 LogRel((DEVICE_NAME ":vboxNetFltPortOsConnectInterface failed to open VNIC '%s'. rc=%d\n", pThis->szName, rc));
1644 rc = VERR_OPEN_FAILED;
1645 }
1646
1647 vboxNetFltSolarisFreeVNIC(pVNIC);
1648 }
1649 else
1650 {
1651 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to allocate VNIC private data.\n"));
1652 rc = VERR_NO_MEMORY;
1653 }
1654 }
1655
1656 return rc;
1657}
1658
1659
1660int vboxNetFltPortOsDisconnectInterface(PVBOXNETFLTINS pThis, void *pvIfData)
1661{
1662 Log((DEVICE_NAME ":vboxNetFltPortOsDisconnectInterface pThis=%p\n", pThis));
1663
1664 /*
1665 * It is possible we get called when vboxNetFltPortOsConnectInterface() didn't succeed
1666 * in which case pvIfData will be NULL. See intnetR0NetworkCreateIf() pfnConnectInterface call
1667 * through reference counting in SUPR0ObjRelease() for the "pIf" object.
1668 */
1669 PVBOXNETFLTVNIC pVNIC = pvIfData;
1670 if (RT_LIKELY(pVNIC))
1671 {
1672 AssertMsgReturn(pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC,
1673 ("Invalid magic=%#x (expected %#x)\n", pVNIC->u32Magic, VBOXNETFLTVNIC_MAGIC), VERR_INVALID_POINTER);
1674
1675 /*
1676 * If the underlying interface is a physical interface or a VNIC template, we need to delete the created VNIC.
1677 */
1678 if ( !pThis->u.s.fIsVNIC
1679 || pThis->u.s.fIsVNICTemplate)
1680 {
1681 /*
1682 * Remove the VNIC from the list, destroy and free it.
1683 */
1684 list_remove(&pThis->u.s.hVNICs, pVNIC);
1685 Log((DEVICE_NAME ":vboxNetFltPortOsDisconnectInterface destroying pVNIC=%p\n", pVNIC));
1686 vboxNetFltSolarisDestroyVNIC(pVNIC);
1687 vboxNetFltSolarisFreeVNIC(pVNIC);
1688 }
1689 }
1690
1691 return VINF_SUCCESS;
1692}
1693
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