Skip to content

Commit 0ceb717

Browse files
author
Yury Selivanov
authored
Revert "bpo-32221: makeipaddr(): remove interface part + speedup (GH-4724)" (#5394)
This reverts commit 47c0b1f.
1 parent f36ba12 commit 0ceb717

4 files changed

Lines changed: 28 additions & 94 deletions

File tree

Doc/library/socket.rst

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,6 @@ created. Socket addresses are represented as follows:
7777
backward compatibility. Note, however, omission of *scopeid* can cause problems
7878
in manipulating scoped IPv6 addresses.
7979

80-
.. versionchanged:: 3.7
81-
For multicast addresses (with *scopeid* meaningful) *address* may not contain
82-
``%scope`` (or ``zone id``) part. This information is superfluous and may
83-
be safely omitted (recommended).
84-
8580
- :const:`AF_NETLINK` sockets are represented as pairs ``(pid, groups)``.
8681

8782
- Linux-only support for TIPC is available using the :const:`AF_TIPC`
@@ -635,10 +630,6 @@ The :mod:`socket` module also offers various network-related services:
635630
.. versionchanged:: 3.2
636631
parameters can now be passed using keyword arguments.
637632

638-
.. versionchanged:: 3.7
639-
for IPv6 multicast addresses, string representing an address will not
640-
contain ``%scope`` part.
641-
642633
.. function:: getfqdn([name])
643634

644635
Return a fully qualified domain name for *name*. If *name* is omitted or empty,
@@ -697,8 +688,6 @@ The :mod:`socket` module also offers various network-related services:
697688
or numeric address representation in *host*. Similarly, *port* can contain a
698689
string port name or a numeric port number.
699690

700-
For IPv6 addresses, ``%scope`` is appended to the host part if *sockaddr*
701-
contains meaningful *scopeid*. Usually this happens for multicast addresses.
702691

703692
.. function:: getprotobyname(protocolname)
704693

@@ -1189,10 +1178,6 @@ to sockets.
11891178
an exception, the method now retries the system call instead of raising
11901179
an :exc:`InterruptedError` exception (see :pep:`475` for the rationale).
11911180

1192-
.. versionchanged:: 3.7
1193-
For multicast IPv6 address, first item of *address* does not contain
1194-
``%scope`` part anymore. In order to get full IPv6 address use
1195-
:func:`getnameinfo`.
11961181

11971182
.. method:: socket.recvmsg(bufsize[, ancbufsize[, flags]])
11981183

Lib/test/test_socket.py

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1586,50 +1586,6 @@ def test_flowinfo(self):
15861586
with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
15871587
self.assertRaises(OverflowError, s.bind, (support.HOSTv6, 0, -10))
15881588

1589-
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
1590-
def test_getaddrinfo_ipv6_basic(self):
1591-
((*_, sockaddr),) = socket.getaddrinfo(
1592-
'ff02::1de:c0:face:8D', # Note capital letter `D`.
1593-
1234, socket.AF_INET6,
1594-
socket.SOCK_DGRAM,
1595-
socket.IPPROTO_UDP
1596-
)
1597-
self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, 0))
1598-
1599-
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
1600-
@unittest.skipUnless(
1601-
hasattr(socket, 'if_nameindex'),
1602-
'IPv6 scope id by interface name is not supported'
1603-
)
1604-
def test_getaddrinfo_ipv6_scopeid(self):
1605-
test_interface = 'lo'
1606-
ifindex = socket.if_nametoindex(test_interface)
1607-
((*_, sockaddr),) = socket.getaddrinfo(
1608-
'ff02::1de:c0:face:8D%' + test_interface,
1609-
1234, socket.AF_INET6,
1610-
socket.SOCK_DGRAM,
1611-
socket.IPPROTO_UDP
1612-
)
1613-
# Note missing interface name part in IPv6 address
1614-
self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, ifindex))
1615-
1616-
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
1617-
def test_getaddrinfo_ipv6_scopeid_numeric(self):
1618-
((*_, sockaddr),) = socket.getaddrinfo(
1619-
'ff02::1de:c0:face:8D%42',
1620-
1234, socket.AF_INET6,
1621-
socket.SOCK_DGRAM,
1622-
socket.IPPROTO_UDP
1623-
)
1624-
# Note missing interface name part in IPv6 address
1625-
self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, 42))
1626-
1627-
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
1628-
def test_getnameinfo_ipv6_scopeid(self):
1629-
sockaddr = ('ff02::1de:c0:face:8D', 1234, 0, 100500) # Note capital letter `D`.
1630-
nameinfo = socket.getnameinfo(sockaddr, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV)
1631-
self.assertEqual(nameinfo, ('ff02::1de:c0:face:8d%100500', '1234'))
1632-
16331589
def test_str_for_enums(self):
16341590
# Make sure that the AF_* and SOCK_* constants have enum-like string
16351591
# reprs.

Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst

Lines changed: 0 additions & 4 deletions
This file was deleted.

Modules/socketmodule.c

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,33 +1094,25 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int
10941094
}
10951095

10961096

1097-
/* Convert IPv4 sockaddr to a Python str. */
1097+
/* Create a string object representing an IP address.
1098+
This is always a string of the form 'dd.dd.dd.dd' (with variable
1099+
size numbers). */
10981100

