Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_tlsv12/sys/src/cmd/ratfs/ctlfiles.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "ratfs.h"
2
#include <ip.h>
3
 
4
enum {
5
	ACCEPT = 0,		/* verbs in control file */
6
	REFUSED,
7
	DENIED,
8
	DIALUP,
9
	BLOCKED,
10
	DELAY,
11
	NONE,
12
 
13
	Subchar	=	'#',	/* character substituted for '/' in file names */
14
};
15
 
16
static	Keyword actions[] = {
17
	"allow",		ACCEPT,
18
	"accept",		ACCEPT,
19
	"block",		BLOCKED,
20
	"deny",			DENIED,
21
	"dial",			DIALUP,
22
	"relay",		DELAY,
23
	"delay",		DELAY,
24
	0,			NONE,
25
};
26
 
27
static void	acctinsert(Node*, char*);
28
static char*	getline(Biobuf*);
29
static void	ipinsert(Node*, char*);
30
static void	ipsort(void);
31
 
32
/*
33
 *	Input the configuration file
34
 *	Currently we only process the "ournets"
35
 *	specification.
36
 */
37
void
38
getconf(void)
39
{
40
	Biobuf *bp;
41
	char *cp;
42
	Node *np, *dir, **l;
43
 
44
	if(debugfd >= 0)
45
		fprint(debugfd, "loading %s\n", conffile);
46
 
47
	bp = Bopen(conffile, OREAD);
48
	if(bp == 0)
49
		return;
50
 
51
	dir = finddir(Trusted);
52
	if(dir == 0)
53
		return;
54
 
55
	/*
56
	 * if this isn't the first time, purge permanent entries
57
	 */
58
	trustedqid = Qtrustedfile;
59
	if(lastconftime){
60
		l = &dir->children;
61
		for(np = dir->children; np; np = *l){
62
			if(np->d.type == Trustedperm){
63
				*l = np->sibs;
64
				free(np);
65
			} else {
66
				np->d.qid.path = trustedqid++;
67
				l = &np->sibs;
68
			}
69
		}
70
		dir->count = 0;
71
	}
72
 
73
	for(;;){
74
		cp = getline(bp);
75
		if(cp == 0)
76
			break;
77
		if (strcmp(cp, "ournets") == 0){
78
			for(cp += strlen(cp)+1; cp && *cp; cp += strlen(cp)+1){
79
				np = newnode(dir, cp, Trustedperm, 0111, trustedqid++);
80
				cidrparse(&np->ip, cp);
81
				subslash(cp);
82
				np->d.name = atom(cp);
83
			}
84
		}
85
	}
86
	Bterm(bp);
87
	lastconftime = time(0);
88
}
89
 
90
/*
91
 *	Reload the control file, if necessary
92
 */
93
void
94
reload(void)
95
{
96
	int type, action;
97
	Biobuf *bp;
98
	char *cp;
99
	Node *np, *dir;
100
 
101
	if(debugfd >= 0)
102
		fprint(debugfd,"loading %s\n", ctlfile);
103
 
104
	bp = Bopen(ctlfile, OREAD);
105
	if(bp == 0)
106
		return;
107
 
108
	if(lastctltime){
109
		for(dir = root->children; dir; dir = dir->sibs){
110
			if (dir->d.type != Addrdir)
111
				continue;
112
			for(np = dir->children; np; np = np->sibs)
113
				np->count = 0;
114
		}
115
	}
116
 
117
	for(;;){
118
		cp = getline(bp);
119
		if(cp == 0)
120
			break;
121
		type = *cp;
122
		if(type == '*'){
123
			cp++;
124
			if(*cp == 0)		/* space before keyword */
125
				cp++;
126
		}
127
		action = findkey(cp, actions);
128
		if (action == NONE)
129
			continue;
130
		if (action == ACCEPT)
131
			dir = dirwalk("allow", root);
132
		else
133
		if (action == DELAY)
134
			dir = dirwalk("delay", root);
135
		else
136
			dir = dirwalk(cp, root);
137
		if(dir == 0)
138
			continue;
139
 
140
		for(cp += strlen(cp)+1; cp && *cp; cp += strlen(cp)+1){
141
			if(type == '*')
142
				acctinsert(dir, cp);
143
			else
144
				ipinsert(dir, cp);
145
		}
146
	}
147
	Bterm(bp);
148
	ipsort();
149
	dummy.d.mtime = dummy.d.atime = lastctltime = time(0);
150
}
151
 
152
/*
153
 * get a canonicalized line: a string of null-terminated lower-case
154
 * tokens with a two null bytes at the end.
155
 */
156
static char*
157
getline(Biobuf *bp)
158
{
159
	char c, *cp, *p, *q;
160
	int n;
161
 
162
	static char *buf;
163
	static int bufsize;
164
 
165
	for(;;){
166
		cp = Brdline(bp, '\n');
167
		if(cp == 0)
168
			return 0;
169
		n = Blinelen(bp);
170
		cp[n-1] = 0;
171
		if(buf == 0 || bufsize < n+1){
172
			bufsize += 512;
173
			if(bufsize < n+1)
174
				bufsize = n+1;
175
			buf = realloc(buf, bufsize);
176
			if(buf == 0)
177
				break;
178
		}
179
		q = buf;
180
		for (p = cp; *p; p++){
181
			c = *p;
182
			if(c == '\\' && p[1])	/* we don't allow \<newline> */
183
				c = *++p;
184
			else
185
			if(c == '#')
186
				break;
187
			else
188
			if(c == ' ' || c == '\t' || c == ',')
189
				if(q == buf || q[-1] == 0)
190
					continue;
191
				else
192
					c = 0;
193
			*q++ = tolower(c);
194
		}
195
		if(q != buf){
196
			if(q[-1])
197
				*q++ = 0;
198
			*q = 0;
199
			break;
200
		}
201
	}
202
	return buf;
203
}
204
 
