Back to index

glibc  2.9
Defines | Functions | Variables
ns_name.c File Reference
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <errno.h>
#include <resolv.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>

Go to the source code of this file.

Defines

#define SPRINTF(x)   ((size_t)sprintf x)
#define NS_TYPE_ELT   0x40 /*%< EDNS0 extended label type */
#define DNS_LABELTYPE_BITSTRING   0x41

Functions

static int special (int)
static int printable (int)
static int dn_find (const u_char *, const u_char *, const u_char *const *, const u_char *const *)
static int encode_bitstring (const char **, const char *, unsigned char **, unsigned char **, unsigned const char *)
static int labellen (const u_char *)
static int decode_bitstring (const unsigned char **, char *, const char *)
int ns_name_ntop (const u_char *src, char *dst, size_t dstsiz)
 libresolv_hidden_def (strong_alias(ns_name_ntop)
 libresolv_hidden_def (ns_name_pton)
int ns_name_unpack (const u_char *msg, const u_char *eom, const u_char *src, u_char *dst, size_t dstsiz)
 libresolv_hidden_def (ns_name_pack)
 libresolv_hidden_def (ns_name_uncompress)
 libresolv_hidden_def (ns_name_compress)
int ns_name_skip (const u_char **ptrptr, const u_char *eom)
 libresolv_hidden_def (ns_name_skip)
static int mklower (int ch)

Variables

static const char rcsid [] = "$BINDId: ns_name.c,v 8.15 2000/03/30 22:53:46 vixie Exp $"
static const char digits [] = "0123456789"
static const char digitvalue [256]

Detailed Description

Definition in file ns_name.c.


Define Documentation

#define DNS_LABELTYPE_BITSTRING   0x41

Definition at line 37 of file ns_name.c.

#define NS_TYPE_ELT   0x40 /*%< EDNS0 extended label type */

Definition at line 36 of file ns_name.c.

#define SPRINTF (   x)    ((size_t)sprintf x)

Definition at line 34 of file ns_name.c.


Function Documentation

static int decode_bitstring ( const unsigned char **  cpp,
char *  dn,
const char *  eom 
) [static]

Definition at line 799 of file ns_name.c.

{
       const unsigned char *cp = *cpp;
       char *beg = dn, tc;
       int b, blen, plen, i;

       if ((blen = (*cp & 0xff)) == 0)
              blen = 256;
       plen = (blen + 3) / 4;
       plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
       if (dn + plen >= eom)
              return(-1);

       cp++;
       i = SPRINTF((dn, "\\[x"));
       if (i < 0)
              return (-1);
       dn += i;
       for (b = blen; b > 7; b -= 8, cp++) {
              i = SPRINTF((dn, "%02x", *cp & 0xff));
              if (i < 0)
                     return (-1);
              dn += i;
       }
       if (b > 4) {
              tc = *cp++;
              i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
              if (i < 0)
                     return (-1);
              dn += i;
       } else if (b > 0) {
              tc = *cp++;
              i = SPRINTF((dn, "%1x",
                            ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
              if (i < 0)
                     return (-1);
              dn += i;
       }
       i = SPRINTF((dn, "/%d]", blen));
       if (i < 0)
              return (-1);
       dn += i;

       *cpp = cp;
       return(dn - beg);
}

Here is the caller graph for this function:

static int dn_find ( const u_char domain,
const u_char msg,
const u_char *const dnptrs,
const u_char *const lastdnptr 
) [static]

Definition at line 741 of file ns_name.c.

{
       const u_char *dn, *cp, *sp;
       const u_char * const *cpp;
       u_int n;

       for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
              sp = *cpp;
              /*
               * terminate search on:
               * root label
               * compression pointer
               * unusable offset
               */
              while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
                     (sp - msg) < 0x4000) {
                     dn = domain;
                     cp = sp;
                     while ((n = *cp++) != 0) {
                            /*
                             * check for indirection
                             */
                            switch (n & NS_CMPRSFLGS) {
                            case 0:              /*%< normal case, n == len */
                                   n = labellen(cp - 1); /*%< XXX */
                                   if (n != *dn++)
                                          goto next;

                                   for ((void)NULL; n > 0; n--)
                                          if (mklower(*dn++) !=
                                              mklower(*cp++))
                                                 goto next;
                                   /* Is next root for both ? */
                                   if (*dn == '\0' && *cp == '\0')
                                          return (sp - msg);
                                   if (*dn)
                                          continue;
                                   goto next;
                            case NS_CMPRSFLGS:   /*%< indirection */
                                   cp = msg + (((n & 0x3f) << 8) | *cp);
                                   break;

                            default:      /*%< illegal type */
                                   __set_errno (EMSGSIZE);
                                   return (-1);
                            }
                     }
  next: ;
                     sp += *sp + 1;
              }
       }
       __set_errno (ENOENT);
       return (-1);
}

Here is the call graph for this function:

static int encode_bitstring ( const char **  bp,
const char *  end,
unsigned char **  labelp,
unsigned char **  dst,
unsigned const char *  eom 
) [static]

Definition at line 847 of file ns_name.c.

{
       int afterslash = 0;
       const char *cp = *bp;
       unsigned char *tp;
       char c;
       const char *beg_blen;
       char *end_blen = NULL;
       int value = 0, count = 0, tbcount = 0, blen = 0;

       beg_blen = end_blen = NULL;

       /* a bitstring must contain at least 2 characters */
       if (end - cp < 2)
              return(EINVAL);

       /* XXX: currently, only hex strings are supported */
       if (*cp++ != 'x')
              return(EINVAL);
       if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */
              return(EINVAL);

       for (tp = *dst + 1; cp < end && tp < eom; cp++) {
              switch((c = *cp)) {
              case ']':     /*%< end of the bitstring */
                     if (afterslash) {
                            if (beg_blen == NULL)
                                   return(EINVAL);
                            blen = (int)strtol(beg_blen, &end_blen, 10);
                            if (*end_blen != ']')
                                   return(EINVAL);
                     }
                     if (count)
                            *tp++ = ((value << 4) & 0xff);
                     cp++;  /*%< skip ']' */
                     goto done;
              case '/':
                     afterslash = 1;
                     break;
              default:
                     if (afterslash) {
                            if (!isdigit(c&0xff))
                                   return(EINVAL);
                            if (beg_blen == NULL) {

                                   if (c == '0') {
                                          /* blen never begings with 0 */
                                          return(EINVAL);
                                   }
                                   beg_blen = cp;
                            }
                     } else {
                            if (!isxdigit(c&0xff))
                                   return(EINVAL);
                            value <<= 4;
                            value += digitvalue[(int)c];
                            count += 4;
                            tbcount += 4;
                            if (tbcount > 256)
                                   return(EINVAL);
                            if (count == 8) {
                                   *tp++ = value;
                                   count = 0;
                            }
                     }
                     break;
              }
       }
  done:
       if (cp >= end || tp >= eom)
              return(EMSGSIZE);

       /*
        * bit length validation:
        * If a <length> is present, the number of digits in the <bit-data>
        * MUST be just sufficient to contain the number of bits specified
        * by the <length>. If there are insignificant bits in a final
        * hexadecimal or octal digit, they MUST be zero.
        * RFC2673, Section 3.2.
        */
       if (blen > 0) {
              int traillen;

              if (((blen + 3) & ~3) != tbcount)
                     return(EINVAL);
              traillen = tbcount - blen; /*%< between 0 and 3 */
              if (((value << (8 - traillen)) & 0xff) != 0)
                     return(EINVAL);
       }
       else
              blen = tbcount;
       if (blen == 256)
              blen = 0;

       /* encode the type and the significant bit fields */
       **labelp = DNS_LABELTYPE_BITSTRING;
       **dst = blen;

       *bp = cp;
       *dst = tp;

       return(0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int labellen ( const u_char lp) [static]

Definition at line 953 of file ns_name.c.

{
       int bitlen;
       u_char l = *lp;

       if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
              /* should be avoided by the caller */
              return(-1);
       }

       if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
              if (l == DNS_LABELTYPE_BITSTRING) {
                     if ((bitlen = *(lp + 1)) == 0)
                            bitlen = 256;
                     return((bitlen + 7 ) / 8 + 1);
              }
              return(-1);   /*%< unknwon ELT */
       }
       return(l);
}

Here is the caller graph for this function:

libresolv_hidden_def ( strong_alias ns_name_ntop)

Definition at line 179 of file ns_name.c.

{
       u_char *label, *bp, *eom;
       int c, n, escaped, e = 0;
       char *cp;

       escaped = 0;
       bp = dst;
       eom = dst + dstsiz;
       label = bp++;

       while ((c = *src++) != 0) {
              if (escaped) {
                     if (c == '[') { /*%< start a bit string label */
                            if ((cp = strchr(src, ']')) == NULL) {
                                   __set_errno (EINVAL);
                                   return(-1);
                            }
                            if ((e = encode_bitstring(&src, cp + 2,
                                                   &label, &bp, eom))
                                != 0) {
                                   __set_errno (e);
                                   return(-1);
                            }
                            escaped = 0;
                            label = bp++;
                            if ((c = *src++) == 0)
                                   goto done;
                            else if (c != '.') {
                                   __set_errno (EINVAL);
                                   return(-1);
                            }
                            continue;
                     }
                     else if ((cp = strchr(digits, c)) != NULL) {
                            n = (cp - digits) * 100;
                            if ((c = *src++) == 0 ||
                                (cp = strchr(digits, c)) == NULL) {
                                   __set_errno (EMSGSIZE);
                                   return (-1);
                            }
                            n += (cp - digits) * 10;
                            if ((c = *src++) == 0 ||
                                (cp = strchr(digits, c)) == NULL) {
                                   __set_errno (EMSGSIZE);
                                   return (-1);
                            }
                            n += (cp - digits);
                            if (n > 255) {
                                   __set_errno (EMSGSIZE);
                                   return (-1);
                            }
                            c = n;
                     }
                     escaped = 0;
              } else if (c == '\\') {
                     escaped = 1;
                     continue;
              } else if (c == '.') {
                     c = (bp - label - 1);
                     if ((c & NS_CMPRSFLGS) != 0) {     /*%< Label too big. */
                            __set_errno (EMSGSIZE);
                            return (-1);
                     }
                     if (label >= eom) {
                            __set_errno (EMSGSIZE);
                            return (-1);
                     }
                     *label = c;
                     /* Fully qualified ? */
                     if (*src == '\0') {
                            if (c != 0) {
                                   if (bp >= eom) {
                                          __set_errno (EMSGSIZE);
                                          return (-1);
                                   }
                                   *bp++ = '\0';
                            }
                            if ((bp - dst) > MAXCDNAME) {
                                   __set_errno (EMSGSIZE);
                                   return (-1);
                            }
                            return (1);
                     }
                     if (c == 0 || *src == '.') {
                            __set_errno (EMSGSIZE);
                            return (-1);
                     }
                     label = bp++;
                     continue;
              }
              if (bp >= eom) {
                     __set_errno (EMSGSIZE);
                     return (-1);
              }
              *bp++ = (u_char)c;
       }
       c = (bp - label - 1);
       if ((c & NS_CMPRSFLGS) != 0) {            /*%< Label too big. */
              __set_errno (EMSGSIZE);
              return (-1);
       }
  done:
       if (label >= eom) {
              __set_errno (EMSGSIZE);
              return (-1);
       }
       *label = c;
       if (c != 0) {
              if (bp >= eom) {
                     __set_errno (EMSGSIZE);
                     return (-1);
              }
              *bp++ = 0;
       }
       if ((bp - dst) > MAXCDNAME) {      /*%< src too big */
              __set_errno (EMSGSIZE);
              return (-1);
       }
       return (0);
}

Here is the call graph for this function:

Definition at line 317 of file ns_name.c.

{
       const u_char *cp;
       u_char *dn, *eom;
       u_char c;
       u_int n;
       int l;

       cp = src;
       dn = dst;
       eom = dst + dstsiz;

       if (dn >= eom) {
              __set_errno (EMSGSIZE);
              return (-1);
       }
       while ((n = *cp++) != 0) {
              if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
                     /* Some kind of compression pointer. */
                     __set_errno (EMSGSIZE);
                     return (-1);
              }
              *dn++ = n;
              if ((l = labellen(cp - 1)) < 0) {
                     __set_errno (EMSGSIZE);
                     return (-1);
              }
              if (dn + l >= eom) {
                     __set_errno (EMSGSIZE);
                     return (-1);
              }
              for ((void)NULL; l > 0; l--) {
                     c = *cp++;
                     if (isupper(c))
                            *dn++ = tolower(c);
                     else
                            *dn++ = c;
              }
       }
       *dn++ = '\0';
       return (dn - dst);
}

