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-vt/sys/src/libndb/ndbipinfo.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 <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <ndb.h>
5
#include <ip.h>
6
 
7
enum
8
{
9
	Ffound=	1<<0,
10
	Fignore=1<<1,
11
	Faddr=	1<<2,
12
};
13
 
14
static Ndbtuple*	filter(Ndb *db, Ndbtuple *t, Ndbtuple *f);
15
static Ndbtuple*	mkfilter(int argc, char **argv);
16
static int		filtercomplete(Ndbtuple *f);
17
static Ndbtuple*	toipaddr(Ndb *db, Ndbtuple *t);
18
static int		prefixlen(uchar *ip);
19
static Ndbtuple*	subnet(Ndb *db, uchar *net, Ndbtuple *f, int prefix);
20
 
21
/* make a filter to be used in filter */
22
static Ndbtuple*
23
mkfilter(int argc, char **argv)
24
{
25
	Ndbtuple *t, *first, *last;
26
	char *p;
27
 
28
	last = first = nil;
29
	while(argc-- > 0){
30
		t = ndbnew(0, 0);
31
		if(first)
32
			last->entry = t;
33
		else
34
			first = t;
35
		last = t;
36
		p = *argv++;
37
		if(*p == '@'){			/* @attr=val ? */
38
			t->ptr |= Faddr;	/* return resolved address(es) */
39
			p++;
40
		}
41
		strncpy(t->attr, p, sizeof(t->attr)-1);
42
	}
43
	ndbsetmalloctag(first, getcallerpc(&argc));
44
	return first;
45
}
46
 
47
/* return true if every pair of filter has been used */
48
static int
49
filtercomplete(Ndbtuple *f)
50
{
51
	for(; f; f = f->entry)
52
		if((f->ptr & Fignore) == 0)
53
			return 0;
54
	return 1;
55
}
56
 
57
/* set the attribute of all entries in a tuple */
58
static Ndbtuple*
59
setattr(Ndbtuple *t, char *attr)
60
{
61
	Ndbtuple *nt;
62
 
63
	for(nt = t; nt; nt = nt->entry)
64
		strcpy(nt->attr, attr);
65
	return t;
66
}
67
 
68
/*
69
 *  return only the attr/value pairs in t maching the filter, f.
70
 *  others are freed.  line structure is preserved.
71
 */
72
static Ndbtuple*
73
filter(Ndb *db, Ndbtuple *t, Ndbtuple *f)
74
{
75
	Ndbtuple *nt, *nf, *next;
76
 
77
	/* filter out what we don't want */
78
	for(nt = t; nt; nt = next){
79
		next = nt->entry;
80
 
81
		/* look through filter */
82
		for(nf = f; nf != nil; nf = nf->entry){
83
			if(!(nf->ptr&Fignore) && strcmp(nt->attr, nf->attr) == 0)
84
				break;
85
		}
86
		if(nf == nil){
87
			/* remove nt from t */
88
			t = ndbdiscard(t, nt);
89
		} else {
90
			if(nf->ptr & Faddr)
91
				t = ndbsubstitute(t, nt, setattr(ndbgetipaddr(db, nt->val), nt->attr));
92
			nf->ptr |= Ffound;
93
		}
94
	}
95
 
96
	/* remember filter etnries that matched */
97
	for(nf = f; nf != nil; nf = nf->entry)
98
		if(nf->ptr & Ffound)
99
			nf->ptr = (nf->ptr & ~Ffound) | Fignore;
100
 
101
	ndbsetmalloctag(t, getcallerpc(&db));
102
	return t;
103
}
104
 
105
static int
106
prefixlen(uchar *ip)
107
{
108
	int y, i;
109
 
110
	for(y = IPaddrlen-1; y >= 0; y--)
111
		for(i = 8; i > 0; i--)
112
			if(ip[y] & (1<<(8-i)))
113
				return y*8 + i;
114
	return 0;
115
}
116
 
117
/*
118
 *  look through a containing subset
119
 */
