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