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