Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"u.h"
2
#include	"../port/lib.h"
3
#include	"mem.h"
4
#include	"dat.h"
5
#include	"fns.h"
6
#include	"../port/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;
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;
29
	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
		if(f->alog->buf == nil)
89
			error(Enomem);
90
		f->alog->rptr = f->alog->buf;
91
		f->alog->end = f->alog->buf + Nlog;
92
	}
93
	f->alog->opens++;
94
	unlock(f->alog);
95
	poperror();
96
}
97
 
98
void
99
netlogclose(Fs *f)
100
{
101
	lock(f->alog);
102
	if(waserror()){
103
		unlock(f->alog);
104
		nexterror();
105
	}
106
	f->alog->opens--;
107
	if(f->alog->opens == 0){
108
		free(f->alog->buf);
109
		f->alog->buf = nil;
110
	}
111
	unlock(f->alog);
112
	poperror();
113
}
114
 
115
static int
116
netlogready(void *a)
117
{
118
	Fs *f = a;
119
 
120
	return f->alog->len;
121
}
122
 
123
long
124
netlogread(Fs *f, void *a, ulong, long n)
125
{
126
	int i, d;
127
	char *p, *rptr;
128
 
129
	qlock(f->alog);
130
	if(waserror()){
131
		qunlock(f->alog);
132
		nexterror();
133
	}
134
 
135
	for(;;){
136
		lock(f->alog);
137
		if(f->alog->len){
138
			if(n > f->alog->len)
139
				n = f->alog->len;
140
			d = 0;
141
			rptr = f->alog->rptr;
142
			f->alog->rptr += n;
143
			if(f->alog->rptr >= f->alog->end){
144
				d = f->alog->rptr - f->alog->end;
145
				f->alog->rptr = f->alog->buf + d;
146
			}
147
			f->alog->len -= n;
148
			unlock(f->alog);
149
 
150
			i = n-d;
151
			p = a;
152
			memmove(p, rptr, i);
153
			memmove(p+i, f->alog->buf, d);
154
			break;
155
		}
156
		else
157
			unlock(f->alog);
158
 
159
		sleep(f->alog, netlogready, f);
160
	}
161
 
162
	qunlock(f->alog);
163
	poperror();
164
 
165
	return n;
166
}
167
 
168
void
169
netlogctl(Fs *f, char* s, int n)
170
{
171
	int i, set;
172
	Netlogflag *fp;
173
	Cmdbuf *cb;
174
	Cmdtab *ct;
175
 
176
	cb = parsecmd(s, n);
177
	if(waserror()){
178
		free(cb);
179
		nexterror();
180
	}
181
 
182
	if(cb->nf < 2)
183
		error(Ebadnetctl);
184
 
185
	ct = lookupcmd(cb, routecmd, nelem(routecmd));
186
 
187
	SET(set);
188
 
189
	switch(ct->index){
190
	case CMset:
191
		set = 1;
192
		break;
193
 
194
	case CMclear:
195
		set = 0;
196
		break;
197
 
198
	case CMonly:
199
		parseip(f->alog->iponly, cb->f[1]);
200
		if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
201
			f->alog->iponlyset = 0;
202
		else
203
			f->alog->iponlyset = 1;
204
		free(cb);
205
		poperror();
206
		return;
207
 
208
	default:
209
		cmderror(cb, "unknown netlog control message");
210
	}
211
 
212
	for(i = 1; i < cb->nf; i++){
213
		for(fp = flags; fp->name; fp++)
214
			if(strcmp(fp->name, cb->f[i]) == 0)
215
				break;
216
		if(fp->name == nil)
217
			continue;
218
		if(set)
219
			f->alog->logmask |= fp->mask;
220
		else
221
			f->alog->logmask &= ~fp->mask;
222
	}
223
 
224
	free(cb);
225
	poperror();
226
}
227
 
228
void
229
netlog(Fs *f, int mask, char *fmt, ...)
230
{
231
	char buf[256], *t, *fp;
232
	int i, n;
233
	va_list arg;
234
 
235
	if(!(f->alog->logmask & mask))
236
		return;
237
 
238
	if(f->alog->opens == 0)
239
		return;
240
 
241
	va_start(arg, fmt);
242
	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
243
	va_end(arg);
244
 
245
	lock(f->alog);
246
	i = f->alog->len + n - Nlog;
247
	if(i > 0){
248
		f->alog->len -= i;
249
		f->alog->rptr += i;
250
		if(f->alog->rptr >= f->alog->end)
251
			f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
252
	}
253
	t = f->alog->rptr + f->alog->len;
254
	fp = buf;
255
	f->alog->len += n;
256
	while(n-- > 0){
257
		if(t >= f->alog->end)
258
			t = f->alog->buf + (t - f->alog->end);
259
		*t++ = *fp++;
260
	}
261
	unlock(f->alog);
262
 
263
	wakeup(f->alog);
264
}