| Source file | clang-analyzer | cppcheck | cpychecker | gcc | Notes | 
|---|---|---|---|---|---|
| python-ethtool-0.7/python-ethtool/etherinfo.c | 0 | 0 | 0 | 0 | Incomplete coverage: 1 analysis failure(s) | 
| python-ethtool-0.7/python-ethtool/etherinfo_ipv6_obj.c | 0 | 0 | 0 | 0 | Incomplete coverage: 1 analysis failure(s) | 
| python-ethtool-0.7/python-ethtool/etherinfo_obj.c | 0 | 0 | 5 | 0 | Incomplete coverage: 2 analysis failure(s) | 
| python-ethtool-0.7/python-ethtool/ethtool.c | 2 | 6 | 29 | 1 | Incomplete coverage: 3 analysis failure(s) | 
No issues found
| Tool | Location | Function | stdout | stderr | returncode | 
|---|---|---|---|---|---|
| cpychecker | python-ethtool/etherinfo.c:282: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
  2  *
  3  * Copyright (C) 2009-2011 Red Hat Inc.
  4  *
  5  * David Sommerseth <davids@redhat.com>
  6  * Parts of this code is based on ideas and solutions in iproute2
  7  *
  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
 10  * Software Foundation; version 2.
 11  *
 12  * This application is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * General Public License for more details.
 16  */
 17 
 18 #include <Python.h>
 19 #include <bits/sockaddr.h>
 20 #include <stdio.h>
 21 #include <string.h>
 22 #include <sys/types.h>
 23 #include <unistd.h>
 24 #include <fcntl.h>
 25 #include <stdlib.h>
 26 #include <asm/types.h>
 27 #include <sys/socket.h>
 28 #include <netlink/route/rtnl.h>
 29 #include <assert.h>
 30 #include <errno.h>
 31 #include <pthread.h>
 32 #include "etherinfo_struct.h"
 33 #include "etherinfo.h"
 34 
 35 pthread_mutex_t nlc_counter_mtx = PTHREAD_MUTEX_INITIALIZER;
 36 
 37 /*
 38  *
 39  *   Internal functions for working with struct etherinfo
 40  *
 41  */
 42 
 43 /**
 44  * Simple macro which makes sure the destination string is freed if used earlier.
 45  *
 46  * @param dst Destination pointer
 47  * @param src Source pointer
 48  *
 49  */
 50 #define SET_STR_VALUE(dst, src) {	 \
 51 	if( dst ) {		 \
 52 		free(dst);	 \
 53 	};			 \
 54 	dst = strdup(src);	 \
 55 	}
 56 
 57 
 58 /**
 59  * Frees the memory used by a struct ipv6address pointer chain.  All elements are freed
 60  *
 61  * @param ptr  Pointer to a struct ipv6address chain.
 62  */
 63 void free_ipv6addresses(struct ipv6address *ptr) {
 64 	struct ipv6address *ipv6ptr = ptr;
 65 
 66 	while( ipv6ptr ) {
 67 		struct ipv6address *tmp = ipv6ptr->next;
 68 
 69 		if( ipv6ptr->address ) {
 70 			free(ipv6ptr->address);
 71 			ipv6ptr->address = NULL;
 72 		}
 73 		memset(ipv6ptr, 0, sizeof(struct ipv6address));
 74 		free(ipv6ptr);
 75 		ipv6ptr = tmp;
 76 	}
 77 }
 78 
 79 /**
 80  * Frees the memory used by struct etherinfo, including all struct ipv6address children.
 81  *
 82  * @param ptr Pointer to a struct etherninfo element
 83  */
 84 void free_etherinfo(struct etherinfo *ptr)
 85 {
 86 	if( ptr == NULL ) { // Just for safety
 87 		return;
 88 	}
 89 
 90 	free(ptr->device);
 91 
 92 	if( ptr->hwaddress ) {
 93 		free(ptr->hwaddress);
 94 	}
 95 	if( ptr->ipv4_address ) {
 96 		free(ptr->ipv4_address);
 97 	}
 98 	if( ptr->ipv4_broadcast ) {
 99 		free(ptr->ipv4_broadcast);
100 	}
101 	if( ptr->ipv6_addresses ) {
102 		free_ipv6addresses(ptr->ipv6_addresses);
103 	}
104 	free(ptr);
105 }
106 
107 
108 /**
109  * Add a new IPv6 address record to a struct ipv6address chain
110  *
111  * @param addrptr    Pointer to the current IPv6 address chain.
112  * @param addr       IPv6 address, represented as char * string
113  * @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()
115  *
116  * @return Returns a new pointer to the chain containing the new element
117  */
118 struct ipv6address * etherinfo_add_ipv6(struct ipv6address *addrptr, const char *addr, int netmask, int scope) {
119 	struct ipv6address *newaddr = NULL;
120 
121 	newaddr = calloc(1, sizeof(struct ipv6address)+2);
122 	if( !newaddr ) {
123 		fprintf(stderr, "** ERROR ** Could not allocate memory for a new IPv6 address record (%s/%i [%i])",
124 			addr, netmask, scope);
125 		return addrptr;
126 	}
127 
128 	SET_STR_VALUE(newaddr->address, addr);
129 	newaddr->netmask = netmask;
130 	newaddr->scope = scope;
131 	newaddr->next = addrptr;
132 	return newaddr;
133 }
134 
135 
136 /**
137  *  libnl callback function.  Does the real parsing of a record returned by NETLINK.  This function
138  *  parses LINK related packets
139  *
140  * @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
142  */
143 static void callback_nl_link(struct nl_object *obj, void *arg)
144 {
145 	struct etherinfo *ethi = (struct etherinfo *) arg;
146 	struct rtnl_link *link = (struct rtnl_link *) obj;
147 	struct nl_addr *addr = rtnl_link_get_addr(link);
148 	unsigned int i, len;
149 	unsigned char *binaddr;
150 	char hwaddr[130], *ptr;
151 
152 	if( (ethi == NULL) || (ethi->hwaddress != NULL) || (addr == NULL) ) {
153 		return;
154 	}
155 
156 	binaddr = nl_addr_get_binary_addr(addr);
157 	memset(&hwaddr, 0, 130);
158 	len = 20;
159 	ptr = (char *)&hwaddr;
160 	for( i = 0; i < 6; i++ ) {
161 		if( i == 0 ) {
162 			snprintf(ptr, len, "%02X", *(binaddr+i));
163 			len -= 2;
164 			ptr += 2;
165 		} else {
166 			snprintf(ptr, len, ":%02X", *(binaddr+i));
167 			len -= 3;
168 			ptr += 3;
169 		}
170 	}
171 	SET_STR_VALUE(ethi->hwaddress, hwaddr);
172 }
173 
174 
175 /**
176  *  libnl callback function.  Does the real parsing of a record returned by NETLINK.  This function
177  *  parses ADDRESS related packets
178  *
179  * @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
181  */
182 static void callback_nl_address(struct nl_object *obj, void *arg)
183 {
184 	struct etherinfo *ethi = (struct etherinfo *) arg;
185 	struct nl_addr *addr;
186 	char ip_str[66];
187 	int family;
188 
189 	if( ethi == NULL ) {
190 		return;
191 	}
192 
193 	addr = rtnl_addr_get_local((struct rtnl_addr *)obj);
194 	family = nl_addr_get_family(addr);
195 	switch( family ) {
196 	case AF_INET:
197 	case AF_INET6:
198 		memset(&ip_str, 0, 66);
199 		inet_ntop(family, nl_addr_get_binary_addr(addr), (char *)&ip_str, 64);
200 
201 		if( family == AF_INET ) {
202 			struct nl_addr *brdcst = rtnl_addr_get_broadcast((struct rtnl_addr *)obj);
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 {
214 			ethi->ipv6_addresses = etherinfo_add_ipv6(ethi->ipv6_addresses,
215 								  ip_str,
216 								  rtnl_addr_get_prefixlen((struct rtnl_addr*) obj),
217 								  rtnl_addr_get_scope((struct rtnl_addr*) obj));
218 		}
219 		return;
220 	default:
221 		return;
222 	}
223 }
224 
225 
226 
227 /*
228  *
229  *   Exported functions - API frontend
230  *
231  */
232 
233 /**
234  * Dumps the contents of a struct etherinfo element to file
235  *
236  * @param fp   FILE pointer where to dump
237  * @param ptr  Pointer to a struct etherinfo element
238  */
239 void dump_etherinfo(FILE *fp, struct etherinfo *ptr)
240 {
241 
242 	fprintf(fp, "*** Interface [%i] %s  ", ptr->index, ptr->device);
243 	if( ptr->hwaddress ) {
244 		fprintf(fp, "MAC address: %s", ptr->hwaddress);
245 	}
246 	fprintf(fp, "\n");
247 	if( ptr->ipv4_address ) {
248 		fprintf(fp, "\tIPv4 Address: %s/%i",
249 			ptr->ipv4_address, ptr->ipv4_netmask);
250 		if( ptr->ipv4_broadcast ) {
251 			fprintf(fp, "  -  Broadcast: %s", ptr->ipv4_broadcast);
252 		}
253 		fprintf(fp, "\n");
254 	}
255 	if( ptr->ipv6_addresses ) {
256 		struct ipv6address *ipv6 = ptr->ipv6_addresses;
257 
258 		fprintf(fp, "\tIPv6 addresses:\n");
259 		for(; ipv6; ipv6 = ipv6->next) {
260 			char scope[66];
261 
262 			rtnl_scope2str(ipv6->scope, scope, 64);
263 			fprintf(fp, "\t		       [%s] %s/%i\n",
264 				scope, ipv6->address, ipv6->netmask);
265 		}
266 	}
267 	fprintf(fp, "\n");
268 }
269 
270 
271 /**
272  * Query NETLINK for ethernet configuration
273  *
274  * @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
276  * @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.
278  *
279  * @return Returns 1 on success, otherwise 0.
280  */
281 int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query)
282 {
      stderr   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed283 	struct nl_cache *link_cache;
284 	struct nl_cache *addr_cache;
285 	struct rtnl_addr *addr;
286 	struct rtnl_link *link;
287 	struct etherinfo *ethinf = NULL;
288 	int ret = 0;
289 
290 	if( !data || !data->ethinfo ) {
291 		return 0;
292 	}
293 	ethinf = data->ethinfo;
294 
295 	/* Open a NETLINK connection on-the-fly */
296 	if( !open_netlink(data) ) {
297 		PyErr_Format(PyExc_RuntimeError,
298 			     "Could not open a NETLINK connection for %s",
299 			     ethinf->device);
300 		return 0;
301 	}
302 
303 	/* Find the interface index we're looking up.
304 	 * As we don't expect it to change, we're reusing a "cached"
305 	 * interface index if we have that
306 	 */
307 	if( ethinf->index < 0 ) {
308 		link_cache = rtnl_link_alloc_cache(*data->nlc);
309 		ethinf->index = rtnl_link_name2i(link_cache, ethinf->device);
310 		if( ethinf->index < 0 ) {
311 			return 0;
312 		}
313 		nl_cache_free(link_cache);
314 	}
315 
316 	/* Query the for requested info vai NETLINK */
317 	switch( query ) {
318 	case NLQRY_LINK:
319 		/* Extract MAC/hardware address of the interface */
320 		link_cache = rtnl_link_alloc_cache(*data->nlc);
321 		link = rtnl_link_alloc();
322 		rtnl_link_set_ifindex(link, ethinf->index);
323 		nl_cache_foreach_filter(link_cache, (struct nl_object *)link, callback_nl_link, ethinf);
324 		rtnl_link_put(link);
325 		nl_cache_free(link_cache);
326 		ret = 1;
327 		break;
328 
329 	case NLQRY_ADDR:
330 		/* Extract IP address information */
331 		addr_cache = rtnl_addr_alloc_cache(*data->nlc);
332 		addr = rtnl_addr_alloc();
333 		rtnl_addr_set_ifindex(addr, ethinf->index);
334 
335                 /* Make sure we don't have any old IPv6 addresses saved */
336                 if( ethinf->ipv6_addresses ) {
337                         free_ipv6addresses(ethinf->ipv6_addresses);
338                         ethinf->ipv6_addresses = NULL;
339                 }
340 
341                 /* Retrieve all address information */
342 		nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, callback_nl_address, ethinf);
343 		rtnl_addr_put(addr);
344 		nl_cache_free(addr_cache);
345 		ret = 1;
346 		break;
347 
348 	default:
349 		ret = 0;
350 	}
351 	return ret;
352 }
353 
354 
355 /**
356  * Connects to the NETLINK interface.  This will be called
357  * for each etherinfo object being generated, and it will
358  * keep a separate file descriptor open for each object
359  *
360  * @param data etherinfo_obj_data structure
361  *
362  * @return Returns 1 on success, otherwise 0.
363  */
364 int open_netlink(struct etherinfo_obj_data *data)
365 {
366 	if( !data ) {
367 		return 0;
368 	}
369 
370 	/* Reuse already established NETLINK connection, if a connection exists */
371 	if( *data->nlc ) {
372 		/* If this object has not used NETLINK earlier, tag it as a user */
373 		if( !data->nlc_active ) {
374 			pthread_mutex_lock(&nlc_counter_mtx);
375 			(*data->nlc_users)++;
376 			pthread_mutex_unlock(&nlc_counter_mtx);
377 		}
378 		data->nlc_active = 1;
379 		return 1;
380 	}
381 
382 	/* No earlier connections exists, establish a new one */
383 	*data->nlc = nl_handle_alloc();
384 	nl_connect(*data->nlc, NETLINK_ROUTE);
385 	if( (*data->nlc != NULL) ) {
386 		/* Force O_CLOEXEC flag on the NETLINK socket */
387 		if( fcntl(nl_socket_get_fd(*data->nlc), F_SETFD, FD_CLOEXEC) == -1 ) {
388 			fprintf(stderr,
389 				"**WARNING** Failed to set O_CLOEXEC on NETLINK socket: %s\n",
390 				strerror(errno));
391 		}
392 
393 		/* Tag this object as an active user */
394 		pthread_mutex_lock(&nlc_counter_mtx);
395 		(*data->nlc_users)++;
396 		pthread_mutex_unlock(&nlc_counter_mtx);
397 		data->nlc_active = 1;
398 		return 1;
399 	} else {
400 		return 0;
401 	}
402 }
403 
404 
405 /**
406  * Closes the NETLINK connection.  This should be called automatically whenever
407  * the corresponding etherinfo object is deleted.
408  *
409  * @param ptr  Pointer to the pointer of struct nl_handle, which contains the NETLINK connection
410  */
411 void close_netlink(struct etherinfo_obj_data *data)
412 {
413 	if( !data || !(*data->nlc) ) {
414 		return;
415 	}
416 
417 	/* Untag this object as a NETLINK user */
418 	data->nlc_active = 0;
419 	pthread_mutex_lock(&nlc_counter_mtx);
420 	(*data->nlc_users)--;
421 	pthread_mutex_unlock(&nlc_counter_mtx);
422 
423 	/* Don't close the connection if there are more users */
424 	if( *data->nlc_users > 0) {
425 		return;
426 	}
427 
428 	/* Close NETLINK connection */
429 	nl_close(*data->nlc);
430 	nl_handle_destroy(*data->nlc);
431 	*data->nlc = NULL;
432 }
No issues found
| Tool | Location | Function | stdout | stderr | returncode | 
|---|---|---|---|---|---|
| cpychecker | 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 /*
  2  * Copyright (C) 2009-2010 Red Hat Inc.
  3  *
  4  * David Sommerseth <davids@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 /**
 17  * @file   etherinfo_ipv6_obj.c
 18  * @author David Sommerseth <davids@redhat.com>
 19  * @date   Thu Jul 29 17:51:28 2010
 20  *
 21  * @brief  Python ethtool.etherinfo class functions.
 22  *
 23  */
 24 
 25 #include <Python.h>
 26 #include "structmember.h"
 27 
 28 #include <netlink/route/rtnl.h>
 29 #include "etherinfo_struct.h"
 30 #include "etherinfo.h"
 31 
 32 
 33 /**
 34  * ethtool.etherinfo_ipv6addr deallocator - cleans up when a object is deleted
 35  *
 36  * @param self etherinfo_ipv6addr_py object structure
 37  */
 38 void _ethtool_etherinfo_ipv6_dealloc(etherinfo_ipv6addr_py *self)
 39 {
 40 	if( self->addrdata ) {
 41 		free_ipv6addresses(self->addrdata);
 42 	}
 43 	self->ob_type->tp_free((PyObject*)self);
 44 }
 45 
 46 
 47 /**
 48  * ethtool.etherinfo_ipv6addr function, creating a new etherinfo object
 49  *
 50  * @param type
 51  * @param args
 52  * @param kwds
 53  *
 54  * @return Returns in PyObject with the new object on success, otherwise NULL
 55  */
 56 PyObject *_ethtool_etherinfo_ipv6_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 57 {
 58 	etherinfo_ipv6addr_py *self;
 59 
 60 	self = (etherinfo_ipv6addr_py *)type->tp_alloc(type, 0);
 61 	return (PyObject *)self;
 62 }
 63 
 64 
 65 /**
 66  * ethtool.etherinfo_ipv6addr init (constructor) method.  Makes sure the object is initialised correctly.
 67  *
 68  * @param self
 69  * @param args
 70  * @param kwds
 71  *
 72  * @return Returns 0 on success.
 73  */
 74 int _ethtool_etherinfo_ipv6_init(etherinfo_ipv6addr_py *self, PyObject *args, PyObject *kwds)
 75 {
 76 	static char *etherinfo_kwlist[] = {"etherinfo_ipv6_ptr", NULL};
 77 	PyObject *ethinf_ptr = NULL;
 78 
 79 	if( !PyArg_ParseTupleAndKeywords(args, kwds, "O", etherinfo_kwlist, ðinf_ptr)) {
 80 		PyErr_SetString(PyExc_AttributeError, "Invalid data pointer to constructor");
 81 		return -1;
 82 	}
 83 	self->addrdata = (struct ipv6address *) PyCObject_AsVoidPtr(ethinf_ptr);
 84 	return 0;
 85 }
 86 
 87 /**
 88  * ethtool.etherinfo_ipv6addr function for retrieving data from a Python object.
 89  *
 90  * @param self
 91  * @param attr_o  contains the object member request (which element to return)
 92  *
 93  * @return Returns a PyObject with the value requested on success, otherwise NULL
 94  */
 95 PyObject *_ethtool_etherinfo_ipv6_getter(etherinfo_ipv6addr_py *self, PyObject *attr_o)
 96 {
      stderr   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed 97 	PyObject *ret;
 98 	char *attr = PyString_AsString(attr_o);
 99 
100 	if( !self || !self->addrdata ) {
101 		PyErr_SetString(PyExc_AttributeError, "No data available");
102 		return NULL;
103 	}
104 
105 	if( strcmp(attr, "address") == 0 ) {
106 		ret = RETURN_STRING(self->addrdata->address);
107 	} else if( strcmp(attr, "netmask") == 0 ) {
108 		ret = PyInt_FromLong(self->addrdata->netmask);
109 	} else if( strcmp(attr, "scope") == 0 ) {
110 		char scope[66];
111 
112 		rtnl_scope2str(self->addrdata->scope, scope, 66);
113 		ret = PyString_FromString(scope);
114 	} else {
115 		ret = PyObject_GenericGetAttr((PyObject *)self, attr_o);
116 	}
117 	return ret;
118 }
119 
120 
121 /**
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.
124  *
125  * @param self
126  * @param attr_o
127  * @param val_o
128  *
129  * @return Returns always -1 (failure).
130  */
131 int _ethtool_etherinfo_ipv6_setter(etherinfo_ipv6addr_py *self, PyObject *attr_o, PyObject *val_o)
132 {
133 	PyErr_SetString(PyExc_AttributeError, "etherinfo_ipv6addr member values are read-only.");
134 	return -1;
135 }
136 
137 
138 /**
139  * Creates a human readable format of the information when object is being treated as a string
140  *
141  * @param self
142  *
143  * @return Returns a PyObject with a string with all of the information
144  */
145 PyObject *_ethtool_etherinfo_ipv6_str(etherinfo_ipv6addr_py *self)
146 {
147 	char scope[66];
148 
149 	if( !self || !self->addrdata ) {
150 		PyErr_SetString(PyExc_AttributeError, "No data available");
151 		return NULL;
152 	}
153 
154 	rtnl_scope2str(self->addrdata->scope, scope, 64);
155 	return PyString_FromFormat("[%s] %s/%i",
156 				   scope,
157 				   self->addrdata->address,
158 				   self->addrdata->netmask);
159 }
160 
161 
162 /**
163  * This is required by Python, which lists all accessible methods
164  * in the object.  But no methods are provided.
165  *
166  */
167 static PyMethodDef _ethtool_etherinfo_ipv6_methods[] = {
168     {NULL}  /**< No methods defined */
169 };
170 
171 /**
172  * Defines all accessible object members
173  *
174  */
175 static PyMemberDef _ethtool_etherinfo_ipv6_members[] = {
176     {"address", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0,
177      "IPv6 address"},
178     {"netmask", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0,
179      "IPv6 netmask"},
180     {"scope", T_OBJECT_EX, offsetof(etherinfo_ipv6addr_py, addrdata), 0,
181      "IPv6 IP address scope"},
182     {NULL}  /* End of member list */
183 };
184 
185 /**
186  * Definition of the functions a Python class/object requires.
187  *
188  */
189 PyTypeObject ethtool_etherinfoIPv6Type = {
190     PyObject_HEAD_INIT(NULL)
191     0,                         /*ob_size*/
192     "ethtool.etherinfo_ipv6addr", /*tp_name*/
193     sizeof(etherinfo_ipv6addr_py), /*tp_basicsize*/
194     0,                         /*tp_itemsize*/
195     (destructor)_ethtool_etherinfo_ipv6_dealloc,/*tp_dealloc*/
196     0,                         /*tp_print*/
197     0,                         /*tp_getattr*/
198     0,                         /*tp_setattr*/
199     0,                         /*tp_compare*/
200     0,                         /*tp_repr*/
201     0,                         /*tp_as_number*/
202     0,                         /*tp_as_sequence*/
203     0,                         /*tp_as_mapping*/
204     0,                         /*tp_hash */
205     0,                         /*tp_call*/
206     (reprfunc)_ethtool_etherinfo_ipv6_str,        /*tp_str*/
207     (getattrofunc)_ethtool_etherinfo_ipv6_getter, /*tp_getattro*/
208     (setattrofunc)_ethtool_etherinfo_ipv6_setter, /*tp_setattro*/
209     0,                         /*tp_as_buffer*/
210     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
211     "IPv6 address information", /* tp_doc */
212     0,		               /* tp_traverse */
213     0,		               /* tp_clear */
214     0,		               /* tp_richcompare */
215     0,		               /* tp_weaklistoffset */
216     0,		               /* tp_iter */
217     0,		               /* tp_iternext */
218     _ethtool_etherinfo_ipv6_methods,            /* tp_methods */
219     _ethtool_etherinfo_ipv6_members,            /* tp_members */
220     0,                         /* tp_getset */
221     0,                         /* tp_base */
222     0,                         /* tp_dict */
223     0,                         /* tp_descr_get */
224     0,                         /* tp_descr_set */
225     0,                         /* tp_dictoffset */
226     (initproc)_ethtool_etherinfo_ipv6_init,     /* tp_init */
227     0,                         /* tp_alloc */
228     _ethtool_etherinfo_ipv6_new,                /* tp_new */
229 };
| Location | Tool | Test ID | Function | Issue | 
|---|---|---|---|---|
| python-ethtool/etherinfo_obj.c:203:4 | cpychecker | null-ptr-dereference | _ethtool_etherinfo_str | dereferencing NULL (addr->ob_refcnt) at python-ethtool/etherinfo_obj.c:203 | 
| 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 | 
| python-ethtool/etherinfo_obj.c:274:1 | cpychecker | refcount-too-high | _ethtool_etherinfo_get_ipv6_addresses | ob_refcnt of '*ret.2' is 1 too high | 
| python-ethtool/etherinfo_obj.c:274:1 | cpychecker | refcount-too-high | _ethtool_etherinfo_get_ipv6_addresses | ob_refcnt of '*ipv6_pydata' is 1 too high | 
| Tool | Location | Function | stdout | stderr | returncode | 
|---|---|---|---|---|---|
| cpychecker | python-ethtool/etherinfo_obj.c:103: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 | _ethtool_etherinfo_str | None | this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed | None | 
  1 /*
  2  * Copyright (C) 2009-2011 Red Hat Inc.
  3  *
  4  * David Sommerseth <davids@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 
 17 /**
 18  * @file   etherinfo_obj.c
 19  * @author David Sommerseth <davids@redhat.com>
 20  * @date   Fri Sep  4 18:41:28 2009
 21  *
 22  * @brief  Python ethtool.etherinfo class functions.
 23  *
 24  */
 25 
 26 #include <Python.h>
 27 #include "structmember.h"
 28 
 29 #include <netlink/route/rtnl.h>
 30 #include "etherinfo_struct.h"
 31 #include "etherinfo.h"
 32 
 33 extern PyTypeObject ethtool_etherinfoIPv6Type;
 34 
 35 /**
 36  * ethtool.etherinfo deallocator - cleans up when a object is deleted
 37  *
 38  * @param self etherinfo_py object structure
 39  */
 40 void _ethtool_etherinfo_dealloc(etherinfo_py *self)
 41 {
 42 	if( self->data ) {
 43 		close_netlink(self->data);
 44 
 45 		if( self->data->ethinfo ) {
 46 			free_etherinfo(self->data->ethinfo);
 47 		}
 48 		free(self->data);
 49 	}
 50 	self->ob_type->tp_free((PyObject*)self);
 51 }
 52 
 53 
 54 /**
 55  * ethtool.etherinfo function, creating a new etherinfo object
 56  *
 57  * @param type
 58  * @param args
 59  * @param kwds
 60  *
 61  * @return Returns in PyObject with the new object on success, otherwise NULL
 62  */
 63 PyObject *_ethtool_etherinfo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 64 {
 65 	etherinfo_py *self;
 66 
 67 	self = (etherinfo_py *)type->tp_alloc(type, 0);
 68 	return (PyObject *)self;
 69 }
 70 
 71 
 72 /**
 73  * ethtool.etherinfo init (constructor) method.  Makes sure the object is initialised correctly.
 74  *
 75  * @param self
 76  * @param args
 77  * @param kwds
 78  *
 79  * @return Returns 0 on success.
 80  */
 81 int _ethtool_etherinfo_init(etherinfo_py *self, PyObject *args, PyObject *kwds)
 82 {
 83 	static char *etherinfo_kwlist[] = {"etherinfo_ptr", NULL};
 84 	PyObject *ethinf_ptr = NULL;
 85 
 86 	if( !PyArg_ParseTupleAndKeywords(args, kwds, "O", etherinfo_kwlist, ðinf_ptr)) {
 87 		PyErr_SetString(PyExc_AttributeError, "Invalid data pointer to constructor");
 88 		return -1;
 89 	}
 90 	self->data = (struct etherinfo_obj_data *) PyCObject_AsVoidPtr(ethinf_ptr);
 91 	return 0;
 92 }
 93 
 94 /**
 95  * ethtool.etherinfo function for retrieving data from a Python object.
 96  *
 97  * @param self
 98  * @param attr_o  contains the object member request (which element to return)
 99  *
100  * @return Returns a PyObject with the value requested on success, otherwise NULL
101  */
102 PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o)
103 {
      stderr   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed104 	PyObject *ret;
105 	char *attr = PyString_AsString(attr_o);
106 
107 	if( !self || !self->data ) {
108 		PyErr_SetString(PyExc_AttributeError, "No data available");
109 		return NULL;
110 	}
111 
112 	if( strcmp(attr, "device") == 0 ) {
113 		ret = RETURN_STRING(self->data->ethinfo->device);
114 	} else if( strcmp(attr, "mac_address") == 0 ) {
115 		get_etherinfo(self->data, NLQRY_LINK);
116 		ret = RETURN_STRING(self->data->ethinfo->hwaddress);
117 	} else if( strcmp(attr, "ipv4_address") == 0 ) {
118 		get_etherinfo(self->data, NLQRY_ADDR);
119 		ret = RETURN_STRING(self->data->ethinfo->ipv4_address);
120 	} else if( strcmp(attr, "ipv4_netmask") == 0 ) {
121 		get_etherinfo(self->data, NLQRY_ADDR);
122 		ret = PyInt_FromLong(self->data->ethinfo->ipv4_netmask);
123 	} else if( strcmp(attr, "ipv4_broadcast") == 0 ) {
124 		get_etherinfo(self->data, NLQRY_ADDR);
125 		ret = RETURN_STRING(self->data->ethinfo->ipv4_broadcast);
126 	} else {
127 		ret = PyObject_GenericGetAttr((PyObject *)self, attr_o);
128 	}
129 
130 	return ret;
131 }
132 
133 /**
134  * 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.
136  *
137  * @param self
138  * @param attr_o
139  * @param val_o
140  *
141  * @return Returns always -1 (failure).
142  */
143 int _ethtool_etherinfo_setter(etherinfo_py *self, PyObject *attr_o, PyObject *val_o)
144 {
145 	PyErr_SetString(PyExc_AttributeError, "etherinfo member values are read-only.");
146 	return -1;
147 }
148 
149 
150 /**
151  * Creates a human readable format of the information when object is being treated as a string
152  *
153  * @param self
154  *
155  * @return Returns a PyObject with a string with all of the information
156  */
157 PyObject *_ethtool_etherinfo_str(etherinfo_py *self)
158 {
      stderr   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed159 	PyObject *ret = NULL;
160 
161 	if( !self || !self->data || !self->data->nlc || !self->data->ethinfo ) {
162 		PyErr_SetString(PyExc_AttributeError, "No data available");
163 		return NULL;
164 	}
165 
166 	get_etherinfo(self->data, NLQRY_LINK);
167 	get_etherinfo(self->data, NLQRY_ADDR);
168 
169 	ret = PyString_FromFormat("Device %s:\n", self->data->ethinfo->device);
170 	if( self->data->ethinfo->hwaddress ) {
171 		PyObject *tmp = PyString_FromFormat("\tMAC address: %s\n", self->data->ethinfo->hwaddress);
172 		PyString_Concat(&ret, tmp);
173 		Py_DECREF(tmp);
174 	}
175 
176 	if( self->data->ethinfo->ipv4_address ) {
177 		PyObject *tmp = PyString_FromFormat("\tIPv4 address: %s/%i",
178 						   self->data->ethinfo->ipv4_address,
179 						   self->data->ethinfo->ipv4_netmask);
180 		if( self->data->ethinfo->ipv4_broadcast ) {
181 			PyObject *tmp2 = PyString_FromFormat("	  Broadcast: %s",
182 							     self->data->ethinfo->ipv4_broadcast);
183 			PyString_Concat(&tmp, tmp2);
184 			Py_DECREF(tmp2);
185 		}
186 		PyString_Concat(&tmp, PyString_FromString("\n"));
187 		PyString_Concat(&ret, tmp);
188 		Py_DECREF(tmp);
189 	}
190 
191 	if( self->data->ethinfo->ipv6_addresses ) {
192 		struct ipv6address *ipv6 = self->data->ethinfo->ipv6_addresses;
193 		PyObject *tmp = PyString_FromFormat("\tIPv6 addresses:\n");
194 		PyString_Concat(&ret, tmp);
195 		Py_DECREF(tmp);
196 		for( ; ipv6; ipv6 = ipv6->next) {
197 			char scope[66];
198 
199 			rtnl_scope2str(ipv6->scope, scope, 64);
200 			PyObject *addr = PyString_FromFormat("\t		[%s] %s/%i\n",
201 							     scope, ipv6->address, ipv6->netmask);
202 			PyString_Concat(&ret, addr);
203 			Py_DECREF(addr);
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
204 		}
205 	}
206 	return ret;
207 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
208 
209 
210 /**
211  * Returns a tuple list of ethertool.etherinfo_ipv6addr objects, containing configured
212  * IPv6 addresses
213  *
214  * @param self
215  * @param notused
216  *
217  * @return Returns a Python tuple list of ethertool.etherinfo_ipv6addr objects
218  */
219 PyObject * _ethtool_etherinfo_get_ipv6_addresses(etherinfo_py *self, PyObject *notused) {
220 	PyObject *ret;
221 	struct ipv6address *ipv6 = NULL;
222 	int i = 0;
223 
224 	if( !self || !self->data ) {
225 		PyErr_SetString(PyExc_AttributeError, "No data available");
226 		return NULL;
227 	}
228 
229 	get_etherinfo(self->data, NLQRY_ADDR);
230 	ipv6 = self->data->ethinfo->ipv6_addresses;
231 	ret = PyTuple_New(1);
232 	if( !ret ) {
233 		PyErr_SetString(PyExc_MemoryError,
234 				"[INTERNAL] Failed to allocate tuple list for "
235 				"IPv6 address objects");
236 		return NULL;
237 	}
238 	while( ipv6 ) {
239 		PyObject *ipv6_pyobj = NULL, *ipv6_pydata = NULL, *args = NULL;
240 		struct ipv6address *next = ipv6->next;
241 
242 		ipv6->next = NULL;
243 		ipv6_pydata = PyCObject_FromVoidPtr(ipv6, NULL);
244 		if( !ipv6_pydata ) {
245 			PyErr_SetString(PyExc_MemoryError,
246 					"[INTERNAL] Failed to create python object "
247 					"containing IPv6 address");
248 			return NULL;
249 		}
250 		args = PyTuple_New(1);
251 		if( !args ) {
252 			PyErr_SetString(PyExc_MemoryError,
253 					"[INTERNAL] Failed to allocate argument list "
254 					"a new IPv6 address object");
255 			return NULL;
256 		}
257 		PyTuple_SetItem(args, 0, ipv6_pydata);
258 		ipv6_pyobj = PyObject_CallObject((PyObject *)ðtool_etherinfoIPv6Type, args);
259 		Py_DECREF(args);
260 		if( ipv6_pyobj ) {
261 			PyTuple_SetItem(ret, i++, ipv6_pyobj);
262 			_PyTuple_Resize(&ret, i+1);
263 		} else {
264 			PyErr_SetString(PyExc_RuntimeError,
265 					"[INTERNAL] Failed to initialise the new "
266 					"IPv6 address object");
267 			return NULL;
268 		}
269 		ipv6 = next;
270 	}
271 	_PyTuple_Resize(&ret, i);
272 	self->data->ethinfo->ipv6_addresses = NULL;
273 	return ret;
274 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
275 
276 
277 /**
278  * Defines all available methods in the ethtool.etherinfo class
279  *
280  */
281 static PyMethodDef _ethtool_etherinfo_methods[] = {
282 	{"get_ipv6_addresses", _ethtool_etherinfo_get_ipv6_addresses, METH_NOARGS,
283 	 "Retrieve configured IPv6 addresses.  Returns a tuple list of etherinfo_ipv6addr objects"},
284 	{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 };
304 
305 /**
306  * Definition of the functions a Python class/object requires.
307  *
308  */
309 PyTypeObject ethtool_etherinfoType = {
310     PyObject_HEAD_INIT(NULL)
311     0,                         /*ob_size*/
312     "ethtool.etherinfo",       /*tp_name*/
313     sizeof(etherinfo_py),      /*tp_basicsize*/
314     0,                         /*tp_itemsize*/
315     (destructor)_ethtool_etherinfo_dealloc,/*tp_dealloc*/
316     0,                         /*tp_print*/
317     0,                         /*tp_getattr*/
318     0,                         /*tp_setattr*/
319     0,                         /*tp_compare*/
320     0,                         /*tp_repr*/
321     0,                         /*tp_as_number*/
322     0,                         /*tp_as_sequence*/
323     0,                         /*tp_as_mapping*/
324     0,                         /*tp_hash */
325     0,                         /*tp_call*/
326     (reprfunc)_ethtool_etherinfo_str,        /*tp_str*/
327     (getattrofunc)_ethtool_etherinfo_getter, /*tp_getattro*/
328     (setattrofunc)_ethtool_etherinfo_setter, /*tp_setattro*/
329     0,                         /*tp_as_buffer*/
330     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
331     "Contains information about a specific ethernet device", /* tp_doc */
332     0,		               /* tp_traverse */
333     0,		               /* tp_clear */
334     0,		               /* tp_richcompare */
335     0,		               /* tp_weaklistoffset */
336     0,		               /* tp_iter */
337     0,		               /* tp_iternext */
338     _ethtool_etherinfo_methods,            /* tp_methods */
339     _ethtool_etherinfo_members,            /* tp_members */
340     0,                         /* tp_getset */
341     0,                         /* tp_base */
342     0,                         /* tp_dict */
343     0,                         /* tp_descr_get */
344     0,                         /* tp_descr_set */
345     0,                         /* tp_dictoffset */
346     (initproc)_ethtool_etherinfo_init,     /* tp_init */
347     0,                         /* tp_alloc */
348     _ethtool_etherinfo_new,                /* tp_new */
349 };
| Location | Tool | Test ID | Function | Issue | 
|---|---|---|---|---|
| python-ethtool/ethtool.c:114:8 | gcc | unused-but-set-variable | get_devices | variable 'ret' set but not used | 
| python-ethtool/ethtool.c:123:2 | clang-analyzer | Value stored to 'ret' is never read | ||
| python-ethtool/ethtool.c:123:32 | clang-analyzer | Value stored to 'ret' is never read | ||
| 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:144:1 | cpychecker | refcount-too-high | get_devices | ob_refcnt of '*list' is 1 too high | 
| 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:377:22 | cpychecker | mismatching-type-in-format-string | get_flags | Mismatching type in call to Py_BuildValue with format code "h" | 
| 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:599:0 | cppcheck | uninitvar | Uninitialized variable: err | |
| 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:644: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 | 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 | 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 | cpychecker | returns-NULL-without-setting-exception | get_tso | returning (PyObject*)NULL without setting an exception | 
| python-ethtool/ethtool.c:667:1 | cpychecker | returns-NULL-without-setting-exception | set_tso | returning (PyObject*)NULL without setting an exception | 
| python-ethtool/ethtool.c:676: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 | cpychecker | returns-NULL-without-setting-exception | get_ufo | returning (PyObject*)NULL without setting an exception | 
| python-ethtool/ethtool.c:686: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 | cpychecker | returns-NULL-without-setting-exception | get_gso | returning (PyObject*)NULL without setting an exception | 
| python-ethtool/ethtool.c:696: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 | cpychecker | returns-NULL-without-setting-exception | get_sg | returning (PyObject*)NULL without setting an exception | 
| python-ethtool/ethtool.c:821:1 | cpychecker | returns-NULL-without-setting-exception | get_coalesce | returning (PyObject*)NULL without setting an exception | 
| 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:840:1 | cpychecker | returns-NULL-without-setting-exception | set_coalesce | returning (PyObject*)NULL without setting an exception | 
| python-ethtool/ethtool.c:861:1 | cpychecker | returns-NULL-without-setting-exception | get_ringparam | returning (PyObject*)NULL without setting an exception | 
| 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" | 
| python-ethtool/ethtool.c:880:1 | cpychecker | returns-NULL-without-setting-exception | set_ringparam | returning (PyObject*)NULL without setting an exception | 
   1 /*
   2  * Copyright (C) 2008-2011 Red Hat Inc.
   3  *
   4  * Arnaldo Carvalho de Melo <acme@redhat.com>
   5  * David Sommerseth <davids@redhat.com>
   6  *
   7  * First bits from a Red Hat config tool by Harald Hoyer.
   8  *
   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
  11  * Software Foundation; version 2.
  12  *
  13  * This application is distributed in the hope that it will be useful,
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16  * General Public License for more details.
  17  */
  18 #include <Python.h>
  19 
  20 #include <errno.h>
  21 #include <stddef.h>
  22 #include <stdint.h>
  23 #include <unistd.h>
  24 #include <sys/socket.h>
  25 #include <net/if.h>
  26 #include <sys/socket.h>
  27 #include <sys/ioctl.h>
  28 #include <sys/types.h>
  29 
  30 #include "etherinfo_struct.h"
  31 #include "etherinfo_obj.h"
  32 #include "etherinfo.h"
  33 
  34 static struct nl_handle *nlconnection = NULL;
  35 unsigned int nlconnection_users = 0;  /* How many NETLINK users are active? */
  36 extern PyTypeObject ethtool_etherinfoType;
  37 extern PyTypeObject ethtool_etherinfoIPv6Type;
  38 
  39 #ifndef IFF_DYNAMIC
  40 #define IFF_DYNAMIC     0x8000          /* dialup device with changing addresses*/
  41 #endif
  42 
  43 typedef unsigned long long u64;
  44 typedef __uint32_t u32;
  45 typedef __uint16_t u16;
  46 typedef __uint8_t u8;
  47 
  48 #include "ethtool-copy.h"
  49 #include <linux/sockios.h> /* for SIOCETHTOOL */
  50 
  51 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  52 
  53 #define _PATH_PROCNET_DEV "/proc/net/dev"
  54 
  55 static PyObject *get_active_devices(PyObject *self __unused, PyObject *args __unused)
  56 {
  57 	PyObject *list;
  58 	int numreqs = 30;
  59 	struct ifconf ifc;
  60 	struct ifreq *ifr;
  61 	int n;
  62 
  63 	/* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
  64 	   (as of 2.1.128) */
  65 	/* Open control socket. */
  66 	int skfd = socket(AF_INET, SOCK_DGRAM, 0);
  67 
  68 	if (skfd < 0) {
  69 		PyErr_SetString(PyExc_OSError, strerror(errno));
  70 		return NULL;
  71 	}
  72 
  73 	ifc.ifc_buf = NULL;
  74 	for (;;) {
  75 		ifc.ifc_len = sizeof(struct ifreq) * numreqs;
  76 		ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
  77 
  78 		if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
  79 			PyErr_SetString(PyExc_OSError, strerror(errno));
  80 			free(ifc.ifc_buf);
  81 			close(skfd);
  82 			return NULL;
  83 		}
  84 
  85 		if (ifc.ifc_len == (int)sizeof(struct ifreq) * numreqs) {
  86 			/* assume it overflowed and try again */
  87 			numreqs += 10;
  88 			continue;
  89 		}
  90 		break;
  91 	}
  92 
  93 	list = PyList_New(0);
  94 	ifr = ifc.ifc_req;
  95 	for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
  96 		if (!(ioctl(skfd, SIOCGIFFLAGS, ifr) < 0))
  97 			if (ifr->ifr_flags & IFF_UP) {
  98 				PyObject *str = PyString_FromString(ifr->ifr_name);
  99 				PyList_Append(list, str);
 100 				Py_DECREF(str);
 101 			}
 102 			ifr++;
 103 	}
 104 
 105 	free(ifc.ifc_buf);
 106 	close(skfd);
 107 
 108 	return list;
 109 }
 110 
 111 static PyObject *get_devices(PyObject *self __unused, PyObject *args __unused)
 112 {
 113 	char buffer[256];
 114 	char *ret;;
      (emitted by gcc) 115 	PyObject *list = PyList_New(0);
 116 	FILE *fd = fopen(_PATH_PROCNET_DEV, "r");
 117 
 118 	if (fd == NULL) {
 119 		PyErr_SetString(PyExc_OSError, strerror(errno));
 120 		return NULL;
 121 	}
 122 	/* skip over first two lines */
 123 	ret = fgets(buffer, 256, fd); ret = fgets(buffer, 256, fd);
      (emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
      (emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 124 	while (!feof(fd)) {
 125 		PyObject *str;
 126 		char *name = buffer;
 127 		char *end = buffer;
 128 
 129 		if (fgets(buffer, 256, fd) == NULL)
 130 			break;
 131 		/* find colon */
 132 		while (end && *end != ':')
      (emitted by cppcheck) 133 			end++;
 134 		*end = 0; /* terminate where colon was */
      (emitted by cppcheck) 135 		while (*name == ' ')
 136 			name++; /* skip over leading whitespace if any */
 137 
 138 		str = PyString_FromString(name);
 139 		PyList_Append(list, str);
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 140 		Py_DECREF(str);
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 141 	}
 142 	fclose(fd);
 143 	return list;
 144 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 145 
 146 static PyObject *get_hwaddress(PyObject *self __unused, PyObject *args)
 147 {
 148 	struct ifreq ifr;
 149 	int fd, err;
 150 	char *devname;
 151 	char hwaddr[20];
 152 
 153 	if (!PyArg_ParseTuple(args, "s", &devname))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 154 		return NULL;
 155 
 156 	/* Setup our request structure. */
 157 	memset(&ifr, 0, sizeof(ifr));
 158 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 159 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 160 
 161 	/* Open control socket. */
 162 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 163 	if (fd < 0) {
 164 		PyErr_SetString(PyExc_OSError, strerror(errno));
 165 		return NULL;
 166 	}
 167 
 168 	/* Get current settings. */
 169 	err = ioctl(fd, SIOCGIFHWADDR, &ifr);
 170 	if (err < 0) {
 171 		char buf[2048];
 172 		int eno = errno;
 173 
 174 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 175 		PyErr_SetString(PyExc_IOError, buf);
 176 		close(fd);
 177 		return NULL;
 178 	}
 179 
 180 	close(fd);
 181 
 182 	sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
 183 		(unsigned int)ifr.ifr_hwaddr.sa_data[0] % 256,
 184 		(unsigned int)ifr.ifr_hwaddr.sa_data[1] % 256,
 185 		(unsigned int)ifr.ifr_hwaddr.sa_data[2] % 256,
 186 		(unsigned int)ifr.ifr_hwaddr.sa_data[3] % 256,
 187 		(unsigned int)ifr.ifr_hwaddr.sa_data[4] % 256,
 188 		(unsigned int)ifr.ifr_hwaddr.sa_data[5] % 256);
 189 
 190 	return PyString_FromString(hwaddr);
 191 }
 192 
 193 static PyObject *get_ipaddress(PyObject *self __unused, PyObject *args)
 194 {
 195 	struct ifreq ifr;
 196 	int fd, err;
 197 	char *devname;
 198 	char ipaddr[20];
 199 
 200 	if (!PyArg_ParseTuple(args, "s", &devname))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 201 		return NULL;
 202 
 203 	/* Setup our request structure. */
 204 	memset(&ifr, 0, sizeof(ifr));
 205 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 206 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 207 
 208 	/* Open control socket. */
 209 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 210 	if (fd < 0) {
 211 		PyErr_SetString(PyExc_OSError, strerror(errno));
 212 		return NULL;
 213 	}
 214 
 215 	/* Get current settings. */
 216 	err = ioctl(fd, SIOCGIFADDR, &ifr);
 217 	if (err < 0) {
 218 		char buf[2048];
 219 		int eno = errno;
 220 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 221 		PyErr_SetString(PyExc_IOError, buf);
 222 		close(fd);
 223 		return NULL;
 224 	}
 225 
 226 	close(fd);
 227 
 228 	sprintf(ipaddr, "%u.%u.%u.%u",
 229 		(unsigned int)ifr.ifr_addr.sa_data[2] % 256,
 230 		(unsigned int)ifr.ifr_addr.sa_data[3] % 256,
 231 		(unsigned int)ifr.ifr_addr.sa_data[4] % 256,
 232 		(unsigned int)ifr.ifr_addr.sa_data[5] % 256);
 233 
 234 	return PyString_FromString(ipaddr);
 235 }
 236 
 237 
 238 /**
 239  * Retrieves the current information about all interfaces.  All interfaces will be
 240  * returned as a list of objects per interface.
 241  *
 242  * @param self Not used
 243  * @param args Python arguments
 244  *
 245  * @return Python list of objects on success, otherwise NULL.
 246  */
 247 static PyObject *get_interfaces_info(PyObject *self __unused, PyObject *args) {
      stderr   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed 248 	PyObject *devlist = NULL, *ethinf_py = NULL;
 249 	PyObject *inargs = NULL;
 250 	char **fetch_devs;
 251 	int i = 0, fetch_devs_len = 0;
 252 
 253 	if (!PyArg_ParseTuple(args, "|O", &inargs)) {
 254 		PyErr_SetString(PyExc_LookupError,
 255 				"Argument must be either a string, list or a tuple");
 256 		return NULL;
 257 	}
 258 
 259 	/* Parse input arguments if we got them */
 260 	if( inargs != NULL ) {
 261 		if( PyString_Check(inargs) ) { /* Input argument is just a string */
 262 			fetch_devs_len = 1;
 263 			fetch_devs = calloc(1, sizeof(char *));
 264 			fetch_devs[0] = PyString_AsString(inargs);
 265 		} else if( PyTuple_Check(inargs) ) { /* Input argument is a tuple list with devices */
 266 			int j = 0;
 267 
 268 			fetch_devs_len = PyTuple_Size(inargs);
 269 			fetch_devs = calloc(fetch_devs_len+1, sizeof(char *));
 270 			for( i = 0; i < fetch_devs_len; i++ ) {
 271 				PyObject *elmt = PyTuple_GetItem(inargs, i);
 272 				if( elmt && PyString_Check(elmt) ) {
 273 					fetch_devs[j++] = PyString_AsString(elmt);
 274 				}
 275 			}
 276 			fetch_devs_len = j;
 277 		} else if( PyList_Check(inargs) ) { /* Input argument is a list with devices */
 278 			int j = 0;
 279 
 280 			fetch_devs_len = PyList_Size(inargs);
 281 			fetch_devs = calloc(fetch_devs_len+1, sizeof(char *));
 282 			for( i = 0; i < fetch_devs_len; i++ ) {
 283 				PyObject *elmt = PyList_GetItem(inargs, i);
 284 				if( elmt && PyString_Check(elmt) ) {
 285 					fetch_devs[j++] = PyString_AsString(elmt);
 286 				}
 287 			}
 288 			fetch_devs_len = j;
 289 		} else {
 290 			PyErr_SetString(PyExc_LookupError,
 291 					"Argument must be either a string, list or a tuple");
 292 			return NULL;
 293 		}
 294 	}
 295 
 296 	devlist = PyList_New(0);
 297 	for( i = 0; i < fetch_devs_len; i++ ) {
 298 		struct etherinfo_obj_data *objdata = NULL;
 299 
 300 		/* Allocate memory for data structures for each device */
 301 		objdata = calloc(1, sizeof(struct etherinfo_obj_data));
 302 		if( !objdata ) {
 303 			PyErr_SetString(PyExc_OSError, strerror(errno));
 304 			return NULL;
      (emitted by cppcheck) 305 		}
 306 
 307 		objdata->ethinfo = calloc(1, sizeof(struct etherinfo));
 308 		if( !objdata->ethinfo ) {
 309 			PyErr_SetString(PyExc_OSError, strerror(errno));
 310 			return NULL;
 311 		}
 312 
 313 		/* Store the device name and a reference to the NETLINK connection for
 314 		 * objects to use when quering for device info
 315 		 */
 316 		objdata->ethinfo->device = strdup(fetch_devs[i]);
 317 		objdata->ethinfo->index = -1;
 318 		objdata->nlc = &nlconnection;
 319 		objdata->nlc_users = &nlconnection_users;
 320 
 321 		/* Instantiate a new etherinfo object with the device information */
 322 		ethinf_py = PyCObject_FromVoidPtr(objdata, NULL);
 323 		if( ethinf_py ) {
 324 			/* Prepare the argument list for the object constructor */
 325 			PyObject *args = PyTuple_New(1);
 326 			PyTuple_SetItem(args, 0, ethinf_py);
 327 
 328 			/* Create the object */
 329 			PyObject *dev = PyObject_CallObject((PyObject *)ðtool_etherinfoType, args);
 330 			if( dev ) {
 331 				PyList_Append(devlist, dev);
 332 				Py_DECREF(dev);
 333 			}
 334 			Py_DECREF(args);
 335 		}
 336 	}
 337 	if( fetch_devs_len > 0 ) {
 338 		free(fetch_devs);
 339 	}
 340 
 341 	return devlist;
 342 }
 343 
 344 
 345 static PyObject *get_flags (PyObject *self __unused, PyObject *args)
 346 {
 347 	struct ifreq ifr;
 348 	char *devname;
 349 	int fd, err;
 350 
 351 	if (!PyArg_ParseTuple(args, "s", &devname))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 352 		return NULL;
 353 
 354 	/* Setup our request structure. */
 355 	memset(&ifr, 0, sizeof(ifr));
 356 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 357 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 358 
 359 	/* Open control socket. */
 360 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 361 	if (fd < 0) {
 362 		PyErr_SetString(PyExc_OSError, strerror(errno));
 363 		return NULL;
 364 	}
 365 	err = ioctl(fd, SIOCGIFFLAGS, &ifr);
 366 	if(err < 0) {
 367 		char buf[2048];
 368 		int eno = errno;
 369 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 370 		PyErr_SetString(PyExc_IOError, buf);
 371 		close(fd);
 372 		return NULL;
 373 	}
 374 
 375 	close(fd);
 376 
 377 	return Py_BuildValue("h", ifr.ifr_flags);
        argument 2 ("D.13357") had type
    "int"
  but was expecting
    "short int"
  for format code "h"
   (emitted by cpychecker) 378 
 379 
 380 }
 381 static PyObject *get_netmask (PyObject *self __unused, PyObject *args)
 382 {
 383 	struct ifreq ifr;
 384 	int fd, err;
 385 	char *devname;
 386 	char netmask[20];
 387 
 388 	if (!PyArg_ParseTuple(args, "s", &devname))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 389 		return NULL;
 390 
 391 	/* Setup our request structure. */
 392 	memset(&ifr, 0, sizeof(ifr));
 393 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 394 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 395 
 396 	/* Open control socket. */
 397 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 398 	if (fd < 0) {
 399 		PyErr_SetString(PyExc_OSError, strerror(errno));
 400 		return NULL;
 401 	}
 402 
 403 	/* Get current settings. */
 404 	err = ioctl(fd, SIOCGIFNETMASK, &ifr);
 405 	if (err < 0) {
 406 		char buf[2048];
 407 		int eno = errno;
 408 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 409 		PyErr_SetString(PyExc_IOError, buf);
 410 		close(fd);
 411 		return NULL;
 412 	}
 413 
 414 	close(fd);
 415 
 416 	sprintf(netmask, "%u.%u.%u.%u",
 417 		(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[4] % 256,
 420 		(unsigned int)ifr.ifr_netmask.sa_data[5] % 256);
 421 
 422 	return PyString_FromString(netmask);
 423 }
 424 
 425 static PyObject *get_broadcast(PyObject *self __unused, PyObject *args)
 426 {
 427 	struct ifreq ifr;
 428 	int fd, err;
 429 	char *devname;
 430 	char broadcast[20];
 431 
 432 	if (!PyArg_ParseTuple(args, "s", &devname))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 433 		return NULL;
 434 
 435 	/* Setup our request structure. */
 436 	memset(&ifr, 0, sizeof(ifr));
 437 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 438 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 439 
 440 	/* Open control socket. */
 441 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 442 	if (fd < 0) {
 443 		PyErr_SetString(PyExc_OSError, strerror(errno));
 444 		return NULL;
 445 	}
 446 
 447 	/* Get current settings. */
 448 	err = ioctl(fd, SIOCGIFBRDADDR, &ifr);
 449 	if (err < 0) {
 450 		char buf[2048];
 451 		int eno = errno;
 452 		snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno));
 453 		PyErr_SetString(PyExc_IOError, buf);
 454 		close(fd);
 455 		return NULL;
 456 	}
 457 
 458 	close(fd);
 459 
 460 	sprintf(broadcast, "%u.%u.%u.%u",
 461 		(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[4] % 256,
 464 		(unsigned int)ifr.ifr_broadaddr.sa_data[5] % 256);
 465 
 466 	return PyString_FromString(broadcast);
 467 }
 468 
 469 static PyObject *get_module(PyObject *self __unused, PyObject *args)
 470 {
      stderr   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed 471 	struct ethtool_cmd ecmd;
 472 	struct ifreq ifr;
 473 	int fd, err;
 474 	char buf[2048];
 475 	char *devname;
 476 
 477 	if (!PyArg_ParseTuple(args, "s", &devname))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 478 		return NULL;
 479 
 480 	/* Setup our control structures. */
 481 	memset(&ecmd, 0, sizeof(ecmd));
 482 	memset(&ifr, 0, sizeof(ifr));
 483 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 484 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 485 	ifr.ifr_data = (caddr_t) &buf;
 486 	ecmd.cmd = ETHTOOL_GDRVINFO;
 487 	memcpy(&buf, &ecmd, sizeof(ecmd));
 488 
 489 	/* Open control socket. */
 490 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 491 	if (fd < 0) {
 492 		PyErr_SetString(PyExc_OSError, strerror(errno));
 493 		return NULL;
 494 	}
 495 
 496 	/* Get current settings. */
 497 	err = ioctl(fd, SIOCETHTOOL, &ifr);
 498 
 499 	if (err < 0) {  /* failed? */
 500 		int eno = errno;
 501 		FILE *file;
 502 		int found = 0;
 503 		char driver[100], dev[100];
 504 		close(fd);
 505 
 506 		/* Before bailing, maybe it is a PCMCIA/PC Card? */
 507 		file = fopen("/var/lib/pcmcia/stab", "r");
 508 		if (file == NULL) {
 509 			sprintf(buf, "[Errno %d] %s", eno, strerror(eno));
 510 			PyErr_SetString(PyExc_IOError, buf);
 511 			return NULL;
 512 		}
 513 
 514 		while (!feof(file)) {
 515 			if (fgets(buf, 2048, file) == NULL)
 516 				break;
 517 			buf[2047] = '\0';
 518 			if (strncmp(buf, "Socket", 6) != 0) {
 519 				if (sscanf(buf, "%*d\t%*s\t%100s\t%*d\t%100s\n", driver, dev) > 0) {
      (emitted by cppcheck)      (emitted by cppcheck) 520 					driver[99] = '\0';
 521 					dev[99] = '\0';
 522 					if (strcmp(devname, dev) == 0) {
 523 						found = 1;
 524 						break;
 525 					}
 526 				}
 527 			}
 528 		}
 529 		fclose(file);
 530 		if (!found) {
 531 			sprintf(buf, "[Errno %d] %s", eno, strerror(eno));
 532 			PyErr_SetString(PyExc_IOError, buf);
 533 			return NULL;
 534 		} else
 535 			return PyString_FromString(driver);
 536 	}
 537 
 538 	close(fd);
 539 	return PyString_FromString(((struct ethtool_drvinfo *)buf)->driver);
 540 }
 541 
 542 static PyObject *get_businfo(PyObject *self __unused, PyObject *args)
 543 {
 544 	struct ethtool_cmd ecmd;
 545 	struct ifreq ifr;
 546 	int fd, err;
 547 	char buf[1024];
 548 	char *devname;
 549 
 550 	if (!PyArg_ParseTuple(args, "s", &devname))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 551 		return NULL;
 552 
 553 	/* Setup our control structures. */
 554 	memset(&ecmd, 0, sizeof(ecmd));
 555 	memset(&ifr, 0, sizeof(ifr));
 556 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 557 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 558 	ifr.ifr_data = (caddr_t) &buf;
 559 	ecmd.cmd = ETHTOOL_GDRVINFO;
 560 	memcpy(&buf, &ecmd, sizeof(ecmd));
 561 
 562 	/* Open control socket. */
 563 	fd = socket(AF_INET, SOCK_DGRAM, 0);
 564 	if (fd < 0) {
 565 		PyErr_SetString(PyExc_OSError, strerror(errno));
 566 		return NULL;
 567 	}
 568 
 569 	/* Get current settings. */
 570 	err = ioctl(fd, SIOCETHTOOL, &ifr);
 571 
 572 	if (err < 0) {  /* failed? */
 573 		int eno = errno;
 574 		close(fd);
 575 
 576 		sprintf(buf, "[Errno %d] %s", eno, strerror(eno));
 577 		PyErr_SetString(PyExc_IOError, buf);
 578 		return NULL;
 579 	}
 580 
 581 	close(fd);
 582 	return PyString_FromString(((struct ethtool_drvinfo *)buf)->bus_info);
 583 }
 584 
 585 static int send_command(int cmd, char *devname, void *value)
 586 {
 587 	/* Setup our request structure. */
 588 	int fd, err;
 589 	struct ifreq ifr;
 590 	struct ethtool_value *eval = value;
 591 
 592 	memset(&ifr, 0, sizeof(ifr));
 593 	strncpy(&ifr.ifr_name[0], devname, IFNAMSIZ);
 594 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 595 	ifr.ifr_data = (caddr_t)eval;
 596 	eval->cmd = cmd;
 597 
 598 	/* Open control socket. */
 599 	fd = socket(AF_INET, SOCK_DGRAM, 0), err;
      (emitted by cppcheck) 600 	if (fd < 0) {
 601 		PyErr_SetString(PyExc_OSError, strerror(errno));
 602 		return -1;
 603 	}
 604 
 605 	/* Get current settings. */
 606 	err = ioctl(fd, SIOCETHTOOL, &ifr);
 607 	if (err < 0) {
 608 		char buf[2048];
 609 		sprintf(buf, "[Errno %d] %s", errno, strerror(errno));
 610 		PyErr_SetString(PyExc_IOError, buf);
 611 	}
 612 
 613 	close(fd);
 614 	return err;
 615 }
 616 
 617 static int get_dev_value(int cmd, PyObject *args, void *value)
 618 {
 619 	char *devname;
 620 	int err = -1;
 621 
 622 	if (PyArg_ParseTuple(args, "s", &devname))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 623 		err = send_command(cmd, devname, value);
 624 
 625 	return err;
 626 }
 627 
 628 static int get_dev_int_value(int cmd, PyObject *args, int *value)
 629 {
 630 	struct ethtool_value eval;
 631 	int rc = get_dev_value(cmd, args, &eval);
 632 
 633 	if (rc == 0)
 634 		*value = *(int *)&eval.data;
 635 
 636 	return rc;
 637 }
 638 
 639 static int dev_set_int_value(int cmd, PyObject *args)
 640 {
 641 	struct ethtool_value eval;
 642 	char *devname;
 643 
 644 	if (!PyArg_ParseTuple(args, "si", &devname, &eval.data))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker)        argument 4 ("&eval.data") had type
    "u32 *" (pointing to 32 bits)
  but was expecting
    "int *" (pointing to 32 bits)
  for format code "i"
   (emitted by cpychecker) 645 		return -1;
 646 
 647 	return send_command(cmd, devname, &eval);
 648 }
 649 
 650 static PyObject *get_tso(PyObject *self __unused, PyObject *args)
 651 {
 652 	int value = 0;
 653 
 654 	if (get_dev_int_value(ETHTOOL_GTSO, args, &value) < 0)
 655 		return NULL;
 656 
 657 	return Py_BuildValue("b", value);
        argument 2 ("value.13") had type
    "int"
  but was expecting
    "char"
  for format code "b"
   (emitted by cpychecker) 658 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 659 
 660 static PyObject *set_tso(PyObject *self __unused, PyObject *args)
 661 {
 662 	if (dev_set_int_value(ETHTOOL_STSO, args) < 0)
 663 		return NULL;
 664 
 665 	Py_INCREF(Py_None);
 666 	return Py_None;
 667 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 668 
 669 static PyObject *get_ufo(PyObject *self __unused, PyObject *args)
 670 {
 671 	int value = 0;
 672 
 673 	if (get_dev_int_value(ETHTOOL_GUFO, args, &value) < 0)
 674 		return NULL;
 675 
 676 	return Py_BuildValue("b", value);
        argument 2 ("value.11") had type
    "int"
  but was expecting
    "char"
  for format code "b"
   (emitted by cpychecker) 677 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 678 
 679 static PyObject *get_gso(PyObject *self __unused, PyObject *args)
 680 {
 681 	int value = 0;
 682 
 683 	if (get_dev_int_value(ETHTOOL_GGSO, args, &value) < 0)
 684 		return NULL;
 685 
 686 	return Py_BuildValue("b", value);
        argument 2 ("value.10") had type
    "int"
  but was expecting
    "char"
  for format code "b"
   (emitted by cpychecker) 687 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 688 
 689 static PyObject *get_sg(PyObject *self __unused, PyObject *args)
 690 {
 691 	int value = 0;
 692 
 693 	if (get_dev_int_value(ETHTOOL_GSG, args, &value) < 0)
 694 		return NULL;
 695 
 696 	return Py_BuildValue("b", value);
        argument 2 ("value.5") had type
    "int"
  but was expecting
    "char"
  for format code "b"
   (emitted by cpychecker) 697 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 698 
 699 struct struct_desc {
 700 	char	       *name;
 701 	unsigned short offset;
 702 	unsigned short size;
 703 };
 704 
 705 #define member_desc(type, member_name) { \
 706 	.name = #member_name, \
 707 	.offset = offsetof(type, member_name), \
 708 	.size = sizeof(((type *)0)->member_name), }
 709 
 710 struct struct_desc ethtool_coalesce_desc[] = {
 711 	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_coalesce_usecs_irq),
 714 	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_max_coalesced_frames),
 717 	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, stats_block_coalesce_usecs),
 720 	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, pkt_rate_low),
 723 	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, tx_coalesce_usecs_low),
 726 	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, rx_coalesce_usecs_high),
 729 	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_max_coalesced_frames_high),
 732 	member_desc(struct ethtool_coalesce, rate_sample_interval),
 733 };
 734 
 735 static PyObject *__struct_desc_create_dict(struct struct_desc *table,
 736 					   int nr_entries, void *values)
 737 {
 738 	int i;
 739 	PyObject *dict = PyDict_New();
 740 
 741 	if (dict == NULL)
 742 		goto out;
 743 
 744 	for (i = 0; i < nr_entries; ++i) {
 745 		struct struct_desc *d = &table[i];
 746 		PyObject *objval = NULL;
 747 		void *val = values + d->offset;
 748 
 749 		switch (d->size) {
 750 		case sizeof(uint32_t):
 751 			objval = PyInt_FromLong(*(uint32_t *)val);
 752 			break;
 753 		}
 754 
 755 		if (objval == NULL)
 756 			goto free_dict;
 757 
 758 		if (PyDict_SetItemString(dict, d->name, objval) != 0) {
 759 			Py_DECREF(objval);
 760 			goto free_dict;
 761 		}
 762 			
 763 		Py_DECREF(objval);
 764 	}
 765 out:
 766 	return dict;
 767 free_dict:
 768 	goto out;
 769 	dict = NULL;
 770 }
 771 
 772 #define struct_desc_create_dict(table, values) \
 773 	__struct_desc_create_dict(table, ARRAY_SIZE(table), values)
 774 
 775 static int __struct_desc_from_dict(struct struct_desc *table,
 776 				   int nr_entries, void *to, PyObject *dict)
 777 {
 778 	char buf[2048];
 779 	int i;
 780 
 781 	for (i = 0; i < nr_entries; ++i) {
 782 		struct struct_desc *d = &table[i];
 783 		void *val = to + d->offset;
 784 		PyObject *obj;
 785 
 786 		switch (d->size) {
 787 		case sizeof(uint32_t):
 788 			obj = PyDict_GetItemString(dict, d->name);
 789 			if (obj == NULL) {
 790 				snprintf(buf, sizeof(buf),
 791 					"Missing dict entry for field %s",
 792 					d->name);
 793 				PyErr_SetString(PyExc_IOError, buf);
 794 				return -1;
 795 			}
 796 			*(uint32_t *)val = PyInt_AsLong(obj);
 797 			break;
 798 		default:
 799 			snprintf(buf, sizeof(buf),
 800 				 "Invalid type size %d for field %s",
 801 				 d->size, d->name);
 802 			PyErr_SetString(PyExc_IOError, buf);
 803 			return -1;
 804 		}
 805 	}
 806 
 807 	return 0;
 808 }
 809 
 810 #define struct_desc_from_dict(table, to, dict) \
 811 	__struct_desc_from_dict(table, ARRAY_SIZE(table), to, dict)
 812 
 813 static PyObject *get_coalesce(PyObject *self __unused, PyObject *args)
 814 {
 815 	struct ethtool_coalesce coal;
 816 
 817 	if (get_dev_value(ETHTOOL_GCOALESCE, args, &coal) < 0)
 818 		return NULL;
 819 
 820 	return struct_desc_create_dict(ethtool_coalesce_desc, &coal);
 821 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 822 
 823 static PyObject *set_coalesce(PyObject *self __unused, PyObject *args)
 824 {
 825 	struct ethtool_coalesce coal;
 826 	char *devname;
 827 	PyObject *dict;
 828 
 829 	if (!PyArg_ParseTuple(args, "sO", &devname, &dict))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 830 		return NULL;
 831 
 832 	if (struct_desc_from_dict(ethtool_coalesce_desc, &coal, dict) != 0)
 833 		return NULL;
 834 
 835 	if (send_command(ETHTOOL_SCOALESCE, devname, &coal))
 836 		return NULL;
 837 
 838 	Py_INCREF(Py_None);
 839 	return Py_None;
 840 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 841 
 842 struct struct_desc ethtool_ringparam_desc[] = {
 843 	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_jumbo_max_pending),
 846 	member_desc(struct ethtool_ringparam, tx_max_pending),
 847 	member_desc(struct ethtool_ringparam, rx_pending),
 848 	member_desc(struct ethtool_ringparam, rx_mini_pending),
 849 	member_desc(struct ethtool_ringparam, rx_jumbo_pending),
 850 	member_desc(struct ethtool_ringparam, tx_pending),
 851 };
 852 
 853 static PyObject *get_ringparam(PyObject *self __unused, PyObject *args)
 854 {
 855 	struct ethtool_ringparam ring;
 856 
 857 	if (get_dev_value(ETHTOOL_GRINGPARAM, args, &ring) < 0)
 858 		return NULL;
 859 
 860 	return struct_desc_create_dict(ethtool_ringparam_desc, &ring);
 861 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 862 
 863 static PyObject *set_ringparam(PyObject *self __unused, PyObject *args)
 864 {
 865 	struct ethtool_ringparam ring;
 866 	char *devname;
 867 	PyObject *dict;
 868 
 869 	if (!PyArg_ParseTuple(args, "sO", &devname, &dict))
        argument 3 ("&devname") had type
    "char * *"
  but was expecting
    "const char * *"
  for format code "s"
   (emitted by cpychecker) 870 		return NULL;
 871 
 872 	if (struct_desc_from_dict(ethtool_ringparam_desc, &ring, dict) != 0)
 873 		return NULL;
 874 
 875 	if (send_command(ETHTOOL_SRINGPARAM, devname, &ring))
 876 		return NULL;
 877 
 878 	Py_INCREF(Py_None);
 879 	return Py_None;
 880 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
 881 
 882 static struct PyMethodDef PyEthModuleMethods[] = {
 883 	{
 884 		.ml_name = "get_module",
 885 		.ml_meth = (PyCFunction)get_module,
 886 		.ml_flags = METH_VARARGS,
 887 	},
 888 	{
 889 		.ml_name = "get_businfo",
 890 		.ml_meth = (PyCFunction)get_businfo,
 891 		.ml_flags = METH_VARARGS,
 892 	},
 893 	{
 894 		.ml_name = "get_hwaddr",
 895 		.ml_meth = (PyCFunction)get_hwaddress,
 896 		.ml_flags = METH_VARARGS,
 897 	},
 898 	{
 899 		.ml_name = "get_ipaddr",
 900 		.ml_meth = (PyCFunction)get_ipaddress,
 901 		.ml_flags = METH_VARARGS,
 902 	},
 903 	{
 904 		.ml_name = "get_interfaces_info",
 905 		.ml_meth = (PyCFunction)get_interfaces_info,
 906 		.ml_flags = METH_VARARGS,
 907 		.ml_doc = "Accepts a string, list or tupples of interface names. "
 908 		"Returns a list of ethtool.etherinfo objets with device information."
 909 	},
 910 	{
 911 		.ml_name = "get_netmask",
 912 		.ml_meth = (PyCFunction)get_netmask,
 913 		.ml_flags = METH_VARARGS,
 914 	},
 915 	{
 916 		.ml_name = "get_broadcast",
 917 		.ml_meth = (PyCFunction)get_broadcast,
 918 		.ml_flags = METH_VARARGS,
 919 	},
 920 	{
 921 		.ml_name = "get_coalesce",
 922 		.ml_meth = (PyCFunction)get_coalesce,
 923 		.ml_flags = METH_VARARGS,
 924 	},
 925 	{
 926 		.ml_name = "set_coalesce",
 927 		.ml_meth = (PyCFunction)set_coalesce,
 928 		.ml_flags = METH_VARARGS,
 929 	},
 930 	{
 931 		.ml_name = "get_devices",
 932 		.ml_meth = (PyCFunction)get_devices,
 933 		.ml_flags = METH_VARARGS,
 934 	},
 935 	{
 936 		.ml_name = "get_active_devices",
 937 		.ml_meth = (PyCFunction)get_active_devices,
 938 		.ml_flags = METH_VARARGS,
 939 	},
 940 	{
 941 		.ml_name = "get_ringparam",
 942 		.ml_meth = (PyCFunction)get_ringparam,
 943 		.ml_flags = METH_VARARGS,
 944 	},
 945 	{
 946 		.ml_name = "set_ringparam",
 947 		.ml_meth = (PyCFunction)set_ringparam,
 948 		.ml_flags = METH_VARARGS,
 949 	},
 950 	{
 951 		.ml_name = "get_tso",
 952 		.ml_meth = (PyCFunction)get_tso,
 953 		.ml_flags = METH_VARARGS,
 954 	},
 955 	{
 956 		.ml_name = "set_tso",
 957 		.ml_meth = (PyCFunction)set_tso,
 958 		.ml_flags = METH_VARARGS,
 959 	},
 960 	{
 961 		.ml_name = "get_ufo",
 962 		.ml_meth = (PyCFunction)get_ufo,
 963 		.ml_flags = METH_VARARGS,
 964 	},
 965 	{
 966 		.ml_name = "get_gso",
 967 		.ml_meth = (PyCFunction)get_gso,
 968 		.ml_flags = METH_VARARGS,
 969 	},
 970 	{
 971 		.ml_name = "get_sg",
 972 		.ml_meth = (PyCFunction)get_sg,
 973 		.ml_flags = METH_VARARGS,
 974 	},
 975 	{
 976 		.ml_name = "get_flags",
 977 		.ml_meth = (PyCFunction)get_flags,
 978 		.ml_flags = METH_VARARGS,
 979 	},
 980 	{	.ml_name = NULL, },
 981 };
 982 
 983 
 984 PyMODINIT_FUNC initethtool(void)
 985 {
 986 	PyObject *m;
 987 	m = Py_InitModule3("ethtool", PyEthModuleMethods, "Python ethtool module");
 988 
 989 	// Prepare the ethtool.etherinfo class
 990 	if (PyType_Ready(ðtool_etherinfoType) < 0)
 991 		return;
 992 	Py_INCREF(ðtool_etherinfoType);
 993 	PyModule_AddObject(m, "etherinfo", (PyObject *)ðtool_etherinfoType);
      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 
 995 	// Prepare the ethtool.etherinfo_ipv6addr class
 996 	if (PyType_Ready(ðtool_etherinfoIPv6Type) < 0)
 997 		return;
 998 	Py_INCREF(ðtool_etherinfoIPv6Type);
 999 	PyModule_AddObject(m, "etherinfo_ipv6addr", (PyObject *)ðtool_etherinfoIPv6Type);
1000 
1001 	// Setup constants
1002 	PyModule_AddIntConstant(m, "IFF_UP", IFF_UP);			/* Interface is up. */
1003 	PyModule_AddIntConstant(m, "IFF_BROADCAST", IFF_BROADCAST);	/* Broadcast address valid. */
1004 	PyModule_AddIntConstant(m, "IFF_DEBUG", IFF_DEBUG);		/* Turn on debugging. */
1005 	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 */
1007 	PyModule_AddIntConstant(m, "IFF_NOTRAILERS", IFF_NOTRAILERS);	/* Avoid use of trailers */
1008 	PyModule_AddIntConstant(m, "IFF_RUNNING", IFF_RUNNING);		/* Resources allocated */
1009 	PyModule_AddIntConstant(m, "IFF_NOARP", IFF_NOARP);		/* No address resolution protocol. */
1010 	PyModule_AddIntConstant(m, "IFF_PROMISC", IFF_PROMISC);		/* Receive all packets. */
1011 	PyModule_AddIntConstant(m, "IFF_ALLMULTI", IFF_ALLMULTI);	/* Receive all multicast packets. */
1012 	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. */
1014 	PyModule_AddIntConstant(m, "IFF_MULTICAST", IFF_MULTICAST);	/* Supports multicast. */
1015 	PyModule_AddIntConstant(m, "IFF_PORTSEL", IFF_PORTSEL);		/* Can set media type. */
1016 	PyModule_AddIntConstant(m, "IFF_AUTOMEDIA", IFF_AUTOMEDIA);	/* Auto media select active. */
1017 	PyModule_AddIntConstant(m, "IFF_DYNAMIC", IFF_DYNAMIC);		/* Dialup device with changing addresses.  */
1018 	PyModule_AddIntConstant(m, "AF_INET", AF_INET);                 /* IPv4 interface */
1019 	PyModule_AddIntConstant(m, "AF_INET6", AF_INET6);               /* IPv6 interface */
1020 	PyModule_AddStringConstant(m, "version", "python-ethtool v" VERSION);
1021 }