Old build: SourceRpm(name='python-ethtool', version='0.7', release='4.fc19.src.rpm', buildarch='x86_64')

New build: SourceRpm(name='python-ethtool', version='0.8', release='0.dc309d6b2781dc3810021d2e4e2d669f40227b63.fc17.src.rpm', buildarch='x86_64')

Old file New file clang-analyzer gcc cppcheck cpychecker Notes
python-ethtool-0.7/python-ethtool/etherinfo.c python-ethtool-dc309d6b2781dc3810021d2e4e2d669f40227b63/python-ethtool/etherinfo.c 0 / 0 0 / 0 0 / 0 0 / 0 Incomplete coverage: old has 1 analysis failure(s), new has 2 analysis failure(s)
python-ethtool-0.7/python-ethtool/etherinfo_ipv6_obj.c python-ethtool-dc309d6b2781dc3810021d2e4e2d669f40227b63/python-ethtool/etherinfo_ipv6_obj.c 0 / 0 0 / 0 0 / 0 0 / 0 Incomplete coverage: old has 1 analysis failure(s), new has 1 analysis failure(s)
python-ethtool-0.7/python-ethtool/etherinfo_obj.c python-ethtool-dc309d6b2781dc3810021d2e4e2d669f40227b63/python-ethtool/etherinfo_obj.c 0 / 0 0 / 0 0 / 0 5 / 4 Incomplete coverage: old has 2 analysis failure(s), new has 2 analysis failure(s)
python-ethtool-0.7/python-ethtool/ethtool.c python-ethtool-dc309d6b2781dc3810021d2e4e2d669f40227b63/python-ethtool/ethtool.c 2 / 2 1 / 1 6 / 1 29 / 18 Incomplete coverage: old has 3 analysis failure(s), new has 3 analysis failure(s)
python-ethtool-dc309d6b2781dc3810021d2e4e2d669f40227b63/python-ethtool/netlink-address.c 0 / 0 0 / 0 0 / 0 0 / 0 Incomplete coverage: old has 0 analysis failure(s), new has 1 analysis failure(s)

Comparison of old/new python-ethtool/etherinfo.c

New failures

Incomplete coverage

Tool Location Function stdout stderr returncode
cpychecker python-ethtool/etherinfo.c:256:1 dump_etherinfo None this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed None

Failures in both old/new

Tool Old location New location Function stdout stderr returncode
cpychecker python-ethtool/etherinfo.c:282:1 python-ethtool/etherinfo.c:303:1 get_etherinfo None this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed None
  1 /* etherinfo.c - Retrieve ethernet interface info via NETLINK
  1 /* etherinfo.c - Retrieve ethernet interface info via NETLINK
  2  *
  2  *
  3  * Copyright (C) 2009-2011 Red Hat Inc.
  3  * Copyright (C) 2009-2011 Red Hat Inc.
  4  *
  4  *
  5  * David Sommerseth <davids@redhat.com>
  5  * David Sommerseth <davids@redhat.com>
  6  * Parts of this code is based on ideas and solutions in iproute2
  6  * Parts of this code is based on ideas and solutions in iproute2
  7  *
  7  *
  8  * This application is free software; you can redistribute it and/or modify it
  8  * This application is free software; you can redistribute it and/or modify it
  9  * under the terms of the GNU General Public License as published by the Free
  9  * under the terms of the GNU General Public License as published by the Free
 10  * Software Foundation; version 2.
 10  * Software Foundation; version 2.
 11  *
 11  *
 12  * This application is distributed in the hope that it will be useful,
 12  * This application is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * General Public License for more details.
 15  * General Public License for more details.
 16  */
 16  */
 17 
 17 
 18 #include <Python.h>
 18 #include <Python.h>
 19 #include <bits/sockaddr.h>
 19 #include <bits/sockaddr.h>
 20 #include <stdio.h>
 20 #include <stdio.h>
 21 #include <string.h>
 21 #include <string.h>
 22 #include <sys/types.h>
 22 #include <sys/types.h>
 23 #include <unistd.h>
 23 #include <unistd.h>
 24 #include <fcntl.h>
 24 #include <fcntl.h>
 25 #include <stdlib.h>
 25 #include <stdlib.h>
 26 #include <asm/types.h>
 26 #include <asm/types.h>
 27 #include <sys/socket.h>
 27 #include <sys/socket.h>
 28 #include <netlink/route/rtnl.h>
 28 #include <netlink/route/rtnl.h>
 29 #include <assert.h>
 29 #include <assert.h>
 30 #include <errno.h>
 30 #include <errno.h>
 31 #include <pthread.h>
 31 #include <pthread.h>
 32 #include "etherinfo_struct.h"
 32 #include "etherinfo_struct.h"
 33 #include "etherinfo.h"
 33 #include "etherinfo.h"
 34 
 34 
 35 pthread_mutex_t nlc_counter_mtx = PTHREAD_MUTEX_INITIALIZER;
 35 pthread_mutex_t nlc_counter_mtx = PTHREAD_MUTEX_INITIALIZER;
 36 
 36 
 37 /*
 37 /*
 38  *
 38  *
 39  *   Internal functions for working with struct etherinfo
 39  *   Internal functions for working with struct etherinfo
 40  *
 40  *
 41  */
 41  */
 42 
 42 
 43 /**
 43 /**
 44  * Simple macro which makes sure the destination string is freed if used earlier.
 44  * Simple macro which makes sure the destination string is freed if used earlier.
 45  *
 45  *
 46  * @param dst Destination pointer
 46  * @param dst Destination pointer
 47  * @param src Source pointer
 47  * @param src Source pointer
 48  *
 48  *
 49  */
 49  */
 50 #define SET_STR_VALUE(dst, src) {	 \
 50 #define SET_STR_VALUE(dst, src) {	 \
 51 	if( dst ) {		 \
 51 	if( dst ) {		 \
 52 		free(dst);	 \
 52 		free(dst);	 \
 53 	};			 \
 53 	};			 \
 54 	dst = strdup(src);	 \
 54 	dst = strdup(src);	 \
 55 	}
 55 	}
 56 
 56 
 57 
 57 
 58 /**
 58 /**
 59  * Frees the memory used by a struct ipv6address pointer chain.  All elements are freed
 59  * Frees the memory used by a struct ipv6address pointer chain.  All elements are freed
 60  *
 60  *
 61  * @param ptr  Pointer to a struct ipv6address chain.
 61  * @param ptr  Pointer to a struct ipv6address chain.
 62  */
 62  */
 63 void free_ipv6addresses(struct ipv6address *ptr) {
 63 void free_ipv6addresses(struct ipv6address *ptr) {
 64 	struct ipv6address *ipv6ptr = ptr;
 64 	struct ipv6address *ipv6ptr = ptr;
 65 
 65 
 66 	while( ipv6ptr ) {
 66 	while( ipv6ptr ) {
 67 		struct ipv6address *tmp = ipv6ptr->next;
 67 		struct ipv6address *tmp = ipv6ptr->next;
 68 
 68 
 69 		if( ipv6ptr->address ) {
 69 		if( ipv6ptr->address ) {
 70 			free(ipv6ptr->address);
 70 			free(ipv6ptr->address);
 71 			ipv6ptr->address = NULL;
 71 			ipv6ptr->address = NULL;
 72 		}
 72 		}
 73 		memset(ipv6ptr, 0, sizeof(struct ipv6address));
 73 		memset(ipv6ptr, 0, sizeof(struct ipv6address));
 74 		free(ipv6ptr);
 74 		free(ipv6ptr);
 75 		ipv6ptr = tmp;
 75 		ipv6ptr = tmp;
 76 	}
 76 	}
 77 }
 77 }
 78 
 78 
 79 /**
 79 /**
 80  * Frees the memory used by struct etherinfo, including all struct ipv6address children.
 80  * Frees the memory used by struct etherinfo, including all struct ipv6address children.
 81  *
 81  *
 82  * @param ptr Pointer to a struct etherninfo element
 82  * @param ptr Pointer to a struct etherninfo element
 83  */
 83  */
 84 void free_etherinfo(struct etherinfo *ptr)
 84 void free_etherinfo(struct etherinfo *ptr)
 85 {
 85 {
 86 	if( ptr == NULL ) { // Just for safety
 86 	if( ptr == NULL ) { // Just for safety
 87 		return;
 87 		return;
 88 	}
 88 	}
 89 
 89 
 90 	free(ptr->device);
 90 	free(ptr->device);
 91 
 91 
 92 	if( ptr->hwaddress ) {
 92 	if( ptr->hwaddress ) {
 93 		free(ptr->hwaddress);
 93 		free(ptr->hwaddress);
 94 	}
 94 	}
 95 	if( ptr->ipv4_address ) {
 95 	Py_XDECREF(ptr->ipv4_addresses);
 96 		free(ptr->ipv4_address);
 96 
 97 	}
 98 	if( ptr->ipv4_broadcast ) {
 99 		free(ptr->ipv4_broadcast);
100 	}
101 	if( ptr->ipv6_addresses ) {
 97 	if( ptr->ipv6_addresses ) {
102 		free_ipv6addresses(ptr->ipv6_addresses);
 98 		free_ipv6addresses(ptr->ipv6_addresses);
103 	}
 99 	}
104 	free(ptr);
100 	free(ptr);
105 }
101 }
106 
102 
107 
103 
108 /**
104 /**
109  * Add a new IPv6 address record to a struct ipv6address chain
105  * Add a new IPv6 address record to a struct ipv6address chain
110  *
106  *
111  * @param addrptr    Pointer to the current IPv6 address chain.
107  * @param addrptr    Pointer to the current IPv6 address chain.
112  * @param addr       IPv6 address, represented as char * string
108  * @param addr       IPv6 address, represented as char * string
113  * @param netmask    IPv6 netmask, as returned by libnl rtnl_addr_get_prefixlen()
109  * @param netmask    IPv6 netmask, as returned by libnl rtnl_addr_get_prefixlen()
114  * @param scope      IPV6 address scope, as returned by libnl rtnl_addr_get_scope()
110  * @param scope      IPV6 address scope, as returned by libnl rtnl_addr_get_scope()
115  *
111  *
116  * @return Returns a new pointer to the chain containing the new element
112  * @return Returns a new pointer to the chain containing the new element
117  */
113  */
118 struct ipv6address * etherinfo_add_ipv6(struct ipv6address *addrptr, const char *addr, int netmask, int scope) {
114 struct ipv6address * etherinfo_add_ipv6(struct ipv6address *addrptr, const char *addr, int netmask, int scope) {
119 	struct ipv6address *newaddr = NULL;
115 	struct ipv6address *newaddr = NULL;
120 
116 
121 	newaddr = calloc(1, sizeof(struct ipv6address)+2);
117 	newaddr = calloc(1, sizeof(struct ipv6address)+2);
122 	if( !newaddr ) {
118 	if( !newaddr ) {
123 		fprintf(stderr, "** ERROR ** Could not allocate memory for a new IPv6 address record (%s/%i [%i])",
119 		fprintf(stderr, "** ERROR ** Could not allocate memory for a new IPv6 address record (%s/%i [%i])",
124 			addr, netmask, scope);
120 			addr, netmask, scope);
125 		return addrptr;
121 		return addrptr;
126 	}
122 	}
127 
123 
128 	SET_STR_VALUE(newaddr->address, addr);
124 	SET_STR_VALUE(newaddr->address, addr);
129 	newaddr->netmask = netmask;
125 	newaddr->netmask = netmask;
130 	newaddr->scope = scope;
126 	newaddr->scope = scope;
131 	newaddr->next = addrptr;
127 	newaddr->next = addrptr;
132 	return newaddr;
128 	return newaddr;
133 }
129 }
134 
130 
135 
131 
136 /**
132 /**
137  *  libnl callback function.  Does the real parsing of a record returned by NETLINK.  This function
133  *  libnl callback function.  Does the real parsing of a record returned by NETLINK.  This function
138  *  parses LINK related packets
134  *  parses LINK related packets
139  *
135  *
140  * @param obj   Pointer to a struct nl_object response
136  * @param obj   Pointer to a struct nl_object response
141  * @param arg   Pointer to a struct etherinfo element where the parse result will be saved
137  * @param arg   Pointer to a struct etherinfo element where the parse result will be saved
142  */
138  */
143 static void callback_nl_link(struct nl_object *obj, void *arg)
139 static void callback_nl_link(struct nl_object *obj, void *arg)
144 {
140 {
145 	struct etherinfo *ethi = (struct etherinfo *) arg;
141 	struct etherinfo *ethi = (struct etherinfo *) arg;
146 	struct rtnl_link *link = (struct rtnl_link *) obj;
142 	struct rtnl_link *link = (struct rtnl_link *) obj;
147 	struct nl_addr *addr = rtnl_link_get_addr(link);
143 	struct nl_addr *addr = rtnl_link_get_addr(link);
148 	unsigned int i, len;
144 	unsigned int i, len;
149 	unsigned char *binaddr;
145 	unsigned char *binaddr;
150 	char hwaddr[130], *ptr;
146 	char hwaddr[130], *ptr;
151 
147 
152 	if( (ethi == NULL) || (ethi->hwaddress != NULL) || (addr == NULL) ) {
148 	if( (ethi == NULL) || (ethi->hwaddress != NULL) || (addr == NULL) ) {
153 		return;
149 		return;
154 	}
150 	}
155 
151 
156 	binaddr = nl_addr_get_binary_addr(addr);
152 	binaddr = nl_addr_get_binary_addr(addr);
157 	memset(&hwaddr, 0, 130);
153 	memset(&hwaddr, 0, 130);
158 	len = 20;
154 	len = 20;
159 	ptr = (char *)&hwaddr;
155 	ptr = (char *)&hwaddr;
160 	for( i = 0; i < 6; i++ ) {
156 	for( i = 0; i < 6; i++ ) {
161 		if( i == 0 ) {
157 		if( i == 0 ) {
162 			snprintf(ptr, len, "%02X", *(binaddr+i));
158 			snprintf(ptr, len, "%02X", *(binaddr+i));
163 			len -= 2;
159 			len -= 2;
164 			ptr += 2;
160 			ptr += 2;
165 		} else {
161 		} else {
166 			snprintf(ptr, len, ":%02X", *(binaddr+i));
162 			snprintf(ptr, len, ":%02X", *(binaddr+i));
167 			len -= 3;
163 			len -= 3;
168 			ptr += 3;
164 			ptr += 3;
169 		}
165 		}
170 	}
166 	}
171 	SET_STR_VALUE(ethi->hwaddress, hwaddr);
167 	SET_STR_VALUE(ethi->hwaddress, hwaddr);
172 }
168 }
173 
169 
170 /**
171  * For use by callback_nl_address
172  * Returns 0 for success; -1 for error (though this is currently ignored)
173  */
174 static int
175 append_object_for_netlink_address(struct etherinfo *ethi,
176                                   struct nl_object *obj,
177                                   struct rtnl_addr *addr)
178 {
179 	PyObject *addr_obj;
180 
181 	assert(ethi);
182 	assert(ethi->ipv4_addresses);
183 	assert(addr);
184 
185 	addr_obj = make_python_address_from_rtnl_addr(obj, addr);
186 	if (!addr_obj) {
187 	  return -1;
188 	}
189 
190 	if (-1 == PyList_Append(ethi->ipv4_addresses, addr_obj)) {
191 	  Py_DECREF(addr_obj);
192 	  return -1;
193 	}
194 
195 	Py_DECREF(addr_obj);
196 
197 	/* Success */
198 	return 0;
199 }
174 
200 
175 /**
201 /**
176  *  libnl callback function.  Does the real parsing of a record returned by NETLINK.  This function
202  *  libnl callback function.  Does the real parsing of a record returned by NETLINK.  This function
177  *  parses ADDRESS related packets
203  *  parses ADDRESS related packets
178  *
204  *
179  * @param obj   Pointer to a struct nl_object response
205  * @param obj   Pointer to a struct nl_object response
180  * @param arg   Pointer to a struct etherinfo element where the parse result will be saved
206  * @param arg   Pointer to a struct etherinfo element where the parse result will be saved
181  */
207  */
182 static void callback_nl_address(struct nl_object *obj, void *arg)
208 static void callback_nl_address(struct nl_object *obj, void *arg)
183 {
209 {
184 	struct etherinfo *ethi = (struct etherinfo *) arg;
210 	struct etherinfo *ethi = (struct etherinfo *) arg;
185 	struct nl_addr *addr;
211 	struct nl_addr *addr;
186 	char ip_str[66];
212 	char ip_str[66];
187 	int family;
213 	int family;
188 
214 
189 	if( ethi == NULL ) {
215 	if( ethi == NULL ) {
190 		return;
216 		return;
191 	}
217 	}
192 
218 
193 	addr = rtnl_addr_get_local((struct rtnl_addr *)obj);
219 	addr = rtnl_addr_get_local((struct rtnl_addr *)obj);
194 	family = nl_addr_get_family(addr);
220 	family = nl_addr_get_family(addr);
195 	switch( family ) {
221 	switch( family ) {
196 	case AF_INET:
222 	case AF_INET:
197 	case AF_INET6:
223 	case AF_INET6:
198 		memset(&ip_str, 0, 66);
224 		memset(&ip_str, 0, 66);
199 		inet_ntop(family, nl_addr_get_binary_addr(addr), (char *)&ip_str, 64);
225 		inet_ntop(family, nl_addr_get_binary_addr(addr), (char *)&ip_str, 64);
200 
226 
201 		if( family == AF_INET ) {
227 		if( family == AF_INET ) {
202 			struct nl_addr *brdcst = rtnl_addr_get_broadcast((struct rtnl_addr *)obj);
228                         (void)append_object_for_netlink_address(ethi, obj, (struct rtnl_addr*) addr);
203 			char brdcst_str[66];
204 
205 			SET_STR_VALUE(ethi->ipv4_address, ip_str);
206 			ethi->ipv4_netmask = rtnl_addr_get_prefixlen((struct rtnl_addr*) obj);
207 
208 			if( brdcst ) {
209 				memset(&brdcst_str, 0, 66);
210 				inet_ntop(family, nl_addr_get_binary_addr(brdcst), (char *)&brdcst_str, 64);
211 				SET_STR_VALUE(ethi->ipv4_broadcast, brdcst_str);
212 			}
213 		} else {
229 		} else {
214 			ethi->ipv6_addresses = etherinfo_add_ipv6(ethi->ipv6_addresses,
230 			ethi->ipv6_addresses = etherinfo_add_ipv6(ethi->ipv6_addresses,
215 								  ip_str,
231 								  ip_str,
216 								  rtnl_addr_get_prefixlen((struct rtnl_addr*) obj),
232 								  rtnl_addr_get_prefixlen((struct rtnl_addr*) obj),
217 								  rtnl_addr_get_scope((struct rtnl_addr*) obj));
233 								  rtnl_addr_get_scope((struct rtnl_addr*) obj));
218 		}
234 		}
219 		return;
235 		return;
220 	default:
236 	default:
221 		return;
237 		return;
222 	}
238 	}
223 }
239 }
224 
240 
225 
241 
226 
242 
227 /*
243 /*
228  *
244  *
229  *   Exported functions - API frontend
245  *   Exported functions - API frontend
230  *
246  *
231  */
247  */
232 
248 
233 /**
249 /**
234  * Dumps the contents of a struct etherinfo element to file
250  * Dumps the contents of a struct etherinfo element to file
235  *
251  *
236  * @param fp   FILE pointer where to dump
252  * @param fp   FILE pointer where to dump
237  * @param ptr  Pointer to a struct etherinfo element
253  * @param ptr  Pointer to a struct etherinfo element
238  */
254  */
239 void dump_etherinfo(FILE *fp, struct etherinfo *ptr)
255 void dump_etherinfo(FILE *fp, struct etherinfo *ptr)
240 {
256 {
241 
257 
242 	fprintf(fp, "*** Interface [%i] %s  ", ptr->index, ptr->device);
258 	fprintf(fp, "*** Interface [%i] %s  ", ptr->index, ptr->device);
243 	if( ptr->hwaddress ) {
259 	if( ptr->hwaddress ) {
244 		fprintf(fp, "MAC address: %s", ptr->hwaddress);
260 		fprintf(fp, "MAC address: %s", ptr->hwaddress);
245 	}
261 	}
246 	fprintf(fp, "\n");
262 	fprintf(fp, "\n");
247 	if( ptr->ipv4_address ) {
263 	if( ptr->ipv4_addresses ) {
248 		fprintf(fp, "\tIPv4 Address: %s/%i",
264 		Py_ssize_t i;
249 			ptr->ipv4_address, ptr->ipv4_netmask);
265 		for (i = 0; i < PyList_Size(ptr->ipv4_addresses); i++) {
250 		if( ptr->ipv4_broadcast ) {
266 			PyNetlinkIPv4Address *addr = (PyNetlinkIPv4Address *)PyList_GetItem(ptr->ipv4_addresses, i);
251 			fprintf(fp, "  -  Broadcast: %s", ptr->ipv4_broadcast);
267 			fprintf(fp, "\tIPv4 Address: %s/%i",
252 		}
268                                 PyString_AsString(addr->ipv4_address),
253 		fprintf(fp, "\n");
269                                 addr->ipv4_netmask);
270                         if( addr->ipv4_broadcast ) {
271                               fprintf(fp, "  -  Broadcast: %s", PyString_AsString(addr->ipv4_broadcast));
272                         }
273                         fprintf(fp, "\n");
274                 }
254 	}
275 	}
255 	if( ptr->ipv6_addresses ) {
276 	if( ptr->ipv6_addresses ) {
256 		struct ipv6address *ipv6 = ptr->ipv6_addresses;
277 		struct ipv6address *ipv6 = ptr->ipv6_addresses;
257 
278 
258 		fprintf(fp, "\tIPv6 addresses:\n");
279 		fprintf(fp, "\tIPv6 addresses:\n");
259 		for(; ipv6; ipv6 = ipv6->next) {
280 		for(; ipv6; ipv6 = ipv6->next) {
260 			char scope[66];
281 			char scope[66];
261 
282 
262 			rtnl_scope2str(ipv6->scope, scope, 64);
283 			rtnl_scope2str(ipv6->scope, scope, 64);
263 			fprintf(fp, "\t		       [%s] %s/%i\n",
284 			fprintf(fp, "\t		       [%s] %s/%i\n",
264 				scope, ipv6->address, ipv6->netmask);
285 				scope, ipv6->address, ipv6->netmask);
265 		}
286 		}
266 	}
287 	}
267 	fprintf(fp, "\n");
288 	fprintf(fp, "\n");
268 }
289 }
269 
290 
270 
291 
271 /**
292 /**
272  * Query NETLINK for ethernet configuration
293  * Query NETLINK for ethernet configuration
273  *
294  *
274  * @param ethinf Pointer to an available struct etherinfo element.  The 'device' member
295  * @param ethinf Pointer to an available struct etherinfo element.  The 'device' member
275  *               must contain a valid string to the device to query for information
296  *               must contain a valid string to the device to query for information
276  * @param nlc    Pointer to the libnl handle, which is used for the query against NETLINK
297  * @param nlc    Pointer to the libnl handle, which is used for the query against NETLINK
277  * @param query  What to query for.  Must be NLQRY_LINK or NLQRY_ADDR.
298  * @param query  What to query for.  Must be NLQRY_LINK or NLQRY_ADDR.
278  *
299  *
279  * @return Returns 1 on success, otherwise 0.
300  * @return Returns 1 on success, otherwise 0.
280  */
301  */
281 int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query)
302 int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query)
282 {
303 {
283 	struct nl_cache *link_cache;
304 	struct nl_cache *link_cache;
284 	struct nl_cache *addr_cache;
305 	struct nl_cache *addr_cache;
285 	struct rtnl_addr *addr;
306 	struct rtnl_addr *addr;
286 	struct rtnl_link *link;
307 	struct rtnl_link *link;
287 	struct etherinfo *ethinf = NULL;
308 	struct etherinfo *ethinf = NULL;
288 	int ret = 0;
309 	int ret = 0;
289 
310 
290 	if( !data || !data->ethinfo ) {
311 	if( !data || !data->ethinfo ) {
291 		return 0;
312 		return 0;
292 	}
313 	}
293 	ethinf = data->ethinfo;
314 	ethinf = data->ethinfo;
294 
315 
295 	/* Open a NETLINK connection on-the-fly */
316 	/* Open a NETLINK connection on-the-fly */
296 	if( !open_netlink(data) ) {
317 	if( !open_netlink(data) ) {
297 		PyErr_Format(PyExc_RuntimeError,
318 		PyErr_Format(PyExc_RuntimeError,
298 			     "Could not open a NETLINK connection for %s",
319 			     "Could not open a NETLINK connection for %s",
299 			     ethinf->device);
320 			     ethinf->device);
300 		return 0;
321 		return 0;
301 	}
322 	}
302 
323 
303 	/* Find the interface index we're looking up.
324 	/* Find the interface index we're looking up.
304 	 * As we don't expect it to change, we're reusing a "cached"
325 	 * As we don't expect it to change, we're reusing a "cached"
305 	 * interface index if we have that
326 	 * interface index if we have that
306 	 */
327 	 */
307 	if( ethinf->index < 0 ) {
328 	if( ethinf->index < 0 ) {
308 		link_cache = rtnl_link_alloc_cache(*data->nlc);
329 		link_cache = rtnl_link_alloc_cache(*data->nlc);
309 		ethinf->index = rtnl_link_name2i(link_cache, ethinf->device);
330 		ethinf->index = rtnl_link_name2i(link_cache, ethinf->device);
310 		if( ethinf->index < 0 ) {
331 		if( ethinf->index < 0 ) {
311 			return 0;
332 			return 0;
312 		}
333 		}
313 		nl_cache_free(link_cache);
334 		nl_cache_free(link_cache);
314 	}
335 	}
315 
336 
316 	/* Query the for requested info vai NETLINK */
337 	/* Query the for requested info vai NETLINK */
317 	switch( query ) {
338 	switch( query ) {
318 	case NLQRY_LINK:
339 	case NLQRY_LINK:
319 		/* Extract MAC/hardware address of the interface */
340 		/* Extract MAC/hardware address of the interface */
320 		link_cache = rtnl_link_alloc_cache(*data->nlc);
341 		link_cache = rtnl_link_alloc_cache(*data->nlc);
321 		link = rtnl_link_alloc();
342 		link = rtnl_link_alloc();
322 		rtnl_link_set_ifindex(link, ethinf->index);
343 		rtnl_link_set_ifindex(link, ethinf->index);
323 		nl_cache_foreach_filter(link_cache, (struct nl_object *)link, callback_nl_link, ethinf);
344 		nl_cache_foreach_filter(link_cache, (struct nl_object *)link, callback_nl_link, ethinf);
324 		rtnl_link_put(link);
345 		rtnl_link_put(link);
325 		nl_cache_free(link_cache);
346 		nl_cache_free(link_cache);
326 		ret = 1;
347 		ret = 1;
327 		break;
348 		break;
328 
349 
329 	case NLQRY_ADDR:
350 	case NLQRY_ADDR:
330 		/* Extract IP address information */
351 		/* Extract IP address information */
331 		addr_cache = rtnl_addr_alloc_cache(*data->nlc);
352 		addr_cache = rtnl_addr_alloc_cache(*data->nlc);
332 		addr = rtnl_addr_alloc();
353 		addr = rtnl_addr_alloc();
333 		rtnl_addr_set_ifindex(addr, ethinf->index);
354 		rtnl_addr_set_ifindex(addr, ethinf->index);
334 
355 
335                 /* Make sure we don't have any old IPv6 addresses saved */
356                 /* Make sure we don't have any old IPv6 addresses saved */
336                 if( ethinf->ipv6_addresses ) {
357                 if( ethinf->ipv6_addresses ) {
337                         free_ipv6addresses(ethinf->ipv6_addresses);
358                         free_ipv6addresses(ethinf->ipv6_addresses);
338                         ethinf->ipv6_addresses = NULL;
359                         ethinf->ipv6_addresses = NULL;
339                 }
360                 }
340 
361 
362                 /* Likewise for IPv4 addresses: */
363                 Py_XDECREF(ethinf->ipv4_addresses);
364                 ethinf->ipv4_addresses = PyList_New(0);
365                 if (!ethinf->ipv4_addresses) {
366                         return 0;
367                 }
368 
341                 /* Retrieve all address information */
369                 /* Retrieve all address information */
342 		nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, callback_nl_address, ethinf);
370 		nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, callback_nl_address, ethinf);
343 		rtnl_addr_put(addr);
371 		rtnl_addr_put(addr);
344 		nl_cache_free(addr_cache);
372 		nl_cache_free(addr_cache);
345 		ret = 1;
373 		ret = 1;
346 		break;
374 		break;
347 
375 
348 	default:
376 	default:
349 		ret = 0;
377 		ret = 0;
350 	}
378 	}
351 	return ret;
379 	return ret;
352 }
380 }
353 
381 
354 
382 
355 /**
383 /**
356  * Connects to the NETLINK interface.  This will be called
384  * Connects to the NETLINK interface.  This will be called
357  * for each etherinfo object being generated, and it will
385  * for each etherinfo object being generated, and it will
358  * keep a separate file descriptor open for each object
386  * keep a separate file descriptor open for each object
359  *
387  *
360  * @param data etherinfo_obj_data structure
388  * @param data etherinfo_obj_data structure
361  *
389  *
362  * @return Returns 1 on success, otherwise 0.
390  * @return Returns 1 on success, otherwise 0.
363  */
391  */
364 int open_netlink(struct etherinfo_obj_data *data)
392 int open_netlink(struct etherinfo_obj_data *data)
365 {
393 {
366 	if( !data ) {
394 	if( !data ) {
367 		return 0;
395 		return 0;
368 	}
396 	}
369 
397 
370 	/* Reuse already established NETLINK connection, if a connection exists */
398 	/* Reuse already established NETLINK connection, if a connection exists */
371 	if( *data->nlc ) {
399 	if( *data->nlc ) {
372 		/* If this object has not used NETLINK earlier, tag it as a user */
400 		/* If this object has not used NETLINK earlier, tag it as a user */
373 		if( !data->nlc_active ) {
401 		if( !data->nlc_active ) {
374 			pthread_mutex_lock(&nlc_counter_mtx);
402 			pthread_mutex_lock(&nlc_counter_mtx);
375 			(*data->nlc_users)++;
403 			(*data->nlc_users)++;
376 			pthread_mutex_unlock(&nlc_counter_mtx);
404 			pthread_mutex_unlock(&nlc_counter_mtx);
377 		}
405 		}
378 		data->nlc_active = 1;
406 		data->nlc_active = 1;
379 		return 1;
407 		return 1;
380 	}
408 	}
381 
409 
382 	/* No earlier connections exists, establish a new one */
410 	/* No earlier connections exists, establish a new one */
383 	*data->nlc = nl_handle_alloc();
411 	*data->nlc = nl_handle_alloc();
384 	nl_connect(*data->nlc, NETLINK_ROUTE);
412 	nl_connect(*data->nlc, NETLINK_ROUTE);
385 	if( (*data->nlc != NULL) ) {
413 	if( (*data->nlc != NULL) ) {
386 		/* Force O_CLOEXEC flag on the NETLINK socket */
414 		/* Force O_CLOEXEC flag on the NETLINK socket */
387 		if( fcntl(nl_socket_get_fd(*data->nlc), F_SETFD, FD_CLOEXEC) == -1 ) {
415 		if( fcntl(nl_socket_get_fd(*data->nlc), F_SETFD, FD_CLOEXEC) == -1 ) {
388 			fprintf(stderr,
416 			fprintf(stderr,
389 				"**WARNING** Failed to set O_CLOEXEC on NETLINK socket: %s\n",
417 				"**WARNING** Failed to set O_CLOEXEC on NETLINK socket: %s\n",
390 				strerror(errno));
418 				strerror(errno));
391 		}
419 		}
392 
420 
393 		/* Tag this object as an active user */
421 		/* Tag this object as an active user */
394 		pthread_mutex_lock(&nlc_counter_mtx);
422 		pthread_mutex_lock(&nlc_counter_mtx);
395 		(*data->nlc_users)++;
423 		(*data->nlc_users)++;
396 		pthread_mutex_unlock(&nlc_counter_mtx);
424 		pthread_mutex_unlock(&nlc_counter_mtx);
397 		data->nlc_active = 1;
425 		data->nlc_active = 1;
398 		return 1;
426 		return 1;
399 	} else {
427 	} else {
400 		return 0;
428 		return 0;
401 	}
429 	}
402 }
430 }
403 
431 
404 
432 
405 /**
433 /**
406  * Closes the NETLINK connection.  This should be called automatically whenever
434  * Closes the NETLINK connection.  This should be called automatically whenever
407  * the corresponding etherinfo object is deleted.
435  * the corresponding etherinfo object is deleted.
408  *
436  *
409  * @param ptr  Pointer to the pointer of struct nl_handle, which contains the NETLINK connection
437  * @param ptr  Pointer to the pointer of struct nl_handle, which contains the NETLINK connection
410  */
438  */
411 void close_netlink(struct etherinfo_obj_data *data)
439 void close_netlink(struct etherinfo_obj_data *data)
412 {
440 {
413 	if( !data || !(*data->nlc) ) {
441 	if( !data || !(*data->nlc) ) {
414 		return;
442 		return;
415 	}
443 	}
416 
444 
417 	/* Untag this object as a NETLINK user */
445 	/* Untag this object as a NETLINK user */
418 	data->nlc_active = 0;
446 	data->nlc_active = 0;
419 	pthread_mutex_lock(&nlc_counter_mtx);
447 	pthread_mutex_lock(&nlc_counter_mtx);
420 	(*data->nlc_users)--;
448 	(*data->nlc_users)--;
421 	pthread_mutex_unlock(&nlc_counter_mtx);
449 	pthread_mutex_unlock(&nlc_counter_mtx);
422 
450 
423 	/* Don't close the connection if there are more users */
451 	/* Don't close the connection if there are more users */
424 	if( *data->nlc_users > 0) {
452 	if( *data->nlc_users > 0) {
425 		return;
453 		return;
426 	}
454 	}
427 
455 
428 	/* Close NETLINK connection */
456 	/* Close NETLINK connection */
429 	nl_close(*data->nlc);
457 	nl_close(*data->nlc);
430 	nl_handle_destroy(*data->nlc);
458 	nl_handle_destroy(*data->nlc);
431 	*data->nlc = NULL;
459 	*data->nlc = NULL;
432 }
460 }

