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

ares_expand_name.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 
00025 static int name_length(const unsigned char *encoded, const unsigned char *abuf,
00026                        int alen);
00027 
00028 /* Expand an RFC1035-encoded domain name given by encoded.  The
00029  * containing message is given by abuf and alen.  The result given by
00030  * *s, which is set to a NUL-terminated allocated buffer.  *enclen is
00031  * set to the length of the encoded name (not the length of the
00032  * expanded name; the goal is to tell the caller how many bytes to
00033  * move forward to get past the encoded name).
00034  *
00035  * In the simple case, an encoded name is a series of labels, each
00036  * composed of a one-byte length (limited to values between 0 and 63
00037  * inclusive) followed by the label contents.  The name is terminated
00038  * by a zero-length label.
00039  *
00040  * In the more complicated case, a label may be terminated by an
00041  * indirection pointer, specified by two bytes with the high bits of
00042  * the first byte (corresponding to INDIR_MASK) set to 11.  With the
00043  * two high bits of the first byte stripped off, the indirection
00044  * pointer gives an offset from the beginning of the containing
00045  * message with more labels to decode.  Indirection can happen an
00046  * arbitrary number of times, so we have to detect loops.
00047  *
00048  * Since the expanded name uses '.' as a label separator, we use
00049  * backslashes to escape periods or backslashes in the expanded name.
00050  */
00051 
00052 int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
00053                      int alen, char **s, int *enclen)
00054 {
00055   int len, indir = 0;
00056   char *q;
00057   const unsigned char *p;
00058 
00059   len = name_length(encoded, abuf, alen);
00060   if (len == -1)
00061     return ARES_EBADNAME;
00062 
00063   *s = malloc(len + 1);
00064   if (!*s)
00065     return ARES_ENOMEM;
00066   q = *s;
00067 
00068   /* No error-checking necessary; it was all done by name_length(). */
00069   p = encoded;
00070   while (*p)
00071     {
00072       if ((*p & INDIR_MASK) == INDIR_MASK)
00073         {
00074           if (!indir)
00075             {
00076               *enclen = p + 2 - encoded;
00077               indir = 1;
00078             }
00079           p = abuf + ((*p & ~INDIR_MASK) << 8 | *(p + 1));
00080         }
00081       else
00082         {
00083           len = *p;
00084           p++;
00085           while (len--)
00086             {
00087               if (*p == '.' || *p == '\\')
00088                 *q++ = '\\';
00089               *q++ = *p;
00090               p++;
00091             }
00092           *q++ = '.';
00093         }
00094     }
00095   if (!indir)
00096     *enclen = p + 1 - encoded;
00097 
00098   /* Nuke the trailing period if we wrote one. */
00099   if (q > *s)
00100     *(q - 1) = 0;
00101 
00102   return ARES_SUCCESS;
00103 }
00104 
00105 /* Return the length of the expansion of an encoded domain name, or
00106  * -1 if the encoding is invalid.
00107  */
00108 static int name_length(const unsigned char *encoded, const unsigned char *abuf,
00109                        int alen)
00110 {
00111   int n = 0, offset, indir = 0;
00112 
00113   /* Allow the caller to pass us abuf + alen and have us check for it. */
00114   if (encoded == abuf + alen)
00115     return -1;
00116 
00117   while (*encoded)
00118     {
00119       if ((*encoded & INDIR_MASK) == INDIR_MASK)
00120         {
00121           /* Check the offset and go there. */
00122           if (encoded + 1 >= abuf + alen)
00123             return -1;
00124           offset = (*encoded & ~INDIR_MASK) << 8 | *(encoded + 1);
00125           if (offset >= alen)
00126             return -1;
00127           encoded = abuf + offset;
00128 
00129           /* If we've seen more indirects than the message length,
00130            * then there's a loop.
00131            */
00132           if (++indir > alen)
00133             return -1;
00134         }
00135       else
00136         {
00137           offset = *encoded;
00138           if (encoded + offset + 1 >= abuf + alen)
00139             return -1;
00140           encoded++;
00141           while (offset--)
00142             {
00143               n += (*encoded == '.' || *encoded == '\\') ? 2 : 1;
00144               encoded++;
00145             }
00146           n++;
00147         }
00148     }
00149 
00150   /* If there were any labels at all, then the number of dots is one
00151    * less than the number of labels, so subtract one.
00152    */
00153   return (n) ? n - 1 : n;
00154 }

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