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