Skip to content

Commit d9922c0

Browse files
author
David Sommerseth
committed
Migrated from libnl-1 to libnl-3
This ports the current functionality from libnl-1 to libnl-3.0. At the current stage, it should be functional but more patches cleaning up the code will come. Signed-off-by: David Sommerseth <davids@redhat.com>
1 parent c61363e commit d9922c0

File tree

6 files changed

+71
-82
lines changed

6 files changed

+71
-82
lines changed

python-ethtool/etherinfo.c

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* etherinfo.c - Retrieve ethernet interface info via NETLINK
22
*
3-
* Copyright (C) 2009-2011 Red Hat Inc.
3+
* Copyright (C) 2009-2013 Red Hat Inc.
44
*
55
* David Sommerseth <davids@redhat.com>
66
* Parts of this code is based on ideas and solutions in iproute2
@@ -25,6 +25,13 @@
2525
#include <stdlib.h>
2626
#include <asm/types.h>
2727
#include <sys/socket.h>
28+
#include <arpa/inet.h>
29+
#include <netlink/netlink.h>
30+
#include <netlink/socket.h>
31+
#include <netlink/cache.h>
32+
#include <netlink/addr.h>
33+
#include <netlink/route/addr.h>
34+
#include <netlink/route/link.h>
2835
#include <netlink/route/rtnl.h>
2936
#include <assert.h>
3037
#include <errno.h>
@@ -111,19 +118,29 @@ void free_etherinfo(struct etherinfo *ptr)
111118
*
112119
* @return Returns a new pointer to the chain containing the new element
113120
*/
114-
struct ipv6address * etherinfo_add_ipv6(struct ipv6address *addrptr, const char *addr, int netmask, int scope) {
121+
struct ipv6address * etherinfo_add_ipv6(struct ipv6address *addrptr, struct rtnl_addr *addr) {
115122
struct ipv6address *newaddr = NULL;
123+
char buf[INET6_ADDRSTRLEN+2];
124+
int af_family;
125+
126+
af_family = rtnl_addr_get_family(addr);
127+
if( af_family != AF_INET && af_family != AF_INET6 ) {
128+
return addrptr;
129+
}
130+
131+
memset(&buf, 0, sizeof(buf));
132+
inet_ntop(af_family, nl_addr_get_binary_addr(rtnl_addr_get_local(addr)), buf, sizeof(buf));
116133

117134
newaddr = calloc(1, sizeof(struct ipv6address)+2);
118135
if( !newaddr ) {
119136
fprintf(stderr, "** ERROR ** Could not allocate memory for a new IPv6 address record (%s/%i [%i])",
120-
addr, netmask, scope);
137+
buf, rtnl_addr_get_prefixlen(addr), rtnl_addr_get_scope(addr));
121138
return addrptr;
122139
}
123140

124-
SET_STR_VALUE(newaddr->address, addr);
125-
newaddr->netmask = netmask;
126-
newaddr->scope = scope;
141+
SET_STR_VALUE(newaddr->address, buf);
142+
newaddr->netmask = rtnl_addr_get_prefixlen(addr);
143+
newaddr->scope = rtnl_addr_get_scope(addr);
127144
newaddr->next = addrptr;
128145
return newaddr;
129146
}
@@ -140,30 +157,14 @@ static void callback_nl_link(struct nl_object *obj, void *arg)
140157
{
141158
struct etherinfo *ethi = (struct etherinfo *) arg;
142159
struct rtnl_link *link = (struct rtnl_link *) obj;
143-
struct nl_addr *addr = rtnl_link_get_addr(link);
144-
unsigned int i, len;
145-
unsigned char *binaddr;
146-
char hwaddr[130], *ptr;
160+
char hwaddr[130];
147161

148-
if( (ethi == NULL) || (ethi->hwaddress != NULL) || (addr == NULL) ) {
162+
if( (ethi == NULL) || (ethi->hwaddress != NULL) ) {
149163
return;
150164
}
151165

152-
binaddr = nl_addr_get_binary_addr(addr);
153166
memset(&hwaddr, 0, 130);
154-
len = 20;
155-
ptr = (char *)&hwaddr;
156-
for( i = 0; i < 6; i++ ) {
157-
if( i == 0 ) {
158-
snprintf(ptr, len, "%02X", *(binaddr+i));
159-
len -= 2;
160-
ptr += 2;
161-
} else {
162-
snprintf(ptr, len, ":%02X", *(binaddr+i));
163-
len -= 3;
164-
ptr += 3;
165-
}
166-
}
167+
nl_addr2str(rtnl_link_get_addr(link), hwaddr, sizeof(hwaddr));
167168
SET_STR_VALUE(ethi->hwaddress, hwaddr);
168169
}
169170

@@ -173,7 +174,6 @@ static void callback_nl_link(struct nl_object *obj, void *arg)
173174
*/
174175
static int
175176
append_object_for_netlink_address(struct etherinfo *ethi,
176-
struct nl_object *obj,
177177
struct rtnl_addr *addr)
178178
{
179179
PyObject *addr_obj;
@@ -182,7 +182,7 @@ append_object_for_netlink_address(struct etherinfo *ethi,
182182
assert(ethi->ipv4_addresses);
183183
assert(addr);
184184

185-
addr_obj = make_python_address_from_rtnl_addr(obj, addr);
185+
addr_obj = make_python_address_from_rtnl_addr(addr);
186186
if (!addr_obj) {
187187
return -1;
188188
}
@@ -208,30 +208,18 @@ append_object_for_netlink_address(struct etherinfo *ethi,
208208
static void callback_nl_address(struct nl_object *obj, void *arg)
209209
{
210210
struct etherinfo *ethi = (struct etherinfo *) arg;
211-
struct nl_addr *addr;
212-
char ip_str[66];
213-
int family;
211+
struct rtnl_addr *rtaddr = (struct rtnl_addr *) obj;
214212

215213
if( ethi == NULL ) {
216214
return;
217215
}
218216

219-
addr = rtnl_addr_get_local((struct rtnl_addr *)obj);
220-
family = nl_addr_get_family(addr);
221-
switch( family ) {
217+
switch( rtnl_addr_get_family(rtaddr) ) {
222218
case AF_INET:
219+
append_object_for_netlink_address(ethi, rtaddr);
220+
return;
223221
case AF_INET6:
224-
memset(&ip_str, 0, 66);
225-
inet_ntop(family, nl_addr_get_binary_addr(addr), (char *)&ip_str, 64);
226-
227-
if( family == AF_INET ) {
228-
(void)append_object_for_netlink_address(ethi, obj, (struct rtnl_addr*) addr);
229-
} else {
230-
ethi->ipv6_addresses = etherinfo_add_ipv6(ethi->ipv6_addresses,
231-
ip_str,
232-
rtnl_addr_get_prefixlen((struct rtnl_addr*) obj),
233-
rtnl_addr_get_scope((struct rtnl_addr*) obj));
234-
}
222+
ethi->ipv6_addresses = etherinfo_add_ipv6(ethi->ipv6_addresses, rtaddr);
235223
return;
236224
default:
237225
return;
@@ -326,8 +314,16 @@ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query)
326314
* interface index if we have that
327315
*/
328316
if( ethinf->index < 0 ) {
329-
link_cache = rtnl_link_alloc_cache(*data->nlc);
330-
ethinf->index = rtnl_link_name2i(link_cache, ethinf->device);
317+
if( rtnl_link_alloc_cache(*data->nlc, AF_UNSPEC, &link_cache) < 0) {
318+
return 0;
319+
}
320+
321+
link = rtnl_link_get_by_name(link_cache, ethinf->device);
322+
if( !link ) {
323+
return 0;
324+
}
325+
326+
ethinf->index = rtnl_link_get_ifindex(link);
331327
if( ethinf->index < 0 ) {
332328
return 0;
333329
}
@@ -338,18 +334,22 @@ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query)
338334
switch( query ) {
339335
case NLQRY_LINK:
340336
/* Extract MAC/hardware address of the interface */
341-
link_cache = rtnl_link_alloc_cache(*data->nlc);
337+
if( rtnl_link_alloc_cache(*data->nlc, AF_UNSPEC, &link_cache) < 0) {
338+
return 0;
339+
}
342340
link = rtnl_link_alloc();
343341
rtnl_link_set_ifindex(link, ethinf->index);
344-
nl_cache_foreach_filter(link_cache, (struct nl_object *)link, callback_nl_link, ethinf);
342+
nl_cache_foreach_filter(link_cache, OBJ_CAST(link), callback_nl_link, ethinf);
345343
rtnl_link_put(link);
346344
nl_cache_free(link_cache);
347345
ret = 1;
348346
break;
349347

350348
case NLQRY_ADDR:
351349
/* Extract IP address information */
352-
addr_cache = rtnl_addr_alloc_cache(*data->nlc);
350+
if( rtnl_addr_alloc_cache(*data->nlc, &addr_cache) < 0) {
351+
return 0;
352+
}
353353
addr = rtnl_addr_alloc();
354354
rtnl_addr_set_ifindex(addr, ethinf->index);
355355

@@ -367,7 +367,7 @@ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query)
367367
}
368368

369369
/* Retrieve all address information */
370-
nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, callback_nl_address, ethinf);
370+
nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), callback_nl_address, ethinf);
371371
rtnl_addr_put(addr);
372372
nl_cache_free(addr_cache);
373373
ret = 1;
@@ -408,7 +408,7 @@ int open_netlink(struct etherinfo_obj_data *data)
408408
}
409409

410410
/* No earlier connections exists, establish a new one */
411-
*data->nlc = nl_handle_alloc();
411+
*data->nlc = nl_socket_alloc();
412412
nl_connect(*data->nlc, NETLINK_ROUTE);
413413
if( (*data->nlc != NULL) ) {
414414
/* Force O_CLOEXEC flag on the NETLINK socket */
@@ -455,6 +455,6 @@ void close_netlink(struct etherinfo_obj_data *data)
455455

456456
/* Close NETLINK connection */
457457
nl_close(*data->nlc);
458-
nl_handle_destroy(*data->nlc);
458+
nl_socket_free(*data->nlc);
459459
*data->nlc = NULL;
460460
}

python-ethtool/etherinfo.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,6 @@
1717
#ifndef _ETHERINFO_H
1818
#define _ETHERINFO_H
1919

20-
#include <netlink/addr.h>
21-
#include <netlink/netlink.h>
22-
#include <netlink/handlers.h>
23-
#include <netlink/route/link.h>
24-
#include <netlink/route/addr.h>
25-
#include <arpa/inet.h>
26-
2720
typedef enum {NLQRY_LINK, NLQRY_ADDR} nlQuery; /**< Supported query types in the etherinfo code */
2821

2922
int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query);

