diff -r 416cd57d38cf Doc/library/socket.rst --- a/Doc/library/socket.rst Sun Jul 15 00:38:43 2012 +1000 +++ b/Doc/library/socket.rst Mon Jul 16 15:16:54 2012 +0900 @@ -560,7 +560,7 @@ 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) @@ -576,7 +576,7 @@ 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 -r 416cd57d38cf Lib/test/test_socket.py --- a/Lib/test/test_socket.py Sun Jul 15 00:38:43 2012 +1000 +++ b/Lib/test/test_socket.py Mon Jul 16 15:16:54 2012 +0900 @@ -934,6 +934,14 @@ 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( (socket.error, ValueError), f, a @@ -1012,6 +1020,14 @@ 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( (socket.error, ValueError), f, a diff -r 416cd57d38cf Modules/socketmodule.c --- a/Modules/socketmodule.c Sun Jul 15 00:38:43 2012 +1000 +++ b/Modules/socketmodule.c Mon Jul 16 15:16:54 2012 +0900 @@ -4865,7 +4865,7 @@ 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\ @@ -4873,6 +4873,10 @@ 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) { @@ -4917,12 +4921,52 @@ 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) { @@ -4976,6 +5020,66 @@ 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). */ @@ -5433,7 +5537,7 @@ 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,