ares_create_query.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /* Copyright 1998 by the Massachusetts Institute of Technology.
  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_ARPA_NAMESER_H
  20. # include <arpa/nameser.h>
  21. #else
  22. # include "nameser.h"
  23. #endif
  24. #ifdef HAVE_ARPA_NAMESER_COMPAT_H
  25. # include <arpa/nameser_compat.h>
  26. #endif
  27. #include "ares.h"
  28. #include "ares_dns.h"
  29. #include "ares_private.h"
  30. #ifndef T_OPT
  31. # define T_OPT 41 /* EDNS0 option (meta-RR) */
  32. #endif
  33. /* Header format, from RFC 1035:
  34. * 1 1 1 1 1 1
  35. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  36. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  37. * | ID |
  38. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  39. * |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
  40. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  41. * | QDCOUNT |
  42. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  43. * | ANCOUNT |
  44. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  45. * | NSCOUNT |
  46. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  47. * | ARCOUNT |
  48. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  49. *
  50. * AA, TC, RA, and RCODE are only set in responses. Brief description
  51. * of the remaining fields:
  52. * ID Identifier to match responses with queries
  53. * QR Query (0) or response (1)
  54. * Opcode For our purposes, always QUERY
  55. * RD Recursion desired
  56. * Z Reserved (zero)
  57. * QDCOUNT Number of queries
  58. * ANCOUNT Number of answers
  59. * NSCOUNT Number of name server records
  60. * ARCOUNT Number of additional records
  61. *
  62. * Question format, from RFC 1035:
  63. * 1 1 1 1 1 1
  64. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  65. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  66. * | |
  67. * / QNAME /
  68. * / /
  69. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  70. * | QTYPE |
  71. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  72. * | QCLASS |
  73. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  74. *
  75. * The query name is encoded as a series of labels, each represented
  76. * as a one-byte length (maximum 63) followed by the text of the
  77. * label. The list is terminated by a label of length zero (which can
  78. * be thought of as the root domain).
  79. */
  80. int ares_create_query(const char *name, int dnsclass, int type,
  81. unsigned short id, int rd, unsigned char **bufp,
  82. int *buflenp, int max_udp_size)
  83. {
  84. size_t len;
  85. unsigned char *q;
  86. const char *p;
  87. size_t buflen;
  88. unsigned char *buf;
  89. /* Set our results early, in case we bail out early with an error. */
  90. *buflenp = 0;
  91. *bufp = NULL;
  92. /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */
  93. if (ares__is_onion_domain(name))
  94. return ARES_ENOTFOUND;
  95. /* Allocate a memory area for the maximum size this packet might need. +2
  96. * is for the length byte and zero termination if no dots or ecscaping is
  97. * used.
  98. */
  99. len = strlen(name) + 2 + HFIXEDSZ + QFIXEDSZ +
  100. (max_udp_size ? EDNSFIXEDSZ : 0);
  101. buf = ares_malloc(len);
  102. if (!buf)
  103. return ARES_ENOMEM;
  104. /* Set up the header. */
  105. q = buf;
  106. memset(q, 0, HFIXEDSZ);
  107. DNS_HEADER_SET_QID(q, id);
  108. DNS_HEADER_SET_OPCODE(q, QUERY);
  109. if (rd) {
  110. DNS_HEADER_SET_RD(q, 1);
  111. }
  112. else {
  113. DNS_HEADER_SET_RD(q, 0);
  114. }
  115. DNS_HEADER_SET_QDCOUNT(q, 1);
  116. if (max_udp_size) {
  117. DNS_HEADER_SET_ARCOUNT(q, 1);
  118. }
  119. /* A name of "." is a screw case for the loop below, so adjust it. */
  120. if (strcmp(name, ".") == 0)
  121. name++;
  122. /* Start writing out the name after the header. */
  123. q += HFIXEDSZ;
  124. while (*name)
  125. {
  126. if (*name == '.') {
  127. ares_free (buf);
  128. return ARES_EBADNAME;
  129. }
  130. /* Count the number of bytes in this label. */
  131. len = 0;
  132. for (p = name; *p && *p != '.'; p++)
  133. {
  134. if (*p == '\\' && *(p + 1) != 0)
  135. p++;
  136. len++;
  137. }
  138. if (len > MAXLABEL) {
  139. ares_free (buf);
  140. return ARES_EBADNAME;
  141. }
  142. /* Encode the length and copy the data. */
  143. *q++ = (unsigned char)len;
  144. for (p = name; *p && *p != '.'; p++)
  145. {
  146. if (*p == '\\' && *(p + 1) != 0)
  147. p++;
  148. *q++ = *p;
  149. }
  150. /* Go to the next label and repeat, unless we hit the end. */
  151. if (!*p)
  152. break;
  153. name = p + 1;
  154. }
  155. /* Add the zero-length label at the end. */
  156. *q++ = 0;
  157. /* Finish off the question with the type and class. */
  158. DNS_QUESTION_SET_TYPE(q, type);
  159. DNS_QUESTION_SET_CLASS(q, dnsclass);
  160. q += QFIXEDSZ;
  161. if (max_udp_size)
  162. {
  163. memset(q, 0, EDNSFIXEDSZ);
  164. q++;
  165. DNS_RR_SET_TYPE(q, T_OPT);
  166. DNS_RR_SET_CLASS(q, max_udp_size);
  167. q += (EDNSFIXEDSZ-1);
  168. }
  169. buflen = (q - buf);
  170. /* Reject names that are longer than the maximum of 255 bytes that's
  171. * specified in RFC 1035 ("To simplify implementations, the total length of
  172. * a domain name (i.e., label octets and label length octets) is restricted
  173. * to 255 octets or less."). */
  174. if (buflen > (size_t)(MAXCDNAME + HFIXEDSZ + QFIXEDSZ +
  175. (max_udp_size ? EDNSFIXEDSZ : 0))) {
  176. ares_free (buf);
  177. return ARES_EBADNAME;
  178. }
  179. /* we know this fits in an int at this point */
  180. *buflenp = (int) buflen;
  181. *bufp = buf;
  182. return ARES_SUCCESS;
  183. }