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