home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / in4wjcxu / other / irc / ircd / res_comp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-14  |  7.1 KB  |  330 lines

  1. /*
  2.  * Copyright (c) 1985 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted provided
  6.  * that: (1) source distributions retain this entire copyright notice and
  7.  * comment, and (2) distributions including binaries display the following
  8.  * acknowledgement:  ``This product includes software developed by the
  9.  * University of California, Berkeley and its contributors'' in the
  10.  * documentation or other materials provided with the distribution and in
  11.  * all advertising materials mentioning features or use of this software.
  12.  * Neither the name of the University nor the names of its contributors may
  13.  * be used to endorse or promote products derived from this software without
  14.  * specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  16.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  17.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #if defined(LIBC_SCCS) && !defined(lint)
  21. static char sccsid[] = "@(#)res_comp.c    6.18 (Berkeley) 6/27/90";
  22. #endif /* LIBC_SCCS and not lint */
  23.  
  24. #include <sys/types.h>
  25. #include <stdio.h>
  26. #include "nameser.h"
  27.  
  28. static dn_find();
  29.  
  30. /*
  31.  * Expand compressed domain name 'comp_dn' to full domain name.
  32.  * 'msg' is a pointer to the begining of the message,
  33.  * 'eomorig' points to the first location after the message,
  34.  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  35.  * Return size of compressed name or -1 if there was an error.
  36.  */
  37. dn_expand(msg, eomorig, comp_dn, exp_dn, length)
  38.     u_char *msg, *eomorig, *comp_dn, *exp_dn;
  39.     int length;
  40. {
  41.     register u_char *cp, *dn;
  42.     register int n, c;
  43.     u_char *eom;
  44.     int len = -1, checked = 0;
  45.  
  46.     dn = exp_dn;
  47.     cp = comp_dn;
  48.     eom = exp_dn + length;
  49.     /*
  50.      * fetch next label in domain name
  51.      */
  52.     while (n = *cp++) {
  53.         /*
  54.          * Check for indirection
  55.          */
  56.         switch (n & INDIR_MASK) {
  57.         case 0:
  58.             if (dn != exp_dn) {
  59.                 if (dn >= eom)
  60.                     return (-1);
  61.                 *dn++ = '.';
  62.             }
  63.             if (dn+n >= eom)
  64.                 return (-1);
  65.             checked += n + 1;
  66.             while (--n >= 0) {
  67.                 if ((c = *cp++) == '.') {
  68.                     if (dn + n + 2 >= eom)
  69.                         return (-1);
  70.                     *dn++ = '\\';
  71.                 }
  72.                 *dn++ = c;
  73.                 if (cp >= eomorig)    /* out of range */
  74.                     return(-1);
  75.             }
  76.             break;
  77.  
  78.         case INDIR_MASK:
  79.             if (len < 0)
  80.                 len = cp - comp_dn + 1;
  81.             cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  82.             if (cp < msg || cp >= eomorig)    /* out of range */
  83.                 return(-1);
  84.             checked += 2;
  85.             /*
  86.              * Check for loops in the compressed name;
  87.              * if we've looked at the whole message,
  88.              * there must be a loop.
  89.              */
  90.             if (checked >= eomorig - msg)
  91.                 return (-1);
  92.             break;
  93.  
  94.         default:
  95.             return (-1);            /* flag error */
  96.         }
  97.     }
  98.     *dn = '\0';
  99.     if (len < 0)
  100.         len = cp - comp_dn;
  101.     return (len);
  102. }
  103.  
  104. /*
  105.  * Compress domain name 'exp_dn' into 'comp_dn'.
  106.  * Return the size of the compressed name or -1.
  107.  * 'length' is the size of the array pointed to by 'comp_dn'.
  108.  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  109.  * is a pointer to the beginning of the message. The list ends with NULL.
  110.  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  111.  * by 'dnptrs'. Side effect is to update the list of pointers for
  112.  * labels inserted into the message as we compress the name.
  113.  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  114.  * is NULL, we don't update the list.
  115.  */
  116. dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  117.     u_char *exp_dn, *comp_dn;
  118.     int length;
  119.     u_char **dnptrs, **lastdnptr;
  120. {
  121.     register u_char *cp, *dn;
  122.     register int c, l;
  123.     u_char **cpp, **lpp, *sp, *eob;
  124.     u_char *msg;
  125.  
  126.     dn = exp_dn;
  127.     cp = comp_dn;
  128.     eob = cp + length;
  129.     if (dnptrs != NULL) {
  130.         if ((msg = *dnptrs++) != NULL) {
  131.             for (cpp = dnptrs; *cpp != NULL; cpp++)
  132.                 ;
  133.             lpp = cpp;    /* end of list to search */
  134.         }
  135.     } else
  136.         msg = NULL;
  137.     for (c = *dn++; c != '\0'; ) {
  138.         /* look to see if we can use pointers */
  139.         if (msg != NULL) {
  140.             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
  141.                 if (cp+1 >= eob)
  142.                     return (-1);
  143.                 *cp++ = (l >> 8) | INDIR_MASK;
  144.                 *cp++ = l % 256;
  145.                 return (cp - comp_dn);
  146.             }
  147.             /* not found, save it */
  148.             if (lastdnptr != NULL && cpp < lastdnptr-1) {
  149.                 *cpp++ = cp;
  150.                 *cpp = NULL;
  151.             }
  152.         }
  153.         sp = cp++;    /* save ptr to length byte */
  154.         do {
  155.             if (c == '.') {
  156.                 c = *dn++;
  157.                 break;
  158.             }
  159.             if (c == '\\') {
  160.                 if ((c = *dn++) == '\0')
  161.                     break;
  162.             }
  163.             if (cp >= eob) {
  164.                 if (msg != NULL)
  165.                     *lpp = NULL;
  166.                 return (-1);
  167.             }
  168.             *cp++ = c;
  169.         } while ((c = *dn++) != '\0');
  170.         /* catch trailing '.'s but not '..' */
  171.         if ((l = cp - sp - 1) == 0 && c == '\0') {
  172.             cp--;
  173.             break;
  174.         }
  175.         if (l <= 0 || l > MAXLABEL) {
  176.             if (msg != NULL)
  177.                 *lpp = NULL;
  178.             return (-1);
  179.         }
  180.         *sp = l;
  181.     }
  182.     if (cp >= eob) {
  183.         if (msg != NULL)
  184.             *lpp = NULL;
  185.         return (-1);
  186.     }
  187.     *cp++ = '\0';
  188.     return (cp - comp_dn);
  189. }
  190.  
  191. /*
  192.  * Skip over a compressed domain name. Return the size or -1.
  193.  */
  194. dn_skipname(comp_dn, eom)
  195.     u_char *comp_dn, *eom;
  196. {
  197.     register u_char *cp;
  198.     register int n;
  199.  
  200.     cp = comp_dn;
  201.     while (cp < eom && (n = *cp++)) {
  202.         /*
  203.          * check for indirection
  204.          */
  205.         switch (n & INDIR_MASK) {
  206.         case 0:        /* normal case, n == len */
  207.             cp += n;
  208.             continue;
  209.         default:    /* illegal type */
  210.             return (-1);
  211.         case INDIR_MASK:    /* indirection */
  212.             cp++;
  213.         }
  214.         break;
  215.     }
  216.     return (cp - comp_dn);
  217. }
  218.  
  219. /*
  220.  * Search for expanded name from a list of previously compressed names.
  221.  * Return the offset from msg if found or -1.
  222.  * dnptrs is the pointer to the first name on the list,
  223.  * not the pointer to the start of the message.
  224.  */
  225. static
  226. dn_find(exp_dn, msg, dnptrs, lastdnptr)
  227.     u_char *exp_dn, *msg;
  228.     u_char **dnptrs, **lastdnptr;
  229. {
  230.     register u_char *dn, *cp, **cpp;
  231.     register int n;
  232.     u_char *sp;
  233.  
  234.     for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  235.         dn = exp_dn;
  236.         sp = cp = *cpp;
  237.         while (n = *cp++) {
  238.             /*
  239.              * check for indirection
  240.              */
  241.             switch (n & INDIR_MASK) {
  242.             case 0:        /* normal case, n == len */
  243.                 while (--n >= 0) {
  244.                     if (*dn == '.')
  245.                         goto next;
  246.                     if (*dn == '\\')
  247.                         dn++;
  248.                     if (*dn++ != *cp++)
  249.                         goto next;
  250.                 }
  251.                 if ((n = *dn++) == '\0' && *cp == '\0')
  252.                     return (sp - msg);
  253.                 if (n == '.')
  254.                     continue;
  255.                 goto next;
  256.  
  257.             default:    /* illegal type */
  258.                 return (-1);
  259.  
  260.             case INDIR_MASK:    /* indirection */
  261.                 cp = msg + (((n & 0x3f) << 8) | *cp);
  262.             }
  263.         }
  264.         if (*dn == '\0')
  265.             return (sp - msg);
  266.     next:    ;
  267.     }
  268.     return (-1);
  269. }
  270.  
  271. /*
  272.  * Routines to insert/extract short/long's. Must account for byte
  273.  * order and non-alignment problems. This code at least has the
  274.  * advantage of being portable.
  275.  *
  276.  * used by sendmail.
  277.  */
  278.  
  279. u_short
  280. _getshort(msgp)
  281.     u_char *msgp;
  282. {
  283.     register u_char *p = (u_char *) msgp;
  284. #ifdef vax
  285.     /*
  286.      * vax compiler doesn't put shorts in registers
  287.      */
  288.     register u_long u;
  289. #else
  290.     register u_short u;
  291. #endif
  292.  
  293.     u = *p++ << 8;
  294.     return ((u_short)(u | *p));
  295. }
  296.  
  297. u_long
  298. _getlong(msgp)
  299.     u_char *msgp;
  300. {
  301.     register u_char *p = (u_char *) msgp;
  302.     register u_long u;
  303.  
  304.     u = *p++; u <<= 8;
  305.     u |= *p++; u <<= 8;
  306.     u |= *p++; u <<= 8;
  307.     return (u | *p);
  308. }
  309.  
  310.  
  311. putshort(s, msgp)
  312.     register u_short s;
  313.     register u_char *msgp;
  314. {
  315.  
  316.     msgp[1] = s;
  317.     msgp[0] = s >> 8;
  318. }
  319.  
  320. putlong(l, msgp)
  321.     register u_long l;
  322.     register u_char *msgp;
  323. {
  324.  
  325.     msgp[3] = l;
  326.     msgp[2] = (l >>= 8);
  327.     msgp[1] = (l >>= 8);
  328.     msgp[0] = l >> 8;
  329. }
  330.