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