ultimatepp/bazaar/ProtectClient/NetworkAdapter_POSIX.cpp
micio d1a78c5335 Bazaar/Protect : split hardware encription, client and server codes
git-svn-id: svn://ultimatepp.org/upp/trunk@6171 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2013-07-06 13:17:40 +00:00

221 lines
5 KiB
C++

#include "NetworkAdapter.h"
#ifdef PLATFORM_POSIX
#include <sys/ioctl.h>
#include <net/if.h>
Vector<NetworkAdapter> GetNetworkAdaptersInfo(void)
{
Vector<NetworkAdapter> res;
// this is used to avoid adding duplicate entries
// with same MAC and differing only by adapter family
// (posix may return same interface twice for IPV4 and IPV6)
Index<String>macs;
// Get a socket handle
int sck = socket(PF_INET, SOCK_DGRAM, 0);
if(sck < 0)
return res;
// get a list of all available interfaces
// as buffer size is unknown, we check results and retry as needed
int bufSize = 4096;
struct ifconf ifc = { 0 };
caddr_t buf;
for(int iTry = 0; iTry < 4; iTry++)
{
buf = (caddr_t)new byte[bufSize];
ifc.ifc_len = bufSize;
ifc.ifc_buf = buf;
// get interfaces list,
if (ioctl(sck, SIOCGIFCONF, &ifc) < 0)
{
// failed, free buffer and leave
delete[] buf;
close(sck);
Cerr() << "Failed to get interfaces list\n";
return res;
}
// check if buffer size was big enough
if(ifc.ifc_len != bufSize)
break;
// not big enough, double size and retry
delete[] buf;
bufSize *= 2;
if(iTry >= 3)
{
Cerr() << "Max buffer size too small\n";
close(sck);
return res;
}
}
// iterate through returned data fill result vector
int nIfaces = ifc.ifc_len / sizeof(struct ifreq);
struct ifreq *iface = ifc.ifc_req;
for(int iIface = 0; iIface < nIfaces; iIface++)
{
// platform dependent code to get MAC address
String MAC;
// LINUX
#ifdef SIOCGIFHWADDR
if(ioctl(sck, SIOCGIFHWADDR, iface) < 0)
{
// couldn't get MAC, just leave it empty
continue;
}
MAC = Format("%02x:%02x:%02x:%02x:%02x:%02x",
(byte)iface->ifr_hwaddr.sa_data[0],
(byte)iface->ifr_hwaddr.sa_data[1],
(byte)iface->ifr_hwaddr.sa_data[2],
(byte)iface->ifr_hwaddr.sa_data[3],
(byte)iface->ifr_hwaddr.sa_data[4],
(byte)iface->ifr_hwaddr.sa_data[5]
);
// SOLARIS AND SysVR4 systems
#elif SIOCGENADDR
if (ioctl(sck, SIOCGENADDR, iface) < 0)
{
// couldn't get MAC, just leave it empty
continue;
}
MAC = Format("%02x:%02x:%02x:%02x:%02x:%02x",
(byte)iface->ifr_enaddr[0],
(byte)iface->ifr_enaddr[1],
(byte)iface->ifr_enaddr[2],
(byte)iface->ifr_enaddr[3],
(byte)iface->ifr_enaddr[4],
(byte)iface->ifr_enaddr[5]
);
// Mac OSX and other BSD
#elif __MACH__ || __NetBSD__ || __OpenBSD__ || __FreeBSD__
int mib[6];
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
mib[5] = if_nametoindex(iface->ifr_name);
if (mib[5] == 0)
// nameless interface ? skip
continue;
int len = 0;
if (sysctl(mib, 6, NULL, (size_t*)&len, NULL, 0) != 0)
{
// sysctl error, just leave MAC empty
continue;
}
char *macbuf = new char[len];
if (!macbuf)
{
// can't allocat buffer, skip this MAC
continue;
}
if (sysctl(mib, 6, macbuf, (size_t*)&len, NULL, 0) != 0)
{
delete[] macbuf;
continue;
}
struct if_msghdr *ifm = (struct if_msghdr *)macbuf;
struct sockaddr_dl *sdl = (struct sockaddr_dl *)(ifm + 1);
byte ptr[] = (byte **)LLADDR(sdl);
MAC = Format("%02x:%02x:%02x:%02x:%02x:%02x",
ptr[0],
ptr[1],
ptr[2],
ptr[3],
ptr[4],
ptr[5]
);
delete[] macbuf;
#else
#error OS Distribution Not Recognized
#endif
// remove MAC addresses of 6 nulls...
// loopback interface, for example, don't have a MAC
if(MAC == "00:00:00:00:00:00")
MAC.Clear();
// check out if we've already stored this MAC
// in case, we just skip the interface
if(!MAC.IsEmpty() && macs.Find(MAC) >= 0)
continue;
macs.Add(MAC);
NetworkAdapter &adapter = res.Add();
// set MAC in result
adapter.mac = MAC;
// get interface name
adapter.fullname = iface->ifr_name;
// set interface type from name
if(adapter.fullname.StartsWith("eth"))
adapter.type = "ETHERNET";
else if(adapter.fullname.StartsWith("lo"))
adapter.type = "SOFTWARE_LOOPBACK";
else if(adapter.fullname.StartsWith("ppp"))
adapter.type = "MODEM";
else if(adapter.fullname.StartsWith("hci"))
adapter.type = "BLUETOOTH";
else if(adapter.fullname.StartsWith("tr"))
adapter.type = "TOKENRING";
else if(
adapter.fullname.StartsWith("vbox") ||
adapter.fullname.StartsWith("wifi") ||
adapter.fullname.StartsWith("ath")
)
adapter.type = "VIRTUALBOX";
else if(adapter.fullname.StartsWith("wlan"))
adapter.type = "IEEE80211";
else
adapter.type = "OTHER";
/*
// get interface family and set description with it
// (may be of some use...)
adapter.description = "Family: ";
int family = iface->ifr_addr.sa_family;
switch(family)
{
case AF_PACKET:
adapter.description += "AF_PACKET";
break;
case AF_INET :
adapter.description += "AF_INET";
break;
case AF_INET6 :
adapter.description += "AF_INET6";
break;
default:
adapter.description += "UNKNOWN";
}
*/
// description as name... we dont' have any better choice
adapter.description = adapter.fullname;
iface++;
}
delete[] buf;
close(sck);
return res;
}
#endif