Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / internet / test / _posixifaces.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 POSIX implementation of local network interface enumeration.
6 """
7
8 import sys, socket
9
10 from socket import AF_INET, AF_INET6, inet_ntop
11 from ctypes import (
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
15
16 libc = CDLL(find_library("c"))
17
18 if sys.platform == 'darwin':
19     _sockaddrCommon = [
20         ("sin_len", c_uint8),
21         ("sin_family", c_uint8),
22         ]
23 else:
24     _sockaddrCommon = [
25         ("sin_family", c_ushort),
26         ]
27
28
29
30 class in_addr(Structure):
31     _fields_ = [
32         ("in_addr", c_ubyte * 4),
33         ]
34
35
36
37 class in6_addr(Structure):
38     _fields_ = [
39         ("in_addr", c_ubyte * 16),
40         ]
41
42
43
44 class sockaddr(Structure):
45     _fields_ = _sockaddrCommon + [
46         ("sin_port", c_ushort),
47         ]
48
49
50
51 class sockaddr_in(Structure):
52     _fields_ = _sockaddrCommon + [
53         ("sin_port", c_ushort),
54         ("sin_addr", in_addr),
55         ]
56
57
58
59 class sockaddr_in6(Structure):
60     _fields_ = _sockaddrCommon + [
61         ("sin_port", c_ushort),
62         ("sin_flowinfo", c_uint32),
63         ("sin_addr", in6_addr),
64         ]
65
66
67
68 class ifaddrs(Structure):
69     pass
70
71 ifaddrs_p = POINTER(ifaddrs)
72 ifaddrs._fields_ = [
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)]
80
81 getifaddrs = libc.getifaddrs
82 getifaddrs.argtypes = [POINTER(ifaddrs_p)]
83 getifaddrs.restype = c_int
84
85 freeifaddrs = libc.freeifaddrs
86 freeifaddrs.argtypes = [ifaddrs_p]
87
88 def _interfaces():
89     """
90     Call C{getifaddrs(3)} and return a list of tuples of interface name, address
91     family, and human-readable address representing its results.
92     """
93     ifaddrs = ifaddrs_p()
94     if getifaddrs(pointer(ifaddrs)) < 0:
95         raise OSError()
96     results = []
97     try:
98         while ifaddrs:
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))
105                 else:
106                     addr = None
107
108                 if addr:
109                     packed = ''.join(map(chr, addr[0].sin_addr.in_addr[:]))
110                     results.append((
111                             ifaddrs[0].ifa_name,
112                             family,
113                             inet_ntop(family, packed)))
114
115             ifaddrs = ifaddrs[0].ifa_next
116     finally:
117         freeifaddrs(ifaddrs)
118     return results
119
120
121
122 def posixGetLinkLocalIPv6Addresses():
123     """
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)}.
126     """
127     retList = []
128     for (interface, family, address) in _interfaces():
129         if family == socket.AF_INET6 and address.startswith('fe80:'):
130             retList.append('%s%%%s' % (address, interface))
131     return retList