xref: /plan9/sys/src/9/ip/netlog.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
17dd7cddfSDavid du Colombier #include	"u.h"
27dd7cddfSDavid du Colombier #include	"../port/lib.h"
37dd7cddfSDavid du Colombier #include	"mem.h"
47dd7cddfSDavid du Colombier #include	"dat.h"
57dd7cddfSDavid du Colombier #include	"fns.h"
67dd7cddfSDavid du Colombier #include	"../port/error.h"
77dd7cddfSDavid du Colombier #include	"../ip/ip.h"
87dd7cddfSDavid du Colombier 
97dd7cddfSDavid du Colombier enum {
10f2c197d9SDavid du Colombier 	Nlog		= 16*1024,
117dd7cddfSDavid du Colombier };
127dd7cddfSDavid du Colombier 
137dd7cddfSDavid du Colombier /*
147dd7cddfSDavid du Colombier  *  action log
157dd7cddfSDavid du Colombier  */
167dd7cddfSDavid du Colombier struct Netlog {
177dd7cddfSDavid du Colombier 	Lock;
187dd7cddfSDavid du Colombier 	int	opens;
197dd7cddfSDavid du Colombier 	char*	buf;
207dd7cddfSDavid du Colombier 	char	*end;
217dd7cddfSDavid du Colombier 	char	*rptr;
227dd7cddfSDavid du Colombier 	int	len;
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier 	int	logmask;			/* mask of things to debug */
257dd7cddfSDavid du Colombier 	uchar	iponly[IPaddrlen];		/* ip address to print debugging for */
267dd7cddfSDavid du Colombier 	int	iponlyset;
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier 	QLock;
297dd7cddfSDavid du Colombier 	Rendez;
307dd7cddfSDavid du Colombier };
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier typedef struct Netlogflag {
337dd7cddfSDavid du Colombier 	char*	name;
347dd7cddfSDavid du Colombier 	int	mask;
357dd7cddfSDavid du Colombier } Netlogflag;
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier static Netlogflag flags[] =
387dd7cddfSDavid du Colombier {
397dd7cddfSDavid du Colombier 	{ "ppp",	Logppp, },
407dd7cddfSDavid du Colombier 	{ "ip",		Logip, },
417dd7cddfSDavid du Colombier 	{ "fs",		Logfs, },
427dd7cddfSDavid du Colombier 	{ "tcp",	Logtcp, },
437dd7cddfSDavid du Colombier 	{ "icmp",	Logicmp, },
447dd7cddfSDavid du Colombier 	{ "udp",	Logudp, },
457dd7cddfSDavid du Colombier 	{ "compress",	Logcompress, },
467dd7cddfSDavid du Colombier 	{ "gre",	Loggre, },
473ff48bf5SDavid du Colombier 	{ "tcpwin",	Logtcp|Logtcpwin, },
483ff48bf5SDavid du Colombier 	{ "tcprxmt",	Logtcp|Logtcprxmt, },
497dd7cddfSDavid du Colombier 	{ "udpmsg",	Logudp|Logudpmsg, },
507dd7cddfSDavid du Colombier 	{ "ipmsg",	Logip|Logipmsg, },
517dd7cddfSDavid du Colombier 	{ "esp",	Logesp, },
527dd7cddfSDavid du Colombier 	{ nil,		0, },
537dd7cddfSDavid du Colombier };
547dd7cddfSDavid du Colombier 
559a747e4fSDavid du Colombier char Ebadnetctl[] = "too few arguments for netlog control message";
569a747e4fSDavid du Colombier 
579a747e4fSDavid du Colombier enum
589a747e4fSDavid du Colombier {
599a747e4fSDavid du Colombier 	CMset,
609a747e4fSDavid du Colombier 	CMclear,
619a747e4fSDavid du Colombier 	CMonly,
629a747e4fSDavid du Colombier };
639a747e4fSDavid du Colombier 
649a747e4fSDavid du Colombier static
659a747e4fSDavid du Colombier Cmdtab routecmd[] = {
669a747e4fSDavid du Colombier 	CMset,		"set",		0,
679a747e4fSDavid du Colombier 	CMclear,	"clear",	0,
689a747e4fSDavid du Colombier 	CMonly,		"only",		0,
699a747e4fSDavid du Colombier };
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier void
netloginit(Fs * f)727dd7cddfSDavid du Colombier netloginit(Fs *f)
737dd7cddfSDavid du Colombier {
747dd7cddfSDavid du Colombier 	f->alog = smalloc(sizeof(Netlog));
757dd7cddfSDavid du Colombier }
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier void
netlogopen(Fs * f)787dd7cddfSDavid du Colombier netlogopen(Fs *f)
797dd7cddfSDavid du Colombier {
807dd7cddfSDavid du Colombier 	lock(f->alog);
817dd7cddfSDavid du Colombier 	if(waserror()){
827dd7cddfSDavid du Colombier 		unlock(f->alog);
837dd7cddfSDavid du Colombier 		nexterror();
847dd7cddfSDavid du Colombier 	}
857dd7cddfSDavid du Colombier 	if(f->alog->opens == 0){
867dd7cddfSDavid du Colombier 		if(f->alog->buf == nil)
877dd7cddfSDavid du Colombier 			f->alog->buf = malloc(Nlog);
88aa72973aSDavid du Colombier 		if(f->alog->buf == nil)
89aa72973aSDavid du Colombier 			error(Enomem);
907dd7cddfSDavid du Colombier 		f->alog->rptr = f->alog->buf;
917dd7cddfSDavid du Colombier 		f->alog->end = f->alog->buf + Nlog;
927dd7cddfSDavid du Colombier 	}
937dd7cddfSDavid du Colombier 	f->alog->opens++;
947dd7cddfSDavid du Colombier 	unlock(f->alog);
957dd7cddfSDavid du Colombier 	poperror();
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier void
netlogclose(Fs * f)997dd7cddfSDavid du Colombier netlogclose(Fs *f)
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier 	lock(f->alog);
1027dd7cddfSDavid du Colombier 	if(waserror()){
1037dd7cddfSDavid du Colombier 		unlock(f->alog);
1047dd7cddfSDavid du Colombier 		nexterror();
1057dd7cddfSDavid du Colombier 	}
1067dd7cddfSDavid du Colombier 	f->alog->opens--;
1077dd7cddfSDavid du Colombier 	if(f->alog->opens == 0){
1087dd7cddfSDavid du Colombier 		free(f->alog->buf);
1097dd7cddfSDavid du Colombier 		f->alog->buf = nil;
1107dd7cddfSDavid du Colombier 	}
1117dd7cddfSDavid du Colombier 	unlock(f->alog);
1127dd7cddfSDavid du Colombier 	poperror();
1137dd7cddfSDavid du Colombier }
1147dd7cddfSDavid du Colombier 
1157dd7cddfSDavid du Colombier static int
netlogready(void * a)1167dd7cddfSDavid du Colombier netlogready(void *a)
1177dd7cddfSDavid du Colombier {
1187dd7cddfSDavid du Colombier 	Fs *f = a;
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier 	return f->alog->len;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier long
netlogread(Fs * f,void * a,ulong,long n)1247dd7cddfSDavid du Colombier netlogread(Fs *f, void *a, ulong, long n)
1257dd7cddfSDavid du Colombier {
1267dd7cddfSDavid du Colombier 	int i, d;
1277dd7cddfSDavid du Colombier 	char *p, *rptr;
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier 	qlock(f->alog);
1307dd7cddfSDavid du Colombier 	if(waserror()){
1317dd7cddfSDavid du Colombier 		qunlock(f->alog);
1327dd7cddfSDavid du Colombier 		nexterror();
1337dd7cddfSDavid du Colombier 	}
1347dd7cddfSDavid du Colombier 
1357dd7cddfSDavid du Colombier 	for(;;){
1367dd7cddfSDavid du Colombier 		lock(f->alog);
1377dd7cddfSDavid du Colombier 		if(f->alog->len){
1387dd7cddfSDavid du Colombier 			if(n > f->alog->len)
1397dd7cddfSDavid du Colombier 				n = f->alog->len;
1407dd7cddfSDavid du Colombier 			d = 0;
1417dd7cddfSDavid du Colombier 			rptr = f->alog->rptr;
1427dd7cddfSDavid du Colombier 			f->alog->rptr += n;
1437dd7cddfSDavid du Colombier 			if(f->alog->rptr >= f->alog->end){
1447dd7cddfSDavid du Colombier 				d = f->alog->rptr - f->alog->end;
1457dd7cddfSDavid du Colombier 				f->alog->rptr = f->alog->buf + d;
1467dd7cddfSDavid du Colombier 			}
1477dd7cddfSDavid du Colombier 			f->alog->len -= n;
1487dd7cddfSDavid du Colombier 			unlock(f->alog);
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier 			i = n-d;
1517dd7cddfSDavid du Colombier 			p = a;
1527dd7cddfSDavid du Colombier 			memmove(p, rptr, i);
1537dd7cddfSDavid du Colombier 			memmove(p+i, f->alog->buf, d);
1547dd7cddfSDavid du Colombier 			break;
1557dd7cddfSDavid du Colombier 		}
1567dd7cddfSDavid du Colombier 		else
1577dd7cddfSDavid du Colombier 			unlock(f->alog);
1587dd7cddfSDavid du Colombier 
1597dd7cddfSDavid du Colombier 		sleep(f->alog, netlogready, f);
1607dd7cddfSDavid du Colombier 	}
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier 	qunlock(f->alog);
1637dd7cddfSDavid du Colombier 	poperror();
1647dd7cddfSDavid du Colombier 
1657dd7cddfSDavid du Colombier 	return n;
1667dd7cddfSDavid du Colombier }
1677dd7cddfSDavid du Colombier 
1689a747e4fSDavid du Colombier void
netlogctl(Fs * f,char * s,int n)1699a747e4fSDavid du Colombier netlogctl(Fs *f, char* s, int n)
1707dd7cddfSDavid du Colombier {
1719a747e4fSDavid du Colombier 	int i, set;
1727dd7cddfSDavid du Colombier 	Netlogflag *fp;
1739a747e4fSDavid du Colombier 	Cmdbuf *cb;
1749a747e4fSDavid du Colombier 	Cmdtab *ct;
1757dd7cddfSDavid du Colombier 
1769a747e4fSDavid du Colombier 	cb = parsecmd(s, n);
1779a747e4fSDavid du Colombier 	if(waserror()){
1789a747e4fSDavid du Colombier 		free(cb);
1799a747e4fSDavid du Colombier 		nexterror();
1809a747e4fSDavid du Colombier 	}
1817dd7cddfSDavid du Colombier 
1829a747e4fSDavid du Colombier 	if(cb->nf < 2)
1839a747e4fSDavid du Colombier 		error(Ebadnetctl);
1847dd7cddfSDavid du Colombier 
1859a747e4fSDavid du Colombier 	ct = lookupcmd(cb, routecmd, nelem(routecmd));
1867dd7cddfSDavid du Colombier 
1879a747e4fSDavid du Colombier 	SET(set);
1889a747e4fSDavid du Colombier 
1899a747e4fSDavid du Colombier 	switch(ct->index){
1909a747e4fSDavid du Colombier 	case CMset:
1917dd7cddfSDavid du Colombier 		set = 1;
1929a747e4fSDavid du Colombier 		break;
1939a747e4fSDavid du Colombier 
1949a747e4fSDavid du Colombier 	case CMclear:
1957dd7cddfSDavid du Colombier 		set = 0;
1969a747e4fSDavid du Colombier 		break;
1979a747e4fSDavid du Colombier 
1989a747e4fSDavid du Colombier 	case CMonly:
1999a747e4fSDavid du Colombier 		parseip(f->alog->iponly, cb->f[1]);
2007dd7cddfSDavid du Colombier 		if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
2017dd7cddfSDavid du Colombier 			f->alog->iponlyset = 0;
2027dd7cddfSDavid du Colombier 		else
2037dd7cddfSDavid du Colombier 			f->alog->iponlyset = 1;
2049a747e4fSDavid du Colombier 		free(cb);
205*00d97012SDavid du Colombier 		poperror();
2069a747e4fSDavid du Colombier 		return;
2077dd7cddfSDavid du Colombier 
2089a747e4fSDavid du Colombier 	default:
209*00d97012SDavid du Colombier 		cmderror(cb, "unknown netlog control message");
2109a747e4fSDavid du Colombier 	}
2117dd7cddfSDavid du Colombier 
2129a747e4fSDavid du Colombier 	for(i = 1; i < cb->nf; i++){
2137dd7cddfSDavid du Colombier 		for(fp = flags; fp->name; fp++)
2149a747e4fSDavid du Colombier 			if(strcmp(fp->name, cb->f[i]) == 0)
2157dd7cddfSDavid du Colombier 				break;
2167dd7cddfSDavid du Colombier 		if(fp->name == nil)
2177dd7cddfSDavid du Colombier 			continue;
2187dd7cddfSDavid du Colombier 		if(set)
2197dd7cddfSDavid du Colombier 			f->alog->logmask |= fp->mask;
2207dd7cddfSDavid du Colombier 		else
2217dd7cddfSDavid du Colombier 			f->alog->logmask &= ~fp->mask;
2227dd7cddfSDavid du Colombier 	}
2237dd7cddfSDavid du Colombier 
2249a747e4fSDavid du Colombier 	free(cb);
2259a747e4fSDavid du Colombier 	poperror();
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier void
netlog(Fs * f,int mask,char * fmt,...)2297dd7cddfSDavid du Colombier netlog(Fs *f, int mask, char *fmt, ...)
2307dd7cddfSDavid du Colombier {
231c6569576SDavid du Colombier 	char buf[256], *t, *fp;
2327dd7cddfSDavid du Colombier 	int i, n;
2337dd7cddfSDavid du Colombier 	va_list arg;
2347dd7cddfSDavid du Colombier 
2357dd7cddfSDavid du Colombier 	if(!(f->alog->logmask & mask))
2367dd7cddfSDavid du Colombier 		return;
2377dd7cddfSDavid du Colombier 
2387dd7cddfSDavid du Colombier 	if(f->alog->opens == 0)
2397dd7cddfSDavid du Colombier 		return;
2407dd7cddfSDavid du Colombier 
2419a747e4fSDavid du Colombier 	va_start(arg, fmt);
2429a747e4fSDavid du Colombier 	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
2439a747e4fSDavid du Colombier 	va_end(arg);
2449a747e4fSDavid du Colombier 
2457dd7cddfSDavid du Colombier 	lock(f->alog);
2467dd7cddfSDavid du Colombier 	i = f->alog->len + n - Nlog;
2477dd7cddfSDavid du Colombier 	if(i > 0){
2487dd7cddfSDavid du Colombier 		f->alog->len -= i;
2497dd7cddfSDavid du Colombier 		f->alog->rptr += i;
2507dd7cddfSDavid du Colombier 		if(f->alog->rptr >= f->alog->end)
2517dd7cddfSDavid du Colombier 			f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
2527dd7cddfSDavid du Colombier 	}
2537dd7cddfSDavid du Colombier 	t = f->alog->rptr + f->alog->len;
2547dd7cddfSDavid du Colombier 	fp = buf;
2557dd7cddfSDavid du Colombier 	f->alog->len += n;
2567dd7cddfSDavid du Colombier 	while(n-- > 0){
2577dd7cddfSDavid du Colombier 		if(t >= f->alog->end)
2587dd7cddfSDavid du Colombier 			t = f->alog->buf + (t - f->alog->end);
2597dd7cddfSDavid du Colombier 		*t++ = *fp++;
2607dd7cddfSDavid du Colombier 	}
2617dd7cddfSDavid du Colombier 	unlock(f->alog);
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier 	wakeup(f->alog);
2647dd7cddfSDavid du Colombier }
265