VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 6 days ago

Copyright year updates by scm.

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