--------------------- PatchSet 5200 Date: 2007/08/09 05:11:57 Author: amosjeffries Branch: squid3-ipv6 Tag: (none) Log: Re-write dnsserver for protocol-independance. - removes obsolete -D option. - handles IPv6 nameservers with -s nicely. - update autoconf rules to remove duplicate code between ns*_list when -s actually available. Fixes previous bad conversion where rDNS never lookup up FQDN and output screwed by bad pointers to inet_ntop. Members: configure.in:1.63.2.32->1.63.2.33 src/dnsserver.cc:1.7.4.11->1.7.4.12 Index: squid3/configure.in =================================================================== RCS file: /cvsroot/squid-sf//squid3/configure.in,v retrieving revision 1.63.2.32 retrieving revision 1.63.2.33 diff -u -r1.63.2.32 -r1.63.2.33 --- squid3/configure.in 7 Aug 2007 23:25:10 -0000 1.63.2.32 +++ squid3/configure.in 9 Aug 2007 05:11:57 -0000 1.63.2.33 @@ -1,7 +1,7 @@ dnl Configuration input file for Squid dnl -dnl $Id: configure.in,v 1.63.2.32 2007/08/07 23:25:10 amosjeffries Exp $ +dnl $Id: configure.in,v 1.63.2.33 2007/08/09 05:11:57 amosjeffries Exp $ dnl dnl dnl @@ -11,7 +11,7 @@ AC_CONFIG_AUX_DIR(cfgaux) AC_CONFIG_SRCDIR([src/main.cc]) AM_INIT_AUTOMAKE([tar-ustar]) -AC_REVISION($Revision: 1.63.2.32 $)dnl +AC_REVISION($Revision: 1.63.2.33 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -3347,10 +3347,10 @@ ac_cv_have_res_nsaddr_list="yes", ac_cv_have_res_nsaddr_list="no")) if test $ac_cv_have_res_nsaddr_list = "yes" ; then - AC_DEFINE(HAVE_RES_NSADDR_LIST,1,[If _res structure has nsaddr_list member]) + AC_DEFINE(_SQUID_RES_NSADDR_LIST,_res.nsaddr_list,[If _res structure has nsaddr_list member]) fi -if test $ac_cv_have_res_nsaddr_list = "no" ; then +if test "$_SQUID_RES_NSADDR_LIST" == ""; then AC_CACHE_CHECK(for _res.ns_list, ac_cv_have_res_ns_list, AC_TRY_COMPILE([ #if HAVE_SYS_TYPES_H @@ -3373,7 +3373,7 @@ ac_cv_have_res_ns_list="yes", ac_cv_have_res_ns_list="no")) if test $ac_cv_have_res_ns_list = "yes" ; then - AC_DEFINE(HAVE_RES_NS_LIST,1,[If _res structure has ns_list member]) + AC_DEFINE(_SQUID_RES_NSADDR_LIST,_res.ns_list,[If _res structure has ns_list member]) fi fi Index: squid3/src/dnsserver.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/dnsserver.cc,v retrieving revision 1.7.4.11 retrieving revision 1.7.4.12 diff -u -r1.7.4.11 -r1.7.4.12 --- squid3/src/dnsserver.cc 5 Aug 2007 13:49:31 -0000 1.7.4.11 +++ squid3/src/dnsserver.cc 9 Aug 2007 05:11:58 -0000 1.7.4.12 @@ -1,6 +1,6 @@ /* - * $Id: dnsserver.cc,v 1.7.4.11 2007/08/05 13:49:31 amosjeffries Exp $ + * $Id: dnsserver.cc,v 1.7.4.12 2007/08/09 05:11:58 amosjeffries Exp $ * * DEBUG: section 0 DNS Resolver * AUTHOR: Harvest Derived @@ -152,10 +152,10 @@ static void lookup(const char *buf) { - int reverse = 0; int ttl = 0; int retry = 0; - unsigned int i; + unsigned int i = 0; + IPAddress ipa; char ntoabuf[MAX_IPSTRLEN]; struct addrinfo hints; struct addrinfo *AI = NULL; @@ -175,13 +175,11 @@ hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_CANONNAME; - /* check if it's already an IP address in text form. */ for (;;) { + freeaddrinfo(AI); AI = NULL; - res = getaddrinfo(buf,NULL,&hints,&AI); - - if (NULL != AI->ai_canonname) + if( 0 == (res = getaddrinfo(buf,NULL,&hints,&AI)) ) break; if (res != EAI_AGAIN) @@ -193,64 +191,107 @@ sleep(1); } - if (NULL == AI) { - switch(res) - { - case EAI_AGAIN: - printf("$fail Name Server for domain '%s' is unavailable.\n", buf); - break; + /* check if it's already an IP address in text form. */ + ipa = buf; + if( ipa.IsAnyAddr() ) { + /* its a domain name. Use the forward-DNS lookup already done */ - case EAI_FAIL: - printf("$fail DNS Domain '%s' does not exist: %s.\n", buf, gai_strerror(res)); - break; + if(res == 0) { +#if LIBRESOLV_DNS_TTL_HACK + /* DNS TTL handling - bne@CareNet.hu + * for first try it's a dirty hack, by hacking getanswer + * to place the ttl in a global variable */ + if (_dns_ttl_ > -1) + ttl = _dns_ttl_; +#endif + printf("$addr %d", ttl); + + i = 0; + aiptr = AI; + while(NULL != aiptr && 32 >= i) { + memset(ntoabuf, 0, MAX_IPSTRLEN); + /* annoying inet_ntop breaks the nice code by requiring the in*_addr */ + switch(aiptr->ai_family) { + case AF_INET: + inet_ntop(aiptr->ai_family, &((struct sockaddr_in*)aiptr->ai_addr)->sin_addr, ntoabuf, MAX_IPSTRLEN); + break; + case AF_INET6: + inet_ntop(aiptr->ai_family, &((struct sockaddr_in6*)aiptr->ai_addr)->sin6_addr, ntoabuf, MAX_IPSTRLEN); + break; + default: + continue; + } + printf(" %s", ntoabuf); -#if defined(EAI_NODATA) || defined(EAI_NONAME) -#ifdef EAI_NODATA - /* deprecated. obsolete on some OS */ - case EAI_NODATA: -#endif -#ifdef EAI_NONAME - case EAI_NONAME: -#endif - printf("$fail DNS Domain '%s' exists without any IPs: %s.\n", buf, gai_strerror(res)); - break; -#endif - default: - printf("$fail A system error occured looking up Domain '%s': %s.\n", buf, gai_strerror(res)); - } + i++; + aiptr = aiptr->ai_next; + } - return; + printf("\n"); + } } + else /* its an IPA in text form. perform rDNS */ + { + /* You'd expect getaddrinfo given AI_CANONNAME would do a lookup on + * missing FQDN. But no, it only copies the input string to that + * position regardless of its content. + */ + if(NULL != AI && NULL != AI->ai_addr) { + for(;;) { + if( 0 == (res = getnameinfo(AI->ai_addr, AI->ai_addrlen, ntoabuf, MAX_IPSTRLEN, NULL,0,0)) ) + break; -#if LIBRESOLV_DNS_TTL_HACK - /* DNS TTL handling - bne@CareNet.hu - * for first try it's a dirty hack, by hacking getanswer - * to place the ttl in a global variable */ - if (_dns_ttl_ > -1) - ttl = _dns_ttl_; + if (res != EAI_AGAIN) + break; + + if (++retry == 3) + break; + sleep(1); + } + } + + if(res == 0) { +#if LIBRESOLV_DNS_TTL_HACK + /* DNS TTL handling - bne@CareNet.hu + * for first try it's a dirty hack, by hacking getanswer + * to place the ttl in a global variable */ + if (_dns_ttl_ > -1) + ttl = _dns_ttl_; #endif - if (reverse) { - printf("$name %d %s\n", ttl, AI->ai_canonname); - freeaddrinfo(AI); - return; + printf("$name %d %s\n", ttl, ntoabuf); + } } - printf("$addr %d", ttl); + switch(res) { + case 0: + /* no error. */ + break; - i = 0; - aiptr = AI; - while(NULL != aiptr && 32 >= i) { + case EAI_AGAIN: + printf("$fail Name Server for domain '%s' is unavailable.\n", buf); + break; - printf(" %s", inet_ntop(aiptr->ai_family, aiptr->ai_addr, ntoabuf, MAX_IPSTRLEN)); + case EAI_FAIL: + printf("$fail DNS Domain/IP '%s' does not exist: %s.\n", buf, gai_strerror(res)); + break; - i++; - aiptr = aiptr->ai_next; +#if defined(EAI_NODATA) || defined(EAI_NONAME) +#ifdef EAI_NODATA + /* deprecated. obsolete on some OS */ + case EAI_NODATA: +#endif +#ifdef EAI_NONAME + case EAI_NONAME: +#endif + printf("$fail DNS Domain/IP '%s' exists without any FQDN/IPs: %s.\n", buf, gai_strerror(res)); + break; +#endif + default: + printf("$fail A system error occured looking up Domain/IP '%s': %s.\n", buf, gai_strerror(res)); } - printf("\n"); - freeaddrinfo(AI); } @@ -258,11 +299,18 @@ usage(void) { fprintf(stderr, "usage: dnsserver -Dhv -s nameserver\n" +#if !USE_IPV6 "\t-D Enable resolver RES_DEFNAMES and RES_DNSRCH options\n" +#endif "\t-h Help\n" "\t-v Version\n" "\t-s nameserver Specify alternate name server(s). 'nameserver'\n" - "\t must be an IP address, -s option may be repeated\n"); +#if USE_IPV6 + "\t must be an IPv4 address, -s option may be repeated\n" +#else + "\t must be an IP address, -s option may be repeated\n" +#endif + ); } int @@ -275,62 +323,29 @@ IPAddress ipa; int opt_s = 0; -#if HAVE_RES_NSADDR_LIST || HAVE_RES_NS_LIST +#if _SQUID__RES_NSADDR_LIST extern char *optarg; #endif #endif -#if HAVE_RES_INIT +#if HAVE_RES_INIT && !USE_IPV6 res_init(); -#ifdef RES_DEFAULT - - _res.options = RES_DEFAULT; -#endif -#ifdef RES_DEFNAMES - - _res.options &= ~RES_DEFNAMES; -#endif -#ifdef RES_DNSRCH - - _res.options &= ~RES_DNSRCH; -#endif #endif while ((c = getopt(argc, argv, "Dhs:v")) != -1) { switch (c) { case 'D': -#ifdef RES_DEFNAMES - - _res.options |= RES_DEFNAMES; -#endif -#ifdef RES_DNSRCH - - _res.options |= RES_DNSRCH; -#endif - + fprintf(stderr, "-D is now default behaviour from this tool.\n"); break; case 's': -#if HAVE_RES_INIT +#if HAVE_RES_INIT && defined(_SQUID_RES_NSADDR_LIST) if (opt_s == 0) { _res.nscount = 0; - /* - * Setting RES_INIT here causes coredumps when -s is - * used with -D option. It looks to me like setting - * RES_INIT is wrong. The resolver code sets RES_INIT - * after calling res_init(). When we change the _res - * structure and set RES_INIT, some internal resolver - * structures get confused. -DW 2.1.p1 - */ -#if SEEMS_WRONG - - _res.options |= RES_INIT; -#endif - opt_s = 1; } else if (_res.nscount == MAXNS) { fprintf(stderr, "Too many -s options, only %d are allowed\n", @@ -338,25 +353,17 @@ break; } -#if HAVE_RES_NSADDR_LIST - _res.nsaddr_list[_res.nscount] = _res.nsaddr_list[0]; + _SQUID_RES_NSADDR_LIST[_res.nscount] = _SQUID_RES_NSADDR_LIST[0]; ipa = optarg; - ipa.GetInAddr(_res.nsaddr_list[_res.nscount++].sin_addr); - -#elif HAVE_RES_NS_LIST - - _res.ns_list[_res.nscount] = _res.ns_list[0]; - - ipa = optarg; - ipa.GetInAddr(_res.ns_list[_res.nscount++].addr.sin_addr); - -#else /* Unknown NS list format */ - - fprintf(stderr, "-s is not supported on this resolver\n"); + if( ipa.IPv4() ) { + ipa.GetInAddr(_SQUID_RES_NSADDR_LIST[_res.nscount++].sin_addr); + } + else { + fprintf(stderr, "IPv6 nameservers not supported on this resolver\n"); + } -#endif -#else /* !HAVE_RES_INIT */ +#else /* !HAVE_RES_INIT || !defined(_SQUID_RES_NSADDR_LIST) */ fprintf(stderr, "-s is not supported on this resolver\n");