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