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