backward compatibility. Note, however, omission of *scopeid* can cause problems
in manipulating scoped IPv6 addresses.
- .. versionchanged:: 3.7
- For multicast addresses (with *scopeid* meaningful) *address* may not contain
- ``%scope`` (or ``zone id``) part. This information is superfluous and may
- be safely omitted (recommended).
-
- :const:`AF_NETLINK` sockets are represented as pairs ``(pid, groups)``.
- Linux-only support for TIPC is available using the :const:`AF_TIPC`
.. versionchanged:: 3.2
parameters can now be passed using keyword arguments.
- .. versionchanged:: 3.7
- for IPv6 multicast addresses, string representing an address will not
- contain ``%scope`` part.
-
.. function:: getfqdn([name])
Return a fully qualified domain name for *name*. If *name* is omitted or empty,
or numeric address representation in *host*. Similarly, *port* can contain a
string port name or a numeric port number.
- For IPv6 addresses, ``%scope`` is appended to the host part if *sockaddr*
- contains meaningful *scopeid*. Usually this happens for multicast addresses.
.. function:: getprotobyname(protocolname)
an exception, the method now retries the system call instead of raising
an :exc:`InterruptedError` exception (see :pep:`475` for the rationale).
- .. versionchanged:: 3.7
- For multicast IPv6 address, first item of *address* does not contain
- ``%scope`` part anymore. In order to get full IPv6 address use
- :func:`getnameinfo`.
.. method:: socket.recvmsg(bufsize[, ancbufsize[, flags]])
with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
self.assertRaises(OverflowError, s.bind, (support.HOSTv6, 0, -10))
- @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
- def test_getaddrinfo_ipv6_basic(self):
- ((*_, sockaddr),) = socket.getaddrinfo(
- 'ff02::1de:c0:face:8D', # Note capital letter `D`.
- 1234, socket.AF_INET6,
- socket.SOCK_DGRAM,
- socket.IPPROTO_UDP
- )
- self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, 0))
-
- @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
- @unittest.skipUnless(
- hasattr(socket, 'if_nameindex'),
- 'IPv6 scope id by interface name is not supported'
- )
- def test_getaddrinfo_ipv6_scopeid(self):
- test_interface = 'lo'
- ifindex = socket.if_nametoindex(test_interface)
- ((*_, sockaddr),) = socket.getaddrinfo(
- 'ff02::1de:c0:face:8D%' + test_interface,
- 1234, socket.AF_INET6,
- socket.SOCK_DGRAM,
- socket.IPPROTO_UDP
- )
- # Note missing interface name part in IPv6 address
- self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, ifindex))
-
- @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
- def test_getaddrinfo_ipv6_scopeid_numeric(self):
- ((*_, sockaddr),) = socket.getaddrinfo(
- 'ff02::1de:c0:face:8D%42',
- 1234, socket.AF_INET6,
- socket.SOCK_DGRAM,
- socket.IPPROTO_UDP
- )
- # Note missing interface name part in IPv6 address
- self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, 42))
-
- @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
- def test_getnameinfo_ipv6_scopeid(self):
- sockaddr = ('ff02::1de:c0:face:8D', 1234, 0, 100500) # Note capital letter `D`.
- nameinfo = socket.getnameinfo(sockaddr, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV)
- self.assertEqual(nameinfo, ('ff02::1de:c0:face:8d%100500', '1234'))
-
def test_str_for_enums(self):
# Make sure that the AF_* and SOCK_* constants have enum-like string
# reprs.
+++ /dev/null
-Various functions returning tuple containig IPv6 addresses now omit ``%scope``
-part since the same information is already encoded in *scopeid* tuple item.
-Especially this speeds up :func:`socket.recvfrom` when it receives multicast
-packet since useless resolving of network interface name is omitted.
}
-/* Convert IPv4 sockaddr to a Python str. */
+/* Create a string object representing an IP address.
+ This is always a string of the form 'dd.dd.dd.dd' (with variable
+ size numbers). */
static PyObject *
-make_ipv4_addr(const struct sockaddr_in *addr)
+makeipaddr(struct sockaddr *addr, int addrlen)
{
- char buf[INET_ADDRSTRLEN];
- if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
- return PyUnicode_FromString(buf);
-}
-
-#ifdef ENABLE_IPV6
-/* Convert IPv6 sockaddr to a Python str. */
+ char buf[NI_MAXHOST];
+ int error;
-static PyObject *
-make_ipv6_addr(const struct sockaddr_in6 *addr)
-{
- char buf[INET6_ADDRSTRLEN];
- if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) {
- PyErr_SetFromErrno(PyExc_OSError);
+ error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
+ NI_NUMERICHOST);
+ if (error) {
+ set_gaierror(error);
return NULL;
}
return PyUnicode_FromString(buf);
}
-#endif
+
#ifdef USE_BLUETOOTH
/* Convert a string representation of a Bluetooth address into a numeric
case AF_INET:
{
- const struct sockaddr_in *a = (const struct sockaddr_in *)addr;
- PyObject *addrobj = make_ipv4_addr(a);
+ struct sockaddr_in *a;
+ PyObject *addrobj = makeipaddr(addr, sizeof(*a));
PyObject *ret = NULL;
if (addrobj) {
+ a = (struct sockaddr_in *)addr;
ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port));
Py_DECREF(addrobj);
}
#ifdef ENABLE_IPV6
case AF_INET6:
{
- const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)addr;
- PyObject *addrobj = make_ipv6_addr(a);
+ struct sockaddr_in6 *a;
+ PyObject *addrobj = makeipaddr(addr, sizeof(*a));
PyObject *ret = NULL;
if (addrobj) {
+ a = (struct sockaddr_in6 *)addr;
ret = Py_BuildValue("OiII",
addrobj,
ntohs(a->sin6_port),
socket_gethostbyname(PyObject *self, PyObject *args)
{
char *name;
- struct sockaddr_in addrbuf;
+ sock_addr_t addrbuf;
PyObject *ret = NULL;
if (!PyArg_ParseTuple(args, "et:gethostbyname", "idna", &name))
return NULL;
- if (setipaddr(name, (struct sockaddr *)&addrbuf, sizeof(addrbuf), AF_INET) < 0)
+ if (setipaddr(name, SAS2SA(&addrbuf), sizeof(addrbuf), AF_INET) < 0)
goto finally;
- ret = make_ipv4_addr(&addrbuf);
+ ret = makeipaddr(SAS2SA(&addrbuf), sizeof(struct sockaddr_in));
finally:
PyMem_Free(name);
return ret;
sin.sin_len = sizeof(sin);
#endif
memcpy(&sin.sin_addr, *pch, sizeof(sin.sin_addr));
- tmp = make_ipv4_addr(&sin);
+ tmp = makeipaddr((struct sockaddr *)&sin, sizeof(sin));
if (pch == h->h_addr_list && alen >= sizeof(sin))
memcpy((char *) addr, &sin, sizeof(sin));
sin6.sin6_len = sizeof(sin6);
#endif
memcpy(&sin6.sin6_addr, *pch, sizeof(sin6.sin6_addr));
- tmp = make_ipv6_addr(&sin6);
+ tmp = makeipaddr((struct sockaddr *)&sin6,
+ sizeof(sin6));
if (pch == h->h_addr_list && alen >= sizeof(sin6))
memcpy((char *) addr, &sin6, sizeof(sin6));
Py_buffer packed_ip;
const char* retval;
#ifdef ENABLE_IPV6
- char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
+ char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1];
#else
- char ip[INET_ADDRSTRLEN];
+ char ip[INET_ADDRSTRLEN + 1];
#endif
+ /* Guarantee NUL-termination for PyUnicode_FromString() below */
+ memset((void *) &ip[0], '\0', sizeof(ip));
+
if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) {
return NULL;
}
return NULL;
}
- /* inet_ntop guarantee NUL-termination of resulting string. */
retval = inet_ntop(af, packed_ip.buf, ip, sizeof(ip));
PyBuffer_Release(&packed_ip);
if (!retval) {