VirtualBox

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

Last change on this file since 56265 was 55980, checked in by vboxsync, 10 years ago

iprt/log.h,++: Added extended logger instance getters that also checks whether the given logger and group-flags are enabled, making the LogRel* checks more efficient in avoid uncessary RTLogLoggerEx parameter building and calls. Ditto for debug logging. The LOG_INSTANCE and LOG_REL_INSTANCE tricks are gone for now.

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