Discussion:
getaddrinfo: how to wildcard everything?
(too old to reply)
Mouse
2021-03-18 15:39:38 UTC
Permalink
I'm finding myself with a small problem.

I have a program that can be told to listen on a particular (TCP) port.
It can also have a host address specified, but, if not, it uses
getaddrinfo() with a nil host string pointer.

This works fine.

Now, I want to add to this program the ability to let the kernel select
a port, that is, to bind to port 0. It is to then use getsockname and
report the port number. I implemented this by passing nil as the
service string to getaddrinfo().

When a host address is specified, this works fine. But, when no host
address is specified, getaddrinfo() fails, instead of returning port-0
structs for each supported address family.

What is the correct way to loop over all supported address families,
letting the kernel select a suitable port number for each one?
getaddrinfo(0,0,...) is the logically obvious way to do this, but that
doesn't work (to be fair, getaddrinfo(3) specifically says it won't
work - "[o]ne or both of [the first two] arguments must be a non-NULL
pointer" - but that's not much help here.)

Of course, I could just fix getaddrinfo() on my machines, and I may do
that. But that wouldn't help elsewhere, and this is one of the few
programs I actually want to use on other, stock, machines, some of
which are not even running any version of NetBSD. At least one such
other OS has a getaddrinfo(3) that (with different wording) makes the
same statement about non-nil arguments.

So I'm wondering if anyone here has enough insight into the design
decisions behind getaddrinfo() to know what the designer(s) intended
people use to do what I'm trying to do here: bind a port-0 (or moral
equivalent) socket in each supported address family. So far I'm not
seeing any way to do this that doesn't involve writing per-AF code in
the application, which of course is what getaddrinfo() is supposed to
free applications from.

/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML ***@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Robert Elz
2021-03-19 17:27:51 UTC
Permalink
Date: Thu, 18 Mar 2021 11:39:38 -0400 (EDT)
From: Mouse <***@Rodents-Montreal.ORG>
Message-ID: <***@Stone.Rodents-Montreal.ORG>

I have seen no replies to your message, so ...

| So I'm wondering if anyone here has enough insight into the design
| decisions behind getaddrinfo() to know what the designer(s) intended
| people use to do what I'm trying to do here: bind a port-0 (or moral
| equivalent) socket in each supported address family.

I am not going to claim to any particular insight, but I suspect that
the mindset might have been that there were a few uses for getaddrinfo()
imagined, but enumerating address families was not one of them.

I'm not sure it is worth it either ... there are just 2 (IPv4 and IPv6)
and if a new one were added, any code written to deal with those two would
need to be modified to handle something different, almost certainly.

So, in practice, no-one wants to look up nothing, just to find out what
address families exist (if an implementation doesn't support one of the
two, you'd discover that on attempted use).

But for a hackish kind of solution to your problem, nothing says that you
are required to use the address structures returned from getaddrinfo()
unaltered - they're not opaque. So, you can just look for some random
well known service (telnet, ftp, http, echo, ...) and when you get the
results back, simply overwrite the port number field with the 0 you wanted
to get returned.

You could also just try "0" as the service name, though I'm not sure how
portable that would be, if it works.

kre


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Mouse
2021-03-19 20:07:57 UTC
Permalink
Post by Robert Elz
Post by Mouse
So I'm wondering if anyone here has enough insight into the design
decisions behind getaddrinfo() to know what the designer(s) intended
people use to do what I'm trying to do here: bind a port-0 (or moral
equivalent) socket in each supported address family.
I am not going to claim to any particular insight, but I suspect that
the mindset might have been that there were a few uses for
getaddrinfo() imagined, but enumerating address families was not one
of them.
Not enumerating address families per se, but binding to a
kernel-selected port in each supported address family.
Post by Robert Elz
I'm not sure it is worth it either ... there are just 2 (IPv4 and IPv6)
...at the moment...
Post by Robert Elz
and if a new one were added, any code written to deal with those two
would need to be modified to handle something different, almost
certainly.
Most of my uses of getaddrinfo() don't need to do anything with
->ai_family beyond passing to to socket(). I was hoping - and, I must
admit, expecting - that this would be just another such.
Post by Robert Elz
So, in practice, no-one wants to look up nothing, just to find out
what address families exist (if an implementation doesn't support one
of the two, you'd discover that on attempted use).
No, it's not just to find out what AFs are supported. It's to bind a
wildcard socket (port 0 or moral equivalent with address INADDR_ANY or
:: or moral equivalent) in each of them (and then use getsockname and
getnameinfo to report the address it got bound to).
Post by Robert Elz
But for a hackish kind of solution to your problem, nothing says that
you are required to use the address structures returned from
getaddrinfo() unaltered - they're not opaque.
If you don't want to write AF-specific code, they might as well be.
Post by Robert Elz
So, you can just look for some random well known service (telnet,
ftp, http, echo, ...) and when you get the results back, simply
overwrite the port number field with the 0 you wanted to get
returned.
Even _finding_ the port number requires looking at the address family
(whether in ai_family or ss_family) and writing AF-specific code for
each AF. That's what I was trying to avoid. See also my next
paragraph.
Post by Robert Elz
You could also just try "0" as the service name, though I'm not sure
how portable that would be, if it works.
It would, at a minimum, be specific to service implementations being
small integers, as opposed to, say, DECnet, where they are (short)
strings instead, with the equivalent of port 0 - if there is one! -
being, I don't what, maybe a zero-length string? This is another
reason why just overwriting the port number involves AF-specific code:
what to overwrite it with is AF-specific. It's just an API/ABI design
similarity that means 0 is appropriate for both AF_INET and AF_INET6.
(For that matter, I don't see anything in 793 that singles out port 0
for anything special, nor do I think there should be; I call it an
API/ABI design bug that it's special to the socket layer. "Kernel
selects port" should be indicated in some out-of-band way, not by a
distinguished in-band value.)

/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML ***@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Robert Elz
2021-03-19 22:52:12 UTC
Permalink
Date: Fri, 19 Mar 2021 16:07:57 -0400 (EDT)
From: Mouse <***@Rodents-Montreal.ORG>
Message-ID: <***@Stone.Rodents-Montreal.ORG>

| Not enumerating address families per se, but binding to a
| kernel-selected port in each supported address family.

But binding TCP right? (I think I recall that from your previous message).

| > I'm not sure it is worth it either ... there are just 2 (IPv4 and
| > IPv6)
|
| ...at the moment...

