"Fossies" - the Fresh Open Source Software Archive

Member "c-ares-1.17.2/src/lib/ares_create_query.c" (8 Aug 2021, 6139 Bytes) of package /linux/misc/dns/c-ares-1.17.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ares_create_query.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.17.1_vs_1.17.2.

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