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