Here is the call graph for this function:

Definition at line 565 of file ns_name.c.

{
       u_char tmp[NS_MAXCDNAME];
       int n;

       if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
              return (-1);
       if (ns_name_ntop(tmp, dst, dstsiz) == -1)
              return (-1);
       return (n);
}

Here is the call graph for this function:

Definition at line 589 of file ns_name.c.

{
       u_char tmp[NS_MAXCDNAME];

       if (ns_name_pton(src, tmp, sizeof tmp) == -1)
              return (-1);
       return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
}

Here is the call graph for this function:

Definition at line 616 of file ns_name.c.

{
       while (dnptrs < lastdnptr && *dnptrs != NULL) {
              if (*dnptrs >= src) {
                     *dnptrs = NULL;
                     break;
              }
              dnptrs++;
       }
}

Definition at line 678 of file ns_name.c.

                {
       switch (ch) {
       case 0x22: /*%< '"' */
       case 0x2E: /*%< '.' */
       case 0x3B: /*%< ';' */
       case 0x5C: /*%< '\\' */
       case 0x28: /*%< '(' */
       case 0x29: /*%< ')' */
       /* Special modifiers in zone files. */
       case 0x40: /*%< '@' */
       case 0x24: /*%< '$' */
              return (1);
       default:
              return (0);
       }
}
static int mklower ( int  ch) [static]

