dial.c, which needed netlog.c, so netlog too.
[akaros.git] / kern / src / net / netlog.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 enum {
17         Nlog            = 4*1024,
18 };
19
20 /*
21  *  action log
22  */
23 struct Netlog {
24         spinlock_t lock;
25         int     opens;
26         char*   buf;
27         char    *end;
28         char    *rptr;
29         int     len;
30
31         int     logmask;                        /* mask of things to debug */
32         uint8_t iponly[IPaddrlen];              /* ip address to print debugging for */
33         int     iponlyset;
34
35         qlock_t qlock;
36         struct rendez r;
37 };
38
39 typedef struct Netlogflag {
40         char*   name;
41         int     mask;
42 } Netlogflag;
43
44 static Netlogflag flags[] =
45 {
46         { "ppp",        Logppp, },
47         { "ip",         Logip, },
48         { "fs",         Logfs, },
49         { "tcp",        Logtcp, },
50         { "il",         Logil, },
51         { "icmp",       Logicmp, },
52         { "udp",        Logudp, },
53         { "compress",   Logcompress, },
54         { "ilmsg",      Logil|Logilmsg, },
55         { "gre",        Loggre, },
56         { "tcpwin",     Logtcp|Logtcpwin, },
57         { "tcprxmt",    Logtcp|Logtcprxmt, },
58         { "udpmsg",     Logudp|Logudpmsg, },
59         { "ipmsg",      Logip|Logipmsg, },
60         { "esp",        Logesp, },
61         { NULL,         0, },
62 };
63
64 char Ebadnetctl[] = "too few arguments for netlog control message";
65
66 enum
67 {
68         CMset,
69         CMclear,
70         CMonly,
71 };
72
73 static
74 struct cmdtab routecmd[] = {
75         {CMset,         "set",          0},
76         {CMclear,       "clear",        0},
77         {CMonly,                "only",         0},
78 };
79
80 void
81 netloginit(struct Fs *f)
82 {
83         f->alog = kzmalloc(sizeof(struct Netlog), 0);
84 }
85
86 void
87 netlogopen(struct Fs *f)
88 {
89         ERRSTACK(2);
90         spin_lock(&f->alog->lock);
91         if(waserror()){
92                 spin_unlock(&f->alog->lock);
93                 nexterror();
94         }
95         if(f->alog->opens == 0){
96                 if(f->alog->buf == NULL)
97                         f->alog->buf = kzmalloc(Nlog, 0);
98                 f->alog->rptr = f->alog->buf;
99                 f->alog->end = f->alog->buf + Nlog;
100         }
101         f->alog->opens++;
102         spin_unlock(&f->alog->lock);
103         poperror();
104 }
105
106 void
107 netlogclose(struct Fs *f)
108 {
109         ERRSTACK(2);
110         spin_lock(&f->alog->lock);
111         if(waserror()){
112                 spin_unlock(&f->alog->lock);
113                 nexterror();
114         }
115         f->alog->opens--;
116         if(f->alog->opens == 0){
117                 kfree(f->alog->buf);
118                 f->alog->buf = NULL;
119         }
120         spin_unlock(&f->alog->lock);
121         poperror();
122 }
123
124 static int
125 netlogready(void *a)
126 {
127         struct Fs *f = a;
128
129         return f->alog->len;
130 }
131
132 long
133 netlogread(struct Fs *f, void *a, uint32_t unused, long n)
134 {
135         ERRSTACK(2);
136         int i, d;
137         char *p, *rptr;
138
139         qlock(&f->alog->qlock);
140         if(waserror()){
141                 qunlock(&f->alog->qlock);
142                 nexterror();
143         }
144
145         for(;;){
146                 spin_lock(&f->alog->lock);
147                 if(f->alog->len){
148                         if(n > f->alog->len)
149                                 n = f->alog->len;
150                         d = 0;
151                         rptr = f->alog->rptr;
152                         f->alog->rptr += n;
153                         if(f->alog->rptr >= f->alog->end){
154                                 d = f->alog->rptr - f->alog->end;
155                                 f->alog->rptr = f->alog->buf + d;
156                         }
157                         f->alog->len -= n;
158                         spin_unlock(&f->alog->lock);
159
160                         i = n-d;
161                         p = a;
162                         memmove(p, rptr, i);
163                         memmove(p+i, f->alog->buf, d);
164                         break;
165                 }
166                 else
167                         spin_unlock(&f->alog->lock);
168
169                 rendez_sleep(&f->alog->r, netlogready, f);
170         }
171
172         qunlock(&f->alog->qlock);
173         poperror();
174
175         return n;
176 }
177
178 void
179 netlogctl(struct Fs *f, char* s, int n)
180 {
181         ERRSTACK(2);
182         int i, set = 0;
183         Netlogflag *fp;
184         struct cmdbuf *cb;
185         struct cmdtab *ct;
186
187         cb = parsecmd(s, n);
188         if(waserror()){
189                 kfree(cb);
190                 nexterror();
191         }
192
193         if(cb->nf < 2)
194                 error(Ebadnetctl);
195
196         ct = lookupcmd(cb, routecmd, ARRAY_SIZE(routecmd));
197
198         switch(ct->index){
199         case CMset:
200                 set = 1;
201                 break;
202
203         case CMclear:
204                 set = 0;
205                 break;
206
207         case CMonly:
208                 parseip(f->alog->iponly, cb->f[1]);
209                 if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
210                         f->alog->iponlyset = 0;
211                 else
212                         f->alog->iponlyset = 1;
213                 kfree(cb);
214                 return;
215
216         default:
217                 cmderror(cb, "unknown ip control message");
218         }
219
220         for(i = 1; i < cb->nf; i++){
221                 for(fp = flags; fp->name; fp++)
222                         if(strcmp(fp->name, cb->f[i]) == 0)
223                                 break;
224                 if(fp->name == NULL)
225                         continue;
226                 if(set)
227                         f->alog->logmask |= fp->mask;
228                 else
229                         f->alog->logmask &= ~fp->mask;
230         }
231
232         kfree(cb);
233         poperror();
234 }
235
236 void
237 netlog(struct Fs *f, int mask, char *fmt, ...)
238 {
239         char buf[128], *t, *fp;
240         int i, n;
241         va_list arg;
242
243         if(!(f->alog->logmask & mask))
244                 return;
245
246         if(f->alog->opens == 0)
247                 return;
248
249         va_start(arg, fmt);
250         n = snprintf(buf, sizeof(buf), fmt, arg);
251         va_end(arg);
252
253         spin_lock(&f->alog->lock);
254         i = f->alog->len + n - Nlog;
255         if(i > 0){
256                 f->alog->len -= i;
257                 f->alog->rptr += i;
258                 if(f->alog->rptr >= f->alog->end)
259                         f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
260         }
261         t = f->alog->rptr + f->alog->len;
262         fp = buf;
263         f->alog->len += n;
264         while(n-- > 0){
265                 if(t >= f->alog->end)
266                         t = f->alog->buf + (t - f->alog->end);
267                 *t++ = *fp++;
268         }
269         spin_unlock(&f->alog->lock);
270
271         rendez_wakeup(&f->alog->r);
272 }