diff options
Diffstat (limited to 'python-ethtool/etherinfo.c')
-rw-r--r-- | python-ethtool/etherinfo.c | 141 |
1 files changed, 59 insertions, 82 deletions
diff --git a/python-ethtool/etherinfo.c b/python-ethtool/etherinfo.c index 6075f30..7ae5798 100644 --- a/python-ethtool/etherinfo.c +++ b/python-ethtool/etherinfo.c @@ -24,14 +24,9 @@ #include <stdlib.h> #include <asm/types.h> #include <sys/socket.h> -#include <netlink/addr.h> -#include <netlink/netlink.h> -#include <netlink/handlers.h> -#include <netlink/route/link.h> -#include <netlink/route/addr.h> -#include <arpa/inet.h> #include <assert.h> #include <errno.h> +#include "etherinfo_struct.h" #include "etherinfo.h" /* @@ -39,20 +34,6 @@ * Internal functions for working with struct etherinfo * */ - -inline struct etherinfo *new_etherinfo_record() -{ - struct etherinfo *ptr; - - ptr = malloc(sizeof(struct etherinfo)+1); - if( ptr ) { - memset(ptr, 0, sizeof(struct etherinfo)+1); - } - - return ptr; -} - - void free_etherinfo(struct etherinfo *ptr) { if( ptr == NULL ) { // Just for safety @@ -82,6 +63,13 @@ void free_etherinfo(struct etherinfo *ptr) * */ +#define SET_STR_VALUE(dst, src) { \ + if( dst ) { \ + free(dst); \ + }; \ + dst = strdup(src); \ + } + static void callback_nl_link(struct nl_object *obj, void *arg) { struct etherinfo *ethi = (struct etherinfo *) arg; @@ -110,7 +98,7 @@ static void callback_nl_link(struct nl_object *obj, void *arg) ptr += 3; } } - ethi->hwaddress = strdup(hwaddr); + SET_STR_VALUE(ethi->hwaddress, hwaddr); } @@ -137,16 +125,16 @@ static void callback_nl_address(struct nl_object *obj, void *arg) struct nl_addr *brdcst = rtnl_addr_get_broadcast((struct rtnl_addr *)obj); char brdcst_str[66]; - ethi->ipv4_address = strdup(ip_str); + SET_STR_VALUE(ethi->ipv4_address, ip_str); ethi->ipv4_netmask = rtnl_addr_get_prefixlen((struct rtnl_addr*) obj); if( brdcst ) { memset(&brdcst_str, 0, 66); inet_ntop(family, nl_addr_get_binary_addr(brdcst), (char *)&brdcst_str, 64); - ethi->ipv4_broadcast = strdup(brdcst_str); + SET_STR_VALUE(ethi->ipv4_broadcast, brdcst_str); } } else { - ethi->ipv6_address = strdup(ip_str); + SET_STR_VALUE(ethi->ipv6_address, ip_str); ethi->ipv6_netmask = rtnl_addr_get_prefixlen((struct rtnl_addr*) obj); } return; @@ -186,70 +174,59 @@ void dump_etherinfo(FILE *fp, struct etherinfo *ptr) fprintf(fp, "\n"); } -struct etherinfo *get_etherinfo(const char *ifdevname) + +int get_etherinfo(struct etherinfo *ethinf, struct _nlconnection *nlc, nlQuery query) { - struct etherinfo *ethinf = NULL; - struct nl_handle *handle; struct nl_cache *link_cache; struct nl_cache *addr_cache; struct rtnl_addr *addr; struct rtnl_link *link; - int ifindex; - - /* Establish connection to NETLINK */ - handle = nl_handle_alloc(); - nl_connect(handle, NETLINK_ROUTE); - - /* Find the interface index we're looking up */ - link_cache = rtnl_link_alloc_cache(handle); - ifindex = rtnl_link_name2i(link_cache, ifdevname); - if( ifindex < 0 ) { - return NULL; - } - - /* Create an empty record, where ethernet information will be saved */ - ethinf = new_etherinfo_record(); - if( !ethinf ) { - return NULL; - } - ethinf->index = ifindex; - ethinf->device = strdup(ifdevname); /* Should extract via libnl - nl_link callback? */ - - /* Extract MAC/hardware address of the interface */ - link = rtnl_link_alloc(); - rtnl_link_set_ifindex(link, ifindex); - nl_cache_foreach_filter(link_cache, (struct nl_object *)link, callback_nl_link, ethinf); - rtnl_link_put(link); - nl_cache_free(link_cache); - - /* Extract IP address information */ - addr_cache = rtnl_addr_alloc_cache(handle); - addr = rtnl_addr_alloc(); - rtnl_addr_set_ifindex(addr, ifindex); - nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, callback_nl_address, ethinf); - rtnl_addr_put(addr); - nl_cache_free(addr_cache); - - /* Close NETLINK connection */ - nl_close(handle); - nl_handle_destroy(handle); - - return ethinf; -} + int ret = 0; -#ifdef TESTPROG -// Simple standalone test program -int main(int argc, char **argv) { - struct etherinfo *inf = NULL; - - inf = get_etherinfo(argv[1]); - if( inf == NULL ) { - fprintf(stderr, "Operation failed. Could not retrieve ethernet information\n"); - exit(2); + if( !ethinf || !nlc ) { + return 0; } - dump_etherinfo(stdout, inf); - free_etherinfo(inf); - return 0; + /* Find the interface index we're looking up. + * As we don't expect it to change, we're reusing a "cached" + * interface index if we have that + */ + if( ethinf->index < 0 ) { + link_cache = rtnl_link_alloc_cache(nlc->nlrt_handle); + ethinf->index = rtnl_link_name2i(link_cache, ethinf->device); + if( ethinf->index < 0 ) { + return 0; + } + nl_cache_free(link_cache); + } + + /* Query the for requested info vai NETLINK */ + switch( query ) { + case NLQRY_LINK: + /* Extract MAC/hardware address of the interface */ + link_cache = rtnl_link_alloc_cache(nlc->nlrt_handle); + link = rtnl_link_alloc(); + rtnl_link_set_ifindex(link, ethinf->index); + nl_cache_foreach_filter(link_cache, (struct nl_object *)link, callback_nl_link, ethinf); + rtnl_link_put(link); + nl_cache_free(link_cache); + ret = 1; + break; + + case NLQRY_ADDR: + /* Extract IP address information */ + addr_cache = rtnl_addr_alloc_cache(nlc->nlrt_handle); + addr = rtnl_addr_alloc(); + rtnl_addr_set_ifindex(addr, ethinf->index); + nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, callback_nl_address, ethinf); + rtnl_addr_put(addr); + nl_cache_free(addr_cache); + ret = 1; + break; + + default: + ret = 0; + } + return ret; } -#endif + |