|
|
1.1 ! root 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 <arpa/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.