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 } 264