Comparison of old/new python-ethtool/etherinfo_ipv6_obj.c

Failures in both old/new

Tool Old location New location Function stdout stderr returncode
cpychecker python-ethtool/etherinfo_ipv6_obj.c:96:1 python-ethtool/etherinfo_ipv6_obj.c:96:1 _ethtool_etherinfo_ipv6_getter None this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed None
  1 /*
  1 /*
  2  * Copyright (C) 2009-2010 Red Hat Inc.
  2  * Copyright (C) 2009-2010 Red Hat Inc.
  3  *
  3  *
  4  * David Sommerseth <davids@redhat.com>
  4  * David Sommerseth <davids@redhat.com>
  5  *
  5  *
  6  * This application is free software; you can redistribute it and/or modify it
  6  * This application is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License as published by the Free
  7  * under the terms of the GNU General Public License as published by the Free
  8  * Software Foundation; version 2.
  8  * Software Foundation; version 2.
  9  *
  9  *
 10  * This application is distributed in the hope that it will be useful,
 10  * This application is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  * General Public License for more details.
 13  * General Public License for more details.
 14  */
 14  */
 15 
 15 
 16 /**
 16 /**
 17  * @file   etherinfo_ipv6_obj.c
 17  * @file   etherinfo_ipv6_obj.c
 18  * @author David Sommerseth <davids@redhat.com>
 18  * @author David Sommerseth <davids@redhat.com>
 19  * @date   Thu Jul 29 17:51:28 2010
 19  * @date   Thu Jul 29 17:51:28 2010
 20  *
 20  *
 21  * @brief  Python ethtool.etherinfo class functions.
 21  * @brief  Python ethtool.etherinfo class functions.
 22  *
 22  *
 23  */
 23  */
 24 
 24 
 25 #include <Python.h>
 25 #include <Python.h>
 26 #include "structmember.h"
 26 #include "structmember.h"
 27 
 27 
 28 #include <netlink/route/rtnl.h>
 28 #include <netlink/route/rtnl.h>
 29 #include "etherinfo_struct.h"
 29 #include "etherinfo_struct.h"
 30 #include "etherinfo.h"
 30 #include "etherinfo.h"
 31 
 31 
 32 
 32 
 33 /**
 33 /**
 34  * ethtool.etherinfo_ipv6addr deallocator - cleans up when a object is deleted
 34  * ethtool.etherinfo_ipv6addr deallocator - cleans up when a object is deleted
 35  *
 35  *
 36  * @param self etherinfo_ipv6addr_py object structure
 36  * @param self etherinfo_ipv6addr_py object structure
 37  */
 37  */
 38 void _ethtool_etherinfo_ipv6_dealloc(etherinfo_ipv6addr_py *self)
 38 void _ethtool_etherinfo_ipv6_dealloc(etherinfo_ipv6addr_py *self)
 39 {
 39 {
 40 	if( self->addrdata ) {
 40 	if( self->addrdata ) {
 41 		free_ipv6addresses(self->addrdata);
 41 		free_ipv6addresses(self->addrdata);
 42 	}
 42 	}
 43 	self->ob_type->tp_free((PyObject*)self);
 43 	self->ob_type->tp_free((PyObject*)self);
 44 }
 44 }
 45 
 45 
 46 
 46 
 47 /**
 47 /**
 48  * ethtool.etherinfo_ipv6addr function, creating a new etherinfo object
 48  * ethtool.etherinfo_ipv6addr function, creating a new etherinfo object
 49  *
 49  *
 50  * @param type
 50  * @param type
 51  * @param args
 51  * @param args
 52  * @param kwds
 52  * @param kwds
 53  *
 53  *
 54  * @return Returns in PyObject with the new object on success, otherwise NULL
 54  * @return Returns in PyObject with the new object on success, otherwise NULL
 55  */
 55  */
 56 PyObject *_ethtool_etherinfo_ipv6_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 56 PyObject *_ethtool_etherinfo_ipv6_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 57 {
 57 {
 58 	etherinfo_ipv6addr_py *self;
 58 	etherinfo_ipv6addr_py *self;
 59 
 59 
 60 	self = (etherinfo_ipv6addr_py *)type->tp_alloc(type, 0);
 60 	self = (etherinfo_ipv6addr_py *)type->tp_alloc(type, 0);
 61 	return (PyObject *)self;
 61 	return (PyObject *)self;
 62 }
 62 }
 63 
 63 
 64 
 64 
 65 /**
 65 /**
 66  * ethtool.etherinfo_ipv6addr init (constructor) method.  Makes sure the object is initialised correctly.
 66  * ethtool.etherinfo_ipv6addr init (constructor) method.  Makes sure the object is initialised correctly.
 67  *
 67  *
 68  * @param self
 68  * @param self
 69  * @param args
 69  * @param args
 70  * @param kwds
 70  * @param kwds
 71  *
 71  *
 72  * @return Returns 0 on success.
 72  * @return Returns 0 on success.
 73  */
 73  */
 74 int _ethtool_etherinfo_ipv6_init(etherinfo_ipv6addr_py *self, PyObject *args, PyObject *kwds)
 74 int _ethtool_etherinfo_ipv6_init(etherinfo_ipv6addr_py *self, PyObject *args, PyObject *kwds)
 75 {
 75 {
 76 	static char *etherinfo_kwlist[] = {"etherinfo_ipv6_ptr", NULL};
 76 	static char *etherinfo_kwlist[] = {"etherinfo_ipv6_ptr", NULL};
 77 	PyObject *ethinf_ptr = NULL;
 77 	PyObject *ethinf_ptr = NULL;
 78 
 78 
 79 	if( !PyArg_ParseTupleAndKeywords(args, kwds, "O", etherinfo_kwlist, &ethinf_ptr)) {
 79 	if( !PyArg_ParseTupleAndKeywords(args, kwds, "O", etherinfo_kwlist, &ethinf_ptr)) {
 80 		PyErr_SetString(PyExc_AttributeError, "Invalid data pointer to constructor");
 80 		PyErr_SetString(PyExc_AttributeError, "Invalid data pointer to constructor");
 81 		return -1;
 81 		return -1;
 82 	}
 82 	}
 83 	self->addrdata = (struct ipv6address *) PyCObject_AsVoidPtr(ethinf_ptr);
 83 	self->addrdata = (struct ipv6address *) PyCObject_AsVoidPtr(ethinf_ptr);
 84 	return 0;
 84 	return 0;
 85 }
 85 }
 86 
 86 
 87 /**
 87 /**
 88  * ethtool.etherinfo_ipv6addr function for retrieving data from a Python object.
 88  * ethtool.etherinfo_ipv6addr function for retrieving data from a Python object.
 89  *
 89  *
 90  * @param self
 90  * @param self
 91  * @param attr_o  contains the object member request (which element to return)
 91  * @param attr_o  contains the object member request (which element to return)
 92  *
 92  *
 93  * @return Returns a PyObject with the value requested on success, otherwise NULL
 93  * @return Returns a PyObject with the value requested on success, otherwise NULL
 94  */
 94  */
 95 PyObject *_ethtool_etherinfo_ipv6_getter(etherinfo_ipv6addr_py *self, PyObject *attr_o)
 95 PyObject *_ethtool_etherinfo_ipv6_getter(etherinfo_ipv6addr_py *self, PyObject *attr_o)
 96 {
 96 {
 97 	PyObject *ret;
 97 	PyObject *ret;
 98 	char *attr = PyString_AsString(attr_o);
 98 	char *attr = PyString_AsString(attr_o);
 99 
 99 
100 	if( !self || !self->addrdata ) {
100 	if( !self || !self->addrdata ) {
101 		PyErr_SetString(PyExc_AttributeError, "No data available");
101 		PyErr_SetString(PyExc_AttributeError, "No data available");
102 		return NULL;
102 		return NULL;
103 	}
103 	}
104 
104 
105 	if( strcmp(attr, "address") == 0 ) {
105 	if( strcmp(attr, "address") == 0 ) {
106 		ret = RETURN_STRING(self->addrdata->address);
106 		ret = RETURN_STRING(self->addrdata->address);
107 	} else if( strcmp(attr, "netmask") == 0 ) {
107 	} else if( strcmp(attr, "netmask") == 0 ) {
108 		ret = PyInt_FromLong(self->addrdata->netmask);
108 		ret = PyInt_FromLong(self->addrdata->netmask);
109 	} else if( strcmp(attr, "scope") == 0 ) {
109 	} else if( strcmp(attr, "scope") == 0 ) {
110 		char scope[66];
110 		char scope[66];
111 
111 
112 		rtnl_scope2str(self->addrdata->scope, scope, 66);
112 		rtnl_scope2str(self->addrdata->scope, scope, 66);
113 		ret = PyString_FromString(scope);
113 		ret = PyString_FromString(scope);
114 	} else {
114 	} else {
115 		ret = PyObject_GenericGetAttr((PyObject *)self, attr_o);
115 		ret = PyObject_GenericGetAttr((PyObject *)self, attr_o);
116 	}
116 	}
117 	return ret;
117 	return ret;
118 }
118 }
119 
119 
120 
120 
121 /**
121 /**
122  * ethtool.etherinfo_ipv6addr function for setting a value to a object member.  This feature is
122  * ethtool.etherinfo_ipv6addr function for setting a value to a object member.  This feature is
123  * disabled by always returning -1, as the values are read-only by the user.
123  * disabled by always returning -1, as the values are read-only by the user.
124  *
124  *
125  * @param self
125  * @param self
126  * @param attr_o
126  * @param attr_o
127  * @param val_o
127  * @param val_o
128  *
128  *
129  * @return Returns always -1 (failure).
129  * @return Returns always -1 (failure).
130  */
130  */
131 int _ethtool_etherinfo_ipv6_setter(etherinfo_ipv6addr_py *self, PyObject *attr_o, PyObject *val_o)
131 int _ethtool_etherinfo_ipv6_setter(etherinfo_ipv6addr_py *self, PyObject *attr_o, PyObject *val_o)
132 {
132 {
133 	PyErr_SetString(PyExc_AttributeError, "etherinfo_ipv6addr member values are read-only.");
133 	PyErr_SetString(PyExc_AttributeError, "etherinfo_ipv6addr member values are read-only.");
134 	return -1;
134 	return -1;
135 }
135 }
136 
136 
137 
137 
138 /**
138 /**
139  * Creates a human readable format of the information when object is being treated as a string
139  * Creates a human readable format of the information when object is being treated as a string
140  *
140  *
141  * @param self
141  * @param self
142  *
142  *
143  * @return Returns a PyObject with a string with all of the information
143  * @return Returns a PyObject with a string with all of the information
144  */
144  */
145 PyObject *_ethtool_etherinfo_ipv6_str(etherinfo_ipv6addr_py *self)
145 PyObject *_ethtool_etherinfo_ipv6_str(etherinfo_ipv6addr_py *self)
146 {
146 {
147 	char scope[66];
147 	char scope[66];
148 
148 
149 	if( !self || !self->addrdata ) {
149 	if( !self || !self->addrdata ) {
150 		PyErr_SetString(PyExc_AttributeError, "No data available");
150 		PyErr_SetString(PyExc_AttributeError, "No data available");
151 		return NULL;
151 		return NULL;
152 	}
152 	}
153 
153 
154 	rtnl_scope2str(self->addrdata->scope, scope, 64);
154 	rtnl_scope2str(self->addrdata->scope, scope, 64);
155 	return PyString_FromFormat("[%s] %s/%i",
155 	return PyString_FromFormat("[%s] %s/%i",
156 				   scope,
156 				   scope,
157 				   self->addrdata->address,
157 				   self->addrdata->address,
158 				   self->addrdata->netmask);
158 				   self->addrdata->netmask);
159 }
159 }
160 
160 
161 
161 
162 /**
162 /**
163  * This is required by Python, which lists all accessible methods
163  * This is required by Python, which lists all accessible methods
164  * in the object.  But no methods are provided.
164  * in the object.  But no methods are provided.
165  *
165  *
166  */
166  */
167 static PyMethodDef _ethtool_etherinfo_ipv6_methods[] = {
167 static PyMethodDef _ethtool_etherinfo_ipv6_methods[] = {
168     {NULL}  /**< No methods defined */
168     {NULL}  /**< No methods defined */
169 };
169 };
170 
170 
171 /**
171 /**
172  * Defines all accessible object members
172  * Defines all accessible object members
173  *
173  *
174  */
174  */
175 static PyMemberDef _ethtool_etherinfo_ipv6_members[] = {
175 static PyMemberDef _ethtool_etherinfo_ipv6_members[] = {
176     {"address", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0,
176     {"address", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0,
177      "IPv6 address"},
177      "IPv6 address"},
178     {"netmask", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0,
178     {"netmask", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0,
179      "IPv6 netmask"},
179      "IPv6 netmask"},
180     {"scope", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0,
180     {"scope", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0,
181      "IPv6 IP address scope"},
181      "IPv6 IP address scope"},
182     {NULL}  /* End of member list */
182     {NULL}  /* End of member list */
183 };
183 };
184 
184 
185 /**
185 /**
186  * Definition of the functions a Python class/object requires.
186  * Definition of the functions a Python class/object requires.
187  *
187  *
188  */
188  */
189 PyTypeObject ethtool_etherinfoIPv6Type = {
189 PyTypeObject ethtool_etherinfoIPv6Type = {
190     PyObject_HEAD_INIT(NULL)
190     PyObject_HEAD_INIT(NULL)
191     0,                         /*ob_size*/
191     0,                         /*ob_size*/
192     "ethtool.etherinfo_ipv6addr", /*tp_name*/
192     "ethtool.etherinfo_ipv6addr", /*tp_name*/
193     sizeof(etherinfo_ipv6addr_py), /*tp_basicsize*/
193     sizeof(etherinfo_ipv6addr_py), /*tp_basicsize*/
194     0,                         /*tp_itemsize*/
194     0,                         /*tp_itemsize*/
195     (destructor)_ethtool_etherinfo_ipv6_dealloc,/*tp_dealloc*/
195     (destructor)_ethtool_etherinfo_ipv6_dealloc,/*tp_dealloc*/
196     0,                         /*tp_print*/
196     0,                         /*tp_print*/
197     0,                         /*tp_getattr*/
197     0,                         /*tp_getattr*/
198     0,                         /*tp_setattr*/
198     0,                         /*tp_setattr*/
199     0,                         /*tp_compare*/
199     0,                         /*tp_compare*/
200     0,                         /*tp_repr*/
200     0,                         /*tp_repr*/
201     0,                         /*tp_as_number*/
201     0,                         /*tp_as_number*/
202     0,                         /*tp_as_sequence*/
202     0,                         /*tp_as_sequence*/
203     0,                         /*tp_as_mapping*/
203     0,                         /*tp_as_mapping*/
204     0,                         /*tp_hash */
204     0,                         /*tp_hash */
205     0,                         /*tp_call*/
205     0,                         /*tp_call*/
206     (reprfunc)_ethtool_etherinfo_ipv6_str,        /*tp_str*/
206     (reprfunc)_ethtool_etherinfo_ipv6_str,        /*tp_str*/
207     (getattrofunc)_ethtool_etherinfo_ipv6_getter, /*tp_getattro*/
207     (getattrofunc)_ethtool_etherinfo_ipv6_getter, /*tp_getattro*/
208     (setattrofunc)_ethtool_etherinfo_ipv6_setter, /*tp_setattro*/
208     (setattrofunc)_ethtool_etherinfo_ipv6_setter, /*tp_setattro*/
209     0,                         /*tp_as_buffer*/
209     0,                         /*tp_as_buffer*/
210     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
210     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
211     "IPv6 address information", /* tp_doc */
211     "IPv6 address information", /* tp_doc */
212     0,		               /* tp_traverse */
212     0,		               /* tp_traverse */
213     0,		               /* tp_clear */
213     0,		               /* tp_clear */
214     0,		               /* tp_richcompare */
214     0,		               /* tp_richcompare */
215     0,		               /* tp_weaklistoffset */
215     0,		               /* tp_weaklistoffset */
216     0,		               /* tp_iter */
216     0,		               /* tp_iter */
217     0,		               /* tp_iternext */
217     0,		               /* tp_iternext */
218     _ethtool_etherinfo_ipv6_methods,            /* tp_methods */
218     _ethtool_etherinfo_ipv6_methods,            /* tp_methods */
219     _ethtool_etherinfo_ipv6_members,            /* tp_members */
219     _ethtool_etherinfo_ipv6_members,            /* tp_members */
220     0,                         /* tp_getset */
220     0,                         /* tp_getset */
221     0,                         /* tp_base */
221     0,                         /* tp_base */
222     0,                         /* tp_dict */
222     0,                         /* tp_dict */
223     0,                         /* tp_descr_get */
223     0,                         /* tp_descr_get */
224     0,                         /* tp_descr_set */
224     0,                         /* tp_descr_set */
225     0,                         /* tp_dictoffset */
225     0,                         /* tp_dictoffset */
226     (initproc)_ethtool_etherinfo_ipv6_init,     /* tp_init */
226     (initproc)_ethtool_etherinfo_ipv6_init,     /* tp_init */
227     0,                         /* tp_alloc */
227     0,                         /* tp_alloc */
228     _ethtool_etherinfo_ipv6_new,                /* tp_new */
228     _ethtool_etherinfo_ipv6_new,                /* tp_new */
229 };
229 };