Definition at line 724 of file ns_name.c.

                {
       if (ch >= 0x41 && ch <= 0x5A)
              return (ch + 0x20);
       return (ch);
}

Here is the caller graph for this function:

int ns_name_ntop ( const u_char src,
char *  dst,
size_t  dstsiz 
)

Definition at line 89 of file ns_name.c.

{
       const u_char *cp;
       char *dn, *eom;
       u_char c;
       u_int n;
       int l;

       cp = src;
       dn = dst;
       eom = dst + dstsiz;

       while ((n = *cp++) != 0) {
              if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
                     /* Some kind of compression pointer. */
                     __set_errno (EMSGSIZE);
                     return (-1);
              }
              if (dn != dst) {
                     if (dn >= eom) {
                            __set_errno (EMSGSIZE);
                            return (-1);
                     }
                     *dn++ = '.';
              }
              if ((l = labellen(cp - 1)) < 0) {
                     __set_errno (EMSGSIZE);
                     return(-1);
              }
              if (dn + l >= eom) {
                     __set_errno (EMSGSIZE);
                     return (-1);
              }
              if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
                     int m;

                     if (n != DNS_LABELTYPE_BITSTRING) {
                            /* XXX: labellen should reject this case */
                            __set_errno (EINVAL);
                            return(-1);
                     }
                     if ((m = decode_bitstring(&cp, dn, eom)) < 0)
                     {
                            __set_errno (EMSGSIZE);
                            return(-1);
                     }
                     dn += m;
                     continue;
              }
              for ((void)NULL; l > 0; l--) {
                     c = *cp++;
                     if (special(c)) {
                            if (dn + 1 >= eom) {
                                   __set_errno (EMSGSIZE);
                                   return (-1);
                            }
                            *dn++ = '\\';
                            *dn++ = (char)c;
                     } else if (!printable(c)) {
                            if (dn + 3 >= eom) {
                                   __set_errno (EMSGSIZE);
                                   return (-1);
                            }
                            *dn++ = '\\';
                            *dn++ = digits[c / 100];
                            *dn++ = digits[(c % 100) / 10];
                            *dn++ = digits[c % 10];
                     } else {
                            if (dn >= eom) {
                                   __set_errno (EMSGSIZE);
                                   return (-1);
                            }
                            *dn++ = (char)c;
                     }
              }
       }
       if (dn == dst) {
              if (dn >= eom) {
                     __set_errno (EMSGSIZE);
                     return (-1);
              }
              *dn++ = '.';
       }
       if (dn >= eom) {
              __set_errno (EMSGSIZE);
              return (-1);
       }
       *dn++ = '\0';
       return (dn - dst);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ns_name_skip ( const u_char **  ptrptr,
const u_char eom 
)

