| /* |
| * this currently only works for ethernet bootp's -- presotto |
| */ |
| #include <u.h> |
| #include <libc.h> |
| #include <ip.h> |
| #include <bio.h> |
| #include <ndb.h> |
| #include "dat.h" |
| |
| static void check72(Info *iip); |
| |
| Ndb *db; |
| char *ndbfile; |
| |
| Iplifc* |
| findlifc(uchar *ip) |
| { |
| uchar x[IPaddrlen]; |
| Ipifc *ifc; |
| Iplifc *lifc; |
| |
| for(ifc = ipifcs; ifc; ifc = ifc->next){ |
| for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ |
| if(lifc->net[0] == 0) |
| continue; |
| maskip(ip, lifc->mask, x); |
| if(memcmp(x, lifc->net, IPaddrlen) == 0) |
| return lifc; |
| } |
| } |
| return nil; |
| } |
| |
| int |
| forme(uchar *ip) |
| { |
| Ipifc *ifc; |
| Iplifc *lifc; |
| |
| extern uchar xmyipaddr[IPaddrlen]; |
| |
| if(memcmp(ip, xmyipaddr, IPaddrlen) == 0) |
| return 1; |
| |
| for(ifc = ipifcs; ifc; ifc = ifc->next){ |
| for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next) |
| if(memcmp(ip, lifc->ip, IPaddrlen) == 0) |
| return 1; |
| } |
| return 0; |
| } |
| |
| uchar noetheraddr[6]; |
| |
| static void |
| setipaddr(uchar *addr, char *ip) |
| { |
| if(ipcmp(addr, IPnoaddr) == 0) |
| parseip(addr, ip); |
| } |
| |
| static void |
| setipmask(uchar *mask, char *ip) |
| { |
| if(ipcmp(mask, IPnoaddr) == 0) |
| parseipmask(mask, ip); |
| } |
| |
| /* |
| * do an ipinfo with defaults |
| */ |
| int |
| lookupip(uchar *ipaddr, Info *iip, int gate) |
| { |
| char ip[32]; |
| Ndbtuple *t, *nt; |
| char *attrs[32], **p; |
| |
| if(db == 0) |
| db = ndbopen(ndbfile); |
| if(db == 0){ |
| fprint(2, "can't open db\n"); |
| return -1; |
| } |
| |
| p = attrs; |
| *p++ = "ip"; |
| *p++ = "ipmask"; |
| *p++ = "@ipgw"; |
| if(!gate){ |
| *p++ = "bootf"; |
| *p++ = "bootf2"; |
| *p++ = "@tftp"; |
| *p++ = "@tftp2"; |
| *p++ = "rootpath"; |
| *p++ = "dhcp"; |
| *p++ = "vendorclass"; |
| *p++ = "ether"; |
| *p++ = "dom"; |
| *p++ = "@fs"; |
| *p++ = "@auth"; |
| } |
| *p = 0; |
| |
| memset(iip, 0, sizeof(*iip)); |
| snprint(ip, sizeof(ip), "%I", ipaddr); |
| t = ndbipinfo(db, "ip", ip, attrs, p - attrs); |
| if(t == nil) |
| return -1; |
| |
| for(nt = t; nt != nil; nt = nt->entry){ |
| if(strcmp(nt->attr, "ip") == 0) |
| setipaddr(iip->ipaddr, nt->val); |
| else |
| if(strcmp(nt->attr, "ipmask") == 0) |
| setipmask(iip->ipmask, nt->val); |
| else |
| if(strcmp(nt->attr, "fs") == 0) |
| setipaddr(iip->fsip, nt->val); |
| else |
| if(strcmp(nt->attr, "auth") == 0) |
| setipaddr(iip->auip, nt->val); |
| else |
| if(strcmp(nt->attr, "tftp") == 0) |
| setipaddr(iip->tftp, nt->val); |
| else |
| if(strcmp(nt->attr, "tftp2") == 0) |
| setipaddr(iip->tftp2, nt->val); |
| else |
| if(strcmp(nt->attr, "ipgw") == 0) |
| setipaddr(iip->gwip, nt->val); |
| else |
| if(strcmp(nt->attr, "ether") == 0){ |
| if(memcmp(iip->etheraddr, noetheraddr, 6) == 0) |
| parseether(iip->etheraddr, nt->val); |
| iip->indb = 1; |
| } |
| else |
| if(strcmp(nt->attr, "dhcp") == 0){ |
| if(iip->dhcpgroup[0] == 0) |
| strcpy(iip->dhcpgroup, nt->val); |
| } |
| else |
| if(strcmp(nt->attr, "bootf") == 0){ |
| if(iip->bootf[0] == 0) |
| strcpy(iip->bootf, nt->val); |
| } |
| else |
| if(strcmp(nt->attr, "bootf2") == 0){ |
| if(iip->bootf2[0] == 0) |
| strcpy(iip->bootf2, nt->val); |
| } |
| else |
| if(strcmp(nt->attr, "vendor") == 0){ |
| if(iip->vendor[0] == 0) |
| strcpy(iip->vendor, nt->val); |
| } |
| else |
| if(strcmp(nt->attr, "dom") == 0){ |
| if(iip->domain[0] == 0) |
| strcpy(iip->domain, nt->val); |
| } |
| else |
| if(strcmp(nt->attr, "rootpath") == 0){ |
| if(iip->rootpath[0] == 0) |
| strcpy(iip->rootpath, nt->val); |
| } |
| } |
| ndbfree(t); |
| maskip(iip->ipaddr, iip->ipmask, iip->ipnet); |
| return 0; |
| } |
| |
| static uchar zeroes[6]; |
| |
| /* |
| * lookup info about a client in the database. Find an address on the |
| * same net as riip. |
| */ |
| int |
| lookup(Bootp *bp, Info *iip, Info *riip) |
| { |
| Ndbtuple *t, *nt; |
| Ndbs s; |
| char *hwattr; |
| char *hwval, hwbuf[33]; |
| uchar ciaddr[IPaddrlen]; |
| |
| if(db == 0) |
| db = ndbopen(ndbfile); |
| if(db == 0){ |
| fprint(2, "can't open db\n"); |
| return -1; |
| } |
| |
| memset(iip, 0, sizeof(*iip)); |
| |
| /* client knows its address? */ |
| v4tov6(ciaddr, bp->ciaddr); |
| if(validip(ciaddr)){ |
| if(lookupip(ciaddr, iip, 0) < 0) |
| return -1; /* don't know anything about it */ |
| |
| check72(iip); |
| |
| if(!samenet(riip->ipaddr, iip)){ |
| warning(0, "%I not on %I", ciaddr, riip->ipnet); |
| return -1; |
| } |
| |
| /* |
| * see if this is a masquerade, i.e., if the ether |
| * address doesn't match what we expected it to be. |
| */ |
| if(memcmp(iip->etheraddr, zeroes, 6) != 0) |
| if(memcmp(bp->chaddr, iip->etheraddr, 6) != 0) |
| warning(0, "ciaddr %I rcvd from %E instead of %E", |
| ciaddr, bp->chaddr, iip->etheraddr); |
| |
| return 0; |
| } |
| |
| if(bp->hlen > Maxhwlen) |
| return -1; |
| switch(bp->htype){ |
| case 1: |
| hwattr = "ether"; |
| hwval = hwbuf; |
| snprint(hwbuf, sizeof(hwbuf), "%E", bp->chaddr); |
| break; |
| default: |
| syslog(0, blog, "not ethernet %E, htype %d, hlen %d", |
| bp->chaddr, bp->htype, bp->hlen); |
| return -1; |
| } |
| |
| /* |
| * use hardware address to find an ip address on |
| * same net as riip |
| */ |
| t = ndbsearch(db, &s, hwattr, hwval); |
| while(t){ |
| for(nt = t; nt; nt = nt->entry){ |
| if(strcmp(nt->attr, "ip") != 0) |
| continue; |
| parseip(ciaddr, nt->val); |
| if(lookupip(ciaddr, iip, 0) < 0) |
| continue; |
| if(samenet(riip->ipaddr, iip)){ |
| ndbfree(t); |
| return 0; |
| } |
| } |
| ndbfree(t); |
| t = ndbsnext(&s, hwattr, hwval); |
| } |
| return -1; |
| } |
| |
| /* |
| * interface to ndbipinfo |
| */ |
| Ndbtuple* |
| lookupinfo(uchar *ipaddr, char **attr, int n) |
| { |
| char ip[32]; |
| |
| sprint(ip, "%I", ipaddr); |
| return ndbipinfo(db, "ip", ip, attr, n); |
| } |
| |
| /* |
| * return the ip addresses for a type of server for system ip |
| */ |
| int |
| lookupserver(char *attr, uchar **ipaddrs, Ndbtuple *t) |
| { |
| Ndbtuple *nt; |
| int rv = 0; |
| |
| for(nt = t; rv < 2 && nt != nil; nt = nt->entry) |
| if(strcmp(nt->attr, attr) == 0){ |
| parseip(ipaddrs[rv], nt->val); |
| rv++; |
| } |
| return rv; |
| } |
| |
| /* |
| * just lookup the name |
| */ |
| void |
| lookupname(char *val, Ndbtuple *t) |
| { |
| Ndbtuple *nt; |
| |
| for(nt = t; nt != nil; nt = nt->entry) |
| if(strcmp(nt->attr, "dom") == 0){ |
| strcpy(val, nt->val); |
| break; |
| } |
| } |
| |
| uchar slash120[IPaddrlen] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0 }; |
| uchar net72[IPaddrlen] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
| 0x0, 0x0, 0xff, 0xff, 135, 104, 72, 0 }; |
| |
| static void |
| check72(Info *iip) |
| { |
| uchar net[IPaddrlen]; |
| |
| maskip(iip->ipaddr, slash120, net); |
| if(ipcmp(net, net72) == 0) |
| syslog(0, blog, "check72 %I %M gw %I", iip->ipaddr, iip->ipmask, iip->gwip); |
| } |