ares_expand_name.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* $Id$ */
  2. /* Copyright 1998 by the Massachusetts Institute of Technology.
  3. *
  4. * Permission to use, copy, modify, and distribute this
  5. * software and its documentation for any purpose and without
  6. * fee is hereby granted, provided that the above copyright
  7. * notice appear in all copies and that both that copyright
  8. * notice and this permission notice appear in supporting
  9. * documentation, and that the name of M.I.T. not be used in
  10. * advertising or publicity pertaining to distribution of the
  11. * software without specific, written prior permission.
  12. * M.I.T. makes no representations about the suitability of
  13. * this software for any purpose. It is provided "as is"
  14. * without express or implied warranty.
  15. */
  16. #include "setup.h"
  17. #ifdef HAVE_SYS_SOCKET_H
  18. # include <sys/socket.h>
  19. #endif
  20. #ifdef HAVE_NETINET_IN_H
  21. # include <netinet/in.h>
  22. #endif
  23. #ifdef HAVE_ARPA_NAMESER_H
  24. # include <arpa/nameser.h>
  25. #else
  26. # include "nameser.h"
  27. #endif
  28. #ifdef HAVE_ARPA_NAMESER_COMPAT_H
  29. # include <arpa/nameser_compat.h>
  30. #endif
  31. #include <stdlib.h>
  32. #include "ares.h"
  33. #include "ares_private.h" /* for the memdebug */
  34. static int name_length(const unsigned char *encoded, const unsigned char *abuf,
  35. int alen);
  36. /* Expand an RFC1035-encoded domain name given by encoded. The
  37. * containing message is given by abuf and alen. The result given by
  38. * *s, which is set to a NUL-terminated allocated buffer. *enclen is
  39. * set to the length of the encoded name (not the length of the
  40. * expanded name; the goal is to tell the caller how many bytes to
  41. * move forward to get past the encoded name).
  42. *
  43. * In the simple case, an encoded name is a series of labels, each
  44. * composed of a one-byte length (limited to values between 0 and 63
  45. * inclusive) followed by the label contents. The name is terminated
  46. * by a zero-length label.
  47. *
  48. * In the more complicated case, a label may be terminated by an
  49. * indirection pointer, specified by two bytes with the high bits of
  50. * the first byte (corresponding to INDIR_MASK) set to 11. With the
  51. * two high bits of the first byte stripped off, the indirection
  52. * pointer gives an offset from the beginning of the containing
  53. * message with more labels to decode. Indirection can happen an
  54. * arbitrary number of times, so we have to detect loops.
  55. *
  56. * Since the expanded name uses '.' as a label separator, we use
  57. * backslashes to escape periods or backslashes in the expanded name.
  58. */
  59. int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
  60. int alen, char **s, long *enclen)
  61. {
  62. int len, indir = 0;
  63. char *q;
  64. const unsigned char *p;
  65. len = name_length(encoded, abuf, alen);
  66. if (len == -1)
  67. return ARES_EBADNAME;
  68. *s = malloc(len + 1);
  69. if (!*s)
  70. return ARES_ENOMEM;
  71. q = *s;
  72. if (len == 0) {
  73. /* RFC2181 says this should be ".": the root of the DNS tree.
  74. * Since this function strips trailing dots though, it becomes ""
  75. */
  76. q[0] = '\0';
  77. *enclen = 1; /* the caller should move one byte to get past this */
  78. return ARES_SUCCESS;
  79. }
  80. /* No error-checking necessary; it was all done by name_length(). */
  81. p = encoded;
  82. while (*p)
  83. {
  84. if ((*p & INDIR_MASK) == INDIR_MASK)
  85. {
  86. if (!indir)
  87. {
  88. *enclen = p + 2 - encoded;
  89. indir = 1;
  90. }
  91. p = abuf + ((*p & ~INDIR_MASK) << 8 | *(p + 1));
  92. }
  93. else
  94. {
  95. len = *p;
  96. p++;
  97. while (len--)
  98. {
  99. if (*p == '.' || *p == '\\')
  100. *q++ = '\\';
  101. *q++ = *p;
  102. p++;
  103. }
  104. *q++ = '.';
  105. }
  106. }
  107. if (!indir)
  108. *enclen = p + 1 - encoded;
  109. /* Nuke the trailing period if we wrote one. */
  110. if (q > *s)
  111. *(q - 1) = 0;
  112. else
  113. *q = 0; /* zero terminate */
  114. return ARES_SUCCESS;
  115. }
  116. /* Return the length of the expansion of an encoded domain name, or
  117. * -1 if the encoding is invalid.
  118. */
  119. static int name_length(const unsigned char *encoded, const unsigned char *abuf,
  120. int alen)
  121. {
  122. int n = 0, offset, indir = 0;
  123. /* Allow the caller to pass us abuf + alen and have us check for it. */
  124. if (encoded == abuf + alen)
  125. return -1;
  126. while (*encoded)
  127. {
  128. if ((*encoded & INDIR_MASK) == INDIR_MASK)
  129. {
  130. /* Check the offset and go there. */
  131. if (encoded + 1 >= abuf + alen)
  132. return -1;
  133. offset = (*encoded & ~INDIR_MASK) << 8 | *(encoded + 1);
  134. if (offset >= alen)
  135. return -1;
  136. encoded = abuf + offset;
  137. /* If we've seen more indirects than the message length,
  138. * then there's a loop.
  139. */
  140. if (++indir > alen)
  141. return -1;
  142. }
  143. else
  144. {
  145. offset = *encoded;
  146. if (encoded + offset + 1 >= abuf + alen)
  147. return -1;
  148. encoded++;
  149. while (offset--)
  150. {
  151. n += (*encoded == '.' || *encoded == '\\') ? 2 : 1;
  152. encoded++;
  153. }
  154. n++;
  155. }
  156. }
  157. /* If there were any labels at all, then the number of dots is one
  158. * less than the number of labels, so subtract one.
  159. */
  160. return (n) ? n - 1 : n;
  161. }
  162. /* Like ares_expand_name but returns EBADRESP in case of invalid input. */
  163. int ares__expand_name_for_response(const unsigned char *encoded,
  164. const unsigned char *abuf, int alen,
  165. char **s, long *enclen)
  166. {
  167. int status = ares_expand_name(encoded, abuf, alen, s, enclen);
  168. if (status == ARES_EBADNAME)
  169. status = ARES_EBADRESP;
  170. return status;
  171. }