]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/ip/netlog.c
merge
[plan9front.git] / sys / src / 9 / ip / netlog.c
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                 poperror();
204                 return;
205
206         default:
207                 cmderror(cb, "unknown ip control message");
208         }
209
210         for(i = 1; i < cb->nf; i++){
211                 for(fp = flags; fp->name; fp++)
212                         if(strcmp(fp->name, cb->f[i]) == 0)
213                                 break;
214                 if(fp->name == nil)
215                         continue;
216                 if(set)
217                         f->alog->logmask |= fp->mask;
218                 else
219                         f->alog->logmask &= ~fp->mask;
220         }
221
222         free(cb);
223         poperror();
224 }
225
226 void
227 netlog(Fs *f, int mask, char *fmt, ...)
228 {
229         char buf[256], *t, *fp;
230         int i, n;
231         va_list arg;
232
233         if(!(f->alog->logmask & mask))
234                 return;
235
236         if(f->alog->opens == 0)
237                 return;
238
239         va_start(arg, fmt);
240         n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
241         va_end(arg);
242
243         lock(f->alog);
244         i = f->alog->len + n - Nlog;
245         if(i > 0){
246                 f->alog->len -= i;
247                 f->alog->rptr += i;
248                 if(f->alog->rptr >= f->alog->end)
249                         f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
250         }
251         t = f->alog->rptr + f->alog->len;
252         fp = buf;
253         f->alog->len += n;
254         while(n-- > 0){
255                 if(t >= f->alog->end)
256                         t = f->alog->buf + (t - f->alog->end);
257                 *t++ = *fp++;
258         }
259         unlock(f->alog);
260
261         wakeup(f->alog);
262 }