If there's a replacement, who can tell what it might be like?

| > You could also just try "0" as the service name, though I'm not sure
| > how portable that would be, if it works.

| It would, at a minimum, be specific to service implementations being
| small integers,

Yes, but you're using TCP (SOCK_STREAM) right? Most other protocol
stacks have no real equivalent. The protocol that's used comes with
all kinds of semantics that you cannot just ignore and pretend that
anything will do. TP4 wouldn't work, it needs an accompanying session
protocol to handle graceful close (if even that really does it) for
example, and that's about the closest other transport protocol to TCP.
Session protocols don't typically live in the kernel...

There's just so much you can do to be independant of the environment.

| (For that matter, I don't see anything in 793 that singles out port 0
| for anything special,

No, there isn't, but it has been a reserved port number since the
beginning of time (probably from before TCP/UDP were invented, it was
the way Postel worked, and will continue to be that until port numbers
no longer exist (or longer), so using it to indicate something different
is not any big issue.

kre


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Robert Elz
2021-03-20 09:43:59 UTC
Permalink
Date: Sat, 20 Mar 2021 08:12:42 +0000 (UTC)
From: Jonathan Stone <***@yahoo.com>
Message-ID: <***@mail.yahoo.com>

| Technically, it was Joyce K. Reynolds
| from IANA.

Joyce did the IANA work, for a long tine, and was
in practical control, but Jon was IANA, and port 0
was, and still is, reserved to him.

kre

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Mouse
2021-03-20 01:50:43 UTC
Permalink
Post by Robert Elz
Post by Mouse
Not enumerating address families per se, but binding to a
kernel-selected port in each supported address family.
But binding TCP right? (I think I recall that from your previous message).
Well, SOCK_STREAM. TCP is just the canonical protocol backing
SOCK_STREAM for AF_INET{,6}.
Post by Robert Elz
Post by Mouse
Post by Robert Elz
I'm not sure it is worth it either ... there are just 2 (IPv4 and IPv6)
...at the moment...
If there's a replacement, who can tell what it might be like?
If it supports SOCK_STREAM and kernel-selected port-analogs, it's good
enough for my purposes here.
Post by Robert Elz
Post by Mouse
Post by Robert Elz
You could also just try "0" as the service name, though I'm not
sure how portable that would be, if it works.
It would, at a minimum, be specific to service implementations being
small integers,
Yes, but you're using TCP (SOCK_STREAM) right?
SOCK_STREAM, yes. TCP only because I don't have anything intra-machine
set up except IP; if I had DECnet or ISO/OSI or whatever, I'd want them
to show up too.
Post by Robert Elz
Most other protocol stacks have no real equivalent.
Well, back in the day, I used DECnet on Ultrix, and I think it had a
SOCK_STREAM implementation. It certainly had _something_ I used to
transport IP packets; it might have been SOCK_SEQPACKET, but I think it
was SOCK_STREAM. (I'm moderately sure its port analog was a
(relatively short) string. I don't recall whether it had an analog of
binding to a kernel-selected port.)
Post by Robert Elz
The protocol that's used comes with all kinds of semantics that you
cannot just ignore and pretend that anything will do.
If it provides SOCK_STREAM semantics, it's good enough for the purposes
of my original request. TCP can't be the only thing providing that
(for example, under 5.2, I see what looks at a quick glance like
SOCK_STREAM support in netbt, netiso, and netnatm, as well as
netinet{,6}).
Post by Robert Elz
Post by Mouse
(For that matter, I don't see anything in 793 that singles out port
0 for anything special,
No, there isn't, but it has been a reserved port number since the
beginning of time
Is this documented anywhere? If not, I expect interoperability
problems.

/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML ***@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Robert Elz
2021-03-20 06:02:30 UTC
Permalink
Date: Fri, 19 Mar 2021 21:50:43 -0400 (EDT)
From: Mouse <***@Rodents-Montreal.ORG>
Message-ID: <***@Stone.Rodents-Montreal.ORG>

| >> 0 for anything special,
| > it has been a reserved port number
|
| Is this documented anywhere?

The IANA port registry, where all the assigned
port numbers are listed. 0 is reserved to Postel.

He would never have allowed it to be assigned.
Now everything uses the sockets interface, which
uses port 0 in its API as you know, so no-one
is going to even think about about using it for
something different, it would not work almost
anywhere.

There has been some attempted communication
betwern POSIX and the IETF about whose
responsibility it is to document this, POSIX
specifies the sockets interface, but the IETF
the port number registry (now that Jon is
no longer with us to do it personally).
The IETF (IESG) hasn't responded. Must chase
them again about that. All they need to
do is to change it from reserved to Postel
to reserved to Posix (s/tel/ix/) ...
Then the uses of port 0 will be added to
posix.

kre

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Loading...