integrate changes from bind 4.9 (most of them); continue to use address
[unix-history] / usr / src / lib / libc / net / res_comp.c
index 1fff41a..8dd1f75 100644 (file)
@@ -1,38 +1,63 @@
-/*
+/*-
  * Copyright (c) 1985 Regents of the University of California.
  * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
  */
 
  */
 
-#ifndef lint
-static char sccsid[] = "@(#)res_comp.c 5.4 (Berkeley) %G%";
-#endif not lint
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_comp.c 6.23 (Berkeley) %G%";
+static char rcsid[] = "$Id: res_comp.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $";
+#endif /* LIBC_SCCS and not lint */
 
 
-#include <sys/types.h>
-#include <stdio.h>
-#include <ctype.h>
+#include <sys/param.h>
 #include <arpa/nameser.h>
 #include <arpa/nameser.h>
+#include <netinet/in.h>
+#include <resolv.h>
+#include <stdio.h>
 
 
+static int dn_find();
 
 /*
  * Expand compressed domain name 'comp_dn' to full domain name.
 
 /*
  * Expand compressed domain name 'comp_dn' to full domain name.
- * Expanded names are converted to upper case.
  * 'msg' is a pointer to the begining of the message,
  * 'msg' is a pointer to the begining of the message,
+ * 'eomorig' points to the first location after the message,
  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  * Return size of compressed name or -1 if there was an error.
  */
  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  * Return size of compressed name or -1 if there was an error.
  */
-dn_expand(msg, comp_dn, exp_dn, length)
-       char *msg, *comp_dn, *exp_dn;
+dn_expand(msg, eomorig, comp_dn, exp_dn, length)
+       const u_char *msg, *eomorig, *comp_dn;
+       u_char *exp_dn;
        int length;
 {
        int length;
 {
-       register char *cp, *dn;
+       register u_char *cp, *dn;
        register int n, c;
        register int n, c;
-       char *eom;
-       int len = -1;
+       u_char *eom;
+       int len = -1, checked = 0;
 
        dn = exp_dn;
 
        dn = exp_dn;
-       cp = comp_dn;
-       eom = exp_dn + length - 1;
+       cp = (u_char *)comp_dn;
+       eom = exp_dn + length;
        /*
         * fetch next label in domain name
         */
        /*
         * fetch next label in domain name
         */
@@ -49,23 +74,33 @@ dn_expand(msg, comp_dn, exp_dn, length)
                        }
                        if (dn+n >= eom)
                                return (-1);
                        }
                        if (dn+n >= eom)
                                return (-1);
-                       while (--n >= 0)
-                               if (islower(c = *cp++))
-                                       *dn++ = toupper(c);
-                               else {
-                                       if (c == '.') {
-                                               if (dn+n+1 >= eom)
-                                                       return (-1);
-                                               *dn++ = '\\';
-                                       }
-                                       *dn++ = c;
+                       checked += n + 1;
+                       while (--n >= 0) {
+                               if ((c = *cp++) == '.') {
+                                       if (dn + n + 2 >= eom)
+                                               return (-1);
+                                       *dn++ = '\\';
                                }
                                }
+                               *dn++ = c;
+                               if (cp >= eomorig)      /* out of range */
+                                       return(-1);
+                       }
                        break;
 
                case INDIR_MASK:
                        if (len < 0)
                                len = cp - comp_dn + 1;
                        break;
 
                case INDIR_MASK:
                        if (len < 0)
                                len = cp - comp_dn + 1;
-                       cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+                       cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+                       if (cp < msg || cp >= eomorig)  /* out of range */
+                               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 >= eomorig - msg)
+                               return (-1);
                        break;
 
                default:
                        break;
 
                default:
@@ -91,18 +126,18 @@ dn_expand(msg, comp_dn, exp_dn, length)
  * is NULL, we don't update the list.
  */
 dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  * is NULL, we don't update the list.
  */
 dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
-       char *exp_dn, *comp_dn;
+       const u_char *exp_dn;
+       u_char *comp_dn, **dnptrs, **lastdnptr;
        int length;
        int length;
-       char **dnptrs, **lastdnptr;
 {
 {
-       register char *cp, *dn;
+       register u_char *cp, *dn;
        register int c, l;
        register int c, l;
-       char **cpp, **lpp, *sp, *eob;
-       char *msg;
+       u_char **cpp, **lpp, *sp, *eob;
+       u_char *msg;
 
 
-       dn = exp_dn;
+       dn = (u_char *)exp_dn;
        cp = comp_dn;
        cp = comp_dn;
-       eob = comp_dn + length;
+       eob = cp + length;
        if (dnptrs != NULL) {
                if ((msg = *dnptrs++) != NULL) {
                        for (cpp = dnptrs; *cpp != NULL; cpp++)
        if (dnptrs != NULL) {
                if ((msg = *dnptrs++) != NULL) {
                        for (cpp = dnptrs; *cpp != NULL; cpp++)
@@ -118,7 +153,7 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
                                if (cp+1 >= eob)
                                        return (-1);
                                *cp++ = (l >> 8) | INDIR_MASK;
                                if (cp+1 >= eob)
                                        return (-1);
                                *cp++ = (l >> 8) | INDIR_MASK;
-                               *cp++ = l;
+                               *cp++ = l % 256;
                                return (cp - comp_dn);
                        }
                        /* not found, save it */
                                return (cp - comp_dn);
                        }
                        /* not found, save it */
@@ -137,8 +172,11 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
                                if ((c = *dn++) == '\0')
                                        break;
                        }
                                if ((c = *dn++) == '\0')
                                        break;
                        }
-                       if (cp >= eob)
+                       if (cp >= eob) {
+                               if (msg != NULL)
+                                       *lpp = NULL;
                                return (-1);
                                return (-1);
+                       }
                        *cp++ = c;
                } while ((c = *dn++) != '\0');
                /* catch trailing '.'s but not '..' */
                        *cp++ = c;
                } while ((c = *dn++) != '\0');
                /* catch trailing '.'s but not '..' */
