From: joeyh Date: Wed, 8 Mar 2006 02:59:27 +0000 (+0000) Subject: * Added ifinfo, by Benjamin BAYART (originally called ifcfg). X-Git-Tag: 0.5~5 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e50ccc1b36213de52ae78c2703d391ea8941a7b1;p=moreutils * Added ifinfo, by Benjamin BAYART (originally called ifcfg). * Made ifinfo -Wall clean. * Made ifinfo support -h and print usage on unknown options. * Cleaned up ifinfo's behavior when asked to print info for nonexistant devices. Still needs improvement. --- diff --git a/Makefile b/Makefile index d950595..78d111c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -BINS=isutf8 sponge +BINS=isutf8 sponge ifdata PERLSCRIPTS=vidir vipe ts and not -MANS=sponge.1 vidir.1 vipe.1 isutf8.1 ts.1 and.1 not.1 +MANS=sponge.1 vidir.1 vipe.1 isutf8.1 ts.1 and.1 not.1 ifdata.1 CFLAGS=-O2 -g -Wall all: $(BINS) $(MANS) @@ -25,5 +25,8 @@ isutf8.1: isutf8.docbook sponge.1: sponge.docbook docbook2x-man sponge.docbook +ifdata.1: ifdata.docbook + docbook2x-man ifdata.docbook + %.1: % pod2man --center=" " --release="moreutils" $< > $@; diff --git a/README b/README index 96c5222..243a080 100644 --- a/README +++ b/README @@ -15,6 +15,8 @@ and print lines that are present in one file and another not print lines that are present in one file but not another +ifdata + get network interface info without parsing ifconfig output Your suggestions of additional tools to add to this collection are diff --git a/debian/changelog b/debian/changelog index 7777952..f40b9b5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +moreutils (0.5) UNRELEASED; urgency=low + + * Added ifdata, by Benjamin BAYART (originally called ifcfg). + * Made ifdata -Wall clean. + * Made ifdata support -h and print usage on unknown options. + * Cleaned up ifdata's behavior when asked to print info for nonexistant + devices. Still needs improvement. + + -- Joey Hess Tue, 7 Mar 2006 21:54:45 -0500 + moreutils (0.4) unstable; urgency=low * Added versions of and(1) and not(1) that support arbitrary numbers of diff --git a/debian/control b/debian/control index 1a98b9e..44b6d2d 100644 --- a/debian/control +++ b/debian/control @@ -20,4 +20,4 @@ Description: additional unix utilities - vipe: edit a pipe using your text editor - and: print lines that are present in one file and another - not: print lines that are present in one file but not another - + - ifdata: get network interface info without parsing ifconfig output diff --git a/debian/copyright b/debian/copyright index 6718bac..1f3a9a4 100644 --- a/debian/copyright +++ b/debian/copyright @@ -7,6 +7,10 @@ the GPL. spong is Copyright (C) 2006 by Tollef Fog Heen, under the terms of the GPL version 2. Name and concept by Colin Watson. +ifdata is Copyright (C) 2002 by Benjamin BAYART, under the terms of +the GPL. It was originally called ifcfg and has a web page here: +http://edgard.dyn.fdn.fr/developpements/ifcfg.shtml + Everything else is copyright 2006 by Joey Hess, under the terms of GPL. The full text of the GNU GPL can be found in /usr/share/common-licenses/GPL on Debian systems. diff --git a/ifinfo.c b/ifinfo.c new file mode 100644 index 0000000..c65ef16 --- /dev/null +++ b/ifinfo.c @@ -0,0 +1,604 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#define DO_EXISTS 1 +#define DO_PEXISTS 2 +#define DO_PADDRESS 3 +#define DO_PMASK 4 +#define DO_PMTU 5 +#define DO_PCAST 6 +#define DO_PALL 7 +#define DO_PFLAGS 8 +#define DO_SINPACKETS 9 +#define DO_SINBYTES 10 +#define DO_SINERRORS 11 +#define DO_SINDROPS 12 +#define DO_SINALL 13 +#define DO_SINFIFO 14 +#define DO_SINFRAME 15 +#define DO_SINCOMPRESSES 16 +#define DO_SINMULTICAST 17 +#define DO_SOUTALL 18 +#define DO_SOUTBYTES 19 +#define DO_SOUTPACKETS 20 +#define DO_SOUTERRORS 21 +#define DO_SOUTDROPS 22 +#define DO_SOUTFIFO 23 +#define DO_SOUTCOLLS 24 +#define DO_SOUTCARRIER 25 +#define DO_SOUTMULTICAST 26 +#define DO_PNETWORK 27 + +struct if_stat { + unsigned long long int in_packets; + unsigned long long int in_bytes; + unsigned long long int in_errors; + unsigned long long int in_drops; + unsigned long long int in_fifo; + unsigned long long int in_frame; + unsigned long long int in_compress; + unsigned long long int in_multicast; + unsigned long long int out_bytes; + unsigned long long int out_packets; + unsigned long long int out_errors; + unsigned long long int out_drops; + unsigned long long int out_fifo; + unsigned long long int out_colls; + unsigned long long int out_carrier; + unsigned long long int out_multicast; +}; + + +void print_quad_ipv4(unsigned int i) { + printf("%d.%d.%d.%d", + i&0xff, + (i&0xff00)>>8, + (i&0xff0000)>>16, + (i&0xff000000)>>24); +} + +void print_quad_ipv6(uint16_t *a) { + int i; + for (i=0; i<7; i++) { + printf("%04x:",a[i]); + } + printf("%04x",a[i]); +} + +void print_quad(struct sockaddr *adr) { + switch (adr->sa_family) { + case AF_INET: + print_quad_ipv4(((struct sockaddr_in*)adr)->sin_addr.s_addr); + break; + case AF_INET6: + print_quad_ipv6(((struct sockaddr_in6*)adr)->sin6_addr.s6_addr16); + break; + default: + printf("NON-IP"); + break; + } +} + +#define PREPARE_SOCK(iface) int sock; \ + static struct ifreq req; \ + int res; \ + sock=socket(PF_INET,SOCK_DGRAM,IPPROTO_IP); \ + strcpy(req.ifr_name,iface) +#define CALL_IOCTL(call) res=ioctl(sock,call,&req) +#define END_SOCK close(sock) +#define CALL_ERROR(todo) if (res==-1) { perror("ioctl"); close(sock); todo; } + +int if_exists(char *iface) { + PREPARE_SOCK(iface); + CALL_IOCTL(SIOCGIFFLAGS); + if (res==-1 && errno==ENODEV) { + END_SOCK; + return 0; + } + CALL_ERROR(return 0); + END_SOCK; + return 1; +} + +#define PRINT_IF(cond,tell) if (req.ifr_flags & cond) printf(tell); else printf("No "tell) + +void if_flags(char *iface) { + PREPARE_SOCK(iface); + CALL_IOCTL(SIOCGIFFLAGS); + CALL_ERROR(return); + PRINT_IF(IFF_UP,"Up\n"); + PRINT_IF(IFF_BROADCAST,"Broadcast\n"); + PRINT_IF(IFF_DEBUG,"Debugging\n"); + PRINT_IF(IFF_LOOPBACK,"Loopback\n"); + PRINT_IF(IFF_POINTOPOINT,"Ppp\n"); + PRINT_IF(IFF_NOTRAILERS,"No-trailers\n"); + PRINT_IF(IFF_RUNNING,"Running\n"); + PRINT_IF(IFF_NOARP,"No-arp\n"); + PRINT_IF(IFF_PROMISC,"Promiscuous\n"); + PRINT_IF(IFF_ALLMULTI,"All-multicast\n"); + PRINT_IF(IFF_MASTER,"Load-master\n"); + PRINT_IF(IFF_SLAVE,"Load-slave\n"); + PRINT_IF(IFF_MULTICAST,"Multicast\n"); + PRINT_IF(IFF_PORTSEL,"Port-select\n"); + PRINT_IF(IFF_AUTOMEDIA,"Auto-detect\n"); + PRINT_IF(IFF_DYNAMIC,"Dynaddr\n"); + PRINT_IF(0xffff0000,"Unknown-flags"); +} + +struct sockaddr *if_addr(char *iface) { + PREPARE_SOCK(iface); + CALL_IOCTL(SIOCGIFADDR); + if (res==-1 && errno==EADDRNOTAVAIL) { + return &req.ifr_addr; + } + CALL_ERROR(return NULL); + END_SOCK; + return &req.ifr_addr; +} + +struct sockaddr *if_mask(char *iface) { + PREPARE_SOCK(iface); + CALL_IOCTL(SIOCGIFNETMASK); + if (res==-1 && errno==EADDRNOTAVAIL) { + return &req.ifr_addr; + } + CALL_ERROR(return NULL); + END_SOCK; + return &req.ifr_addr; +} + +struct sockaddr *if_network(char *iface) { + struct sockaddr *res; + res=if_mask(iface); + long int mask=((struct sockaddr_in*)res)->sin_addr.s_addr; + res=if_addr(iface); + ((struct sockaddr_in*)res)->sin_addr.s_addr &= mask; + return res; +} + +struct sockaddr *if_bcast(char *iface) { + PREPARE_SOCK(iface); + CALL_IOCTL(SIOCGIFBRDADDR); + if (res==-1 && errno==EADDRNOTAVAIL) { + return &req.ifr_addr; + } + CALL_ERROR(return NULL); + END_SOCK; + return &req.ifr_addr; +} + +int if_mtu(char *iface) { + PREPARE_SOCK(iface); + CALL_IOCTL(SIOCGIFMTU); + CALL_ERROR(return 0); + END_SOCK; + return req.ifr_mtu; +} + +#define START 1 +#define SKIP_LINE 2 +#define START_LINE 3 +#define START_IFNAME 4 +#define IFACE_FOUND 5 +#define RX_BYTES 6 +#define WAIT_RX_PACKETS 7 +#define RX_PACKETS 8 +#define WAIT_RX_ERRORS 9 +#define RX_ERRORS 10 +#define WAIT_RX_DROPS 11 +#define RX_DROPS 12 +#define WAIT_RX_FIFO 13 +#define RX_FIFO 14 +#define WAIT_RX_FRAME 15 +#define RX_FRAME 16 +#define WAIT_RX_COMPRESS 17 +#define RX_COMPRESS 18 +#define WAIT_RX_MULTICAST 19 +#define RX_MULTICAST 20 +#define WAIT_TX_BYTES 21 +#define TX_BYTES 22 +#define WAIT_TX_PACKETS 23 +#define TX_PACKETS 24 +#define WAIT_TX_ERRORS 25 +#define TX_ERRORS 26 +#define WAIT_TX_DROPS 27 +#define TX_DROPS 28 +#define WAIT_TX_FIFO 29 +#define TX_FIFO 30 +#define WAIT_TX_COLLS 31 +#define TX_COLLS 32 +#define WAIT_TX_CARRIER 33 +#define TX_CARRIER 34 +#define WAIT_TX_MULTICAST 35 +#define TX_MULTICAST 36 + +#define FIRST_DIGIT(val,digit) do {val=digit-'0'; } while(0) +#define NEXT_DIGIT(val,digit) do {val*=10; val+=digit-'0'; } while(0) + +#define READ_INT(cas,val,next) \ + case WAIT_##cas: \ + if (isdigit(buffer[i])) { \ + state=cas; \ + FIRST_DIGIT(val,buffer[i]); \ + } \ + break; \ + case cas: \ + if (isdigit(buffer[i])) \ + NEXT_DIGIT(val,buffer[i]); \ + else \ + state=next; \ + break; + + +//#define FIRST_DIGIT(val,digit) do {val=digit-'0'; printf(#val " = %d\n",val); } while(0) +//#define NEXT_DIGIT(val,digit) do {val*=10; val+=digit-'0'; printf(#val " -> %d\n",val);} while(0) +struct if_stat *get_stats(char *iface) { + int fd; + unsigned char buffer[4096]; + int i,j=0; + int state=START; + int len; + struct if_stat *res=malloc(sizeof(struct if_stat)); + fd=open("/proc/net/dev",O_RDONLY); + if (fd==-1) { + perror("open"); + return NULL; + } + while ((len=read(fd,buffer,4096))) { + for (i=0; iin_bytes,buffer[i]); + } + break; + case RX_BYTES: + if (isdigit(buffer[i])) + NEXT_DIGIT(res->in_bytes,buffer[i]); + else + state=WAIT_RX_PACKETS; + break; + READ_INT(RX_PACKETS,res->in_packets,WAIT_RX_ERRORS); + READ_INT(RX_ERRORS,res->in_errors,WAIT_RX_DROPS); + READ_INT(RX_DROPS,res->in_drops,WAIT_RX_FIFO); + READ_INT(RX_FIFO,res->in_fifo,WAIT_RX_FRAME); + READ_INT(RX_FRAME,res->in_frame,WAIT_RX_COMPRESS); + READ_INT(RX_COMPRESS,res->in_compress,WAIT_RX_MULTICAST); + READ_INT(RX_MULTICAST,res->in_multicast,WAIT_TX_BYTES); + READ_INT(TX_BYTES,res->out_bytes,WAIT_TX_PACKETS); + READ_INT(TX_PACKETS,res->out_packets,WAIT_TX_ERRORS); + READ_INT(TX_ERRORS,res->out_errors,WAIT_TX_DROPS); + READ_INT(TX_DROPS,res->out_drops,WAIT_TX_FIFO); + READ_INT(TX_FIFO,res->out_fifo,WAIT_TX_COLLS); + READ_INT(TX_COLLS,res->out_colls,WAIT_TX_CARRIER); + READ_INT(TX_CARRIER,res->out_carrier,WAIT_TX_MULTICAST); + READ_INT(TX_MULTICAST,res->out_carrier,SKIP_LINE); + default: + fprintf(stderr,"Mon totomate est po bon!\n"); + break; + } + } + } + return res; +} + +void usage(char *name) { + fprintf(stderr,"Usage: %s [options] iface\n",name); + fprintf(stderr," -e Says if iface exists or not\n" + " -p Print out the whole config of iface\n" + " -pe Print out yes or no according to existence\n" + " -pa Print out the address\n" + " -pn Print netmask\n" + " -pN Print network address\n" + " -pb Print broadcast\n" + " -pm Print mtu\n" + " -pf Print flags\n" + " -si Print all statistics on input\n" + " -sip Print # of in packets\n" + " -sib Print # of in bytes\n" + " -sie Print # of in errors\n" + " -sid Print # of in drops\n" + " -sif Print # of in fifo overruns\n" + " -sic Print # of in compress\n" + " -sim Print # of in multicast\n" + " -so Print all statistics on output\n" + " -sop Print # of out packets\n" + " -sob Print # of out bytes\n" + " -soe Print # of out errors\n" + " -sod Print # of out drops\n" + " -sof Print # of out fifo overruns\n" + " -sox Print # of out collisions\n" + " -soc Print # of out carrier loss\n" + " -som Print # of out multicast\n"); +} + +void add_do(int *ndo, int **todo, int act) { + *todo=realloc(*todo,(*ndo+1)*sizeof(int)); + (*todo)[*ndo]=act; + *ndo+=1; +} + +#define PRINT_OR_ERR(adr) if (adr) print_quad(adr); else { fprintf(stderr, "Error\n"); exit(1); } + +void please_do(int ndo, int *todo, char *ifname) { + int i; + struct sockaddr *sadr; + struct if_stat *stats=NULL; + if (!ndo) return; +// printf("J'ai %d actions a réaliser\n",ndo); + for (i=0; iin_packets); + break; + case DO_SINBYTES: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->in_bytes); + break; + case DO_SINERRORS: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->in_errors); + break; + case DO_SINDROPS: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->in_drops); + break; + case DO_SINFIFO: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->in_fifo); + break; + case DO_SINFRAME: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->in_frame); + break; + case DO_SINCOMPRESSES: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->in_compress); + break; + case DO_SINMULTICAST: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->in_multicast); + break; + case DO_SINALL: + if (!stats) stats=get_stats(ifname); + printf("%llu %llu %llu %llu %llu %llu %llu %llu", + stats->in_packets, + stats->in_bytes, + stats->in_errors, + stats->in_drops, + stats->in_fifo, + stats->in_frame, + stats->in_compress, + stats->in_multicast); + break; + case DO_SOUTBYTES: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->out_bytes); + break; + case DO_SOUTPACKETS: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->out_packets); + break; + case DO_SOUTERRORS: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->out_errors); + break; + case DO_SOUTDROPS: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->out_drops); + break; + case DO_SOUTFIFO: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->out_fifo); + break; + case DO_SOUTCOLLS: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->out_colls); + break; + case DO_SOUTCARRIER: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->out_carrier); + break; + case DO_SOUTMULTICAST: + if (!stats) stats=get_stats(ifname); + printf("%llu",stats->out_multicast); + break; + case DO_SOUTALL: + if (!stats) stats=get_stats(ifname); + printf("%llu %llu %llu %llu %llu %llu %llu %llu", + stats->out_packets, + stats->out_bytes, + stats->out_errors, + stats->out_drops, + stats->out_fifo, + stats->out_colls, + stats->out_carrier, + stats->out_multicast); + break; + default: + printf("Je comprends pas ce que je dois faire: %d\n",todo[i]); + break; + } + printf("\n"); + } +} + +int main(int argc, char *argv[]) { + int ndo=0; + int *todo=NULL; + char *me=*argv; + char *ifname=NULL; + int narg=0; + /* + print_quad(&res.ifr_addr); + s=socket(PF_INET6,SOCK_DGRAM,IPPROTO_IP); + ret=ioctl(s,SIOCGIFADDR,&res); + print_quad(&res.ifr_addr); + */ + if (argc==1) { + usage(me); + return 1; + } + narg++; + while (narg + + + + + + + + + + Joey + Hess + + 2006-03-07 + + + + ifdata + 1 + + + + ifdata + get network interface info without parsing ifconfig output + + + + + ifdata + options + iface + + + + + DESCRIPTION + + ifdata can be used to check for the existence + of a network interface, or to get information abut the interface, such + as its IP address. Unlike ifconfig or ip, + ifdata has simple to parse output that is designed + to be easily used by a shell script. + + + + + OPTIONS + + + + + + + Print out a help summary. + + + + + + + Test to see if the interface exists. ifdata will exit + nonzero if the interface does not exist. + + + + + + + Prints out the whole configuration of the interface. + + + + + + + Prints "yes" or "no" if the interface exists or not. + + + + + + + Prints the IPv4 address of the interface. + + + + + + + Prints the netmask of the interface. + + + + + + + Prints the network address of the interface. + + + + + + + Prints the broadcast address of the interface. + + + + + + + Prints the MTU of the interface. + + + + + + + Prints the flags of the interface. + + + + + + + Prints out all the input statistics of the interface. + + + + + + + Prints the number of input packets. + + + + + + + Prints the number of input bytes. + + + + + + + Prints the number of input errors. + + + + + + + Prints the number of input drops. + + + + + + + Prints the number of input fifo overruns. + + + + + + + Print the number of input compress. + + + + + + + Prints the number of input multicast. + + + + + + + Prints out all the output statistics of the interface. + + + + + + + Prints the number of output packets. + + + + + + + Prints the number of output bytes. + + + + + + + Prints the number of output errors. + + + + + + + Prints the number of output drops. + + + + + + + Prints the number of output fifo overruns. + + + + + + + Print the number of output collisions. + + + + + + + Prints the number of output carrier loss. + + + + + + + Prints the number of output multicast. + + + + + + + +