convDNS2M.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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. if ((dp->x[i].offset>>8) & 0xc0)
  121. dnslog("convDNS2M: offset too big for "
  122. "DNS packet format");
  123. *p++ = dp->x[i].offset>>8 | 0xc0;
  124. *p++ = dp->x[i].offset;
  125. return p;
  126. }
  127. /* if there's room, enter this name in dictionary */
  128. if(dp->n < Ndict)
  129. if(last){
  130. /* the whole name is already in dp->buf */
  131. last = strchr(last, '.') + 1;
  132. dp->x[dp->n].name = last;
  133. dp->x[dp->n].offset = p - dp->start;
  134. dp->n++;
  135. } else {
  136. /* add to dp->buf */
  137. i = strlen(np);
  138. if(dp->ep + i + 1 < &dp->buf[sizeof dp->buf]){
  139. strcpy(dp->ep, np);
  140. dp->x[dp->n].name = dp->ep;
  141. last = dp->ep;
  142. dp->x[dp->n].offset = p - dp->start;
  143. dp->ep += i + 1;
  144. dp->n++;
  145. }
  146. }
  147. /* put next component into message */
  148. cp = strchr(np, '.');
  149. if(cp == nil){
  150. i = strlen(np);
  151. cp = np + i; /* point to null terminator */
  152. } else {
  153. i = cp - np;
  154. cp++; /* point past '.' */
  155. }
  156. if(ep-p < i+1)
  157. return ep+1;
  158. if (i > Labellen)
  159. return ep+1;
  160. *p++ = i; /* count of chars in label */
  161. memmove(p, np, i);
  162. np = cp;
  163. p += i;
  164. }
  165. if(p >= ep)
  166. return ep+1;
  167. *p++ = 0; /* add top level domain */
  168. return p;
  169. }
  170. static uchar*
  171. convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
  172. {
  173. uchar *lp, *data;
  174. int len, ttl;
  175. Txt *t;
  176. NAME(rp->owner->name);
  177. USHORT(rp->type);
  178. USHORT(rp->owner->class);
  179. /* egregious overuse of ttl (it's absolute time in the cache) */
  180. if(rp->db)
  181. ttl = rp->ttl;
  182. else
  183. ttl = rp->ttl - now;
  184. if(ttl < 0)
  185. ttl = 0;
  186. ULONG(ttl);
  187. lp = p; /* leave room for the rdata length */
  188. p += 2;
  189. data = p;
  190. if(data >= ep)
  191. return p+1;
  192. switch(rp->type){
  193. case Thinfo:
  194. SYMBOL(rp->cpu->name);
  195. SYMBOL(rp->os->name);
  196. break;
  197. case Tcname:
  198. case Tmb:
  199. case Tmd:
  200. case Tmf:
  201. case Tns:
  202. NAME(rp->host->name);
  203. break;
  204. case Tmg:
  205. case Tmr:
  206. NAME(rp->mb->name);
  207. break;
  208. case Tminfo:
  209. NAME(rp->rmb->name);
  210. NAME(rp->mb->name);
  211. break;
  212. case Tmx:
  213. USHORT(rp->pref);
  214. NAME(rp->host->name);
  215. break;
  216. case Ta:
  217. V4ADDR(rp->ip->name);
  218. break;
  219. case Taaaa:
  220. V6ADDR(rp->ip->name);
  221. break;
  222. case Tptr:
  223. NAME(rp->ptr->name);
  224. break;
  225. case Tsoa:
  226. NAME(rp->host->name);
  227. NAME(rp->rmb->name);
  228. ULONG(rp->soa->serial);
  229. ULONG(rp->soa->refresh);
  230. ULONG(rp->soa->retry);
  231. ULONG(rp->soa->expire);
  232. ULONG(rp->soa->minttl);
  233. break;
  234. case Tsrv:
  235. USHORT(rp->srv->pri);
  236. USHORT(rp->srv->weight);
  237. USHORT(rp->port);
  238. STRING(rp->host->name); /* rfc2782 sez no name compression */
  239. break;
  240. case Ttxt:
  241. for(t = rp->txt; t != nil; t = t->next)
  242. STRING(t->p);
  243. break;
  244. case Tnull:
  245. BYTES(rp->null->data, rp->null->dlen);
  246. break;
  247. case Trp:
  248. NAME(rp->rmb->name);
  249. NAME(rp->rp->name);
  250. break;
  251. case Tkey:
  252. USHORT(rp->key->flags);
  253. UCHAR(rp->key->proto);
  254. UCHAR(rp->key->alg);
  255. BYTES(rp->key->data, rp->key->dlen);
  256. break;
  257. case Tsig:
  258. USHORT(rp->sig->type);
  259. UCHAR(rp->sig->alg);
  260. UCHAR(rp->sig->labels);
  261. ULONG(rp->sig->ttl);
  262. ULONG(rp->sig->exp);
  263. ULONG(rp->sig->incep);
  264. USHORT(rp->sig->tag);
  265. NAME(rp->sig->signer->name);
  266. BYTES(rp->sig->data, rp->sig->dlen);
  267. break;
  268. case Tcert:
  269. USHORT(rp->cert->type);
  270. USHORT(rp->cert->tag);
  271. UCHAR(rp->cert->alg);
  272. BYTES(rp->cert->data, rp->cert->dlen);
  273. break;
  274. }
  275. /* stuff in the rdata section length */
  276. len = p - data;
  277. *lp++ = len >> 8;
  278. *lp = len;
  279. return p;
  280. }
  281. static uchar*
  282. convQ2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
  283. {
  284. NAME(rp->owner->name);
  285. USHORT(rp->type);
  286. USHORT(rp->owner->class);
  287. return p;
  288. }
  289. static uchar*
  290. rrloop(RR *rp, int *countp, uchar *p, uchar *ep, Dict *dp, int quest)
  291. {
  292. uchar *np;
  293. *countp = 0;
  294. for(; rp && p < ep; rp = rp->next){
  295. if(quest)
  296. np = convQ2M(rp, p, ep, dp);
  297. else
  298. np = convRR2M(rp, p, ep, dp);
  299. if(np > ep)
  300. break;
  301. p = np;
  302. (*countp)++;
  303. }
  304. return p;
  305. }
  306. /*
  307. * convert into a message
  308. */
  309. int
  310. convDNS2M(DNSmsg *m, uchar *buf, int len)
  311. {
  312. ulong trunc = 0;
  313. uchar *p, *ep, *np;
  314. Dict d;
  315. d.n = 0;
  316. d.start = buf;
  317. d.ep = d.buf;
  318. memset(buf, 0, len);
  319. m->qdcount = m->ancount = m->nscount = m->arcount = 0;
  320. /* first pack in the RR's so we can get real counts */
  321. p = buf + 12;
  322. ep = buf + len;
  323. p = rrloop(m->qd, &m->qdcount, p, ep, &d, 1);
  324. p = rrloop(m->an, &m->ancount, p, ep, &d, 0);
  325. p = rrloop(m->ns, &m->nscount, p, ep, &d, 0);
  326. p = rrloop(m->ar, &m->arcount, p, ep, &d, 0);
  327. if(p > ep) {
  328. trunc = Ftrunc;
  329. dnslog("udp packet full; truncating my reply");
  330. p = ep;
  331. }
  332. /* now pack the rest */
  333. np = p;
  334. p = buf;
  335. ep = buf + len;
  336. USHORT(m->id);
  337. USHORT(m->flags | trunc);
  338. USHORT(m->qdcount);
  339. USHORT(m->ancount);
  340. USHORT(m->nscount);
  341. USHORT(m->arcount);
  342. USED(p);
  343. return np - buf;
  344. }