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