summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlastair Houghton <alastair@alastairs-place.net>2016-08-23 09:36:04 +0100
committerAlastair Houghton <alastair@alastairs-place.net>2016-08-23 09:36:04 +0100
commit70ebb6e4fe76d60f8103e99540ab71cb282115d7 (patch)
tree1069ea11e5b13f6f022aa62b6cd70aa0323ebc70
parentad862f3d7966c79dfadc12f257f53eed5ef347c6 (diff)
parent77147ee8ca3811399a79f3aaa9ce4a293891392b (diff)
downloadnetifaces-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.c55
-rw-r--r--setup.py61
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
diff --git a/setup.py b/setup.py
index b289cc9..0ce3742 100644
--- a/setup.py
+++ b/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',