Comparison of old/new python-ethtool/etherinfo_obj.c

New issues

Location Tool Test ID Function Issue
python-ethtool/etherinfo_obj.c:183:1 cpychecker refcount-too-high _ethtool_etherinfo_getter ob_refcnt of '*py_addr' is 1 too high

Fixed issues

Location Tool Test ID Function Issue
python-ethtool/etherinfo_obj.c:207:1 cpychecker refcount-too-high _ethtool_etherinfo_str ob_refcnt of PyStringObject is 1 too high
python-ethtool/etherinfo_obj.c:274:1 cpychecker refcount-too-high _ethtool_etherinfo_get_ipv6_addresses ob_refcnt of '*ret' is 1 too high

Issues in both old/new

Old location New location Tool Test ID Function Issue
python-ethtool/etherinfo_obj.c:203:4 python-ethtool/etherinfo_obj.c:257:4 cpychecker null-ptr-dereference _ethtool_etherinfo_str dereferencing NULL (addr->ob_refcnt) at python-ethtool/etherinfo_obj.c:257
python-ethtool/etherinfo_obj.c:274:1 python-ethtool/etherinfo_obj.c:346:1 cpychecker refcount-too-high _ethtool_etherinfo_get_ipv6_addresses ob_refcnt of '*ipv6_pydata' is 1 too high
python-ethtool/etherinfo_obj.c:274:1 python-ethtool/etherinfo_obj.c:346:1 cpychecker refcount-too-high _ethtool_etherinfo_get_ipv6_addresses ob_refcnt of '*ret.2' is 1 too high

Failures in both old/new

