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