Example #1
0
/*
 *  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;
}
Example #2
0
/*
 *  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;
}
Example #3
0
File: cs.c Project: brho/akaros
/*
 *  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";
}
Example #4
0
File: query.c Project: aahud/harvey
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);
	}
}
Example #5
0
/*
 *  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;
}
Example #6
0
/*
 *  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;
}
Example #7
0
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);
}
Example #8
0
/*
 *  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;
}
Example #9
0
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;
}
Example #10
0
/*
 *  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);
	}
}
Example #11
0
/*
 *  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;
}
Example #12
0
/* 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;
}
Example #13
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;
}
Example #14
0
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;
}
Example #15
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;
}