Esempio n. 1
0
File: cs.c Progetto: brho/akaros
/*
 *  call the dns process and have it try to translate a name
 */
static struct ndbtuple *dnsiplookup(char *host, struct ndbs *s)
{
	char buf[Maxreply];
	struct ndbtuple *t;

	spinlock_unlock(&dblock);

	/* save the name */
	snprintf(buf, sizeof(buf), "%s", host);

	if (strcmp(ipattr(buf), "ip") == 0)
		t = dnsquery(mntpt, buf, "ptr");
	else {
		t = dnsquery(mntpt, buf, "ip");
		/* special case: query ipv6 (AAAA dns RR) too */
		if (ipv6lookups)
			t = dnsip6lookup(mntpt, buf, t);
	}
	s->t = t;

	if (t == NULL) {
		snprintf(buf, sizeof(buf), "%r");
		if (strstr(buf, "exist"))
			werrstr("can't translate address: %s", buf);
		else if (strstr(buf, "dns failure"))
			werrstr("temporary problem: %s", buf);
	}

	spinlock_lock(&dblock);
	return t;
}
Esempio n. 2
0
/*
 *  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;
}
Esempio n. 3
0
File: rmtdns.c Progetto: npe9/harvey
int
rmtdns(char *net, char *path)
{
	int fd, n, nb, r;
	char *domain, *cp, buf[Maxdomain + 5];

	if(net == 0 || path == 0)
		return 0;

	domain = strdup(path);
	cp = strchr(domain, '!');
	if(cp){
		*cp = 0;
		n = cp-domain;
	} else
		n = strlen(domain);

	if(*domain == '[' && domain[n-1] == ']'){ /* accept [nnn.nnn.nnn.nnn] */
		domain[n-1] = 0;
		r = strcmp(ipattr(domain+1), "ip");
		domain[n-1] = ']';
	} else
		r = strcmp(ipattr(domain), "ip"); /* accept nnn.nnn.nnn.nnn */
	if(r == 0){
		free(domain);
		return 0;
	}

	snprint(buf, sizeof buf, "%s/dns", net);
	fd = open(buf, ORDWR);			/* look up all others */
	if(fd < 0){				/* dns screw up - can't check */
		free(domain);
		return 0;
	}

	n = snprint(buf, sizeof buf, "%s all", domain);
	free(domain);
	seek(fd, 0, 0);
	nb = write(fd, buf, n);
	close(fd);
	if(nb != n){
		rerrstr(buf, sizeof buf);
		if (strcmp(buf, "dns: name does not exist") == 0)
			return -1;
	}
	return 0;
}
Esempio n. 4
0
/* notify a slave that an area has changed. */
static void
send_notify(char *slave, RR *soa, Request *req)
{
	int i, len, n, reqno, status, fd;
	char *err;
	uchar ibuf[Maxudp+Udphdrsize], obuf[Maxudp+Udphdrsize];
	RR *rp;
	Udphdr *up = (Udphdr*)obuf;
	DNSmsg repmsg;

	/* create the request */
	reqno = rand();
	n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno);

	/* get an address */
	if(strcmp(ipattr(slave), "ip") == 0) {
		if (parseip(up->raddr, slave) == -1)
			dnslog("bad address %s to notify", slave);
	} else {
		rp = dnresolve(slave, Cin, Ta, req, nil, 0, 1, 1, &status);
		if(rp == nil)
			rp = dnresolve(slave, Cin, Taaaa, req, nil, 0, 1, 1, &status);
		if(rp == nil)
			return;
		parseip(up->raddr, rp->ip->name);
		rrfreelist(rp);		/* was rrfree */
	}

	fd = udpport(nil);
	if(fd < 0)
		return;

	/* send 3 times or until we get anything back */
	n += Udphdrsize;
	for(i = 0; i < 3; i++, freeanswers(&repmsg)){
		dnslog("sending %d byte notify to %s/%I.%d about %s", n, slave,
			up->raddr, nhgets(up->rport), soa->owner->name);
		memset(&repmsg, 0, sizeof repmsg);
		if(write(fd, obuf, n) != n)
			break;
		alarm(2*1000);
		len = read(fd, ibuf, sizeof ibuf);
		alarm(0);
		if(len <= Udphdrsize)
			continue;
		err = convM2DNS(&ibuf[Udphdrsize], len, &repmsg, nil);
		if(err != nil) {
			free(err);
			continue;
		}
		if(repmsg.id == reqno && (repmsg.flags & Omask) == Onotify)
			break;
	}
	if (i < 3)
		freeanswers(&repmsg);
	close(fd);
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}
Esempio n. 7
0
File: cs.c Progetto: brho/akaros
/*
 *  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);
			}
		}
	}
}
Esempio n. 8
0
File: cs.c Progetto: brho/akaros
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;
}
Esempio n. 9
0
File: cs.c Progetto: brho/akaros
/*
 *  lookup (and translate) an ip destination
 */
