netlog.c (3969B)
1 #include "u.h" 2 #include "lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "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 lk; 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 qlock; 29 Rendez 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->rendez, 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 = 1; 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->rendez); 261 }