Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 *  this currently only works for ethernet bootp's -- presotto
3
 */
4
#include <u.h>
5
#include <libc.h>
6
#include <ip.h>
7
#include <bio.h>
8
#include <ndb.h>
9
#include "dat.h"
10
 
11
static Ndb *db;
12
char *ndbfile;
13
 
14
/*
15
 * open ndbfile as db if not already open.  also check for stale data
16
 * and reload as needed.
17
 */
18
static Ndb *
19
opendb(void)
20
{
21
	static ulong lastcheck;
22
 
23
	/* check no more often than once every minute */
24
	if(db == nil) {
25
		db = ndbopen(ndbfile);
26
		if(db != nil)
27
			lastcheck = now;
28
	} else if(now >= lastcheck + 60) {
29
		if (ndbchanged(db))
30
			ndbreopen(db);
31
		lastcheck = now;
32
	}
33
	return db;
34
}
35
 
36
Iplifc*
37
findlifc(uchar *ip)
38
{
39
	uchar x[IPaddrlen];
40
	Ipifc *ifc;
41
	Iplifc *lifc;
42
 
43
	for(ifc = ipifcs; ifc; ifc = ifc->next){
44
		for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
45
			if(lifc->net[0] == 0)
46
				continue;
47
			maskip(ip, lifc->mask, x);
48
			if(memcmp(x, lifc->net, IPaddrlen) == 0)
49
				return lifc;
50
		}
51
	}
52
	return nil;
53
}
54
 
55
int
56
forme(uchar *ip)
57
{
58
	Ipifc *ifc;
59
	Iplifc *lifc;
60
 
61
	for(ifc = ipifcs; ifc; ifc = ifc->next){
62
		for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next)
63
			if(memcmp(ip, lifc->ip, IPaddrlen) == 0)
64
				return 1;
65
	}
66
	return 0;
67
}
68
 
69
uchar noetheraddr[6];
70
 
71
static void
72
setipaddr(uchar *addr, char *ip)
73
{
74
	if(ipcmp(addr, IPnoaddr) == 0)
75
		parseip(addr, ip);
76
}
77
 
78
static void
79
setipmask(uchar *mask, char *ip)
80
{
81
	if(ipcmp(mask, IPnoaddr) == 0)
82
		parseipmask(mask, ip);
83
}
84
 
85
/*
86
 *  do an ipinfo with defaults
87
 */
88
int
89
lookupip(uchar *ipaddr, Info *iip, int gate)
90
{
91
	char ip[32];
92
	Ndbtuple *t, *nt;
93
	char *attrs[32], **p;
94
 
95
	if(opendb() == nil){
96
		warning(1, "can't open db");
97
		return -1;
98
	}
99
 
100
	p = attrs;
101
	*p++ = "ip";
102
	*p++ = "ipmask";
103
	*p++ = "@ipgw";
104
	if(!gate){
105
		*p++ = "bootf";
106
		*p++ = "bootf2";
107
		*p++ = "@tftp";
108
		*p++ = "@tftp2";
109
		*p++ = "rootpath";
110
		*p++ = "dhcp";
111
		*p++ = "vendorclass";
112
		*p++ = "ether";
113
		*p++ = "dom";
114
		*p++ = "@fs";
115
		*p++ = "@auth";
116
	}
117
	*p = 0;
118
 
119
	memset(iip, 0, sizeof(*iip));
120
	snprint(ip, sizeof(ip), "%I", ipaddr);
121
	t = ndbipinfo(db, "ip", ip, attrs, p - attrs);
122
	if(t == nil)
123
		return -1;
124
 
125
	for(nt = t; nt != nil; nt = nt->entry){
126
		if(strcmp(nt->attr, "ip") == 0)
127
			setipaddr(iip->ipaddr, nt->val);
128
		else
129
		if(strcmp(nt->attr, "ipmask") == 0)
130
			setipmask(iip->ipmask, nt->val);
131
		else
132
		if(strcmp(nt->attr, "fs") == 0)
133
			setipaddr(iip->fsip, nt->val);
134
		else
135
		if(strcmp(nt->attr, "auth") == 0)
136
			setipaddr(iip->auip, nt->val);
137
		else
138
		if(strcmp(nt->attr, "tftp") == 0)
139
			setipaddr(iip->tftp, nt->val);
140
		else
141
		if(strcmp(nt->attr, "tftp2") == 0)
142
			setipaddr(iip->tftp2, nt->val);
143
		else
144
		if(strcmp(nt->attr, "ipgw") == 0)
145
			setipaddr(iip->gwip, nt->val);
146
		else
147
		if(strcmp(nt->attr, "ether") == 0){
148
			/*
149
			 * this is probably wrong for machines with multiple
150
			 * ethers.  bootp or dhcp requests could come from any
151
			 * of the ethers listed in the ndb entry.
152
			 */
153
			if(memcmp(iip->etheraddr, noetheraddr, 6) == 0)
154
				parseether(iip->etheraddr, nt->val);
155
			iip->indb = 1;
156
		}
157
		else
158
		if(strcmp(nt->attr, "dhcp") == 0){
159
			if(iip->dhcpgroup[0] == 0)
160
				strcpy(iip->dhcpgroup, nt->val);
161
		}
162
		else
163
		if(strcmp(nt->attr, "bootf") == 0){
164
			if(iip->bootf[0] == 0)
165
				strcpy(iip->bootf, nt->val);
166
		}
167
		else
168
		if(strcmp(nt->attr, "bootf2") == 0){
169
			if(iip->bootf2[0] == 0)
170
				strcpy(iip->bootf2, nt->val);
171
		}
172
		else
173
		if(strcmp(nt->attr, "vendor") == 0){
174
			if(iip->vendor[0] == 0)
175
				strcpy(iip->vendor, nt->val);
176
		}
177
		else
178
		if(strcmp(nt->attr, "dom") == 0){
179
			if(iip->domain[0] == 0)
180
				strcpy(iip->domain, nt->val);
181
		}
182
		else
183
		if(strcmp(nt->attr, "rootpath") == 0){
184
			if(iip->rootpath[0] == 0)
185
				strcpy(iip->rootpath, nt->val);
186
		}
187
	}
188
	ndbfree(t);
189
	maskip(iip->ipaddr, iip->ipmask, iip->ipnet);
190
	return 0;
191
}
192
 
