Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

ares_mkquery.c

Go to the documentation of this file.
00001 /* Copyright 1998 by the Massachusetts Institute of Technology.
00002  *
00003  * Permission to use, copy, modify, and distribute this
00004  * software and its documentation for any purpose and without
00005  * fee is hereby granted, provided that the above copyright
00006  * notice appear in all copies and that both that copyright
00007  * notice and this permission notice appear in supporting
00008  * documentation, and that the name of M.I.T. not be used in
00009  * advertising or publicity pertaining to distribution of the
00010  * software without specific, written prior permission.
00011  * M.I.T. makes no representations about the suitability of
00012  * this software for any purpose.  It is provided "as is"
00013  * without express or implied warranty.
00014  *
00015  * CHANGELOG: this file has been modified by Sergio Perez Alcañiz <serpeal@disca.upv.es> 
00016  *            Departamento de Informática de Sistemas y Computadores          
00017  *            Universidad Politécnica de Valencia                             
00018  *            Valencia (Spain)    
00019  *            Date: April 2003                                          
00020  *
00021  */
00022 
00023 #include "ares_private.h"
00024 #include "ares_dns.h"
00025 
00026 /* Header format, from RFC 1035:
00027  *                                  1  1  1  1  1  1
00028  *    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
00029  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00030  *  |                      ID                       |
00031  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00032  *  |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
00033  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00034  *  |                    QDCOUNT                    |
00035  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00036  *  |                    ANCOUNT                    |
00037  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00038  *  |                    NSCOUNT                    |
00039  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00040  *  |                    ARCOUNT                    |
00041  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00042  *
00043  * AA, TC, RA, and RCODE are only set in responses.  Brief description
00044  * of the remaining fields:
00045  *      ID      Identifier to match responses with queries
00046  *      QR      Query (0) or response (1)
00047  *      Opcode  For our purposes, always QUERY
00048  *      RD      Recursion desired
00049  *      Z       Reserved (zero)
00050  *      QDCOUNT Number of queries
00051  *      ANCOUNT Number of answers
00052  *      NSCOUNT Number of name server records
00053  *      ARCOUNT Number of additional records
00054  *
00055  * Question format, from RFC 1035:
00056  *                                  1  1  1  1  1  1
00057  *    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
00058  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00059  *  |                                               |
00060  *  /                     QNAME                     /
00061  *  /                                               /
00062  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00063  *  |                     QTYPE                     |
00064  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00065  *  |                     QCLASS                    |
00066  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
00067  *
00068  * The query name is encoded as a series of labels, each represented
00069  * as a one-byte length (maximum 63) followed by the text of the
00070  * label.  The list is terminated by a label of length zero (which can
00071  * be thought of as the root domain).
00072  */
00073 
00074 int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id,
00075                  int rd, unsigned char **buf, int *buflen)
00076 {
00077   int len;
00078   unsigned char *q;
00079   const char *p;
00080 
00081   /* Compute the length of the encoded name so we can check buflen.
00082    * Start counting at 1 for the zero-length label at the end. */
00083   len = 1;
00084   for (p = name; *p; p++)
00085     {
00086       if (*p == '\\' && *(p + 1) != 0)
00087         p++;
00088       len++;
00089     }
00090   /* If there are n periods in the name, there are n + 1 labels, and
00091    * thus n + 1 length fields, unless the name is empty or ends with a
00092    * period.  So add 1 unless name is empty or ends with a period.
00093    */
00094   if (*name && *(p - 1) != '.')
00095     len++;
00096 
00097   *buflen = len + HFIXEDSZ + QFIXEDSZ;
00098   *buf = malloc(*buflen);
00099   if (!*buf)
00100       return ARES_ENOMEM;
00101 
00102   /* Set up the header. */
00103   q = *buf;
00104   memset(q, 0, HFIXEDSZ);
00105   DNS_HEADER_SET_QID(q, id);
00106   DNS_HEADER_SET_OPCODE(q, QUERY);
00107   DNS_HEADER_SET_RD(q, (rd) ? 1 : 0);
00108   DNS_HEADER_SET_QDCOUNT(q, 1);
00109 
00110   /* A name of "." is a screw case for the loop below, so adjust it. */
00111   if (strcmp(name, ".") == 0)
00112     name++;
00113 
00114   /* Start writing out the name after the header. */
00115   q += HFIXEDSZ;
00116   while (*name)
00117     {
00118       if (*name == '.')
00119         return ARES_EBADNAME;
00120 
00121       /* Count the number of bytes in this label. */
00122       len = 0;
00123       for (p = name; *p && *p != '.'; p++)
00124         {
00125           if (*p == '\\' && *(p + 1) != 0)
00126             p++;
00127           len++;
00128         }
00129       if (len > MAXLABEL)
00130         return ARES_EBADNAME;
00131 
00132       /* Encode the length and copy the data. */
00133       *q++ = len;
00134       for (p = name; *p && *p != '.'; p++)
00135         {
00136           if (*p == '\\' && *(p + 1) != 0)
00137             p++;
00138           *q++ = *p;
00139         }
00140 
00141       /* Go to the next label and repeat, unless we hit the end. */
00142       if (!*p)
00143         break;
00144       name = p + 1;
00145     }
00146 
00147   /* Add the zero-length label at the end. */
00148   *q++ = 0;
00149 
00150   /* Finish off the question with the type and class. */
00151   DNS_QUESTION_SET_TYPE(q, type);
00152   DNS_QUESTION_SET_CLASS(q, dnsclass);
00153 
00154   return ARES_SUCCESS;
00155 }

Generated on Wed Jan 14 12:58:55 2004 for RTL-lwIP-0.4 by doxygen 1.3.4