bindaddr-perpeer.patch, take two.
"Miquel van Smoorenburg"
list-inn-workers at news.cistron.nl
Mon Apr 14 21:38:07 UTC 2008
In article <47f9dd0f$0$14351$e4fe514c at news.xs4all.nl>,
Miquel van Smoorenburg <list-inn-workers at news.cistron.nl> wrote:
>The best fix would be to make sure that both bindaddress and
>bindaddress6 work simultaneously, using bindaddress for IPv4
>peer addresses and bindaddress6 for IPv6 peer addresses. If a
>peer has IPv6 addresses, and at least one of them works, never
>fall back to IPv4. If none of the IPv6 addresses work, do fall
>back to IPv4. Next, make innfeed reckognize "bindaddress: none"
>and "bindaddress6: none" config settings instead of yet another
>config item like force-ipv4 / force-ipv6.
Here is the patch for inn-2.4.3. It also applies to -STABLE
if the force-ipv4 patch is reverted first. So, there's also a
patch to do just that
Because the mailinglist appears to eat attachments, both patches
are included inline below.
There's no inn-2.5 version yet.
============= inn-STABLE-remove-force-ipv4.patch ========================
diff -ruN orig/inn-STABLE-20080414/NEWS inn-STABLE-20080414/NEWS
--- orig/inn-STABLE-20080414/NEWS 2008-04-14 11:08:15.000000000 +0200
+++ inn-STABLE-20080414/NEWS 2008-04-14 23:17:07.000000000 +0200
@@ -50,10 +50,6 @@
available on v6 sockets. Thanks to Miquel van Smoorenburg for this
patch.
- * Marco d'Itri added a *force-ipv4* peer configuration option for
- innfeed that, if set, tells innfeed to never attempt an IPv6
- connection to that host.
-
* Added a *nnrpdflags* parameter to inn.conf (modeled on the concept of
*innflags*) to permit passing of command line arguments to instances
of nnrpd spawned from innd.
diff -ruN orig/inn-STABLE-20080414/doc/man/innfeed.conf.5 inn-STABLE-20080414/doc/man/innfeed.conf.5
--- orig/inn-STABLE-20080414/doc/man/innfeed.conf.5 2008-04-14 11:08:15.000000000 +0200
+++ inn-STABLE-20080414/doc/man/innfeed.conf.5 2008-04-14 23:17:53.000000000 +0200
@@ -466,10 +466,6 @@
This key requires a positive integer value. It defines the tcp/ip port
number to use when connecting to the remote.
.TP
-.B force-ipv4
-This key requires a boolean value. By default it is set to false.
-If it is set to true, innfeed will not try to use IPv6 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 orig/inn-STABLE-20080414/doc/pod/news.pod inn-STABLE-20080414/doc/pod/news.pod
--- orig/inn-STABLE-20080414/doc/pod/news.pod 2008-04-14 11:08:15.000000000 +0200
+++ inn-STABLE-20080414/doc/pod/news.pod 2008-04-14 23:18:14.000000000 +0200
@@ -74,12 +74,6 @@
=item *
-Marco d'Itri added a I<force-ipv4> peer configuration option for B<innfeed>
-that, if set, tells B<innfeed> to never attempt an IPv6 connection to that
-host.
-
-=item *
-
Added a I<nnrpdflags> parameter to F<inn.conf> (modeled on the concept of
I<innflags>) to permit passing of command line arguments to instances of
B<nnrpd> spawned from B<innd>.
diff -ruN orig/inn-STABLE-20080414/innfeed/host.c inn-STABLE-20080414/innfeed/host.c
--- orig/inn-STABLE-20080414/innfeed/host.c 2008-04-14 11:08:15.000000000 +0200
+++ inn-STABLE-20080414/innfeed/host.c 2008-04-14 23:20:11.000000000 +0200
@@ -87,7 +87,6 @@
unsigned int absMaxConnections;
unsigned int maxChecks;
unsigned short portNum;
- bool forceIPv4;
unsigned int closePeriod;
unsigned int dynamicMethod;
bool wantStreaming;
@@ -499,7 +498,6 @@
params->absMaxConnections=MAX_CXNS;
params->maxChecks=MAX_Q_SIZE;
params->portNum=PORTNUM;
- params->forceIPv4=FORCE_IPv4;
params->closePeriod=CLOSE_PERIOD;
params->dynamicMethod=METHOD_STATIC;
params->wantStreaming=STREAM;
@@ -1124,13 +1122,10 @@
#ifdef HAVE_INET6
int gai_ret;
struct addrinfo *res, *p;
- struct addrinfo hints;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = host->params->forceIPv4 ? PF_INET : PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- gai_ret = getaddrinfo(host->params->ipName, NULL, &hints, &res);
- if (gai_ret != 0 || res == NULL)
+ if(( gai_ret = getaddrinfo(host->params->ipName, NULL, NULL, &res)) != 0
+ || res == NULL )
+
{
warn ("%s can't resolve hostname %s: %s", host->params->peerName,
host->params->ipName, gai_ret == 0 ? "no addresses returned"
@@ -2679,7 +2674,6 @@
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);
- GETBOOL(s,fp,"force-ipv4",NOTREQ,p->forceIPv4,inherit);
GETINT(s,fp,"backlog-limit",0,LONG_MAX,REQ,p->backlogLimit, inherit);
if (findValue (s,"backlog-factor",inherit) == NULL &&
diff -ruN orig/inn-STABLE-20080414/innfeed/innfeed.h inn-STABLE-20080414/innfeed/innfeed.h
--- orig/inn-STABLE-20080414/innfeed/innfeed.h 2008-04-14 11:08:15.000000000 +0200
+++ inn-STABLE-20080414/innfeed/innfeed.h 2008-04-14 23:20:20.000000000 +0200
@@ -62,7 +62,6 @@
#define NOCHECKHIGH 95.0 /* no-check-high */
#define NOCHECKLOW 90.0 /* no-check-low */
#define PORTNUM 119 /* port-number */
-#define FORCE_IPv4 false /* force using IPv4 */
#define BLOGLIMIT 0 /* backlog-limit */
#define LIMIT_FUDGE 1.10 /* backlog-factor */
#define BLOGLIMIT_HIGH 0 /* backlog-limit-high */
============= inn-2.4.3-bindaddr-perpeer.patch ========================
diff -ruN orig/inn-2.4.3/doc/man/innfeed.conf.5 inn-2.4.3/doc/man/innfeed.conf.5
--- orig/inn-2.4.3/doc/man/innfeed.conf.5 2006-03-20 05:14:57.000000000 +0100
+++ inn-2.4.3/doc/man/innfeed.conf.5 2008-04-08 13:00:07.000000000 +0200
@@ -289,17 +289,6 @@
descriptors free for stdio. Certain systems, Sun's in particular, require
this. SunOS 4.1.x usually requires a value of 128 and Solaris requires a
value of 256. The default if this is not specified, is 0.
-.TP
-.B bindaddress
-This key requires a string value. It specifies which outgoing IPv4 address
-innfeed should bind the local end of its connections to.
-Must be in dotted-quad format (nnn.nnn.nnn.nnn).
-If not set, innfeed defaults to letting the kernel choose this address.
-The default value is unset.
-.TP
-.B bindaddress6
-This key requires a string value. It behave like \fBbindaddress\fP except
-for outgoing IPv6 connections.
.\"..................................................
.SH "GLOBAL PEER DEFAULTS"
.PP
@@ -455,6 +444,22 @@
percentages of articles accepted; a lower number will result in a faster
response.
.TP
+.B bindaddress
+This key requires a string value. It specifies which outgoing IPv4 address
+innfeed should bind the local end of its connection to.
+Must be in dotted-quad format (nnn.nnn.nnn.nnn), the value "*",
+or the value "none". If not set or set to "*", innfeed defaults
+to letting the kernel choose this address.
+If set to "none", innfeed will not use IPv4 for outgoing connections
+to peers in this scope. (i.e. it forces IPv6).
+The default value is unset.
+.TP
+.B bindaddress6
+This key requires a string value. It behaves like \fBbindaddress\fP except
+for outgoing IPv6 connections. Must be in numeric IPv6 format, the
+value "::" or the value "none". If set to "none", innfeed will not use
+IPv6 for outgoing connections in this scope.
+.TP
.B port-number
This key requires a positive integer value. It defines the tcp/ip port
number to use when connecting to the remote.
diff -ruN orig/inn-2.4.3/innfeed/connection.c inn-2.4.3/innfeed/connection.c
--- orig/inn-2.4.3/innfeed/connection.c 2006-03-20 05:14:57.000000000 +0100
+++ inn-2.4.3/innfeed/connection.c 2008-04-14 23:05:42.000000000 +0200
@@ -207,10 +207,6 @@
static unsigned int gCxnCount = 0 ;
static unsigned int max_reconnect_period = MAX_RECON_PER ;
static unsigned int init_reconnect_period = INIT_RECON_PER ;
-static struct sockaddr_in *bind_addr = NULL;
-#ifdef HAVE_INET6
-static struct sockaddr_in6 *bind_addr6 = NULL;
-#endif
#if 0
static bool inited = false ;
#endif
@@ -364,43 +360,6 @@
iv = INIT_RECON_PER ;
init_reconnect_period = (unsigned int) iv ;
-#ifdef HAVE_INET6
- if (getString (topScope,"bindaddress6",&sv,NO_INHERIT))
- {
- struct addrinfo *res, hints;
-
- memset( &hints, 0, sizeof( hints ) );
- hints.ai_flags = AI_NUMERICHOST;
- if( getaddrinfo( sv, NULL, &hints, &res ) )
- {
- logOrPrint (LOG_ERR, fp,
- "innfeed unable to determine IPv6 bind address") ;
- }
- else
- {
- bind_addr6 = (struct sockaddr_in6 *) xmalloc (res->ai_addrlen);
- memcpy( bind_addr6, res->ai_addr, res->ai_addrlen );
- }
- }
-#endif
-
- if (getString (topScope,"bindaddress",&sv,NO_INHERIT))
- {
- struct in_addr addr ;
-
- if (!inet_aton(sv,&addr))
- {
- logOrPrint (LOG_ERR, fp,
- "innfeed unable to determine IPv4 bind address") ;
- }
- else
- {
- bind_addr = (struct sockaddr_in *)
- xmalloc (sizeof(struct sockaddr_in));
- make_sin( (struct sockaddr_in *)bind_addr, &addr );
- }
- }
-
return rval ;
}
@@ -515,13 +474,16 @@
*/
bool cxnConnect (Connection cxn)
{
- struct sockaddr_storage cxnAddr, cxnSelf ;
- struct sockaddr *retAddr;
+ const struct sockaddr_storage cxnAddr, cxnSelf ;
+ const struct sockaddr *retAddr;
int fd, rval ;
const char *peerName = hostPeerName (cxn->myHost) ;
char msgbuf[100];
+ const struct sockaddr_in *bind_addr = hostBindAddr (cxn->myHost) ;
+ int family = 0;
#ifdef HAVE_INET6
char paddr[INET6_ADDRSTRLEN];
+ const struct sockaddr_in6 *bind_addr6 = hostBindAddr6 (cxn->myHost) ;
#endif
ASSERT (cxn->myEp == NULL) ;
@@ -545,7 +507,10 @@
cxn->state = cxnConnectingS ;
- retAddr = hostIpAddr (cxn->myHost) ;
+#ifdef HAVE_INET6
+ family = hostAddrFamily (cxn->myHost);
+#endif
+ retAddr = hostIpAddr (cxn->myHost, family) ;
if (retAddr == NULL)
{
@@ -1380,6 +1345,30 @@
/*
+ * This is called when we are so far in the connection setup that
+ * we're confident it'll work. If the connection is IPv6, remove
+ * the IPv4 addresses from the address list.
+ */
+static void connectionIfIpv6DeleteIpv4Addr (Connection cxn)
+{
+#ifdef HAVE_INET6
+ struct sockaddr_storage ss;
+ socklen_t len = sizeof(ss);
+
+ if (getpeername (endPointFd (cxn->myEp), (struct sockaddr *)&ss, &len) < 0)
+ return;
+ if (ss.ss_family != AF_INET6)
+ return;
+
+ hostDeleteIpv4Addr (cxn->myHost);
+#endif
+}
+
+
+
+
+
+/*
* Called when the banner message has been read off the wire and is
* in the buffer(s). When this function returns the state of the
* Connection will still be cxnConnectingS unless something broken,
@@ -1472,6 +1461,10 @@
if ( isOk )
{
+ /* If we got this far and the connection is IPv6, remove
+ the IPv4 addresses from the address list. */
+ connectionIfIpv6DeleteIpv4Addr (cxn);
+
if (hostUsername (cxn->myHost) != NULL
&& hostPassword (cxn->myHost) != NULL)
issueAuthUser (e,cxn);
diff -ruN orig/inn-2.4.3/innfeed/host.c inn-2.4.3/innfeed/host.c
--- orig/inn-2.4.3/innfeed/host.c 2006-03-20 05:14:57.000000000 +0100
+++ inn-2.4.3/innfeed/host.c 2008-04-14 23:06:11.000000000 +0200
@@ -81,6 +81,11 @@
{
char *peerName;
char *ipName;
+ struct sockaddr_in *bindAddr;
+#ifdef HAVE_INET6
+ struct sockaddr_in6 *bindAddr6;
+#endif
+ int family;
unsigned int articleTimeout;
unsigned int responseTimeout;
unsigned int initialConnections;
@@ -486,12 +491,31 @@
params->peerName = xstrdup(params->peerName);
if (params->ipName)
params->ipName = xstrdup(params->ipName);
+ if (params->bindAddr)
+ {
+ struct sockaddr_in *s = params->bindAddr;
+ params->bindAddr = xmalloc(sizeof(*s));
+ memcpy(params->bindAddr, s, sizeof(*s));
+ }
+#ifdef HAVE_INET6
+ if (params->bindAddr6)
+ {
+ struct sockaddr_in6 *s = params->bindAddr6;
+ params->bindAddr6 = xmalloc(sizeof(*s));
+ memcpy(params->bindAddr6, s, sizeof(*s));
+ }
+#endif
}
else
{
/* Fill in defaults */
params->peerName=NULL;
params->ipName=NULL;
+ params->bindAddr=NULL;
+#ifdef HAVE_INET6
+ params->bindAddr6=NULL;
+#endif
+ params->family = 0;
params->articleTimeout=ARTTOUT;
params->responseTimeout=RESPTOUT;
params->initialConnections=INIT_CXNS;
@@ -530,6 +554,10 @@
free (params->peerName) ;
if (params->ipName)
free (params->ipName) ;
+ if (params->bindAddr)
+ free (params->bindAddr) ;
+ if (params->bindAddr6)
+ free (params->bindAddr6) ;
free (params) ;
}
@@ -1107,7 +1135,7 @@
return nh ;
}
-struct sockaddr *hostIpAddr (Host host)
+struct sockaddr *hostIpAddr (Host host, int family)
{
int i ;
struct sockaddr **newIpAddrPtrs = NULL;
@@ -1122,8 +1150,11 @@
#ifdef HAVE_INET6
int gai_ret;
struct addrinfo *res, *p;
+ struct addrinfo hints;
- if(( gai_ret = getaddrinfo(host->params->ipName, NULL, NULL, &res)) != 0
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family ? family : AF_UNSPEC;
+ if(( gai_ret = getaddrinfo(host->params->ipName, NULL, &hints, &res)) != 0
|| res == NULL )
{
@@ -1227,6 +1258,27 @@
}
+#ifdef HAVE_INET6
+/*
+ * Delete IPv4 addresses from the address list.
+ */
+void hostDeleteIpv4Addr (Host host)
+{
+ int i, j;
+
+ if (!host->ipAddrs)
+ return;
+ for (i = 0, j = 0; host->ipAddrs[i]; i++) {
+ if (host->ipAddrs[i]->sa_family != AF_INET)
+ host->ipAddrs[j++] = host->ipAddrs[i];
+ if (i == host->nextIpAddr)
+ host->nextIpAddr -= (i - j);
+ }
+ host->ipAddrs[j] = 0;
+}
+#endif
+
+
void hostIpFailed (Host host)
{
if (host->ipAddrs)
@@ -1275,6 +1327,31 @@
fprintf (fp,"%s peer-name : %s\n",indent,host->params->peerName) ;
fprintf (fp,"%s ip-name : %s\n",indent,host->params->ipName) ;
+ if (host->params->family == AF_INET6)
+ {
+ fprintf (fp,"%s bindaddress : none\n",indent);
+ }
+ else
+ {
+ fprintf (fp,"%s bindaddress : %s\n",indent,
+ host->params->bindAddr == NULL ||
+ host->params->bindAddr->sin_addr.s_addr == 0 ? "*" :
+ inet_ntoa(host->params->bindAddr->sin_addr));
+ }
+#ifdef HAVE_INET6
+ if (host->params->family == AF_INET)
+ {
+ fprintf (fp,"%s bindaddress6 : none\n",indent);
+ }
+ else
+ {
+ char buf[128];
+ fprintf (fp,"%s bindaddress6 : %s\n",indent,
+ host->params->bindAddr6 == NULL ? "::" :
+ inet_ntop(AF_INET6, &host->params->bindAddr6->sin6_addr,
+ buf, sizeof(buf)));
+ }
+#endif
fprintf (fp,"%s abs-max-connections : %d\n",indent,
host->params->absMaxConnections) ;
fprintf (fp,"%s active-connections : %d\n",indent,host->activeCxns) ;
@@ -2425,6 +2502,38 @@
}
/*
+ * get the IPv4 bindaddress
+ */
+const struct sockaddr_in *hostBindAddr (Host host)
+{
+ ASSERT (host != NULL) ;
+
+ return host->params->bindAddr ;
+}
+
+#ifdef HAVE_INET6
+/*
+ * get the IPv6 bindaddress
+ */
+const struct sockaddr_in6 *hostBindAddr6 (Host host)
+{
+ ASSERT (host != NULL) ;
+
+ return host->params->bindAddr6 ;
+}
+
+/*
+ * get the address family
+ */
+int hostAddrFamily (Host host)
+{
+ ASSERT (host != NULL) ;
+
+ return host->params->family ;
+}
+#endif
+
+/*
* get the username and password for authentication
*/
const char *hostUsername (Host host)
@@ -2611,6 +2720,66 @@
}
+#ifdef HAVE_INET6
+ if (getString(s,"bindaddress6",&q,isDefault?NO_INHERIT:INHERIT))
+ {
+ struct addrinfo *res, hints;
+
+ if ( strcmp(q, "none") == 0)
+ p->family = AF_INET;
+ else if (p->family == AF_INET)
+ p->family = 0;
+
+ if ( strcmp(q, "::") != 0 && strcmp(q, "none") != 0) {
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_flags = AI_NUMERICHOST;
+ if( getaddrinfo( q, NULL, &hints, &res ) )
+ {
+ logOrPrint (LOG_ERR, fp,
+ "unable to determine IPv6 bind address for %s",
+ p->peerName) ;
+ }
+ else
+ {
+ p->bindAddr6 = (struct sockaddr_in6 *) xmalloc (res->ai_addrlen);
+ memcpy( p->bindAddr6, res->ai_addr, res->ai_addrlen );
+ }
+ }
+ }
+#endif
+
+ if (getString(s,"bindaddress",&q,isDefault?NO_INHERIT:INHERIT))
+ {
+ struct in_addr addr ;
+
+#ifdef HAVE_INET6
+ if ( strcmp(q, "none") == 0) {
+ if (p->family) {
+ logOrPrint (LOG_ERR,fp,"cannot set bindaddress and bindaddress6"
+ "to \"none\" - ignoring both for %s",p->peerName);
+ p->family = 0;
+ } else {
+ p->family = AF_INET6;
+ }
+ } else if (p->family == AF_INET6)
+ p->family = 0;
+#endif
+
+ if ( strcmp(q, "*") != 0 && strcmp(q, "none") != 0) {
+ if (!inet_aton(q,&addr))
+ {
+ logOrPrint (LOG_ERR, fp,
+ "unable to determine IPv4 bind address for %s",
+ p->peerName) ;
+ }
+ else
+ {
+ p->bindAddr = (struct sockaddr_in *)
+ xmalloc (sizeof(struct sockaddr_in));
+ make_sin( (struct sockaddr_in *)p->bindAddr, &addr );
+ }
+ }
+ }
/* check required global defaults are there and have good values */
diff -ruN orig/inn-2.4.3/innfeed/host.h inn-2.4.3/innfeed/host.h
--- orig/inn-2.4.3/innfeed/host.h 2006-03-20 05:14:57.000000000 +0100
+++ inn-2.4.3/innfeed/host.h 2008-04-14 23:05:58.000000000 +0200
@@ -85,7 +85,10 @@
void hostSendArticle (Host host, Article article) ;
/* return an IP address for the host */
-struct sockaddr *hostIpAddr (Host host) ;
+struct sockaddr *hostIpAddr (Host host, int family) ;
+
+/* Delete all IPv4 addresses from the address list */
+void hostDeleteIpv4Addr (Host host);
/* mark the current IP address as failed and rotate to the next one */
void hostIpFailed (Host host) ;
@@ -150,6 +153,13 @@
/* get the name that INN uses for this host */
const char *hostPeerName (Host host) ;
+/* get the bindaddress */
+const struct sockaddr_in *hostBindAddr(Host host) ;
+#ifdef HAVE_INET6
+const struct sockaddr_in6 *hostBindAddr6(Host host) ;
+int hostAddrFamily (Host host);
+#endif
+
/* get the username and password for authentication */
const char *hostUsername (Host host) ;
const char *hostPassword (Host host) ;
--
The From: and Reply-To: addresses are internal news2mail gateway addresses.
Reply to the list or to "Miquel van Smoorenburg" <miquels at cistron.nl>
More information about the inn-workers
mailing list