summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1999-07-08 22:29:54 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1999-07-08 22:29:54 +0000
commit2fd3cd638723c894b6ab7e224f4f5112a6ada1b2 (patch)
treef58f122190dd57b2450cc7fe17dedac77f3eb675 /lib/libc
parentb84a5bf6fd39ea3ae215d4976236018f66d278c2 (diff)
use SIOCGIFCONF much more carefully
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/net/if_indextoname.c48
-rw-r--r--lib/libc/net/if_nameindex.c48
-rw-r--r--lib/libc/net/if_nametoindex.c48
3 files changed, 102 insertions, 42 deletions
diff --git a/lib/libc/net/if_indextoname.c b/lib/libc/net/if_indextoname.c
index cca862de617..b05e82e9ff0 100644
--- a/lib/libc/net/if_indextoname.c
+++ b/lib/libc/net/if_indextoname.c
@@ -45,29 +45,48 @@ static char __name[IFNAMSIZ];
char *
if_indextoname(unsigned int index, char *name)
{
- int i, fd, len;
+ int i, fd = -1, extra, len = 0;
struct ifconf ifconf;
- char lastname[IFNAMSIZ], iname[IFNAMSIZ], *retname = NULL;
+ char lastname[IFNAMSIZ], iname[IFNAMSIZ], *retname = NULL, *inbuf;
struct sockaddr *sa;
void *p;
- if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
- return 0;
+ ifconf.ifc_buf = 0;
if (!name)
name = __name;
- ifconf.ifc_len = 0;
- ifconf.ifc_buf = 0;
- if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf))
- goto ret;
- if (ifconf.ifc_len < IFNAMSIZ)
- goto ret;
- if (!(ifconf.ifc_buf = malloc(ifconf.ifc_len)))
- goto ret;
- if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf))
+ if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
goto ret;
+ /*
+ * Try ifc_len == 0 hack first, to get the actual length.
+ * If that fails, revert to a loop which grows the ifc_buf
+ * until it is sufficiently large.
+ */
+ extra = sizeof(struct ifreq);
+ while (1) {
+ ifconf.ifc_len = len;
+ if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf) == -1 &&
+ ifconf.ifc_buf)
+ goto ret;
+ if (ifconf.ifc_buf &&
+ ifconf.ifc_len + extra < len)
+ break;
+ if (ifconf.ifc_buf) {
+ if (len == 0)
+ len = 4096;
+ ifconf.ifc_len = len *= 2;
+ } else {
+ len = ifconf.ifc_len;
+ extra = 0;
+ }
+ inbuf = realloc(ifconf.ifc_buf, ifconf.ifc_len);
+ if (inbuf == NULL)
+ goto ret;
+ ifconf.ifc_buf = inbuf;
+ }
+
i = 0;
p = ifconf.ifc_buf;
len = ifconf.ifc_len;
@@ -112,7 +131,8 @@ if_indextoname(unsigned int index, char *name)
retname = name;
}
ret:
- close(fd);
+ if (fd != -1)
+ close(fd);
if (ifconf.ifc_buf)
free(ifconf.ifc_buf);
return (retname);
diff --git a/lib/libc/net/if_nameindex.c b/lib/libc/net/if_nameindex.c
index 8714c1f95a1..8643397db27 100644
--- a/lib/libc/net/if_nameindex.c
+++ b/lib/libc/net/if_nameindex.c
@@ -43,29 +43,48 @@
struct if_nameindex *
if_nameindex(void)
{
- int i, j, fd, len;
+ int i, j, fd = -1, extra, len = 0;
struct if_nameindex *nameindex = NULL;
struct ifconf ifconf;
- char lastname[IFNAMSIZ], *c;
+ char lastname[IFNAMSIZ], *c, *inbuf;
struct if_nameindex *n;
struct sockaddr_dl *sd;
struct sockaddr *sa;
void *p;
- if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
- return NULL;
+ ifconf.ifc_buf = NULL;
- ifconf.ifc_len = 0;
- ifconf.ifc_buf = 0;
- if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf))
- goto ret;
- if (ifconf.ifc_len < IFNAMSIZ)
- goto ret;
- if (!(ifconf.ifc_buf = malloc(ifconf.ifc_len)))
- goto ret;
- if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf))
+ if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
goto ret;
+ /*
+ * Try ifc_len == 0 hack first, to get the actual length.
+ * If that fails, revert to a loop which grows the ifc_buf
+ * until it is sufficiently large.
+ */
+ extra = sizeof(struct ifreq);
+ while (1) {
+ ifconf.ifc_len = len;
+ if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf) == -1 &&
+ ifconf.ifc_buf)
+ goto ret;
+ if (ifconf.ifc_buf &&
+ ifconf.ifc_len + extra < len)
+ break;
+ if (ifconf.ifc_buf) {
+ if (len == 0)
+ len = 4096;
+ ifconf.ifc_len = len *= 2;
+ } else {
+ len = ifconf.ifc_len;
+ extra = 0;
+ }
+ inbuf = realloc(ifconf.ifc_buf, ifconf.ifc_len);
+ if (inbuf == NULL)
+ goto ret;
+ ifconf.ifc_buf = inbuf;
+ }
+
i = sizeof(struct if_nameindex);
j = 0;
p = ifconf.ifc_buf;
@@ -138,7 +157,8 @@ if_nameindex(void)
n->if_index = i;
ret:
- close(fd);
+ if (fd != -1)
+ close(fd);
if (ifconf.ifc_buf)
free(ifconf.ifc_buf);
return (nameindex);
diff --git a/lib/libc/net/if_nametoindex.c b/lib/libc/net/if_nametoindex.c
index 0318f606808..d41f8ecad11 100644
--- a/lib/libc/net/if_nametoindex.c
+++ b/lib/libc/net/if_nametoindex.c
@@ -43,27 +43,46 @@
unsigned int
if_nametoindex(const char *name)
{
- int i, fd, len;
+ int i, fd = -1, extra, len = 0;
struct ifconf ifconf;
- char lastname[IFNAMSIZ], *thisname;
+ char lastname[IFNAMSIZ], *thisname, *inbuf;
unsigned int index = 0;
struct sockaddr *sa;
void *p;
- if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
- return 0;
-
- ifconf.ifc_len = 0;
ifconf.ifc_buf = 0;
- if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf))
- goto ret;
- if (ifconf.ifc_len < IFNAMSIZ)
- goto ret;
- if (!(ifconf.ifc_buf = malloc(ifconf.ifc_len)))
- goto ret;
- if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf))
+
+ if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
goto ret;
+ /*
+ * Try ifc_len == 0 hack first, to get the actual length.
+ * If that fails, revert to a loop which grows the ifc_buf
+ * until it is sufficiently large.
+ */
+ extra = sizeof(struct ifreq);
+ while (1) {
+ ifconf.ifc_len = len;
+ if (ioctl(fd, SIOCGIFCONF, (void *) &ifconf) == -1 &&
+ ifconf.ifc_buf)
+ goto ret;
+ if (ifconf.ifc_buf &&
+ ifconf.ifc_len + extra < len)
+ break;
+ if (ifconf.ifc_buf) {
+ if (len == 0)
+ len = 4096;
+ ifconf.ifc_len = len *= 2;
+ } else {
+ len = ifconf.ifc_len;
+ extra = 0;
+ }
+ inbuf = realloc(ifconf.ifc_buf, ifconf.ifc_len);
+ if (inbuf == NULL)
+ goto ret;
+ ifconf.ifc_buf = inbuf;
+ }
+
i = 0;
p = ifconf.ifc_buf;
len = ifconf.ifc_len;
@@ -106,7 +125,8 @@ if_nametoindex(const char *name)
index = i;
ret:
- close(fd);
+ if (fd != -1)
+ close(fd);
if (ifconf.ifc_buf)
free(ifconf.ifc_buf);
return index;