dnudpserver.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <ip.h>
  12. #include "dns.h"
  13. enum {
  14. Logqueries = 0,
  15. };
  16. static int udpannounce(char*);
  17. static void reply(int, uint8_t*, DNSmsg*, Request*);
  18. typedef struct Inprogress Inprogress;
  19. struct Inprogress
  20. {
  21. int inuse;
  22. Udphdr uh;
  23. DN *owner;
  24. uint16_t type;
  25. int id;
  26. };
  27. Inprogress inprog[Maxactive+2];
  28. typedef struct Forwtarg Forwtarg;
  29. struct Forwtarg {
  30. char *host;
  31. uint8_t addr[IPaddrlen];
  32. int fd;
  33. uint32_t lastdial;
  34. };
  35. Forwtarg forwtarg[10];
  36. int currtarg;
  37. static char *hmsg = "headers";
  38. /*
  39. * record client id and ignore retransmissions.
  40. * we're still single thread at this point.
  41. */
  42. static Inprogress*
  43. clientrxmit(DNSmsg *req, uint8_t *buf)
  44. {
  45. Inprogress *p, *empty;
  46. Udphdr *uh;
  47. uh = (Udphdr *)buf;
  48. empty = nil;
  49. for(p = inprog; p < &inprog[Maxactive]; p++){
  50. if(p->inuse == 0){
  51. if(empty == nil)
  52. empty = p;
  53. continue;
  54. }
  55. if(req->id == p->id && req->qd != nil &&
  56. req->qd->owner == p->owner && req->qd->type == p->type &&
  57. memcmp(uh, &p->uh, Udphdrsize) == 0)
  58. return nil;
  59. }
  60. if(empty == nil)
  61. return nil; /* shouldn't happen: see slave() & Maxactive def'n */
  62. if(req->qd == nil) {
  63. dnslog("clientrxmit: nil req->qd");
  64. return nil;
  65. }
  66. empty->id = req->id;
  67. empty->owner = req->qd->owner;
  68. empty->type = req->qd->type;
  69. if (empty->type != req->qd->type)
  70. dnslog("clientrxmit: bogus req->qd->type %d", req->qd->type);
  71. memmove(&empty->uh, uh, Udphdrsize);
  72. empty->inuse = 1;
  73. return empty;
  74. }
  75. int
  76. addforwtarg(char *host)
  77. {
  78. Forwtarg *tp;
  79. if (currtarg >= nelem(forwtarg)) {
  80. dnslog("too many forwarding targets");
  81. return -1;
  82. }
  83. tp = forwtarg + currtarg;
  84. if (parseip(tp->addr, host) < 0) {
  85. dnslog("can't parse ip %s", host);
  86. return -1;
  87. }
  88. tp->lastdial = time(nil);
  89. tp->fd = udpport(mntpt);
  90. if (tp->fd < 0)
  91. return -1;
  92. free(tp->host);
  93. tp->host = estrdup(host);
  94. currtarg++;
  95. return 0;
  96. }
  97. /*
  98. * fast forwarding of incoming queries to other dns servers.
  99. * intended primarily for debugging.
  100. */
  101. static void
  102. redistrib(uint8_t *buf, int len)
  103. {
  104. Forwtarg *tp;
  105. Udphdr *uh;
  106. static uint8_t outpkt[1500];
  107. assert(len <= sizeof outpkt);
  108. memmove(outpkt, buf, len);
  109. uh = (Udphdr *)outpkt;
  110. for (tp = forwtarg; tp < forwtarg + currtarg; tp++)
  111. if (tp->fd > 0) {
  112. memmove(outpkt, tp->addr, sizeof tp->addr);
  113. hnputs(uh->rport, Dnsport);
  114. if (write(tp->fd, outpkt, len) != len) {
  115. close(tp->fd);
  116. tp->fd = -1;
  117. }
  118. } else if (tp->host && time(nil) - tp->lastdial > 60) {
  119. tp->lastdial = time(nil);
  120. tp->fd = udpport(mntpt);
  121. }
  122. }
  123. /*
  124. * a process to act as a dns server for outside reqeusts
  125. */
  126. void
  127. dnudpserver(char *mntpt)
  128. {
  129. int fd, len, op, rcode;
  130. char *err;
  131. char tname[32];
  132. uint8_t buf[Udphdrsize + Maxpayload];
  133. DNSmsg reqmsg, repmsg;
  134. Inprogress *p;
  135. Request req;
  136. Udphdr *uh;
  137. /*
  138. * fork sharing text, data, and bss with parent.
  139. * stay in the same note group.
  140. */
  141. switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
  142. case -1:
  143. break;
  144. case 0:
  145. break;
  146. default:
  147. return;
  148. }
  149. fd = -1;
  150. restart:
  151. procsetname("udp server announcing");
  152. if(fd >= 0)
  153. close(fd);
  154. while((fd = udpannounce(mntpt)) < 0)
  155. sleep(5000);
  156. // procsetname("udp server");
  157. memset(&req, 0, sizeof req);
  158. if(setjmp(req.mret))
  159. putactivity(0);
  160. req.isslave = 0;
  161. req.id = 0;
  162. req.aborttime = 0;
  163. /* loop on requests */
  164. for(;; putactivity(0)){
  165. procsetname("served %d udp; %d alarms",
  166. stats.qrecvdudp, stats.alarms);
  167. memset(&repmsg, 0, sizeof repmsg);
  168. memset(&reqmsg, 0, sizeof reqmsg);
  169. alarm(60*1000);
  170. len = read(fd, buf, sizeof buf);
  171. alarm(0);
  172. if(len <= Udphdrsize)
  173. goto restart;
  174. redistrib(buf, len);
  175. uh = (Udphdr*)buf;
  176. len -= Udphdrsize;
  177. // dnslog("read received UDP from %I to %I",
  178. // ((Udphdr*)buf)->raddr, ((Udphdr*)buf)->laddr);
  179. getactivity(&req, 0);
  180. req.aborttime = timems() + Maxreqtm;
  181. // req.from = smprint("%I", ((Udphdr*)buf)->raddr);
  182. req.from = smprint("%I", buf);
  183. rcode = 0;
  184. stats.qrecvdudp++;
  185. err = convM2DNS(&buf[Udphdrsize], len, &reqmsg, &rcode);
  186. if(err){
  187. /* first bytes in buf are source IP addr */
  188. dnslog("server: input error: %s from %I", err, buf);
  189. free(err);
  190. goto freereq;
  191. }
  192. if (rcode == 0)
  193. if(reqmsg.qdcount < 1){
  194. dnslog("server: no questions from %I", buf);
  195. goto freereq;
  196. } else if(reqmsg.flags & Fresp){
  197. dnslog("server: reply not request from %I", buf);
  198. goto freereq;
  199. }
  200. op = reqmsg.flags & Omask;
  201. if(op != Oquery && op != Onotify){
  202. dnslog("server: op %d from %I", reqmsg.flags & Omask,
  203. buf);
  204. goto freereq;
  205. }
  206. if(debug || (trace && subsume(trace, reqmsg.qd->owner->name)))
  207. dnslog("%d: serve (%I/%d) %d %s %s",
  208. req.id, buf, uh->rport[0]<<8 | uh->rport[1],
  209. reqmsg.id, reqmsg.qd->owner->name,
  210. rrname(reqmsg.qd->type, tname, sizeof tname));
  211. p = clientrxmit(&reqmsg, buf);
  212. if(p == nil){
  213. if(debug)
  214. dnslog("%d: duplicate", req.id);
  215. goto freereq;
  216. }
  217. if (Logqueries) {
  218. RR *rr;
  219. for (rr = reqmsg.qd; rr; rr = rr->next)
  220. syslog(0, "dnsq", "id %d: (%I/%d) %d %s %s",
  221. req.id, buf, uh->rport[0]<<8 |
  222. uh->rport[1], reqmsg.id,
  223. reqmsg.qd->owner->name,
  224. rrname(reqmsg.qd->type, tname,
  225. sizeof tname));
  226. }
  227. /* loop through each question */
  228. while(reqmsg.qd){
  229. memset(&repmsg, 0, sizeof repmsg);
  230. switch(op){
  231. case Oquery:
  232. dnserver(&reqmsg, &repmsg, &req, buf, rcode);
  233. break;
  234. case Onotify:
  235. dnnotify(&reqmsg, &repmsg, &req);
  236. break;
  237. }
  238. /* send reply on fd to address in buf's udp hdr */
  239. reply(fd, buf, &repmsg, &req);
  240. freeanswers(&repmsg);
  241. }
  242. p->inuse = 0;
  243. freereq:
  244. free(req.from);
  245. req.from = nil;
  246. freeanswers(&reqmsg);
  247. if(req.isslave){
  248. putactivity(0);
  249. _exits(0);
  250. }
  251. }
  252. }
  253. /*
  254. * announce on well-known dns udp port and set message style interface
  255. */
  256. static int
  257. udpannounce(char *mntpt)
  258. {
  259. int data, ctl;
  260. char dir[64], datafile[64+6];
  261. static int whined;
  262. /* get a udp port */
  263. sprint(datafile, "%s/udp!*!dns", mntpt);
  264. ctl = announce(datafile, dir);
  265. if(ctl < 0){
  266. if(!whined++)
  267. warning("can't announce on %s", datafile);
  268. return -1;
  269. }
  270. /* turn on header style interface */
  271. if(write(ctl, hmsg, strlen(hmsg)) != strlen(hmsg))
  272. abort(); /* hmsg */
  273. snprint(datafile, sizeof(datafile), "%s/data", dir);
  274. data = open(datafile, ORDWR);
  275. if(data < 0){
  276. close(ctl);
  277. if(!whined++)
  278. warning("can't open %s to announce on dns udp port",
  279. datafile);
  280. return -1;
  281. }
  282. close(ctl);
  283. return data;
  284. }
  285. static void
  286. reply(int fd, uint8_t *buf, DNSmsg *rep, Request *reqp)
  287. {
  288. int len;
  289. char tname[32];
  290. if(debug || (trace && subsume(trace, rep->qd->owner->name)))
  291. dnslog("%d: reply (%I/%d) %d %s %s qd %R an %R ns %R ar %R",
  292. reqp->id, buf, buf[4]<<8 | buf[5],
  293. rep->id, rep->qd->owner->name,
  294. rrname(rep->qd->type, tname, sizeof tname),
  295. rep->qd, rep->an, rep->ns, rep->ar);
  296. len = convDNS2M(rep, &buf[Udphdrsize], Maxdnspayload);
  297. len += Udphdrsize;
  298. if(write(fd, buf, len) != len)
  299. dnslog("error sending reply: %r");
  300. }