convM2DNS.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include "dns.h"
  5. typedef struct Scan Scan;
  6. struct Scan
  7. {
  8. uchar *base;
  9. uchar *p;
  10. uchar *ep;
  11. char *err;
  12. };
  13. #define NAME(x) gname(x, sp)
  14. #define SYMBOL(x) (x = gsym(sp))
  15. #define STRING(x) (x = gstr(sp))
  16. #define USHORT(x) (x = gshort(sp))
  17. #define ULONG(x) (x = glong(sp))
  18. #define UCHAR(x) (x = gchar(sp))
  19. #define V4ADDR(x) (x = gv4addr(sp))
  20. #define V6ADDR(x) (x = gv6addr(sp))
  21. #define BYTES(x, y) (y = gbytes(sp, &x, len - (sp->p - data)))
  22. static char *toolong = "too long";
  23. /*
  24. * get a ushort/ulong
  25. */
  26. static ushort
  27. gchar(Scan *sp)
  28. {
  29. ushort x;
  30. if(sp->err)
  31. return 0;
  32. if(sp->ep - sp->p < 1){
  33. sp->err = toolong;
  34. return 0;
  35. }
  36. x = sp->p[0];
  37. sp->p += 1;
  38. return x;
  39. }
  40. static ushort
  41. gshort(Scan *sp)
  42. {
  43. ushort x;
  44. if(sp->err)
  45. return 0;
  46. if(sp->ep - sp->p < 2){
  47. sp->err = toolong;
  48. return 0;
  49. }
  50. x = (sp->p[0]<<8) | sp->p[1];
  51. sp->p += 2;
  52. return x;
  53. }
  54. static ulong
  55. glong(Scan *sp)
  56. {
  57. ulong x;
  58. if(sp->err)
  59. return 0;
  60. if(sp->ep - sp->p < 4){
  61. sp->err = toolong;
  62. return 0;
  63. }
  64. x = (sp->p[0]<<24) | (sp->p[1]<<16) | (sp->p[2]<<8) | sp->p[3];
  65. sp->p += 4;
  66. return x;
  67. }
  68. /*
  69. * get an ip address
  70. */
  71. static DN*
  72. gv4addr(Scan *sp)
  73. {
  74. char addr[32];
  75. if(sp->err)
  76. return 0;
  77. if(sp->ep - sp->p < 4){
  78. sp->err = toolong;
  79. return 0;
  80. }
  81. snprint(addr, sizeof(addr), "%V", sp->p);
  82. sp->p += 4;
  83. return dnlookup(addr, Cin, 1);
  84. }
  85. static DN*
  86. gv6addr(Scan *sp)
  87. {
  88. char addr[64];
  89. if(sp->err)
  90. return 0;
  91. if(sp->ep - sp->p < IPaddrlen){
  92. sp->err = toolong;
  93. return 0;
  94. }
  95. snprint(addr, sizeof(addr), "%I", sp->p);
  96. sp->p += IPaddrlen;
  97. return dnlookup(addr, Cin, 1);
  98. }
  99. /*
  100. * get a string. make it an internal symbol.
  101. */
  102. static DN*
  103. gsym(Scan *sp)
  104. {
  105. int n;
  106. char sym[Strlen+1];
  107. if(sp->err)
  108. return 0;
  109. n = *(sp->p++);
  110. if(sp->p+n > sp->ep){
  111. sp->err = toolong;
  112. return 0;
  113. }
  114. if(n > Strlen){
  115. sp->err = "illegal string";
  116. return 0;
  117. }
  118. strncpy(sym, (char*)sp->p, n);
  119. sym[n] = 0;
  120. sp->p += n;
  121. return dnlookup(sym, Csym, 1);
  122. }
  123. /*
  124. * get a string. don't make it an internal symbol.
  125. */
  126. static Txt*
  127. gstr(Scan *sp)
  128. {
  129. int n;
  130. char sym[Strlen+1];
  131. Txt *t;
  132. if(sp->err)
  133. return 0;
  134. n = *(sp->p++);
  135. if(sp->p+n > sp->ep){
  136. sp->err = toolong;
  137. return 0;
  138. }
  139. if(n > Strlen){
  140. sp->err = "illegal string";
  141. return 0;
  142. }
  143. strncpy(sym, (char*)sp->p, n);
  144. sym[n] = 0;
  145. sp->p += n;
  146. t = emalloc(sizeof(*t));
  147. t->next = nil;
  148. t->p = estrdup(sym);
  149. return t;
  150. }
  151. /*
  152. * get a sequence of bytes
  153. */
  154. static int
  155. gbytes(Scan *sp, uchar **p, int n)
  156. {
  157. if(sp->err)
  158. return 0;
  159. if(sp->p+n > sp->ep || n < 0){
  160. sp->err = toolong;
  161. return 0;
  162. }
  163. *p = emalloc(n);
  164. memmove(*p, sp->p, n);
  165. sp->p += n;
  166. return n;
  167. }
  168. /*
  169. * get a domain name. 'to' must point to a buffer at least Domlen+1 long.
  170. */
  171. static char*
  172. gname(char *to, Scan *sp)
  173. {
  174. int len, off;
  175. int pointer;
  176. int n;
  177. char *tostart;
  178. char *toend;
  179. uchar *p;
  180. tostart = to;
  181. if(sp->err)
  182. goto err;
  183. pointer = 0;
  184. p = sp->p;
  185. toend = to + Domlen;
  186. for(len = 0; *p; len += pointer ? 0 : (n+1)){
  187. if((*p & 0xc0) == 0xc0){
  188. /* pointer to other spot in message */
  189. if(pointer++ > 10){
  190. sp->err = "pointer loop";
  191. goto err;
  192. }
  193. off = ((p[0]<<8) + p[1]) & 0x3ff;
  194. p = sp->base + off;
  195. if(p >= sp->ep){
  196. sp->err = "bad pointer";
  197. goto err;
  198. }
  199. n = 0;
  200. continue;
  201. }
  202. n = *p++;
  203. if(len + n < Domlen - 1){
  204. if(to + n > toend){
  205. sp->err = toolong;
  206. goto err;
  207. }
  208. memmove(to, p, n);
  209. to += n;
  210. }
  211. p += n;
  212. if(*p){
  213. if(to >= toend){
  214. sp->err = toolong;
  215. goto err;
  216. }
  217. *to++ = '.';
  218. }
  219. }
  220. *to = 0;
  221. if(pointer)
  222. sp->p += len + 2; /* + 2 for pointer */
  223. else
  224. sp->p += len + 1; /* + 1 for the null domain */
  225. return tostart;
  226. err:
  227. *tostart = 0;
  228. return tostart;
  229. }
  230. /*
  231. * convert the next RR from a message
  232. */
  233. static RR*
  234. convM2RR(Scan *sp)
  235. {
  236. RR *rp;
  237. int type;
  238. int class;
  239. uchar *data;
  240. int len;
  241. char dname[Domlen+1];
  242. Txt *t, **l;
  243. retry:
  244. NAME(dname);
  245. USHORT(type);
  246. USHORT(class);
  247. rp = rralloc(type);
  248. rp->owner = dnlookup(dname, class, 1);
  249. rp->type = type;
  250. ULONG(rp->ttl);
  251. rp->ttl += now;
  252. USHORT(len);
  253. data = sp->p;
  254. if(sp->p + len > sp->ep)
  255. sp->err = toolong;
  256. if(sp->err){
  257. rrfree(rp);
  258. return 0;
  259. }
  260. switch(type){
  261. default:
  262. /* unknown type, just ignore it */
  263. sp->p = data + len;
  264. rrfree(rp);
  265. goto retry;
  266. case Thinfo:
  267. SYMBOL(rp->cpu);
  268. SYMBOL(rp->os);
  269. break;
  270. case Tcname:
  271. case Tmb:
  272. case Tmd:
  273. case Tmf:
  274. case Tns:
  275. rp->host = dnlookup(NAME(dname), Cin, 1);
  276. break;
  277. case Tmg:
  278. case Tmr:
  279. rp->mb = dnlookup(NAME(dname), Cin, 1);
  280. break;
  281. case Tminfo:
  282. rp->rmb = dnlookup(NAME(dname), Cin, 1);
  283. rp->mb = dnlookup(NAME(dname), Cin, 1);
  284. break;
  285. case Tmx:
  286. USHORT(rp->pref);
  287. rp->host = dnlookup(NAME(dname), Cin, 1);
  288. break;
  289. case Ta:
  290. V4ADDR(rp->ip);
  291. break;
  292. case Taaaa:
  293. V6ADDR(rp->ip);
  294. break;
  295. case Tptr:
  296. rp->ptr = dnlookup(NAME(dname), Cin, 1);
  297. break;
  298. case Tsoa:
  299. rp->host = dnlookup(NAME(dname), Cin, 1);
  300. rp->rmb = dnlookup(NAME(dname), Cin, 1);
  301. ULONG(rp->soa->serial);
  302. ULONG(rp->soa->refresh);
  303. ULONG(rp->soa->retry);
  304. ULONG(rp->soa->expire);
  305. ULONG(rp->soa->minttl);
  306. break;
  307. case Ttxt:
  308. l = &rp->txt;
  309. *l = nil;
  310. while(sp->p-data < len){
  311. STRING(t);
  312. *l = t;
  313. l = &t->next;
  314. }
  315. break;
  316. case Tnull:
  317. BYTES(rp->null->data, rp->null->dlen);
  318. break;
  319. case Trp:
  320. rp->rmb = dnlookup(NAME(dname), Cin, 1);
  321. rp->rp = dnlookup(NAME(dname), Cin, 1);
  322. break;
  323. case Tkey:
  324. USHORT(rp->key->flags);
  325. UCHAR(rp->key->proto);
  326. UCHAR(rp->key->alg);
  327. BYTES(rp->key->data, rp->key->dlen);
  328. break;
  329. case Tsig:
  330. USHORT(rp->sig->type);
  331. UCHAR(rp->sig->alg);
  332. UCHAR(rp->sig->labels);
  333. ULONG(rp->sig->ttl);
  334. ULONG(rp->sig->exp);
  335. ULONG(rp->sig->incep);
  336. USHORT(rp->sig->tag);
  337. rp->sig->signer = dnlookup(NAME(dname), Cin, 1);
  338. BYTES(rp->sig->data, rp->sig->dlen);
  339. break;
  340. case Tcert:
  341. USHORT(rp->cert->type);
  342. USHORT(rp->cert->tag);
  343. UCHAR(rp->cert->alg);
  344. BYTES(rp->cert->data, rp->cert->dlen);
  345. break;
  346. }
  347. if(sp->p - data != len)
  348. sp->err = "bad RR len";
  349. return rp;
  350. }
  351. /*
  352. * convert the next question from a message
  353. */
  354. static RR*
  355. convM2Q(Scan *sp)
  356. {
  357. char dname[Domlen+1];
  358. int type;
  359. int class;
  360. RR *rp;
  361. NAME(dname);
  362. USHORT(type);
  363. USHORT(class);
  364. if(sp->err)
  365. return 0;
  366. rp = rralloc(type);
  367. rp->owner = dnlookup(dname, class, 1);
  368. return rp;
  369. }
  370. static RR*
  371. rrloop(Scan *sp, int count, int quest)
  372. {
  373. int i;
  374. static char errbuf[64];
  375. RR *first, *rp, **l;
  376. if(sp->err)
  377. return 0;
  378. l = &first;
  379. first = 0;
  380. for(i = 0; i < count; i++){
  381. rp = quest ? convM2Q(sp) : convM2RR(sp);
  382. if(rp == 0)
  383. break;
  384. if(sp->err){
  385. rrfree(rp);
  386. break;
  387. }
  388. *l = rp;
  389. l = &rp->next;
  390. }
  391. return first;
  392. }
  393. /*
  394. * convert the next DNS from a message stream
  395. */
  396. char*
  397. convM2DNS(uchar *buf, int len, DNSmsg *m)
  398. {
  399. Scan scan;
  400. Scan *sp;
  401. char *err;
  402. scan.base = buf;
  403. scan.p = buf;
  404. scan.ep = buf + len;
  405. scan.err = 0;
  406. sp = &scan;
  407. memset(m, 0, sizeof(DNSmsg));
  408. USHORT(m->id);
  409. USHORT(m->flags);
  410. USHORT(m->qdcount);
  411. USHORT(m->ancount);
  412. USHORT(m->nscount);
  413. USHORT(m->arcount);
  414. m->qd = rrloop(sp, m->qdcount, 1);
  415. m->an = rrloop(sp, m->ancount, 0);
  416. m->ns = rrloop(sp, m->nscount, 0);
  417. err = scan.err; /* live with bad ar's */
  418. m->ar = rrloop(sp, m->arcount, 0);
  419. return err;
  420. }