convM2DNS.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  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; /* input buffer */
  9. uchar *p; /* current position */
  10. uchar *ep; /* byte after the end */
  11. char *err;
  12. char errbuf[256]; /* hold a formatted error sometimes */
  13. int rcode; /* outgoing response codes (reply flags) */
  14. int stop; /* flag: stop processing */
  15. int trunc; /* flag: input truncated */
  16. };
  17. static int
  18. errneg(RR *rp, Scan *sp, int actual)
  19. {
  20. snprint(sp->errbuf, sizeof sp->errbuf, "negative len %d: %R",
  21. actual, rp);
  22. sp->err = sp->errbuf;
  23. return 0;
  24. }
  25. static int
  26. errtoolong(RR *rp, Scan *sp, int remain, int need, char *where)
  27. {
  28. char *p, *ep;
  29. char ptype[64];
  30. p = sp->errbuf;
  31. ep = sp->errbuf + sizeof sp->errbuf - 1;
  32. if (where)
  33. p = seprint(p, ep, "%s: ", where);
  34. if (rp)
  35. p = seprint(p, ep, "type %s RR: ",
  36. rrname(rp->type, ptype, sizeof ptype));
  37. p = seprint(p, ep, "%d bytes needed; %d remain", need, remain);
  38. if (rp)
  39. seprint(p, ep, ": %R", rp);
  40. sp->err = sp->errbuf;
  41. /* hack to cope with servers that don't set Ftrunc when they should */
  42. if (remain < Maxudp && need > Maxudp)
  43. sp->trunc = 1;
  44. if (debug && rp)
  45. dnslog("malformed rr: %R", rp);
  46. return 0;
  47. }
  48. /*
  49. * get a ushort/ulong
  50. */
  51. static ushort
  52. gchar(RR *rp, Scan *sp)
  53. {
  54. ushort x;
  55. if(sp->err)
  56. return 0;
  57. if(sp->ep - sp->p < 1)
  58. return errtoolong(rp, sp, sp->ep - sp->p, 1, "gchar");
  59. x = sp->p[0];
  60. sp->p += 1;
  61. return x;
  62. }
  63. static ushort
  64. gshort(RR *rp, Scan *sp)
  65. {
  66. ushort x;
  67. if(sp->err)
  68. return 0;
  69. if(sp->ep - sp->p < 2)
  70. return errtoolong(rp, sp, sp->ep - sp->p, 2, "gshort");
  71. x = sp->p[0]<<8 | sp->p[1];
  72. sp->p += 2;
  73. return x;
  74. }
  75. static ulong
  76. glong(RR *rp, Scan *sp)
  77. {
  78. ulong x;
  79. if(sp->err)
  80. return 0;
  81. if(sp->ep - sp->p < 4)
  82. return errtoolong(rp, sp, sp->ep - sp->p, 4, "glong");
  83. x = sp->p[0]<<24 | sp->p[1]<<16 | sp->p[2]<<8 | sp->p[3];
  84. sp->p += 4;
  85. return x;
  86. }
  87. /*
  88. * get an ip address
  89. */
  90. static DN*
  91. gv4addr(RR *rp, Scan *sp)
  92. {
  93. char addr[32];
  94. if(sp->err)
  95. return 0;
  96. if(sp->ep - sp->p < 4)
  97. return (DN*)errtoolong(rp, sp, sp->ep - sp->p, 4, "gv4addr");
  98. snprint(addr, sizeof addr, "%V", sp->p);
  99. sp->p += 4;
  100. return dnlookup(addr, Cin, 1);
  101. }
  102. static DN*
  103. gv6addr(RR *rp, Scan *sp)
  104. {
  105. char addr[64];
  106. if(sp->err)
  107. return 0;
  108. if(sp->ep - sp->p < IPaddrlen)
  109. return (DN*)errtoolong(rp, sp, sp->ep - sp->p, IPaddrlen,
  110. "gv6addr");
  111. snprint(addr, sizeof addr, "%I", sp->p);
  112. sp->p += IPaddrlen;
  113. return dnlookup(addr, Cin, 1);
  114. }
  115. /*
  116. * get a string. make it an internal symbol.
  117. */
  118. static DN*
  119. gsym(RR *rp, Scan *sp)
  120. {
  121. int n;
  122. char sym[Strlen+1];
  123. if(sp->err)
  124. return 0;
  125. n = 0;
  126. if (sp->p < sp->ep)
  127. n = *(sp->p++);
  128. if(sp->ep - sp->p < n)
  129. return (DN*)errtoolong(rp, sp, sp->ep - sp->p, n, "gsym");
  130. if(n > Strlen){
  131. sp->err = "illegal string (symbol)";
  132. return 0;
  133. }
  134. strncpy(sym, (char*)sp->p, n);
  135. sym[n] = 0;
  136. if (strlen(sym) != n)
  137. sp->err = "symbol shorter than declared length";
  138. sp->p += n;
  139. return dnlookup(sym, Csym, 1);
  140. }
  141. /*
  142. * get a string. don't make it an internal symbol.
  143. */
  144. static Txt*
  145. gstr(RR *rp, Scan *sp)
  146. {
  147. int n;
  148. char sym[Strlen+1];
  149. Txt *t;
  150. if(sp->err)
  151. return 0;
  152. n = 0;
  153. if (sp->p < sp->ep)
  154. n = *(sp->p++);
  155. if(sp->ep - sp->p < n)
  156. return (Txt*)errtoolong(rp, sp, sp->ep - sp->p, n, "gstr");
  157. if(n > Strlen){
  158. sp->err = "illegal string";
  159. return 0;
  160. }
  161. strncpy(sym, (char*)sp->p, n);
  162. sym[n] = 0;
  163. if (strlen(sym) != n)
  164. sp->err = "string shorter than declared length";
  165. sp->p += n;
  166. t = emalloc(sizeof(*t));
  167. t->next = nil;
  168. t->p = estrdup(sym);
  169. return t;
  170. }
  171. /*
  172. * get a sequence of bytes
  173. */
  174. static int
  175. gbytes(RR *rp, Scan *sp, uchar **p, int n)
  176. {
  177. *p = nil; /* i think this is a good idea */
  178. if(sp->err)
  179. return 0;
  180. if(n < 0)
  181. return errneg(rp, sp, n);
  182. if(sp->ep - sp->p < n)
  183. return errtoolong(rp, sp, sp->ep - sp->p, n, "gbytes");
  184. *p = emalloc(n);
  185. memmove(*p, sp->p, n);
  186. sp->p += n;
  187. return n;
  188. }
  189. /*
  190. * get a domain name. 'to' must point to a buffer at least Domlen+1 long.
  191. */
  192. static char*
  193. gname(char *to, RR *rp, Scan *sp)
  194. {
  195. int len, off, pointer, n;
  196. char *tostart, *toend;
  197. uchar *p;
  198. tostart = to;
  199. if(sp->err || sp->stop)
  200. goto err;
  201. pointer = 0;
  202. p = sp->p;
  203. if (p == nil) {
  204. dnslog("gname: %R: nil sp->p", rp);
  205. goto err;
  206. }
  207. toend = to + Domlen;
  208. for(len = 0; *p && p < sp->ep; len += (pointer? 0: n+1)) {
  209. n = 0;
  210. switch (*p & 0300) {
  211. case 0: /* normal label */
  212. if (p < sp->ep)
  213. n = *p++ & 077; /* pick up length */
  214. if(len + n < Domlen - 1){
  215. if(n > toend - to){
  216. errtoolong(rp, sp, toend - to, n,
  217. "name too long");
  218. goto err;
  219. }
  220. memmove(to, p, n);
  221. to += n;
  222. }
  223. p += n;
  224. if(*p){
  225. if(to >= toend){
  226. errtoolong(rp, sp, toend - to, 2,
  227. "more name components but no bytes left");
  228. goto err;
  229. }
  230. *to++ = '.';
  231. }
  232. break;
  233. case 0100: /* edns extended label type, rfc 2671 */
  234. /*
  235. * treat it like an EOF for now; it seems to be at
  236. * the end of a long tcp reply.
  237. */
  238. dnslog("edns label; first byte 0%o = '%c'", *p, *p);
  239. sp->stop = 1;
  240. goto err;
  241. case 0200: /* reserved */
  242. sp->err = "reserved-use label present";
  243. goto err;
  244. case 0300: /* pointer to other spot in message */
  245. if(pointer++ > 10){
  246. sp->err = "pointer loop";
  247. goto err;
  248. }
  249. off = (p[0] & 077)<<8 | p[1];
  250. p = sp->base + off;
  251. if(p >= sp->ep){
  252. sp->err = "bad pointer";
  253. goto err;
  254. }
  255. n = 0;
  256. break;
  257. }
  258. }
  259. *to = 0;
  260. if(pointer)
  261. sp->p += len + 2; /* + 2 for pointer */
  262. else
  263. sp->p += len + 1; /* + 1 for the null domain */
  264. return tostart;
  265. err:
  266. *tostart = 0;
  267. return tostart;
  268. }
  269. /*
  270. * ms windows 2000 seems to get the bytes backward in the type field
  271. * of ptr records, so return a format error as feedback.
  272. */
  273. static ushort
  274. mstypehack(Scan *sp, ushort type, char *where)
  275. {
  276. if ((uchar)type == 0 && (type>>8) != 0) {
  277. USED(where);
  278. // dnslog("%s: byte-swapped type field in ptr rr from win2k",
  279. // where);
  280. if (sp->rcode == Rok)
  281. sp->rcode = Rformat;
  282. type >>= 8;
  283. }
  284. return type;
  285. }
  286. #define NAME(x) gname(x, rp, sp)
  287. #define SYMBOL(x) ((x) = gsym(rp, sp))
  288. #define STRING(x) ((x) = gstr(rp, sp))
  289. #define USHORT(x) ((x) = gshort(rp, sp))
  290. #define ULONG(x) ((x) = glong(rp, sp))
  291. #define UCHAR(x) ((x) = gchar(rp, sp))
  292. #define V4ADDR(x) ((x) = gv4addr(rp, sp))
  293. #define V6ADDR(x) ((x) = gv6addr(rp, sp))
  294. #define BYTES(x, y) ((y) = gbytes(rp, sp, &(x), len - (sp->p - data)))
  295. /*
  296. * convert the next RR from a message
  297. */
  298. static RR*
  299. convM2RR(Scan *sp, char *what)
  300. {
  301. int type, class, len, left;
  302. char dname[Domlen+1];
  303. uchar *data;
  304. RR *rp;
  305. Txt *t, **l;
  306. retry:
  307. rp = nil;
  308. NAME(dname);
  309. USHORT(type);
  310. USHORT(class);
  311. type = mstypehack(sp, type, "convM2RR");
  312. rp = rralloc(type);
  313. rp->owner = dnlookup(dname, class, 1);
  314. rp->type = type;
  315. ULONG(rp->ttl);
  316. rp->ttl += now;
  317. USHORT(len); /* length of data following */
  318. data = sp->p;
  319. assert(data != nil);
  320. left = sp->ep - sp->p;
  321. /*
  322. * ms windows generates a lot of badly-formatted hints.
  323. * hints are only advisory, so don't log complaints about them.
  324. * it also generates answers in which p overshoots ep by exactly
  325. * one byte; this seems to be harmless, so don't log them either.
  326. */
  327. if (len > left &&
  328. !(strcmp(what, "hints") == 0 ||
  329. sp->p == sp->ep + 1 && strcmp(what, "answers") == 0))
  330. errtoolong(rp, sp, left, len, "convM2RR");
  331. if(sp->err || sp->rcode || sp->stop){
  332. rrfree(rp);
  333. return nil;
  334. }
  335. /* even if we don't log an error message, truncate length to fit data */
  336. if (len > left)
  337. len = left;
  338. switch(type){
  339. default:
  340. /* unknown type, just ignore it */
  341. sp->p = data + len;
  342. rrfree(rp);
  343. goto retry;
  344. case Thinfo:
  345. SYMBOL(rp->cpu);
  346. SYMBOL(rp->os);
  347. break;
  348. case Tcname:
  349. case Tmb:
  350. case Tmd:
  351. case Tmf:
  352. case Tns:
  353. rp->host = dnlookup(NAME(dname), Cin, 1);
  354. break;
  355. case Tmg:
  356. case Tmr:
  357. rp->mb = dnlookup(NAME(dname), Cin, 1);
  358. break;
  359. case Tminfo:
  360. rp->rmb = dnlookup(NAME(dname), Cin, 1);
  361. rp->mb = dnlookup(NAME(dname), Cin, 1);
  362. break;
  363. case Tmx:
  364. USHORT(rp->pref);
  365. rp->host = dnlookup(NAME(dname), Cin, 1);
  366. break;
  367. case Ta:
  368. V4ADDR(rp->ip);
  369. break;
  370. case Taaaa:
  371. V6ADDR(rp->ip);
  372. break;
  373. case Tptr:
  374. rp->ptr = dnlookup(NAME(dname), Cin, 1);
  375. break;
  376. case Tsoa:
  377. rp->host = dnlookup(NAME(dname), Cin, 1);
  378. rp->rmb = dnlookup(NAME(dname), Cin, 1);
  379. ULONG(rp->soa->serial);
  380. ULONG(rp->soa->refresh);
  381. ULONG(rp->soa->retry);
  382. ULONG(rp->soa->expire);
  383. ULONG(rp->soa->minttl);
  384. break;
  385. case Tsrv:
  386. USHORT(rp->srv->pri);
  387. USHORT(rp->srv->weight);
  388. USHORT(rp->port);
  389. /*
  390. * rfc2782 sez no name compression but to be
  391. * backward-compatible with rfc2052, we try to expand the name.
  392. * if the length is under 64 bytes, either interpretation is
  393. * fine; if it's longer, we'll assume it's compressed,
  394. * as recommended by rfc3597.
  395. */
  396. rp->host = dnlookup(NAME(dname), Cin, 1);
  397. break;
  398. case Ttxt:
  399. l = &rp->txt;
  400. *l = nil;
  401. while(sp->p - data < len){
  402. STRING(t);
  403. *l = t;
  404. l = &t->next;
  405. }
  406. break;
  407. case Tnull:
  408. BYTES(rp->null->data, rp->null->dlen);
  409. break;
  410. case Trp:
  411. rp->rmb = dnlookup(NAME(dname), Cin, 1);
  412. rp->rp = dnlookup(NAME(dname), Cin, 1);
  413. break;
  414. case Tkey:
  415. USHORT(rp->key->flags);
  416. UCHAR(rp->key->proto);
  417. UCHAR(rp->key->alg);
  418. BYTES(rp->key->data, rp->key->dlen);
  419. break;
  420. case Tsig:
  421. USHORT(rp->sig->type);
  422. UCHAR(rp->sig->alg);
  423. UCHAR(rp->sig->labels);
  424. ULONG(rp->sig->ttl);
  425. ULONG(rp->sig->exp);
  426. ULONG(rp->sig->incep);
  427. USHORT(rp->sig->tag);
  428. rp->sig->signer = dnlookup(NAME(dname), Cin, 1);
  429. BYTES(rp->sig->data, rp->sig->dlen);
  430. break;
  431. case Tcert:
  432. USHORT(rp->cert->type);
  433. USHORT(rp->cert->tag);
  434. UCHAR(rp->cert->alg);
  435. BYTES(rp->cert->data, rp->cert->dlen);
  436. break;
  437. }
  438. if(sp->p - data != len) {
  439. char ptype[64];
  440. /*
  441. * ms windows 2000 generates cname queries for reverse lookups
  442. * with this particular error. don't bother logging it.
  443. *
  444. * server: input error: bad cname RR len (actual 2 != len 0):
  445. * 235.9.104.135.in-addr.arpa cname
  446. * 235.9.104.135.in-addr.arpa from 135.104.9.235
  447. */
  448. if (type == Tcname && sp->p - data == 2 && len == 0)
  449. return rp;
  450. if (len > sp->p - data){
  451. dnslog("bad %s RR len (%d bytes nominal, %lud actual): %R",
  452. rrname(type, ptype, sizeof ptype), len,
  453. sp->p - data, rp);
  454. rrfree(rp);
  455. rp = nil;
  456. }
  457. }
  458. // if(rp) dnslog("convM2RR: got %R", rp);
  459. return rp;
  460. }
  461. /*
  462. * convert the next question from a message
  463. */
  464. static RR*
  465. convM2Q(Scan *sp)
  466. {
  467. char dname[Domlen+1];
  468. int type, class;
  469. RR *rp;
  470. rp = nil;
  471. NAME(dname);
  472. USHORT(type);
  473. USHORT(class);
  474. if(sp->err || sp->rcode || sp->stop)
  475. return nil;
  476. type = mstypehack(sp, type, "convM2Q");
  477. rp = rralloc(type);
  478. rp->owner = dnlookup(dname, class, 1);
  479. return rp;
  480. }
  481. static RR*
  482. rrloop(Scan *sp, char *what, int count, int quest)
  483. {
  484. int i;
  485. RR *first, *rp, **l;
  486. if(sp->err || sp->rcode || sp->stop)
  487. return nil;
  488. l = &first;
  489. first = nil;
  490. for(i = 0; i < count; i++){
  491. rp = quest? convM2Q(sp): convM2RR(sp, what);
  492. if(rp == nil)
  493. break;
  494. setmalloctag(rp, getcallerpc(&sp));
  495. /*
  496. * it might be better to ignore the bad rr, possibly break out,
  497. * but return the previous rrs, if any. that way our callers
  498. * would know that they had got a response, however ill-formed.
  499. */
  500. if(sp->err || sp->rcode || sp->stop){
  501. rrfree(rp);
  502. break;
  503. }
  504. *l = rp;
  505. l = &rp->next;
  506. }
  507. // if(first)
  508. // setmalloctag(first, getcallerpc(&sp));
  509. return first;
  510. }
  511. /*
  512. * convert the next DNS from a message stream.
  513. * if there are formatting errors or the like during parsing of the message,
  514. * set *codep to the outgoing response code (e.g., Rformat), which will
  515. * abort processing and reply immediately with the outgoing response code.
  516. */
  517. char*
  518. convM2DNS(uchar *buf, int len, DNSmsg *m, int *codep)
  519. {
  520. char *err = nil;
  521. RR *rp = nil;
  522. Scan scan;
  523. Scan *sp;
  524. assert(len >= 0);
  525. assert(buf != nil);
  526. sp = &scan;
  527. memset(sp, 0, sizeof *sp);
  528. sp->base = sp->p = buf;
  529. sp->ep = buf + len;
  530. sp->err = nil;
  531. sp->errbuf[0] = '\0';
  532. sp->rcode = Rok;
  533. memset(m, 0, sizeof *m);
  534. USHORT(m->id);
  535. USHORT(m->flags);
  536. USHORT(m->qdcount);
  537. USHORT(m->ancount);
  538. USHORT(m->nscount);
  539. USHORT(m->arcount);
  540. m->qd = rrloop(sp, "questions", m->qdcount, 1);
  541. m->an = rrloop(sp, "answers", m->ancount, 0);
  542. m->ns = rrloop(sp, "nameservers",m->nscount, 0);
  543. if (sp->stop)
  544. sp->err = nil;
  545. if (sp->err)
  546. err = strdup(sp->err); /* live with bad ar's */
  547. m->ar = rrloop(sp, "hints", m->arcount, 0);
  548. if (sp->trunc)
  549. m->flags |= Ftrunc;
  550. if (sp->stop)
  551. sp->rcode = Rok;
  552. if (codep)
  553. *codep = sp->rcode;
  554. return err;
  555. }