[Openswan dev] dynamically allocate number of interfaces

Michael Richardson mcr at xelerance.com
Thu Aug 10 11:18:13 CEST 2006


Here's a patch to fix plutos use of SIOCGIFCONF for when the buffer size
cannot hold all the interfaces configured on a system.  Not sure what
the actual limit is,  but it fails on a system with 2000+

This patch is against #public (which has moved the function to
sysdep_*.c), and remembers how many interfaces it tried last time.
Everytime you do "--listen", it has to re-list the interfaces.

This is against OpenSwan 2.4.6,  but should apply to most versions I suspect,

Signed-off-by: David McCullough <david.mccullough at securecomputing.com>
Signed-off-by: Michael Richardson <mcr at xelerance.com>

---

14d777fe6b2aca49dcdf5e7d30463ffb90fa2b2d
 programs/pluto/sysdep_bsd.c   |   39 ++++++++++++++++++++++++++++-----------
 programs/pluto/sysdep_linux.c |   37 +++++++++++++++++++++++++++----------
 2 files changed, 55 insertions(+), 21 deletions(-)

14d777fe6b2aca49dcdf5e7d30463ffb90fa2b2d
diff --git a/programs/pluto/sysdep_bsd.c b/programs/pluto/sysdep_bsd.c
index b86347a..4af81df 100644
--- a/programs/pluto/sysdep_bsd.c
+++ b/programs/pluto/sysdep_bsd.c
@@ -197,9 +197,10 @@ struct raw_iface *
 find_raw_ifaces4(void)
 {
     static const int on = TRUE;	/* by-reference parameter; constant, we hope */
-    int j;	/* index into buf */
+    int j;	                /* index into buf */
+    static int num=64;          /* number of interfaces */
     struct ifconf ifconf;
-    struct ifreq buf[300];	/* for list of interfaces -- arbitrary limit */
+    struct ifreq *buf;	     /* for list of interfaces -- arbitrary limit */
     struct raw_iface *rifaces = NULL;
     int master_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);    /* Get a UDP socket */
 
@@ -222,16 +223,32 @@ find_raw_ifaces4(void)
 	    exit_log_errno((e, "bind() failed in find_raw_ifaces4()"));
     }
 
-    /* Get local interfaces.  See netdevice(7). */
-    ifconf.ifc_len = sizeof(buf);
-    ifconf.ifc_buf = (void *) buf;
-    zero(buf);
-
-    if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
-	exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
-
+    buf = NULL;
+   
+    /* a million interfaces is probably the maximum, ever... */
+    while(num < (1024*1024)) {
+	    /* Get local interfaces.  See netdevice(7). */
+	    ifconf.ifc_len = num * sizeof(struct ifreq);
+	    buf = (void *) realloc(buf, ifconf.ifc_len);
+	    if (!buf)
+		    exit_log_errno((e, "realloc of %d in find_raw_ifaces4()",
+				    ifconf.ifc_len));
+	    memset(buf, 0, num*sizeof(struct ifreq));
+	    ifconf.ifc_buf = (void *) buf;
+	    
+	    if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
+		    exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
+	    
+	    /* if we got back less than we asked for, we have them all */
+	    if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num))
+		    break;
+	    
+	    /* try again and ask for more this time */
+	    num *= 2;
+    }
+  
     /* Add an entry to rifaces for each interesting interface. */
-    for (j = 0; (j+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; j++)
+    for (j = 0; (j+1) * sizeof(struct ifreq) <= (size_t)ifconf.ifc_len; j++)
     {
 	struct raw_iface ri;
 	const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr;
diff --git a/programs/pluto/sysdep_linux.c b/programs/pluto/sysdep_linux.c
index f0f82ad..36a78cf 100644
--- a/programs/pluto/sysdep_linux.c
+++ b/programs/pluto/sysdep_linux.c
@@ -196,8 +196,9 @@ find_raw_ifaces4(void)
 {
     static const int on = TRUE;	/* by-reference parameter; constant, we hope */
     int j;	/* index into buf */
+    static int    num=64;    /* number of interfaces */
     struct ifconf ifconf;
-    struct ifreq buf[300];	/* for list of interfaces -- arbitrary limit */
+    struct ifreq *buf;	     /* for list of interfaces -- arbitrary limit */
     struct raw_iface *rifaces = NULL;
     int master_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);    /* Get a UDP socket */
 
@@ -220,16 +221,32 @@ find_raw_ifaces4(void)
 	    exit_log_errno((e, "bind() failed in find_raw_ifaces4()"));
     }
 
-    /* Get local interfaces.  See netdevice(7). */
-    ifconf.ifc_len = sizeof(buf);
-    ifconf.ifc_buf = (void *) buf;
-    zero(buf);
-
-    if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
-	exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
-
+    buf = NULL;
+   
+    /* a million interfaces is probably the maximum, ever... */
+    while(num < (1024*1024)) {
+	    /* Get local interfaces.  See netdevice(7). */
+	    ifconf.ifc_len = num * sizeof(struct ifreq);
+	    buf = (void *) realloc(buf, ifconf.ifc_len);
+	    if (!buf)
+		    exit_log_errno((e, "realloc of %d in find_raw_ifaces4()",
+				    ifconf.ifc_len));
+	    memset(buf, 0, num*sizeof(struct ifreq));
+	    ifconf.ifc_buf = (void *) buf;
+	    
+	    if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1)
+		    exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()"));
+	    
+	    /* if we got back less than we asked for, we have them all */
+	    if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num))
+		    break;
+	    
+	    /* try again and ask for more this time */
+	    num *= 2;
+    }
+  
     /* Add an entry to rifaces for each interesting interface. */
-    for (j = 0; (j+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; j++)
+    for (j = 0; (j+1) * sizeof(struct ifreq) <= (size_t)ifconf.ifc_len; j++)
     {
 	struct raw_iface ri;
 	const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr;
-- 
1.3.GIT

commit-id 14d777fe6b2aca49dcdf5e7d30463ffb90fa2b2d

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 480 bytes
Desc: not available
Url : http://lists.openswan.org/pipermail/dev/attachments/20060810/9406f70b/attachment.bin


More information about the Dev mailing list