Bug 817804

Summary: getaddrinfo returns IP address in ai_canonname
Product: [Fedora] Fedora Reporter: Simo Sorce <ssorce>
Component: glibcAssignee: Jeff Law <law>
Status: CLOSED INSUFFICIENT_DATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: rawhideCC: codonell, fweimer, jakub, law, myllynen, pspacek, schwab
Target Milestone: ---Keywords: Reopened
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2012-05-22 12:31:20 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 880347    

Description Simo Sorce 2012-05-01 11:11:33 UTC
When using AI_CANONNAME|AI_ADDRCONFIG as hints.ai_flags (everything else iin hints is zeroed out on a DNS name ai_canonname is returned with a string representation of the IPv4 IP address instead of the passed in FQDN.
The FQDN passed in is an A name and is arguably the canonical name. No PTR record is available for that IP address.

This is similar to bug #714823 except that it happens with AF_UNSPEC as well.

This is a regression and a behaviour change that breaks GSSAPI/krb5 ability to properly resolve host name -> principal name to obtain a ticket.

In order to test the name ptr-mismatch.kerberos.org can be used.

When getaddrinfo is called with the flags above the ai_canonname returned should either be NULL or contain ptr-mismatch.kerberos.org

Comment 1 Simo Sorce 2012-05-01 17:01:23 UTC
As an additional data point removing AI_ADDRCONFIG seem to not cause the bogus ai_canonname to be returned

Comment 2 Jeff Law 2012-05-08 03:52:09 UTC
Simo, I've done some more investigation on this issue and I'm actually starting to think glibc's implementation is correct and is consistent with other implementations.

The Open Group Base Specification states:

If the AI_CANONNAME flag is specified and the nodename argument is not null, the function shall attempt to determine the canonical name corresponding to nodename (for example, if nodename is an alias or shorthand notation for a complete name).

Note:
    Since different implementations use different conceptual models, the terms ``canonical name'' and ``alias'' cannot be precisely defined for the general case. However, Domain Name System implementations are expected to interpret them as they are used in RFC 1034.

    A numeric host address string is not a ``name'', and thus does not have a ``canonical name'' form; no address to host name translation is performed. See below for handling of the case where a canonical name cannot be obtained.

[ ... ]

If nodename is not null, and if requested by the AI_CANONNAME flag, the ai_canonname field of the first returned addrinfo structure shall point to a null-terminated string containing the canonical name corresponding to the input nodename; if the canonical name is not available, then ai_canonname shall refer to the nodename argument or a string with the same contents. The contents of the ai_flags field of the returned structures are undefined.



While I'm sure that's not the answer you wanted to hear, it may explain why the patch from Andreas was never upstreamed -- by my reading of the specification, the patch Andreas installed into RHEL 6 was blatently wrong.

Comment 3 Simo Sorce 2012-05-08 11:51:39 UTC
Sorry Jeff, but in the text you quote I can see nowhere that returning a numeric address as ai_canonname is correct.

You actually quote: "A numeric host address string is not a ``name''".
If it is not a name, how can it be considered a ''canonical name'' ?

Here we are seeing that glibc is returning the string "1.2.3.4" after it attempted to resolve "a.name.redhat.com" and found the IP address.

I read above: "if the canonical name is not available, then ai_canonname shall refer to the nodename argument or a string with the same contents."
In what way this means getaddrinfo should return "1.2.3.4" instead of "a.name.redhat.com" ?

Comment 4 Simo Sorce 2012-05-09 14:00:58 UTC
It looks like there was a misunderstanding on the conditions that cause this error.
getaddrinfo() is given a fqdn name to resolve with hints set to just AI_CANONNAME|AI_ADDRCONFIG

The expected result is the same fqdn passed in unless it is a CNAME in which case we expect the A name it resolves to in ai_canonname.

We do not expect an IP address nor the result of a PTR operation on the address A points to.

Comment 5 Jeff Law 2012-05-21 20:38:32 UTC
include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
main()
{
 char *node = "ptr-mismatch.kerberos.org";
 char *service = "";
 struct addrinfo hints;
 struct addrinfo *res;

 memset (&hints, 0, sizeof (hints));
 hints.ai_flags = AI_CANONNAME|AI_ADDRCONFIG;
 if (getaddrinfo (node, service, &hints, &res) != 0)
   exit (-1);
 printf("Done\n");
}

On a Fedora 17-beta box I get:

(gdb) p *res
$4 = {ai_flags = 34, ai_family = 2, ai_socktype = 1, ai_protocol = 6, 
  ai_addrlen = 16, ai_addr = 0x602d20, 
  ai_canonname = 0x602cd0 "www.kerberos.org", ai_next = 0x602d40}
(gdb) p *res->ai_next
$5 = {ai_flags = 34, ai_family = 2, ai_socktype = 2, ai_protocol = 17, 
  ai_addrlen = 16, ai_addr = 0x602d70, ai_canonname = 0x0, ai_next = 0x602d90}
(gdb) p *res->ai_next->ai_next
$6 = {ai_flags = 34, ai_family = 2, ai_socktype = 3, ai_protocol = 0, 
  ai_addrlen = 16, ai_addr = 0x602dc0, ai_canonname = 0x0, ai_next = 0x0}


When I look at the records for ptr-mismatch.kerberos.org:

;; ANSWER SECTION:
ptr-mismatch.kerberos.org. 1629 IN      CNAME   www.kerberos.org.
www.kerberos.org.       1629    IN      A       18.9.62.44


So there is a defined canonical name for ptr-mismatch.kerberos.org

So how again are we supposed to test this?

Comment 6 Simo Sorce 2012-05-22 00:46:33 UTC
That is intentional, www.kerberos.org is the A name.

If you want a mismatched PTR, then just lookup www.kerberos.org, you will see it point to an IP address, and the reverse does not match.

The CNAME is actually used for other related tests, to check that the canonical name returned is correct (www.kerberos.org is the proper canonical name for ptr-mismatch.kerberos.org).

Comment 7 Jeff Law 2012-05-22 03:29:51 UTC
Simo,

This would be a whole lot easier if you'd just cobble together a test rather than expecting me to do so from your descriptions.  Ultimately you understand the inputs, outputs and other conditions better than I and thus you're natrually the right person to write a little test.

Given the trivial little test I posted, if I lookup ptr-mismatch.kerberos.org, the returned result in res->ai_canonname is www.kerberos.org.  Is that a correct or incorrect result?  If it's incorrect, what is the correct result?

If I lookup www.kerberos.org by changing the value of "node", then I get www.kerberos.org as the result in res->ai_canonname.  Is that a correct or incorrect result?  If that's incorrect, what is the correct result?

I'd like to get this resolved and probably can once I have a test which shows the problem.

Comment 8 Simo Sorce 2012-05-22 12:31:20 UTC
Hi Jeff,
I tried your program, slightly modified so that I could pass in argv[1] as the host to resolve and print res->ai_canonname

Unfortunately it appears I can't reproduce anymore. Now any address I try always return the proper name and not a stringified raw ip address as I've seen earlier this month.

Unfortunately the machine on which I used to reproduce has, since, been updated so I am not sure what exact version of glibc this happened on :/

I tried both on F16 and F17. I guess something may have changed once again in glibc and the problem went away.
I will close INSUFFICIENT_DATA for now, and re-open only if I find another way to reproduce.