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 analyzed 283 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 analyzed 104 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 analyzed 159 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 }