convDNS2M.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include "dns.h"
  5. /*
  6. * a dictionary of domain names for packing messages
  7. */
  8. enum
  9. {
  10. Ndict= 64,
  11. };
  12. typedef struct Dict Dict;
  13. struct Dict
  14. {
  15. struct {
  16. ushort offset; /* pointer to packed name in message */
  17. char *name; /* pointer to unpacked name in buf */
  18. } x[Ndict];
  19. int n; /* size of dictionary */
  20. uchar *start; /* start of packed message */
  21. char buf[16*1024]; /* buffer for unpacked names (was 4k) */
  22. char *ep; /* first free char in buf */
  23. };
  24. #define NAME(x) p = pname(p, ep, x, dp)
  25. #define SYMBOL(x) p = psym(p, ep, x)
  26. #define STRING(x) p = pstr(p, ep, x)
  27. #define BYTES(x, n) p = pbytes(p, ep, x, n)
  28. #define USHORT(x) p = pushort(p, ep, x)
  29. #define UCHAR(x) p = puchar(p, ep, x)
  30. #define ULONG(x) p = pulong(p, ep, x)
  31. #define V4ADDR(x) p = pv4addr(p, ep, x)
  32. #define V6ADDR(x) p = pv6addr(p, ep, x)
  33. static uchar*
  34. psym(uchar *p, uchar *ep, char *np)
  35. {
  36. int n;
  37. n = strlen(np);
  38. if(n >= Strlen) /* DNS maximum length string */
  39. n = Strlen - 1;
  40. if(ep - p < n+1) /* see if it fits in the buffer */
  41. return ep+1;
  42. *p++ = n;
  43. memmove(p, np, n);
  44. return p + n;
  45. }
  46. static uchar*
  47. pstr(uchar *p, uchar *ep, char *np)
  48. {
  49. return psym(p, ep, np);
  50. }
  51. static uchar*
  52. pbytes(uchar *p, uchar *ep, uchar *np, int n)
  53. {
  54. if(ep - p < n)
  55. return ep+1;
  56. memmove(p, np, n);
  57. return p + n;
  58. }
  59. static uchar*
  60. puchar(uchar *p, uchar *ep, int val)
  61. {
  62. if(ep - p < 1)
  63. return ep+1;
  64. *p++ = val;
  65. return p;
  66. }
  67. static uchar*
  68. pushort(uchar *p, uchar *ep, int val)
  69. {
  70. if(ep - p < 2)
  71. return ep+1;
  72. *p++ = val>>8;
  73. *p++ = val;
  74. return p;
  75. }
  76. static uchar*
  77. pulong(uchar *p, uchar *ep, int val)
  78. {
  79. if(ep - p < 4)
  80. return ep+1;
  81. *p++ = val>>24;
  82. *p++ = val>>16;
  83. *p++ = val>>8;
  84. *p++ = val;
  85. return p;
  86. }
  87. static uchar*
  88. pv4addr(uchar *p, uchar *ep, char *name)
  89. {
  90. uchar ip[IPaddrlen];
  91. if(ep - p < 4)
  92. return ep+1;
  93. parseip(ip, name);
  94. v6tov4(p, ip);
  95. return p + 4;
  96. }
  97. static uchar*
  98. pv6addr(uchar *p, uchar *ep, char *name)
  99. {
  100. if(ep - p < IPaddrlen)
  101. return ep+1;
  102. parseip(p, name);
  103. return p + IPaddrlen;
  104. }
  105. static uchar*
  106. pname(uchar *p, uchar *ep, char *np, Dict *dp)
  107. {
  108. int i;
  109. char *cp;
  110. char *last; /* last component packed */
  111. if(strlen(np) >= Domlen) /* make sure we don't exceed DNS limits */
  112. return ep+1;
  113. last = 0;
  114. while(*np){
  115. /* look through every component in the dictionary for a match */
  116. for(i = 0; i < dp->n; i++)
  117. if(strcmp(np, dp->x[i].name) == 0){
  118. if(ep - p < 2)
  119. return ep+1;
  120. *p++ = (dp->x[i].offset>>8) | 0xc0;
  121. *p++ = dp->x[i].offset;
  122. return p;
  123. }
  124. /* if there's room, enter this name in dictionary */
  125. if(dp->n < Ndict)
  126. if(last){
  127. /* the whole name is already in dp->buf */
  128. last = strchr(last, '.') + 1;
  129. dp->x[dp->n].name = last;
  130. dp->x[dp->n].offset = p - dp->start;
  131. dp->n++;
  132. } else {
  133. /* add to dp->buf */
  134. i = strlen(np);
  135. if(dp->ep + i + 1 < &dp->buf[sizeof dp->buf]){
  136. strcpy(dp->ep, np);
  137. dp->x[dp->n].name = dp->ep;
  138. last = dp->ep;
  139. dp->x[dp->n].offset = p - dp->start;
  140. dp->ep += i + 1;
  141. dp->n++;
  142. }
  143. }
  144. /* put next component into message */
  145. cp = strchr(np, '.');
  146. if(cp == nil){
  147. i = strlen(np);
  148. cp = np + i; /* point to null terminator */
  149. } else {
  150. i = cp - np;
  151. cp++; /* point past '.' */
  152. }
  153. if(ep-p < i+1)
  154. return ep+1;
  155. if (i > Labellen)
  156. return ep+1;
  157. *p++ = i; /* count of chars in label */
  158. memmove(p, np, i);
  159. np = cp;
  160. p += i;
  161. }
  162. if(p >= ep)
  163. return ep+1;
  164. *p++ = 0; /* add top level domain */
  165. return p;
  166. }
  167. static uchar*
  168. convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
  169. {
  170. uchar *lp, *data;
  171. int len, ttl;
  172. Txt *t;
  173. NAME(rp->owner->name);
  174. USHORT(rp->type);
  175. USHORT(rp->owner->class);
  176. /* egregious overuse of ttl (it's absolute time in the cache) */
  177. if(rp->db)
  178. ttl = rp->ttl;
  179. else
  180. ttl = rp->ttl - now;
  181. if(ttl < 0)
  182. ttl = 0;
  183. ULONG(ttl);
  184. lp = p; /* leave room for the rdata length */
  185. p += 2;
  186. data = p;
  187. if(data >= ep)
  188. return p+1;
  189. switch(rp->type){
  190. case Thinfo:
  191. SYMBOL(rp->cpu->name);
  192. SYMBOL(rp->os->name);
  193. break;
  194. case Tcname:
  195. case Tmb:
  196. case Tmd:
  197. case Tmf:
  198. case Tns:
  199. NAME(rp->host->name);
  200. break;
  201. case Tmg:
  202. case Tmr:
  203. NAME(rp->mb->name);
  204. break;
  205. case Tminfo:
  206. NAME(rp->rmb->name);
  207. NAME(rp->mb->name);
  208. break;
  209. case Tmx:
  210. USHORT(rp->pref);
  211. NAME(rp->host->name);
  212. break;
  213. case Ta:
  214. V4ADDR(rp->ip->name);
  215. break;
  216. case Taaaa:
  217. V6ADDR(rp->ip->name);
  218. break;
  219. case Tptr:
  220. NAME(rp->ptr->name);
  221. break;
  222. case Tsoa:
  223. NAME(rp->host->name);
  224. NAME(rp->rmb->name);
  225. ULONG(rp->soa->serial);
  226. ULONG(rp->soa->refresh);
  227. ULONG(rp->soa->retry);
  228. ULONG(rp->soa->expire);
  229. ULONG(rp->soa->minttl);
  230. break;
  231. case Tsrv:
  232. USHORT(rp->srv->pri);
  233. USHORT(rp->srv->weight);
  234. USHORT(rp->srv->port);
  235. STRING(rp->srv->target->name);
  236. break;
  237. case Ttxt:
  238. for(t = rp->txt; t != nil; t = t->next)
  239. STRING(t->p);
  240. break;
  241. case Tnull:
  242. BYTES(rp->null->data, rp->null->dlen);
  243. break;
  244. case Trp:
  245. NAME(rp->rmb->name);
  246. NAME(rp->rp->name);
  247. break;
  248. case Tkey:
  249. USHORT(rp->key->flags);
  250. UCHAR(rp->key->proto);
  251. UCHAR(rp->key->alg);
  252. BYTES(rp->key->data, rp->key->dlen);
  253. break;
  254. case Tsig:
  255. USHORT(rp->sig->type);
  256. UCHAR(rp->sig->alg);
  257. UCHAR(rp->sig->labels);
  258. ULONG(rp->sig->ttl);
  259. ULONG(rp->sig->exp);
  260. ULONG(rp->sig->incep);
  261. USHORT(rp->sig->tag);
  262. NAME(rp->sig->signer->name);
  263. BYTES(rp->sig->data, rp->sig->dlen);
  264. break;
  265. case Tcert:
  266. USHORT(rp->cert->type);
  267. USHORT(rp->cert->tag);
  268. UCHAR(rp->cert->alg);
  269. BYTES(rp->cert->data, rp->cert->dlen);
  270. break;
  271. }
  272. /* stuff in the rdata section length */
  273. len = p - data;
  274. *lp++ = len >> 8;
  275. *lp = len;
  276. return p;
  277. }
  278. static uchar*
  279. convQ2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
  280. {
  281. NAME(rp->owner->name);
  282. USHORT(rp->type);
  283. USHORT(rp->owner->class);
  284. return p;
  285. }
  286. static uchar*
  287. rrloop(RR *rp, int *countp, uchar *p, uchar *ep, Dict *dp, int quest)
  288. {
  289. uchar *np;
  290. *countp = 0;
  291. for(; rp && p < ep; rp = rp->next){
  292. if(quest)
  293. np = convQ2M(rp, p, ep, dp);
  294. else
  295. np = convRR2M(rp, p, ep, dp);
  296. if(np > ep)
  297. break;
  298. p = np;
  299. (*countp)++;
  300. }
  301. return p;
  302. }
  303. /*
  304. * convert into a message
  305. */
  306. int
  307. convDNS2M(DNSmsg *m, uchar *buf, int len)
  308. {
  309. ulong trunc = 0;
  310. uchar *p, *ep, *np;
  311. Dict d;
  312. d.n = 0;
  313. d.start = buf;
  314. d.ep = d.buf;
  315. memset(buf, 0, len);
  316. m->qdcount = m->ancount = m->nscount = m->arcount = 0;
  317. /* first pack in the RR's so we can get real counts */
  318. p = buf + 12;
  319. ep = buf + len;
  320. p = rrloop(m->qd, &m->qdcount, p, ep, &d, 1);
  321. p = rrloop(m->an, &m->ancount, p, ep, &d, 0);
  322. p = rrloop(m->ns, &m->nscount, p, ep, &d, 0);
  323. p = rrloop(m->ar, &m->arcount, p, ep, &d, 0);
  324. if(p > ep) {
  325. trunc = Ftrunc;
  326. dnslog("udp packet full; truncating my reply");
  327. p = ep;
  328. }
  329. /* now pack the rest */
  330. np = p;
  331. p = buf;
  332. ep = buf + len;
  333. USHORT(m->id);
  334. USHORT(m->flags | trunc);
  335. USHORT(m->qdcount);
  336. USHORT(m->ancount);
  337. USHORT(m->nscount);
  338. USHORT(m->arcount);
  339. USED(p);
  340. return np - buf;
  341. }