ns_name.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  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 ISC DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  15. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <sys/types.h>
  18. #include <netinet/in.h>
  19. #include <arpa/nameser.h>
  20. #include <errno.h>
  21. #include <resolv.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <stdlib.h>
  25. #include <limits.h>
  26. # define SPRINTF(x) ((size_t)sprintf x)
  27. /* Data. */
  28. static const char digits[] = "0123456789";
  29. /* Forward. */
  30. static int special(int);
  31. static int printable(int);
  32. static int dn_find(const u_char *, const u_char *,
  33. const u_char * const *,
  34. const u_char * const *);
  35. static int labellen(const u_char *);
  36. /* Public. */
  37. /*%
  38. * Convert an encoded domain name to printable ascii as per RFC1035.
  39. * return:
  40. *\li Number of bytes written to buffer, or -1 (with errno set)
  41. *
  42. * notes:
  43. *\li The root is returned as "."
  44. *\li All other domains are returned in non absolute form
  45. */
  46. int
  47. ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
  48. {
  49. const u_char *cp;
  50. char *dn, *eom;
  51. u_char c;
  52. u_int n;
  53. int l;
  54. cp = src;
  55. dn = dst;
  56. eom = dst + dstsiz;
  57. while ((n = *cp++) != 0) {
  58. if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
  59. /* Some kind of compression pointer. */
  60. __set_errno (EMSGSIZE);
  61. return (-1);
  62. }
  63. if (dn != dst) {
  64. if (dn >= eom) {
  65. __set_errno (EMSGSIZE);
  66. return (-1);
  67. }
  68. *dn++ = '.';
  69. }
  70. if ((l = labellen(cp - 1)) < 0) {
  71. __set_errno (EMSGSIZE);
  72. return(-1);
  73. }
  74. if (dn + l >= eom) {
  75. __set_errno (EMSGSIZE);
  76. return (-1);
  77. }
  78. for ((void)NULL; l > 0; l--) {
  79. c = *cp++;
  80. if (special(c)) {
  81. if (dn + 1 >= eom) {
  82. __set_errno (EMSGSIZE);
  83. return (-1);
  84. }
  85. *dn++ = '\\';
  86. *dn++ = (char)c;
  87. } else if (!printable(c)) {
  88. if (dn + 3 >= eom) {
  89. __set_errno (EMSGSIZE);
  90. return (-1);
  91. }
  92. *dn++ = '\\';
  93. *dn++ = digits[c / 100];
  94. *dn++ = digits[(c % 100) / 10];
  95. *dn++ = digits[c % 10];
  96. } else {
  97. if (dn >= eom) {
  98. __set_errno (EMSGSIZE);
  99. return (-1);
  100. }
  101. *dn++ = (char)c;
  102. }
  103. }
  104. }
  105. if (dn == dst) {
  106. if (dn >= eom) {
  107. __set_errno (EMSGSIZE);
  108. return (-1);
  109. }
  110. *dn++ = '.';
  111. }
  112. if (dn >= eom) {
  113. __set_errno (EMSGSIZE);
  114. return (-1);
  115. }
  116. *dn++ = '\0';
  117. return (dn - dst);
  118. }
  119. libresolv_hidden_def (ns_name_ntop)
  120. strong_alias (ns_name_ntop, __ns_name_ntop)
  121. /*%
  122. * Convert an ascii string into an encoded domain name as per RFC1035.
  123. *
  124. * return:
  125. *
  126. *\li -1 if it fails
  127. *\li 1 if string was fully qualified
  128. *\li 0 is string was not fully qualified
  129. *
  130. * notes:
  131. *\li Enforces label and domain length limits.
  132. */
  133. int
  134. ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
  135. {
  136. u_char *label, *bp, *eom;
  137. int c, n, escaped;
  138. char *cp;
  139. escaped = 0;
  140. bp = dst;
  141. eom = dst + dstsiz;
  142. label = bp++;
  143. while ((c = *src++) != 0) {
  144. if (escaped) {
  145. if ((cp = strchr(digits, c)) != NULL) {
  146. n = (cp - digits) * 100;
  147. if ((c = *src++) == 0 ||
  148. (cp = strchr(digits, c)) == NULL) {
  149. __set_errno (EMSGSIZE);
  150. return (-1);
  151. }
  152. n += (cp - digits) * 10;
  153. if ((c = *src++) == 0 ||
  154. (cp = strchr(digits, c)) == NULL) {
  155. __set_errno (EMSGSIZE);
  156. return (-1);
  157. }
  158. n += (cp - digits);
  159. if (n > 255) {
  160. __set_errno (EMSGSIZE);
  161. return (-1);
  162. }
  163. c = n;
  164. }
  165. escaped = 0;
  166. } else if (c == '\\') {
  167. escaped = 1;
  168. continue;
  169. } else if (c == '.') {
  170. c = (bp - label - 1);
  171. if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
  172. __set_errno (EMSGSIZE);
  173. return (-1);
  174. }
  175. if (label >= eom) {
  176. __set_errno (EMSGSIZE);
  177. return (-1);
  178. }
  179. *label = c;
  180. /* Fully qualified ? */
  181. if (*src == '\0') {
  182. if (c != 0) {
  183. if (bp >= eom) {
  184. __set_errno (EMSGSIZE);
  185. return (-1);
  186. }
  187. *bp++ = '\0';
  188. }
  189. if ((bp - dst) > MAXCDNAME) {
  190. __set_errno (EMSGSIZE);
  191. return (-1);
  192. }
  193. return (1);
  194. }
  195. if (c == 0 || *src == '.') {
  196. __set_errno (EMSGSIZE);
  197. return (-1);
  198. }
  199. label = bp++;
  200. continue;
  201. }
  202. if (bp >= eom) {
  203. __set_errno (EMSGSIZE);
  204. return (-1);
  205. }
  206. *bp++ = (u_char)c;
  207. }
  208. if (escaped) {
  209. /* Trailing backslash. */
  210. __set_errno (EMSGSIZE);
  211. return -1;
  212. }
  213. c = (bp - label - 1);
  214. if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
  215. __set_errno (EMSGSIZE);
  216. return (-1);
  217. }
  218. if (label >= eom) {
  219. __set_errno (EMSGSIZE);
  220. return (-1);
  221. }
  222. *label = c;
  223. if (c != 0) {
  224. if (bp >= eom) {
  225. __set_errno (EMSGSIZE);
  226. return (-1);
  227. }
  228. *bp++ = 0;
  229. }
  230. if ((bp - dst) > MAXCDNAME) { /*%< src too big */
  231. __set_errno (EMSGSIZE);
  232. return (-1);
  233. }
  234. return (0);
  235. }
  236. libresolv_hidden_def (ns_name_pton)
  237. /*%
  238. * Convert a network strings labels into all lowercase.
  239. *
  240. * return:
  241. *\li Number of bytes written to buffer, or -1 (with errno set)
  242. *
  243. * notes:
  244. *\li Enforces label and domain length limits.
  245. */
  246. int
  247. ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
  248. {
  249. const u_char *cp;
  250. u_char *dn, *eom;
  251. u_char c;
  252. u_int n;
  253. int l;
  254. cp = src;
  255. dn = dst;
  256. eom = dst + dstsiz;
  257. if (dn >= eom) {
  258. __set_errno (EMSGSIZE);
  259. return (-1);
  260. }
  261. while ((n = *cp++) != 0) {
  262. if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
  263. /* Some kind of compression pointer. */
  264. __set_errno (EMSGSIZE);
  265. return (-1);
  266. }
  267. *dn++ = n;
  268. if ((l = labellen(cp - 1)) < 0) {
  269. __set_errno (EMSGSIZE);
  270. return (-1);
  271. }
  272. if (dn + l >= eom) {
  273. __set_errno (EMSGSIZE);
  274. return (-1);
  275. }
  276. for ((void)NULL; l > 0; l--) {
  277. c = *cp++;
  278. if (isupper(c))
  279. *dn++ = tolower(c);
  280. else
  281. *dn++ = c;
  282. }
  283. }
  284. *dn++ = '\0';
  285. return (dn - dst);
  286. }
  287. /*%
  288. * Unpack a domain name from a message, source may be compressed.
  289. *
  290. * return:
  291. *\li -1 if it fails, or consumed octets if it succeeds.
  292. */
  293. int
  294. ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
  295. u_char *dst, size_t dstsiz)
  296. {
  297. const u_char *srcp, *dstlim;
  298. u_char *dstp;
  299. int n, len, checked, l;
  300. len = -1;
  301. checked = 0;
  302. dstp = dst;
  303. srcp = src;
  304. dstlim = dst + dstsiz;
  305. if (srcp < msg || srcp >= eom) {
  306. __set_errno (EMSGSIZE);
  307. return (-1);
  308. }
  309. /* Fetch next label in domain name. */
  310. while ((n = *srcp++) != 0) {
  311. /* Check for indirection. */
  312. switch (n & NS_CMPRSFLGS) {
  313. case 0:
  314. /* Limit checks. */
  315. if ((l = labellen(srcp - 1)) < 0) {
  316. __set_errno (EMSGSIZE);
  317. return(-1);
  318. }
  319. if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
  320. __set_errno (EMSGSIZE);
  321. return (-1);
  322. }
  323. checked += l + 1;
  324. *dstp++ = n;
  325. memcpy(dstp, srcp, l);
  326. dstp += l;
  327. srcp += l;
  328. break;
  329. case NS_CMPRSFLGS:
  330. if (srcp >= eom) {
  331. __set_errno (EMSGSIZE);
  332. return (-1);
  333. }
  334. if (len < 0)
  335. len = srcp - src + 1;
  336. srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
  337. if (srcp < msg || srcp >= eom) { /*%< Out of range. */
  338. __set_errno (EMSGSIZE);
  339. return (-1);
  340. }
  341. checked += 2;
  342. /*
  343. * Check for loops in the compressed name;
  344. * if we've looked at the whole message,
  345. * there must be a loop.
  346. */
  347. if (checked >= eom - msg) {
  348. __set_errno (EMSGSIZE);
  349. return (-1);
  350. }
  351. break;
  352. default:
  353. __set_errno (EMSGSIZE);
  354. return (-1); /*%< flag error */
  355. }
  356. }
  357. *dstp = '\0';
  358. if (len < 0)
  359. len = srcp - src;
  360. return (len);
  361. }
  362. libresolv_hidden_def (ns_name_unpack)
  363. strong_alias (ns_name_unpack, __ns_name_unpack)
  364. /*%
  365. * Pack domain name 'domain' into 'comp_dn'.
  366. *
  367. * return:
  368. *\li Size of the compressed name, or -1.
  369. *
  370. * notes:
  371. *\li 'dnptrs' is an array of pointers to previous compressed names.
  372. *\li dnptrs[0] is a pointer to the beginning of the message. The array
  373. * ends with NULL.
  374. *\li 'lastdnptr' is a pointer to the end of the array pointed to
  375. * by 'dnptrs'.
  376. *
  377. * Side effects:
  378. *\li The list of pointers in dnptrs is updated for labels inserted into
  379. * the message as we compress the name. If 'dnptr' is NULL, we don't
  380. * try to compress names. If 'lastdnptr' is NULL, we don't update the
  381. * list.
  382. */
  383. int
  384. ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
  385. const u_char **dnptrs, const u_char **lastdnptr)
  386. {
  387. u_char *dstp;
  388. const u_char **cpp, **lpp, *eob, *msg;
  389. const u_char *srcp;
  390. int n, l, first = 1;
  391. srcp = src;
  392. dstp = dst;
  393. eob = dstp + dstsiz;
  394. lpp = cpp = NULL;
  395. if (dnptrs != NULL) {
  396. if ((msg = *dnptrs++) != NULL) {
  397. for (cpp = dnptrs; *cpp != NULL; cpp++)
  398. (void)NULL;
  399. lpp = cpp; /*%< end of list to search */
  400. }
  401. } else
  402. msg = NULL;
  403. /* make sure the domain we are about to add is legal */
  404. l = 0;
  405. do {
  406. int l0;
  407. n = *srcp;
  408. if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
  409. __set_errno (EMSGSIZE);
  410. return (-1);
  411. }
  412. if ((l0 = labellen(srcp)) < 0) {
  413. __set_errno (EINVAL);
  414. return(-1);
  415. }
  416. l += l0 + 1;
  417. if (l > MAXCDNAME) {
  418. __set_errno (EMSGSIZE);
  419. return (-1);
  420. }
  421. srcp += l0 + 1;
  422. } while (n != 0);
  423. /* from here on we need to reset compression pointer array on error */
  424. srcp = src;
  425. do {
  426. /* Look to see if we can use pointers. */
  427. n = *srcp;
  428. if (n != 0 && msg != NULL) {
  429. l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
  430. (const u_char * const *)lpp);
  431. if (l >= 0) {
  432. if (dstp + 1 >= eob) {
  433. goto cleanup;
  434. }
  435. *dstp++ = (l >> 8) | NS_CMPRSFLGS;
  436. *dstp++ = l % 256;
  437. return (dstp - dst);
  438. }
  439. /* Not found, save it. */
  440. if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
  441. (dstp - msg) < 0x4000 && first) {
  442. *cpp++ = dstp;
  443. *cpp = NULL;
  444. first = 0;
  445. }
  446. }
  447. /* copy label to buffer */
  448. if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
  449. /* Should not happen. */
  450. goto cleanup;
  451. }
  452. n = labellen(srcp);
  453. if (n + 1 > eob - dstp) {
  454. goto cleanup;
  455. }
  456. memcpy(dstp, srcp, n + 1);
  457. srcp += n + 1;
  458. dstp += n + 1;
  459. } while (n != 0);
  460. if (dstp > eob) {
  461. cleanup:
  462. if (msg != NULL)
  463. *lpp = NULL;
  464. __set_errno (EMSGSIZE);
  465. return (-1);
  466. }
  467. return (dstp - dst);
  468. }
  469. libresolv_hidden_def (ns_name_pack)
  470. /*%
  471. * Expand compressed domain name to presentation format.
  472. *
  473. * return:
  474. *\li Number of bytes read out of `src', or -1 (with errno set).
  475. *
  476. * note:
  477. *\li Root domain returns as "." not "".
  478. */
  479. int
  480. ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
  481. char *dst, size_t dstsiz)
  482. {
  483. u_char tmp[NS_MAXCDNAME];
  484. int n;
  485. if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
  486. return (-1);
  487. if (ns_name_ntop(tmp, dst, dstsiz) == -1)
  488. return (-1);
  489. return (n);
  490. }
  491. libresolv_hidden_def (ns_name_uncompress)
  492. /*%
  493. * Compress a domain name into wire format, using compression pointers.
  494. *
  495. * return:
  496. *\li Number of bytes consumed in `dst' or -1 (with errno set).
  497. *
  498. * notes:
  499. *\li 'dnptrs' is an array of pointers to previous compressed names.
  500. *\li dnptrs[0] is a pointer to the beginning of the message.
  501. *\li The list ends with NULL. 'lastdnptr' is a pointer to the end of the
  502. * array pointed to by 'dnptrs'. Side effect is to update the list of
  503. * pointers for labels inserted into the message as we compress the name.
  504. *\li If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  505. * is NULL, we don't update the list.
  506. */
  507. int
  508. ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
  509. const u_char **dnptrs, const u_char **lastdnptr)
  510. {
  511. u_char tmp[NS_MAXCDNAME];
  512. if (ns_name_pton(src, tmp, sizeof tmp) == -1)
  513. return (-1);
  514. return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
  515. }
  516. libresolv_hidden_def (ns_name_compress)
  517. /*%
  518. * Reset dnptrs so that there are no active references to pointers at or
  519. * after src.
  520. */
  521. void
  522. ns_name_rollback(const u_char *src, const u_char **dnptrs,
  523. const u_char **lastdnptr)
  524. {
  525. while (dnptrs < lastdnptr && *dnptrs != NULL) {
  526. if (*dnptrs >= src) {
  527. *dnptrs = NULL;
  528. break;
  529. }
  530. dnptrs++;
  531. }
  532. }
  533. /*%
  534. * Advance *ptrptr to skip over the compressed name it points at.
  535. *
  536. * return:
  537. *\li 0 on success, -1 (with errno set) on failure.
  538. */
  539. int
  540. ns_name_skip(const u_char **ptrptr, const u_char *eom)
  541. {
  542. const u_char *cp;
  543. u_int n;
  544. cp = *ptrptr;
  545. while (cp < eom && (n = *cp++) != 0) {
  546. /* Check for indirection. */
  547. switch (n & NS_CMPRSFLGS) {
  548. case 0: /*%< normal case, n == len */
  549. cp += n;
  550. continue;
  551. case NS_CMPRSFLGS: /*%< indirection */
  552. cp++;
  553. break;
  554. default: /*%< illegal type */
  555. __set_errno (EMSGSIZE);
  556. return (-1);
  557. }
  558. break;
  559. }
  560. if (cp > eom) {
  561. __set_errno (EMSGSIZE);
  562. return (-1);
  563. }
  564. *ptrptr = cp;
  565. return (0);
  566. }
  567. libresolv_hidden_def (ns_name_skip)
  568. /* Private. */
  569. /*%
  570. * Thinking in noninternationalized USASCII (per the DNS spec),
  571. * is this character special ("in need of quoting") ?
  572. *
  573. * return:
  574. *\li boolean.
  575. */
  576. static int
  577. special(int ch) {
  578. switch (ch) {
  579. case 0x22: /*%< '"' */
  580. case 0x2E: /*%< '.' */
  581. case 0x3B: /*%< ';' */
  582. case 0x5C: /*%< '\\' */
  583. case 0x28: /*%< '(' */
  584. case 0x29: /*%< ')' */
  585. /* Special modifiers in zone files. */
  586. case 0x40: /*%< '@' */
  587. case 0x24: /*%< '$' */
  588. return (1);
  589. default:
  590. return (0);
  591. }
  592. }
  593. /*%
  594. * Thinking in noninternationalized USASCII (per the DNS spec),
  595. * is this character visible and not a space when printed ?
  596. *
  597. * return:
  598. *\li boolean.
  599. */
  600. static int
  601. printable(int ch) {
  602. return (ch > 0x20 && ch < 0x7f);
  603. }
  604. /*%
  605. * Thinking in noninternationalized USASCII (per the DNS spec),
  606. * convert this character to lower case if it's upper case.
  607. */
  608. static int
  609. mklower(int ch) {
  610. if (ch >= 0x41 && ch <= 0x5A)
  611. return (ch + 0x20);
  612. return (ch);
  613. }
  614. /*%
  615. * Search for the counted-label name in an array of compressed names.
  616. *
  617. * return:
  618. *\li offset from msg if found, or -1.
  619. *
  620. * notes:
  621. *\li dnptrs is the pointer to the first name on the list,
  622. *\li not the pointer to the start of the message.
  623. */
  624. static int
  625. dn_find(const u_char *domain, const u_char *msg,
  626. const u_char * const *dnptrs,
  627. const u_char * const *lastdnptr)
  628. {
  629. const u_char *dn, *cp, *sp;
  630. const u_char * const *cpp;
  631. u_int n;
  632. for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  633. sp = *cpp;
  634. /*
  635. * terminate search on:
  636. * root label
  637. * compression pointer
  638. * unusable offset
  639. */
  640. while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
  641. (sp - msg) < 0x4000) {
  642. dn = domain;
  643. cp = sp;
  644. while ((n = *cp++) != 0) {
  645. /*
  646. * check for indirection
  647. */
  648. switch (n & NS_CMPRSFLGS) {
  649. case 0: /*%< normal case, n == len */
  650. n = labellen(cp - 1); /*%< XXX */
  651. if (n != *dn++)
  652. goto next;
  653. for ((void)NULL; n > 0; n--)
  654. if (mklower(*dn++) !=
  655. mklower(*cp++))
  656. goto next;
  657. /* Is next root for both ? */
  658. if (*dn == '\0' && *cp == '\0')
  659. return (sp - msg);
  660. if (*dn)
  661. continue;
  662. goto next;
  663. case NS_CMPRSFLGS: /*%< indirection */
  664. cp = msg + (((n & 0x3f) << 8) | *cp);
  665. break;
  666. default: /*%< illegal type */
  667. __set_errno (EMSGSIZE);
  668. return (-1);
  669. }
  670. }
  671. next: ;
  672. sp += *sp + 1;
  673. }
  674. }
  675. __set_errno (ENOENT);
  676. return (-1);
  677. }
  678. /* Return the length of the encoded label starting at LP, or -1 for
  679. compression references and extended label types. */
  680. static int
  681. labellen (const unsigned char *lp)
  682. {
  683. if (*lp <= 63)
  684. return *lp;
  685. return -1;
  686. }
  687. /*! \file */