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