Commit | Line | Data |
---|---|---|
b423e985 | 1 | /* |
8ea4199d | 2 | * Copyright (c) 1985 Regents of the University of California. |
6b2f9dd0 KB |
3 | * All rights reserved. |
4 | * | |
269a7923 | 5 | * %sccs.include.redist.c% |
b423e985 RC |
6 | */ |
7 | ||
2ce81398 | 8 | #if defined(LIBC_SCCS) && !defined(lint) |
bc27c43a | 9 | static char sccsid[] = "@(#)res_comp.c 6.22 (Berkeley) %G%"; |
6b2f9dd0 | 10 | #endif /* LIBC_SCCS and not lint */ |
8ea4199d | 11 | |
bc27c43a | 12 | #include <sys/param.h> |
aa45ab0f | 13 | #include <arpa/nameser.h> |
24fac7d8 KB |
14 | #include <netinet/in.h> |
15 | #include <resolv.h> | |
16 | #include <stdio.h> | |
fbc82d3e | 17 | |
a64d62d8 CL |
18 | static dn_find(); |
19 | ||
fbc82d3e | 20 | /* |
36534519 | 21 | * Expand compressed domain name 'comp_dn' to full domain name. |
36534519 | 22 | * 'msg' is a pointer to the begining of the message, |
127b68cb | 23 | * 'eomorig' points to the first location after the message, |
36534519 | 24 | * 'exp_dn' is a pointer to a buffer of size 'length' for the result. |
fbc82d3e RC |
25 | * Return size of compressed name or -1 if there was an error. |
26 | */ | |
127b68cb | 27 | dn_expand(msg, eomorig, comp_dn, exp_dn, length) |
24fac7d8 KB |
28 | const u_char *msg, *eomorig, *comp_dn; |
29 | u_char *exp_dn; | |
127b68cb | 30 | int length; |
fbc82d3e | 31 | { |
34082ede | 32 | register u_char *cp, *dn; |
fbc82d3e | 33 | register int n, c; |
34082ede | 34 | u_char *eom; |
19f533a7 | 35 | int len = -1, checked = 0; |
fbc82d3e RC |
36 | |
37 | dn = exp_dn; | |
24fac7d8 | 38 | cp = (u_char *)comp_dn; |
f2cfc0ce | 39 | eom = exp_dn + length; |
fbc82d3e RC |
40 | /* |
41 | * fetch next label in domain name | |
42 | */ | |
43 | while (n = *cp++) { | |
44 | /* | |
45 | * Check for indirection | |
46 | */ | |
47 | switch (n & INDIR_MASK) { | |
48 | case 0: | |
36534519 RC |
49 | if (dn != exp_dn) { |
50 | if (dn >= eom) | |
51 | return (-1); | |
fbc82d3e | 52 | *dn++ = '.'; |
36534519 | 53 | } |
fbc82d3e RC |
54 | if (dn+n >= eom) |
55 | return (-1); | |
19f533a7 | 56 | checked += n + 1; |
91c656a0 | 57 | while (--n >= 0) { |
80f420a7 | 58 | if ((c = *cp++) == '.') { |
e81082fb | 59 | if (dn + n + 2 >= eom) |
80f420a7 JB |
60 | return (-1); |
61 | *dn++ = '\\'; | |
36534519 | 62 | } |
80f420a7 | 63 | *dn++ = c; |
127b68cb | 64 | if (cp >= eomorig) /* out of range */ |
91c656a0 KD |
65 | return(-1); |
66 | } | |
fbc82d3e RC |
67 | break; |
68 | ||
69 | case INDIR_MASK: | |
36534519 | 70 | if (len < 0) |
fbc82d3e | 71 | len = cp - comp_dn + 1; |
24fac7d8 | 72 | cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff)); |
127b68cb | 73 | if (cp < msg || cp >= eomorig) /* out of range */ |
91c656a0 | 74 | return(-1); |
19f533a7 MK |
75 | checked += 2; |
76 | /* | |
77 | * Check for loops in the compressed name; | |
78 | * if we've looked at the whole message, | |
79 | * there must be a loop. | |
80 | */ | |
81 | if (checked >= eomorig - msg) | |
82 | return (-1); | |
fbc82d3e RC |
83 | break; |
84 | ||
85 | default: | |
86 | return (-1); /* flag error */ | |
87 | } | |
88 | } | |
89 | *dn = '\0'; | |
36534519 | 90 | if (len < 0) |
fbc82d3e RC |
91 | len = cp - comp_dn; |
92 | return (len); | |
93 | } | |
94 | ||
95 | /* | |
36534519 RC |
96 | * Compress domain name 'exp_dn' into 'comp_dn'. |
97 | * Return the size of the compressed name or -1. | |
98 | * 'length' is the size of the array pointed to by 'comp_dn'. | |
99 | * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0] | |
fbc82d3e | 100 | * is a pointer to the beginning of the message. The list ends with NULL. |
36534519 RC |
101 | * 'lastdnptr' is a pointer to the end of the arrary pointed to |
102 | * by 'dnptrs'. Side effect is to update the list of pointers for | |
103 | * labels inserted into the message as we compress the name. | |
104 | * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' | |
105 | * is NULL, we don't update the list. | |
fbc82d3e RC |
106 | */ |
107 | dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) | |
24fac7d8 KB |
108 | const u_char *exp_dn; |
109 | u_char *comp_dn, **dnptrs, **lastdnptr; | |
fbc82d3e | 110 | int length; |
fbc82d3e | 111 | { |
34082ede | 112 | register u_char *cp, *dn; |
fbc82d3e | 113 | register int c, l; |
34082ede MK |
114 | u_char **cpp, **lpp, *sp, *eob; |
115 | u_char *msg; | |
fbc82d3e | 116 | |
24fac7d8 | 117 | dn = (u_char *)exp_dn; |
fbc82d3e | 118 | cp = comp_dn; |
a34de0ef | 119 | eob = cp + length; |
fbc82d3e RC |
120 | if (dnptrs != NULL) { |
121 | if ((msg = *dnptrs++) != NULL) { | |
122 | for (cpp = dnptrs; *cpp != NULL; cpp++) | |
123 | ; | |
124 | lpp = cpp; /* end of list to search */ | |
125 | } | |
126 | } else | |
127 | msg = NULL; | |
128 | for (c = *dn++; c != '\0'; ) { | |
129 | /* look to see if we can use pointers */ | |
130 | if (msg != NULL) { | |
131 | if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) { | |
132 | if (cp+1 >= eob) | |
133 | return (-1); | |
134 | *cp++ = (l >> 8) | INDIR_MASK; | |
659c2773 | 135 | *cp++ = l % 256; |
fbc82d3e RC |
136 | return (cp - comp_dn); |
137 | } | |
138 | /* not found, save it */ | |
139 | if (lastdnptr != NULL && cpp < lastdnptr-1) { | |
140 | *cpp++ = cp; | |
141 | *cpp = NULL; | |
142 | } | |
143 | } | |
144 | sp = cp++; /* save ptr to length byte */ | |
145 | do { | |
146 | if (c == '.') { | |
147 | c = *dn++; | |
148 | break; | |
149 | } | |
36534519 RC |
150 | if (c == '\\') { |
151 | if ((c = *dn++) == '\0') | |
152 | break; | |
153 | } | |
f2cfc0ce JB |
154 | if (cp >= eob) { |
155 | if (msg != NULL) | |
156 | *lpp = NULL; | |
fbc82d3e | 157 | return (-1); |
f2cfc0ce | 158 | } |
fbc82d3e RC |
159 | *cp++ = c; |
160 | } while ((c = *dn++) != '\0'); | |
36534519 RC |
161 | /* catch trailing '.'s but not '..' */ |
162 | if ((l = cp - sp - 1) == 0 && c == '\0') { | |
163 | cp--; | |
164 | break; | |
165 | } | |
f2cfc0ce JB |
166 | if (l <= 0 || l > MAXLABEL) { |
167 | if (msg != NULL) | |
168 | *lpp = NULL; | |
fbc82d3e | 169 | return (-1); |
f2cfc0ce | 170 | } |
fbc82d3e RC |
171 | *sp = l; |
172 | } | |
f2cfc0ce JB |
173 | if (cp >= eob) { |
174 | if (msg != NULL) | |
175 | *lpp = NULL; | |
fbc82d3e | 176 | return (-1); |
f2cfc0ce | 177 | } |
fbc82d3e RC |
178 | *cp++ = '\0'; |
179 | return (cp - comp_dn); | |
180 | } | |
181 | ||
182 | /* | |
36534519 | 183 | * Skip over a compressed domain name. Return the size or -1. |
fbc82d3e | 184 | */ |
371d3c9b | 185 | __dn_skipname(comp_dn, eom) |
16dfe61e | 186 | const u_char *comp_dn, *eom; |
fbc82d3e | 187 | { |
34082ede | 188 | register u_char *cp; |
fbc82d3e RC |
189 | register int n; |
190 | ||
16dfe61e | 191 | cp = (u_char *)comp_dn; |
34082ede | 192 | while (cp < eom && (n = *cp++)) { |
fbc82d3e RC |
193 | /* |
194 | * check for indirection | |
195 | */ | |
196 | switch (n & INDIR_MASK) { | |
197 | case 0: /* normal case, n == len */ | |
198 | cp += n; | |
199 | continue; | |
200 | default: /* illegal type */ | |
201 | return (-1); | |
202 | case INDIR_MASK: /* indirection */ | |
203 | cp++; | |
204 | } | |
205 | break; | |
206 | } | |
36534519 | 207 | return (cp - comp_dn); |
fbc82d3e RC |
208 | } |
209 | ||
210 | /* | |
211 | * Search for expanded name from a list of previously compressed names. | |
212 | * Return the offset from msg if found or -1. | |
3182644d MK |
213 | * dnptrs is the pointer to the first name on the list, |
214 | * not the pointer to the start of the message. | |
fbc82d3e | 215 | */ |
3182644d | 216 | static |
fbc82d3e | 217 | dn_find(exp_dn, msg, dnptrs, lastdnptr) |
34082ede MK |
218 | u_char *exp_dn, *msg; |
219 | u_char **dnptrs, **lastdnptr; | |
fbc82d3e | 220 | { |
34082ede | 221 | register u_char *dn, *cp, **cpp; |
fbc82d3e | 222 | register int n; |
34082ede | 223 | u_char *sp; |
fbc82d3e | 224 | |
3182644d | 225 | for (cpp = dnptrs; cpp < lastdnptr; cpp++) { |
fbc82d3e RC |
226 | dn = exp_dn; |
227 | sp = cp = *cpp; | |
228 | while (n = *cp++) { | |
229 | /* | |
230 | * check for indirection | |
231 | */ | |
232 | switch (n & INDIR_MASK) { | |
233 | case 0: /* normal case, n == len */ | |
36534519 | 234 | while (--n >= 0) { |
f2cfc0ce JB |
235 | if (*dn == '.') |
236 | goto next; | |
36534519 RC |
237 | if (*dn == '\\') |
238 | dn++; | |
fbc82d3e RC |
239 | if (*dn++ != *cp++) |
240 | goto next; | |
36534519 | 241 | } |
fbc82d3e RC |
242 | if ((n = *dn++) == '\0' && *cp == '\0') |
243 | return (sp - msg); | |
244 | if (n == '.') | |
245 | continue; | |
246 | goto next; | |
247 | ||
248 | default: /* illegal type */ | |
249 | return (-1); | |
250 | ||
251 | case INDIR_MASK: /* indirection */ | |
34082ede | 252 | cp = msg + (((n & 0x3f) << 8) | *cp); |
fbc82d3e RC |
253 | } |
254 | } | |
255 | if (*dn == '\0') | |
256 | return (sp - msg); | |
257 | next: ; | |
258 | } | |
259 | return (-1); | |
260 | } | |
11e57e73 RC |
261 | |
262 | /* | |
263 | * Routines to insert/extract short/long's. Must account for byte | |
264 | * order and non-alignment problems. This code at least has the | |
265 | * advantage of being portable. | |
414b2e0c KB |
266 | * |
267 | * used by sendmail. | |
11e57e73 RC |
268 | */ |
269 | ||
270 | u_short | |
20087cad | 271 | _getshort(msgp) |
34082ede | 272 | u_char *msgp; |
11e57e73 RC |
273 | { |
274 | register u_char *p = (u_char *) msgp; | |
a34de0ef JB |
275 | #ifdef vax |
276 | /* | |
277 | * vax compiler doesn't put shorts in registers | |
278 | */ | |
279 | register u_long u; | |
280 | #else | |
27a3141f | 281 | register u_short u; |
a34de0ef | 282 | #endif |
11e57e73 | 283 | |
27a3141f | 284 | u = *p++ << 8; |
a34de0ef | 285 | return ((u_short)(u | *p)); |
11e57e73 RC |
286 | } |
287 | ||
288 | u_long | |
20087cad | 289 | _getlong(msgp) |
34082ede | 290 | u_char *msgp; |
11e57e73 RC |
291 | { |
292 | register u_char *p = (u_char *) msgp; | |
577f64e7 | 293 | register u_long u; |
11e57e73 | 294 | |
577f64e7 KD |
295 | u = *p++; u <<= 8; |
296 | u |= *p++; u <<= 8; | |
297 | u |= *p++; u <<= 8; | |
298 | return (u | *p); | |
11e57e73 RC |
299 | } |
300 | ||
16dfe61e KB |
301 | void |
302 | #ifdef __STDC__ | |
303 | __putshort(register u_short s, register u_char *msgp) | |
304 | #else | |
371d3c9b | 305 | __putshort(s, msgp) |
11e57e73 | 306 | register u_short s; |
34082ede | 307 | register u_char *msgp; |
16dfe61e | 308 | #endif |
11e57e73 | 309 | { |
11e57e73 RC |
310 | msgp[1] = s; |
311 | msgp[0] = s >> 8; | |
312 | } | |
313 | ||
16dfe61e | 314 | void |
371d3c9b | 315 | __putlong(l, msgp) |
11e57e73 | 316 | register u_long l; |
34082ede | 317 | register u_char *msgp; |
11e57e73 | 318 | { |
11e57e73 RC |
319 | msgp[3] = l; |
320 | msgp[2] = (l >>= 8); | |
321 | msgp[1] = (l >>= 8); | |
322 | msgp[0] = l >> 8; | |
323 | } |