17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "../port/error.h"
77dd7cddfSDavid du Colombier #include "../ip/ip.h"
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier enum {
10f2c197d9SDavid du Colombier Nlog = 16*1024,
117dd7cddfSDavid du Colombier };
127dd7cddfSDavid du Colombier
137dd7cddfSDavid du Colombier /*
147dd7cddfSDavid du Colombier * action log
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier struct Netlog {
177dd7cddfSDavid du Colombier Lock;
187dd7cddfSDavid du Colombier int opens;
197dd7cddfSDavid du Colombier char* buf;
207dd7cddfSDavid du Colombier char *end;
217dd7cddfSDavid du Colombier char *rptr;
227dd7cddfSDavid du Colombier int len;
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier int logmask; /* mask of things to debug */
257dd7cddfSDavid du Colombier uchar iponly[IPaddrlen]; /* ip address to print debugging for */
267dd7cddfSDavid du Colombier int iponlyset;
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier QLock;
297dd7cddfSDavid du Colombier Rendez;
307dd7cddfSDavid du Colombier };
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier typedef struct Netlogflag {
337dd7cddfSDavid du Colombier char* name;
347dd7cddfSDavid du Colombier int mask;
357dd7cddfSDavid du Colombier } Netlogflag;
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier static Netlogflag flags[] =
387dd7cddfSDavid du Colombier {
397dd7cddfSDavid du Colombier { "ppp", Logppp, },
407dd7cddfSDavid du Colombier { "ip", Logip, },
417dd7cddfSDavid du Colombier { "fs", Logfs, },
427dd7cddfSDavid du Colombier { "tcp", Logtcp, },
437dd7cddfSDavid du Colombier { "icmp", Logicmp, },
447dd7cddfSDavid du Colombier { "udp", Logudp, },
457dd7cddfSDavid du Colombier { "compress", Logcompress, },
467dd7cddfSDavid du Colombier { "gre", Loggre, },
473ff48bf5SDavid du Colombier { "tcpwin", Logtcp|Logtcpwin, },
483ff48bf5SDavid du Colombier { "tcprxmt", Logtcp|Logtcprxmt, },
497dd7cddfSDavid du Colombier { "udpmsg", Logudp|Logudpmsg, },
507dd7cddfSDavid du Colombier { "ipmsg", Logip|Logipmsg, },
517dd7cddfSDavid du Colombier { "esp", Logesp, },
527dd7cddfSDavid du Colombier { nil, 0, },
537dd7cddfSDavid du Colombier };
547dd7cddfSDavid du Colombier
559a747e4fSDavid du Colombier char Ebadnetctl[] = "too few arguments for netlog control message";
569a747e4fSDavid du Colombier
579a747e4fSDavid du Colombier enum
589a747e4fSDavid du Colombier {
599a747e4fSDavid du Colombier CMset,
609a747e4fSDavid du Colombier CMclear,
619a747e4fSDavid du Colombier CMonly,
629a747e4fSDavid du Colombier };
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier static
659a747e4fSDavid du Colombier Cmdtab routecmd[] = {
669a747e4fSDavid du Colombier CMset, "set", 0,
679a747e4fSDavid du Colombier CMclear, "clear", 0,
689a747e4fSDavid du Colombier CMonly, "only", 0,
699a747e4fSDavid du Colombier };
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier void
netloginit(Fs * f)727dd7cddfSDavid du Colombier netloginit(Fs *f)
737dd7cddfSDavid du Colombier {
747dd7cddfSDavid du Colombier f->alog = smalloc(sizeof(Netlog));
757dd7cddfSDavid du Colombier }
767dd7cddfSDavid du Colombier
777dd7cddfSDavid du Colombier void
netlogopen(Fs * f)787dd7cddfSDavid du Colombier netlogopen(Fs *f)
797dd7cddfSDavid du Colombier {
807dd7cddfSDavid du Colombier lock(f->alog);
817dd7cddfSDavid du Colombier if(waserror()){
827dd7cddfSDavid du Colombier unlock(f->alog);
837dd7cddfSDavid du Colombier nexterror();
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier if(f->alog->opens == 0){
867dd7cddfSDavid du Colombier if(f->alog->buf == nil)
877dd7cddfSDavid du Colombier f->alog->buf = malloc(Nlog);
88aa72973aSDavid du Colombier if(f->alog->buf == nil)
89aa72973aSDavid du Colombier error(Enomem);
907dd7cddfSDavid du Colombier f->alog->rptr = f->alog->buf;
917dd7cddfSDavid du Colombier f->alog->end = f->alog->buf + Nlog;
927dd7cddfSDavid du Colombier }
937dd7cddfSDavid du Colombier f->alog->opens++;
947dd7cddfSDavid du Colombier unlock(f->alog);
957dd7cddfSDavid du Colombier poperror();
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier
987dd7cddfSDavid du Colombier void
netlogclose(Fs * f)997dd7cddfSDavid du Colombier netlogclose(Fs *f)
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier lock(f->alog);
1027dd7cddfSDavid du Colombier if(waserror()){
1037dd7cddfSDavid du Colombier unlock(f->alog);
1047dd7cddfSDavid du Colombier nexterror();
1057dd7cddfSDavid du Colombier }
1067dd7cddfSDavid du Colombier f->alog->opens--;
1077dd7cddfSDavid du Colombier if(f->alog->opens == 0){
1087dd7cddfSDavid du Colombier free(f->alog->buf);
1097dd7cddfSDavid du Colombier f->alog->buf = nil;
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier unlock(f->alog);
1127dd7cddfSDavid du Colombier poperror();
1137dd7cddfSDavid du Colombier }
1147dd7cddfSDavid du Colombier
1157dd7cddfSDavid du Colombier static int
netlogready(void * a)1167dd7cddfSDavid du Colombier netlogready(void *a)
1177dd7cddfSDavid du Colombier {
1187dd7cddfSDavid du Colombier Fs *f = a;
1197dd7cddfSDavid du Colombier
1207dd7cddfSDavid du Colombier return f->alog->len;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier
1237dd7cddfSDavid du Colombier long
netlogread(Fs * f,void * a,ulong,long n)1247dd7cddfSDavid du Colombier netlogread(Fs *f, void *a, ulong, long n)
1257dd7cddfSDavid du Colombier {
1267dd7cddfSDavid du Colombier int i, d;
1277dd7cddfSDavid du Colombier char *p, *rptr;
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier qlock(f->alog);
1307dd7cddfSDavid du Colombier if(waserror()){
1317dd7cddfSDavid du Colombier qunlock(f->alog);
1327dd7cddfSDavid du Colombier nexterror();
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier
1357dd7cddfSDavid du Colombier for(;;){
1367dd7cddfSDavid du Colombier lock(f->alog);
1377dd7cddfSDavid du Colombier if(f->alog->len){
1387dd7cddfSDavid du Colombier if(n > f->alog->len)
1397dd7cddfSDavid du Colombier n = f->alog->len;
1407dd7cddfSDavid du Colombier d = 0;
1417dd7cddfSDavid du Colombier rptr = f->alog->rptr;
1427dd7cddfSDavid du Colombier f->alog->rptr += n;
1437dd7cddfSDavid du Colombier if(f->alog->rptr >= f->alog->end){
1447dd7cddfSDavid du Colombier d = f->alog->rptr - f->alog->end;
1457dd7cddfSDavid du Colombier f->alog->rptr = f->alog->buf + d;
1467dd7cddfSDavid du Colombier }
1477dd7cddfSDavid du Colombier f->alog->len -= n;
1487dd7cddfSDavid du Colombier unlock(f->alog);
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier i = n-d;
1517dd7cddfSDavid du Colombier p = a;
1527dd7cddfSDavid du Colombier memmove(p, rptr, i);
1537dd7cddfSDavid du Colombier memmove(p+i, f->alog->buf, d);
1547dd7cddfSDavid du Colombier break;
1557dd7cddfSDavid du Colombier }
1567dd7cddfSDavid du Colombier else
1577dd7cddfSDavid du Colombier unlock(f->alog);
1587dd7cddfSDavid du Colombier
1597dd7cddfSDavid du Colombier sleep(f->alog, netlogready, f);
1607dd7cddfSDavid du Colombier }
1617dd7cddfSDavid du Colombier
1627dd7cddfSDavid du Colombier qunlock(f->alog);
1637dd7cddfSDavid du Colombier poperror();
1647dd7cddfSDavid du Colombier
1657dd7cddfSDavid du Colombier return n;
1667dd7cddfSDavid du Colombier }
1677dd7cddfSDavid du Colombier
1689a747e4fSDavid du Colombier void
netlogctl(Fs * f,char * s,int n)1699a747e4fSDavid du Colombier netlogctl(Fs *f, char* s, int n)
1707dd7cddfSDavid du Colombier {
1719a747e4fSDavid du Colombier int i, set;
1727dd7cddfSDavid du Colombier Netlogflag *fp;
1739a747e4fSDavid du Colombier Cmdbuf *cb;
1749a747e4fSDavid du Colombier Cmdtab *ct;
1757dd7cddfSDavid du Colombier
1769a747e4fSDavid du Colombier cb = parsecmd(s, n);
1779a747e4fSDavid du Colombier if(waserror()){
1789a747e4fSDavid du Colombier free(cb);
1799a747e4fSDavid du Colombier nexterror();
1809a747e4fSDavid du Colombier }
1817dd7cddfSDavid du Colombier
1829a747e4fSDavid du Colombier if(cb->nf < 2)
1839a747e4fSDavid du Colombier error(Ebadnetctl);
1847dd7cddfSDavid du Colombier
1859a747e4fSDavid du Colombier ct = lookupcmd(cb, routecmd, nelem(routecmd));
1867dd7cddfSDavid du Colombier
1879a747e4fSDavid du Colombier SET(set);
1889a747e4fSDavid du Colombier
1899a747e4fSDavid du Colombier switch(ct->index){
1909a747e4fSDavid du Colombier case CMset:
1917dd7cddfSDavid du Colombier set = 1;
1929a747e4fSDavid du Colombier break;
1939a747e4fSDavid du Colombier
1949a747e4fSDavid du Colombier case CMclear:
1957dd7cddfSDavid du Colombier set = 0;
1969a747e4fSDavid du Colombier break;
1979a747e4fSDavid du Colombier
1989a747e4fSDavid du Colombier case CMonly:
1999a747e4fSDavid du Colombier parseip(f->alog->iponly, cb->f[1]);
2007dd7cddfSDavid du Colombier if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
2017dd7cddfSDavid du Colombier f->alog->iponlyset = 0;
2027dd7cddfSDavid du Colombier else
2037dd7cddfSDavid du Colombier f->alog->iponlyset = 1;
2049a747e4fSDavid du Colombier free(cb);
205*00d97012SDavid du Colombier poperror();
2069a747e4fSDavid du Colombier return;
2077dd7cddfSDavid du Colombier
2089a747e4fSDavid du Colombier default:
209*00d97012SDavid du Colombier cmderror(cb, "unknown netlog control message");
2109a747e4fSDavid du Colombier }
2117dd7cddfSDavid du Colombier
2129a747e4fSDavid du Colombier for(i = 1; i < cb->nf; i++){
2137dd7cddfSDavid du Colombier for(fp = flags; fp->name; fp++)
2149a747e4fSDavid du Colombier if(strcmp(fp->name, cb->f[i]) == 0)
2157dd7cddfSDavid du Colombier break;
2167dd7cddfSDavid du Colombier if(fp->name == nil)
2177dd7cddfSDavid du Colombier continue;
2187dd7cddfSDavid du Colombier if(set)
2197dd7cddfSDavid du Colombier f->alog->logmask |= fp->mask;
2207dd7cddfSDavid du Colombier else
2217dd7cddfSDavid du Colombier f->alog->logmask &= ~fp->mask;
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier
2249a747e4fSDavid du Colombier free(cb);
2259a747e4fSDavid du Colombier poperror();
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier
2287dd7cddfSDavid du Colombier void
netlog(Fs * f,int mask,char * fmt,...)2297dd7cddfSDavid du Colombier netlog(Fs *f, int mask, char *fmt, ...)
2307dd7cddfSDavid du Colombier {
231c6569576SDavid du Colombier char buf[256], *t, *fp;
2327dd7cddfSDavid du Colombier int i, n;
2337dd7cddfSDavid du Colombier va_list arg;
2347dd7cddfSDavid du Colombier
2357dd7cddfSDavid du Colombier if(!(f->alog->logmask & mask))
2367dd7cddfSDavid du Colombier return;
2377dd7cddfSDavid du Colombier
2387dd7cddfSDavid du Colombier if(f->alog->opens == 0)
2397dd7cddfSDavid du Colombier return;
2407dd7cddfSDavid du Colombier
2419a747e4fSDavid du Colombier va_start(arg, fmt);
2429a747e4fSDavid du Colombier n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
2439a747e4fSDavid du Colombier va_end(arg);
2449a747e4fSDavid du Colombier
2457dd7cddfSDavid du Colombier lock(f->alog);
2467dd7cddfSDavid du Colombier i = f->alog->len + n - Nlog;
2477dd7cddfSDavid du Colombier if(i > 0){
2487dd7cddfSDavid du Colombier f->alog->len -= i;
2497dd7cddfSDavid du Colombier f->alog->rptr += i;
2507dd7cddfSDavid du Colombier if(f->alog->rptr >= f->alog->end)
2517dd7cddfSDavid du Colombier f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
2527dd7cddfSDavid du Colombier }
2537dd7cddfSDavid du Colombier t = f->alog->rptr + f->alog->len;
2547dd7cddfSDavid du Colombier fp = buf;
2557dd7cddfSDavid du Colombier f->alog->len += n;
2567dd7cddfSDavid du Colombier while(n-- > 0){
2577dd7cddfSDavid du Colombier if(t >= f->alog->end)
2587dd7cddfSDavid du Colombier t = f->alog->buf + (t - f->alog->end);
2597dd7cddfSDavid du Colombier *t++ = *fp++;
2607dd7cddfSDavid du Colombier }
2617dd7cddfSDavid du Colombier unlock(f->alog);
2627dd7cddfSDavid du Colombier
2637dd7cddfSDavid du Colombier wakeup(f->alog);
2647dd7cddfSDavid du Colombier }
265