From c008151601e617b90ef1c599f4023c788143e785 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Thu, 31 Mar 2022 16:17:16 -0400 Subject: [PATCH] start implementing our own limited equivalent to netifaces --- setup.py | 3 - src/allmydata/util/_posix_netifaces.py | 98 ++++++++++++++++++++++++++ src/allmydata/util/iputil.py | 2 +- src/allmydata/util/netifaces.py | 12 ++++ 4 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 src/allmydata/util/_posix_netifaces.py create mode 100644 src/allmydata/util/netifaces.py diff --git a/setup.py b/setup.py index 5285b5d08..591b04868 100644 --- a/setup.py +++ b/setup.py @@ -119,9 +119,6 @@ install_requires = [ # Support for Python 3 transition "future >= 0.18.2", - # Discover local network configuration - "netifaces", - # Utility code: "pyutil >= 3.3.0", diff --git a/src/allmydata/util/_posix_netifaces.py b/src/allmydata/util/_posix_netifaces.py new file mode 100644 index 000000000..81126a5f6 --- /dev/null +++ b/src/allmydata/util/_posix_netifaces.py @@ -0,0 +1,98 @@ + +from cffi import FFI +from socket import inet_ntop, AF_INET, AF_INET6 + +ffi = FFI() +ffi.cdef(""" +struct in_addr { + union { + struct { + unsigned char s_b1; + unsigned char s_b2; + unsigned char s_b3; + unsigned char s_b4; + } S_un_b; + struct { + unsigned short s_w1; + unsigned short s_w2; + } S_un_w; + unsigned long S_addr; + } S_un; +}; + +struct in6_addr { + uint8_t s6_addr[16]; /* IPv6 address */ +}; + +struct sockaddr { + unsigned short sa_family; + char sa_data[14]; +}; + +struct sockaddr_in { + unsigned short sin_family; + unsigned short sin_port; + struct in_addr sin_addr; +}; + +struct sockaddr_in6 { + unsigned char sin6_len; /* length of this structure */ + unsigned char sin6_family; /* AF_INET6 */ + uint16_t sin6_port; /* Transport layer port # */ + uint32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ +}; + +struct ifaddrs { + struct ifaddrs *ifa_next; /* Next item in list */ + char *ifa_name; /* Name of interface */ + unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */ + struct sockaddr *ifa_addr; /* Address of interface */ + struct sockaddr *ifa_netmask; /* Netmask of interface */ +}; + +int getifaddrs(struct ifaddrs **ifap); +void freeifaddrs(struct ifaddrs *ifa); +""") +_C = ffi.dlopen(None) + +def interfaces(): + result = {} + + # The memory allocated is garbage collected along with ifaddrs_p + ifaddrs_p = ffi.new("struct ifaddrs**") + + errno = _C.getifaddrs(ifaddrs_p) + if errno == 0: + try: + # Success, read the values. + ifaddr = ifaddrs_p[0] + while ifaddr != ffi.NULL: + addr = _sockaddr_to_address(ifaddr.ifa_addr) + if addr is not None: + result.setdefault(ffi.string(ifaddr.ifa_name), []).append(addr) + ifaddr = ifaddr.ifa_next + finally: + # The ifaddrs structs themselves are dynamically allocated by + # getifaddrs and need to be freed. + _C.freeifaddrs(ifaddrs_p[0]) + else: + raise OSError(errno) + + return result + + +def _sockaddr_to_address(sockaddr): + if sockaddr.sa_family == AF_INET: + sockaddr_x = ffi.cast("struct sockaddr_in*", sockaddr) + offset = 4 + size = 4 + elif sockaddr.sa_family == AF_INET6: + sockaddr_x = ffi.cast("struct sockaddr_in6*", sockaddr) + offset = 8 + size = 16 + else: + return None + + buf = ffi.buffer(sockaddr_x, offset + size)[offset:offset + size] + return inet_ntop(sockaddr.sa_family, buf) diff --git a/src/allmydata/util/iputil.py b/src/allmydata/util/iputil.py index fd3e88c7f..2ad967346 100644 --- a/src/allmydata/util/iputil.py +++ b/src/allmydata/util/iputil.py @@ -19,7 +19,7 @@ from zope.interface import implementer import attr -from netifaces import ( +from .netifaces import ( interfaces, ifaddresses, ) diff --git a/src/allmydata/util/netifaces.py b/src/allmydata/util/netifaces.py new file mode 100644 index 000000000..105fbacfe --- /dev/null +++ b/src/allmydata/util/netifaces.py @@ -0,0 +1,12 @@ + +__all__ = [ + "interfaces", +] + +from twisted.python.runtime import platform + +if platform.isWindows(): + from ._windows_netifaces import interfaces +else: + from ._posix_netifaces import interfaces +