static struct ndbtuple *iplookup(struct network *np, char *host, char *serv,
                                 int nolookup)
{
	char *attr, *dnsname;
	struct ndbtuple *t, *nt;
	struct ndbs s;
	char ts[Maxservice];
	char dollar[Maxhost];
	uint8_t ip[IPaddrlen];
	uint8_t net[IPaddrlen];
	uint8_t tnet[IPaddrlen];
	struct ipifc *ifc;
	struct iplifc *lifc;

	/*
	 *  start with the service since it's the most likely to fail
	 *  and costs the least
	 */
	werrstr("can't translate address");
	if (serv == 0 || ipserv(np, serv, ts, sizeof(ts)) == 0) {
		werrstr("can't translate service");
		return 0;
	}

	/* for dial strings with no host */
	if (strcmp(host, "*") == 0)
		return ndbnew("ip", "*");

	/*
	 *  hack till we go v6 :: = 0.0.0.0
	 */
	if (strcmp("::", host) == 0)
		return ndbnew("ip", "*");

	/*
	 *  '$' means the rest of the name is an attribute that we
	 *  need to search for
	 */
	if (*host == '$') {
		if (ipattrlookup(db, ipaddr, host + 1, dollar, sizeof(dollar)))
			host = dollar;
	}

	/*
	 *  turn '[ip address]' into just 'ip address'
	 */
	if (*host == '[' && host[strlen(host) - 1] == ']') {
		host++;
		host[strlen(host) - 1] = 0;
	}

	/*
	 *  just accept addresses
	 */
	attr = ipattr(host);
	if (strcmp(attr, "ip") == 0)
		return ndbnew("ip", host);

	/*
	 *  give the domain name server the first opportunity to
	 *  resolve domain names.  if that fails try the database.
	 */
	t = 0;
	werrstr("can't translate address");
	if (strcmp(attr, "dom") == 0)
		t = dnsiplookup(host, &s);
	if (t == 0)
		free(ndbgetvalue(db, &s, attr, host, "ip", &t));
	if (t == 0) {
		dnsname = ndbgetvalue(db, &s, attr, host, "dom", NULL);
		if (dnsname) {
			t = dnsiplookup(dnsname, &s);
			free(dnsname);
		}
	}
	if (t == 0)
		t = dnsiplookup(host, &s);
	if (t == 0)
		return 0;

	/*
	 *  reorder the tuple to have the matched line first and
	 *  save that in the request structure.
	 */
	t = reorder(t, s.t);

	/*
	 * reorder according to our interfaces
	 */
	spinlock_lock(&ipifclock);
	for (ifc = ipifcs; ifc != NULL; ifc = ifc->next) {
		for (lifc = ifc->lifc; lifc != NULL; lifc = lifc->next) {
			maskip(lifc->ip, lifc->mask, net);
			for (nt = t; nt; nt = nt->entry) {
				if (strcmp(nt->attr, "ip") != 0)
					continue;
				parseip(ip, nt->val);
				maskip(ip, lifc->mask, tnet);
				if (memcmp(net, tnet, IPaddrlen) == 0) {
					t = reorder(t, nt);
					spinlock_unlock(&ipifclock);
					return t;
				}
			}
		}
	}
	spinlock_unlock(&ipifclock);

	return t;
}