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