2019-03-21 16:00:09 +03:00
|
|
|
#!/usr/bin/env python2
|
2016-10-18 14:46:56 +03:00
|
|
|
# This software released into the public domain. Anyone is free to copy,
|
|
|
|
# modify, publish, use, compile, sell, or distribute this software,
|
|
|
|
# either in source code form or as a compiled binary, for any purpose,
|
|
|
|
# commercial or non-commercial, and by any means.
|
|
|
|
|
|
|
|
import socket
|
|
|
|
import ctypes
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
|
|
class sockaddr(ctypes.Structure):
|
|
|
|
_fields_ = [("sa_family", ctypes.c_short),
|
|
|
|
("__pad1", ctypes.c_ushort),
|
|
|
|
("ipv4_addr", ctypes.c_byte * 4),
|
|
|
|
("ipv6_addr", ctypes.c_byte * 16),
|
|
|
|
("__pad2", ctypes.c_ulong)]
|
|
|
|
|
|
|
|
if hasattr(ctypes, 'windll'):
|
|
|
|
WSAStringToAddressA = ctypes.windll.ws2_32.WSAStringToAddressA
|
|
|
|
WSAAddressToStringA = ctypes.windll.ws2_32.WSAAddressToStringA
|
|
|
|
else:
|
|
|
|
def not_windows():
|
|
|
|
raise SystemError(
|
|
|
|
"Invalid platform. ctypes.windll must be available."
|
|
|
|
)
|
|
|
|
WSAStringToAddressA = not_windows
|
|
|
|
WSAAddressToStringA = not_windows
|
|
|
|
|
|
|
|
|
|
|
|
def inet_pton(address_family, ip_string):
|
|
|
|
addr = sockaddr()
|
|
|
|
addr.sa_family = address_family
|
|
|
|
addr_size = ctypes.c_int(ctypes.sizeof(addr))
|
|
|
|
|
|
|
|
if WSAStringToAddressA(
|
|
|
|
ip_string,
|
|
|
|
address_family,
|
|
|
|
None,
|
|
|
|
ctypes.byref(addr),
|
|
|
|
ctypes.byref(addr_size)
|
|
|
|
) != 0:
|
|
|
|
raise socket.error(ctypes.FormatError())
|
|
|
|
|
|
|
|
if address_family == socket.AF_INET:
|
|
|
|
return ctypes.string_at(addr.ipv4_addr, 4)
|
|
|
|
if address_family == socket.AF_INET6:
|
|
|
|
return ctypes.string_at(addr.ipv6_addr, 16)
|
|
|
|
|
|
|
|
raise socket.error('unknown address family')
|
|
|
|
|
|
|
|
|
|
|
|
def inet_ntop(address_family, packed_ip):
|
|
|
|
addr = sockaddr()
|
|
|
|
addr.sa_family = address_family
|
|
|
|
addr_size = ctypes.c_int(ctypes.sizeof(addr))
|
|
|
|
ip_string = ctypes.create_string_buffer(128)
|
|
|
|
ip_string_size = ctypes.c_int(ctypes.sizeof(ip_string))
|
|
|
|
|
|
|
|
if address_family == socket.AF_INET:
|
|
|
|
if len(packed_ip) != ctypes.sizeof(addr.ipv4_addr):
|
|
|
|
raise socket.error('packed IP wrong length for inet_ntoa')
|
|
|
|
ctypes.memmove(addr.ipv4_addr, packed_ip, 4)
|
|
|
|
elif address_family == socket.AF_INET6:
|
|
|
|
if len(packed_ip) != ctypes.sizeof(addr.ipv6_addr):
|
|
|
|
raise socket.error('packed IP wrong length for inet_ntoa')
|
|
|
|
ctypes.memmove(addr.ipv6_addr, packed_ip, 16)
|
|
|
|
else:
|
|
|
|
raise socket.error('unknown address family')
|
|
|
|
|
|
|
|
if WSAAddressToStringA(
|
|
|
|
ctypes.byref(addr),
|
|
|
|
addr_size,
|
|
|
|
None,
|
|
|
|
ip_string,
|
|
|
|
ctypes.byref(ip_string_size)
|
|
|
|
) != 0:
|
|
|
|
raise socket.error(ctypes.FormatError())
|
|
|
|
|
|
|
|
return ip_string[:ip_string_size.value - 1]
|
|
|
|
|
|
|
|
# Adding our two functions to the socket library
|
|
|
|
if os.name == 'nt':
|
|
|
|
socket.inet_pton = inet_pton
|
|
|
|
socket.inet_ntop = inet_ntop
|