One should always read the spec! It turns out that getaddrinfo() can already do the filtering I did manually in my original patches. Here is a set of smarter patches that lets getaddrinfo() filter instead.
-- Henning Makholm "No one seems to know what distinguishes a bell from a whistle."
This patch fixes a problem with the IPv6-mode address resolution in innfeed. The upstream code neglects to tell getaddrinfo(3) that it wants a SOCK_STREAM; thus each address for the hostname thrice gets reported thrice: one with each of SOCK_STREAM, SOCK_DGRAM and SOCK_RAW. Therefore an address that is unreachable will be tried three times before innfeed goes on to try another address. This patch amends the getaddrinfo(3) call to request a SOCK_STREAM address. Created by Henning Makholm <[EMAIL PROTECTED]> on 2005-10-30 while investigating Debian bug #336264. This patch is in the public domain. diff -ruN inn-2.4.2.orig/innfeed/host.c inn-2.4.2/innfeed/host.c --- inn-2.4.2.orig/innfeed/host.c 2004-12-22 05:21:19.000000000 +0100 +++ inn-2.4.2/innfeed/host.c 2005-10-30 11:20:07.903313828 +0100 @@ -1122,10 +1122,12 @@ #ifdef HAVE_INET6 int gai_ret; struct addrinfo *res, *p; + struct addrinfo template = {0}; + template.ai_family = PF_UNSPEC; + template.ai_socktype = SOCK_STREAM; - if(( gai_ret = getaddrinfo(host->params->ipName, NULL, NULL, &res)) != 0 - || res == NULL ) - + gai_ret = getaddrinfo(host->params->ipName, NULL, &template, &res); + if( gai_ret != 0 || res == NULL ) { warn ("%s can't resolve hostname %s: %s", host->params->peerName, host->params->ipName, gai_ret == 0 ? "no addresses returned"
This patch must be applied after 'antiudp.patch'. It fixes Debian bug #336264, by adding an innfeed configuration option 'avoid-ipv6' that suppresses IPv6 connections unless IPV6 addresses is all we have. In the interest of being non-intrusive the option is off by default, but it should be mostly harmless to have it on for all feeds (such that user configuration would in most cases be necessary for using IPv6 transport); after all there are no documented guarantees about the order in which which getaddrinfo(3) returns alternative addresses. Created by Henning Makholm <[EMAIL PROTECTED]> on 2005-10-30. This patch is in the public domain. diff -ruN inn-2.4.2.orig/doc/man/innfeed.conf.5 inn-2.4.2/doc/man/innfeed.conf.5 --- inn-2.4.2.orig/doc/man/innfeed.conf.5 2004-12-22 05:21:19.000000000 +0100 +++ inn-2.4.2/doc/man/innfeed.conf.5 2005-10-30 11:31:16.741264716 +0100 @@ -459,6 +459,11 @@ This key requires a positive integer value. It defines the tcp/ip port number to use when connecting to the remote. .TP +.B avoid-ipv6 +This key requires a boolean value. By default it is set to false. +If it is set to true, and the \fBip-name\fP has any IPv4 addresses, +innfeed will not try to use IPv6 communication with that peer. +.TP .B drop-deferred This key requires a boolean value. By default it is set to false. When set to true, and a peer replies with code 431 or 436 (try again later) just diff -ruN inn-2.4.2.orig/innfeed/host.c inn-2.4.2/innfeed/host.c --- inn-2.4.2.orig/innfeed/host.c 2005-10-30 11:44:36.148433795 +0100 +++ inn-2.4.2/innfeed/host.c 2005-10-30 11:43:31.612219409 +0100 @@ -87,6 +87,9 @@ unsigned int absMaxConnections; unsigned int maxChecks; unsigned short portNum; +#ifdef HAVE_INET6 + bool avoidInet6; +#endif unsigned int closePeriod; unsigned int dynamicMethod; bool wantStreaming; @@ -498,6 +501,9 @@ params->absMaxConnections=MAX_CXNS; params->maxChecks=MAX_Q_SIZE; params->portNum=PORTNUM; +#ifdef HAVE_INET6 + params->avoidInet6=AVOID_INET6; +#endif params->closePeriod=CLOSE_PERIOD; params->dynamicMethod=METHOD_STATIC; params->wantStreaming=STREAM; @@ -1123,10 +1129,26 @@ int gai_ret; struct addrinfo *res, *p; struct addrinfo template = {0}; - template.ai_family = PF_UNSPEC; template.ai_socktype = SOCK_STREAM; - gai_ret = getaddrinfo(host->params->ipName, NULL, &template, &res); + if (host->params->avoidInet6) + { + template.ai_family = PF_INET; + gai_ret = getaddrinfo(host->params->ipName, NULL, &template, &res); + if (gai_ret == EAI_ADDRFAMILY || gai_ret == EAI_NODATA) + { + warn ("%s hostname %s has no IPv4 addresses\n", + host->params->peerName,host->params->ipName); + template.ai_family = PF_UNSPEC; + gai_ret = getaddrinfo(host->params->ipName,NULL,&template, &res); + } + } + else + { + template.ai_family = PF_UNSPEC; + gai_ret = getaddrinfo(host->params->ipName, NULL, &template, &res); + } + if( gai_ret != 0 || res == NULL ) { warn ("%s can't resolve hostname %s: %s", host->params->peerName, @@ -2676,6 +2698,9 @@ GETREAL(s,fp,"no-check-low",0.0,100.0,REQ,p->lowPassLow, inherit); GETREAL(s,fp,"no-check-filter",0.1,DBL_MAX,REQ,p->lowPassFilter, inherit); GETINT(s,fp,"port-number",0,LONG_MAX,REQ,p->portNum, inherit); +#ifdef HAVE_INET6 + GETBOOL(s,fp,"avoid-ipv6",NOTREQ,p->avoidInet6,inherit); +#endif GETINT(s,fp,"backlog-limit",0,LONG_MAX,REQ,p->backlogLimit, inherit); if (findValue (s,"backlog-factor",inherit) == NULL && diff -ruN inn-2.4.2.orig/innfeed/innfeed.h inn-2.4.2/innfeed/innfeed.h --- inn-2.4.2.orig/innfeed/innfeed.h 2004-12-22 05:21:19.000000000 +0100 +++ inn-2.4.2/innfeed/innfeed.h 2005-10-30 11:31:16.742264580 +0100 @@ -62,6 +62,7 @@ #define NOCHECKHIGH 95.0 /* no-check-high */ #define NOCHECKLOW 90.0 /* no-check-low */ #define PORTNUM 119 /* port-number */ +#define AVOID_INET6 false /* suppress IPv6 use */ #define BLOGLIMIT 0 /* backlog-limit */ #define LIMIT_FUDGE 1.10 /* backlog-factor */ #define BLOGLIMIT_HIGH 0 /* backlog-limit-high */ diff -ruN inn-2.4.2.orig/samples/innfeed.conf inn-2.4.2/samples/innfeed.conf --- inn-2.4.2.orig/samples/innfeed.conf 2004-12-22 05:21:19.000000000 +0100 +++ inn-2.4.2/samples/innfeed.conf 2005-10-30 11:31:16.743264444 +0100 @@ -56,6 +56,7 @@ no-check-low: 90.0 no-check-filter: 50.0 port-number: 119 +avoid-ipv6: false drop-deferred: false min-queue-connection: false backlog-limit: 0