Blame


1 3e0d8fb3 2005-12-27 devnull #include <u.h>
2 3e0d8fb3 2005-12-27 devnull #include <libc.h>
3 3e0d8fb3 2005-12-27 devnull #include <ip.h>
4 3e0d8fb3 2005-12-27 devnull #include <bio.h>
5 3e0d8fb3 2005-12-27 devnull #include <ndb.h>
6 3e0d8fb3 2005-12-27 devnull #include "dns.h"
7 3e0d8fb3 2005-12-27 devnull
8 3e0d8fb3 2005-12-27 devnull static int udpannounce(char*);
9 3e0d8fb3 2005-12-27 devnull static void reply(int, uchar*, DNSmsg*, Request*);
10 3e0d8fb3 2005-12-27 devnull
11 3e0d8fb3 2005-12-27 devnull extern char *logfile;
12 3e0d8fb3 2005-12-27 devnull
13 3e0d8fb3 2005-12-27 devnull static void
14 3e0d8fb3 2005-12-27 devnull ding(void *x, char *msg)
15 3e0d8fb3 2005-12-27 devnull {
16 3e0d8fb3 2005-12-27 devnull USED(x);
17 3e0d8fb3 2005-12-27 devnull if(strcmp(msg, "alarm") == 0)
18 3e0d8fb3 2005-12-27 devnull noted(NCONT);
19 3e0d8fb3 2005-12-27 devnull else
20 3e0d8fb3 2005-12-27 devnull noted(NDFLT);
21 3e0d8fb3 2005-12-27 devnull }
22 3e0d8fb3 2005-12-27 devnull
23 3e0d8fb3 2005-12-27 devnull typedef struct Inprogress Inprogress;
24 3e0d8fb3 2005-12-27 devnull struct Inprogress
25 3e0d8fb3 2005-12-27 devnull {
26 3e0d8fb3 2005-12-27 devnull int inuse;
27 3e0d8fb3 2005-12-27 devnull OUdphdr uh;
28 3e0d8fb3 2005-12-27 devnull DN *owner;
29 3e0d8fb3 2005-12-27 devnull int type;
30 3e0d8fb3 2005-12-27 devnull int id;
31 3e0d8fb3 2005-12-27 devnull };
32 3e0d8fb3 2005-12-27 devnull Inprogress inprog[Maxactive+2];
33 3e0d8fb3 2005-12-27 devnull
34 3e0d8fb3 2005-12-27 devnull /*
35 3e0d8fb3 2005-12-27 devnull * record client id and ignore retransmissions.
36 3e0d8fb3 2005-12-27 devnull * we're still single thread at this point.
37 3e0d8fb3 2005-12-27 devnull */
38 3e0d8fb3 2005-12-27 devnull static Inprogress*
39 3e0d8fb3 2005-12-27 devnull clientrxmit(DNSmsg *req, uchar *buf)
40 3e0d8fb3 2005-12-27 devnull {
41 3e0d8fb3 2005-12-27 devnull Inprogress *p, *empty;
42 3e0d8fb3 2005-12-27 devnull OUdphdr *uh;
43 3e0d8fb3 2005-12-27 devnull
44 3e0d8fb3 2005-12-27 devnull uh = (OUdphdr *)buf;
45 3e0d8fb3 2005-12-27 devnull empty = 0;
46 3e0d8fb3 2005-12-27 devnull for(p = inprog; p < &inprog[Maxactive]; p++){
47 3e0d8fb3 2005-12-27 devnull if(p->inuse == 0){
48 3e0d8fb3 2005-12-27 devnull if(empty == 0)
49 3e0d8fb3 2005-12-27 devnull empty = p;
50 3e0d8fb3 2005-12-27 devnull continue;
51 3e0d8fb3 2005-12-27 devnull }
52 3e0d8fb3 2005-12-27 devnull if(req->id == p->id)
53 3e0d8fb3 2005-12-27 devnull if(req->qd->owner == p->owner)
54 3e0d8fb3 2005-12-27 devnull if(req->qd->type == p->type)
55 3e0d8fb3 2005-12-27 devnull if(memcmp(uh, &p->uh, OUdphdrsize) == 0)
56 3e0d8fb3 2005-12-27 devnull return 0;
57 3e0d8fb3 2005-12-27 devnull }
58 3e0d8fb3 2005-12-27 devnull if(empty == 0)
59 3e0d8fb3 2005-12-27 devnull return 0; /* shouldn't happen - see slave() and definition of Maxactive */
60 3e0d8fb3 2005-12-27 devnull
61 3e0d8fb3 2005-12-27 devnull empty->id = req->id;
62 3e0d8fb3 2005-12-27 devnull empty->owner = req->qd->owner;
63 3e0d8fb3 2005-12-27 devnull empty->type = req->qd->type;
64 3e0d8fb3 2005-12-27 devnull memmove(&empty->uh, uh, OUdphdrsize);
65 3e0d8fb3 2005-12-27 devnull empty->inuse = 1;
66 3e0d8fb3 2005-12-27 devnull return empty;
67 3e0d8fb3 2005-12-27 devnull }
68 3e0d8fb3 2005-12-27 devnull
69 3e0d8fb3 2005-12-27 devnull /*
70 3e0d8fb3 2005-12-27 devnull * a process to act as a dns server for outside reqeusts
71 3e0d8fb3 2005-12-27 devnull */
72 3e0d8fb3 2005-12-27 devnull void
73 3e0d8fb3 2005-12-27 devnull dnudpserver(char *mntpt)
74 3e0d8fb3 2005-12-27 devnull {
75 3e0d8fb3 2005-12-27 devnull int fd, len, op;
76 3e0d8fb3 2005-12-27 devnull Request req;
77 3e0d8fb3 2005-12-27 devnull DNSmsg reqmsg, repmsg;
78 3e0d8fb3 2005-12-27 devnull uchar buf[OUdphdrsize + Maxudp + 1024];
79 3e0d8fb3 2005-12-27 devnull char *err;
80 3e0d8fb3 2005-12-27 devnull Inprogress *p;
81 3e0d8fb3 2005-12-27 devnull char tname[32];
82 3e0d8fb3 2005-12-27 devnull OUdphdr *uh;
83 3e0d8fb3 2005-12-27 devnull
84 3e0d8fb3 2005-12-27 devnull /* fork sharing text, data, and bss with parent */
85 3e0d8fb3 2005-12-27 devnull switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
86 3e0d8fb3 2005-12-27 devnull case -1:
87 3e0d8fb3 2005-12-27 devnull break;
88 3e0d8fb3 2005-12-27 devnull case 0:
89 3e0d8fb3 2005-12-27 devnull break;
90 3e0d8fb3 2005-12-27 devnull default:
91 3e0d8fb3 2005-12-27 devnull return;
92 3e0d8fb3 2005-12-27 devnull }
93 3e0d8fb3 2005-12-27 devnull
94 3e0d8fb3 2005-12-27 devnull fd = -1;
95 3e0d8fb3 2005-12-27 devnull notify(ding);
96 3e0d8fb3 2005-12-27 devnull restart:
97 3e0d8fb3 2005-12-27 devnull if(fd >= 0)
98 3e0d8fb3 2005-12-27 devnull close(fd);
99 3e0d8fb3 2005-12-27 devnull while((fd = udpannounce(mntpt)) < 0)
100 3e0d8fb3 2005-12-27 devnull sleep(5000);
101 3e0d8fb3 2005-12-27 devnull if(setjmp(req.mret))
102 3e0d8fb3 2005-12-27 devnull putactivity();
103 3e0d8fb3 2005-12-27 devnull req.isslave = 0;
104 3e0d8fb3 2005-12-27 devnull
105 3e0d8fb3 2005-12-27 devnull /* loop on requests */
106 3e0d8fb3 2005-12-27 devnull for(;; putactivity()){
107 3e0d8fb3 2005-12-27 devnull memset(&repmsg, 0, sizeof(repmsg));
108 3e0d8fb3 2005-12-27 devnull memset(&reqmsg, 0, sizeof(reqmsg));
109 3e0d8fb3 2005-12-27 devnull alarm(60*1000);
110 3e0d8fb3 2005-12-27 devnull len = udpread(fd, (OUdphdr*)buf, buf+OUdphdrsize, sizeof(buf)-OUdphdrsize);
111 3e0d8fb3 2005-12-27 devnull alarm(0);
112 3e0d8fb3 2005-12-27 devnull if(len <= 0)
113 3e0d8fb3 2005-12-27 devnull goto restart;
114 3e0d8fb3 2005-12-27 devnull uh = (OUdphdr*)buf;
115 3e0d8fb3 2005-12-27 devnull getactivity(&req);
116 3e0d8fb3 2005-12-27 devnull req.aborttime = now + 30; /* don't spend more than 30 seconds */
117 3e0d8fb3 2005-12-27 devnull err = convM2DNS(&buf[OUdphdrsize], len, &reqmsg);
118 3e0d8fb3 2005-12-27 devnull if(err){
119 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "server: input error: %s from %I", err, buf);
120 3e0d8fb3 2005-12-27 devnull continue;
121 3e0d8fb3 2005-12-27 devnull }
122 3e0d8fb3 2005-12-27 devnull if(reqmsg.qdcount < 1){
123 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "server: no questions from %I", buf);
124 3e0d8fb3 2005-12-27 devnull goto freereq;
125 3e0d8fb3 2005-12-27 devnull }
126 3e0d8fb3 2005-12-27 devnull if(reqmsg.flags & Fresp){
127 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "server: reply not request from %I", buf);
128 3e0d8fb3 2005-12-27 devnull goto freereq;
129 3e0d8fb3 2005-12-27 devnull }
130 3e0d8fb3 2005-12-27 devnull op = reqmsg.flags & Omask;
131 3e0d8fb3 2005-12-27 devnull if(op != Oquery && op != Onotify){
132 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "server: op %d from %I", reqmsg.flags & Omask, buf);
133 3e0d8fb3 2005-12-27 devnull goto freereq;
134 3e0d8fb3 2005-12-27 devnull }
135 3e0d8fb3 2005-12-27 devnull
136 3e0d8fb3 2005-12-27 devnull if(debug || (trace && subsume(trace, reqmsg.qd->owner->name))){
137 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "%d: serve (%I/%d) %d %s %s",
138 3e0d8fb3 2005-12-27 devnull req.id, buf, ((uh->rport[0])<<8)+uh->rport[1],
139 3e0d8fb3 2005-12-27 devnull reqmsg.id,
140 3e0d8fb3 2005-12-27 devnull reqmsg.qd->owner->name,
141 3e0d8fb3 2005-12-27 devnull rrname(reqmsg.qd->type, tname, sizeof tname));
142 3e0d8fb3 2005-12-27 devnull }
143 3e0d8fb3 2005-12-27 devnull
144 3e0d8fb3 2005-12-27 devnull p = clientrxmit(&reqmsg, buf);
145 3e0d8fb3 2005-12-27 devnull if(p == 0){
146 3e0d8fb3 2005-12-27 devnull if(debug)
147 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "%d: duplicate", req.id);
148 3e0d8fb3 2005-12-27 devnull goto freereq;
149 3e0d8fb3 2005-12-27 devnull }
150 3e0d8fb3 2005-12-27 devnull
151 3e0d8fb3 2005-12-27 devnull /* loop through each question */
152 3e0d8fb3 2005-12-27 devnull while(reqmsg.qd){
153 3e0d8fb3 2005-12-27 devnull memset(&repmsg, 0, sizeof(repmsg));
154 3e0d8fb3 2005-12-27 devnull switch(op){
155 3e0d8fb3 2005-12-27 devnull case Oquery:
156 3e0d8fb3 2005-12-27 devnull dnserver(&reqmsg, &repmsg, &req);
157 3e0d8fb3 2005-12-27 devnull break;
158 3e0d8fb3 2005-12-27 devnull case Onotify:
159 3e0d8fb3 2005-12-27 devnull dnnotify(&reqmsg, &repmsg, &req);
160 3e0d8fb3 2005-12-27 devnull break;
161 3e0d8fb3 2005-12-27 devnull }
162 3e0d8fb3 2005-12-27 devnull reply(fd, buf, &repmsg, &req);
163 3e0d8fb3 2005-12-27 devnull rrfreelist(repmsg.qd);
164 3e0d8fb3 2005-12-27 devnull rrfreelist(repmsg.an);
165 3e0d8fb3 2005-12-27 devnull rrfreelist(repmsg.ns);
166 3e0d8fb3 2005-12-27 devnull rrfreelist(repmsg.ar);
167 3e0d8fb3 2005-12-27 devnull }
168 3e0d8fb3 2005-12-27 devnull
169 3e0d8fb3 2005-12-27 devnull p->inuse = 0;
170 3e0d8fb3 2005-12-27 devnull
171 3e0d8fb3 2005-12-27 devnull freereq:
172 3e0d8fb3 2005-12-27 devnull rrfreelist(reqmsg.qd);
173 3e0d8fb3 2005-12-27 devnull rrfreelist(reqmsg.an);
174 3e0d8fb3 2005-12-27 devnull rrfreelist(reqmsg.ns);
175 3e0d8fb3 2005-12-27 devnull rrfreelist(reqmsg.ar);
176 3e0d8fb3 2005-12-27 devnull
177 3e0d8fb3 2005-12-27 devnull if(req.isslave){
178 3e0d8fb3 2005-12-27 devnull putactivity();
179 3e0d8fb3 2005-12-27 devnull _exits(0);
180 3e0d8fb3 2005-12-27 devnull }
181 3e0d8fb3 2005-12-27 devnull
182 3e0d8fb3 2005-12-27 devnull }
183 3e0d8fb3 2005-12-27 devnull }
184 3e0d8fb3 2005-12-27 devnull
185 3e0d8fb3 2005-12-27 devnull /*
186 3e0d8fb3 2005-12-27 devnull * announce on udp port
187 3e0d8fb3 2005-12-27 devnull */
188 3e0d8fb3 2005-12-27 devnull static int
189 3e0d8fb3 2005-12-27 devnull udpannounce(char *mntpt)
190 3e0d8fb3 2005-12-27 devnull {
191 3e0d8fb3 2005-12-27 devnull int fd;
192 3e0d8fb3 2005-12-27 devnull char buf[40];
193 3e0d8fb3 2005-12-27 devnull
194 3e0d8fb3 2005-12-27 devnull USED(mntpt);
195 3e0d8fb3 2005-12-27 devnull
196 3e0d8fb3 2005-12-27 devnull if((fd=announce("udp!*!nameserver", buf)) < 0)
197 3e0d8fb3 2005-12-27 devnull warning("can't announce on dns udp port");
198 3e0d8fb3 2005-12-27 devnull return fd;
199 3e0d8fb3 2005-12-27 devnull }
200 3e0d8fb3 2005-12-27 devnull
201 3e0d8fb3 2005-12-27 devnull static void
202 3e0d8fb3 2005-12-27 devnull reply(int fd, uchar *buf, DNSmsg *rep, Request *reqp)
203 3e0d8fb3 2005-12-27 devnull {
204 3e0d8fb3 2005-12-27 devnull int len;
205 3e0d8fb3 2005-12-27 devnull char tname[32];
206 3e0d8fb3 2005-12-27 devnull RR *rp;
207 3e0d8fb3 2005-12-27 devnull
208 3e0d8fb3 2005-12-27 devnull if(debug || (trace && subsume(trace, rep->qd->owner->name)))
209 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "%d: reply (%I/%d) %d %s %s an %R ns %R ar %R",
210 3e0d8fb3 2005-12-27 devnull reqp->id, buf, ((buf[4])<<8)+buf[5],
211 3e0d8fb3 2005-12-27 devnull rep->id, rep->qd->owner->name,
212 3e0d8fb3 2005-12-27 devnull rrname(rep->qd->type, tname, sizeof tname), rep->an, rep->ns, rep->ar);
213 3e0d8fb3 2005-12-27 devnull
214 3e0d8fb3 2005-12-27 devnull len = convDNS2M(rep, &buf[OUdphdrsize], Maxudp);
215 3e0d8fb3 2005-12-27 devnull if(len <= 0){
216 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "error converting reply: %s %d", rep->qd->owner->name,
217 3e0d8fb3 2005-12-27 devnull rep->qd->type);
218 3e0d8fb3 2005-12-27 devnull for(rp = rep->an; rp; rp = rp->next)
219 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "an %R", rp);
220 3e0d8fb3 2005-12-27 devnull for(rp = rep->ns; rp; rp = rp->next)
221 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "ns %R", rp);
222 3e0d8fb3 2005-12-27 devnull for(rp = rep->ar; rp; rp = rp->next)
223 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "ar %R", rp);
224 3e0d8fb3 2005-12-27 devnull return;
225 3e0d8fb3 2005-12-27 devnull }
226 3e0d8fb3 2005-12-27 devnull if(udpwrite(fd, (OUdphdr*)buf, buf+OUdphdrsize, len) != len)
227 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "error sending reply: %r");
228 3e0d8fb3 2005-12-27 devnull }