summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/socket.rst4
-rw-r--r--Lib/test/test_socket.py16
-rw-r--r--Modules/socketmodule.c108
3 files changed, 124 insertions, 4 deletions
diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
index 658b8c9..b01238c 100644
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -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
:c:func:`inet_pton`.
- Availability: Unix (maybe not all platforms).
+ Availability: Unix (maybe not all platforms), Windows.
.. 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
: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.
..
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index beff31a..eb8619f 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -980,6 +980,14 @@ class GeneralModuleTests(unittest.TestCase):
return
except ImportError:
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)
assertInvalid = lambda a: self.assertRaises(
(OSError, ValueError), f, a
@@ -1058,6 +1066,14 @@ class GeneralModuleTests(unittest.TestCase):
return
except ImportError:
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)
assertInvalid = lambda a: self.assertRaises(
(OSError, ValueError), f, a
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 0396bf4..6c4b050 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -5023,7 +5023,7 @@ socket_inet_ntoa(PyObject *self, PyObject *args)
return PyUnicode_FromString(inet_ntoa(packed_addr));
}
-#ifdef HAVE_INET_PTON
+#if defined(HAVE_INET_PTON) || defined(MS_WINDOWS)
PyDoc_STRVAR(inet_pton_doc,
"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\
for use with low-level network functions.");
+#endif
+
+#ifdef HAVE_INET_PTON
+
static PyObject *
socket_inet_pton(PyObject *self, PyObject *args)
{
@@ -5075,12 +5079,52 @@ socket_inet_pton(PyObject *self, PyObject *args)
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,
"inet_ntop(af, packed_ip) -> string formatted IP address\n\
\n\
Convert a packed IP address of the given family to string format.");
+#endif
+
+
+#ifdef HAVE_INET_PTON
static PyObject *
socket_inet_ntop(PyObject *self, PyObject *args)
{
@@ -5134,6 +5178,66 @@ socket_inet_ntop(PyObject *self, PyObject *args)
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 */
/* Python interface to getaddrinfo(host, port). */
@@ -5600,7 +5704,7 @@ static PyMethodDef socket_methods[] = {
METH_VARARGS, inet_aton_doc},
{"inet_ntoa", socket_inet_ntoa,
METH_VARARGS, inet_ntoa_doc},
-#ifdef HAVE_INET_PTON
+#if defined(HAVE_INET_PTON) || defined(MS_WINDOWS)
{"inet_pton", socket_inet_pton,
METH_VARARGS, inet_pton_doc},
{"inet_ntop", socket_inet_ntop,