plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

ndb.c (6152B)


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