Subject: Re: Clarifications wanted on Basic API (RFC 2553)

From: Jim Bound <[email-masked]>
Date: Tue, 01 Feb 2000 23:22:55 -0500

Hi Brian,

>When implementing the basic API functions for our 1.4 release, there were a
>number of places where I had to guess as to what the proper behavior should
>be.  So I'm soliciting clarifications from anyone with an opinion,
>especially the RFC authors, and would also like to hear what other existing
>implementations do.

I am responding serially so I will get to all the responses to your mail
too eventually.

I am sure when we are done all will still not be totally defined.

As a note it would help if all would space their questions out
individually and not with runon sentences so I can respond (or others)
to each question or comment as they occur inline.  thanks...

>I'm primarily interested in answers to the getaddrinfo and getnameinfo
>questions, but I'll do this in the order they're presented in the RFC.  If
>this whole thing is too long to wade through, please at least look at those.

We need to address each detail so thats fine.

>Section 3.10, sockaddr_storage:
>I believe the consensus now is to use ss_family and not __ss_family.
>Correct me if I'm wrong.

That is correct and as it is specified in XNS 5.2 as specified in
sys/sockets.h.

>Section 6.1, getipnodebyname:
>What is the namespace for error_num?  Regular system error number space, or
>a private one?  Four errors are explicitly listed (HOST_NOT_FOUND,
>NO_ADDRESS, NO_RECOVERY, and TRY_AGAIN).  The spec doesn't say that we're
>supposed to define these in an include file somewhere, so I assumed that
>you're supposed to use the system error codes that are the closest in
>meaning.  Is this correct?

It is not specified if it is to be regular or private system number
space its an implementation choice.  But it must be thread safe.
Yes that is correct and all that is expected.

>Also, the text says "error_num will be set to one of the following values"
>and then lists only the above four errors.  Is the intent really that no
>other errors are acceptable?  I could see returning errors for invalid
>arguments, things that would fault, etc.  We currently return an invalid
>argument error if the combination of the "af" and "flags" arguments yield a
>name resolution lookup type we don't support.  Likewise we return a fault
>error code if the name argument is NULL, and an out of memory error code if
>the system can't allocate space to hold the returned hostent structure.  Is
>this o.k.?

Yes that is fine.  The error returns assume that the function was able
to execute when passed in correctly and after editing errors.  This is a
good point.  We could extend the meaning of TRY_AGAIN to mean specific
implementation error codes can be passed in.  I could argue that NULL is
HOST_NOT_FOUND, and likewise for an unsupported af and flags argument.
Another way to treat it is with EINVAL for the cases you mention.

But as we are deprecating the use of this API I suggest we not spend a
lot of time on its syntax or semantics at this point.

>And is returning a fault error better than just letting the user's code
>fault?  For this API, I think it is.

Yes it is.

>The AI_ADDRCONFIG flag is supposed to indicate that a AAAA query "should
>occur only if the node has at least one IPv6 source address configured".  I
>assume this definition excludes the loopback address.  Does it also exclude
>link-local?  If our stack is present on a machine with interfaces, then
>people will have link-local addresses even if they don't have any native
>IPv6 connectivity to anywhere off of their local link.  But maybe the
>machine they issued the query for is a node on the local link...  How about
>automatic tunneling addresses?  We automatically assign one of those for
>every IPv4 address, so if you have an IPv4 address, you have an IPv6 address
>that can reach any other IPv6 enabled machine on the IPv4 Internet.  And if
>you don't have an IPv4 address, then you're probably not issuing a
>getaddrinfo call with this flag set.

It specifies the address must be a valid IPv4 or IPv6 source address.
The intention was that it was an address that has been configured for an
IPv6 interface.  I think loopback should be excluded.  I do not think
tunnels apply as they are psuedo-interfaces.  I think link-local is
valid.  I think what is a valid IPv6 source address in RFC 2373 is the
test.  We need to move this field to getaddrinfo section too.  We can
add these parameters but I would like to hear what other implementors
think and how they have implemented it.  I would think the simple case
is the loopback is excluded and the addresses are retrieved that have
actually been configured for an interface not a psuedo-interface.

>Section 6.2 getipnodebyaddr:
>The same error code issue that I asked about for getipnodebyname applies
>here as well.

