Exemple #1
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;
}
Exemple #2
0
/*
 *  return only the attr/value pairs in t maching the filter, f.
 *  others are freed.  line structure is preserved.
 */
static Ndbtuple*
filter(Ndb *db, Ndbtuple *t, Ndbtuple *f)
{
	Ndbtuple *nt, *nf, *next;

	/* filter out what we don't want */
	for(nt = t; nt; nt = next){
		next = nt->entry;

		/* look through filter */
		for(nf = f; nf != nil; nf = nf->entry){
			if(!(nf->ptr&Fignore) && strcmp(nt->attr, nf->attr) == 0)
				break;
		}
		if(nf == nil){
			/* remove nt from t */
			t = ndbdiscard(t, nt);
		} else {
			if(nf->ptr & Faddr)
				t = ndbsubstitute(t, nt, setattr(ndbgetipaddr(db, nt->val), nt->attr));
			nf->ptr |= Ffound;
		}
	}

	/* remember filter etnries that matched */
	for(nf = f; nf != nil; nf = nf->entry)
		if(nf->ptr & Ffound)
			nf->ptr = (nf->ptr & ~Ffound) | Fignore;

	ndbsetmalloctag(t, getcallerpc(&db));
	return t;
}
Exemple #3
0
/*
 *  parse the next entry in the file
 */
struct ndbtuple*
ndbparse(struct ndb *db)
{
	char *line;
	struct ndbtuple *t;
	struct ndbtuple *first, *last;
	int len;

	first = last = 0;
	for(;;){
		if((line = fgets(db->buf, sizeof(db->buf),db->b)) == 0)
			break;
		len = strlen(db->buf);
		if(line[len-1] != '\n')
			break;
		if(first && !isspace(*line) && *line != '#'){
			fseek(db->b, -len, 1);
			break;
		}
		t = _ndbparseline(line);
		if(t == 0)
			continue;
		if(first)
			last->entry = t;
		else
			first = t;
		last = t;
		while(last->entry)
			last = last->entry;
	}
	ndbsetmalloctag(first, getcallerpc(&db));
	return first;
}
Exemple #4
0
/*
 *  parse all tuples in a line.  we assume that the
 *  line ends in a '\n'.
 *
 *  the tuples are linked as a list using ->entry and
 *  as a ring using ->line.
 */
Ndbtuple*
_ndbparseline(char *cp)
{
	Ndbtuple *t;
	Ndbtuple *first, *last;

	first = last = 0;
	while(*cp != '#' && *cp != '\n'){
		t = 0;
		cp = _ndbparsetuple(cp, &t);
		if(cp == 0)
			break;
		if(first){
			last->line = t;
			last->entry = t;
		} else
			first = t;
		last = t;
		t->line = 0;
		t->entry = 0;
		setmalloctag(t, getcallerpc());
	}
	if(first)
		last->line = first;
	ndbsetmalloctag(first, getcallerpc());
	return first;
}
Exemple #5
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.
 */
Ndbtuple*
dnsquery(char *net, char *val, char *type)
{
    char rip[128];
    char *p;
    Ndbtuple *t;
    int fd;

    /* if the address is V4 or V6 null address, give up early */
    if(strcmp(val, "::") == 0 || strcmp(val, "0.0.0.0") == 0)
        return nil;

    if(net == nil)
        net = "/net";
    snprint(rip, sizeof(rip), "%s/dns", net);
    fd = open(rip, ORDWR);
    if(fd < 0) {
        if(strcmp(net, "/net") == 0)
            snprint(rip, sizeof(rip), "/srv/dns");
        else {
            snprint(rip, sizeof(rip), "/srv/dns%s", net);
            p = strrchr(rip, '/');
            *p = '_';
        }
        fd = open(rip, ORDWR);
        if(fd < 0)
            return nil;
        if(mount(fd, -1, net, MBEFORE, "") < 0) {
            close(fd);
            return nil;
        }
        /* fd is now closed */
        snprint(rip, sizeof(rip), "%s/dns", net);
        fd = open(rip, ORDWR);
        if(fd < 0)
            return nil;
    }

    /* zero out the error string */
    werrstr("");

    /* if this is a reverse lookup, first lookup the domain name */
    if(strcmp(type, "ptr") == 0) {
        mkptrname(val, rip, sizeof rip);
        t = doquery(fd, rip, "ptr");
    } else
        t = doquery(fd, val, type);

    /*
     * TODO: make fd static and keep it open to reduce 9P traffic
     * walking to /net*^/dns.
     */
    close(fd);
    ndbsetmalloctag(t, getcallerpc(&net));
    return t;
}
Exemple #6
0
/* 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;
}
Exemple #7
0
static Ndbtuple*
doquery(int fd, char *dn, char *type)
{
    char buf[1024];
    int n;
    Ndbtuple *t, *first, *last;

    seek(fd, 0, 0);
    snprint(buf, sizeof(buf), "!%s %s", dn, type);
    if(write(fd, buf, strlen(buf)) < 0)
        return nil;

    seek(fd, 0, 0);

    first = last = nil;

    for(;;) {
        n = read(fd, buf, sizeof(buf)-2);
        if(n <= 0)
            break;
        if(buf[n-1] != '\n')
            buf[n++] = '\n';	/* ndbparsline needs a trailing new line */
        buf[n] = 0;

        /* check for the error condition */
        if(buf[0] == '!') {
            werrstr("%s", buf+1);
            return nil;
        }

        t = _ndbparseline(buf);
        if(t != nil) {
            if(first)
                last->entry = t;
            else
                first = t;
            last = t;

            while(last->entry)
                last = last->entry;
        }
    }

    ndbsetmalloctag(first, getcallerpc(&fd));
    return first;
}
Exemple #8
0
/*
 *  allocate a tuple
 */
