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