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