@ -154,17 +154,18 @@ class DNSUtils:
# try find cached own hostnames (this tuple-key cannot be used elsewhere):
key = ( ' self ' , ' hostname ' , fqdn )
name = DNSUtils . CACHE_ipToName . get ( key )
if name is not None :
return name
# get it using different ways (hostname, fully-qualified or vice versa):
if name is None :
name = ' '
for hostname in (
( getfqdn , socket . gethostname ) if fqdn else ( socket . gethostname , getfqdn )
) :
try :
name = hostname ( )
break
except Exception as e : # pragma: no cover
logSys . warning ( " Retrieving own hostnames failed: %s " , e )
name = ' '
for hostname in (
( getfqdn , socket . gethostname ) if fqdn else ( socket . gethostname , getfqdn )
) :
try :
name = hostname ( )
break
except Exception as e : # pragma: no cover
logSys . warning ( " Retrieving own hostnames failed: %s " , e )
# cache and return :
DNSUtils . CACHE_ipToName . set ( key , name )
return name
@ -177,11 +178,12 @@ class DNSUtils:
""" Get own host names of self """
# try find cached own hostnames:
names = DNSUtils . CACHE_ipToName . get ( DNSUtils . _getSelfNames_key )
if names is not None :
return names
# get it using different ways (a set with names of localhost, hostname, fully qualified):
if names is None :
names = set ( [
' localhost ' , DNSUtils . getHostname ( False ) , DNSUtils . getHostname ( True )
] ) - set ( [ ' ' ] ) # getHostname can return ''
names = set ( [
' localhost ' , DNSUtils . getHostname ( False ) , DNSUtils . getHostname ( True )
] ) - set ( [ ' ' ] ) # getHostname can return ''
# cache and return :
DNSUtils . CACHE_ipToName . set ( DNSUtils . _getSelfNames_key , names )
return names
@ -194,14 +196,19 @@ class DNSUtils:
""" Get own IP addresses of self """
# to find cached own IPs:
ips = DNSUtils . CACHE_nameToIp . get ( DNSUtils . _getSelfIPs_key )
# get it using different ways (a set with IPs of localhost, hostname, fully qualified):
if ips is None :
ips = set ( )
for hostname in DNSUtils . getSelfNames ( ) :
try :
ips | = set ( DNSUtils . textToIp ( hostname , ' yes ' ) )
except Exception as e : # pragma: no cover
logSys . warning ( " Retrieving own IPs of %s failed: %s " , hostname , e )
if ips is not None :
return ips
# firstly try to obtain from network interfaces if possible (implemented for this platform):
try :
ips = IPAddrSet ( [ a for ni , a in DNSUtils . _NetworkInterfacesAddrs ( ) ] )
except :
ips = IPAddrSet ( )
# extend it using different ways (a set with IPs of localhost, hostname, fully qualified):
for hostname in DNSUtils . getSelfNames ( ) :
try :
ips | = IPAddrSet ( DNSUtils . textToIp ( hostname , ' yes ' ) )
except Exception as e : # pragma: no cover
logSys . warning ( " Retrieving own IPs of %s failed: %s " , hostname , e )
# cache and return :
DNSUtils . CACHE_nameToIp . set ( DNSUtils . _getSelfIPs_key , ips )
return ips
@ -586,6 +593,9 @@ class IPAddr(object):
"""
return isinstance ( ip , IPAddr ) and ( ip == self or ip . isInNet ( self ) )
def __contains__ ( self , ip ) :
return self . contains ( ip )
# Pre-calculated map: addr to maskplen
def __getMaskMap ( ) :
m6 = ( 1 << 128 ) - 1
@ -635,3 +645,111 @@ class IPAddr(object):
# An IPv4 compatible IPv6 to be reused
IPAddr . IP6_4COMPAT = IPAddr ( " ::ffff:0:0 " , 96 )
class IPAddrSet ( set ) :
def __contains__ ( self , ip ) :
if not isinstance ( ip , IPAddr ) : ip = IPAddr ( ip )
# IP can be found directly or IP is in each subnet:
return set . __contains__ ( self , ip ) or any ( n . contains ( ip ) for n in self )
def _NetworkInterfacesAddrs ( ) :
# Closure implementing lazy load modules and libc and define _NetworkInterfacesAddrs on demand:
# Currently tested on Linux only (TODO: implement for MacOS, Solaris, etc)
from ctypes import (
Structure , Union , POINTER ,
pointer , get_errno , cast ,
c_ushort , c_byte , c_void_p , c_char_p , c_uint , c_int , c_uint16 , c_uint32
)
import ctypes . util
import ctypes
class struct_sockaddr ( Structure ) :
_fields_ = [
( ' sa_family ' , c_ushort ) ,
( ' sa_data ' , c_byte * 14 ) , ]
class struct_sockaddr_in ( Structure ) :
_fields_ = [
( ' sin_family ' , c_ushort ) ,
( ' sin_port ' , c_uint16 ) ,
( ' sin_addr ' , c_byte * 4 ) ]
class struct_sockaddr_in6 ( Structure ) :
_fields_ = [
( ' sin6_family ' , c_ushort ) ,
( ' sin6_port ' , c_uint16 ) ,
( ' sin6_flowinfo ' , c_uint32 ) ,
( ' sin6_addr ' , c_byte * 16 ) ,
( ' sin6_scope_id ' , c_uint32 ) ]
class union_ifa_ifu ( Union ) :
_fields_ = [
( ' ifu_broadaddr ' , POINTER ( struct_sockaddr ) ) ,
( ' ifu_dstaddr ' , POINTER ( struct_sockaddr ) ) , ]
class struct_ifaddrs ( Structure ) :
pass
struct_ifaddrs . _fields_ = [
( ' ifa_next ' , POINTER ( struct_ifaddrs ) ) ,
( ' ifa_name ' , c_char_p ) ,
( ' ifa_flags ' , c_uint ) ,
( ' ifa_addr ' , POINTER ( struct_sockaddr ) ) ,
( ' ifa_netmask ' , POINTER ( struct_sockaddr ) ) ,
( ' ifa_ifu ' , union_ifa_ifu ) ,
( ' ifa_data ' , c_void_p ) , ]
libc = ctypes . CDLL ( ctypes . util . find_library ( ' c ' ) )
def ifap_iter ( ifap ) :
ifa = ifap . contents
while True :
yield ifa
if not ifa . ifa_next :
break
ifa = ifa . ifa_next . contents
def getfamaddr ( ifa ) :
sa = ifa . ifa_addr . contents
fam = sa . sa_family
if fam == socket . AF_INET :
sa = cast ( pointer ( sa ) , POINTER ( struct_sockaddr_in ) ) . contents
addr = socket . inet_ntop ( fam , sa . sin_addr )
nm = ifa . ifa_netmask . contents
if nm is not None and nm . sa_family == socket . AF_INET :
nm = cast ( pointer ( nm ) , POINTER ( struct_sockaddr_in ) ) . contents
addr + = ' / ' + socket . inet_ntop ( fam , nm . sin_addr )
return IPAddr ( addr )
elif fam == socket . AF_INET6 :
sa = cast ( pointer ( sa ) , POINTER ( struct_sockaddr_in6 ) ) . contents
addr = socket . inet_ntop ( fam , sa . sin6_addr )
nm = ifa . ifa_netmask . contents
if nm is not None and nm . sa_family == socket . AF_INET6 :
nm = cast ( pointer ( nm ) , POINTER ( struct_sockaddr_in6 ) ) . contents
addr + = ' / ' + socket . inet_ntop ( fam , nm . sin6_addr )
return IPAddr ( addr )
return None
def _NetworkInterfacesAddrs ( ) :
ifap = POINTER ( struct_ifaddrs ) ( )
result = libc . getifaddrs ( pointer ( ifap ) )
if result != 0 :
raise OSError ( get_errno ( ) )
del result
try :
for ifa in ifap_iter ( ifap ) :
name = ifa . ifa_name . decode ( " UTF-8 " )
addr = getfamaddr ( ifa )
if addr :
yield name , addr
finally :
libc . freeifaddrs ( ifap )
DNSUtils . _NetworkInterfacesAddrs = staticmethod ( _NetworkInterfacesAddrs ) ;
return _NetworkInterfacesAddrs ( )
DNSUtils . _NetworkInterfacesAddrs = staticmethod ( _NetworkInterfacesAddrs ) ;