You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
3.4 KiB

4 years ago
  1. # Copyright (c) 2014 Stefan C. Mueller
  2. # Permission is hereby granted, free of charge, to any person obtaining a copy
  3. # of this software and associated documentation files (the "Software"), to
  4. # deal in the Software without restriction, including without limitation the
  5. # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  6. # sell copies of the Software, and to permit persons to whom the Software is
  7. # furnished to do so, subject to the following conditions:
  8. #
  9. # The above copyright notice and this permission notice shall be included in
  10. # all copies or substantial portions of the Software.
  11. #
  12. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  17. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  18. # IN THE SOFTWARE.
  19. import sys
  20. import os
  21. import ctypes.util
  22. import ipaddress
  23. import collections
  24. import ifaddr._shared as shared
  25. #from ifaddr._shared import sockaddr, Interface, sockaddr_to_ip, ipv6_prefixlength
  26. class ifaddrs(ctypes.Structure):
  27. pass
  28. ifaddrs._fields_ = [('ifa_next', ctypes.POINTER(ifaddrs)),
  29. ('ifa_name', ctypes.c_char_p),
  30. ('ifa_flags', ctypes.c_uint),
  31. ('ifa_addr', ctypes.POINTER(shared.sockaddr)),
  32. ('ifa_netmask', ctypes.POINTER(shared.sockaddr))]
  33. libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
  34. def get_adapters():
  35. addr0 = addr = ctypes.POINTER(ifaddrs)()
  36. retval = libc.getifaddrs(ctypes.byref(addr))
  37. if retval != 0:
  38. eno = ctypes.get_errno()
  39. raise OSError(eno, os.strerror(eno))
  40. ips = collections.OrderedDict()
  41. def add_ip(adapter_name, ip):
  42. if not adapter_name in ips:
  43. ips[adapter_name] = shared.Adapter(adapter_name, adapter_name, [])
  44. ips[adapter_name].ips.append(ip)
  45. while addr:
  46. name = addr[0].ifa_name
  47. if sys.version_info[0] > 2:
  48. name = name.decode(encoding='UTF-8')
  49. ip = shared.sockaddr_to_ip(addr[0].ifa_addr)
  50. if ip:
  51. if addr[0].ifa_netmask and not addr[0].ifa_netmask[0].sa_familiy:
  52. addr[0].ifa_netmask[0].sa_familiy = addr[0].ifa_addr[0].sa_familiy
  53. netmask = shared.sockaddr_to_ip(addr[0].ifa_netmask)
  54. if isinstance(netmask, tuple):
  55. netmask = netmask[0]
  56. if sys.version_info[0] > 2:
  57. netmaskStr = str(netmask)
  58. else:
  59. netmaskStr = unicode(netmask)
  60. prefixlen = shared.ipv6_prefixlength(ipaddress.IPv6Address(netmaskStr))
  61. else:
  62. if sys.version_info[0] > 2:
  63. netmaskStr = str('0.0.0.0/' + netmask)
  64. else:
  65. netmaskStr = unicode('0.0.0.0/' + netmask)
  66. prefixlen = ipaddress.IPv4Network(netmaskStr).prefixlen
  67. ip = shared.IP(ip, prefixlen, name)
  68. add_ip(name, ip)
  69. addr = addr[0].ifa_next
  70. libc.freeifaddrs(addr0)
  71. return ips.values()