VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdp.c

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.7 KB
RevLine 
[16960]1/* $Id: VBoxNetAdp.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxNetAdp - Virtual Network Adapter Driver (Host), Common Code.
4 */
5
6/*
[98103]7 * Copyright (C) 2008-2023 Oracle and/or its affiliates.
[16960]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
[69250]11 *
[96407]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 *
[69250]25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
[96407]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
[69250]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.
[96407]33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
[16960]35 */
36
[17184]37/** @page pg_netadp VBoxNetAdp - Network Adapter
38 *
39 * This is a kernel module that creates a virtual interface that can be attached
40 * to an internal network.
41 *
42 * In the big picture we're one of the three trunk interface on the internal
43 * network, the one named "TAP Interface": @image html Networking_Overview.gif
44 *
45 */
46
[57358]47
48/*********************************************************************************************************************************
49* Header Files *
50*********************************************************************************************************************************/
[17184]51#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
[16960]52#include "VBoxNetAdpInternal.h"
53
54#include <VBox/log.h>
55#include <VBox/err.h>
[18973]56#include <iprt/string.h>
57
58
59VBOXNETADP g_aAdapters[VBOXNETADP_MAX_INSTANCES];
[35809]60static uint8_t g_aUnits[VBOXNETADP_MAX_UNITS/8];
[18973]61
62
[35809]63DECLINLINE(int) vboxNetAdpGetUnitByName(const char *pcszName)
64{
[35824]65 uint32_t iUnit = RTStrToUInt32(pcszName + sizeof(VBOXNETADP_NAME) - 1);
[35815]66 bool fOld;
[18973]67
[35824]68 if (iUnit >= VBOXNETADP_MAX_UNITS)
[35809]69 return -1;
70
[35824]71 fOld = ASMAtomicBitTestAndSet(g_aUnits, iUnit);
72 return fOld ? -1 : (int)iUnit;
[35809]73}
74
75DECLINLINE(int) vboxNetAdpGetNextAvailableUnit(void)
76{
[35815]77 bool fOld;
[35824]78 int iUnit;
[35809]79 /* There is absolutely no chance that all units are taken */
80 do {
[35824]81 iUnit = ASMBitFirstClear(g_aUnits, VBOXNETADP_MAX_UNITS);
82 if (iUnit < 0)
[35809]83 break;
[35824]84 fOld = ASMAtomicBitTestAndSet(g_aUnits, iUnit);
[35815]85 } while (fOld);
[35809]86
[35824]87 return iUnit;
[35809]88}
89
[35824]90DECLINLINE(void) vboxNetAdpReleaseUnit(int iUnit)
[35809]91{
[36907]92 bool fSet = ASMAtomicBitTestAndClear(g_aUnits, iUnit);
[36951]93 NOREF(fSet);
[36907]94 Assert(fSet);
[35809]95}
96
[18973]97/**
98 * Generate a suitable MAC address.
99 *
100 * @param pThis The instance.
101 * @param pMac Where to return the MAC address.
102 */
103DECLHIDDEN(void) vboxNetAdpComposeMACAddress(PVBOXNETADP pThis, PRTMAC pMac)
104{
105 /* Use a locally administered version of the OUI we use for the guest NICs. */
106 pMac->au8[0] = 0x08 | 2;
107 pMac->au8[1] = 0x00;
108 pMac->au8[2] = 0x27;
109
[35824]110 pMac->au8[3] = 0; /* pThis->iUnit >> 16; */
111 pMac->au8[4] = 0; /* pThis->iUnit >> 8; */
112 pMac->au8[5] = pThis->iUnit;
[18973]113}
114
[35824]115int vboxNetAdpCreate(PVBOXNETADP *ppNew, const char *pcszName)
[18973]116{
117 int rc;
118 unsigned i;
119 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
120 {
121 PVBOXNETADP pThis = &g_aAdapters[i];
122
123 if (ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Transitional, kVBoxNetAdpState_Invalid))
124 {
125 RTMAC Mac;
126 /* Found an empty slot -- use it. */
127 Log(("vboxNetAdpCreate: found empty slot: %d\n", i));
[35809]128 if (pcszName)
129 {
130 Log(("vboxNetAdpCreate: using name: %s\n", pcszName));
[35824]131 pThis->iUnit = vboxNetAdpGetUnitByName(pcszName);
[72870]132 strncpy(pThis->szName, pcszName, sizeof(pThis->szName) - 1);
[35809]133 pThis->szName[sizeof(pThis->szName) - 1] = '\0';
134 }
135 else
136 {
[35824]137 pThis->iUnit = vboxNetAdpGetNextAvailableUnit();
[35809]138 pThis->szName[0] = '\0';
139 }
[35824]140 if (pThis->iUnit < 0)
[35809]141 rc = VERR_INVALID_PARAMETER;
142 else
143 {
144 vboxNetAdpComposeMACAddress(pThis, &Mac);
145 rc = vboxNetAdpOsCreate(pThis, &Mac);
[35824]146 Log(("vboxNetAdpCreate: pThis=%p pThis->iUnit=%d, pThis->szName=%s\n",
147 pThis, pThis->iUnit, pThis->szName));
[35809]148 }
[18973]149 if (RT_SUCCESS(rc))
150 {
151 *ppNew = pThis;
152 ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Active);
[35809]153 Log2(("VBoxNetAdpCreate: Created %s\n", g_aAdapters[i].szName));
[18973]154 }
155 else
156 {
157 ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Invalid);
158 Log(("vboxNetAdpCreate: vboxNetAdpOsCreate failed with '%Rrc'.\n", rc));
159 }
160 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
[35809]161 Log2(("VBoxNetAdpCreate: Scanning entry: state=%d unit=%d name=%s\n",
[35824]162 g_aAdapters[i].enmState, g_aAdapters[i].iUnit, g_aAdapters[i].szName));
[18973]163 return rc;
164 }
165 }
166 Log(("vboxNetAdpCreate: no empty slots!\n"));
167
168 /* All slots in adapter array are busy. */
169 return VERR_OUT_OF_RESOURCES;
170}
171
[35824]172int vboxNetAdpDestroy(PVBOXNETADP pThis)
[18973]173{
174 int rc = VINF_SUCCESS;
175
176 if (!ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Transitional, kVBoxNetAdpState_Active))
177 return VERR_INTNET_FLT_IF_BUSY;
178
[35824]179 Assert(pThis->iUnit >= 0 && pThis->iUnit < VBOXNETADP_MAX_UNITS);
[18973]180 vboxNetAdpOsDestroy(pThis);
[35824]181 vboxNetAdpReleaseUnit(pThis->iUnit);
182 pThis->iUnit = -1;
[35809]183 pThis->szName[0] = '\0';
[18973]184
185 ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Invalid);
186
187 return rc;
188}
189
190int vboxNetAdpInit(void)
191{
192 unsigned i;
193 /*
194 * Init common members and call OS-specific init.
195 */
[35809]196 memset(g_aUnits, 0, sizeof(g_aUnits));
197 memset(g_aAdapters, 0, sizeof(g_aAdapters));
[41272]198 LogFlow(("vboxnetadp: max host-only interfaces supported: %d (%d bytes)\n",
199 VBOXNETADP_MAX_INSTANCES, sizeof(g_aAdapters)));
[18973]200 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
201 {
202 g_aAdapters[i].enmState = kVBoxNetAdpState_Invalid;
[35824]203 g_aAdapters[i].iUnit = -1;
[18973]204 vboxNetAdpOsInit(&g_aAdapters[i]);
205 }
206
[35785]207 return VINF_SUCCESS;
[18973]208}
209
210/**
211 * Finds an adapter by its name.
212 *
213 * @returns Pointer to the instance by the given name. NULL if not found.
214 * @param pszName The name of the instance.
215 */
216PVBOXNETADP vboxNetAdpFindByName(const char *pszName)
217{
218 unsigned i;
219
220 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
221 {
222 PVBOXNETADP pThis = &g_aAdapters[i];
223 Log2(("VBoxNetAdp: Scanning entry: state=%d name=%s\n", pThis->enmState, pThis->szName));
[23068]224 if ( strcmp(pThis->szName, pszName) == 0
225 && ASMAtomicReadU32((uint32_t volatile *)&pThis->enmState) == kVBoxNetAdpState_Active)
226 return pThis;
[18973]227 }
228 return NULL;
229}
230
231void vboxNetAdpShutdown(void)
232{
233 unsigned i;
234
235 /* Remove virtual adapters */
236 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
237 vboxNetAdpDestroy(&g_aAdapters[i]);
238}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use