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 <auth.h>
4 3e0d8fb3 2005-12-27 devnull #include <fcall.h>
5 3e0d8fb3 2005-12-27 devnull #include <bio.h>
6 3e0d8fb3 2005-12-27 devnull #include <ctype.h>
7 3e0d8fb3 2005-12-27 devnull #include <ip.h>
8 3e0d8fb3 2005-12-27 devnull #include <ndb.h>
9 5c9f76b5 2006-02-14 devnull #include <thread.h>
10 3e0d8fb3 2005-12-27 devnull #include "dns.h"
14 3e0d8fb3 2005-12-27 devnull Maxrequest= 1024,
15 3e0d8fb3 2005-12-27 devnull Ncache= 8,
16 3e0d8fb3 2005-12-27 devnull Maxpath= 128,
17 3e0d8fb3 2005-12-27 devnull Maxreply= 512,
18 3e0d8fb3 2005-12-27 devnull Maxrrr= 16,
19 3e0d8fb3 2005-12-27 devnull Maxfdata= 8192,
25 3e0d8fb3 2005-12-27 devnull typedef struct Mfile Mfile;
26 3e0d8fb3 2005-12-27 devnull typedef struct Job Job;
27 3e0d8fb3 2005-12-27 devnull typedef struct Network Network;
29 3e0d8fb3 2005-12-27 devnull int vers; /* incremented each clone/attach */
31 3e0d8fb3 2005-12-27 devnull struct Mfile
33 3e0d8fb3 2005-12-27 devnull Mfile *next; /* next free mfile */
36 3e0d8fb3 2005-12-27 devnull char *user;
40 3e0d8fb3 2005-12-27 devnull int type; /* reply type */
41 3e0d8fb3 2005-12-27 devnull char reply[Maxreply];
42 3e0d8fb3 2005-12-27 devnull ushort rr[Maxrrr]; /* offset of rr's */
43 3e0d8fb3 2005-12-27 devnull ushort nrr; /* number of rr's */
47 226d80b8 2006-04-01 devnull * active local requests
49 3e0d8fb3 2005-12-27 devnull struct Job
51 3e0d8fb3 2005-12-27 devnull Job *next;
52 3e0d8fb3 2005-12-27 devnull int flushed;
53 3e0d8fb3 2005-12-27 devnull Fcall request;
54 3e0d8fb3 2005-12-27 devnull Fcall reply;
56 3e0d8fb3 2005-12-27 devnull Lock joblock;
57 3e0d8fb3 2005-12-27 devnull Job *joblist;
61 3e0d8fb3 2005-12-27 devnull Mfile *inuse; /* active mfile's */
62 3e0d8fb3 2005-12-27 devnull } mfalloc;
64 3e0d8fb3 2005-12-27 devnull int mfd[2];
65 3e0d8fb3 2005-12-27 devnull int debug;
66 3e0d8fb3 2005-12-27 devnull int traceactivity;
67 3e0d8fb3 2005-12-27 devnull int cachedb;
68 3e0d8fb3 2005-12-27 devnull ulong now;
69 3e0d8fb3 2005-12-27 devnull int testing;
70 3e0d8fb3 2005-12-27 devnull char *trace;
71 3e0d8fb3 2005-12-27 devnull int needrefresh;
72 3e0d8fb3 2005-12-27 devnull int resolver;
73 3e0d8fb3 2005-12-27 devnull uchar ipaddr[IPaddrlen]; /* my ip address */
74 3e0d8fb3 2005-12-27 devnull int maxage;
75 3e0d8fb3 2005-12-27 devnull char *zonerefreshprogram;
76 3e0d8fb3 2005-12-27 devnull int sendnotifies;
78 3e0d8fb3 2005-12-27 devnull void rversion(Job*);
79 3e0d8fb3 2005-12-27 devnull void rauth(Job*);
80 3e0d8fb3 2005-12-27 devnull void rflush(Job*);
81 3e0d8fb3 2005-12-27 devnull void rattach(Job*, Mfile*);
82 3e0d8fb3 2005-12-27 devnull char* rwalk(Job*, Mfile*);
83 3e0d8fb3 2005-12-27 devnull void ropen(Job*, Mfile*);
84 3e0d8fb3 2005-12-27 devnull void rcreate(Job*, Mfile*);
85 3e0d8fb3 2005-12-27 devnull void rread(Job*, Mfile*);
86 3e0d8fb3 2005-12-27 devnull void rwrite(Job*, Mfile*, Request*);
87 3e0d8fb3 2005-12-27 devnull void rclunk(Job*, Mfile*);
88 3e0d8fb3 2005-12-27 devnull void rremove(Job*, Mfile*);
89 3e0d8fb3 2005-12-27 devnull void rstat(Job*, Mfile*);
90 3e0d8fb3 2005-12-27 devnull void rwstat(Job*, Mfile*);
91 3e0d8fb3 2005-12-27 devnull void sendmsg(Job*, char*);
92 5c9f76b5 2006-02-14 devnull void mountinit(char*);
93 3e0d8fb3 2005-12-27 devnull void io(void);
94 3e0d8fb3 2005-12-27 devnull int fillreply(Mfile*, int);
95 3e0d8fb3 2005-12-27 devnull Job* newjob(void);
96 3e0d8fb3 2005-12-27 devnull void freejob(Job*);
97 3e0d8fb3 2005-12-27 devnull void setext(char*, int, char*);
99 b7f150b0 2006-02-24 devnull char *tcpaddr = "tcp!*!domain";
100 b7f150b0 2006-02-24 devnull char *udpaddr = "udp!*!domain";
101 3e0d8fb3 2005-12-27 devnull char *logfile = "dns";
102 3e0d8fb3 2005-12-27 devnull char *dbfile;
103 3e0d8fb3 2005-12-27 devnull char mntpt[Maxpath];
104 3e0d8fb3 2005-12-27 devnull char *LOG;
107 3e0d8fb3 2005-12-27 devnull usage(void)
109 c7a7e3c4 2006-02-24 devnull fprint(2, "usage: dns [-dnrst] [-a maxage] [-f ndb-file] [-T tcpaddr] [-U udpaddr] [-x service] [-z zoneprog]\n");
110 5c9f76b5 2006-02-14 devnull threadexitsall("usage");
114 49a1496c 2006-02-20 devnull checkaddress(void)
116 49a1496c 2006-02-20 devnull char *u, *t;
118 49a1496c 2006-02-20 devnull u = strchr(udpaddr, '!');
119 49a1496c 2006-02-20 devnull t = strchr(tcpaddr, '!');
120 49a1496c 2006-02-20 devnull if(u && t && strcmp(u, t) != 0)
121 49a1496c 2006-02-20 devnull fprint(2, "warning: announce mismatch %s %s\n", udpaddr, tcpaddr);
125 5c9f76b5 2006-02-14 devnull threadmain(int argc, char *argv[])
127 5c9f76b5 2006-02-14 devnull int serveudp, servetcp;
128 5c9f76b5 2006-02-14 devnull char *service;
130 5c9f76b5 2006-02-14 devnull serveudp = 0;
131 5c9f76b5 2006-02-14 devnull servetcp = 0;
132 5c9f76b5 2006-02-14 devnull service = "dns";
133 3e0d8fb3 2005-12-27 devnull ARGBEGIN{
134 3e0d8fb3 2005-12-27 devnull case 'd':
135 3e0d8fb3 2005-12-27 devnull debug = 1;
136 3e0d8fb3 2005-12-27 devnull traceactivity = 1;
138 3e0d8fb3 2005-12-27 devnull case 'f':
139 5c9f76b5 2006-02-14 devnull dbfile = EARGF(usage());
141 5c9f76b5 2006-02-14 devnull case 'x':
142 5c9f76b5 2006-02-14 devnull service = EARGF(usage());
144 3e0d8fb3 2005-12-27 devnull case 'r':
145 3e0d8fb3 2005-12-27 devnull resolver = 1;
147 3e0d8fb3 2005-12-27 devnull case 's':
148 19256e0d 2006-02-17 devnull serveudp = 1;
149 3e0d8fb3 2005-12-27 devnull cachedb = 1;
151 49a1496c 2006-02-20 devnull case 't':
152 5c9f76b5 2006-02-14 devnull servetcp = 1;
153 5c9f76b5 2006-02-14 devnull cachedb = 1;
155 3e0d8fb3 2005-12-27 devnull case 'a':
156 5c9f76b5 2006-02-14 devnull maxage = atoi(EARGF(usage()));
158 3e0d8fb3 2005-12-27 devnull case 'z':
159 5c9f76b5 2006-02-14 devnull zonerefreshprogram = EARGF(usage());
161 3e0d8fb3 2005-12-27 devnull case 'n':
162 3e0d8fb3 2005-12-27 devnull sendnotifies = 1;
164 49a1496c 2006-02-20 devnull case 'U':
165 b7f150b0 2006-02-24 devnull udpaddr = estrdup(netmkaddr(EARGF(usage()), "udp", "domain"));
167 49a1496c 2006-02-20 devnull case 'T':
168 b7f150b0 2006-02-24 devnull tcpaddr = estrdup(netmkaddr(EARGF(usage()), "tcp", "domain"));
170 49a1496c 2006-02-20 devnull default:
171 49a1496c 2006-02-20 devnull usage();
174 49a1496c 2006-02-20 devnull if(argc)
175 49a1496c 2006-02-20 devnull usage();
176 49a1496c 2006-02-20 devnull if(serveudp && servetcp)
177 49a1496c 2006-02-20 devnull checkaddress();
179 5c9f76b5 2006-02-14 devnull rfork(RFNOTEG);
181 3e0d8fb3 2005-12-27 devnull /* start syslog before we fork */
182 3e0d8fb3 2005-12-27 devnull fmtinstall('F', fcallfmt);
183 3e0d8fb3 2005-12-27 devnull dninit();
184 19256e0d 2006-02-17 devnull if(myipaddr(ipaddr, mntpt) < 0)
185 3e0d8fb3 2005-12-27 devnull sysfatal("can't read my ip address");
187 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "starting dns on %I", ipaddr);
189 3e0d8fb3 2005-12-27 devnull opendatabase();
191 5c9f76b5 2006-02-14 devnull mountinit(service);
193 3e0d8fb3 2005-12-27 devnull now = time(0);
194 3e0d8fb3 2005-12-27 devnull srand(now*getpid());
195 3e0d8fb3 2005-12-27 devnull db2cache(1);
197 5c9f76b5 2006-02-14 devnull if(serveudp)
198 5c9f76b5 2006-02-14 devnull proccreate(dnudpserver, nil, STACK);
199 5c9f76b5 2006-02-14 devnull if(servetcp)
200 5c9f76b5 2006-02-14 devnull proccreate(dntcpserver, nil, STACK);
201 3e0d8fb3 2005-12-27 devnull if(sendnotifies)
202 5c9f76b5 2006-02-14 devnull proccreate(notifyproc, nil, STACK);
208 3e0d8fb3 2005-12-27 devnull * if a mount point is specified, set the cs extention to be the mount point
209 3e0d8fb3 2005-12-27 devnull * with '_'s replacing '/'s
212 3e0d8fb3 2005-12-27 devnull setext(char *ext, int n, char *p)
214 3e0d8fb3 2005-12-27 devnull int i, c;
217 3e0d8fb3 2005-12-27 devnull for(i = 0; i < n; i++){
218 3e0d8fb3 2005-12-27 devnull c = p[i];
219 3e0d8fb3 2005-12-27 devnull if(c == 0)
221 3e0d8fb3 2005-12-27 devnull if(c == '/')
222 3e0d8fb3 2005-12-27 devnull c = '_';
223 3e0d8fb3 2005-12-27 devnull ext[i] = c;
225 3e0d8fb3 2005-12-27 devnull ext[i] = 0;
229 5c9f76b5 2006-02-14 devnull mountinit(char *service)
231 3e0d8fb3 2005-12-27 devnull int p[2];
233 3e0d8fb3 2005-12-27 devnull if(pipe(p) < 0)
234 3e0d8fb3 2005-12-27 devnull abort(); /* "pipe failed" */;
235 5c9f76b5 2006-02-14 devnull if(post9pservice(p[1], service) < 0)
236 5c9f76b5 2006-02-14 devnull fprint(2, "post9pservice dns: %r\n");
237 5c9f76b5 2006-02-14 devnull close(p[1]);
238 3e0d8fb3 2005-12-27 devnull mfd[0] = mfd[1] = p[0];
242 3e0d8fb3 2005-12-27 devnull newfid(int fid, int needunused)
244 3e0d8fb3 2005-12-27 devnull Mfile *mf;
246 3e0d8fb3 2005-12-27 devnull lock(&mfalloc.lk);
247 3e0d8fb3 2005-12-27 devnull for(mf = mfalloc.inuse; mf != nil; mf = mf->next){
248 3e0d8fb3 2005-12-27 devnull if(mf->fid == fid){
249 3e0d8fb3 2005-12-27 devnull unlock(&mfalloc.lk);
250 3e0d8fb3 2005-12-27 devnull if(needunused)
251 3e0d8fb3 2005-12-27 devnull return nil;
252 3e0d8fb3 2005-12-27 devnull return mf;
255 387ae1db 2006-02-02 devnull if(!needunused){
256 387ae1db 2006-02-02 devnull unlock(&mfalloc.lk);
257 387ae1db 2006-02-02 devnull return nil;
259 3e0d8fb3 2005-12-27 devnull mf = emalloc(sizeof(*mf));
260 3e0d8fb3 2005-12-27 devnull if(mf == nil)
261 3e0d8fb3 2005-12-27 devnull sysfatal("out of memory");
262 3e0d8fb3 2005-12-27 devnull mf->fid = fid;
263 3e0d8fb3 2005-12-27 devnull mf->next = mfalloc.inuse;
264 3e0d8fb3 2005-12-27 devnull mfalloc.inuse = mf;
265 3e0d8fb3 2005-12-27 devnull unlock(&mfalloc.lk);
266 3e0d8fb3 2005-12-27 devnull return mf;
270 3e0d8fb3 2005-12-27 devnull freefid(Mfile *mf)
272 3e0d8fb3 2005-12-27 devnull Mfile **l;
274 3e0d8fb3 2005-12-27 devnull lock(&mfalloc.lk);
275 3e0d8fb3 2005-12-27 devnull for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next){
276 3e0d8fb3 2005-12-27 devnull if(*l == mf){
277 3e0d8fb3 2005-12-27 devnull *l = mf->next;
278 3e0d8fb3 2005-12-27 devnull if(mf->user)
279 3e0d8fb3 2005-12-27 devnull free(mf->user);
280 3e0d8fb3 2005-12-27 devnull free(mf);
281 3e0d8fb3 2005-12-27 devnull unlock(&mfalloc.lk);
285 3e0d8fb3 2005-12-27 devnull sysfatal("freeing unused fid");
289 3e0d8fb3 2005-12-27 devnull copyfid(Mfile *mf, int fid)
291 3e0d8fb3 2005-12-27 devnull Mfile *nmf;
293 3e0d8fb3 2005-12-27 devnull nmf = newfid(fid, 1);
294 3e0d8fb3 2005-12-27 devnull if(nmf == nil)
295 3e0d8fb3 2005-12-27 devnull return nil;
296 3e0d8fb3 2005-12-27 devnull nmf->fid = fid;
297 3e0d8fb3 2005-12-27 devnull nmf->user = estrdup(mf->user);
298 3e0d8fb3 2005-12-27 devnull nmf->qid.type = mf->qid.type;
299 3e0d8fb3 2005-12-27 devnull nmf->qid.path = mf->qid.path;
300 3e0d8fb3 2005-12-27 devnull nmf->qid.vers = vers++;
301 3e0d8fb3 2005-12-27 devnull return nmf;
305 3e0d8fb3 2005-12-27 devnull newjob(void)
307 3e0d8fb3 2005-12-27 devnull Job *job;
309 3e0d8fb3 2005-12-27 devnull job = emalloc(sizeof(*job));
310 3e0d8fb3 2005-12-27 devnull lock(&joblock);
311 3e0d8fb3 2005-12-27 devnull job->next = joblist;
312 3e0d8fb3 2005-12-27 devnull joblist = job;
313 3e0d8fb3 2005-12-27 devnull job->request.tag = -1;
314 3e0d8fb3 2005-12-27 devnull unlock(&joblock);
315 3e0d8fb3 2005-12-27 devnull return job;
319 3e0d8fb3 2005-12-27 devnull freejob(Job *job)
321 3e0d8fb3 2005-12-27 devnull Job **l;
323 3e0d8fb3 2005-12-27 devnull lock(&joblock);
324 3e0d8fb3 2005-12-27 devnull for(l = &joblist; *l; l = &(*l)->next){
325 3e0d8fb3 2005-12-27 devnull if((*l) == job){
326 3e0d8fb3 2005-12-27 devnull *l = job->next;
327 3e0d8fb3 2005-12-27 devnull free(job);
331 3e0d8fb3 2005-12-27 devnull unlock(&joblock);
335 3e0d8fb3 2005-12-27 devnull flushjob(int tag)
337 3e0d8fb3 2005-12-27 devnull Job *job;
339 3e0d8fb3 2005-12-27 devnull lock(&joblock);
340 3e0d8fb3 2005-12-27 devnull for(job = joblist; job; job = job->next){
341 3e0d8fb3 2005-12-27 devnull if(job->request.tag == tag && job->request.type != Tflush){
342 3e0d8fb3 2005-12-27 devnull job->flushed = 1;
346 3e0d8fb3 2005-12-27 devnull unlock(&joblock);
350 5c9f76b5 2006-02-14 devnull ioproc0(void *v)
353 3e0d8fb3 2005-12-27 devnull Mfile *mf;
354 3e0d8fb3 2005-12-27 devnull uchar mdata[IOHDRSZ + Maxfdata];
355 3e0d8fb3 2005-12-27 devnull Request req;
356 3e0d8fb3 2005-12-27 devnull Job *job;
358 5c9f76b5 2006-02-14 devnull USED(v);
360 3e0d8fb3 2005-12-27 devnull for(;;){
361 3e0d8fb3 2005-12-27 devnull n = read9pmsg(mfd[0], mdata, sizeof mdata);
362 19256e0d 2006-02-17 devnull if(n <= 0){
363 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "error reading mntpt: %r");
366 3e0d8fb3 2005-12-27 devnull job = newjob();
367 3e0d8fb3 2005-12-27 devnull if(convM2S(mdata, n, &job->request) != n){
368 3e0d8fb3 2005-12-27 devnull freejob(job);
369 3e0d8fb3 2005-12-27 devnull continue;
371 3e0d8fb3 2005-12-27 devnull if(debug)
372 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "%F", &job->request);
374 3e0d8fb3 2005-12-27 devnull getactivity(&req);
375 3e0d8fb3 2005-12-27 devnull req.aborttime = now + 60; /* don't spend more than 60 seconds */
377 387ae1db 2006-02-02 devnull mf = nil;
378 387ae1db 2006-02-02 devnull switch(job->request.type){
379 387ae1db 2006-02-02 devnull case Tversion:
380 387ae1db 2006-02-02 devnull case Tauth:
381 387ae1db 2006-02-02 devnull case Tflush:
383 387ae1db 2006-02-02 devnull case Tattach:
384 387ae1db 2006-02-02 devnull mf = newfid(job->request.fid, 1);
385 387ae1db 2006-02-02 devnull if(mf == nil){
386 387ae1db 2006-02-02 devnull sendmsg(job, "fid in use");
387 387ae1db 2006-02-02 devnull goto skip;
390 387ae1db 2006-02-02 devnull default:
391 387ae1db 2006-02-02 devnull mf = newfid(job->request.fid, 0);
392 387ae1db 2006-02-02 devnull if(mf == nil){
393 387ae1db 2006-02-02 devnull sendmsg(job, "unknown fid");
394 387ae1db 2006-02-02 devnull goto skip;
399 3e0d8fb3 2005-12-27 devnull switch(job->request.type){
400 3e0d8fb3 2005-12-27 devnull default:
401 3e0d8fb3 2005-12-27 devnull syslog(1, logfile, "unknown request type %d", job->request.type);
403 3e0d8fb3 2005-12-27 devnull case Tversion:
404 3e0d8fb3 2005-12-27 devnull rversion(job);
406 3e0d8fb3 2005-12-27 devnull case Tauth:
407 3e0d8fb3 2005-12-27 devnull rauth(job);
409 3e0d8fb3 2005-12-27 devnull case Tflush:
410 3e0d8fb3 2005-12-27 devnull rflush(job);
412 3e0d8fb3 2005-12-27 devnull case Tattach:
413 3e0d8fb3 2005-12-27 devnull rattach(job, mf);
415 3e0d8fb3 2005-12-27 devnull case Twalk:
416 3e0d8fb3 2005-12-27 devnull rwalk(job, mf);
418 3e0d8fb3 2005-12-27 devnull case Topen:
419 3e0d8fb3 2005-12-27 devnull ropen(job, mf);
421 3e0d8fb3 2005-12-27 devnull case Tcreate:
422 3e0d8fb3 2005-12-27 devnull rcreate(job, mf);
424 3e0d8fb3 2005-12-27 devnull case Tread:
425 3e0d8fb3 2005-12-27 devnull rread(job, mf);
427 3e0d8fb3 2005-12-27 devnull case Twrite:
428 3e0d8fb3 2005-12-27 devnull rwrite(job, mf, &req);
430 3e0d8fb3 2005-12-27 devnull case Tclunk:
431 3e0d8fb3 2005-12-27 devnull rclunk(job, mf);
433 3e0d8fb3 2005-12-27 devnull case Tremove:
434 3e0d8fb3 2005-12-27 devnull rremove(job, mf);
436 3e0d8fb3 2005-12-27 devnull case Tstat:
437 3e0d8fb3 2005-12-27 devnull rstat(job, mf);
439 3e0d8fb3 2005-12-27 devnull case Twstat:
440 3e0d8fb3 2005-12-27 devnull rwstat(job, mf);
444 3e0d8fb3 2005-12-27 devnull freejob(job);
445 3e0d8fb3 2005-12-27 devnull putactivity();
450 5c9f76b5 2006-02-14 devnull io(void)
454 5c9f76b5 2006-02-14 devnull for(i=0; i<Maxactive; i++)
455 5c9f76b5 2006-02-14 devnull proccreate(ioproc0, 0, STACK);
459 3e0d8fb3 2005-12-27 devnull rversion(Job *job)
461 3e0d8fb3 2005-12-27 devnull if(job->request.msize > IOHDRSZ + Maxfdata)
462 3e0d8fb3 2005-12-27 devnull job->reply.msize = IOHDRSZ + Maxfdata;
464 3e0d8fb3 2005-12-27 devnull job->reply.msize = job->request.msize;
465 3e0d8fb3 2005-12-27 devnull if(strncmp(job->request.version, "9P2000", 6) != 0)
466 3e0d8fb3 2005-12-27 devnull sendmsg(job, "unknown 9P version");
468 3e0d8fb3 2005-12-27 devnull job->reply.version = "9P2000";
469 3e0d8fb3 2005-12-27 devnull sendmsg(job, 0);
474 3e0d8fb3 2005-12-27 devnull rauth(Job *job)
476 3e0d8fb3 2005-12-27 devnull sendmsg(job, "dns: authentication not required");
480 3e0d8fb3 2005-12-27 devnull * don't flush till all the slaves are done
483 3e0d8fb3 2005-12-27 devnull rflush(Job *job)
485 3e0d8fb3 2005-12-27 devnull flushjob(job->request.oldtag);
486 3e0d8fb3 2005-12-27 devnull sendmsg(job, 0);
490 3e0d8fb3 2005-12-27 devnull rattach(Job *job, Mfile *mf)
492 3e0d8fb3 2005-12-27 devnull if(mf->user != nil)
493 3e0d8fb3 2005-12-27 devnull free(mf->user);
494 3e0d8fb3 2005-12-27 devnull mf->user = estrdup(job->request.uname);
495 3e0d8fb3 2005-12-27 devnull mf->qid.vers = vers++;
496 3e0d8fb3 2005-12-27 devnull mf->qid.type = QTDIR;
497 3e0d8fb3 2005-12-27 devnull mf->qid.path = 0LL;
498 3e0d8fb3 2005-12-27 devnull job->reply.qid = mf->qid;
499 3e0d8fb3 2005-12-27 devnull sendmsg(job, 0);
503 3e0d8fb3 2005-12-27 devnull rwalk(Job *job, Mfile *mf)
505 3e0d8fb3 2005-12-27 devnull char *err;
506 3e0d8fb3 2005-12-27 devnull char **elems;
507 3e0d8fb3 2005-12-27 devnull int nelems;
509 3e0d8fb3 2005-12-27 devnull Mfile *nmf;
510 3e0d8fb3 2005-12-27 devnull Qid qid;
512 3e0d8fb3 2005-12-27 devnull err = 0;
513 3e0d8fb3 2005-12-27 devnull nmf = nil;
514 3e0d8fb3 2005-12-27 devnull elems = job->request.wname;
515 3e0d8fb3 2005-12-27 devnull nelems = job->request.nwname;
516 3e0d8fb3 2005-12-27 devnull job->reply.nwqid = 0;
518 3e0d8fb3 2005-12-27 devnull if(job->request.newfid != job->request.fid){
519 3e0d8fb3 2005-12-27 devnull /* clone fid */
520 3e0d8fb3 2005-12-27 devnull if(job->request.newfid<0){
521 3e0d8fb3 2005-12-27 devnull err = "clone newfid out of range";
522 3e0d8fb3 2005-12-27 devnull goto send;
524 3e0d8fb3 2005-12-27 devnull nmf = copyfid(mf, job->request.newfid);
525 3e0d8fb3 2005-12-27 devnull if(nmf == nil){
526 3e0d8fb3 2005-12-27 devnull err = "clone bad newfid";
527 3e0d8fb3 2005-12-27 devnull goto send;
529 3e0d8fb3 2005-12-27 devnull mf = nmf;
531 3e0d8fb3 2005-12-27 devnull /* else nmf will be nil */
533 3e0d8fb3 2005-12-27 devnull qid = mf->qid;
534 3e0d8fb3 2005-12-27 devnull if(nelems > 0){
535 3e0d8fb3 2005-12-27 devnull /* walk fid */
536 3e0d8fb3 2005-12-27 devnull for(i=0; i<nelems && i<MAXWELEM; i++){
537 3e0d8fb3 2005-12-27 devnull if((qid.type & QTDIR) == 0){
538 3e0d8fb3 2005-12-27 devnull err = "not a directory";
541 3e0d8fb3 2005-12-27 devnull if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){
542 3e0d8fb3 2005-12-27 devnull qid.type = QTDIR;
543 3e0d8fb3 2005-12-27 devnull qid.path = Qdir;
545 3e0d8fb3 2005-12-27 devnull job->reply.wqid[i] = qid;
546 3e0d8fb3 2005-12-27 devnull job->reply.nwqid++;
547 3e0d8fb3 2005-12-27 devnull continue;
549 3e0d8fb3 2005-12-27 devnull if(strcmp(elems[i], "dns") == 0){
550 3e0d8fb3 2005-12-27 devnull qid.type = QTFILE;
551 3e0d8fb3 2005-12-27 devnull qid.path = Qdns;
552 3e0d8fb3 2005-12-27 devnull goto Found;
554 3e0d8fb3 2005-12-27 devnull err = "file does not exist";
560 3e0d8fb3 2005-12-27 devnull if(nmf != nil && (err!=nil || job->reply.nwqid<nelems))
561 3e0d8fb3 2005-12-27 devnull freefid(nmf);
562 3e0d8fb3 2005-12-27 devnull if(err == nil)
563 3e0d8fb3 2005-12-27 devnull mf->qid = qid;
564 3e0d8fb3 2005-12-27 devnull sendmsg(job, err);
565 3e0d8fb3 2005-12-27 devnull return err;
569 3e0d8fb3 2005-12-27 devnull ropen(Job *job, Mfile *mf)
571 3e0d8fb3 2005-12-27 devnull int mode;
572 3e0d8fb3 2005-12-27 devnull char *err;
574 3e0d8fb3 2005-12-27 devnull err = 0;
575 3e0d8fb3 2005-12-27 devnull mode = job->request.mode;
576 3e0d8fb3 2005-12-27 devnull if(mf->qid.type & QTDIR){
577 3e0d8fb3 2005-12-27 devnull if(mode)
578 3e0d8fb3 2005-12-27 devnull err = "permission denied";
580 3e0d8fb3 2005-12-27 devnull job->reply.qid = mf->qid;
581 3e0d8fb3 2005-12-27 devnull job->reply.iounit = 0;
582 3e0d8fb3 2005-12-27 devnull sendmsg(job, err);
586 3e0d8fb3 2005-12-27 devnull rcreate(Job *job, Mfile *mf)
588 3e0d8fb3 2005-12-27 devnull USED(mf);
589 3e0d8fb3 2005-12-27 devnull sendmsg(job, "creation permission denied");
593 3e0d8fb3 2005-12-27 devnull rread(Job *job, Mfile *mf)
595 3e0d8fb3 2005-12-27 devnull int i, n, cnt;
596 3e0d8fb3 2005-12-27 devnull long off;
597 3e0d8fb3 2005-12-27 devnull Dir dir;
598 3e0d8fb3 2005-12-27 devnull uchar buf[Maxfdata];
599 3e0d8fb3 2005-12-27 devnull char *err;
600 3e0d8fb3 2005-12-27 devnull long clock;
603 3e0d8fb3 2005-12-27 devnull err = 0;
604 3e0d8fb3 2005-12-27 devnull off = job->request.offset;
605 3e0d8fb3 2005-12-27 devnull cnt = job->request.count;
606 3e0d8fb3 2005-12-27 devnull if(mf->qid.type & QTDIR){
607 3e0d8fb3 2005-12-27 devnull clock = time(0);
608 3e0d8fb3 2005-12-27 devnull if(off == 0){
609 3e0d8fb3 2005-12-27 devnull dir.name = "dns";
610 3e0d8fb3 2005-12-27 devnull dir.qid.type = QTFILE;
611 3e0d8fb3 2005-12-27 devnull dir.qid.vers = vers;
612 3e0d8fb3 2005-12-27 devnull dir.qid.path = Qdns;
613 3e0d8fb3 2005-12-27 devnull dir.mode = 0666;
614 3e0d8fb3 2005-12-27 devnull dir.length = 0;
615 3e0d8fb3 2005-12-27 devnull dir.uid = mf->user;
616 3e0d8fb3 2005-12-27 devnull dir.gid = mf->user;
617 3e0d8fb3 2005-12-27 devnull dir.muid = mf->user;
618 3e0d8fb3 2005-12-27 devnull dir.atime = clock; /* wrong */
619 3e0d8fb3 2005-12-27 devnull dir.mtime = clock; /* wrong */
620 3e0d8fb3 2005-12-27 devnull n = convD2M(&dir, buf, sizeof buf);
622 3e0d8fb3 2005-12-27 devnull job->reply.data = (char*)buf;
623 3e0d8fb3 2005-12-27 devnull } else {
624 3e0d8fb3 2005-12-27 devnull for(i = 1; i <= mf->nrr; i++)
625 3e0d8fb3 2005-12-27 devnull if(mf->rr[i] > off)
627 3e0d8fb3 2005-12-27 devnull if(i > mf->nrr)
628 3e0d8fb3 2005-12-27 devnull goto send;
629 3e0d8fb3 2005-12-27 devnull if(off + cnt > mf->rr[i])
630 3e0d8fb3 2005-12-27 devnull n = mf->rr[i] - off;
632 3e0d8fb3 2005-12-27 devnull n = cnt;
633 3e0d8fb3 2005-12-27 devnull job->reply.data = mf->reply + off;
636 3e0d8fb3 2005-12-27 devnull job->reply.count = n;
637 3e0d8fb3 2005-12-27 devnull sendmsg(job, err);
641 3e0d8fb3 2005-12-27 devnull rwrite(Job *job, Mfile *mf, Request *req)
643 3e0d8fb3 2005-12-27 devnull int cnt, rooted, status;
645 3e0d8fb3 2005-12-27 devnull char *err, *p, *atype;
646 3e0d8fb3 2005-12-27 devnull RR *rp, *tp, *neg;
647 3e0d8fb3 2005-12-27 devnull int wantsav;
648 5c9f76b5 2006-02-14 devnull static char *dumpfile;
650 3e0d8fb3 2005-12-27 devnull err = 0;
651 3e0d8fb3 2005-12-27 devnull cnt = job->request.count;
652 3e0d8fb3 2005-12-27 devnull if(mf->qid.type & QTDIR){
653 3e0d8fb3 2005-12-27 devnull err = "can't write directory";
654 3e0d8fb3 2005-12-27 devnull goto send;
656 3e0d8fb3 2005-12-27 devnull if(cnt >= Maxrequest){
657 3e0d8fb3 2005-12-27 devnull err = "request too long";
658 3e0d8fb3 2005-12-27 devnull goto send;
660 3e0d8fb3 2005-12-27 devnull job->request.data[cnt] = 0;
661 3e0d8fb3 2005-12-27 devnull if(cnt > 0 && job->request.data[cnt-1] == '\n')
662 3e0d8fb3 2005-12-27 devnull job->request.data[cnt-1] = 0;
665 3e0d8fb3 2005-12-27 devnull * special commands
667 5c9f76b5 2006-02-14 devnull p = job->request.data;
668 5c9f76b5 2006-02-14 devnull if(strcmp(p, "debug")==0){
669 3e0d8fb3 2005-12-27 devnull debug ^= 1;
670 3e0d8fb3 2005-12-27 devnull goto send;
671 5c9f76b5 2006-02-14 devnull } else if(strcmp(p, "dump")==0){
672 5c9f76b5 2006-02-14 devnull if(dumpfile == nil)
673 5c9f76b5 2006-02-14 devnull dumpfile = unsharp("#9/ndb/dnsdump");
674 5c9f76b5 2006-02-14 devnull dndump(dumpfile);
675 3e0d8fb3 2005-12-27 devnull goto send;
676 5c9f76b5 2006-02-14 devnull } else if(strncmp(p, "dump ", 5) == 0){
677 19256e0d 2006-02-17 devnull if(*(p+5))
678 19256e0d 2006-02-17 devnull dndump(p+5);
680 19256e0d 2006-02-17 devnull err = "bad filename";
681 5c9f76b5 2006-02-14 devnull goto send;
682 5c9f76b5 2006-02-14 devnull } else if(strcmp(p, "refresh")==0){
683 3e0d8fb3 2005-12-27 devnull needrefresh = 1;
684 3e0d8fb3 2005-12-27 devnull goto send;
688 3e0d8fb3 2005-12-27 devnull * kill previous reply
690 3e0d8fb3 2005-12-27 devnull mf->nrr = 0;
691 3e0d8fb3 2005-12-27 devnull mf->rr[0] = 0;
694 3e0d8fb3 2005-12-27 devnull * break up request (into a name and a type)
696 3e0d8fb3 2005-12-27 devnull atype = strchr(job->request.data, ' ');
697 3e0d8fb3 2005-12-27 devnull if(atype == 0){
698 3e0d8fb3 2005-12-27 devnull err = "illegal request";
699 3e0d8fb3 2005-12-27 devnull goto send;
701 3e0d8fb3 2005-12-27 devnull *atype++ = 0;
704 3e0d8fb3 2005-12-27 devnull * tracing request
706 3e0d8fb3 2005-12-27 devnull if(strcmp(atype, "trace") == 0){
707 3e0d8fb3 2005-12-27 devnull if(trace)
708 3e0d8fb3 2005-12-27 devnull free(trace);
709 3e0d8fb3 2005-12-27 devnull if(*job->request.data)
710 3e0d8fb3 2005-12-27 devnull trace = estrdup(job->request.data);
712 3e0d8fb3 2005-12-27 devnull trace = 0;
713 3e0d8fb3 2005-12-27 devnull goto send;
716 3e0d8fb3 2005-12-27 devnull mf->type = rrtype(atype);
717 3e0d8fb3 2005-12-27 devnull if(mf->type < 0){
718 3e0d8fb3 2005-12-27 devnull err = "unknown type";
719 3e0d8fb3 2005-12-27 devnull goto send;
722 3e0d8fb3 2005-12-27 devnull p = atype - 2;
723 3e0d8fb3 2005-12-27 devnull if(p >= job->request.data && *p == '.'){
724 3e0d8fb3 2005-12-27 devnull rooted = 1;
727 3e0d8fb3 2005-12-27 devnull rooted = 0;
729 3e0d8fb3 2005-12-27 devnull p = job->request.data;
730 3e0d8fb3 2005-12-27 devnull if(*p == '!'){
731 3e0d8fb3 2005-12-27 devnull wantsav = 1;
734 3e0d8fb3 2005-12-27 devnull wantsav = 0;
735 3e0d8fb3 2005-12-27 devnull dncheck(0, 1);
736 3e0d8fb3 2005-12-27 devnull rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status);
737 3e0d8fb3 2005-12-27 devnull dncheck(0, 1);
738 3e0d8fb3 2005-12-27 devnull neg = rrremneg(&rp);
739 3e0d8fb3 2005-12-27 devnull if(neg){
740 3e0d8fb3 2005-12-27 devnull status = neg->negrcode;
741 3e0d8fb3 2005-12-27 devnull rrfreelist(neg);
743 3e0d8fb3 2005-12-27 devnull if(rp == 0){
744 3e0d8fb3 2005-12-27 devnull switch(status){
745 3e0d8fb3 2005-12-27 devnull case Rname:
746 3e0d8fb3 2005-12-27 devnull err = "name does not exist";
748 3e0d8fb3 2005-12-27 devnull case Rserver:
749 3e0d8fb3 2005-12-27 devnull err = "dns failure";
751 3e0d8fb3 2005-12-27 devnull default:
752 3e0d8fb3 2005-12-27 devnull err = "resource does not exist";
755 3e0d8fb3 2005-12-27 devnull } else {
756 3e0d8fb3 2005-12-27 devnull lock(&joblock);
757 3e0d8fb3 2005-12-27 devnull if(!job->flushed){
758 3e0d8fb3 2005-12-27 devnull /* format data to be read later */
760 3e0d8fb3 2005-12-27 devnull mf->nrr = 0;
761 3e0d8fb3 2005-12-27 devnull for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp &&
762 3e0d8fb3 2005-12-27 devnull tsame(mf->type, tp->type); tp = tp->next){
763 3e0d8fb3 2005-12-27 devnull mf->rr[mf->nrr++] = n;
764 3e0d8fb3 2005-12-27 devnull if(wantsav)
765 3e0d8fb3 2005-12-27 devnull n += snprint(mf->reply+n, Maxreply-n, "%Q", tp);
767 3e0d8fb3 2005-12-27 devnull n += snprint(mf->reply+n, Maxreply-n, "%R", tp);
769 3e0d8fb3 2005-12-27 devnull mf->rr[mf->nrr] = n;
771 3e0d8fb3 2005-12-27 devnull unlock(&joblock);
772 3e0d8fb3 2005-12-27 devnull rrfreelist(rp);
776 3e0d8fb3 2005-12-27 devnull dncheck(0, 1);
777 3e0d8fb3 2005-12-27 devnull job->reply.count = cnt;
778 3e0d8fb3 2005-12-27 devnull sendmsg(job, err);
782 3e0d8fb3 2005-12-27 devnull rclunk(Job *job, Mfile *mf)
784 3e0d8fb3 2005-12-27 devnull freefid(mf);
785 3e0d8fb3 2005-12-27 devnull sendmsg(job, 0);
789 3e0d8fb3 2005-12-27 devnull rremove(Job *job, Mfile *mf)
791 3e0d8fb3 2005-12-27 devnull USED(mf);
792 3e0d8fb3 2005-12-27 devnull sendmsg(job, "remove permission denied");
796 3e0d8fb3 2005-12-27 devnull rstat(Job *job, Mfile *mf)
798 3e0d8fb3 2005-12-27 devnull Dir dir;
799 3e0d8fb3 2005-12-27 devnull uchar buf[IOHDRSZ+Maxfdata];
801 3e0d8fb3 2005-12-27 devnull if(mf->qid.type & QTDIR){
802 3e0d8fb3 2005-12-27 devnull dir.name = ".";
803 3e0d8fb3 2005-12-27 devnull dir.mode = DMDIR|0555;
804 3e0d8fb3 2005-12-27 devnull } else {
805 3e0d8fb3 2005-12-27 devnull dir.name = "dns";
806 3e0d8fb3 2005-12-27 devnull dir.mode = 0666;
808 3e0d8fb3 2005-12-27 devnull dir.qid = mf->qid;
809 3e0d8fb3 2005-12-27 devnull dir.length = 0;
810 3e0d8fb3 2005-12-27 devnull dir.uid = mf->user;
811 3e0d8fb3 2005-12-27 devnull dir.gid = mf->user;
812 3e0d8fb3 2005-12-27 devnull dir.muid = mf->user;
813 3e0d8fb3 2005-12-27 devnull dir.atime = dir.mtime = time(0);
814 3e0d8fb3 2005-12-27 devnull job->reply.nstat = convD2M(&dir, buf, sizeof buf);
815 3e0d8fb3 2005-12-27 devnull job->reply.stat = buf;
816 3e0d8fb3 2005-12-27 devnull sendmsg(job, 0);
820 3e0d8fb3 2005-12-27 devnull rwstat(Job *job, Mfile *mf)
822 3e0d8fb3 2005-12-27 devnull USED(mf);
823 3e0d8fb3 2005-12-27 devnull sendmsg(job, "wstat permission denied");
827 3e0d8fb3 2005-12-27 devnull sendmsg(Job *job, char *err)
830 3e0d8fb3 2005-12-27 devnull uchar mdata[IOHDRSZ + Maxfdata];
831 3e0d8fb3 2005-12-27 devnull char ename[ERRMAX];
833 3e0d8fb3 2005-12-27 devnull if(err){
834 3e0d8fb3 2005-12-27 devnull job->reply.type = Rerror;
835 3e0d8fb3 2005-12-27 devnull snprint(ename, sizeof(ename), "dns: %s", err);
836 3e0d8fb3 2005-12-27 devnull job->reply.ename = ename;
838 3e0d8fb3 2005-12-27 devnull job->reply.type = job->request.type+1;
840 3e0d8fb3 2005-12-27 devnull job->reply.tag = job->request.tag;
841 3e0d8fb3 2005-12-27 devnull n = convS2M(&job->reply, mdata, sizeof mdata);
842 3e0d8fb3 2005-12-27 devnull if(n == 0){
843 3e0d8fb3 2005-12-27 devnull syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply);
844 3e0d8fb3 2005-12-27 devnull abort();
846 3e0d8fb3 2005-12-27 devnull lock(&joblock);
847 3e0d8fb3 2005-12-27 devnull if(job->flushed == 0)
848 3e0d8fb3 2005-12-27 devnull if(write(mfd[1], mdata, n)!=n)
849 3e0d8fb3 2005-12-27 devnull sysfatal("mount write");
850 3e0d8fb3 2005-12-27 devnull unlock(&joblock);
851 3e0d8fb3 2005-12-27 devnull if(debug)
852 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "%F %d", &job->reply, n);
856 3e0d8fb3 2005-12-27 devnull * the following varies between dnsdebug and dns
859 3e0d8fb3 2005-12-27 devnull logreply(int id, uchar *addr, DNSmsg *mp)
863 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: rcvd %I flags:%s%s%s%s%s", id, addr,
864 3e0d8fb3 2005-12-27 devnull mp->flags & Fauth ? " auth" : "",
865 3e0d8fb3 2005-12-27 devnull mp->flags & Ftrunc ? " trunc" : "",
866 3e0d8fb3 2005-12-27 devnull mp->flags & Frecurse ? " rd" : "",
867 3e0d8fb3 2005-12-27 devnull mp->flags & Fcanrec ? " ra" : "",
868 3e0d8fb3 2005-12-27 devnull mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
869 3e0d8fb3 2005-12-27 devnull " nx" : "");
870 3e0d8fb3 2005-12-27 devnull for(rp = mp->qd; rp != nil; rp = rp->next)
871 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: rcvd %I qd %s", id, addr, rp->owner->name);
872 3e0d8fb3 2005-12-27 devnull for(rp = mp->an; rp != nil; rp = rp->next)
873 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: rcvd %I an %R", id, addr, rp);
874 3e0d8fb3 2005-12-27 devnull for(rp = mp->ns; rp != nil; rp = rp->next)
875 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: rcvd %I ns %R", id, addr, rp);
876 3e0d8fb3 2005-12-27 devnull for(rp = mp->ar; rp != nil; rp = rp->next)
877 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: rcvd %I ar %R", id, addr, rp);
881 3e0d8fb3 2005-12-27 devnull logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
883 3e0d8fb3 2005-12-27 devnull char buf[12];
885 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d.%d: sending to %I/%s %s %s",
886 3e0d8fb3 2005-12-27 devnull id, subid, addr, sname, rname, rrname(type, buf, sizeof buf));
890 3e0d8fb3 2005-12-27 devnull getdnsservers(int class)
892 3e0d8fb3 2005-12-27 devnull return dnsservers(class);