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.67 by tdb, Thu Apr 8 10:56:13 2004 UTC vs.
Revision 1.77 by tdb, Sun Jan 22 18:10:39 2006 UTC

# Line 49 | Line 49
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 69 | 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(sg_network_io_stats *s) {
80          s->interface_name = NULL;
# Line 88 | Line 94 | static void network_stat_destroy(sg_network_io_stats *
94   VECTOR_DECLARE_STATIC(network_stats, sg_network_io_stats, 5,
95                        network_stat_init, network_stat_destroy);
96  
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          sg_network_io_stats *network_stat_ptr;
# Line 109 | Line 147 | sg_network_io_stats *sg_get_network_io_stats(int *entr
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(SG_ERROR_GETIFADDRS, NULL);
162 >                sg_set_error_with_errno(SG_ERROR_GETIFADDRS, NULL);
163                  return NULL;
164          }
165  
# Line 153 | Line 200 | sg_network_io_stats *sg_get_network_io_stats(int *entr
200          interfaces=0;
201  
202          for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
203 <                if (!strcmp(ksp->ks_class, "net")) {
203 >                if (strcmp(ksp->ks_class, "net") == 0) {
204                          kstat_read(kc, ksp, NULL);
205  
206   #ifdef SOL7
# Line 244 | Line 291 | sg_network_io_stats *sg_get_network_io_stats(int *entr
291   #ifdef LINUX
292          f=fopen("/proc/net/dev", "r");
293          if(f==NULL){
294 <                sg_set_error(SG_ERROR_OPEN, "/proc/net/dev");
294 >                sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/net/dev");
295                  return NULL;
296          }
297          /* read the 2 lines.. Its the title, so we dont care :) */
# Line 294 | Line 341 | sg_network_io_stats *sg_get_network_io_stats(int *entr
341          sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
342          return NULL;
343   #endif
344 + #ifdef HPUX
345 +        sg_set_error(SG_ERROR_UNSUPPORTED, "HP-UX");
346 +        return NULL;
347 + #endif
348  
349 + #ifdef WIN32
350 +        interfaces = 0;
351 +
352 +        if((if_table = win32_get_devices()) == NULL) {
353 +                sg_set_error(SG_ERROR_DEVICES, "network");
354 +                return NULL;
355 +        }
356 +
357 +        if(VECTOR_RESIZE(network_stats, if_table->dwNumEntries) < 0) {
358 +                free(if_table);
359 +                return NULL;
360 +        }
361 +
362 +        for (i=0; i<if_table->dwNumEntries; i++) {
363 +                network_stat_ptr=network_stats+i;
364 +                if_row = if_table->table[i];
365 +
366 +                if(sg_update_string(&network_stat_ptr->interface_name,
367 +                                        if_row.bDescr) < 0) {
368 +                        free(if_table);
369 +                        return NULL;
370 +                }
371 +                network_stat_ptr->tx = if_row.dwOutOctets;
372 +                network_stat_ptr->rx = if_row.dwInOctets;
373 +                network_stat_ptr->ipackets = if_row.dwInUcastPkts + if_row.dwInNUcastPkts;
374 +                network_stat_ptr->opackets = if_row.dwOutUcastPkts + if_row.dwOutNUcastPkts;
375 +                network_stat_ptr->ierrors = if_row.dwInErrors;
376 +                network_stat_ptr->oerrors = if_row.dwOutErrors;
377 +                network_stat_ptr->collisions = 0; /* can't do that */
378 +                network_stat_ptr->systime = time(NULL);
379 +
380 +                interfaces++;
381 +        }
382 +        free(if_table);
383 +
384 +        /* Please say there's a nicer way to do this...  If windows has two (or
385 +         * more) identical network cards, GetIfTable returns them with the same
386 +         * name, not like in Device Manager where the other has a #2 etc after
387 +         * it. So, add the #number here. Should we be doing this? Or should the
388 +         * end programs be dealing with duplicate names? Currently breaks
389 +         * watch.pl in rrdgraphing. But Unix does not have the issue of
390 +         * duplicate net device names.
391 +         */
392 +        for (i=0; i<interfaces; i++) {
393 +                no = 2;
394 +                for(j=i+1; j<interfaces; j++) {
395 +                        network_stat_ptr=network_stats+j;
396 +                        if(strcmp(network_stats[i].interface_name,
397 +                                        network_stat_ptr->interface_name) == 0) {
398 +                                if(snprintf(buf, sizeof(buf), " #%d", no) < 0) {
399 +                                        break;
400 +                                }
401 +                                if(sg_concat_string(&network_stat_ptr->interface_name, buf) != 0) {
402 +                                        return NULL;
403 +                                }
404 +
405 +                                no++;
406 +                        }
407 +                }
408 +        }
409 + #endif
410 +
411          *entries=interfaces;
412  
413          return network_stats;  
414   }
415  
416   static long long transfer_diff(long long new, long long old){
417 < #if defined(SOL7) || defined(LINUX) || defined(FREEBSD) || defined(DFBSD) || defined(OPENBSD)
417 > #if defined(SOL7) || defined(LINUX) || defined(FREEBSD) || defined(DFBSD) || defined(OPENBSD) || defined(WIN32)
418          /* 32-bit quantities, so we must explicitly deal with wraparound. */
419   #define MAXVAL 0x100000000LL
420          if (new >= old) {
# Line 390 | Line 503 | sg_network_io_stats *sg_get_network_io_stats_diff(int
503          return diff;
504   }
505  
506 + int sg_network_io_compare_name(const void *va, const void *vb) {
507 +        const sg_network_io_stats *a = (const sg_network_io_stats *)va;
508 +        const sg_network_io_stats *b = (const sg_network_io_stats *)vb;
509 +
510 +        return strcmp(a->interface_name, b->interface_name);
511 + }
512 +
513   /* NETWORK INTERFACE STATS */
514  
515   static void network_iface_stat_init(sg_network_iface_stats *s) {
516          s->interface_name = NULL;
517          s->speed = 0;
518 <        s->dup = SG_IFACE_DUPLEX_UNKNOWN;
518 >        s->duplex = SG_IFACE_DUPLEX_UNKNOWN;
519   }
520  
521   static void network_iface_stat_destroy(sg_network_iface_stats *s) {
# Line 427 | Line 547 | sg_network_iface_stats *sg_get_network_iface_stats(int
547          char line[8096];
548          int sock;
549   #endif
550 + #ifdef WIN32
551 +        PMIB_IFTABLE if_table;
552 +        MIB_IFROW if_row;
553 +        int i,j,no;
554 +        char buf[5];
555 + #endif
556  
557   #ifdef ALLBSD
558          if(getifaddrs(&net) != 0){
559 <                sg_set_error(SG_ERROR_GETIFADDRS, NULL);
559 >                sg_set_error_with_errno(SG_ERROR_GETIFADDRS, NULL);
560                  return NULL;
561          }
562  
# Line 462 | Line 588 | sg_network_iface_stats *sg_get_network_iface_stats(int
588                  }
589  
590                  network_iface_stat_ptr->speed = 0;
591 <                network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
591 >                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
592                  ifaces++;
593  
594                  memset(&ifmed, 0, sizeof(struct ifmediareq));
# Line 519 | Line 645 | sg_network_iface_stats *sg_get_network_iface_stats(int
645                  }
646  
647                  if( (ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active ){
648 <                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_FULL;
648 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL;
649                  }else if( (ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active ){
650 <                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_HALF;
650 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF;
651                  }else{
652 <                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
652 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
653                  }
654  
655          }      
# Line 538 | Line 664 | sg_network_iface_stats *sg_get_network_iface_stats(int
664          }
665  
666          if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
667 <                sg_set_error(SG_ERROR_SOCKET, NULL);
667 >                sg_set_error_with_errno(SG_ERROR_SOCKET, NULL);
668                  return NULL;
669          }
670  
671          for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
672 <                if (!strcmp(ksp->ks_class, "net")) {
672 >                if (strcmp(ksp->ks_class, "net") == 0) {
673                          struct ifreq ifr;
674  
675                          kstat_read(kc, ksp, NULL);
# Line 568 | Line 694 | sg_network_iface_stats *sg_get_network_iface_stats(int
694                          if ((ifr.ifr_flags & IFF_UP) != 0) {
695                                  network_iface_stat_ptr->up = 1;
696                          } else {
697 <                                network_iface_stat_ptr->up = 1;
697 >                                network_iface_stat_ptr->up = 0;
698                          }
699  
700                          if ((knp = kstat_data_lookup(ksp, "ifspeed")) != NULL) {
# Line 577 | Line 703 | sg_network_iface_stats *sg_get_network_iface_stats(int
703                                  network_iface_stat_ptr->speed = 0;
704                          }
705  
706 <                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
706 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
707                          if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) {
708                                  switch (knp->value.ui32) {
709                                  case 1:
710 <                                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_HALF;
710 >                                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF;
711                                          break;
712                                  case 2:
713 <                                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_FULL;
713 >                                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL;
714                                          break;
715                                  }
716                          }
# Line 593 | Line 719 | sg_network_iface_stats *sg_get_network_iface_stats(int
719  
720          close(sock);
721          kstat_close(kc);
722 < #endif  
722 > #endif
723   #ifdef LINUX
724          f = fopen("/proc/net/dev", "r");
725          if(f == NULL){
726 <                sg_set_error(SG_ERROR_OPEN, "/proc/net/dev");
726 >                sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/net/dev");
727                  return NULL;
728          }
729  
730          /* Setup stuff so we can do the ioctl to get the info */
731          if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
732 <                sg_set_error(SG_ERROR_SOCKET, NULL);
732 >                sg_set_error_with_errno(SG_ERROR_SOCKET, NULL);
733                  return NULL;
734          }
735  
# Line 664 | Line 790 | sg_network_iface_stats *sg_get_network_iface_stats(int
790                          network_iface_stat_ptr->speed = ethcmd.speed;
791  
792                          switch (ethcmd.duplex) {
793 <                        case 0x00:
794 <                                network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_FULL;
793 >                        case DUPLEX_FULL:
794 >                                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL;
795                                  break;
796 <                        case 0x01:
797 <                                network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_HALF;
796 >                        case DUPLEX_HALF:
797 >                                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF;
798                                  break;
799                          default:
800 <                                network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
800 >                                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
801                          }
802                  } else {
803                          /* Not all interfaces support the ethtool ioctl. */
804                          network_iface_stat_ptr->speed = 0;
805 <                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
805 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
806                  }
807  
808                  ifaces++;
# Line 684 | Line 810 | sg_network_iface_stats *sg_get_network_iface_stats(int
810          close(sock);
811          fclose(f);
812   #endif
813 + #ifdef CYGWIN
814 +        sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
815 +        return NULL;
816 + #endif
817 + #ifdef HPUX
818 +        sg_set_error(SG_ERROR_UNSUPPORTED, "HP-UX");
819 +        return NULL;
820 + #endif
821 + #ifdef WIN32
822 +        ifaces = 0;
823 +
824 +        if((if_table = win32_get_devices()) == NULL) {
825 +                sg_set_error(SG_ERROR_DEVICES, "network interfaces");
826 +                return NULL;
827 +        }
828 +
829 +        if(VECTOR_RESIZE(network_iface_stats, if_table->dwNumEntries) < 0) {
830 +                free(if_table);
831 +                return NULL;
832 +        }
833 +
834 +        for(i=0; i<if_table->dwNumEntries; i++) {
835 +                network_iface_stat_ptr=network_iface_stats+i;
836 +                if_row = if_table->table[i];
837 +
838 +                if(sg_update_string(&network_iface_stat_ptr->interface_name,
839 +                                        if_row.bDescr) < 0) {
840 +                        free(if_table);
841 +                        return NULL;
842 +                }
843 +                network_iface_stat_ptr->speed = if_row.dwSpeed /1000000;
844 +
845 +                if((if_row.dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED ||
846 +                                if_row.dwOperStatus ==
847 +                                        MIB_IF_OPER_STATUS_OPERATIONAL) &&
848 +                                if_row.dwAdminStatus == 1) {
849 +                        network_iface_stat_ptr->up = 1;
850 +                } else {
851 +                        network_iface_stat_ptr->up = 0;
852 +                }
853 +
854 +                ifaces++;
855 +        }
856 +        free(if_table);
857 +
858 +        /* again with the renumbering */
859 +        for (i=0; i<ifaces; i++) {
860 +                no = 2;
861 +                for(j=i+1; j<ifaces; j++) {
862 +                        network_iface_stat_ptr=network_iface_stats+j;
863 +                        if(strcmp(network_iface_stats[i].interface_name,
864 +                                        network_iface_stat_ptr->interface_name) == 0) {
865 +                                if(snprintf(buf, sizeof(buf), " #%d", no) < 0) {
866 +                                        break;
867 +                                }
868 +                                if(sg_concat_string(&network_iface_stat_ptr->interface_name, buf) != 0) {
869 +                                        return NULL;
870 +                                }
871 +
872 +                                no++;
873 +                        }
874 +                }
875 +        }
876 + #endif
877 +
878 + #ifdef SG_ENABLE_DEPRECATED
879 +        network_iface_stat_ptr->dup = network_iface_stat_ptr->duplex;
880 + #endif
881 +
882          *entries = ifaces;
883          return network_iface_stats;
884 + }
885 +
886 + int sg_network_iface_compare_name(const void *va, const void *vb) {
887 +        const sg_network_iface_stats *a = (const sg_network_iface_stats *)va;
888 +        const sg_network_iface_stats *b = (const sg_network_iface_stats *)vb;
889 +
890 +        return strcmp(a->interface_name, b->interface_name);
891   }
892  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines