This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][BZ 14307] Avoid duplicate DNS requests in case answer islonger than a (relatively small) implementation limit


Hi,

The attached patch fixes an issue identified in http://sourceware.org/bugzilla/show_bug.cgi?id=14307.
In summary, getaddrinfo() sends duplicate DNS queries in case the answer is larger than a relatively small limit.
This limit is easily reached for common queries, e.g. "www.google.com" on x86_64 hosts.

getaddrinfo() in sysdeps/posix/getaddrinfo.c currently uses an initial temporary buffer of 512 bytes to contain the answer
- possibly inspired by RFC1035 (http://www.ietf.org/rfc/rfc1035.txt section 2.3.4 Size limits) which originally limited the maximum size of DNS responses to 512 bytes.
A significant part of this buffer is used for a struct host_data, the size of which varies per platform ( 208 bytes on x86, 400 bytes on x86_64 ).
Consequently, for answers larger than 512-400=112 bytes, the temporary buffer is too small and the exact same query is retried with a larger response buffer. 
This results in spurious DNS traffic on the network, and a longer delay (extra RTT to DNS server) before the client can continue processing. Given that the issue is triggered by relatively common queries such as "www.google.com", and also given the pending introduction of some new top-level domains with significantly longer suffixes, it seems appropriate to adjust the initially allowed/expected DNS response size in glibc, to avoid unnescessary network traffic and processing delays.

This patch increases the size of the temporary buffer by sizeof(struct host_data) - in two places - such that the first query response fits more easily. Because sizeof(struct host_data) varies per target platform, this patch reduces (but does not totally eliminate) the observed difference in network behavior for various platforms.

Comments on the patch:
* I picked nss/nsswitch.h because it is already being included by both dns-host.c and getaddrinfo.c
* I initially added sizeof(struct host_data) as a separate factor, such that the duplication of the temp buffer size would not include it more than once. My thinking was that such duplication would cause a difference in behavior between x86 and x86_64 hosts for identical queries, which could be considered undesirable
* This patch likely also fixes bug #13904
* I found the issue in a call to __gethostbyname2_r() in getaddrinfo() and tested the attached fix; I subsequently noticed that a similar buffer was used in a call to __gethostbyaddr_r() in the same function, so I applied a similar fix there - but without testing

The second attachement is a self-contained test program which reproduces the issue on x86_64

Please let me know if you would prefer multiple patches, or if there are other issues with the attached patch

Best regards,
-Jeroen-

2012-07-02  Jeroen van Bemmel <jvb127@gmail.com>
	* sysdeps/posix/getaddrinfo.c ( gaih_inet ): Increase the size of the temporary buffer used to invoke __gethostbyname2_r and __gethostbyaddr_r to make room for struct host_data.
	* resolv/nss_dns/dns-host.c (global scope): Move definition of implementation constants MAX_NR_ALIASES and MAX_NR_ADDRS to header file nss/nsswitch.h.
	* nss/nsswitch.h (global scope): Add definition of implementation constants MAX_NR_ALIASES and MAX_NR_ADDRS (moved from resolv/nss_dns/dns-host.c).

Attachment: glibc_getaddrinfo.patch
Description: Binary data

Attachment: test-getaddrinfo.c
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]