Definition at line 642 of file ns_name.c.

{
       const u_char *cp;
       u_int n;
       int l;

       cp = *ptrptr;
       while (cp < eom && (n = *cp++) != 0) {
              /* Check for indirection. */
              switch (n & NS_CMPRSFLGS) {
              case 0:                     /*%< normal case, n == len */
                     cp += n;
                     continue;
              case NS_TYPE_ELT: /*%< EDNS0 extended label */
                     if ((l = labellen(cp - 1)) < 0) {
                            __set_errno (EMSGSIZE);
                            return(-1);
                     }
                     cp += l;
                     continue;
              case NS_CMPRSFLGS:   /*%< indirection */
                     cp++;
                     break;
              default:             /*%< illegal type */
                     __set_errno (EMSGSIZE);
                     return (-1);
              }
              break;
       }
       if (cp > eom) {
              __set_errno (EMSGSIZE);
              return (-1);
       }
       *ptrptr = cp;
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ns_name_unpack ( const u_char msg,
const u_char eom,
const u_char src,
u_char dst,
size_t  dstsiz 
)

Definition at line 380 of file ns_name.c.

{
       const u_char *srcp, *dstlim;
       u_char *dstp;
       int n, len, checked, l;

       len = -1;
       checked = 0;
       dstp = dst;
       srcp = src;
       dstlim = dst + dstsiz;
       if (srcp < msg || srcp >= eom) {
              __set_errno (EMSGSIZE);
              return (-1);
       }
       /* Fetch next label in domain name. */
       while ((n = *srcp++) != 0) {
              /* Check for indirection. */
              switch (n & NS_CMPRSFLGS) {
              case 0:
              case NS_TYPE_ELT:
                     /* Limit checks. */
                     if ((l = labellen(srcp - 1)) < 0) {
                            __set_errno (EMSGSIZE);
                            return(-1);
                     }
                     if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
                            __set_errno (EMSGSIZE);
                            return (-1);
                     }
                     checked += l + 1;
                     *dstp++ = n;
                     memcpy(dstp, srcp, l);
                     dstp += l;
                     srcp += l;
                     break;

              case NS_CMPRSFLGS:
                     if (srcp >= eom) {
                            __set_errno (EMSGSIZE);
                            return (-1);
                     }
                     if (len < 0)
                            len = srcp - src + 1;
                     srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
                     if (srcp < msg || srcp >= eom) {  /*%< Out of range. */
                            __set_errno (EMSGSIZE);
                            return (-1);
                     }
                     checked += 2;
                     /*
                      * Check for loops in the compressed name;
                      * if we've looked at the whole message,
                      * there must be a loop.
                      */
                     if (checked >= eom - msg) {
                            __set_errno (EMSGSIZE);
                            return (-1);
                     }
                     break;

              default:
                     __set_errno (EMSGSIZE);
                     return (-1);                /*%< flag error */
              }
       }
       *dstp = '\0';
       if (len < 0)
              len = srcp - src;
       return (len);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int printable ( int  ch) [static]

Definition at line 715 of file ns_name.c.

                  {
       return (ch > 0x20 && ch < 0x7f);
}

Here is the caller graph for this function:

static int special ( int  ) [static]

Here is the caller graph for this function:


Variable Documentation

const char digits[] = "0123456789" [static]

Definition at line 41 of file ns_name.c.

const char digitvalue[256] [static]
Initial value:
 {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, 
       -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
       -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
}

Definition at line 43 of file ns_name.c.

const char rcsid[] = "$BINDId: ns_name.c,v 8.15 2000/03/30 22:53:46 vixie Exp $" [static]

Definition at line 19 of file ns_name.c.