VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/solaris/NetIf-solaris.cpp@ 98103

Last change on this file since 98103 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.4 KB
Line 
1/* $Id: NetIf-solaris.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * Main - NetIfList, Solaris implementation.
4 */
5
6/*
7 * Copyright (C) 2008-2023 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 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29
30/*********************************************************************************************************************************
31* Header Files *
32*********************************************************************************************************************************/
33#define LOG_GROUP LOG_GROUP_MAIN_HOST
34
35#include <iprt/errcore.h>
36#include <iprt/ctype.h>
37#include <iprt/mem.h>
38#include <iprt/path.h>
39#include <list>
40
41#include "LoggingNew.h"
42#include "HostNetworkInterfaceImpl.h"
43#include "netif.h"
44
45#ifdef VBOX_WITH_HOSTNETIF_API
46
47#include <map>
48#include <iprt/sanitized/string>
49#include <fcntl.h>
50#include <unistd.h>
51#include <stropts.h>
52#include <limits.h>
53#include <stdio.h>
54#include <libdevinfo.h>
55#include <net/if.h>
56#include <sys/socket.h>
57#include <sys/sockio.h>
58#include <net/if_arp.h>
59#include <net/if.h>
60#include <sys/types.h>
61#include <kstat.h>
62
63#include "DynLoadLibSolaris.h"
64
65/** @todo Unify this define with VBoxNetFltBow-solaris.c */
66#define VBOXBOW_VNIC_TEMPLATE_NAME "vboxvnic_template"
67
68
69static uint32_t getInstance(const char *pszIfaceName, char *pszDevName)
70{
71 /*
72 * Get the instance number from the interface name, then clip it off.
73 */
74 int cbInstance = 0;
75 size_t cbIface = strlen(pszIfaceName);
76 const char *pszEnd = pszIfaceName + cbIface - 1;
77 for (size_t i = 0; i < cbIface - 1; i++)
78 {
79 if (!RT_C_IS_DIGIT(*pszEnd))
80 break;
81 cbInstance++;
82 pszEnd--;
83 }
84
85 uint32_t uInstance = RTStrToUInt32(pszEnd + 1);
86 strncpy(pszDevName, pszIfaceName, cbIface - cbInstance);
87 pszDevName[cbIface - cbInstance] = '\0';
88 return uInstance;
89}
90
91static uint32_t kstatGet(const char *name)
92{
93 kstat_ctl_t *kc;
94 uint32_t uSpeed = 0;
95
96 if ((kc = kstat_open()) == 0)
97 {
98 LogRel(("kstat_open() -> %d\n", errno));
99 return 0;
100 }
101
102 kstat_t *ksAdapter = kstat_lookup(kc, (char *)"link", -1, (char *)name);
103 if (ksAdapter == 0)
104 {
105 char szModule[KSTAT_STRLEN];
106 uint32_t uInstance = getInstance(name, szModule);
107 ksAdapter = kstat_lookup(kc, szModule, uInstance, (char *)"phys");
108 if (ksAdapter == 0)
109 ksAdapter = kstat_lookup(kc, szModule, uInstance, (char*)name);
110 }
111 if (ksAdapter == 0)
112 LogRel(("Failed to get network statistics for %s\n", name));
113 else if (kstat_read(kc, ksAdapter, 0) == -1)
114 LogRel(("kstat_read(%s) -> %d\n", name, errno));
115 else
116 {
117 kstat_named_t *kn;
118 if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"ifspeed")) != NULL)
119 uSpeed = (uint32_t)(kn->value.ul / 1000000); /* bits -> Mbits */
120 else
121 LogRel(("kstat_data_lookup(ifspeed) -> %d, name=%s\n", errno, name));
122 }
123 kstat_close(kc);
124 LogFlow(("kstatGet(%s) -> %u Mbit/s\n", name, uSpeed));
125 return uSpeed;
126}
127
128static void queryIfaceSpeed(PNETIFINFO pInfo)
129{
130 /* Don't query interface speed for inactive interfaces (see @bugref{6345}). */
131 if (pInfo->enmStatus == NETIF_S_UP)
132 pInfo->uSpeedMbits = kstatGet(pInfo->szShortName);
133 else
134 pInfo->uSpeedMbits = 0;
135 LogFlow(("queryIfaceSpeed(%s) -> %u\n", pInfo->szShortName, pInfo->uSpeedMbits));
136}
137
138static void vboxSolarisAddHostIface(char *pszIface, int Instance, void *pvHostNetworkInterfaceList)
139{
140 std::list<ComObjPtr<HostNetworkInterface> > *pList =
141 (std::list<ComObjPtr<HostNetworkInterface> > *)pvHostNetworkInterfaceList;
142 Assert(pList);
143
144 typedef std::map <std::string, std::string> NICMap;
145 typedef std::pair <std::string, std::string> NICPair;
146 static NICMap SolarisNICMap;
147 if (SolarisNICMap.empty())
148 {
149 SolarisNICMap.insert(NICPair("afe", "ADMtek Centaur/Comet Fast Ethernet"));
150 SolarisNICMap.insert(NICPair("atge", "Atheros/Attansic Gigabit Ethernet"));
151 SolarisNICMap.insert(NICPair("aggr", "Link Aggregation Interface"));
152 SolarisNICMap.insert(NICPair("bfe", "Broadcom BCM4401 Fast Ethernet"));
153 SolarisNICMap.insert(NICPair("bge", "Broadcom BCM57xx Gigabit Ethernet"));
154 SolarisNICMap.insert(NICPair("bnx", "Broadcom NetXtreme Gigabit Ethernet"));
155 SolarisNICMap.insert(NICPair("bnxe", "Broadcom NetXtreme II 10 Gigabit Ethernet"));
156 SolarisNICMap.insert(NICPair("ce", "Cassini Gigabit Ethernet"));
157 SolarisNICMap.insert(NICPair("chxge", "Chelsio Ethernet"));
158 SolarisNICMap.insert(NICPair("dmfe", "Davicom 9102 Fast Ethernet"));
159 SolarisNICMap.insert(NICPair("dnet", "DEC 21040/41 21140 Ethernet"));
160 SolarisNICMap.insert(NICPair("e1000", "Intel PRO/1000 Gigabit Ethernet"));
161 SolarisNICMap.insert(NICPair("e1000g", "Intel PRO/1000 Gigabit Ethernet"));
162 SolarisNICMap.insert(NICPair("elx", "3COM Etherlink III Ethernet"));
163 SolarisNICMap.insert(NICPair("elxl", "3COM Etherlink XL Ethernet"));
164 SolarisNICMap.insert(NICPair("eri", "eri Fast Ethernet"));
165 SolarisNICMap.insert(NICPair("ge", "GEM Gigabit Ethernet"));
166 SolarisNICMap.insert(NICPair("hme", "SUNW,hme Fast-Ethernet"));
167 SolarisNICMap.insert(NICPair("hxge", "Sun Blade 10 Gigabit Ethernet"));
168 SolarisNICMap.insert(NICPair("igb", "Intel 82575 PCI-E Gigabit Ethernet"));
169 SolarisNICMap.insert(NICPair("ipge", "PCI-E Gigabit Ethernet"));
170 SolarisNICMap.insert(NICPair("iprb", "Intel 82557/58/59 Ethernet"));
171 SolarisNICMap.insert(NICPair("ixgb", "Intel 82597ex 10 Gigabit Ethernet"));
172 SolarisNICMap.insert(NICPair("ixgbe", "Intel 10 Gigabit PCI-E Ethernet"));
173 SolarisNICMap.insert(NICPair("mcxe", "Mellanox ConnectX-2 10 Gigabit Ethernet"));
174 SolarisNICMap.insert(NICPair("mxfe", "Macronix 98715 Fast Ethernet"));
175 SolarisNICMap.insert(NICPair("nfo", "Nvidia Gigabit Ethernet"));
176 SolarisNICMap.insert(NICPair("nge", "Nvidia Gigabit Ethernet"));
177 SolarisNICMap.insert(NICPair("ntxn", "NetXen 10/1 Gigabit Ethernet"));
178 SolarisNICMap.insert(NICPair("nxge", "Sun 10/1 Gigabit Ethernet"));
179 SolarisNICMap.insert(NICPair("pcelx", "3COM EtherLink III PCMCIA Ethernet"));
180 SolarisNICMap.insert(NICPair("pcn", "AMD PCnet Ethernet"));
181 SolarisNICMap.insert(NICPair("qfe", "SUNW,qfe Quad Fast-Ethernet"));
182 SolarisNICMap.insert(NICPair("rge", "Realtek Gigabit Ethernet"));
183 SolarisNICMap.insert(NICPair("rtls", "Realtek 8139 Fast Ethernet"));
184 SolarisNICMap.insert(NICPair("sfe", "SiS900 Fast Ethernet"));
185 SolarisNICMap.insert(NICPair("skge", "SksKonnect Gigabit Ethernet"));
186 SolarisNICMap.insert(NICPair("spwr", "SMC EtherPower II 10/100 (9432) Ethernet"));
187 SolarisNICMap.insert(NICPair("vboxnet", "VirtualBox Host Ethernet"));
188 SolarisNICMap.insert(NICPair(VBOXBOW_VNIC_TEMPLATE_NAME, "VirtualBox VNIC Template"));
189 SolarisNICMap.insert(NICPair("vlan", "Virtual LAN Ethernet"));
190 SolarisNICMap.insert(NICPair("vr", "VIA Rhine Fast Ethernet"));
191 SolarisNICMap.insert(NICPair("vnic", "Virtual Network Interface Ethernet"));
192 SolarisNICMap.insert(NICPair("xge", "Neterior Xframe 10Gigabit Ethernet"));
193 SolarisNICMap.insert(NICPair("yge", "Marvell Yukon 2 Fast Ethernet"));
194 }
195
196 /*
197 * Try picking up description from our NIC map.
198 */
199 char szNICInstance[128];
200 RTStrPrintf(szNICInstance, sizeof(szNICInstance), "%s%d", pszIface, Instance);
201 char szNICDesc[256];
202 std::string Description = SolarisNICMap[pszIface];
203 if (Description != "VirtualBox Host Ethernet")
204 {
205 if (Description != "")
206 RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s - %s", szNICInstance, Description.c_str());
207 else if (!strncmp(szNICInstance, RT_STR_TUPLE(VBOXBOW_VNIC_TEMPLATE_NAME)))
208 {
209 /*
210 * We want prefix matching only for "vboxvnic_template" as it's possible to create "vboxvnic_template_abcd123",
211 * which our Solaris Crossbow NetFilter driver will interpret as a VNIC template.
212 */
213 Description = SolarisNICMap[VBOXBOW_VNIC_TEMPLATE_NAME];
214 RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s - %s", szNICInstance, Description.c_str());
215 }
216 else
217 RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s - Ethernet", szNICInstance);
218 }
219 else
220 RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s", szNICInstance);
221
222 /*
223 * Try to get IP V4 address and netmask as well as Ethernet address.
224 */
225 NETIFINFO Info;
226 RT_ZERO(Info);
227 int Sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
228 if (Sock > 0)
229 {
230 struct lifreq IfReq;
231 RTStrCopy(IfReq.lifr_name, sizeof(IfReq.lifr_name), szNICInstance);
232 if (ioctl(Sock, SIOCGLIFADDR, &IfReq) >= 0)
233 {
234 memcpy(Info.IPAddress.au8, &((struct sockaddr_in *)&IfReq.lifr_addr)->sin_addr.s_addr,
235 sizeof(Info.IPAddress.au8));
236 struct arpreq ArpReq;
237 memcpy(&ArpReq.arp_pa, &IfReq.lifr_addr, sizeof(struct sockaddr_in));
238
239 /*
240 * We might fail if the interface has not been assigned an IP address.
241 * That doesn't matter; as long as it's plumbed we can pick it up.
242 * But, if it has not acquired an IP address we cannot obtain it's MAC
243 * address this way, so we just use all zeros there.
244 */
245 if (ioctl(Sock, SIOCGARP, &ArpReq) >= 0)
246 {
247 memcpy(&Info.MACAddress, ArpReq.arp_ha.sa_data, sizeof(Info.MACAddress));
248 }
249
250 }
251
252 if (ioctl(Sock, SIOCGLIFNETMASK, &IfReq) >= 0)
253 {
254 memcpy(Info.IPNetMask.au8, &((struct sockaddr_in *)&IfReq.lifr_addr)->sin_addr.s_addr,
255 sizeof(Info.IPNetMask.au8));
256 }
257 if (ioctl(Sock, SIOCGLIFFLAGS, &IfReq) >= 0)
258 {
259 Info.enmStatus = IfReq.lifr_flags & IFF_UP ? NETIF_S_UP : NETIF_S_DOWN;
260 }
261 close(Sock);
262 }
263 /*
264 * Try to get IP V6 address and netmask.
265 */
266 Sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
267 if (Sock > 0)
268 {
269 struct lifreq IfReq;
270 RTStrCopy(IfReq.lifr_name, sizeof(IfReq.lifr_name), szNICInstance);
271 if (ioctl(Sock, SIOCGLIFADDR, &IfReq) >= 0)
272 {
273 memcpy(Info.IPv6Address.au8, ((struct sockaddr_in6 *)&IfReq.lifr_addr)->sin6_addr.s6_addr,
274 sizeof(Info.IPv6Address.au8));
275 }
276 if (ioctl(Sock, SIOCGLIFNETMASK, &IfReq) >= 0)
277 {
278 memcpy(Info.IPv6NetMask.au8, ((struct sockaddr_in6 *)&IfReq.lifr_addr)->sin6_addr.s6_addr,
279 sizeof(Info.IPv6NetMask.au8));
280 }
281 close(Sock);
282 }
283
284 /*
285 * Construct UUID with interface name and the MAC address if available.
286 */
287 RTUUID Uuid;
288 RTUuidClear(&Uuid);
289 memcpy(&Uuid, szNICInstance, RT_MIN(strlen(szNICInstance), sizeof(Uuid)));
290 Uuid.Gen.u8ClockSeqHiAndReserved = (Uuid.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80;
291 Uuid.Gen.u16TimeHiAndVersion = (Uuid.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000;
292 Uuid.Gen.au8Node[0] = Info.MACAddress.au8[0];
293 Uuid.Gen.au8Node[1] = Info.MACAddress.au8[1];
294 Uuid.Gen.au8Node[2] = Info.MACAddress.au8[2];
295 Uuid.Gen.au8Node[3] = Info.MACAddress.au8[3];
296 Uuid.Gen.au8Node[4] = Info.MACAddress.au8[4];
297 Uuid.Gen.au8Node[5] = Info.MACAddress.au8[5];
298 Info.Uuid = Uuid;
299 Info.enmMediumType = NETIF_T_ETHERNET;
300 strncpy(Info.szShortName, szNICInstance, sizeof(Info.szShortName) - 1);
301
302 HostNetworkInterfaceType_T enmType;
303 if (strncmp(szNICInstance, RT_STR_TUPLE("vboxnet")))
304 enmType = HostNetworkInterfaceType_Bridged;
305 else
306 enmType = HostNetworkInterfaceType_HostOnly;
307 queryIfaceSpeed(&Info);
308 ComObjPtr<HostNetworkInterface> IfObj;
309 IfObj.createObject();
310 if (SUCCEEDED(IfObj->init(szNICDesc, enmType, &Info)))
311 pList->push_back(IfObj);
312}
313
314static boolean_t vboxSolarisAddLinkHostIface(const char *pszIface, void *pvHostNetworkInterfaceList)
315{
316 /*
317 * Skip IPSEC interfaces. It's at IP level.
318 */
319 if (!strncmp(pszIface, RT_STR_TUPLE("ip.tun")))
320 return _B_FALSE;
321
322 /*
323 * Skip our own dynamic VNICs but don't skip VNIC templates.
324 * These names originate from VBoxNetFltBow-solaris.c, hardcoded here for now.
325 * .
326 * ASSUMES template name is longer than 'vboxvnic'.
327 */
328 if ( strncmp(pszIface, RT_STR_TUPLE(VBOXBOW_VNIC_TEMPLATE_NAME))
329 && !strncmp(pszIface, RT_STR_TUPLE("vboxvnic")))
330 return _B_FALSE;
331
332 /*
333 * Clip off the zone instance number from the interface name (if any).
334 */
335 char szIfaceName[128];
336 strcpy(szIfaceName, pszIface);
337 char *pszColon = (char *)memchr(szIfaceName, ':', sizeof(szIfaceName));
338 if (pszColon)
339 *pszColon = '\0';
340
341 /*
342 * Get the instance number from the interface name, then clip it off.
343 */
344 int cbInstance = 0;
345 size_t cbIface = strlen(szIfaceName);
346 const char *pszEnd = pszIface + cbIface - 1;
347 for (size_t i = 0; i < cbIface - 1; i++)
348 {
349 if (!RT_C_IS_DIGIT(*pszEnd))
350 break;
351 cbInstance++;
352 pszEnd--;
353 }
354
355 int Instance = atoi(pszEnd + 1);
356 strncpy(szIfaceName, pszIface, cbIface - cbInstance);
357 szIfaceName[cbIface - cbInstance] = '\0';
358
359 /*
360 * Add the interface.
361 */
362 vboxSolarisAddHostIface(szIfaceName, Instance, pvHostNetworkInterfaceList);
363
364 /*
365 * Continue walking...
366 */
367 return _B_FALSE;
368}
369
370static bool vboxSolarisSortNICList(const ComObjPtr<HostNetworkInterface> Iface1, const ComObjPtr<HostNetworkInterface> Iface2)
371{
372 Bstr Iface1Str;
373 (*Iface1).COMGETTER(Name) (Iface1Str.asOutParam());
374
375 Bstr Iface2Str;
376 (*Iface2).COMGETTER(Name) (Iface2Str.asOutParam());
377
378 return Iface1Str < Iface2Str;
379}
380
381static bool vboxSolarisSameNIC(const ComObjPtr<HostNetworkInterface> Iface1, const ComObjPtr<HostNetworkInterface> Iface2)
382{
383 Bstr Iface1Str;
384 (*Iface1).COMGETTER(Name) (Iface1Str.asOutParam());
385
386 Bstr Iface2Str;
387 (*Iface2).COMGETTER(Name) (Iface2Str.asOutParam());
388
389 return (Iface1Str == Iface2Str);
390}
391
392static int vboxSolarisAddPhysHostIface(di_node_t Node, di_minor_t Minor, void *pvHostNetworkInterfaceList)
393{
394 NOREF(Minor);
395
396 char *pszDriverName = di_driver_name(Node);
397 int Instance = di_instance(Node);
398
399 /*
400 * Skip aggregations.
401 */
402 if (!strcmp(pszDriverName, "aggr"))
403 return DI_WALK_CONTINUE;
404
405 /*
406 * Skip softmacs.
407 */
408 if (!strcmp(pszDriverName, "softmac"))
409 return DI_WALK_CONTINUE;
410
411 /*
412 * Driver names doesn't always imply the same link name probably since
413 * S11's vanity names by default (e.g. highly descriptive "net0") names
414 * was introduced. Try opening the link to find out if it really exists.
415 *
416 * This weeds out listing of "e1000g0" as a valid interface on my S11.2
417 * Dell Optiplex box.
418 */
419 if (VBoxSolarisLibDlpiFound())
420 {
421 /** @todo should we try also opening "linkname+instance"? */
422 dlpi_handle_t hLink;
423 if (g_pfnLibDlpiOpen(pszDriverName, &hLink, 0) != DLPI_SUCCESS)
424 return DI_WALK_CONTINUE;
425 g_pfnLibDlpiClose(hLink);
426 }
427
428 vboxSolarisAddHostIface(pszDriverName, Instance, pvHostNetworkInterfaceList);
429 return DI_WALK_CONTINUE;
430}
431
432int NetIfList(std::list<ComObjPtr<HostNetworkInterface> > &list)
433{
434 /*
435 * Use libdevinfo for determining all physical interfaces.
436 */
437 di_node_t Root;
438 Root = di_init("/", DINFOCACHE);
439 if (Root != DI_NODE_NIL)
440 {
441 di_walk_minor(Root, DDI_NT_NET, 0 /* flag */, &list, vboxSolarisAddPhysHostIface);
442 di_fini(Root);
443 }
444
445 /*
446 * Use libdlpi for determining all DLPI interfaces.
447 */
448 if (VBoxSolarisLibDlpiFound())
449 g_pfnLibDlpiWalk(vboxSolarisAddLinkHostIface, &list, 0);
450
451 /*
452 * This gets only the list of all plumbed logical interfaces.
453 * This is needed for zones which cannot access the device tree
454 * and in this case we just let them use the list of plumbed interfaces
455 * on the zone.
456 */
457 int Sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
458 if (Sock > 0)
459 {
460 struct lifnum IfNum;
461 RT_ZERO(IfNum);
462 IfNum.lifn_family = AF_INET;
463 int rc = ioctl(Sock, SIOCGLIFNUM, &IfNum);
464 if (!rc)
465 {
466 int cIfaces = RT_MIN(1024, IfNum.lifn_count); /* sane limit */
467 size_t cbIfaces = (unsigned)RT_MAX(cIfaces, 1) * sizeof(struct lifreq);
468 struct lifreq *paIfaces = (struct lifreq *)RTMemTmpAlloc(cbIfaces);
469 if (paIfaces)
470 {
471 struct lifconf IfConfig;
472 RT_ZERO(IfConfig);
473 IfConfig.lifc_family = AF_INET;
474 IfConfig.lifc_len = (int)cbIfaces;
475 IfConfig.lifc_buf = (caddr_t)paIfaces;
476 rc = ioctl(Sock, SIOCGLIFCONF, &IfConfig);
477 if (!rc)
478 {
479 for (int i = 0; i < cIfaces; i++)
480 {
481 /*
482 * Skip loopback interfaces.
483 */
484 if (!strncmp(paIfaces[i].lifr_name, RT_STR_TUPLE("lo")))
485 continue;
486
487#if 0
488 rc = ioctl(Sock, SIOCGLIFADDR, &(paIfaces[i]));
489 if (rc >= 0)
490 {
491 memcpy(Info.IPAddress.au8, ((struct sockaddr *)&paIfaces[i].lifr_addr)->sa_data,
492 sizeof(Info.IPAddress.au8));
493 // SIOCGLIFNETMASK
494 struct arpreq ArpReq;
495 memcpy(&ArpReq.arp_pa, &paIfaces[i].lifr_addr, sizeof(struct sockaddr_in));
496
497 /*
498 * We might fail if the interface has not been assigned an IP address.
499 * That doesn't matter; as long as it's plumbed we can pick it up.
500 * But, if it has not acquired an IP address we cannot obtain it's MAC
501 * address this way, so we just use all zeros there.
502 */
503 rc = ioctl(Sock, SIOCGARP, &ArpReq);
504 if (rc >= 0)
505 memcpy(&Info.MACAddress, ArpReq.arp_ha.sa_data, sizeof(Info.MACAddress));
506
507 char szNICDesc[LIFNAMSIZ + 256];
508 char *pszIface = paIfaces[i].lifr_name;
509 strcpy(szNICDesc, pszIface);
510
511 vboxSolarisAddLinkHostIface(pszIface, &list);
512 }
513#endif
514
515 vboxSolarisAddLinkHostIface(paIfaces[i].lifr_name, &list);
516 }
517 }
518 RTMemTmpFree(paIfaces);
519 }
520 }
521 close(Sock);
522 }
523
524 /*
525 * Weed out duplicates caused by dlpi_walk inconsistencies across Nevadas.
526 */
527 list.sort(vboxSolarisSortNICList);
528 list.unique(vboxSolarisSameNIC);
529
530 return VINF_SUCCESS;
531}
532
533#else
534int NetIfList(std::list <ComObjPtr<HostNetworkInterface> > &list)
535{
536 return VERR_NOT_IMPLEMENTED;
537}
538#endif
539
540int NetIfGetConfigByName(PNETIFINFO pInfo)
541{
542 NOREF(pInfo);
543 return VERR_NOT_IMPLEMENTED;
544}
545
546/**
547 * Retrieve the physical link speed in megabits per second. If the interface is
548 * not up or otherwise unavailable the zero speed is returned.
549 *
550 * @returns VBox status code.
551 *
552 * @param pcszIfName Interface name.
553 * @param puMbits Where to store the link speed.
554 */
555int NetIfGetLinkSpeed(const char *pcszIfName, uint32_t *puMbits)
556{
557 *puMbits = kstatGet(pcszIfName);
558 return VINF_SUCCESS;
559}
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