plong

Unnamed repository; edit this file 'description' to name the repository.
git clone https://git.inz.fi/plong
Log | Files | Refs

net.c (2727B)


      1 #include <stdio.h>
      2 #include <errno.h>
      3 #include <string.h>
      4 #include <net/if.h>
      5 #include "util.h"
      6 #include "net.h"
      7 
      8 #define _STRINGIFY(x) #x
      9 #define STRINGIFY(x) _STRINGIFY(x)
     10 
     11 static int _net_read(struct net *n, FILE *f, char *linebuf, size_t bsz)
     12 {
     13 	size_t i;
     14 	char namebuf[IF_NAMESIZE + 1];
     15 
     16 	for (i = 0; fgets(linebuf, bsz, f); i++) {
     17 		if (sscanf(linebuf, " %" STRINGIFY(IF_NAMESIZE) "[^:]:"
     18 			   UINT_SCAN(NET_FIELDS), namebuf
     19 #define X(d, na) , &n->ifaces[i].d ## na
     20 			   NET_FIELDS(X)
     21 #undef X
     22 		    ) < COUNT(NET_FIELDS))
     23 			return ENODATA;
     24 		if (!(n->ifaces[i].ifidx = if_nametoindex(namebuf)))
     25 			i--;
     26 	}
     27 	n->n = i;
     28 
     29 	clock_gettime(CLOCK_REALTIME, &n->stamp);
     30 
     31 	return 0;
     32 }
     33 
     34 int net_init(struct net *n)
     35 {
     36 	char linebuf[512];
     37 	char *i;
     38 	FILE *f = fopen("/proc/net/dev", "r");
     39 	int r = ENODATA;
     40 
     41 	if (!f)
     42 		return errno;
     43 	if (!fgets(linebuf, sizeof(linebuf), f) ||
     44 	    !fgets(linebuf, sizeof(linebuf), f))
     45 		goto out;
     46 	if (!*(i = linebuf + strcspn(linebuf, "|")))
     47 		goto out;
     48 	i++;
     49 #define X(d, n) \
     50 	if (memcmp(i, #n, sizeof(#n) - 1)) \
     51 		goto out; \
     52 	i += sizeof(#n) - 1; \
     53 	if (*i != ' ' && *i != '|' && *i != '\n') \
     54 		goto out; \
     55 	i += strspn(i, " ");
     56 
     57 	NET_FIELDS_RX(X)
     58 	
     59 	if (*i++ != '|')
     60 		goto out;
     61 
     62 	NET_FIELDS_TX(X)
     63 #undef X
     64 
     65 	if (*i != '\n')
     66 		goto out;
     67 	r = _net_read(n, f, linebuf, sizeof(linebuf));
     68 out:
     69 	fclose(f);
     70 	return r;
     71 }
     72 
     73 int net_poll(struct net *n, struct json *j)
     74 {
     75 	int r = ENODATA;
     76 	FILE *f = fopen("/proc/net/dev", "r");
     77 	char linebuf[512];
     78 	struct net n0 = *n;
     79 	size_t oi;
     80 	size_t ni;
     81 
     82 	if (!f)
     83 		return errno;
     84 	if (!fgets(linebuf, sizeof(linebuf), f) ||
     85 	    !fgets(linebuf, sizeof(linebuf), f))
     86 		goto out;
     87 
     88 	if ((r = _net_read(n, f, linebuf, sizeof(linebuf))))
     89 		goto out;
     90 
     91 	for (oi = 0, ni = 0; ni < n->n; ni++) {
     92 		char namebuf[IF_NAMESIZE + 1];
     93 		while (oi < n0.n && n0.ifaces[oi].ifidx < n->ifaces[ni].ifidx)
     94 			oi++;
     95 		if (!if_indextoname(n->ifaces[ni].ifidx, namebuf))
     96 			continue;
     97 		if ((r = json_obj_key(j, "milliseconds")))
     98 			goto out;
     99 		if ((r = json_int(j, ((intmax_t)n->stamp.tv_sec - n0.stamp.tv_sec) * 1000 + ((intmax_t)n->stamp.tv_nsec - n0.stamp.tv_nsec) / 1000000)))
    100 			goto out;
    101 		if ((r = json_obj_key(j, namebuf)))
    102 			goto out;
    103 		if ((r = json_obj_open(j)))
    104 			goto out;
    105 		if (oi < n0.n && n->ifaces[ni].ifidx == n0.ifaces[oi].ifidx) {
    106 #define X(d, na) \
    107 			if ((r = json_obj_key(j, #d #na))) \
    108 				goto out; \
    109 			if ((r = json_int(j, n->ifaces[ni].d ## na - n0.ifaces[oi].d ## na))) \
    110 				goto out;
    111 			NET_FIELDS(X)
    112 #undef X
    113 		} else {
    114 #define X(d, na) \
    115 			if ((r = json_obj_key(j, #d #na))) \
    116 				goto out; \
    117 			if ((r = json_int(j, 0))) \
    118 				goto out;
    119 			NET_FIELDS(X)
    120 #undef X
    121 		}
    122 		if ((r = json_obj_close(j)))
    123 			goto out;
    124 	}
    125 out:
    126 	fclose(f);
    127 	return r;
    128 }