xref: /plan9/sys/src/cmd/ip/dhcpd/ndb.c (revision 0a84db5e29c8e13ff34694780ad5447552e05609)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  *  this currently only works for ethernet bootp's -- presotto
37dd7cddfSDavid du Colombier  */
47dd7cddfSDavid du Colombier #include <u.h>
57dd7cddfSDavid du Colombier #include <libc.h>
67dd7cddfSDavid du Colombier #include <ip.h>
77dd7cddfSDavid du Colombier #include <bio.h>
87dd7cddfSDavid du Colombier #include <ndb.h>
97dd7cddfSDavid du Colombier #include "dat.h"
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier Ndb *db;
127dd7cddfSDavid du Colombier char *ndbfile;
137dd7cddfSDavid du Colombier 
149a747e4fSDavid du Colombier Iplifc*
159a747e4fSDavid du Colombier findlifc(uchar *ip)
167dd7cddfSDavid du Colombier {
177dd7cddfSDavid du Colombier 	uchar x[IPaddrlen];
187dd7cddfSDavid du Colombier 	Ipifc *ifc;
199a747e4fSDavid du Colombier 	Iplifc *lifc;
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	for(ifc = ipifcs; ifc; ifc = ifc->next){
229a747e4fSDavid du Colombier 		for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
239a747e4fSDavid du Colombier 			if(lifc->net[0] == 0)
247dd7cddfSDavid du Colombier 				continue;
259a747e4fSDavid du Colombier 			maskip(ip, lifc->mask, x);
269a747e4fSDavid du Colombier 			if(memcmp(x, lifc->net, IPaddrlen) == 0)
279a747e4fSDavid du Colombier 				return lifc;
287dd7cddfSDavid du Colombier 		}
299a747e4fSDavid du Colombier 	}
309a747e4fSDavid du Colombier 	return nil;
317dd7cddfSDavid du Colombier }
327dd7cddfSDavid du Colombier 
339a747e4fSDavid du Colombier int
347dd7cddfSDavid du Colombier forme(uchar *ip)
357dd7cddfSDavid du Colombier {
367dd7cddfSDavid du Colombier 	Ipifc *ifc;
379a747e4fSDavid du Colombier 	Iplifc *lifc;
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier 	for(ifc = ipifcs; ifc; ifc = ifc->next){
409a747e4fSDavid du Colombier 		for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next)
419a747e4fSDavid du Colombier 			if(memcmp(ip, lifc->ip, IPaddrlen) == 0)
429a747e4fSDavid du Colombier 				return 1;
437dd7cddfSDavid du Colombier 	}
447dd7cddfSDavid du Colombier 	return 0;
457dd7cddfSDavid du Colombier }
467dd7cddfSDavid du Colombier 
477dd7cddfSDavid du Colombier uchar noetheraddr[6];
487dd7cddfSDavid du Colombier 
497dd7cddfSDavid du Colombier static void
507dd7cddfSDavid du Colombier setipaddr(uchar *addr, char *ip)
517dd7cddfSDavid du Colombier {
527dd7cddfSDavid du Colombier 	if(ipcmp(addr, IPnoaddr) == 0)
537dd7cddfSDavid du Colombier 		parseip(addr, ip);
547dd7cddfSDavid du Colombier }
557dd7cddfSDavid du Colombier 
567dd7cddfSDavid du Colombier static void
577dd7cddfSDavid du Colombier setipmask(uchar *mask, char *ip)
587dd7cddfSDavid du Colombier {
597dd7cddfSDavid du Colombier 	if(ipcmp(mask, IPnoaddr) == 0)
607dd7cddfSDavid du Colombier 		parseipmask(mask, ip);
617dd7cddfSDavid du Colombier }
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier /*
647dd7cddfSDavid du Colombier  *  do an ipinfo with defaults
657dd7cddfSDavid du Colombier  */
667dd7cddfSDavid du Colombier int
673ff48bf5SDavid du Colombier lookupip(uchar *ipaddr, Info *iip, int gate)
687dd7cddfSDavid du Colombier {
697dd7cddfSDavid du Colombier 	char ip[32];
707dd7cddfSDavid du Colombier 	Ndbtuple *t, *nt;
717dd7cddfSDavid du Colombier 	char *attrs[32], **p;
727dd7cddfSDavid du Colombier 
737dd7cddfSDavid du Colombier 	if(db == 0)
747dd7cddfSDavid du Colombier 		db = ndbopen(ndbfile);
757dd7cddfSDavid du Colombier 	if(db == 0){
768c6ab946SDavid du Colombier 		warning(1, "can't open db");
777dd7cddfSDavid du Colombier 		return -1;
787dd7cddfSDavid du Colombier 	}
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier 	p = attrs;
817dd7cddfSDavid du Colombier 	*p++ = "ip";
827dd7cddfSDavid du Colombier 	*p++ = "ipmask";
833ff48bf5SDavid du Colombier 	*p++ = "@ipgw";
843ff48bf5SDavid du Colombier 	if(!gate){
857dd7cddfSDavid du Colombier 		*p++ = "bootf";
86da51d93aSDavid du Colombier 		*p++ = "bootf2";
873ff48bf5SDavid du Colombier 		*p++ = "@tftp";
88da51d93aSDavid du Colombier 		*p++ = "@tftp2";
899a747e4fSDavid du Colombier 		*p++ = "rootpath";
907dd7cddfSDavid du Colombier 		*p++ = "dhcp";
9139734e7eSDavid du Colombier 		*p++ = "vendorclass";
927dd7cddfSDavid du Colombier 		*p++ = "ether";
937dd7cddfSDavid du Colombier 		*p++ = "dom";
947dd7cddfSDavid du Colombier 		*p++ = "@fs";
957dd7cddfSDavid du Colombier 		*p++ = "@auth";
963ff48bf5SDavid du Colombier 	}
977dd7cddfSDavid du Colombier 	*p = 0;
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier 	memset(iip, 0, sizeof(*iip));
1007dd7cddfSDavid du Colombier 	snprint(ip, sizeof(ip), "%I", ipaddr);
1017dd7cddfSDavid du Colombier 	t = ndbipinfo(db, "ip", ip, attrs, p - attrs);
1027dd7cddfSDavid du Colombier 	if(t == nil)
1037dd7cddfSDavid du Colombier 		return -1;
1047dd7cddfSDavid du Colombier 
1057dd7cddfSDavid du Colombier 	for(nt = t; nt != nil; nt = nt->entry){
1067dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "ip") == 0)
1077dd7cddfSDavid du Colombier 			setipaddr(iip->ipaddr, nt->val);
1087dd7cddfSDavid du Colombier 		else
1097dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "ipmask") == 0)
1107dd7cddfSDavid du Colombier 			setipmask(iip->ipmask, nt->val);
1117dd7cddfSDavid du Colombier 		else
1127dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "fs") == 0)
1137dd7cddfSDavid du Colombier 			setipaddr(iip->fsip, nt->val);
1147dd7cddfSDavid du Colombier 		else
1157dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "auth") == 0)
1167dd7cddfSDavid du Colombier 			setipaddr(iip->auip, nt->val);
1177dd7cddfSDavid du Colombier 		else
1183ff48bf5SDavid du Colombier 		if(strcmp(nt->attr, "tftp") == 0)
1193ff48bf5SDavid du Colombier 			setipaddr(iip->tftp, nt->val);
1203ff48bf5SDavid du Colombier 		else
1213ff48bf5SDavid du Colombier 		if(strcmp(nt->attr, "tftp2") == 0)
1223ff48bf5SDavid du Colombier 			setipaddr(iip->tftp2, nt->val);
1233ff48bf5SDavid du Colombier 		else
1247dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "ipgw") == 0)
1257dd7cddfSDavid du Colombier 			setipaddr(iip->gwip, nt->val);
1267dd7cddfSDavid du Colombier 		else
1277dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "ether") == 0){
1282ddf2468SDavid du Colombier 			/*
1292ddf2468SDavid du Colombier 			 * this is probably wrong for machines with multiple
1302ddf2468SDavid du Colombier 			 * ethers.  bootp or dhcp requests could come from any
1312ddf2468SDavid du Colombier 			 * of the ethers listed in the ndb entry.
1322ddf2468SDavid du Colombier 			 */
1337dd7cddfSDavid du Colombier 			if(memcmp(iip->etheraddr, noetheraddr, 6) == 0)
1347dd7cddfSDavid du Colombier 				parseether(iip->etheraddr, nt->val);
1357dd7cddfSDavid du Colombier 			iip->indb = 1;
1367dd7cddfSDavid du Colombier 		}
1377dd7cddfSDavid du Colombier 		else
1387dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "dhcp") == 0){
1397dd7cddfSDavid du Colombier 			if(iip->dhcpgroup[0] == 0)
1407dd7cddfSDavid du Colombier 				strcpy(iip->dhcpgroup, nt->val);
1417dd7cddfSDavid du Colombier 		}
1427dd7cddfSDavid du Colombier 		else
1437dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "bootf") == 0){
1447dd7cddfSDavid du Colombier 			if(iip->bootf[0] == 0)
1457dd7cddfSDavid du Colombier 				strcpy(iip->bootf, nt->val);
1467dd7cddfSDavid du Colombier 		}
1477dd7cddfSDavid du Colombier 		else
1489a747e4fSDavid du Colombier 		if(strcmp(nt->attr, "bootf2") == 0){
1499a747e4fSDavid du Colombier 			if(iip->bootf2[0] == 0)
1509a747e4fSDavid du Colombier 				strcpy(iip->bootf2, nt->val);
1519a747e4fSDavid du Colombier 		}
1529a747e4fSDavid du Colombier 		else
1537dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "vendor") == 0){
1547dd7cddfSDavid du Colombier 			if(iip->vendor[0] == 0)
1557dd7cddfSDavid du Colombier 				strcpy(iip->vendor, nt->val);
1567dd7cddfSDavid du Colombier 		}
1577dd7cddfSDavid du Colombier 		else
1587dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "dom") == 0){
1597dd7cddfSDavid du Colombier 			if(iip->domain[0] == 0)
1607dd7cddfSDavid du Colombier 				strcpy(iip->domain, nt->val);
1617dd7cddfSDavid du Colombier 		}
1629a747e4fSDavid du Colombier 		else
1639a747e4fSDavid du Colombier 		if(strcmp(nt->attr, "rootpath") == 0){
1649a747e4fSDavid du Colombier 			if(iip->rootpath[0] == 0)
1659a747e4fSDavid du Colombier 				strcpy(iip->rootpath, nt->val);
1669a747e4fSDavid du Colombier 		}
1677dd7cddfSDavid du Colombier 	}
1687dd7cddfSDavid du Colombier 	ndbfree(t);
1697dd7cddfSDavid du Colombier 	maskip(iip->ipaddr, iip->ipmask, iip->ipnet);
1707dd7cddfSDavid du Colombier 	return 0;
1717dd7cddfSDavid du Colombier }
1727dd7cddfSDavid du Colombier 
1737dd7cddfSDavid du Colombier static uchar zeroes[6];
1747dd7cddfSDavid du Colombier 
1757dd7cddfSDavid du Colombier /*
1767dd7cddfSDavid du Colombier  *  lookup info about a client in the database.  Find an address on the
1777dd7cddfSDavid du Colombier  *  same net as riip.
1787dd7cddfSDavid du Colombier  */
1797dd7cddfSDavid du Colombier int
1807dd7cddfSDavid du Colombier lookup(Bootp *bp, Info *iip, Info *riip)
1817dd7cddfSDavid du Colombier {
1827dd7cddfSDavid du Colombier 	Ndbtuple *t, *nt;
1837dd7cddfSDavid du Colombier 	Ndbs s;
1847dd7cddfSDavid du Colombier 	char *hwattr;
1857dd7cddfSDavid du Colombier 	char *hwval, hwbuf[33];
1867dd7cddfSDavid du Colombier 	uchar ciaddr[IPaddrlen];
1877dd7cddfSDavid du Colombier 
1887dd7cddfSDavid du Colombier 	if(db == 0)
1897dd7cddfSDavid du Colombier 		db = ndbopen(ndbfile);
1907dd7cddfSDavid du Colombier 	if(db == 0){
1918c6ab946SDavid du Colombier 		warning(1, "can't open db");
1927dd7cddfSDavid du Colombier 		return -1;
1937dd7cddfSDavid du Colombier 	}
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier 	memset(iip, 0, sizeof(*iip));
1967dd7cddfSDavid du Colombier 
1977dd7cddfSDavid du Colombier 	/* client knows its address? */
1987dd7cddfSDavid du Colombier 	v4tov6(ciaddr, bp->ciaddr);
1997dd7cddfSDavid du Colombier 	if(validip(ciaddr)){
200*0a84db5eSDavid du Colombier 		if(lookupip(ciaddr, iip, 0) < 0) {
201*0a84db5eSDavid du Colombier 			if (debug)
202*0a84db5eSDavid du Colombier 				warning(0, "don't know %I", ciaddr);
2037dd7cddfSDavid du Colombier 			return -1;	/* don't know anything about it */
204*0a84db5eSDavid du Colombier 		}
2057dd7cddfSDavid du Colombier 		if(!samenet(riip->ipaddr, iip)){
2067dd7cddfSDavid du Colombier 			warning(0, "%I not on %I", ciaddr, riip->ipnet);
2077dd7cddfSDavid du Colombier 			return -1;
2087dd7cddfSDavid du Colombier 		}
2097dd7cddfSDavid du Colombier 
2107dd7cddfSDavid du Colombier 		/*
2117dd7cddfSDavid du Colombier 		 *  see if this is a masquerade, i.e., if the ether
2127dd7cddfSDavid du Colombier 		 *  address doesn't match what we expected it to be.
2137dd7cddfSDavid du Colombier 		 */
2147dd7cddfSDavid du Colombier 		if(memcmp(iip->etheraddr, zeroes, 6) != 0)
2157dd7cddfSDavid du Colombier 		if(memcmp(bp->chaddr, iip->etheraddr, 6) != 0)
2167dd7cddfSDavid du Colombier 			warning(0, "ciaddr %I rcvd from %E instead of %E",
2177dd7cddfSDavid du Colombier 				ciaddr, bp->chaddr, iip->etheraddr);
2187dd7cddfSDavid du Colombier 
2197dd7cddfSDavid du Colombier 		return 0;
2207dd7cddfSDavid du Colombier 	}
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier 	if(bp->hlen > Maxhwlen)
2237dd7cddfSDavid du Colombier 		return -1;
2247dd7cddfSDavid du Colombier 	switch(bp->htype){
2257dd7cddfSDavid du Colombier 	case 1:
2267dd7cddfSDavid du Colombier 		hwattr = "ether";
2277dd7cddfSDavid du Colombier 		hwval = hwbuf;
2287dd7cddfSDavid du Colombier 		snprint(hwbuf, sizeof(hwbuf), "%E", bp->chaddr);
2297dd7cddfSDavid du Colombier 		break;
2307dd7cddfSDavid du Colombier 	default:
2317dd7cddfSDavid du Colombier 		syslog(0, blog, "not ethernet %E, htype %d, hlen %d",
2327dd7cddfSDavid du Colombier 			bp->chaddr, bp->htype, bp->hlen);
2337dd7cddfSDavid du Colombier 		return -1;
2347dd7cddfSDavid du Colombier 	}
2357dd7cddfSDavid du Colombier 
2367dd7cddfSDavid du Colombier 	/*
2377dd7cddfSDavid du Colombier 	 *  use hardware address to find an ip address on
2387dd7cddfSDavid du Colombier 	 *  same net as riip
2397dd7cddfSDavid du Colombier 	 */
2407dd7cddfSDavid du Colombier 	t = ndbsearch(db, &s, hwattr, hwval);
2417dd7cddfSDavid du Colombier 	while(t){
2427dd7cddfSDavid du Colombier 		for(nt = t; nt; nt = nt->entry){
2437dd7cddfSDavid du Colombier 			if(strcmp(nt->attr, "ip") != 0)
2447dd7cddfSDavid du Colombier 				continue;
2457dd7cddfSDavid du Colombier 			parseip(ciaddr, nt->val);
2463ff48bf5SDavid du Colombier 			if(lookupip(ciaddr, iip, 0) < 0)
2477dd7cddfSDavid du Colombier 				continue;
2487dd7cddfSDavid du Colombier 			if(samenet(riip->ipaddr, iip)){
2497dd7cddfSDavid du Colombier 				ndbfree(t);
2507dd7cddfSDavid du Colombier 				return 0;
2517dd7cddfSDavid du Colombier 			}
2527dd7cddfSDavid du Colombier 		}
2537dd7cddfSDavid du Colombier 		ndbfree(t);
2547dd7cddfSDavid du Colombier 		t = ndbsnext(&s, hwattr, hwval);
2557dd7cddfSDavid du Colombier 	}
2567dd7cddfSDavid du Colombier 	return -1;
2577dd7cddfSDavid du Colombier }
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier /*
2603ff48bf5SDavid du Colombier  *  interface to ndbipinfo
2613ff48bf5SDavid du Colombier  */
2623ff48bf5SDavid du Colombier Ndbtuple*
2633ff48bf5SDavid du Colombier lookupinfo(uchar *ipaddr, char **attr, int n)
2643ff48bf5SDavid du Colombier {
2653ff48bf5SDavid du Colombier 	char ip[32];
2663ff48bf5SDavid du Colombier 
2673ff48bf5SDavid du Colombier 	sprint(ip, "%I", ipaddr);
2683ff48bf5SDavid du Colombier 	return ndbipinfo(db, "ip", ip, attr, n);
2693ff48bf5SDavid du Colombier }
2703ff48bf5SDavid du Colombier 
2713ff48bf5SDavid du Colombier /*
2727dd7cddfSDavid du Colombier  *  return the ip addresses for a type of server for system ip
2737dd7cddfSDavid du Colombier  */
2747dd7cddfSDavid du Colombier int
2753ff48bf5SDavid du Colombier lookupserver(char *attr, uchar **ipaddrs, Ndbtuple *t)
2767dd7cddfSDavid du Colombier {
2773ff48bf5SDavid du Colombier 	Ndbtuple *nt;
2787dd7cddfSDavid du Colombier 	int rv = 0;
2797dd7cddfSDavid du Colombier 
2807dd7cddfSDavid du Colombier 	for(nt = t; rv < 2 && nt != nil; nt = nt->entry)
2817dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, attr) == 0){
2827dd7cddfSDavid du Colombier 			parseip(ipaddrs[rv], nt->val);
2837dd7cddfSDavid du Colombier 			rv++;
2847dd7cddfSDavid du Colombier 		}
2857dd7cddfSDavid du Colombier 	return rv;
2867dd7cddfSDavid du Colombier }
2877dd7cddfSDavid du Colombier 
2887dd7cddfSDavid du Colombier /*
2897dd7cddfSDavid du Colombier  *  just lookup the name
2907dd7cddfSDavid du Colombier  */
2917dd7cddfSDavid du Colombier void
2923ff48bf5SDavid du Colombier lookupname(char *val, Ndbtuple *t)
2937dd7cddfSDavid du Colombier {
2943ff48bf5SDavid du Colombier 	Ndbtuple *nt;
2957dd7cddfSDavid du Colombier 
2967dd7cddfSDavid du Colombier 	for(nt = t; nt != nil; nt = nt->entry)
2977dd7cddfSDavid du Colombier 		if(strcmp(nt->attr, "dom") == 0){
2987dd7cddfSDavid du Colombier 			strcpy(val, nt->val);
2997dd7cddfSDavid du Colombier 			break;
3007dd7cddfSDavid du Colombier 		}
3013ff48bf5SDavid du Colombier }
302