1: /*
   2:  * Copyright (c) 1985 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #if defined(LIBC_SCCS) && !defined(lint)
   8: static char sccsid[] = "@(#)res_comp.c	6.7 (Berkeley) 3/11/86";
   9: #endif LIBC_SCCS and not lint
  10: 
  11: #include <sys/types.h>
  12: #include <stdio.h>
  13: #include <arpa/nameser.h>
  14: 
  15: 
  16: /*
  17:  * Expand compressed domain name 'comp_dn' to full domain name.
  18:  * 'msg' is a pointer to the begining of the message,
  19:  * 'eomorig' points to the first location after the message,
  20:  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  21:  * Return size of compressed name or -1 if there was an error.
  22:  */
  23: dn_expand(msg, eomorig, comp_dn, exp_dn, length)
  24:     char *msg, *eomorig, *comp_dn, *exp_dn;
  25:     int length;
  26: {
  27:     register char *cp, *dn;
  28:     register int n, c;
  29:     char *eom;
  30:     int len = -1;
  31: 
  32:     dn = exp_dn;
  33:     cp = comp_dn;
  34:     eom = exp_dn + length - 1;
  35:     /*
  36: 	 * fetch next label in domain name
  37: 	 */
  38:     while (n = *cp++) {
  39:         /*
  40: 		 * Check for indirection
  41: 		 */
  42:         switch (n & INDIR_MASK) {
  43:         case 0:
  44:             if (dn != exp_dn) {
  45:                 if (dn >= eom)
  46:                     return (-1);
  47:                 *dn++ = '.';
  48:             }
  49:             if (dn+n >= eom)
  50:                 return (-1);
  51:             while (--n >= 0) {
  52:                 if ((c = *cp++) == '.') {
  53:                     if (dn+n+1 >= eom)
  54:                         return (-1);
  55:                     *dn++ = '\\';
  56:                 }
  57:                 *dn++ = c;
  58:                 if (cp >= eomorig)  /* out of range */
  59:                     return(-1);
  60:             }
  61:             break;
  62: 
  63:         case INDIR_MASK:
  64:             if (len < 0)
  65:                 len = cp - comp_dn + 1;
  66:             cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  67:             if (cp < msg || cp >= eomorig)  /* out of range */
  68:                 return(-1);
  69:             break;
  70: 
  71:         default:
  72:             return (-1);            /* flag error */
  73:         }
  74:     }
  75:     *dn = '\0';
  76:     if (len < 0)
  77:         len = cp - comp_dn;
  78:     return (len);
  79: }
  80: 
  81: /*
  82:  * Compress domain name 'exp_dn' into 'comp_dn'.
  83:  * Return the size of the compressed name or -1.
  84:  * 'length' is the size of the array pointed to by 'comp_dn'.
  85:  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  86:  * is a pointer to the beginning of the message. The list ends with NULL.
  87:  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  88:  * by 'dnptrs'. Side effect is to update the list of pointers for
  89:  * labels inserted into the message as we compress the name.
  90:  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  91:  * is NULL, we don't update the list.
  92:  */
  93: dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  94:     char *exp_dn, *comp_dn;
  95:     int length;
  96:     char **dnptrs, **lastdnptr;
  97: {
  98:     register char *cp, *dn;
  99:     register int c, l;
 100:     char **cpp, **lpp, *sp, *eob;
 101:     char *msg;
 102: 
 103:     dn = exp_dn;
 104:     cp = comp_dn;
 105:     eob = cp + length;
 106:     if (dnptrs != NULL) {
 107:         if ((msg = *dnptrs++) != NULL) {
 108:             for (cpp = dnptrs; *cpp != NULL; cpp++)
 109:                 ;
 110:             lpp = cpp;  /* end of list to search */
 111:         }
 112:     } else
 113:         msg = NULL;
 114:     for (c = *dn++; c != '\0'; ) {
 115:         /* look to see if we can use pointers */
 116:         if (msg != NULL) {
 117:             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
 118:                 if (cp+1 >= eob)
 119:                     return (-1);
 120:                 *cp++ = (l >> 8) | INDIR_MASK;
 121:                 *cp++ = l % 256;
 122:                 return (cp - comp_dn);
 123:             }
 124:             /* not found, save it */
 125:             if (lastdnptr != NULL && cpp < lastdnptr-1) {
 126:                 *cpp++ = cp;
 127:                 *cpp = NULL;
 128:             }
 129:         }
 130:         sp = cp++;  /* save ptr to length byte */
 131:         do {
 132:             if (c == '.') {
 133:                 c = *dn++;
 134:                 break;
 135:             }
 136:             if (c == '\\') {
 137:                 if ((c = *dn++) == '\0')
 138:                     break;
 139:             }
 140:             if (cp >= eob)
 141:                 return (-1);
 142:             *cp++ = c;
 143:         } while ((c = *dn++) != '\0');
 144:         /* catch trailing '.'s but not '..' */
 145:         if ((l = cp - sp - 1) == 0 && c == '\0') {
 146:             cp--;
 147:             break;
 148:         }
 149:         if (l <= 0 || l > MAXLABEL)
 150:             return (-1);
 151:         *sp = l;
 152:     }
 153:     if (cp >= eob)
 154:         return (-1);
 155:     *cp++ = '\0';
 156:     return (cp - comp_dn);
 157: }
 158: 
 159: /*
 160:  * Skip over a compressed domain name. Return the size or -1.
 161:  */
 162: dn_skip(comp_dn)
 163:     char *comp_dn;
 164: {
 165:     register char *cp;
 166:     register int n;
 167: 
 168:     cp = comp_dn;
 169:     while (n = *cp++) {
 170:         /*
 171: 		 * check for indirection
 172: 		 */
 173:         switch (n & INDIR_MASK) {
 174:         case 0:     /* normal case, n == len */
 175:             cp += n;
 176:             continue;
 177:         default:    /* illegal type */
 178:             return (-1);
 179:         case INDIR_MASK:    /* indirection */
 180:             cp++;
 181:         }
 182:         break;
 183:     }
 184:     return (cp - comp_dn);
 185: }
 186: 
 187: /*
 188:  * Search for expanded name from a list of previously compressed names.
 189:  * Return the offset from msg if found or -1.
 190:  */
 191: dn_find(exp_dn, msg, dnptrs, lastdnptr)
 192:     char *exp_dn, *msg;
 193:     char **dnptrs, **lastdnptr;
 194: {
 195:     register char *dn, *cp, **cpp;
 196:     register int n;
 197:     char *sp;
 198: 
 199:     for (cpp = dnptrs + 1; cpp < lastdnptr; cpp++) {
 200:         dn = exp_dn;
 201:         sp = cp = *cpp;
 202:         while (n = *cp++) {
 203:             /*
 204: 			 * check for indirection
 205: 			 */
 206:             switch (n & INDIR_MASK) {
 207:             case 0:     /* normal case, n == len */
 208:                 while (--n >= 0) {
 209:                     if (*dn == '\\')
 210:                         dn++;
 211:                     if (*dn++ != *cp++)
 212:                         goto next;
 213:                 }
 214:                 if ((n = *dn++) == '\0' && *cp == '\0')
 215:                     return (sp - msg);
 216:                 if (n == '.')
 217:                     continue;
 218:                 goto next;
 219: 
 220:             default:    /* illegal type */
 221:                 return (-1);
 222: 
 223:             case INDIR_MASK:    /* indirection */
 224:                 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
 225:             }
 226:         }
 227:         if (*dn == '\0')
 228:             return (sp - msg);
 229:     next:   ;
 230:     }
 231:     return (-1);
 232: }
 233: 
 234: /*
 235:  * Routines to insert/extract short/long's. Must account for byte
 236:  * order and non-alignment problems. This code at least has the
 237:  * advantage of being portable.
 238:  */
 239: 
 240: u_short
 241: getshort(msgp)
 242:     char *msgp;
 243: {
 244:     register u_char *p = (u_char *) msgp;
 245: #ifdef vax
 246:     /*
 247: 	 * vax compiler doesn't put shorts in registers
 248: 	 */
 249:     register u_long u;
 250: #else
 251:     register u_short u;
 252: #endif
 253: 
 254:     u = *p++ << 8;
 255:     return ((u_short)(u | *p));
 256: }
 257: 
 258: u_long
 259: getlong(msgp)
 260:     char *msgp;
 261: {
 262:     register u_char *p = (u_char *) msgp;
 263:     register u_long u;
 264: 
 265:     u = *p++; u <<= 8;
 266:     u |= *p++; u <<= 8;
 267:     u |= *p++; u <<= 8;
 268:     return (u | *p);
 269: }
 270: 
 271: 
 272: putshort(s, msgp)
 273:     register u_short s;
 274:     register char *msgp;
 275: {
 276: 
 277:     msgp[1] = s;
 278:     msgp[0] = s >> 8;
 279: }
 280: 
 281: putlong(l, msgp)
 282:     register u_long l;
 283:     register char *msgp;
 284: {
 285: 
 286:     msgp[3] = l;
 287:     msgp[2] = (l >>= 8);
 288:     msgp[1] = (l >>= 8);
 289:     msgp[0] = l >> 8;
 290: }

Defined functions

dn_comp defined in line 93; used 12 times
dn_find defined in line 191; used 1 times
putshort defined in line 272; used 18 times

Defined variables

sccsid defined in line 8; never used
Last modified: 1986-03-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1256
Valid CSS Valid XHTML 1.0 Strict