home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / NETWORK / ISP / bind.4.8.3.lzh / BIND483 / RES / res_comp.c < prev    next >
Text File  |  1994-09-23  |  7KB  |  336 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. #ifdef OSK
  25. #include <types.h>
  26. #include <stdio.h>
  27. #include <nameser.h>
  28. #else
  29. #include <sys/types.h>
  30. #include <stdio.h>
  31. #include <arpa/nameser.h>
  32. #endif
  33.  
  34. static dn_find();
  35.  
  36. /*
  37.  * Expand compressed domain name 'comp_dn' to full domain name.
  38.  * 'msg' is a pointer to the begining of the message,
  39.  * 'eomorig' points to the first location after the message,
  40.  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  41.  * Return size of compressed name or -1 if there was an error.
  42.  */
  43. dn_expand(msg, eomorig, comp_dn, exp_dn, length)
  44.     u_char *msg, *eomorig, *comp_dn, *exp_dn;
  45.     int length;
  46. {
  47.     register u_char *cp, *dn;
  48.     register int n, c;
  49.     u_char *eom;
  50.     int len = -1, checked = 0;
  51.  
  52.     dn = exp_dn;
  53.     cp = comp_dn;
  54.     eom = exp_dn + length;
  55.     /*
  56.      * fetch next label in domain name
  57.      */
  58.     while (n = *cp++) {
  59.         /*
  60.          * Check for indirection
  61.          */
  62.         switch (n & INDIR_MASK) {
  63.         case 0:
  64.             if (dn != exp_dn) {
  65.                 if (dn >= eom)
  66.                     return (-1);
  67.                 *dn++ = '.';
  68.             }
  69.             if (dn+n >= eom)
  70.                 return (-1);
  71.             checked += n + 1;
  72.             while (--n >= 0) {
  73.                 if ((c = *cp++) == '.') {
  74.                     if (dn + n + 2 >= eom)
  75.                         return (-1);
  76.                     *dn++ = '\\';
  77.                 }
  78.                 *dn++ = c;
  79.                 if (cp >= eomorig)    /* out of range */
  80.                     return(-1);
  81.             }
  82.             break;
  83.  
  84.         case INDIR_MASK:
  85.             if (len < 0)
  86.                 len = cp - comp_dn + 1;
  87.             cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  88.             if (cp < msg || cp >= eomorig)    /* out of range */
  89.                 return(-1);
  90.             checked += 2;
  91.             /*
  92.              * Check for loops in the compressed name;
  93.              * if we've looked at the whole message,
  94.              * there must be a loop.
  95.              */
  96.             if (checked >= eomorig - msg)
  97.                 return (-1);
  98.             break;
  99.  
  100.         default:
  101.             return (-1);            /* flag error */
  102.         }
  103.     }
  104.     *dn = '\0';
  105.     if (len < 0)
  106.         len = cp - comp_dn;
  107.     return (len);
  108. }
  109.  
  110. /*
  111.  * Compress domain name 'exp_dn' into 'comp_dn'.
  112.  * Return the size of the compressed name or -1.
  113.  * 'length' is the size of the array pointed to by 'comp_dn'.
  114.  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  115.  * is a pointer to the beginning of the message. The list ends with NULL.
  116.  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  117.  * by 'dnptrs'. Side effect is to update the list of pointers for
  118.  * labels inserted into the message as we compress the name.
  119.  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  120.  * is NULL, we don't update the list.
  121.  */
  122. dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  123.     u_char *exp_dn, *comp_dn;
  124.     int length;
  125.     u_char **dnptrs, **lastdnptr;
  126. {
  127.     register u_char *cp, *dn;
  128.     register int c, l;
  129.     u_char **cpp, **lpp, *sp, *eob;
  130.     u_char *msg;
  131.  
  132.     dn = exp_dn;
  133.     cp = comp_dn;
  134.     eob = cp + length;
  135.     if (dnptrs != NULL) {
  136.         if ((msg = *dnptrs++) != NULL) {
  137.             for (cpp = dnptrs; *cpp != NULL; cpp++)
  138.                 ;
  139.             lpp = cpp;    /* end of list to search */
  140.         }
  141.     } else
  142.         msg = NULL;
  143.     for (c = *dn++; c != '\0'; ) {
  144.         /* look to see if we can use pointers */
  145.         if (msg != NULL) {
  146.             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
  147.                 if (cp+1 >= eob)
  148.                     return (-1);
  149.                 *cp++ = (l >> 8) | INDIR_MASK;
  150.                 *cp++ = l % 256;
  151.                 return (cp - comp_dn);
  152.             }
  153.             /* not found, save it */
  154.             if (lastdnptr != NULL && cpp < lastdnptr-1) {
  155.                 *cpp++ = cp;
  156.                 *cpp = NULL;
  157.             }
  158.         }
  159.         sp = cp++;    /* save ptr to length byte */
  160.         do {
  161.             if (c == '.') {
  162.                 c = *dn++;
  163.                 break;
  164.             }
  165.             if (c == '\\') {
  166.                 if ((c = *dn++) == '\0')
  167.                     break;
  168.             }
  169.             if (cp >= eob) {
  170.                 if (msg != NULL)
  171.                     *lpp = NULL;
  172.                 return (-1);
  173.             }
  174.             *cp++ = c;
  175.         } while ((c = *dn++) != '\0');
  176.         /* catch trailing '.'s but not '..' */
  177.         if ((l = cp - sp - 1) == 0 && c == '\0') {
  178.             cp--;
  179.             break;
  180.         }
  181.         if (l <= 0 || l > MAXLABEL) {
  182.             if (msg != NULL)
  183.                 *lpp = NULL;
  184.             return (-1);
  185.         }
  186.         *sp = l;
  187.     }
  188.     if (cp >= eob) {
  189.         if (msg != NULL)
  190.             *lpp = NULL;
  191.         return (-1);
  192.     }
  193.     *cp++ = '\0';
  194.     return (cp - comp_dn);
  195. }
  196.  
  197. /*
  198.  * Skip over a compressed domain name. Return the size or -1.
  199.  */
  200. dn_skipname(comp_dn, eom)
  201.     u_char *comp_dn, *eom;
  202. {
  203.     register u_char *cp;
  204.     register int n;
  205.  
  206.     cp = comp_dn;
  207.     while (cp < eom && (n = *cp++)) {
  208.         /*
  209.          * check for indirection
  210.          */
  211.         switch (n & INDIR_MASK) {
  212.         case 0:        /* normal case, n == len */
  213.             cp += n;
  214.             continue;
  215.         default:    /* illegal type */
  216.             return (-1);
  217.         case INDIR_MASK:    /* indirection */
  218.             cp++;
  219.         }
  220.         break;
  221.     }
  222.     return (cp - comp_dn);
  223. }
  224.  
  225. /*
  226.  * Search for expanded name from a list of previously compressed names.
  227.  * Return the offset from msg if found or -1.
  228.  * dnptrs is the pointer to the first name on the list,
  229.  * not the pointer to the start of the message.
  230.  */
  231. static
  232. dn_find(exp_dn, msg, dnptrs, lastdnptr)
  233.     u_char *exp_dn, *msg;
  234.     u_char **dnptrs, **lastdnptr;
  235. {
  236.     register u_char *dn, *cp, **cpp;
  237.     register int n;
  238.     u_char *sp;
  239.  
  240.     for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  241.         dn = exp_dn;
  242.         sp = cp = *cpp;
  243.         while (n = *cp++) {
  244.             /*
  245.              * check for indirection
  246.              */
  247.             switch (n & INDIR_MASK) {
  248.             case 0:        /* normal case, n == len */
  249.                 while (--n >= 0) {
  250.                     if (*dn == '.')
  251.                         goto next;
  252.                     if (*dn == '\\')
  253.                         dn++;
  254.                     if (*dn++ != *cp++)
  255.                         goto next;
  256.                 }
  257.                 if ((n = *dn++) == '\0' && *cp == '\0')
  258.                     return (sp - msg);
  259.                 if (n == '.')
  260.                     continue;
  261.                 goto next;
  262.  
  263.             default:    /* illegal type */
  264.                 return (-1);
  265.  
  266.             case INDIR_MASK:    /* indirection */
  267.                 cp = msg + (((n & 0x3f) << 8) | *cp);
  268.             }
  269.         }
  270.         if (*dn == '\0')
  271.             return (sp - msg);
  272.     next:    ;
  273.     }
  274.     return (-1);
  275. }
  276.  
  277. /*
  278.  * Routines to insert/extract short/long's. Must account for byte
  279.  * order and non-alignment problems. This code at least has the
  280.  * advantage of being portable.
  281.  *
  282.  * used by sendmail.
  283.  */
  284.  
  285. u_short
  286. _getshort(msgp)
  287.     u_char *msgp;
  288. {
  289.     register u_char *p = (u_char *) msgp;
  290. #ifdef vax
  291.     /*
  292.      * vax compiler doesn't put shorts in registers
  293.      */
  294.     register u_long u;
  295. #else
  296.     register u_short u;
  297. #endif
  298.  
  299.     u = *p++ << 8;
  300.     return ((u_short)(u | *p));
  301. }
  302.  
  303. u_long
  304. _getlong(msgp)
  305.     u_char *msgp;
  306. {
  307.     register u_char *p = (u_char *) msgp;
  308.     register u_long u;
  309.  
  310.     u = *p++; u <<= 8;
  311.     u |= *p++; u <<= 8;
  312.     u |= *p++; u <<= 8;
  313.     return (u | *p);
  314. }
  315.  
  316.  
  317. putshort(s, msgp)
  318.     register u_short s;
  319.     register u_char *msgp;
  320. {
  321.  
  322.     msgp[1] = s;
  323.     msgp[0] = s >> 8;
  324. }
  325.  
  326. putlong(l, msgp)
  327.     register u_long l;
  328.     register u_char *msgp;
  329. {
  330.  
  331.     msgp[3] = l;
  332.     msgp[2] = (l >>= 8);
  333.     msgp[1] = (l >>= 8);
  334.     msgp[0] = l >> 8;
  335. }
  336.