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 } 320