Subject: Re: getaddrinfo with numeric port number and hints->ai_socktype == 0

From: David Borman <[email-masked]>
Date: Thu, 17 Feb 2000 14:59:47 -0600 (CST)

I've been thinking about this, and I've changed my mind a few
times over the course of the discussion. :-)

Before trying to answer what should be returned with a numeric service
number an no sockettype, the questions in my mind are:
	o What is the purpose of getaddrinfo(), i.e. what is the
	  primary use for information returned by getaddrinfo()?
	o If getaddrinfo() just calls getservby{name,port}(),
	  should it blindly propogate the symantics of those routines?
	o What is the purpose of calling getaddrinfo() with
	  a service name, but without specifying a socket type?

I pulled down the current copy of tcp/udp port assignments, to
see what combinations are there.  At the top, it states:

    Ports are used in the TCP [RFC793] to name the ends of logical
    connections which carry long term conversations.  For the purpose of
    providing services to unknown callers, a service contact port is
    defined.  This list specifies the port used by the server process as
    its contact port.  The contact port is sometimes called the
    "well-known port".

    To the extent possible, these same port assignments are used with the
    UDP [RFC768].

For the majority of assignments, the same number is assigned to the
same name for both TCP and UDP.  You have cases where the same
protocol provides both TCP and UDP service:
	echo	7/tcp
	echo	7/udp

Cases where both the TCP and UDP port number are assigned, but
the protocol only uses the TCP port:
	ftp	21/tcp
	ftp	21/udp

Other cases where both the TCP and UDP port number are assigned,
but the protocol only uses the UDP port:
	tftp	69/tcp
	tftp	69/udp

And, there are other cases, where one protocol has the TCP port
assignment, and another protocol has the UDP port assignment:
	shell	514/tcp
	syslog	514/udp

As to using getaddrinfo() with a service name, my understanding is that
it's main purpose in life is to provide a protocol independent method
for an application, given a service or address/service, to get the
information necessary to create a socket, then issue a bind()/listen()/
accept() or connect() call, and be able to do something useful with the
socket.  To that end, if getaddrinfo() can't return a non-zero ai_socktype
field, the information is not useful, because you can't specify a type of
0 on a socket() call.  So, following that logic:

     1)	In the returned addrinfo structures, if a servname was
	specified, then ai_socktype cannot be returned as 0.  Thus,
	if the ai_socktype cannot be determined because of ambiguity,
	an error should be returned.

I'll argue as others have that the calling application has to know
whether it can handle a SOCK_STREAM or SOCK_DGRAM socket, so it should
fill in that information when making the getaddrinfo() call, it shouldn't
just leave hints.ai_socktype zero.  The only question in my mind is if
an application can handle both SOCK_STREAM and SOCK_DGRAM (like for the
"echo" service), should it be able to get the necessary information in
one getaddrinfo() call for both protocols, or should it need to make two
separate getaddrinfo() calls, one for SOCK_STREAM and one for SOCK_DGRAM?

The more I think about it, the only reason I can see for allowing
hints.ai_socktype = 0 is to provide a short cut to avoid having to call
getaddrinfo() twice, once for each socket type.

The Bind 8.2.1 version of getaddrinfo() (which I wrote), fails on
numerical service names if hints.ai_socktype is not specified.  I can't
see blindly returning both a SOCK_STREAM and SOCK_DGRAM structure, given
the above line of thinking.

Currently, the getaddrinfo() in Bind, given a service name, will
look up the service name using getservbyname(), and if the protocol
isn't specified, getservbyname() just returns the first name match.
Thus, if you wrote an tftp client and called getaddrinfo() for "tftp"
without specifying a socket type, and you used the results for
creating your socket, things would work as long as the udp port
was the first tftp service listed in /etc/services.  But if someone
added "tftp 69/tcp" in /etc/services before the "tftp 69/udp" entry,
then your tftp application would break.  That seems like a bad thing
to me.  So, I'd actually be inclined to go the other direction, and
modify getaddrinfo() to fail any service name lookup in which the
hints.socktype was left unspecified.  That way you'd have deterministic
behavior.  The application would fail from the beginning, rather than
working for awhile, and then breaking when someone added the "tftp 69/tcp"
entry in /etc/services.

			-David Borman, [email-masked]
--------------------------------------------------------------------
IETF IPng Working Group Mailing List
IPng Home Page:                      http://playground.sun.com/ipng
FTP archive:                      ftp://playground.sun.com/pub/ipng
Direct all administrative requests to [email-masked]
--------------------------------------------------------------------

---

From: Vladislav Yasevich <[email-masked]>
Date: Fri, 18 Feb 2000 11:14:45 -0500

David

I am playing "devil's advocate" here because I agree with you that we need to
make
getaddrinfo() more deterministic.

The whole idea of the 'hints' is that they limit what getaddrinfo() returns. So,
logic follows that if the limitation is not specified (hints->ai_socktype == 0),
then all supported values should be returned.

If the application does not specify the socket type then it means one of two
things:
	1.  The application does not care can support all types.
	2.  There is a bug in the application that should be fixed.

The same thing goes for the address family.

-vlad

-- 
+++++++++++++++++++++++++++++++
Vladislav Yasevich
Compaq Computer Corp.
110 Spit Brook Rd ZK03-3/T07
Nashua, NH 03062
(603) 884-1079
--------------------------------------------------------------------
IETF IPng Working Group Mailing List
IPng Home Page:                      http://playground.sun.com/ipng
FTP archive:                      ftp://playground.sun.com/pub/ipng
Direct all administrative requests to [email-masked]
--------------------------------------------------------------------