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