1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
5 POSIX implementation of local network interface enumeration.
10 from socket import AF_INET, AF_INET6, inet_ntop
12 CDLL, POINTER, Structure, c_char_p, c_ushort, c_int,
13 c_uint32, c_uint8, c_void_p, c_ubyte, pointer, cast)
14 from ctypes.util import find_library
16 libc = CDLL(find_library("c"))
18 if sys.platform == 'darwin':
21 ("sin_family", c_uint8),
25 ("sin_family", c_ushort),
30 class in_addr(Structure):
32 ("in_addr", c_ubyte * 4),
37 class in6_addr(Structure):
39 ("in_addr", c_ubyte * 16),
44 class sockaddr(Structure):
45 _fields_ = _sockaddrCommon + [
46 ("sin_port", c_ushort),
51 class sockaddr_in(Structure):
52 _fields_ = _sockaddrCommon + [
53 ("sin_port", c_ushort),
54 ("sin_addr", in_addr),
59 class sockaddr_in6(Structure):
60 _fields_ = _sockaddrCommon + [
61 ("sin_port", c_ushort),
62 ("sin_flowinfo", c_uint32),
63 ("sin_addr", in6_addr),
68 class ifaddrs(Structure):
71 ifaddrs_p = POINTER(ifaddrs)
73 ('ifa_next', ifaddrs_p),
74 ('ifa_name', c_char_p),
75 ('ifa_flags', c_uint32),
76 ('ifa_addr', POINTER(sockaddr)),
77 ('ifa_netmask', POINTER(sockaddr)),
78 ('ifa_dstaddr', POINTER(sockaddr)),
79 ('ifa_data', c_void_p)]
81 getifaddrs = libc.getifaddrs
82 getifaddrs.argtypes = [POINTER(ifaddrs_p)]
83 getifaddrs.restype = c_int
85 freeifaddrs = libc.freeifaddrs
86 freeifaddrs.argtypes = [ifaddrs_p]
90 Call C{getifaddrs(3)} and return a list of tuples of interface name, address
91 family, and human-readable address representing its results.
94 if getifaddrs(pointer(ifaddrs)) < 0:
99 if ifaddrs[0].ifa_addr:
100 family = ifaddrs[0].ifa_addr[0].sin_family
101 if family == AF_INET:
102 addr = cast(ifaddrs[0].ifa_addr, POINTER(sockaddr_in))
103 elif family == AF_INET6:
104 addr = cast(ifaddrs[0].ifa_addr, POINTER(sockaddr_in6))
109 packed = ''.join(map(chr, addr[0].sin_addr.in_addr[:]))
113 inet_ntop(family, packed)))
115 ifaddrs = ifaddrs[0].ifa_next
122 def posixGetLinkLocalIPv6Addresses():
124 Return a list of strings in colon-hex format representing all the link local
125 IPv6 addresses available on the system, as reported by I{getifaddrs(3)}.
128 for (interface, family, address) in _interfaces():
129 if family == socket.AF_INET6 and address.startswith('fe80:'):
130 retList.append('%s%%%s' % (address, interface))