ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/network_stats.c
Revision: 1.44
Committed: Sat Feb 14 16:58:19 2004 UTC (20 years, 3 months ago) by ats
Content type: text/plain
Branch: MAIN
Changes since 1.43: +56 -34 lines
Log Message:
Rework iface_stat code for Solaris so that it uses SIOCGIFFLAGS to find out
whether an interface is up or not. This means that we need to link with
-lsocket -lnsl now to get socket().

Also make the comment about when bytes-transferred stats a bit more explicit.
We're now in the slightly odd situation where it's possible for an interface to
show up in either or both of get_network_stats and get_network_iface_stats: for
instance, on raptor at the moment, ce0 is in use so shows up in both, lo0
doesn't have kstats for bytes transferred and thus only shows up in the second,
and ce1 exists but hasn't been plumbed so only shows up in the first. I'd be
mildly inclined to "fix" this by making get_network_stats do a SIOCGIFFLAGS
ioctl so unplumbed interfaces don't show up at all (and add packets
received/transmited to the get_network_stats result so we can at least show
something for lo0).

File Contents

# User Rev Content
1 tdb 1.22 /*
2 pajs 1.1 * i-scream central monitoring system
3 tdb 1.15 * http://www.i-scream.org
4 tdb 1.22 * Copyright (C) 2000-2004 i-scream
5 pajs 1.1 *
6 tdb 1.22 * This library is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU Lesser General Public
8     * License as published by the Free Software Foundation; either
9     * version 2.1 of the License, or (at your option) any later version.
10 pajs 1.1 *
11 tdb 1.22 * This library is distributed in the hope that it will be useful,
12 pajs 1.1 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 tdb 1.22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     * Lesser General Public License for more details.
15 pajs 1.1 *
16 tdb 1.22 * You should have received a copy of the GNU Lesser General Public
17     * License along with this library; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19     * 02111-1307 USA
20 tdb 1.23 *
21 ats 1.44 * $Id: network_stats.c,v 1.43 2004/02/14 15:48:42 ats Exp $
22 pajs 1.1 */
23    
24     #ifdef HAVE_CONFIG_H
25     #include "config.h"
26     #endif
27    
28 tdb 1.4 #include <stdlib.h>
29 pajs 1.6 #include <string.h>
30 pajs 1.1 #include "statgrab.h"
31 tdb 1.11 #include <time.h>
32 pajs 1.1 #ifdef SOLARIS
33     #include <kstat.h>
34     #include <sys/sysinfo.h>
35 ats 1.44 #include <sys/types.h>
36     #include <sys/socket.h>
37     #include <sys/ioctl.h>
38     #include <net/if.h>
39     #include <netinet/in.h>
40     #include <sys/sockio.h>
41 pajs 1.6 #endif
42     #ifdef LINUX
43     #include <stdio.h>
44     #include <sys/types.h>
45     #include <regex.h>
46 pajs 1.27 #include <sys/ioctl.h>
47     #include <sys/socket.h>
48     #include <net/if.h>
49     #include <ctype.h>
50 pajs 1.6 #include "tools.h"
51 pajs 1.27 /* Stuff which could be defined by defining KERNEL, but
52     * that would be a bad idea, so we'll just declare it here
53     */
54     typedef __uint8_t u8;
55     typedef __uint16_t u16;
56     typedef __uint32_t u32;
57 ats 1.42 typedef __uint64_t u64;
58 pajs 1.27 #include <linux/ethtool.h>
59     #include <linux/sockios.h>
60 ats 1.32 #include <unistd.h>
61 pajs 1.1 #endif
62 ats 1.18 #ifdef ALLBSD
63 pajs 1.14 #include <sys/types.h>
64     #include <sys/socket.h>
65     #include <ifaddrs.h>
66     #include <net/if.h>
67 pajs 1.26 #include <net/if_media.h>
68     #include <sys/ioctl.h>
69 pajs 1.14 #endif
70 pajs 1.1
71 pajs 1.3 static network_stat_t *network_stats=NULL;
72     static int interfaces=0;
73 pajs 1.1
74 pajs 1.3 void network_stat_init(int start, int end, network_stat_t *net_stats){
75    
76     for(net_stats+=start; start<end; start++){
77     net_stats->interface_name=NULL;
78     net_stats->tx=0;
79     net_stats->rx=0;
80     net_stats++;
81     }
82     }
83    
84     network_stat_t *network_stat_malloc(int needed_entries, int *cur_entries, network_stat_t *net_stats){
85    
86     if(net_stats==NULL){
87    
88     if((net_stats=malloc(needed_entries * sizeof(network_stat_t)))==NULL){
89 pajs 1.1 return NULL;
90     }
91 pajs 1.3 network_stat_init(0, needed_entries, net_stats);
92     *cur_entries=needed_entries;
93    
94 pajs 1.1 return net_stats;
95     }
96 pajs 1.3
97    
98     if(*cur_entries<needed_entries){
99     net_stats=realloc(net_stats, (sizeof(network_stat_t)*needed_entries));
100     if(net_stats==NULL){
101 pajs 1.1 return NULL;
102     }
103 pajs 1.3 network_stat_init(*cur_entries, needed_entries, net_stats);
104     *cur_entries=needed_entries;
105 pajs 1.1 }
106    
107     return net_stats;
108     }
109    
110 pajs 1.3
111 pajs 1.1 network_stat_t *get_network_stats(int *entries){
112 pajs 1.6
113     static int sizeof_network_stats=0;
114     network_stat_t *network_stat_ptr;
115    
116     #ifdef SOLARIS
117 pajs 1.1 kstat_ctl_t *kc;
118     kstat_t *ksp;
119     kstat_named_t *knp;
120 pajs 1.6 #endif
121 pajs 1.3
122 pajs 1.6 #ifdef LINUX
123     FILE *f;
124 pajs 1.12 /* Horrible big enough, but it should be easily big enough */
125 pajs 1.6 char line[8096];
126     regex_t regex;
127     regmatch_t line_match[4];
128 pajs 1.14 #endif
129 ats 1.18 #ifdef ALLBSD
130 pajs 1.14 struct ifaddrs *net, *net_ptr;
131     struct if_data *net_data;
132     #endif
133    
134 ats 1.18 #ifdef ALLBSD
135 pajs 1.14 if(getifaddrs(&net) != 0){
136     return NULL;
137     }
138    
139     interfaces=0;
140    
141     for(net_ptr=net;net_ptr!=NULL;net_ptr=net_ptr->ifa_next){
142     if(net_ptr->ifa_addr->sa_family != AF_LINK) continue;
143     network_stats=network_stat_malloc((interfaces+1), &sizeof_network_stats, network_stats);
144     if(network_stats==NULL){
145     return NULL;
146     }
147     network_stat_ptr=network_stats+interfaces;
148    
149     if(network_stat_ptr->interface_name!=NULL) free(network_stat_ptr->interface_name);
150     network_stat_ptr->interface_name=strdup(net_ptr->ifa_name);
151     if(network_stat_ptr->interface_name==NULL) return NULL;
152     net_data=(struct if_data *)net_ptr->ifa_data;
153     network_stat_ptr->rx=net_data->ifi_ibytes;
154     network_stat_ptr->tx=net_data->ifi_obytes;
155     network_stat_ptr->systime=time(NULL);
156     interfaces++;
157     }
158     freeifaddrs(net);
159 pajs 1.6 #endif
160 pajs 1.1
161 pajs 1.6 #ifdef SOLARIS
162 pajs 1.1 if ((kc = kstat_open()) == NULL) {
163     return NULL;
164     }
165    
166 pajs 1.6 interfaces=0;
167 pajs 1.3
168 pajs 1.1 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
169     if (!strcmp(ksp->ks_class, "net")) {
170     kstat_read(kc, ksp, NULL);
171    
172 pajs 1.7 #ifdef SOL7
173     #define RLOOKUP "rbytes"
174     #define WLOOKUP "obytes"
175     #define VALTYPE value.ui32
176     #else
177     #define RLOOKUP "rbytes64"
178     #define WLOOKUP "obytes64"
179     #define VALTYPE value.ui64
180     #endif
181    
182     if((knp=kstat_data_lookup(ksp, RLOOKUP))==NULL){
183 ats 1.44 /* This is a network interface, but it doesn't
184     * have the rbytes/obytes values; for instance,
185     * the loopback devices have this behaviour
186     * (although they do track packets in/out). */
187 pajs 1.1 continue;
188     }
189 pajs 1.3
190     network_stats=network_stat_malloc((interfaces+1), &sizeof_network_stats, network_stats);
191 pajs 1.1 if(network_stats==NULL){
192     return NULL;
193     }
194     network_stat_ptr=network_stats+interfaces;
195 pajs 1.7 network_stat_ptr->rx=knp->VALTYPE;
196 pajs 1.1
197 pajs 1.7 if((knp=kstat_data_lookup(ksp, WLOOKUP))==NULL){
198 pajs 1.1 continue;
199     }
200 pajs 1.7 network_stat_ptr->tx=knp->VALTYPE;
201 pajs 1.1 if(network_stat_ptr->interface_name!=NULL){
202     free(network_stat_ptr->interface_name);
203     }
204     network_stat_ptr->interface_name=strdup(ksp->ks_name);
205 pajs 1.3
206     network_stat_ptr->systime=time(NULL);
207 pajs 1.1 interfaces++;
208     }
209     }
210 pajs 1.2
211     kstat_close(kc);
212 pajs 1.6 #endif
213     #ifdef LINUX
214     f=fopen("/proc/net/dev", "r");
215     if(f==NULL){
216     return NULL;
217     }
218     /* read the 2 lines.. Its the title, so we dont care :) */
219     fgets(line, sizeof(line), f);
220     fgets(line, sizeof(line), f);
221    
222    
223     if((regcomp(&regex, "^[[:space:]]*([^:]+):[[:space:]]*([[:digit:]]+)[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+([[:digit:]]+)", REG_EXTENDED))!=0){
224     return NULL;
225     }
226    
227     interfaces=0;
228 pajs 1.1
229 pajs 1.6 while((fgets(line, sizeof(line), f)) != NULL){
230     if((regexec(&regex, line, 4, line_match, 0))!=0){
231     continue;
232     }
233     network_stats=network_stat_malloc((interfaces+1), &sizeof_network_stats, network_stats);
234     if(network_stats==NULL){
235     return NULL;
236     }
237     network_stat_ptr=network_stats+interfaces;
238    
239     if(network_stat_ptr->interface_name!=NULL){
240     free(network_stat_ptr->interface_name);
241     }
242    
243     network_stat_ptr->interface_name=get_string_match(line, &line_match[1]);
244     network_stat_ptr->rx=get_ll_match(line, &line_match[2]);
245     network_stat_ptr->tx=get_ll_match(line, &line_match[3]);
246     network_stat_ptr->systime=time(NULL);
247    
248     interfaces++;
249     }
250 pajs 1.12 fclose(f);
251 pajs 1.13 regfree(&regex);
252 pajs 1.6
253     #endif
254 ats 1.20
255     #ifdef CYGWIN
256     return NULL;
257     #endif
258    
259 pajs 1.1 *entries=interfaces;
260    
261     return network_stats;
262 pajs 1.3 }
263    
264 pajs 1.8 long long transfer_diff(long long new, long long old){
265 pajs 1.17 #if defined(SOL7) || defined(LINUX) || defined(FREEBSD)
266 ats 1.19 #define MAXVAL 4294967296LL
267 pajs 1.8 #else
268 ats 1.19 #define MAXVAL 18446744073709551616LL
269 pajs 1.8 #endif
270     long long result;
271 pajs 1.10 if(new>=old){
272 pajs 1.8 result = (new-old);
273     }else{
274     result = (MAXVAL+(new-old));
275     }
276    
277     return result;
278    
279     }
280    
281 ats 1.24 network_stat_t *get_network_stats_diff(int *entries) {
282     static network_stat_t *diff = NULL;
283     static int diff_count = 0;
284     network_stat_t *src, *dest;
285     int i, j, new_count;
286    
287     if (network_stats == NULL) {
288     /* No previous stats, so we can't calculate a difference. */
289     return get_network_stats(entries);
290 pajs 1.3 }
291    
292 ats 1.24 /* Resize the results array to match the previous stats. */
293     diff = network_stat_malloc(interfaces, &diff_count, diff);
294     if (diff == NULL) {
295 pajs 1.3 return NULL;
296     }
297    
298 ats 1.24 /* Copy the previous stats into the result. */
299     for (i = 0; i < diff_count; i++) {
300     src = &network_stats[i];
301     dest = &diff[i];
302 pajs 1.3
303 ats 1.24 if (dest->interface_name != NULL) {
304     free(dest->interface_name);
305 pajs 1.3 }
306 ats 1.24 dest->interface_name = strdup(src->interface_name);
307     dest->rx = src->rx;
308     dest->tx = src->tx;
309     dest->systime = src->systime;
310     }
311 pajs 1.3
312 ats 1.24 /* Get a new set of stats. */
313     if (get_network_stats(&new_count) == NULL) {
314 ats 1.21 return NULL;
315     }
316 pajs 1.3
317 ats 1.24 /* For each previous stat... */
318     for (i = 0; i < diff_count; i++) {
319     dest = &diff[i];
320    
321     /* ... find the corresponding new stat ... */
322     for (j = 0; j < new_count; j++) {
323     /* Try the new stat in the same position first,
324     since that's most likely to be it. */
325     src = &network_stats[(i + j) % new_count];
326     if (strcmp(src->interface_name, dest->interface_name) == 0) {
327     break;
328     }
329     }
330     if (j == new_count) {
331     /* No match found. */
332     continue;
333 pajs 1.3 }
334    
335 ats 1.24 /* ... and subtract the previous stat from it to get the
336     difference. */
337     dest->rx = transfer_diff(src->rx, dest->rx);
338     dest->tx = transfer_diff(src->tx, dest->tx);
339     dest->systime = src->systime - dest->systime;
340 pajs 1.3 }
341    
342 ats 1.24 *entries = diff_count;
343     return diff;
344     }
345 pajs 1.25 /* NETWORK INTERFACE STATS */
346    
347     void network_iface_stat_init(int start, int end, network_iface_stat_t *net_stats){
348    
349     for(net_stats+=start; start<end; start++){
350     net_stats->interface_name=NULL;
351     net_stats->speed=0;
352 ats 1.31 net_stats->dup=UNKNOWN_DUPLEX;
353 pajs 1.25 net_stats++;
354     }
355     }
356    
357     network_iface_stat_t *network_iface_stat_malloc(int needed_entries, int *cur_entries, network_iface_stat_t *net_stats){
358    
359     if(net_stats==NULL){
360    
361     if((net_stats=malloc(needed_entries * sizeof(network_iface_stat_t)))==NULL){
362     return NULL;
363     }
364     network_iface_stat_init(0, needed_entries, net_stats);
365     *cur_entries=needed_entries;
366    
367     return net_stats;
368     }
369    
370    
371     if(*cur_entries<needed_entries){
372     net_stats=realloc(net_stats, (sizeof(network_iface_stat_t)*needed_entries));
373     if(net_stats==NULL){
374     return NULL;
375     }
376     network_iface_stat_init(*cur_entries, needed_entries, net_stats);
377     *cur_entries=needed_entries;
378     }
379    
380     return net_stats;
381     }
382    
383     network_iface_stat_t *get_network_iface_stats(int *entries){
384     static network_iface_stat_t *network_iface_stats;
385     network_iface_stat_t *network_iface_stat_ptr;
386     static int sizeof_network_iface_stats=0;
387 ats 1.43 int ifaces = 0;
388 pajs 1.25
389     #ifdef SOLARIS
390     kstat_ctl_t *kc;
391     kstat_t *ksp;
392     kstat_named_t *knp;
393 ats 1.44 int sock;
394 pajs 1.25 #endif
395 pajs 1.26 #ifdef ALLBSD
396     struct ifaddrs *net, *net_ptr;
397     struct ifmediareq ifmed;
398 pajs 1.36 struct ifreq ifr;
399 ats 1.37 int sock;
400 pajs 1.26 int x;
401     #endif
402 pajs 1.27 #ifdef LINUX
403     FILE *f;
404     /* Horrible big enough, but it should be easily big enough */
405     char line[8096];
406     int sock;
407     #endif
408 ats 1.43
409 pajs 1.26 #ifdef ALLBSD
410     if(getifaddrs(&net) != 0){
411     return NULL;
412     }
413    
414 ats 1.37 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == 0) return NULL;
415 pajs 1.26
416     for(net_ptr=net; net_ptr!=NULL; net_ptr=net_ptr->ifa_next){
417     if(net_ptr->ifa_addr->sa_family != AF_LINK) continue;
418     network_iface_stats=network_iface_stat_malloc((ifaces+1), &sizeof_network_iface_stats, network_iface_stats);
419     if(network_iface_stats==NULL){
420     return NULL;
421     }
422     network_iface_stat_ptr = network_iface_stats + ifaces;
423    
424 ats 1.40 memset(&ifr, 0, sizeof(ifr));
425     strncpy(ifr.ifr_name, net_ptr->ifa_name, sizeof(ifr.ifr_name));
426    
427     if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0){
428     continue;
429     }
430     if((ifr.ifr_flags & IFF_UP) != 0){
431     network_iface_stat_ptr->up = 1;
432     }else{
433     network_iface_stat_ptr->up = 0;
434     }
435    
436     if (network_iface_stat_ptr->interface_name != NULL) free(network_iface_stat_ptr->interface_name);
437     network_iface_stat_ptr->interface_name = strdup(net_ptr->ifa_name);
438     if (network_iface_stat_ptr->interface_name == NULL) return NULL;
439    
440     network_iface_stat_ptr->speed = 0;
441     network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
442     ifaces++;
443    
444 pajs 1.26 memset(&ifmed, 0, sizeof(struct ifmediareq));
445     strlcpy(ifmed.ifm_name, net_ptr->ifa_name, sizeof(ifmed.ifm_name));
446 ats 1.37 if(ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmed) == -1){
447 ats 1.40 /* Not all interfaces support the media ioctls. */
448 pajs 1.26 continue;
449     }
450    
451     /* We may need to change this if we start doing wireless devices too */
452     if( (ifmed.ifm_active | IFM_ETHER) != ifmed.ifm_active ){
453     /* Not a ETHER device */
454     continue;
455     }
456    
457     /* Only intrested in the first 4 bits) - Assuming only ETHER devices */
458     x = ifmed.ifm_active & 0x0f;
459     switch(x){
460     /* 10 Mbit connections. Speedy :) */
461     case(IFM_10_T):
462     case(IFM_10_2):
463     case(IFM_10_5):
464     case(IFM_10_STP):
465     case(IFM_10_FL):
466     network_iface_stat_ptr->speed = 10;
467     break;
468     /* 100 Mbit conneections */
469     case(IFM_100_TX):
470     case(IFM_100_FX):
471     case(IFM_100_T4):
472     case(IFM_100_VG):
473     case(IFM_100_T2):
474     network_iface_stat_ptr->speed = 100;
475     break;
476     /* 1000 Mbit connections */
477     case(IFM_1000_SX):
478     case(IFM_1000_LX):
479     case(IFM_1000_CX):
480 ats 1.31 #if defined(FREEBSD) && !defined(FREEBSD5)
481 pajs 1.26 case(IFM_1000_TX):
482 tdb 1.28 case(IFM_1000_FX):
483 ats 1.31 #else
484     case(IFM_1000_T):
485 tdb 1.28 #endif
486 pajs 1.26 network_iface_stat_ptr->speed = 1000;
487     break;
488     /* We don't know what it is */
489     default:
490     network_iface_stat_ptr->speed = 0;
491     break;
492     }
493    
494     if( (ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active ){
495     network_iface_stat_ptr->dup = FULL_DUPLEX;
496     }else if( (ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active ){
497     network_iface_stat_ptr->dup = HALF_DUPLEX;
498     }else{
499 ats 1.31 network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
500 pajs 1.26 }
501 pajs 1.36
502 pajs 1.26 }
503     freeifaddrs(net);
504 ats 1.37 close(sock);
505 pajs 1.26 #endif
506 pajs 1.25
507     #ifdef SOLARIS
508 ats 1.44 if ((kc = kstat_open()) == NULL) {
509     return NULL;
510     }
511    
512     if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
513     return NULL;
514     }
515 pajs 1.25
516 ats 1.44 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
517     if (!strcmp(ksp->ks_class, "net")) {
518     struct ifreq ifr;
519    
520     kstat_read(kc, ksp, NULL);
521    
522     strncpy(ifr.ifr_name, ksp->ks_name, sizeof ifr.ifr_name);
523     if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
524     /* Not a network interface. */
525 pajs 1.25 continue;
526     }
527 ats 1.44
528     network_iface_stats = network_iface_stat_malloc(ifaces + 1, &sizeof_network_iface_stats, network_iface_stats);
529     if (network_iface_stats == NULL) {
530 pajs 1.25 return NULL;
531     }
532 pajs 1.26 network_iface_stat_ptr = network_iface_stats + ifaces;
533 ats 1.44 ifaces++;
534    
535     if (network_iface_stat_ptr->interface_name != NULL) free(network_iface_stat_ptr->interface_name);
536     network_iface_stat_ptr->interface_name = strdup(ksp->ks_name);
537     if (network_iface_stat_ptr->interface_name == NULL) return NULL;
538 pajs 1.25
539 ats 1.44 if ((ifr.ifr_flags & IFF_UP) != 0) {
540     network_iface_stat_ptr->up = 1;
541     } else {
542     network_iface_stat_ptr->up = 1;
543     }
544 pajs 1.35
545 ats 1.44 if ((knp = kstat_data_lookup(ksp, "ifspeed")) != NULL) {
546     network_iface_stat_ptr->speed = knp->value.ui64 / (1000 * 1000);
547     } else {
548     network_iface_stat_ptr->speed = 0;
549 pajs 1.25 }
550    
551 pajs 1.33 network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
552 ats 1.44 if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) {
553     switch (knp->value.ui32) {
554     case 1:
555     network_iface_stat_ptr->dup = HALF_DUPLEX;
556     break;
557     case 2:
558     network_iface_stat_ptr->dup = FULL_DUPLEX;
559     break;
560     }
561 pajs 1.33 }
562 pajs 1.25 }
563     }
564 ats 1.44
565     close(sock);
566 pajs 1.25 kstat_close(kc);
567     #endif
568 pajs 1.27 #ifdef LINUX
569     f = fopen("/proc/net/dev", "r");
570     if(f == NULL){
571     return NULL;
572     }
573    
574     /* Setup stuff so we can do the ioctl to get the info */
575     if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
576     return NULL;
577     }
578    
579     /* Ignore first 2 lines.. Just headings */
580 pajs 1.29 if((fgets(line, sizeof(line), f)) == NULL) return NULL;
581     if((fgets(line, sizeof(line), f)) == NULL) return NULL;
582 pajs 1.27
583     while((fgets(line, sizeof(line), f)) != NULL){
584     char *name, *ptr;
585     struct ifreq ifr;
586 ats 1.38 struct ethtool_cmd ethcmd;
587 pajs 1.27 int err;
588    
589     /* Get the interface name */
590     ptr = strchr(line, ':');
591     if (ptr == NULL) continue;
592     *ptr='\0';
593     name = line;
594     while(isspace(*(name))){
595     name++;
596     }
597    
598 ats 1.38 memset(&ifr, 0, sizeof ifr);
599     strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
600 pajs 1.27
601 ats 1.38 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
602     continue;
603     }
604 pajs 1.27
605     /* We have a good interface to add */
606     network_iface_stats=network_iface_stat_malloc((ifaces+1), &sizeof_network_iface_stats, network_iface_stats);
607     if(network_iface_stats==NULL){
608     return NULL;
609     }
610     network_iface_stat_ptr = network_iface_stats + ifaces;
611     network_iface_stat_ptr->interface_name = strdup(name);
612 ats 1.38 if ((ifr.ifr_flags & IFF_UP) != 0) {
613 pajs 1.35 network_iface_stat_ptr->up = 1;
614 ats 1.38 } else {
615 pajs 1.35 network_iface_stat_ptr->up = 0;
616     }
617    
618 ats 1.38 memset(&ethcmd, 0, sizeof ethcmd);
619     ethcmd.cmd = ETHTOOL_GSET;
620     ifr.ifr_data = (caddr_t) &ethcmd;
621    
622     err = ioctl(sock, SIOCETHTOOL, &ifr);
623     if (err == 0) {
624     network_iface_stat_ptr->speed = ethcmd.speed;
625    
626     switch (ethcmd.duplex) {
627     case 0x00:
628     network_iface_stat_ptr->dup = FULL_DUPLEX;
629     break;
630     case 0x01:
631     network_iface_stat_ptr->dup = HALF_DUPLEX;
632     break;
633     default:
634     network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
635     }
636     } else {
637     /* Not all interfaces support the ethtool ioctl. */
638 ats 1.39 network_iface_stat_ptr->speed = 0;
639 ats 1.38 network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
640 pajs 1.27 }
641 ats 1.38
642 pajs 1.27 ifaces++;
643     }
644 pajs 1.30 close(sock);
645 ats 1.38 fclose(f);
646 pajs 1.27 #endif
647 pajs 1.26 *entries = ifaces;
648 pajs 1.25 return network_iface_stats;
649     }
650