python-ethtool/etherinfo_struct.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2009-2011 Red Hat Inc.
2+
* Copyright (C) 2009-2013 Red Hat Inc.
33
*
44
* David Sommerseth <davids@redhat.com>
55
*
@@ -13,7 +13,6 @@
1313
* General Public License for more details.
1414
*/
1515

16-
#include <netlink/route/addr.h>
1716

1817
/**
1918
* @file etherinfo_struct.h
@@ -66,7 +65,7 @@ struct ipv6address {
6665
*
6766
*/
6867
struct etherinfo_obj_data {
69-
struct nl_handle **nlc; /**< Contains NETLINK connection info (global) */
68+
struct nl_sock **nlc; /**< Contains NETLINK connection info (global) */
7069
unsigned int *nlc_users; /**< Resource counter for the NETLINK connection (global) */
7170
unsigned short nlc_active; /**< Is this instance using NETLINK? */
7271
struct etherinfo *ethinfo; /**< Contains info about our current interface */
@@ -99,9 +98,7 @@ typedef struct {
9998
*/
10099
#define RETURN_STRING(str) (str ? PyString_FromString(str) : (Py_INCREF(Py_None), Py_None))
101100

102-
PyObject *
103-
make_python_address_from_rtnl_addr(struct nl_object *obj,
104-
struct rtnl_addr *addr);
101+
PyObject * make_python_address_from_rtnl_addr(struct rtnl_addr *addr);
105102

106103

107104
#endif

python-ethtool/ethtool.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2008-2011 Red Hat Inc.
2+
* Copyright (C) 2008-2013 Red Hat Inc.
33
*
44
* Arnaldo Carvalho de Melo <acme@redhat.com>
55
* David Sommerseth <davids@redhat.com>
@@ -22,17 +22,17 @@
2222
#include <stdint.h>
2323
#include <unistd.h>
2424
#include <sys/socket.h>
25-
#include <net/if.h>
2625
#include <sys/socket.h>
2726
#include <sys/ioctl.h>
2827
#include <sys/types.h>
2928
#include <ifaddrs.h>
29+
#include <netlink/route/addr.h>
3030

3131
#include "etherinfo_struct.h"
3232
#include "etherinfo_obj.h"
3333
#include "etherinfo.h"
3434

35-
static struct nl_handle *nlconnection = NULL;
35+
static struct nl_sock *nlconnection = NULL;
3636
unsigned int nlconnection_users = 0; /* How many NETLINK users are active? */
3737
extern PyTypeObject ethtool_etherinfoType;
3838
extern PyTypeObject ethtool_etherinfoIPv6Type;

python-ethtool/netlink-address.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
#include <Python.h>
1818
#include "structmember.h"
1919

20-
#include <netlink/route/rtnl.h>
20+
#include <arpa/inet.h>
21+
#include <netlink/addr.h>
22+
#include <netlink/route/addr.h>
2123
#include "etherinfo_struct.h"
2224
#include "etherinfo.h"
2325

2426
/* IPv4 Addresses: */
2527
static PyObject *
26-
PyNetlinkIPv4Address_from_rtnl_addr(struct nl_object *nl_obj, struct rtnl_addr *addr)
28+
PyNetlinkIPv4Address_from_rtnl_addr(struct rtnl_addr *addr)
2729
{
2830
PyNetlinkIPv4Address *py_obj;
2931
char buf[INET_ADDRSTRLEN+1];
@@ -37,7 +39,7 @@ PyNetlinkIPv4Address_from_rtnl_addr(struct nl_object *nl_obj, struct rtnl_addr *
3739

3840
/* Set ipv4_address: */
3941
memset(&buf, 0, sizeof(buf));
40-
if (!inet_ntop(AF_INET, nl_addr_get_binary_addr((struct nl_addr *)addr),
42+
if (!inet_ntop(AF_INET, nl_addr_get_binary_addr(rtnl_addr_get_local(addr)),
4143
buf, sizeof(buf))) {
4244
PyErr_SetFromErrno(PyExc_RuntimeError);
4345
goto error;
@@ -48,11 +50,11 @@ PyNetlinkIPv4Address_from_rtnl_addr(struct nl_object *nl_obj, struct rtnl_addr *
4850
}
4951

5052
/* Set ipv4_netmask: */
51-
py_obj->ipv4_netmask = rtnl_addr_get_prefixlen((struct rtnl_addr*)nl_obj);
53+
py_obj->ipv4_netmask = rtnl_addr_get_prefixlen(addr);
5254

5355
/* Set ipv4_broadcast: */
5456
py_obj->ipv4_broadcast = NULL;
55-
brdcst = rtnl_addr_get_broadcast((struct rtnl_addr*)nl_obj);
57+
brdcst = rtnl_addr_get_broadcast(addr);
5658
if( brdcst ) {
5759
memset(&buf, 0, sizeof(buf));
5860
if (!inet_ntop(AF_INET, nl_addr_get_binary_addr(brdcst),
@@ -132,18 +134,14 @@ PyTypeObject ethtool_netlink_ipv4_address_Type = {
132134

133135
/* Factory function, in case we want to generalize this to add IPv6 support */
134136
PyObject *
135-
make_python_address_from_rtnl_addr(struct nl_object *obj,
136-
struct rtnl_addr *addr)
137+
make_python_address_from_rtnl_addr(struct rtnl_addr *addr)
137138
{
138-
int family;
139139
assert(addr);
140140

141-
family = nl_addr_get_family((struct nl_addr *)addr);
142-
143-
switch( family ) {
141+
switch( rtnl_addr_get_family(addr) ) {
144142

145143
case AF_INET:
146-
return PyNetlinkIPv4Address_from_rtnl_addr(obj, addr);
144+
return PyNetlinkIPv4Address_from_rtnl_addr(addr);
147145

148146
/*
149147
For now, we just support IPv4 addresses.

setup.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import commands
55
import sys
66

7-
version = '0.8'
7+
version = '0.9'
88

99
def pkgconfig(pkg):
1010
def _str2list(pkgstr, onlystr):
@@ -43,7 +43,8 @@ def _str2list(pkgstr, onlystr):
4343
}
4444

4545

46-
libnl = pkgconfig('libnl-1')
46+
libnl = pkgconfig('libnl-3.0')
47+
libnl['libs'].append('nl-route-3')
4748

4849
# don't reformat this line, Makefile parses it
4950
setup(name='ethtool',

0 commit comments

Comments
 (0)