ns_print.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. /*
  2. * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (c) 1996-1999 by Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
  10. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
  11. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
  12. * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  15. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  16. * SOFTWARE.
  17. */
  18. /* Import. */
  19. #include <sys/types.h>
  20. #include <sys/socket.h>
  21. #include <netinet/in.h>
  22. #include <arpa/nameser.h>
  23. #include <arpa/inet.h>
  24. #include <assert.h>
  25. #include <errno.h>
  26. #include <resolv.h>
  27. #include <string.h>
  28. #include <ctype.h>
  29. #define SPRINTF(x) ((size_t)sprintf x)
  30. /* Forward. */
  31. static size_t prune_origin(const char *name, const char *origin);
  32. static int charstr(const u_char *rdata, const u_char *edata,
  33. char **buf, size_t *buflen);
  34. static int addname(const u_char *msg, size_t msglen,
  35. const u_char **p, const char *origin,
  36. char **buf, size_t *buflen);
  37. static void addlen(size_t len, char **buf, size_t *buflen);
  38. static int addstr(const char *src, size_t len,
  39. char **buf, size_t *buflen);
  40. static int addtab(size_t len, size_t target, int spaced,
  41. char **buf, size_t *buflen);
  42. /* Macros. */
  43. #define T(x) \
  44. do { \
  45. if ((x) < 0) \
  46. return (-1); \
  47. } while (0)
  48. /* Public. */
  49. /*%
  50. * Convert an RR to presentation format.
  51. *
  52. * return:
  53. *\li Number of characters written to buf, or -1 (check errno).
  54. */
  55. int
  56. ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
  57. const char *name_ctx, const char *origin,
  58. char *buf, size_t buflen)
  59. {
  60. int n;
  61. n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
  62. ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
  63. ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
  64. name_ctx, origin, buf, buflen);
  65. return (n);
  66. }
  67. libresolv_hidden_def (ns_sprintrr)
  68. /*%
  69. * Convert the fields of an RR into presentation format.
  70. *
  71. * return:
  72. *\li Number of characters written to buf, or -1 (check errno).
  73. */
  74. int
  75. ns_sprintrrf(const u_char *msg, size_t msglen,
  76. const char *name, ns_class class, ns_type type,
  77. u_long ttl, const u_char *rdata, size_t rdlen,
  78. const char *name_ctx, const char *origin,
  79. char *buf, size_t buflen)
  80. {
  81. const char *obuf = buf;
  82. const u_char *edata = rdata + rdlen;
  83. int spaced = 0;
  84. const char *comment;
  85. char tmp[100];
  86. char errbuf[40];
  87. int len, x;
  88. /*
  89. * Owner.
  90. */
  91. if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
  92. T(addstr("\t\t\t", 3, &buf, &buflen));
  93. } else {
  94. len = prune_origin(name, origin);
  95. if (*name == '\0') {
  96. goto root;
  97. } else if (len == 0) {
  98. T(addstr("@\t\t\t", 4, &buf, &buflen));
  99. } else {
  100. T(addstr(name, len, &buf, &buflen));
  101. /* Origin not used or not root, and no trailing dot? */
  102. if (((origin == NULL || origin[0] == '\0') ||
  103. (origin[0] != '.' && origin[1] != '\0' &&
  104. name[len] == '\0')) && name[len - 1] != '.') {
  105. root:
  106. T(addstr(".", 1, &buf, &buflen));
  107. len++;
  108. }
  109. T(spaced = addtab(len, 24, spaced, &buf, &buflen));
  110. }
  111. }
  112. /*
  113. * TTL, Class, Type.
  114. */
  115. T(x = ns_format_ttl(ttl, buf, buflen));
  116. addlen(x, &buf, &buflen);
  117. len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
  118. T(addstr(tmp, len, &buf, &buflen));
  119. T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
  120. /*
  121. * RData.
  122. */
  123. switch (type) {
  124. case ns_t_a:
  125. if (rdlen != (size_t)NS_INADDRSZ)
  126. goto formerr;
  127. (void) inet_ntop(AF_INET, rdata, buf, buflen);
  128. addlen(strlen(buf), &buf, &buflen);
  129. break;
  130. case ns_t_cname:
  131. case ns_t_mb:
  132. case ns_t_mg:
  133. case ns_t_mr:
  134. case ns_t_ns:
  135. case ns_t_ptr:
  136. case ns_t_dname:
  137. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  138. break;
  139. case ns_t_hinfo:
  140. case ns_t_isdn:
  141. /* First word. */
  142. T(len = charstr(rdata, edata, &buf, &buflen));
  143. if (len == 0)
  144. goto formerr;
  145. rdata += len;
  146. T(addstr(" ", 1, &buf, &buflen));
  147. /* Second word, optional in ISDN records. */
  148. if (type == ns_t_isdn && rdata == edata)
  149. break;
  150. T(len = charstr(rdata, edata, &buf, &buflen));
  151. if (len == 0)
  152. goto formerr;
  153. rdata += len;
  154. break;
  155. case ns_t_soa: {
  156. u_long t;
  157. /* Server name. */
  158. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  159. T(addstr(" ", 1, &buf, &buflen));
  160. /* Administrator name. */
  161. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  162. T(addstr(" (\n", 3, &buf, &buflen));
  163. spaced = 0;
  164. if ((edata - rdata) != 5*NS_INT32SZ)
  165. goto formerr;
  166. /* Serial number. */
  167. t = ns_get32(rdata); rdata += NS_INT32SZ;
  168. T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
  169. len = SPRINTF((tmp, "%lu", t));
  170. T(addstr(tmp, len, &buf, &buflen));
  171. T(spaced = addtab(len, 16, spaced, &buf, &buflen));
  172. T(addstr("; serial\n", 9, &buf, &buflen));
  173. spaced = 0;
  174. /* Refresh interval. */
  175. t = ns_get32(rdata); rdata += NS_INT32SZ;
  176. T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
  177. T(len = ns_format_ttl(t, buf, buflen));
  178. addlen(len, &buf, &buflen);
  179. T(spaced = addtab(len, 16, spaced, &buf, &buflen));
  180. T(addstr("; refresh\n", 10, &buf, &buflen));
  181. spaced = 0;
  182. /* Retry interval. */
  183. t = ns_get32(rdata); rdata += NS_INT32SZ;
  184. T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
  185. T(len = ns_format_ttl(t, buf, buflen));
  186. addlen(len, &buf, &buflen);
  187. T(spaced = addtab(len, 16, spaced, &buf, &buflen));
  188. T(addstr("; retry\n", 8, &buf, &buflen));
  189. spaced = 0;
  190. /* Expiry. */
  191. t = ns_get32(rdata); rdata += NS_INT32SZ;
  192. T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
  193. T(len = ns_format_ttl(t, buf, buflen));
  194. addlen(len, &buf, &buflen);
  195. T(spaced = addtab(len, 16, spaced, &buf, &buflen));
  196. T(addstr("; expiry\n", 9, &buf, &buflen));
  197. spaced = 0;
  198. /* Minimum TTL. */
  199. t = ns_get32(rdata); rdata += NS_INT32SZ;
  200. T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
  201. T(len = ns_format_ttl(t, buf, buflen));
  202. addlen(len, &buf, &buflen);
  203. T(addstr(" )", 2, &buf, &buflen));
  204. T(spaced = addtab(len, 16, spaced, &buf, &buflen));
  205. T(addstr("; minimum\n", 10, &buf, &buflen));
  206. break;
  207. }
  208. case ns_t_mx:
  209. case ns_t_afsdb:
  210. case ns_t_rt: {
  211. u_int t;
  212. if (rdlen < (size_t)NS_INT16SZ)
  213. goto formerr;
  214. /* Priority. */
  215. t = ns_get16(rdata);
  216. rdata += NS_INT16SZ;
  217. len = SPRINTF((tmp, "%u ", t));
  218. T(addstr(tmp, len, &buf, &buflen));
  219. /* Target. */
  220. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  221. break;
  222. }
  223. case ns_t_px: {
  224. u_int t;
  225. if (rdlen < (size_t)NS_INT16SZ)
  226. goto formerr;
  227. /* Priority. */
  228. t = ns_get16(rdata);
  229. rdata += NS_INT16SZ;
  230. len = SPRINTF((tmp, "%u ", t));
  231. T(addstr(tmp, len, &buf, &buflen));
  232. /* Name1. */
  233. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  234. T(addstr(" ", 1, &buf, &buflen));
  235. /* Name2. */
  236. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  237. break;
  238. }
  239. case ns_t_x25:
  240. T(len = charstr(rdata, edata, &buf, &buflen));
  241. if (len == 0)
  242. goto formerr;
  243. rdata += len;
  244. break;
  245. case ns_t_txt:
  246. while (rdata < edata) {
  247. T(len = charstr(rdata, edata, &buf, &buflen));
  248. if (len == 0)
  249. goto formerr;
  250. rdata += len;
  251. if (rdata < edata)
  252. T(addstr(" ", 1, &buf, &buflen));
  253. }
  254. break;
  255. case ns_t_nsap: {
  256. char t[2+255*3];
  257. (void) inet_nsap_ntoa(rdlen, rdata, t);
  258. T(addstr(t, strlen(t), &buf, &buflen));
  259. break;
  260. }
  261. case ns_t_aaaa:
  262. if (rdlen != (size_t)NS_IN6ADDRSZ)
  263. goto formerr;
  264. (void) inet_ntop(AF_INET6, rdata, buf, buflen);
  265. addlen(strlen(buf), &buf, &buflen);
  266. break;
  267. case ns_t_loc: {
  268. char t[255];
  269. /* XXX protocol format checking? */
  270. (void) loc_ntoa(rdata, t);
  271. T(addstr(t, strlen(t), &buf, &buflen));
  272. break;
  273. }
  274. case ns_t_naptr: {
  275. u_int order, preference;
  276. char t[50];
  277. if (rdlen < 2U*NS_INT16SZ)
  278. goto formerr;
  279. /* Order, Precedence. */
  280. order = ns_get16(rdata); rdata += NS_INT16SZ;
  281. preference = ns_get16(rdata); rdata += NS_INT16SZ;
  282. len = SPRINTF((t, "%u %u ", order, preference));
  283. T(addstr(t, len, &buf, &buflen));
  284. /* Flags. */
  285. T(len = charstr(rdata, edata, &buf, &buflen));
  286. if (len == 0)
  287. goto formerr;
  288. rdata += len;
  289. T(addstr(" ", 1, &buf, &buflen));
  290. /* Service. */
  291. T(len = charstr(rdata, edata, &buf, &buflen));
  292. if (len == 0)
  293. goto formerr;
  294. rdata += len;
  295. T(addstr(" ", 1, &buf, &buflen));
  296. /* Regexp. */
  297. T(len = charstr(rdata, edata, &buf, &buflen));
  298. if (len < 0)
  299. return (-1);
  300. if (len == 0)
  301. goto formerr;
  302. rdata += len;
  303. T(addstr(" ", 1, &buf, &buflen));
  304. /* Server. */
  305. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  306. break;
  307. }
  308. case ns_t_srv: {
  309. u_int priority, weight, port;
  310. char t[50];
  311. if (rdlen < 3U*NS_INT16SZ)
  312. goto formerr;
  313. /* Priority, Weight, Port. */
  314. priority = ns_get16(rdata); rdata += NS_INT16SZ;
  315. weight = ns_get16(rdata); rdata += NS_INT16SZ;
  316. port = ns_get16(rdata); rdata += NS_INT16SZ;
  317. len = SPRINTF((t, "%u %u %u ", priority, weight, port));
  318. T(addstr(t, len, &buf, &buflen));
  319. /* Server. */
  320. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  321. break;
  322. }
  323. case ns_t_minfo:
  324. case ns_t_rp:
  325. /* Name1. */
  326. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  327. T(addstr(" ", 1, &buf, &buflen));
  328. /* Name2. */
  329. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  330. break;
  331. case ns_t_wks: {
  332. int n, lcnt;
  333. if (rdlen < 1U + NS_INT32SZ)
  334. goto formerr;
  335. /* Address. */
  336. (void) inet_ntop(AF_INET, rdata, buf, buflen);
  337. addlen(strlen(buf), &buf, &buflen);
  338. rdata += NS_INADDRSZ;
  339. /* Protocol. */
  340. len = SPRINTF((tmp, " %u ( ", *rdata));
  341. T(addstr(tmp, len, &buf, &buflen));
  342. rdata += NS_INT8SZ;
  343. /* Bit map. */
  344. n = 0;
  345. lcnt = 0;
  346. while (rdata < edata) {
  347. u_int c = *rdata++;
  348. do {
  349. if (c & 0200) {
  350. if (lcnt == 0) {
  351. T(addstr("\n\t\t\t\t", 5,
  352. &buf, &buflen));
  353. lcnt = 10;
  354. spaced = 0;
  355. }
  356. len = SPRINTF((tmp, "%d ", n));
  357. T(addstr(tmp, len, &buf, &buflen));
  358. lcnt--;
  359. }
  360. c <<= 1;
  361. } while (++n & 07);
  362. }
  363. T(addstr(")", 1, &buf, &buflen));
  364. break;
  365. }
  366. case ns_t_cert: {
  367. u_int c_type, key_tag, alg;
  368. int n;
  369. unsigned int siz;
  370. char base64_cert[8192], tmp[40];
  371. const char *leader;
  372. c_type = ns_get16(rdata); rdata += NS_INT16SZ;
  373. key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
  374. alg = (u_int) *rdata++;
  375. len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
  376. T(addstr(tmp, len, &buf, &buflen));
  377. siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
  378. if (siz > sizeof(base64_cert) * 3/4) {
  379. const char *str = "record too long to print";
  380. T(addstr(str, strlen(str), &buf, &buflen));
  381. }
  382. else {
  383. len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
  384. if (len < 0)
  385. goto formerr;
  386. else if (len > 15) {
  387. T(addstr(" (", 2, &buf, &buflen));
  388. leader = "\n\t\t";
  389. spaced = 0;
  390. }
  391. else
  392. leader = " ";
  393. for (n = 0; n < len; n += 48) {
  394. T(addstr(leader, strlen(leader),
  395. &buf, &buflen));
  396. T(addstr(base64_cert + n, MIN(len - n, 48),
  397. &buf, &buflen));
  398. }
  399. if (len > 15)
  400. T(addstr(" )", 2, &buf, &buflen));
  401. }
  402. break;
  403. }
  404. case ns_t_tkey: {
  405. /* KJD - need to complete this */
  406. u_long t;
  407. int mode, err, keysize;
  408. /* Algorithm name. */
  409. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  410. T(addstr(" ", 1, &buf, &buflen));
  411. /* Inception. */
  412. t = ns_get32(rdata); rdata += NS_INT32SZ;
  413. len = SPRINTF((tmp, "%lu ", t));
  414. T(addstr(tmp, len, &buf, &buflen));
  415. /* Experation. */
  416. t = ns_get32(rdata); rdata += NS_INT32SZ;
  417. len = SPRINTF((tmp, "%lu ", t));
  418. T(addstr(tmp, len, &buf, &buflen));
  419. /* Mode , Error, Key Size. */
  420. /* Priority, Weight, Port. */
  421. mode = ns_get16(rdata); rdata += NS_INT16SZ;
  422. err = ns_get16(rdata); rdata += NS_INT16SZ;
  423. keysize = ns_get16(rdata); rdata += NS_INT16SZ;
  424. len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
  425. T(addstr(tmp, len, &buf, &buflen));
  426. /* XXX need to dump key, print otherdata length & other data */
  427. break;
  428. }
  429. case ns_t_tsig: {
  430. /* BEW - need to complete this */
  431. int n;
  432. T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
  433. T(addstr(" ", 1, &buf, &buflen));
  434. rdata += 8; /*%< time */
  435. n = ns_get16(rdata); rdata += INT16SZ;
  436. rdata += n; /*%< sig */
  437. n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
  438. sprintf(buf, "%d", ns_get16(rdata));
  439. rdata += INT16SZ;
  440. addlen(strlen(buf), &buf, &buflen);
  441. break;
  442. }
  443. case ns_t_a6: {
  444. struct in6_addr a;
  445. int pbyte, pbit;
  446. /* prefix length */
  447. if (rdlen == 0U) goto formerr;
  448. len = SPRINTF((tmp, "%d ", *rdata));
  449. T(addstr(tmp, len, &buf, &buflen));
  450. pbit = *rdata;
  451. if (pbit > 128) goto formerr;
  452. pbyte = (pbit & ~7) / 8;
  453. rdata++;
  454. /* address suffix: provided only when prefix len != 128 */
  455. if (pbit < 128) {
  456. if (rdata + pbyte >= edata) goto formerr;
  457. memset(&a, 0, sizeof(a));
  458. memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
  459. (void) inet_ntop(AF_INET6, &a, buf, buflen);
  460. addlen(strlen(buf), &buf, &buflen);
  461. rdata += sizeof(a) - pbyte;
  462. }
  463. /* prefix name: provided only when prefix len > 0 */
  464. if (pbit == 0)
  465. break;
  466. if (rdata >= edata) goto formerr;
  467. T(addstr(" ", 1, &buf, &buflen));
  468. T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
  469. break;
  470. }
  471. case ns_t_opt: {
  472. len = SPRINTF((tmp, "%u bytes", class));
  473. T(addstr(tmp, len, &buf, &buflen));
  474. break;
  475. }
  476. default:
  477. snprintf (errbuf, sizeof (errbuf), "unknown RR type %d", type);
  478. comment = errbuf;
  479. goto hexify;
  480. }
  481. return (buf - obuf);
  482. formerr:
  483. comment = "RR format error";
  484. hexify: {
  485. int n, m;
  486. char *p;
  487. len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
  488. rdlen != 0U ? " (" : "", comment));
  489. T(addstr(tmp, len, &buf, &buflen));
  490. while (rdata < edata) {
  491. p = tmp;
  492. p += SPRINTF((p, "\n\t"));
  493. spaced = 0;
  494. n = MIN(16, edata - rdata);
  495. for (m = 0; m < n; m++)
  496. p += SPRINTF((p, "%02x ", rdata[m]));
  497. T(addstr(tmp, p - tmp, &buf, &buflen));
  498. if (n < 16) {
  499. T(addstr(")", 1, &buf, &buflen));
  500. T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
  501. }
  502. p = tmp;
  503. p += SPRINTF((p, "; "));
  504. for (m = 0; m < n; m++)
  505. *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
  506. ? rdata[m]
  507. : '.';
  508. T(addstr(tmp, p - tmp, &buf, &buflen));
  509. rdata += n;
  510. }
  511. return (buf - obuf);
  512. }
  513. }
  514. libresolv_hidden_def (ns_sprintrrf)
  515. /* Private. */
  516. /*%
  517. * size_t
  518. * prune_origin(name, origin)
  519. * Find out if the name is at or under the current origin.
  520. * return:
  521. * Number of characters in name before start of origin,
  522. * or length of name if origin does not match.
  523. * notes:
  524. * This function should share code with samedomain().
  525. */
  526. static size_t
  527. prune_origin(const char *name, const char *origin) {
  528. const char *oname = name;
  529. while (*name != '\0') {
  530. if (origin != NULL && ns_samename(name, origin) == 1)
  531. return (name - oname - (name > oname));
  532. while (*name != '\0') {
  533. if (*name == '\\') {
  534. name++;
  535. /* XXX need to handle \nnn form. */
  536. if (*name == '\0')
  537. break;
  538. } else if (*name == '.') {
  539. name++;
  540. break;
  541. }
  542. name++;
  543. }
  544. }
  545. return (name - oname);
  546. }
  547. /*%
  548. * int
  549. * charstr(rdata, edata, buf, buflen)
  550. * Format a <character-string> into the presentation buffer.
  551. * return:
  552. * Number of rdata octets consumed
  553. * 0 for protocol format error
  554. * -1 for output buffer error
  555. * side effects:
  556. * buffer is advanced on success.
  557. */
  558. static int
  559. charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
  560. const u_char *odata = rdata;
  561. size_t save_buflen = *buflen;
  562. char *save_buf = *buf;
  563. if (addstr("\"", 1, buf, buflen) < 0)
  564. goto enospc;
  565. if (rdata < edata) {
  566. int n = *rdata;
  567. if (rdata + 1 + n <= edata) {
  568. rdata++;
  569. while (n-- > 0) {
  570. if (strchr("\n\"\\", *rdata) != NULL)
  571. if (addstr("\\", 1, buf, buflen) < 0)
  572. goto enospc;
  573. if (addstr((const char *)rdata, 1,
  574. buf, buflen) < 0)
  575. goto enospc;
  576. rdata++;
  577. }
  578. }
  579. }
  580. if (addstr("\"", 1, buf, buflen) < 0)
  581. goto enospc;
  582. return (rdata - odata);
  583. enospc:
  584. __set_errno (ENOSPC);
  585. *buf = save_buf;
  586. *buflen = save_buflen;
  587. return (-1);
  588. }
  589. static int
  590. addname(const u_char *msg, size_t msglen,
  591. const u_char **pp, const char *origin,
  592. char **buf, size_t *buflen)
  593. {
  594. size_t newlen, save_buflen = *buflen;
  595. char *save_buf = *buf;
  596. int n;
  597. n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
  598. if (n < 0)
  599. goto enospc; /*%< Guess. */
  600. newlen = prune_origin(*buf, origin);
  601. if (**buf == '\0') {
  602. goto root;
  603. } else if (newlen == 0U) {
  604. /* Use "@" instead of name. */
  605. if (newlen + 2 > *buflen)
  606. goto enospc; /* No room for "@\0". */
  607. (*buf)[newlen++] = '@';
  608. (*buf)[newlen] = '\0';
  609. } else {
  610. if (((origin == NULL || origin[0] == '\0') ||
  611. (origin[0] != '.' && origin[1] != '\0' &&
  612. (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
  613. /* No trailing dot. */
  614. root:
  615. if (newlen + 2 > *buflen)
  616. goto enospc; /* No room for ".\0". */
  617. (*buf)[newlen++] = '.';
  618. (*buf)[newlen] = '\0';
  619. }
  620. }
  621. *pp += n;
  622. addlen(newlen, buf, buflen);
  623. **buf = '\0';
  624. return (newlen);
  625. enospc:
  626. __set_errno (ENOSPC);
  627. *buf = save_buf;
  628. *buflen = save_buflen;
  629. return (-1);
  630. }
  631. static void
  632. addlen(size_t len, char **buf, size_t *buflen) {
  633. assert(len <= *buflen);
  634. *buf += len;
  635. *buflen -= len;
  636. }
  637. static int
  638. addstr(const char *src, size_t len, char **buf, size_t *buflen) {
  639. if (len >= *buflen) {
  640. __set_errno (ENOSPC);
  641. return (-1);
  642. }
  643. memcpy(*buf, src, len);
  644. addlen(len, buf, buflen);
  645. **buf = '\0';
  646. return (0);
  647. }
  648. static int
  649. addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
  650. size_t save_buflen = *buflen;
  651. char *save_buf = *buf;
  652. int t;
  653. if (spaced || len >= target - 1) {
  654. T(addstr(" ", 2, buf, buflen));
  655. spaced = 1;
  656. } else {
  657. for (t = (target - len - 1) / 8; t >= 0; t--)
  658. if (addstr("\t", 1, buf, buflen) < 0) {
  659. *buflen = save_buflen;
  660. *buf = save_buf;
  661. return (-1);
  662. }
  663. spaced = 0;
  664. }
  665. return (spaced);
  666. }