PATCH: innfeed bindaddress per peer

"Miquel van Smoorenburg" list-inn-workers at news.cistron.nl
Sun Mar 23 13:09:13 UTC 2008


This patch allows you to set innfeeds bindaddress/bindaddress6 keys
on a per-peer basis.

Since you cannot connect to an IPv4 address if you bind to an
IPv6 address and the other way around, I've also changed hostIpAddr()
to take an extra 'family' argument, so that we skip v4 addresses
for v6 sockets and vice versa.

inn-2.4.3-bindaddr-perpeer.patch

diff -ruN t/inn-2.4.3/doc/man/innfeed.conf.5 inn-2.4.3/doc/man/innfeed.conf.5
--- t/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-03-18 18:57:14.000000000 +0100
@@ -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,18 @@
 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) or the string "all".
+If set, innfeed cannot connect to IPv6 addresses in this scope.
+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 behaves like \fBbindaddress\fP except
+for outgoing IPv6 connections.
+.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 t/inn-2.4.3/innfeed/connection.c inn-2.4.3/innfeed/connection.c
--- t/inn-2.4.3/innfeed/connection.c	2006-03-20 05:14:57.000000000 +0100
+++ inn-2.4.3/innfeed/connection.c	2008-03-18 18:48:31.000000000 +0100
@@ -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,14 +474,17 @@
  */
 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) ;
 #ifdef HAVE_INET6
   char paddr[INET6_ADDRSTRLEN];
+  const struct sockaddr_in6 *bind_addr6 = hostBindAddr6 (cxn->myHost) ;
 #endif
+  int family = 0;
 
   ASSERT (cxn->myEp == NULL) ;
 
@@ -545,7 +507,14 @@
 
   cxn->state = cxnConnectingS ;
 
-  retAddr = hostIpAddr (cxn->myHost) ;
+#ifdef HAVE_INET6
+  if (bind_addr6)
+    family = AF_INET6;
+  else if (bind_addr)
+    family = AF_INET;
+#endif
+
+  retAddr = hostIpAddr (cxn->myHost, family) ;
 
   if (retAddr == NULL)
     {
diff -ruN t/inn-2.4.3/innfeed/host.c inn-2.4.3/innfeed/host.c
--- t/inn-2.4.3/innfeed/host.c	2006-03-20 05:14:57.000000000 +0100
+++ inn-2.4.3/innfeed/host.c	2008-03-18 18:47:01.000000000 +0100
@@ -81,6 +81,10 @@
 {
   char *peerName;
   char *ipName;
+  struct sockaddr_in *bindAddr;
+#ifdef HAVE_INET6
+  struct sockaddr_in6 *bindAddr6;
+#endif
   unsigned int articleTimeout;
   unsigned int responseTimeout;
   unsigned int initialConnections;
@@ -486,12 +490,30 @@
 	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->articleTimeout=ARTTOUT;
       params->responseTimeout=RESPTOUT;
       params->initialConnections=INIT_CXNS;
@@ -530,6 +552,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 +1133,7 @@
   return nh ;
 }
 
-struct sockaddr *hostIpAddr (Host host)
+struct sockaddr *hostIpAddr (Host host, int family)
 {
   int i ;
   struct sockaddr **newIpAddrPtrs = NULL;
@@ -1122,8 +1148,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 )
 
 	{
@@ -1275,6 +1304,20 @@
   
   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->bindAddr)
+    {
+      fprintf (fp,"%s    bindaddress : %s\n",indent,
+	inet_ntoa(host->params->bindAddr->sin_addr));
+    }
+#if HAVE_INET6
+  if (host->params->bindAddr6)
+    {
+      char buf[128];
+      fprintf (fp,"%s    bindaddress6 : %s\n",indent,
+	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 +2468,28 @@
 }
 
 /*
+ * 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 ;
+}
+#endif
+
+/*
  * get the username and password for authentication
  */
 const char *hostUsername (Host host)
@@ -2611,6 +2676,48 @@
 
     }
 
+#ifdef HAVE_INET6
+  if (getString(s,"bindaddress6",&q,isDefault?NO_INHERIT:INHERIT))
+    {
+      struct addrinfo *res, hints;
+
+      memset( &hints, 0, sizeof( hints ) );
+      hints.ai_flags = AI_NUMERICHOST;
+      if ( strcmp(q, "all") == 0 || strcmp(q, "any") == 0)
+	q = "::";
+      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 ;
+
+      if ( strcmp(q, "all") == 0 || strcmp(q, "any") == 0)
+	q = "0.0.0.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 t/inn-2.4.3/innfeed/host.h inn-2.4.3/innfeed/host.h
--- t/inn-2.4.3/innfeed/host.h	2006-03-20 05:14:57.000000000 +0100
+++ inn-2.4.3/innfeed/host.h	2008-03-18 17:58:22.000000000 +0100
@@ -85,7 +85,7 @@
 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) ;
 
 /* mark the current IP address as failed and rotate to the next one */
 void hostIpFailed (Host host) ;
@@ -150,6 +150,12 @@
 /* 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) ;
+#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