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 }