win_inet_pton.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # This software released into the public domain. Anyone is free to copy,
  2. # modify, publish, use, compile, sell, or distribute this software,
  3. # either in source code form or as a compiled binary, for any purpose,
  4. # commercial or non-commercial, and by any means.
  5. import socket
  6. import os
  7. import sys
  8. def inject_into_socket():
  9. import ctypes
  10. class in_addr(ctypes.Structure):
  11. _fields_ = [("S_addr", ctypes.c_ubyte * 4)]
  12. class in6_addr(ctypes.Structure):
  13. _fields_ = [("Byte", ctypes.c_ubyte * 16)]
  14. if hasattr(ctypes, "windll"):
  15. # InetNtopW(
  16. # INT family,
  17. # const VOID *pAddr,
  18. # PWSTR pStringBuf,
  19. # size_t StringBufSize
  20. # ) -> PCWSTR
  21. InetNtopW = ctypes.windll.ws2_32.InetNtopW
  22. # InetPtonW(
  23. # INT family,
  24. # PCWSTR pszAddrString,
  25. # PVOID pAddrBuf
  26. # ) -> INT
  27. InetPtonW = ctypes.windll.ws2_32.InetPtonW
  28. # WSAGetLastError() -> INT
  29. WSAGetLastError = ctypes.windll.ws2_32.WSAGetLastError
  30. else:
  31. def not_windows():
  32. raise SystemError("Invalid platform. ctypes.windll must be available.")
  33. InetNtopW = not_windows
  34. InetPtonW = not_windows
  35. WSAGetLastError = not_windows
  36. def inet_pton(address_family, ip_string):
  37. if sys.version_info[0] > 2 and isinstance(ip_string, bytes):
  38. raise TypeError("inet_pton() argument 2 must be str, not bytes")
  39. if address_family == socket.AF_INET:
  40. family = 2
  41. addr = in_addr()
  42. elif address_family == socket.AF_INET6:
  43. family = 23
  44. addr = in6_addr()
  45. else:
  46. raise OSError("unknown address family")
  47. ip_string = ctypes.c_wchar_p(ip_string)
  48. ret = InetPtonW(ctypes.c_int(family), ip_string, ctypes.byref(addr))
  49. if ret == 1:
  50. if address_family == socket.AF_INET:
  51. return ctypes.string_at(addr.S_addr, 4)
  52. else:
  53. return ctypes.string_at(addr.Byte, 16)
  54. elif ret == 0:
  55. raise socket.error("illegal IP address string passed to inet_pton")
  56. else:
  57. err = WSAGetLastError()
  58. if err == 10047:
  59. e = socket.error("unknown address family")
  60. elif err == 10014:
  61. e = OSError("bad address")
  62. else:
  63. e = OSError("unknown error from inet_ntop")
  64. e.errno = err
  65. raise e
  66. def inet_ntop(address_family, packed_ip):
  67. if address_family == socket.AF_INET:
  68. addr = in_addr()
  69. if len(packed_ip) != ctypes.sizeof(addr.S_addr):
  70. raise ValueError("packed IP wrong length for inet_ntop")
  71. ctypes.memmove(addr.S_addr, packed_ip, 4)
  72. buffer_len = 16
  73. family = 2
  74. elif address_family == socket.AF_INET6:
  75. addr = in6_addr()
  76. if len(packed_ip) != ctypes.sizeof(addr.Byte):
  77. raise ValueError("packed IP wrong length for inet_ntop")
  78. ctypes.memmove(addr.Byte, packed_ip, 16)
  79. buffer_len = 46
  80. family = 23
  81. else:
  82. raise ValueError("unknown address family")
  83. buffer = ctypes.create_unicode_buffer(buffer_len)
  84. ret = InetNtopW(
  85. ctypes.c_int(family),
  86. ctypes.byref(addr),
  87. ctypes.byref(buffer),
  88. ctypes.sizeof(buffer),
  89. )
  90. if ret is None:
  91. err = WSAGetLastError()
  92. if err == 10047:
  93. e = ValueError("unknown address family")
  94. else:
  95. e = OSError("unknown error from inet_ntop")
  96. e.errno = err
  97. return ctypes.wstring_at(buffer, buffer_len).rstrip("\x00")
  98. # Adding our two functions to the socket library
  99. socket.inet_pton = inet_pton
  100. socket.inet_ntop = inet_ntop
  101. if os.name == "nt" and not hasattr(socket, "inet_pton"):
  102. inject_into_socket()