PATCH: inn-CURRENT-bindaddr-perpeer.patch [was: Re: innfeed, bindaddress, force-ipv4, ipv6]
"Miquel van Smoorenburg"
list-inn-workers at news.cistron.nl
Mon Apr 21 12:09:49 UTC 2008
In article <4807b7ff$0$14354$e4fe514c at news.xs4all.nl>,
Miquel van Smoorenburg <list-inn-workers at news.cistron.nl> wrote:
>I'll work on a 2.5 version soon.
.. and here it is. I've decided to keep the force-ipv4 key for now.
# ----- inn-CURRENT-bindaddr-perpeer.patch ----
diff -ruN orig/inn-CURRENT-20080417/doc/man/innfeed.conf.5 inn-CURRENT-20080417/doc/man/innfeed.conf.5
--- orig/inn-CURRENT-20080417/doc/man/innfeed.conf.5 2008-04-17 11:04:44.000000000 +0200
+++ inn-CURRENT-20080417/doc/man/innfeed.conf.5 2008-04-18 00:12:16.000000000 +0200
@@ -296,19 +296,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 the value of \fBsourceaddress\fP from
-inn.conf(5).
-The default value is unset.
-.TP
-.B bindaddress6
-This key requires a string value. It behaves like \fBbindaddress\fP except
-for outgoing IPv6 connections. A value containing colons must be enclosed
-in double quotes.
.\"..................................................
.SH "GLOBAL PEER DEFAULTS"
.PP
@@ -464,13 +451,34 @@
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 an IPv4 address in dotted-quad format (nnn.nnn.nnn.nnn), "any",
+or "none". If not set or set to "any", 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).
+If not set in innfeed.conf, innfeed defaults to the value of
+\fBsourceaddress\fP from inn.conf(5) (which by default 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 (note
+that a value containing colons must be enclosed in double quotes), "any",
+or "none". If set to "none", innfeed will not use IPv6 for outgoing
+connections to peers in this scope.
+If not set in innfeed.conf, innfeed defaults to the value of
+\fBsourceaddress6\fP from inn.conf(5) (which by default is unset).
+.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.
.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.
+Setting it to true is the same as setting "bindaddress6: none"
+and removing "bindaddress: none" if it was set.
.TP
.B drop-deferred
This key requires a boolean value. By default it is set to false. When
diff -ruN orig/inn-CURRENT-20080417/innfeed/connection.c inn-CURRENT-20080417/innfeed/connection.c
--- orig/inn-CURRENT-20080417/innfeed/connection.c 2008-04-17 11:04:44.000000000 +0200
+++ inn-CURRENT-20080417/innfeed/connection.c 2008-04-18 00:28:11.000000000 +0200
@@ -362,12 +362,6 @@
iv = INIT_RECON_PER ;
init_reconnect_period = (unsigned int) iv ;
- if (getString (topScope,"bindaddress",&sv,NO_INHERIT))
- innconf->sourceaddress = sv;
-
- if (getString (topScope,"bindaddress6",&sv,NO_INHERIT))
- innconf->sourceaddress6 = sv;
-
return rval ;
}
@@ -484,6 +478,7 @@
{
struct sockaddr *cxnAddr;
int fd, rval;
+ const char *src;
const char *peerName = hostPeerName (cxn->myHost) ;
ASSERT (cxn->myEp == NULL) ;
@@ -515,7 +510,14 @@
return false ;
}
- fd = network_client_create (cxnAddr->sa_family, SOCK_STREAM, NULL);
+ if (cxnAddr->sa_family == AF_INET)
+ src = hostBindAddr(cxn->myHost);
+ else
+ src = hostBindAddr6(cxn->myHost);
+ if (src && strcmp(src, "none") == 0)
+ src = NULL;
+
+ fd = network_client_create (cxnAddr->sa_family, SOCK_STREAM, src);
if (fd < 0)
{
syswarn ("%s:%d cxnsleep can't create socket", peerName, cxn->ident) ;
@@ -1270,7 +1272,23 @@
}
+/*
+ * 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)
+{
+ 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_INET)
+ return;
+ hostDeleteIpv4Addr (cxn->myHost);
+}
/*
@@ -1366,6 +1384,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-CURRENT-20080417/innfeed/host.c inn-CURRENT-20080417/innfeed/host.c
--- orig/inn-CURRENT-20080417/innfeed/host.c 2008-04-17 11:04:44.000000000 +0200
+++ inn-CURRENT-20080417/innfeed/host.c 2008-04-21 13:59:26.000000000 +0200
@@ -83,6 +83,8 @@
{
char *peerName;
char *ipName;
+ char *bindAddr;
+ char *bindAddr6;
unsigned int articleTimeout;
unsigned int responseTimeout;
unsigned int initialConnections;
@@ -489,12 +491,18 @@
params->peerName = xstrdup(params->peerName);
if (params->ipName)
params->ipName = xstrdup(params->ipName);
+ if (params->bindAddr)
+ params->bindAddr = xstrdup(params->bindAddr);
+ if (params->bindAddr6)
+ params->bindAddr6 = xstrdup(params->bindAddr6);
}
else
{
/* Fill in defaults */
params->peerName=NULL;
params->ipName=NULL;
+ params->bindAddr=NULL;
+ params->bindAddr6=NULL;
params->articleTimeout=ARTTOUT;
params->responseTimeout=RESPTOUT;
params->initialConnections=INIT_CXNS;
@@ -534,6 +542,10 @@
free (params->peerName) ;
if (params->ipName)
free (params->ipName) ;
+ if (params->bindAddr)
+ free (params->bindAddr) ;
+ if (params->bindAddr6)
+ free (params->bindAddr6) ;
free (params) ;
}
@@ -1129,9 +1141,15 @@
char port[20];
memset(&hints, 0, sizeof(hints));
- hints.ai_family = host->params->forceIPv4 ? PF_INET : NETWORK_AF_HINT;
+ hints.ai_family = NETWORK_AF_HINT;
+#ifdef HAVE_INET6
+ if (host->params->bindAddr && strcmp(host->params->bindAddr, "none") == 0)
+ hints.ai_family = AF_INET6;
+ if (host->params->bindAddr6 && strcmp(host->params->bindAddr6, "none") == 0)
+ hints.ai_family = AF_INET;
+#endif
hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
snprintf(port, sizeof(port), "%hu", host->params->portNum);
gai_ret = getaddrinfo(host->params->ipName, port, &hints, &res);
if (gai_ret != 0 || res == NULL)
@@ -1192,6 +1210,25 @@
}
+/*
+ * 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;
+}
+
+
void hostIpFailed (Host host)
{
if (host->ipAddrs)
@@ -1240,6 +1277,10 @@
fprintf (fp,"%s peer-name : %s\n",indent,host->params->peerName) ;
fprintf (fp,"%s ip-name : %s\n",indent,host->params->ipName) ;
+ fprintf (fp,"%s bindaddress : %s\n",indent,
+ host->params->bindAddr ? host->params->bindAddr : "any") ;
+ fprintf (fp,"%s bindaddress6 : %s\n",indent,
+ host->params->bindAddr6 ? host->params->bindAddr6 : "any") ;
fprintf (fp,"%s abs-max-connections : %d\n",indent,
host->params->absMaxConnections) ;
fprintf (fp,"%s active-connections : %d\n",indent,host->activeCxns) ;
@@ -2390,6 +2431,26 @@
}
/*
+ * get the IPv4 bindAddr
+ */
+const char *hostBindAddr (Host host)
+{
+ ASSERT (host != NULL) ;
+
+ return host->params->bindAddr ;
+}
+
+/*
+ * get the IPv6 bindAddr
+ */
+const char *hostBindAddr6 (Host host)
+{
+ ASSERT (host != NULL) ;
+
+ return host->params->bindAddr6 ;
+}
+
+/*
* get the username and password for authentication
*/
const char *hostUsername (Host host)
@@ -2580,6 +2641,28 @@
}
+ if (getString(s,"bindaddress",&q,isDefault?NO_INHERIT:INHERIT))
+ {
+ if (p->bindAddr)
+ free(p->bindAddr);
+ p->bindAddr = q;
+ }
+ if (getString(s,"bindaddress6",&q,isDefault?NO_INHERIT:INHERIT))
+ {
+ if (p->bindAddr6)
+ free(p->bindAddr6);
+ p->bindAddr6 = q;
+ }
+ if ( p->bindAddr && strcmp(p->bindAddr, "none") == 0 &&
+ p->bindAddr6 && strcmp(p->bindAddr6, "none") == 0)
+ {
+ logOrPrint (LOG_ERR,fp,"cannot set both bindaddress and bindaddress6"
+ "to \"none\" - ignoring them for %s",p->peerName);
+ free(p->bindAddr);
+ free(p->bindAddr6);
+ p->bindAddr = NULL;
+ p->bindAddr6 = NULL;
+ }
/* check required global defaults are there and have good values */
@@ -2643,9 +2726,23 @@
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);
+ GETBOOL(s,fp,"force-ipv4",NOTREQ,p->forceIPv4,inherit);
+ if (p->forceIPv4)
+ {
+ if (p->bindAddr && strcmp(p->bindAddr, "none") == 0)
+ {
+ free(p->bindAddr);
+ p->bindAddr = NULL;
+ }
+ if (p->bindAddr6)
+ {
+ free(p->bindAddr6);
+ p->bindAddr6 = xstrdup("none");
+ }
+ }
+
if (findValue (s,"backlog-factor",inherit) == NULL &&
findValue (s,"backlog-limit-high",inherit) == NULL)
{
diff -ruN orig/inn-CURRENT-20080417/innfeed/host.h inn-CURRENT-20080417/innfeed/host.h
--- orig/inn-CURRENT-20080417/innfeed/host.h 2008-04-17 11:04:44.000000000 +0200
+++ inn-CURRENT-20080417/innfeed/host.h 2008-04-18 00:20:34.000000000 +0200
@@ -87,6 +87,9 @@
/* return an IP address for the host */
struct sockaddr *hostIpAddr (Host host) ;
+/* 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,10 @@
/* get the name that INN uses for this host */
const char *hostPeerName (Host host) ;
+/* get the bindaddress */
+const char *hostBindAddr (Host host) ;
+const char *hostBindAddr6 (Host host) ;
+
/* get the username and password for authentication */
const char *hostUsername (Host host) ;
const char *hostPassword (Host host) ;
diff -ruN orig/inn-CURRENT-20080417/innfeed/main.c inn-CURRENT-20080417/innfeed/main.c
--- orig/inn-CURRENT-20080417/innfeed/main.c 2008-04-17 11:04:44.000000000 +0200
+++ inn-CURRENT-20080417/innfeed/main.c 2008-04-18 00:03:57.000000000 +0200
@@ -961,15 +961,6 @@
fprintf (fp," News spool: %s\n",newsspool) ;
fprintf (fp," Pid file: %s\n",pidFile) ;
fprintf (fp," Log file: %s\n",(logFile == NULL ? "(none)" : logFile));
- if (innconf->sourceaddress != NULL || innconf->sourceaddress6 != NULL)
- {
- fprintf (fp," Bind address:") ;
- if (innconf->sourceaddress != NULL)
- fprintf (fp," %s (IPv4)",innconf->sourceaddress) ;
- if (innconf->sourceaddress6 != NULL)
- fprintf (fp," %s (IPv6)",innconf->sourceaddress6) ;
- fprintf (fp,"\n") ;
- }
fprintf (fp," Debug level: %2ld Mmap: %s\n",
(long)loggingLevel,boolToString(useMMap)) ;
fprintf (fp,"\n") ;
diff -ruN orig/inn-CURRENT-20080417/lib/network.c inn-CURRENT-20080417/lib/network.c
--- orig/inn-CURRENT-20080417/lib/network.c 2008-04-17 11:04:44.000000000 +0200
+++ inn-CURRENT-20080417/lib/network.c 2008-04-18 02:20:07.000000000 +0200
@@ -390,10 +390,11 @@
if (family == AF_INET) {
struct sockaddr_in saddr;
- if (source == NULL)
+ if (source == NULL && innconf != NULL)
source = innconf->sourceaddress;
- if (source == NULL || strcmp(source, "all") == 0)
- return true;
+ if (source == NULL ||
+ strcmp(source, "all") == 0 || strcmp(source, "any") == 0)
+ return true;
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
if (!inet_aton(source, &saddr.sin_addr))
@@ -404,10 +405,11 @@
else if (family == AF_INET6) {
struct sockaddr_in6 saddr;
- if (source == NULL)
+ if (source == NULL && innconf != NULL)
source = innconf->sourceaddress6;
- if (source == NULL || strcmp(source, "all") == 0)
- return true;
+ if (source == NULL ||
+ strcmp(source, "all") == 0 || strcmp(source, "any") == 0)
+ return true;
memset(&saddr, 0, sizeof(saddr));
saddr.sin6_family = AF_INET6;
if (inet_pton(AF_INET6, source, &saddr.sin6_addr) < 1)
--
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