![cinap_lenrek](/assets/img/avatar_default.png)
Fsprotocone(): qopen() and qbypass() can fail and return nil, so make sure the connection was not partially created by checking if read and write queues have been setup by the protocol create hanler. on error, free any resources of the partial connection and error out. netlogopen(): check malloc() error.
268 lines
4 KiB
C
268 lines
4 KiB
C
#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, },
|
|
{ "il", Logil, },
|
|
{ "tcp", Logtcp, },
|
|
{ "icmp", Logicmp, },
|
|
{ "udp", Logudp, },
|
|
{ "compress", Logcompress, },
|
|
{ "logilmsg", 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);
|
|
if(f->alog->buf == nil)
|
|
error(Enomem);
|
|
}
|
|
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);
|
|
poperror();
|
|
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);
|
|
}
|