ares_parse_naptr_reply.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* Copyright 1998 by the Massachusetts Institute of Technology.
  2. * Copyright (C) 2009 by Jakub Hrozek <jhrozek@redhat.com>
  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 "ares_setup.h"
  17. #ifdef HAVE_NETINET_IN_H
  18. # include <netinet/in.h>
  19. #endif
  20. #ifdef HAVE_NETDB_H
  21. # include <netdb.h>
  22. #endif
  23. #ifdef HAVE_ARPA_INET_H
  24. # include <arpa/inet.h>
  25. #endif
  26. #ifdef HAVE_ARPA_NAMESER_H
  27. # include <arpa/nameser.h>
  28. #else
  29. # include "nameser.h"
  30. #endif
  31. #ifdef HAVE_ARPA_NAMESER_COMPAT_H
  32. # include <arpa/nameser_compat.h>
  33. #endif
  34. #include "ares.h"
  35. #include "ares_dns.h"
  36. #include "ares_data.h"
  37. #include "ares_private.h"
  38. /* AIX portability check */
  39. #ifndef T_NAPTR
  40. #define T_NAPTR 35 /* naming authority pointer */
  41. #endif
  42. int
  43. ares_parse_naptr_reply (const unsigned char *abuf, int alen,
  44. struct ares_naptr_reply **naptr_out)
  45. {
  46. unsigned int qdcount, ancount, i;
  47. const unsigned char *aptr, *vptr;
  48. int status, rr_type, rr_class, rr_len, rr_ttl;
  49. long len;
  50. char *hostname = NULL, *rr_name = NULL;
  51. struct ares_naptr_reply *naptr_head = NULL;
  52. struct ares_naptr_reply *naptr_last = NULL;
  53. struct ares_naptr_reply *naptr_curr;
  54. /* Set *naptr_out to NULL for all failure cases. */
  55. *naptr_out = NULL;
  56. /* Give up if abuf doesn't have room for a header. */
  57. if (alen < HFIXEDSZ)
  58. return ARES_EBADRESP;
  59. /* Fetch the question and answer count from the header. */
  60. qdcount = DNS_HEADER_QDCOUNT (abuf);
  61. ancount = DNS_HEADER_ANCOUNT (abuf);
  62. if (qdcount != 1)
  63. return ARES_EBADRESP;
  64. if (ancount == 0)
  65. return ARES_ENODATA;
  66. /* Expand the name from the question, and skip past the question. */
  67. aptr = abuf + HFIXEDSZ;
  68. status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
  69. if (status != ARES_SUCCESS)
  70. return status;
  71. if (aptr + len + QFIXEDSZ > abuf + alen)
  72. {
  73. ares_free (hostname);
  74. return ARES_EBADRESP;
  75. }
  76. aptr += len + QFIXEDSZ;
  77. /* Examine each answer resource record (RR) in turn. */
  78. for (i = 0; i < ancount; i++)
  79. {
  80. /* Decode the RR up to the data field. */
  81. status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
  82. if (status != ARES_SUCCESS)
  83. {
  84. break;
  85. }
  86. aptr += len;
  87. if (aptr + RRFIXEDSZ > abuf + alen)
  88. {
  89. status = ARES_EBADRESP;
  90. break;
  91. }
  92. rr_type = DNS_RR_TYPE (aptr);
  93. rr_class = DNS_RR_CLASS (aptr);
  94. rr_len = DNS_RR_LEN (aptr);
  95. rr_ttl = DNS_RR_TTL (aptr);
  96. aptr += RRFIXEDSZ;
  97. if (aptr + rr_len > abuf + alen)
  98. {
  99. status = ARES_EBADRESP;
  100. break;
  101. }
  102. /* Check if we are really looking at a NAPTR record */
  103. if (rr_class == C_IN && rr_type == T_NAPTR)
  104. {
  105. /* parse the NAPTR record itself */
  106. /* RR must contain at least 7 bytes = 2 x int16 + 3 x name */
  107. if (rr_len < 7)
  108. {
  109. status = ARES_EBADRESP;
  110. break;
  111. }
  112. /* Allocate storage for this NAPTR answer appending it to the list */
  113. naptr_curr = ares_malloc_data(ARES_DATATYPE_NAPTR_REPLY);
  114. if (!naptr_curr)
  115. {
  116. status = ARES_ENOMEM;
  117. break;
  118. }
  119. if (naptr_last)
  120. {
  121. naptr_last->next = naptr_curr;
  122. }
  123. else
  124. {
  125. naptr_head = naptr_curr;
  126. }
  127. naptr_last = naptr_curr;
  128. naptr_curr->ttl = rr_ttl;
  129. vptr = aptr;
  130. naptr_curr->order = DNS__16BIT(vptr);
  131. vptr += sizeof(unsigned short);
  132. naptr_curr->preference = DNS__16BIT(vptr);
  133. vptr += sizeof(unsigned short);
  134. status = ares_expand_string(vptr, abuf, alen, &naptr_curr->flags, &len);
  135. if (status != ARES_SUCCESS)
  136. break;
  137. vptr += len;
  138. status = ares_expand_string(vptr, abuf, alen, &naptr_curr->service, &len);
  139. if (status != ARES_SUCCESS)
  140. break;
  141. vptr += len;
  142. status = ares_expand_string(vptr, abuf, alen, &naptr_curr->regexp, &len);
  143. if (status != ARES_SUCCESS)
  144. break;
  145. vptr += len;
  146. status = ares_expand_name(vptr, abuf, alen, &naptr_curr->replacement, &len);
  147. if (status != ARES_SUCCESS)
  148. break;
  149. }
  150. /* Don't lose memory in the next iteration */
  151. ares_free (rr_name);
  152. rr_name = NULL;
  153. /* Move on to the next record */
  154. aptr += rr_len;
  155. }
  156. if (hostname)
  157. ares_free (hostname);
  158. if (rr_name)
  159. ares_free (rr_name);
  160. /* clean up on error */
  161. if (status != ARES_SUCCESS)
  162. {
  163. if (naptr_head)
  164. ares_free_data (naptr_head);
  165. return status;
  166. }
  167. /* everything looks fine, return the data */
  168. *naptr_out = naptr_head;
  169. return ARES_SUCCESS;
  170. }