Discussion:
on netstat's ``tcp'' and ``tcp6''
(too old to reply)
Boris Dorestand
2021-01-30 12:02:17 UTC
Permalink
I have a program (whose source code I don't know) listening on TCP port
8547. I connect to it by using an IPv4 address. When I look at
netstat's output, I can't see the ``tcp'' line relative to port 8547. I
see the following type of output:

--8<---------------cut here---------------start------------->8---
%netstat -na | grep LISTEN
[...]
tcp 0 0 0.0.0.0:1234 0.0.0.0:* LISTEN
[...]
tcp6 0 0 :::8547 :::* LISTEN
[...]
--8<---------------cut here---------------end--------------->8---

Because I can connect to it by specifying the machine's IPv4 address, I
expected to see a ``tcp'' line with the port 8547 on it. Instead, I see
a ``tcp6'' line, so that surprised me. To prove that there is no
8547-line that's not a tcp6-line, let me show you this:

--8<---------------cut here---------------start------------->8---
%netstat -na | grep LISTEN | grep 8547
tcp6 0 0 :::8547 :::* LISTEN
%
--8<---------------cut here---------------end--------------->8---

How does it work? When software supports both IPv4 and IPv6, I see only
a tcp6-line? I'm totally surprised here. Thank you for any information
on this.
Richard Kettlewell
2021-01-30 17:32:55 UTC
Permalink
Post by Boris Dorestand
How does it work? When software supports both IPv4 and IPv6, I see
only a tcp6-line? I'm totally surprised here. Thank you for any
information on this.
See IPV6_V6ONLY in https://man7.org/linux/man-pages/man7/ipv6.7.html
--
https://www.greenend.org.uk/rjk/
Boris Dorestand
2021-02-01 17:14:16 UTC
Permalink
Post by Richard Kettlewell
Post by Boris Dorestand
How does it work? When software supports both IPv4 and IPv6, I see
only a tcp6-line? I'm totally surprised here. Thank you for any
information on this.
See IPV6_V6ONLY in https://man7.org/linux/man-pages/man7/ipv6.7.html
%uname -a
Linux ip-172-26-10-188 5.4.0-1032-aws #33~18.04.1-Ubuntu SMP
Thu Dec 10 08:19:06 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

I guess my kernel is 5.4?

So I guess this server on port 8547 is setting IPV6_V6ONLY to zero and
so it is listening on both IPv4 and IPv6? My question is why doesn't
netstat actually report both IPv4 and IPv6? It only reports ``tcp6''.

%netstat -na | grep LISTEN | grep 8547
tcp6 0 0 :::8547 :::* LISTEN
%

Thank you so much for the documentation reference.
Richard Kettlewell
2021-02-01 17:41:38 UTC
Permalink
Post by Boris Dorestand
So I guess this server on port 8547 is setting IPV6_V6ONLY to zero and
so it is listening on both IPv4 and IPv6? My question is why doesn't
netstat actually report both IPv4 and IPv6? It only reports ``tcp6''.
%netstat -na | grep LISTEN | grep 8547
tcp6 0 0 :::8547 :::* LISTEN
%
Thank you so much for the documentation reference.
netstat lists sockets, and there’s only one socket, which accepts both
address families.
--
https://www.greenend.org.uk/rjk/
Grant Taylor
2021-01-31 02:02:47 UTC
Permalink
Post by Boris Dorestand
How does it work? When software supports both IPv4 and IPv6, I see
only a tcp6-line? I'm totally surprised here. Thank you for any
information on this.
This is an oddity of IPv6 support. It's possible, though I don't know
under what conditions, for an IPv6 socket to support IPv4 clients. This
was designed on purpose to make it easy to migrate programs to support IPv6.

IMHO this is the expected behavior.
--
Grant. . . .
unix || die
Boris Dorestand
2021-02-01 17:18:15 UTC
Permalink
Post by Grant Taylor
Post by Boris Dorestand
How does it work? When software supports both IPv4 and IPv6, I see
only a tcp6-line? I'm totally surprised here. Thank you for any
information on this.
This is an oddity of IPv6 support. It's possible, though I don't know
under what conditions, for an IPv6 socket to support IPv4 clients.
This was designed on purpose to make it easy to migrate programs to
support IPv6.
IMHO this is the expected behavior.
Thank you. I read your answer as saying that if the program writer set
IPV6_V6ONLY (https://man7.org/linux/man-pages/man7/ipv6.7.html) to zero,
then the socket binds to both IPv4 and IPv6 and netstat only reports the
tcp6-line. (See my follow-up (<***@example.com>) to Richard
Kettlewell.) If that's correct, okay, that answers my question.

Thanks to all other thread participants too. I read all posts and
appreciate all comments.
Grant Taylor
2021-02-01 17:25:45 UTC
Permalink
Post by Boris Dorestand
Thank you. I read your answer as saying that if the program writer
set IPV6_V6ONLY (https://man7.org/linux/man-pages/man7/ipv6.7.html)
to zero, then the socket binds to both IPv4 and IPv6 and netstat only
to Richard Kettlewell.) If that's correct, okay, that answers my
question.
That summary makes perfect sense and matches (or exceeds) my working
understanding.
Post by Boris Dorestand
Thanks to all other thread participants too. I read all posts and
appreciate all comments.
:-)
--
Grant. . . .
unix || die
Rainer Weikusat
2021-02-01 20:00:27 UTC
Permalink
Post by Boris Dorestand
Post by Grant Taylor
Post by Boris Dorestand
How does it work? When software supports both IPv4 and IPv6, I see
only a tcp6-line? I'm totally surprised here. Thank you for any
information on this.
This is an oddity of IPv6 support. It's possible, though I don't know
under what conditions, for an IPv6 socket to support IPv4 clients.
This was designed on purpose to make it easy to migrate programs to
support IPv6.
IMHO this is the expected behavior.
Thank you. I read your answer as saying that if the program writer set
IPV6_V6ONLY (https://man7.org/linux/man-pages/man7/ipv6.7.html) to zero,
then the socket binds to both IPv4 and IPv6 and netstat only reports the
tcp6-line.
That's not quite correct: Sockets don't "bind to protocols" but they
will be bound (either automatically or by calling bind) to protocol
addresses. Both IPv4 and IPv6 share the same "port namespace". If a
TCPv4 segment destined to a certain port arrives and there's only an
IPv6 socket using this port, the kernel will forward the segment to it
and the IPv4 source address will appear as IPv6-mapped-IPv4 address to
the application.

Conceptually, there's a sort of automatic network address translation
happening here: An IPv4 datagram from 1.2.3.4 sent to 4.3.2.1 will
appear at the application level as IPv6 datagram from ::ffff:0102:0304
to ::ffff:0403:0201 and a reply from the application conceptually from
::ffff:0403:0201 to ::ffff:0102:0304 will cause an IPv4 datagram from
4.3.2.1 to be sent to 1.2.3.4.

There's is only one socket.
Boris Dorestand
2021-02-03 21:38:11 UTC
Permalink
Post by Rainer Weikusat
Post by Boris Dorestand
Post by Grant Taylor
Post by Boris Dorestand
How does it work? When software supports both IPv4 and IPv6, I see
only a tcp6-line? I'm totally surprised here. Thank you for any
information on this.
This is an oddity of IPv6 support. It's possible, though I don't know
under what conditions, for an IPv6 socket to support IPv4 clients.
This was designed on purpose to make it easy to migrate programs to
support IPv6.
IMHO this is the expected behavior.
Thank you. I read your answer as saying that if the program writer set
IPV6_V6ONLY (https://man7.org/linux/man-pages/man7/ipv6.7.html) to zero,
then the socket binds to both IPv4 and IPv6 and netstat only reports the
tcp6-line.
That's not quite correct: Sockets don't "bind to protocols" but they
will be bound (either automatically or by calling bind) to protocol
addresses. Both IPv4 and IPv6 share the same "port namespace". If a
TCPv4 segment destined to a certain port arrives and there's only an
IPv6 socket using this port, the kernel will forward the segment to it
and the IPv4 source address will appear as IPv6-mapped-IPv4 address to
the application.
Conceptually, there's a sort of automatic network address translation
happening here: An IPv4 datagram from 1.2.3.4 sent to 4.3.2.1 will
appear at the application level as IPv6 datagram from ::ffff:0102:0304
to ::ffff:0403:0201 and a reply from the application conceptually from
::ffff:0403:0201 to ::ffff:0102:0304 will cause an IPv4 datagram from
4.3.2.1 to be sent to 1.2.3.4.
There's is only one socket.
Thanks for the correction. I see. They share the same port namespace.
So I guess I can also say that IPv6 generalizes IPv4. It seems that
this solves some of the so-called ``IPv6 mess'' that Daniel J. Bernstein
talked about some years ago:

https://cr.yp.to/djbdns/ipv6mess.html

Does it not? I mean, there's a backward compatibility now. A software
writer can now worry about IPv6 and still support IPv4. If that's so,
who's responsible for this solution? Kernel writers?
Grant Taylor
2021-02-03 23:16:08 UTC
Permalink
Post by Boris Dorestand
Thanks for the correction. I see. They share the same port namespace.
So I guess I can also say that IPv6 generalizes IPv4. It seems
that this solves some of the so-called ``IPv6 mess'' that Daniel
https://cr.yp.to/djbdns/ipv6mess.html
Does it not? I mean, there's a backward compatibility now. A software
writer can now worry about IPv6 and still support IPv4. If that's so,
who's responsible for this solution? Kernel writers?
It helps.

The socket is backwards compatible.

But programs still have to be able to handle an IPv6 address. E.g. 4
bytes won't store an IPv6 address. ;-) Database fields need to be bigger.

But it does remove (or lessen) one (of many) aspects of the problem.
--
Grant. . . .
unix || die
Jorgen Grahn
2021-02-04 07:00:25 UTC
Permalink
Post by Boris Dorestand
Post by Rainer Weikusat
Post by Boris Dorestand
Post by Grant Taylor
Post by Boris Dorestand
How does it work? When software supports both IPv4 and IPv6, I see
only a tcp6-line? I'm totally surprised here. Thank you for any
information on this.
This is an oddity of IPv6 support. It's possible, though I don't know
under what conditions, for an IPv6 socket to support IPv4 clients.
This was designed on purpose to make it easy to migrate programs to
support IPv6.
IMHO this is the expected behavior.
Thank you. I read your answer as saying that if the program writer set
IPV6_V6ONLY (https://man7.org/linux/man-pages/man7/ipv6.7.html) to zero,
then the socket binds to both IPv4 and IPv6 and netstat only reports the
tcp6-line.
That's not quite correct: Sockets don't "bind to protocols" but they
will be bound (either automatically or by calling bind) to protocol
addresses. Both IPv4 and IPv6 share the same "port namespace". If a
TCPv4 segment destined to a certain port arrives and there's only an
IPv6 socket using this port, the kernel will forward the segment to it
and the IPv4 source address will appear as IPv6-mapped-IPv4 address to
the application.
Conceptually, there's a sort of automatic network address translation
happening here: An IPv4 datagram from 1.2.3.4 sent to 4.3.2.1 will
appear at the application level as IPv6 datagram from ::ffff:0102:0304
to ::ffff:0403:0201 and a reply from the application conceptually from
::ffff:0403:0201 to ::ffff:0102:0304 will cause an IPv4 datagram from
4.3.2.1 to be sent to 1.2.3.4.
There's is only one socket.
Thanks for the correction. I see. They share the same port namespace.
So I guess I can also say that IPv6 generalizes IPv4. It seems that
this solves some of the so-called ``IPv6 mess'' that Daniel J. Bernstein
https://cr.yp.to/djbdns/ipv6mess.html
The text is undated, but it seems to be ~20 years old.
Post by Boris Dorestand
Does it not? I mean, there's a backward compatibility now. A software
writer can now worry about IPv6 and still support IPv4.
Ever since getaddrinfo(3) was invented, 15--20 years ago, as a
programmer you don't have to worry much about IPv4 versus IPv6[1].

This doesn't solve the problem that your Internet is going to be quite
small if you bring down the IPv4 half of your internet connection.
/That/ part of DJB's text still applies.
Post by Boris Dorestand
If that's so, who's responsible for this solution? Kernel writers?
I don't think the thing you discussed upthread is really vital for
dual IPv4/IPv6 hosts to work. It's more like a convenience.

/Jorgen

[1] If you're using ordinary TCP or UDP.
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Rainer Weikusat
2021-02-04 15:03:15 UTC
Permalink
[...]
Post by Rainer Weikusat
That's not quite correct: Sockets don't "bind to protocols" but they
will be bound (either automatically or by calling bind) to protocol
addresses. Both IPv4 and IPv6 share the same "port namespace". If a
TCPv4 segment destined to a certain port arrives and there's only an
IPv6 socket using this port, the kernel will forward the segment to it
and the IPv4 source address will appear as IPv6-mapped-IPv4 address to
the application.
[...]
It seems that this solves some of the so-called ``IPv6 mess'' that
https://cr.yp.to/djbdns/ipv6mess.html
Does it not?
I don't think so. IPv6-mapped-IPv4 addresses handle a specific
application use-case: An IPv6 application binding to the wildcard
address on a host which has both a public IPv4 address and a public IPv6
address can communicate with IPv4 applications running on other hosts
sending traffic to the public IPv4 address.

Obviously, this only works for protocols which don't use internet
addresses anywhere except in the IP datagram header.

There's still no way an IPv4 application can (directly) interact with
applications running on IPv6-only hosts.

Rainer Weikusat
2021-01-31 23:07:46 UTC
Permalink
Post by Boris Dorestand
I have a program (whose source code I don't know) listening on TCP port
8547. I connect to it by using an IPv4 address. When I look at
netstat's output, I can't see the ``tcp'' line relative to port 8547. I
%netstat -na | grep LISTEN
[...]
tcp 0 0 0.0.0.0:1234 0.0.0.0:* LISTEN
[...]
tcp6 0 0 :::8547 :::* LISTEN
[...]
Because I can connect to it by specifying the machine's IPv4 address, I
expected to see a ``tcp'' line with the port 8547 on it. Instead, I see
a ``tcp6'' line, so that surprised me.
The IPv6 address space contains all of the IPv4 address space in form of
so-called IPv6-mapped-IPv4 addresses: An IPv6 address of the form

::ffff:aabb:ccdd

is equivalent to the IPv4 address

aa.bb.cc.dd

and the usual textual notation for these addresses is actually

:ffff:aa.bb.cc.dd

Transparent support for this feature enables programs using IPv4 to
talk to other program with no explicit support for IPv4.
Keith Thompson
2021-02-01 01:43:31 UTC
Permalink
Rainer Weikusat <***@talktalk.net> writes:
[...]
Post by Rainer Weikusat
The IPv6 address space contains all of the IPv4 address space in form of
so-called IPv6-mapped-IPv4 addresses: An IPv6 address of the form
::ffff:aabb:ccdd
is equivalent to the IPv4 address
aa.bb.cc.dd
Right, except that IPv6 addresses are normally written in hex and
IPv4 addresses in decimal, so for example

::ffff:904c:23fc

would be equivalent to

144.76.35.252

(I picked the IP address of my Usenet server)
Post by Rainer Weikusat
and the usual textual notation for these addresses is actually
:ffff:aa.bb.cc.dd
Wikipedia says it starts with "::ffff", not ":ffff".

And my example in that notation would be, as I understand it:

::ffff:144.76.35.252

(IPv6 uses decimal rather than hex in this one context.)

https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses
Post by Rainer Weikusat
Transparent support for this feature enables programs using IPv4 to
talk to other program with no explicit support for IPv4.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
Rainer Weikusat
2021-02-01 15:16:11 UTC
Permalink
Post by Keith Thompson
[...]
Post by Rainer Weikusat
The IPv6 address space contains all of the IPv4 address space in form of
so-called IPv6-mapped-IPv4 addresses: An IPv6 address of the form
::ffff:aabb:ccdd
^^
Post by Keith Thompson
Post by Rainer Weikusat
is equivalent to the IPv4 address
aa.bb.cc.dd
Right, except that IPv6 addresses are normally written in hex and
IPv4 addresses in decimal, so for example
::ffff:904c:23fc
would be equivalent to
144.76.35.252
(I picked the IP address of my Usenet server)
Post by Rainer Weikusat
and the usual textual notation for these addresses is actually
:ffff:aa.bb.cc.dd
Wikipedia says it starts with "::ffff", not ":ffff".
That's because :: represents the largest, consecutive stream of
zero-bytes in an IPv6 address. Thanks for pointing out the typo, but I
didn't forget about this since I wrote the ::-using example above.
Loading...