diff options
author | Mike Frysinger <vapier@gentoo.org> | 2006-01-06 04:57:40 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2006-01-06 04:57:40 +0000 |
commit | c47542925c44be2522adb442f268506dee9f34a7 (patch) | |
tree | bec955a1c15c5a41ca6c3a6fc3fc3c59f75e0f24 /libc/inet/if_index.c | |
parent | d2d573391d1cb10aa4f9ac4125741810354dd740 (diff) |
as weber notes in Bug 99:
if_nameindex doesnt list all of my interfaces!
this is because we are still using the old style ioctl(SIOCGIFINDEX) for
gathering interface names/indexes. while this code is pretty small, the
kernel does not return all interfaces via this method. so we import the
new style netlink code from glibc and make it optional so those people
who need the full functionality can get it.
Diffstat (limited to 'libc/inet/if_index.c')
-rw-r--r-- | libc/inet/if_index.c | 133 |
1 files changed, 131 insertions, 2 deletions
diff --git a/libc/inet/if_index.c b/libc/inet/if_index.c index dfddbc0d4..40e46d538 100644 --- a/libc/inet/if_index.c +++ b/libc/inet/if_index.c @@ -36,6 +36,8 @@ #include <sys/ioctl.h> #include <libc-internal.h> +#include "netlinkaccess.h" + extern int __opensock(void) attribute_hidden; unsigned int @@ -78,7 +80,9 @@ if_freenameindex (struct if_nameindex *ifn) } free (ifn); } +hidden_strong_alias(if_freenameindex,__if_freenameindex) +#if !__ASSUME_NETLINK_SUPPORT struct if_nameindex * if_nameindex (void) { @@ -157,6 +161,131 @@ if_nameindex (void) return idx; #endif } +#else +struct if_nameindex * +if_nameindex (void) +{ + unsigned int nifs = 0; + struct netlink_handle nh = { 0, 0, 0, NULL, NULL }; + struct if_nameindex *idx = NULL; + struct netlink_res *nlp; + + if (__netlink_open (&nh) < 0) + return NULL; + + + /* Tell the kernel that we wish to get a list of all + active interfaces. Collect all data for every interface. */ + if (__netlink_request (&nh, RTM_GETLINK) < 0) + goto exit_free; + + /* Count the interfaces. */ + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through all entries we got from the kernel and look, which + message type they contain. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + /* Check if the message is what we want. */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + ++nifs; + } + } + + idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); + if (idx == NULL) + { + nomem: + __set_errno (ENOBUFS); + goto exit_free; + } + + /* Add the interfaces. */ + nifs = 0; + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through all entries we got from the kernel and look, which + message type they contain. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + /* Check if the message is what we want. */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + { + struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh); + struct rtattr *rta = IFLA_RTA (ifim); + size_t rtasize = IFLA_PAYLOAD (nlh); + + idx[nifs].if_index = ifim->ifi_index; + + while (RTA_OK (rta, rtasize)) + { + char *rta_data = RTA_DATA (rta); + size_t rta_payload = RTA_PAYLOAD (rta); + + if (rta->rta_type == IFLA_IFNAME) + { + idx[nifs].if_name = __strndup (rta_data, rta_payload); + if (idx[nifs].if_name == NULL) + { + idx[nifs].if_index = 0; + __if_freenameindex (idx); + idx = NULL; + goto nomem; + } + break; + } + + rta = RTA_NEXT (rta, rtasize); + } + + ++nifs; + } + } + } + + idx[nifs].if_index = 0; + idx[nifs].if_name = NULL; + + exit_free: + __netlink_free_handle (&nh); + __netlink_close (&nh); + + return idx; +} +#endif +hidden_strong_alias(if_nameindex,__if_nameindex) + +#if 0 +struct if_nameindex * +if_nameindex (void) +{ + return (if_nameindex_netlink () != NULL ? : if_nameindex_ioctl ()); +} +#endif char * if_indextoname (unsigned int ifindex, char *ifname) @@ -194,7 +323,7 @@ if_indextoname (unsigned int ifindex, char *ifname) struct if_nameindex *p; char *result = NULL; - idx = if_nameindex(); + idx = __if_nameindex(); if (idx != NULL) { @@ -205,7 +334,7 @@ if_indextoname (unsigned int ifindex, char *ifname) break; } - if_freenameindex (idx); + __if_freenameindex (idx); if (result == NULL) __set_errno (ENXIO); |