home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ixemul-45.0-src.tgz / tar.out / contrib / ixemul / net / res_comp.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  9KB  |  368 lines

  1. /*    $NetBSD: res_comp.c,v 1.6 1995/02/25 06:20:55 cgd Exp $    */
  2.  
  3. /*-
  4.  * Copyright (c) 1985, 1993
  5.  *    The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 3. All advertising materials mentioning features or use of this software
  16.  *    must display the following acknowledgement:
  17.  *    This product includes software developed by the University of
  18.  *    California, Berkeley and its contributors.
  19.  * 4. Neither the name of the University nor the names of its contributors
  20.  *    may be used to endorse or promote products derived from this software
  21.  *    without specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  * -
  35.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  36.  * 
  37.  * Permission to use, copy, modify, and distribute this software for any
  38.  * purpose with or without fee is hereby granted, provided that the above
  39.  * copyright notice and this permission notice appear in all copies, and that
  40.  * the name of Digital Equipment Corporation not be used in advertising or
  41.  * publicity pertaining to distribution of the document or software without
  42.  * specific, written prior permission.
  43.  * 
  44.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  45.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  46.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  47.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  48.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  49.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  50.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  51.  * SOFTWARE.
  52.  * -
  53.  * --Copyright--
  54.  */
  55.  
  56. #if defined(LIBC_SCCS) && !defined(lint)
  57. #if 0
  58. static char sccsid[] = "@(#)res_comp.c    8.1 (Berkeley) 6/4/93";
  59. static char rcsid[] = "$Id: res_comp.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel ";
  60. #else
  61. static char rcsid[] = "$NetBSD: res_comp.c,v 1.6 1995/02/25 06:20:55 cgd Exp $";
  62. #endif
  63. #endif /* LIBC_SCCS and not lint */
  64.  
  65. #include <sys/param.h>
  66. #include <arpa/nameser.h>
  67. #include <netinet/in.h>
  68. #include <resolv.h>
  69. #include <stdio.h>
  70.  
  71. static int dn_find();
  72.  
  73. /*
  74.  * Expand compressed domain name 'comp_dn' to full domain name.
  75.  * 'msg' is a pointer to the begining of the message,
  76.  * 'eomorig' points to the first location after the message,
  77.  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  78.  * Return size of compressed name or -1 if there was an error.
  79.  */
  80. int
  81. dn_expand(msg, eomorig, comp_dn, exp_dn, length)
  82.     const u_char *msg, *eomorig, *comp_dn;
  83.     u_char *exp_dn;
  84.     int length;
  85. {
  86.     register u_char *cp, *dn;
  87.     register int n, c;
  88.     u_char *eom;
  89.     int len = -1, checked = 0;
  90.  
  91.     dn = exp_dn;
  92.     cp = (u_char *)comp_dn;
  93.     eom = exp_dn + length;
  94.     /*
  95.      * fetch next label in domain name
  96.      */
  97.     while ((n = *cp++)) {
  98.         /*
  99.          * Check for indirection
  100.          */
  101.         switch (n & INDIR_MASK) {
  102.         case 0:
  103.             if (dn != exp_dn) {
  104.                 if (dn >= eom)
  105.                     return (-1);
  106.                 *dn++ = '.';
  107.             }
  108.             if (dn+n >= eom)
  109.                 return (-1);
  110.             checked += n + 1;
  111.             while (--n >= 0) {
  112.                 if ((c = *cp++) == '.') {
  113.                     if (dn + n + 2 >= eom)
  114.                         return (-1);
  115.                     *dn++ = '\\';
  116.                 }
  117.                 *dn++ = c;
  118.                 if (cp >= eomorig)    /* out of range */
  119.                     return(-1);
  120.             }
  121.             break;
  122.  
  123.         case INDIR_MASK:
  124.             if (len < 0)
  125.                 len = cp - comp_dn + 1;
  126.             cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  127.             if (cp < msg || cp >= eomorig)    /* out of range */
  128.                 return(-1);
  129.             checked += 2;
  130.             /*
  131.              * Check for loops in the compressed name;
  132.              * if we've looked at the whole message,
  133.              * there must be a loop.
  134.              */
  135.             if (checked >= eomorig - msg)
  136.                 return (-1);
  137.             break;
  138.  
  139.         default:
  140.             return (-1);            /* flag error */
  141.         }
  142.     }
  143.     *dn = '\0';
  144.     if (len < 0)
  145.         len = cp - comp_dn;
  146.     return (len);
  147. }
  148.  
  149. /*
  150.  * Compress domain name 'exp_dn' into 'comp_dn'.
  151.  * Return the size of the compressed name or -1.
  152.  * 'length' is the size of the array pointed to by 'comp_dn'.
  153.  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  154.  * is a pointer to the beginning of the message. The list ends with NULL.
  155.  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  156.  * by 'dnptrs'. Side effect is to update the list of pointers for
  157.  * labels inserted into the message as we compress the name.
  158.  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  159.  * is NULL, we don't update the list.
  160.  */
  161. int
  162. dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  163.     const u_char *exp_dn;
  164.     u_char *comp_dn, **dnptrs, **lastdnptr;
  165.     int length;
  166. {
  167.     register u_char *cp, *dn;
  168.     register int c, l;
  169.     u_char **cpp = NULL, **lpp = NULL, *sp, *eob;
  170.     u_char *msg;
  171.  
  172.     dn = (u_char *)exp_dn;
  173.     cp = comp_dn;
  174.     eob = cp + length;
  175.     if (dnptrs != NULL) {
  176.         if ((msg = *dnptrs++) != NULL) {
  177.             for (cpp = dnptrs; *cpp != NULL; cpp++)
  178.                 ;
  179.             lpp = cpp;    /* end of list to search */
  180.         }
  181.     } else
  182.         msg = NULL;
  183.     for (c = *dn++; c != '\0'; ) {
  184.         /* look to see if we can use pointers */
  185.         if (msg != NULL) {
  186.             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
  187.                 if (cp+1 >= eob)
  188.                     return (-1);
  189.                 *cp++ = (l >> 8) | INDIR_MASK;
  190.                 *cp++ = l % 256;
  191.                 return (cp - comp_dn);
  192.             }
  193.             /* not found, save it */
  194.             if (lastdnptr != NULL && cpp < lastdnptr-1) {
  195.                 *cpp++ = cp;
  196.                 *cpp = NULL;
  197.             }
  198.         }
  199.         sp = cp++;    /* save ptr to length byte */
  200.         do {
  201.             if (c == '.') {
  202.                 c = *dn++;
  203.                 break;
  204.             }
  205.             if (c == '\\') {
  206.                 if ((c = *dn++) == '\0')
  207.                     break;
  208.             }
  209.             if (cp >= eob) {
  210.                 if (msg != NULL)
  211.                     *lpp = NULL;
  212.                 return (-1);
  213.             }
  214.             *cp++ = c;
  215.         } while ((c = *dn++) != '\0');
  216.         /* catch trailing '.'s but not '..' */
  217.         if ((l = cp - sp - 1) == 0 && c == '\0') {
  218.             cp--;
  219.             break;
  220.         }
  221.         if (l <= 0 || l > MAXLABEL) {
  222.             if (msg != NULL)
  223.                 *lpp = NULL;
  224.             return (-1);
  225.         }
  226.         *sp = l;
  227.     }
  228.     if (cp >= eob) {
  229.         if (msg != NULL)
  230.             *lpp = NULL;
  231.         return (-1);
  232.     }
  233.     *cp++ = '\0';
  234.     return (cp - comp_dn);
  235. }
  236.  
  237. /*
  238.  * Skip over a compressed domain name. Return the size or -1.
  239.  */
  240. int
  241. __dn_skipname(comp_dn, eom)
  242.     const u_char *comp_dn, *eom;
  243. {
  244.     register u_char *cp;
  245.     register int n;
  246.  
  247.     cp = (u_char *)comp_dn;
  248.     while (cp < eom && (n = *cp++)) {
  249.         /*
  250.          * check for indirection
  251.          */
  252.         switch (n & INDIR_MASK) {
  253.         case 0:            /* normal case, n == len */
  254.             cp += n;
  255.             continue;
  256.         case INDIR_MASK:    /* indirection */
  257.             cp++;
  258.             break;
  259.         default:        /* illegal type */
  260.             return (-1);
  261.         }
  262.         break;
  263.     }
  264.     if (cp > eom)
  265.         return -1;
  266.     return (cp - comp_dn);
  267. }
  268.  
  269. /*
  270.  * Search for expanded name from a list of previously compressed names.
  271.  * Return the offset from msg if found or -1.
  272.  * dnptrs is the pointer to the first name on the list,
  273.  * not the pointer to the start of the message.
  274.  */
  275. static int
  276. dn_find(exp_dn, msg, dnptrs, lastdnptr)
  277.     u_char *exp_dn, *msg;
  278.     u_char **dnptrs, **lastdnptr;
  279. {
  280.     register u_char *dn, *cp, **cpp;
  281.     register int n;
  282.     u_char *sp;
  283.  
  284.     for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  285.         dn = exp_dn;
  286.         sp = cp = *cpp;
  287.         while ((n = *cp++)) {
  288.             /*
  289.              * check for indirection
  290.              */
  291.             switch (n & INDIR_MASK) {
  292.             case 0:        /* normal case, n == len */
  293.                 while (--n >= 0) {
  294.                     if (*dn == '.')
  295.                         goto next;
  296.                     if (*dn == '\\')
  297.                         dn++;
  298.                     if (*dn++ != *cp++)
  299.                         goto next;
  300.                 }
  301.                 if ((n = *dn++) == '\0' && *cp == '\0')
  302.                     return (sp - msg);
  303.                 if (n == '.')
  304.                     continue;
  305.                 goto next;
  306.  
  307.             default:    /* illegal type */
  308.                 return (-1);
  309.  
  310.             case INDIR_MASK:    /* indirection */
  311.                 cp = msg + (((n & 0x3f) << 8) | *cp);
  312.             }
  313.         }
  314.         if (*dn == '\0')
  315.             return (sp - msg);
  316.     next:    ;
  317.     }
  318.     return (-1);
  319. }
  320.  
  321. /*
  322.  * Routines to insert/extract short/long's. Must account for byte
  323.  * order and non-alignment problems. This code at least has the
  324.  * advantage of being portable.
  325.  *
  326.  * used by sendmail.
  327.  */
  328.  
  329. u_short
  330. _getshort(msgp)
  331.     register u_char *msgp;
  332. {
  333.     register u_int16_t u;
  334.  
  335.     GETSHORT(u, msgp);
  336.     return (u);
  337. }
  338.  
  339. u_int32_t
  340. _getlong(msgp)
  341.     register u_char *msgp;
  342. {
  343.     register u_int32_t u;
  344.  
  345.     GETLONG(u, msgp);
  346.     return (u);
  347. }
  348.  
  349. void
  350. #if defined(__STDC__) || defined(__cplusplus)
  351. __putshort(register u_int16_t s, register u_char *msgp)
  352. #else
  353. __putshort(s, msgp)
  354.     register u_int16_t s;
  355.     register u_char *msgp;
  356. #endif
  357. {
  358.     PUTSHORT(s, msgp);
  359. }
  360.  
  361. void
  362. __putlong(l, msgp)
  363.     register u_int32_t l;
  364.     register u_char *msgp;
  365. {
  366.     PUTLONG(l, msgp);
  367. }
  368.