diff options
author | Alastair Houghton <alastair@alastairs-place.net> | 2016-08-23 09:36:04 +0100 |
---|---|---|
committer | Alastair Houghton <alastair@alastairs-place.net> | 2016-08-23 09:36:04 +0100 |
commit | 70ebb6e4fe76d60f8103e99540ab71cb282115d7 (patch) | |
tree | 1069ea11e5b13f6f022aa62b6cd70aa0323ebc70 | |
parent | ad862f3d7966c79dfadc12f257f53eed5ef347c6 (diff) | |
parent | 77147ee8ca3811399a79f3aaa9ce4a293891392b (diff) | |
download | netifaces-70ebb6e4fe76d60f8103e99540ab71cb282115d7.tar.gz |
Merged in steffann/netifaces (pull request #5), though it's missing a `close()` call, so until I check in the fix, the tip will leak sockets for IPv6.
Add support for retrieving IPv6 address flags on BSD/Mac-OS
-rw-r--r-- | netifaces.c | 55 | ||||
-rw-r--r-- | setup.py | 61 |
2 files changed, 112 insertions, 4 deletions
diff --git a/netifaces.c b/netifaces.c index 6268fd7..18b013f 100644 --- a/netifaces.c +++ b/netifaces.c @@ -45,6 +45,14 @@ # include <arpa/inet.h> # endif +# if HAVE_GETIFADDRS +# if HAVE_IPV6_SOCKET_IOCTLS +# include <sys/ioctl.h> +# include <netinet/in.h> +# include <netinet/in_var.h> +# endif +# endif + # if HAVE_SOCKET_IOCTLS # include <sys/ioctl.h> # include <netinet/in.h> @@ -813,7 +821,7 @@ ifaddrs (PyObject *self, PyObject *args) for (addr = addrs; addr; addr = addr->ifa_next) { char buffer[256]; - PyObject *pyaddr = NULL, *netmask = NULL, *braddr = NULL; + PyObject *pyaddr = NULL, *netmask = NULL, *braddr = NULL, *flags = NULL; if (strcmp (addr->ifa_name, ifname) != 0) continue; @@ -827,7 +835,30 @@ ifaddrs (PyObject *self, PyObject *args) 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; + continue; + + /* For IPv6 addresses we try to get the flags. */ + if (addr->ifa_addr->sa_family == AF_INET6) { + struct sockaddr_in6 *sin; + struct in6_ifreq ifr6; + + int sock6 = socket (AF_INET6, SOCK_DGRAM, 0); + + if (sock6 < 0) { + Py_DECREF (result); + PyErr_SetFromErrno (PyExc_OSError); + freeifaddrs (addrs); + return NULL; + } + + sin = (struct sockaddr_in6 *)addr->ifa_addr; + strncpy (ifr6.ifr_name, addr->ifa_name, IFNAMSIZ); + ifr6.ifr_addr = *sin; + + if (ioctl (sock6, SIOCGIFAFLAG_IN6, &ifr6) >= 0) { + flags = PyLong_FromUnsignedLong (ifr6.ifr_ifru.ifru_flags6); + } + } if (string_from_sockaddr (addr->ifa_addr, buffer, sizeof (buffer)) == 0) pyaddr = PyString_FromString (buffer); @@ -845,6 +876,7 @@ ifaddrs (PyObject *self, PyObject *args) Py_XDECREF (pyaddr); Py_XDECREF (netmask); Py_XDECREF (braddr); + Py_XDECREF (flags); Py_DECREF (result); freeifaddrs (addrs); return NULL; @@ -861,10 +893,14 @@ ifaddrs (PyObject *self, PyObject *args) else PyDict_SetItemString (dict, "broadcast", braddr); } + + if (flags) + PyDict_SetItemString (dict, "flags", flags); Py_XDECREF (pyaddr); Py_XDECREF (netmask); Py_XDECREF (braddr); + Py_XDECREF (flags); if (!add_to_family (result, addr->ifa_addr->sa_family, dict)) { Py_DECREF (result); @@ -2606,6 +2642,21 @@ MODULE_INIT(netifaces) PyDict_SetItem(address_family_dict, PyInt_FromLong(AF_BLUETOOTH), PyString_FromString("AF_BLUETOOTH")); #endif +#ifdef IN6_IFF_AUTOCONF + PyModule_AddIntConstant (m, "IN6_IFF_AUTOCONF", IN6_IFF_AUTOCONF); +#endif +#ifdef IN6_IFF_TEMPORARY + PyModule_AddIntConstant (m, "IN6_IFF_TEMPORARY", IN6_IFF_TEMPORARY); +#endif +#ifdef IN6_IFF_DYNAMIC + PyModule_AddIntConstant (m, "IN6_IFF_DYNAMIC", IN6_IFF_DYNAMIC); +#endif +#ifdef IN6_IFF_OPTIMISTIC + PyModule_AddIntConstant (m, "IN6_IFF_OPTIMISTIC", IN6_IFF_OPTIMISTIC); +#endif +#ifdef IN6_IFF_SECURED + PyModule_AddIntConstant (m, "IN6_IFF_SECURED", IN6_IFF_SECURED); +#endif PyModule_AddObject(m, "address_families", address_family_dict); // Add-in the version number from setup.py @@ -22,7 +22,7 @@ else: output = getattr(builtins, 'print', lambda x: True) -__version__ = "0.10.4" +__version__ = "0.10.5" # Disable hard links, otherwise building distributions fails on OS X try: @@ -209,6 +209,63 @@ class my_build_ext(build_ext): results['have_getnameinfo'] = result + if results['have_getifaddrs']: + output("checking for IPv6 socket IOCTLs...", end='') + + result = results.get('have_ipv6_socket_ioctls', 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, 'conftest4.out') + self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) + + result = [] + ioctls = ('SIOCGIFAFLAG_IN6',) + 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 <netinet/in_var.h> + #include <arpa/inet.h> + %(addedinc)s + int main(void) { + int fd = socket (AF_INET6, SOCK_DGRAM, IPPROTO_IPV6); + struct in6_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: + output("%r. %s" % (result, cached)) + for ioctl in result: + self.compiler.define_macro('HAVE_%s' % ioctl, 1) + self.compiler.define_macro('HAVE_IPV6_SOCKET_IOCTLS', 1) + else: + output("not found. %s" % cached) + + results['have_ipv6_socket_ioctls'] = result + if not results['have_getifaddrs']: output("checking for socket IOCTLs...", end='') @@ -361,7 +418,7 @@ class my_build_ext(build_ext): if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) - outname = os.path.join(self.build_temp, 'conftest4.out') + outname = os.path.join(self.build_temp, 'conftest5.out') self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) sockaddrs = ('at', 'ax25', 'dl', 'eon', 'in', 'in6', |