xref: /plan9-contrib/sys/src/9k/ip/netlog.c (revision 9ef1f84b659abcb917c5c090acbce0772e494f21)
1*9ef1f84bSDavid du Colombier #include	"u.h"
2*9ef1f84bSDavid du Colombier #include	"../port/lib.h"
3*9ef1f84bSDavid du Colombier #include	"mem.h"
4*9ef1f84bSDavid du Colombier #include	"dat.h"
5*9ef1f84bSDavid du Colombier #include	"fns.h"
6*9ef1f84bSDavid du Colombier #include	"../port/error.h"
7*9ef1f84bSDavid du Colombier #include	"../ip/ip.h"
8*9ef1f84bSDavid du Colombier 
9*9ef1f84bSDavid du Colombier enum {
10*9ef1f84bSDavid du Colombier 	Nlog		= 16*1024,
11*9ef1f84bSDavid du Colombier };
12*9ef1f84bSDavid du Colombier 
13*9ef1f84bSDavid du Colombier /*
14*9ef1f84bSDavid du Colombier  *  action log
15*9ef1f84bSDavid du Colombier  */
16*9ef1f84bSDavid du Colombier struct Netlog {
17*9ef1f84bSDavid du Colombier 	Lock;
18*9ef1f84bSDavid du Colombier 	int	opens;
19*9ef1f84bSDavid du Colombier 	char*	buf;
20*9ef1f84bSDavid du Colombier 	char	*end;
21*9ef1f84bSDavid du Colombier 	char	*rptr;
22*9ef1f84bSDavid du Colombier 	int	len;
23*9ef1f84bSDavid du Colombier 
24*9ef1f84bSDavid du Colombier 	int	logmask;			/* mask of things to debug */
25*9ef1f84bSDavid du Colombier 	uchar	iponly[IPaddrlen];		/* ip address to print debugging for */
26*9ef1f84bSDavid du Colombier 	int	iponlyset;
27*9ef1f84bSDavid du Colombier 
28*9ef1f84bSDavid du Colombier 	QLock;
29*9ef1f84bSDavid du Colombier 	Rendez;
30*9ef1f84bSDavid du Colombier };
31*9ef1f84bSDavid du Colombier 
32*9ef1f84bSDavid du Colombier typedef struct Netlogflag {
33*9ef1f84bSDavid du Colombier 	char*	name;
34*9ef1f84bSDavid du Colombier 	int	mask;
35*9ef1f84bSDavid du Colombier } Netlogflag;
36*9ef1f84bSDavid du Colombier 
37*9ef1f84bSDavid du Colombier static Netlogflag flags[] =
38*9ef1f84bSDavid du Colombier {
39*9ef1f84bSDavid du Colombier 	{ "ppp",	Logppp, },
40*9ef1f84bSDavid du Colombier 	{ "ip",		Logip, },
41*9ef1f84bSDavid du Colombier 	{ "fs",		Logfs, },
42*9ef1f84bSDavid du Colombier 	{ "tcp",	Logtcp, },
43*9ef1f84bSDavid du Colombier 	{ "icmp",	Logicmp, },
44*9ef1f84bSDavid du Colombier 	{ "udp",	Logudp, },
45*9ef1f84bSDavid du Colombier 	{ "compress",	Logcompress, },
46*9ef1f84bSDavid du Colombier 	{ "gre",	Loggre, },
47*9ef1f84bSDavid du Colombier 	{ "tcpwin",	Logtcp|Logtcpwin, },
48*9ef1f84bSDavid du Colombier 	{ "tcprxmt",	Logtcp|Logtcprxmt, },
49*9ef1f84bSDavid du Colombier 	{ "udpmsg",	Logudp|Logudpmsg, },
50*9ef1f84bSDavid du Colombier 	{ "ipmsg",	Logip|Logipmsg, },
51*9ef1f84bSDavid du Colombier 	{ "esp",	Logesp, },
52*9ef1f84bSDavid du Colombier 	{ nil,		0, },
53*9ef1f84bSDavid du Colombier };
54*9ef1f84bSDavid du Colombier 
55*9ef1f84bSDavid du Colombier char Ebadnetctl[] = "too few arguments for netlog control message";
56*9ef1f84bSDavid du Colombier 
57*9ef1f84bSDavid du Colombier enum
58*9ef1f84bSDavid du Colombier {
59*9ef1f84bSDavid du Colombier 	CMset,
60*9ef1f84bSDavid du Colombier 	CMclear,
61*9ef1f84bSDavid du Colombier 	CMonly,
62*9ef1f84bSDavid du Colombier };
63*9ef1f84bSDavid du Colombier 
64*9ef1f84bSDavid du Colombier static
65*9ef1f84bSDavid du Colombier Cmdtab routecmd[] = {
66*9ef1f84bSDavid du Colombier 	CMset,		"set",		0,
67*9ef1f84bSDavid du Colombier 	CMclear,	"clear",	0,
68*9ef1f84bSDavid du Colombier 	CMonly,		"only",		0,
69*9ef1f84bSDavid du Colombier };
70*9ef1f84bSDavid du Colombier 
71*9ef1f84bSDavid du Colombier void
netloginit(Fs * f)72*9ef1f84bSDavid du Colombier netloginit(Fs *f)
73*9ef1f84bSDavid du Colombier {
74*9ef1f84bSDavid du Colombier 	f->alog = smalloc(sizeof(Netlog));
75*9ef1f84bSDavid du Colombier }
76*9ef1f84bSDavid du Colombier 
77*9ef1f84bSDavid du Colombier void
netlogopen(Fs * f)78*9ef1f84bSDavid du Colombier netlogopen(Fs *f)
79*9ef1f84bSDavid du Colombier {
80*9ef1f84bSDavid du Colombier 	lock(f->alog);
81*9ef1f84bSDavid du Colombier 	if(waserror()){
82*9ef1f84bSDavid du Colombier 		unlock(f->alog);
83*9ef1f84bSDavid du Colombier 		nexterror();
84*9ef1f84bSDavid du Colombier 	}
85*9ef1f84bSDavid du Colombier 	if(f->alog->opens == 0){
86*9ef1f84bSDavid du Colombier 		if(f->alog->buf == nil)
87*9ef1f84bSDavid du Colombier 			f->alog->buf = malloc(Nlog);
88*9ef1f84bSDavid du Colombier 		if(f->alog->buf == nil)
89*9ef1f84bSDavid du Colombier 			error(Enomem);
90*9ef1f84bSDavid du Colombier 		f->alog->rptr = f->alog->buf;
91*9ef1f84bSDavid du Colombier 		f->alog->end = f->alog->buf + Nlog;
92*9ef1f84bSDavid du Colombier 	}
93*9ef1f84bSDavid du Colombier 	f->alog->opens++;
94*9ef1f84bSDavid du Colombier 	unlock(f->alog);
95*9ef1f84bSDavid du Colombier 	poperror();
96*9ef1f84bSDavid du Colombier }
97*9ef1f84bSDavid du Colombier 
98*9ef1f84bSDavid du Colombier void
netlogclose(Fs * f)99*9ef1f84bSDavid du Colombier netlogclose(Fs *f)
100*9ef1f84bSDavid du Colombier {
101*9ef1f84bSDavid du Colombier 	lock(f->alog);
102*9ef1f84bSDavid du Colombier 	if(waserror()){
103*9ef1f84bSDavid du Colombier 		unlock(f->alog);
104*9ef1f84bSDavid du Colombier 		nexterror();
105*9ef1f84bSDavid du Colombier 	}
106*9ef1f84bSDavid du Colombier 	f->alog->opens--;
107*9ef1f84bSDavid du Colombier 	if(f->alog->opens == 0){
108*9ef1f84bSDavid du Colombier 		free(f->alog->buf);
109*9ef1f84bSDavid du Colombier 		f->alog->buf = nil;
110*9ef1f84bSDavid du Colombier 	}
111*9ef1f84bSDavid du Colombier 	unlock(f->alog);
112*9ef1f84bSDavid du Colombier 	poperror();
113*9ef1f84bSDavid du Colombier }
114*9ef1f84bSDavid du Colombier 
115*9ef1f84bSDavid du Colombier static int
netlogready(void * a)116*9ef1f84bSDavid du Colombier netlogready(void *a)
117*9ef1f84bSDavid du Colombier {
118*9ef1f84bSDavid du Colombier 	Fs *f = a;
119*9ef1f84bSDavid du Colombier 
120*9ef1f84bSDavid du Colombier 	return f->alog->len;
121*9ef1f84bSDavid du Colombier }
122*9ef1f84bSDavid du Colombier 
123*9ef1f84bSDavid du Colombier long
netlogread(Fs * f,void * a,ulong,long n)124*9ef1f84bSDavid du Colombier netlogread(Fs *f, void *a, ulong, long n)
125*9ef1f84bSDavid du Colombier {
126*9ef1f84bSDavid du Colombier 	int i, d;
127*9ef1f84bSDavid du Colombier 	char *p, *rptr;
128*9ef1f84bSDavid du Colombier 
129*9ef1f84bSDavid du Colombier 	qlock(f->alog);
130*9ef1f84bSDavid du Colombier 	if(waserror()){
131*9ef1f84bSDavid du Colombier 		qunlock(f->alog);
132*9ef1f84bSDavid du Colombier 		nexterror();
133*9ef1f84bSDavid du Colombier 	}
134*9ef1f84bSDavid du Colombier 
135*9ef1f84bSDavid du Colombier 	for(;;){
136*9ef1f84bSDavid du Colombier 		lock(f->alog);
137*9ef1f84bSDavid du Colombier 		if(f->alog->len){
138*9ef1f84bSDavid du Colombier 			if(n > f->alog->len)
139*9ef1f84bSDavid du Colombier 				n = f->alog->len;
140*9ef1f84bSDavid du Colombier 			d = 0;
141*9ef1f84bSDavid du Colombier 			rptr = f->alog->rptr;
142*9ef1f84bSDavid du Colombier 			f->alog->rptr += n;
143*9ef1f84bSDavid du Colombier 			if(f->alog->rptr >= f->alog->end){
144*9ef1f84bSDavid du Colombier 				d = f->alog->rptr - f->alog->end;
145*9ef1f84bSDavid du Colombier 				f->alog->rptr = f->alog->buf + d;
146*9ef1f84bSDavid du Colombier 			}
147*9ef1f84bSDavid du Colombier 			f->alog->len -= n;
148*9ef1f84bSDavid du Colombier 			unlock(f->alog);
149*9ef1f84bSDavid du Colombier 
150*9ef1f84bSDavid du Colombier 			i = n-d;
151*9ef1f84bSDavid du Colombier 			p = a;
152*9ef1f84bSDavid du Colombier 			memmove(p, rptr, i);
153*9ef1f84bSDavid du Colombier 			memmove(p+i, f->alog->buf, d);
154*9ef1f84bSDavid du Colombier 			break;
155*9ef1f84bSDavid du Colombier 		}
156*9ef1f84bSDavid du Colombier 		else
157*9ef1f84bSDavid du Colombier 			unlock(f->alog);
158*9ef1f84bSDavid du Colombier 
159*9ef1f84bSDavid du Colombier 		sleep(f->alog, netlogready, f);
160*9ef1f84bSDavid du Colombier 	}
161*9ef1f84bSDavid du Colombier 
162*9ef1f84bSDavid du Colombier 	qunlock(f->alog);
163*9ef1f84bSDavid du Colombier 	poperror();
164*9ef1f84bSDavid du Colombier 
165*9ef1f84bSDavid du Colombier 	return n;
166*9ef1f84bSDavid du Colombier }
167*9ef1f84bSDavid du Colombier 
168*9ef1f84bSDavid du Colombier void
netlogctl(Fs * f,char * s,int n)169*9ef1f84bSDavid du Colombier netlogctl(Fs *f, char* s, int n)
170*9ef1f84bSDavid du Colombier {
171*9ef1f84bSDavid du Colombier 	int i, set;
172*9ef1f84bSDavid du Colombier 	Netlogflag *fp;
173*9ef1f84bSDavid du Colombier 	Cmdbuf *cb;
174*9ef1f84bSDavid du Colombier 	Cmdtab *ct;
175*9ef1f84bSDavid du Colombier 
176*9ef1f84bSDavid du Colombier 	cb = parsecmd(s, n);
177*9ef1f84bSDavid du Colombier 	if(waserror()){
178*9ef1f84bSDavid du Colombier 		free(cb);
179*9ef1f84bSDavid du Colombier 		nexterror();
180*9ef1f84bSDavid du Colombier 	}
181*9ef1f84bSDavid du Colombier 
182*9ef1f84bSDavid du Colombier 	if(cb->nf < 2)
183*9ef1f84bSDavid du Colombier 		error(Ebadnetctl);
184*9ef1f84bSDavid du Colombier 
185*9ef1f84bSDavid du Colombier 	ct = lookupcmd(cb, routecmd, nelem(routecmd));
186*9ef1f84bSDavid du Colombier 
187*9ef1f84bSDavid du Colombier 	SET(set);
188*9ef1f84bSDavid du Colombier 
189*9ef1f84bSDavid du Colombier 	switch(ct->index){
190*9ef1f84bSDavid du Colombier 	case CMset:
191*9ef1f84bSDavid du Colombier 		set = 1;
192*9ef1f84bSDavid du Colombier 		break;
193*9ef1f84bSDavid du Colombier 
194*9ef1f84bSDavid du Colombier 	case CMclear:
195*9ef1f84bSDavid du Colombier 		set = 0;
196*9ef1f84bSDavid du Colombier 		break;
197*9ef1f84bSDavid du Colombier 
198*9ef1f84bSDavid du Colombier 	case CMonly:
199*9ef1f84bSDavid du Colombier 		parseip(f->alog->iponly, cb->f[1]);
200*9ef1f84bSDavid du Colombier 		if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
201*9ef1f84bSDavid du Colombier 			f->alog->iponlyset = 0;
202*9ef1f84bSDavid du Colombier 		else
203*9ef1f84bSDavid du Colombier 			f->alog->iponlyset = 1;
204*9ef1f84bSDavid du Colombier 		free(cb);
205*9ef1f84bSDavid du Colombier 		poperror();
206*9ef1f84bSDavid du Colombier 		return;
207*9ef1f84bSDavid du Colombier 
208*9ef1f84bSDavid du Colombier 	default:
209*9ef1f84bSDavid du Colombier 		cmderror(cb, "unknown netlog control message");
210*9ef1f84bSDavid du Colombier 	}
211*9ef1f84bSDavid du Colombier 
212*9ef1f84bSDavid du Colombier 	for(i = 1; i < cb->nf; i++){
213*9ef1f84bSDavid du Colombier 		for(fp = flags; fp->name; fp++)
214*9ef1f84bSDavid du Colombier 			if(strcmp(fp->name, cb->f[i]) == 0)
215*9ef1f84bSDavid du Colombier 				break;
216*9ef1f84bSDavid du Colombier 		if(fp->name == nil)
217*9ef1f84bSDavid du Colombier 			continue;
218*9ef1f84bSDavid du Colombier 		if(set)
219*9ef1f84bSDavid du Colombier 			f->alog->logmask |= fp->mask;
220*9ef1f84bSDavid du Colombier 		else
221*9ef1f84bSDavid du Colombier 			f->alog->logmask &= ~fp->mask;
222*9ef1f84bSDavid du Colombier 	}
223*9ef1f84bSDavid du Colombier 
224*9ef1f84bSDavid du Colombier 	free(cb);
225*9ef1f84bSDavid du Colombier 	poperror();
226*9ef1f84bSDavid du Colombier }
227*9ef1f84bSDavid du Colombier 
228*9ef1f84bSDavid du Colombier void
netlog(Fs * f,int mask,char * fmt,...)229*9ef1f84bSDavid du Colombier netlog(Fs *f, int mask, char *fmt, ...)
230*9ef1f84bSDavid du Colombier {
231*9ef1f84bSDavid du Colombier 	char buf[256], *t, *fp;
232*9ef1f84bSDavid du Colombier 	int i, n;
233*9ef1f84bSDavid du Colombier 	va_list arg;
234*9ef1f84bSDavid du Colombier 
235*9ef1f84bSDavid du Colombier 	if(!(f->alog->logmask & mask))
236*9ef1f84bSDavid du Colombier 		return;
237*9ef1f84bSDavid du Colombier 
238*9ef1f84bSDavid du Colombier 	if(f->alog->opens == 0)
239*9ef1f84bSDavid du Colombier 		return;
240*9ef1f84bSDavid du Colombier 
241*9ef1f84bSDavid du Colombier 	va_start(arg, fmt);
242*9ef1f84bSDavid du Colombier 	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
243*9ef1f84bSDavid du Colombier 	va_end(arg);
244*9ef1f84bSDavid du Colombier 
245*9ef1f84bSDavid du Colombier 	lock(f->alog);
246*9ef1f84bSDavid du Colombier 	i = f->alog->len + n - Nlog;
247*9ef1f84bSDavid du Colombier 	if(i > 0){
248*9ef1f84bSDavid du Colombier 		f->alog->len -= i;
249*9ef1f84bSDavid du Colombier 		f->alog->rptr += i;
250*9ef1f84bSDavid du Colombier 		if(f->alog->rptr >= f->alog->end)
251*9ef1f84bSDavid du Colombier 			f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
252*9ef1f84bSDavid du Colombier 	}
253*9ef1f84bSDavid du Colombier 	t = f->alog->rptr + f->alog->len;
254*9ef1f84bSDavid du Colombier 	fp = buf;
255*9ef1f84bSDavid du Colombier 	f->alog->len += n;
256*9ef1f84bSDavid du Colombier 	while(n-- > 0){
257*9ef1f84bSDavid du Colombier 		if(t >= f->alog->end)
258*9ef1f84bSDavid du Colombier 			t = f->alog->buf + (t - f->alog->end);
259*9ef1f84bSDavid du Colombier 		*t++ = *fp++;
260*9ef1f84bSDavid du Colombier 	}
261*9ef1f84bSDavid du Colombier 	unlock(f->alog);
262*9ef1f84bSDavid du Colombier 
263*9ef1f84bSDavid du Colombier 	wakeup(f->alog);
264*9ef1f84bSDavid du Colombier }
265