>Again, we return errors that aren't explicitly listed: a fault error instead
>of faulting if "src" is a NULL pointer, an invalid arguments error if "len"
>isn't the right size for the given "af", and an address family not supported
>error if  "af" isn't one of the address families we support.

same answers as previously provided.

>Section 6.3 freehostent:
>I have the same question that Itojun just asked about freeaddrinfo - what to
>do if "ptr" is NULL?  You can't return an error, so the options are to take
>a fault, or just ignore the call.  I agree with itojun that you should take
>the fault -- this is a good way to get the programmer's attention that there
>is something wrong with their code.  Changing the call to return an error
>code doesn't strike me as any better than just silently ignoring a NULL ptr
>since far too many programmers don't bother to check return values from
>calls like this.

I agree returing an error is not good what XNS did is specify the
programmer must only pass pointers provided by getipnodebyname and
getipnodebyaddr.  But this is deprecated too.  We should make sure
freeaddrinfo is correct.

>Section 6.4 freeaddrinfo:
>Exact same issue as for freehostent.

Take the fault but further specify as XNS 5.2 did where the pointer must
come from.

>Section 6.4 getaddrinfo:
>The spec is explicit about getaddrinfo having its own error code namespace
>and what the various EAI_* error codes are.  It's not always clear about
>which one to use in certain situations, however.  For example, EAI_SERVICE
>means "servname not supported for ai_socktype".  But there's also EAI_NONAME
>for "nodename nor servname provided, or not known".  So what to return if
>someone gives you a service name that isn't valid for the requested socket
>type?  Am I actually expected to look up the service name for all other
>socket types just so I can return EAI_SERVICE if it exists and EAI_NONAME if
>it doesn't?  

Yes.  But XNS provides much more info on error code processing and we
should bring that into the discussion.  Can you look at XNS version?
And then comment.  

>Also, the spec says that in the "hints" structure, "all members
>other than ai_flags, ai_family, ai_socktype, and ai_protocol must be zero or
>a NULL pointer".  Okay, but what error code do I return if they aren't?
>None really seem to apply, so currently I'm returning EAI_FAIL.

EAI_FAIL is what I would use.  This is indicative of the sockets API I
have no issue adding additional more defined error codes.  But do others
want to do this too.

>The existence of the EAI_BADFLAGS error implies that there is a combination
>of input parameters that would warrant such a return value.  Am I really
>supposed to return this if I see a flag I don't recognize?  That would make
>it hard to introduce new flags in the future as new programs requesting the
>new flag would fail on old systems.  So I don't do that.

This is a problem and one we need to fix.  Good catch.  XNS did not fix
this either.  But we are faced with changing and altering a non-IETF API
and spec????  We can't really own this API like we did getipnodebyname
(not ownership in the sense of a standard but "control").

But I am not sure we can make all old systems work anyway in all cases.

>The precise meaning of  the AI_CANONNAME flag is unclear to me.  It says
>that if this flag is set, then upon return, the first addrinfo struct's
>ai_canonname field will point to "a null terminated string containing the
>canonical name of the specified nodename".  Someone define canonical name
>for me please.  Is this supposed to be the fully qualified domain name for
>the host that, in DNS parlance, you get if you follow all the alias
>pointers?  

Its the CNAME for the nodename in DNSese. Does that help? 

>But what if someone passes in an IPv6 address literal into
>getaddrinfo when this flag is set?  Am I supposed to do a reverse address
>lookup just to fill in the ai_canonname field?  

No.  I think thats bad flags.  But we should discuss.
I suppose it could be done I would argue it should not be done.
In fact I would assume AI_NUMBERICHOST operation and the two cannot be
set together?

