You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

510 lines
18 KiB

  1. --- a/dns.c
  2. +++ b/dns.c
  3. @@ -921,6 +921,507 @@ void restell(char *s)
  4. fputs("\r",stderr);
  5. }
  6. +#ifdef __UCLIBC__
  7. +
  8. +static const char digits[] = "0123456789";
  9. +#define __set_errno(e) (errno = (e))
  10. +
  11. +#define NS_PUT16(s, cp) do { \
  12. + register u_int16_t t_s = (u_int16_t)(s); \
  13. + register u_char *t_cp = (u_char *)(cp); \
  14. + *t_cp++ = t_s >> 8; \
  15. + *t_cp = t_s; \
  16. + (cp) += NS_INT16SZ; \
  17. +} while (0)
  18. +
  19. +
  20. +
  21. +#define NS_PUT32(l, cp) do { \
  22. + register u_int32_t t_l = (u_int32_t)(l); \
  23. + register u_char *t_cp = (u_char *)(cp); \
  24. + *t_cp++ = t_l >> 24; \
  25. + *t_cp++ = t_l >> 16; \
  26. + *t_cp++ = t_l >> 8; \
  27. + *t_cp = t_l; \
  28. + (cp) += NS_INT32SZ; \
  29. +} while (0)
  30. +
  31. +
  32. +void
  33. +ns_put16(u_int src, u_char *dst) {
  34. + NS_PUT16(src, dst);
  35. +}
  36. +
  37. +void
  38. +ns_put32(u_long src, u_char *dst) {
  39. + NS_PUT32(src, dst);
  40. +}
  41. +
  42. +void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
  43. +void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
  44. +
  45. +int
  46. +mklower(int ch) {
  47. + if (ch >= 0x41 && ch <= 0x5A)
  48. + return (ch + 0x20);
  49. + return (ch);
  50. +}
  51. +
  52. +
  53. +static int
  54. +dn_find(const u_char *domain, const u_char *msg,
  55. + const u_char * const *dnptrs,
  56. + const u_char * const *lastdnptr)
  57. +{
  58. + const u_char *dn, *cp, *sp;
  59. + const u_char * const *cpp;
  60. + u_int n;
  61. +
  62. + for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  63. + sp = *cpp;
  64. + /*
  65. + * terminate search on:
  66. + * root label
  67. + * compression pointer
  68. + * unusable offset
  69. + */
  70. + while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
  71. + (sp - msg) < 0x4000) {
  72. + dn = domain;
  73. + cp = sp;
  74. + while ((n = *cp++) != 0) {
  75. + /*
  76. + * check for indirection
  77. + */
  78. + switch (n & NS_CMPRSFLGS) {
  79. + case 0: /* normal case, n == len */
  80. + if (n != *dn++)
  81. + goto next;
  82. + for ((void)NULL; n > 0; n--)
  83. + if (mklower(*dn++) !=
  84. + mklower(*cp++))
  85. + goto next;
  86. + /* Is next root for both ? */
  87. + if (*dn == '\0' && *cp == '\0')
  88. + return (sp - msg);
  89. + if (*dn)
  90. + continue;
  91. + goto next;
  92. +
  93. + case NS_CMPRSFLGS: /* indirection */
  94. + cp = msg + (((n & 0x3f) << 8) | *cp);
  95. + break;
  96. +
  97. + default: /* illegal type */
  98. + __set_errno (EMSGSIZE);
  99. + return (-1);
  100. + }
  101. + }
  102. + next:
  103. + sp += *sp + 1;
  104. + }
  105. + }
  106. + __set_errno (ENOENT);
  107. + return (-1);
  108. +}
  109. +
  110. +
  111. +int
  112. +ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
  113. + const u_char **dnptrs, const u_char **lastdnptr)
  114. +{
  115. + u_char *dstp;
  116. + const u_char **cpp, **lpp, *eob, *msg;
  117. + const u_char *srcp;
  118. + int n, l, first = 1;
  119. +
  120. + srcp = src;
  121. + dstp = dst;
  122. + eob = dstp + dstsiz;
  123. + lpp = cpp = NULL;
  124. + if (dnptrs != NULL) {
  125. + if ((msg = *dnptrs++) != NULL) {
  126. + for (cpp = dnptrs; *cpp != NULL; cpp++)
  127. + (void)NULL;
  128. + lpp = cpp; /* end of list to search */
  129. + }
  130. + } else
  131. + msg = NULL;
  132. +
  133. + /* make sure the domain we are about to add is legal */
  134. + l = 0;
  135. + do {
  136. + n = *srcp;
  137. + if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) {
  138. + __set_errno (EMSGSIZE);
  139. + return (-1);
  140. + }
  141. + if (n == 0x41)
  142. + n = *++srcp / 8;
  143. + l += n + 1;
  144. + if (l > MAXCDNAME) {
  145. + __set_errno (EMSGSIZE);
  146. + return (-1);
  147. + }
  148. + srcp += n + 1;
  149. + } while (n != 0);
  150. +
  151. + /* from here on we need to reset compression pointer array on error */
  152. + srcp = src;
  153. + do {
  154. + /* Look to see if we can use pointers. */
  155. + n = *srcp;
  156. + if (n != 0 && n != 0x41 && msg != NULL) {
  157. + l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
  158. + (const u_char * const *)lpp);
  159. + if (l >= 0) {
  160. + if (dstp + 1 >= eob) {
  161. + goto cleanup;
  162. + }
  163. + *dstp++ = (l >> 8) | NS_CMPRSFLGS;
  164. + *dstp++ = l % 256;
  165. + return (dstp - dst);
  166. + }
  167. + /* Not found, save it. */
  168. + if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
  169. + (dstp - msg) < 0x4000 && first) {
  170. + *cpp++ = dstp;
  171. + *cpp = NULL;
  172. + first = 0;
  173. + }
  174. + }
  175. + /* copy label to buffer */
  176. + if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) { /* Should not happen. */
  177. + goto cleanup;
  178. + }
  179. + if (n == 0x41) {
  180. + n = *++srcp / 8;
  181. + if (dstp + 1 >= eob)
  182. + goto cleanup;
  183. + *dstp++ = 0x41;
  184. + }
  185. + if (dstp + 1 + n >= eob) {
  186. + goto cleanup;
  187. + }
  188. + memcpy(dstp, srcp, n + 1);
  189. + srcp += n + 1;
  190. + dstp += n + 1;
  191. + } while (n != 0);
  192. +
  193. + if (dstp > eob) {
  194. +cleanup:
  195. + if (msg != NULL)
  196. + *lpp = NULL;
  197. + __set_errno (EMSGSIZE);
  198. + return (-1);
  199. + }
  200. + return (dstp - dst);
  201. +}
  202. +
  203. +
  204. +int
  205. +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
  206. + u_char *label, *bp, *eom;
  207. + int c, n, escaped;
  208. + char *cp;
  209. +
  210. + escaped = 0;
  211. + bp = dst;
  212. + eom = dst + dstsiz;
  213. + label = bp++;
  214. +
  215. + while ((c = *src++) != 0) {
  216. + if (escaped) {
  217. + if ((cp = strchr(digits, c)) != NULL) {
  218. + n = (cp - digits) * 100;
  219. + if ((c = *src++) == 0 ||
  220. + (cp = strchr(digits, c)) == NULL) {
  221. + __set_errno (EMSGSIZE);
  222. + return (-1);
  223. + }
  224. + n += (cp - digits) * 10;
  225. + if ((c = *src++) == 0 ||
  226. + (cp = strchr(digits, c)) == NULL) {
  227. + __set_errno (EMSGSIZE);
  228. + return (-1);
  229. + }
  230. + n += (cp - digits);
  231. + if (n > 255) {
  232. + __set_errno (EMSGSIZE);
  233. + return (-1);
  234. + }
  235. + c = n;
  236. + } else if (c == '[' && label == bp - 1 && *src == 'x') {
  237. + /* Theoretically we would have to handle \[o
  238. + as well but we do not since we do not need
  239. + it internally. */
  240. + *label = 0x41;
  241. + label = bp++;
  242. + ++src;
  243. + while (isxdigit (*src)) {
  244. + n = *src > '9' ? *src - 'a' + 10 : *src - '0';
  245. + ++src;
  246. + if (! isxdigit(*src)) {
  247. + __set_errno (EMSGSIZE);
  248. + return (-1);
  249. + }
  250. + n <<= 4;
  251. + n += *src > '9' ? *src - 'a' + 10 : *src - '0';
  252. + if (bp + 1 >= eom) {
  253. + __set_errno (EMSGSIZE);
  254. + return (-1);
  255. + }
  256. + *bp++ = n;
  257. + ++src;
  258. + }
  259. + *label = (bp - label - 1) * 8;
  260. + if (*src++ != ']' || *src++ != '.') {
  261. + __set_errno (EMSGSIZE);
  262. + return (-1);
  263. + }
  264. + escaped = 0;
  265. + label = bp++;
  266. + if (bp >= eom) {
  267. + __set_errno (EMSGSIZE);
  268. + return (-1);
  269. + }
  270. + continue;
  271. + }
  272. + escaped = 0;
  273. + } else if (c == '\\') {
  274. + escaped = 1;
  275. + continue;
  276. + } else if (c == '.') {
  277. + c = (bp - label - 1);
  278. + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
  279. + __set_errno (EMSGSIZE);
  280. + return (-1);
  281. + }
  282. + if (label >= eom) {
  283. + __set_errno (EMSGSIZE);
  284. + return (-1);
  285. + }
  286. + *label = c;
  287. + /* Fully qualified ? */
  288. + if (*src == '\0') {
  289. + if (c != 0) {
  290. + if (bp >= eom) {
  291. + __set_errno (EMSGSIZE);
  292. + return (-1);
  293. + }
  294. + *bp++ = '\0';
  295. + }
  296. + if ((bp - dst) > MAXCDNAME) {
  297. + __set_errno (EMSGSIZE);
  298. + return (-1);
  299. + }
  300. + return (1);
  301. + }
  302. + if (c == 0 || *src == '.') {
  303. + __set_errno (EMSGSIZE);
  304. + return (-1);
  305. + }
  306. + label = bp++;
  307. + continue;
  308. + }
  309. + if (bp >= eom) {
  310. + __set_errno (EMSGSIZE);
  311. + return (-1);
  312. + }
  313. + *bp++ = (u_char)c;
  314. + }
  315. + c = (bp - label - 1);
  316. + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
  317. + __set_errno (EMSGSIZE);
  318. + return (-1);
  319. + }
  320. + if (label >= eom) {
  321. + __set_errno (EMSGSIZE);
  322. + return (-1);
  323. + }
  324. + *label = c;
  325. + if (c != 0) {
  326. + if (bp >= eom) {
  327. + __set_errno (EMSGSIZE);
  328. + return (-1);
  329. + }
  330. + *bp++ = 0;
  331. + }
  332. + if ((bp - dst) > MAXCDNAME) { /* src too big */
  333. + __set_errno (EMSGSIZE);
  334. + return (-1);
  335. + }
  336. + return (0);
  337. +}
  338. +
  339. +
  340. +
  341. +int
  342. +ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
  343. + const u_char **dnptrs, const u_char **lastdnptr)
  344. +{
  345. + u_char tmp[NS_MAXCDNAME];
  346. +
  347. + if (ns_name_pton(src, tmp, sizeof tmp) == -1)
  348. + return (-1);
  349. + return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
  350. +}
  351. +
  352. +
  353. +int
  354. +dn_comp(const char *src, u_char *dst, int dstsiz,
  355. + u_char **dnptrs, u_char **lastdnptr)
  356. +{
  357. + return (ns_name_compress(src, dst, (size_t)dstsiz,
  358. + (const u_char **)dnptrs,
  359. + (const u_char **)lastdnptr));
  360. +}
  361. +
  362. +
  363. +
  364. +
  365. +int
  366. +res_nmkquery(res_state statp,
  367. + int op, /* opcode of query */
  368. + const char *dname, /* domain name */
  369. + int class, int type, /* class and type of query */
  370. + const u_char *data, /* resource record data */
  371. + int datalen, /* length of data */
  372. + const u_char *newrr_in, /* new rr for modify or append */
  373. + u_char *buf, /* buffer to put query */
  374. + int buflen) /* size of buffer */
  375. +{
  376. + register HEADER *hp;
  377. + register u_char *cp;
  378. + register int n;
  379. + u_char *dnptrs[20], **dpp, **lastdnptr;
  380. +
  381. +#ifdef DEBUG
  382. + if (statp->options & RES_DEBUG)
  383. + printf(";; res_nmkquery(%s, %s, %s, %s)\n",
  384. + _res_opcodes[op], dname, p_class(class), p_type(type));
  385. +#endif
  386. + /*
  387. + * Initialize header fields.
  388. + */
  389. + if ((buf == NULL) || (buflen < HFIXEDSZ))
  390. + return (-1);
  391. + memset(buf, 0, HFIXEDSZ);
  392. + hp = (HEADER *) buf;
  393. + /* We randomize the IDs every time. The old code just
  394. + incremented by one after the initial randomization which
  395. + still predictable if the application does multiple
  396. + requests. */
  397. +#if 0
  398. + hp->id = htons(++statp->id);
  399. +#else
  400. + hp->id = htons(statp->id);
  401. + int randombits;
  402. + do
  403. + {
  404. +#ifdef RANDOM_BITS
  405. + RANDOM_BITS (randombits);
  406. +#else
  407. + struct timeval tv;
  408. + gettimeofday (&tv, NULL);
  409. + randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
  410. +#endif
  411. + }
  412. + while ((randombits & 0xffff) == 0);
  413. + statp->id = (statp->id + randombits) & 0xffff;
  414. +#endif
  415. + hp->opcode = op;
  416. + hp->rd = (statp->options & RES_RECURSE) != 0;
  417. + hp->rcode = NOERROR;
  418. + cp = buf + HFIXEDSZ;
  419. + buflen -= HFIXEDSZ;
  420. + dpp = dnptrs;
  421. + *dpp++ = buf;
  422. + *dpp++ = NULL;
  423. + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
  424. + /*
  425. + * perform opcode specific processing
  426. + */
  427. + switch (op) {
  428. + case QUERY: /*FALLTHROUGH*/
  429. + case NS_NOTIFY_OP:
  430. + if ((buflen -= QFIXEDSZ) < 0)
  431. + return (-1);
  432. + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
  433. + return (-1);
  434. + cp += n;
  435. + buflen -= n;
  436. + __putshort(type, cp);
  437. + cp += INT16SZ;
  438. + __putshort(class, cp);
  439. + cp += INT16SZ;
  440. + hp->qdcount = htons(1);
  441. + if (op == QUERY || data == NULL)
  442. + break;
  443. + /*
  444. + * Make an additional record for completion domain.
  445. + */
  446. + buflen -= RRFIXEDSZ;
  447. + n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
  448. + if (n < 0)
  449. + return (-1);
  450. + cp += n;
  451. + buflen -= n;
  452. + __putshort(T_NULL, cp);
  453. + cp += INT16SZ;
  454. + __putshort(class, cp);
  455. + cp += INT16SZ;
  456. + __putlong(0, cp);
  457. + cp += INT32SZ;
  458. + __putshort(0, cp);
  459. + cp += INT16SZ;
  460. + hp->arcount = htons(1);
  461. + break;
  462. +
  463. + case IQUERY:
  464. + /*
  465. + * Initialize answer section
  466. + */
  467. + if (buflen < 1 + RRFIXEDSZ + datalen)
  468. + return (-1);
  469. + *cp++ = '\0'; /* no domain name */
  470. + __putshort(type, cp);
  471. + cp += INT16SZ;
  472. + __putshort(class, cp);
  473. + cp += INT16SZ;
  474. + __putlong(0, cp);
  475. + cp += INT32SZ;
  476. + __putshort(datalen, cp);
  477. + cp += INT16SZ;
  478. + if (datalen) {
  479. + memcpy(cp, data, datalen);
  480. + cp += datalen;
  481. + }
  482. + hp->ancount = htons(1);
  483. + break;
  484. +
  485. + default:
  486. + return (-1);
  487. + }
  488. + return (cp - buf);
  489. +}
  490. +
  491. +int
  492. +res_mkquery(int op, /* opcode of query */
  493. + const char *dname, /* domain name */
  494. + int class, int type, /* class and type of query */
  495. + const u_char *data, /* resource record data */
  496. + int datalen, /* length of data */
  497. + const u_char *newrr_in, /* new rr for modify or append */
  498. + u_char *buf, /* buffer to put query */
  499. + int buflen) /* size of buffer */
  500. +{
  501. + return (res_nmkquery(&_res, op, dname, class, type,
  502. + data, datalen,
  503. + newrr_in, buf, buflen));
  504. +}
  505. +
  506. +#endif
  507. void dorequest(char *s,int type,word id)
  508. {