193
static uchar zeroes[6];
194
 
195
/*
196
 *  lookup info about a client in the database.  Find an address on the
197
 *  same net as riip.
198
 */
199
int
200
lookup(Bootp *bp, Info *iip, Info *riip)
201
{
202
	Ndbtuple *t, *nt;
203
	Ndbs s;
204
	char *hwattr;
205
	char *hwval, hwbuf[33];
206
	uchar ciaddr[IPaddrlen];
207
 
208
	if(opendb() == nil){
209
		warning(1, "can't open db");
210
		return -1;
211
	}
212
 
213
	memset(iip, 0, sizeof(*iip));
214
 
215
	/* client knows its address? */
216
	v4tov6(ciaddr, bp->ciaddr);
217
	if(validip(ciaddr)){
218
		if(lookupip(ciaddr, iip, 0) < 0) {
219
			if (debug)
220
				warning(0, "don't know %I", ciaddr);
221
			return -1;	/* don't know anything about it */
222
		}
223
		if(!samenet(riip->ipaddr, iip)){
224
			warning(0, "%I not on %I", ciaddr, riip->ipnet);
225
			return -1;
226
		}
227
 
228
		/*
229
		 *  see if this is a masquerade, i.e., if the ether
230
		 *  address doesn't match what we expected it to be.
231
		 */
232
		if(memcmp(iip->etheraddr, zeroes, 6) != 0)
233
		if(memcmp(bp->chaddr, iip->etheraddr, 6) != 0)
234
			warning(0, "ciaddr %I rcvd from %E instead of %E",
235
				ciaddr, bp->chaddr, iip->etheraddr);
236
 
237
		return 0;
238
	}
239
 
240
	if(bp->hlen > Maxhwlen)
241
		return -1;
242
	switch(bp->htype){
243
	case 1:
244
		hwattr = "ether";
245
		hwval = hwbuf;
246
		snprint(hwbuf, sizeof(hwbuf), "%E", bp->chaddr);
247
		break;
248
	default:
249
		syslog(0, blog, "not ethernet %E, htype %d, hlen %d",
250
			bp->chaddr, bp->htype, bp->hlen);
251
		return -1;
252
	}
253
 
254
	/*
255
	 *  use hardware address to find an ip address on
256
	 *  same net as riip
257
	 */
258
	t = ndbsearch(db, &s, hwattr, hwval);
259
	while(t){
260
		for(nt = t; nt; nt = nt->entry){
261
			if(strcmp(nt->attr, "ip") != 0)
262
				continue;
263
			parseip(ciaddr, nt->val);
264
			if(lookupip(ciaddr, iip, 0) < 0)
265
				continue;
266
			if(samenet(riip->ipaddr, iip)){
267
				ndbfree(t);
268
				return 0;
269
			}
270
		}
271
		ndbfree(t);
272
		t = ndbsnext(&s, hwattr, hwval);
273
	}
274
	return -1;
275
}
276
 
277
/*
278
 *  interface to ndbipinfo
279
 */
280
Ndbtuple*
281
lookupinfo(uchar *ipaddr, char **attr, int n)
282
{
283
	char ip[32];
284
 
285
	sprint(ip, "%I", ipaddr);
286
	return ndbipinfo(db, "ip", ip, attr, n);
287
}
288
 
289
/*
290
 *  return the ip addresses for a type of server for system ip
291
 */
292
int
293
lookupserver(char *attr, uchar **ipaddrs, Ndbtuple *t)
294
{
295
	Ndbtuple *nt;
296
	int rv = 0;
297
 
298
	for(nt = t; rv < 2 && nt != nil; nt = nt->entry)
299
		if(strcmp(nt->attr, attr) == 0){
300
			parseip(ipaddrs[rv], nt->val);
301
			rv++;
302
		}
303
	return rv;
304
}
305
 
306
/*
307
 *  just lookup the name
308
 */
309
void
310
lookupname(char *val, Ndbtuple *t)
311
{
312
	Ndbtuple *nt;
313
 
314
	for(nt = t; nt != nil; nt = nt->entry)
315
		if(strcmp(nt->attr, "dom") == 0){
316
			strcpy(val, nt->val);
317
			break;
318
		}
319
}