From c47542925c44be2522adb442f268506dee9f34a7 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 6 Jan 2006 04:57:40 +0000 Subject: 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. --- libc/inet/if_index.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 2 deletions(-) (limited to 'libc/inet/if_index.c') 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 #include +#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); -- cgit v1.2.3