Tool Old location New location Function stdout stderr returncode
cpychecker python-ethtool/etherinfo_obj.c:103:1 python-ethtool/etherinfo_obj.c:138:1 _ethtool_etherinfo_getter None this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed None
cpychecker python-ethtool/etherinfo_obj.c:158:1 python-ethtool/etherinfo_obj.c:210:1 _ethtool_etherinfo_str None this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed None
  1 /*
  1 /*
  2  * Copyright (C) 2009-2011 Red Hat Inc.
  2  * Copyright (C) 2009-2011 Red Hat Inc.
  3  *
  3  *
  4  * David Sommerseth <davids@redhat.com>
  4  * David Sommerseth <davids@redhat.com>
  5  *
  5  *
  6  * This application is free software; you can redistribute it and/or modify it
  6  * This application is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License as published by the Free
  7  * under the terms of the GNU General Public License as published by the Free
  8  * Software Foundation; version 2.
  8  * Software Foundation; version 2.
  9  *
  9  *
 10  * This application is distributed in the hope that it will be useful,
 10  * This application is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  * General Public License for more details.
 13  * General Public License for more details.
 14  */
 14  */
 15 
 15 
 16 
 16 
 17 /**
 17 /**
 18  * @file   etherinfo_obj.c
 18  * @file   etherinfo_obj.c
 19  * @author David Sommerseth <davids@redhat.com>
 19  * @author David Sommerseth <davids@redhat.com>
 20  * @date   Fri Sep  4 18:41:28 2009
 20  * @date   Fri Sep  4 18:41:28 2009
 21  *
 21  *
 22  * @brief  Python ethtool.etherinfo class functions.
 22  * @brief  Python ethtool.etherinfo class functions.
 23  *
 23  *
 24  */
 24  */
 25 
 25 
 26 #include <Python.h>
 26 #include <Python.h>
 27 #include "structmember.h"
 27 #include "structmember.h"
 28 
 28 
 29 #include <netlink/route/rtnl.h>
 29 #include <netlink/route/rtnl.h>
 30 #include "etherinfo_struct.h"
 30 #include "etherinfo_struct.h"
 31 #include "etherinfo.h"
 31 #include "etherinfo.h"
 32 
 32 
 33 extern PyTypeObject ethtool_etherinfoIPv6Type;
 33 extern PyTypeObject ethtool_etherinfoIPv6Type;
 34 
 34 
 35 /**
 35 /**
 36  * ethtool.etherinfo deallocator - cleans up when a object is deleted
 36  * ethtool.etherinfo deallocator - cleans up when a object is deleted
 37  *
 37  *
 38  * @param self etherinfo_py object structure
 38  * @param self etherinfo_py object structure
 39  */
 39  */
 40 void _ethtool_etherinfo_dealloc(etherinfo_py *self)
 40 void _ethtool_etherinfo_dealloc(etherinfo_py *self)
 41 {
 41 {
 42 	if( self->data ) {
 42 	if( self->data ) {
 43 		close_netlink(self->data);
 43 		close_netlink(self->data);
 44 
 44 
 45 		if( self->data->ethinfo ) {
 45 		if( self->data->ethinfo ) {
 46 			free_etherinfo(self->data->ethinfo);
 46 			free_etherinfo(self->data->ethinfo);
 47 		}
 47 		}
 48 		free(self->data);
 48 		free(self->data);
 49 	}
 49 	}
 50 	self->ob_type->tp_free((PyObject*)self);
 50 	self->ob_type->tp_free((PyObject*)self);
 51 }
 51 }
 52 
 52 
 53 
 53 
 54 /**
 54 /**
 55  * ethtool.etherinfo function, creating a new etherinfo object
 55  * ethtool.etherinfo function, creating a new etherinfo object
 56  *
 56  *
 57  * @param type
 57  * @param type
 58  * @param args
 58  * @param args
 59  * @param kwds
 59  * @param kwds
 60  *
 60  *
 61  * @return Returns in PyObject with the new object on success, otherwise NULL
 61  * @return Returns in PyObject with the new object on success, otherwise NULL
 62  */
 62  */
 63 PyObject *_ethtool_etherinfo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 63 PyObject *_ethtool_etherinfo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 64 {
 64 {
 65 	etherinfo_py *self;
 65 	etherinfo_py *self;
 66 
 66 
 67 	self = (etherinfo_py *)type->tp_alloc(type, 0);
 67 	self = (etherinfo_py *)type->tp_alloc(type, 0);
 68 	return (PyObject *)self;
 68 	return (PyObject *)self;
 69 }
 69 }
 70 
 70 
 71 
 71 
 72 /**
 72 /**
 73  * ethtool.etherinfo init (constructor) method.  Makes sure the object is initialised correctly.
 73  * ethtool.etherinfo init (constructor) method.  Makes sure the object is initialised correctly.
 74  *
 74  *
 75  * @param self
 75  * @param self
 76  * @param args
 76  * @param args
 77  * @param kwds
 77  * @param kwds
 78  *
 78  *
 79  * @return Returns 0 on success.
 79  * @return Returns 0 on success.
 80  */
 80  */
 81 int _ethtool_etherinfo_init(etherinfo_py *self, PyObject *args, PyObject *kwds)
 81 int _ethtool_etherinfo_init(etherinfo_py *self, PyObject *args, PyObject *kwds)
 82 {
 82 {
 83 	static char *etherinfo_kwlist[] = {"etherinfo_ptr", NULL};
 83 	static char *etherinfo_kwlist[] = {"etherinfo_ptr", NULL};
 84 	PyObject *ethinf_ptr = NULL;
 84 	PyObject *ethinf_ptr = NULL;
 85 
 85 
 86 	if( !PyArg_ParseTupleAndKeywords(args, kwds, "O", etherinfo_kwlist, &ethinf_ptr)) {
 86 	if( !PyArg_ParseTupleAndKeywords(args, kwds, "O", etherinfo_kwlist, &ethinf_ptr)) {
 87 		PyErr_SetString(PyExc_AttributeError, "Invalid data pointer to constructor");
 87 		PyErr_SetString(PyExc_AttributeError, "Invalid data pointer to constructor");
 88 		return -1;
 88 		return -1;
 89 	}
 89 	}
 90 	self->data = (struct etherinfo_obj_data *) PyCObject_AsVoidPtr(ethinf_ptr);
 90 	self->data = (struct etherinfo_obj_data *) PyCObject_AsVoidPtr(ethinf_ptr);
 91 	return 0;
 91 	return 0;
 92 }
 92 }
 93 
 93 
 94 /*
 95   The old approach of having a single IPv4 address per device meant each result
 96   that came in from netlink overwrote the old result.
 97 
 98   Mimic it by returning the last entry in the list (if any).
 99 
100   The return value is a *borrowed reference* (or NULL)
101 */
102 static PyNetlinkIPv4Address*
103 get_last_address(etherinfo_py *self)
104 {
105 	Py_ssize_t size;
106 	PyObject *list;
107 
108 	assert(self);
109 	list = self->data->ethinfo->ipv4_addresses;
110 	if (!list) {
111 		return NULL;
112 	}
113 
114 	if (!PyList_Check(list)) {
115 		return NULL;
116 	}
117 
118 	size = PyList_Size(list);
119 	if (size > 0) {
120 		PyObject *item = PyList_GetItem(list, size - 1);
121 		if (Py_TYPE(item) == &ethtool_netlink_ipv4_address_Type) {
122 			return (PyNetlinkIPv4Address*)item;
123 		}
124 	}
125 
126 	return NULL;
127 }
128 
 94 /**
129 /**
 95  * ethtool.etherinfo function for retrieving data from a Python object.
130  * ethtool.etherinfo function for retrieving data from a Python object.
 96  *
131  *
 97  * @param self
132  * @param self
 98  * @param attr_o  contains the object member request (which element to return)
133  * @param attr_o  contains the object member request (which element to return)
 99  *
134  *
100  * @return Returns a PyObject with the value requested on success, otherwise NULL
135  * @return Returns a PyObject with the value requested on success, otherwise NULL
101  */
136  */
102 PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o)
137 PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o)
103 {
138 {
104 	PyObject *ret;
105 	char *attr = PyString_AsString(attr_o);
139 	char *attr = PyString_AsString(attr_o);
140 	PyNetlinkIPv4Address *py_addr;
106 
141 
107 	if( !self || !self->data ) {
142 	if( !self || !self->data ) {
108 		PyErr_SetString(PyExc_AttributeError, "No data available");
143 		PyErr_SetString(PyExc_AttributeError, "No data available");
109 		return NULL;
144 		return NULL;
110 	}
145 	}
111 
146 
112 	if( strcmp(attr, "device") == 0 ) {
147 	if( strcmp(attr, "device") == 0 ) {
113 		ret = RETURN_STRING(self->data->ethinfo->device);
148 		return RETURN_STRING(self->data->ethinfo->device);
114 	} else if( strcmp(attr, "mac_address") == 0 ) {
149 	} else if( strcmp(attr, "mac_address") == 0 ) {
115 		get_etherinfo(self->data, NLQRY_LINK);
150 		get_etherinfo(self->data, NLQRY_LINK);
116 		ret = RETURN_STRING(self->data->ethinfo->hwaddress);
151 		return RETURN_STRING(self->data->ethinfo->hwaddress);
117 	} else if( strcmp(attr, "ipv4_address") == 0 ) {
152 	} else if( strcmp(attr, "ipv4_address") == 0 ) {
118 		get_etherinfo(self->data, NLQRY_ADDR);
153 		get_etherinfo(self->data, NLQRY_ADDR);
119 		ret = RETURN_STRING(self->data->ethinfo->ipv4_address);
154 		/* For compatiblity with old approach, return last IPv4 address: */
155 		py_addr = get_last_address(self);
156 		if (py_addr) {
157 		  if (py_addr->ipv4_address) {
158 		      Py_INCREF(py_addr->ipv4_address);
159 		      return py_addr->ipv4_address;
160 		  }
161 		}
162 		Py_RETURN_NONE;
120 	} else if( strcmp(attr, "ipv4_netmask") == 0 ) {
163 	} else if( strcmp(attr, "ipv4_netmask") == 0 ) {
121 		get_etherinfo(self->data, NLQRY_ADDR);
164 		get_etherinfo(self->data, NLQRY_ADDR);
122 		ret = PyInt_FromLong(self->data->ethinfo->ipv4_netmask);
165 		py_addr = get_last_address(self);
166 		if (py_addr) {
167 		  return PyInt_FromLong(py_addr->ipv4_netmask);
168 		}
169 		return PyInt_FromLong(0);
123 	} else if( strcmp(attr, "ipv4_broadcast") == 0 ) {
170 	} else if( strcmp(attr, "ipv4_broadcast") == 0 ) {
124 		get_etherinfo(self->data, NLQRY_ADDR);
171 		get_etherinfo(self->data, NLQRY_ADDR);
125 		ret = RETURN_STRING(self->data->ethinfo->ipv4_broadcast);
172 		py_addr = get_last_address(self);
173 		if (py_addr) {
174 		  if (py_addr->ipv4_broadcast) {
175 		      Py_INCREF(py_addr->ipv4_broadcast);
176 		      return py_addr->ipv4_broadcast;
177 		  }
178 		}
179 		Py_RETURN_NONE;
126 	} else {
180 	} else {
127 		ret = PyObject_GenericGetAttr((PyObject *)self, attr_o);
181 		return PyObject_GenericGetAttr((PyObject *)self, attr_o);
128 	}
182 	}
129 
130 	return ret;
131 }
183 }
132 
184 
133 /**
185 /**
134  * ethtool.etherinfo function for setting a value to a object member.  This feature is
186  * ethtool.etherinfo function for setting a value to a object member.  This feature is
135  * disabled by always returning -1, as the values are read-only by the user.
187  * disabled by always returning -1, as the values are read-only by the user.
136  *
188  *
137  * @param self
189  * @param self
138  * @param attr_o
190  * @param attr_o
139  * @param val_o
191  * @param val_o
140  *
192  *
141  * @return Returns always -1 (failure).
193  * @return Returns always -1 (failure).
142  */
194  */
143 int _ethtool_etherinfo_setter(etherinfo_py *self, PyObject *attr_o, PyObject *val_o)
195 int _ethtool_etherinfo_setter(etherinfo_py *self, PyObject *attr_o, PyObject *val_o)
144 {
196 {
145 	PyErr_SetString(PyExc_AttributeError, "etherinfo member values are read-only.");
197 	PyErr_SetString(PyExc_AttributeError, "etherinfo member values are read-only.");
146 	return -1;
198 	return -1;
147 }
199 }
148 
200 
149 
201 
150 /**
202 /**
151  * Creates a human readable format of the information when object is being treated as a string
203  * Creates a human readable format of the information when object is being treated as a string
152  *
204  *
153  * @param self
205  * @param self
154  *
206  *
155  * @return Returns a PyObject with a string with all of the information
207  * @return Returns a PyObject with a string with all of the information
156  */
208  */
157 PyObject *_ethtool_etherinfo_str(etherinfo_py *self)
209 PyObject *_ethtool_etherinfo_str(etherinfo_py *self)
158 {
210 {
159 	PyObject *ret = NULL;
211 	PyObject *ret = NULL;
160 
212 
161 	if( !self || !self->data || !self->data->nlc || !self->data->ethinfo ) {
213 	if( !self || !self->data || !self->data->nlc || !self->data->ethinfo ) {
162 		PyErr_SetString(PyExc_AttributeError, "No data available");
214 		PyErr_SetString(PyExc_AttributeError, "No data available");
163 		return NULL;
215 		return NULL;
164 	}
216 	}
165 
217 
166 	get_etherinfo(self->data, NLQRY_LINK);
218 	get_etherinfo(self->data, NLQRY_LINK);
167 	get_etherinfo(self->data, NLQRY_ADDR);
219 	get_etherinfo(self->data, NLQRY_ADDR);
168 
220 
169 	ret = PyString_FromFormat("Device %s:\n", self->data->ethinfo->device);
221 	ret = PyString_FromFormat("Device %s:\n", self->data->ethinfo->device);
170 	if( self->data->ethinfo->hwaddress ) {
222 	if( self->data->ethinfo->hwaddress ) {
171 		PyObject *tmp = PyString_FromFormat("\tMAC address: %s\n", self->data->ethinfo->hwaddress);
223 		PyObject *tmp = PyString_FromFormat("\tMAC address: %s\n", self->data->ethinfo->hwaddress);
172 		PyString_Concat(&ret, tmp);
224 		PyString_Concat(&ret, tmp);
173 		Py_DECREF(tmp);
225 		Py_DECREF(tmp);
174 	}
226 	}
175 
227 
176 	if( self->data->ethinfo->ipv4_address ) {
228 	if( self->data->ethinfo->ipv4_addresses ) {
177 		PyObject *tmp = PyString_FromFormat("\tIPv4 address: %s/%i",
229                Py_ssize_t i;
178 						   self->data->ethinfo->ipv4_address,
230                for (i = 0; i < PyList_Size(self->data->ethinfo->ipv4_addresses); i++) {
179 						   self->data->ethinfo->ipv4_netmask);
231                        PyNetlinkIPv4Address *py_addr = (PyNetlinkIPv4Address *)PyList_GetItem(self->data->ethinfo->ipv4_addresses, i);
180 		if( self->data->ethinfo->ipv4_broadcast ) {
232                        PyObject *tmp = PyString_FromFormat("\tIPv4 address: ");
181 			PyObject *tmp2 = PyString_FromFormat("	  Broadcast: %s",
233                        PyString_Concat(&tmp, py_addr->ipv4_address);
182 							     self->data->ethinfo->ipv4_broadcast);
234                        PyString_ConcatAndDel(&tmp, PyString_FromFormat("/%d", py_addr->ipv4_netmask));
183 			PyString_Concat(&tmp, tmp2);
235                        if (py_addr->ipv4_broadcast ) {
184 			Py_DECREF(tmp2);
236                                 PyString_ConcatAndDel(&tmp,
185 		}
237                                                       PyString_FromString("	  Broadcast: "));
186 		PyString_Concat(&tmp, PyString_FromString("\n"));
238                                 PyString_Concat(&tmp, py_addr->ipv4_broadcast);
187 		PyString_Concat(&ret, tmp);
239                        }
188 		Py_DECREF(tmp);
240                        PyString_ConcatAndDel(&tmp, PyString_FromString("\n"));
241                        PyString_ConcatAndDel(&ret, tmp);
242                }
189 	}
243 	}
190 
244 
191 	if( self->data->ethinfo->ipv6_addresses ) {
245 	if( self->data->ethinfo->ipv6_addresses ) {
192 		struct ipv6address *ipv6 = self->data->ethinfo->ipv6_addresses;
246 		struct ipv6address *ipv6 = self->data->ethinfo->ipv6_addresses;
193 		PyObject *tmp = PyString_FromFormat("\tIPv6 addresses:\n");
247 		PyObject *tmp = PyString_FromFormat("\tIPv6 addresses:\n");
194 		PyString_Concat(&ret, tmp);
248 		PyString_Concat(&ret, tmp);
195 		Py_DECREF(tmp);
249 		Py_DECREF(tmp);
196 		for( ; ipv6; ipv6 = ipv6->next) {
250 		for( ; ipv6; ipv6 = ipv6->next) {
197 			char scope[66];
251 			char scope[66];
198 
252 
199 			rtnl_scope2str(ipv6->scope, scope, 64);
253 			rtnl_scope2str(ipv6->scope, scope, 64);
200 			PyObject *addr = PyString_FromFormat("\t		[%s] %s/%i\n",
254 			PyObject *addr = PyString_FromFormat("\t		[%s] %s/%i\n",
201 							     scope, ipv6->address, ipv6->netmask);
255 							     scope, ipv6->address, ipv6->netmask);
202 			PyString_Concat(&ret, addr);
256 			PyString_Concat(&ret, addr);
203 			Py_DECREF(addr);
257 			Py_DECREF(addr);
204 		}
258 		}
205 	}
259 	}
260 	return ret;
261 }
262 
263 static PyObject *
264 _ethtool_etherinfo_get_ipv4_addresses(etherinfo_py *self, PyObject *notused) {
265 	PyObject *ret;
266 
267 	if( !self || !self->data ) {
268 		PyErr_SetString(PyExc_AttributeError, "No data available");
269 		return NULL;
270 	}
271 
272 	get_etherinfo(self->data, NLQRY_ADDR);
273 
274 	/* Transfer ownership of reference: */
275 	ret = self->data->ethinfo->ipv4_addresses;
276 	self->data->ethinfo->ipv4_addresses = NULL;
277 
206 	return ret;
278 	return ret;
207 }
279 }
208 
280 
209 
281 
210 /**
282 /**
211  * Returns a tuple list of ethertool.etherinfo_ipv6addr objects, containing configured
283  * Returns a tuple list of ethertool.etherinfo_ipv6addr objects, containing configured
212  * IPv6 addresses
284  * IPv6 addresses
213  *
285  *
214  * @param self
286  * @param self
215  * @param notused
287  * @param notused
216  *
288  *
217  * @return Returns a Python tuple list of ethertool.etherinfo_ipv6addr objects
289  * @return Returns a Python tuple list of ethertool.etherinfo_ipv6addr objects
218  */
290  */
219 PyObject * _ethtool_etherinfo_get_ipv6_addresses(etherinfo_py *self, PyObject *notused) {
291 PyObject * _ethtool_etherinfo_get_ipv6_addresses(etherinfo_py *self, PyObject *notused) {
220 	PyObject *ret;
292 	PyObject *ret;
221 	struct ipv6address *ipv6 = NULL;
293 	struct ipv6address *ipv6 = NULL;
222 	int i = 0;
294 	int i = 0;
223 
295 
224 	if( !self || !self->data ) {
296 	if( !self || !self->data ) {
225 		PyErr_SetString(PyExc_AttributeError, "No data available");
297 		PyErr_SetString(PyExc_AttributeError, "No data available");
226 		return NULL;
298 		return NULL;
227 	}
299 	}
228 
300 
229 	get_etherinfo(self->data, NLQRY_ADDR);
301 	get_etherinfo(self->data, NLQRY_ADDR);
230 	ipv6 = self->data->ethinfo->ipv6_addresses;
302 	ipv6 = self->data->ethinfo->ipv6_addresses;
231 	ret = PyTuple_New(1);
303 	ret = PyTuple_New(1);
232 	if( !ret ) {
304 	if( !ret ) {
233 		PyErr_SetString(PyExc_MemoryError,
305 		PyErr_SetString(PyExc_MemoryError,
234 				"[INTERNAL] Failed to allocate tuple list for "
306 				"[INTERNAL] Failed to allocate tuple list for "
235 				"IPv6 address objects");
307 				"IPv6 address objects");
236 		return NULL;
308 		return NULL;
237 	}
309 	}
238 	while( ipv6 ) {
310 	while( ipv6 ) {
239 		PyObject *ipv6_pyobj = NULL, *ipv6_pydata = NULL, *args = NULL;
311 		PyObject *ipv6_pyobj = NULL, *ipv6_pydata = NULL, *args = NULL;
240 		struct ipv6address *next = ipv6->next;
312 		struct ipv6address *next = ipv6->next;
241 
313 
242 		ipv6->next = NULL;
314 		ipv6->next = NULL;
243 		ipv6_pydata = PyCObject_FromVoidPtr(ipv6, NULL);
315 		ipv6_pydata = PyCObject_FromVoidPtr(ipv6, NULL);
244 		if( !ipv6_pydata ) {
316 		if( !ipv6_pydata ) {
245 			PyErr_SetString(PyExc_MemoryError,
317 			PyErr_SetString(PyExc_MemoryError,
246 					"[INTERNAL] Failed to create python object "
318 					"[INTERNAL] Failed to create python object "
247 					"containing IPv6 address");
319 					"containing IPv6 address");
248 			return NULL;
320 			return NULL;
249 		}
321 		}
250 		args = PyTuple_New(1);
322 		args = PyTuple_New(1);
251 		if( !args ) {
323 		if( !args ) {
252 			PyErr_SetString(PyExc_MemoryError,
324 			PyErr_SetString(PyExc_MemoryError,
253 					"[INTERNAL] Failed to allocate argument list "
325 					"[INTERNAL] Failed to allocate argument list "
254 					"a new IPv6 address object");
326 					"a new IPv6 address object");
255 			return NULL;
327 			return NULL;
256 		}
328 		}
257 		PyTuple_SetItem(args, 0, ipv6_pydata);
329 		PyTuple_SetItem(args, 0, ipv6_pydata);
258 		ipv6_pyobj = PyObject_CallObject((PyObject *)&ethtool_etherinfoIPv6Type, args);
330 		ipv6_pyobj = PyObject_CallObject((PyObject *)&ethtool_etherinfoIPv6Type, args);
259 		Py_DECREF(args);
331 		Py_DECREF(args);
260 		if( ipv6_pyobj ) {
332 		if( ipv6_pyobj ) {
261 			PyTuple_SetItem(ret, i++, ipv6_pyobj);
333 			PyTuple_SetItem(ret, i++, ipv6_pyobj);
262 			_PyTuple_Resize(&ret, i+1);
334 			_PyTuple_Resize(&ret, i+1);
263 		} else {
335 		} else {
264 			PyErr_SetString(PyExc_RuntimeError,
336 			PyErr_SetString(PyExc_RuntimeError,
265 					"[INTERNAL] Failed to initialise the new "
337 					"[INTERNAL] Failed to initialise the new "
266 					"IPv6 address object");
338 					"IPv6 address object");
267 			return NULL;
339 			return NULL;
268 		}
340 		}
269 		ipv6 = next;
341 		ipv6 = next;
270 	}
342 	}
271 	_PyTuple_Resize(&ret, i);
343 	_PyTuple_Resize(&ret, i);
272 	self->data->ethinfo->ipv6_addresses = NULL;
344 	self->data->ethinfo->ipv6_addresses = NULL;
273 	return ret;
345 	return ret;
274 }
346 }
275 
347 
276 
348 
277 /**
349 /**
278  * Defines all available methods in the ethtool.etherinfo class
350  * Defines all available methods in the ethtool.etherinfo class
279  *
351  *
280  */
352  */
281 static PyMethodDef _ethtool_etherinfo_methods[] = {
353 static PyMethodDef _ethtool_etherinfo_methods[] = {
282 	{"get_ipv6_addresses", _ethtool_etherinfo_get_ipv6_addresses, METH_NOARGS,
354 	{"get_ipv4_addresses", (PyCFunction)_ethtool_etherinfo_get_ipv4_addresses, METH_NOARGS,
355 	 "Retrieve configured IPv4 addresses.  Returns a list of NetlinkIP4Address objects"},
356 	{"get_ipv6_addresses", (PyCFunction)_ethtool_etherinfo_get_ipv6_addresses, METH_NOARGS,
283 	 "Retrieve configured IPv6 addresses.  Returns a tuple list of etherinfo_ipv6addr objects"},
357 	 "Retrieve configured IPv6 addresses.  Returns a tuple list of etherinfo_ipv6addr objects"},
284 	{NULL}  /**< No methods defined */
358 	{NULL}  /**< No methods defined */
285 };
286 
287 /**
288  * Defines all accessible object members
289  *
290  */
291 static PyMemberDef _ethtool_etherinfo_members[] = {
292     {"device", T_OBJECT_EX, offsetof(etherinfo_py, data), 0,
293      "Device name of the interface"},
294     {"mac_address", T_OBJECT_EX, offsetof(etherinfo_py, data), 0,
295      "MAC address / hardware address of the interface"},
296     {"ipv4_address", T_OBJECT_EX, offsetof(etherinfo_py, data), 0,
297      "IPv4 address"},
298     {"ipv4_netmask", T_INT, offsetof(etherinfo_py, data), 0,
299      "IPv4 netmask in bits"},
300     {"ipv4_broadcast", T_OBJECT_EX, offsetof(etherinfo_py, data), 0,
301      "IPv4 broadcast address"},
302     {NULL}  /* End of member list */
303 };
359 };
304 
360 
305 /**
361 /**
306  * Definition of the functions a Python class/object requires.
362  * Definition of the functions a Python class/object requires.
307  *
363  *
308  */
364  */
309 PyTypeObject ethtool_etherinfoType = {
365 PyTypeObject ethtool_etherinfoType = {
310     PyObject_HEAD_INIT(NULL)
366     PyObject_HEAD_INIT(NULL)
311     0,                         /*ob_size*/
367     0,                         /*ob_size*/
312     "ethtool.etherinfo",       /*tp_name*/
368     "ethtool.etherinfo",       /*tp_name*/
313     sizeof(etherinfo_py),      /*tp_basicsize*/
369     sizeof(etherinfo_py),      /*tp_basicsize*/
314     0,                         /*tp_itemsize*/
370     0,                         /*tp_itemsize*/
315     (destructor)_ethtool_etherinfo_dealloc,/*tp_dealloc*/
371     (destructor)_ethtool_etherinfo_dealloc,/*tp_dealloc*/
316     0,                         /*tp_print*/
372     0,                         /*tp_print*/
317     0,                         /*tp_getattr*/
373     0,                         /*tp_getattr*/
318     0,                         /*tp_setattr*/
374     0,                         /*tp_setattr*/
319     0,                         /*tp_compare*/
375     0,                         /*tp_compare*/
320     0,                         /*tp_repr*/
376     0,                         /*tp_repr*/
321     0,                         /*tp_as_number*/
377     0,                         /*tp_as_number*/
322     0,                         /*tp_as_sequence*/
378     0,                         /*tp_as_sequence*/
323     0,                         /*tp_as_mapping*/
379     0,                         /*tp_as_mapping*/
324     0,                         /*tp_hash */
380     0,                         /*tp_hash */
325     0,                         /*tp_call*/
381     0,                         /*tp_call*/
326     (reprfunc)_ethtool_etherinfo_str,        /*tp_str*/
382     (reprfunc)_ethtool_etherinfo_str,        /*tp_str*/
327     (getattrofunc)_ethtool_etherinfo_getter, /*tp_getattro*/
383     (getattrofunc)_ethtool_etherinfo_getter, /*tp_getattro*/
328     (setattrofunc)_ethtool_etherinfo_setter, /*tp_setattro*/
384     (setattrofunc)_ethtool_etherinfo_setter, /*tp_setattro*/
329     0,                         /*tp_as_buffer*/
385     0,                         /*tp_as_buffer*/
330     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
386     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
331     "Contains information about a specific ethernet device", /* tp_doc */
387     "Contains information about a specific ethernet device", /* tp_doc */
332     0,		               /* tp_traverse */
388     0,		               /* tp_traverse */
333     0,		               /* tp_clear */
389     0,		               /* tp_clear */
334     0,		               /* tp_richcompare */
390     0,		               /* tp_richcompare */
335     0,		               /* tp_weaklistoffset */
391     0,		               /* tp_weaklistoffset */
336     0,		               /* tp_iter */
392     0,		               /* tp_iter */
337     0,		               /* tp_iternext */
393     0,		               /* tp_iternext */
338     _ethtool_etherinfo_methods,            /* tp_methods */
394     _ethtool_etherinfo_methods,            /* tp_methods */
339     _ethtool_etherinfo_members,            /* tp_members */
395     0,                         /* tp_members */
340     0,                         /* tp_getset */
396     0,                         /* tp_getset */
341     0,                         /* tp_base */
397     0,                         /* tp_base */
342     0,                         /* tp_dict */
398     0,                         /* tp_dict */
343     0,                         /* tp_descr_get */
399     0,                         /* tp_descr_get */
344     0,                         /* tp_descr_set */
400     0,                         /* tp_descr_set */
345     0,                         /* tp_dictoffset */
401     0,                         /* tp_dictoffset */
346     (initproc)_ethtool_etherinfo_init,     /* tp_init */
402     (initproc)_ethtool_etherinfo_init,     /* tp_init */
347     0,                         /* tp_alloc */
403     0,                         /* tp_alloc */
348     _ethtool_etherinfo_new,                /* tp_new */
404     _ethtool_etherinfo_new,                /* tp_new */
349 };
405 };

Comparison of old/new python-ethtool/ethtool.c

New issues

Location Tool Test ID Function Issue
python-ethtool/ethtool.c:132:15 cpychecker usage-of-uninitialized-data get_devices comparison against uninitialized data (D.13623) at python-ethtool/ethtool.c:132
python-ethtool/ethtool.c:328:19 cpychecker null-ptr-argument get_interfaces_info calling PyTuple_SetItem with NULL as argument 1 (args) at python-ethtool/ethtool.c:328

Fixed issues

Location Tool Test ID Function Issue
python-ethtool/ethtool.c:132:0 cppcheck nullPointer Possible null pointer dereference: end - otherwise it is redundant to check it against null.
python-ethtool/ethtool.c:134:0 cppcheck nullPointer Possible null pointer dereference: end - otherwise it is redundant to check it against null.
python-ethtool/ethtool.c:139:16 cpychecker null-ptr-argument get_devices calling PyList_Append with NULL as argument 1 (list) at python-ethtool/ethtool.c:139
python-ethtool/ethtool.c:140:3 cpychecker null-ptr-dereference get_devices dereferencing NULL (str->ob_refcnt) at python-ethtool/ethtool.c:140
python-ethtool/ethtool.c:153:23 cpychecker mismatching-type-in-format-string get_hwaddress Mismatching type in call to PyArg_ParseTuple with format code "s"
python-ethtool/ethtool.c:200:23 cpychecker mismatching-type-in-format-string get_ipaddress Mismatching type in call to PyArg_ParseTuple with format code "s"
python-ethtool/ethtool.c:304:0 cppcheck memleak Memory leak: fetch_devs
python-ethtool/ethtool.c:351:23 cpychecker mismatching-type-in-format-string get_flags Mismatching type in call to PyArg_ParseTuple with format code "s"
python-ethtool/ethtool.c:388:23 cpychecker mismatching-type-in-format-string get_netmask Mismatching type in call to PyArg_ParseTuple with format code "s"
python-ethtool/ethtool.c:432:23 cpychecker mismatching-type-in-format-string get_broadcast Mismatching type in call to PyArg_ParseTuple with format code "s"
python-ethtool/ethtool.c:477:23 cpychecker mismatching-type-in-format-string get_module Mismatching type in call to PyArg_ParseTuple with format code "s"
python-ethtool/ethtool.c:519:0 cppcheck invalidScanfFormatWidth Width 100 given in format string (no. 1) is larger than destination buffer 'driver[100]', use %99s to prevent overflowing it.
python-ethtool/ethtool.c:519:0 cppcheck invalidScanfFormatWidth Width 100 given in format string (no. 2) is larger than destination buffer 'dev[100]', use %99s to prevent overflowing it.
python-ethtool/ethtool.c:550:23 cpychecker mismatching-type-in-format-string get_businfo Mismatching type in call to PyArg_ParseTuple with format code "s"
python-ethtool/ethtool.c:622:22 cpychecker mismatching-type-in-format-string get_dev_value Mismatching type in call to PyArg_ParseTuple with format code "s"
python-ethtool/ethtool.c:829:23 cpychecker mismatching-type-in-format-string set_coalesce Mismatching type in call to PyArg_ParseTuple with format code "sO"
python-ethtool/ethtool.c:869:23 cpychecker mismatching-type-in-format-string set_ringparam Mismatching type in call to PyArg_ParseTuple with format code "sO"

Issues in both old/new

Old location New location Tool Test ID Function Issue
python-ethtool/ethtool.c:114:8 python-ethtool/ethtool.c:114:8 gcc unused-but-set-variable get_devices variable 'ret' set but not used
python-ethtool/ethtool.c:123:32 python-ethtool/ethtool.c:123:32 clang-analyzer Value stored to 'ret' is never read
python-ethtool/ethtool.c:123:2 python-ethtool/ethtool.c:123:32 clang-analyzer Value stored to 'ret' is never read
python-ethtool/ethtool.c:123:2 python-ethtool/ethtool.c:123:2 clang-analyzer Value stored to 'ret' is never read
python-ethtool/ethtool.c:123:32 python-ethtool/ethtool.c:123:2 clang-analyzer Value stored to 'ret' is never read
python-ethtool/ethtool.c:144:1 python-ethtool/ethtool.c:144:1 cpychecker refcount-too-high get_devices ob_refcnt of '*list' is 1 too high
python-ethtool/ethtool.c:377:22 python-ethtool/ethtool.c:378:22 cpychecker mismatching-type-in-format-string get_flags Mismatching type in call to Py_BuildValue with format code "h"
python-ethtool/ethtool.c:599:0 python-ethtool/ethtool.c:600:0 cppcheck uninitvar Uninitialized variable: err
python-ethtool/ethtool.c:644:23 python-ethtool/ethtool.c:645:23 cpychecker mismatching-type-in-format-string dev_set_int_value Mismatching type in call to PyArg_ParseTuple with format code "si"
python-ethtool/ethtool.c:644:23 python-ethtool/ethtool.c:645:23 cpychecker mismatching-type-in-format-string dev_set_int_value Mismatching type in call to PyArg_ParseTuple with format code "si"
python-ethtool/ethtool.c:657:22 python-ethtool/ethtool.c:658:22 cpychecker mismatching-type-in-format-string get_tso Mismatching type in call to Py_BuildValue with format code "b"
python-ethtool/ethtool.c:658:1 python-ethtool/ethtool.c:659:1 cpychecker returns-NULL-without-setting-exception get_tso returning (PyObject*)NULL without setting an exception
python-ethtool/ethtool.c:667:1 python-ethtool/ethtool.c:668:1 cpychecker returns-NULL-without-setting-exception set_tso returning (PyObject*)NULL without setting an exception
python-ethtool/ethtool.c:676:22 python-ethtool/ethtool.c:677:22 cpychecker mismatching-type-in-format-string get_ufo Mismatching type in call to Py_BuildValue with format code "b"
python-ethtool/ethtool.c:677:1 python-ethtool/ethtool.c:678:1 cpychecker returns-NULL-without-setting-exception get_ufo returning (PyObject*)NULL without setting an exception
python-ethtool/ethtool.c:686:22 python-ethtool/ethtool.c:687:22 cpychecker mismatching-type-in-format-string get_gso Mismatching type in call to Py_BuildValue with format code "b"
python-ethtool/ethtool.c:687:1 python-ethtool/ethtool.c:688:1 cpychecker returns-NULL-without-setting-exception get_gso returning (PyObject*)NULL without setting an exception
python-ethtool/ethtool.c:696:22 python-ethtool/ethtool.c:697:22 cpychecker mismatching-type-in-format-string get_sg Mismatching type in call to Py_BuildValue with format code "b"
python-ethtool/ethtool.c:697:1 python-ethtool/ethtool.c:698:1 cpychecker returns-NULL-without-setting-exception get_sg returning (PyObject*)NULL without setting an exception
python-ethtool/ethtool.c:821:1 python-ethtool/ethtool.c:822:1 cpychecker returns-NULL-without-setting-exception get_coalesce returning (PyObject*)NULL without setting an exception
python-ethtool/ethtool.c:840:1 python-ethtool/ethtool.c:841:1 cpychecker returns-NULL-without-setting-exception set_coalesce returning (PyObject*)NULL without setting an exception
python-ethtool/ethtool.c:861:1 python-ethtool/ethtool.c:862:1 cpychecker returns-NULL-without-setting-exception get_ringparam returning (PyObject*)NULL without setting an exception
python-ethtool/ethtool.c:880:1 python-ethtool/ethtool.c:881:1 cpychecker returns-NULL-without-setting-exception set_ringparam returning (PyObject*)NULL without setting an exception

