sockaddr's now require length (K. Sklower);
[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 *
5 * Redistribution and use in source and binary forms are permitted
f4f66d2c
KB
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.
b423e985
RC
16 */
17
2ce81398 18#if defined(LIBC_SCCS) && !defined(lint)
f4f66d2c 19static char sccsid[] = "@(#)res_comp.c 6.14 (Berkeley) %G%";
6b2f9dd0 20#endif /* LIBC_SCCS and not lint */
8ea4199d 21
fbc82d3e
RC
22#include <sys/types.h>
23#include <stdio.h>
aa45ab0f 24#include <arpa/nameser.h>
fbc82d3e 25
fbc82d3e 26/*
36534519 27 * Expand compressed domain name 'comp_dn' to full domain name.
36534519 28 * 'msg' is a pointer to the begining of the message,
127b68cb 29 * 'eomorig' points to the first location after the message,
36534519 30 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
fbc82d3e
RC
31 * Return size of compressed name or -1 if there was an error.
32 */
127b68cb 33dn_expand(msg, eomorig, comp_dn, exp_dn, length)
34082ede 34 u_char *msg, *eomorig, *comp_dn, *exp_dn;
127b68cb 35 int length;
fbc82d3e 36{
34082ede 37 register u_char *cp, *dn;
fbc82d3e 38 register int n, c;
34082ede 39 u_char *eom;
19f533a7 40 int len = -1, checked = 0;
fbc82d3e
RC
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:
36534519
RC
54 if (dn != exp_dn) {
55 if (dn >= eom)
56 return (-1);
fbc82d3e 57 *dn++ = '.';
36534519 58 }
fbc82d3e
RC
59 if (dn+n >= eom)
60 return (-1);
19f533a7 61 checked += n + 1;
91c656a0 62 while (--n >= 0) {
80f420a7
JB
63 if ((c = *cp++) == '.') {
64 if (dn+n+1 >= eom)
65 return (-1);
66 *dn++ = '\\';
36534519 67 }
80f420a7 68 *dn++ = c;
127b68cb 69 if (cp >= eomorig) /* out of range */
91c656a0
KD
70 return(-1);
71 }
fbc82d3e
RC
72 break;
73
74 case INDIR_MASK:
36534519 75 if (len < 0)
fbc82d3e
RC
76 len = cp - comp_dn + 1;
77 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
127b68cb 78 if (cp < msg || cp >= eomorig) /* out of range */
91c656a0 79 return(-1);
19f533a7
MK
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);
fbc82d3e
RC
88 break;
89
90 default:
91 return (-1); /* flag error */
92 }
93 }
94 *dn = '\0';
36534519 95 if (len < 0)
fbc82d3e
RC
96 len = cp - comp_dn;
97 return (len);
98}
99
100/*
36534519
RC
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]
fbc82d3e 105 * is a pointer to the beginning of the message. The list ends with NULL.
36534519
RC
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.
fbc82d3e
RC
111 */
112dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
34082ede 113 u_char *exp_dn, *comp_dn;
fbc82d3e 114 int length;
34082ede 115 u_char **dnptrs, **lastdnptr;
fbc82d3e 116{
34082ede 117 register u_char *cp, *dn;
fbc82d3e 118 register int c, l;
34082ede
MK
119 u_char **cpp, **lpp, *sp, *eob;
120 u_char *msg;
fbc82d3e
RC
121
122 dn = exp_dn;
123 cp = comp_dn;
a34de0ef 124 eob = cp + length;
fbc82d3e
RC
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;
659c2773 140 *cp++ = l % 256;
fbc82d3e
RC
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 }
36534519
RC
155 if (c == '\\') {
156 if ((c = *dn++) == '\0')
157 break;
158 }
fbc82d3e
RC
159 if (cp >= eob)
160 return (-1);
161 *cp++ = c;
162 } while ((c = *dn++) != '\0');
36534519
RC
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)
fbc82d3e
RC
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/*
36534519 179 * Skip over a compressed domain name. Return the size or -1.
fbc82d3e 180 */
34082ede
MK
181dn_skipname(comp_dn, eom)
182 u_char *comp_dn, *eom;
fbc82d3e 183{
34082ede 184 register u_char *cp;
fbc82d3e
RC
185 register int n;
186
36534519 187 cp = comp_dn;
34082ede 188 while (cp < eom && (n = *cp++)) {
fbc82d3e
RC
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 }
36534519 203 return (cp - comp_dn);
fbc82d3e
RC
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.
3182644d
MK
209 * dnptrs is the pointer to the first name on the list,
210 * not the pointer to the start of the message.
fbc82d3e 211 */
3182644d 212static
fbc82d3e 213dn_find(exp_dn, msg, dnptrs, lastdnptr)
34082ede
MK
214 u_char *exp_dn, *msg;
215 u_char **dnptrs, **lastdnptr;
fbc82d3e 216{
34082ede 217 register u_char *dn, *cp, **cpp;
fbc82d3e 218 register int n;
34082ede 219 u_char *sp;
fbc82d3e 220
3182644d 221 for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
fbc82d3e
RC
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 */
36534519
RC
230 while (--n >= 0) {
231 if (*dn == '\\')
232 dn++;
fbc82d3e
RC
233 if (*dn++ != *cp++)
234 goto next;
36534519 235 }
fbc82d3e
RC
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 */
34082ede 246 cp = msg + (((n & 0x3f) << 8) | *cp);
fbc82d3e
RC
247 }
248 }
249 if (*dn == '\0')
250 return (sp - msg);
251 next: ;
252 }
253 return (-1);
254}
11e57e73
RC
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.
414b2e0c
KB
260 *
261 * used by sendmail.
11e57e73
RC
262 */
263
264u_short
20087cad 265_getshort(msgp)
34082ede 266 u_char *msgp;
11e57e73
RC
267{
268 register u_char *p = (u_char *) msgp;
a34de0ef
JB
269#ifdef vax
270 /*
271 * vax compiler doesn't put shorts in registers
272 */
273 register u_long u;
274#else
27a3141f 275 register u_short u;
a34de0ef 276#endif
11e57e73 277
27a3141f 278 u = *p++ << 8;
a34de0ef 279 return ((u_short)(u | *p));
11e57e73
RC
280}
281
282u_long
20087cad 283_getlong(msgp)
34082ede 284 u_char *msgp;
11e57e73
RC
285{
286 register u_char *p = (u_char *) msgp;
577f64e7 287 register u_long u;
11e57e73 288
577f64e7
KD
289 u = *p++; u <<= 8;
290 u |= *p++; u <<= 8;
291 u |= *p++; u <<= 8;
292 return (u | *p);
11e57e73
RC
293}
294
577f64e7 295
11e57e73
RC
296putshort(s, msgp)
297 register u_short s;
34082ede 298 register u_char *msgp;
11e57e73
RC
299{
300
301 msgp[1] = s;
302 msgp[0] = s >> 8;
303}
304
11e57e73
RC
305putlong(l, msgp)
306 register u_long l;
34082ede 307 register u_char *msgp;
11e57e73
RC
308{
309
310 msgp[3] = l;
311 msgp[2] = (l >>= 8);
312 msgp[1] = (l >>= 8);
313 msgp[0] = l >> 8;
314}