From: Jimmy Huang Date: Fri, 31 Aug 2012 22:13:35 +0000 (-0700) Subject: Initial import to Tizen X-Git-Tag: 1.0_branch^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cea9952198fadf9c92b9ce483a34b0dfbc426239;p=profile%2Fivi%2Fpython-netifaces.git Initial import to Tizen Signed-off-by: Jimmy Huang --- cea9952198fadf9c92b9ce483a34b0dfbc426239 diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000..9dcb201 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,25 @@ +Metadata-Version: 1.0 +Name: netifaces +Version: 0.6 +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 + 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..bc4298b --- /dev/null +++ b/netifaces.c @@ -0,0 +1,1262 @@ +#include + +#ifndef WIN32 + +# include +# include +# include +# include + +# if HAVE_SOCKET_IOCTLS +# include +# include +# include +#if defined(__sun) +#include +#include +#include +#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 +#endif + +/* For the benefit of stupid platforms (Linux), include all the sockaddr + definitions we can lay our hands on. It can also be useful for the benefit + of another stupid platform (FreeBSD, see PR 152036). */ +#include +# if HAVE_NETASH_ASH_H +# include +# endif +# if HAVE_NETATALK_AT_H +# include +# endif +# if HAVE_NETAX25_AX25_H +# include +# endif +# if HAVE_NETECONET_EC_H +# include +# endif +# if HAVE_NETIPX_IPX_H +# include +# endif +# if HAVE_NETPACKET_PACKET_H +# include +# endif +# if HAVE_NETROSE_ROSE_H +# include +# endif +# if HAVE_LINUX_IRDA_H +# include +# endif +# if HAVE_LINUX_ATM_H +# include +# endif +# if HAVE_LINUX_LLC_H +# include +# endif +# if HAVE_LINUX_TIPC_H +# include +# endif +# if HAVE_LINUX_DN_H +# include +# 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); +} + +#if !HAVE_SOCKADDR_SA_LEN +#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 +# 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 +# include + +#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) +{ + struct sockaddr* bigaddr = 0; + int failure; + struct sockaddr* gniaddr; + socklen_t gnilen; + + if (!addr || addr->sa_family == AF_UNSPEC) + return -1; + + if (SA_LEN(addr) < af_to_len(addr->sa_family)) { + /* Someteims ifa_netmask can be truncated. So let's detruncate it. FreeBSD + * PR: kern/152036: getifaddrs(3) returns truncated sockaddrs for netmasks + * -- http://www.freebsd.org/cgi/query-pr.cgi?pr=152036 */ + gnilen = af_to_len(addr->sa_family); + bigaddr = calloc(1, gnilen); + if (!bigaddr) + return -1; + memcpy(bigaddr, addr, SA_LEN(addr)); +#if HAVE_SOCKADDR_SA_LEN + bigaddr->sa_len = gnilen; +#endif + gniaddr = bigaddr; + } else { + gnilen = SA_LEN(addr); + gniaddr = addr; + } + + failure = getnameinfo (gniaddr, gnilen, + buffer, buflen, + NULL, 0, + NI_NUMERICHOST); + + if (bigaddr) { + free(bigaddr); + bigaddr = 0; + } + + if (failure) { + 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) */ + PyObject *address_family_dict = PyDict_New(); +#ifdef AF_UNSPEC + PyModule_AddIntConstant (m, "AF_UNSPEC", AF_UNSPEC); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_UNSPEC), + PyString_FromString("AF_UNSPEC")); +#endif +#ifdef AF_UNIX + PyModule_AddIntConstant (m, "AF_UNIX", AF_UNIX); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_UNIX), + PyString_FromString("AF_UNIX")); +#endif +#ifdef AF_FILE + PyModule_AddIntConstant (m, "AF_FILE", AF_FILE); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_FILE), + PyString_FromString("AF_FILE")); +#endif +#ifdef AF_INET + PyModule_AddIntConstant (m, "AF_INET", AF_INET); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_INET), + PyString_FromString("AF_INET")); +#endif +#ifdef AF_AX25 + PyModule_AddIntConstant (m, "AF_AX25", AF_AX25); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_AX25), + PyString_FromString("AF_AX25")); +#endif +#ifdef AF_IMPLINK + PyModule_AddIntConstant (m, "AF_IMPLINK", AF_IMPLINK); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_IMPLINK), + PyString_FromString("AF_IMPLINK")); +#endif +#ifdef AF_PUP + PyModule_AddIntConstant (m, "AF_PUP", AF_PUP); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_PUP), + PyString_FromString("AF_PUP")); +#endif +#ifdef AF_CHAOS + PyModule_AddIntConstant (m, "AF_CHAOS", AF_CHAOS); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_CHAOS), + PyString_FromString("AF_CHAOS")); +#endif +#ifdef AF_NS + PyModule_AddIntConstant (m, "AF_NS", AF_NS); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NS), + PyString_FromString("AF_NS")); +#endif +#ifdef AF_ISO + PyModule_AddIntConstant (m, "AF_ISO", AF_ISO); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ISO), + PyString_FromString("AF_ISO")); +#endif +#ifdef AF_ECMA + PyModule_AddIntConstant (m, "AF_ECMA", AF_ECMA); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ECMA), + PyString_FromString("AF_ECMA")); +#endif +#ifdef AF_DATAKIT + PyModule_AddIntConstant (m, "AF_DATAKIT", AF_DATAKIT); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_DATAKIT), + PyString_FromString("AF_DATAKIT")); +#endif +#ifdef AF_CCITT + PyModule_AddIntConstant (m, "AF_CCITT", AF_CCITT); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_CCITT), + PyString_FromString("AF_CCITT")); +#endif +#ifdef AF_SNA + PyModule_AddIntConstant (m, "AF_SNA", AF_SNA); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SNA), + PyString_FromString("AF_SNA")); +#endif +#ifdef AF_DECnet + PyModule_AddIntConstant (m, "AF_DECnet", AF_DECnet); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_DECnet), + PyString_FromString("AF_DECnet")); +#endif +#ifdef AF_DLI + PyModule_AddIntConstant (m, "AF_DLI", AF_DLI); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_DLI), + PyString_FromString("AF_DLI")); +#endif +#ifdef AF_LAT + PyModule_AddIntConstant (m, "AF_LAT", AF_LAT); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_LAT), + PyString_FromString("AF_LAT")); +#endif +#ifdef AF_HYLINK + PyModule_AddIntConstant (m, "AF_HYLINK", AF_HYLINK); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_HYLINK), + PyString_FromString("AF_HYLINK")); +#endif +#ifdef AF_APPLETALK + PyModule_AddIntConstant (m, "AF_APPLETALK", AF_APPLETALK); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_APPLETALK), + PyString_FromString("AF_APPLETALK")); +#endif +#ifdef AF_ROUTE + PyModule_AddIntConstant (m, "AF_ROUTE", AF_ROUTE); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ROUTE), + PyString_FromString("AF_ROUTE")); +#endif +#ifdef AF_LINK + PyModule_AddIntConstant (m, "AF_LINK", AF_LINK); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_LINK), + PyString_FromString("AF_LINK")); +#endif +#ifdef AF_PACKET + PyModule_AddIntConstant (m, "AF_PACKET", AF_PACKET); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_PACKET), + PyString_FromString("AF_PACKET")); +#endif +#ifdef AF_COIP + PyModule_AddIntConstant (m, "AF_COIP", AF_COIP); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_COIP), + PyString_FromString("AF_COIP")); +#endif +#ifdef AF_CNT + PyModule_AddIntConstant (m, "AF_CNT", AF_CNT); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_CNT), + PyString_FromString("AF_CNT")); +#endif +#ifdef AF_IPX + PyModule_AddIntConstant (m, "AF_IPX", AF_IPX); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_IPX), + PyString_FromString("AF_IPX")); +#endif +#ifdef AF_SIP + PyModule_AddIntConstant (m, "AF_SIP", AF_SIP); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SIP), + PyString_FromString("AF_SIP")); +#endif +#ifdef AF_NDRV + PyModule_AddIntConstant (m, "AF_NDRV", AF_NDRV); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NDRV), + PyString_FromString("AF_NDRV")); +#endif +#ifdef AF_ISDN + PyModule_AddIntConstant (m, "AF_ISDN", AF_ISDN); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ISDN), + PyString_FromString("AF_ISDN")); +#endif +#ifdef AF_INET6 + PyModule_AddIntConstant (m, "AF_INET6", AF_INET6); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_INET6), + PyString_FromString("AF_INET6")); +#endif +#ifdef AF_NATM + PyModule_AddIntConstant (m, "AF_NATM", AF_NATM); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NATM), + PyString_FromString("AF_NATM")); +#endif +#ifdef AF_SYSTEM + PyModule_AddIntConstant (m, "AF_SYSTEM", AF_SYSTEM); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SYSTEM), + PyString_FromString("AF_SYSTEM")); +#endif +#ifdef AF_NETBIOS + PyModule_AddIntConstant (m, "AF_NETBIOS", AF_NETBIOS); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETBIOS), + PyString_FromString("AF_NETBIOS")); +#endif +#ifdef AF_NETBEUI + PyModule_AddIntConstant (m, "AF_NETBEUI", AF_NETBEUI); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETBEUI), + PyString_FromString("AF_NETBEUI")); +#endif +#ifdef AF_PPP + PyModule_AddIntConstant (m, "AF_PPP", AF_PPP); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_PPP), + PyString_FromString("AF_PPP")); +#endif +#ifdef AF_ATM + PyModule_AddIntConstant (m, "AF_ATM", AF_ATM); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ATM), + PyString_FromString("AF_ATM")); +#endif +#ifdef AF_ATMPVC + PyModule_AddIntConstant (m, "AF_ATMPVC", AF_ATMPVC); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ATMPVC), + PyString_FromString("AF_ATMPVC")); +#endif +#ifdef AF_ATMSVC + PyModule_AddIntConstant (m, "AF_ATMSVC", AF_ATMSVC); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ATMSVC), + PyString_FromString("AF_ATMSVC")); +#endif +#ifdef AF_NETGRAPH + PyModule_AddIntConstant (m, "AF_NETGRAPH", AF_NETGRAPH); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETGRAPH), + PyString_FromString("AF_NETGRAPH")); +#endif +#ifdef AF_VOICEVIEW + PyModule_AddIntConstant (m, "AF_VOICEVIEW", AF_VOICEVIEW); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_VOICEVIEW), + PyString_FromString("AF_VOICEVIEW")); +#endif +#ifdef AF_FIREFOX + PyModule_AddIntConstant (m, "AF_FIREFOX", AF_FIREFOX); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_FIREFOX), + PyString_FromString("AF_FIREFOX")); +#endif +#ifdef AF_UNKNOWN1 + PyModule_AddIntConstant (m, "AF_UNKNOWN1", AF_UNKNOWN1); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_UNKNOWN1), + PyString_FromString("AF_UNKNOWN1")); +#endif +#ifdef AF_BAN + PyModule_AddIntConstant (m, "AF_BAN", AF_BAN); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_BAN), + PyString_FromString("AF_BAN")); +#endif +#ifdef AF_CLUSTER + PyModule_AddIntConstant (m, "AF_CLUSTER", AF_CLUSTER); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_CLUSTER), + PyString_FromString("AF_CLUSTER")); +#endif +#ifdef AF_12844 + PyModule_AddIntConstant (m, "AF_12844", AF_12844); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_12844), + PyString_FromString("AF_12844")); +#endif +#ifdef AF_IRDA + PyModule_AddIntConstant (m, "AF_IRDA", AF_IRDA); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_IRDA), + PyString_FromString("AF_IRDA")); +#endif +#ifdef AF_NETDES + PyModule_AddIntConstant (m, "AF_NETDES", AF_NETDES); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETDES), + PyString_FromString("AF_NETDES")); +#endif +#ifdef AF_NETROM + PyModule_AddIntConstant (m, "AF_NETROM", AF_NETROM); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETROM), + PyString_FromString("AF_NETROM")); +#endif +#ifdef AF_BRIDGE + PyModule_AddIntConstant (m, "AF_BRIDGE", AF_BRIDGE); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_BRIDGE), + PyString_FromString("AF_BRIDGE")); +#endif +#ifdef AF_X25 + PyModule_AddIntConstant (m, "AF_X25", AF_X25); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_X25), + PyString_FromString("AF_X25")); +#endif +#ifdef AF_ROSE + PyModule_AddIntConstant (m, "AF_ROSE", AF_ROSE); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ROSE), + PyString_FromString("AF_ROSE")); +#endif +#ifdef AF_SECURITY + PyModule_AddIntConstant (m, "AF_SECURITY", AF_SECURITY); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SECURITY), + PyString_FromString("AF_SECURITY")); +#endif +#ifdef AF_KEY + PyModule_AddIntConstant (m, "AF_KEY", AF_KEY); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_KEY), + PyString_FromString("AF_KEY")); +#endif +#ifdef AF_NETLINK + PyModule_AddIntConstant (m, "AF_NETLINK", AF_NETLINK); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_NETLINK), + PyString_FromString("AF_NETLINK")); +#endif +#ifdef AF_ASH + PyModule_AddIntConstant (m, "AF_ASH", AF_ASH); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ASH), + PyString_FromString("AF_ASH")); +#endif +#ifdef AF_ECONET + PyModule_AddIntConstant (m, "AF_ECONET", AF_ECONET); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_ECONET), + PyString_FromString("AF_ECONET")); +#endif +#ifdef AF_SNA + PyModule_AddIntConstant (m, "AF_SNA", AF_SNA); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_SNA), + PyString_FromString("AF_SNA")); +#endif +#ifdef AF_PPPOX + PyModule_AddIntConstant (m, "AF_PPPOX", AF_PPPOX); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_PPPOX), + PyString_FromString("AF_PPPOX")); +#endif +#ifdef AF_WANPIPE + PyModule_AddIntConstant (m, "AF_WANPIPE", AF_WANPIPE); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_WANPIPE), + PyString_FromString("AF_WANPIPE")); +#endif +#ifdef AF_BLUETOOTH + PyModule_AddIntConstant (m, "AF_BLUETOOTH", AF_BLUETOOTH); + PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_BLUETOOTH), + PyString_FromString("AF_BLUETOOTH")); +#endif + PyModule_AddObject(m, "address_families", address_family_dict); +} diff --git a/netifaces.egg-info/PKG-INFO b/netifaces.egg-info/PKG-INFO new file mode 100755 index 0000000..9dcb201 --- /dev/null +++ b/netifaces.egg-info/PKG-INFO @@ -0,0 +1,25 @@ +Metadata-Version: 1.0 +Name: netifaces +Version: 0.6 +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/packaging/python-netifaces.changes b/packaging/python-netifaces.changes new file mode 100644 index 0000000..7b445ea --- /dev/null +++ b/packaging/python-netifaces.changes @@ -0,0 +1,2 @@ +* Fri Aug 31 22:13:02 UTC 2012 - jimmy.huang@intel.com +- Intial import from upstream. diff --git a/packaging/python-netifaces.spec b/packaging/python-netifaces.spec new file mode 100644 index 0000000..5caa207 --- /dev/null +++ b/packaging/python-netifaces.spec @@ -0,0 +1,37 @@ +Name: python-netifaces +Version: 0.6 +Release: 1 +Group: System/Libraries +License: MIT +Url: http://alastairs-place.net/netifaces/ +Summary: Portable network interface information +Source: http://alastairs-place.net/projects/netifaces/netifaces-%{version}.tar.gz +BuildRequires: pkgconfig(python) +BuildRequires: python-setuptools + +%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. + +%prep +%setup -q -n netifaces-%{version} + +%build +python setup.py build + +%install +python setup.py install --prefix=%{_prefix} --root=%{buildroot} + +%files +%defattr(-,root,root,-) +%doc README +%{python_sitearch}/* 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..a9335e4 --- /dev/null +++ b/setup.py @@ -0,0 +1,409 @@ +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 + +# Disable hard links, otherwise building distributions fails +del os.link + +# 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 + #include + #include + 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 + #include + #include + #include + #include + 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 + #include + #include + """ + + for ioctl in ioctls: + testrig = """ + #include + #include + #include + #include + #include + #include + %(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 + #include + #include + #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 + #include + #include + + 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 + #include + #include + #include + #include + %(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.6', + 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])