>I'm thinking yes, although I
>currently don't do that.  But what if AI_NUMERICHOST is also set?  The text
>describing AI_NUMERICHOST states "this flag prevents any type of name
>resolution service from being called", so I'd think I couldn't perform a
>reverse address lookup in that case.  Or maybe I can -- does "any type of
>name resolution service" include looking in /etc/hosts or a local cache of
>previous DNS lookups?  If the only reason to avoid a "name resolution
>service" is to prevent the delay of hitting the DNS or equivalent, then that
>might be o.k.  If it really means that one is forbidden from finding some
>sort of "canonical name" (I assume an address literal doesn't qualify) by
>any means, does this make it illegal to set both the AI_CANONNAME and
>AI_NUMERICHOST flags?  Currently I return EAI_BADFLAGS in this case -- hey,
>a use for that error code after all!

yes I think its illegal and we should say that.

>What am I supposed to do if in the "hints" structure, someone passes in a
>value for ai_socktype that is at odds with ai_protocol?  (e.g. SOCK_STREAM
>with UDP).  Is getaddrinfo supposed to check if the particular triple of
>address family, socket type, and protocol is supported on the system?  The
>existence of the EAI_ADDRFAMILY error implies that just checking that the
>address family is supported is enough (which is all I currently do).

EAI_ADDRFAMILY is correct I think too.
XNS is more verbose but I think we need to define this in text further.

>Likewise, the spec isn't clear about whether one should use the value in
>ai_socktype or ai_protocol when performing protocol specific service
>lookups.  The actual port number to name mappings appear to be assigned via
>protocol (specifically, UDP and TCP).  But the EAI_SERVICE error code says
>"servname not supported for ai_socktype", it doesn't say "for ai_protocol".
>The spec appears to assume that SOCK_STREAM means TCP and vice-versa, and
>SOCK_DGRAM means UDP and vice-versa.  Consider this line "if the caller
>handles only TCP and not UDP, then the ai_socktype member of the hints
>structure should be set to SOCK_STREAM" -- instead of saying that
>ai_protocol should be set to IP_PROTOCOL_TCP.  Currently, I use ai_socktype
>with hardwired mappings from SOCK_STREAM to TCP and SOCK_DGRAM to UDP to
>perform the service lookup, and only use ai_protocol to know what to set the
>ai_protocol field in the returned addrinfo structures to.  I do it this way,
>because in my experience, programmers typically leave the protocol value
>unspecified in socket() calls, instead choosing to specify the socket type.

I think we need to be flexible here as I always specify the protocol
value as one person.

>In the returned addrinfo structures, the spec is silent on what the ai_flags
>field should be.  I can think of two possibilities: zero, or whatever was
>passed into getaddrinfo in the ai_flags field of the hints structure.
>Currently, I always return zero in this field.

This should be specified one way or the other.

>Section 6.5 getnameinfo:
>The spec says "the salen argument gives the length of the sockaddr_in or
>sockaddr_in6 structure".  An overly pedantic member of our team (ok, it was
>Rich :-) thinks this means that salen must exactly equal the length of a
>sockaddr_in if sa->sa_family == AF_INET or it must exactly equal the length
>of a sockaddr_in6 if sa->sa_family == AF_INET6 (i.e. just insisting salen is
>large enough to hold a sockaddr of the appropriate type isn't good enough,
>it must be exactly the right size).  The rest of us disagree, because that
>would mean that you can't call getnameinfo with a pointer to a struct
>sockaddr_storage and salen set to sizeof(struct sockaddr_storage).  Losing
>that capability loses a lot of the address independence feature that makes
>getnameinfo so nice in the first place.  We'd really like to be able to
>perform a getpeername call, with the result going into a sockaddr_storage,
>and then be able to just pass that to getnameinfo to find out who we're
>talking to without having to add any address family specific code.

I would think it should be allowed to support what getpeername returns.
Thus Rich is right?  But should be more flexible and can we without
breaking existing binaries? 

>The spec doesn't say anything about the error code namespace, so I used the
>regular system one.

We winged this.  Now that getipnodebyname is gone we should think if we
can be more verbose here?

>Section 6.6 inet_pton:
>Should we check if "src" and/or "dst" is a NULL pointer and return an error
>(0?) if so?  Or just let it fault?  For "dst", the spec says that the buffer
>it points to must be large enough to hold the expected result, so if we
>treat a NULL pointer like any other too-small buffer, faulting would seem
>appropriate.  For "src" though, it would seem returning 0 (for an invalid
>input string) would be appropriate.

THe return should be zero as its not valid per the spec.
If src is wrong then don't look at dst?

>Section 6.6 inet_ntop:
>Here the spec says that "dst" must be non-NULL, but doesn't say what error
>to set if it isn't.  However, ENOSPC is what is supposed to be set if the
>size of the buffer "dst" points to is inadequate.  So would that apply,
>should it be EFAULT, or should we just let it fault?