10991101
static PyObject *
1100-
make_ipv4_addr(const struct sockaddr_in *addr)
1102+
makeipaddr(struct sockaddr *addr, int addrlen)
11011103
{
1102-
char buf[INET_ADDRSTRLEN];
1103-
if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) {
1104-
PyErr_SetFromErrno(PyExc_OSError);
1105-
return NULL;
1106-
}
1107-
return PyUnicode_FromString(buf);
1108-
}
1109-
1110-
#ifdef ENABLE_IPV6
1111-
/* Convert IPv6 sockaddr to a Python str. */
1104+
char buf[NI_MAXHOST];
1105+
int error;
11121106

1113-
static PyObject *
1114-
make_ipv6_addr(const struct sockaddr_in6 *addr)
1115-
{
1116-
char buf[INET6_ADDRSTRLEN];
1117-
if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) {
1118-
PyErr_SetFromErrno(PyExc_OSError);
1107+
error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
1108+
NI_NUMERICHOST);
1109+
if (error) {
1110+
set_gaierror(error);
11191111
return NULL;
11201112
}
11211113
return PyUnicode_FromString(buf);
11221114
}
1123-
#endif
1115+
11241116

11251117
#ifdef USE_BLUETOOTH
11261118
/* Convert a string representation of a Bluetooth address into a numeric
@@ -1185,10 +1177,11 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
11851177

11861178
case AF_INET:
11871179
{
1188-
const struct sockaddr_in *a = (const struct sockaddr_in *)addr;
1189-
PyObject *addrobj = make_ipv4_addr(a);
1180+
struct sockaddr_in *a;
1181+
PyObject *addrobj = makeipaddr(addr, sizeof(*a));
11901182
PyObject *ret = NULL;
11911183
if (addrobj) {
1184+
a = (struct sockaddr_in *)addr;
11921185
ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port));
11931186
Py_DECREF(addrobj);
11941187
}
@@ -1232,10 +1225,11 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
12321225
#ifdef ENABLE_IPV6
12331226
case AF_INET6:
12341227
{
1235-
const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)addr;
1236-
PyObject *addrobj = make_ipv6_addr(a);
1228+
struct sockaddr_in6 *a;
1229+
PyObject *addrobj = makeipaddr(addr, sizeof(*a));
12371230
PyObject *ret = NULL;
12381231
if (addrobj) {
1232+
a = (struct sockaddr_in6 *)addr;
12391233
ret = Py_BuildValue("OiII",
12401234
addrobj,
12411235
ntohs(a->sin6_port),
@@ -5042,14 +5036,14 @@ static PyObject *
50425036
socket_gethostbyname(PyObject *self, PyObject *args)
50435037
{
50445038
char *name;
5045-
struct sockaddr_in addrbuf;
5039+
sock_addr_t addrbuf;
50465040
PyObject *ret = NULL;
50475041

50485042
if (!PyArg_ParseTuple(args, "et:gethostbyname", "idna", &name))
50495043
return NULL;
5050-
if (setipaddr(name, (struct sockaddr *)&addrbuf, sizeof(addrbuf), AF_INET) < 0)
5044+
if (setipaddr(name, SAS2SA(&addrbuf), sizeof(addrbuf), AF_INET) < 0)
50515045
goto finally;
5052-
ret = make_ipv4_addr(&addrbuf);
5046+
ret = makeipaddr(SAS2SA(&addrbuf), sizeof(struct sockaddr_in));
50535047
finally:
50545048
PyMem_Free(name);
50555049
return ret;
@@ -5151,7 +5145,7 @@ gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af)
51515145
sin.sin_len = sizeof(sin);
51525146
#endif
51535147
memcpy(&sin.sin_addr, *pch, sizeof(sin.sin_addr));
5154-
tmp = make_ipv4_addr(&sin);
5148+
tmp = makeipaddr((struct sockaddr *)&sin, sizeof(sin));
51555149

51565150
if (pch == h->h_addr_list && alen >= sizeof(sin))
51575151
memcpy((char *) addr, &sin, sizeof(sin));
@@ -5168,7 +5162,8 @@ gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af)
51685162
sin6.sin6_len = sizeof(sin6);
51695163
#endif
51705164
memcpy(&sin6.sin6_addr, *pch, sizeof(sin6.sin6_addr));
5171-
tmp = make_ipv6_addr(&sin6);
5165+
tmp = makeipaddr((struct sockaddr *)&sin6,
5166+
sizeof(sin6));
51725167

51735168
if (pch == h->h_addr_list && alen >= sizeof(sin6))
51745169
memcpy((char *) addr, &sin6, sizeof(sin6));
@@ -5939,11 +5934,14 @@ socket_inet_ntop(PyObject *self, PyObject *args)
59395934
Py_buffer packed_ip;
59405935
const char* retval;
59415936
#ifdef ENABLE_IPV6
5942-
char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
5937+
char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1];
59435938
#else
5944-
char ip[INET_ADDRSTRLEN];
5939+
char ip[INET_ADDRSTRLEN + 1];
59455940
#endif
59465941

5942+
/* Guarantee NUL-termination for PyUnicode_FromString() below */
5943+
memset((void *) &ip[0], '\0', sizeof(ip));
5944+
59475945
if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) {
59485946
return NULL;
59495947
}
@@ -5971,7 +5969,6 @@ socket_inet_ntop(PyObject *self, PyObject *args)
59715969
return NULL;
59725970
}
59735971

5974-
/* inet_ntop guarantee NUL-termination of resulting string. */
59755972
retval = inet_ntop(af, packed_ip.buf, ip, sizeof(ip));
59765973
PyBuffer_Release(&packed_ip);
59775974
if (!retval) {

0 commit comments

Comments
 (0)