ares__parse_into_addrinfo.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /* Copyright (C) 2019 by Andrew Selivanov
  2. *
  3. * Permission to use, copy, modify, and distribute this
  4. * software and its documentation for any purpose and without
  5. * fee is hereby granted, provided that the above copyright
  6. * notice appear in all copies and that both that copyright
  7. * notice and this permission notice appear in supporting
  8. * documentation, and that the name of M.I.T. not be used in
  9. * advertising or publicity pertaining to distribution of the
  10. * software without specific, written prior permission.
  11. * M.I.T. makes no representations about the suitability of
  12. * this software for any purpose. It is provided "as is"
  13. * without express or implied warranty.
  14. */
  15. #include "ares_setup.h"
  16. #ifdef HAVE_NETINET_IN_H
  17. # include <netinet/in.h>
  18. #endif
  19. #ifdef HAVE_NETDB_H
  20. # include <netdb.h>
  21. #endif
  22. #ifdef HAVE_ARPA_INET_H
  23. # include <arpa/inet.h>
  24. #endif
  25. #ifdef HAVE_ARPA_NAMESER_H
  26. # include <arpa/nameser.h>
  27. #else
  28. # include "nameser.h"
  29. #endif
  30. #ifdef HAVE_ARPA_NAMESER_COMPAT_H
  31. # include <arpa/nameser_compat.h>
  32. #endif
  33. #ifdef HAVE_STRINGS_H
  34. # include <strings.h>
  35. #endif
  36. #ifdef HAVE_LIMITS_H
  37. # include <limits.h>
  38. #endif
  39. #include "ares.h"
  40. #include "ares_dns.h"
  41. #include "ares_private.h"
  42. int ares__parse_into_addrinfo2(const unsigned char *abuf,
  43. int alen,
  44. char **question_hostname,
  45. struct ares_addrinfo *ai)
  46. {
  47. unsigned int qdcount, ancount;
  48. int status, i, rr_type, rr_class, rr_len, rr_ttl;
  49. int got_a = 0, got_aaaa = 0, got_cname = 0;
  50. long len;
  51. const unsigned char *aptr;
  52. char *hostname, *rr_name = NULL, *rr_data;
  53. struct ares_addrinfo_cname *cname, *cnames = NULL;
  54. struct ares_addrinfo_node *node, *nodes = NULL;
  55. struct sockaddr_in *sin;
  56. struct sockaddr_in6 *sin6;
  57. *question_hostname = NULL;
  58. /* Give up if abuf doesn't have room for a header. */
  59. if (alen < HFIXEDSZ)
  60. return ARES_EBADRESP;
  61. /* Fetch the question and answer count from the header. */
  62. qdcount = DNS_HEADER_QDCOUNT(abuf);
  63. ancount = DNS_HEADER_ANCOUNT(abuf);
  64. if (qdcount != 1)
  65. return ARES_EBADRESP;
  66. /* Expand the name from the question, and skip past the question. */
  67. aptr = abuf + HFIXEDSZ;
  68. status = ares__expand_name_for_response(aptr, abuf, alen, question_hostname, &len);
  69. if (status != ARES_SUCCESS)
  70. return status;
  71. if (aptr + len + QFIXEDSZ > abuf + alen)
  72. {
  73. return ARES_EBADRESP;
  74. }
  75. hostname = *question_hostname;
  76. aptr += len + QFIXEDSZ;
  77. /* Examine each answer resource record (RR) in turn. */
  78. for (i = 0; i < (int)ancount; i++)
  79. {
  80. /* Decode the RR up to the data field. */
  81. status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len);
  82. if (status != ARES_SUCCESS)
  83. {
  84. rr_name = NULL;
  85. goto failed_stat;
  86. }
  87. aptr += len;
  88. if (aptr + RRFIXEDSZ > abuf + alen)
  89. {
  90. status = ARES_EBADRESP;
  91. goto failed_stat;
  92. }
  93. rr_type = DNS_RR_TYPE(aptr);
  94. rr_class = DNS_RR_CLASS(aptr);
  95. rr_len = DNS_RR_LEN(aptr);
  96. rr_ttl = DNS_RR_TTL(aptr);
  97. aptr += RRFIXEDSZ;
  98. if (aptr + rr_len > abuf + alen)
  99. {
  100. status = ARES_EBADRESP;
  101. goto failed_stat;
  102. }
  103. if (rr_class == C_IN && rr_type == T_A
  104. && rr_len == sizeof(struct in_addr)
  105. && strcasecmp(rr_name, hostname) == 0)
  106. {
  107. got_a = 1;
  108. if (aptr + sizeof(struct in_addr) > abuf + alen)
  109. { /* LCOV_EXCL_START: already checked above */
  110. status = ARES_EBADRESP;
  111. goto failed_stat;
  112. } /* LCOV_EXCL_STOP */
  113. node = ares__append_addrinfo_node(&nodes);
  114. if (!node)
  115. {
  116. status = ARES_ENOMEM;
  117. goto failed_stat;
  118. }
  119. sin = ares_malloc(sizeof(struct sockaddr_in));
  120. if (!sin)
  121. {
  122. status = ARES_ENOMEM;
  123. goto failed_stat;
  124. }
  125. memset(sin, 0, sizeof(struct sockaddr_in));
  126. memcpy(&sin->sin_addr.s_addr, aptr, sizeof(struct in_addr));
  127. sin->sin_family = AF_INET;
  128. node->ai_addr = (struct sockaddr *)sin;
  129. node->ai_family = AF_INET;
  130. node->ai_addrlen = sizeof(struct sockaddr_in);
  131. node->ai_ttl = rr_ttl;
  132. status = ARES_SUCCESS;
  133. }
  134. else if (rr_class == C_IN && rr_type == T_AAAA
  135. && rr_len == sizeof(struct ares_in6_addr)
  136. && strcasecmp(rr_name, hostname) == 0)
  137. {
  138. got_aaaa = 1;
  139. if (aptr + sizeof(struct ares_in6_addr) > abuf + alen)
  140. { /* LCOV_EXCL_START: already checked above */
  141. status = ARES_EBADRESP;
  142. goto failed_stat;
  143. } /* LCOV_EXCL_STOP */
  144. node = ares__append_addrinfo_node(&nodes);
  145. if (!node)
  146. {
  147. status = ARES_ENOMEM;
  148. goto failed_stat;
  149. }
  150. sin6 = ares_malloc(sizeof(struct sockaddr_in6));
  151. if (!sin6)
  152. {
  153. status = ARES_ENOMEM;
  154. goto failed_stat;
  155. }
  156. memset(sin6, 0, sizeof(struct sockaddr_in6));
  157. memcpy(&sin6->sin6_addr.s6_addr, aptr, sizeof(struct ares_in6_addr));
  158. sin6->sin6_family = AF_INET6;
  159. node->ai_addr = (struct sockaddr *)sin6;
  160. node->ai_family = AF_INET6;
  161. node->ai_addrlen = sizeof(struct sockaddr_in6);
  162. node->ai_ttl = rr_ttl;
  163. status = ARES_SUCCESS;
  164. }
  165. if (rr_class == C_IN && rr_type == T_CNAME)
  166. {
  167. got_cname = 1;
  168. status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data,
  169. &len);
  170. if (status != ARES_SUCCESS)
  171. {
  172. goto failed_stat;
  173. }
  174. /* Decode the RR data and replace the hostname with it. */
  175. /* SA: Seems wrong as it introduses order dependency. */
  176. hostname = rr_data;
  177. cname = ares__append_addrinfo_cname(&cnames);
  178. if (!cname)
  179. {
  180. status = ARES_ENOMEM;
  181. ares_free(rr_data);
  182. goto failed_stat;
  183. }
  184. cname->ttl = rr_ttl;
  185. cname->alias = rr_name;
  186. cname->name = rr_data;
  187. }
  188. else
  189. {
  190. ares_free(rr_name);
  191. }
  192. aptr += rr_len;
  193. if (aptr > abuf + alen)
  194. { /* LCOV_EXCL_START: already checked above */
  195. status = ARES_EBADRESP;
  196. goto failed_stat;
  197. } /* LCOV_EXCL_STOP */
  198. }
  199. if (status == ARES_SUCCESS)
  200. {
  201. ares__addrinfo_cat_nodes(&ai->nodes, nodes);
  202. if (got_cname)
  203. {
  204. ares__addrinfo_cat_cnames(&ai->cnames, cnames);
  205. return status;
  206. }
  207. else if (got_a == 0 && got_aaaa == 0)
  208. {
  209. /* the check for naliases to be zero is to make sure CNAME responses
  210. don't get caught here */
  211. status = ARES_ENODATA;
  212. }
  213. }
  214. return status;
  215. failed_stat:
  216. ares_free(rr_name);
  217. ares__freeaddrinfo_cnames(cnames);
  218. ares__freeaddrinfo_nodes(nodes);
  219. return status;
  220. }
  221. int ares__parse_into_addrinfo(const unsigned char *abuf,
  222. int alen,
  223. struct ares_addrinfo *ai)
  224. {
  225. int status;
  226. char *question_hostname;
  227. status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, ai);
  228. ares_free(question_hostname);
  229. return status;
  230. }