tags 336264 + patch thanks I looked a bit more at my problems with IPv6. It turns out that the connection eventually gets established, but it takes a looong time.
The peer I'm connecting (news.szn.dk) to has two AAAA records and one A record in DNS. That makes getaddrinfo(3) return a list of nine separate address blocks: 2001:1448:89::1/tcp (SOCK_STREAM) 2001:1448:89::1/udp (SOCK_DGRAM) 2001:1448:89::1/raw (SOCK_RAW) 2002:d99d:1ca::1/tcp (SOCK_STREAM) 2002:d99d:1ca::1/udp (SOCK_DGRAM) 2002:d99d:1ca::1/raw (SOCK_RAW) 212.157.1.202/tcp (SOCK_STREAM) 212.157.1.202/udp (SOCK_DGRAM) 212.157.1.202/raw (SOCK_RAW) Because the lookup code in innfeed/host.c does not look at the socket type component, it only tries the IPv4 entry after all of the first 6 results have been tried. That takes well above half an hour on my machine. I attach a patch 'antiudp.patch' for that makes the code ignore non-SOCK_STREAM results. This makes the useful address be tried sooner and somewhat mitigates the problem. I also attach a patch 'avoid-ipv6.patch' which adds a per-peer configuration option in innfeed.conf that, if set, will make innfeed completely ignore IPv6 addresses, unless there are no IPv4 addresses for the host at all. Setting this option on machines with no IPv6 connectivity should eliminate the problem entirely. The two patches overlap and must be applied in succession. The first one fixes what is arguably a bug in the existing code; the second one is more a feature addition that one might conceivably want to implement in a different way instead. -- Henning Makholm "... not one has been remembered from the time when the author studied freshman physics. Quite the contrary: he merely remembers that such and such is true, and to explain it he invents a demonstration at the moment it is needed."
This patch fixes a problem with the IPv6-mode address resolution in innfeed. The getaddrinfo(3) function in glibc reports each address for the hostname thrice: one with each of SOCK_STREAM, SOCK_DGRAM and SOCK_RAW. The upstream code ignores this difference, and therefore an address that is unreachable will be tried three times before innfeed goes on to try another address. With this patch, hostIpAddr() skips results that oar not of the SOCK_STREAM type. 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 03:19:47.089123146 +0100 @@ -1133,7 +1133,7 @@ } else { - /* figure number of pointers that need space */ + /* figure maximum number of pointers that need space */ i = 0; for ( p = res ; p ; p = p->ai_next ) ++i; @@ -1147,11 +1147,24 @@ /* copy the addresses from the getaddrinfo linked list */ for( p = res ; p ; p = p->ai_next ) { + if (p->ai_socktype != SOCK_STREAM) + continue ; memcpy( &newIpAddrs[i], p->ai_addr, p->ai_addrlen ); newIpAddrPtrs[i] = (struct sockaddr *)(&newIpAddrs[i]); ++i; } - newIpAddrPtrs[i] = NULL ; + + if (i) + newIpAddrPtrs[i] = NULL ; + else + { + warn ("%s hostname %s resolves to no useful addresses\n", + host->params->peerName, host->params->ipName); + free(newIpAddrs); + free(newIpAddrPtrs); + newIpAddrs = NULL ; + newIpAddrPtrs = NULL ; + } freeaddrinfo( res ); } #else
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 -u inn-2.4.2/innfeed/host.c inn-2.4.2/innfeed/host.c --- inn-2.4.2/innfeed/host.c 2005-10-30 03:19:47.089123146 +0100 +++ inn-2.4.2/innfeed/host.c 2005-10-30 03:02:24.866066324 +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; @@ -1122,6 +1128,7 @@ #ifdef HAVE_INET6 int gai_ret; struct addrinfo *res, *p; + bool avoid6 ; if(( gai_ret = getaddrinfo(host->params->ipName, NULL, NULL, &res)) != 0 || res == NULL ) @@ -1134,9 +1141,26 @@ else { /* figure maximum number of pointers that need space */ + /* also, only enable IPv6 avoiding if there are IPv4 addrs */ i = 0; - for ( p = res ; p ; p = p->ai_next ) ++i; + avoid6 = false ; + for ( p = res ; p ; p = p->ai_next ) + { + ++i; + if (p->ai_socktype == SOCK_STREAM + && p->ai_addr->sa_family == AF_INET) + avoid6 = true ; + } + if (host->params->avoidInet6) + { + if (!avoid6) + warn ("%s hostname %s has no IPv4 addresses\n", + host->params->peerName,host->params->ipName); + } + else + avoid6 = false; + newIpAddrPtrs = (struct sockaddr **) xmalloc ( (i + 1) * sizeof(struct sockaddr *) ); @@ -1149,6 +1173,8 @@ { if (p->ai_socktype != SOCK_STREAM) continue ; + if (avoid6 && p->ai_addr->sa_family == AF_INET6) + continue ; memcpy( &newIpAddrs[i], p->ai_addr, p->ai_addrlen ); newIpAddrPtrs[i] = (struct sockaddr *)(&newIpAddrs[i]); ++i; @@ -2687,6 +2713,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 && --- 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 02:49:37.806562439 +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 --- 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 02:31:56.016097496 +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 */ --- 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 02:53:07.091052639 +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