diff options
author | Rich Felker <dalias@aerifal.cx> | 2011-08-03 12:13:13 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2011-08-03 12:13:13 -0400 |
commit | fc0ecd35d8e0041c81bbe08c10c7fcb946da85e0 (patch) | |
tree | e17efdc95dad3d34a3d070f25b328397a4d038b9 /src/network/if_nameindex.c | |
parent | 50304f2eefb4c79ceaf4605203f3825a35d831c0 (diff) | |
download | musl-fc0ecd35d8e0041c81bbe08c10c7fcb946da85e0.tar.gz |
implement if_nameindex and if_freenameindex
Diffstat (limited to 'src/network/if_nameindex.c')
-rw-r--r-- | src/network/if_nameindex.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/network/if_nameindex.c b/src/network/if_nameindex.c new file mode 100644 index 00000000..580acce0 --- /dev/null +++ b/src/network/if_nameindex.c @@ -0,0 +1,58 @@ +#define _GNU_SOURCE +#include <net/if.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <errno.h> +#include "syscall.h" + +#include <stdio.h> + +static void *do_nameindex(int s, size_t n) +{ + size_t i, len; + struct ifconf conf; + struct if_nameindex *idx; + + idx = malloc(n * (sizeof(struct if_nameindex)+sizeof(struct ifreq))); + if (!idx) return 0; + + conf.ifc_buf = (void *)&idx[n]; + conf.ifc_len = len = n * sizeof(struct ifreq); + if (ioctl(s, SIOCGIFCONF, &conf) < 0) { + free(idx); + return 0; + } + if (conf.ifc_len == len) { + free(idx); + return (void *)-1; + } + + n = conf.ifc_len / sizeof(struct ifreq); + for (i=0; i<n; i++) { + if (ioctl(s, SIOCGIFINDEX, &conf.ifc_req[i]) < 0) { + i--; + n--; + continue; + } + idx[i].if_index = conf.ifc_req[i].ifr_ifindex; + idx[i].if_name = conf.ifc_req[i].ifr_name; + } + idx[i].if_name = 0; + idx[i].if_index = 0; + + return idx; +} + +struct if_nameindex *if_nameindex() +{ + size_t n; + void *p = 0; + int s = socket(AF_UNIX, SOCK_DGRAM, 0); + if (s>=0) { + for (n=0; (p=do_nameindex(s, n)) == (void *)-1; n++); + __syscall(SYS_close, s); + } + errno = ENOBUFS; + return p; +} |