diff options
author | Guido van Rossum <guido@python.org> | 2003-04-25 05:48:32 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2003-04-25 05:48:32 (GMT) |
commit | 47dfa4a89ad1ce110a8218e43cae228302019297 (patch) | |
tree | 1bd9ec116ee42905854d5cb59fdacc00a432e322 /Modules/socketmodule.c | |
parent | 45f41300298ca522fba9366989317f34a2d7e2db (diff) | |
download | cpython-47dfa4a89ad1ce110a8218e43cae228302019297.zip cpython-47dfa4a89ad1ce110a8218e43cae228302019297.tar.gz cpython-47dfa4a89ad1ce110a8218e43cae228302019297.tar.bz2 |
Patch by Jp Calderone:
- The socket module now provides the functions inet_pton and inet_ntop
for converting between string and packed representation of IP addresses.
See SF patch #658327.
This still needs a bit of work in the doc area, because it is not
available on all platforms (especially not on Windows).
Diffstat (limited to 'Modules/socketmodule.c')
-rw-r--r-- | Modules/socketmodule.c | 115 |
1 files changed, 114 insertions, 1 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index ba64cb8..fd6ede0 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -35,6 +35,7 @@ Module interface: --> List of (family, socktype, proto, canonname, sockaddr) - socket.getnameinfo(sockaddr, flags) --> (host, port) - socket.AF_INET, socket.SOCK_STREAM, etc.: constants from <socket.h> +- socket.has_ipv6: boolean value indicating if IPv6 is supported - socket.inet_aton(IP address) -> 32-bit packed IP representation - socket.inet_ntoa(packed IP) -> IP address string - socket.getdefaulttimeout() -> None | float @@ -62,6 +63,9 @@ Local naming conventions: #include "Python.h" +#undef MAX +#define MAX(x, y) ((x) < (y) ? (y) : (x)) + /* Socket object documentation */ PyDoc_STRVAR(sock_doc, "socket([family[, type[, proto]]]) -> socket object\n\ @@ -2776,6 +2780,100 @@ socket_inet_ntoa(PyObject *self, PyObject *args) return PyString_FromString(inet_ntoa(packed_addr)); } +#ifdef HAVE_INET_PTON + +PyDoc_STRVAR(inet_pton_doc, +"inet_pton(af, ip) -> packed IP address string\n\ +\n\ +Convert an IP address from string format to a packed string suitable\n\ +for use with low-level network functions."); + +static PyObject * +socket_inet_pton(PyObject *self, PyObject *args) +{ + int af; + char* ip; + int retval; + char packed[MAX(sizeof(struct in_addr), sizeof(struct in6_addr))]; + + if (!PyArg_ParseTuple(args, "is:inet_pton", &af, &ip)) { + return NULL; + } + + retval = inet_pton(af, ip, packed); + if (retval < 0) { + PyErr_SetFromErrno(socket_error); + return NULL; + } else if (retval == 0) { + PyErr_SetString(socket_error, + "illegal IP address string passed to inet_pton"); + return NULL; + } else if (af == AF_INET) { + return PyString_FromStringAndSize(packed, + sizeof(struct in_addr)); + } else if (af == AF_INET6) { + return PyString_FromStringAndSize(packed, + sizeof(struct in6_addr)); + } else { + PyErr_SetString(socket_error, "unknown address family"); + return NULL; + } +} + +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."); + +static PyObject * +socket_inet_ntop(PyObject *self, PyObject *args) +{ + int af; + char* packed; + int len; + const char* retval; + char ip[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1]; + + /* Guarantee NUL-termination for PyString_FromString() below */ + memset((void *) &ip[0], '\0', sizeof(ip) + 1); + + if (!PyArg_ParseTuple(args, "is#:inet_ntop", &af, &packed, &len)) { + return NULL; + } + + if (af == AF_INET) { + if (len != sizeof(struct in_addr)) { + PyErr_SetString(PyExc_ValueError, + "invalid length of packed IP address string"); + return NULL; + } + } else if (af == AF_INET6) { + if (len != sizeof(struct in6_addr)) { + PyErr_SetString(PyExc_ValueError, + "invalid length of packed IP address string"); + return NULL; + } + } else { + PyErr_Format(PyExc_ValueError, + "unknown address family %d", af); + return NULL; + } + + retval = inet_ntop(af, packed, ip, sizeof(ip)); + if (!retval) { + PyErr_SetFromErrno(socket_error); + return NULL; + } else { + return PyString_FromString(retval); + } + + /* NOTREACHED */ + PyErr_SetString(PyExc_RuntimeError, "invalid handling of inet_ntop"); + return NULL; +} + +#endif /* HAVE_INET_PTON */ + /* Python interface to getaddrinfo(host, port). */ /*ARGSUSED*/ @@ -3035,6 +3133,12 @@ static PyMethodDef socket_methods[] = { METH_VARARGS, inet_aton_doc}, {"inet_ntoa", socket_inet_ntoa, METH_VARARGS, inet_ntoa_doc}, +#ifdef HAVE_INET_PTON + {"inet_pton", socket_inet_pton, + METH_VARARGS, inet_pton_doc}, + {"inet_ntop", socket_inet_ntop, + METH_VARARGS, inet_ntop_doc}, +#endif {"getaddrinfo", socket_getaddrinfo, METH_VARARGS, getaddrinfo_doc}, {"getnameinfo", socket_getnameinfo, @@ -3178,7 +3282,7 @@ See the socket module for documentation."); PyMODINIT_FUNC init_socket(void) { - PyObject *m; + PyObject *m, *has_ipv6; if (!os_init()) return; @@ -3214,6 +3318,14 @@ init_socket(void) (PyObject *)&sock_type) != 0) return; +#ifdef ENABLE_IPV6 + has_ipv6 = Py_True; +#else + has_ipv6 = Py_False; +#endif + Py_INCREF(has_ipv6); + PyModule_AddObject(m, "has_ipv6", has_ipv6); + /* Export C API */ if (PyModule_AddObject(m, PySocket_CAPI_NAME, PyCObject_FromVoidPtr((void *)&PySocketModuleAPI, NULL) @@ -3800,6 +3912,7 @@ init_socket(void) #ifndef HAVE_INET_PTON /* Simplistic emulation code for inet_pton that only works for IPv4 */ +/* These are not exposed because they do not set errno properly */ int inet_pton(int af, const char *src, void *dst) |