NetIf-darwin.cpp revision 22db201c588c7242f5f3cd47d999225cefad6475
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/* $Id$ */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/** @file
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Main - NetIfList, Darwin implementation.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/*
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * available from http://www.virtualbox.org. This file is free software;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * General Public License (GPL) as published by the Free Software
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * additional information or have any questions.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/*******************************************************************************
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync* Header Files *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync*******************************************************************************/
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/*
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Deal with conflicts first.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * PVM - BSD mess, that FreeBSD has correct a long time ago.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * iprt/types.h before sys/param.h - prevents UINT32_C and friends.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/types.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <sys/param.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#undef PVM
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync#define LOG_GROUP LOG_GROUP_MAIN
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/err.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/alloc.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <string.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <sys/socket.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <sys/ioctl.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <sys/sysctl.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <netinet/in.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <net/if.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <net/if_dl.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <net/if_types.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <net/route.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <ifaddrs.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <errno.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <unistd.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <list>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include "HostNetworkInterfaceImpl.h"
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include "netif.h"
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include "iokit.h"
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include "Logging.h"
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#if 0
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsyncint NetIfList(std::list <ComObjPtr <HostNetworkInterface> > &list)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync{
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (sock < 0)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Log(("NetIfList: socket() -> %d\n", errno));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return NULL;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync struct ifaddrs *IfAddrs, *pAddr;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync int rc = getifaddrs(&IfAddrs);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (rc)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync close(sock);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Log(("NetIfList: getifaddrs() -> %d\n", rc));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return VERR_INTERNAL_ERROR;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync PDARWINETHERNIC pEtherNICs = DarwinGetEthernetControllers();
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync while (pEtherNICs)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync size_t cbNameLen = strlen(pEtherNICs->szName) + 1;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync PNETIFINFO pNew = (PNETIFINFO)RTMemAllocZ(RT_OFFSETOF(NETIFINFO, szName[cbNameLen]));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->MACAddress = pEtherNICs->Mac;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->enmMediumType = NETIF_T_ETHERNET;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->Uuid = pEtherNICs->Uuid;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(sizeof(pNew->szShortName) > sizeof(pEtherNICs->szBSDName));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync memcpy(pNew->szShortName, pEtherNICs->szBSDName, sizeof(pEtherNICs->szBSDName));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->szShortName[sizeof(pEtherNICs->szBSDName)] = '\0';
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync memcpy(pNew->szName, pEtherNICs->szName, cbNameLen);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync struct ifreq IfReq;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync strcpy(IfReq.ifr_name, pNew->szShortName);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (ioctl(sock, SIOCGIFFLAGS, &IfReq) < 0)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Log(("NetIfList: ioctl(SIOCGIFFLAGS) -> %d\n", errno));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->enmStatus = NETIF_S_UNKNOWN;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync else
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->enmStatus = (IfReq.ifr_flags & IFF_UP) ? NETIF_S_UP : NETIF_S_DOWN;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync for (pAddr = IfAddrs; pAddr != NULL; pAddr = pAddr->ifa_next)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (strcmp(pNew->szShortName, pAddr->ifa_name))
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync continue;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync struct sockaddr_in *pIPAddr, *pIPNetMask;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync struct sockaddr_in6 *pIPv6Addr, *pIPv6NetMask;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync switch (pAddr->ifa_addr->sa_family)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync case AF_INET:
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (pNew->IPAddress.u)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync break;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pIPAddr = (struct sockaddr_in *)pAddr->ifa_addr;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(sizeof(pNew->IPAddress) == sizeof(pIPAddr->sin_addr));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->IPAddress.u = pIPAddr->sin_addr.s_addr;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pIPNetMask = (struct sockaddr_in *)pAddr->ifa_netmask;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(pIPNetMask->sin_family == AF_INET);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(sizeof(pNew->IPNetMask) == sizeof(pIPNetMask->sin_addr));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->IPNetMask.u = pIPNetMask->sin_addr.s_addr;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync break;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync case AF_INET6:
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (pNew->IPv6Address.s.Lo || pNew->IPv6Address.s.Hi)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync break;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pIPv6Addr = (struct sockaddr_in6 *)pAddr->ifa_addr;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(sizeof(pNew->IPv6Address) == sizeof(pIPv6Addr->sin6_addr));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync memcpy(pNew->IPv6Address.au8,
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pIPv6Addr->sin6_addr.__u6_addr.__u6_addr8,
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync sizeof(pNew->IPv6Address));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pIPv6NetMask = (struct sockaddr_in6 *)pAddr->ifa_netmask;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(pIPv6NetMask->sin6_family == AF_INET6);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(sizeof(pNew->IPv6NetMask) == sizeof(pIPv6NetMask->sin6_addr));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync memcpy(pNew->IPv6NetMask.au8,
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pIPv6NetMask->sin6_addr.__u6_addr.__u6_addr8,
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync sizeof(pNew->IPv6NetMask));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync break;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync ComObjPtr<HostNetworkInterface> IfObj;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync IfObj.createObject();
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (SUCCEEDED(IfObj->init(Bstr(pEtherNICs->szName), HostNetworkInterfaceType_Bridged, pNew)))
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync list.push_back(IfObj);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTMemFree(pNew);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /* next, free current */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync void *pvFree = pEtherNICs;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pEtherNICs = pEtherNICs->pNext;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTMemFree(pvFree);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync freeifaddrs(IfAddrs);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync close(sock);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return VINF_SUCCESS;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync}
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#else
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#define ROUNDUP(a) \
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsyncvoid extractAddresses(int iAddrMask, caddr_t cp, caddr_t cplim, PNETIFINFO pInfo)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync{
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync struct sockaddr *sa, *addresses[RTAX_MAX];
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync for (int i = 0; i < RTAX_MAX && cp < cplim; i++) {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (!(iAddrMask & (1 << i)))
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync continue;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync sa = (struct sockaddr *)cp;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync addresses[i] = sa;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync ADVANCE(cp, sa);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync switch (addresses[RTAX_IFA]->sa_family)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync case AF_INET:
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (!pInfo->IPAddress.u)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pInfo->IPAddress.u = ((struct sockaddr_in *)addresses[RTAX_IFA])->sin_addr.s_addr;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pInfo->IPNetMask.u = ((struct sockaddr_in *)addresses[RTAX_NETMASK])->sin_addr.s_addr;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync break;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync case AF_INET6:
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (!pInfo->IPv6Address.s.Lo && !pInfo->IPv6Address.s.Hi)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync memcpy(pInfo->IPv6Address.au8,
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync ((struct sockaddr_in6 *)addresses[RTAX_IFA])->sin6_addr.__u6_addr.__u6_addr8,
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync sizeof(pInfo->IPv6Address));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync memcpy(pInfo->IPv6NetMask.au8,
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync ((struct sockaddr_in6 *)addresses[RTAX_NETMASK])->sin6_addr.__u6_addr.__u6_addr8,
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync sizeof(pInfo->IPv6NetMask));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync break;
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync default:
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Log(("NetIfList: Unsupported address family: %u\n", sa->sa_family));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync break;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync}
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsyncint NetIfList(std::list <ComObjPtr <HostNetworkInterface> > &list)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync{
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync int rc = VINF_SUCCESS;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync size_t cbNeeded;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync char *pBuf, *pNext;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync int aiMib[6];
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync aiMib[0] = CTL_NET;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync aiMib[1] = PF_ROUTE;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync aiMib[2] = 0;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync aiMib[3] = 0; /* address family */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync aiMib[4] = NET_RT_IFLIST;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync aiMib[5] = 0;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (sysctl(aiMib, 6, NULL, &cbNeeded, NULL, 0) < 0)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Log(("NetIfList: Failed to get estimate for list size (errno=%d).\n", errno));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return RTErrConvertFromErrno(errno);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if ((pBuf = (char*)malloc(cbNeeded)) == NULL)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return VERR_NO_MEMORY;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (sysctl(aiMib, 6, pBuf, &cbNeeded, NULL, 0) < 0)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync free(pBuf);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Log(("NetIfList: Failed to retrieve interface table (errno=%d).\n", errno));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return RTErrConvertFromErrno(errno);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (sock < 0)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync free(pBuf);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Log(("NetIfList: socket() -> %d\n", errno));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return RTErrConvertFromErrno(errno);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync PDARWINETHERNIC pNIC;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync PDARWINETHERNIC pEtherNICs = DarwinGetEthernetControllers();
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync char *pEnd = pBuf + cbNeeded;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync for (pNext = pBuf; pNext < pEnd;)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync struct if_msghdr *pIfMsg = (struct if_msghdr *)pNext;
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (pIfMsg->ifm_type != RTM_IFINFO)
{
Log(("NetIfList: Got message %u while expecting %u.\n",
pIfMsg->ifm_type, RTM_IFINFO));
rc = VERR_INTERNAL_ERROR;
break;
}
struct sockaddr_dl *pSdl = (struct sockaddr_dl *)(pIfMsg + 1);
size_t cbNameLen = pSdl->sdl_nlen + 1;
for (pNIC = pEtherNICs; pNIC; pNIC = pNIC->pNext)
if (!strncmp(pSdl->sdl_data, pNIC->szBSDName, pSdl->sdl_len))
{
cbNameLen = strlen(pEtherNICs->szName) + 1;
break;
}
PNETIFINFO pNew = (PNETIFINFO)RTMemAllocZ(RT_OFFSETOF(NETIFINFO, szName[cbNameLen]));
if (!pNew)
{
rc = VERR_NO_MEMORY;
break;
}
memcpy(pNew->MACAddress.au8, LLADDR(pSdl), sizeof(pNew->MACAddress.au8));
pNew->enmMediumType = NETIF_T_ETHERNET;
Assert(sizeof(pNew->szShortName) >= cbNameLen);
memcpy(pNew->szShortName, pSdl->sdl_data, cbNameLen);
/*
* If we found the adapter in the list returned by
* DarwinGetEthernetControllers() copy the name and UUID from there.
*/
if (pNIC)
{
memcpy(pNew->szName, pNIC->szName, cbNameLen);
pNew->Uuid = pNIC->Uuid;
}
else
{
memcpy(pNew->szName, pSdl->sdl_data, cbNameLen);
/* Generate UUID from name and MAC address. */
RTUUID uuid;
RTUuidClear(&uuid);
memcpy(&uuid, pNew->szShortName, RT_MIN(cbNameLen, sizeof(uuid)));
uuid.Gen.u8ClockSeqHiAndReserved = (uuid.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80;
uuid.Gen.u16TimeHiAndVersion = (uuid.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000;
memcpy(uuid.Gen.au8Node, pNew->MACAddress.au8, sizeof(uuid.Gen.au8Node));
pNew->Uuid = uuid;
}
pNext += pIfMsg->ifm_msglen;
while (pNext < pEnd)
{
struct ifa_msghdr *pIfAddrMsg = (struct ifa_msghdr *)pNext;
if (pIfAddrMsg->ifam_type != RTM_NEWADDR)
break;
extractAddresses(pIfAddrMsg->ifam_addrs, (char *)(pIfAddrMsg + 1), pIfAddrMsg->ifam_msglen + (char *)pIfAddrMsg, pNew);
pNext += pIfAddrMsg->ifam_msglen;
}
if (pSdl->sdl_type == IFT_ETHER)
{
struct ifreq IfReq;
strcpy(IfReq.ifr_name, pNew->szShortName);
if (ioctl(sock, SIOCGIFFLAGS, &IfReq) < 0)
{
Log(("NetIfList: ioctl(SIOCGIFFLAGS) -> %d\n", errno));
pNew->enmStatus = NETIF_S_UNKNOWN;
}
else
pNew->enmStatus = (IfReq.ifr_flags & IFF_UP) ? NETIF_S_UP : NETIF_S_DOWN;
HostNetworkInterfaceType_T enmType;
if (strncmp("vboxnet", pNew->szName, 7))
enmType = HostNetworkInterfaceType_Bridged;
else
enmType = HostNetworkInterfaceType_HostOnly;
ComObjPtr<HostNetworkInterface> IfObj;
IfObj.createObject();
if (SUCCEEDED(IfObj->init(Bstr(pNew->szName), enmType, pNew)))
list.push_back(IfObj);
}
RTMemFree(pNew);
}
for (pNIC = pEtherNICs; pNIC;)
{
void *pvFree = pNIC;
pNIC = pNIC->pNext;
RTMemFree(pvFree);
}
close(sock);
free(pBuf);
return rc;
}
#endif