struct ndbtuple*
ndbnew(char *attr, char *val)
{
	struct ndbtuple *t;

	t = calloc(1, sizeof(*t));
	if(t == NULL){
		fprintf(stderr, "ndbnew %r");
		exit(1);
	}
	if(attr != NULL)
		strncpy(t->attr, attr, sizeof(t->attr)-1);
	t->val = t->valbuf;
	if(val != NULL)
		ndbsetval(t, val, strlen(val));
	ndbsetmalloctag(t, getcallerpc(&attr));
	return t;	
}
Exemple #9
0
struct ndbtuple*
ndbgetval(struct ndb *db,
	  struct ndbs *s, char *attr, char *val, char *rattr, char *buf)
{
	struct ndbtuple *t;
	char *p;

	p = ndbgetvalue(db, s, attr, val, rattr, &t);
	if(p == NULL){
		if(buf != NULL)
			*buf = 0;
	} else {
		if(buf != NULL){
			strncpy(buf, p, Ndbvlen-1);
			buf[Ndbvlen-1] = 0;
		}
		free(p);
	}
	ndbsetmalloctag(t, getcallerpc(&db));
	return t;
}
Exemple #10
0
static Ndbtuple*
ndbcopy(Ndb *db, Ndbtuple *from_t, Ndbs *from_s, Ndbs *to_s)
{
	Ndbtuple *first, *to_t, *last, *line;
	int newline;

	*to_s = *from_s;
	to_s->t = nil;
	to_s->db = db;

	newline = 1;
	last = nil;
	first = nil;
	line = nil;
	for(; from_t != nil; from_t = from_t->entry){
		to_t = ndbnew(from_t->attr, from_t->val);

		/* have s point to matching tuple */
		if(from_s->t == from_t)
			to_s->t = to_t;

		if(newline)
			line = to_t;
		else
			last->line = to_t;

		if(last != nil)
			last->entry = to_t;
		else {
			first = to_t;
			line = to_t;
		}
		to_t->entry = nil;
		to_t->line = line;
		last = to_t;
		newline = from_t->line != from_t->entry;
	}
	ndbsetmalloctag(first, getcallerpc(&db));
	return first;
}
Exemple #11
0
/* make a filter to be used in filter */
static Ndbtuple*
mkfilter(int argc, char **argv)
{
	Ndbtuple *t, *first, *last;
	char *p;

	last = first = nil;
	while(argc-- > 0){
		t = ndbnew(0, 0);
		if(first)
			last->entry = t;
		else
			first = t;
		last = t;
		p = *argv++;
		if(*p == '@'){			/* @attr=val ? */
			t->ptr |= Faddr;	/* return resolved address(es) */
			p++;
		}
		strncpy(t->attr, p, sizeof(t->attr)-1);
	}
	ndbsetmalloctag(first, getcallerpc(&argc));
	return first;
}
Exemple #12
0
/* 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;
}
Exemple #13
0
Ndbtuple*
_ndbcacheadd(Ndb *db, Ndbs *s, char *attr, char *val, Ndbtuple *t)
{
	Ndbcache *c, **l;

	c = mallocz(sizeof *c, 1);
	if(c == nil)
		return nil;
	c->attr = strdup(attr);
	if(c->attr == nil)
		goto err;
	c->val = strdup(val);
	if(c->val == nil)
		goto err;
	c->t = ndbcopy(db, t, s, &c->s);
	if(c->t == nil && t != nil)
		goto err;

	/* add to front */
	c->next = db->cache;
	db->cache = c;

	/* trim list */
	if(db->ncache < Maxcached){
		db->ncache++;
		return t;
	}
	for(l = &db->cache; (*l)->next; l = &(*l)->next)
		;
	c = *l;
	*l = nil;
err:
	ndbcachefree(c);
	ndbsetmalloctag(t, getcallerpc(&db));
	return t;
}
Exemple #14
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;
}
Exemple #15
0
/*
 *  look up the ip attributes 'list' for an entry that has the
 *  given 'attr=val' and a 'ip=' tuples.
 *
 *  return NULL if not found.
 */
struct ndbtuple*
csipinfo(char *netroot, char *attr, char *val, char **list, int n)
{
	struct ndbtuple *t, *first, *last;
	int i;
	char line[1024];
	int fd;
	char *p, *e;
	int left,amt;

	if(netroot)
		snprintf(line, sizeof(line), "%s/cs", netroot);
	else
		strcpy(line, "/net/cs");
	fd = open(line, O_RDWR);
	if(fd < 0)
		return 0;
	lseek(fd, 0, 0);
	left = sizeof(line);
	amt = snprintf(line, left, "!ipinfo %s=%s", attr, val);
	if(amt < 0)
		return 0;
	left -= amt;
	for(i = 0; i < n; i++){
		if(*list == NULL)
			break;
		amt = snprintf(p, left, " %s", *list++);
		if(amt < 0)
			return 0;
		left -= amt;
	}
	
	if(write(fd, line, strlen(line)) < 0){
		close(fd);
		return 0;
	}
	lseek(fd, 0, 0);

	first = last = 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;
	}
	close(fd);

	ndbsetmalloctag(first, getcallerpc(&netroot));
	return first;
}