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
netloginit(Fs * f)72 netloginit(Fs *f)
73 {
74 f->alog = smalloc(sizeof(Netlog));
75 }
76
77 void
netlogopen(Fs * f)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 if(f->alog->buf == nil)
89 error(Enomem);
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
netlogclose(Fs * f)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
netlogready(void * a)116 netlogready(void *a)
117 {
118 Fs *f = a;
119
120 return f->alog->len;
121 }
122
123 long
netlogread(Fs * f,void * a,ulong,long n)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
netlogctl(Fs * f,char * s,int n)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 poperror();
206 return;
207
208 default:
209 cmderror(cb, "unknown netlog control message");
210 }
211
212 for(i = 1; i < cb->nf; i++){
213 for(fp = flags; fp->name; fp++)
214 if(strcmp(fp->name, cb->f[i]) == 0)
215 break;
216 if(fp->name == nil)
217 continue;
218 if(set)
219 f->alog->logmask |= fp->mask;
220 else
221 f->alog->logmask &= ~fp->mask;
222 }
223
224 free(cb);
225 poperror();
226 }
227
228 void
netlog(Fs * f,int mask,char * fmt,...)229 netlog(Fs *f, int mask, char *fmt, ...)
230 {
231 char buf[256], *t, *fp;
232 int i, n;
233 va_list arg;
234
235 if(!(f->alog->logmask & mask))
236 return;
237
238 if(f->alog->opens == 0)
239 return;
240
241 va_start(arg, fmt);
242 n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
243 va_end(arg);
244
245 lock(f->alog);
246 i = f->alog->len + n - Nlog;
247 if(i > 0){
248 f->alog->len -= i;
249 f->alog->rptr += i;
250 if(f->alog->rptr >= f->alog->end)
251 f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
252 }
253 t = f->alog->rptr + f->alog->len;
254 fp = buf;
255 f->alog->len += n;
256 while(n-- > 0){
257 if(t >= f->alog->end)
258 t = f->alog->buf + (t - f->alog->end);
259 *t++ = *fp++;
260 }
261 unlock(f->alog);
262
263 wakeup(f->alog);
264 }
265