void main(int argc, char *argv[]) { int kid, pid; char servefile[Maxpath], ext[Maxpath]; Dir *dir; setnetmtpt(mntpt, sizeof mntpt, nil); ext[0] = 0; ARGBEGIN{ case 'a': maxage = atol(EARGF(usage())); if (maxage <= 0) maxage = Defmaxage; break; case 'd': debug = 1; traceactivity = 1; break; case 'f': dbfile = EARGF(usage()); break; case 'F': cfg.justforw = cfg.resolver = 1; break; case 'n': sendnotifies = 1; break; case 'N': target = atol(EARGF(usage())); if (target < 1000) target = 1000; break; case 'o': cfg.straddle = 1; /* straddle inside & outside networks */ break; case 'r': cfg.resolver = 1; break; case 'R': norecursion = 1; break; case 's': cfg.serve = 1; /* serve network */ cfg.cachedb = 1; break; case 't': testing = 1; break; case 'T': addforwtarg(EARGF(usage())); break; case 'x': setnetmtpt(mntpt, sizeof mntpt, EARGF(usage())); setext(ext, sizeof ext, mntpt); break; case 'z': zonerefreshprogram = EARGF(usage()); break; default: usage(); break; }ARGEND if(argc != 0) usage(); if(testing) mainmem->flags |= POOL_NOREUSE | POOL_ANTAGONISM; mainmem->flags |= POOL_ANTAGONISM; rfork(RFREND|RFNOTEG); cfg.inside = (*mntpt == '\0' || strcmp(mntpt, "/net") == 0); /* start syslog before we fork */ fmtinstall('F', fcallfmt); dninit(); /* this really shouldn't be fatal */ if(myipaddr(ipaddr, mntpt) < 0) sysfatal("can't read my ip address"); dnslog("starting %s%sdns %s%s%son %I's %s", (cfg.straddle? "straddling ": ""), (cfg.cachedb? "caching ": ""), (cfg.serve? "udp server ": ""), (cfg.justforw? "forwarding-only ": ""), (cfg.resolver? "resolver ": ""), ipaddr, mntpt); opendatabase(); now = time(nil); /* open time files before we fork */ nowns = nsec(); snprint(servefile, sizeof servefile, "#s/dns%s", ext); dir = dirstat(servefile); if (dir) sysfatal("%s exists; another dns instance is running", servefile); free(dir); /* don't unmount here; could deadlock */ // while (unmount(servefile, mntpt) >= 0) // ; mountinit(servefile, mntpt); /* forks, parent exits */ srand(now*getpid()); db2cache(1); // dnageallnever(); if (cfg.straddle && !seerootns()) dnslog("straddle server misconfigured; can't resolve root name servers"); /* * fork without sharing heap. * parent waits around for child to die, then forks & restarts. * child may spawn udp server, notify procs, etc.; when it gets too * big or too old, it kills itself and any children. * * /srv/dns remains open and valid, but /net/dns was only mounted in * a child's separate namespace from 9p service, to avoid a deadlock * from serving our own namespace, so we must remount it upon restart, * in a separate process and namespace. */ for (;;) { start = time(nil); /* don't unmount here; could deadlock */ // unmount(servefile, mntpt); kid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG); switch (kid) { case -1: sysfatal("fork failed: %r"); case 0: if(cfg.serve) dnudpserver(mntpt); if(sendnotifies) notifyproc(); io(); /* serve 9p; return implies restart */ _exits("restart"); } sleep(1000); /* wait for 9p service to start */ justremount(servefile, mntpt); while ((pid = waitpid()) != kid && pid != -1) continue; dnslog("restarting"); } }
void main(int argc, char *argv[]) { int len, rcode; char tname[32]; char *err, *ext = ""; unsigned char buf[64*1024], callip[IPaddrlen]; DNSmsg reqmsg, repmsg; Request req; alarm(2*60*1000); cfg.cachedb = 1; ARGBEGIN{ case 'd': debug++; break; case 'f': dbfile = EARGF(usage()); break; case 'r': cfg.resolver = 1; break; case 'R': norecursion = 1; break; case 'x': ext = EARGF(usage()); break; default: usage(); break; }ARGEND if(debug < 2) debug = 0; if(argc > 0) getcaller(argv[0]); cfg.inside = 1; dninit(); snprint(mntpt, sizeof mntpt, "/net%s", ext); if(myipaddr(ipaddr, mntpt) < 0) sysfatal("can't read my ip address"); dnslog("dnstcp call from %s to %I", caller, ipaddr); memset(callip, 0, sizeof callip); parseip(callip, caller); db2cache(1); memset(&req, 0, sizeof req); setjmp(req.mret); req.isslave = 0; procsetname("main loop"); /* loop on requests */ for(;; putactivity(0)){ now = time(nil); memset(&repmsg, 0, sizeof repmsg); len = readmsg(0, buf, sizeof buf); if(len <= 0) break; getactivity(&req, 0); req.aborttime = timems() + S2MS(15*Min); rcode = 0; memset(&reqmsg, 0, sizeof reqmsg); err = convM2DNS(buf, len, &reqmsg, &rcode); if(err){ dnslog("server: input error: %s from %s", err, caller); free(err); break; } if (rcode == 0) { if(reqmsg.qdcount < 1){ dnslog("server: no questions from %s", caller); break; } else if(reqmsg.flags & Fresp){ dnslog("server: reply not request from %s", caller); break; } else if((reqmsg.flags & Omask) != Oquery){ dnslog("server: op %d from %s", reqmsg.flags & Omask, caller); break; } } if(debug) dnslog("[%d] %d: serve (%s) %d %s %s", getpid(), req.id, caller, reqmsg.id, reqmsg.qd->owner->name, rrname(reqmsg.qd->type, tname, sizeof tname)); /* loop through each question */ while(reqmsg.qd) if(reqmsg.qd->type == Taxfr) dnzone(&reqmsg, &repmsg, &req); else { dnserver(&reqmsg, &repmsg, &req, callip, rcode); reply(1, &repmsg, &req); rrfreelist(repmsg.qd); rrfreelist(repmsg.an); rrfreelist(repmsg.ns); rrfreelist(repmsg.ar); } rrfreelist(reqmsg.qd); /* qd will be nil */ rrfreelist(reqmsg.an); rrfreelist(reqmsg.ns); rrfreelist(reqmsg.ar); if(req.isslave){ putactivity(0); _exits(0); } } refreshmain(mntpt); }
void threadmain(int argc, char *argv[]) { int serveudp, servetcp; char *service; serveudp = 0; servetcp = 0; service = "dns"; ARGBEGIN{ case 'd': debug = 1; traceactivity = 1; break; case 'f': dbfile = EARGF(usage()); break; case 'x': service = EARGF(usage()); break; case 'r': resolver = 1; break; case 's': serveudp = 1; cachedb = 1; break; case 't': servetcp = 1; cachedb = 1; break; case 'a': maxage = atoi(EARGF(usage())); break; case 'z': zonerefreshprogram = EARGF(usage()); break; case 'n': sendnotifies = 1; break; case 'U': udpaddr = estrdup(netmkaddr(EARGF(usage()), "udp", "domain")); break; case 'T': tcpaddr = estrdup(netmkaddr(EARGF(usage()), "tcp", "domain")); break; default: usage(); }ARGEND if(argc) usage(); if(serveudp && servetcp) checkaddress(); rfork(RFNOTEG); /* start syslog before we fork */ fmtinstall('F', fcallfmt); dninit(); if(myipaddr(ipaddr, mntpt) < 0) sysfatal("can't read my ip address"); syslog(0, logfile, "starting dns on %I", ipaddr); opendatabase(); mountinit(service); now = time(0); srand(now*getpid()); db2cache(1); if(serveudp) proccreate(dnudpserver, nil, STACK); if(servetcp) proccreate(dntcpserver, nil, STACK); if(sendnotifies) proccreate(notifyproc, nil, STACK); io(); }