summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <davids@redhat.com>2010-04-26 20:38:57 +0200
committerDavid Sommerseth <davids@redhat.com>2010-04-26 20:38:57 +0200
commitd3fd6b84f461a4d7ffbf3f3eae37381150b69e82 (patch)
tree4de791e5b791b50fe42056443b6dbfae2c3a29f1
parentbfdcac6b16806416a6c0295fcfad5d820595d88c (diff)
downloadpython-ethtool-d3fd6b84f461a4d7ffbf3f3eae37381150b69e82.tar.gz
python-ethtool-d3fd6b84f461a4d7ffbf3f3eae37381150b69e82.tar.xz
python-ethtool-d3fd6b84f461a4d7ffbf3f3eae37381150b69e82.zip
Rewritten ethtool to make use of libnl instead of accessing NETLINK directly
-rw-r--r--python-ethtool/etherinfo.c510
-rw-r--r--python-ethtool/etherinfo.h4
-rw-r--r--python-ethtool/ethtool.c52
-rw-r--r--setup.py54
4 files changed, 186 insertions, 434 deletions
diff --git a/python-ethtool/etherinfo.c b/python-ethtool/etherinfo.c
index f06b448..6075f30 100644
--- a/python-ethtool/etherinfo.c
+++ b/python-ethtool/etherinfo.c
@@ -24,23 +24,16 @@
#include <stdlib.h>
#include <asm/types.h>
#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/if_arp.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.h"
-#define GET_LINK 1
-#define GET_IPV4 2
-#define GET_IPV6 4
-
-struct nl_request {
- struct nlmsghdr nlmsg_info;
- struct ifaddrmsg ifaddrmsg_info;
-};
-
/*
*
* Internal functions for working with struct etherinfo
@@ -60,54 +53,17 @@ inline struct etherinfo *new_etherinfo_record()
}
-#define SET_STRVALUE(ptr, val) if ( (ptr == NULL) && (val != NULL) ) ptr = val;
-
-int update_etherinfo(struct etherinfo *ipadrchain, int index, int af_type,
- char *ipadr, int ipmask, char *ipv4brd)
-{
- struct etherinfo *ptr = NULL;
-
- // Look up the record we will update
- for( ptr = ipadrchain; ptr != NULL; ptr = ptr->next) {
- if( ptr->index == index ) {
- break;
- }
- }
- if( ptr == NULL ) {
- PyErr_SetString(PyExc_RuntimeError,
- "Could not locate interface record");
- return 0;
- }
-
- switch( af_type ) {
- case AF_INET:
- SET_STRVALUE(ptr->ipv4_address, ipadr);
- ptr->ipv4_netmask = ipmask;
- SET_STRVALUE(ptr->ipv4_broadcast, ipv4brd);
- break;
- case AF_INET6:
- SET_STRVALUE(ptr->ipv6_address, ipadr);
- ptr->ipv6_netmask = ipmask;
- break;
- }
- return 1;
-}
-
-
void free_etherinfo(struct etherinfo *ptr)
{
if( ptr == NULL ) { // Just for safety
return;
}
- if( ptr->next != NULL ) {
- free_etherinfo(ptr->next);
- }
free(ptr->device);
- if( ptr->hwaddress ) {
- free(ptr->hwaddress);
- }
+ if( ptr->hwaddress ) {
+ free(ptr->hwaddress);
+ }
if( ptr->ipv4_address ) {
free(ptr->ipv4_address);
}
@@ -122,401 +78,171 @@ void free_etherinfo(struct etherinfo *ptr)
/*
- *
- * NETLINK specific functions
+ * libnl callback functions
*
*/
-int open_netlink_socket(struct sockaddr_nl *local)
+static void callback_nl_link(struct nl_object *obj, void *arg)
{
- int fd;
-
- assert( local != NULL && local->nl_family == AF_NETLINK );
-
- fd = socket(local->nl_family, SOCK_RAW, NETLINK_ROUTE);
- if(fd < 0) {
- PyErr_SetString(PyExc_OSError, strerror(errno));
- return -1;
+ struct etherinfo *ethi = (struct etherinfo *) arg;
+ struct rtnl_link *link = (struct rtnl_link *) obj;
+ struct nl_addr *addr = rtnl_link_get_addr(link);
+ unsigned int i, len;
+ unsigned char *binaddr;
+ char hwaddr[130], *ptr;
+
+ if( (ethi == NULL) || (ethi->hwaddress != NULL) ) {
+ return;
}
- if(bind(fd, (struct sockaddr*) local, sizeof(*local)) < 0) {
- PyErr_SetString(PyExc_OSError, strerror(errno));
- return -1;
+ binaddr = nl_addr_get_binary_addr(addr);
+ memset(&hwaddr, 0, 130);
+ len = 20;
+ ptr = (char *)&hwaddr;
+ for( i = 0; i < 6; i++ ) {
+ if( i == 0 ) {
+ snprintf(ptr, len, "%02X", *(binaddr+i));
+ len -= 2;
+ ptr += 2;
+ } else {
+ snprintf(ptr, len, ":%02X", *(binaddr+i));
+ len -= 3;
+ ptr += 3;
+ }
}
-
- return fd;
+ ethi->hwaddress = strdup(hwaddr);
}
-int send_netlink_query(int fd, int get_type)
+static void callback_nl_address(struct nl_object *obj, void *arg)
{
- struct sockaddr_nl peer;
- struct msghdr msg_info;
- struct nl_request netlink_req;
- struct iovec iov_info;
-
- memset(&peer, 0, sizeof(peer));
- peer.nl_family = AF_NETLINK;
- peer.nl_pad = 0;
- peer.nl_pid = 0;
- peer.nl_groups = 0;
-
- memset(&msg_info, 0, sizeof(msg_info));
- msg_info.msg_name = (void *) &peer;
- msg_info.msg_namelen = sizeof(peer);
-
- memset(&netlink_req, 0, sizeof(netlink_req));
- netlink_req.nlmsg_info.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- netlink_req.nlmsg_info.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- netlink_req.nlmsg_info.nlmsg_pid = getpid();
-
- // Set the information we want to query for
- netlink_req.nlmsg_info.nlmsg_type = (get_type == GET_LINK ? RTM_GETLINK : RTM_GETADDR);
- netlink_req.ifaddrmsg_info.ifa_family = (get_type == GET_IPV6 ? AF_INET6 : AF_INET);
-
- iov_info.iov_base = (void *) &netlink_req.nlmsg_info;
- iov_info.iov_len = netlink_req.nlmsg_info.nlmsg_len;
- msg_info.msg_iov = &iov_info;
- msg_info.msg_iovlen = 1;
-
- if( sendmsg(fd, &msg_info, 0) < 0 ) {
- PyErr_SetString(PyExc_OSError, strerror(errno));
- return 0;
- }
- return 1;
-}
+ struct etherinfo *ethi = (struct etherinfo *) arg;
+ struct nl_addr *addr;
+ char ip_str[66];
+ int family;
+ if( ethi == NULL ) {
+ return;
+ }
-int read_netlink_results(int fd, struct sockaddr_nl *local,
- int (*callback)(struct nlmsghdr *, struct etherinfo *, struct etherinfo **idxptr),
- struct etherinfo *ethinf)
-{
- struct etherinfo *process_ethinfo_idxptr = NULL; // Int. index ptr for callback function
- struct sockaddr_nl nladdr;
- struct iovec iov;
- struct msghdr msg;
- char buf[16384];
-
- memset(&nladdr, 0, sizeof(nladdr));
- memset(&iov, 0, sizeof(iov));
- memset(&msg, 0, sizeof(msg));
- memset(&buf, 0, sizeof(buf));
-
- msg.msg_name = &nladdr;
- msg.msg_namelen = sizeof(nladdr);
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- iov.iov_base = buf;
- while (1) {
- int status;
- struct nlmsghdr *h;
-
- iov.iov_len = sizeof(buf);
- status = recvmsg(fd, &msg, 0);
-
- if (status < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- PyErr_SetString(PyExc_OSError, strerror(errno));
- return 0;
- }
-
- if (status == 0) {
- PyErr_SetString(PyExc_RuntimeError, "EOF on netlink");
- return 0;
- }
+ addr = rtnl_addr_get_local((struct rtnl_addr *)obj);
+ family = nl_addr_get_family(addr);
+ switch( family ) {
+ case AF_INET:
+ case AF_INET6:
+ memset(&ip_str, 0, 66);
+ inet_ntop(family, nl_addr_get_binary_addr(addr), (char *)&ip_str, 64);
- h = (struct nlmsghdr *)buf;
- while (NLMSG_OK(h, status)) {
- if (nladdr.nl_pid != 0 ||
- h->nlmsg_pid != local->nl_pid ) {
- goto skip_data;
- }
+ if( family == AF_INET ) {
+ struct nl_addr *brdcst = rtnl_addr_get_broadcast((struct rtnl_addr *)obj);
+ char brdcst_str[66];
- if (h->nlmsg_type == NLMSG_DONE) {
- return 1;
- }
+ ethi->ipv4_address = strdup(ip_str);
+ ethi->ipv4_netmask = rtnl_addr_get_prefixlen((struct rtnl_addr*) obj);
- if (h->nlmsg_type == NLMSG_ERROR) {
- struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
-
- if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
- PyErr_SetString(PyExc_RuntimeError,
- "Error message truncated\n");
- } else {
- errno = -err->error;
- PyErr_SetString(PyExc_OSError, strerror(errno));
- }
- return 0;
- }
- // Process/decode data
- if( !callback(h, ethinf, &process_ethinfo_idxptr) ) {
- // Error already set in callback
- return 0;
+ 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);
}
- skip_data:
- h = NLMSG_NEXT(h, status);
- }
-
- if (msg.msg_flags & MSG_TRUNC) {
- PyErr_SetString(PyExc_RuntimeError, "Message truncated\n");
- continue;
- }
- if (status) {
- PyErr_SetString(PyExc_RuntimeError, "Not all data available was processed");
- return 0;
+ } else {
+ ethi->ipv6_address = strdup(ip_str);
+ ethi->ipv6_netmask = rtnl_addr_get_prefixlen((struct rtnl_addr*) obj);
}
+ return;
+ default:
+ return;
}
}
+
/*
*
- * Internal functions for processing NETLINK_ROUTE results
+ * Exported functions - API frontend
*
*/
-/* ll_addr_n2a - stolen from iproute2 source */
-const char *ll_addr_n2a(unsigned char *addr, int alen, int type, char *buf, int blen)
+void dump_etherinfo(FILE *fp, struct etherinfo *ptr)
{
- int i;
- int l;
- if (alen == 4 &&
- (type == ARPHRD_TUNNEL || type == ARPHRD_SIT || type == ARPHRD_IPGRE)) {
- return inet_ntop(AF_INET, addr, buf, blen);
+ fprintf(fp, "*** Interface [%i] %s ", ptr->index, ptr->device);
+ if( ptr->hwaddress ) {
+ fprintf(fp, "MAC address: %s", ptr->hwaddress);
}
- if (alen == 16 && type == ARPHRD_TUNNEL6) {
- return inet_ntop(AF_INET6, addr, buf, blen);
- }
- l = 0;
- for (i=0; i<alen; i++) {
- if (i==0) {
- snprintf(buf+l, blen, "%02x", addr[i]);
- blen -= 2;
- l += 2;
- } else {
- snprintf(buf+l, blen, ":%02x", addr[i]);
- blen -= 3;
- l += 3;
- }
- }
- return buf;
-
-}
-
-
-// Callback function for processing RTM_GETLINK results
-int etherinfo_proc_getlink(struct nlmsghdr *msg, struct etherinfo *ethinfchain, struct etherinfo **idxptr)
-{
- int len = 0;
- struct ifinfomsg *ifinfo = NLMSG_DATA(msg);
- struct rtattr *rta = NULL;
-
- assert( ethinfchain != NULL );
-
- rta = IFLA_RTA(ifinfo);
- len = IFLA_PAYLOAD(msg);
-
- // Set the index pointer to the record we will update/register
- *idxptr = ((*idxptr) == NULL ? ethinfchain : (*idxptr)->next);
- if( (*idxptr)->next == NULL ) {
- // Append new record if we hit the end of the chain
- (*idxptr)->next = new_etherinfo_record();
- if( *idxptr == NULL ) {
- PyErr_SetString(PyExc_RuntimeError,
- "Could not allocate memory to another interface");
- return 0;
- }
- }
-
- // Store information
- (*idxptr)->index = ifinfo->ifi_index;
- (*idxptr)->type = ifinfo->ifi_type;
- while( RTA_OK(rta, len) ) {
- switch( rta->rta_type ) {
- case IFLA_IFNAME:
- (*idxptr)->device = strdup((char *)RTA_DATA(rta));
- if( !(*idxptr)->device ) {
- PyErr_SetString(PyExc_RuntimeError,
- "Could not allocate memory for interface name");
- return 0;
- }
- break;
-
- case IFLA_ADDRESS:
- (*idxptr)->hwaddress = (char *)malloc(258);
- if( !(*idxptr)->hwaddress ) {
- PyErr_SetString(PyExc_RuntimeError,
- "Could not allocate memory for hardware address");
- return 0;
- }
- memset((*idxptr)->hwaddress, 0, 258);
- ll_addr_n2a(RTA_DATA(rta), RTA_PAYLOAD(rta), ifinfo->ifi_type,
- (*idxptr)->hwaddress, 256);
- break;
- default:
- break;
+ fprintf(fp, "\n");
+ if( ptr->ipv4_address ) {
+ fprintf(fp, "\tIPv4 Address: %s/%i",
+ ptr->ipv4_address, ptr->ipv4_netmask);
+ if( ptr->ipv4_broadcast ) {
+ fprintf(fp, " - Broadcast: %s", ptr->ipv4_broadcast);
}
-
- rta = RTA_NEXT(rta, len);
+ fprintf(fp, "\n");
}
- return 1;
-}
-
-// Callback function for processing RTM_GETADDR results
-int etherinfo_proc_getaddr(struct nlmsghdr *msg, struct etherinfo *ethinfchain, struct etherinfo **idxptr)
-{
- int len = 0;
- struct ifaddrmsg *ifaddr = NLMSG_DATA(msg);
- struct rtattr *rta = NULL;
- char *ifa_addr = NULL, *ifa_brd = NULL;
- int ifa_netmask = 0;
-
- assert( ethinfchain != NULL );
-
- rta = IFA_RTA(ifaddr);
- len = IFA_PAYLOAD(msg);
-
- // Copy interesting information to our buffers
- while( RTA_OK(rta, len) ) {
- switch( rta->rta_type ) {
- case IFA_ADDRESS: // IP address + netmask
- ifa_addr = (char *) malloc(130);
- if( !ifa_addr ) {
- PyErr_SetString(PyExc_RuntimeError,
- "Could not allocate memory for IP address");
- return 0;
- }
- memset(ifa_addr, 0, 130);
- inet_ntop(ifaddr->ifa_family, RTA_DATA(rta), ifa_addr, 128);
- ifa_netmask = ifaddr->ifa_prefixlen;
- break;
-
- case IFA_BROADCAST:
- ifa_brd = (char *) malloc(130);
- if( !ifa_brd ) {
- PyErr_SetString(PyExc_RuntimeError,
- "Could not allocate memory for broadcase address");
- return 0;
- }
- memset(ifa_brd, 0, 130);
- inet_ntop(ifaddr->ifa_family, RTA_DATA(rta), ifa_brd, 128);
- break;
-
- default:
- break;
- }
- rta = RTA_NEXT(rta, len);
+ if( ptr->ipv6_address ) {
+ fprintf(fp, "\tIPv6 address: %s/%i\n",
+ ptr->ipv6_address, ptr->ipv6_netmask);
}
-
- // Update the corresponding etherinfo record
- return update_etherinfo(ethinfchain, ifaddr->ifa_index, ifaddr->ifa_family,
- ifa_addr, ifa_netmask, ifa_brd);
+ fprintf(fp, "\n");
}
-
-/*
- *
- * Exported functions - API frontend
- *
- */
-
-void dump_etherinfo(FILE *fp, struct etherinfo *ethinfo)
+struct etherinfo *get_etherinfo(const char *ifdevname)
{
- struct etherinfo *ptr;
-
- for( ptr = ethinfo; ptr->next != NULL; ptr = ptr->next ) {
- if( (ptr->type != ARPHRD_ETHER) && (ptr->type != ARPHRD_LOOPBACK) ) {
- continue;
- }
- fprintf(fp, "*** Interface [%i] %s ", ptr->index, ptr->device);
- if( ptr->hwaddress ) {
- fprintf(fp, "MAC address: %s", ptr->hwaddress);
- }
- fprintf(fp, "\n");
- if( ptr->ipv4_address ) {
- fprintf(fp, "\tIPv4 Address: %s/%i",
- ptr->ipv4_address, ptr->ipv4_netmask);
- if( ptr->ipv4_broadcast ) {
- fprintf(fp, " - Broadcast: %s", ptr->ipv4_broadcast);
- }
- fprintf(fp, "\n");
- }
- if( ptr->ipv6_address ) {
- fprintf(fp, "\tIPv6 address: %s/%i\n",
- ptr->ipv6_address, ptr->ipv6_netmask);
- }
- fprintf(fp, "\n");
- }
-}
-
-struct etherinfo *get_etherinfo()
-{
- int fd;
- struct sockaddr_nl local;
struct etherinfo *ethinf = NULL;
-
- // open NETLINK socket
- memset(&local, 0, sizeof(local));
- local.nl_family = AF_NETLINK;
- local.nl_pad = 0;
- local.nl_pid = getpid();
- local.nl_groups = 0;
- fd = open_netlink_socket(&local);
- if( fd < 0 ) {
+ 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
+ /* 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? */
- // Get some hardware info - ifname, type and hwaddress. Populates ethinf
- if( !send_netlink_query(fd, GET_LINK) ) {
- goto error;
- }
- if( !read_netlink_results(fd, &local, etherinfo_proc_getlink, ethinf) ) {
- goto error;
- }
-
+ /* 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);
- // IPv4 information - updates the interfaces found in ethinfo
- if( !send_netlink_query(fd, GET_IPV4) ) {
- goto error;
- }
- if( !read_netlink_results(fd, &local, etherinfo_proc_getaddr, ethinf) ) {
- goto error;
- }
-
-
- // IPv6 information - updates the interfaces found in ethinfo
- if( !send_netlink_query(fd, GET_IPV6) ) {
- goto error;
- }
- if( !read_netlink_results(fd, &local, etherinfo_proc_getaddr, ethinf) ) {
- goto error;
- }
- goto exit;
+ /* 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);
- error:
- free_etherinfo(ethinf);
- ethinf = NULL;
+ /* Close NETLINK connection */
+ nl_close(handle);
+ nl_handle_destroy(handle);
- exit:
- close(fd);
return ethinf;
}
#ifdef TESTPROG
// Simple standalone test program
-int main() {
+int main(int argc, char **argv) {
struct etherinfo *inf = NULL;
- inf = get_etherinfo();
+ inf = get_etherinfo(argv[1]);
if( inf == NULL ) {
fprintf(stderr, "Operation failed. Could not retrieve ethernet information\n");
exit(2);
diff --git a/python-ethtool/etherinfo.h b/python-ethtool/etherinfo.h
index 996bd45..bda5185 100644
--- a/python-ethtool/etherinfo.h
+++ b/python-ethtool/etherinfo.h
@@ -18,8 +18,7 @@
#define _ETHERINFO_H
struct etherinfo {
- int index;
- int type;
+ int index;
char *device;
char *hwaddress;
char *ipv4_address;
@@ -27,7 +26,6 @@ struct etherinfo {
char *ipv4_broadcast;
char *ipv6_address;
int ipv6_netmask;
- struct etherinfo *next;
};
struct etherinfo *get_etherinfo();
diff --git a/python-ethtool/ethtool.c b/python-ethtool/ethtool.c
index 8d67844..d84bc79 100644
--- a/python-ethtool/ethtool.c
+++ b/python-ethtool/ethtool.c
@@ -233,9 +233,9 @@ static PyObject *get_ipaddress(PyObject *self __unused, PyObject *args)
static PyObject *get_interface_info(PyObject *self __unused, PyObject *args) {
PyObject *devlist = NULL, *ethinf_py = NULL;
PyObject *inargs = NULL;
- struct etherinfo *devinfo = NULL, *ptr = NULL;
+ struct etherinfo *devinfo = NULL;
char **fetch_devs;
- int fetch_devs_len = 0;
+ int i = 0, fetch_devs_len = 0;
if (!PyArg_ParseTuple(args, "|O", &inargs)) {
PyErr_SetString(PyExc_LookupError,
@@ -250,7 +250,7 @@ static PyObject *get_interface_info(PyObject *self __unused, PyObject *args) {
fetch_devs = calloc(1, sizeof(char *));
fetch_devs[0] = PyString_AsString(inargs);
} else if( PyTuple_Check(inargs) ) { /* Input argument is a tuple list with devices */
- int i, j = 0;
+ int j = 0;
fetch_devs_len = PyTuple_Size(inargs);
fetch_devs = calloc(fetch_devs_len+1, sizeof(char *));
@@ -262,7 +262,7 @@ static PyObject *get_interface_info(PyObject *self __unused, PyObject *args) {
}
fetch_devs_len = j;
} else if( PyList_Check(inargs) ) { /* Input argument is a list with devices */
- int i, j = 0;
+ int j = 0;
fetch_devs_len = PyList_Size(inargs);
fetch_devs = calloc(fetch_devs_len+1, sizeof(char *));
@@ -279,35 +279,15 @@ static PyObject *get_interface_info(PyObject *self __unused, PyObject *args) {
return NULL;
}
}
- devinfo = get_etherinfo();
- if( !devinfo ) {
- PyErr_SetString(PyExc_OSError, strerror(errno));
- return NULL;
- }
- /* Slice up the etherinfo struct and populate individual objects with
- * the current ethernet information.
- */
- devlist = PyList_New(0);
- while( devinfo->next != NULL ) {
- /* Get copy of pointers, before we start slicing it up */
- ptr = devinfo->next; /* Fetch the pointer to the next element first */
- devinfo->next = NULL; /* Make the current slice do not point anywhere else */
-
- /* Skip this device only if we have a list of devices and the current one */
- /* does not match */
- if( fetch_devs_len > 0) {
- int i;
- for( i = 0; i < fetch_devs_len; i++ ) {
- if( fetch_devs[i] && (strcmp(fetch_devs[i], devinfo->device) == 0) ) {
- goto found_dev; /* Add this device to the devlist */
- }
- }
- /* Free the info which we don't need, and continue */
- free_etherinfo(devinfo);
- goto next_dev;
+
+ for( i = 0; i < fetch_devs_len; i++ ) {
+ devinfo = get_etherinfo(fetch_devs[i]);
+ if( !devinfo ) {
+ PyErr_SetString(PyExc_OSError, strerror(errno));
+ return NULL;
}
- found_dev:
+
/* Instantiate a new etherinfo object with the device information */
ethinf_py = PyCObject_FromVoidPtr(devinfo, NULL);
if( ethinf_py ) {
@@ -319,14 +299,10 @@ static PyObject *get_interface_info(PyObject *self __unused, PyObject *args) {
PyObject *dev = PyObject_CallObject((PyObject *)&ethtool_etherinfoType, args);
PyList_Append(devlist, dev);
}
- next_dev:
- devinfo = ptr; /* Go to the next element */
- }
- /* clean up headers which might not be used or considered interesting */
- if( devinfo != NULL ) {
- free_etherinfo(devinfo);
+ if( devinfo != NULL ) {
+ free_etherinfo(devinfo);
+ }
}
-
if( fetch_devs_len > 0 ) {
free(fetch_devs);
}
diff --git a/setup.py b/setup.py
index 3098123..aed2186 100644
--- a/setup.py
+++ b/setup.py
@@ -1,11 +1,51 @@
#!/usr/bin/python2
from distutils.core import setup, Extension
+import commands
ethtool = Extension('ethtool',
sources = ['python-ethtool/ethtool.c',
'python-ethtool/etherinfo.c', 'python-ethtool/etherinfo_obj.c'])
+def pkgconfig(pkg):
+ def _str2list(pkgstr, onlystr):
+ res = []
+ for l in pkgstr.split(" "):
+ if l.find(onlystr) == 0:
+ res.append(l.replace(onlystr, "", 1))
+ return res
+
+ (res, cflags) = commands.getstatusoutput('pkg-config --cflags-only-other %s' % pkg)
+ if res != 0:
+ print 'Failed to query pkg-config --cflags-only-other %s' % pkg
+ sys.exit(1)
+
+ (res, includes) = commands.getstatusoutput('pkg-config --cflags-only-I %s' % pkg)
+ if res != 0:
+ print 'Failed to query pkg-config --cflags-only-I %s' % pkg
+ sys.exit(1)
+
+ (res, libs) = commands.getstatusoutput('pkg-config --libs-only-l %s' % pkg)
+ if res != 0:
+ print 'Failed to query pkg-config --libs-only-l %s' % pkg
+ sys.exit(1)
+
+ (res, libdirs) = commands.getstatusoutput('pkg-config --libs-only-L %s' % pkg)
+ if res != 0:
+ print 'Failed to query pkg-config --libs-only-L %s' % pkg
+ sys.exit(1)
+
+
+ # Clean up the results and return what we've extracted from pkg-config
+ return {'cflags': cflags,
+ 'include': _str2list(includes, '-I'),
+ 'libs': _str2list(libs, '-l'),
+ 'libdirs': _str2list(libdirs, '-L')
+ }
+
+
+libnl = pkgconfig('libnl-1')
+
# don't reformat this line, Makefile parses it
setup(name='ethtool',
version='0.2',
@@ -13,4 +53,16 @@ setup(name='ethtool',
author='Harald Hoyer & Arnaldo Carvalho de Melo',
author_email='acme@redhat.com',
url='http://fedoraproject.org/wiki/python-ethtool',
- ext_modules=[ethtool])
+ ext_modules=[
+ Extension(
+ 'ethtool',
+ sources = [
+ 'python-ethtool/ethtool.c',
+ 'python-ethtool/etherinfo.c',
+ 'python-ethtool/etherinfo_obj.c'],
+ include_dirs = libnl['include'],
+ library_dirs = libnl['libdirs'],
+ libraries = libnl['libs']
+ )
+ ]
+)