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