Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <ndb.h>
5
#include <ndbhf.h>
6
 
7
static void nstrcpy(char*, char*, int);
8
static void mkptrname(char*, char*, int);
9
static Ndbtuple *doquery(int, char *dn, char *type);
10
 
11
/*
12
 *  search for a tuple that has the given 'attr=val' and also 'rattr=x'.
13
 *  copy 'x' into 'buf' and return the whole tuple.
14
 *
15
 *  return 0 if not found.
16
 */
17
Ndbtuple*
18
dnsquery(char *net, char *val, char *type)
19
{
20
	char rip[128];
21
	char *p;
22
	Ndbtuple *t;
23
	int fd;
24
 
25
	/* if the address is V4 or V6 null address, give up early */
26
	if(strcmp(val, "::") == 0 || strcmp(val, "0.0.0.0") == 0)
27
		return nil;
28
 
29
	if(net == nil)
30
		net = "/net";
31
	snprint(rip, sizeof(rip), "%s/dns", net);
32
	fd = open(rip, ORDWR);
33
	if(fd < 0){
34
		if(strcmp(net, "/net") == 0)
35
			snprint(rip, sizeof(rip), "/srv/dns");
36
		else {
37
			snprint(rip, sizeof(rip), "/srv/dns%s", net);
38
			p = strrchr(rip, '/');
39
			*p = '_';
40
		}
41
		fd = open(rip, ORDWR);
42
		if(fd < 0)
43
			return nil;
44
		if(mount(fd, -1, net, MBEFORE, "") < 0){
45
			close(fd);
46
			return nil;
47
		}
48
		/* fd is now closed */
49
		snprint(rip, sizeof(rip), "%s/dns", net);
50
		fd = open(rip, ORDWR);
51
		if(fd < 0)
52
			return nil;
53
	}
54
 
55
	/* zero out the error string */
56
	werrstr("");
57
 
58
	/* if this is a reverse lookup, first lookup the domain name */
59
	if(strcmp(type, "ptr") == 0){
60
		mkptrname(val, rip, sizeof rip);
61
		t = doquery(fd, rip, "ptr");
62
	} else
63
		t = doquery(fd, val, type);
64
 
65
	/*
66
	 * TODO: make fd static and keep it open to reduce 9P traffic
67
	 * walking to /net*^/dns.  Must be prepared to re-open it on error.
68
	 */
69
	close(fd);
70
	ndbsetmalloctag(t, getcallerpc(&net));
71
	return t;
72
}
73
 
74
/*
75
 *  convert address into a reverse lookup address
76
 */
77
static void
78
mkptrname(char *ip, char *rip, int rlen)
79
{
80
	char buf[128];
81
	char *p, *np;
82
	int len;
83
 
84
	if(cistrstr(ip, "in-addr.arpa") || cistrstr(ip, "ip6.arpa")){
85
		nstrcpy(rip, ip, rlen);
86
		return;
87
	}
88
 
89
	nstrcpy(buf, ip, sizeof buf);
90
	for(p = buf; *p; p++)
91
		;
92
	*p = '.';
93
	np = rip;
94
	len = 0;
95
	while(p >= buf){
96
		len++;
97
		p--;
98
		if(*p == '.'){
99
			memmove(np, p+1, len);
100
			np += len;
101
			len = 0;
102
		}
103
	}
104
	memmove(np, p+1, len);
105
	np += len;
106
	strcpy(np, "in-addr.arpa");
107
}
108
 
109
static void
110
nstrcpy(char *to, char *from, int len)
111
{
112
	strncpy(to, from, len);
113
	to[len-1] = 0;
114
}
115
 
116
static Ndbtuple*
117
doquery(int fd, char *dn, char *type)
118
{
119
	char buf[1024];
120
	int n;
121
	Ndbtuple *t, *first, *last;
122
 
123
	seek(fd, 0, 0);
124
	snprint(buf, sizeof(buf), "!%s %s", dn, type);
125
	if(write(fd, buf, strlen(buf)) < 0)
126
		return nil;
127
 
128
	seek(fd, 0, 0);
129
 
130
	first = last = nil;
131
 
132
	for(;;){
133
		n = read(fd, buf, sizeof(buf)-2);
134
		if(n <= 0)
135
			break;
136
		if(buf[n-1] != '\n')
137
			buf[n++] = '\n';	/* ndbparsline needs a trailing new line */
138
		buf[n] = 0;
139
 
140
		/* check for the error condition */
141
		if(buf[0] == '!'){
142
			werrstr("%s", buf+1);
143
			return nil;
144
		}
145
 
146
		t = _ndbparseline(buf);
147
		if(t != nil){
148
			if(first)
149
				last->entry = t;
150
			else
151
				first = t;
152
			last = t;
153
 
154
			while(last->entry)
155
				last = last->entry;
156
		}
157
	}
158
 
159
	ndbsetmalloctag(first, getcallerpc(&fd));
160
	return first;
161
}