/* * use dns to resolve the mx request */ static int mxlookup(DS *ds, char *domain) { int i, n, nmx; Ndbtuple *t, *tmx, *tpref, *tip; strcpy(domain, ds->host); ds->netdir = "/net"; nmx = 0; if((t = dnsquery(nil, ds->host, "mx")) != nil){ for(tmx=t; (tmx=ndbfindattr(tmx->entry, nil, "mx")) != nil && nmx<Nmx; ){ for(tpref=tmx->line; tpref != tmx; tpref=tpref->line){ if(strcmp(tpref->attr, "pref") == 0){ strncpy(mx[nmx].host, tmx->val, sizeof(mx[n].host)-1); mx[nmx].pref = atoi(tpref->val); nmx++; break; } } } ndbfree(t); } /* * no mx record? try name itself. */ /* * BUG? If domain has no dots, then we used to look up ds->host * but return domain instead of ds->host in the list. Now we return * ds->host. What will this break? */ if(nmx == 0){ mx[0].pref = 1; strncpy(mx[0].host, ds->host, sizeof(mx[0].host)); nmx++; } /* * look up all ip addresses */ for(i = 0; i < nmx; i++){ if((t = dnsquery(nil, mx[i].host, "ip")) == nil) goto no; if((tip = ndbfindattr(t, nil, "ip")) == nil){ ndbfree(t); goto no; } strncpy(mx[i].ip, tip->val, sizeof(mx[i].ip)-1); ndbfree(t); continue; no: /* remove mx[i] and go around again */ nmx--; mx[i] = mx[nmx]; i--; } return nmx; }
/* * 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 parse(char *file) { int i; Ndb *db; Ndbtuple *t, *nt, *tt, *ipnett; char *p; db = ndbopen(file); if(db == 0) exits("no database"); while(t = ndbparse(db)){ for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ip") == 0) break; if(strcmp(nt->attr, "flavor") == 0 && strcmp(nt->val, "console") == 0) return; } if(nt == 0){ ndbfree(t); continue; } /* dump anything not on our nets */ ipnett = 0; for(tt = t; tt; tt = tt->entry){ if(strcmp(tt->attr, "ipnet") == 0){ ipnett = tt; break; } if(strcmp(tt->attr, "dom") == 0){ i = strlen(tt->val); p = tt->val+i-domnamlen; if(p >= tt->val && strcmp(p, domname) == 0) break; } } if(tt == 0){ ndbfree(t); continue; } for(; nt; nt = nt->entry){ if(strcmp(nt->attr, "ip") != 0) continue; x[nx].it = nt; x[nx].nt = ipnett; x[nx++].t = t; } } }
/* * return true of the speaker may speak for the user * * a speaker may always speak for himself/herself */ int speaksfor(char *speaker, char *user) { Ndbtuple *tp, *ntp; Ndbs s; int ok; char notuser[Maxpath]; if(strcmp(speaker, user) == 0) return 1; if(db == 0) return 0; tp = ndbsearch(db, &s, "hostid", speaker); if(tp == 0) return 0; ok = 0; snprint(notuser, sizeof notuser, "!%s", user); for(ntp = tp; ntp; ntp = ntp->entry) if(strcmp(ntp->attr, "uid") == 0){ if(strcmp(ntp->val, notuser) == 0){ ok = 0; break; } if(*ntp->val == '*' || strcmp(ntp->val, user) == 0) ok = 1; } ndbfree(tp); return ok; }
/* * lookup an ip address */ static int getipaddr(Ndb *db, char *name, uchar *to, Ipinfo *iip) { Ndbtuple *t, *nt; char buf[Ndbvlen]; uchar subnet[IPaddrlen]; Ndbs s; char *attr; attr = ipattr(name); if(strcmp(attr, "ip") == 0){ parseip(to, name); return 1; } t = ndbgetval(db, &s, attr, name, "ip", buf); if(t){ /* first look for match on same subnet */ for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ip") != 0) continue; parseip(to, nt->val); maskip(to, iip->ipmask, subnet); if(memcmp(subnet, iip->ipnet, sizeof(subnet)) == 0) return 1; } /* otherwise, just take what we have */ ndbfree(t); parseip(to, buf); return 1; } return 0; }
int nbnameresolve(NbName nbname, uchar *ipaddr) { ulong r, ttl; char name[NETPATHLEN]; NbName copy; Ndbtuple *t; /* for now, just use dns */ if (nbremotenametablefind(nbname, ipaddr)) { //print("%B found in cache\n", nbname); return 1; } if (nbnsfindname(nil, nbname, ipaddr, &ttl) == 0) { nbremotenametableadd(nbname, ipaddr, ttl); return 1; } nbnamecpy(copy, nbname); copy[NbNameLen - 1] = 0; nbmkstringfromname(name, sizeof(name), copy); t = dnsquery("/net", name, "ip"); if (t == nil) return 0; r = parseip(ipaddr, t->line->val); ndbfree(t); return r != -1; }
/* * 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; }
/* * 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; }
static void ndbcachefree(Ndbcache *c) { free(c->val); free(c->attr); if(c->t) ndbfree(c->t); free(c); }
void search(Ndb *db, char *attr, char *val, char **rattr, int nrattr) { Ndbtuple *t, *tt; tt = ndbipinfo(db, attr, val, rattr, nrattr); for(t = tt; t; t = t->entry) print("%s=%s ", t->attr, t->val); print("\n"); ndbfree(tt); }
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; }
/* * translate an ip service name into a port number. If it's a numeric port * number, look for restricted access. * * the service '*' needs no translation. */ static char *ipserv(struct network *np, char *name, char *buf, int blen) { char *p; int alpha = 0; int restr = 0; char port[10]; struct ndbtuple *t, *nt; struct ndbs s; /* '*' means any service */ if (strcmp(name, "*") == 0) { strlcpy(buf, name, blen); return buf; } /* see if it's numeric or symbolic */ port[0] = 0; for (p = name; *p; p++) { if (!isdigit(*p)) { if (isalpha(*p) || *p == '-' || *p == '$') alpha = 1; else return 0; } } t = NULL; p = NULL; if (alpha) { p = ndbgetvalue(db, &s, np->net, name, "port", &t); if (p == NULL) return 0; } else { /* look up only for tcp ports < 1024 to get the restricted * attribute */ if (atoi(name) < 1024 && strcmp(np->net, "tcp") == 0) p = ndbgetvalue(db, &s, "port", name, "port", &t); if (p == NULL) p = strdup(name); } if (t) { for (nt = t; nt; nt = nt->entry) if (strcmp(nt->attr, "restricted") == 0) restr = 1; ndbfree(t); } snprintf(buf, blen, "%s%s", p, restr ? "!r" : ""); free(p); return buf; }
/* * lookup an ip attribute */ static int ipattrlookup(struct ndb *db, char *ipa, char *attr, char *val, int vlen) { struct ndbtuple *t, *nt; char *alist[2]; alist[0] = attr; t = ndbipinfo(db, "ip", ipa, alist, 1); if (t == NULL) return 0; for (nt = t; nt != NULL; nt = nt->entry) { if (strcmp(nt->attr, attr) == 0) { strlcpy(val, nt->val, vlen); ndbfree(t); return 1; } } /* we shouldn't get here */ ndbfree(t); return 0; }
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); } }
/* * the database entry in 'file' indicates the list of files * that makeup the database. Open each one and search in * the same order. */ struct ndb* ndbopen(char *file) { struct ndb *db, *first, *last; struct ndbs s; struct ndbtuple *t, *nt; if(file == 0) file = deffile; db = doopen(file); if(db == 0) { return 0; } first = last = db; t = ndbsearch(db, &s, "database", ""); fseek(db->b, 0, 0); if(t == 0) { return db; } for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "file") != 0) continue; if(strcmp(nt->val, file) == 0){ /* default file can be reordered in the list */ if(first->next == 0) continue; if(strcmp(first->file, file) == 0){ db = first; first = first->next; last->next = db; db->next = 0; last = db; } continue; } db = doopen(nt->val); if(db == 0) continue; last->next = db; last = db; } ndbfree(t); return first; }
/* * resolve an ip address */ static struct ndbtuple *ipresolve(char *attr, char *host) { struct ndbtuple *t, *nt, **l; t = iplookup(&network[0], host, "*", 0); for (l = &t; *l != NULL;) { nt = *l; if (strcmp(nt->attr, "ip") != 0) { *l = nt->entry; nt->entry = NULL; ndbfree(nt); continue; } strlcpy(nt->attr, attr, sizeof(nt->attr)); l = &nt->entry; } return t; }
/* return list of ip addresses for a name */ Ndbtuple* ndbgetipaddr(Ndb *db, char *val) { char *attr, *p; Ndbtuple *it, *first, *last, *next; Ndbs s; /* already an IP address? */ attr = ipattr(val); if(strcmp(attr, "ip") == 0){ it = ndbnew("ip", val); ndbsetmalloctag(it, getcallerpc(&db)); return it; } /* look it up */ p = ndbgetvalue(db, &s, attr, val, "ip", &it); if(p == nil) return nil; free(p); /* remove the non-ip entries */ first = last = nil; for(; it; it = next){ next = it->entry; if(strcmp(it->attr, "ip") == 0){ if(first == nil) first = it; else last->entry = it; it->entry = nil; it->line = first; last = it; } else { it->entry = nil; ndbfree(it); } } ndbsetmalloctag(first, getcallerpc(&db)); return first; }
static void recursesubnet(Ndb *db, uchar *addr, uchar *mask, char *attr, char *name, char *name1) { Ndbs s; Ndbtuple *t, *nt; uchar submask[IPaddrlen], net[IPaddrlen]; char ip[Ndbvlen]; int found; maskip(addr, mask, net); sprint(ip, "%I", net); t = ndbsearch(db, &s, "ip", ip); if(t == 0) return; for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ipmask") == 0){ parseip(submask, nt->val); if(memcmp(submask, mask, IPaddrlen) != 0) recursesubnet(db, addr, submask, attr, name, name1); break; } } if(name[0] == 0){ found = 0; for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, attr) == 0){ if(found){ strcpy(name, nt->val); name1[0] = 0; found = 1; } else { strcpy(name1, nt->val); break; } } } } ndbfree(t); }
/* remove a from t and free it */ Ndbtuple* ndbdiscard(Ndbtuple *t, Ndbtuple *a) { Ndbtuple *nt; /* unchain a */ for(nt = t; nt != nil; nt = nt->entry){ if(nt->line == a) nt->line = a->line; if(nt->entry == a) nt->entry = a->entry; } /* a may be start of chain */ if(t == a) t = a->entry; /* free a */ a->entry = nil; ndbfree(a); return t; }
/* remove a from t and free it */ struct ndbtuple* ndbdiscard(struct ndbtuple *t, struct ndbtuple *a) { struct ndbtuple *nt; /* unchain a */ for(nt = t; nt != NULL; nt = nt->entry){ if(nt->line == a) nt->line = a->line; if(nt->entry == a) nt->entry = a->entry; } /* a may be start of chain */ if(t == a) t = a->entry; /* free a */ a->entry = NULL; ndbfree(a); ndbsetmalloctag(t, getcallerpc(&t)); return t; }
/* * lookup a subnet and fill in anything we can */ static void recursesubnet(Ndb *db, uint8_t *mask, Ipinfo *iip, char *fs, char *gw, char *au) { Ndbs s; Ndbtuple *t; uint8_t submask[IPaddrlen]; char ip[Ndbvlen]; memmove(iip->ipmask, mask, 4); maskip(iip->ipaddr, iip->ipmask, iip->ipnet); sprint(ip, "%I", iip->ipnet); t = ndbsearch(db, &s, "ip", ip); print("%s->", ip); if(t){ /* look for a further subnet */ if(lookval(t, s.t, "ipmask", ip)){ parseip(submask, ip); /* recurse only if it has changed */ if(!equivip(submask, mask)) recursesubnet(db, submask, iip, fs, gw, au); } /* fill in what we don't have */ if(gw[0] == 0) lookval(t, s.t, "ipgw", gw); if(fs[0] == 0) lookval(t, s.t, "fs", fs); if(au[0] == 0) lookval(t, s.t, "auth", au); ndbfree(t); } }
/* * get the system name */ static void ipid(void) { uint8_t addr[6]; struct ndbtuple *t, *tt; char *p, *attr; struct ndbs s; int f; char buf[Maxpath]; /* use environment, ether addr, or ipaddr to get system name */ if (mysysname == 0) { /* * environment has priority. * * on the sgi power the default system name * is the ip address. ignore that. * */ p = getenv("sysname"); if (p && *p) { attr = ipattr(p); if (strcmp(attr, "ip") != 0) mysysname = strdup(p); } /* * the /net/ndb contains what the network * figured out from DHCP. use that name if * there is one. */ if (mysysname == 0 && netdb != NULL) { ndbreopen(netdb); for (tt = t = ndbparse(netdb); t != NULL; t = t->entry) { if (strcmp(t->attr, "sys") == 0) { mysysname = strdup(t->val); break; } } ndbfree(tt); } /* next network database, ip address, and ether address to find * a name */ if (mysysname == 0) { t = NULL; if (isvalidip(ipa)) free(ndbgetvalue(db, &s, "ip", ipaddr, "sys", &t)); if (t == NULL) { for (f = 0; f < 3; f++) { snprintf(buf, sizeof(buf), "%s/ether%d", mntpt, f); if (myetheraddr(addr, buf) < 0) continue; snprintf(eaddr, sizeof(eaddr), "%E", addr); free(ndbgetvalue(db, &s, "ether", eaddr, "sys", &t)); if (t != NULL) break; } } for (tt = t; tt != NULL; tt = tt->entry) { if (strcmp(tt->attr, "sys") == 0) { mysysname = strdup(tt->val); break; } } ndbfree(t); } /* nothing else worked, use the ip address */ if (mysysname == 0 && isvalidip(ipa)) mysysname = strdup(ipaddr); /* set /dev/sysname if we now know it */ if (mysysname) { f = open("/dev/sysname", O_RDWR); if (f >= 0) { write(f, mysysname, strlen(mysysname)); close(f); } } } }
/* * 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* csgetvalue(char *netroot, char *attr, char *val, char *rattr, Ndbtuple **pp) { Ndbtuple *t, *first, *last; int n, linefound; char line[1024]; int fd; int oops = 0; char *rv; if(pp) *pp = nil; rv = nil; if(netroot) snprint(line, sizeof(line), "%s/cs", netroot); else strcpy(line, "/net/cs"); fd = open(line, ORDWR); if(fd < 0) return 0; seek(fd, 0, 0); snprint(line, sizeof(line), "!%s=%s %s=*", attr, val, rattr); if(write(fd, line, strlen(line)) < 0){ close(fd); return 0; } seek(fd, 0, 0); first = last = 0; linefound = 0; for(;;){ n = read(fd, line, sizeof(line)-2); if(n <= 0) break; line[n] = '\n'; line[n+1] = 0; t = _ndbparseline(line); if(t == 0) continue; if(first) last->entry = t; else first = t; last = t; while(last->entry) last = last->entry; for(; t; t = t->entry){ if(linefound == 0){ if(strcmp(rattr, t->attr) == 0){ linefound = 1; rv = strdup(t->val); } } } } close(fd); if(oops){ werrstr("buffer too short"); ndbfree(first); return nil; } if(pp){ setmalloctag(first, getcallerpc(&netroot)); *pp = first; } else ndbfree(first); return rv; }
static int dbmonitor(Ndb* db, Mode* mode, char* type, char* size) { Ndbs s; Ndbtuple *t, *tuple; char *p, attr[Namelen+1], val[Namelen+1], buf[2*Namelen+1]; int clock, x, i; /* * Clock rate hack. * If the size is 'XxYxZ@NMHz' then override the database entry's * 'clock=' with 'N*1000000'. */ clock = 0; strcpy(buf, size); if(p = strchr(buf, '@')){ *p++ = 0; if((clock = strtol(p, &p, 0)) && strcmp(p, "MHz") == 0) clock *= 1000000; } memset(mode, 0, sizeof(Mode)); if((p = strchr(buf, 'x')) && (p = strchr(p+1, 'x'))){ *p++ = 0; mode->z = atoi(p); } strcpy(attr, type); strcpy(val, buf); if(p = ndbgetvalue(db, &s, attr, "", "videobw", nil)){ mode->videobw = atol(p)*1000000UL; free(p); } if(mode->x == 0 && ((mode->x = strtol(val, &p, 0)) == 0 || *p++ != 'x')) return 0; if(mode->y == 0 && (mode->y = strtol(p, &p, 0)) == 0) return 0; i = 0; buggery: if((tuple = ndbsearch(db, &s, attr, val)) == 0) return 0; for(t = tuple->entry; t; t = t->entry){ if(strcmp(t->attr, "clock") == 0 && mode->frequency == 0) mode->frequency = strtod(t->val, 0)*1000000; else if(strcmp(t->attr, "defaultclock") == 0 && mode->deffrequency == 0) mode->deffrequency = strtod(t->val, 0)*1000000; else if(strcmp(t->attr, "ht") == 0 && mode->ht == 0) mode->ht = strtol(t->val, 0, 0); else if(strcmp(t->attr, "shb") == 0 && mode->shb == 0) mode->shb = strtol(t->val, 0, 0); else if(strcmp(t->attr, "ehb") == 0 && mode->ehb == 0) mode->ehb = strtol(t->val, 0, 0); else if(strcmp(t->attr, "shs") == 0 && mode->shs == 0) mode->shs = strtol(t->val, 0, 0); else if(strcmp(t->attr, "ehs") == 0 && mode->ehs == 0) mode->ehs = strtol(t->val, 0, 0); else if(strcmp(t->attr, "vt") == 0 && mode->vt == 0) mode->vt = strtol(t->val, 0, 0); else if(strcmp(t->attr, "vrs") == 0 && mode->vrs == 0) mode->vrs = strtol(t->val, 0, 0); else if(strcmp(t->attr, "vre") == 0 && mode->vre == 0) mode->vre = strtol(t->val, 0, 0); else if(strcmp(t->attr, "hsync") == 0) mode->hsync = *t->val; else if(strcmp(t->attr, "vsync") == 0) mode->vsync = *t->val; else if(strcmp(t->attr, "interlace") == 0) mode->interlace = *t->val; else if(strcmp(t->attr, "include") == 0 /*&& strcmp(t->val, val) != 0*/){ strcpy(attr, t->attr); strcpy(val, t->val); ndbfree(tuple); if(i++ > 5) error("dbmonitor: implausible include depth at %s=%s\n", attr, val); goto buggery; } else if(strcmp(t->attr, "include") == 0){ print("warning: bailed out of infinite loop in attr %s=%s\n", attr, val); } else addattr(&mode->attr, t); } ndbfree(tuple); if((x = strtol(size, &p, 0)) == 0 || x != mode->x || *p++ != 'x') return 0; if((x = strtol(p, &p, 0)) == 0 || x != mode->y || *p++ != 'x') return 0; if((x = strtol(p, &p, 0)) == 0 || x != mode->z) return 0; if(clock) mode->frequency = clock; return 1; }
/* * 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; }
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 a request. the network "net" means we should pick the * best network to get there. */ static int lookup(struct mfile *mf) { struct network *np; char *cp; struct ndbtuple *nt, *t; char reply[Maxreply]; int i, rv; int hack; /* open up the standard db files */ if (db == 0) ndbinit(); if (db == 0) error(1, 0, "%s: %r", "can't open mf->network database\n"); rv = 0; if (mf->net == NULL) return 0; /* must have been a genquery */ if (strcmp(mf->net, "net") == 0) { /* * go through set of default nets */ for (np = mf->nextnet; np; np = np->next) { nt = (*np->lookup)(np, mf->host, mf->serv, 1); if (nt == NULL) continue; hack = np->fasttimeouthack && !lookforproto(nt, np->net); for (t = nt; mf->nreply < Nreply && t; t = t->entry) { cp = (*np->trans)(t, np, mf->serv, mf->rem, hack); if (!cp) continue; /* avoid duplicates */ for (i = 0; i < mf->nreply; i++) if (strcmp(mf->reply[i], cp) == 0) break; if (i == mf->nreply) { /* save the reply */ mf->replylen[mf->nreply] = strlen(cp); mf->reply[mf->nreply++] = cp; rv++; } } ndbfree(nt); np = np->next; break; } mf->nextnet = np; return rv; } /* * if not /net, we only get one lookup */ if (mf->nreply != 0) return 0; /* * look for a specific network */ for (np = netlist; np && np->net != NULL; np++) { if (np->fasttimeouthack) continue; if (strcmp(np->net, mf->net) == 0) break; } if (np && np->net != NULL) { /* * known network */ nt = (*np->lookup)(np, mf->host, mf->serv, 1); for (t = nt; mf->nreply < Nreply && t; t = t->entry) { cp = (*np->trans)(t, np, mf->serv, mf->rem, 0); if (cp) { mf->replylen[mf->nreply] = strlen(cp); mf->reply[mf->nreply++] = cp; rv++; } } ndbfree(nt); return rv; } /* * not a known network, don't translate host or service */ if (mf->serv) snprintf(reply, sizeof(reply), "%s/%s/clone %s!%s", mntpt, mf->net, mf->host, mf->serv); else snprintf(reply, sizeof(reply), "%s/%s/clone %s", mntpt, mf->net, mf->host); mf->reply[0] = strdup(reply); mf->replylen[0] = strlen(reply); mf->nreply = 1; return 1; }
/* returns 0 on success, error message on failure */ char* secureidcheck(char *user, char *response) { Packet *req = nil, *resp = nil; ulong u[4]; uchar x[16]; char *radiussecret; char ruser[ 64]; char dest[3*IPaddrlen+20]; Secret shared, pass; char *rv = "authentication failed"; Ndbs s; Ndbtuple *t, *nt, *tt; uchar *ip; static Ndb *netdb; if(netdb == nil) netdb = ndbopen(0); /* bad responses make them disable the fob, avoid silly checks */ if(strlen(response) < 4 || strpbrk(response,"abcdefABCDEF") != nil) goto out; /* get radius secret */ radiussecret = ndbgetvalue(db, &s, "radius", "lra-radius", "secret", &t); if(radiussecret == nil){ syslog(0, AUTHLOG, "secureidcheck: nil radius secret: %r"); goto out; } /* translate user name if we have to */ strcpy(ruser, user); for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "uid") == 0 && strcmp(nt->val, user) == 0) for(tt = nt->line; tt != nt; tt = tt->line) if(strcmp(tt->attr, "rid") == 0){ strcpy(ruser, tt->val); break; } } ndbfree(t); u[0] = fastrand(); u[1] = fastrand(); u[2] = fastrand(); u[3] = fastrand(); req = newRequest((uchar*)u); if(req == nil) goto out; shared.s = (uchar*)radiussecret; shared.len = strlen(radiussecret); ip = getipv4addr(); if(ip == nil){ syslog(0, AUTHLOG, "no interfaces: %r\n"); goto out; } if(setAttribute(req, R_NASIPAddress, ip + IPv4off, 4) < 0) goto out; if(setAttribute(req, R_UserName, (uchar*)ruser, strlen(ruser)) < 0) goto out; pass.s = (uchar*)response; pass.len = strlen(response); hide(&shared, req->authenticator, &pass, x); if(setAttribute(req, R_UserPassword, x, 16) < 0) goto out; t = ndbsearch(netdb, &s, "sys", "lra-radius"); if(t == nil){ syslog(0, AUTHLOG, "secureidcheck: nil radius sys search: %r\n"); goto out; } for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ip") != 0) continue; snprint(dest,sizeof dest,"udp!%s!oradius", nt->val); resp = rpc(dest, &shared, req); if(resp == nil){ syslog(0, AUTHLOG, "%s nil response", dest); continue; } if(resp->ID != req->ID){ syslog(0, AUTHLOG, "%s mismatched ID req=%d resp=%d", dest, req->ID, resp->ID); freePacket(resp); resp = nil; continue; } switch(resp->code){ case R_AccessAccept: syslog(0, AUTHLOG, "%s accepted ruser=%s", dest, ruser); rv = nil; break; case R_AccessReject: syslog(0, AUTHLOG, "%s rejected ruser=%s %s", dest, ruser, replymsg(resp)); rv = "secureid failed"; break; case R_AccessChallenge: syslog(0, AUTHLOG, "%s challenge ruser=%s %s", dest, ruser, replymsg(resp)); rv = "secureid out of sync"; break; default: syslog(0, AUTHLOG, "%s code=%d ruser=%s %s", dest, resp->code, ruser, replymsg(resp)); break; } break; /* we have a proper reply, no need to ask again */ } ndbfree(t); free(radiussecret); out: freePacket(req); freePacket(resp); return rv; }
/* * 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; }
static char *ipinfoquery(struct mfile *mf, char **list, int n) { int i, nresolve; int resolve[Maxattr]; struct ndbtuple *t, *nt, **l; char *attr, *val; /* skip 'ipinfo' */ list++; n--; if (n < 1) return "bad query"; /* get search attribute=value, or assume ip=myipaddr */ attr = *list; val = strchr(attr, '='); if (val != NULL) { *val++ = 0; list++; n--; } else { attr = "ip"; val = ipaddr; } if (n < 1) return "bad query"; /* * don't let ndbipinfo resolve the addresses, we're * better at it. */ nresolve = 0; for (i = 0; i < n; i++) if (*list[i] == '@') { /* @attr=val ? */ list[i]++; resolve[i] = 1; /* we'll resolve it */ nresolve++; } else resolve[i] = 0; t = ndbipinfo(db, attr, val, list, n); if (t == NULL) return "no match"; if (nresolve != 0) { for (l = &t; *l != NULL;) { nt = *l; /* already an address? */ if (strcmp(ipattr(nt->val), "ip") == 0) { l = &(*l)->entry; continue; } /* user wants it resolved? */ for (i = 0; i < n; i++) if (strcmp(list[i], nt->attr) == 0) break; if (i >= n || resolve[i] == 0) { l = &(*l)->entry; continue; } /* resolve address and replace entry */ *l = ipresolve(nt->attr, nt->val); while (*l != NULL) l = &(*l)->entry; *l = nt->entry; nt->entry = NULL; ndbfree(nt); } } /* make it all one line */ for (nt = t; nt != NULL; nt = nt->entry) { if (nt->entry == NULL) nt->line = t; else nt->line = nt->entry; } qreply(mf, t); return NULL; }