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; |
113 |
|
|
114 |
|
#ifdef ALLBSD |
115 |
|
if(getifaddrs(&net) != 0){ |
116 |
+ |
sg_set_error_with_errno(SG_ERROR_GETIFADDRS, NULL); |
117 |
|
return NULL; |
118 |
|
} |
119 |
|
|
147 |
|
|
148 |
|
#ifdef SOLARIS |
149 |
|
if ((kc = kstat_open()) == NULL) { |
150 |
+ |
sg_set_error(SG_ERROR_KSTAT_OPEN, NULL); |
151 |
|
return NULL; |
152 |
|
} |
153 |
|
|
154 |
|
interfaces=0; |
155 |
|
|
156 |
< |
for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { |
156 |
> |
for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { |
157 |
|
if (!strcmp(ksp->ks_class, "net")) { |
158 |
|
kstat_read(kc, ksp, NULL); |
159 |
|
|
245 |
|
#ifdef LINUX |
246 |
|
f=fopen("/proc/net/dev", "r"); |
247 |
|
if(f==NULL){ |
248 |
+ |
sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/net/dev"); |
249 |
|
return NULL; |
250 |
|
} |
251 |
|
/* read the 2 lines.. Its the title, so we dont care :) */ |
254 |
|
|
255 |
|
|
256 |
|
if((regcomp(®ex, "^ *([^:]+): *([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){ |
257 |
+ |
sg_set_error(SG_ERROR_PARSE, NULL); |
258 |
|
return NULL; |
259 |
|
} |
260 |
|
|
292 |
|
#endif |
293 |
|
|
294 |
|
#ifdef CYGWIN |
295 |
+ |
sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin"); |
296 |
|
return NULL; |
297 |
|
#endif |
298 |
+ |
#ifdef HPUX |
299 |
+ |
sg_set_error(SG_ERROR_UNSUPPORTED, "HP-UX"); |
300 |
+ |
return NULL; |
301 |
+ |
#endif |
302 |
|
|
303 |
|
*entries=interfaces; |
304 |
|
|
395 |
|
return diff; |
396 |
|
} |
397 |
|
|
398 |
+ |
int sg_network_io_compare_name(const void *va, const void *vb) { |
399 |
+ |
const sg_network_io_stats *a = (const sg_network_io_stats *)va; |
400 |
+ |
const sg_network_io_stats *b = (const sg_network_io_stats *)vb; |
401 |
+ |
|
402 |
+ |
return strcmp(a->interface_name, b->interface_name); |
403 |
+ |
} |
404 |
+ |
|
405 |
|
/* NETWORK INTERFACE STATS */ |
406 |
|
|
407 |
|
static void network_iface_stat_init(sg_network_iface_stats *s) { |
408 |
|
s->interface_name = NULL; |
409 |
|
s->speed = 0; |
410 |
< |
s->dup = SG_IFACE_DUPLEX_UNKNOWN; |
410 |
> |
s->duplex = SG_IFACE_DUPLEX_UNKNOWN; |
411 |
|
} |
412 |
|
|
413 |
|
static void network_iface_stat_destroy(sg_network_iface_stats *s) { |
442 |
|
|
443 |
|
#ifdef ALLBSD |
444 |
|
if(getifaddrs(&net) != 0){ |
445 |
+ |
sg_set_error_with_errno(SG_ERROR_GETIFADDRS, NULL); |
446 |
|
return NULL; |
447 |
|
} |
448 |
|
|
474 |
|
} |
475 |
|
|
476 |
|
network_iface_stat_ptr->speed = 0; |
477 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN; |
477 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN; |
478 |
|
ifaces++; |
479 |
|
|
480 |
|
memset(&ifmed, 0, sizeof(struct ifmediareq)); |
531 |
|
} |
532 |
|
|
533 |
|
if( (ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active ){ |
534 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_FULL; |
534 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL; |
535 |
|
}else if( (ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active ){ |
536 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_HALF; |
536 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF; |
537 |
|
}else{ |
538 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN; |
538 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN; |
539 |
|
} |
540 |
|
|
541 |
|
} |
545 |
|
|
546 |
|
#ifdef SOLARIS |
547 |
|
if ((kc = kstat_open()) == NULL) { |
548 |
+ |
sg_set_error(SG_ERROR_KSTAT_OPEN, NULL); |
549 |
|
return NULL; |
550 |
|
} |
551 |
|
|
552 |
|
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { |
553 |
+ |
sg_set_error_with_errno(SG_ERROR_SOCKET, NULL); |
554 |
|
return NULL; |
555 |
|
} |
556 |
|
|
589 |
|
network_iface_stat_ptr->speed = 0; |
590 |
|
} |
591 |
|
|
592 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN; |
592 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN; |
593 |
|
if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) { |
594 |
|
switch (knp->value.ui32) { |
595 |
|
case 1: |
596 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_HALF; |
596 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF; |
597 |
|
break; |
598 |
|
case 2: |
599 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_FULL; |
599 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL; |
600 |
|
break; |
601 |
|
} |
602 |
|
} |
609 |
|
#ifdef LINUX |
610 |
|
f = fopen("/proc/net/dev", "r"); |
611 |
|
if(f == NULL){ |
612 |
+ |
sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/net/dev"); |
613 |
|
return NULL; |
614 |
|
} |
615 |
|
|
616 |
|
/* Setup stuff so we can do the ioctl to get the info */ |
617 |
|
if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ |
618 |
+ |
sg_set_error_with_errno(SG_ERROR_SOCKET, NULL); |
619 |
|
return NULL; |
620 |
|
} |
621 |
|
|
622 |
|
/* Ignore first 2 lines.. Just headings */ |
623 |
< |
if((fgets(line, sizeof(line), f)) == NULL) return NULL; |
624 |
< |
if((fgets(line, sizeof(line), f)) == NULL) return NULL; |
623 |
> |
if((fgets(line, sizeof(line), f)) == NULL) { |
624 |
> |
sg_set_error(SG_ERROR_PARSE, NULL); |
625 |
> |
return NULL; |
626 |
> |
} |
627 |
> |
if((fgets(line, sizeof(line), f)) == NULL) { |
628 |
> |
sg_set_error(SG_ERROR_PARSE, NULL); |
629 |
> |
return NULL; |
630 |
> |
} |
631 |
|
|
632 |
|
while((fgets(line, sizeof(line), f)) != NULL){ |
633 |
|
char *name, *ptr; |
676 |
|
network_iface_stat_ptr->speed = ethcmd.speed; |
677 |
|
|
678 |
|
switch (ethcmd.duplex) { |
679 |
< |
case 0x00: |
680 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_FULL; |
679 |
> |
case DUPLEX_FULL: |
680 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_FULL; |
681 |
|
break; |
682 |
< |
case 0x01: |
683 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_HALF; |
682 |
> |
case DUPLEX_HALF: |
683 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_HALF; |
684 |
|
break; |
685 |
|
default: |
686 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN; |
686 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN; |
687 |
|
} |
688 |
|
} else { |
689 |
|
/* Not all interfaces support the ethtool ioctl. */ |
690 |
|
network_iface_stat_ptr->speed = 0; |
691 |
< |
network_iface_stat_ptr->dup = SG_IFACE_DUPLEX_UNKNOWN; |
691 |
> |
network_iface_stat_ptr->duplex = SG_IFACE_DUPLEX_UNKNOWN; |
692 |
|
} |
693 |
|
|
694 |
|
ifaces++; |
696 |
|
close(sock); |
697 |
|
fclose(f); |
698 |
|
#endif |
699 |
+ |
#ifdef CYGWIN |
700 |
+ |
sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin"); |
701 |
+ |
return NULL; |
702 |
+ |
#endif |
703 |
+ |
#ifdef HPUX |
704 |
+ |
sg_set_error(SG_ERROR_UNSUPPORTED, "HP-UX"); |
705 |
+ |
return NULL; |
706 |
+ |
#endif |
707 |
+ |
|
708 |
+ |
#ifdef SG_ENABLE_DEPRECATED |
709 |
+ |
network_iface_stat_ptr->dup = network_iface_stat_ptr->duplex; |
710 |
+ |
#endif |
711 |
+ |
|
712 |
|
*entries = ifaces; |
713 |
|
return network_iface_stats; |
714 |
+ |
} |
715 |
+ |
|
716 |
+ |
int sg_network_iface_compare_name(const void *va, const void *vb) { |
717 |
+ |
const sg_network_iface_stats *a = (const sg_network_iface_stats *)va; |
718 |
+ |
const sg_network_iface_stats *b = (const sg_network_iface_stats *)vb; |
719 |
+ |
|
720 |
+ |
return strcmp(a->interface_name, b->interface_name); |
721 |
|
} |
722 |
|
|