ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/network_stats.c
(Generate patch)

Comparing projects/libstatgrab/src/libstatgrab/network_stats.c (file contents):
Revision 1.61 by tdb, Mon Apr 5 00:17:40 2004 UTC vs.
Revision 1.81 by tdb, Wed Jun 9 14:44:28 2010 UTC

# Line 1 | Line 1
1   /*
2 < * i-scream central monitoring system
2 > * i-scream libstatgrab
3   * http://www.i-scream.org
4   * Copyright (C) 2000-2004 i-scream
5   *
# Line 45 | Line 45
45   #ifdef LINUX
46   #include <stdio.h>
47   #include <sys/types.h>
48 #include <regex.h>
48   #include <sys/ioctl.h>
49   #include <sys/socket.h>
50   #include <net/if.h>
51   #include <ctype.h>
52 < /* Stuff which could be defined by defining KERNEL, but
53 < * that would be a bad idea, so we'll just declare it here
54 < */
52 > #include <linux/version.h>
53 > #include <asm/types.h>
54 > /* These aren't defined by asm/types.h unless the kernel is being
55 >   compiled, but some versions of ethtool.h need them. */
56   typedef __uint8_t u8;
57   typedef __uint16_t u16;
58   typedef __uint32_t u32;
# Line 70 | Line 70 | typedef __uint64_t u64;
70   #include <sys/ioctl.h>
71   #include <unistd.h>
72   #endif
73 + #ifdef WIN32
74 + #include <windows.h>
75 + #include <Iphlpapi.h>
76 + #include "win32.h"
77 + #endif
78  
79 < static void network_stat_init(network_stat_t *s) {
79 > static void network_stat_init(sg_network_io_stats *s) {
80          s->interface_name = NULL;
81          s->tx = 0;
82          s->rx = 0;
# Line 82 | Line 87 | static void network_stat_init(network_stat_t *s) {
87          s->collisions = 0;
88   }
89  
90 < static void network_stat_destroy(network_stat_t *s) {
90 > static void network_stat_destroy(sg_network_io_stats *s) {
91          free(s->interface_name);
92   }
93  
94 < VECTOR_DECLARE_STATIC(network_stats, network_stat_t, 5,
95 <                      network_stat_init, network_stat_destroy);
94 > VECTOR_DECLARE_STATIC(network_stats, sg_network_io_stats, 5,
95 >                      network_stat_init, network_stat_destroy);
96  
97 < network_stat_t *get_network_stats(int *entries){
97 > #ifdef WIN32
98 > static PMIB_IFTABLE win32_get_devices()
99 > {
100 >        PMIB_IFTABLE if_table;
101 >        PMIB_IFTABLE tmp;
102 >        unsigned long dwSize = 0;
103 >
104 >        // Allocate memory for pointers
105 >        if_table = sg_malloc(sizeof(MIB_IFTABLE));
106 >        if(if_table == NULL) {
107 >                return NULL;
108 >        }
109 >
110 >        // Get necessary size for the buffer
111 >        if(GetIfTable(if_table, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
112 >                tmp = sg_realloc(if_table, dwSize);
113 >                if(tmp == NULL) {
114 >                        free(if_table);
115 >                        return NULL;
116 >                }
117 >                if_table = tmp;
118 >        }
119 >
120 >        // Get the data
121 >        if(GetIfTable(if_table, &dwSize, 0) != NO_ERROR) {
122 >                free(if_table);
123 >                return NULL;
124 >        }
125 >        return if_table;
126 > }
127 > #endif /* WIN32 */
128 >
129 > sg_network_io_stats *sg_get_network_io_stats(int *entries){
130          int interfaces;
131 <        network_stat_t *network_stat_ptr;
131 >        sg_network_io_stats *network_stat_ptr;
132  
133   #ifdef SOLARIS
134 <        kstat_ctl_t *kc;
135 <        kstat_t *ksp;
134 >        kstat_ctl_t *kc;
135 >        kstat_t *ksp;
136          kstat_named_t *knp;
137   #endif
138  
# Line 110 | Line 147 | network_stat_t *get_network_stats(int *entries){
147          struct ifaddrs *net, *net_ptr;
148          struct if_data *net_data;
149   #endif
150 + #ifdef WIN32
151 +        PMIB_IFTABLE if_table;
152 +        MIB_IFROW if_row;
153 +        int i, no, j;
154  
155 +        /* used for duplicate interface names. 5 for space, hash, up to two
156 +         * numbers and terminating slash */
157 +        char buf[5];
158 + #endif
159 +
160   #ifdef ALLBSD
161          if(getifaddrs(&net) != 0){
162 +                sg_set_error_with_errno(SG_ERROR_GETIFADDRS, NULL);
163                  return NULL;
164          }
165  
# Line 126 | Line 173 | network_stat_t *get_network_stats(int *entries){
173                  }
174                  network_stat_ptr=network_stats+interfaces;
175                  
176 <                if (update_string(&network_stat_ptr->interface_name,
177 <                                  net_ptr->ifa_name) == NULL) {
176 >                if (sg_update_string(&network_stat_ptr->interface_name,
177 >                                     net_ptr->ifa_name) < 0) {
178                          return NULL;
179                  }
180                  net_data=(struct if_data *)net_ptr->ifa_data;
# Line 145 | Line 192 | network_stat_t *get_network_stats(int *entries){
192   #endif
193  
194   #ifdef SOLARIS
195 <        if ((kc = kstat_open()) == NULL) {
196 <                return NULL;
197 <        }
195 >        if ((kc = kstat_open()) == NULL) {
196 >                sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
197 >                return NULL;
198 >        }
199  
200          interfaces=0;
201  
202 <        for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
203 <                if (!strcmp(ksp->ks_class, "net")) {
204 <                        kstat_read(kc, ksp, NULL);
202 >        for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
203 >                if (strcmp(ksp->ks_class, "net") == 0) {
204 >                        kstat_read(kc, ksp, NULL);
205  
206   #ifdef SOL7
207   #define LRX "rbytes"
# Line 182 | Line 230 | network_stat_t *get_network_stats(int *entries){
230  
231                          /* Create new network_stats */
232                          if (VECTOR_RESIZE(network_stats, interfaces + 1) < 0) {
233 +                                kstat_close(kc);
234                                  return NULL;
235                          }
236                          network_stat_ptr=network_stats+interfaces;
237  
238 +                        /* Read interface name */
239 +                        if (sg_update_string(&network_stat_ptr->interface_name,
240 +                                             ksp->ks_name) < 0) {
241 +                                kstat_close(kc);
242 +                                return NULL;
243 +                        }
244 +
245                          /* Finish reading rx */
246                          network_stat_ptr->rx=knp->VALTYPE;
247  
# Line 225 | Line 281 | network_stat_t *get_network_stats(int *entries){
281                          }
282                          network_stat_ptr->collisions=knp->value.ui32;
283  
228                        /* Read interface name */
229                        if (update_string(&network_stat_ptr->interface_name,
230                                          ksp->ks_name) == NULL) {
231                                return NULL;
232                        }
284  
285                          /* Store systime */
286                          network_stat_ptr->systime=time(NULL);
# Line 243 | Line 294 | network_stat_t *get_network_stats(int *entries){
294   #ifdef LINUX
295          f=fopen("/proc/net/dev", "r");
296          if(f==NULL){
297 +                sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/net/dev");
298                  return NULL;
299          }
300          /* read the 2 lines.. Its the title, so we dont care :) */
# Line 251 | Line 303 | network_stat_t *get_network_stats(int *entries){
303  
304  
305          if((regcomp(&regex, "^ *([^:]+): *([0-9]+) +([0-9]+) +([0-9]+) +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +([0-9]+) +([0-9]+) +([0-9]+) +[0-9]+ +[0-9]+ +([0-9]+)", REG_EXTENDED))!=0){
306 +                sg_set_error(SG_ERROR_PARSE, NULL);
307                  return NULL;
308          }
309  
# Line 264 | Line 317 | network_stat_t *get_network_stats(int *entries){
317                  if (VECTOR_RESIZE(network_stats, interfaces + 1) < 0) {
318                          return NULL;
319                  }
320 <                network_stat_ptr=network_stats+interfaces;
320 >                network_stat_ptr=network_stats+interfaces;
321  
322                  if(network_stat_ptr->interface_name!=NULL){
323                          free(network_stat_ptr->interface_name);
324                  }
325  
326 <                network_stat_ptr->interface_name=get_string_match(line, &line_match[1]);
327 <                network_stat_ptr->rx=get_ll_match(line, &line_match[2]);
328 <                network_stat_ptr->tx=get_ll_match(line, &line_match[5]);
329 <                network_stat_ptr->ipackets=get_ll_match(line, &line_match[3]);
330 <                network_stat_ptr->opackets=get_ll_match(line, &line_match[6]);
331 <                network_stat_ptr->ierrors=get_ll_match(line, &line_match[4]);
332 <                network_stat_ptr->oerrors=get_ll_match(line, &line_match[7]);
333 <                network_stat_ptr->collisions=get_ll_match(line, &line_match[8]);
326 >                network_stat_ptr->interface_name=sg_get_string_match(line, &line_match[1]);
327 >                network_stat_ptr->rx=sg_get_ll_match(line, &line_match[2]);
328 >                network_stat_ptr->tx=sg_get_ll_match(line, &line_match[5]);
329 >                network_stat_ptr->ipackets=sg_get_ll_match(line, &line_match[3]);
330 >                network_stat_ptr->opackets=sg_get_ll_match(line, &line_match[6]);
331 >                network_stat_ptr->ierrors=sg_get_ll_match(line, &line_match[4]);
332 >                network_stat_ptr->oerrors=sg_get_ll_match(line, &line_match[7]);
333 >                network_stat_ptr->collisions=sg_get_ll_match(line, &line_match[8]);
334                  network_stat_ptr->systime=time(NULL);
335  
336                  interfaces++;
# Line 288 | Line 341 | network_stat_t *get_network_stats(int *entries){
341   #endif
342  
343   #ifdef CYGWIN
344 +        sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
345          return NULL;
346   #endif
347 + #ifdef HPUX
348 +        sg_set_error(SG_ERROR_UNSUPPORTED, "HP-UX");
349 +        return NULL;
350 + #endif
351  
352 + #ifdef WIN32
353 +        interfaces = 0;
354 +
355 +        if((if_table = win32_get_devices()) == NULL) {
356 +                sg_set_error(SG_ERROR_DEVICES, "network");
357 +                return NULL;
358 +        }
359 +
360 +        if(VECTOR_RESIZE(network_stats, if_table->dwNumEntries) < 0) {
361 +                free(if_table);
362 +                return NULL;
363 +        }
364 +
365 +        for (i=0; i<if_table->dwNumEntries; i++) {
366 +                network_stat_ptr=network_stats+i;
367 +                if_row = if_table->table[i];
368 +
369 +                if(sg_update_string(&network_stat_ptr->interface_name,
370 +                                        if_row.bDescr) < 0) {
371 +                        free(if_table);
372 +                        return NULL;
373 +                }
374 +                network_stat_ptr->tx = if_row.dwOutOctets;
375 +                network_stat_ptr->rx = if_row.dwInOctets;
376 +                network_stat_ptr->ipackets = if_row.dwInUcastPkts + if_row.dwInNUcastPkts;
377 +                network_stat_ptr->opackets = if_row.dwOutUcastPkts + if_row.dwOutNUcastPkts;
378 +                network_stat_ptr->ierrors = if_row.dwInErrors;
379 +                network_stat_ptr->oerrors = if_row.dwOutErrors;
380 +                network_stat_ptr->collisions = 0; /* can't do that */
381 +                network_stat_ptr->systime = time(NULL);
382 +
383 +                interfaces++;
384 +        }
385 +        free(if_table);
386 +
387 +        /* Please say there's a nicer way to do this...  If windows has two (or
388 +         * more) identical network cards, GetIfTable returns them with the same
389 +         * name, not like in Device Manager where the other has a #2 etc after
390 +         * it. So, add the #number here. Should we be doing this? Or should the
391 +         * end programs be dealing with duplicate names? Currently breaks
392 +         * watch.pl in rrdgraphing. But Unix does not have the issue of
393 +         * duplicate net device names.
394 +         */
395 +        for (i=0; i<interfaces; i++) {
396 +                no = 2;
397 +                for(j=i+1; j<interfaces; j++) {
398 +                        network_stat_ptr=network_stats+j;
399 +                        if(strcmp(network_stats[i].interface_name,
400 +                                        network_stat_ptr->interface_name) == 0) {
401 +                                if(snprintf(buf, sizeof(buf), " #%d", no) < 0) {
402 +                                        break;
403 +                                }
404 +                                if(sg_concat_string(&network_stat_ptr->interface_name, buf) != 0) {
405 +                                        return NULL;
406 +                                }
407 +
408 +                                no++;
409 +                        }
410 +                }
411 +        }
412 + #endif
413 +
414          *entries=interfaces;
415  
416          return network_stats;  
417   }
418  
419 < long long transfer_diff(long long new, long long old){
420 < #if defined(SOL7) || defined(LINUX) || defined(FREEBSD) || defined(DFBSD) || defined(OPENBSD)
419 > static long long transfer_diff(long long new, long long old){
420 > #if defined(SOL7) || defined(LINUX) || defined(FREEBSD) || defined(DFBSD) || defined(OPENBSD) || defined(WIN32)
421          /* 32-bit quantities, so we must explicitly deal with wraparound. */
422   #define MAXVAL 0x100000000LL
423          if (new >= old) {
# Line 311 | Line 431 | long long transfer_diff(long long new, long long old){
431   #endif
432   }
433  
434 < network_stat_t *get_network_stats_diff(int *entries) {
435 <        VECTOR_DECLARE_STATIC(diff, network_stat_t, 1,
436 <                              network_stat_init, network_stat_destroy);
437 <        network_stat_t *src = NULL, *dest;
434 > sg_network_io_stats *sg_get_network_io_stats_diff(int *entries) {
435 >        VECTOR_DECLARE_STATIC(diff, sg_network_io_stats, 1,
436 >                              network_stat_init, network_stat_destroy);
437 >        sg_network_io_stats *src = NULL, *dest;
438          int i, j, diff_count, new_count;
439  
440          if (network_stats == NULL) {
441                  /* No previous stats, so we can't calculate a difference. */
442 <                return get_network_stats(entries);
442 >                return sg_get_network_io_stats(entries);
443          }
444  
445          /* Resize the results array to match the previous stats. */
# Line 333 | Line 453 | network_stat_t *get_network_stats_diff(int *entries) {
453                  src = &network_stats[i];
454                  dest = &diff[i];
455  
456 <                if (update_string(&dest->interface_name,
457 <                                  src->interface_name) == NULL) {
456 >                if (sg_update_string(&dest->interface_name,
457 >                                     src->interface_name) < 0) {
458                          return NULL;
459                  }
460                  dest->rx = src->rx;
# Line 348 | Line 468 | network_stat_t *get_network_stats_diff(int *entries) {
468          }
469  
470          /* Get a new set of stats. */
471 <        if (get_network_stats(&new_count) == NULL) {
471 >        if (sg_get_network_io_stats(&new_count) == NULL) {
472                  return NULL;
473          }
474  
# Line 386 | Line 506 | network_stat_t *get_network_stats_diff(int *entries) {
506          return diff;
507   }
508  
509 + int sg_network_io_compare_name(const void *va, const void *vb) {
510 +        const sg_network_io_stats *a = (const sg_network_io_stats *)va;
511 +        const sg_network_io_stats *b = (const sg_network_io_stats *)vb;
512 +
513 +        return strcmp(a->interface_name, b->interface_name);
514 + }
515 +
516   /* NETWORK INTERFACE STATS */
517  
518 < static void network_iface_stat_init(network_iface_stat_t *s) {
518 > static void network_iface_stat_init(sg_network_iface_stats *s) {
519          s->interface_name = NULL;
520          s->speed = 0;
521 <        s->dup = UNKNOWN_DUPLEX;
521 >        s->duplex = SG_IFACE_DUPLEX_UNKNOWN;
522   }
523  
524 < static void network_iface_stat_destroy(network_iface_stat_t *s) {
524 > static void network_iface_stat_destroy(sg_network_iface_stats *s) {
525          free(s->interface_name);
526   }
527  
528 < network_iface_stat_t *get_network_iface_stats(int *entries){
529 <        VECTOR_DECLARE_STATIC(network_iface_stats, network_iface_stat_t, 5,
530 <                              network_iface_stat_init, network_iface_stat_destroy);
531 <        network_iface_stat_t *network_iface_stat_ptr;
528 > sg_network_iface_stats *sg_get_network_iface_stats(int *entries){
529 >        VECTOR_DECLARE_STATIC(network_iface_stats, sg_network_iface_stats, 5,
530 >                              network_iface_stat_init, network_iface_stat_destroy);
531 >        sg_network_iface_stats *network_iface_stat_ptr;
532          int ifaces = 0;
533  
534   #ifdef SOLARIS
535 <        kstat_ctl_t *kc;
536 <        kstat_t *ksp;
535 >        kstat_ctl_t *kc;
536 >        kstat_t *ksp;
537          kstat_named_t *knp;
538          int sock;
539   #endif
540   #ifdef ALLBSD
541 <        struct ifaddrs *net, *net_ptr;
541 >        struct ifaddrs *net, *net_ptr;
542          struct ifmediareq ifmed;
543          struct ifreq ifr;
544          int sock;
545          int x;
546   #endif
547   #ifdef LINUX
548 <        FILE *f;
549 <        /* Horrible big enough, but it should be easily big enough */
550 <        char line[8096];
548 >        FILE *f;
549 >        /* Horrible big enough, but it should be easily big enough */
550 >        char line[8096];
551          int sock;
552   #endif
553 + #ifdef WIN32
554 +        PMIB_IFTABLE if_table;
555 +        MIB_IFROW if_row;
556 +        int i,j,no;
557 +        char buf[5];
558 + #endif
559  
560   #ifdef ALLBSD
561 <        if(getifaddrs(&net) != 0){
562 <                return NULL;
563 <        }
561 >        if(getifaddrs(&net) != 0){
562 >                sg_set_error_with_errno(SG_ERROR_GETIFADDRS, NULL);
563 >                return NULL;
564 >        }
565  
566          if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == 0) return NULL;
567  
568          for(net_ptr=net; net_ptr!=NULL; net_ptr=net_ptr->ifa_next){
569 <                if(net_ptr->ifa_addr->sa_family != AF_LINK) continue;
569 >                if(net_ptr->ifa_addr->sa_family != AF_LINK) continue;
570  
571                  if (VECTOR_RESIZE(network_iface_stats, ifaces + 1) < 0) {
572 <                        return NULL;
573 <                }
574 <                network_iface_stat_ptr = network_iface_stats + ifaces;
572 >                        return NULL;
573 >                }
574 >                network_iface_stat_ptr = network_iface_stats + ifaces;
575  
576                  memset(&ifr, 0, sizeof(ifr));
577                  strncpy(ifr.ifr_name, net_ptr->ifa_name, sizeof(ifr.ifr_name));
# Line 451 | Line 585 | network_iface_stat_t *get_network_iface_stats(int *ent
585                          network_iface_stat_ptr->up = 0;
586                  }
587  
588 <                if (update_string(&network_iface_stat_ptr->interface_name,
589 <                                  net_ptr->ifa_name) == NULL) {
588 >                if (sg_update_string(&network_iface_stat_ptr->interface_name,
589 >                                     net_ptr->ifa_name) < 0) {
590                          return NULL;
591                  }
592  
593                  network_iface_stat_ptr->speed = 0;
594 <                network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
594 >                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
595                  ifaces++;
596  
597                  memset(&ifmed, 0, sizeof(struct ifmediareq));
598 <                strlcpy(ifmed.ifm_name, net_ptr->ifa_name, sizeof(ifmed.ifm_name));
598 >                sg_strlcpy(ifmed.ifm_name, net_ptr->ifa_name, sizeof(ifmed.ifm_name));
599                  if(ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmed) == -1){
600                          /* Not all interfaces support the media ioctls. */
601                          continue;
# Line 473 | Line 607 | network_iface_stat_t *get_network_iface_stats(int *ent
607                          continue;
608                  }
609  
610 <                /* Only intrested in the first 4 bits)  - Assuming only ETHER devices */
611 <                x = ifmed.ifm_active & 0x0f;    
610 >                /* Assuming only ETHER devices */
611 >                x = IFM_SUBTYPE(ifmed.ifm_active);
612                  switch(x){
613                          /* 10 Mbit connections. Speedy :) */
614                          case(IFM_10_T):
# Line 484 | Line 618 | network_iface_stat_t *get_network_iface_stats(int *ent
618                          case(IFM_10_FL):
619                                  network_iface_stat_ptr->speed = 10;
620                                  break;
621 <                        /* 100 Mbit conneections */
621 >                        /* 100 Mbit connections */
622                          case(IFM_100_TX):
623                          case(IFM_100_FX):
624                          case(IFM_100_T4):
# Line 514 | Line 648 | network_iface_stat_t *get_network_iface_stats(int *ent
648                  }
649  
650                  if( (ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active ){
651 <                        network_iface_stat_ptr->dup = FULL_DUPLEX;
651 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL;
652                  }else if( (ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active ){
653 <                        network_iface_stat_ptr->dup = HALF_DUPLEX;
653 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF;
654                  }else{
655 <                        network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
655 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
656                  }
657  
658          }      
# Line 528 | Line 662 | network_iface_stat_t *get_network_iface_stats(int *ent
662  
663   #ifdef SOLARIS
664          if ((kc = kstat_open()) == NULL) {
665 +                sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
666                  return NULL;
667          }
668  
669          if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
670 +                sg_set_error_with_errno(SG_ERROR_SOCKET, NULL);
671 +                kstat_close(kc);
672                  return NULL;
673          }
674  
675          for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
676 <                if (!strcmp(ksp->ks_class, "net")) {
676 >                if (strcmp(ksp->ks_class, "net") == 0) {
677                          struct ifreq ifr;
678  
679                          kstat_read(kc, ksp, NULL);
# Line 548 | Line 685 | network_iface_stat_t *get_network_iface_stats(int *ent
685                          }
686  
687                          if (VECTOR_RESIZE(network_iface_stats, ifaces + 1) < 0) {
688 +                                kstat_close(kc);
689                                  return NULL;
690                          }
691                          network_iface_stat_ptr = network_iface_stats + ifaces;
692                          ifaces++;
693  
694 <                        if (update_string(&network_iface_stat_ptr->interface_name,
695 <                                          ksp->ks_name) == NULL) {
694 >                        if (sg_update_string(&network_iface_stat_ptr->interface_name,
695 >                                             ksp->ks_name) < 0) {
696 >                                kstat_close(kc);
697                                  return NULL;
698                          }
699  
700                          if ((ifr.ifr_flags & IFF_UP) != 0) {
701 <                                network_iface_stat_ptr->up = 1;
701 >                                if ((knp = kstat_data_lookup(ksp, "link_up")) != NULL) {
702 >                                        /* take in to account if link
703 >                                         * is up as well as interface */
704 >                                        if (knp->value.ui32 != 0u) {
705 >                                                network_iface_stat_ptr->up = 1;
706 >                                        } else {
707 >                                                network_iface_stat_ptr->up = 0;
708 >                                        }
709 >                                }
710 >                                else {
711 >                                        /* maintain compatibility */
712 >                                        network_iface_stat_ptr->up = 1;
713 >                                }
714                          } else {
715 <                                network_iface_stat_ptr->up = 1;
715 >                                network_iface_stat_ptr->up = 0;
716                          }
717  
718                          if ((knp = kstat_data_lookup(ksp, "ifspeed")) != NULL) {
# Line 570 | Line 721 | network_iface_stat_t *get_network_iface_stats(int *ent
721                                  network_iface_stat_ptr->speed = 0;
722                          }
723  
724 <                        network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
724 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
725                          if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) {
726                                  switch (knp->value.ui32) {
727                                  case 1:
728 <                                        network_iface_stat_ptr->dup = HALF_DUPLEX;
728 >                                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF;
729                                          break;
730                                  case 2:
731 <                                        network_iface_stat_ptr->dup = FULL_DUPLEX;
731 >                                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL;
732                                          break;
733                                  }
734                          }
# Line 586 | Line 737 | network_iface_stat_t *get_network_iface_stats(int *ent
737  
738          close(sock);
739          kstat_close(kc);
740 < #endif  
740 > #endif
741   #ifdef LINUX
742          f = fopen("/proc/net/dev", "r");
743 <        if(f == NULL){
744 <                return NULL;
745 <        }
743 >        if(f == NULL){
744 >                sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/net/dev");
745 >                return NULL;
746 >        }
747  
748          /* Setup stuff so we can do the ioctl to get the info */
749          if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
750 +                sg_set_error_with_errno(SG_ERROR_SOCKET, NULL);
751                  return NULL;
752          }
753  
754          /* Ignore first 2 lines.. Just headings */
755 <        if((fgets(line, sizeof(line), f)) == NULL) return NULL;
756 <        if((fgets(line, sizeof(line), f)) == NULL) return NULL;
755 >        if((fgets(line, sizeof(line), f)) == NULL) {
756 >                sg_set_error(SG_ERROR_PARSE, NULL);
757 >                return NULL;
758 >        }
759 >        if((fgets(line, sizeof(line), f)) == NULL) {
760 >                sg_set_error(SG_ERROR_PARSE, NULL);
761 >                return NULL;
762 >        }
763  
764 <        while((fgets(line, sizeof(line), f)) != NULL){
765 <                char *name, *ptr;
766 <                struct ifreq ifr;
767 <                struct ethtool_cmd ethcmd;
768 <                int err;
764 >        while((fgets(line, sizeof(line), f)) != NULL){
765 >                char *name, *ptr;
766 >                struct ifreq ifr;
767 >                struct ethtool_cmd ethcmd;
768 >                int err;
769  
770                  /* Get the interface name */
771 <                ptr = strchr(line, ':');
772 <                if (ptr == NULL) continue;
773 <                *ptr='\0';
774 <                name = line;
775 <                while(isspace(*(name))){
776 <                        name++;
777 <                }
771 >                ptr = strchr(line, ':');
772 >                if (ptr == NULL) continue;
773 >                *ptr='\0';
774 >                name = line;
775 >                while(isspace(*(name))){
776 >                        name++;
777 >                }
778  
779 <                memset(&ifr, 0, sizeof ifr);
780 <                strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
779 >                memset(&ifr, 0, sizeof ifr);
780 >                strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
781  
782                  if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
783                          continue;
# Line 630 | Line 789 | network_iface_stat_t *get_network_iface_stats(int *ent
789                  }
790                  network_iface_stat_ptr = network_iface_stats + ifaces;
791                  
792 <                if (update_string(&network_iface_stat_ptr->interface_name,
793 <                                  name) == NULL) {
792 >                if (sg_update_string(&network_iface_stat_ptr->interface_name,
793 >                                     name) < 0) {
794                          return NULL;
795                  }
796                  if ((ifr.ifr_flags & IFF_UP) != 0) {
# Line 640 | Line 799 | network_iface_stat_t *get_network_iface_stats(int *ent
799                          network_iface_stat_ptr->up = 0;
800                  }
801  
802 <                memset(&ethcmd, 0, sizeof ethcmd);
803 <                ethcmd.cmd = ETHTOOL_GSET;
804 <                ifr.ifr_data = (caddr_t) &ethcmd;
802 >                memset(&ethcmd, 0, sizeof ethcmd);
803 >                ethcmd.cmd = ETHTOOL_GSET;
804 >                ifr.ifr_data = (caddr_t) &ethcmd;
805  
806 <                err = ioctl(sock, SIOCETHTOOL, &ifr);
807 <                if (err == 0) {
806 >                err = ioctl(sock, SIOCETHTOOL, &ifr);
807 >                if (err == 0) {
808                          network_iface_stat_ptr->speed = ethcmd.speed;
809  
810                          switch (ethcmd.duplex) {
811 <                        case 0x00:
812 <                                network_iface_stat_ptr->dup = FULL_DUPLEX;
811 >                        case DUPLEX_FULL:
812 >                                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL;
813                                  break;
814 <                        case 0x01:
815 <                                network_iface_stat_ptr->dup = HALF_DUPLEX;
814 >                        case DUPLEX_HALF:
815 >                                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF;
816                                  break;
817                          default:
818 <                                network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
818 >                                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
819                          }
820                  } else {
821                          /* Not all interfaces support the ethtool ioctl. */
822                          network_iface_stat_ptr->speed = 0;
823 <                        network_iface_stat_ptr->dup = UNKNOWN_DUPLEX;
823 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
824                  }
825  
826                  ifaces++;
# Line 669 | Line 828 | network_iface_stat_t *get_network_iface_stats(int *ent
828          close(sock);
829          fclose(f);
830   #endif
831 + #ifdef CYGWIN
832 +        sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
833 +        return NULL;
834 + #endif
835 + #ifdef HPUX
836 +        sg_set_error(SG_ERROR_UNSUPPORTED, "HP-UX");
837 +        return NULL;
838 + #endif
839 + #ifdef WIN32
840 +        ifaces = 0;
841 +
842 +        if((if_table = win32_get_devices()) == NULL) {
843 +                sg_set_error(SG_ERROR_DEVICES, "network interfaces");
844 +                return NULL;
845 +        }
846 +
847 +        if(VECTOR_RESIZE(network_iface_stats, if_table->dwNumEntries) < 0) {
848 +                free(if_table);
849 +                return NULL;
850 +        }
851 +
852 +        for(i=0; i<if_table->dwNumEntries; i++) {
853 +                network_iface_stat_ptr=network_iface_stats+i;
854 +                if_row = if_table->table[i];
855 +
856 +                if(sg_update_string(&network_iface_stat_ptr->interface_name,
857 +                                        if_row.bDescr) < 0) {
858 +                        free(if_table);
859 +                        return NULL;
860 +                }
861 +                network_iface_stat_ptr->speed = if_row.dwSpeed /1000000;
862 +
863 +                if((if_row.dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED ||
864 +                                if_row.dwOperStatus ==
865 +                                        MIB_IF_OPER_STATUS_OPERATIONAL) &&
866 +                                if_row.dwAdminStatus == 1) {
867 +                        network_iface_stat_ptr->up = 1;
868 +                } else {
869 +                        network_iface_stat_ptr->up = 0;
870 +                }
871 +
872 +                ifaces++;
873 +        }
874 +        free(if_table);
875 +
876 +        /* again with the renumbering */
877 +        for (i=0; i<ifaces; i++) {
878 +                no = 2;
879 +                for(j=i+1; j<ifaces; j++) {
880 +                        network_iface_stat_ptr=network_iface_stats+j;
881 +                        if(strcmp(network_iface_stats[i].interface_name,
882 +                                        network_iface_stat_ptr->interface_name) == 0) {
883 +                                if(snprintf(buf, sizeof(buf), " #%d", no) < 0) {
884 +                                        break;
885 +                                }
886 +                                if(sg_concat_string(&network_iface_stat_ptr->interface_name, buf) != 0) {
887 +                                        return NULL;
888 +                                }
889 +
890 +                                no++;
891 +                        }
892 +                }
893 +        }
894 + #endif
895 +
896 + #ifdef SG_ENABLE_DEPRECATED
897 +        network_iface_stat_ptr->dup = network_iface_stat_ptr->duplex;
898 + #endif
899 +
900          *entries = ifaces;
901          return network_iface_stats;
902 + }
903 +
904 + int sg_network_iface_compare_name(const void *va, const void *vb) {
905 +        const sg_network_iface_stats *a = (const sg_network_iface_stats *)va;
906 +        const sg_network_iface_stats *b = (const sg_network_iface_stats *)vb;
907 +
908 +        return strcmp(a->interface_name, b->interface_name);
909   }
910  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines