nicolas / debian.moreutils (public) (License: GPL-2, GPL-2+, Expat, BSD-2-Clause, Public Domain) (since 2018-09-25) (hash sha1)
Debian packaging of joeyh's moreutils

/ifdata.c (adf9f8748240c9924718bc9af0433784efdcc936) (13328 bytes) (mode 100644) (type blob)

#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netdb.h>
#include <sys/ioctl.h>

#if defined(__linux__)
	#include <linux/sockios.h>
	#include <linux/if.h>
#endif

#if defined(__FreeBSD_kernel__)
	#include <net/if.h>
#endif

#if defined(__GNU__)
	#include <net/if.h>
#endif

#if defined(__APPLE__)
	#define s6_addr16 __u6_addr.__u6_addr16
	#include <net/if.h>
#endif

#if defined(__sun)
   #define s6_addr16 _S6_un._S6_u8
   #include <net/if.h>
   #include <sys/sockio.h>
#endif

#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>

enum {
	DO_EXISTS = 1,
	DO_PEXISTS,
	DO_PADDRESS,
	DO_PMASK,
	DO_PMTU,
	DO_PCAST,
	DO_PALL,
	DO_PFLAGS,
	DO_SINPACKETS,
	DO_SINBYTES,
	DO_SINERRORS,
	DO_SINDROPS,
	DO_SINALL,
	DO_SINFIFO,
	DO_SINFRAME,
	DO_SINCOMPRESSES,
	DO_SINMULTICAST,
	DO_SOUTALL,
	DO_SOUTBYTES,
	DO_SOUTPACKETS,
	DO_SOUTERRORS,
	DO_SOUTDROPS,
	DO_SOUTFIFO,
	DO_SOUTCOLLS,
	DO_SOUTCARRIER,
	DO_SOUTMULTICAST,
	DO_PNETWORK,
	DO_PHWADDRESS,
	DO_BIPS,
	DO_BOPS
};

struct if_stat {
	unsigned long long in_packets, in_bytes, in_errors, in_drops;
	unsigned long long in_fifo, in_frame, in_compress, in_multicast;
	unsigned long long out_bytes, out_packets, out_errors, out_drops;
	unsigned long long out_fifo, out_colls, out_carrier, out_multicast;
};


void print_quad_ipv4(in_addr_t i) {
	i = ntohl(i);
	printf("%d.%d.%d.%d",
		(i & 0xff000000) >> 24,
		(i & 0x00ff0000) >> 16,
		(i & 0x0000ff00) >>  8,
		(i & 0x000000ff));
}

void print_quad_ipv6(uint16_t *a) {
	printf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
		a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
}

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;
	}
}

enum print_error_enum {
	PRINT_ERROR,
	PRINT_NO_ERROR,
};

/**
 * return 0 success
 *        1 error
 */
static int do_socket_ioctl(const char *ifname, const unsigned long int request,
                           struct ifreq *req, int *ioctl_errno,
                           const enum print_error_enum print_error) {
	int sock, res;

	if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1)
		return 1;
	strncpy(req->ifr_name, ifname, IFNAMSIZ);
	req->ifr_name[IFNAMSIZ - 1] = 0;

	if ((res = ioctl(sock, request, req)) == -1) {
		if (ioctl_errno)
			*ioctl_errno = errno;
		if (print_error == PRINT_ERROR)
			fprintf(stderr, "ioctl on %s: %s\n", ifname, strerror(errno));
		close(sock);
		return 1;
	}

	close(sock);

	return 0;
}

int if_exists(const char *iface) {
	struct ifreq r;
	return !do_socket_ioctl(iface, SIOCGIFFLAGS, &r, NULL, PRINT_NO_ERROR);
}

#if defined(__linux__)

void if_flags(const char *iface) {
	struct ifreq r;
	unsigned int i;
	const struct {
		unsigned int flag;
		char *name;
	} flags[] = {
		{ IFF_UP,          "Up" },
		{ IFF_BROADCAST,   "Broadcast" },
		{ IFF_DEBUG,       "Debugging" },
		{ IFF_LOOPBACK,    "Loopback" },
		{ IFF_POINTOPOINT, "Ppp" },
		{ IFF_NOTRAILERS,  "No-trailers" },
		{ IFF_RUNNING,     "Running" },
		{ IFF_NOARP,       "No-arp" },
		{ IFF_PROMISC,     "Promiscuous" },
		{ IFF_ALLMULTI,    "All-multicast" },
		{ IFF_MASTER,      "Load-master" },
		{ IFF_SLAVE,       "Load-slave" },
		{ IFF_MULTICAST,   "Multicast" },
		{ IFF_PORTSEL,     "Port-select" },
		{ IFF_AUTOMEDIA,   "Auto-detect" },
		{ IFF_DYNAMIC,     "Dynaddr" },
		{ 0xffff0000,      "Unknown-flags" },
	};

	if (do_socket_ioctl(iface, SIOCGIFFLAGS, &r, NULL, PRINT_ERROR))
		return;

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++)
		printf("%s%s%s", (r.ifr_flags & flags[i].flag) ? "On  " : "Off ",
		       flags[i].name,
		       sizeof(flags) / sizeof(flags[0]) - 1 == i ? "" : "\n");
}

void if_hwaddr(const char *iface) {
	struct ifreq r;
	unsigned char *hwaddr;

	if (do_socket_ioctl(iface, SIOCGIFHWADDR, &r, NULL, PRINT_ERROR))
		return;

	hwaddr = (unsigned char *)r.ifr_hwaddr.sa_data;
	printf("%02X:%02X:%02X:%02X:%02X:%02X",
	       hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
}

#endif

static struct sockaddr *if_addr_value(const char *iface, struct ifreq *r, 
                                      unsigned long int request) {
	int e;

	if (do_socket_ioctl(iface, request, r, &e, PRINT_NO_ERROR)) {
		if (e == EADDRNOTAVAIL)
			return &r->ifr_addr;
		return NULL;
	}
	return &r->ifr_addr;
}

struct sockaddr *if_addr(const char *iface, struct ifreq *r) {
	return if_addr_value(iface, r, SIOCGIFADDR);
}

struct sockaddr *if_mask(const char *iface, struct ifreq *r) {
	return if_addr_value(iface, r, SIOCGIFNETMASK);
}

struct sockaddr *if_bcast(const char *iface, struct ifreq *r) {
	return if_addr_value(iface, r, SIOCGIFBRDADDR);
}

struct sockaddr *if_network(const char *iface) {
	struct sockaddr *saddr;
	static struct ifreq req;
	unsigned int mask;

	if (!(saddr = if_mask(iface, &req)))
		return NULL;

	mask  = ((struct sockaddr_in*)saddr)->sin_addr.s_addr;

	if (!(saddr = if_addr(iface, &req)))
		return NULL;

	((struct sockaddr_in*)saddr)->sin_addr.s_addr &= mask;
	return saddr;
}

int if_mtu(const char *iface) {
	static struct ifreq req;

	if (do_socket_ioctl(iface, SIOCGIFMTU, &req, NULL, PRINT_ERROR))
		return 0;

	return req.ifr_mtu;
}

#if defined(__linux__)

static void skipline(FILE *fd) {
	int ch;
	do {
		ch = getc(fd);
	} while (ch != '\n' && ch != EOF);
}

struct if_stat *get_stats(const char *iface) {
	FILE *fd;
	struct if_stat *ifstat;
	char name[10];

	if (!(ifstat = malloc(sizeof(struct if_stat)))) {
		perror("malloc");
		return NULL;
	}

	if ((fd = fopen("/proc/net/dev", "r")) == NULL) {
		perror("fopen(\"/proc/net/dev\")");
		free(ifstat);
		return NULL;
	}

	/* Skip header */
	skipline(fd);
	skipline(fd);

	do {
		int items = fscanf(fd,
			" %20[^:]:%llu %llu %llu %llu %llu %llu %llu %llu "
			"%llu %llu %llu %llu %llu %llu %llu %llu",
			name,
			&ifstat->in_bytes,    &ifstat->in_packets,
			&ifstat->in_errors,   &ifstat->in_drops,
			&ifstat->in_fifo,     &ifstat->in_frame,
			&ifstat->in_compress, &ifstat->in_multicast,
			&ifstat->out_bytes,   &ifstat->out_packets,
			&ifstat->out_errors,  &ifstat->out_drops,
			&ifstat->out_fifo,    &ifstat->out_colls,
			&ifstat->out_carrier, &ifstat->out_carrier
		);
		
		if (items == -1)
			break;
		if (items != 17) {
			fprintf(stderr, "Invalid data read, check!\n");
			break;
		}

		if (!strncmp(name, iface, sizeof(name))) {
			fclose(fd);
			return ifstat;
		}
	} while (!feof(fd));

	fclose(fd);
	free(ifstat);
	return NULL;
}

#endif

const struct {
	char *option;
	unsigned int flag;
	unsigned int is_stat;
	char *description;
} options[] = {
	{ "-e",   DO_EXISTS,        0, "Reports interface existence via return code" },
	{ "-p",   DO_PALL,          0, "Print out the whole config of iface" },
	{ "-pe",  DO_PEXISTS,       0, "Print out yes or no according to existence" },
	{ "-pa",  DO_PADDRESS,      0, "Print out the address" },
	{ "-pn",  DO_PMASK,         0, "Print netmask" },
	{ "-pN",  DO_PNETWORK,      0, "Print network address" },
	{ "-pb",  DO_PCAST,         0, "Print broadcast" },
	{ "-pm",  DO_PMTU,          0, "Print mtu" },
#if defined(__linux__)
	{ "-ph",  DO_PHWADDRESS,    0, "Print out the hardware address" },
	{ "-pf",  DO_PFLAGS,        0, "Print flags" },
	{ "-si",  DO_SINALL,        1, "Print all statistics on input" },
	{ "-sip", DO_SINPACKETS,    1, "Print # of in packets" },
	{ "-sib", DO_SINBYTES,      1, "Print # of in bytes" },
	{ "-sie", DO_SINERRORS,     1, "Print # of in errors" },
	{ "-sid", DO_SINDROPS,      1, "Print # of in drops" },
	{ "-sif", DO_SINFIFO,       1, "Print # of in fifo overruns" },
	{ "-sic", DO_SINCOMPRESSES, 1, "Print # of in compress" },
	{ "-sim", DO_SINMULTICAST,  1, "Print # of in multicast" },
	{ "-so",  DO_SOUTALL,       1, "Print all statistics on output" },
	{ "-sop", DO_SOUTPACKETS,   1, "Print # of out packets" },
	{ "-sob", DO_SOUTBYTES,     1, "Print # of out bytes" },
	{ "-soe", DO_SOUTERRORS,    1, "Print # of out errors" },
	{ "-sod", DO_SOUTDROPS,     1, "Print # of out drops" },
	{ "-sof", DO_SOUTFIFO,      1, "Print # of out fifo overruns" },
	{ "-sox", DO_SOUTCOLLS,     1, "Print # of out collisions" },
	{ "-soc", DO_SOUTCARRIER,   1, "Print # of out carrier loss" },
	{ "-som", DO_SOUTMULTICAST, 1, "Print # of out multicast" },
	{ "-bips",DO_BIPS,          1, "Print # of incoming bytes per second" },
	{ "-bops",DO_BOPS,          1, "Print # of outgoing bytes per second" },
#endif
};

void usage(const char *name) {
	unsigned int i;

	fprintf(stderr, "Usage: %s [options] iface\n", name);
	for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
		fprintf(stderr, "  %5s   %s\n",
			options[i].option, options[i].description);
	}
}

void add_do(int *ndo, int **todo, int act) {
	*todo = realloc(*todo, (*ndo+1) * sizeof(int));
	(*todo)[*ndo] = act;
	*ndo += 1;
}

static void print_addr(struct sockaddr *sadr) {
	if (!sadr) {
		fprintf(stderr, "Error\n");
		exit(1);
	}
	print_quad(sadr);
}

struct if_stat *ifstats, *ifstats2 = NULL;

void please_do(int ndo, int *todo, const char *ifname) {
	int i;
	static struct ifreq req;
	if (!ndo) return;
	// printf("I have %d items in my queue.\n",ndo);
	for (i=0; i<ndo; i++) {
		switch (todo[i]) {
			case DO_EXISTS:
				exit(!if_exists(ifname));
			case DO_PEXISTS:
				printf("%s", if_exists(ifname) ? "yes" : "no");
				break;
			case DO_PADDRESS:
				print_addr(if_addr(ifname, &req));
				break;
#if defined(__linux__)
			case DO_PHWADDRESS:
				if_hwaddr(ifname);
				break;
			case DO_PFLAGS:
				if_flags(ifname);
				break;
#endif
			case DO_PMASK:
				print_addr(if_mask(ifname, &req));
				break;
			case DO_PCAST:
				print_addr(if_bcast(ifname, &req));
				break;
			case DO_PMTU:
				printf("%d", if_mtu(ifname));
				break;
			case DO_PNETWORK:
				print_addr(if_network(ifname));
				break;
			case DO_PALL:
				print_addr(if_addr(ifname, &req));
				printf(" ");
				print_addr(if_mask(ifname, &req));
				printf(" ");
				print_addr(if_bcast(ifname, &req));
				printf(" ");
				printf("%d", if_mtu(ifname));
				break;
#if defined(__linux__)
			case DO_SINPACKETS:
				printf("%llu",ifstats->in_packets);
				break;
			case DO_SINBYTES:
				printf("%llu",ifstats->in_bytes);
				break;
			case DO_SINERRORS:
				printf("%llu",ifstats->in_errors);
				break;
			case DO_SINDROPS:
				printf("%llu",ifstats->in_drops);
				break;
			case DO_SINFIFO:
				printf("%llu",ifstats->in_fifo);
				break;
			case DO_SINFRAME:
				printf("%llu",ifstats->in_frame);
				break;
			case DO_SINCOMPRESSES:
				printf("%llu",ifstats->in_compress);
				break;
			case DO_SINMULTICAST:
				printf("%llu",ifstats->in_multicast);
				break;
			case DO_SINALL:
				printf("%llu %llu %llu %llu %llu %llu %llu %llu",
					ifstats->in_bytes, ifstats->in_packets,
					ifstats->in_errors, ifstats->in_drops,
					ifstats->in_fifo, ifstats->in_frame,
					ifstats->in_compress, ifstats->in_multicast);
				break;
			case DO_SOUTBYTES:
				printf("%llu",ifstats->out_bytes);
				break;
			case DO_SOUTPACKETS:
				printf("%llu",ifstats->out_packets);
				break;
			case DO_SOUTERRORS:
				printf("%llu",ifstats->out_errors);
				break;
			case DO_SOUTDROPS:
				printf("%llu",ifstats->out_drops);
				break;
			case DO_SOUTFIFO:
				printf("%llu",ifstats->out_fifo);
				break;
			case DO_SOUTCOLLS:
				printf("%llu",ifstats->out_colls);
				break;
			case DO_SOUTCARRIER:
				printf("%llu",ifstats->out_carrier);
				break;
			case DO_SOUTMULTICAST:
				printf("%llu",ifstats->out_multicast);
				break;
			case DO_BIPS:
				if (ifstats2 == NULL) {
					sleep(1);
					ifstats2 = get_stats(ifname);
				}
				printf("%llu", ifstats2->in_bytes-ifstats->in_bytes);
				break;
			case DO_BOPS:
				if (ifstats2 == NULL) {
					sleep(1);
					ifstats2 = get_stats(ifname);
				}
				printf("%llu", ifstats2->out_bytes-ifstats->out_bytes);
				break;
			case DO_SOUTALL:
				printf("%llu %llu %llu %llu %llu %llu %llu %llu",
					ifstats->out_bytes, ifstats->out_packets,
					ifstats->out_errors, ifstats->out_drops,
					ifstats->out_fifo, ifstats->out_colls,
					ifstats->out_carrier, ifstats->out_multicast);
				break;
#endif
			default:
				printf("Unknown command: %d", todo[i]);
				break;
		}
		printf("\n");
	}
}

int main(int argc, char *argv[]) {
	int ndo=0;
	int *todo=NULL;
	char *ifname=NULL;
	int narg = 0;
	int do_stats = 0;
	unsigned int i, found;

	if (argc == 1) {
		usage(*argv);
		return 1;
	}

	while (narg < argc - 1) {
		narg++;

		found = 0;

		for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
			if (!strcmp(argv[narg], options[i].option)) {
				add_do(&ndo, &todo, options[i].flag);
				do_stats |= options[i].is_stat;
				found = 1;
				break;
			}
		}

		if (found)
			continue;

		if (argv[narg][0] == '-') {
			usage(*argv);
			return 1;
		}
		else {
			ifname = argv[narg];
			break;
		}
	}

	if (narg + 1 < argc || !ifname) {
		usage(*argv);
		return 1;
	}

#if defined(__linux__)
	if (do_stats && (ifstats = get_stats(ifname)) == NULL) {
		fprintf(stderr, "Error getting statistics for %s\n", ifname);
		return 1;
	}
#endif

	please_do(ndo, todo, ifname);

	return 0;
}


Mode Type Size Ref File
100644 blob 44 5d425843f23db3bb6970a55c953f345e3a8c8fe1 .gitattributes
100644 blob 17989 b7b5f53df1412df1e117607f18385b39004cdaa2 COPYING
100644 blob 1113 4f8af10c6b1b101e9fb3046bc3164ae1d6f5ab2d Makefile
100644 blob 1191 c60df6c95587ab2183d3a3114f3d7de231433a79 README
100755 blob 806 83a4eed00f82e3bcc81856149b47cffc4091f9aa check-isutf8
100755 blob 1333 fe012f6f144b0370cca7020a131564a07971a0ee chronic
100755 blob 3050 99a4de6125bfdcec457529419eb700c0707e9fe6 combine
040000 tree - b2d92708c4ffa1a73dae3e148fe7c68641526e84 debian
100644 blob 5102 d2f68a1ac365a0c8df88d4b64a400f63fffe4c69 errno.c
100644 blob 3878 e045f7e90d9f774bbc76c7cda0d81136d1200533 errno.docbook
100644 blob 13328 adf9f8748240c9924718bc9af0433784efdcc936 ifdata.c
100644 blob 7339 47f414301c47a69a81694c3b5affd71261207d49 ifdata.docbook
100644 blob 3061 e8bc10048f75efccf7db285eef3db76cc73417ba ifne.c
100644 blob 2465 e9c45692b7b95e77ea0184732f883d278c9415f6 ifne.docbook
100644 blob 7598 971112457c834ca97fdecb5880dc7c749dc8ca44 isutf8.c
100644 blob 3088 f0d0dbe51a3e1afc2616807d631bcd15ccd07cbe isutf8.docbook
100644 blob 5471 4925409bd548b058f07defe913724868801040df lckdo.c
100644 blob 3637 3fbf797b177d6933ce106cce2e8368e5094702ab lckdo.docbook
100644 blob 5783 d183d04a5f249072da9be3e1d30d4e205e1be021 mispipe.c
100644 blob 2569 cc966c8b0b9b4c911cb0587055c100dbca2a7d41 mispipe.docbook
100644 blob 5374 b9d7ab2a6aac22da55ce228bae7de6f2c7b03f51 parallel.c
100644 blob 3703 bd490e2d3cde03942366b58b7221cac0229f45ee parallel.docbook
100644 blob 1188 a8565c0245914cfa8bc8fb2c46dcb83c7f1dd8ab pee.c
100644 blob 2330 239f17fa72f5a225f026c209883fb35c6afa8b8b pee.docbook
100644 blob 7301 a53a2cf1906998c91533f5f5435ceeeeb1a7cd59 physmem.c
100644 blob 8715 969703f4bb99b50dec1a006fae373087a0a3845b sponge.c
100644 blob 2228 07a264572d0fd50bfb4fe549c633d485e002f99a sponge.docbook
100755 blob 3667 2a04392c49a4e3f6d1e99721f3634fc9b97f2e2a ts
100755 blob 4495 a77739f27d8cab6843471de92857fe5064f9ace4 vidir
100755 blob 1406 adc44a06055de36017d3395cf2756aa8fa170ad0 vipe
100755 blob 2518 98d1445a5f8106f04be690f85d802a7f6decfd13 zrun
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/nicolas/debian.moreutils

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/nicolas/debian.moreutils

Clone this repository using git:
git clone git://git.rocketgit.com/user/nicolas/debian.moreutils

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main