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