]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/ip/netlog.c
kernel: dont use atomic increment for Proc.nlocks, maintain Lock.m for lock(), use...
[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         { "il",         Logil, },
43         { "tcp",        Logtcp, },
44         { "icmp",       Logicmp, },
45         { "udp",        Logudp, },
46         { "compress",   Logcompress, },
47         { "logilmsg",   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                         if(f->alog->buf == nil)
91                                 error(Enomem);
92                 }
93                 f->alog->rptr = f->alog->buf;
94                 f->alog->end = f->alog->buf + Nlog;
95         }
96         f->alog->opens++;
97         unlock(f->alog);
98         poperror();
99 }
100
101 void
102 netlogclose(Fs *f)
103 {
104         lock(f->alog);
105         if(waserror()){
106                 unlock(f->alog);
107                 nexterror();
108         }
109         f->alog->opens--;
110         if(f->alog->opens == 0){
111                 free(f->alog->buf);
112                 f->alog->buf = nil;
113         }
114         unlock(f->alog);
115         poperror();
116 }
117
118 static int
119 netlogready(void *a)
120 {
121         Fs *f = a;
122
123         return f->alog->len;
124 }
125
126 long
127 netlogread(Fs *f, void *a, ulong, long n)
128 {
129         int i, d;
130         char *p, *rptr;
131
132         qlock(f->alog);
133         if(waserror()){
134                 qunlock(f->alog);
135                 nexterror();
136         }
137
138         for(;;){
139                 lock(f->alog);
140                 if(f->alog->len){
141                         if(n > f->alog->len)
142                                 n = f->alog->len;
143                         d = 0;
144                         rptr = f->alog->rptr;
145                         f->alog->rptr += n;
146                         if(f->alog->rptr >= f->alog->end){
147                                 d = f->alog->rptr - f->alog->end;
148                                 f->alog->rptr = f->alog->buf + d;
149                         }
150                         f->alog->len -= n;
151                         unlock(f->alog);
152
153                         i = n-d;
154                         p = a;
155                         memmove(p, rptr, i);
156                         memmove(p+i, f->alog->buf, d);
157                         break;
158                 }
159                 else
160                         unlock(f->alog);
161
162                 sleep(f->alog, netlogready, f);
163         }
164
165         qunlock(f->alog);
166         poperror();
167
168         return n;
169 }
170
171 void
172 netlogctl(Fs *f, char* s, int n)
173 {
174         int i, set;
175         Netlogflag *fp;
176         Cmdbuf *cb;
177         Cmdtab *ct;
178
179         cb = parsecmd(s, n);
180         if(waserror()){
181                 free(cb);
182                 nexterror();
183         }
184
185         if(cb->nf < 2)
186                 error(Ebadnetctl);
187
188         ct = lookupcmd(cb, routecmd, nelem(routecmd));
189
190         SET(set);
191
192         switch(ct->index){
193         case CMset:
194                 set = 1;
195                 break;
196
197         case CMclear:
198                 set = 0;
199                 break;
200
201         case CMonly:
202                 parseip(f->alog->iponly, cb->f[1]);
203                 if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
204                         f->alog->iponlyset = 0;
205                 else
206                         f->alog->iponlyset = 1;
207                 free(cb);
208                 poperror();
209                 return;
210
211         default:
212                 cmderror(cb, "unknown ip control message");
213         }
214
215         for(i = 1; i < cb->nf; i++){
216                 for(fp = flags; fp->name; fp++)
217                         if(strcmp(fp->name, cb->f[i]) == 0)
218                                 break;
219                 if(fp->name == nil)
220                         continue;
221                 if(set)
222                         f->alog->logmask |= fp->mask;
223                 else
224                         f->alog->logmask &= ~fp->mask;
225         }
226
227         free(cb);
228         poperror();
229 }
230
231 void
232 netlog(Fs *f, int mask, char *fmt, ...)
233 {
234         char buf[256], *t, *fp;
235         int i, n;
236         va_list arg;
237
238         if(!(f->alog->logmask & mask))
239                 return;
240
241         if(f->alog->opens == 0)
242                 return;
243
244         va_start(arg, fmt);
245         n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
246         va_end(arg);
247
248         lock(f->alog);
249         i = f->alog->len + n - Nlog;
250         if(i > 0){
251                 f->alog->len -= i;
252                 f->alog->rptr += i;
253                 if(f->alog->rptr >= f->alog->end)
254                         f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
255         }
256         t = f->alog->rptr + f->alog->len;
257         fp = buf;
258         f->alog->len += n;
259         while(n-- > 0){
260                 if(t >= f->alog->end)
261                         t = f->alog->buf + (t - f->alog->end);
262                 *t++ = *fp++;
263         }
264         unlock(f->alog);
265
266         wakeup(f->alog);
267 }