120
static Ndbtuple*
121
subnet(Ndb *db, uchar *net, Ndbtuple *f, int prefix)
122
{
123
	Ndbs s;
124
	Ndbtuple *t, *nt, *xt;
125
	char netstr[128];
126
	uchar mask[IPaddrlen];
127
	int masklen;
128
 
129
	t = nil;
130
	sprint(netstr, "%I", net);
131
	nt = ndbsearch(db, &s, "ip", netstr);
132
	while(nt != nil){
133
		xt = ndbfindattr(nt, nt, "ipnet");
134
		if(xt){
135
			xt = ndbfindattr(nt, nt, "ipmask");
136
			if(xt)
137
				parseipmask(mask, xt->val);
138
			else
139
				ipmove(mask, defmask(net));
140
			masklen = prefixlen(mask);
141
			if(masklen <= prefix){
142
				t = ndbconcatenate(t, filter(db, nt, f));
143
				nt = nil;
144
			}
145
		}
146
		ndbfree(nt);
147
		nt = ndbsnext(&s, "ip", netstr);
148
	}
149
	ndbsetmalloctag(t, getcallerpc(&db));
150
	return t;
151
}
152
 
153
/*
154
 *  fill in all the requested attributes for a system.
155
 *  if the system's entry doesn't have all required,
156
 *  walk through successively more inclusive networks
157
 *  for inherited attributes.
158
 */
159
Ndbtuple*
160
ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n)
161
{
162
	Ndbtuple *t, *nt, *f;
163
	Ndbs s;
164
	char *ipstr;
165
	uchar net[IPaddrlen], ip[IPaddrlen];
166
	int prefix, smallestprefix, force;
167
	vlong r;
168
 
169
	/* just in case */
170
	fmtinstall('I', eipfmt);
171
	fmtinstall('M', eipfmt);
172
 
173
	/* get needed attributes */
174
	f = mkfilter(n, alist);
175
 
176
	/*
177
	 *  first look for a matching entry with an ip address
178
	 */
179
	t = nil;
180
	ipstr = ndbgetvalue(db, &s, attr, val, "ip", &nt);
181
	if(ipstr == nil){
182
		/* none found, make one up */
183
		if(strcmp(attr, "ip") != 0) {
184
			ndbfree(f);
185
			return nil;	
186
		}
187
		t = ndbnew("ip", val);
188
		t->line = t;
189
		t->entry = nil;
190
		r = parseip(net, val);
191
		if(r == -1)
192
			ndbfree(t);
193
	} else {
194
		/* found one */
195
		while(nt != nil){
196
			nt = ndbreorder(nt, s.t);
197
			t = ndbconcatenate(t, nt);
198
			nt = ndbsnext(&s, attr, val);
199
		}
200
		r = parseip(net, ipstr);
201
		free(ipstr);
202
	}
203
	if(r < 0){
204
		ndbfree(f);
205
		return nil;
206
	}
207
	ipmove(ip, net);
208
	t = filter(db, t, f);
209
 
210
	/*
211
	 *  now go through subnets to fill in any missing attributes
212
	 */
213
	if(isv4(net)){
214
		prefix = 127;
215
		smallestprefix = 100;
216
		force = 0;
217
	} else {
218
		/* in v6, the last 8 bytes have no structure (we hope) */
219
		prefix = 64;
220
		smallestprefix = 2;
221
		memset(net+8, 0, 8);
222
		force = 1;
223
	}
224
 
225
	/*
226
	 *  to find a containing network, keep turning off
227
	 *  the lower bit and look for a network with
228
	 *  that address and a shorter mask.  tedius but
229
	 *  complete, we may need to find a trick to speed this up.
230
	 */
231
	for(; prefix >= smallestprefix; prefix--){
232
		if(filtercomplete(f))
233
			break;
234
		if(!force && (net[prefix/8] & (1<<(7-(prefix%8)))) == 0)
235
			continue;
236
		force = 0;
237
		net[prefix/8] &= ~(1<<(7-(prefix%8)));
238
		t = ndbconcatenate(t, subnet(db, net, f, prefix));
239
	}
240
 
241
	/*
242
	 *  if there's an unfulfilled ipmask, make one up
243
	 */
244
	nt = ndbfindattr(f, f, "ipmask");
245
	if(nt && !(nt->ptr & Fignore)){
246
		char x[64];
247
 
248
		snprint(x, sizeof(x), "%M", defmask(ip));
249
		t = ndbconcatenate(t, ndbnew("ipmask", x));
250
	}
251
 
252
	ndbfree(f);
253
	ndbsetmalloctag(t, getcallerpc(&db));
254
	return t;
255
}