shithub: netgraph

ref: e78b5e27f582a692b81369be4614d0a7b8eee9cb
dir: /netgraph.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ndb.h>
#include <String.h>
#include "dat.h"
#include "fns.h"

static void
usage(void)
{
	fprint(2, "usage: %s [-ip] [-s systuples] [-n ipnettuples]\n", argv0);
	exits("usage");
}

#define MAXSYSTP 24

char *Sipnet = "ipnet";

char *netdir = nil;

char *systuples[MAXSYSTP];
int nsystuples = 0;
char *ipnettuples[MAXSYSTP];
int nipnettuples = 0;

/* A3 format: 842 x 1191 */
int pagewidth = 1191;
int pageheight = 842;

int showipnet = 0;

static void
procrequest(char *key, char *val)
{
	if (issysarg(key)) {
		gensys(key, val);
		return;
	}
	if (isnetarg(key)) {
		genipnet(key, val);
		return;
	}
}

static void
procinput(char *s)
{
	char *c;
	
	c = strchr(s, '=');
	if (!(c && c[0] && c[1]))
		return;
	
	c[0] = 0;
	c++;
	
	procrequest(s, c);
}

void
dumptuples(Tuple *t, void*)
{
	fprint(2, "  %s=%s\n", t->key, t->value);
}

void
dumpsys(Sys *s, void*)
{
	fprint(2, "sys: %d %d\n", s->p.x, s->p.y);
	fortuple(s, dumptuples, nil);
}

void
dumpipnet(Ipnet *n, void*)
{
	fprint(2, "ipnet\n");
	fortuple(n, dumptuples, nil);
}

static Color
hue2color(float h)
{
	Color c;
	int i = h;
	float f = h * 6. - i;
	float p = 0.;
	float q = 1. - f;
	float t = 1. - (1. - f);
	
	switch (i % 6) {
	case 0: c.r = 1; c.g = t; c.b = p; break;
	case 1: c.r = q; c.g = 1; c.b = p; break;
	case 2: c.r = p; c.g = 1; c.b = t; break;
	case 3: c.r = p; c.g = q; c.b = 1; break;
	case 4: c.r = t; c.g = p; c.b = 1; break;
	case 5: c.r = 1; c.g = p; c.b = q; break;
	}
	c.r = c.r < 0 ? 0 : c.r;
	c.g = c.g < 0 ? 0 : c.g;
	c.b = c.b < 0 ? 0 : c.b;
	return c;
}

typedef struct Calcipnetparams Calcipnetparams;
struct Calcipnetparams {
	int i;
	int x;
};

static void
calcnetlayout(Ipnet *n, void *aux)
{
	Calcipnetparams *p = aux;
	int num = numipnets();
	int i = p->i;
	float step = 2*PI / num;
	float hue = (step * i) / PI;
	
	n->color = hue2color(hue);
	
	setblocksize(n);
	
	n->p.x = p->x + 5;
	n->p.y = 5;
	
	p->i++;
	p->x += n->width + 10;
}

static void
calcsyslayout(Sys *s, void *aux)
{
	int n = numsystems();
	int *ip = aux;
	int i = *ip;
	float step = 2*PI / n;
	
	setblocksize(s);
	
	float pagex = pagewidth/2.;
	float pagey = pageheight/2.;
	float spread = 0.6;
	
	s->p.x = cos(step * i) * pagex * spread + pagex - s->width/2;
	s->p.y = sin(step * i) * pagey * spread + pagey - s->height/2;
	
	(*ip)++;
}

static void
calcconn(Tuple *t, void *aux)
{
	Sys *from = aux;
	Sys *to = findsys(t->key, t->value);
	if (!to)
		return;
	if (to == from)
		return;
	addconn(from, to, t->key);
}

void
calcconns(Sys *s, void*)
{
	fortuple(s, calcconn, s);
}

static void
drawconns(Conn *c, void*)
{
	dconn(c->from, c->to, s_to_c(c->types));
}

static void
drawsystems(Sys *s, void*)
{
	dblock(s);
}

static void
drawipnets(Ipnet *n, void*)
{
	dblock(n);
}

static void
injectpdfout(void)
{
	char *size;
	int p[2];
	
	pipe(p);
	
	switch (fork()) {
	case -1:
		sysfatal("fork: %r");
	case 0:
		break;
	default: /* parent */
		dup(p[0], 1);
		close(p[1]);
		return;
	}
	/* child */
	dup(p[1], 0);
	close(p[0]);
	size = smprint("-g%dx%d", pagewidth, pageheight);
	execl("/bin/ps2pdf", "ps2pdf", size, "-r72", nil);
	sysfatal("execl: %r");
}

void
main(int argc, char **argv)
{
	Biobuf *bin;
	Calcipnetparams netparams;
	char *stp = "sys,ether,ip,ipgw,ipnet,dom,auth,authdom";
	char *ntp = "ipnet,ip,ipmask,ipgw,authdom,auth,fs,dns";
	char *s;
	int i;
	int pdf = 0;
	
	ARGBEGIN{
	case 'h':
		usage();
	case 's':
		stp = EARGF(usage());
		break;
	case 'n':
		ntp = EARGF(usage());
		break;
	case 'x':
		netdir = EARGF(usage());
		break;
	case 'i':
		showipnet++;
		break;
	case 'p':
		pdf++;
		break;
	}ARGEND;
	
	if (pdf)
		injectpdfout();
	
	nsystuples = getfields(stp, systuples, MAXSYSTP, 1, ",");
	nipnettuples = getfields(ntp, ipnettuples, MAXSYSTP, 1, ",");
	
	bin = Bfdopen(0, OREAD);
	if (!bin)
		sysfatal("%r");
	
	while (s = Brdstr(bin, '\n', 1)) {
		procinput(s);
		free(s);
	}
	
	Bterm(bin);
	
	/* calculation stage */
	i = 0;
	forsys(calcsyslayout, &i);
	
	netparams.i = 0;
	netparams.x = 0;
	fornet(calcnetlayout, &netparams);
	
	forsys(calcconns, nil);
	
	/* drawing stage */
	dheader();
	forconn(drawconns, nil);
	forsys(drawsystems, nil);
	fornet(drawipnets, nil);
	dfooter();
}

static int
tryaddsys(char *s, void *aux)
{
	char *sys = aux;
	return gensys(s, sys);
}

void
fillblockvalue(Block *b, char *key, char *ids, char *idv)
{
	char *val;
	Ndbtuple *t;
	
	val = csgetvalue(netdir, ids, idv, key, nil);
	if (val) {
		addtuple(b, key, val, 0);
		return;
	}
	t = csipinfo(netdir, ids, idv, &key, 1);
	if (t) {
		if (t->val)
			val = strdup(t->val);
		ndbfree(t);
	}
	if (!val)
		return;
	addtuple(b, key, val, 1);
	
	if (!isconnsrv(key))
		return;
	
	forsysarg(tryaddsys, val);
}