summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlastair Houghton <alastair@coriolis-systems.com>2011-10-10 18:47:57 +0100
committerAlastair Houghton <alastair@coriolis-systems.com>2011-10-10 18:47:57 +0100
commit3ec8a8da849d5c59e5ba6ab532fa1bddb80b804c (patch)
treeb76fbdf6abf6d924adcdc485e5c879e3d22e45e4
downloadnetifaces-3ec8a8da849d5c59e5ba6ab532fa1bddb80b804c.tar.gz
Added netifaces-0.5 source code.
-rw-r--r--.hgignore4
-rw-r--r--PKG-INFO25
-rw-r--r--README156
-rw-r--r--netifaces.c1110
-rwxr-xr-xnetifaces.egg-info/PKG-INFO25
-rwxr-xr-xnetifaces.egg-info/SOURCES.txt8
-rwxr-xr-xnetifaces.egg-info/dependency_links.txt1
-rwxr-xr-xnetifaces.egg-info/top_level.txt1
-rw-r--r--setup.cfg5
-rw-r--r--setup.py406
10 files changed, 1741 insertions, 0 deletions
diff --git a/.hgignore b/.hgignore
new file mode 100644
index 0000000..88a289f
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,4 @@
+syntax: glob
+build
+*.pyc
+*~
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..8fe1dcf
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,25 @@
+Metadata-Version: 1.0
+Name: netifaces
+Version: 0.5
+Summary: Portable network interface information.
+Home-page: http://alastairs-place.net/netifaces
+Author: Alastair Houghton
+Author-email: alastair@alastairs-place.net
+License: MIT License
+Description: netifaces provides a (hopefully portable-ish) way for Python programmers to
+ get access to a list of the network interfaces on the local machine, and to
+ obtain the addresses of those network interfaces.
+
+ The package has been tested on Mac OS X, Windows XP, Windows Vista, Linux
+ and Solaris. On Windows, it is currently not able to retrieve IPv6
+ addresses, owing to shortcomings of the Windows API.
+
+ It should work on other UNIX-like systems provided they implement
+ either getifaddrs() or support the SIOCGIFxxx socket options, although the
+ data provided by the socket options is normally less complete.
+
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Topic :: System :: Networking
diff --git a/README b/README
new file mode 100644
index 0000000..c820760
--- /dev/null
+++ b/README
@@ -0,0 +1,156 @@
+netifaces 0.4
+=============
+
+1. What is this?
+----------------
+
+It's been annoying me for some time that there's no easy way to get the
+address(es) of the machine's network interfaces from Python. There is
+a good reason for this difficulty, which is that it is virtually impossible
+to do so in a portable manner. However, it seems to me that there should
+be a package you can easy_install that will take care of working out the
+details of doing so on the machine you're using, then you can get on with
+writing Python code without concerning yourself with the nitty gritty of
+system-dependent low-level networking APIs.
+
+This package attempts to solve that problem.
+
+2. How do I use it?
+-------------------
+
+First you need to install it, which you can do by typing
+
+ tar xvzf netifaces-0.4.tar.gz
+ cd netifaces-0.4
+ python setup.py install
+
+Once that's done, you'll need to start Python and do something like the
+following:
+
+ >>> import netifaces
+
+Then if you enter
+
+ >>> netifaces.interfaces()
+ ['lo0', 'gif0', 'stf0', 'en0', 'en1', 'fw0']
+
+you'll see the list of interface identifiers for your machine.
+
+You can ask for the addresses of a particular interface by doing
+
+ >>> netifaces.ifaddresses('lo0')
+ {18: [{'addr': ''}], 2: [{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}], 30: [{'peer': '::1', 'netmask': 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', 'addr': '::1'}, {'peer': '', 'netmask': 'ffff:ffff:ffff:ffff::', 'addr': 'fe80::1%lo0'}]}
+
+Hmmmm. That result looks a bit cryptic; let's break it apart and explain
+what each piece means. It returned a dictionary, so let's look there first:
+
+ { 18: [...], 2: [...], 30: [...] }
+
+Each of the numbers refers to a particular address family. In this case, we
+have three address families listed; on my system, 18 is AF_LINK (which means
+the link layer interface, e.g. Ethernet), 2 is AF_INET (normal Internet
+addresses), and 30 is AF_INET6 (IPv6).
+
+But wait! Don't use these numbers in your code. The numeric values here are
+system dependent; fortunately, I thought of that when writing netifaces, so
+the module declares a range of values that you might need. e.g.
+
+ >>> netifaces.AF_LINK
+ 18
+
+Again, on your system, the number may be different.
+
+So, what we've established is that the dictionary that's returned has one
+entry for each address family for which this interface has an address. Let's
+take a look at the AF_INET addresses now:
+
+ >>> addrs = netifaces.ifaddresses('lo0')
+ >>> addrs[netifaces.AF_INET]
+ [{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}]
+
+You might be wondering why this value is a list. The reason is that it's
+possible for an interface to have more than one address, even within the
+same family. I'll say that again: *you can have more than one address of
+the same type associated with each interface*.
+
+*Asking for "the" address of a particular interface doesn't make sense.*
+
+Right, so, we can see that this particular interface only has one address,
+and, because it's a loopback interface, it's point-to-point and therefore
+has a *peer* address rather than a broadcast address.
+
+Let's look at a more interesting interface.
+
+ >>> addrs = netifaces.ifaddresses('en0')
+ >>> addrs[netifaces.AF_INET]
+ [{'broadcast': '10.15.255.255', 'netmask': '255.240.0.0', 'addr': '10.0.1.4'}, {'broadcast': '192.168.0.255', 'addr': '192.168.0.47'}]
+
+This interface has two addresses (see, I told you...) Both of them are
+regular IPv4 addresses, although in one case the netmask has been changed
+from its default. The netmask *may not* appear on your system if it's set
+to the default for the address range.
+
+Because this interface isn't point-to-point, it also has broadcast addresses.
+
+Now, say we want, instead of the IP addresses, to get the MAC address; that
+is, the hardware address of the Ethernet adapter running this interface. We
+can do
+
+ >>> addrs[netifaces.AF_LINK]
+ [{'addr': '00:12:34:56:78:9a'}]
+
+Note that this may not be available on platforms without getifaddrs(), unless
+they happen to implement SIOCGIFHWADDR. Note also that you just get the
+address; it's unlikely that you'll see anything else with an AF_LINK address.
+Oh, and don't assume that all AF_LINK addresses are Ethernet; you might, for
+instance, be on a Mac, in which case:
+
+ >>> addrs = netifaces.ifaddresses('fw0')
+ >>> addrs[netifaces.AF_LINK]
+ [{'addr': '00:12:34:56:78:9a:bc:de'}]
+
+No, that isn't an exceptionally long Ethernet MAC address---it's a FireWire
+address.
+
+3. This is great! What platforms does it work on?
+--------------------------------------------------
+
+Well, see, here's the thing. It's been tested on Mac OS X, and it seems to
+work. (OS X helpfully has some of the SIOCGIFxxx ioctl()s, which means that
+most of those have been tested too, the only glaring exception being the
+SIOCGIFHWADDR ioctl(), which OS X just doesn't have.)
+
+It should probably work on most of the other UNIX-like systems with relatively
+minor changes. If you do have to change something, send it to me at
+<alastair AT alastairs-place.net> and I'll see if I can merge it in.
+
+It also works just fine on Windows, using the GetAdaptersInfo() function.
+Note, though, that on Windows it isn't possible (yet) to retrieve IPv6
+addresses. I don't use Windows at the moment, so this isn't a priority for
+me. If you know how to fix it, drop me a line and I'll consider adding any
+necessary code.
+
+4. What license is this under?
+------------------------------
+
+It's an 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. \ No newline at end of file
diff --git a/netifaces.c b/netifaces.c
new file mode 100644
index 0000000..a0e3546
--- /dev/null
+++ b/netifaces.c
@@ -0,0 +1,1110 @@
+#include <Python.h>
+
+#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 the benefit of stupid platforms (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
+#define SA_LEN(sa) sa->sa_len
+#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 <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
+
+#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;
+ 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;
+ 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)
+ 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 int
+add_to_family (PyObject *result, int family, PyObject *dict)
+{
+ PyObject *py_family = PyInt_FromLong (family);
+ PyObject *list = PyDict_GetItem (result, py_family);
+
+ if (!py_family) {
+ Py_DECREF (dict);
+ Py_XDECREF (list);
+ return FALSE;
+ }
+
+ if (!list) {
+ list = PyList_New (1);
+ if (!list) {
+ Py_DECREF (dict);
+ Py_DECREF (py_family);
+ return FALSE;
+ }
+
+ PyList_SET_ITEM (list, 0, dict);
+ PyDict_SetItem (result, py_family, list);
+ Py_DECREF (list);
+ } else {
+ PyList_Append (list, dict);
+ Py_DECREF (dict);
+ }
+
+ return TRUE;
+}
+
+static PyObject *
+ifaddrs (PyObject *self, PyObject *args)
+{
+ const char *ifname;
+ PyObject *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;
+#endif
+
+ if (!PyArg_ParseTuple (args, "s", &ifname))
+ return NULL;
+
+ result = PyDict_New ();
+
+ if (!result)
+ return NULL;
+
+#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) {
+ Py_DECREF (result);
+ PyErr_SetString (PyExc_MemoryError, "Not enough memory");
+ return NULL;
+ }
+ }
+ } while (dwRet == ERROR_BUFFER_OVERFLOW);
+
+ /* If we failed, then fail in Python too */
+ if (dwRet != ERROR_SUCCESS && dwRet != ERROR_NO_DATA) {
+ Py_DECREF (result);
+ if (pAdapterInfo)
+ free (pAdapterInfo);
+
+ PyErr_SetString (PyExc_OSError,
+ "Unable to obtain adapter information.");
+ return NULL;
+ }
+
+ for (pInfo = pAdapterInfo; pInfo; pInfo = pInfo->Next) {
+ char buffer[256];
+
+ if (strcmp (pInfo->AdapterName, ifname) != 0)
+ continue;
+
+ found = TRUE;
+
+ /* Do the physical address */
+ if (256 >= 3 * pInfo->AddressLength) {
+ PyObject *hwaddr, *dict;
+ 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';
+
+ hwaddr = PyString_FromString (buffer);
+ dict = PyDict_New ();
+
+ if (!dict) {
+ Py_XDECREF (hwaddr);
+ Py_DECREF (result);
+ free (pAdapterInfo);
+ return NULL;
+ }
+
+ PyDict_SetItemString (dict, "addr", hwaddr);
+ Py_DECREF (hwaddr);
+
+ if (!add_to_family (result, AF_LINK, dict)) {
+ Py_DECREF (result);
+ free (pAdapterInfo);
+ return NULL;
+ }
+ }
+
+ for (str = &pInfo->IpAddressList; str; str = str->Next) {
+ PyObject *addr = PyString_FromString (str->IpAddress.String);
+ PyObject *mask = PyString_FromString (str->IpMask.String);
+ PyObject *bcast = NULL;
+ PyObject *dict;
+
+ /* 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)
+ bcast = PyString_FromString (brstr);
+ }
+
+ dict = PyDict_New ();
+
+ if (!dict) {
+ Py_XDECREF (addr);
+ Py_XDECREF (mask);
+ Py_XDECREF (bcast);
+ Py_DECREF (result);
+ free (pAdapterInfo);
+ return NULL;
+ }
+
+ if (addr)
+ PyDict_SetItemString (dict, "addr", addr);
+ if (mask)
+ PyDict_SetItemString (dict, "netmask", mask);
+ if (bcast)
+ PyDict_SetItemString (dict, "broadcast", bcast);
+
+ Py_XDECREF (addr);
+ Py_XDECREF (mask);
+ Py_XDECREF (bcast);
+
+ if (!add_to_family (result, AF_INET, dict)) {
+ Py_DECREF (result);
+ free (pAdapterInfo);
+ return NULL;
+ }
+ }
+ }
+
+ free (pAdapterInfo);
+#elif HAVE_GETIFADDRS
+ struct ifaddrs *addrs = NULL;
+ struct ifaddrs *addr = NULL;
+
+ if (getifaddrs (&addrs) < 0) {
+ Py_DECREF (result);
+ PyErr_SetFromErrno (PyExc_OSError);
+ return NULL;
+ }
+
+ for (addr = addrs; addr; addr = addr->ifa_next) {
+ char buffer[256];
+ PyObject *pyaddr = NULL, *netmask = NULL, *braddr = NULL;
+
+ if (strcmp (addr->ifa_name, ifname) != 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)
+ pyaddr = PyString_FromString (buffer);
+
+ if (string_from_sockaddr (addr->ifa_netmask, buffer, sizeof (buffer)) == 0)
+ netmask = PyString_FromString (buffer);
+
+ if (string_from_sockaddr (addr->ifa_broadaddr, buffer, sizeof (buffer)) == 0)
+ braddr = PyString_FromString (buffer);
+
+ PyObject *dict = PyDict_New();
+
+ if (!dict) {
+ Py_XDECREF (pyaddr);
+ Py_XDECREF (netmask);
+ Py_XDECREF (braddr);
+ Py_DECREF (result);
+ freeifaddrs (addrs);
+ return NULL;
+ }
+
+ if (pyaddr)
+ PyDict_SetItemString (dict, "addr", pyaddr);
+ if (netmask)
+ PyDict_SetItemString (dict, "netmask", netmask);
+
+ if (braddr) {
+ if (addr->ifa_flags & (IFF_POINTOPOINT | IFF_LOOPBACK))
+ PyDict_SetItemString (dict, "peer", braddr);
+ else
+ PyDict_SetItemString (dict, "broadcast", braddr);
+ }
+
+ Py_XDECREF (pyaddr);
+ Py_XDECREF (netmask);
+ Py_XDECREF (braddr);
+
+ if (!add_to_family (result, addr->ifa_addr->sa_family, dict)) {
+ Py_DECREF (result);
+ freeifaddrs (addrs);
+ return NULL;
+ }
+ }
+
+ freeifaddrs (addrs);
+#elif HAVE_SOCKET_IOCTLS
+
+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (sock < 0) {
+ Py_DECREF (result);
+ PyErr_SetFromErrno (PyExc_OSError);
+ return NULL;
+ }
+
+ struct CNAME(ifreq) ifr;
+ PyObject *addr = NULL, *netmask = NULL, *braddr = NULL, *dstaddr = NULL;
+ int is_p2p = FALSE;
+ char buffer[256];
+
+ strncpy (ifr.CNAME(ifr_name), ifname, IFNAMSIZ);
+
+#if HAVE_SIOCGIFHWADDR
+ if (ioctl (sock, SIOCGIFHWADDR, &ifr) == 0) {
+ found = TRUE;
+
+ if (string_from_sockaddr (ifr->CNAME(ifr_addr), buffer, sizeof (buffer)) == 0) {
+ PyObject *hwaddr = PyString_FromString (buffer);
+ PyObject *dict = PyDict_New ();
+ PyObject *list = PyList_New (1);
+ PyObject *family = PyInt_FromLong (AF_LINK);
+
+ if (!hwaddr || !dict || !list || !family) {
+ Py_XDECREF (hwaddr);
+ Py_XDECREF (dict);
+ Py_XDECREF (list)
+ Py_XDECREF (family);
+ Py_XDECREF (result);
+ close (sock);
+ return NULL;
+ }
+
+ PyDict_SetItemString (dict, "addr", hwaddr);
+ Py_DECREF (hwaddr);
+
+ PyList_SET_ITEM (list, 0, dict);
+
+ PyDict_SetItem (result, family, list);
+ Py_DECREF (family);
+ Py_DECREF (list);
+ }
+ }
+#endif
+
+#if HAVE_SIOCGIFADDR
+#if HAVE_SIOCGLIFNUM
+ if (ioctl (sock, SIOCGLIFADDR, &ifr) == 0) {
+#else
+ if (ioctl (sock, SIOCGIFADDR, &ifr) == 0) {
+#endif
+ found = TRUE;
+
+ if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0)
+ addr = PyString_FromString (buffer);
+ }
+#endif
+
+#if HAVE_SIOCGIFNETMASK
+#if HAVE_SIOCGLIFNUM
+ if (ioctl (sock, SIOCGLIFNETMASK, &ifr) == 0) {
+#else
+ if (ioctl (sock, SIOCGIFNETMASK, &ifr) == 0) {
+#endif
+ found = TRUE;
+
+ if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0)
+ netmask = PyString_FromString (buffer);
+ }
+#endif
+
+#if HAVE_SIOCGIFFLAGS
+#if HAVE_SIOCGLIFNUM
+ if (ioctl (sock, SIOCGLIFFLAGS, &ifr) == 0) {
+#else
+ if (ioctl (sock, SIOCGIFFLAGS, &ifr) == 0) {
+#endif
+ found = TRUE;
+
+ 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
+ found = TRUE;
+
+ if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0)
+ braddr = PyString_FromString (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
+ found = TRUE;
+
+ if (string_from_sockaddr ((struct sockaddr *)&ifr.CNAME(ifr_addr), buffer, sizeof (buffer)) == 0)
+ dstaddr = PyString_FromString (buffer);
+ }
+#endif
+
+ PyObject *dict = PyDict_New();
+
+ if (!dict) {
+ Py_XDECREF (addr);
+ Py_XDECREF (netmask);
+ Py_XDECREF (braddr);
+ Py_XDECREF (dstaddr);
+ Py_DECREF (result);
+ close (sock);
+ return NULL;
+ }
+
+ if (addr)
+ PyDict_SetItemString (dict, "addr", addr);
+ if (netmask)
+ PyDict_SetItemString (dict, "netmask", netmask);
+ if (braddr)
+ PyDict_SetItemString (dict, "broadcast", braddr);
+ if (dstaddr)
+ PyDict_SetItemString (dict, "peer", dstaddr);
+
+ Py_XDECREF (addr);
+ Py_XDECREF (netmask);
+ Py_XDECREF (braddr);
+ Py_XDECREF (dstaddr);
+
+ if (!PyDict_Size (dict))
+ Py_DECREF (dict);
+ else {
+ PyObject *list = PyList_New(1);
+
+ if (!list) {
+ Py_DECREF (dict);
+ Py_DECREF (result);
+ close (sock);
+ return NULL;
+ }
+
+ PyList_SET_ITEM (list, 0, dict);
+
+ PyObject *family = PyInt_FromLong (AF_INET);
+ if (!family) {
+ Py_DECREF (result);
+ Py_DECREF (list);
+ close (sock);
+ return NULL;
+ }
+
+ PyDict_SetItem (result, family, list);
+ Py_DECREF (family);
+ Py_DECREF (list);
+ }
+
+ close (sock);
+
+#endif /* HAVE_SOCKET_IOCTLS */
+
+ if (found)
+ return result;
+ else {
+ Py_DECREF (result);
+ PyErr_SetString (PyExc_ValueError,
+ "You must specify a valid interface name.");
+ return NULL;
+ }
+}
+
+static PyObject *
+interfaces (PyObject *self)
+{
+ PyObject *result;
+
+#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) {
+ PyErr_SetString (PyExc_MemoryError, "Not enough memory");
+ return NULL;
+ }
+ }
+ } while (dwRet == ERROR_BUFFER_OVERFLOW);
+
+ /* If we failed, then fail in Python too */
+ if (dwRet != ERROR_SUCCESS && dwRet != ERROR_NO_DATA) {
+ if (pAdapterInfo)
+ free (pAdapterInfo);
+
+ PyErr_SetString (PyExc_OSError,
+ "Unable to obtain adapter information.");
+ return NULL;
+ }
+
+ result = PyList_New(0);
+
+ if (dwRet == ERROR_NO_DATA) {
+ free (pAdapterInfo);
+ return result;
+ }
+
+ for (pInfo = pAdapterInfo; pInfo; pInfo = pInfo->Next) {
+ PyObject *ifname = PyString_FromString (pInfo->AdapterName);
+
+ PyList_Append (result, ifname);
+ Py_DECREF (ifname);
+ }
+
+ free (pAdapterInfo);
+#elif HAVE_GETIFADDRS
+ const char *prev_name = NULL;
+ struct ifaddrs *addrs = NULL;
+ struct ifaddrs *addr = NULL;
+
+ result = PyList_New (0);
+
+ if (getifaddrs (&addrs) < 0) {
+ Py_DECREF (result);
+ PyErr_SetFromErrno (PyExc_OSError);
+ return NULL;
+ }
+
+ for (addr = addrs; addr; addr = addr->ifa_next) {
+ if (!prev_name || strncmp (addr->ifa_name, prev_name, IFNAMSIZ) != 0) {
+ PyObject *ifname = PyString_FromString (addr->ifa_name);
+
+ if (!PySequence_Contains (result, ifname))
+ PyList_Append (result, ifname);
+ Py_DECREF (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) {
+ PyErr_SetFromErrno (PyExc_OSError);
+ return NULL;
+ }
+
+ // Try to find out how much space we need
+#if HAVE_SIOCGSIZIFCONF
+ if (ioctl (fd, SIOCGSIZIFCONF, &len) < 0)
+ len = -1;
+#elif HAVE_SIOCGLIFNUM
+ { 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)) {
+ PyErr_SetString (PyExc_MemoryError, "Not enough memory");
+ close (fd);
+ return NULL;
+ }
+
+#if HAVE_SIOCGLIFNUM
+ if (ioctl (fd, SIOCGLIFCONF, &ifc) < 0) {
+#else
+ if (ioctl (fd, SIOCGIFCONF, &ifc) < 0) {
+#endif
+ free (ifc.CNAME(ifc_req));
+ PyErr_SetFromErrno (PyExc_OSError);
+ close (fd);
+ return NULL;
+ }
+
+ result = PyList_New (0);
+ 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) {
+ PyObject *name = PyString_FromString (pfreq->CNAME(ifr_name));
+
+ if (!PySequence_Contains (result, name))
+ PyList_Append (result, name);
+ Py_XDECREF (name);
+
+ prev_name = pfreq->CNAME(ifr_name);
+ }
+ }
+
+ free (ifc.CNAME(ifc_buf));
+ close (fd);
+#endif /* HAVE_SIOCGIFCONF */
+
+ return result;
+}
+
+static PyMethodDef methods[] = {
+ { "ifaddresses", (PyCFunction)ifaddrs, METH_VARARGS,
+ "Obtain information about the specified network interface.\n"
+"\n"
+"Returns a dict whose keys are equal to the address family constants,\n"
+"e.g. netifaces.AF_INET, and whose values are a list of addresses in\n"
+"that family that are attached to the network interface." },
+ { "interfaces", (PyCFunction)interfaces, METH_NOARGS,
+ "Obtain a list of the interfaces available on this machine." },
+ { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC
+initnetifaces (void)
+{
+ PyObject *m;
+
+#ifdef WIN32
+ WSADATA wsad;
+ int iResult;
+
+ iResult = WSAStartup(MAKEWORD (2, 2), &wsad);
+#endif
+
+ m = Py_InitModule ("netifaces", methods);
+
+ /* Address families (auto-detect using #ifdef) */
+#ifdef AF_UNSPEC
+ PyModule_AddIntConstant (m, "AF_UNSPEC", AF_UNSPEC);
+#endif
+#ifdef AF_UNIX
+ PyModule_AddIntConstant (m, "AF_UNIX", AF_UNIX);
+#endif
+#ifdef AF_FILE
+ PyModule_AddIntConstant (m, "AF_FILE", AF_FILE);
+#endif
+#ifdef AF_INET
+ PyModule_AddIntConstant (m, "AF_INET", AF_INET);
+#endif
+#ifdef AF_AX25
+ PyModule_AddIntConstant (m, "AF_AX25", AF_AX25);
+#endif
+#ifdef AF_IMPLINK
+ PyModule_AddIntConstant (m, "AF_IMPLINK", AF_IMPLINK);
+#endif
+#ifdef AF_PUP
+ PyModule_AddIntConstant (m, "AF_PUP", AF_PUP);
+#endif
+#ifdef AF_CHAOS
+ PyModule_AddIntConstant (m, "AF_CHAOS", AF_CHAOS);
+#endif
+#ifdef AF_NS
+ PyModule_AddIntConstant (m, "AF_NS", AF_NS);
+#endif
+#ifdef AF_ISO
+ PyModule_AddIntConstant (m, "AF_ISO", AF_ISO);
+#endif
+#ifdef AF_ECMA
+ PyModule_AddIntConstant (m, "AF_ECMA", AF_ECMA);
+#endif
+#ifdef AF_DATAKIT
+ PyModule_AddIntConstant (m, "AF_DATAKIT", AF_DATAKIT);
+#endif
+#ifdef AF_CCITT
+ PyModule_AddIntConstant (m, "AF_CCITT", AF_CCITT);
+#endif
+#ifdef AF_SNA
+ PyModule_AddIntConstant (m, "AF_SNA", AF_SNA);
+#endif
+#ifdef AF_DECnet
+ PyModule_AddIntConstant (m, "AF_DECnet", AF_DECnet);
+#endif
+#ifdef AF_DLI
+ PyModule_AddIntConstant (m, "AF_DLI", AF_DLI);
+#endif
+#ifdef AF_LAT
+ PyModule_AddIntConstant (m, "AF_LAT", AF_LAT);
+#endif
+#ifdef AF_HYLINK
+ PyModule_AddIntConstant (m, "AF_HYLINK", AF_HYLINK);
+#endif
+#ifdef AF_APPLETALK
+ PyModule_AddIntConstant (m, "AF_APPLETALK", AF_APPLETALK);
+#endif
+#ifdef AF_ROUTE
+ PyModule_AddIntConstant (m, "AF_ROUTE", AF_ROUTE);
+#endif
+#ifdef AF_LINK
+ PyModule_AddIntConstant (m, "AF_LINK", AF_LINK);
+#endif
+#ifdef AF_PACKET
+ PyModule_AddIntConstant (m, "AF_PACKET", AF_PACKET);
+#endif
+#ifdef AF_COIP
+ PyModule_AddIntConstant (m, "AF_COIP", AF_COIP);
+#endif
+#ifdef AF_CNT
+ PyModule_AddIntConstant (m, "AF_CNT", AF_CNT);
+#endif
+#ifdef AF_IPX
+ PyModule_AddIntConstant (m, "AF_IPX", AF_IPX);
+#endif
+#ifdef AF_SIP
+ PyModule_AddIntConstant (m, "AF_SIP", AF_SIP);
+#endif
+#ifdef AF_NDRV
+ PyModule_AddIntConstant (m, "AF_NDRV", AF_NDRV);
+#endif
+#ifdef AF_ISDN
+ PyModule_AddIntConstant (m, "AF_ISDN", AF_ISDN);
+#endif
+#ifdef AF_INET6
+ PyModule_AddIntConstant (m, "AF_INET6", AF_INET6);
+#endif
+#ifdef AF_NATM
+ PyModule_AddIntConstant (m, "AF_NATM", AF_NATM);
+#endif
+#ifdef AF_SYSTEM
+ PyModule_AddIntConstant (m, "AF_SYSTEM", AF_SYSTEM);
+#endif
+#ifdef AF_NETBIOS
+ PyModule_AddIntConstant (m, "AF_NETBIOS", AF_NETBIOS);
+#endif
+#ifdef AF_NETBEUI
+ PyModule_AddIntConstant (m, "AF_NETBEUI", AF_NETBEUI);
+#endif
+#ifdef AF_PPP
+ PyModule_AddIntConstant (m, "AF_PPP", AF_PPP);
+#endif
+#ifdef AF_ATM
+ PyModule_AddIntConstant (m, "AF_ATM", AF_ATM);
+#endif
+#ifdef AF_ATMPVC
+ PyModule_AddIntConstant (m, "AF_ATMPVC", AF_ATMPVC);
+#endif
+#ifdef AF_ATMSVC
+ PyModule_AddIntConstant (m, "AF_ATMSVC", AF_ATMSVC);
+#endif
+#ifdef AF_NETGRAPH
+ PyModule_AddIntConstant (m, "AF_NETGRAPH", AF_NETGRAPH);
+#endif
+#ifdef AF_VOICEVIEW
+ PyModule_AddIntConstant (m, "AF_VOICEVIEW", AF_VOICEVIEW);
+#endif
+#ifdef AF_FIREFOX
+ PyModule_AddIntConstant (m, "AF_FIREFOX", AF_FIREFOX);
+#endif
+#ifdef AF_UNKNOWN1
+ PyModule_AddIntConstant (m, "AF_UNKNOWN1", AF_UNKNOWN1);
+#endif
+#ifdef AF_BAN
+ PyModule_AddIntConstant (m, "AF_BAN", AF_BAN);
+#endif
+#ifdef AF_CLUSTER
+ PyModule_AddIntConstant (m, "AF_CLUSTER", AF_CLUSTER);
+#endif
+#ifdef AF_12844
+ PyModule_AddIntConstant (m, "AF_12844", AF_12844);
+#endif
+#ifdef AF_IRDA
+ PyModule_AddIntConstant (m, "AF_IRDA", AF_IRDA);
+#endif
+#ifdef AF_NETDES
+ PyModule_AddIntConstant (m, "AF_NETDES", AF_NETDES);
+#endif
+#ifdef AF_NETROM
+ PyModule_AddIntConstant (m, "AF_NETROM", AF_NETROM);
+#endif
+#ifdef AF_BRIDGE
+ PyModule_AddIntConstant (m, "AF_BRIDGE", AF_BRIDGE);
+#endif
+#ifdef AF_X25
+ PyModule_AddIntConstant (m, "AF_X25", AF_X25);
+#endif
+#ifdef AF_ROSE
+ PyModule_AddIntConstant (m, "AF_ROSE", AF_ROSE);
+#endif
+#ifdef AF_SECURITY
+ PyModule_AddIntConstant (m, "AF_SECURITY", AF_SECURITY);
+#endif
+#ifdef AF_KEY
+ PyModule_AddIntConstant (m, "AF_KEY", AF_KEY);
+#endif
+#ifdef AF_NETLINK
+ PyModule_AddIntConstant (m, "AF_NETLINK", AF_NETLINK);
+#endif
+#ifdef AF_ASH
+ PyModule_AddIntConstant (m, "AF_ASH", AF_ASH);
+#endif
+#ifdef AF_ECONET
+ PyModule_AddIntConstant (m, "AF_ECONET", AF_ECONET);
+#endif
+#ifdef AF_SNA
+ PyModule_AddIntConstant (m, "AF_SNA", AF_SNA);
+#endif
+#ifdef AF_PPPOX
+ PyModule_AddIntConstant (m, "AF_PPPOX", AF_PPPOX);
+#endif
+#ifdef AF_WANPIPE
+ PyModule_AddIntConstant (m, "AF_WANPIPE", AF_WANPIPE);
+#endif
+#ifdef AF_BLUETOOTH
+ PyModule_AddIntConstant (m, "AF_BLUETOOTH", AF_BLUETOOTH);
+#endif
+}
diff --git a/netifaces.egg-info/PKG-INFO b/netifaces.egg-info/PKG-INFO
new file mode 100755
index 0000000..8fe1dcf
--- /dev/null
+++ b/netifaces.egg-info/PKG-INFO
@@ -0,0 +1,25 @@
+Metadata-Version: 1.0
+Name: netifaces
+Version: 0.5
+Summary: Portable network interface information.
+Home-page: http://alastairs-place.net/netifaces
+Author: Alastair Houghton
+Author-email: alastair@alastairs-place.net
+License: MIT License
+Description: netifaces provides a (hopefully portable-ish) way for Python programmers to
+ get access to a list of the network interfaces on the local machine, and to
+ obtain the addresses of those network interfaces.
+
+ The package has been tested on Mac OS X, Windows XP, Windows Vista, Linux
+ and Solaris. On Windows, it is currently not able to retrieve IPv6
+ addresses, owing to shortcomings of the Windows API.
+
+ It should work on other UNIX-like systems provided they implement
+ either getifaddrs() or support the SIOCGIFxxx socket options, although the
+ data provided by the socket options is normally less complete.
+
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Topic :: System :: Networking
diff --git a/netifaces.egg-info/SOURCES.txt b/netifaces.egg-info/SOURCES.txt
new file mode 100755
index 0000000..3699ec0
--- /dev/null
+++ b/netifaces.egg-info/SOURCES.txt
@@ -0,0 +1,8 @@
+README
+netifaces.c
+setup.cfg
+setup.py
+netifaces.egg-info/PKG-INFO
+netifaces.egg-info/SOURCES.txt
+netifaces.egg-info/dependency_links.txt
+netifaces.egg-info/top_level.txt \ No newline at end of file
diff --git a/netifaces.egg-info/dependency_links.txt b/netifaces.egg-info/dependency_links.txt
new file mode 100755
index 0000000..8b13789
--- /dev/null
+++ b/netifaces.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/netifaces.egg-info/top_level.txt b/netifaces.egg-info/top_level.txt
new file mode 100755
index 0000000..3f008fd
--- /dev/null
+++ b/netifaces.egg-info/top_level.txt
@@ -0,0 +1 @@
+netifaces
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..861a9f5
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..8a84b2b
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,406 @@
+import setuptools
+import os
+import sys
+import distutils.spawn
+from setuptools import setup, Extension
+from setuptools.command.build_ext import build_ext
+from distutils.errors import *
+import pickle
+
+# On Windows, we need ws2_32 and iphlpapi
+if getattr(sys, 'getwindowsversion', None):
+ libraries = ['ws2_32', 'iphlpapi']
+ def_macros = [('WIN32', 1)]
+else:
+ mos = getattr(sys, 'platform', None)
+ libraries = []
+ if mos.startswith('sunos'):
+ libraries = ['socket', 'nsl']
+ def_macros = []
+
+iface_mod = Extension('netifaces', sources=['netifaces.c'],
+ libraries=libraries,
+ define_macros=def_macros)
+
+#
+# There must be a better way to do this...
+#
+class my_build_ext(build_ext):
+ def build_extensions(self):
+ self.check_requirements()
+ build_ext.build_extensions(self)
+
+ def test_build(self, contents, link=True, execute=True, libraries=None,
+ include_dirs=None, library_dirs=None):
+ name = os.path.join(self.build_temp, 'conftest-%s.c' % self.conftestidx)
+ self.conftestidx += 1
+ if os.path.exists(name):
+ os.unlink(name)
+ thefile = open(name, 'w')
+ print >>thefile, contents
+ thefile.close()
+
+ tmpext = Extension('_dummy', [], libraries = libraries)
+ libraries = self.get_libraries(tmpext)
+
+ sys.stdout.flush()
+ sys.stderr.flush()
+ mystdout = os.dup(1)
+ mystderr = os.dup(2)
+ result = True
+ try:
+ os.dup2(self.ctout, 1)
+ os.dup2(self.ctout, 2)
+ try:
+ objects = self.compiler.compile([name],
+ output_dir=self.build_temp,
+ include_dirs=include_dirs,
+ debug=self.debug)
+ if link:
+ self.compiler.link_executable(objects,
+ 'conftest',
+ output_dir=self.build_temp,
+ library_dirs=library_dirs,
+ libraries=libraries,
+ debug=self.debug)
+ if execute:
+ abspath = os.path.abspath(os.path.join(self.build_temp,
+ 'conftest'))
+ pipe = os.popen(abspath, 'r')
+ result = pipe.read().strip()
+ status = pipe.close()
+ if status is None:
+ status = 0
+ if result == '':
+ result = True
+ if status != 0:
+ result = False
+
+ finally:
+ os.dup2(mystdout, 1)
+ os.dup2(mystderr, 2)
+ except CompileError:
+ return False
+ except DistutilsExecError:
+ return False
+ return result
+
+ def check_requirements(self):
+ # Load the cached config data from a previous run if possible; compiling
+ # things to test for features is slow
+ cache_file = os.path.join(self.build_temp, 'config.cache')
+ if os.path.exists(cache_file):
+ myfile = open(cache_file, 'r')
+ try:
+ results = pickle.load(myfile)
+ finally:
+ myfile.close()
+ else:
+ results = {}
+
+ self.conftestidx = 0
+
+ print "checking for getifaddrs...",
+
+ result = results.get('have_getifaddrs', None)
+ if result is not None:
+ cached = '(cached)'
+ else:
+ cached = ''
+
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ outname = os.path.join(self.build_temp, 'conftest.out')
+ self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC)
+ testrig = """
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <ifaddrs.h>
+ int main(void) {
+ struct ifaddrs *addrs;
+ int ret;
+ ret = getifaddrs(&addrs);
+ freeifaddrs (addrs);
+ return 0;
+ }
+ """
+ if self.test_build(testrig):
+ result = True
+ else:
+ result = False
+
+ if result:
+ print "found. %s" % cached
+ self.compiler.define_macro('HAVE_GETIFADDRS', 1)
+ else:
+ print "not found. %s" % cached
+
+ results['have_getifaddrs'] = result
+
+ print "checking for getnameinfo...",
+
+ result = results.get('have_getnameinfo', None)
+ if result is not None:
+ cached = '(cached)'
+ else:
+ cached = ''
+
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ outname = os.path.join(self.build_temp, 'conftest2.out')
+ self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC)
+ testrig = """
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <stdlib.h>
+ int main(void) {
+ struct sockaddr_in sin;
+ char buffer[256];
+ int ret;
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = 0;
+ sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ ret = getnameinfo ((struct sockaddr *)&sin, sizeof (sin),
+ buffer, sizeof (buffer),
+ NULL, 0,
+ NI_NUMERICHOST);
+
+ return 0;
+ }
+ """
+ if self.test_build(testrig,libraries=libraries):
+ result = True
+ else:
+ result = False
+
+ if result:
+ print "found. %s" % cached
+ self.compiler.define_macro('HAVE_GETNAMEINFO', 1)
+ else:
+ print "not found. %s" % cached
+
+ results['have_getnameinfo'] = result
+
+ if not results['have_getifaddrs']:
+ print "checking for socket IOCTLs...",
+
+ result = results.get('have_socket_ioctls', None)
+ if result is not None:
+ cached = '(cached)'
+ else:
+ cached = ''
+
+ result = []
+ ioctls = ('SIOCGIFCONF',
+ 'SIOCGSIZIFCONF',
+ 'SIOCGIFHWADDR',
+ 'SIOCGIFADDR',
+ 'SIOCGIFFLAGS',
+ 'SIOCGIFDSTADDR',
+ 'SIOCGIFBRDADDR',
+ 'SIOCGIFNETMASK',
+ 'SIOCGLIFNUM',
+ 'SIOCGLIFCONF',
+ 'SIOCGLIFFLAGS')
+ added_includes = ""
+ if mos.startswith('sunos'):
+ added_includes = """
+ #include <unistd.h>
+ #include <stropts.h>
+ #include <sys/sockio.h>
+ """
+
+ for ioctl in ioctls:
+ testrig = """
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/ioctl.h>
+ #include <net/if.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ %(addedinc)s
+ int main(void) {
+ int fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ struct ifreq ifreq;
+
+ ioctl(fd, %(ioctl)s, &ifreq);
+
+ return 0;
+ }
+ """ % { 'ioctl': ioctl , 'addedinc': added_includes}
+
+ if self.test_build(testrig,libraries=libraries):
+ result.append(ioctl)
+
+ if result:
+ print "%r. %s" % (result, cached)
+ for ioctl in result:
+ self.compiler.define_macro('HAVE_%s' % ioctl, 1)
+ self.compiler.define_macro('HAVE_SOCKET_IOCTLS', 1)
+ else:
+ print "not found. %s" % cached
+
+ results['have_socket_ioctls'] = result
+
+ print "checking for optional header files...",
+
+ result = results.get('have_headers', None)
+ if result is not None:
+ cached = '(cached)'
+ else:
+ cached = ''
+
+ result =[]
+ 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',
+ 'linux/irda.h', 'linux/atm.h',
+ 'linux/llc.h', 'linux/tipc.h',
+ 'linux/dn.h')
+
+ for header in headers:
+ testrig = """
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+ #include <%s>
+ int main (void) { return 0; }
+ """ % header
+
+ if self.test_build(testrig, link=False, execute=False):
+ result.append(header)
+
+ if result:
+ print "%s. %s" % (' '.join(result), cached)
+ for header in result:
+ macro = header.upper().replace('.', '_').replace('/', '_')
+ self.compiler.define_macro('HAVE_%s' % macro, 1)
+ else:
+ print "none found. %s" % cached
+
+ optional_headers = result
+ results['have_headers'] = result
+
+ print "checking whether struct sockaddr has a length field...",
+
+ result = results.get('have_sockaddr_sa_len', None)
+ if result is not None:
+ cached = '(cached)'
+ else:
+ cached = ''
+
+ testrig = """
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+
+ int main (void) {
+ struct sockaddr sa;
+ sa.sa_len = 5;
+ return 0;
+ }
+ """
+
+ result = self.test_build(testrig, execute=False)
+
+ if result:
+ print 'yes. %s' % cached
+ self.compiler.define_macro('HAVE_SOCKADDR_SA_LEN', 1)
+ else:
+ print 'no. %s' % cached
+
+ results['have_sockaddr_sa_len'] = result
+
+ if not results['have_sockaddr_sa_len']:
+ # GAK! On certain stupid platforms (Linux), there's no sa_len.
+ # Macho Linux programmers apparently think that it's not needed,
+ # however, unfortunately, getifaddrs() doesn't return the
+ # lengths, because they're in the sa_len field on just about
+ # everything but Linux.
+ print "checking which sockaddr_xxx structs are defined...",
+
+ result = results.get('have_sockaddrs', None)
+ if result is not None:
+ cached = '(cached)'
+ else:
+ cached = ''
+
+ sockaddrs = ('at', 'ax25', 'dl', 'eon', 'in', 'in6',
+ 'inarp', 'ipx', 'iso', 'ns', 'un', 'x25',
+ 'rose', 'ash', 'ec', 'll', 'atmpvc', 'atmsvc',
+ 'dn', 'irda', 'llc')
+ result = []
+ for sockaddr in sockaddrs:
+ testrig = """
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/un.h>
+ #include <net/if.h>
+ #include <netinet/in.h>
+ %(includes)s
+
+ int main (void) {
+ struct sockaddr_%(sockaddr)s sa;
+ return 0;
+ }
+ """ % { 'includes': '\n'.join(["#include <%s>" % header
+ for header
+ in optional_headers]),
+ 'sockaddr': sockaddr }
+
+ if self.test_build(testrig, execute=False):
+ result.append(sockaddr)
+
+ if result:
+ print '%s. %s' % (' '.join(result), cached)
+ for sockaddr in result:
+ self.compiler.define_macro('HAVE_SOCKADDR_%s' \
+ % sockaddr.upper(), 1)
+ else:
+ print 'none! %s' % cached
+
+ results['have_sockaddrs'] = result
+
+ # Save the results to our config.cache file
+ myfile = open(cache_file, 'w')
+ try:
+ pickle.dump(results, myfile)
+ finally:
+ myfile.close()
+
+# Don't bother detecting socket ioctls on Windows
+if not getattr(sys, 'getwindowsversion', None):
+ setuptools.command.build_ext.build_ext = my_build_ext
+
+setup (name='netifaces',
+ version='0.5',
+ description="Portable network interface information.",
+ license="MIT License",
+ long_description="""\
+netifaces provides a (hopefully portable-ish) way for Python programmers to
+get access to a list of the network interfaces on the local machine, and to
+obtain the addresses of those network interfaces.
+
+The package has been tested on Mac OS X, Windows XP, Windows Vista, Linux
+and Solaris. On Windows, it is currently not able to retrieve IPv6
+addresses, owing to shortcomings of the Windows API.
+
+It should work on other UNIX-like systems provided they implement
+either getifaddrs() or support the SIOCGIFxxx socket options, although the
+data provided by the socket options is normally less complete.
+""",
+ author='Alastair Houghton',
+ author_email='alastair@alastairs-place.net',
+ url='http://alastairs-place.net/netifaces',
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: MIT License',
+ 'Topic :: System :: Networking',
+ ],
+ ext_modules=[iface_mod])