|
|
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.