minor scattered syntax nits reported or inspired by Mike Kupfer
[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)
f2cfc0ce 19static char sccsid[] = "@(#)res_comp.c 6.15 (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;
f2cfc0ce 44 eom = exp_dn + length;
fbc82d3e
RC
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 }
f2cfc0ce
JB
159 if (cp >= eob) {
160 if (msg != NULL)
161 *lpp = NULL;
fbc82d3e 162 return (-1);
f2cfc0ce 163 }
fbc82d3e
RC
164 *cp++ = c;
165 } while ((c = *dn++) != '\0');
36534519
RC
166 /* catch trailing '.'s but not '..' */
167 if ((l = cp - sp - 1) == 0 && c == '\0') {
168 cp--;
169 break;
170 }
f2cfc0ce
JB
171 if (l <= 0 || l > MAXLABEL) {
172 if (msg != NULL)
173 *lpp = NULL;
fbc82d3e 174 return (-1);
f2cfc0ce 175 }
fbc82d3e
RC
176 *sp = l;
177 }
f2cfc0ce
JB
178 if (cp >= eob) {
179 if (msg != NULL)
180 *lpp = NULL;
fbc82d3e 181 return (-1);
f2cfc0ce 182 }
fbc82d3e
RC
183 *cp++ = '\0';
184 return (cp - comp_dn);
185}
186
187/*
36534519 188 * Skip over a compressed domain name. Return the size or -1.
fbc82d3e 189 */
34082ede
MK
190dn_skipname(comp_dn, eom)
191 u_char *comp_dn, *eom;
fbc82d3e 192{
34082ede 193 register u_char *cp;
fbc82d3e
RC
194 register int n;
195
36534519 196 cp = comp_dn;
34082ede 197 while (cp < eom && (n = *cp++)) {
fbc82d3e
RC
198 /*
199 * check for indirection
200 */
201 switch (n & INDIR_MASK) {
202 case 0: /* normal case, n == len */
203 cp += n;
204 continue;
205 default: /* illegal type */
206 return (-1);
207 case INDIR_MASK: /* indirection */
208 cp++;
209 }
210 break;
211 }
36534519 212 return (cp - comp_dn);
fbc82d3e
RC
213}
214
215/*
216 * Search for expanded name from a list of previously compressed names.
217 * Return the offset from msg if found or -1.
3182644d
MK
218 * dnptrs is the pointer to the first name on the list,
219 * not the pointer to the start of the message.
fbc82d3e 220 */
3182644d 221static
fbc82d3e 222dn_find(exp_dn, msg, dnptrs, lastdnptr)
34082ede
MK
223 u_char *exp_dn, *msg;
224 u_char **dnptrs, **lastdnptr;
fbc82d3e 225{
34082ede 226 register u_char *dn, *cp, **cpp;
fbc82d3e 227 register int n;
34082ede 228 u_char *sp;
fbc82d3e 229
3182644d 230 for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
fbc82d3e
RC
231 dn = exp_dn;
232 sp = cp = *cpp;
233 while (n = *cp++) {
234 /*
235 * check for indirection
236 */
237 switch (n & INDIR_MASK) {
238 case 0: /* normal case, n == len */
36534519 239 while (--n >= 0) {
f2cfc0ce
JB
240 if (*dn == '.')
241 goto next;
36534519
RC
242 if (*dn == '\\')
243 dn++;
fbc82d3e
RC
244 if (*dn++ != *cp++)
245 goto next;
36534519 246 }
fbc82d3e
RC
247 if ((n = *dn++) == '\0' && *cp == '\0')
248 return (sp - msg);
249 if (n == '.')
250 continue;
251 goto next;
252
253 default: /* illegal type */
254 return (-1);
255
256 case INDIR_MASK: /* indirection */
34082ede 257 cp = msg + (((n & 0x3f) << 8) | *cp);
fbc82d3e
RC
258 }
259 }
260 if (*dn == '\0')
261 return (sp - msg);
262 next: ;
263 }
264 return (-1);
265}
11e57e73
RC
266
267/*
268 * Routines to insert/extract short/long's. Must account for byte
269 * order and non-alignment problems. This code at least has the
270 * advantage of being portable.
414b2e0c
KB
271 *
272 * used by sendmail.
11e57e73
RC
273 */
274
275u_short
20087cad 276_getshort(msgp)
34082ede 277 u_char *msgp;
11e57e73
RC
278{
279 register u_char *p = (u_char *) msgp;
a34de0ef
JB
280#ifdef vax
281 /*
282 * vax compiler doesn't put shorts in registers
283 */
284 register u_long u;
285#else
27a3141f 286 register u_short u;
a34de0ef 287#endif
11e57e73 288
27a3141f 289 u = *p++ << 8;
a34de0ef 290 return ((u_short)(u | *p));
11e57e73
RC
291}
292
293u_long
20087cad 294_getlong(msgp)
34082ede 295 u_char *msgp;
11e57e73
RC
296{
297 register u_char *p = (u_char *) msgp;
577f64e7 298 register u_long u;
11e57e73 299
577f64e7
KD
300 u = *p++; u <<= 8;
301 u |= *p++; u <<= 8;
302 u |= *p++; u <<= 8;
303 return (u | *p);
11e57e73
RC
304}
305
577f64e7 306
11e57e73
RC
307putshort(s, msgp)
308 register u_short s;
34082ede 309 register u_char *msgp;
11e57e73
RC
310{
311
312 msgp[1] = s;
313 msgp[0] = s >> 8;
314}
315
11e57e73
RC
316putlong(l, msgp)
317 register u_long l;
34082ede 318 register u_char *msgp;
11e57e73
RC
319{
320
321 msgp[3] = l;
322 msgp[2] = (l >>= 8);
323 msgp[1] = (l >>= 8);
324 msgp[0] = l >> 8;
325}