205
/*
206
 *	Match a keyword
207
 */
208
int
209
findkey(char *val, Keyword *p)
210
{
211
 
212
	for(; p->name; p++)
213
		if(strcmp(val, p->name) == 0)
214
				break;
215
	return p->code;
216
}
217
 
218
/*
219
 *	parse a cidr specification in either IP/mask or IP#mask format
220
 */
221
void
222
cidrparse(Cidraddr *cidr, char *cp)
223
{
224
 
225
	char *p, *slash;
226
	int c;
227
	ulong a, m;
228
	uchar addr[IPv4addrlen];
229
	uchar mask[IPv4addrlen];
230
	char buf[64];
231
 
232
	/*
233
	 * find '/' or '#' character in the cidr specification
234
	 */
235
	slash = 0;
236
	for(p = buf; p < buf+sizeof(buf)-1 && *cp; p++) {
237
		c = *cp++;
238
		switch(c) {
239
		case Subchar:
240
			c = '/';
241
			slash = p;
242
			break;
243
		case '/':
244
			slash = p;
245
			break;
246
		default:
247
			break;
248
		}
249
		*p = c;
250
	}
251
	*p = 0;
252
 
253
	v4parsecidr(addr, mask, buf);
254
	a = nhgetl(addr);
255
	m = nhgetl(mask);
256
	/*
257
	 * if a mask isn't specified, we build a minimal mask
258
	 * instead of using the default mask for that net.  in this
259
	 * case we never allow a class A mask (0xff000000).
260
	 */
261
	if(slash == 0){
262
		m = 0xff000000;
263
		p = buf;
264
		for(p = strchr(p, '.'); p && p[1]; p = strchr(p+1, '.'))
265
				m = (m>>8)|0xff000000;
266
 
267
		/* force at least a class B */
268
		m |= 0xffff0000;
269
	}
270
	cidr->ipaddr = a;
271
	cidr->mask = m;
272
}
273
 
274
/*
275
 *	Substitute Subchar ('#') for '/'
276
 */
277
char*
278
subslash(char *os)
279
{
280
	char *s;
281
 
282
	for(s=os; *s; s++)
283
		if(*s == '/')
284
			*s = Subchar;
285
	return os;
286
}
287
 
288
/*
289
 *	Insert an account pseudo-file in a directory
290
 */
291
static void
292
acctinsert(Node *np, char *cp)
293
{
294
	int i;
295
	char *tmp;
296
	Address *ap;
297
 
298
	static char *dangerous[] = { "*", "!", "*!", "!*", "*!*", 0 };
299
 
300
	if(cp == 0 || *cp == 0)
301
		return;
302
 
303
	/* rule out dangerous patterns */
304
	for (i = 0; dangerous[i]; i++)
305
		if(strcmp(cp, dangerous[i])== 0)
306
			return;
307
 
308
	np = dirwalk("account", np);
309
	if(np == 0)
310
		return;
311
 
312
	i = np->count++;
313
	if(i >= np->allocated){
314
		np->allocated = np->count;
315
		np->addrs = realloc(np->addrs, np->allocated*sizeof(Address));
316
		if(np->addrs == 0)
317
			fatal("out of memory");
318
	}
319
 
320
	ap = &np->addrs[i];			/* new entry on end */
321
	tmp = strdup(cp);
322
	if(tmp == nil)
323
		fatal("out of memory");
324
	subslash(tmp);
325
	ap->name = atom(tmp);
326
	free(tmp);
327
}
328
 
329
/*
330
 *	Insert an IP address pseudo-file in a directory
331
 */
332
static void
333
ipinsert(Node *np, char *cp)
334
{
335
	char *tmp;
336
	int i;
337
	Address *ap;
338
	if(cp == 0 || *cp == 0)
339
		return;
340
 
341
	np = dirwalk("ip", np);
342
	if(np == 0)
343
		return;
344
 
345
	i = np->count++;
346
	if(i >= np->allocated){
347
		np->allocated = np->count;
348
		np->addrs = realloc(np->addrs, np->allocated*sizeof(Address));
349
		if(np->addrs == 0)
350
			fatal("out of memory");
351
	}
352
 
353
	ap = &np->addrs[i];				/* new entry on end */
354
	tmp = strdup(cp);
355
	if(tmp == nil)
356
		fatal("out of memory");
357
	subslash(tmp);
358
	ap->name = atom(tmp);
359
	free(tmp);
360
	cidrparse(&ap->ip, cp);
361
}
362
 
363
int
364
ipcomp(void *a, void *b)
365
{
366
	ulong aip, bip;
367
 
368
	aip = ((Address*)a)->ip.ipaddr;
369
	bip = ((Address*)b)->ip.ipaddr;
370
	if(aip > bip)
371
		return 1;
372
	if(aip < bip)
373
		return -1;
374
	return 0;
375
}
376
 
377
/*
378
 *	Sort a directory of IP addresses
379
 */
380
static void
381
ipsort(void)
382
{
383
	int base;
384
	Node *dir, *np;
385
 
386
	base = Qaddrfile;
387
	for(dir = root->children; dir; dir = dir->sibs){
388
		if (dir->d.type != Addrdir)
389
			continue;
390
		for(np = dir->children; np; np = np->sibs){
391
			if(np->d.type == IPaddr && np->count && np->addrs)
392
				qsort(np->addrs, np->count, sizeof(Address), ipcomp);
393
			np->baseqid = base;
394
			base += np->count;
395
		}
396
	}
397
}