Blame SOURCES/net-snmp-5.8-ipAddress-faster-load.patch

bc6b3f
diff -urNp a/agent/mibgroup/mibII/ipAddr.c b/agent/mibgroup/mibII/ipAddr.c
bc6b3f
--- a/agent/mibgroup/mibII/ipAddr.c	2020-06-10 14:14:30.113696471 +0200
bc6b3f
+++ b/agent/mibgroup/mibII/ipAddr.c	2020-06-10 14:27:15.345354018 +0200
bc6b3f
@@ -495,14 +495,16 @@ Address_Scan_Next(Index, Retin_ifaddr)
bc6b3f
 }
bc6b3f
 
bc6b3f
 #elif defined(linux)
bc6b3f
+#include <errno.h>
bc6b3f
 static struct ifreq *ifr;
bc6b3f
 static int ifr_counter;
bc6b3f
 
bc6b3f
 static void
bc6b3f
 Address_Scan_Init(void)
bc6b3f
 {
bc6b3f
-    int num_interfaces = 0;
bc6b3f
+    int i;
bc6b3f
     int fd;
bc6b3f
+    int lastlen = 0;
bc6b3f
 
bc6b3f
     /* get info about all interfaces */
bc6b3f
 
bc6b3f
@@ -510,28 +512,45 @@ Address_Scan_Init(void)
bc6b3f
     SNMP_FREE(ifc.ifc_buf);
bc6b3f
     ifr_counter = 0;
bc6b3f
 
bc6b3f
-    do
bc6b3f
-    {
bc6b3f
 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
bc6b3f
 	{
bc6b3f
 	    DEBUGMSGTL(("snmpd", "socket open failure in Address_Scan_Init\n"));
bc6b3f
 	    return;
bc6b3f
 	}
bc6b3f
-	num_interfaces += 16;
bc6b3f
 
bc6b3f
-	ifc.ifc_len = sizeof(struct ifreq) * num_interfaces;
bc6b3f
-	ifc.ifc_buf = (char*) realloc(ifc.ifc_buf, ifc.ifc_len);
bc6b3f
-	
bc6b3f
-	    if (ioctl(fd, SIOCGIFCONF, &ifc) < 0)
bc6b3f
-	    {
bc6b3f
-		ifr=NULL;
bc6b3f
-		close(fd);
bc6b3f
-	   	return;
bc6b3f
-	    }
bc6b3f
-	    close(fd);
bc6b3f
+    /*
bc6b3f
+     * Cope with lots of interfaces and brokenness of ioctl SIOCGIFCONF
bc6b3f
+     * on some platforms; see W. R. Stevens, ``Unix Network Programming
bc6b3f
+     * Volume I'', p.435...
bc6b3f
+     */
bc6b3f
+
bc6b3f
+    for (i = 8;; i *= 2) {
bc6b3f
+        ifc.ifc_len = sizeof(struct ifreq) * i;
bc6b3f
+        ifc.ifc_req = calloc(i, sizeof(struct ifreq));
bc6b3f
+
bc6b3f
+        if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
bc6b3f
+            if (errno != EINVAL || lastlen != 0) {
bc6b3f
+                /*
bc6b3f
+                 * Something has gone genuinely wrong...
bc6b3f
+                 */
bc6b3f
+                snmp_log(LOG_ERR, "bad rc from ioctl, errno %d", errno);
bc6b3f
+                SNMP_FREE(ifc.ifc_buf);
bc6b3f
+                close(fd);
bc6b3f
+                return;
bc6b3f
+            }
bc6b3f
+        } else {
bc6b3f
+            if (ifc.ifc_len == lastlen) {
bc6b3f
+                /*
bc6b3f
+                 * The length is the same as the last time; we're done...
bc6b3f
+                 */
bc6b3f
+                break;
bc6b3f
+            }
bc6b3f
+            lastlen = ifc.ifc_len;
bc6b3f
+        }
bc6b3f
+        free(ifc.ifc_buf); /* no SNMP_FREE, getting ready to reassign */
bc6b3f
     }
bc6b3f
-    while (ifc.ifc_len >= (sizeof(struct ifreq) * num_interfaces));
bc6b3f
-    
bc6b3f
+
bc6b3f
+    close(fd);
bc6b3f
     ifr = ifc.ifc_req;
bc6b3f
 }
bc6b3f