vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

netlog.c (3969B)


      1 #include	"u.h"
      2 #include	"lib.h"
      3 #include	"mem.h"
      4 #include	"dat.h"
      5 #include	"fns.h"
      6 #include	"error.h"
      7 #include	"ip/ip.h"
      8 
      9 enum {
     10 	Nlog		= 16*1024,
     11 };
     12 
     13 /*
     14  *  action log
     15  */
     16 struct Netlog {
     17 	Lock	lk;
     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	qlock;
     29 	Rendez	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 	{ "icmp",	Logicmp, },
     44 	{ "udp",	Logudp, },
     45 	{ "compress",	Logcompress, },
     46 	{ "gre",	Loggre, },
     47 	{ "tcpwin",	Logtcp|Logtcpwin, },
     48 	{ "tcprxmt",	Logtcp|Logtcprxmt, },
     49 	{ "udpmsg",	Logudp|Logudpmsg, },
     50 	{ "ipmsg",	Logip|Logipmsg, },
     51 	{ "esp",	Logesp, },
     52 	{ nil,		0, },
     53 };
     54 
     55 char Ebadnetctl[] = "too few arguments for netlog control message";
     56 
     57 enum
     58 {
     59 	CMset,
     60 	CMclear,
     61 	CMonly,
     62 };
     63 
     64 static
     65 Cmdtab routecmd[] = {
     66 	CMset,		"set",		0,
     67 	CMclear,	"clear",	0,
     68 	CMonly,		"only",		0,
     69 };
     70 
     71 void
     72 netloginit(Fs *f)
     73 {
     74 	f->alog = smalloc(sizeof(Netlog));
     75 }
     76 
     77 void
     78 netlogopen(Fs *f)
     79 {
     80 	LOCK(f->alog);
     81 	if(waserror()){
     82 		UNLOCK(f->alog);
     83 		nexterror();
     84 	}
     85 	if(f->alog->opens == 0){
     86 		if(f->alog->buf == nil)
     87 			f->alog->buf = malloc(Nlog);
     88 		f->alog->rptr = f->alog->buf;
     89 		f->alog->end = f->alog->buf + Nlog;
     90 	}
     91 	f->alog->opens++;
     92 	UNLOCK(f->alog);
     93 	poperror();
     94 }
     95 
     96 void
     97 netlogclose(Fs *f)
     98 {
     99 	LOCK(f->alog);
    100 	if(waserror()){
    101 		UNLOCK(f->alog);
    102 		nexterror();
    103 	}
    104 	f->alog->opens--;
    105 	if(f->alog->opens == 0){
    106 		free(f->alog->buf);
    107 		f->alog->buf = nil;
    108 	}
    109 	UNLOCK(f->alog);
    110 	poperror();
    111 }
    112 
    113 static int
    114 netlogready(void *a)
    115 {
    116 	Fs *f = a;
    117 
    118 	return f->alog->len;
    119 }
    120 
    121 long
    122 netlogread(Fs *f, void *a, ulong _, long n)
    123 {
    124 	int i, d;
    125 	char *p, *rptr;
    126 
    127 	QLOCK(f->alog);
    128 	if(waserror()){
    129 		QUNLOCK(f->alog);
    130 		nexterror();
    131 	}
    132 
    133 	for(;;){
    134 		LOCK(f->alog);
    135 		if(f->alog->len){
    136 			if(n > f->alog->len)
    137 				n = f->alog->len;
    138 			d = 0;
    139 			rptr = f->alog->rptr;
    140 			f->alog->rptr += n;
    141 			if(f->alog->rptr >= f->alog->end){
    142 				d = f->alog->rptr - f->alog->end;
    143 				f->alog->rptr = f->alog->buf + d;
    144 			}
    145 			f->alog->len -= n;
    146 			UNLOCK(f->alog);
    147 
    148 			i = n-d;
    149 			p = a;
    150 			memmove(p, rptr, i);
    151 			memmove(p+i, f->alog->buf, d);
    152 			break;
    153 		}
    154 		else
    155 			UNLOCK(f->alog);
    156 
    157 		sleep(&f->alog->rendez, netlogready, f);
    158 	}
    159 
    160 	QUNLOCK(f->alog);
    161 	poperror();
    162 
    163 	return n;
    164 }
    165 
    166 void
    167 netlogctl(Fs *f, char* s, int n)
    168 {
    169 	int i, set;
    170 	Netlogflag *fp;
    171 	Cmdbuf *cb;
    172 	Cmdtab *ct;
    173 
    174 	cb = parsecmd(s, n);
    175 	if(waserror()){
    176 		free(cb);
    177 		nexterror();
    178 	}
    179 
    180 	if(cb->nf < 2)
    181 		error(Ebadnetctl);
    182 
    183 	ct = lookupcmd(cb, routecmd, nelem(routecmd));
    184 
    185 	set = 1;
    186 
    187 	switch(ct->index){
    188 	case CMset:
    189 		set = 1;
    190 		break;
    191 
    192 	case CMclear:
    193 		set = 0;
    194 		break;
    195 
    196 	case CMonly:
    197 		parseip(f->alog->iponly, cb->f[1]);
    198 		if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
    199 			f->alog->iponlyset = 0;
    200 		else
    201 			f->alog->iponlyset = 1;
    202 		free(cb);
    203 		return;
    204 
    205 	default:
    206 		cmderror(cb, "unknown ip control message");
    207 	}
    208 
    209 	for(i = 1; i < cb->nf; i++){
    210 		for(fp = flags; fp->name; fp++)
    211 			if(strcmp(fp->name, cb->f[i]) == 0)
    212 				break;
    213 		if(fp->name == nil)
    214 			continue;
    215 		if(set)
    216 			f->alog->logmask |= fp->mask;
    217 		else
    218 			f->alog->logmask &= ~fp->mask;
    219 	}
    220 
    221 	free(cb);
    222 	poperror();
    223 }
    224 
    225 void
    226 netlog(Fs *f, int mask, char *fmt, ...)
    227 {
    228 	char buf[128], *t, *fp;
    229 	int i, n;
    230 	va_list arg;
    231 
    232 	if(!(f->alog->logmask & mask))
    233 		return;
    234 
    235 	if(f->alog->opens == 0)
    236 		return;
    237 
    238 	va_start(arg, fmt);
    239 	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
    240 	va_end(arg);
    241 
    242 	LOCK(f->alog);
    243 	i = f->alog->len + n - Nlog;
    244 	if(i > 0){
    245 		f->alog->len -= i;
    246 		f->alog->rptr += i;
    247 		if(f->alog->rptr >= f->alog->end)
    248 			f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
    249 	}
    250 	t = f->alog->rptr + f->alog->len;
    251 	fp = buf;
    252 	f->alog->len += n;
    253 	while(n-- > 0){
    254 		if(t >= f->alog->end)
    255 			t = f->alog->buf + (t - f->alog->end);
    256 		*t++ = *fp++;
    257 	}
    258 	UNLOCK(f->alog);
    259 
    260 	wakeup(&f->alog->rendez);
    261 }