add in the inferno stack.
[akaros.git] / kern / src / net / 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            = 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 }