@@ -146,12 +184,18 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
                        cp--;
                        break;
                }
                        cp--;
                        break;
                }
-               if (l <= 0 || l > MAXLABEL)
+               if (l <= 0 || l > MAXLABEL) {
+                       if (msg != NULL)
+                               *lpp = NULL;
                        return (-1);
                        return (-1);
+               }
                *sp = l;
        }
                *sp = l;
        }
-       if (cp >= eob)
+       if (cp >= eob) {
+               if (msg != NULL)
+                       *lpp = NULL;
                return (-1);
                return (-1);
+       }
        *cp++ = '\0';
        return (cp - comp_dn);
 }
        *cp++ = '\0';
        return (cp - comp_dn);
 }
@@ -159,14 +203,14 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
 /*
  * Skip over a compressed domain name. Return the size or -1.
  */
 /*
  * Skip over a compressed domain name. Return the size or -1.
  */
-dn_skip(comp_dn)
-       char *comp_dn;
+__dn_skipname(comp_dn, eom)
+       const u_char *comp_dn, *eom;
 {
 {
-       register char *cp;
+       register u_char *cp;
        register int n;
 
        register int n;
 
-       cp = comp_dn;
-       while (n = *cp++) {
+       cp = (u_char *)comp_dn;
+       while (cp < eom && (n = *cp++)) {
                /*
                 * check for indirection
                 */
                /*
                 * check for indirection
                 */
@@ -187,14 +231,17 @@ dn_skip(comp_dn)
 /*
  * Search for expanded name from a list of previously compressed names.
  * Return the offset from msg if found or -1.
 /*
  * Search for expanded name from a list of previously compressed names.
  * Return the offset from msg if found or -1.
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
  */
  */
+static int
 dn_find(exp_dn, msg, dnptrs, lastdnptr)
 dn_find(exp_dn, msg, dnptrs, lastdnptr)
-       char *exp_dn, *msg;
-       char **dnptrs, **lastdnptr;
+       u_char *exp_dn, *msg;
+       u_char **dnptrs, **lastdnptr;
 {
 {
-       register char *dn, *cp, **cpp;
+       register u_char *dn, *cp, **cpp;
        register int n;
        register int n;
-       char *sp;
+       u_char *sp;
 
        for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
                dn = exp_dn;
 
        for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
                dn = exp_dn;
@@ -206,6 +253,8 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
                        switch (n & INDIR_MASK) {
                        case 0:         /* normal case, n == len */
                                while (--n >= 0) {
                        switch (n & INDIR_MASK) {
                        case 0:         /* normal case, n == len */
                                while (--n >= 0) {
+                                       if (*dn == '.')
+                                               goto next;
                                        if (*dn == '\\')
                                                dn++;
                                        if (*dn++ != *cp++)
                                        if (*dn == '\\')
                                                dn++;
                                        if (*dn++ != *cp++)
@@ -221,7 +270,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
                                return (-1);
 
                        case INDIR_MASK:        /* indirection */
                                return (-1);
 
                        case INDIR_MASK:        /* indirection */
-                               cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+                               cp = msg + (((n & 0x3f) << 8) | *cp);
                        }
                }
                if (*dn == '\0')
                        }
                }
                if (*dn == '\0')
@@ -235,47 +284,46 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
  * Routines to insert/extract short/long's. Must account for byte
  * order and non-alignment problems. This code at least has the
  * advantage of being portable.
  * Routines to insert/extract short/long's. Must account for byte
  * order and non-alignment problems. This code at least has the
  * advantage of being portable.
+ *
+ * used by sendmail.
  */
 
 u_short
  */
 
 u_short
-getshort(msgp)
-       char *msgp;
+_getshort(msgp)
+       register u_char *msgp;
 {
 {
-       register u_char *p = (u_char *) msgp;
+       register u_int16_t u;
 
 
-       return ((*p++ << 8) | *p);
+       GETSHORT(u, msgp);
+       return (u);
 }
 
 }
 
-u_long
-getlong(msgp)
-       char *msgp;
+u_int32_t
+_getlong(msgp)
+       register u_char *msgp;
 {
 {
-       register u_char *p = (u_char *) msgp;
-       register u_long u;
+       register u_int32_t u;
 
 
-       u = *p++; u <<= 8;
-       u |= *p++; u <<= 8;
-       u |= *p++; u <<= 8;
-       return (u | *p);
+       GETLONG(u, msgp);
+       return (u);
 }
 
 }
 
-
-putshort(s, msgp)
-       register u_short s;
-       register char *msgp;
+void
+#if defined(__STDC__) || defined(__cplusplus)
+__putshort(register u_short s, register u_char *msgp)
+#else
+__putshort(s, msgp)
+       register u_int16_t s;
+       register u_char *msgp;
+#endif
 {
 {
-
-       msgp[1] = s;
-       msgp[0] = s >> 8;
+       PUTSHORT(s, msgp);
 }
 
 }
 
-putlong(l, msgp)
-       register u_long l;
-       register char *msgp;
+void
+__putlong(l, msgp)
+       register u_int32_t l;
+       register u_char *msgp;
 {
 {
-
-       msgp[3] = l;
-       msgp[2] = (l >>= 8);
-       msgp[1] = (l >>= 8);
-       msgp[0] = l >> 8;
+       PUTLONG(l, msgp);
 }
 }