flag fields are u_int's
[unix-history] / usr / src / lib / libc / net / res_comp.c
CommitLineData
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)
16dfe61e 9static char sccsid[] = "@(#)res_comp.c 6.21 (Berkeley) %G%";
6b2f9dd0 10#endif /* LIBC_SCCS and not lint */
8ea4199d 11
fbc82d3e 12#include <sys/types.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
18static 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 27dn_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 */
107dn_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 216static
fbc82d3e 217dn_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
270u_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
288u_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
301void
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 314void
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}