2011-03-30 12:46:40 +00:00
|
|
|
#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 = 16*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, },
|
2012-05-03 08:47:40 +00:00
|
|
|
{ "il", Logil, },
|
2011-03-30 12:46:40 +00:00
|
|
|
{ "tcp", Logtcp, },
|
|
|
|
{ "icmp", Logicmp, },
|
|
|
|
{ "udp", Logudp, },
|
|
|
|
{ "compress", Logcompress, },
|
2012-05-03 08:47:40 +00:00
|
|
|
{ "logilmsg", Logilmsg, },
|
2011-03-30 12:46:40 +00:00
|
|
|
{ "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);
|
2012-02-13 04:56:47 +00:00
|
|
|
poperror();
|
2011-03-30 12:46:40 +00:00
|
|
|
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[256], *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);
|
|
|
|
}
|