Failures in both old/new

Tool Old location New location Function stdout stderr returncode
cpychecker python-ethtool/ethtool.c:247:79 python-ethtool/ethtool.c:247:79 get_interfaces_info None this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed None
cpychecker python-ethtool/ethtool.c:470:1 python-ethtool/ethtool.c:471:1 get_module None this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed None
cpychecker python-ethtool/ethtool.c:993:20 python-ethtool/ethtool.c:994:20 initethtool None Traceback (most recent call last): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 130, in _check_refcounts self.options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts rep = impl_check_refcounts(ctxt, fun, options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts limits=limits) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces transitions = curstate.get_transitions() File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions return self._get_transitions_for_stmt(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt return self._get_transitions_for_GimpleCall(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall return meth(stmt, *args) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject s_success.cpython.steal_reference(v_value, stmt.loc) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference _steal_ref) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount check_isinstance(oldvalue, RefcountValue) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance raise TypeError('%s / %r is not an instance of %s' % (obj, obj, types)) TypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from python-ethtool/ethtool.c:993 / WithinRange(gcctype='long int', loc=gcc.Location(file='python-ethtool/ethtool.c', line=993), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of <class 'libcpychecker.refcounts.RefcountValue'> None
   1 /*
   1 /*
   2  * Copyright (C) 2008-2011 Red Hat Inc.
   2  * Copyright (C) 2008-2011 Red Hat Inc.
   3  *
   3  *
   4  * Arnaldo Carvalho de Melo <acme@redhat.com>
   4  * Arnaldo Carvalho de Melo <acme@redhat.com>
   5  * David Sommerseth <davids@redhat.com>
   5  * David Sommerseth <davids@redhat.com>
   6  *
   6  *
   7  * First bits from a Red Hat config tool by Harald Hoyer.
   7  * First bits from a Red Hat config tool by Harald Hoyer.
   8  *
   8  *
   9  * This application is free software; you can redistribute it and/or modify it
   9  * This application is free software; you can redistribute it and/or modify it
  10  * under the terms of the GNU General Public License as published by the Free
  10  * under the terms of the GNU General Public License as published by the Free
  11  * Software Foundation; version 2.
  11  * Software Foundation; version 2.
  12  *
  12  *
  13  * This application is distributed in the hope that it will be useful,
  13  * This application is distributed in the hope that it will be useful,
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16  * General Public License for more details.
  16  * General Public License for more details.
  17  */
  17  */
  18 #include <Python.h>
  18 #include <Python.h>
  19 
  19 
  20 #include <errno.h>
  20 #include <errno.h>
  21 #include <stddef.h>
  21 #include <stddef.h>
  22 #include <stdint.h>
  22 #include <stdint.h>
  23 #include <unistd.h>
  23 #include <unistd.h>
  24 #include <sys/socket.h>
  24 #include <sys/socket.h>
  25 #include <net/if.h>
  25 #include <net/if.h>
  26 #include <sys/socket.h>
  26 #include <sys/socket.h>
  27 #include <sys/ioctl.h>
  27 #include <sys/ioctl.h>
  28 #include <sys/types.h>
  28 #include <sys/types.h>
  29 
  29 
  30 #include "etherinfo_struct.h"
  30 #include "etherinfo_struct.h"
  31 #include "etherinfo_obj.h"
  31 #include "etherinfo_obj.h"
  32 #include "etherinfo.h"
  32 #include "etherinfo.h"
  33 
  33 
  34 static struct nl_handle *nlconnection = NULL;
  34 static struct nl_handle *nlconnection = NULL;
  35 unsigned int nlconnection_users = 0;  /* How many NETLINK users are active? */
  35 unsigned int nlconnection_users = 0;  /* How many NETLINK users are active? */
  36 extern PyTypeObject ethtool_etherinfoType;
  36 extern PyTypeObject ethtool_etherinfoType;
  37 extern PyTypeObject ethtool_etherinfoIPv6Type;
  37 extern PyTypeObject ethtool_etherinfoIPv6Type;
  38 
  38 
  39 #ifndef IFF_DYNAMIC
  39 #ifndef IFF_DYNAMIC
  40 #define IFF_DYNAMIC     0x8000          /* dialup device with changing addresses*/
  40 #define IFF_DYNAMIC     0x8000          /* dialup device with changing addresses*/
  41 #endif
  41 #endif
  42 
  42 
  43 typedef unsigned long long u64;
  43 typedef unsigned long long u64;
  44 typedef __uint32_t u32;
  44 typedef __uint32_t u32;
  45 typedef __uint16_t u16;
  45 typedef __uint16_t u16;
  46 typedef __uint8_t u8;
  46 typedef __uint8_t u8;
  47 
  47 
  48 #include "ethtool-copy.h"
  48 #include "ethtool-copy.h"
  49 #include <linux/sockios.h> /* for SIOCETHTOOL */
  49 #include <linux/sockios.h> /* for SIOCETHTOOL */
  50 
  50 
  51 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  51 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  52 
  52 
  53 #define _PATH_PROCNET_DEV "/proc/net/dev"
  53 #define _PATH_PROCNET_DEV "/proc/net/dev"
  54 
  54 
  55 static PyObject *get_active_devices(PyObject *self __unused, PyObject *args __unused)
  55 static PyObject *get_active_devices(PyObject *self __unused, PyObject *args __unused)
  56 {
  56 {
  57 	PyObject *list;
  57 	PyObject *list;
  58 	int numreqs = 30;
  58 	int numreqs = 30;
  59 	struct ifconf ifc;
  59 	struct ifconf ifc;
  60 	struct ifreq *ifr;
  60 	struct ifreq *ifr;
  61 	int n;
  61 	int n;
  62 
  62 
  63 	/* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
  63 	/* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
  64 	   (as of 2.1.128) */
  64 	   (as of 2.1.128) */
  65 	/* Open control socket. */
  65 	/* Open control socket. */
  66 	int skfd = socket(AF_INET, SOCK_DGRAM, 0);
  66 	int skfd = socket(AF_INET, SOCK_DGRAM, 0);
  67 
  67 
  68 	if (skfd < 0) {
  68 	if (skfd < 0) {
  69 		PyErr_SetString(PyExc_OSError, strerror(errno));
  69 		PyErr_SetString(PyExc_OSError, strerror(errno));
  70 		return NULL;
  70 		return NULL;
  71 	}
  71 	}
  72 
  72 
  73 	ifc.ifc_buf = NULL;
  73 	ifc.ifc_buf = NULL;
  74 	for (;;) {
  74 	for (;;) {
  75 		ifc.ifc_len = sizeof(struct ifreq) * numreqs;
  75 		ifc.ifc_len = sizeof(struct ifreq) * numreqs;
  76 		ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
  76 		ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
  77 
  77 
  78 		if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
  78 		if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
  79 			PyErr_SetString(PyExc_OSError, strerror(errno));
  79 			PyErr_SetString(PyExc_OSError, strerror(errno));
  80 			free(ifc.ifc_buf);
  80 			free(ifc.ifc_buf);
  81 			close(skfd);
  81 			close(skfd);
  82 			return NULL;
  82 			return NULL;
  83 		}
  83 		}
  84 
  84 
  85 		if (ifc.ifc_len == (int)sizeof(struct ifreq) * numreqs) {
  85 		if (ifc.ifc_len == (int)sizeof(struct ifreq) * numreqs) {
  86 			/* assume it overflowed and try again */
  86 			/* assume it overflowed and try again */
  87 			numreqs += 10;
  87 			numreqs += 10;
  88 			continue;
  88 			continue;
  89 		}
  89 		}
  90 		break;
  90 		break;
  91 	}
  91 	}
  92 
  92 
  93 	list = PyList_New(0);
  93 	list = PyList_New(0);
  94 	ifr = ifc.ifc_req;
  94 	ifr = ifc.ifc_req;
  95 	for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
  95 	for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
  96 		if (!(ioctl(skfd, SIOCGIFFLAGS, ifr) < 0))
  96 		if (!(ioctl(skfd, SIOCGIFFLAGS, ifr) < 0))
  97 			if (ifr->ifr_flags & IFF_UP) {
  97 			if (ifr->ifr_flags & IFF_UP) {
  98 				PyObject *str = PyString_FromString(ifr->ifr_name);
  98 				PyObject *str = PyString_FromString(ifr->ifr_name);
  99 				PyList_Append(list, str);
  99 				PyList_Append(list, str);
 100 				Py_DECREF(str);
 100 				Py_DECREF(str);
 101 			}
 101 			}
 102 			ifr++;
 102 			ifr++;
 103 	}
 103 	}
 104 
 104 
 105 	free(ifc.ifc_buf);
 105 	free(ifc.ifc_buf);
 106 	close(skfd);
 106 	close(skfd);
 107 
 107 
 108 	return list;
 108 	return list;
 109 }
 109 }
 110 
 110 
 111 static PyObject *get_devices(PyObject *self __unused, PyObject *args __unused)
 111 static PyObject *get_devices(PyObject *self __unused, PyObject *args __unused)
 112 {
 112 {
 113 	char buffer[256];
 113 	char buffer[256];
 114 	char *ret;;
 114 	char *ret;;
 115 	PyObject *list = PyList_New(0);
 115 	PyObject *list = PyList_New(0);
 116 	FILE *fd = fopen(_PATH_PROCNET_DEV, "r");
 116 	FILE *fd = fopen(_PATH_PROCNET_DEV, "r");
 117 
 117 
 118 	if (fd == NULL) {
 118 	if (fd == NULL) {
 119 		PyErr_SetString(PyExc_OSError, strerror(errno));
 119 		PyErr_SetString(PyExc_OSError, strerror(errno));
 120 		return NULL;
 120 		return NULL;
 121 	}
 121 	}
 122 	/* skip over first two lines */
 122 	/* skip over first two lines */
 123 	ret = fgets(buffer, 256, fd); ret = fgets(buffer, 256, fd);
 123 	ret = fgets(buffer, 256, fd); ret = fgets(buffer, 256, fd);
 124 	while (!feof(fd)) {
 124 	while (!feof(fd)) {
 125 		PyObject *str;
 125 		PyObject *str;
 126 		char *name = buffer;
 126 		char *name = buffer;
 127 		char *end = buffer;
 127 		char *end = buffer;
 128 
 128 
 129 		if (fgets(buffer, 256, fd) == NULL)
 129 		if (fgets(buffer, 256, fd) == NULL)
 130 			break;
 130 			break;
 131 		/* find colon */
 131 		/* find colon */
 132 		while (end && *end != ':')
 132 		while (*end && *end != ':')
 133 			end++;
 133 			end++;
 134 		*end = 0; /* terminate where colon was */
 134 		*end = 0; /* terminate where colon was */
 135 		while (*name == ' ')
 135 		while (*name == ' ')
 136 			name++; /* skip over leading whitespace if any */
 136 			name++; /* skip over leading whitespace if any */
 137 
 137 
 138 		str = PyString_FromString(name);
 138 		str = PyString_FromString(name);
 139 		PyList_Append(list, str);
 139 		PyList_Append(list, str);
 140 		Py_DECREF(str);
 140 		Py_DECREF(str);
 141 	}
 141 	}
 142 	fclose(fd);
 142 	fclose(fd);
 143 	return list;
 143 	return list;
 144 }
 144 }
 145 
 145 
 146 static PyObject *get_hwaddress(PyObject *self __unused, PyObject *args)
 146 static PyObject *get_hwaddress(PyObject *self __unused, PyObject *args)
 147 {
 147 {
 148 	struct ifreq ifr;
 148 	struct ifreq ifr;
 149 	int fd, err;
 149 	int fd, err;
 150 	char *devname;
 150 	const char *devname;
 151 	char hwaddr[20];
 151 	char hwaddr[20];
 152 
 152 
 153 	if (!PyArg_ParseTuple(args, "s", &devname))
 153 	if (!PyArg_ParseTuple(args, "s", &devname))
 154 		return NULL;
 154 		return NULL;
 155 
 155 
 156 	/* Setup our request structure. */
 156 	/* Setup our request structure. */
 157 	memset(&ifr, 0, sizeof(ifr));
 157 	memset(&ifr, 0, sizeof(ifr));
 158 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 158 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 159 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 159 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 160 
 160 
 161 	/* Open control socket. */
 161 	/* Open control socket. */
 162 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 162 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 163 	if (fd < 0) {
 163 	if (fd < 0) {
 164 		PyErr_SetString(PyExc_OSError, strerror(errno));
 164 		PyErr_SetString(PyExc_OSError, strerror(errno));
 165 		return NULL;
 165 		return NULL;
 166 	}
 166 	}
 167 
 167 
 168 	/* Get current settings. */
 168 	/* Get current settings. */
 169 	err = ioctl(fd, SIOCGIFHWADDR, &ifr);
 169 	err = ioctl(fd, SIOCGIFHWADDR, &ifr);
 170 	if (err < 0) {
 170 	if (err < 0) {
 171 		char buf[2048];
 171 		char buf[2048];
 172 		int eno = errno;
 172 		int eno = errno;
 173 
 173 
 174 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 174 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 175 		PyErr_SetString(PyExc_IOError, buf);
 175 		PyErr_SetString(PyExc_IOError, buf);
 176 		close(fd);
 176 		close(fd);
 177 		return NULL;
 177 		return NULL;
 178 	}
 178 	}
 179 
 179 
 180 	close(fd);
 180 	close(fd);
 181 
 181 
 182 	sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
 182 	sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
 183 		(unsigned int)ifr.ifr_hwaddr.sa_data[0] % 256,
 183 		(unsigned int)ifr.ifr_hwaddr.sa_data[0] % 256,
 184 		(unsigned int)ifr.ifr_hwaddr.sa_data[1] % 256,
 184 		(unsigned int)ifr.ifr_hwaddr.sa_data[1] % 256,
 185 		(unsigned int)ifr.ifr_hwaddr.sa_data[2] % 256,
 185 		(unsigned int)ifr.ifr_hwaddr.sa_data[2] % 256,
 186 		(unsigned int)ifr.ifr_hwaddr.sa_data[3] % 256,
 186 		(unsigned int)ifr.ifr_hwaddr.sa_data[3] % 256,
 187 		(unsigned int)ifr.ifr_hwaddr.sa_data[4] % 256,
 187 		(unsigned int)ifr.ifr_hwaddr.sa_data[4] % 256,
 188 		(unsigned int)ifr.ifr_hwaddr.sa_data[5] % 256);
 188 		(unsigned int)ifr.ifr_hwaddr.sa_data[5] % 256);
 189 
 189 
 190 	return PyString_FromString(hwaddr);
 190 	return PyString_FromString(hwaddr);
 191 }
 191 }
 192 
 192 
 193 static PyObject *get_ipaddress(PyObject *self __unused, PyObject *args)
 193 static PyObject *get_ipaddress(PyObject *self __unused, PyObject *args)
 194 {
 194 {
 195 	struct ifreq ifr;
 195 	struct ifreq ifr;
 196 	int fd, err;
 196 	int fd, err;
 197 	char *devname;
 197 	const char *devname;
 198 	char ipaddr[20];
 198 	char ipaddr[20];
 199 
 199 
 200 	if (!PyArg_ParseTuple(args, "s", &devname))
 200 	if (!PyArg_ParseTuple(args, "s", &devname))
 201 		return NULL;
 201 		return NULL;
 202 
 202 
 203 	/* Setup our request structure. */
 203 	/* Setup our request structure. */
 204 	memset(&ifr, 0, sizeof(ifr));
 204 	memset(&ifr, 0, sizeof(ifr));
 205 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 205 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 206 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 206 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 207 
 207 
 208 	/* Open control socket. */
 208 	/* Open control socket. */
 209 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 209 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 210 	if (fd < 0) {
 210 	if (fd < 0) {
 211 		PyErr_SetString(PyExc_OSError, strerror(errno));
 211 		PyErr_SetString(PyExc_OSError, strerror(errno));
 212 		return NULL;
 212 		return NULL;
 213 	}
 213 	}
 214 
 214 
 215 	/* Get current settings. */
 215 	/* Get current settings. */
 216 	err = ioctl(fd, SIOCGIFADDR, &ifr);
 216 	err = ioctl(fd, SIOCGIFADDR, &ifr);
 217 	if (err < 0) {
 217 	if (err < 0) {
 218 		char buf[2048];
 218 		char buf[2048];
 219 		int eno = errno;
 219 		int eno = errno;
 220 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 220 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 221 		PyErr_SetString(PyExc_IOError, buf);
 221 		PyErr_SetString(PyExc_IOError, buf);
 222 		close(fd);
 222 		close(fd);
 223 		return NULL;
 223 		return NULL;
 224 	}
 224 	}
 225 
 225 
 226 	close(fd);
 226 	close(fd);
 227 
 227 
 228 	sprintf(ipaddr, "%u.%u.%u.%u",
 228 	sprintf(ipaddr, "%u.%u.%u.%u",
 229 		(unsigned int)ifr.ifr_addr.sa_data[2] % 256,
 229 		(unsigned int)ifr.ifr_addr.sa_data[2] % 256,
 230 		(unsigned int)ifr.ifr_addr.sa_data[3] % 256,
 230 		(unsigned int)ifr.ifr_addr.sa_data[3] % 256,
 231 		(unsigned int)ifr.ifr_addr.sa_data[4] % 256,
 231 		(unsigned int)ifr.ifr_addr.sa_data[4] % 256,
 232 		(unsigned int)ifr.ifr_addr.sa_data[5] % 256);
 232 		(unsigned int)ifr.ifr_addr.sa_data[5] % 256);
 233 
 233 
 234 	return PyString_FromString(ipaddr);
 234 	return PyString_FromString(ipaddr);
 235 }
 235 }
 236 
 236 
 237 
 237 
 238 /**
 238 /**
 239  * Retrieves the current information about all interfaces.  All interfaces will be
 239  * Retrieves the current information about all interfaces.  All interfaces will be
 240  * returned as a list of objects per interface.
 240  * returned as a list of objects per interface.
 241  *
 241  *
 242  * @param self Not used
 242  * @param self Not used
 243  * @param args Python arguments
 243  * @param args Python arguments
 244  *
 244  *
 245  * @return Python list of objects on success, otherwise NULL.
 245  * @return Python list of objects on success, otherwise NULL.
 246  */
 246  */
 247 static PyObject *get_interfaces_info(PyObject *self __unused, PyObject *args) {
 247 static PyObject *get_interfaces_info(PyObject *self __unused, PyObject *args) {
 248 	PyObject *devlist = NULL, *ethinf_py = NULL;
 248 	PyObject *devlist = NULL, *ethinf_py = NULL;
 249 	PyObject *inargs = NULL;
 249 	PyObject *inargs = NULL;
 250 	char **fetch_devs;
 250 	char **fetch_devs = NULL;
 251 	int i = 0, fetch_devs_len = 0;
 251 	int i = 0, fetch_devs_len = 0;
 252 
 252 
 253 	if (!PyArg_ParseTuple(args, "|O", &inargs)) {
 253 	if (!PyArg_ParseTuple(args, "|O", &inargs)) {
 254 		PyErr_SetString(PyExc_LookupError,
 254 		PyErr_SetString(PyExc_LookupError,
 255 				"Argument must be either a string, list or a tuple");
 255 				"Argument must be either a string, list or a tuple");
 256 		return NULL;
 256 		return NULL;
 257 	}
 257 	}
 258 
 258 
 259 	/* Parse input arguments if we got them */
 259 	/* Parse input arguments if we got them */
 260 	if( inargs != NULL ) {
 260 	if( inargs != NULL ) {
 261 		if( PyString_Check(inargs) ) { /* Input argument is just a string */
 261 		if( PyString_Check(inargs) ) { /* Input argument is just a string */
 262 			fetch_devs_len = 1;
 262 			fetch_devs_len = 1;
 263 			fetch_devs = calloc(1, sizeof(char *));
 263 			fetch_devs = calloc(1, sizeof(char *));
 264 			fetch_devs[0] = PyString_AsString(inargs);
 264 			fetch_devs[0] = PyString_AsString(inargs);
 265 		} else if( PyTuple_Check(inargs) ) { /* Input argument is a tuple list with devices */
 265 		} else if( PyTuple_Check(inargs) ) { /* Input argument is a tuple list with devices */
 266 			int j = 0;
 266 			int j = 0;
 267 
 267 
 268 			fetch_devs_len = PyTuple_Size(inargs);
 268 			fetch_devs_len = PyTuple_Size(inargs);
 269 			fetch_devs = calloc(fetch_devs_len+1, sizeof(char *));
 269 			fetch_devs = calloc(fetch_devs_len+1, sizeof(char *));
 270 			for( i = 0; i < fetch_devs_len; i++ ) {
 270 			for( i = 0; i < fetch_devs_len; i++ ) {
 271 				PyObject *elmt = PyTuple_GetItem(inargs, i);
 271 				PyObject *elmt = PyTuple_GetItem(inargs, i);
 272 				if( elmt && PyString_Check(elmt) ) {
 272 				if( elmt && PyString_Check(elmt) ) {
 273 					fetch_devs[j++] = PyString_AsString(elmt);
 273 					fetch_devs[j++] = PyString_AsString(elmt);
 274 				}
 274 				}
 275 			}
 275 			}
 276 			fetch_devs_len = j;
 276 			fetch_devs_len = j;
 277 		} else if( PyList_Check(inargs) ) { /* Input argument is a list with devices */
 277 		} else if( PyList_Check(inargs) ) { /* Input argument is a list with devices */
 278 			int j = 0;
 278 			int j = 0;
 279 
 279 
 280 			fetch_devs_len = PyList_Size(inargs);
 280 			fetch_devs_len = PyList_Size(inargs);
 281 			fetch_devs = calloc(fetch_devs_len+1, sizeof(char *));
 281 			fetch_devs = calloc(fetch_devs_len+1, sizeof(char *));
 282 			for( i = 0; i < fetch_devs_len; i++ ) {
 282 			for( i = 0; i < fetch_devs_len; i++ ) {
 283 				PyObject *elmt = PyList_GetItem(inargs, i);
 283 				PyObject *elmt = PyList_GetItem(inargs, i);
 284 				if( elmt && PyString_Check(elmt) ) {
 284 				if( elmt && PyString_Check(elmt) ) {
 285 					fetch_devs[j++] = PyString_AsString(elmt);
 285 					fetch_devs[j++] = PyString_AsString(elmt);
 286 				}
 286 				}
 287 			}
 287 			}
 288 			fetch_devs_len = j;
 288 			fetch_devs_len = j;
 289 		} else {
 289 		} else {
 290 			PyErr_SetString(PyExc_LookupError,
 290 			PyErr_SetString(PyExc_LookupError,
 291 					"Argument must be either a string, list or a tuple");
 291 					"Argument must be either a string, list or a tuple");
 292 			return NULL;
 292 			return NULL;
 293 		}
 293 		}
 294 	}
 294 	}
 295 
 295 
 296 	devlist = PyList_New(0);
 296 	devlist = PyList_New(0);
 297 	for( i = 0; i < fetch_devs_len; i++ ) {
 297 	for( i = 0; i < fetch_devs_len; i++ ) {
 298 		struct etherinfo_obj_data *objdata = NULL;
 298 		struct etherinfo_obj_data *objdata = NULL;
 299 
 299 
 300 		/* Allocate memory for data structures for each device */
 300 		/* Allocate memory for data structures for each device */
 301 		objdata = calloc(1, sizeof(struct etherinfo_obj_data));
 301 		objdata = calloc(1, sizeof(struct etherinfo_obj_data));
 302 		if( !objdata ) {
 302 		if( !objdata ) {
 303 			PyErr_SetString(PyExc_OSError, strerror(errno));
 303 			PyErr_SetString(PyExc_OSError, strerror(errno));
 304 			free(fetch_devs);
 304 			return NULL;
 305 			return NULL;
 305 		}
 306 		}
 306 
 307 
 307 		objdata->ethinfo = calloc(1, sizeof(struct etherinfo));
 308 		objdata->ethinfo = calloc(1, sizeof(struct etherinfo));
 308 		if( !objdata->ethinfo ) {
 309 		if( !objdata->ethinfo ) {
 309 			PyErr_SetString(PyExc_OSError, strerror(errno));
 310 			PyErr_SetString(PyExc_OSError, strerror(errno));
 311 			free(fetch_devs);
 310 			return NULL;
 312 			return NULL;
 311 		}
 313 		}
 312 
 314 
 313 		/* Store the device name and a reference to the NETLINK connection for
 315 		/* Store the device name and a reference to the NETLINK connection for
 314 		 * objects to use when quering for device info
 316 		 * objects to use when quering for device info
 315 		 */
 317 		 */
 316 		objdata->ethinfo->device = strdup(fetch_devs[i]);
 318 		objdata->ethinfo->device = strdup(fetch_devs[i]);
 317 		objdata->ethinfo->index = -1;
 319 		objdata->ethinfo->index = -1;
 318 		objdata->nlc = &nlconnection;
 320 		objdata->nlc = &nlconnection;
 319 		objdata->nlc_users = &nlconnection_users;
 321 		objdata->nlc_users = &nlconnection_users;
 320 
 322 
 321 		/* Instantiate a new etherinfo object with the device information */
 323 		/* Instantiate a new etherinfo object with the device information */
 322 		ethinf_py = PyCObject_FromVoidPtr(objdata, NULL);
 324 		ethinf_py = PyCObject_FromVoidPtr(objdata, NULL);
 323 		if( ethinf_py ) {
 325 		if( ethinf_py ) {
 324 			/* Prepare the argument list for the object constructor */
 326 			/* Prepare the argument list for the object constructor */
 325 			PyObject *args = PyTuple_New(1);
 327 			PyObject *args = PyTuple_New(1);
 326 			PyTuple_SetItem(args, 0, ethinf_py);
 328 			PyTuple_SetItem(args, 0, ethinf_py);
 327 
 329 
 328 			/* Create the object */
 330 			/* Create the object */
 329 			PyObject *dev = PyObject_CallObject((PyObject *)&ethtool_etherinfoType, args);
 331 			PyObject *dev = PyObject_CallObject((PyObject *)&ethtool_etherinfoType, args);
 330 			if( dev ) {
 332 			if( dev ) {
 331 				PyList_Append(devlist, dev);
 333 				PyList_Append(devlist, dev);
 332 				Py_DECREF(dev);
 334 				Py_DECREF(dev);
 333 			}
 335 			}
 334 			Py_DECREF(args);
 336 			Py_DECREF(args);
 335 		}
 337 		}
 336 	}
 338 	}
 337 	if( fetch_devs_len > 0 ) {
 339 
 338 		free(fetch_devs);
 340 	free(fetch_devs);
 339 	}
 340 
 341 
 341 	return devlist;
 342 	return devlist;
 342 }
 343 }
 343 
 344 
 344 
 345 
 345 static PyObject *get_flags (PyObject *self __unused, PyObject *args)
 346 static PyObject *get_flags (PyObject *self __unused, PyObject *args)
 346 {
 347 {
 347 	struct ifreq ifr;
 348 	struct ifreq ifr;
 348 	char *devname;
 349 	const char *devname;
 349 	int fd, err;
 350 	int fd, err;
 350 
 351 
 351 	if (!PyArg_ParseTuple(args, "s", &devname))
 352 	if (!PyArg_ParseTuple(args, "s", &devname))
 352 		return NULL;
 353 		return NULL;
 353 
 354 
 354 	/* Setup our request structure. */
 355 	/* Setup our request structure. */
 355 	memset(&ifr, 0, sizeof(ifr));
 356 	memset(&ifr, 0, sizeof(ifr));
 356 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 357 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 357 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 358 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 358 
 359 
 359 	/* Open control socket. */
 360 	/* Open control socket. */
 360 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 361 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 361 	if (fd < 0) {
 362 	if (fd < 0) {
 362 		PyErr_SetString(PyExc_OSError, strerror(errno));
 363 		PyErr_SetString(PyExc_OSError, strerror(errno));
 363 		return NULL;
 364 		return NULL;
 364 	}
 365 	}
 365 	err = ioctl(fd, SIOCGIFFLAGS, &ifr);
 366 	err = ioctl(fd, SIOCGIFFLAGS, &ifr);
 366 	if(err < 0) {
 367 	if(err < 0) {
 367 		char buf[2048];
 368 		char buf[2048];
 368 		int eno = errno;
 369 		int eno = errno;
 369 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 370 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 370 		PyErr_SetString(PyExc_IOError, buf);
 371 		PyErr_SetString(PyExc_IOError, buf);
 371 		close(fd);
 372 		close(fd);
 372 		return NULL;
 373 		return NULL;
 373 	}
 374 	}
 374 
 375 
 375 	close(fd);
 376 	close(fd);
 376 
 377 
 377 	return Py_BuildValue("h", ifr.ifr_flags);
 378 	return Py_BuildValue("h", ifr.ifr_flags);
 378 
 379 
 379 
 380 
 380 }
 381 }
 381 static PyObject *get_netmask (PyObject *self __unused, PyObject *args)
 382 static PyObject *get_netmask (PyObject *self __unused, PyObject *args)
 382 {
 383 {
 383 	struct ifreq ifr;
 384 	struct ifreq ifr;
 384 	int fd, err;
 385 	int fd, err;
 385 	char *devname;
 386 	const char *devname;
 386 	char netmask[20];
 387 	char netmask[20];
 387 
 388 
 388 	if (!PyArg_ParseTuple(args, "s", &devname))
 389 	if (!PyArg_ParseTuple(args, "s", &devname))
 389 		return NULL;
 390 		return NULL;
 390 
 391 
 391 	/* Setup our request structure. */
 392 	/* Setup our request structure. */
 392 	memset(&ifr, 0, sizeof(ifr));
 393 	memset(&ifr, 0, sizeof(ifr));
 393 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 394 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 394 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 395 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 395 
 396 
 396 	/* Open control socket. */
 397 	/* Open control socket. */
 397 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 398 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 398 	if (fd < 0) {
 399 	if (fd < 0) {
 399 		PyErr_SetString(PyExc_OSError, strerror(errno));
 400 		PyErr_SetString(PyExc_OSError, strerror(errno));
 400 		return NULL;
 401 		return NULL;
 401 	}
 402 	}
 402 
 403 
 403 	/* Get current settings. */
 404 	/* Get current settings. */
 404 	err = ioctl(fd, SIOCGIFNETMASK, &ifr);
 405 	err = ioctl(fd, SIOCGIFNETMASK, &ifr);
 405 	if (err < 0) {
 406 	if (err < 0) {
 406 		char buf[2048];
 407 		char buf[2048];
 407 		int eno = errno;
 408 		int eno = errno;
 408 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 409 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 409 		PyErr_SetString(PyExc_IOError, buf);
 410 		PyErr_SetString(PyExc_IOError, buf);
 410 		close(fd);
 411 		close(fd);
 411 		return NULL;
 412 		return NULL;
 412 	}
 413 	}
 413 
 414 
 414 	close(fd);
 415 	close(fd);
 415 
 416 
 416 	sprintf(netmask, "%u.%u.%u.%u",
 417 	sprintf(netmask, "%u.%u.%u.%u",
 417 		(unsigned int)ifr.ifr_netmask.sa_data[2] % 256,
 418 		(unsigned int)ifr.ifr_netmask.sa_data[2] % 256,
 418 		(unsigned int)ifr.ifr_netmask.sa_data[3] % 256,
 419 		(unsigned int)ifr.ifr_netmask.sa_data[3] % 256,
 419 		(unsigned int)ifr.ifr_netmask.sa_data[4] % 256,
 420 		(unsigned int)ifr.ifr_netmask.sa_data[4] % 256,
 420 		(unsigned int)ifr.ifr_netmask.sa_data[5] % 256);
 421 		(unsigned int)ifr.ifr_netmask.sa_data[5] % 256);
 421 
 422 
 422 	return PyString_FromString(netmask);
 423 	return PyString_FromString(netmask);
 423 }
 424 }
 424 
 425 
 425 static PyObject *get_broadcast(PyObject *self __unused, PyObject *args)
 426 static PyObject *get_broadcast(PyObject *self __unused, PyObject *args)
 426 {
 427 {
 427 	struct ifreq ifr;
 428 	struct ifreq ifr;
 428 	int fd, err;
 429 	int fd, err;
 429 	char *devname;
 430 	const char *devname;
 430 	char broadcast[20];
 431 	char broadcast[20];
 431 
 432 
 432 	if (!PyArg_ParseTuple(args, "s", &devname))
 433 	if (!PyArg_ParseTuple(args, "s", &devname))
 433 		return NULL;
 434 		return NULL;
 434 
 435 
 435 	/* Setup our request structure. */
 436 	/* Setup our request structure. */
 436 	memset(&ifr, 0, sizeof(ifr));
 437 	memset(&ifr, 0, sizeof(ifr));
 437 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 438 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 438 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 439 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 439 
 440 
 440 	/* Open control socket. */
 441 	/* Open control socket. */
 441 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 442 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 442 	if (fd < 0) {
 443 	if (fd < 0) {
 443 		PyErr_SetString(PyExc_OSError, strerror(errno));
 444 		PyErr_SetString(PyExc_OSError, strerror(errno));
 444 		return NULL;
 445 		return NULL;
 445 	}
 446 	}
 446 
 447 
 447 	/* Get current settings. */
 448 	/* Get current settings. */
 448 	err = ioctl(fd, SIOCGIFBRDADDR, &ifr);
 449 	err = ioctl(fd, SIOCGIFBRDADDR, &ifr);
 449 	if (err < 0) {
 450 	if (err < 0) {
 450 		char buf[2048];
 451 		char buf[2048];
 451 		int eno = errno;
 452 		int eno = errno;
 452 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 453 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 453 		PyErr_SetString(PyExc_IOError, buf);
 454 		PyErr_SetString(PyExc_IOError, buf);
 454 		close(fd);
 455 		close(fd);
 455 		return NULL;
 456 		return NULL;
 456 	}
 457 	}
 457 
 458 
 458 	close(fd);
 459 	close(fd);
 459 
 460 
 460 	sprintf(broadcast, "%u.%u.%u.%u",
 461 	sprintf(broadcast, "%u.%u.%u.%u",
 461 		(unsigned int)ifr.ifr_broadaddr.sa_data[2] % 256,
 462 		(unsigned int)ifr.ifr_broadaddr.sa_data[2] % 256,
 462 		(unsigned int)ifr.ifr_broadaddr.sa_data[3] % 256,
 463 		(unsigned int)ifr.ifr_broadaddr.sa_data[3] % 256,
 463 		(unsigned int)ifr.ifr_broadaddr.sa_data[4] % 256,
 464 		(unsigned int)ifr.ifr_broadaddr.sa_data[4] % 256,
 464 		(unsigned int)ifr.ifr_broadaddr.sa_data[5] % 256);
 465 		(unsigned int)ifr.ifr_broadaddr.sa_data[5] % 256);
 465 
 466 
 466 	return PyString_FromString(broadcast);
 467 	return PyString_FromString(broadcast);
 467 }
 468 }
 468 
 469 
 469 static PyObject *get_module(PyObject *self __unused, PyObject *args)
 470 static PyObject *get_module(PyObject *self __unused, PyObject *args)
 470 {
 471 {
 471 	struct ethtool_cmd ecmd;
 472 	struct ethtool_cmd ecmd;
 472 	struct ifreq ifr;
 473 	struct ifreq ifr;
 473 	int fd, err;
 474 	int fd, err;
 474 	char buf[2048];
 475 	char buf[2048];
 475 	char *devname;
 476 	const char *devname;
 476 
 477 
 477 	if (!PyArg_ParseTuple(args, "s", &devname))
 478 	if (!PyArg_ParseTuple(args, "s", &devname))
 478 		return NULL;
 479 		return NULL;
 479 
 480 
 480 	/* Setup our control structures. */
 481 	/* Setup our control structures. */
 481 	memset(&ecmd, 0, sizeof(ecmd));
 482 	memset(&ecmd, 0, sizeof(ecmd));
 482 	memset(&ifr, 0, sizeof(ifr));
 483 	memset(&ifr, 0, sizeof(ifr));
 483 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 484 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 484 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 485 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 485 	ifr.ifr_data = (caddr_t) &buf;
 486 	ifr.ifr_data = (caddr_t) &buf;
 486 	ecmd.cmd = ETHTOOL_GDRVINFO;
 487 	ecmd.cmd = ETHTOOL_GDRVINFO;
 487 	memcpy(&buf, &ecmd, sizeof(ecmd));
 488 	memcpy(&buf, &ecmd, sizeof(ecmd));
 488 
 489 
 489 	/* Open control socket. */
 490 	/* Open control socket. */
 490 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 491 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 491 	if (fd < 0) {
 492 	if (fd < 0) {
 492 		PyErr_SetString(PyExc_OSError, strerror(errno));
 493 		PyErr_SetString(PyExc_OSError, strerror(errno));
 493 		return NULL;
 494 		return NULL;
 494 	}
 495 	}
 495 
 496 
 496 	/* Get current settings. */
 497 	/* Get current settings. */
 497 	err = ioctl(fd, SIOCETHTOOL, &ifr);
 498 	err = ioctl(fd, SIOCETHTOOL, &ifr);
 498 
 499 
 499 	if (err < 0) {  /* failed? */
 500 	if (err < 0) {  /* failed? */
 500 		int eno = errno;
 501 		int eno = errno;
 501 		FILE *file;
 502 		FILE *file;
 502 		int found = 0;
 503 		int found = 0;
 503 		char driver[100], dev[100];
 504 		char driver[101], dev[101];
 504 		close(fd);
 505 		close(fd);
 505 
 506 
 506 		/* Before bailing, maybe it is a PCMCIA/PC Card? */
 507 		/* Before bailing, maybe it is a PCMCIA/PC Card? */
 507 		file = fopen("/var/lib/pcmcia/stab", "r");
 508 		file = fopen("/var/lib/pcmcia/stab", "r");
 508 		if (file == NULL) {
 509 		if (file == NULL) {
 509 			sprintf(buf, "[Errno %d] %s", eno, strerror(eno));
 510 			sprintf(buf, "[Errno %d] %s", eno, strerror(eno));
 510 			PyErr_SetString(PyExc_IOError, buf);
 511 			PyErr_SetString(PyExc_IOError, buf);
 511 			return NULL;
 512 			return NULL;
 512 		}
 513 		}
 513 
 514 
 514 		while (!feof(file)) {
 515 		while (!feof(file)) {
 515 			if (fgets(buf, 2048, file) == NULL)
 516 			if (fgets(buf, 2048, file) == NULL)
 516 				break;
 517 				break;
 517 			buf[2047] = '\0';
 518 			buf[2047] = '\0';
 518 			if (strncmp(buf, "Socket", 6) != 0) {
 519 			if (strncmp(buf, "Socket", 6) != 0) {
 519 				if (sscanf(buf, "%*d\t%*s\t%100s\t%*d\t%100s\n", driver, dev) > 0) {
 520 				if (sscanf(buf, "%*d\t%*s\t%100s\t%*d\t%100s\n", driver, dev) > 0) {
 520 					driver[99] = '\0';
 521 					driver[99] = '\0';
 521 					dev[99] = '\0';
 522 					dev[99] = '\0';
 522 					if (strcmp(devname, dev) == 0) {
 523 					if (strcmp(devname, dev) == 0) {
 523 						found = 1;
 524 						found = 1;
 524 						break;
 525 						break;
 525 					}
 526 					}
 526 				}
 527 				}
 527 			}
 528 			}
 528 		}
 529 		}
 529 		fclose(file);
 530 		fclose(file);
 530 		if (!found) {
 531 		if (!found) {
 531 			sprintf(buf, "[Errno %d] %s", eno, strerror(eno));
 532 			sprintf(buf, "[Errno %d] %s", eno, strerror(eno));
 532 			PyErr_SetString(PyExc_IOError, buf);
 533 			PyErr_SetString(PyExc_IOError, buf);
 533 			return NULL;
 534 			return NULL;
 534 		} else
 535 		} else
 535 			return PyString_FromString(driver);
 536 			return PyString_FromString(driver);
 536 	}
 537 	}
 537 
 538 
 538 	close(fd);
 539 	close(fd);
 539 	return PyString_FromString(((struct ethtool_drvinfo *)buf)->driver);
 540 	return PyString_FromString(((struct ethtool_drvinfo *)buf)->driver);
 540 }
 541 }
 541 
 542 
 542 static PyObject *get_businfo(PyObject *self __unused, PyObject *args)
 543 static PyObject *get_businfo(PyObject *self __unused, PyObject *args)
 543 {
 544 {
 544 	struct ethtool_cmd ecmd;
 545 	struct ethtool_cmd ecmd;
 545 	struct ifreq ifr;
 546 	struct ifreq ifr;
 546 	int fd, err;
 547 	int fd, err;
 547 	char buf[1024];
 548 	char buf[1024];
 548 	char *devname;
 549 	const char *devname;
 549 
 550 
 550 	if (!PyArg_ParseTuple(args, "s", &devname))
 551 	if (!PyArg_ParseTuple(args, "s", &devname))
 551 		return NULL;
 552 		return NULL;
 552 
 553 
 553 	/* Setup our control structures. */
 554 	/* Setup our control structures. */
 554 	memset(&ecmd, 0, sizeof(ecmd));
 555 	memset(&ecmd, 0, sizeof(ecmd));
 555 	memset(&ifr, 0, sizeof(ifr));
 556 	memset(&ifr, 0, sizeof(ifr));
 556 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 557 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 557 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 558 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 558 	ifr.ifr_data = (caddr_t) &buf;
 559 	ifr.ifr_data = (caddr_t) &buf;
 559 	ecmd.cmd = ETHTOOL_GDRVINFO;
 560 	ecmd.cmd = ETHTOOL_GDRVINFO;
 560 	memcpy(&buf, &ecmd, sizeof(ecmd));
 561 	memcpy(&buf, &ecmd, sizeof(ecmd));
 561 
 562 
 562 	/* Open control socket. */
 563 	/* Open control socket. */
 563 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 564 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 564 	if (fd < 0) {
 565 	if (fd < 0) {
 565 		PyErr_SetString(PyExc_OSError, strerror(errno));
 566 		PyErr_SetString(PyExc_OSError, strerror(errno));
 566 		return NULL;
 567 		return NULL;
 567 	}
 568 	}
 568 
 569 
 569 	/* Get current settings. */
 570 	/* Get current settings. */
 570 	err = ioctl(fd, SIOCETHTOOL, &ifr);
 571 	err = ioctl(fd, SIOCETHTOOL, &ifr);
 571 
 572 
 572 	if (err < 0) {  /* failed? */
 573 	if (err < 0) {  /* failed? */
 573 		int eno = errno;
 574 		int eno = errno;
 574 		close(fd);
 575 		close(fd);
 575 
 576 
 576 		sprintf(buf, "[Errno %d] %s", eno, strerror(eno));
 577 		sprintf(buf, "[Errno %d] %s", eno, strerror(eno));
 577 		PyErr_SetString(PyExc_IOError, buf);
 578 		PyErr_SetString(PyExc_IOError, buf);
 578 		return NULL;
 579 		return NULL;
 579 	}
 580 	}
 580 
 581 
 581 	close(fd);
 582 	close(fd);
 582 	return PyString_FromString(((struct ethtool_drvinfo *)buf)->bus_info);
 583 	return PyString_FromString(((struct ethtool_drvinfo *)buf)->bus_info);
 583 }
 584 }
 584 
 585 
 585 static int send_command(int cmd, char *devname, void *value)
 586 static int send_command(int cmd, const char *devname, void *value)
 586 {
 587 {
 587 	/* Setup our request structure. */
 588 	/* Setup our request structure. */
 588 	int fd, err;
 589 	int fd, err;
 589 	struct ifreq ifr;
 590 	struct ifreq ifr;
 590 	struct ethtool_value *eval = value;
 591 	struct ethtool_value *eval = value;
 591 
 592 
 592 	memset(&ifr, 0, sizeof(ifr));
 593 	memset(&ifr, 0, sizeof(ifr));
 593 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 594 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 594 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 595 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 595 	ifr.ifr_data = (caddr_t)eval;
 596 	ifr.ifr_data = (caddr_t)eval;
 596 	eval->cmd = cmd;
 597 	eval->cmd = cmd;
 597 
 598 
 598 	/* Open control socket. */
 599 	/* Open control socket. */
 599 	fd = socket(AF_INET, SOCK_DGRAM, 0), err;
 600 	fd = socket(AF_INET, SOCK_DGRAM, 0), err;
 600 	if (fd < 0) {
 601 	if (fd < 0) {
 601 		PyErr_SetString(PyExc_OSError, strerror(errno));
 602 		PyErr_SetString(PyExc_OSError, strerror(errno));
 602 		return -1;
 603 		return -1;
 603 	}
 604 	}
 604 
 605 
 605 	/* Get current settings. */
 606 	/* Get current settings. */
 606 	err = ioctl(fd, SIOCETHTOOL, &ifr);
 607 	err = ioctl(fd, SIOCETHTOOL, &ifr);
 607 	if (err < 0) {
 608 	if (err < 0) {
 608 		char buf[2048];
 609 		char buf[2048];
 609 		sprintf(buf, "[Errno %d] %s", errno, strerror(errno));
 610 		sprintf(buf, "[Errno %d] %s", errno, strerror(errno));
 610 		PyErr_SetString(PyExc_IOError, buf);
 611 		PyErr_SetString(PyExc_IOError, buf);
 611 	}
 612 	}
 612 
 613 
 613 	close(fd);
 614 	close(fd);
 614 	return err;
 615 	return err;
 615 }
 616 }
 616 
 617 
 617 static int get_dev_value(int cmd, PyObject *args, void *value)
 618 static int get_dev_value(int cmd, PyObject *args, void *value)
 618 {
 619 {
 619 	char *devname;
 620 	const char *devname;
 620 	int err = -1;
 621 	int err = -1;
 621 
 622 
 622 	if (PyArg_ParseTuple(args, "s", &devname))
 623 	if (PyArg_ParseTuple(args, "s", &devname))
 623 		err = send_command(cmd, devname, value);
 624 		err = send_command(cmd, devname, value);
 624 
 625 
 625 	return err;
 626 	return err;
 626 }
 627 }
 627 
 628 
 628 static int get_dev_int_value(int cmd, PyObject *args, int *value)
 629 static int get_dev_int_value(int cmd, PyObject *args, int *value)
 629 {
 630 {
 630 	struct ethtool_value eval;
 631 	struct ethtool_value eval;
 631 	int rc = get_dev_value(cmd, args, &eval);
 632 	int rc = get_dev_value(cmd, args, &eval);
 632 
 633 
 633 	if (rc == 0)
 634 	if (rc == 0)
 634 		*value = *(int *)&eval.data;
 635 		*value = *(int *)&eval.data;
 635 
 636 
 636 	return rc;
 637 	return rc;
 637 }
 638 }
 638 
 639 
 639 static int dev_set_int_value(int cmd, PyObject *args)
 640 static int dev_set_int_value(int cmd, PyObject *args)
 640 {
 641 {
 641 	struct ethtool_value eval;
 642 	struct ethtool_value eval;
 642 	char *devname;
 643 	const char *devname;
 643 
 644 
 644 	if (!PyArg_ParseTuple(args, "si", &devname, &eval.data))
 645 	if (!PyArg_ParseTuple(args, "si", &devname, &eval.data))
 645 		return -1;
 646 		return -1;
 646 
 647 
 647 	return send_command(cmd, devname, &eval);
 648 	return send_command(cmd, devname, &eval);
 648 }
 649 }
 649 
 650 
 650 static PyObject *get_tso(PyObject *self __unused, PyObject *args)
 651 static PyObject *get_tso(PyObject *self __unused, PyObject *args)
 651 {
 652 {
 652 	int value = 0;
 653 	int value = 0;
 653 
 654 
 654 	if (get_dev_int_value(ETHTOOL_GTSO, args, &value) < 0)
 655 	if (get_dev_int_value(ETHTOOL_GTSO, args, &value) < 0)
 655 		return NULL;
 656 		return NULL;
 656 
 657 
 657 	return Py_BuildValue("b", value);
 658 	return Py_BuildValue("b", value);
 658 }
 659 }
 659 
 660 
 660 static PyObject *set_tso(PyObject *self __unused, PyObject *args)
 661 static PyObject *set_tso(PyObject *self __unused, PyObject *args)
 661 {
 662 {
 662 	if (dev_set_int_value(ETHTOOL_STSO, args) < 0)
 663 	if (dev_set_int_value(ETHTOOL_STSO, args) < 0)
 663 		return NULL;
 664 		return NULL;
 664 
 665 
 665 	Py_INCREF(Py_None);
 666 	Py_INCREF(Py_None);
 666 	return Py_None;
 667 	return Py_None;
 667 }
 668 }
 668 
 669 
 669 static PyObject *get_ufo(PyObject *self __unused, PyObject *args)
 670 static PyObject *get_ufo(PyObject *self __unused, PyObject *args)
 670 {
 671 {
 671 	int value = 0;
 672 	int value = 0;
 672 
 673 
 673 	if (get_dev_int_value(ETHTOOL_GUFO, args, &value) < 0)
 674 	if (get_dev_int_value(ETHTOOL_GUFO, args, &value) < 0)
 674 		return NULL;
 675 		return NULL;
 675 
 676 
 676 	return Py_BuildValue("b", value);
 677 	return Py_BuildValue("b", value);
 677 }
 678 }
 678 
 679 
 679 static PyObject *get_gso(PyObject *self __unused, PyObject *args)
 680 static PyObject *get_gso(PyObject *self __unused, PyObject *args)
 680 {
 681 {
 681 	int value = 0;
 682 	int value = 0;
 682 
 683 
 683 	if (get_dev_int_value(ETHTOOL_GGSO, args, &value) < 0)
 684 	if (get_dev_int_value(ETHTOOL_GGSO, args, &value) < 0)
 684 		return NULL;
 685 		return NULL;
 685 
 686 
 686 	return Py_BuildValue("b", value);
 687 	return Py_BuildValue("b", value);
 687 }
 688 }
 688 
 689 
 689 static PyObject *get_sg(PyObject *self __unused, PyObject *args)
 690 static PyObject *get_sg(PyObject *self __unused, PyObject *args)
 690 {
 691 {
 691 	int value = 0;
 692 	int value = 0;
 692 
 693 
 693 	if (get_dev_int_value(ETHTOOL_GSG, args, &value) < 0)
 694 	if (get_dev_int_value(ETHTOOL_GSG, args, &value) < 0)
 694 		return NULL;
 695 		return NULL;
 695 
 696 
 696 	return Py_BuildValue("b", value);
 697 	return Py_BuildValue("b", value);
 697 }
 698 }
 698 
 699 
 699 struct struct_desc {
 700 struct struct_desc {
 700 	char	       *name;
 701 	char	       *name;
 701 	unsigned short offset;
 702 	unsigned short offset;
 702 	unsigned short size;
 703 	unsigned short size;
 703 };
 704 };
 704 
 705 
 705 #define member_desc(type, member_name) { \
 706 #define member_desc(type, member_name) { \
 706 	.name = #member_name, \
 707 	.name = #member_name, \
 707 	.offset = offsetof(type, member_name), \
 708 	.offset = offsetof(type, member_name), \
 708 	.size = sizeof(((type *)0)->member_name), }
 709 	.size = sizeof(((type *)0)->member_name), }
 709 
 710 
 710 struct struct_desc ethtool_coalesce_desc[] = {
 711 struct struct_desc ethtool_coalesce_desc[] = {
 711 	member_desc(struct ethtool_coalesce, rx_coalesce_usecs),
 712 	member_desc(struct ethtool_coalesce, rx_coalesce_usecs),
 712 	member_desc(struct ethtool_coalesce, rx_max_coalesced_frames),
 713 	member_desc(struct ethtool_coalesce, rx_max_coalesced_frames),
 713 	member_desc(struct ethtool_coalesce, rx_coalesce_usecs_irq),
 714 	member_desc(struct ethtool_coalesce, rx_coalesce_usecs_irq),
 714 	member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_irq),
 715 	member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_irq),
 715 	member_desc(struct ethtool_coalesce, tx_coalesce_usecs),
 716 	member_desc(struct ethtool_coalesce, tx_coalesce_usecs),
 716 	member_desc(struct ethtool_coalesce, tx_max_coalesced_frames),
 717 	member_desc(struct ethtool_coalesce, tx_max_coalesced_frames),
 717 	member_desc(struct ethtool_coalesce, tx_coalesce_usecs_irq),
 718 	member_desc(struct ethtool_coalesce, tx_coalesce_usecs_irq),
 718 	member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_irq),
 719 	member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_irq),
 719 	member_desc(struct ethtool_coalesce, stats_block_coalesce_usecs),
 720 	member_desc(struct ethtool_coalesce, stats_block_coalesce_usecs),
 720 	member_desc(struct ethtool_coalesce, use_adaptive_rx_coalesce),
 721 	member_desc(struct ethtool_coalesce, use_adaptive_rx_coalesce),
 721 	member_desc(struct ethtool_coalesce, use_adaptive_tx_coalesce),
 722 	member_desc(struct ethtool_coalesce, use_adaptive_tx_coalesce),
 722 	member_desc(struct ethtool_coalesce, pkt_rate_low),
 723 	member_desc(struct ethtool_coalesce, pkt_rate_low),
 723 	member_desc(struct ethtool_coalesce, rx_coalesce_usecs_low),
 724 	member_desc(struct ethtool_coalesce, rx_coalesce_usecs_low),
 724 	member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_low),
 725 	member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_low),
 725 	member_desc(struct ethtool_coalesce, tx_coalesce_usecs_low),
 726 	member_desc(struct ethtool_coalesce, tx_coalesce_usecs_low),
 726 	member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_low),
 727 	member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_low),
 727 	member_desc(struct ethtool_coalesce, pkt_rate_high),
 728 	member_desc(struct ethtool_coalesce, pkt_rate_high),
 728 	member_desc(struct ethtool_coalesce, rx_coalesce_usecs_high),
 729 	member_desc(struct ethtool_coalesce, rx_coalesce_usecs_high),
 729 	member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_high),
 730 	member_desc(struct ethtool_coalesce, rx_max_coalesced_frames_high),
 730 	member_desc(struct ethtool_coalesce, tx_coalesce_usecs_high),
 731 	member_desc(struct ethtool_coalesce, tx_coalesce_usecs_high),
 731 	member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_high),
 732 	member_desc(struct ethtool_coalesce, tx_max_coalesced_frames_high),
 732 	member_desc(struct ethtool_coalesce, rate_sample_interval),
 733 	member_desc(struct ethtool_coalesce, rate_sample_interval),
 733 };
 734 };
 734 
 735 
 735 static PyObject *__struct_desc_create_dict(struct struct_desc *table,
 736 static PyObject *__struct_desc_create_dict(struct struct_desc *table,
 736 					   int nr_entries, void *values)
 737 					   int nr_entries, void *values)
 737 {
 738 {
 738 	int i;
 739 	int i;
 739 	PyObject *dict = PyDict_New();
 740 	PyObject *dict = PyDict_New();
 740 
 741 
 741 	if (dict == NULL)
 742 	if (dict == NULL)
 742 		goto out;
 743 		goto out;
 743 
 744 
 744 	for (i = 0; i < nr_entries; ++i) {
 745 	for (i = 0; i < nr_entries; ++i) {
 745 		struct struct_desc *d = &table[i];
 746 		struct struct_desc *d = &table[i];
 746 		PyObject *objval = NULL;
 747 		PyObject *objval = NULL;
 747 		void *val = values + d->offset;
 748 		void *val = values + d->offset;
 748 
 749 
 749 		switch (d->size) {
 750 		switch (d->size) {
 750 		case sizeof(uint32_t):
 751 		case sizeof(uint32_t):
 751 			objval = PyInt_FromLong(*(uint32_t *)val);
 752 			objval = PyInt_FromLong(*(uint32_t *)val);
 752 			break;
 753 			break;
 753 		}
 754 		}
 754 
 755 
 755 		if (objval == NULL)
 756 		if (objval == NULL)
 756 			goto free_dict;
 757 			goto free_dict;
 757 
 758 
 758 		if (PyDict_SetItemString(dict, d->name, objval) != 0) {
 759 		if (PyDict_SetItemString(dict, d->name, objval) != 0) {
 759 			Py_DECREF(objval);
 760 			Py_DECREF(objval);
 760 			goto free_dict;
 761 			goto free_dict;
 761 		}
 762 		}
 762 			
 763 			
 763 		Py_DECREF(objval);
 764 		Py_DECREF(objval);
 764 	}
 765 	}
 765 out:
 766 out:
 766 	return dict;
 767 	return dict;
 767 free_dict:
 768 free_dict:
 768 	goto out;
 769 	goto out;
 769 	dict = NULL;
 770 	dict = NULL;
 770 }
 771 }
 771 
 772 
 772 #define struct_desc_create_dict(table, values) \
 773 #define struct_desc_create_dict(table, values) \
 773 	__struct_desc_create_dict(table, ARRAY_SIZE(table), values)
 774 	__struct_desc_create_dict(table, ARRAY_SIZE(table), values)
 774 
 775 
 775 static int __struct_desc_from_dict(struct struct_desc *table,
 776 static int __struct_desc_from_dict(struct struct_desc *table,
 776 				   int nr_entries, void *to, PyObject *dict)
 777 				   int nr_entries, void *to, PyObject *dict)
 777 {
 778 {
 778 	char buf[2048];
 779 	char buf[2048];
 779 	int i;
 780 	int i;
 780 
 781 
 781 	for (i = 0; i < nr_entries; ++i) {
 782 	for (i = 0; i < nr_entries; ++i) {
 782 		struct struct_desc *d = &table[i];
 783 		struct struct_desc *d = &table[i];
 783 		void *val = to + d->offset;
 784 		void *val = to + d->offset;
 784 		PyObject *obj;
 785 		PyObject *obj;
 785 
 786 
 786 		switch (d->size) {
 787 		switch (d->size) {
 787 		case sizeof(uint32_t):
 788 		case sizeof(uint32_t):
 788 			obj = PyDict_GetItemString(dict, d->name);
 789 			obj = PyDict_GetItemString(dict, d->name);
 789 			if (obj == NULL) {
 790 			if (obj == NULL) {
 790 				snprintf(buf, sizeof(buf),
 791 				snprintf(buf, sizeof(buf),
 791 					"Missing dict entry for field %s",
 792 					"Missing dict entry for field %s",
 792 					d->name);
 793 					d->name);
 793 				PyErr_SetString(PyExc_IOError, buf);
 794 				PyErr_SetString(PyExc_IOError, buf);
 794 				return -1;
 795 				return -1;
 795 			}
 796 			}
 796 			*(uint32_t *)val = PyInt_AsLong(obj);
 797 			*(uint32_t *)val = PyInt_AsLong(obj);
 797 			break;
 798 			break;
 798 		default:
 799 		default:
 799 			snprintf(buf, sizeof(buf),
 800 			snprintf(buf, sizeof(buf),
 800 				 "Invalid type size %d for field %s",
 801 				 "Invalid type size %d for field %s",
 801 				 d->size, d->name);
 802 				 d->size, d->name);
 802 			PyErr_SetString(PyExc_IOError, buf);
 803 			PyErr_SetString(PyExc_IOError, buf);
 803 			return -1;
 804 			return -1;
 804 		}
 805 		}
 805 	}
 806 	}
 806 
 807 
 807 	return 0;
 808 	return 0;
 808 }
 809 }
 809 
 810 
 810 #define struct_desc_from_dict(table, to, dict) \
 811 #define struct_desc_from_dict(table, to, dict) \
 811 	__struct_desc_from_dict(table, ARRAY_SIZE(table), to, dict)
 812 	__struct_desc_from_dict(table, ARRAY_SIZE(table), to, dict)
 812 
 813 
 813 static PyObject *get_coalesce(PyObject *self __unused, PyObject *args)
 814 static PyObject *get_coalesce(PyObject *self __unused, PyObject *args)
 814 {
 815 {
 815 	struct ethtool_coalesce coal;
 816 	struct ethtool_coalesce coal;
 816 
 817 
 817 	if (get_dev_value(ETHTOOL_GCOALESCE, args, &coal) < 0)
 818 	if (get_dev_value(ETHTOOL_GCOALESCE, args, &coal) < 0)
 818 		return NULL;
 819 		return NULL;
 819 
 820 
 820 	return struct_desc_create_dict(ethtool_coalesce_desc, &coal);
 821 	return struct_desc_create_dict(ethtool_coalesce_desc, &coal);
 821 }
 822 }
 822 
 823 
 823 static PyObject *set_coalesce(PyObject *self __unused, PyObject *args)
 824 static PyObject *set_coalesce(PyObject *self __unused, PyObject *args)
 824 {
 825 {
 825 	struct ethtool_coalesce coal;
 826 	struct ethtool_coalesce coal;
 826 	char *devname;
 827 	const char *devname;
 827 	PyObject *dict;
 828 	PyObject *dict;
 828 
 829 
 829 	if (!PyArg_ParseTuple(args, "sO", &devname, &dict))
 830 	if (!PyArg_ParseTuple(args, "sO", &devname, &dict))
 830 		return NULL;
 831 		return NULL;
 831 
 832 
 832 	if (struct_desc_from_dict(ethtool_coalesce_desc, &coal, dict) != 0)
 833 	if (struct_desc_from_dict(ethtool_coalesce_desc, &coal, dict) != 0)
 833 		return NULL;
 834 		return NULL;
 834 
 835 
 835 	if (send_command(ETHTOOL_SCOALESCE, devname, &coal))
 836 	if (send_command(ETHTOOL_SCOALESCE, devname, &coal))
 836 		return NULL;
 837 		return NULL;
 837 
 838 
 838 	Py_INCREF(Py_None);
 839 	Py_INCREF(Py_None);
 839 	return Py_None;
 840 	return Py_None;
 840 }
 841 }
 841 
 842 
 842 struct struct_desc ethtool_ringparam_desc[] = {
 843 struct struct_desc ethtool_ringparam_desc[] = {
 843 	member_desc(struct ethtool_ringparam, rx_max_pending),
 844 	member_desc(struct ethtool_ringparam, rx_max_pending),
 844 	member_desc(struct ethtool_ringparam, rx_mini_max_pending),
 845 	member_desc(struct ethtool_ringparam, rx_mini_max_pending),
 845 	member_desc(struct ethtool_ringparam, rx_jumbo_max_pending),
 846 	member_desc(struct ethtool_ringparam, rx_jumbo_max_pending),
 846 	member_desc(struct ethtool_ringparam, tx_max_pending),
 847 	member_desc(struct ethtool_ringparam, tx_max_pending),
 847 	member_desc(struct ethtool_ringparam, rx_pending),
 848 	member_desc(struct ethtool_ringparam, rx_pending),
 848 	member_desc(struct ethtool_ringparam, rx_mini_pending),
 849 	member_desc(struct ethtool_ringparam, rx_mini_pending),
 849 	member_desc(struct ethtool_ringparam, rx_jumbo_pending),
 850 	member_desc(struct ethtool_ringparam, rx_jumbo_pending),
 850 	member_desc(struct ethtool_ringparam, tx_pending),
 851 	member_desc(struct ethtool_ringparam, tx_pending),
 851 };
 852 };
 852 
 853 
 853 static PyObject *get_ringparam(PyObject *self __unused, PyObject *args)
 854 static PyObject *get_ringparam(PyObject *self __unused, PyObject *args)
 854 {
 855 {
 855 	struct ethtool_ringparam ring;
 856 	struct ethtool_ringparam ring;
 856 
 857 
 857 	if (get_dev_value(ETHTOOL_GRINGPARAM, args, &ring) < 0)
 858 	if (get_dev_value(ETHTOOL_GRINGPARAM, args, &ring) < 0)
 858 		return NULL;
 859 		return NULL;
 859 
 860 
 860 	return struct_desc_create_dict(ethtool_ringparam_desc, &ring);
 861 	return struct_desc_create_dict(ethtool_ringparam_desc, &ring);
 861 }
 862 }
 862 
 863 
 863 static PyObject *set_ringparam(PyObject *self __unused, PyObject *args)
 864 static PyObject *set_ringparam(PyObject *self __unused, PyObject *args)
 864 {
 865 {
 865 	struct ethtool_ringparam ring;
 866 	struct ethtool_ringparam ring;
 866 	char *devname;
 867 	const char *devname;
 867 	PyObject *dict;
 868 	PyObject *dict;
 868 
 869 
 869 	if (!PyArg_ParseTuple(args, "sO", &devname, &dict))
 870 	if (!PyArg_ParseTuple(args, "sO", &devname, &dict))
 870 		return NULL;
 871 		return NULL;
 871 
 872 
 872 	if (struct_desc_from_dict(ethtool_ringparam_desc, &ring, dict) != 0)
 873 	if (struct_desc_from_dict(ethtool_ringparam_desc, &ring, dict) != 0)
 873 		return NULL;
 874 		return NULL;
 874 
 875 
 875 	if (send_command(ETHTOOL_SRINGPARAM, devname, &ring))
 876 	if (send_command(ETHTOOL_SRINGPARAM, devname, &ring))
 876 		return NULL;
 877 		return NULL;
 877 
 878 
 878 	Py_INCREF(Py_None);
 879 	Py_INCREF(Py_None);
 879 	return Py_None;
 880 	return Py_None;
 880 }
 881 }
 881 
 882 
 882 static struct PyMethodDef PyEthModuleMethods[] = {
 883 static struct PyMethodDef PyEthModuleMethods[] = {
 883 	{
 884 	{
 884 		.ml_name = "get_module",
 885 		.ml_name = "get_module",
 885 		.ml_meth = (PyCFunction)get_module,
 886 		.ml_meth = (PyCFunction)get_module,
 886 		.ml_flags = METH_VARARGS,
 887 		.ml_flags = METH_VARARGS,
 887 	},
 888 	},
 888 	{
 889 	{
 889 		.ml_name = "get_businfo",
 890 		.ml_name = "get_businfo",
 890 		.ml_meth = (PyCFunction)get_businfo,
 891 		.ml_meth = (PyCFunction)get_businfo,
 891 		.ml_flags = METH_VARARGS,
 892 		.ml_flags = METH_VARARGS,
 892 	},
 893 	},
 893 	{
 894 	{
 894 		.ml_name = "get_hwaddr",
 895 		.ml_name = "get_hwaddr",
 895 		.ml_meth = (PyCFunction)get_hwaddress,
 896 		.ml_meth = (PyCFunction)get_hwaddress,
 896 		.ml_flags = METH_VARARGS,
 897 		.ml_flags = METH_VARARGS,
 897 	},
 898 	},
 898 	{
 899 	{
 899 		.ml_name = "get_ipaddr",
 900 		.ml_name = "get_ipaddr",
 900 		.ml_meth = (PyCFunction)get_ipaddress,
 901 		.ml_meth = (PyCFunction)get_ipaddress,
 901 		.ml_flags = METH_VARARGS,
 902 		.ml_flags = METH_VARARGS,
 902 	},
 903 	},
 903 	{
 904 	{
 904 		.ml_name = "get_interfaces_info",
 905 		.ml_name = "get_interfaces_info",
 905 		.ml_meth = (PyCFunction)get_interfaces_info,
 906 		.ml_meth = (PyCFunction)get_interfaces_info,
 906 		.ml_flags = METH_VARARGS,
 907 		.ml_flags = METH_VARARGS,
 907 		.ml_doc = "Accepts a string, list or tupples of interface names. "
 908 		.ml_doc = "Accepts a string, list or tupples of interface names. "
 908 		"Returns a list of ethtool.etherinfo objets with device information."
 909 		"Returns a list of ethtool.etherinfo objets with device information."
 909 	},
 910 	},
 910 	{
 911 	{
 911 		.ml_name = "get_netmask",
 912 		.ml_name = "get_netmask",
 912 		.ml_meth = (PyCFunction)get_netmask,
 913 		.ml_meth = (PyCFunction)get_netmask,
 913 		.ml_flags = METH_VARARGS,
 914 		.ml_flags = METH_VARARGS,
 914 	},
 915 	},
 915 	{
 916 	{
 916 		.ml_name = "get_broadcast",
 917 		.ml_name = "get_broadcast",
 917 		.ml_meth = (PyCFunction)get_broadcast,
 918 		.ml_meth = (PyCFunction)get_broadcast,
 918 		.ml_flags = METH_VARARGS,
 919 		.ml_flags = METH_VARARGS,
 919 	},
 920 	},
 920 	{
 921 	{
 921 		.ml_name = "get_coalesce",
 922 		.ml_name = "get_coalesce",
 922 		.ml_meth = (PyCFunction)get_coalesce,
 923 		.ml_meth = (PyCFunction)get_coalesce,
 923 		.ml_flags = METH_VARARGS,
 924 		.ml_flags = METH_VARARGS,
 924 	},
 925 	},
 925 	{
 926 	{
 926 		.ml_name = "set_coalesce",
 927 		.ml_name = "set_coalesce",
 927 		.ml_meth = (PyCFunction)set_coalesce,
 928 		.ml_meth = (PyCFunction)set_coalesce,
 928 		.ml_flags = METH_VARARGS,
 929 		.ml_flags = METH_VARARGS,
 929 	},
 930 	},
 930 	{
 931 	{
 931 		.ml_name = "get_devices",
 932 		.ml_name = "get_devices",
 932 		.ml_meth = (PyCFunction)get_devices,
 933 		.ml_meth = (PyCFunction)get_devices,
 933 		.ml_flags = METH_VARARGS,
 934 		.ml_flags = METH_VARARGS,
 934 	},
 935 	},
 935 	{
 936 	{
 936 		.ml_name = "get_active_devices",
 937 		.ml_name = "get_active_devices",
 937 		.ml_meth = (PyCFunction)get_active_devices,
 938 		.ml_meth = (PyCFunction)get_active_devices,
 938 		.ml_flags = METH_VARARGS,
 939 		.ml_flags = METH_VARARGS,
 939 	},
 940 	},
 940 	{
 941 	{
 941 		.ml_name = "get_ringparam",
 942 		.ml_name = "get_ringparam",
 942 		.ml_meth = (PyCFunction)get_ringparam,
 943 		.ml_meth = (PyCFunction)get_ringparam,
 943 		.ml_flags = METH_VARARGS,
 944 		.ml_flags = METH_VARARGS,
 944 	},
 945 	},
 945 	{
 946 	{
 946 		.ml_name = "set_ringparam",
 947 		.ml_name = "set_ringparam",
 947 		.ml_meth = (PyCFunction)set_ringparam,
 948 		.ml_meth = (PyCFunction)set_ringparam,
 948 		.ml_flags = METH_VARARGS,
 949 		.ml_flags = METH_VARARGS,
 949 	},
 950 	},
 950 	{
 951 	{
 951 		.ml_name = "get_tso",
 952 		.ml_name = "get_tso",
 952 		.ml_meth = (PyCFunction)get_tso,
 953 		.ml_meth = (PyCFunction)get_tso,
 953 		.ml_flags = METH_VARARGS,
 954 		.ml_flags = METH_VARARGS,
 954 	},
 955 	},
 955 	{
 956 	{
 956 		.ml_name = "set_tso",
 957 		.ml_name = "set_tso",
 957 		.ml_meth = (PyCFunction)set_tso,
 958 		.ml_meth = (PyCFunction)set_tso,
 958 		.ml_flags = METH_VARARGS,
 959 		.ml_flags = METH_VARARGS,
 959 	},
 960 	},
 960 	{
 961 	{
 961 		.ml_name = "get_ufo",
 962 		.ml_name = "get_ufo",
 962 		.ml_meth = (PyCFunction)get_ufo,
 963 		.ml_meth = (PyCFunction)get_ufo,
 963 		.ml_flags = METH_VARARGS,
 964 		.ml_flags = METH_VARARGS,
 964 	},
 965 	},
 965 	{
 966 	{
 966 		.ml_name = "get_gso",
 967 		.ml_name = "get_gso",
 967 		.ml_meth = (PyCFunction)get_gso,
 968 		.ml_meth = (PyCFunction)get_gso,
 968 		.ml_flags = METH_VARARGS,
 969 		.ml_flags = METH_VARARGS,
 969 	},
 970 	},
 970 	{
 971 	{
 971 		.ml_name = "get_sg",
 972 		.ml_name = "get_sg",
 972 		.ml_meth = (PyCFunction)get_sg,
 973 		.ml_meth = (PyCFunction)get_sg,
 973 		.ml_flags = METH_VARARGS,
 974 		.ml_flags = METH_VARARGS,
 974 	},
 975 	},
 975 	{
 976 	{
 976 		.ml_name = "get_flags",
 977 		.ml_name = "get_flags",
 977 		.ml_meth = (PyCFunction)get_flags,
 978 		.ml_meth = (PyCFunction)get_flags,
 978 		.ml_flags = METH_VARARGS,
 979 		.ml_flags = METH_VARARGS,
 979 	},
 980 	},
 980 	{	.ml_name = NULL, },
 981 	{	.ml_name = NULL, },
 981 };
 982 };
 982 
 983 
 983 
 984 
 984 PyMODINIT_FUNC initethtool(void)
 985 PyMODINIT_FUNC initethtool(void)
 985 {
 986 {
 986 	PyObject *m;
 987 	PyObject *m;
 987 	m = Py_InitModule3("ethtool", PyEthModuleMethods, "Python ethtool module");
 988 	m = Py_InitModule3("ethtool", PyEthModuleMethods, "Python ethtool module");
 988 
 989 
 989 	// Prepare the ethtool.etherinfo class
 990 	// Prepare the ethtool.etherinfo class
 990 	if (PyType_Ready(&ethtool_etherinfoType) < 0)
 991 	if (PyType_Ready(&ethtool_etherinfoType) < 0)
 991 		return;
 992 		return;
 992 	Py_INCREF(&ethtool_etherinfoType);
 993 	Py_INCREF(&ethtool_etherinfoType);
 993 	PyModule_AddObject(m, "etherinfo", (PyObject *)&ethtool_etherinfoType);
Failure runninng cpychecker
stderr
Traceback (most recent call last): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 130, in _check_refcounts self.options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts rep = impl_check_refcounts(ctxt, fun, options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts limits=limits) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces transitions = curstate.get_transitions() File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions return self._get_transitions_for_stmt(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt return self._get_transitions_for_GimpleCall(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall return meth(stmt, *args) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject s_success.cpython.steal_reference(v_value, stmt.loc) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference _steal_ref) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount check_isinstance(oldvalue, RefcountValue) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance raise TypeError('%s / %r is not an instance of %s' % (obj, obj, types)) TypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from python-ethtool/ethtool.c:992 / WithinRange(gcctype='long int', loc=gcc.Location(file='python-ethtool/ethtool.c', line=992), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of <class 'libcpychecker.refcounts.RefcountValue'>
 994 	PyModule_AddObject(m, "etherinfo", (PyObject *)&ethtool_etherinfoType);
Failure runninng cpychecker
stderr
Traceback (most recent call last): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 130, in _check_refcounts self.options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts rep = impl_check_refcounts(ctxt, fun, options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts limits=limits) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces transitions = curstate.get_transitions() File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions return self._get_transitions_for_stmt(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt return self._get_transitions_for_GimpleCall(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall return meth(stmt, *args) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject s_success.cpython.steal_reference(v_value, stmt.loc) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference _steal_ref) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount check_isinstance(oldvalue, RefcountValue) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance raise TypeError('%s / %r is not an instance of %s' % (obj, obj, types)) TypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from python-ethtool/ethtool.c:993 / WithinRange(gcctype='long int', loc=gcc.Location(file='python-ethtool/ethtool.c', line=993), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of <class 'libcpychecker.refcounts.RefcountValue'>
 994 
 995 
 995 	// Prepare the ethtool.etherinfo_ipv6addr class
 996 	// Prepare the ethtool.etherinfo_ipv6addr class
 996 	if (PyType_Ready(&ethtool_etherinfoIPv6Type) < 0)
 997 	if (PyType_Ready(&ethtool_etherinfoIPv6Type) < 0)
 997 		return;
 998 		return;
 998 	Py_INCREF(&ethtool_etherinfoIPv6Type);
 999 	Py_INCREF(&ethtool_etherinfoIPv6Type);
 999 	PyModule_AddObject(m, "etherinfo_ipv6addr", (PyObject *)&ethtool_etherinfoIPv6Type);
1000 	PyModule_AddObject(m, "etherinfo_ipv6addr", (PyObject *)&ethtool_etherinfoIPv6Type);
1001 
1002 	if (PyType_Ready(&ethtool_netlink_ipv4_address_Type))
1003 		return;
1000 
1004 
1001 	// Setup constants
1005 	// Setup constants
1002 	PyModule_AddIntConstant(m, "IFF_UP", IFF_UP);			/* Interface is up. */
1006 	PyModule_AddIntConstant(m, "IFF_UP", IFF_UP);			/* Interface is up. */
1003 	PyModule_AddIntConstant(m, "IFF_BROADCAST", IFF_BROADCAST);	/* Broadcast address valid. */
1007 	PyModule_AddIntConstant(m, "IFF_BROADCAST", IFF_BROADCAST);	/* Broadcast address valid. */
1004 	PyModule_AddIntConstant(m, "IFF_DEBUG", IFF_DEBUG);		/* Turn on debugging. */
1008 	PyModule_AddIntConstant(m, "IFF_DEBUG", IFF_DEBUG);		/* Turn on debugging. */
1005 	PyModule_AddIntConstant(m, "IFF_LOOPBACK", IFF_LOOPBACK);	/* Is a loopback net */
1009 	PyModule_AddIntConstant(m, "IFF_LOOPBACK", IFF_LOOPBACK);	/* Is a loopback net */
1006 	PyModule_AddIntConstant(m, "IFF_POINTOPOINT", IFF_POINTOPOINT); /* Is a point-to-point link */
1010 	PyModule_AddIntConstant(m, "IFF_POINTOPOINT", IFF_POINTOPOINT); /* Is a point-to-point link */
1007 	PyModule_AddIntConstant(m, "IFF_NOTRAILERS", IFF_NOTRAILERS);	/* Avoid use of trailers */
1011 	PyModule_AddIntConstant(m, "IFF_NOTRAILERS", IFF_NOTRAILERS);	/* Avoid use of trailers */
1008 	PyModule_AddIntConstant(m, "IFF_RUNNING", IFF_RUNNING);		/* Resources allocated */
1012 	PyModule_AddIntConstant(m, "IFF_RUNNING", IFF_RUNNING);		/* Resources allocated */
1009 	PyModule_AddIntConstant(m, "IFF_NOARP", IFF_NOARP);		/* No address resolution protocol. */
1013 	PyModule_AddIntConstant(m, "IFF_NOARP", IFF_NOARP);		/* No address resolution protocol. */
1010 	PyModule_AddIntConstant(m, "IFF_PROMISC", IFF_PROMISC);		/* Receive all packets. */
1014 	PyModule_AddIntConstant(m, "IFF_PROMISC", IFF_PROMISC);		/* Receive all packets. */
1011 	PyModule_AddIntConstant(m, "IFF_ALLMULTI", IFF_ALLMULTI);	/* Receive all multicast packets. */
1015 	PyModule_AddIntConstant(m, "IFF_ALLMULTI", IFF_ALLMULTI);	/* Receive all multicast packets. */
1012 	PyModule_AddIntConstant(m, "IFF_MASTER", IFF_MASTER);		/* Master of a load balancer. */
1016 	PyModule_AddIntConstant(m, "IFF_MASTER", IFF_MASTER);		/* Master of a load balancer. */
1013 	PyModule_AddIntConstant(m, "IFF_SLAVE", IFF_SLAVE);		/* Slave of a load balancer. */
1017 	PyModule_AddIntConstant(m, "IFF_SLAVE", IFF_SLAVE);		/* Slave of a load balancer. */
1014 	PyModule_AddIntConstant(m, "IFF_MULTICAST", IFF_MULTICAST);	/* Supports multicast. */
1018 	PyModule_AddIntConstant(m, "IFF_MULTICAST", IFF_MULTICAST);	/* Supports multicast. */
1015 	PyModule_AddIntConstant(m, "IFF_PORTSEL", IFF_PORTSEL);		/* Can set media type. */
1019 	PyModule_AddIntConstant(m, "IFF_PORTSEL", IFF_PORTSEL);		/* Can set media type. */
1016 	PyModule_AddIntConstant(m, "IFF_AUTOMEDIA", IFF_AUTOMEDIA);	/* Auto media select active. */
1020 	PyModule_AddIntConstant(m, "IFF_AUTOMEDIA", IFF_AUTOMEDIA);	/* Auto media select active. */
1017 	PyModule_AddIntConstant(m, "IFF_DYNAMIC", IFF_DYNAMIC);		/* Dialup device with changing addresses.  */
1021 	PyModule_AddIntConstant(m, "IFF_DYNAMIC", IFF_DYNAMIC);		/* Dialup device with changing addresses.  */
1018 	PyModule_AddIntConstant(m, "AF_INET", AF_INET);                 /* IPv4 interface */
1022 	PyModule_AddIntConstant(m, "AF_INET", AF_INET);                 /* IPv4 interface */
1019 	PyModule_AddIntConstant(m, "AF_INET6", AF_INET6);               /* IPv6 interface */
1023 	PyModule_AddIntConstant(m, "AF_INET6", AF_INET6);               /* IPv6 interface */
1020 	PyModule_AddStringConstant(m, "version", "python-ethtool v" VERSION);
1024 	PyModule_AddStringConstant(m, "version", "python-ethtool v" VERSION);
1021 }
1025 }

Added file: python-ethtool/netlink-address.c

New failures

Incomplete coverage

Tool Location Function stdout stderr returncode
cpychecker python-ethtool/netlink-address.c:90:1 netlink_ipv4_address_repr None this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed None
  1 /*
  2  * Copyright (C) 2011, 2012 Red Hat Inc.
  3  *
  4  * David Malcolm <dmalcolm@redhat.com>
  5  *
  6  * This application is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License as published by the Free
  8  * Software Foundation; version 2.
  9  *
 10  * This application is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 13  * General Public License for more details.
 14  */
 15 
 16 /* Python object corresponding to a (struct rtnl_addr) */
 17 #include <Python.h>
 18 #include "structmember.h"
 19 
 20 #include <netlink/route/rtnl.h>
 21 #include "etherinfo_struct.h"
 22 #include "etherinfo.h"
 23 
 24 /* IPv4 Addresses: */
 25 static PyObject *
 26 PyNetlinkIPv4Address_from_rtnl_addr(struct nl_object *nl_obj, struct rtnl_addr *addr)
 27 {
 28 	PyNetlinkIPv4Address *py_obj;
 29 	char buf[INET_ADDRSTRLEN+1];
 30 	struct nl_addr *brdcst;
 31 
 32 	py_obj = PyObject_New(PyNetlinkIPv4Address,
 33 			      &ethtool_netlink_ipv4_address_Type);
 34 	if (!py_obj) {
 35 		return NULL;
 36 	}
 37 
 38 	/* Set ipv4_address: */
 39 	memset(&buf, 0, sizeof(buf));
 40 	if (!inet_ntop(AF_INET, nl_addr_get_binary_addr((struct nl_addr *)addr),
 41 		       buf, sizeof(buf))) {
 42 		PyErr_SetFromErrno(PyExc_RuntimeError);
 43 		goto error;
 44 	}
 45 	py_obj->ipv4_address = PyString_FromString(buf);
 46 	if (!py_obj->ipv4_address) {
 47 		goto error;
 48 	}
 49 
 50 	/* Set ipv4_netmask: */
 51 	py_obj->ipv4_netmask = rtnl_addr_get_prefixlen((struct rtnl_addr*)nl_obj);
 52 
 53 	/* Set ipv4_broadcast: */
 54 	py_obj->ipv4_broadcast = NULL;
 55 	brdcst = rtnl_addr_get_broadcast((struct rtnl_addr*)nl_obj);
 56 	if( brdcst ) {
 57 		memset(&buf, 0, sizeof(buf));
 58 		if (!inet_ntop(AF_INET, nl_addr_get_binary_addr(brdcst),
 59 			       buf, sizeof(buf))) {
 60 			PyErr_SetFromErrno(PyExc_RuntimeError);
 61 			goto error;
 62 		}
 63 		py_obj->ipv4_broadcast = PyString_FromString(buf);
 64 		if (!py_obj->ipv4_broadcast) {
 65 			goto error;
 66 		}
 67 	}
 68 
 69 	return (PyObject*)py_obj;
 70 
 71  error:
 72 	Py_DECREF(py_obj);
 73 	return NULL;
 74 }
 75 
 76 static void
 77 netlink_ipv4_address_dealloc(PyNetlinkIPv4Address *obj)
 78 {
 79 	Py_DECREF(obj->ipv4_address);
 80 	Py_XDECREF(obj->ipv4_broadcast);
 81 
 82 	/* We can call PyObject_Del directly rather than calling through
 83 	   tp_free since the type is not subtypable (Py_TPFLAGS_BASETYPE is
 84 	   not set): */
 85 	PyObject_Del(obj);
 86 }
 87 
 88 static PyObject*
 89 netlink_ipv4_address_repr(PyNetlinkIPv4Address *obj)
 90 {
 91 	PyObject *result = PyString_FromString("ethtool.NetlinkIPv4Address(address='");
 92 	PyString_Concat(&result, obj->ipv4_address);
 93 	PyString_ConcatAndDel(&result,
 94 			      PyString_FromFormat("', netmask=%d",
 95 						  obj->ipv4_netmask));
 96 	if (obj->ipv4_broadcast) {
 97 		PyString_ConcatAndDel(&result, PyString_FromString(", broadcast='"));
 98 		PyString_Concat(&result, obj->ipv4_broadcast);
 99 		PyString_ConcatAndDel(&result, PyString_FromString("'"));
100 	}
101 	PyString_ConcatAndDel(&result, PyString_FromString(")"));
102 	return result;
103 }
104 
105 static PyMemberDef _ethtool_netlink_ipv4_address_members[] = {
106 	{"address",
107 	 T_OBJECT_EX,
108 	 offsetof(PyNetlinkIPv4Address, ipv4_address),
109 	 0,
110 	 NULL},
111 	{"netmask",
112 	 T_INT,
113 	 offsetof(PyNetlinkIPv4Address, ipv4_netmask),
114 	 0,
115 	 NULL},
116 	{"broadcast",
117 	 T_OBJECT, /* can be NULL */
118 	 offsetof(PyNetlinkIPv4Address, ipv4_broadcast),
119 	 0,
120 	 NULL},
121 	{NULL}  /* End of member list */
122 };
123 
124 PyTypeObject ethtool_netlink_ipv4_address_Type = {
125 	PyVarObject_HEAD_INIT(0, 0)
126 	.tp_name = "ethtool.NetlinkIPv4Address",
127 	.tp_basicsize = sizeof(PyNetlinkIPv4Address),
128 	.tp_dealloc = (destructor)netlink_ipv4_address_dealloc,
129 	.tp_repr = (reprfunc)netlink_ipv4_address_repr,
130 	.tp_members = _ethtool_netlink_ipv4_address_members,
131 };
132 
133 /* Factory function, in case we want to generalize this to add IPv6 support */
134 PyObject *
135 make_python_address_from_rtnl_addr(struct nl_object *obj,
136 				   struct rtnl_addr *addr)
137 {
138 	int family;
139 	assert(addr);
140 
141 	family = nl_addr_get_family((struct nl_addr *)addr);
142 
143 	switch( family ) {
144 
145 	case AF_INET:
146 		return PyNetlinkIPv4Address_from_rtnl_addr(obj, addr);
147 
148 		/*
149 		  For now, we just support IPv4 addresses.
150 		*/
151 
152 	default:
153 		return PyErr_SetFromErrno(PyExc_RuntimeError);
154 	}
155 }
156 
157 /*
158 Local variables:
159 c-basic-offset: 8
160 indent-tabs-mode: y
161 End:
162 */