pcaprub : -add several native function to get all the informations about the network intefaces, original code is a python c extension called netifaces
-add also some initial wrappers into capture mixin -Fixes #4376 git-svn-id: file:///home/svn/framework3/trunk@12799 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
8600bc5bef
commit
40f06cd3e1
|
@ -16,3 +16,28 @@ The latest version can be obtained from Subversion:
|
|||
|
||||
The Metasploit Project also provides a Subversion repository:
|
||||
svn checkout http://metasploit.com/svn/framework3/trunk/external/pcaprub/
|
||||
|
||||
The Metasploit Project also added some code from the python netifaces c extension
|
||||
|
||||
Original c/python netifaces code is under MIT-style license.
|
||||
Here goes:
|
||||
|
||||
Copyright (c) 2007, 2008 Alastair Houghton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
|
@ -1,4 +1,104 @@
|
|||
require 'mkmf'
|
||||
|
||||
puts("platform is #{RUBY_PLATFORM}")
|
||||
|
||||
########################
|
||||
# Netifaces
|
||||
########################
|
||||
puts "\n[*] Running checks for netifaces code added by metasploit project"
|
||||
puts "-----------------------------------------------------------------"
|
||||
#uncoment to force ioctl on non windows systems
|
||||
#@force_ioctl = true
|
||||
@supported_archs = ["i386-mingw32", "i486-linux", "universal-darwin10.0", "i386-openbsd4.8","i386-freebsd8","arm-linux-eabi"]
|
||||
#arm-linux-eabi tested on maemo5 / N900
|
||||
puts "[*] Warning : this platform as not been tested" unless @supported_archs.include? RUBY_PLATFORM
|
||||
|
||||
if RUBY_PLATFORM =~ /i386-mingw32/
|
||||
unless have_library("ws2_32" ) and
|
||||
have_library("iphlpapi") and
|
||||
have_header("windows.h") and
|
||||
have_header("winsock2.h") and
|
||||
have_header("iphlpapi.h")
|
||||
puts "\nNot all dependencies are satisfied, please check logs"
|
||||
exit
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
headers = ['net/if_dl.h', 'netash/ash.h','netatalk/at.h', 'netax25/ax25.h',
|
||||
'neteconet/ec.h', 'netipx/ipx.h','netpacket/packet.h', 'netrose/rose.h']
|
||||
if RUBY_PLATFORM =~ /linux/
|
||||
headers += [ 'linux/irda.h', 'linux/atm.h',
|
||||
'linux/llc.h', 'linux/tipc.h',
|
||||
'linux/dn.h']
|
||||
end
|
||||
additionnal_headers = ["sys/types.h","sys/socket.h","sys/un.h","net/if.h","netinet/in.h"]
|
||||
optional_headers = []
|
||||
sockaddrs = [ 'at', 'ax25', 'dl', 'eon', 'in', 'in6',
|
||||
'inarp', 'ipx', 'iso', 'ns', 'un', 'x25',
|
||||
'rose', 'ash', 'ec', 'll', 'atmpvc', 'atmsvc',
|
||||
'dn', 'irda', 'llc']
|
||||
|
||||
# 1) Check for getifaddrs
|
||||
unless @force_ioctl
|
||||
need_ioctl = !(have_func("getifaddrs"))
|
||||
end
|
||||
|
||||
# 2) Check for getnameinfo or redefine it in netifaces.c
|
||||
have_func("getnameinfo")
|
||||
|
||||
# 3) Whitout getifaddrs we'll have to deal with ioctls
|
||||
if need_ioctl or @force_ioctl
|
||||
ioctls = [
|
||||
'SIOCGIFCONF','SIOCGSIZIFCONF','SIOCGIFHWADDR','SIOCGIFADDR','SIOCGIFFLAGS','SIOCGIFDSTADDR',
|
||||
'SIOCGIFBRDADDR','SIOCGIFNETMASK','SIOCGLIFNUM','SIOCGLIFCONF','SIOCGLIFFLAGS']
|
||||
ioctls_headers = ['sys/types.h','sys/socket.h','sys/ioctl.h','net/if.h','netinet/in.h','arpa/inet.h']
|
||||
#TODO Test this on sunos
|
||||
#if RUBY_PLATFORM =~ /sunos/
|
||||
# ioctls_headers += ['unistd.h','stropts.h','sys/sockio.h']
|
||||
#end
|
||||
$defs.push '-DHAVE_SOCKET_IOCTLS'
|
||||
ioctls.each do |ioctl|
|
||||
if have_macro(ioctl, ioctls_headers)
|
||||
$defs.push "-DHAVE_#{ioctl}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# 4) Check for optionnal headers
|
||||
headers.each do |header|
|
||||
if have_header(header)
|
||||
optional_headers.push(header)
|
||||
end
|
||||
end
|
||||
|
||||
# 5) On certain platforms (Linux), there's no sa_len.
|
||||
# Unfortunately, getifaddrs() doesn't return the
|
||||
# lengths, because they're in the sa_len field on just about
|
||||
# everything but Linux.
|
||||
# In this case we will define a macro that will return the sa_len from
|
||||
# the sockaddr_xx structure if they are available
|
||||
if (!have_struct_member("struct sockaddr", "sa_len", ["sys/types.h","sys/socket.h","net/if.h"]))
|
||||
sockaddrs.each do |sockaddr|
|
||||
have_type("struct sockaddr_" + sockaddr, additionnal_headers + optional_headers)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#rework the defs to make them compatible with the original netifaces.c code
|
||||
$defs = $defs.map do |a|
|
||||
if a =~ /^-DHAVE_TYPE_STRUCT_SOCKADDR_.*$/ then a.gsub("TYPE_STRUCT_","")
|
||||
elsif a == "-DHAVE_ST_SA_LEN" then a.gsub("HAVE_ST_","HAVE_SOCKADDR_")
|
||||
else a
|
||||
end
|
||||
end
|
||||
|
||||
########################
|
||||
# Pcap
|
||||
########################
|
||||
|
||||
puts "\n[*] Running checks for pcap code..."
|
||||
puts "-----------------------------------"
|
||||
if /i386-mingw32/ =~ RUBY_PLATFORM
|
||||
dir_config("pcap","C:/WpdPack/include","C:/WpdPack/lib")
|
||||
have_library("wpcap", "pcap_open_live")
|
||||
|
|
|
@ -0,0 +1,688 @@
|
|||
#include "ruby.h"
|
||||
|
||||
#ifndef RUBY_19
|
||||
#include "rubysig.h"
|
||||
#endif
|
||||
|
||||
#include "netifaces.h"
|
||||
|
||||
#if !defined(WIN32)
|
||||
#if !HAVE_GETNAMEINFO
|
||||
#undef getnameinfo
|
||||
#undef NI_NUMERICHOST
|
||||
|
||||
#define getnameinfo our_getnameinfo
|
||||
#define NI_NUMERICHOST 1
|
||||
|
||||
/* A very simple getnameinfo() for platforms without */
|
||||
static int
|
||||
getnameinfo (const struct sockaddr *addr, int addr_len,
|
||||
char *buffer, int buflen,
|
||||
char *buf2, int buf2len,
|
||||
int flags)
|
||||
{
|
||||
switch (addr->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
const struct sockaddr_in *sin = (struct sockaddr_in *)addr;
|
||||
const unsigned char *bytes = (unsigned char *)&sin->sin_addr.s_addr;
|
||||
char tmpbuf[20];
|
||||
|
||||
sprintf (tmpbuf, "%d.%d.%d.%d",
|
||||
bytes[0], bytes[1], bytes[2], bytes[3]);
|
||||
|
||||
strncpy (buffer, tmpbuf, buflen);
|
||||
}
|
||||
break;
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
const struct sockaddr_in6 *sin = (const struct sockaddr_in6 *)addr;
|
||||
const unsigned char *bytes = sin->sin6_addr.s6_addr;
|
||||
int n;
|
||||
char tmpbuf[80], *ptr = tmpbuf;
|
||||
int done_double_colon = FALSE;
|
||||
int colon_mode = FALSE;
|
||||
|
||||
for (n = 0; n < 8; ++n)
|
||||
{
|
||||
unsigned char b1 = bytes[2 * n];
|
||||
unsigned char b2 = bytes[2 * n + 1];
|
||||
|
||||
if (b1)
|
||||
{
|
||||
if (colon_mode)
|
||||
{
|
||||
colon_mode = FALSE;
|
||||
*ptr++ = ':';
|
||||
}
|
||||
sprintf (ptr, "%x%02x", b1, b2);
|
||||
ptr += strlen (ptr);
|
||||
*ptr++ = ':';
|
||||
}
|
||||
else if (b2)
|
||||
{
|
||||
if (colon_mode)
|
||||
{
|
||||
colon_mode = FALSE;
|
||||
*ptr++ = ':';
|
||||
}
|
||||
sprintf (ptr, "%x", b2);
|
||||
ptr += strlen (ptr);
|
||||
*ptr++ = ':';
|
||||
}
|
||||
else {
|
||||
if (!colon_mode)
|
||||
{
|
||||
if (done_double_colon)
|
||||
{
|
||||
*ptr++ = '0';
|
||||
*ptr++ = ':';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n == 0)
|
||||
*ptr++ = ':';
|
||||
colon_mode = TRUE;
|
||||
done_double_colon = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (colon_mode)
|
||||
{
|
||||
colon_mode = FALSE;
|
||||
*ptr++ = ':';
|
||||
*ptr++ = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
*--ptr = '\0';
|
||||
}
|
||||
|
||||
strncpy (buffer, tmpbuf, buflen);
|
||||
}
|
||||
break;
|
||||
#endif /* AF_INET6 */
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
string_from_sockaddr (struct sockaddr *addr,
|
||||
char *buffer,
|
||||
int buflen)
|
||||
{
|
||||
if (!addr || addr->sa_family == AF_UNSPEC)
|
||||
return -1;
|
||||
|
||||
if (getnameinfo (addr, SA_LEN(addr),
|
||||
buffer, buflen,
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST) != 0)
|
||||
{
|
||||
int n, len;
|
||||
char *ptr;
|
||||
const char *data;
|
||||
|
||||
len = SA_LEN(addr);
|
||||
|
||||
#if HAVE_AF_LINK
|
||||
/* BSD-like systems have AF_LINK */
|
||||
if (addr->sa_family == AF_LINK)
|
||||
{
|
||||
struct sockaddr_dl *dladdr = (struct sockaddr_dl *)addr;
|
||||
len = dladdr->sdl_alen;
|
||||
if(len >=0)
|
||||
data = LLADDR(dladdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
#if defined(AF_PACKET)
|
||||
/* Linux has AF_PACKET instead */
|
||||
if (addr->sa_family == AF_PACKET)
|
||||
{
|
||||
struct sockaddr_ll *lladdr = (struct sockaddr_ll *)addr;
|
||||
len = lladdr->sll_halen;
|
||||
//amaloteaux: openbsd and maybe other systems have a len of 0 for enc0,pflog0 .. interfaces
|
||||
if(len >=0)
|
||||
data = (const char *)lladdr->sll_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
/* We don't know anything about this sockaddr, so just display
|
||||
the entire data area in binary. */
|
||||
len -= (sizeof (struct sockaddr) - sizeof (addr->sa_data));
|
||||
data = addr->sa_data;
|
||||
#if defined(AF_PACKET)
|
||||
}
|
||||
#endif
|
||||
#if HAVE_AF_LINK
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((buflen < 3 * len) || len <= 0)
|
||||
return -1;
|
||||
|
||||
ptr = buffer;
|
||||
buffer[0] = '\0';
|
||||
|
||||
for (n = 0; n < len; ++n)
|
||||
{
|
||||
sprintf (ptr, "%02x:", data[n] & 0xff);
|
||||
ptr += 3;
|
||||
}
|
||||
*--ptr = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* !defined(WIN32) */
|
||||
|
||||
static VALUE add_to_family(VALUE result, VALUE family, VALUE value)
|
||||
{
|
||||
Check_Type(result, T_HASH);
|
||||
Check_Type(family, T_FIXNUM);
|
||||
Check_Type(value, T_HASH);
|
||||
VALUE list;
|
||||
|
||||
list = rb_hash_aref(result, family);
|
||||
|
||||
if (list == Qnil)
|
||||
list = rb_ary_new();
|
||||
else
|
||||
Check_Type(list, T_ARRAY);
|
||||
|
||||
rb_ary_push(list, value);
|
||||
rb_hash_aset(result, family, list);
|
||||
return result;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rbnetifaces_s_addresses (VALUE class, VALUE dev)
|
||||
{
|
||||
Check_Type(dev, T_STRING);
|
||||
|
||||
VALUE result;
|
||||
int found = FALSE;
|
||||
result = rb_hash_new();
|
||||
|
||||
#if defined(WIN32)
|
||||
PIP_ADAPTER_INFO pAdapterInfo = NULL;
|
||||
PIP_ADAPTER_INFO pInfo = NULL;
|
||||
ULONG ulBufferLength = 0;
|
||||
DWORD dwRet;
|
||||
PIP_ADDR_STRING str;
|
||||
|
||||
//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];
|
||||
|
||||
if (strcmp (pInfo->AdapterName, StringValuePtr(dev)) != 0)
|
||||
continue;
|
||||
|
||||
VALUE rbhardw = Qnil;
|
||||
VALUE rbaddr = Qnil;
|
||||
VALUE rbnetmask = Qnil;
|
||||
VALUE rbbraddr = Qnil;
|
||||
|
||||
found = TRUE;
|
||||
|
||||
// Do the physical address
|
||||
if (256 >= 3 * pInfo->AddressLength)
|
||||
{
|
||||
VALUE hash_hardw;
|
||||
hash_hardw = rb_hash_new();
|
||||
|
||||
char *ptr = buffer;
|
||||
unsigned n;
|
||||
|
||||
*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
|
||||
struct ifaddrs *addrs = NULL;
|
||||
struct ifaddrs *addr = NULL;
|
||||
|
||||
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);
|
||||
|
||||
VALUE result2;
|
||||
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
|
||||
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (sock < 0)
|
||||
{
|
||||
rb_raise(rb_eRuntimeError, "Unknow error at OS level");
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
struct CNAME(ifreq) ifr;
|
||||
|
||||
char buffer[256];
|
||||
int is_p2p = FALSE;
|
||||
VALUE rbaddr = Qnil;
|
||||
VALUE rbnetmask = Qnil;
|
||||
VALUE rbbraddr = Qnil;
|
||||
VALUE rbdstaddr = 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
|
||||
VALUE result2;
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
VALUE
|
||||
rbnetifaces_s_interfaces (VALUE self)
|
||||
{
|
||||
VALUE result;
|
||||
result = rb_ary_new();
|
||||
|
||||
#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)
|
||||
{
|
||||
VALUE ifname = rb_str_new2(pInfo->AdapterName);
|
||||
//VALUE ifname = rb_str_new2(pInfo->Description);
|
||||
if(!rb_ary_includes(result, ifname))
|
||||
rb_ary_push(result, ifname);
|
||||
}
|
||||
|
||||
free (pAdapterInfo);
|
||||
|
||||
#elif HAVE_GETIFADDRS
|
||||
const char *prev_name = NULL;
|
||||
struct ifaddrs *addrs = NULL;
|
||||
struct ifaddrs *addr = NULL;
|
||||
|
||||
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
|
||||
|
||||
const char *prev_name = NULL;
|
||||
int fd = socket (AF_INET, SOCK_DGRAM, 0);
|
||||
struct CNAME(ifconf) ifc;
|
||||
int len = -1, n;
|
||||
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;
|
||||
}
|
||||
|
||||
struct CNAME(ifreq) *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;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
#ifndef WIN32
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <net/if.h>
|
||||
# include <netdb.h>
|
||||
|
||||
# if HAVE_SOCKET_IOCTLS
|
||||
# include <sys/ioctl.h>
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
#if defined(__sun)
|
||||
#include <unistd.h>
|
||||
#include <stropts.h>
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
# endif /* HAVE_SOCKET_IOCTLS */
|
||||
|
||||
/* For logical interfaces support we convert all names to same name prefixed with l */
|
||||
#if HAVE_SIOCGLIFNUM
|
||||
#define CNAME(x) l##x
|
||||
#else
|
||||
#define CNAME(x) x
|
||||
#endif
|
||||
|
||||
#if HAVE_NET_IF_DL_H
|
||||
# include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
/* For Linux, include all the sockaddr
|
||||
definitions we can lay our hands on. */
|
||||
#if !HAVE_SOCKADDR_SA_LEN
|
||||
# if HAVE_NETASH_ASH_H
|
||||
# include <netash/ash.h>
|
||||
# endif
|
||||
# if HAVE_NETATALK_AT_H
|
||||
# include <netatalk/at.h>
|
||||
# endif
|
||||
# if HAVE_NETAX25_AX25_H
|
||||
# include <netax25/ax25.h>
|
||||
# endif
|
||||
# if HAVE_NETECONET_EC_H
|
||||
# include <neteconet/ec.h>
|
||||
# endif
|
||||
# if HAVE_NETIPX_IPX_H
|
||||
# include <netipx/ipx.h>
|
||||
# endif
|
||||
# if HAVE_NETPACKET_PACKET_H
|
||||
# include <netpacket/packet.h>
|
||||
# endif
|
||||
# if HAVE_NETROSE_ROSE_H
|
||||
# include <netrose/rose.h>
|
||||
# endif
|
||||
# if HAVE_LINUX_IRDA_H
|
||||
# include <linux/irda.h>
|
||||
# endif
|
||||
# if HAVE_LINUX_ATM_H
|
||||
# include <linux/atm.h>
|
||||
# endif
|
||||
# if HAVE_LINUX_LLC_H
|
||||
# include <linux/llc.h>
|
||||
# endif
|
||||
# if HAVE_LINUX_TIPC_H
|
||||
# include <linux/tipc.h>
|
||||
# endif
|
||||
# if HAVE_LINUX_DN_H
|
||||
# include <linux/dn.h>
|
||||
# endif
|
||||
|
||||
/* Map address families to sizes of sockaddr structs */
|
||||
static int af_to_len(int af)
|
||||
{
|
||||
switch (af)
|
||||
{
|
||||
case AF_INET: return sizeof (struct sockaddr_in);
|
||||
#if defined(AF_INET6) && HAVE_SOCKADDR_IN6
|
||||
case AF_INET6: return sizeof (struct sockaddr_in6);
|
||||
#endif
|
||||
#if defined(AF_AX25) && HAVE_SOCKADDR_AX25
|
||||
# if defined(AF_NETROM)
|
||||
case AF_NETROM: /* I'm assuming this is carried over x25 */
|
||||
# endif
|
||||
case AF_AX25: return sizeof (struct sockaddr_ax25);
|
||||
#endif
|
||||
#if defined(AF_IPX) && HAVE_SOCKADDR_IPX
|
||||
case AF_IPX: return sizeof (struct sockaddr_ipx);
|
||||
#endif
|
||||
#if defined(AF_APPLETALK) && HAVE_SOCKADDR_AT
|
||||
case AF_APPLETALK: return sizeof (struct sockaddr_at);
|
||||
#endif
|
||||
#if defined(AF_ATMPVC) && HAVE_SOCKADDR_ATMPVC
|
||||
case AF_ATMPVC: return sizeof (struct sockaddr_atmpvc);
|
||||
#endif
|
||||
#if defined(AF_ATMSVC) && HAVE_SOCKADDR_ATMSVC
|
||||
case AF_ATMSVC: return sizeof (struct sockaddr_atmsvc);
|
||||
#endif
|
||||
#if defined(AF_X25) && HAVE_SOCKADDR_X25
|
||||
case AF_X25: return sizeof (struct sockaddr_x25);
|
||||
#endif
|
||||
#if defined(AF_ROSE) && HAVE_SOCKADDR_ROSE
|
||||
case AF_ROSE: return sizeof (struct sockaddr_rose);
|
||||
#endif
|
||||
#if defined(AF_DECnet) && HAVE_SOCKADDR_DN
|
||||
case AF_DECnet: return sizeof (struct sockaddr_dn);
|
||||
#endif
|
||||
#if defined(AF_PACKET) && HAVE_SOCKADDR_LL
|
||||
case AF_PACKET: return sizeof (struct sockaddr_ll);
|
||||
#endif
|
||||
#if defined(AF_ASH) && HAVE_SOCKADDR_ASH
|
||||
case AF_ASH: return sizeof (struct sockaddr_ash);
|
||||
#endif
|
||||
#if defined(AF_ECONET) && HAVE_SOCKADDR_EC
|
||||
case AF_ECONET: return sizeof (struct sockaddr_ec);
|
||||
#endif
|
||||
#if defined(AF_IRDA) && HAVE_SOCKADDR_IRDA
|
||||
case AF_IRDA: return sizeof (struct sockaddr_irda);
|
||||
#endif
|
||||
}
|
||||
return sizeof (struct sockaddr);
|
||||
}
|
||||
|
||||
#define SA_LEN(sa) af_to_len(sa->sa_family)
|
||||
#if HAVE_SIOCGLIFNUM
|
||||
#define SS_LEN(sa) af_to_len(sa->ss_family)
|
||||
#else
|
||||
#define SS_LEN(sa) SA_LEN(sa)
|
||||
#endif
|
||||
#else
|
||||
//remove a warning on openbsd
|
||||
#ifndef SA_LEN
|
||||
#define SA_LEN(sa) sa->sa_len
|
||||
#endif
|
||||
#endif /* !HAVE_SOCKADDR_SA_LEN */
|
||||
|
||||
# if HAVE_GETIFADDRS
|
||||
# include <ifaddrs.h>
|
||||
# endif /* HAVE_GETIFADDRS */
|
||||
|
||||
# if !HAVE_GETIFADDRS && (!HAVE_SOCKET_IOCTLS || !HAVE_SIOCGIFCONF)
|
||||
/* If the platform doesn't define, what we need, barf. If you're seeing this,
|
||||
it means you need to write suitable code to retrieve interface information
|
||||
on your system. */
|
||||
# error You need to add code for your platform.
|
||||
# endif
|
||||
|
||||
#else /* defined(WIN32) */
|
||||
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
#endif /* defined(WIN32) */
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/* On systems without AF_LINK (Windows, for instance), define it anyway, but
|
||||
give it a crazy value. On Linux, which has AF_PACKET but not AF_LINK,
|
||||
define AF_LINK as the latter instead. */
|
||||
#ifndef AF_LINK
|
||||
# ifdef AF_PACKET
|
||||
# define AF_LINK AF_PACKET
|
||||
# else
|
||||
# define AF_LINK -1000
|
||||
# endif
|
||||
# define HAVE_AF_LINK 0
|
||||
#else
|
||||
# define HAVE_AF_LINK 1
|
||||
#endif
|
||||
|
||||
|
||||
//Prototypes
|
||||
//Get a list of the adresses for a network interface
|
||||
VALUE rbnetifaces_s_addresses (VALUE class, VALUE dev);
|
||||
//Get a list of the network interfaces
|
||||
VALUE rbnetifaces_s_interfaces (VALUE self);
|
||||
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include "rubysig.h"
|
||||
#endif
|
||||
|
||||
#include "netifaces.h"
|
||||
|
||||
#include <pcap.h>
|
||||
|
||||
|
@ -524,51 +525,236 @@ rbpcap_stats(VALUE self)
|
|||
void
|
||||
Init_pcaprub()
|
||||
{
|
||||
// Pcap
|
||||
rb_cPcap = rb_define_class("Pcap", rb_cObject);
|
||||
rb_define_module_function(rb_cPcap, "version", rbpcap_s_version, 0);
|
||||
rb_define_module_function(rb_cPcap, "lookupdev", rbpcap_s_lookupdev, 0);
|
||||
rb_define_module_function(rb_cPcap, "lookupnet", rbpcap_s_lookupnet, 1);
|
||||
rb_define_module_function(rb_cPcap, "lookupaddrs", rbpcap_s_lookupaddrs, 1);
|
||||
// Pcap
|
||||
rb_cPcap = rb_define_class("Pcap", rb_cObject);
|
||||
rb_define_module_function(rb_cPcap, "version", rbpcap_s_version, 0);
|
||||
rb_define_module_function(rb_cPcap, "lookupdev", rbpcap_s_lookupdev, 0);
|
||||
rb_define_module_function(rb_cPcap, "lookupnet", rbpcap_s_lookupnet, 1);
|
||||
rb_define_module_function(rb_cPcap, "lookupaddrs", rbpcap_s_lookupaddrs, 1);
|
||||
|
||||
rb_define_const(rb_cPcap, "DLT_NULL", INT2NUM(DLT_NULL));
|
||||
rb_define_const(rb_cPcap, "DLT_EN10MB", INT2NUM(DLT_EN10MB));
|
||||
rb_define_const(rb_cPcap, "DLT_EN3MB", INT2NUM(DLT_EN3MB));
|
||||
rb_define_const(rb_cPcap, "DLT_AX25", INT2NUM(DLT_AX25));
|
||||
rb_define_const(rb_cPcap, "DLT_PRONET", INT2NUM(DLT_PRONET));
|
||||
rb_define_const(rb_cPcap, "DLT_CHAOS", INT2NUM(DLT_CHAOS));
|
||||
rb_define_const(rb_cPcap, "DLT_IEEE802", INT2NUM(DLT_IEEE802));
|
||||
rb_define_const(rb_cPcap, "DLT_ARCNET", INT2NUM(DLT_ARCNET));
|
||||
rb_define_const(rb_cPcap, "DLT_SLIP", INT2NUM(DLT_SLIP));
|
||||
rb_define_const(rb_cPcap, "DLT_PPP", INT2NUM(DLT_PPP));
|
||||
rb_define_const(rb_cPcap, "DLT_FDDI", INT2NUM(DLT_FDDI));
|
||||
rb_define_const(rb_cPcap, "DLT_ATM_RFC1483", INT2NUM(DLT_ATM_RFC1483));
|
||||
rb_define_const(rb_cPcap, "DLT_RAW", INT2NUM(DLT_RAW));
|
||||
rb_define_const(rb_cPcap, "DLT_SLIP_BSDOS", INT2NUM(DLT_SLIP_BSDOS));
|
||||
rb_define_const(rb_cPcap, "DLT_PPP_BSDOS", INT2NUM(DLT_PPP_BSDOS));
|
||||
rb_define_const(rb_cPcap, "DLT_IEEE802_11", INT2NUM(DLT_IEEE802_11));
|
||||
rb_define_const(rb_cPcap, "DLT_IEEE802_11_RADIO", INT2NUM(DLT_IEEE802_11_RADIO));
|
||||
rb_define_const(rb_cPcap, "DLT_IEEE802_11_RADIO_AVS", INT2NUM(DLT_IEEE802_11_RADIO_AVS));
|
||||
rb_define_const(rb_cPcap, "DLT_LINUX_SLL", INT2NUM(DLT_LINUX_SLL));
|
||||
rb_define_const(rb_cPcap, "DLT_PRISM_HEADER", INT2NUM(DLT_PRISM_HEADER));
|
||||
rb_define_const(rb_cPcap, "DLT_AIRONET_HEADER", INT2NUM(DLT_AIRONET_HEADER));
|
||||
rb_define_const(rb_cPcap, "DLT_NULL", INT2NUM(DLT_NULL));
|
||||
rb_define_const(rb_cPcap, "DLT_EN10MB", INT2NUM(DLT_EN10MB));
|
||||
rb_define_const(rb_cPcap, "DLT_EN3MB", INT2NUM(DLT_EN3MB));
|
||||
rb_define_const(rb_cPcap, "DLT_AX25", INT2NUM(DLT_AX25));
|
||||
rb_define_const(rb_cPcap, "DLT_PRONET", INT2NUM(DLT_PRONET));
|
||||
rb_define_const(rb_cPcap, "DLT_CHAOS", INT2NUM(DLT_CHAOS));
|
||||
rb_define_const(rb_cPcap, "DLT_IEEE802", INT2NUM(DLT_IEEE802));
|
||||
rb_define_const(rb_cPcap, "DLT_ARCNET", INT2NUM(DLT_ARCNET));
|
||||
rb_define_const(rb_cPcap, "DLT_SLIP", INT2NUM(DLT_SLIP));
|
||||
rb_define_const(rb_cPcap, "DLT_PPP", INT2NUM(DLT_PPP));
|
||||
rb_define_const(rb_cPcap, "DLT_FDDI", INT2NUM(DLT_FDDI));
|
||||
rb_define_const(rb_cPcap, "DLT_ATM_RFC1483", INT2NUM(DLT_ATM_RFC1483));
|
||||
rb_define_const(rb_cPcap, "DLT_RAW", INT2NUM(DLT_RAW));
|
||||
rb_define_const(rb_cPcap, "DLT_SLIP_BSDOS", INT2NUM(DLT_SLIP_BSDOS));
|
||||
rb_define_const(rb_cPcap, "DLT_PPP_BSDOS", INT2NUM(DLT_PPP_BSDOS));
|
||||
rb_define_const(rb_cPcap, "DLT_IEEE802_11", INT2NUM(DLT_IEEE802_11));
|
||||
rb_define_const(rb_cPcap, "DLT_IEEE802_11_RADIO", INT2NUM(DLT_IEEE802_11_RADIO));
|
||||
rb_define_const(rb_cPcap, "DLT_IEEE802_11_RADIO_AVS", INT2NUM(DLT_IEEE802_11_RADIO_AVS));
|
||||
rb_define_const(rb_cPcap, "DLT_LINUX_SLL", INT2NUM(DLT_LINUX_SLL));
|
||||
rb_define_const(rb_cPcap, "DLT_PRISM_HEADER", INT2NUM(DLT_PRISM_HEADER));
|
||||
rb_define_const(rb_cPcap, "DLT_AIRONET_HEADER", INT2NUM(DLT_AIRONET_HEADER));
|
||||
|
||||
rb_define_singleton_method(rb_cPcap, "new", rbpcap_new_s, 0);
|
||||
rb_define_singleton_method(rb_cPcap, "new", rbpcap_new_s, 0);
|
||||
|
||||
rb_define_singleton_method(rb_cPcap, "open_live", rbpcap_open_live_s, 4);
|
||||
rb_define_singleton_method(rb_cPcap, "open_offline", rbpcap_open_offline_s, 1);
|
||||
rb_define_singleton_method(rb_cPcap, "open_dead", rbpcap_open_dead_s, 2);
|
||||
rb_define_singleton_method(rb_cPcap, "dump_open", rbpcap_dump_open, 1);
|
||||
rb_define_singleton_method(rb_cPcap, "open_live", rbpcap_open_live_s, 4);
|
||||
rb_define_singleton_method(rb_cPcap, "open_offline", rbpcap_open_offline_s, 1);
|
||||
rb_define_singleton_method(rb_cPcap, "open_dead", rbpcap_open_dead_s, 2);
|
||||
rb_define_singleton_method(rb_cPcap, "dump_open", rbpcap_dump_open, 1);
|
||||
|
||||
rb_define_method(rb_cPcap, "dump", rbpcap_dump, 3);
|
||||
rb_define_method(rb_cPcap, "dump", rbpcap_dump, 3);
|
||||
|
||||
rb_define_method(rb_cPcap, "each", rbpcap_capture, 0);
|
||||
rb_define_method(rb_cPcap, "next", rbpcap_next, 0);
|
||||
rb_define_method(rb_cPcap, "setfilter", rbpcap_setfilter, 1);
|
||||
rb_define_method(rb_cPcap, "inject", rbpcap_inject, 1);
|
||||
rb_define_method(rb_cPcap, "datalink", rbpcap_datalink, 0);
|
||||
rb_define_method(rb_cPcap, "each", rbpcap_capture, 0);
|
||||
rb_define_method(rb_cPcap, "next", rbpcap_next, 0);
|
||||
rb_define_method(rb_cPcap, "setfilter", rbpcap_setfilter, 1);
|
||||
rb_define_method(rb_cPcap, "inject", rbpcap_inject, 1);
|
||||
rb_define_method(rb_cPcap, "datalink", rbpcap_datalink, 0);
|
||||
|
||||
rb_define_method(rb_cPcap, "snapshot", rbpcap_snapshot, 0);
|
||||
rb_define_method(rb_cPcap, "snaplen", rbpcap_snapshot, 0);
|
||||
rb_define_method(rb_cPcap, "stats", rbpcap_stats, 0);
|
||||
rb_define_method(rb_cPcap, "snapshot", rbpcap_snapshot, 0);
|
||||
rb_define_method(rb_cPcap, "snaplen", rbpcap_snapshot, 0);
|
||||
rb_define_method(rb_cPcap, "stats", rbpcap_stats, 0);
|
||||
|
||||
|
||||
//Netifaces
|
||||
rb_define_module_function(rb_cPcap, "interfaces", rbnetifaces_s_interfaces, 0);
|
||||
rb_define_module_function(rb_cPcap, "addresses", rbnetifaces_s_addresses, 1);
|
||||
|
||||
//constants
|
||||
// Address families (auto-detect using #ifdef)
|
||||
|
||||
#ifdef AF_INET
|
||||
rb_define_const(rb_cPcap, "AF_INET", INT2NUM(AF_INET));
|
||||
#endif
|
||||
#ifdef AF_INET6
|
||||
rb_define_const(rb_cPcap, "AF_INET6", INT2NUM(AF_INET6));
|
||||
#endif
|
||||
#ifdef AF_UNSPEC
|
||||
rb_define_const(rb_cPcap, "AF_UNSPEC", INT2NUM(AF_UNSPEC));
|
||||
#endif
|
||||
#ifdef AF_UNIX
|
||||
rb_define_const(rb_cPcap, "AF_UNIX", INT2NUM(AF_UNIX));
|
||||
#endif
|
||||
#ifdef AF_FILE
|
||||
rb_define_const(rb_cPcap, "AF_FILE", INT2NUM(AF_FILE));
|
||||
#endif
|
||||
|
||||
#ifdef AF_AX25
|
||||
rb_define_const(rb_cPcap, "AF_AX25", INT2NUM(AF_AX25));
|
||||
#endif
|
||||
#ifdef AF_IMPLINK
|
||||
rb_define_const(rb_cPcap, "AF_IMPLINK", INT2NUM(AF_IMPLINK));
|
||||
#endif
|
||||
#ifdef AF_PUP
|
||||
rb_define_const(rb_cPcap, "AF_PUP", INT2NUM(AF_PUP));
|
||||
#endif
|
||||
#ifdef AF_CHAOS
|
||||
rb_define_const(rb_cPcap, "AF_CHAOS", INT2NUM(AF_CHAOS));
|
||||
#endif
|
||||
#ifdef AF_NS
|
||||
rb_define_const(rb_cPcap, "AF_NS", INT2NUM(AF_NS));
|
||||
#endif
|
||||
#ifdef AF_ISO
|
||||
rb_define_const(rb_cPcap, "AF_ISO", INT2NUM(AF_ISO));
|
||||
#endif
|
||||
#ifdef AF_ECMA
|
||||
rb_define_const(rb_cPcap, "AF_ECMA", INT2NUM(AF_ECMA));
|
||||
#endif
|
||||
#ifdef AF_DATAKIT
|
||||
rb_define_const(rb_cPcap, "AF_DATAKIT", INT2NUM(AF_DATAKIT));
|
||||
#endif
|
||||
#ifdef AF_CCITT
|
||||
rb_define_const(rb_cPcap, "AF_CCITT", INT2NUM(AF_CCITT));
|
||||
#endif
|
||||
#ifdef AF_SNA
|
||||
rb_define_const(rb_cPcap, "AF_SNA", INT2NUM(AF_SNA));
|
||||
#endif
|
||||
#ifdef AF_DECnet
|
||||
rb_define_const(rb_cPcap, "AF_DECnet", INT2NUM(AF_DECnet));
|
||||
#endif
|
||||
#ifdef AF_DLI
|
||||
rb_define_const(rb_cPcap, "AF_DLI", INT2NUM(AF_DLI));
|
||||
#endif
|
||||
#ifdef AF_LAT
|
||||
rb_define_const(rb_cPcap, "AF_LAT", INT2NUM(AF_LAT));
|
||||
#endif
|
||||
#ifdef AF_HYLINK
|
||||
rb_define_const(rb_cPcap, "AF_HYLINK", INT2NUM(AF_HYLINK));
|
||||
#endif
|
||||
#ifdef AF_APPLETALK
|
||||
rb_define_const(rb_cPcap, "AF_APPLETALK", INT2NUM(AF_APPLETALK));
|
||||
#endif
|
||||
#ifdef AF_ROUTE
|
||||
rb_define_const(rb_cPcap, "AF_ROUTE", INT2NUM(AF_ROUTE));
|
||||
#endif
|
||||
#ifdef AF_LINK
|
||||
rb_define_const(rb_cPcap, "AF_LINK", INT2NUM(AF_LINK));
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
rb_define_const(rb_cPcap, "AF_PACKET", INT2NUM(AF_PACKET));
|
||||
#endif
|
||||
#ifdef AF_COIP
|
||||
rb_define_const(rb_cPcap, "AF_COIP", INT2NUM(AF_COIP));
|
||||
#endif
|
||||
#ifdef AF_CNT
|
||||
rb_define_const(rb_cPcap, "AF_CNT", INT2NUM(AF_CNT));
|
||||
#endif
|
||||
#ifdef AF_IPX
|
||||
rb_define_const(rb_cPcap, "AF_IPX", INT2NUM(AF_IPX));
|
||||
#endif
|
||||
#ifdef AF_SIP
|
||||
rb_define_const(rb_cPcap, "AF_SIP", INT2NUM(AF_SIP));
|
||||
#endif
|
||||
#ifdef AF_NDRV
|
||||
rb_define_const(rb_cPcap, "AF_NDRV", INT2NUM(AF_NDRV));
|
||||
#endif
|
||||
#ifdef AF_ISDN
|
||||
rb_define_const(rb_cPcap, "AF_ISDN", INT2NUM(AF_ISDN));
|
||||
#endif
|
||||
#ifdef AF_NATM
|
||||
rb_define_const(rb_cPcap, "AF_NATM", INT2NUM(AF_NATM));
|
||||
#endif
|
||||
#ifdef AF_SYSTEM
|
||||
rb_define_const(rb_cPcap, "AF_SYSTEM", INT2NUM(AF_SYSTEM));
|
||||
#endif
|
||||
#ifdef AF_NETBIOS
|
||||
rb_define_const(rb_cPcap, "AF_NETBIOS", INT2NUM(AF_NETBIOS));
|
||||
#endif
|
||||
#ifdef AF_NETBEUI
|
||||
rb_define_const(rb_cPcap, "AF_NETBEUI", INT2NUM(AF_NETBEUI));
|
||||
#endif
|
||||
#ifdef AF_PPP
|
||||
rb_define_const(rb_cPcap, "AF_PPP", INT2NUM(AF_PPP));
|
||||
#endif
|
||||
#ifdef AF_ATM
|
||||
rb_define_const(rb_cPcap, "AF_ATM", INT2NUM(AF_ATM));
|
||||
#endif
|
||||
#ifdef AF_ATMPVC
|
||||
rb_define_const(rb_cPcap, "AF_ATMPVC", INT2NUM(AF_ATMPVC));
|
||||
#endif
|
||||
#ifdef AF_ATMSVC
|
||||
rb_define_const(rb_cPcap, "AF_ATMSVC", INT2NUM(AF_ATMSVC));
|
||||
#endif
|
||||
#ifdef AF_NETGRAPH
|
||||
rb_define_const(rb_cPcap, "AF_NETGRAPH", INT2NUM(AF_NETGRAPH));
|
||||
#endif
|
||||
#ifdef AF_VOICEVIEW
|
||||
rb_define_const(rb_cPcap, "AF_VOICEVIEW", INT2NUM(AF_VOICEVIEW));
|
||||
#endif
|
||||
#ifdef AF_FIREFOX
|
||||
rb_define_const(rb_cPcap, "AF_FIREFOX", INT2NUM(AF_FIREFOX));
|
||||
#endif
|
||||
#ifdef AF_UNKNOWN1
|
||||
rb_define_const(rb_cPcap, "AF_UNKNOWN1", INT2NUM(AF_UNKNOWN1));
|
||||
#endif
|
||||
#ifdef AF_BAN
|
||||
rb_define_const(rb_cPcap, "AF_BAN", INT2NUM(AF_BAN));
|
||||
#endif
|
||||
#ifdef AF_CLUSTER
|
||||
rb_define_const(rb_cPcap, "AF_CLUSTER", INT2NUM(AF_CLUSTER));
|
||||
#endif
|
||||
#ifdef AF_12844
|
||||
rb_define_const(rb_cPcap, "AF_12844", INT2NUM(AF_12844));
|
||||
#endif
|
||||
#ifdef AF_IRDA
|
||||
rb_define_const(rb_cPcap, "AF_IRDA", INT2NUM(AF_IRDA));
|
||||
#endif
|
||||
#ifdef AF_NETDES
|
||||
rb_define_const(rb_cPcap, "AF_NETDES", INT2NUM(AF_NETDES));
|
||||
#endif
|
||||
#ifdef AF_NETROM
|
||||
rb_define_const(rb_cPcap, "AF_NETROM", INT2NUM(AF_NETROM));
|
||||
#endif
|
||||
#ifdef AF_BRIDGE
|
||||
rb_define_const(rb_cPcap, "AF_BRIDGE", INT2NUM(AF_BRIDGE));
|
||||
#endif
|
||||
#ifdef AF_X25
|
||||
rb_define_const(rb_cPcap, "AF_X25", INT2NUM(AF_X25));
|
||||
#endif
|
||||
#ifdef AF_ROSE
|
||||
rb_define_const(rb_cPcap, "AF_ROSE", INT2NUM(AF_ROSE));
|
||||
#endif
|
||||
#ifdef AF_SECURITY
|
||||
rb_define_const(rb_cPcap, "AF_SECURITY", INT2NUM(AF_SECURITY));
|
||||
#endif
|
||||
#ifdef AF_KEY
|
||||
rb_define_const(rb_cPcap, "AF_KEY", INT2NUM(AF_KEY));
|
||||
#endif
|
||||
#ifdef AF_NETLINK
|
||||
rb_define_const(rb_cPcap, "AF_NETLINK", INT2NUM(AF_NETLINK));
|
||||
#endif
|
||||
#ifdef AF_ASH
|
||||
rb_define_const(rb_cPcap, "AF_ASH", INT2NUM(AF_ASH));
|
||||
#endif
|
||||
#ifdef AF_ECONET
|
||||
rb_define_const(rb_cPcap, "AF_ECONET", INT2NUM(AF_ECONET));
|
||||
#endif
|
||||
#ifdef AF_PPPOX
|
||||
rb_define_const(rb_cPcap, "AF_PPPOX", INT2NUM(AF_PPPOX));
|
||||
#endif
|
||||
#ifdef AF_WANPIPE
|
||||
rb_define_const(rb_cPcap, "AF_WANPIPE", INT2NUM(AF_WANPIPE));
|
||||
#endif
|
||||
#ifdef AF_BLUETOOTH
|
||||
rb_define_const(rb_cPcap, "AF_BLUETOOTH", INT2NUM(AF_BLUETOOTH));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -100,5 +100,26 @@ class Pcap::UnitTest < Test::Unit::TestCase
|
|||
puts "Background thread ticked #{@c} times while capture was running"
|
||||
true
|
||||
end
|
||||
|
||||
def test_netifaces_constants
|
||||
puts "AF_LINK Value is #{Pcap::AF_LINK}"
|
||||
puts "AF_INET Value is #{Pcap::AF_INET}"
|
||||
puts "AF_INET6 Value is #{Pcap::AF_INET6}" if Pcap::AF_INET6
|
||||
end
|
||||
|
||||
def test_netifaces_functions
|
||||
Pcap.interfaces.sort.each do |iface|
|
||||
puts "#{iface} :"
|
||||
Pcap.addresses(iface).sort.each do |family,values|
|
||||
puts "\t#{family} :"
|
||||
values.each do |val|
|
||||
puts "\t\taddr : #{val['addr']}" if val.has_key?("addr")
|
||||
puts "\t\tnetmask : #{val['netmask']}" if val.has_key?("netmask")
|
||||
puts "\t\tbroadcast : #{val['broadcast']}" if val.has_key?("broadcast")
|
||||
puts "\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -382,14 +382,6 @@ module Exploit::Capture
|
|||
end
|
||||
end
|
||||
|
||||
# lookupaddr is not available in pcaprub 0.9.2 and prior,
|
||||
# which is going to be installed in a lot of places. Modules
|
||||
# which want it should check explicitly for it. TODO: Bug upstream
|
||||
# to release it for real in 0.9.3
|
||||
def lookupaddr_implemented?
|
||||
@pcaprub_loaded and Pcap.respond_to?(:lookupaddrs)
|
||||
end
|
||||
|
||||
def lookupnet
|
||||
check_pcaprub_loaded
|
||||
dev = datastore['INTERFACE'] || ::Pcap.lookupdev
|
||||
|
@ -413,6 +405,96 @@ module Exploit::Capture
|
|||
|
||||
attr_accessor :capture, :arp_cache, :arp_capture, :dst_cache
|
||||
|
||||
# lookupaddr is not available in pcaprub 0.9.2 and prior,
|
||||
# which is going to be installed in a lot of places. Modules
|
||||
# which want it should check explicitly for it. TODO: Bug upstream
|
||||
# to release it for real in 0.9.3
|
||||
def lookupaddr_implemented?
|
||||
@pcaprub_loaded and Pcap.respond_to?(:lookupaddrs)
|
||||
end
|
||||
|
||||
#Netifaces code
|
||||
|
||||
def list_interfaces
|
||||
check_pcaprub_loaded
|
||||
Pcap.interfaces
|
||||
end
|
||||
|
||||
def is_interface?(dev)
|
||||
check_pcaprub_loaded
|
||||
Pcap.interfaces.include? dev
|
||||
end
|
||||
|
||||
def get_mac(dev)
|
||||
check_pcaprub_loaded
|
||||
addrs = Pcap.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
raise RuntimeError, "Can not get mac address for interface #{dev}" if !addrs[Pcap::AF_LINK][0]['addr']
|
||||
addrs[Pcap::AF_LINK][0]['addr']
|
||||
end
|
||||
|
||||
def get_ipv4_addr_count(dev)
|
||||
check_pcaprub_loaded
|
||||
addrs = Pcap.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
addrs[Pcap::AF_INET].length
|
||||
end
|
||||
|
||||
def get_ipv4_addr(dev, num=0)
|
||||
check_pcaprub_loaded
|
||||
addrs = Pcap.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} do not have an ipv4 address at position #{num}" if addrs[Pcap::AF_INET].length < num + 1
|
||||
raise RuntimeError, "Can not get the ipv4 address for interface #{dev}" if !addrs[Pcap::AF_INET][num]['addr']
|
||||
addrs[Pcap::AF_INET][num]['addr']
|
||||
end
|
||||
|
||||
def get_ipv4_netmask(dev, num=0)
|
||||
check_pcaprub_loaded
|
||||
addrs = Pcap.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} do not have an ipv4 address at position #{num}" if addrs[Pcap::AF_INET].length < num + 1
|
||||
raise RuntimeError, "Can not get ipv4 netmask for interface #{dev}" if !addrs[Pcap::AF_INET][num]['netmask']
|
||||
addrs[Pcap::AF_INET][num]['netmask']
|
||||
end
|
||||
|
||||
def get_ipv4_broadcast(dev, num=0)
|
||||
check_pcaprub_loaded
|
||||
addrs = Pcap.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} do not have an ipv4 address at position #{num}" if addrs[Pcap::AF_INET].length < num + 1
|
||||
raise RuntimeError, "Can not get ipv4 broadcast address for interface #{dev}" if !addrs[Pcap::AF_INET][num]['broadcast']
|
||||
addrs[Pcap::AF_INET][num]['broadcast']
|
||||
end
|
||||
|
||||
def get_ipv6_addr_count(dev)
|
||||
check_pcaprub_loaded
|
||||
raise RuntimeError, "Ipv6 informations are not available on this platform" if !Pcap::AF_INET6
|
||||
addrs = Pcap.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
addrs[Pcap::AF_INET6].length
|
||||
end
|
||||
|
||||
def get_ipv6_addr(dev, num=0)
|
||||
check_pcaprub_loaded
|
||||
raise RuntimeError, "Ipv6 informations are not available on this platform" if !Pcap::AF_INET6
|
||||
addrs = Pcap.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} do not have an ipv6 address at position #{num}" if addrs[Pcap::AF_INET6].length < num + 1
|
||||
raise RuntimeError, "Can not get ipv6 address for interface #{dev}" if !addrs[Pcap::AF_INET6][num]['addr']
|
||||
addrs[Pcap::AF_INET6][num]['addr'].gsub(/%(.)*$/,'')
|
||||
end
|
||||
|
||||
def get_ipv6_netmask(dev, num=0)
|
||||
check_pcaprub_loaded
|
||||
raise RuntimeError, "Ipv6 informations are not available on this platform" if !Pcap::AF_INET6
|
||||
addrs = Pcap.addresses(dev)
|
||||
raise RuntimeError, "Interface #{dev} do not exists" if !addrs
|
||||
raise RuntimeError, "Interface #{dev} do not have an ipv6 address at position #{num}" if addrs[Pcap::AF_INET6].length < num + 1
|
||||
raise RuntimeError, "Can not get ipv6 netmask address for interface #{dev}" if !addrs[Pcap::AF_INET6][num]['netmask']
|
||||
addrs[Pcap::AF_INET6][num]['netmask']
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue