module NetworkInterface
Constants
- AF_12844
- AF_APPLETALK
- AF_ASH
- AF_ATM
- AF_ATMPVC
- AF_ATMSVC
- AF_AX25
- AF_BAN
- AF_BLUETOOTH
- AF_BRIDGE
- AF_CCITT
- AF_CHAOS
- AF_CLUSTER
- AF_CNT
- AF_COIP
- AF_DATAKIT
- AF_DECnet
- AF_DLI
- AF_ECMA
- AF_ECONET
- AF_FILE
- AF_FIREFOX
- AF_HYLINK
- AF_IMPLINK
- AF_INET
- AF_INET6
- AF_IPX
- AF_IRDA
- AF_ISDN
- AF_ISO
- AF_KEY
- AF_LAT
- AF_LINK
- AF_NATM
- AF_NDRV
- AF_NETBEUI
- AF_NETBIOS
- AF_NETDES
- AF_NETGRAPH
- AF_NETLINK
- AF_NETROM
- AF_NS
- AF_PACKET
- AF_PPP
- AF_PPPOX
- AF_PUP
- AF_ROSE
- AF_ROUTE
- AF_SECURITY
- AF_SIP
- AF_SNA
- AF_SYSTEM
- AF_UNIX
- AF_UNKNOWN1
- AF_UNSPEC
- AF_VOICEVIEW
- AF_WANPIPE
- AF_X25
- VERSION
Public Class Methods
addresses(p1)
click to toggle source
VALUE
rbnetifaces_s_addresses (VALUE class, VALUE dev)
{
VALUE result;
int found = FALSE;
#if defined(WIN32)
PIP_ADAPTER_INFO pAdapterInfo = NULL;
PIP_ADAPTER_INFO pInfo = NULL;
ULONG ulBufferLength = 0;
DWORD dwRet;
PIP_ADDR_STRING str;
#elif HAVE_GETIFADDRS
struct ifaddrs *addrs = NULL;
struct ifaddrs *addr = NULL;
VALUE result2;
#elif HAVE_SOCKET_IOCTLS
int sock;
struct CNAME(ifreq) ifr;
char buffer[256];
int is_p2p = FALSE;
VALUE rbaddr = Qnil;
VALUE rbnetmask = Qnil;
VALUE rbbraddr = Qnil;
VALUE rbdstaddr = Qnil;
VALUE result2;
#endif
Check_Type(dev, T_STRING);
result = rb_hash_new();
#if defined(WIN32)
//First, retrieve the adapter information. We do this in a loop, in
//case someone adds or removes adapters in the meantime.
do
{
dwRet = GetAdaptersInfo(pAdapterInfo, &ulBufferLength);
if (dwRet == ERROR_BUFFER_OVERFLOW)
{
if (pAdapterInfo)
free (pAdapterInfo);
pAdapterInfo = (PIP_ADAPTER_INFO)malloc (ulBufferLength);
if (!pAdapterInfo)
{
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
return Qnil;
}
}
} while (dwRet == ERROR_BUFFER_OVERFLOW);
// If we failed, then fail in Ruby too
if (dwRet != ERROR_SUCCESS && dwRet != ERROR_NO_DATA)
{
if (pAdapterInfo)
free (pAdapterInfo);
rb_raise(rb_eRuntimeError, "Unable to obtain adapter information.");
return Qnil;
}
for (pInfo = pAdapterInfo; pInfo; pInfo = pInfo->Next)
{
char buffer[256];
//dev is the iface GUID on windows with "\\Device\\NPF_" prefix
int cmpAdapterNamelen = (MAX_ADAPTER_NAME_LENGTH + 4) + 12;
char cmpAdapterName[cmpAdapterNamelen];
int AdapterName_len = strlen(pInfo->AdapterName);
VALUE rbhardw = Qnil;
VALUE rbaddr = Qnil;
VALUE rbnetmask = Qnil;
VALUE rbbraddr = Qnil;
memset(cmpAdapterName, 0x00, cmpAdapterNamelen);
strncpy(cmpAdapterName, "\\Device\\NPF_", 12);
strncpy(cmpAdapterName + 12, pInfo->AdapterName, AdapterName_len);
if (strcmp (cmpAdapterName, StringValuePtr(dev)) != 0)
continue;
found = TRUE;
// Do the physical address
if (256 >= 3 * pInfo->AddressLength)
{
char *ptr = buffer;
unsigned n;
VALUE hash_hardw;
hash_hardw = rb_hash_new();
*ptr = '\0';
for (n = 0; n < pInfo->AddressLength; ++n)
{
sprintf (ptr, "%02x:", pInfo->Address[n] & 0xff);
ptr += 3;
}
*--ptr = '\0';
rbhardw = rb_str_new2(buffer);
rb_hash_aset(hash_hardw, rb_str_new2("addr"), rbhardw);
result = add_to_family(result, INT2FIX(AF_LINK), hash_hardw);
}
for (str = &pInfo->IpAddressList; str; str = str->Next)
{
VALUE result2;
result2 = rb_hash_new();
if(str->IpAddress.String)
rbaddr = rb_str_new2(str->IpAddress.String);
if(str->IpMask.String)
rbnetmask = rb_str_new2(str->IpMask.String);
//If this isn't the loopback interface, work out the broadcast
//address, for better compatibility with other platforms.
if (pInfo->Type != MIB_IF_TYPE_LOOPBACK)
{
unsigned long inaddr = inet_addr (str->IpAddress.String);
unsigned long inmask = inet_addr (str->IpMask.String);
struct in_addr in;
char *brstr;
in.S_un.S_addr = (inaddr | ~inmask) & 0xfffffffful;
brstr = inet_ntoa (in);
if (brstr)
rbbraddr = rb_str_new2(brstr);
}
if (rbaddr)
rb_hash_aset(result2, rb_str_new2("addr"), rbaddr);
if (rbnetmask)
rb_hash_aset(result2, rb_str_new2("netmask"), rbnetmask);
if (rbbraddr)
rb_hash_aset(result2, rb_str_new2("broadcast"), rbbraddr);
result = add_to_family(result, INT2FIX(AF_INET), result2);
}
} // for
free (pAdapterInfo);
#elif HAVE_GETIFADDRS
if (getifaddrs (&addrs) < 0)
{
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
}
for (addr = addrs; addr; addr = addr->ifa_next)
{
char buffer[256];
VALUE rbaddr = Qnil;
VALUE rbnetmask = Qnil;
VALUE rbbraddr = Qnil;
if (strcmp (addr->ifa_name, StringValuePtr(dev)) != 0)
continue;
/* Sometimes there are records without addresses (e.g. in the case of a
dial-up connection via ppp, which on Linux can have a link address
record with no actual address). We skip these as they aren't useful.
Thanks to Christian Kauhaus for reporting this issue. */
if (!addr->ifa_addr)
continue;
found = TRUE;
if (string_from_sockaddr (addr->ifa_addr, buffer, sizeof (buffer)) == 0)
rbaddr = rb_str_new2(buffer);
if (string_from_sockaddr (addr->ifa_netmask, buffer, sizeof (buffer)) == 0)
rbnetmask = rb_str_new2(buffer);
if (string_from_sockaddr (addr->ifa_broadaddr, buffer, sizeof (buffer)) == 0)
rbbraddr = rb_str_new2(buffer);
result2 = rb_hash_new();
if (rbaddr)
rb_hash_aset(result2, rb_str_new2("addr"), rbaddr);
if (rbnetmask)
rb_hash_aset(result2, rb_str_new2("netmask"), rbnetmask);
if (rbbraddr)
{
if (addr->ifa_flags & (IFF_POINTOPOINT | IFF_LOOPBACK))
rb_hash_aset(result2, rb_str_new2("peer"), rbbraddr);
else
rb_hash_aset(result2, rb_str_new2("broadcast"), rbbraddr);
}
if (rbaddr || rbnetmask || rbbraddr)
result = add_to_family(result, INT2FIX(addr->ifa_addr->sa_family), result2);
}
freeifaddrs (addrs);
#elif HAVE_SOCKET_IOCTLS
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
return Qnil;
}
strncpy (ifr.CNAME(ifr_name), StringValuePtr(dev), IFNAMSIZ);
#if HAVE_SIOCGIFHWADDR
if (ioctl (sock, SIOCGIFHWADDR, &ifr) == 0)
{
if (string_from_sockaddr (&(ifr.CNAME(ifr_addr)), buffer, sizeof (buffer)) == 0)
{
found = TRUE;
VALUE rbhardw = Qnil;
VALUE hash_hardw;
hash_hardw = rb_hash_new();
rbhardw = rb_str_new2(buffer);
rb_hash_aset(hash_hardw, rb_str_new2("addr"), rbhardw);
result = add_to_family(result, INT2FIX(AF_LINK), hash_hardw);
}
}
#endif
#if HAVE_SIOCGIFADDR
#if HAVE_SIOCGLIFNUM
if (ioctl (sock, SIOCGLIFADDR, &ifr) == 0)
{
#else
if (ioctl (sock, SIOCGIFADDR, &ifr) == 0)
{
#endif
if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0)
{
found = TRUE;
rbaddr = rb_str_new2(buffer);
}
}
#endif
#if HAVE_SIOCGIFNETMASK
#if HAVE_SIOCGLIFNUM
if (ioctl (sock, SIOCGLIFNETMASK, &ifr) == 0)
{
#else
if (ioctl (sock, SIOCGIFNETMASK, &ifr) == 0)
{
#endif
if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0)
{
found = TRUE;
rbnetmask = rb_str_new2(buffer);
}
}
#endif
#if HAVE_SIOCGIFFLAGS
#if HAVE_SIOCGLIFNUM
if (ioctl (sock, SIOCGLIFFLAGS, &ifr) == 0)
{
#else
if (ioctl (sock, SIOCGIFFLAGS, &ifr) == 0)
{
#endif
if (ifr.CNAME(ifr_flags) & IFF_POINTOPOINT)
{
is_p2p = TRUE;
}
}
#endif
#if HAVE_SIOCGIFBRDADDR
#if HAVE_SIOCGLIFNUM
if (!is_p2p && ioctl (sock, SIOCGLIFBRDADDR, &ifr) == 0)
{
#else
if (!is_p2p && ioctl (sock, SIOCGIFBRDADDR, &ifr) == 0)
{
#endif
if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0)
{
found = TRUE;
rbbraddr = rb_str_new2(buffer);
}
}
#endif
#if HAVE_SIOCGIFDSTADDR
#if HAVE_SIOCGLIFNUM
if (is_p2p && ioctl (sock, SIOCGLIFBRDADDR, &ifr) == 0)
{
#else
if (is_p2p && ioctl (sock, SIOCGIFBRDADDR, &ifr) == 0)
{
#endif
if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0)
{
found = TRUE;
rbdstaddr = rb_str_new2(buffer);
}
}
#endif
result2 = rb_hash_new();
if (rbaddr)
rb_hash_aset(result2, rb_str_new2("addr"), rbaddr);
if (rbnetmask)
rb_hash_aset(result2, rb_str_new2("netmask"), rbnetmask);
if (rbbraddr)
rb_hash_aset(result2, rb_str_new2("broadcast"), rbbraddr);
if (rbdstaddr)
rb_hash_aset(result2, rb_str_new2("peer"), rbbraddr);
if (rbaddr || rbnetmask || rbbraddr || rbdstaddr)
result = add_to_family(result, INT2FIX(AF_INET), result2);
close (sock);
#endif /* HAVE_SOCKET_IOCTLS */
if (found)
return result;
else
return Qnil;
}
interface_info(p1)
click to toggle source
informations
VALUE
rbnetifaces_s_interface_info (VALUE self, VALUE dev)
{
VALUE result = Qnil;
#if defined(WIN32)
PIP_ADAPTER_INFO pAdapterInfo = NULL;
PIP_ADAPTER_INFO pInfo = NULL;
ULONG ulBufferLength = 0;
DWORD dwRet;
// First, retrieve the adapter information
do {
dwRet = GetAdaptersInfo(pAdapterInfo, &ulBufferLength);
if (dwRet == ERROR_BUFFER_OVERFLOW)
{
if (pAdapterInfo)
free (pAdapterInfo);
pAdapterInfo = (PIP_ADAPTER_INFO)malloc (ulBufferLength);
if (!pAdapterInfo)
{
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
}
}
} while (dwRet == ERROR_BUFFER_OVERFLOW);
// If we failed, then fail in Ruby too
if (dwRet != ERROR_SUCCESS && dwRet != ERROR_NO_DATA)
{
if (pAdapterInfo)
free (pAdapterInfo);
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
return Qnil;
}
if (dwRet == ERROR_NO_DATA)
{
free (pAdapterInfo);
return result;
}
for (pInfo = pAdapterInfo; pInfo; pInfo = pInfo->Next)
{
// registry name location
const char* prefix = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
const char* sufix = "\\Connection";
int prefix_len, sufix_len, adaptername_len;
char* keypath = NULL;
HKEY hKey;
LONG lRet = 0;
LPBYTE buffer = NULL;
DWORD dwSize = 0;
//dev is the iface GUID on windows with "\\Device\\NPF_" prefix
int cmpAdapterNamelen = (MAX_ADAPTER_NAME_LENGTH + 4) + 12;
char cmpAdapterName[cmpAdapterNamelen];
int AdapterName_len = strlen(pInfo->AdapterName);
memset(cmpAdapterName, 0x00, cmpAdapterNamelen);
strncpy(cmpAdapterName, "\\Device\\NPF_", 12);
strncpy(cmpAdapterName + 12, pInfo->AdapterName, AdapterName_len);
if (strcmp (cmpAdapterName, StringValuePtr(dev)) != 0)
continue;
result = rb_hash_new();
rb_hash_aset(result, rb_str_new2("description"), rb_str_new2(pInfo->Description));
rb_hash_aset(result, rb_str_new2("guid"), rb_str_new2(pInfo->AdapterName));
// Get the name from the registry
prefix_len = strlen(prefix);
sufix_len = strlen(sufix);
adaptername_len = strlen(pInfo->AdapterName);
keypath = malloc(prefix_len + sufix_len + adaptername_len + 1);
memset(keypath, 0x00, prefix_len + sufix_len + adaptername_len + 1);
strncpy(keypath, prefix, prefix_len);
strncpy(keypath + prefix_len, pInfo->AdapterName, adaptername_len);
strncpy(keypath + prefix_len + adaptername_len, sufix, sufix_len);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keypath, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
// obtain current value size
lRet = RegQueryValueEx(hKey, "Name", NULL, NULL, NULL, &dwSize);
if (dwSize > 0 && ERROR_SUCCESS == lRet)
{
buffer = malloc((dwSize * sizeof(BYTE)) + 4);
memset(buffer, 0x00, (dwSize * sizeof(BYTE)) + 4);
lRet = RegQueryValueEx(hKey, "Name", NULL, NULL, buffer, &dwSize);
if (ERROR_SUCCESS == lRet)
{
rb_hash_aset(result, rb_str_new2("name"), rb_str_new2(buffer));
}
else
{
rb_hash_aset(result, rb_str_new2("name"), rb_str_new2(""));
}
free(buffer);
}
else
{
rb_hash_aset(result, rb_str_new2("name"), rb_str_new2(""));
}
RegCloseKey(hKey);
}
else
{
rb_hash_aset(result, rb_str_new2("name"), rb_str_new2(""));
}
free(keypath);
}
free (pAdapterInfo);
#endif
return result;
}
interfaces()
click to toggle source
VALUE
rbnetifaces_s_interfaces (VALUE self)
{
VALUE result;
#if defined(WIN32)
PIP_ADAPTER_INFO pAdapterInfo = NULL;
PIP_ADAPTER_INFO pInfo = NULL;
ULONG ulBufferLength = 0;
DWORD dwRet;
#elif HAVE_GETIFADDRS
const char *prev_name = NULL;
struct ifaddrs *addrs = NULL;
struct ifaddrs *addr = NULL;
#elif HAVE_SIOCGIFCONF
const char *prev_name = NULL;
int fd, len, n;
struct CNAME(ifconf) ifc;
struct CNAME(ifreq) *pfreq;
#endif
result = rb_ary_new();
#if defined(WIN32)
// First, retrieve the adapter information
do {
dwRet = GetAdaptersInfo(pAdapterInfo, &ulBufferLength);
if (dwRet == ERROR_BUFFER_OVERFLOW)
{
if (pAdapterInfo)
free (pAdapterInfo);
pAdapterInfo = (PIP_ADAPTER_INFO)malloc (ulBufferLength);
if (!pAdapterInfo)
{
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
}
}
} while (dwRet == ERROR_BUFFER_OVERFLOW);
// If we failed, then fail in Ruby too
if (dwRet != ERROR_SUCCESS && dwRet != ERROR_NO_DATA)
{
if (pAdapterInfo)
free (pAdapterInfo);
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
return Qnil;
}
if (dwRet == ERROR_NO_DATA)
{
free (pAdapterInfo);
return result;
}
for (pInfo = pAdapterInfo; pInfo; pInfo = pInfo->Next)
{
int outputnamelen = (MAX_ADAPTER_NAME_LENGTH + 4) + 12;
char outputname[outputnamelen];
int AdapterName_len = strlen(pInfo->AdapterName);
VALUE ifname;
memset(outputname, 0x00, outputnamelen);
strncpy(outputname, "\\Device\\NPF_", 12);
strncpy(outputname + 12, pInfo->AdapterName, AdapterName_len);
ifname = rb_str_new2(outputname) ;
if(!rb_ary_includes(result, ifname))
rb_ary_push(result, ifname);
}
free (pAdapterInfo);
#elif HAVE_GETIFADDRS
if (getifaddrs (&addrs) < 0)
{
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
}
for (addr = addrs; addr; addr = addr->ifa_next)
{
if (!prev_name || strncmp (addr->ifa_name, prev_name, IFNAMSIZ) != 0)
{
VALUE ifname = rb_str_new2(addr->ifa_name);
if(!rb_ary_includes(result, ifname))
rb_ary_push(result, ifname);
prev_name = addr->ifa_name;
}
}
freeifaddrs (addrs);
#elif HAVE_SIOCGIFCONF
fd = socket (AF_INET, SOCK_DGRAM, 0);
len = -1;
if (fd < 0) {
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
return Qnil;
}
// Try to find out how much space we need
#if HAVE_SIOCGSIZIFCONF
if (ioctl (fd, SIOCGSIZIFCONF, &len) < 0)
len = -1;
#elif HAVE_SIOCGLIFNUM
#error This code need to be checked first
/*
{ struct lifnum lifn;
lifn.lifn_family = AF_UNSPEC;
lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
ifc.lifc_family = AF_UNSPEC;
ifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
if (ioctl (fd, SIOCGLIFNUM, (char *)&lifn) < 0)
len = -1;
else
len = lifn.lifn_count;
}
*/
#endif
// As a last resort, guess
if (len < 0)
len = 64;
ifc.CNAME(ifc_len) = len * sizeof (struct CNAME(ifreq));
ifc.CNAME(ifc_buf) = malloc (ifc.CNAME(ifc_len));
if (!ifc.CNAME(ifc_buf)) {
close (fd);
rb_raise(rb_eRuntimeError, "Not enough memory");
return Qnil;
}
#if HAVE_SIOCGLIFNUM
if (ioctl (fd, SIOCGLIFCONF, &ifc) < 0) {
#else
if (ioctl (fd, SIOCGIFCONF, &ifc) < 0) {
#endif
free (ifc.CNAME(ifc_req));
close (fd);
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
return Qnil;
}
pfreq = ifc.CNAME(ifc_req);
for (n = 0; n < ifc.CNAME(ifc_len)/sizeof(struct CNAME(ifreq));n++,pfreq++)
{
if (!prev_name || strncmp (prev_name, pfreq->CNAME(ifr_name), IFNAMSIZ) != 0)
{
VALUE ifname = rb_str_new2(pfreq->CNAME(ifr_name));
if(!rb_ary_includes(result, ifname))
rb_ary_push(result, ifname);
prev_name = pfreq->CNAME(ifr_name);
}
}
free (ifc.CNAME(ifc_buf));
close (fd);
#endif //
return result;
}