| 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; |
| 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; |
| 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); |
| 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 |
| 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) { |
| 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){ |
| 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); |
| 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){ |
| 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 |