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