/* * look through a containing subset */ static Ndbtuple* subnet(Ndb *db, uint8_t *net, Ndbtuple *f, int prefix) { Ndbs s; Ndbtuple *t, *nt, *xt; char netstr[128]; uint8_t mask[IPaddrlen]; int masklen; t = nil; sprint(netstr, "%I", net); nt = ndbsearch(db, &s, "ip", netstr); while(nt != nil){ xt = ndbfindattr(nt, nt, "ipnet"); if(xt){ xt = ndbfindattr(nt, nt, "ipmask"); if(xt) parseipmask(mask, xt->val); else ipmove(mask, defmask(net)); masklen = prefixlen(mask); if(masklen <= prefix){ t = ndbconcatenate(t, filter(db, nt, f)); nt = nil; } } ndbfree(nt); nt = ndbsnext(&s, "ip", netstr); } ndbsetmalloctag(t, getcallerpc(&db)); return t; }
/* * generic query lookup. The query is of one of the following * forms: * * attr1=val1 attr2=val2 attr3=val3 ... * * returns the matching tuple * * ipinfo attr=val attr1 attr2 attr3 ... * * is like ipinfo and returns the attr{1-n} * associated with the ip address. */ static char *genquery(struct mfile *mf, char *query) { int i, n; char *p; char *attr[Maxattr]; char *val[Maxattr]; struct ndbtuple *t; struct ndbs s; n = getfields(query, attr, COUNT_OF(attr), 1, " "); if (n == 0) return "bad query"; if (strcmp(attr[0], "ipinfo") == 0) return ipinfoquery(mf, attr, n); /* parse pairs */ for (i = 0; i < n; i++) { p = strchr(attr[i], '='); if (p == 0) return "bad query"; *p++ = 0; val[i] = p; } /* give dns a chance */ if ((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]) { t = dnsiplookup(val[0], &s); if (t) { if (qmatch(t, attr, val, n)) { qreply(mf, t); ndbfree(t); return 0; } ndbfree(t); } } /* first pair is always the key. It can't be a '*' */ t = ndbsearch(db, &s, attr[0], val[0]); /* search is the and of all the pairs */ while (t) { if (qmatch(t, attr, val, n)) { qreply(mf, t); ndbfree(t); return 0; } ndbfree(t); t = ndbsnext(&s, attr[0], val[0]); } return "no match"; }
void search(Ndb *db, char *attr, char *val, char *rattr) { char *p; Ndbs s; Ndbtuple *t, *nt; /* first entry with a matching rattr */ if(rattr && !all){ p = ndbgetvalue(db, &s, attr, val, rattr, &t); if (multiple) prmatch(t, rattr); else if(p) Bprint(&bout, "%s\n", p); ndbfree(t); free(p); return; } /* all entries with matching rattrs */ if(rattr) { for(t = ndbsearch(db, &s, attr, val); t != nil; t = ndbsnext(&s, attr, val)){ prmatch(t, rattr); ndbfree(t); } return; } /* all entries */ for(t = ndbsearch(db, &s, attr, val); t; t = ndbsnext(&s, attr, val)){ for(nt = t; nt; nt = nt->entry) Bprint(&bout, "%s=%s ", nt->attr, nt->val); Bprint(&bout, "\n"); ndbfree(t); } }
/* * search for a tuple that has the given 'attr=val' and also 'rattr=x'. * copy 'x' into 'buf' and return the whole tuple. * * return 0 if not found. */ char* ndbgetvalue(struct ndb *db, struct ndbs *s, char *attr, char *val, char *rattr, struct ndbtuple **pp) { struct ndbtuple *t, *nt; char *rv; struct ndbs temps; if(s == NULL) s = &temps; if(pp) *pp = NULL; t = ndbsearch(db, s, attr, val); while(t){ /* first look on same line (closer binding) */ nt = s->t; for(;;){ if(strcmp(rattr, nt->attr) == 0){ rv = strdup(nt->val); if(pp != NULL) *pp = t; else ndbfree(t); return rv; } nt = nt->line; if(nt == s->t) break; } /* search whole tuple */ for(nt = t; nt; nt = nt->entry){ if(strcmp(rattr, nt->attr) == 0){ rv = strdup(nt->val); if(pp != NULL) *pp = t; else ndbfree(t); return rv; } } ndbfree(t); t = ndbsnext(s, attr, val); } return NULL; }
/* * return the ip addresses for a type of server for system ip */ int lookupserver(char *attr, uchar ipaddrs[2][IPaddrlen], Ipinfo *iip) { Ndbtuple *t, *nt; Ndbs s; char ip[32]; char name[Ndbvlen]; char name1[Ndbvlen]; int i; name[0] = name1[0] = 0; snprint(ip, sizeof(ip), "%I", iip->ipaddr); t = ndbsearch(db, &s, "ip", ip); while(t){ for(nt = t; nt; nt = nt->entry){ if(strcmp(attr, nt->attr) == 0){ if(*name == 0) strcpy(name, nt->val); else { strcpy(name1, nt->val); break; } } } if(name[0]) break; t = ndbsnext(&s, "ip", ip); } if(name[0] == 0) recursesubnet(db, iip->ipaddr, classmask[CLASS(iip->ipaddr)], attr, name, name1); i = 0; if(name[0] && getipaddr(db, name, *ipaddrs, iip) == 1){ ipaddrs++; i++; } if(name1[0] && getipaddr(db, name1, *ipaddrs, iip) == 1) i++; return i; }
int dbctlr(char* name, Vga* vga) { Ndb *db; Ndbs s; Ndbtuple *tuple; Ndbtuple *pcituple; db = dbopen(name); /* * Search vgadb for a matching BIOS string or PCI id. * If we have both, the BIOS string wins. */ pcituple = nil; for(tuple = ndbsearch(db, &s, "ctlr", ""); tuple; tuple = ndbsnext(&s, "ctlr", "")){ if(!pcituple && dbpci(vga, tuple)) pcituple = tuple; if(dbbios(vga, tuple)){ save(vga, tuple); if(pcituple && pcituple != tuple) ndbfree(pcituple); ndbfree(tuple); ndbclose(db); return 1; } if(tuple != pcituple) ndbfree(tuple); } if(pcituple){ save(vga, pcituple); ndbfree(pcituple); } ndbclose(db); if(pcituple) return 1; return 0; }
/* * fill in all the requested attributes for a system. * if the system's entry doesn't have all required, * walk through successively more inclusive networks * for inherited attributes. */ Ndbtuple* ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n) { Ndbtuple *t, *nt, *f; Ndbs s; char *ipstr; uint8_t net[IPaddrlen], ip[IPaddrlen]; int prefix, smallestprefix, force; int64_t r; /* just in case */ fmtinstall('I', eipfmt); fmtinstall('M', eipfmt); /* get needed attributes */ f = mkfilter(n, alist); /* * first look for a matching entry with an ip address */ t = nil; ipstr = ndbgetvalue(db, &s, attr, val, "ip", &nt); if(ipstr == nil){ /* none found, make one up */ if(strcmp(attr, "ip") != 0) { ndbfree(f); return nil; } t = ndbnew("ip", val); t->line = t; t->entry = nil; r = parseip(net, val); if(r == -1) ndbfree(t); } else { /* found one */ while(nt != nil){ nt = ndbreorder(nt, s.t); t = ndbconcatenate(t, nt); nt = ndbsnext(&s, attr, val); } r = parseip(net, ipstr); free(ipstr); } if(r < 0){ ndbfree(f); return nil; } ipmove(ip, net); t = filter(db, t, f); /* * now go through subnets to fill in any missing attributes */ if(isv4(net)){ prefix = 127; smallestprefix = 100; force = 0; } else { /* in v6, the last 8 bytes have no structure (we hope) */ prefix = 64; smallestprefix = 2; memset(net+8, 0, 8); force = 1; } /* * to find a containing network, keep turning off * the lower bit and look for a network with * that address and a shorter mask. tedius but * complete, we may need to find a trick to speed this up. */ for(; prefix >= smallestprefix; prefix--){ if(filtercomplete(f)) break; if(!force && (net[prefix/8] & (1<<(7-(prefix%8)))) == 0) continue; force = 0; net[prefix/8] &= ~(1<<(7-(prefix%8))); t = ndbconcatenate(t, subnet(db, net, f, prefix)); } /* * if there's an unfulfilled ipmask, make one up */ nt = ndbfindattr(f, f, "ipmask"); if(nt && !(nt->ptr & Fignore)){ char x[64]; snprint(x, sizeof(x), "%M", defmask(ip)); t = ndbconcatenate(t, ndbnew("ipmask", x)); } ndbfree(f); ndbsetmalloctag(t, getcallerpc(&db)); return t; }
/* * find out everything we can about a system from what has been * specified. */ int ipinfo(Ndb *db, char *etherin, char *ipin, char *name, Ipinfo *iip) { Ndbtuple *t; Ndbs s; char ether[Ndbvlen]; char ip[Ndbvlen]; char fsname[Ndbvlen]; char gwname[Ndbvlen]; char auname[Ndbvlen]; memset(iip, 0, sizeof(Ipinfo)); fsname[0] = 0; gwname[0] = 0; auname[0] = 0; /* * look for a matching entry */ t = 0; if(etherin) t = ndbgetval(db, &s, "ether", etherin, "ip", ip); if(t == 0 && ipin) t = ndbsearch(db, &s, "ip", ipin); if(t == 0 && name) t = ndbgetval(db, &s, ipattr(name), name, "ip", ip); if(t){ /* * copy in addresses and name */ if(lookval(t, s.t, "ip", ip)) parseip(iip->ipaddr, ip); if(lookval(t, s.t, "ether", ether)) parseether(iip->etheraddr, ether); lookval(t, s.t, "dom", iip->domain); /* * Look for bootfile, fs, and gateway. * If necessary, search through all entries for * this ip address. */ while(t){ if(iip->bootf[0] == 0) lookval(t, s.t, "bootf", iip->bootf); if(fsname[0] == 0) lookval(t, s.t, "fs", fsname); if(gwname[0] == 0) lookval(t, s.t, "ipgw", gwname); if(auname[0] == 0) lookval(t, s.t, "auth", auname); ndbfree(t); if(iip->bootf[0] && fsname[0] && gwname[0] && auname[0]) break; t = ndbsnext(&s, "ether", ether); } } else if(ipin) { /* * copy in addresses (all we know) */ parseip(iip->ipaddr, ipin); if(etherin) parseether(iip->etheraddr, etherin); } else return -1; /* * Look up the client's network and find a subnet mask for it. * Fill in from the subnet (or net) entry anything we can't figure * out from the client record. */ recursesubnet(db, classmask[CLASS(iip->ipaddr)], iip, fsname, gwname, auname); /* lookup fs's and gw's ip addresses */ if(fsname[0]) lookupip(db, fsname, iip->fsip, iip); if(gwname[0]) lookupip(db, gwname, iip->gwip, iip); if(auname[0]) lookupip(db, auname, iip->auip, iip); return 0; }
Mode* dbmode(char* name, char* type, char* size) { Ndb *db; Ndbs s; Ndbtuple *t, *tuple; Mode *mode; char attr[Namelen+1]; ulong videobw; db = dbopen(name); mode = alloc(sizeof(Mode)); strcpy(attr, type); videobw = 0; /* * Look for the attr=size entry. */ if(dbmonitor(db, mode, attr, size)){ strcpy(mode->type, type); strcpy(mode->size, size); ndbclose(db); return mode; } if(mode->videobw && videobw == 0) /* we at least found that; save it away */ videobw = mode->videobw; /* * Not found. Look for an attr="" entry and then * for an alias=attr within. */ buggery: for(tuple = ndbsearch(db, &s, attr, ""); tuple; tuple = ndbsnext(&s, attr, "")){ for(t = tuple->entry; t; t = t->entry){ if(strcmp(t->attr, "alias")) continue; strcpy(attr, t->val); if(dbmonitor(db, mode, attr, size)){ strcpy(mode->type, type); strcpy(mode->size, size); ndbfree(tuple); ndbclose(db); if(videobw) mode->videobw = videobw; return mode; } /* * Found an alias but no match for size, * restart looking for attr="" with the * new attr. */ ndbfree(tuple); goto buggery; } ndbfree(tuple); } free(mode); ndbclose(db); return 0; }
/* * 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(opendb() == nil){ warning(1, "can't open db"); return -1; } memset(iip, 0, sizeof(*iip)); /* client knows its address? */ v4tov6(ciaddr, bp->ciaddr); if(validip(ciaddr)){ if(lookupip(ciaddr, iip, 0) < 0) { if (debug) warning(0, "don't know %I", ciaddr); return -1; /* don't know anything about it */ } 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; }