I think ENOSPC is pretty clear?  The error condition is intuitive isn't
it?  As you see it?

>The spec doesn't say anything about what to do if "src" is NULL.  Options
>appear to be to set EFAULT and return NULL, or just let it fault.

In this case return EAFNOSUPPORT.  A null addr for AF is not supported?
We could be more verbose I agree.

>The spec doesn't say anything about the error code namespace, although the
>names appear to be Unix system error codes (strangely different approach
>than the generic names used in Section 6.1 and 6.2 -- presumably different
>authors), so I used the regular system one.

I would use the system ones and this problem goes away with
getipnodebyname gone in the spec.

>Well, that's about it,

thanks
/jim
--------------------------------------------------------------------
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: Dave Thaler <[email-masked]>
Date: Wed, 2 Feb 2000 10:38:50 -0800

> actually been configured for an interface not a psuedo-interface.

I think we need to be very clear here when discussing this point.
For example, are we talking about "all addresses on the loopback
interface" or are we talking about "the loopback address only"?
And are we talking about "all addresses on all pseudo-interfaces"
(L2TP tunnels, etc) or a specific pseudo-interface only?

> >canonical name of the specified nodename".  
[...]
> yes I think its illegal and we should say that.

Here's a technical argument for the alternative (in short: it's marginally
more convenient)...

There may be ways that an implementation can obtain the CNAME
without doing an off-machine DNS-query (e.g. look in the local
cache, or /etc/hosts, or whatever), so setting AI_CANONNAME does
not mean that an actual DNS/whatever query needs to be done.

The AI_NUMERICHOST is in my opinion most useful for mapping
to, for example, the "-n" command line of traceroute, etc.
which to me as a user, most often means "I really don't
care about the names, just go fast!" :)

Finally, such utilities often want to have both the address (in
a sockaddr...) and some name (CNAME or not) they can print in
messages.  The code is simplest if there is some field in addrinfo
that it can expect to be filled in in all cases (rather than
adding checks to do it one way in one case, and a different way
in another case).  Today, the only such field is the ai_canonname
field, which AI_CANONNAME means to fill in.

Hence, the most convenient way for a traceroute-like utility to work
is to always set AI_CANONNAME (or another flag that says to fill in
another field, if you prefer) so it can use that field to print
messages.  And to set AI_NUMERICHOST based on whether the -n or
equivalent option was specified.

If ai_canonname MUST hold a CNAME, then perhaps this is an argument
for another field (which perhaps either points to the same thing as 
ai_canonname or nodename) simply to make the app writer's job easier.

Anyhow, that's the technical argument.  Now you can discuss whether
it's a good or bad idea to add/change something just for the sake
of minor convenience :)  

-Dave

---

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

Hope it's not too late to add to this, but I was just looking/fixing our
implementation of getaddrinfo() and had a question.

Suppose the user specified the nodename and AI_PASSIVE flag when calling
getaddrinfo().  What would be the correct behavior:
	1.  Return a EAI_BADFLAGS.
	2.  Ignore the AI_PASSIVE flag, and return the address that the
	    nodename resolves to. (our current implementation)
	3.  Ignore the nodename and return an unspecified address.

Thanks
-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]
--------------------------------------------------------------------

---

From: David Borman <[email-masked]>
Date: Mon, 21 Feb 2000 11:49:13 -0600 (CST)

> From: Francis Dupont <[email-masked]>
> Subject: Re: Clarifications wanted on Basic API (RFC 2553) 
> Date: Fri, 18 Feb 2000 23:04:48 +0100
...
>    The AI_PASSIVE bit only affects things when nodename is NULL, so
>    yes, if nodename != NULL, you effectivly ignore the AI_PASSIVE bit.
>
> => I don't understand why you don't take the AI_PASSIVE bit into account
> and bind() the socket to the address of the nodename?

Sorry, I guess I wasn't clear.  The AI_PASSIVE bit is only there to
specify for getaddrinfo() what to fill in for the address when
nodename == NULL.  So, if nodename is not NULL, getaddrinfo() effectivly
ignores the AI_PASSIVE bit.  The calling application would of course
do its normal bind()/listen()/accept().

		-David Borman, [email-masked]