ifaddrs.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. routines for getting network interface addresses
  5. """
  6. # by Benjamin C. Wiley Sittler, BSD/OSX support by Greg Hazel
  7. __all__ = [
  8. 'getifaddrs',
  9. 'getaddrs',
  10. 'getnetaddrs',
  11. 'getbroadaddrs',
  12. 'getdstaddrs',
  13. 'main',
  14. 'IFF_UP',
  15. 'IFF_BROADCAST',
  16. 'IFF_DEBUG',
  17. 'IFF_LOOPBACK',
  18. 'IFF_POINTOPOINT',
  19. 'IFF_NOTRAILERS',
  20. 'IFF_RUNNING',
  21. 'IFF_NOARP',
  22. 'IFF_PROMISC',
  23. 'IFF_ALLMULTI',
  24. 'IFF_MASTER',
  25. 'IFF_SLAVE',
  26. 'IFF_MULTICAST',
  27. 'IFF_PORTSEL',
  28. 'IFF_AUTOMEDIA',
  29. 'IFF_DYNAMIC',
  30. 'IFF_LOWER_UP',
  31. 'IFF_DORMANT',
  32. 'ARPHRD_NETROM',
  33. 'ARPHRD_ETHER',
  34. 'ARPHRD_EETHER',
  35. 'ARPHRD_AX25',
  36. 'ARPHRD_PRONET',
  37. 'ARPHRD_CHAOS',
  38. 'ARPHRD_IEEE802',
  39. 'ARPHRD_ARCNET',
  40. 'ARPHRD_APPLETLK',
  41. 'ARPHRD_DLCI',
  42. 'ARPHRD_ATM',
  43. 'ARPHRD_METRICOM',
  44. 'ARPHRD_IEEE1394',
  45. 'ARPHRD_EUI64',
  46. 'ARPHRD_INFINIBAND',
  47. 'ARPHRD_SLIP',
  48. 'ARPHRD_SLIP6',
  49. 'ARPHRD_RSRVD',
  50. 'ARPHRD_ADAPT',
  51. 'ARPHRD_X25',
  52. 'ARPHRD_HWX25',
  53. 'ARPHRD_PPP',
  54. 'ARPHRD_CISCO',
  55. 'ARPHRD_HDLC',
  56. 'ARPHRD_DDCMP',
  57. 'ARPHRD_RAWHDLC',
  58. 'ARPHRD_TUNNEL',
  59. 'ARPHRD_TUNNEL6',
  60. 'ARPHRD_FRAD',
  61. 'ARPHRD_SKIP',
  62. 'ARPHRD_LOOPBACK',
  63. 'ARPHRD_LOCALTLK',
  64. 'ARPHRD_FDDI',
  65. 'ARPHRD_BIF',
  66. 'ARPHRD_SIT',
  67. 'ARPHRD_IPDDP',
  68. 'ARPHRD_IPGRE',
  69. 'ARPHRD_PIMREG',
  70. 'ARPHRD_HIPPI',
  71. 'ARPHRD_ASH',
  72. 'ARPHRD_ECONET',
  73. 'ARPHRD_IRDA',
  74. 'ARPHRD_FCPP',
  75. 'ARPHRD_FCAL',
  76. 'ARPHRD_FCPL',
  77. 'ARPHRD_FCFABRIC',
  78. 'ARPHRD_IEEE802_TR',
  79. 'ARPHRD_IEEE80211',
  80. 'ARPHRD_IEEE80211_PRISM',
  81. 'ARPHRD_IEEE80211_RADIOTAP',
  82. 'ARPHRD_VOID',
  83. 'ARPHRD_NONE',
  84. 'ETH_P_LOOP',
  85. 'ETH_P_PUP',
  86. 'ETH_P_PUPAT',
  87. 'ETH_P_IP',
  88. 'ETH_P_X25',
  89. 'ETH_P_ARP',
  90. 'ETH_P_BPQ',
  91. 'ETH_P_IEEEPUP',
  92. 'ETH_P_IEEEPUPAT',
  93. 'ETH_P_DEC',
  94. 'ETH_P_DNA_DL',
  95. 'ETH_P_DNA_RC',
  96. 'ETH_P_DNA_RT',
  97. 'ETH_P_LAT',
  98. 'ETH_P_DIAG',
  99. 'ETH_P_CUST',
  100. 'ETH_P_SCA',
  101. 'ETH_P_RARP',
  102. 'ETH_P_ATALK',
  103. 'ETH_P_AARP',
  104. 'ETH_P_8021Q',
  105. 'ETH_P_IPX',
  106. 'ETH_P_IPV6',
  107. 'ETH_P_SLOW',
  108. 'ETH_P_WCCP',
  109. 'ETH_P_PPP_DISC',
  110. 'ETH_P_PPP_SES',
  111. 'ETH_P_MPLS_UC',
  112. 'ETH_P_MPLS_MC',
  113. 'ETH_P_ATMMPOA',
  114. 'ETH_P_ATMFATE',
  115. 'ETH_P_AOE',
  116. 'ETH_P_TIPC',
  117. 'ETH_P_802_3',
  118. 'ETH_P_AX25',
  119. 'ETH_P_ALL',
  120. 'ETH_P_802_2',
  121. 'ETH_P_SNAP',
  122. 'ETH_P_DDCMP',
  123. 'ETH_P_WAN_PPP',
  124. 'ETH_P_PPP_MP',
  125. 'ETH_P_LOCALTALK',
  126. 'ETH_P_PPPTALK',
  127. 'ETH_P_TR_802_2',
  128. 'ETH_P_MOBITEX',
  129. 'ETH_P_CONTROL',
  130. 'ETH_P_IRDA',
  131. 'ETH_P_ECONET',
  132. 'ETH_P_HDLC',
  133. 'ETH_P_ARCNET',
  134. ]
  135. import sys
  136. import os
  137. import socket
  138. import struct
  139. from ctypes import *
  140. from BTL.obsoletepythonsupport import set
  141. _libc = None
  142. BSD = sys.platform.startswith('darwin') or sys.platform.startswith('freebsd')
  143. def libc():
  144. global _libc
  145. if _libc is None:
  146. uname = os.uname()
  147. assert sizeof(c_ushort) == 2
  148. assert sizeof(c_uint) == 4
  149. if sys.platform.startswith('darwin'):
  150. _libc = CDLL('libc.dylib')
  151. elif sys.platform.startswith('freebsd'):
  152. _libc = CDLL('libc.so.6')
  153. else:
  154. assert uname[0] == 'Linux' and [ int(x) for x in uname[2].split('.')[:2] ] >= [ 2, 2 ]
  155. _libc = CDLL('libc.so.6')
  156. return _libc
  157. def errno():
  158. return cast(addressof(libc().errno), POINTER(POINTER(c_int)))[0][0]
  159. uint16_t = c_ushort
  160. uint32_t = c_uint
  161. uint8_t = c_ubyte
  162. if BSD:
  163. sa_family_t = c_uint8
  164. def SOCKADDR_COMMON(prefix):
  165. """
  166. Common data: address family and length.
  167. """
  168. return [ (prefix + 'len', c_uint8),
  169. (prefix + 'family', sa_family_t) ]
  170. else:
  171. sa_family_t = c_ushort
  172. def SOCKADDR_COMMON(prefix):
  173. """
  174. Common data: address family and length.
  175. """
  176. return [ (prefix + 'family', sa_family_t) ]
  177. SOCKADDR_COMMON_SIZE = sum([ sizeof(t) for n, t in SOCKADDR_COMMON('') ])
  178. class sockaddr(Structure):
  179. """
  180. Structure describing a generic socket address.
  181. """
  182. pass
  183. sockaddr._fields_ = SOCKADDR_COMMON('sa_') + [ # Common data: address family and length.
  184. ('sa_data', ARRAY(c_ubyte, 14)), # Address data.
  185. ]
  186. class sockaddr_storage(Structure):
  187. """
  188. Structure large enough to hold any socket address (with the historical exception of AF_UNIX). We reserve 128 bytes.
  189. """
  190. pass
  191. _SS_SIZE = 128
  192. __ss_aligntype = c_ulong
  193. sockaddr_storage._fields_ = SOCKADDR_COMMON('ss_') + [ # Address family, etc.
  194. ('__ss_align', __ss_aligntype), # Force desired alignment.
  195. ('__ss_padding', ARRAY(c_byte, _SS_SIZE - 2 * sizeof(__ss_aligntype))),
  196. ]
  197. class sockaddr_ll(Structure):
  198. pass
  199. sockaddr_ll._fields_ = SOCKADDR_COMMON('sll_') + [
  200. ('sll_protocol', c_ushort),
  201. ('sll_ifindex', c_int),
  202. ('sll_hatype', c_ushort),
  203. ('sll_pkttype', c_ubyte),
  204. ('sll_halen', c_ubyte),
  205. ('sll_addr', ARRAY(c_ubyte, 8)),
  206. ]
  207. in_port_t = uint16_t
  208. in_addr_t = uint32_t
  209. class in_addr(Structure):
  210. """
  211. Internet address.
  212. """
  213. pass
  214. in_addr._fields_ = [
  215. ('s_addr', in_addr_t)
  216. ]
  217. class in6_u(Union):
  218. pass
  219. in6_u._fields_ = [
  220. ('u6_addr8', ARRAY(uint8_t, 16)),
  221. ('u6_addr16', ARRAY(uint16_t, 8)),
  222. ('u6_addr32', ARRAY(uint32_t, 4)),
  223. ]
  224. class in6_addr(Structure):
  225. """
  226. IPv6 address
  227. """
  228. pass
  229. in6_addr._fields_ = [
  230. ('in6_u', in6_u),
  231. ]
  232. class sockaddr_in(Structure):
  233. """
  234. Structure describing an Internet socket address.
  235. """
  236. pass
  237. sockaddr_in._fields_ = SOCKADDR_COMMON('sin_') + [
  238. ('sin_port', in_port_t), # Port number.
  239. ('sin_addr', in_addr), # Internet address.
  240. ('sin_zero', ARRAY(c_ubyte, sizeof(sockaddr) - SOCKADDR_COMMON_SIZE - sizeof(in_port_t) - sizeof(in_addr))), # Pad to size of `struct sockaddr'.
  241. ]
  242. class sockaddr_in6(Structure):
  243. """
  244. Structure describing an IPv6 socket address.
  245. """
  246. pass
  247. sockaddr_in6._fields_ = SOCKADDR_COMMON('sin6_') + [
  248. ('sin6_port', in_port_t), # Transport layer port #
  249. ('sin6_flowinfo', uint32_t), # IPv6 flow information
  250. ('sin6_addr', in6_addr), # IPv6 address
  251. ('sin6_scope_id', uint32_t), # IPv6 scope-id
  252. ]
  253. class net_device_stats(Structure):
  254. """
  255. Network device statistics.
  256. """
  257. pass
  258. net_device_stats._fields_ = [
  259. ('rx_packets', c_ulong),
  260. ('tx_packets', c_ulong),
  261. ('rx_bytes', c_ulong),
  262. ('tx_bytes', c_ulong),
  263. ('rx_errors', c_ulong),
  264. ('tx_errors', c_ulong),
  265. ('rx_dropped', c_ulong),
  266. ('tx_dropped', c_ulong),
  267. ('multicast', c_ulong),
  268. ('collisions', c_ulong),
  269. ('rx_length_errors', c_ulong),
  270. ('rx_over_errors', c_ulong),
  271. ('rx_crc_errors', c_ulong),
  272. ('rx_frame_errors', c_ulong),
  273. ('rx_fifo_errors', c_ulong),
  274. ('rx_missed_errors', c_ulong),
  275. ('tx_aborted_errors', c_ulong),
  276. ('tx_carrier_errors', c_ulong),
  277. ('tx_fifo_errors', c_ulong),
  278. ('tx_heartbeat_errors', c_ulong),
  279. ('tx_window_errors', c_ulong),
  280. ('rx_compressed', c_ulong),
  281. ('tx_compressed', c_ulong),
  282. ]
  283. class ifa_ifu(Union):
  284. """
  285. At most one of the following two is valid. If the IFF_BROADCAST
  286. bit is set in `ifa_flags', then `ifa_broadaddr' is valid. If the
  287. IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid.
  288. It is never the case that both these bits are set at once.
  289. """
  290. pass
  291. ifa_ifu._fields_=[
  292. ('ifu_broadaddr', POINTER(sockaddr)), # Broadcast address of this interface.
  293. ('ifu_dstaddr', POINTER(sockaddr)), # Point-to-point destination address.
  294. ]
  295. class ifaddrs(Structure):
  296. """
  297. The `getifaddrs' function generates a linked list of these structures.
  298. Each element of the list describes one network interface.
  299. """
  300. pass
  301. ifaddrs._fields_=[
  302. ('ifa_next', POINTER(ifaddrs)), # Pointer to the next structure.
  303. ('ifa_name', c_char_p), # Name of this network interface.
  304. ('ifa_flags', c_uint), # Flags as from SIOCGIFFLAGS ioctl.
  305. ('ifa_addr', POINTER(sockaddr)), # Network address of this interface.
  306. ('ifa_netmask', POINTER(sockaddr)), # Netmask of this interface.
  307. ('ifa_ifu', ifa_ifu),
  308. ('ifa_data', c_void_p), # Address-specific data (may be unused).
  309. ]
  310. class NamedLong(long):
  311. def __new__(self, name, value):
  312. self._long = long.__new__(self, value)
  313. self._long._name = name
  314. return self._long
  315. def __repr__(self):
  316. return self._name
  317. pass
  318. class OrSet(set):
  319. def __repr__(self):
  320. return ' | '.join([ repr(x) for x in self ])
  321. IFF_UP = NamedLong(name = 'IFF_UP', value = 0x1)
  322. IFF_BROADCAST = NamedLong(name = 'IFF_BROADCAST', value = 0x2)
  323. IFF_DEBUG = NamedLong(name = 'IFF_DEBUG', value = 0x4)
  324. IFF_LOOPBACK = NamedLong(name = 'IFF_LOOPBACK', value = 0x8)
  325. IFF_POINTOPOINT = NamedLong(name = 'IFF_POINTOPOINT', value = 0x10)
  326. IFF_NOTRAILERS = NamedLong(name = 'IFF_NOTRAILERS', value = 0x20)
  327. IFF_RUNNING = NamedLong(name = 'IFF_RUNNING', value = 0x40)
  328. IFF_NOARP = NamedLong(name = 'IFF_NOARP', value = 0x80)
  329. IFF_PROMISC = NamedLong(name = 'IFF_PROMISC', value = 0x100)
  330. IFF_ALLMULTI = NamedLong(name = 'IFF_ALLMULTI', value = 0x200)
  331. IFF_MASTER = NamedLong(name = 'IFF_MASTER', value = 0x400)
  332. IFF_SLAVE = NamedLong(name = 'IFF_SLAVE', value = 0x800)
  333. IFF_MULTICAST = NamedLong(name = 'IFF_MULTICAST', value = 0x1000)
  334. IFF_PORTSEL = NamedLong(name = 'IFF_PORTSEL', value = 0x2000)
  335. IFF_AUTOMEDIA = NamedLong(name = 'IFF_AUTOMEDIA', value = 0x4000)
  336. IFF_DYNAMIC = NamedLong(name = 'IFF_DYNAMIC', value = 0x8000L)
  337. IFF_LOWER_UP = NamedLong(name = 'IFF_LOWER_UP', value = 0x10000)
  338. IFF_DORMANT = NamedLong(name = 'IFF_DORMANT', value = 0x20000)
  339. ARPHRD_NETROM = NamedLong(name = 'ARPHRD_NETROM', value = 0)
  340. ARPHRD_ETHER = NamedLong(name = 'ARPHRD_ETHER', value = 1)
  341. ARPHRD_EETHER = NamedLong(name = 'ARPHRD_EETHER', value = 2)
  342. ARPHRD_AX25 = NamedLong(name = 'ARPHRD_AX25', value = 3)
  343. ARPHRD_PRONET = NamedLong(name = 'ARPHRD_PRONET', value = 4)
  344. ARPHRD_CHAOS = NamedLong(name = 'ARPHRD_CHAOS', value = 5)
  345. ARPHRD_IEEE802 = NamedLong(name = 'ARPHRD_IEEE802', value = 6)
  346. ARPHRD_ARCNET = NamedLong(name = 'ARPHRD_ARCNET', value = 7)
  347. ARPHRD_APPLETLK = NamedLong(name = 'ARPHRD_APPLETLK', value = 8)
  348. ARPHRD_DLCI = NamedLong(name = 'ARPHRD_DLCI', value = 15)
  349. ARPHRD_ATM = NamedLong(name = 'ARPHRD_ATM', value = 19)
  350. ARPHRD_METRICOM = NamedLong(name = 'ARPHRD_METRICOM', value = 23)
  351. ARPHRD_IEEE1394 = NamedLong(name = 'ARPHRD_IEEE1394', value = 24)
  352. ARPHRD_EUI64 = NamedLong(name = 'ARPHRD_EUI64', value = 27)
  353. ARPHRD_INFINIBAND = NamedLong(name = 'ARPHRD_INFINIBAND', value = 32)
  354. ARPHRD_SLIP = NamedLong(name = 'ARPHRD_SLIP', value = 256)
  355. ARPHRD_SLIP6 = NamedLong(name = 'ARPHRD_SLIP6', value = 258)
  356. ARPHRD_RSRVD = NamedLong(name = 'ARPHRD_RSRVD', value = 260)
  357. ARPHRD_ADAPT = NamedLong(name = 'ARPHRD_ADAPT', value = 264)
  358. ARPHRD_X25 = NamedLong(name = 'ARPHRD_X25', value = 271)
  359. ARPHRD_HWX25 = NamedLong(name = 'ARPHRD_HWX25', value = 272)
  360. ARPHRD_PPP = NamedLong(name = 'ARPHRD_PPP', value = 512)
  361. ARPHRD_CISCO = NamedLong(name = 'ARPHRD_CISCO', value = 513)
  362. ARPHRD_HDLC = NamedLong(name = 'ARPHRD_HDLC', value = ARPHRD_CISCO)
  363. ARPHRD_DDCMP = NamedLong(name = 'ARPHRD_DDCMP', value = 517)
  364. ARPHRD_RAWHDLC = NamedLong(name = 'ARPHRD_RAWHDLC', value = 518)
  365. ARPHRD_TUNNEL = NamedLong(name = 'ARPHRD_TUNNEL', value = 768)
  366. ARPHRD_TUNNEL6 = NamedLong(name = 'ARPHRD_TUNNEL6', value = 769)
  367. ARPHRD_FRAD = NamedLong(name = 'ARPHRD_FRAD', value = 770)
  368. ARPHRD_SKIP = NamedLong(name = 'ARPHRD_SKIP', value = 771)
  369. ARPHRD_LOOPBACK = NamedLong(name = 'ARPHRD_LOOPBACK', value = 772)
  370. ARPHRD_LOCALTLK = NamedLong(name = 'ARPHRD_LOCALTLK', value = 773)
  371. ARPHRD_FDDI = NamedLong(name = 'ARPHRD_FDDI', value = 774)
  372. ARPHRD_BIF = NamedLong(name = 'ARPHRD_BIF', value = 775)
  373. ARPHRD_SIT = NamedLong(name = 'ARPHRD_SIT', value = 776)
  374. ARPHRD_IPDDP = NamedLong(name = 'ARPHRD_IPDDP', value = 777)
  375. ARPHRD_IPGRE = NamedLong(name = 'ARPHRD_IPGRE', value = 778)
  376. ARPHRD_PIMREG = NamedLong(name = 'ARPHRD_PIMREG', value = 779)
  377. ARPHRD_HIPPI = NamedLong(name = 'ARPHRD_HIPPI', value = 780)
  378. ARPHRD_ASH = NamedLong(name = 'ARPHRD_ASH', value = 781)
  379. ARPHRD_ECONET = NamedLong(name = 'ARPHRD_ECONET', value = 782)
  380. ARPHRD_IRDA = NamedLong(name = 'ARPHRD_IRDA', value = 783)
  381. ARPHRD_FCPP = NamedLong(name = 'ARPHRD_FCPP', value = 784)
  382. ARPHRD_FCAL = NamedLong(name = 'ARPHRD_FCAL', value = 785)
  383. ARPHRD_FCPL = NamedLong(name = 'ARPHRD_FCPL', value = 786)
  384. ARPHRD_FCFABRIC = NamedLong(name = 'ARPHRD_FCFABRIC', value = 787)
  385. ARPHRD_IEEE802_TR = NamedLong(name = 'ARPHRD_IEEE802_TR', value = 800)
  386. ARPHRD_IEEE80211 = NamedLong(name = 'ARPHRD_IEEE80211', value = 801)
  387. ARPHRD_IEEE80211_PRISM = NamedLong(name = 'ARPHRD_IEEE80211_PRISM', value = 802)
  388. ARPHRD_IEEE80211_RADIOTAP = NamedLong(name = 'ARPHRD_IEEE80211_RADIOTAP', value = 803)
  389. ARPHRD_VOID = NamedLong(name = 'ARPHRD_VOID', value = 0xFFFF)
  390. ARPHRD_NONE = NamedLong(name = 'ARPHRD_NONE', value = 0xFFFE)
  391. ETH_P_LOOP = NamedLong(name = 'ETH_P_LOOP', value = 0x0060)
  392. ETH_P_PUP = NamedLong(name = 'ETH_P_PUP', value = 0x0200)
  393. ETH_P_PUPAT = NamedLong(name = 'ETH_P_PUPAT', value = 0x0201)
  394. ETH_P_IP = NamedLong(name = 'ETH_P_IP', value = 0x0800)
  395. ETH_P_X25 = NamedLong(name = 'ETH_P_X25', value = 0x0805)
  396. ETH_P_ARP = NamedLong(name = 'ETH_P_ARP', value = 0x0806)
  397. ETH_P_BPQ = NamedLong(name = 'ETH_P_BPQ', value = 0x08FF)
  398. ETH_P_IEEEPUP = NamedLong(name = 'ETH_P_IEEEPUP', value = 0x0a00)
  399. ETH_P_IEEEPUPAT = NamedLong(name = 'ETH_P_IEEEPUPAT', value = 0x0a01)
  400. ETH_P_DEC = NamedLong(name = 'ETH_P_DEC', value = 0x6000)
  401. ETH_P_DNA_DL = NamedLong(name = 'ETH_P_DNA_DL', value = 0x6001)
  402. ETH_P_DNA_RC = NamedLong(name = 'ETH_P_DNA_RC', value = 0x6002)
  403. ETH_P_DNA_RT = NamedLong(name = 'ETH_P_DNA_RT', value = 0x6003)
  404. ETH_P_LAT = NamedLong(name = 'ETH_P_LAT', value = 0x6004)
  405. ETH_P_DIAG = NamedLong(name = 'ETH_P_DIAG', value = 0x6005)
  406. ETH_P_CUST = NamedLong(name = 'ETH_P_CUST', value = 0x6006)
  407. ETH_P_SCA = NamedLong(name = 'ETH_P_SCA', value = 0x6007)
  408. ETH_P_RARP = NamedLong(name = 'ETH_P_RARP', value = 0x8035)
  409. ETH_P_ATALK = NamedLong(name = 'ETH_P_ATALK', value = 0x809B)
  410. ETH_P_AARP = NamedLong(name = 'ETH_P_AARP', value = 0x80F3)
  411. ETH_P_8021Q = NamedLong(name = 'ETH_P_8021Q', value = 0x8100)
  412. ETH_P_IPX = NamedLong(name = 'ETH_P_IPX', value = 0x8137)
  413. ETH_P_IPV6 = NamedLong(name = 'ETH_P_IPV6', value = 0x86DD)
  414. ETH_P_SLOW = NamedLong(name = 'ETH_P_SLOW', value = 0x8809)
  415. ETH_P_WCCP = NamedLong(name = 'ETH_P_WCCP', value = 0x883E)
  416. ETH_P_PPP_DISC = NamedLong(name = 'ETH_P_PPP_DISC', value = 0x8863)
  417. ETH_P_PPP_SES = NamedLong(name = 'ETH_P_PPP_SES', value = 0x8864)
  418. ETH_P_MPLS_UC = NamedLong(name = 'ETH_P_MPLS_UC', value = 0x8847)
  419. ETH_P_MPLS_MC = NamedLong(name = 'ETH_P_MPLS_MC', value = 0x8848)
  420. ETH_P_ATMMPOA = NamedLong(name = 'ETH_P_ATMMPOA', value = 0x884c)
  421. ETH_P_ATMFATE = NamedLong(name = 'ETH_P_ATMFATE', value = 0x8884)
  422. ETH_P_AOE = NamedLong(name = 'ETH_P_AOE', value = 0x88A2)
  423. ETH_P_TIPC = NamedLong(name = 'ETH_P_TIPC', value = 0x88CA)
  424. ETH_P_802_3 = NamedLong(name = 'ETH_P_802_3', value = 0x0001)
  425. ETH_P_AX25 = NamedLong(name = 'ETH_P_AX25', value = 0x0002)
  426. ETH_P_ALL = NamedLong(name = 'ETH_P_ALL', value = 0x0003)
  427. ETH_P_802_2 = NamedLong(name = 'ETH_P_802_2', value = 0x0004)
  428. ETH_P_SNAP = NamedLong(name = 'ETH_P_SNAP', value = 0x0005)
  429. ETH_P_DDCMP = NamedLong(name = 'ETH_P_DDCMP', value = 0x0006)
  430. ETH_P_WAN_PPP = NamedLong(name = 'ETH_P_WAN_PPP', value = 0x0007)
  431. ETH_P_PPP_MP = NamedLong(name = 'ETH_P_PPP_MP', value = 0x0008)
  432. ETH_P_LOCALTALK = NamedLong(name = 'ETH_P_LOCALTALK', value = 0x0009)
  433. ETH_P_PPPTALK = NamedLong(name = 'ETH_P_PPPTALK', value = 0x0010)
  434. ETH_P_TR_802_2 = NamedLong(name = 'ETH_P_TR_802_2', value = 0x0011)
  435. ETH_P_MOBITEX = NamedLong(name = 'ETH_P_MOBITEX', value = 0x0015)
  436. ETH_P_CONTROL = NamedLong(name = 'ETH_P_CONTROL', value = 0x0016)
  437. ETH_P_IRDA = NamedLong(name = 'ETH_P_IRDA', value = 0x0017)
  438. ETH_P_ECONET = NamedLong(name = 'ETH_P_ECONET', value = 0x0018)
  439. ETH_P_HDLC = NamedLong(name = 'ETH_P_HDLC', value = 0x0019)
  440. ETH_P_ARCNET = NamedLong(name = 'ETH_P_ARCNET', value = 0x001A)
  441. def NamedLongs(x, names):
  442. s = OrSet()
  443. for k in names:
  444. if x & k:
  445. s |= OrSet([k])
  446. x ^= k
  447. k = 1L
  448. while x:
  449. if x & k:
  450. s |= OrSet([k])
  451. x ^= k
  452. k+=k
  453. return s
  454. def _getifaddrs(ifap):
  455. """
  456. Create a linked list of `struct ifaddrs' structures, one for each
  457. network interface on the host machine. If successful, store the
  458. list in *IFAP and return 0. On errors, return -1 and set `errno'.
  459. The storage returned in *IFAP is allocated dynamically and can
  460. only be properly freed by passing it to `freeifaddrs'.
  461. """
  462. __getifaddrs = libc().getifaddrs
  463. return CFUNCTYPE(c_int, POINTER(POINTER(ifaddrs)))(__getifaddrs)(ifap)
  464. def _freeifaddrs(ifa):
  465. """
  466. Reclaim the storage allocated by a previous `getifaddrs' call.
  467. """
  468. __freeifaddrs = libc().freeifaddrs
  469. return CFUNCTYPE(None, POINTER(ifaddrs))(__freeifaddrs)(ifa)
  470. def hardware_type(hatype):
  471. this = sys.modules[__name__]
  472. return ([ x for x in [ NamedLong(n, getattr(this, n)) for n in dir(this) if n[:len('ARPHRD_')] == 'ARPHRD_' ] if x == hatype ] + [ hatype ])[0]
  473. def eth_protocol_type(protocol):
  474. this = sys.modules[__name__]
  475. return ([ x for x in [ NamedLong(n, getattr(this, n)) for n in dir(this) if n[:len('ETH_P_')] == 'ETH_P_' ] if x == protocol ] + [ protocol ])[0]
  476. def packet_type(pkttype):
  477. return ([ x for x in [ NamedLong(n, getattr(socket, n)) for n in dir(socket) if n[:len('PACKET_')] == 'PACKET_' ] if x == pkttype ] + [ pkttype ])[0]
  478. def addrfamily(family):
  479. return ([ x for x in [ NamedLong(n, getattr(socket, n)) for n in dir(socket) if n[:len('AF_')] == 'AF_' ] if x == family ] + [ family ])[0]
  480. def sockaddr2addr(ifname, addr):
  481. """
  482. Convert a sockaddr pointer (addr) to a descriptive dict or None
  483. for a void pointer.
  484. """
  485. if addr:
  486. sa = addr[0]
  487. else:
  488. return None
  489. d = { 'family': addrfamily(sa.sa_family) }
  490. if hasattr(socket, 'AF_INET6') and sa.sa_family == socket.AF_INET6:
  491. sin6 = cast(addr, POINTER(sockaddr_in6))[0]
  492. d['port'] = sin6.sin6_port or None
  493. d['addr'] = ':'.join([ '%04.4x' % socket.ntohs(x) for x in sin6.sin6_addr.in6_u.u6_addr16 ])
  494. d['flowinfo'] = sin6.sin6_flowinfo or None
  495. d['scope_id'] = sin6.sin6_scope_id
  496. elif hasattr(socket, 'AF_INET') and sa.sa_family == socket.AF_INET:
  497. sin = cast(addr, POINTER(sockaddr_in))[0]
  498. d['port'] = sin.sin_port or None
  499. d['addr'] = '.'.join([ str(ord(x)) for x in struct.pack('I', sin.sin_addr.s_addr) ])
  500. elif hasattr(socket, 'AF_PACKET') and sa.sa_family == socket.AF_PACKET:
  501. sll = cast(addr, POINTER(sockaddr_ll))[0]
  502. #d['ifindex'] = sll.sll_ifindex
  503. hwaddr = None
  504. if sll.sll_hatype == ARPHRD_ETHER and sll.sll_halen == 6:
  505. hwaddr = ':'.join([ chr(x).encode('hex') for x in sll.sll_addr[:sll.sll_halen] ])
  506. elif sll.sll_hatype == ARPHRD_SIT and sll.sll_halen == 4:
  507. try:
  508. hwaddr = socket.inet_ntop(socket.AF_INET,
  509. ''.join([ chr(x) for x in sll.sll_addr[:sll.sll_halen] ]))
  510. except:
  511. pass
  512. d['addr'] = (ifname,
  513. eth_protocol_type(sll.sll_protocol),
  514. packet_type(sll.sll_pkttype),
  515. hardware_type(sll.sll_hatype),
  516. ) + ((hwaddr is not None) and (hwaddr,) or ())
  517. else:
  518. pass
  519. try:
  520. if 'addr' in d:
  521. d['addr'] = socket.inet_ntop(sa.sa_family,
  522. socket.inet_pton(sa.sa_family,
  523. d['addr']))
  524. except:
  525. pass
  526. return dict([ (k, v) for k, v in d.items() if v is not None ])
  527. def flagset(flagbits):
  528. if isinstance(flagbits, set):
  529. return flagbits
  530. return NamedLongs(flagbits,
  531. (IFF_UP,
  532. IFF_BROADCAST,
  533. IFF_DEBUG,
  534. IFF_LOOPBACK,
  535. IFF_POINTOPOINT,
  536. IFF_NOTRAILERS,
  537. IFF_RUNNING,
  538. IFF_NOARP,
  539. IFF_PROMISC,
  540. IFF_ALLMULTI,
  541. IFF_MASTER,
  542. IFF_SLAVE,
  543. IFF_MULTICAST,
  544. IFF_PORTSEL,
  545. IFF_AUTOMEDIA,
  546. IFF_DYNAMIC,
  547. IFF_LOWER_UP,
  548. IFF_DORMANT,
  549. ))
  550. def getifaddrs(name = None):
  551. """
  552. Create a list of ifaddrs, one for each network interface on the
  553. host machine. If successful, return the list. On errors, raises
  554. an exception. If the optional name is not None, only entries for
  555. that interface name are returned.
  556. """
  557. ifa = POINTER(ifaddrs)()
  558. ret = _getifaddrs(byref(ifa))
  559. ifa0 = ifa
  560. if ret == -1:
  561. raise IOError(os.strerror(errno()))
  562. try:
  563. iflist = []
  564. while ifa:
  565. d = {
  566. 'name': ifa[0].ifa_name,
  567. 'flags': flagset(ifa[0].ifa_flags),
  568. }
  569. d['addr'] = sockaddr2addr(d['name'], ifa[0].ifa_addr)
  570. d['netmask'] = sockaddr2addr(d['name'], ifa[0].ifa_netmask)
  571. if ifa[0].ifa_flags & IFF_BROADCAST:
  572. d['broadaddr'] = sockaddr2addr(d['name'], ifa[0].ifa_ifu.ifu_broadaddr)
  573. elif ifa[0].ifa_flags & IFF_POINTOPOINT:
  574. d['dstaddr'] = sockaddr2addr(d['name'], ifa[0].ifa_ifu.ifu_dstaddr)
  575. #d['data'] = ifa[0].ifa_data or None
  576. if ifa[0].ifa_data:
  577. if (d.get('addr') is not None and
  578. hasattr(socket, 'AF_PACKET') and
  579. d['addr'].get('family') == socket.AF_PACKET):
  580. nds = cast(ifa[0].ifa_data, POINTER(net_device_stats))[0]
  581. d['data'] = {
  582. 'rx_packets': nds.rx_packets,
  583. 'tx_packets': nds.tx_packets,
  584. 'rx_bytes': nds.rx_bytes,
  585. 'tx_bytes': nds.tx_bytes,
  586. 'rx_errors': nds.rx_errors,
  587. 'tx_errors': nds.tx_errors,
  588. 'rx_dropped': nds.rx_dropped,
  589. 'tx_dropped': nds.tx_dropped,
  590. 'multicast': nds.multicast,
  591. 'collisions': nds.collisions,
  592. 'rx_length_errors': nds.rx_length_errors,
  593. 'rx_over_errors': nds.rx_over_errors,
  594. 'rx_crc_errors': nds.rx_crc_errors,
  595. 'rx_frame_errors': nds.rx_frame_errors,
  596. 'rx_fifo_errors': nds.rx_fifo_errors,
  597. 'rx_missed_errors': nds.rx_missed_errors,
  598. 'tx_aborted_errors': nds.tx_aborted_errors,
  599. 'tx_carrier_errors': nds.tx_carrier_errors,
  600. 'tx_fifo_errors': nds.tx_fifo_errors,
  601. 'tx_heartbeat_errors': nds.tx_heartbeat_errors,
  602. 'tx_window_errors': nds.tx_window_errors,
  603. 'rx_compressed': nds.rx_compressed,
  604. 'tx_compressed': nds.tx_compressed,
  605. }
  606. iflist.append(dict([ (k, v) for k, v in d.items() if v is not None ]))
  607. ifa = ifa[0].ifa_next
  608. return [ iface for iface in iflist if name is None or iface.get('name') == name ]
  609. finally:
  610. _freeifaddrs(ifa0)
  611. def getaddrs(family = None, flags = OrSet([IFF_UP, IFF_RUNNING]), name = None):
  612. flags = flagset(flags)
  613. for a in getifaddrs(name = name):
  614. if family is not None and a.get('addr', {}).get('family') != family:
  615. continue
  616. if flags:
  617. for flag in flags:
  618. if flag not in flagset(a.get('flags', 0)):
  619. continue
  620. if 'addr' in a and 'addr' in a['addr']:
  621. yield a['addr']['addr']
  622. def getnetaddrs(family = None, flags = OrSet([IFF_UP, IFF_RUNNING]), name = None):
  623. flags = flagset(flags)
  624. for a in getifaddrs(name = name):
  625. if family is not None and a.get('addr', {}).get('family') != family:
  626. continue
  627. if 'netmask' in a and a.get('netmask', {}).get('family') != a.get('addr', {}).get('family') != family:
  628. continue
  629. if flags:
  630. for flag in flags:
  631. if flag not in flagset(a.get('flags', 0)):
  632. continue
  633. if 'addr' in a and 'addr' in a['addr']:
  634. yield str(a['addr']['addr']) + (('netmask' in a and 'addr' in a['netmask'] and a['netmask'].get('family') == a['addr']['family']) and '/' + str(a['netmask']['addr']) or '')
  635. def getbroadaddrs(family = None, flags = OrSet([IFF_UP, IFF_RUNNING, IFF_BROADCAST]), name = None):
  636. flags = flagset(flags)
  637. for a in getifaddrs(name = name):
  638. if family is not None and a.get('broadaddr', {}).get('family') != family:
  639. continue
  640. if flags:
  641. for flag in flags:
  642. if flag not in flagset(a.get('flags', 0)):
  643. continue
  644. if 'broadaddr' in a and 'addr' in a['broadaddr']:
  645. yield str(a['broadaddr']['addr']) + (('netmask' in a and 'addr' in a['netmask'] and a['netmask'].get('family') == a['broadaddr']['family']) and '/' + str(a['netmask']['addr']) or '')
  646. def getdstaddrs(family = None, flags = OrSet([IFF_UP, IFF_RUNNING, IFF_POINTOPOINT]), name = None):
  647. flags = flagset(flags)
  648. for a in getifaddrs(name = None):
  649. if family is not None and a.get('dstaddr', {}).get('family') != family:
  650. continue
  651. if flags:
  652. for flag in flags:
  653. if flag not in flagset(a.get('flags', 0)):
  654. continue
  655. if 'dstaddr' in a and 'addr' in a['dstaddr']:
  656. yield a['dstaddr']['addr']
  657. def main():
  658. '''
  659. Print a list of network interfaces.
  660. '''
  661. print 'live interface addresses:'
  662. for a in getaddrs():
  663. print '\t' 'addr', a
  664. for a in getdstaddrs():
  665. print '\t' 'dstaddr', a
  666. for a in getnetaddrs():
  667. print '\t' 'netaddr', a
  668. for a in getbroadaddrs():
  669. print '\t' 'broadaddr', a
  670. print 'all interface details:'
  671. for a in getifaddrs():
  672. print '\t' + a['name'] + ':'
  673. i = a.items()
  674. i.sort()
  675. for k, v in i:
  676. if k not in ('name', 'data'):
  677. print '\t\t' + k, `v`
  678. if 'data' in a:
  679. print '\t\t' 'data' + ':'
  680. i = a['data'].items()
  681. i.sort()
  682. for k, v in i:
  683. print '\t\t\t' + k, `v`
  684. if __name__ == '__main__':
  685. main()