2 * Copyright (c) 1985 Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted provided
6 * that: (1) source distributions retain this entire copyright notice and
7 * comment, and (2) distributions including binaries display the following
8 * acknowledgement: ``This product includes software developed by the
9 * University of California, Berkeley and its contributors'' in the
10 * documentation or other materials provided with the distribution and in
11 * all advertising materials mentioning features or use of this software.
12 * Neither the name of the University nor the names of its contributors may
13 * be used to endorse or promote products derived from this software without
14 * specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 #if defined(LIBC_SCCS) && !defined(lint)
21 static char sccsid
[] = "@(#)res_comp.c 6.18 (Berkeley) 6/27/90";
22 #endif /* LIBC_SCCS and not lint */
25 #include <sys/types.h>
28 #include <net/gen/in.h>
29 #include <net/gen/nameser.h>
30 #include <net/gen/resolv.h>
32 static int dn_find
_ARGS(( const u_char
*exp_dn
, const u_char
*msg
,
33 u_char
**dnptrs
, u_char
**lastdnptr
));
34 int dn_skipname
_ARGS(( const u_char
*comp_dn
, const u_char
*eom
));
36 #define getshort _getshort
37 #define getlong _getlong
38 #define putshort __putshort
39 #define putlong __putlong
41 #include <sys/types.h>
43 #include <arpa/nameser.h>
55 * Expand compressed domain name 'comp_dn' to full domain name.
56 * 'msg' is a pointer to the begining of the message,
57 * 'eomorig' points to the first location after the message,
58 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
59 * Return size of compressed name or -1 if there was an error.
61 dn_expand(msg
, eomorig
, comp_dn
, exp_dn
, length
)
62 CONST u_char
*msg
, *eomorig
, *comp_dn
;
66 register CONST u_char
*cp
;
70 int len
= -1, checked
= 0;
74 eom
= exp_dn
+ length
;
76 * fetch next label in domain name
80 * Check for indirection
82 switch (n
& INDIR_MASK
) {
93 if ((c
= *cp
++) == '.') {
94 if (dn
+ n
+ 2 >= eom
)
99 if (cp
>= eomorig
) /* out of range */
106 len
= cp
- comp_dn
+ 1;
107 cp
= msg
+ (((n
& 0x3f) << 8) | (*cp
& 0xff));
108 if (cp
< msg
|| cp
>= eomorig
) /* out of range */
112 * Check for loops in the compressed name;
113 * if we've looked at the whole message,
114 * there must be a loop.
116 if (checked
>= eomorig
- msg
)
121 return (-1); /* flag error */
131 * Compress domain name 'exp_dn' into 'comp_dn'.
132 * Return the size of the compressed name or -1.
133 * 'length' is the size of the array pointed to by 'comp_dn'.
134 * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
135 * is a pointer to the beginning of the message. The list ends with NULL.
136 * 'lastdnptr' is a pointer to the end of the arrary pointed to
137 * by 'dnptrs'. Side effect is to update the list of pointers for
138 * labels inserted into the message as we compress the name.
139 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
140 * is NULL, we don't update the list.
143 dn_comp(exp_dn
, comp_dn
, length
, dnptrs
, lastdnptr
)
144 CONST u_char
*exp_dn
;
147 u_char
**dnptrs
, **lastdnptr
;
150 register CONST u_char
*dn
;
152 u_char
**cpp
, **lpp
, *sp
, *eob
;
158 if (dnptrs
!= NULL
) {
159 if ((msg
= *dnptrs
++) != NULL
) {
160 for (cpp
= dnptrs
; *cpp
!= NULL
; cpp
++)
162 lpp
= cpp
; /* end of list to search */
166 for (c
= *dn
++; c
!= '\0'; ) {
167 /* look to see if we can use pointers */
169 if ((l
= dn_find(dn
-1, msg
, dnptrs
, lpp
)) >= 0) {
172 *cp
++ = (l
>> 8) | INDIR_MASK
;
174 return (cp
- comp_dn
);
176 /* not found, save it */
177 if (lastdnptr
!= NULL
&& cpp
< lastdnptr
-1) {
182 sp
= cp
++; /* save ptr to length byte */
189 if ((c
= *dn
++) == '\0')
198 } while ((c
= *dn
++) != '\0');
199 /* catch trailing '.'s but not '..' */
200 if ((l
= cp
- sp
- 1) == 0 && c
== '\0') {
204 if (l
<= 0 || l
> MAXLABEL
) {
217 return (cp
- comp_dn
);
221 * Skip over a compressed domain name. Return the size or -1.
223 dn_skipname(comp_dn
, eom
)
224 CONST u_char
*comp_dn
, *eom
;
226 register CONST u_char
*cp
;
230 while (cp
< eom
&& (n
= *cp
++)) {
232 * check for indirection
234 switch (n
& INDIR_MASK
) {
235 case 0: /* normal case, n == len */
238 default: /* illegal type */
240 case INDIR_MASK
: /* indirection */
245 return (cp
- comp_dn
);
249 * Search for expanded name from a list of previously compressed names.
250 * Return the offset from msg if found or -1.
251 * dnptrs is the pointer to the first name on the list,
252 * not the pointer to the start of the message.
255 dn_find(exp_dn
, msg
, dnptrs
, lastdnptr
)
256 CONST u_char
*exp_dn
, *msg
;
257 u_char
**dnptrs
, **lastdnptr
;
259 CONST
register u_char
*dn
, *cp
;
260 register u_char
**cpp
;
264 for (cpp
= dnptrs
; cpp
< lastdnptr
; cpp
++) {
269 * check for indirection
271 switch (n
& INDIR_MASK
) {
272 case 0: /* normal case, n == len */
281 if ((n
= *dn
++) == '\0' && *cp
== '\0')
287 default: /* illegal type */
290 case INDIR_MASK
: /* indirection */
291 cp
= msg
+ (((n
& 0x3f) << 8) | *cp
);
302 * Routines to insert/extract short/long's. Must account for byte
303 * order and non-alignment problems. This code at least has the
304 * advantage of being portable.
313 return ((msgp
[0] << 8) | (msgp
[1] << 0));
320 return ( ((u32_t
) msgp
[0] << 24)
321 | ((u32_t
) msgp
[1] << 16)
322 | ((u32_t
) msgp
[2] << 8)
323 | ((u32_t
) msgp
[3] << 0));