Hello community, here is the log from the commit of package python-netifaces for openSUSE:Factory checked in at 2017-04-28 09:12:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-netifaces (Old) and /work/SRC/openSUSE:Factory/.python-netifaces.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-netifaces" Fri Apr 28 09:12:11 2017 rev:11 rq:484783 version:0.10.5 Changes: -------- --- /work/SRC/openSUSE:Factory/python-netifaces/python-netifaces.changes 2014-05-26 14:43:43.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-netifaces.new/python-netifaces.changes 2017-04-28 09:12:24.153703661 +0200 @@ -1,0 +2,17 @@ +Fri Mar 31 17:31:37 UTC 2017 - [email protected] + +- Use pypi.io as source url. + +------------------------------------------------------------------- +Sat Mar 18 19:50:34 UTC 2017 - [email protected] + +- Update to version 0.10.5: + * Fix setup.py in case there's no print + * Fix a potential one-byte stack overwrite + * Fix possible null pointer deference + * Respect interface priorities when determining default gateway + * Use CIDR notation for IPv6 netmasks + * Ignore broadcast addresses in the 169.254.0.0/16 range +- Convert package to python singlespec. + +------------------------------------------------------------------- Old: ---- netifaces-0.10.4.tar.gz New: ---- netifaces-0.10.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-netifaces.spec ++++++ --- /var/tmp/diff_new_pack.2GfRn8/_old 2017-04-28 09:12:24.989585791 +0200 +++ /var/tmp/diff_new_pack.2GfRn8/_new 2017-04-28 09:12:24.993585227 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-netifaces # -# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. # Copyright (c) 2011 Novell # # All modifications and additions to the file contributed by third parties @@ -17,21 +17,21 @@ # +%{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-netifaces -Version: 0.10.4 +Version: 0.10.5 Release: 0 Summary: Portable network interface information License: MIT Group: Development/Languages/Python Url: http://alastairs-place.net/projects/netifaces/ -Source: https://pypi.python.org/packages/source/n/netifaces/netifaces-%{version}.tar.gz -BuildRequires: python-devel -BuildRequires: python-setuptools -Provides: netifaces +Source: https://pypi.io/packages/source/n/netifaces/netifaces-%{version}.tar.gz +BuildRequires: %{python_module devel} +BuildRequires: %{python_module setuptools} +BuildRequires: python-rpm-macros BuildRoot: %{_tmppath}/%{name}-%{version}-build -%if 0%{?suse_version} && 0%{?suse_version} <= 1110 -%{!?python_sitearch: %global python_sitearch %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} -%endif + +%python_subpackages %description netifaces provides a (hopefully portable-ish) way for Python programmers to @@ -50,12 +50,12 @@ %setup -q -n netifaces-%{version} %build -python setup.py build +%python_build %install -python setup.py install --prefix=%{_prefix} --root=%{buildroot} +%python_install -%files +%files %{python_files} %defattr(-,root,root,-) %doc README.rst %{python_sitearch}/* ++++++ netifaces-0.10.4.tar.gz -> netifaces-0.10.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netifaces-0.10.4/PKG-INFO new/netifaces-0.10.5/PKG-INFO --- old/netifaces-0.10.4/PKG-INFO 2014-05-19 13:40:12.000000000 +0200 +++ new/netifaces-0.10.5/PKG-INFO 2016-08-23 17:28:47.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: netifaces -Version: 0.10.4 +Version: 0.10.5 Summary: Portable network interface information. Home-page: https://bitbucket.org/al45tair/netifaces Author: Alastair Houghton diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netifaces-0.10.4/netifaces.c new/netifaces-0.10.5/netifaces.c --- old/netifaces-0.10.4/netifaces.c 2014-05-19 13:38:09.000000000 +0200 +++ new/netifaces-0.10.5/netifaces.c 2016-08-23 17:00:14.000000000 +0200 @@ -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> @@ -397,7 +405,8 @@ sprintf (ptr, "%02x:", data[n] & 0xff); ptr += 3; } - *--ptr = '\0'; + if (len) + *--ptr = '\0'; } if (!buffer[0]) @@ -405,6 +414,94 @@ return 0; } + +/* Tries to format in CIDR form where possible; falls back to using + string_from_sockaddr(). */ +static int +string_from_netmask (struct sockaddr *addr, + char *buffer, + int buflen) +{ +#ifdef AF_INET6 + if (addr && addr->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; + unsigned n = 16; + unsigned zeroes = 0; + unsigned prefix; + unsigned bytes; + char *bufptr = buffer; + char *bufend = buffer + buflen; + char pfxbuf[16]; + + while (n--) { + unsigned char byte = sin6->sin6_addr.s6_addr[n]; + + /* We need to count the rightmost zeroes */ + unsigned char x = byte; + unsigned zx = 8; + + x &= -x; + if (x) + --zx; + if (x & 0x0f) + zx -= 4; + if (x & 0x03) + zx -= 2; + if (x & 0x05) + zx -= 1; + + zeroes += zx; + + if (byte) + break; + } + + prefix = 128 - zeroes; + bytes = 2 * ((prefix + 15) / 16); + + for (n = 0; n < bytes; ++n) { + unsigned char byte = sin6->sin6_addr.s6_addr[n]; + char ch1, ch2; + + if (n && !(n & 1)) { + if (bufptr < bufend) + *bufptr++ = ':'; + } + + ch1 = '0' + (byte >> 4); + if (ch1 > '9') + ch1 += 'a' - '0' - 10; + ch2 = '0' + (byte & 0xf); + if (ch2 > '9') + ch2 += 'a' - '0' - 10; + + if (bufptr < bufend) + *bufptr++ = ch1; + if (bufptr < bufend) + *bufptr++ = ch2; + } + + if (bytes < 16) { + if (bufend - bufptr > 2) { + *bufptr++ = ':'; + *bufptr++ = ':'; + } + } + + sprintf (pfxbuf, "/%u", prefix); + + if (bufend - bufptr > strlen(pfxbuf)) + strcpy (bufptr, pfxbuf); + + if (buflen) + buffer[buflen - 1] = '\0'; + + return 0; + } +#endif + + return string_from_sockaddr(addr, buffer, buflen); +} #endif /* !defined(WIN32) */ #if defined(WIN32) @@ -440,6 +537,135 @@ return 0; } + +static PyObject * +netmask_from_prefix (unsigned prefix) +{ + char buffer[256]; + char *bufptr = buffer; + char *bufend = buffer + sizeof(buffer); + unsigned bytes = 2 * ((prefix + 15) / 16); + static const unsigned char masks[] = { + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe + }; + unsigned n; + unsigned left = prefix; + char pfxbuf[16]; + + for (n = 0; n < bytes; ++n) { + unsigned char byte; + char ch1, ch2; + + if (left >= 8) { + byte = 0xff; + left -= 8; + } else { + byte = masks[left]; + left = 0; + } + + if (n && !(n & 1)) { + if (bufptr < bufend) + *bufptr++ = ':'; + } + + ch1 = '0' + (byte >> 4); + if (ch1 > '9') + ch1 += 'a' - '0' - 10; + ch2 = '0' + (byte & 0xf); + if (ch2 > '9') + ch2 += 'a' - '0' - 10; + + if (bufptr < bufend) + *bufptr++ = ch1; + if (bufptr < bufend) + *bufptr++ = ch2; + } + + if (bytes < 16) { + if (bufend - bufptr > 2) { + *bufptr++ = ':'; + *bufptr++ = ':'; + } + } + + sprintf (pfxbuf, "/%u", prefix); + + if ((size_t)(bufend - bufptr) > strlen(pfxbuf)) + strcpy (bufptr, pfxbuf); + + buffer[sizeof(buffer) - 1] = '\0'; + + return PyString_FromString(buffer); +} + +/* We dynamically bind to WSAAddressToStringW or WSAAddressToStringA + depending on which is available, as the latter is deprecated and + the former doesn't exist on all Windows versions on which this code + might run. */ +typedef INT (WSAAPI *WSAAddressToStringWPtr)(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOW, LPWSTR, LPDWORD); +typedef INT (WSAAPI *WSAAddressToStringAPtr)(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); + +static WSAAddressToStringWPtr +get_address_to_string_w(void) { + static int ptr_is_set; + static WSAAddressToStringWPtr ptr; + + if (!ptr_is_set) { + HMODULE hmod = LoadLibrary ("ws2_32.dll"); + ptr = (WSAAddressToStringWPtr)GetProcAddress (hmod, "WSAAddressToStringW"); + if (!ptr) + FreeLibrary (hmod); + ptr_is_set = 1; + } + + return ptr; +} + +static WSAAddressToStringAPtr +get_address_to_string_a(void) { + static int ptr_is_set; + static WSAAddressToStringAPtr ptr; + + if (!ptr_is_set) { + HMODULE hmod = LoadLibrary ("ws2_32.dll"); + ptr = (WSAAddressToStringAPtr)GetProcAddress (hmod, "WSAAddressToStringA"); + if (!ptr) + FreeLibrary (hmod); + ptr_is_set = 1; + } + + return ptr; +} + +static PyObject * +string_from_address(SOCKADDR *addr, DWORD addrlen) +{ + WSAAddressToStringWPtr AddressToStringW = get_address_to_string_w(); + + if (AddressToStringW) { + wchar_t buffer[256]; + DWORD dwLen = sizeof(buffer) / sizeof(wchar_t); + INT iRet; + + iRet = AddressToStringW (addr, addrlen, NULL, buffer, &dwLen); + + if (iRet == 0) + return PyUnicode_FromWideChar (buffer, dwLen - 1); + } else { + char buffer[256]; + DWORD dwLen = sizeof(buffer); + WSAAddressToStringAPtr AddressToStringA = get_address_to_string_a(); + INT iRet; + + iRet = AddressToStringA (addr, addrlen, NULL, buffer, &dwLen); + + if (iRet == 0) + return PyString_FromString (buffer); + } + + return NULL; +} #endif static int @@ -551,7 +777,7 @@ PyObject *hwaddr, *dict; char *ptr = buffer; unsigned n; - + *ptr = '\0'; for (n = 0; n < pInfo->PhysicalAddressLength; ++n) { sprintf (ptr, "%02x:", pInfo->PhysicalAddress[n] & 0xff); @@ -582,188 +808,151 @@ for (pUniAddr = pInfo->FirstUnicastAddress; pUniAddr; pUniAddr = pUniAddr->Next) { - DWORD dwLen = sizeof (buffer); - INT iRet = WSAAddressToStringA (pUniAddr->Address.lpSockaddr, - pUniAddr->Address.iSockaddrLength, - NULL, - buffer, - &dwLen); PyObject *addr; PyObject *mask = NULL; PyObject *bcast = NULL; PIP_ADAPTER_PREFIX pPrefix; short family = pUniAddr->Address.lpSockaddr->sa_family; - if (iRet) - continue; + addr = string_from_address (pUniAddr->Address.lpSockaddr, + pUniAddr->Address.iSockaddrLength); - addr = PyString_FromString (buffer); + if (!addr) + continue; /* Find the netmask, where possible */ if (family == AF_INET) { - struct sockaddr_in *pAddr + struct sockaddr_in *pAddr = (struct sockaddr_in *)pUniAddr->Address.lpSockaddr; + int prefix_len = -1; + struct sockaddr_in maskAddr, bcastAddr; + unsigned toDo; + unsigned wholeBytes, remainingBits; + unsigned char *pMaskBits, *pBcastBits; + PIP_ADAPTER_PREFIX pBest = NULL; for (pPrefix = pInfo->FirstPrefix; pPrefix; pPrefix = pPrefix->Next) { struct sockaddr_in *pPrefixAddr = (struct sockaddr_in *)pPrefix->Address.lpSockaddr; - struct sockaddr_in maskAddr, bcastAddr; - unsigned toDo; - unsigned wholeBytes, remainingBits; - unsigned char *pMaskBits, *pBcastBits; - if (pPrefixAddr->sin_family != AF_INET) + if (pPrefixAddr->sin_family != AF_INET + || (prefix_len >= 0 && pPrefix->PrefixLength < prefix_len)) continue; - + if (compare_bits (&pPrefixAddr->sin_addr, &pAddr->sin_addr, - pPrefix->PrefixLength) != 0) - continue; - - memcpy (&maskAddr, - pPrefix->Address.lpSockaddr, - sizeof (maskAddr)); - memcpy (&bcastAddr, - pPrefix->Address.lpSockaddr, - sizeof (bcastAddr)); - - wholeBytes = pPrefix->PrefixLength >> 3; - remainingBits = pPrefix->PrefixLength & 7; - - if (wholeBytes >= 4) - continue; - - toDo = wholeBytes; - pMaskBits = (unsigned char *)&maskAddr.sin_addr; - - while (toDo--) - *pMaskBits++ = 0xff; - - toDo = 4 - wholeBytes; - - pBcastBits = (unsigned char *)&bcastAddr.sin_addr + wholeBytes; - - if (remainingBits) { - static const unsigned char masks[] = { - 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe - }; - *pMaskBits++ = masks[remainingBits]; - *pBcastBits &= masks[remainingBits]; - *pBcastBits++ |= ~masks[remainingBits]; - --toDo; + pPrefix->PrefixLength) == 0) { + prefix_len = pPrefix->PrefixLength; + pBest = pPrefix; } + } - while (toDo--) { - *pMaskBits++ = 0; - *pBcastBits++ = 0xff; - } + if (!pBest) + continue; - dwLen = sizeof (buffer); - iRet = WSAAddressToStringA ((SOCKADDR *)&maskAddr, - sizeof (maskAddr), - NULL, - buffer, - &dwLen); - - if (iRet == 0) - mask = PyString_FromString (buffer); - - dwLen = sizeof (buffer); - iRet = WSAAddressToStringA ((SOCKADDR *)&bcastAddr, - sizeof (bcastAddr), - NULL, - buffer, - &dwLen); + if (prefix_len < 0) + prefix_len = 32; - if (iRet == 0) - bcast = PyString_FromString (buffer); + memcpy (&maskAddr, + pBest->Address.lpSockaddr, + sizeof (maskAddr)); + memcpy (&bcastAddr, + pBest->Address.lpSockaddr, + sizeof (bcastAddr)); + + wholeBytes = prefix_len >> 3; + remainingBits = prefix_len & 7; + + toDo = wholeBytes; + pMaskBits = (unsigned char *)&maskAddr.sin_addr; + + while (toDo--) + *pMaskBits++ = 0xff; + + toDo = 4 - wholeBytes; + + pBcastBits = (unsigned char *)&bcastAddr.sin_addr + wholeBytes; + + if (remainingBits) { + static const unsigned char masks[] = { + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe + }; + *pMaskBits++ = masks[remainingBits]; + *pBcastBits &= masks[remainingBits]; + *pBcastBits++ |= ~masks[remainingBits]; + --toDo; + } - break; + while (toDo--) { + *pMaskBits++ = 0; + *pBcastBits++ = 0xff; } + + mask = string_from_address ((SOCKADDR *)&maskAddr, + sizeof (maskAddr)); + bcast = string_from_address ((SOCKADDR *)&bcastAddr, + sizeof (bcastAddr)); } else if (family == AF_INET6) { struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)pUniAddr->Address.lpSockaddr; + int prefix_len = -1; + struct sockaddr_in6 bcastAddr; + unsigned toDo; + unsigned wholeBytes, remainingBits; + unsigned char *pBcastBits; + PIP_ADAPTER_PREFIX pBest = NULL; for (pPrefix = pInfo->FirstPrefix; pPrefix; pPrefix = pPrefix->Next) { struct sockaddr_in6 *pPrefixAddr = (struct sockaddr_in6 *)pPrefix->Address.lpSockaddr; - struct sockaddr_in6 maskAddr, bcastAddr; - unsigned toDo; - unsigned wholeBytes, remainingBits; - unsigned char *pMaskBits, *pBcastBits; - if (pPrefixAddr->sin6_family != AF_INET6) + if (pPrefixAddr->sin6_family != AF_INET6 + || (prefix_len >= 0 && pPrefix->PrefixLength < prefix_len)) continue; - + if (compare_bits (&pPrefixAddr->sin6_addr, &pAddr->sin6_addr, - pPrefix->PrefixLength) != 0) - continue; - - memcpy (&maskAddr, - pPrefix->Address.lpSockaddr, - sizeof (maskAddr)); - memcpy (&bcastAddr, - pPrefix->Address.lpSockaddr, - sizeof (bcastAddr)); - - wholeBytes = pPrefix->PrefixLength >> 3; - remainingBits = pPrefix->PrefixLength & 7; - - if (wholeBytes >= 8) - continue; - - toDo = wholeBytes; - pMaskBits = (unsigned char *)&maskAddr.sin6_addr; - - while (toDo--) - *pMaskBits++ = 0xff; - - toDo = 8 - wholeBytes; - - pBcastBits = (unsigned char *)&bcastAddr.sin6_addr + wholeBytes; - - if (remainingBits) { - static const unsigned char masks[] = { - 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe - }; - *pMaskBits++ = masks[remainingBits]; - *pBcastBits &= masks[remainingBits]; - *pBcastBits++ |= ~masks[remainingBits]; - --toDo; - } - - while (toDo--) { - *pMaskBits++ = 0; - *pBcastBits++ = 0xff; + pPrefix->PrefixLength) == 0) { + prefix_len = pPrefix->PrefixLength; + pBest = pPrefix; } + } - dwLen = sizeof (buffer); - iRet = WSAAddressToStringA ((SOCKADDR *)&maskAddr, - sizeof (maskAddr), - NULL, - buffer, - &dwLen); - - if (iRet == 0) - mask = PyString_FromString (buffer); - - dwLen = sizeof (buffer); - iRet = WSAAddressToStringA ((SOCKADDR *)&bcastAddr, - sizeof (bcastAddr), - NULL, - buffer, - &dwLen); + if (!pBest) + continue; - if (iRet == 0) - bcast = PyString_FromString (buffer); + if (prefix_len < 0) + prefix_len = 128; - break; + memcpy (&bcastAddr, + pBest->Address.lpSockaddr, + sizeof (bcastAddr)); + + wholeBytes = prefix_len >> 3; + remainingBits = prefix_len & 7; + + toDo = 16 - wholeBytes; + + pBcastBits = (unsigned char *)&bcastAddr.sin6_addr + wholeBytes; + + if (remainingBits) { + static const unsigned char masks[] = { + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe + }; + *pBcastBits &= masks[remainingBits]; + *pBcastBits++ |= ~masks[remainingBits]; + --toDo; } + + while (toDo--) + *pBcastBits++ = 0xff; + + mask = netmask_from_prefix (prefix_len); + bcast = string_from_address ((SOCKADDR *)&bcastAddr, sizeof(bcastAddr)); } { @@ -812,7 +1001,7 @@ 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; @@ -826,17 +1015,55 @@ 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; + +#if HAVE_IPV6_SOCKET_IOCTLS + /* 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); + } + + close (sock6); + } +#endif /* HAVE_IPV6_SOCKET_IOCTLS */ 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) + if (string_from_netmask (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); + /* Cygwin's implementation of getaddrinfo() is buggy and returns broadcast + addresses for 169.254.0.0/16. Nix them here. */ + if (addr->ifa_addr->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)addr->ifa_addr; + + if ((ntohl(sin->sin_addr.s_addr) & 0xffff0000) == 0xa9fe0000) { + Py_XDECREF (braddr); + braddr = NULL; + } + } + { PyObject *dict = PyDict_New(); @@ -844,6 +1071,7 @@ Py_XDECREF (pyaddr); Py_XDECREF (netmask); Py_XDECREF (braddr); + Py_XDECREF (flags); Py_DECREF (result); freeifaddrs (addrs); return NULL; @@ -860,10 +1088,14 @@ 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); @@ -1246,7 +1478,7 @@ if (dwErr == NO_ERROR) { DWORD n; - BOOL bFirstInet = TRUE, bFirstInet6 = TRUE; + ULONG lBestInetMetric = ~(ULONG)0, lBestInet6Metric = ~(ULONG)0; result = PyDict_New(); defaults = PyDict_New(); @@ -1262,12 +1494,9 @@ PyObject *gateway; PyObject *isdefault; PyObject *tuple, *deftuple = NULL; - char gwbuf[256]; WCHAR *pwcsName; DWORD dwFamily = table->Table[n].NextHop.si_family; - BOOL bFirst; - DWORD dwLen; - INT iRet; + BOOL bBest = FALSE; if (table->Table[n].DestinationPrefix.PrefixLength) continue; @@ -1292,15 +1521,11 @@ if (GetIfEntry (&ifRow) != NO_ERROR) continue; - dwLen = sizeof (gwbuf); - iRet = WSAAddressToStringA ((SOCKADDR *)&table->Table[n].NextHop, - sizeof (table->Table[n].NextHop), - NULL, - gwbuf, - &dwLen); + gateway = string_from_address ((SOCKADDR *)&table->Table[n].NextHop, + sizeof (table->Table[n].NextHop)); - if (iRet != NO_ERROR) - continue; + if (!gateway) + continue; /* Strip the prefix from the interface name */ pwcsName = ifRow.wszName; @@ -1309,18 +1534,17 @@ switch (dwFamily) { case AF_INET: - bFirst = bFirstInet; - bFirstInet = FALSE; + bBest = table->Table[n].Metric < lBestInetMetric; + lBestInetMetric = table->Table[n].Metric; break; case AF_INET6: - bFirst = bFirstInet6; - bFirstInet6 = FALSE; + bBest = table->Table[n].Metric < lBestInet6Metric; + lBestInet6Metric = table->Table[n].Metric; break; } ifname = PyUnicode_FromUnicode (pwcsName, wcslen (pwcsName)); - gateway = PyString_FromString (gwbuf); - isdefault = bFirst ? Py_True : Py_False; + isdefault = bBest ? Py_True : Py_False; tuple = PyTuple_Pack (3, gateway, ifname, isdefault); @@ -1356,7 +1580,7 @@ DWORD dwRet; DWORD dwSize = 0; DWORD n; - BOOL bFirst = TRUE; + DWORD dwBestMetric = ~(DWORD)0; do { dwRet = GetIpForwardTable (table, &dwSize, FALSE); @@ -1397,6 +1621,7 @@ DWORD dwGateway; char gwbuf[16]; WCHAR *pwcsName; + BOOL bBest; if (table->table[n].dwForwardDest || !table->table[n].dwForwardNextHop @@ -1421,10 +1646,13 @@ if (_wcsnicmp (L"\\DEVICE\\TCPIP_", pwcsName, 14) == 0) pwcsName += 14; + bBest = table->table[n].dwForwardMetric1 < dwBestMetric; + if (bBest) + dwBestMetric = table->table[n].dwForwardMetric1; + ifname = PyUnicode_FromUnicode (pwcsName, wcslen (pwcsName)); gateway = PyString_FromString (gwbuf); - isdefault = bFirst ? Py_True : Py_False; - bFirst = FALSE; + isdefault = bBest ? Py_True : Py_False; tuple = PyTuple_Pack (3, gateway, ifname, isdefault); @@ -1473,6 +1701,9 @@ int bufsize = pagesize < 8192 ? pagesize : 8192; int is_multi = 0; int interrupted = 0; + int def_priorities[RTNL_FAMILY_MAX]; + + memset(def_priorities, 0xff, sizeof(def_priorities)); result = PyDict_New(); defaults = PyDict_New(); @@ -1582,6 +1813,7 @@ int ifndx = -1; struct rtattr *attrs, *attr; int len; + int priority; /* Ignore messages not for us */ if (pmsg->hdr.nlmsg_seq != seq || pmsg->hdr.nlmsg_pid != sanl.nl_pid) @@ -1616,7 +1848,7 @@ attr = attrs = RTM_RTA(&pmsg->rt); len = RTM_PAYLOAD(&pmsg->hdr); - + priority = -1; while (RTA_OK(attr, len)) { switch (attr->rta_type) { case RTA_GATEWAY: @@ -1628,6 +1860,9 @@ case RTA_OIF: ifndx = *(int *)RTA_DATA(attr); break; + case RTA_PRIORITY: + priority = *(int *)RTA_DATA(attr); + break; default: break; } @@ -1661,6 +1896,19 @@ routing tables on Linux. */ isdefault = pmsg->rt.rtm_table == RT_TABLE_MAIN ? Py_True : Py_False; + + /* Try to pick the active default route based on priority (which + is displayed in the UI as "metric", confusingly) */ + if (pmsg->rt.rtm_family < RTNL_FAMILY_MAX) { + if (def_priorities[pmsg->rt.rtm_family] == -1) + def_priorities[pmsg->rt.rtm_family] = priority; + else { + if (priority == -1 + || priority > def_priorities[pmsg->rt.rtm_family]) + isdefault = Py_False; + } + } + pyifname = PyString_FromString (ifname); pyaddr = PyString_FromString (buffer); @@ -1673,7 +1921,7 @@ Py_DECREF (pyifname); if (tuple && !add_to_family (result, pmsg->rt.rtm_family, tuple)) { - Py_DECREF (deftuple); + Py_XDECREF (deftuple); Py_DECREF (result); free (msgbuf); close (s); @@ -1813,7 +2061,8 @@ #ifdef RTF_IFSCOPE PyObject *isdefault = PyBool_FromLong (!(msg->rtm_flags & RTF_IFSCOPE)); #else - PyObject *isdefault = Py_INCREF(Py_True); + Py_INCREF(Py_True); + PyObject *isdefault = Py_True; #endif tuple = PyTuple_Pack (3, pyaddr, pyifname, isdefault); @@ -2604,6 +2853,21 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netifaces-0.10.4/netifaces.egg-info/PKG-INFO new/netifaces-0.10.5/netifaces.egg-info/PKG-INFO --- old/netifaces-0.10.4/netifaces.egg-info/PKG-INFO 2014-05-19 13:40:12.000000000 +0200 +++ new/netifaces-0.10.5/netifaces.egg-info/PKG-INFO 2016-08-23 17:28:47.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: netifaces -Version: 0.10.4 +Version: 0.10.5 Summary: Portable network interface information. Home-page: https://bitbucket.org/al45tair/netifaces Author: Alastair Houghton diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/netifaces-0.10.4/setup.py new/netifaces-0.10.5/setup.py --- old/netifaces-0.10.4/setup.py 2014-05-19 13:39:39.000000000 +0200 +++ new/netifaces-0.10.5/setup.py 2016-08-23 10:36:16.000000000 +0200 @@ -14,9 +14,15 @@ f.write(' '.join(str(a) for a in args)) f.write(end) else: - output = getattr(__builtins__, 'print') + try: + import builtins + except ImportError: + import __builtin__ + builtins = __builtin__ + + 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: @@ -203,6 +209,63 @@ 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='') @@ -355,7 +418,7 @@ 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',
