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.70 by ats, Sun Nov 7 12:30:54 2004 UTC vs.
Revision 1.79 by tdb, Mon Oct 9 17:23:07 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_with_errno(SG_ERROR_GETIFADDRS, NULL);
# 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 183 | Line 230 | sg_network_io_stats *sg_get_network_io_stats(int *entr
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 226 | Line 281 | sg_network_io_stats *sg_get_network_io_stats(int *entr
281                          }
282                          network_stat_ptr->collisions=knp->value.ui32;
283  
229                        /* Read interface name */
230                        if (sg_update_string(&network_stat_ptr->interface_name,
231                                             ksp->ks_name) < 0) {
232                                return NULL;
233                        }
284  
285                          /* Store systime */
286                          network_stat_ptr->systime=time(NULL);
# Line 299 | Line 349 | sg_network_io_stats *sg_get_network_io_stats(int *entr
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   static long long transfer_diff(long long new, long long old){
420 < #if defined(SOL7) || defined(LINUX) || defined(FREEBSD) || defined(DFBSD) || defined(OPENBSD)
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 406 | Line 518 | int sg_network_io_compare_name(const void *va, const v
518   static void network_iface_stat_init(sg_network_iface_stats *s) {
519          s->interface_name = NULL;
520          s->speed = 0;
521 <        s->dup = SG_IFACE_DUPLEX_UNKNOWN;
521 >        s->duplex = SG_IFACE_DUPLEX_UNKNOWN;
522   }
523  
524   static void network_iface_stat_destroy(sg_network_iface_stats *s) {
# Line 438 | Line 550 | sg_network_iface_stats *sg_get_network_iface_stats(int
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){
# Line 473 | Line 591 | sg_network_iface_stats *sg_get_network_iface_stats(int
591                  }
592  
593                  network_iface_stat_ptr->speed = 0;
594 <                network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
594 >                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
595                  ifaces++;
596  
597                  memset(&ifmed, 0, sizeof(struct ifmediareq));
# Line 530 | Line 648 | sg_network_iface_stats *sg_get_network_iface_stats(int
648                  }
649  
650                  if( (ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active ){
651 <                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_FULL;
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 = SG_IFACE_DUPLEX_HALF;
653 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF;
654                  }else{
655 <                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
655 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
656                  }
657  
658          }      
# Line 550 | Line 668 | sg_network_iface_stats *sg_get_network_iface_stats(int
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 566 | Line 685 | sg_network_iface_stats *sg_get_network_iface_stats(int
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;
# Line 573 | Line 693 | sg_network_iface_stats *sg_get_network_iface_stats(int
693  
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;
702                          } else {
703 <                                network_iface_stat_ptr->up = 1;
703 >                                network_iface_stat_ptr->up = 0;
704                          }
705  
706                          if ((knp = kstat_data_lookup(ksp, "ifspeed")) != NULL) {
# Line 588 | Line 709 | sg_network_iface_stats *sg_get_network_iface_stats(int
709                                  network_iface_stat_ptr->speed = 0;
710                          }
711  
712 <                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
712 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
713                          if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) {
714                                  switch (knp->value.ui32) {
715                                  case 1:
716 <                                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_HALF;
716 >                                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF;
717                                          break;
718                                  case 2:
719 <                                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_FULL;
719 >                                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL;
720                                          break;
721                                  }
722                          }
# Line 604 | Line 725 | sg_network_iface_stats *sg_get_network_iface_stats(int
725  
726          close(sock);
727          kstat_close(kc);
728 < #endif  
728 > #endif
729   #ifdef LINUX
730          f = fopen("/proc/net/dev", "r");
731          if(f == NULL){
# Line 675 | Line 796 | sg_network_iface_stats *sg_get_network_iface_stats(int
796                          network_iface_stat_ptr->speed = ethcmd.speed;
797  
798                          switch (ethcmd.duplex) {
799 <                        case 0x00:
800 <                                network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_FULL;
799 >                        case DUPLEX_FULL:
800 >                                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL;
801                                  break;
802 <                        case 0x01:
803 <                                network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_HALF;
802 >                        case DUPLEX_HALF:
803 >                                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF;
804                                  break;
805                          default:
806 <                                network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
806 >                                network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
807                          }
808                  } else {
809                          /* Not all interfaces support the ethtool ioctl. */
810                          network_iface_stat_ptr->speed = 0;
811 <                        network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN;
811 >                        network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN;
812                  }
813  
814                  ifaces++;
# Line 695 | Line 816 | sg_network_iface_stats *sg_get_network_iface_stats(int
816          close(sock);
817          fclose(f);
818   #endif
819 + #ifdef CYGWIN
820 +        sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
821 +        return NULL;
822 + #endif
823 + #ifdef HPUX
824 +        sg_set_error(SG_ERROR_UNSUPPORTED, "HP-UX");
825 +        return NULL;
826 + #endif
827 + #ifdef WIN32
828 +        ifaces = 0;
829 +
830 +        if((if_table = win32_get_devices()) == NULL) {
831 +                sg_set_error(SG_ERROR_DEVICES, "network interfaces");
832 +                return NULL;
833 +        }
834 +
835 +        if(VECTOR_RESIZE(network_iface_stats, if_table->dwNumEntries) < 0) {
836 +                free(if_table);
837 +                return NULL;
838 +        }
839 +
840 +        for(i=0; i<if_table->dwNumEntries; i++) {
841 +                network_iface_stat_ptr=network_iface_stats+i;
842 +                if_row = if_table->table[i];
843 +
844 +                if(sg_update_string(&network_iface_stat_ptr->interface_name,
845 +                                        if_row.bDescr) < 0) {
846 +                        free(if_table);
847 +                        return NULL;
848 +                }
849 +                network_iface_stat_ptr->speed = if_row.dwSpeed /1000000;
850 +
851 +                if((if_row.dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED ||
852 +                                if_row.dwOperStatus ==
853 +                                        MIB_IF_OPER_STATUS_OPERATIONAL) &&
854 +                                if_row.dwAdminStatus == 1) {
855 +                        network_iface_stat_ptr->up = 1;
856 +                } else {
857 +                        network_iface_stat_ptr->up = 0;
858 +                }
859 +
860 +                ifaces++;
861 +        }
862 +        free(if_table);
863 +
864 +        /* again with the renumbering */
865 +        for (i=0; i<ifaces; i++) {
866 +                no = 2;
867 +                for(j=i+1; j<ifaces; j++) {
868 +                        network_iface_stat_ptr=network_iface_stats+j;
869 +                        if(strcmp(network_iface_stats[i].interface_name,
870 +                                        network_iface_stat_ptr->interface_name) == 0) {
871 +                                if(snprintf(buf, sizeof(buf), " #%d", no) < 0) {
872 +                                        break;
873 +                                }
874 +                                if(sg_concat_string(&network_iface_stat_ptr->interface_name, buf) != 0) {
875 +                                        return NULL;
876 +                                }
877 +
878 +                                no++;
879 +                        }
880 +                }
881 +        }
882 + #endif
883 +
884 + #ifdef SG_ENABLE_DEPRECATED
885 +        network_iface_stat_ptr->dup = network_iface_stat_ptr->duplex;
886 + #endif
887 +
888          *entries = ifaces;
889          return network_iface_stats;
890   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines