Watt-32 tcp/ip  2.2 dev-rel.10
res_comp.c
Go to the documentation of this file.
1 
5 /* ++Copyright++ 1985, 1993
6  * -
7  * Copyright (c) 1985, 1993
8  * The Regents of the University of California. All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  * must display the following acknowledgement:
20  * This product includes software developed by the University of
21  * California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  * may be used to endorse or promote products derived from this software
24  * without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  * -
38  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
39  *
40  * Permission to use, copy, modify, and distribute this software for any
41  * purpose with or without fee is hereby granted, provided that the above
42  * copyright notice and this permission notice appear in all copies, and that
43  * the name of Digital Equipment Corporation not be used in advertising or
44  * publicity pertaining to distribution of the document or software without
45  * specific, written prior permission.
46  *
47  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
48  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
49  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
50  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
51  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
52  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
53  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54  * SOFTWARE.
55  * -
56  * --Copyright--
57  */
58 
59 #include "resolver.h"
60 
61 #if defined(USE_BIND)
62 
63 static int mklower (int);
64 static int dn_find (u_char *, u_char *, u_char **, u_char **);
65 
66 /*
67  * Expand compressed domain name 'comp_dn' to full domain name.
68  * 'msg' is a pointer to the begining of the message,
69  * 'eom_orig' points to the first location after the message,
70  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
71  * Return size of compressed name or -1 if there was an error.
72  */
73 int W32_CALL dn_expand (const u_char *msg, const u_char *eom_orig,
74  const u_char *comp_dn, char *exp_dn, int length)
75 {
76  const u_char *cp;
77  char *dn, *eom;
78  int n, len = -1, checked = 0;
79 
80  dn = exp_dn;
81  cp = comp_dn;
82  eom = exp_dn + length;
83 
84  /* Fetch next label in domain name
85  */
86  while ((n = *cp++) != 0)
87  {
88  /* Check for indirection
89  */
90  switch (n & INDIR_MASK)
91  {
92  case 0:
93  if (dn != exp_dn)
94  {
95  if (dn >= eom)
96  return (-1);
97  *dn++ = '.';
98  }
99  if (dn+n >= eom)
100  return (-1);
101  checked += n + 1;
102  while (--n >= 0)
103  {
104  int c = *cp++;
105  if ((c == '.') || (c == '\\'))
106  {
107  if (dn + n + 2 >= eom)
108  return (-1);
109  *dn++ = '\\';
110  }
111  *dn++ = c;
112  if (cp >= eom_orig) /* out of range */
113  return (-1);
114  }
115  break;
116 
117  case INDIR_MASK:
118  if (len < 0)
119  len = cp - comp_dn + 1;
120  cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
121  if (cp < msg || cp >= eom_orig) /* out of range */
122  return (-1);
123  checked += 2;
124  /*
125  * Check for loops in the compressed name;
126  * if we've looked at the whole message,
127  * there must be a loop.
128  */
129  if (checked >= eom_orig - msg)
130  return (-1);
131  break;
132 
133  default:
134  return (-1); /* flag error */
135  }
136  }
137 
138  *dn = '\0';
139  {
140  int c;
141  for (dn = exp_dn; (c = *dn) != '\0'; dn++)
142  if (isascii(c) && isspace(c))
143  return (-1);
144  }
145 
146  if (len < 0)
147  len = cp - comp_dn;
148  return (len);
149 }
150 
151 /*
152  * Compress domain name 'exp_dn' into 'comp_dn'.
153  * Return the size of the compressed name or -1.
154  * 'length' is the size of the array pointed to by 'comp_dn'.
155  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
156  * is a pointer to the beginning of the message. The list ends with NULL.
157  * 'lastdnptr' is a pointer to the end of the arrary pointed to
158  * by 'dnptrs'. Side effect is to update the list of pointers for
159  * labels inserted into the message as we compress the name.
160  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
161  * is NULL, we don't update the list.
162  */
163 int W32_CALL dn_comp (const char *exp_dn, u_char *comp_dn, int length,
164  u_char **dnptrs, u_char **lastdnptr)
165 {
166  u_char *cp, *dn;
167  u_char **cpp, **lpp, *eob;
168  u_char *msg;
169  u_char *sp = NULL;
170  int c, l = 0;
171 
172  dn = (u_char *)exp_dn;
173  cp = comp_dn;
174  eob = cp + length;
175  lpp = cpp = NULL;
176  if (dnptrs)
177  {
178  if ((msg = *dnptrs++) != NULL)
179  {
180  for (cpp = dnptrs; *cpp; cpp++)
181  ;
182  lpp = cpp; /* end of list to search */
183  }
184  }
185  else
186  msg = NULL;
187 
188  for (c = *dn++; c != '\0'; )
189  {
190  /* look to see if we can use pointers */
191  if (msg)
192  {
193  if ((l = dn_find (dn-1, msg, dnptrs, lpp)) >= 0)
194  {
195  if (cp+1 >= eob)
196  return (-1);
197  *cp++ = (l >> 8) | INDIR_MASK;
198  *cp++ = l % 256;
199  return (cp - comp_dn);
200  }
201  /* not found, save it */
202  if (lastdnptr && cpp < lastdnptr-1)
203  {
204  *cpp++ = cp;
205  *cpp = NULL;
206  }
207  }
208  sp = cp++; /* save ptr to length byte */
209  do
210  {
211  if (c == '.')
212  {
213  c = *dn++;
214  break;
215  }
216  if (c == '\\')
217  {
218  if ((c = *dn++) == '\0')
219  break;
220  }
221  if (cp >= eob)
222  {
223  if (msg)
224  *lpp = NULL;
225  return (-1);
226  }
227  *cp++ = c;
228  }
229  while ((c = *dn++) != '\0');
230 
231  /* catch trailing '.'s but not '..' */
232  if ((l = cp - sp - 1) == 0 && c == '\0')
233  {
234  cp--;
235  break;
236  }
237  if (l <= 0 || l > MAXLABEL)
238  {
239  if (msg)
240  *lpp = NULL;
241  return (-1);
242  }
243  *sp = l;
244  }
245  if (cp >= eob)
246  {
247  if (msg)
248  *lpp = NULL;
249  return (-1);
250  }
251  *cp++ = '\0';
252  return (cp - comp_dn);
253 }
254 
255 /*
256  * Skip over a compressed domain name. Return the size or -1.
257  */
258 int W32_CALL __dn_skipname (const u_char *comp_dn, const u_char *eom)
259 {
260  const u_char *cp = comp_dn;
261 
262  while (cp < eom)
263  {
264  int n = *cp++;
265  if (!n)
266  break;
267 
268  /* check for indirection
269  */
270  switch (n & INDIR_MASK)
271  {
272  case 0: /* normal case, n == len */
273  cp += n;
274  continue;
275  case INDIR_MASK: /* indirection */
276  cp++;
277  break;
278  default: /* illegal type */
279  return (-1);
280  }
281  break;
282  }
283  if (cp > eom)
284  return (-1);
285  return (cp - comp_dn);
286 }
287 
288 
289 static int mklower (int ch)
290 {
291  if (isascii(ch) && isupper(ch))
292  return (tolower(ch));
293  return (ch);
294 }
295 
296 /*
297  * Search for expanded name from a list of previously compressed names.
298  * Return the offset from msg if found or -1.
299  * dnptrs is the pointer to the first name on the list,
300  * not the pointer to the start of the message.
301  */
302 static int dn_find (u_char *exp_dn, u_char *msg, u_char **dnptrs, u_char **lastdnptr)
303 {
304  u_char **cpp;
305 
306  for (cpp = dnptrs; cpp < lastdnptr; cpp++)
307  {
308  u_char *dn = exp_dn;
309  u_char *sp = *cpp;
310  u_char *cp = *cpp;
311  int n;
312 
313  while ((n = *cp++) != 0)
314  {
315  /*
316  * check for indirection
317  */
318  switch (n & INDIR_MASK)
319  {
320  case 0: /* normal case, n == len */
321  while (--n >= 0)
322  {
323  if (*dn == '.')
324  goto next;
325  if (*dn == '\\')
326  dn++;
327  if (mklower(*dn++) != mklower(*cp++))
328  goto next;
329  }
330  if ((n = *dn++) == '\0' && *cp == '\0')
331  return (sp - msg);
332  if (n == '.')
333  continue;
334  goto next;
335 
336  case INDIR_MASK: /* indirection */
337  cp = msg + (((n & 0x3f) << 8) | *cp);
338  break;
339 
340  default: /* illegal type */
341  return (-1);
342  }
343  }
344  if (*dn == '\0')
345  return (sp - msg);
346  next: ;
347  }
348  return (-1);
349 }
350 #endif /* USE_BIND */
351