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

Defined functions

dn_find defined in line 208; used 1 times
putshort defined in line 292; used 14 times

Defined variables

sccsid defined in line 14; never used
Last modified: 1988-09-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3179
Valid CSS Valid XHTML 1.0 Strict