Issue #7171: Add Windows implementation of ``inet_ntop`` and ``inet_pton`` to socket module.
This commit is contained in:
parent
29828a6fa9
commit
da0fc14d46
|
@ -594,7 +594,7 @@ The module :mod:`socket` exports the following constants and functions:
|
||||||
both the value of *address_family* and the underlying implementation of
|
both the value of *address_family* and the underlying implementation of
|
||||||
:c:func:`inet_pton`.
|
:c:func:`inet_pton`.
|
||||||
|
|
||||||
Availability: Unix (maybe not all platforms).
|
Availability: Unix (maybe not all platforms), Windows.
|
||||||
|
|
||||||
|
|
||||||
.. function:: inet_ntop(address_family, packed_ip)
|
.. function:: inet_ntop(address_family, packed_ip)
|
||||||
|
@ -610,7 +610,7 @@ The module :mod:`socket` exports the following constants and functions:
|
||||||
specified address family, :exc:`ValueError` will be raised. A
|
specified address family, :exc:`ValueError` will be raised. A
|
||||||
:exc:`OSError` is raised for errors from the call to :func:`inet_ntop`.
|
:exc:`OSError` is raised for errors from the call to :func:`inet_ntop`.
|
||||||
|
|
||||||
Availability: Unix (maybe not all platforms).
|
Availability: Unix (maybe not all platforms), Windows.
|
||||||
|
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
|
@ -980,6 +980,14 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
return
|
return
|
||||||
except ImportError:
|
except ImportError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
try:
|
||||||
|
inet_pton(AF_INET6, '::')
|
||||||
|
except OSError as e:
|
||||||
|
if e.winerror == 10022:
|
||||||
|
return # IPv6 might not be installed on this PC
|
||||||
|
|
||||||
f = lambda a: inet_pton(AF_INET6, a)
|
f = lambda a: inet_pton(AF_INET6, a)
|
||||||
assertInvalid = lambda a: self.assertRaises(
|
assertInvalid = lambda a: self.assertRaises(
|
||||||
(OSError, ValueError), f, a
|
(OSError, ValueError), f, a
|
||||||
|
@ -1058,6 +1066,14 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
return
|
return
|
||||||
except ImportError:
|
except ImportError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
try:
|
||||||
|
inet_ntop(AF_INET6, b'\x00' * 16)
|
||||||
|
except OSError as e:
|
||||||
|
if e.winerror == 10022:
|
||||||
|
return # IPv6 might not be installed on this PC
|
||||||
|
|
||||||
f = lambda a: inet_ntop(AF_INET6, a)
|
f = lambda a: inet_ntop(AF_INET6, a)
|
||||||
assertInvalid = lambda a: self.assertRaises(
|
assertInvalid = lambda a: self.assertRaises(
|
||||||
(OSError, ValueError), f, a
|
(OSError, ValueError), f, a
|
||||||
|
|
|
@ -5023,7 +5023,7 @@ socket_inet_ntoa(PyObject *self, PyObject *args)
|
||||||
return PyUnicode_FromString(inet_ntoa(packed_addr));
|
return PyUnicode_FromString(inet_ntoa(packed_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_INET_PTON
|
#if defined(HAVE_INET_PTON) || defined(MS_WINDOWS)
|
||||||
|
|
||||||
PyDoc_STRVAR(inet_pton_doc,
|
PyDoc_STRVAR(inet_pton_doc,
|
||||||
"inet_pton(af, ip) -> packed IP address string\n\
|
"inet_pton(af, ip) -> packed IP address string\n\
|
||||||
|
@ -5031,6 +5031,10 @@ PyDoc_STRVAR(inet_pton_doc,
|
||||||
Convert an IP address from string format to a packed string suitable\n\
|
Convert an IP address from string format to a packed string suitable\n\
|
||||||
for use with low-level network functions.");
|
for use with low-level network functions.");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_INET_PTON
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
socket_inet_pton(PyObject *self, PyObject *args)
|
socket_inet_pton(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -5075,12 +5079,52 @@ socket_inet_pton(PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#elif defined(MS_WINDOWS)
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
socket_inet_pton(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
int af;
|
||||||
|
char* ip;
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
|
INT ret, size;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "is:inet_pton", &af, &ip)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = sizeof(addr);
|
||||||
|
ret = WSAStringToAddressA(ip, af, NULL, (LPSOCKADDR)&addr, &size);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
|
||||||
|
return NULL;
|
||||||
|
} else if(af == AF_INET) {
|
||||||
|
struct sockaddr_in *addr4 = (struct sockaddr_in*)&addr;
|
||||||
|
return PyBytes_FromStringAndSize((const char *)&(addr4->sin_addr),
|
||||||
|
sizeof(addr4->sin_addr));
|
||||||
|
} else if (af == AF_INET6) {
|
||||||
|
return PyBytes_FromStringAndSize((const char *)&(addr.sin6_addr),
|
||||||
|
sizeof(addr.sin6_addr));
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_OSError, "unknown address family");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_PTON) || defined(MS_WINDOWS)
|
||||||
|
|
||||||
PyDoc_STRVAR(inet_ntop_doc,
|
PyDoc_STRVAR(inet_ntop_doc,
|
||||||
"inet_ntop(af, packed_ip) -> string formatted IP address\n\
|
"inet_ntop(af, packed_ip) -> string formatted IP address\n\
|
||||||
\n\
|
\n\
|
||||||
Convert a packed IP address of the given family to string format.");
|
Convert a packed IP address of the given family to string format.");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_INET_PTON
|
||||||
static PyObject *
|
static PyObject *
|
||||||
socket_inet_ntop(PyObject *self, PyObject *args)
|
socket_inet_ntop(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -5134,6 +5178,66 @@ socket_inet_ntop(PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(MS_WINDOWS)
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
socket_inet_ntop(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
int af;
|
||||||
|
char* packed;
|
||||||
|
int len;
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
|
DWORD addrlen, ret, retlen;
|
||||||
|
char ip[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1];
|
||||||
|
|
||||||
|
/* Guarantee NUL-termination for PyUnicode_FromString() below */
|
||||||
|
memset((void *) &ip[0], '\0', sizeof(ip));
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "iy#:inet_ntop", &af, &packed, &len)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (af == AF_INET) {
|
||||||
|
struct sockaddr_in * addr4 = (struct sockaddr_in *)&addr;
|
||||||
|
|
||||||
|
if (len != sizeof(struct in_addr)) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"invalid length of packed IP address string");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(addr4, 0, sizeof(struct sockaddr_in));
|
||||||
|
addr4->sin_family = AF_INET;
|
||||||
|
memcpy(&(addr4->sin_addr), packed, sizeof(addr4->sin_addr));
|
||||||
|
addrlen = sizeof(struct sockaddr_in);
|
||||||
|
} else if (af == AF_INET6) {
|
||||||
|
if (len != sizeof(struct in6_addr)) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"invalid length of packed IP address string");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin6_family = AF_INET6;
|
||||||
|
memcpy(&(addr.sin6_addr), packed, sizeof(addr.sin6_addr));
|
||||||
|
addrlen = sizeof(addr);
|
||||||
|
} else {
|
||||||
|
PyErr_Format(PyExc_ValueError,
|
||||||
|
"unknown address family %d", af);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
retlen = sizeof(ip);
|
||||||
|
ret = WSAAddressToStringA((struct sockaddr*)&addr, addrlen, NULL,
|
||||||
|
ip, &retlen);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return PyUnicode_FromString(ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HAVE_INET_PTON */
|
#endif /* HAVE_INET_PTON */
|
||||||
|
|
||||||
/* Python interface to getaddrinfo(host, port). */
|
/* Python interface to getaddrinfo(host, port). */
|
||||||
|
@ -5600,7 +5704,7 @@ static PyMethodDef socket_methods[] = {
|
||||||
METH_VARARGS, inet_aton_doc},
|
METH_VARARGS, inet_aton_doc},
|
||||||
{"inet_ntoa", socket_inet_ntoa,
|
{"inet_ntoa", socket_inet_ntoa,
|
||||||
METH_VARARGS, inet_ntoa_doc},
|
METH_VARARGS, inet_ntoa_doc},
|
||||||
#ifdef HAVE_INET_PTON
|
#if defined(HAVE_INET_PTON) || defined(MS_WINDOWS)
|
||||||
{"inet_pton", socket_inet_pton,
|
{"inet_pton", socket_inet_pton,
|
||||||
METH_VARARGS, inet_pton_doc},
|
METH_VARARGS, inet_pton_doc},
|
||||||
{"inet_ntop", socket_inet_ntop,
|
{"inet_ntop", socket_inet_ntop,
|
||||||
|
|
Loading…
Reference in New Issue