summaryrefslogtreecommitdiff
path: root/os/ip/netlog.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/ip/netlog.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/ip/netlog.c')
-rw-r--r--os/ip/netlog.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/os/ip/netlog.c b/os/ip/netlog.c
new file mode 100644
index 00000000..3ee200fe
--- /dev/null
+++ b/os/ip/netlog.c
@@ -0,0 +1,263 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../ip/ip.h"
+
+enum {
+ Nlog = 4*1024,
+};
+
+/*
+ * action log
+ */
+struct Netlog {
+ Lock;
+ int opens;
+ char* buf;
+ char *end;
+ char *rptr;
+ int len;
+
+ int logmask; /* mask of things to debug */
+ uchar iponly[IPaddrlen]; /* ip address to print debugging for */
+ int iponlyset;
+
+ QLock;
+ Rendez;
+};
+
+typedef struct Netlogflag {
+ char* name;
+ int mask;
+} Netlogflag;
+
+static Netlogflag flags[] =
+{
+ { "ppp", Logppp, },
+ { "ip", Logip, },
+ { "fs", Logfs, },
+ { "tcp", Logtcp, },
+ { "il", Logil, },
+ { "icmp", Logicmp, },
+ { "udp", Logudp, },
+ { "compress", Logcompress, },
+ { "ilmsg", Logil|Logilmsg, },
+ { "gre", Loggre, },
+ { "tcpwin", Logtcp|Logtcpwin, },
+ { "tcprxmt", Logtcp|Logtcprxmt, },
+ { "udpmsg", Logudp|Logudpmsg, },
+ { "ipmsg", Logip|Logipmsg, },
+ { "esp", Logesp, },
+ { nil, 0, },
+};
+
+char Ebadnetctl[] = "too few arguments for netlog control message";
+
+enum
+{
+ CMset,
+ CMclear,
+ CMonly,
+};
+
+static
+Cmdtab routecmd[] = {
+ CMset, "set", 0,
+ CMclear, "clear", 0,
+ CMonly, "only", 0,
+};
+
+void
+netloginit(Fs *f)
+{
+ f->alog = smalloc(sizeof(Netlog));
+}
+
+void
+netlogopen(Fs *f)
+{
+ lock(f->alog);
+ if(waserror()){
+ unlock(f->alog);
+ nexterror();
+ }
+ if(f->alog->opens == 0){
+ if(f->alog->buf == nil)
+ f->alog->buf = malloc(Nlog);
+ f->alog->rptr = f->alog->buf;
+ f->alog->end = f->alog->buf + Nlog;
+ }
+ f->alog->opens++;
+ unlock(f->alog);
+ poperror();
+}
+
+void
+netlogclose(Fs *f)
+{
+ lock(f->alog);
+ if(waserror()){
+ unlock(f->alog);
+ nexterror();
+ }
+ f->alog->opens--;
+ if(f->alog->opens == 0){
+ free(f->alog->buf);
+ f->alog->buf = nil;
+ }
+ unlock(f->alog);
+ poperror();
+}
+
+static int
+netlogready(void *a)
+{
+ Fs *f = a;
+
+ return f->alog->len;
+}
+
+long
+netlogread(Fs *f, void *a, ulong, long n)
+{
+ int i, d;
+ char *p, *rptr;
+
+ qlock(f->alog);
+ if(waserror()){
+ qunlock(f->alog);
+ nexterror();
+ }
+
+ for(;;){
+ lock(f->alog);
+ if(f->alog->len){
+ if(n > f->alog->len)
+ n = f->alog->len;
+ d = 0;
+ rptr = f->alog->rptr;
+ f->alog->rptr += n;
+ if(f->alog->rptr >= f->alog->end){
+ d = f->alog->rptr - f->alog->end;
+ f->alog->rptr = f->alog->buf + d;
+ }
+ f->alog->len -= n;
+ unlock(f->alog);
+
+ i = n-d;
+ p = a;
+ memmove(p, rptr, i);
+ memmove(p+i, f->alog->buf, d);
+ break;
+ }
+ else
+ unlock(f->alog);
+
+ sleep(f->alog, netlogready, f);
+ }
+
+ qunlock(f->alog);
+ poperror();
+
+ return n;
+}
+
+void
+netlogctl(Fs *f, char* s, int n)
+{
+ int i, set;
+ Netlogflag *fp;
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ cb = parsecmd(s, n);
+ if(waserror()){
+ free(cb);
+ nexterror();
+ }
+
+ if(cb->nf < 2)
+ error(Ebadnetctl);
+
+ ct = lookupcmd(cb, routecmd, nelem(routecmd));
+
+ SET(set);
+
+ switch(ct->index){
+ case CMset:
+ set = 1;
+ break;
+
+ case CMclear:
+ set = 0;
+ break;
+
+ case CMonly:
+ parseip(f->alog->iponly, cb->f[1]);
+ if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
+ f->alog->iponlyset = 0;
+ else
+ f->alog->iponlyset = 1;
+ free(cb);
+ return;
+
+ default:
+ cmderror(cb, "unknown ip control message");
+ }
+
+ for(i = 1; i < cb->nf; i++){
+ for(fp = flags; fp->name; fp++)
+ if(strcmp(fp->name, cb->f[i]) == 0)
+ break;
+ if(fp->name == nil)
+ continue;
+ if(set)
+ f->alog->logmask |= fp->mask;
+ else
+ f->alog->logmask &= ~fp->mask;
+ }
+
+ free(cb);
+ poperror();
+}
+
+void
+netlog(Fs *f, int mask, char *fmt, ...)
+{
+ char buf[128], *t, *fp;
+ int i, n;
+ va_list arg;
+
+ if(!(f->alog->logmask & mask))
+ return;
+
+ if(f->alog->opens == 0)
+ return;
+
+ va_start(arg, fmt);
+ n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ lock(f->alog);
+ i = f->alog->len + n - Nlog;
+ if(i > 0){
+ f->alog->len -= i;
+ f->alog->rptr += i;
+ if(f->alog->rptr >= f->alog->end)
+ f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
+ }
+ t = f->alog->rptr + f->alog->len;
+ fp = buf;
+ f->alog->len += n;
+ while(n-- > 0){
+ if(t >= f->alog->end)
+ t = f->alog->buf + (t - f->alog->end);
+ *t++ = *fp++;
+ }
+ unlock(f->alog);
+
+ wakeup(f->alog);
+}