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
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 */
174175static int
175176append_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,
208208static 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}
0 commit comments