00001
00002
00003
00004
00005
00006 from socket import AF_INET, AF_INET6, inet_ntop
00007 from ctypes import (
00008 Structure, Union, POINTER,
00009 pointer, get_errno, cast,
00010 c_ushort, c_byte, c_void_p, c_char_p, c_uint, c_int, c_uint16, c_uint32
00011 )
00012 import ctypes.util
00013 import ctypes
00014
00015 class struct_sockaddr(Structure):
00016 _fields_ = [
00017 ('sa_family', c_ushort),
00018 ('sa_data', c_byte * 14),]
00019
00020 class struct_sockaddr_in(Structure):
00021 _fields_ = [
00022 ('sin_family', c_ushort),
00023 ('sin_port', c_uint16),
00024 ('sin_addr', c_byte * 4)]
00025
00026 class struct_sockaddr_in6(Structure):
00027 _fields_ = [
00028 ('sin6_family', c_ushort),
00029 ('sin6_port', c_uint16),
00030 ('sin6_flowinfo', c_uint32),
00031 ('sin6_addr', c_byte * 16),
00032 ('sin6_scope_id', c_uint32)]
00033
00034 class union_ifa_ifu(Union):
00035 _fields_ = [
00036 ('ifu_broadaddr', POINTER(struct_sockaddr)),
00037 ('ifu_dstaddr', POINTER(struct_sockaddr)),]
00038
00039 class struct_ifaddrs(Structure):
00040 pass
00041 struct_ifaddrs._fields_ = [
00042 ('ifa_next', POINTER(struct_ifaddrs)),
00043 ('ifa_name', c_char_p),
00044 ('ifa_flags', c_uint),
00045 ('ifa_addr', POINTER(struct_sockaddr)),
00046 ('ifa_netmask', POINTER(struct_sockaddr)),
00047 ('ifa_ifu', union_ifa_ifu),
00048 ('ifa_data', c_void_p),]
00049
00050 libc = ctypes.CDLL(ctypes.util.find_library('c'))
00051
00052 def ifap_iter(ifap):
00053 ifa = ifap.contents
00054 while True:
00055 yield ifa
00056 if not ifa.ifa_next:
00057 break
00058 ifa = ifa.ifa_next.contents
00059
00060 def getfamaddr(sa):
00061 family = sa.sa_family
00062 addr = None
00063 if family == AF_INET:
00064 sa = cast(pointer(sa), POINTER(struct_sockaddr_in)).contents
00065 addr = inet_ntop(family, sa.sin_addr)
00066 elif family == AF_INET6:
00067 sa = cast(pointer(sa), POINTER(struct_sockaddr_in6)).contents
00068 addr = inet_ntop(family, sa.sin6_addr)
00069 return family, addr
00070
00071 class NetworkInterface(object):
00072 def __init__(self, name):
00073 self.name = name
00074 self.index = libc.if_nametoindex(name)
00075 self.addresses = {}
00076
00077 def __str__(self):
00078 return "%s [index=%d, IPv4=%s, IPv6=%s]" % (
00079 self.name, self.index,
00080 self.addresses.get(AF_INET),
00081 self.addresses.get(AF_INET6))
00082
00083 def name(self):
00084 return self.name,
00085
00086 def get_network_interfaces():
00087 ifap = POINTER(struct_ifaddrs)()
00088 result = libc.getifaddrs(pointer(ifap))
00089 if result != 0:
00090 raise OSError(get_errno())
00091 del result
00092 try:
00093 retval = {}
00094 for ifa in ifap_iter(ifap):
00095 name = ifa.ifa_name
00096 i = retval.get(name)
00097 if not i:
00098 i = retval[name] = NetworkInterface(name)
00099 family, addr = getfamaddr(ifa.ifa_addr.contents)
00100 if addr:
00101 i.addresses[family] = addr
00102 return retval.values()
00103 finally:
00104 libc.freeifaddrs(ifap)
00105
00106 if __name__ == '__main__':
00107 print [str(ni) for ni in get_network_interfaces()]