ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/network_stats.c
Revision: 1.37
Committed: Sat Feb 14 00:08:51 2004 UTC (20 years, 3 months ago) by ats
Content type: text/plain
Branch: MAIN
Changes since 1.36: +8 -5 lines
Log Message:
Rename BSD "int s" to "int sock" to match Linux code and fix compile error.
Make BSD code set the interface name before calling ioctl so it gets the
stats for the right interface.

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