diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-07-08 22:29:54 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-07-08 22:29:54 +0000 |
commit | 2fd3cd638723c894b6ab7e224f4f5112a6ada1b2 (patch) | |
tree | f58f122190dd57b2450cc7fe17dedac77f3eb675 /lib/libc | |
parent | b84a5bf6fd39ea3ae215d4976236018f66d278c2 (diff) |
use SIOCGIFCONF much more carefully
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/net/if_indextoname.c | 48 | ||||
-rw-r--r-- | lib/libc/net/if_nameindex.c | 48 | ||||
-rw-r--r-- | lib/libc/net/if_nametoindex.c | 48 |
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; |