1*8d67ca89SAndroid Build Coastguard Worker /* $NetBSD: ns_name.c,v 1.9 2012/03/13 21:13:39 christos Exp $ */
2*8d67ca89SAndroid Build Coastguard Worker
3*8d67ca89SAndroid Build Coastguard Worker /*
4*8d67ca89SAndroid Build Coastguard Worker * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5*8d67ca89SAndroid Build Coastguard Worker * Copyright (c) 1996,1999 by Internet Software Consortium.
6*8d67ca89SAndroid Build Coastguard Worker *
7*8d67ca89SAndroid Build Coastguard Worker * Permission to use, copy, modify, and distribute this software for any
8*8d67ca89SAndroid Build Coastguard Worker * purpose with or without fee is hereby granted, provided that the above
9*8d67ca89SAndroid Build Coastguard Worker * copyright notice and this permission notice appear in all copies.
10*8d67ca89SAndroid Build Coastguard Worker *
11*8d67ca89SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12*8d67ca89SAndroid Build Coastguard Worker * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13*8d67ca89SAndroid Build Coastguard Worker * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14*8d67ca89SAndroid Build Coastguard Worker * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15*8d67ca89SAndroid Build Coastguard Worker * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*8d67ca89SAndroid Build Coastguard Worker * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17*8d67ca89SAndroid Build Coastguard Worker * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*8d67ca89SAndroid Build Coastguard Worker */
19*8d67ca89SAndroid Build Coastguard Worker
20*8d67ca89SAndroid Build Coastguard Worker #include <sys/cdefs.h>
21*8d67ca89SAndroid Build Coastguard Worker #ifndef lint
22*8d67ca89SAndroid Build Coastguard Worker #ifdef notdef
23*8d67ca89SAndroid Build Coastguard Worker static const char rcsid[] = "Id: ns_name.c,v 1.11 2009/01/23 19:59:16 each Exp";
24*8d67ca89SAndroid Build Coastguard Worker #else
25*8d67ca89SAndroid Build Coastguard Worker __RCSID("$NetBSD: ns_name.c,v 1.9 2012/03/13 21:13:39 christos Exp $");
26*8d67ca89SAndroid Build Coastguard Worker #endif
27*8d67ca89SAndroid Build Coastguard Worker #endif
28*8d67ca89SAndroid Build Coastguard Worker
29*8d67ca89SAndroid Build Coastguard Worker #include <sys/types.h>
30*8d67ca89SAndroid Build Coastguard Worker
31*8d67ca89SAndroid Build Coastguard Worker #include <netinet/in.h>
32*8d67ca89SAndroid Build Coastguard Worker #include <arpa/nameser.h>
33*8d67ca89SAndroid Build Coastguard Worker
34*8d67ca89SAndroid Build Coastguard Worker #include <assert.h>
35*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
36*8d67ca89SAndroid Build Coastguard Worker #ifdef ANDROID_CHANGES
37*8d67ca89SAndroid Build Coastguard Worker #include "resolv_private.h"
38*8d67ca89SAndroid Build Coastguard Worker #else
39*8d67ca89SAndroid Build Coastguard Worker #include <resolv.h>
40*8d67ca89SAndroid Build Coastguard Worker #endif
41*8d67ca89SAndroid Build Coastguard Worker #include <string.h>
42*8d67ca89SAndroid Build Coastguard Worker #include <ctype.h>
43*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
44*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
45*8d67ca89SAndroid Build Coastguard Worker
46*8d67ca89SAndroid Build Coastguard Worker #define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */
47*8d67ca89SAndroid Build Coastguard Worker #define DNS_LABELTYPE_BITSTRING 0x41
48*8d67ca89SAndroid Build Coastguard Worker
49*8d67ca89SAndroid Build Coastguard Worker /* Data. */
50*8d67ca89SAndroid Build Coastguard Worker
51*8d67ca89SAndroid Build Coastguard Worker static const char digits[] = "0123456789";
52*8d67ca89SAndroid Build Coastguard Worker
53*8d67ca89SAndroid Build Coastguard Worker static const char digitvalue[256] = {
54*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
55*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
56*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
57*8d67ca89SAndroid Build Coastguard Worker 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
58*8d67ca89SAndroid Build Coastguard Worker -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
59*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
60*8d67ca89SAndroid Build Coastguard Worker -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
61*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
62*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
63*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
65*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
66*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
67*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
68*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
69*8d67ca89SAndroid Build Coastguard Worker -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
70*8d67ca89SAndroid Build Coastguard Worker };
71*8d67ca89SAndroid Build Coastguard Worker
72*8d67ca89SAndroid Build Coastguard Worker /* Forward. */
73*8d67ca89SAndroid Build Coastguard Worker
74*8d67ca89SAndroid Build Coastguard Worker static int special(int);
75*8d67ca89SAndroid Build Coastguard Worker static int printable(int);
76*8d67ca89SAndroid Build Coastguard Worker static int dn_find(const u_char *, const u_char *,
77*8d67ca89SAndroid Build Coastguard Worker const u_char * const *,
78*8d67ca89SAndroid Build Coastguard Worker const u_char * const *);
79*8d67ca89SAndroid Build Coastguard Worker static int encode_bitsring(const char **, const char *,
80*8d67ca89SAndroid Build Coastguard Worker unsigned char **, unsigned char **,
81*8d67ca89SAndroid Build Coastguard Worker unsigned const char *);
82*8d67ca89SAndroid Build Coastguard Worker static int labellen(const u_char *);
83*8d67ca89SAndroid Build Coastguard Worker static int decode_bitstring(const unsigned char **,
84*8d67ca89SAndroid Build Coastguard Worker char *, const char *);
85*8d67ca89SAndroid Build Coastguard Worker
86*8d67ca89SAndroid Build Coastguard Worker /* Public. */
87*8d67ca89SAndroid Build Coastguard Worker
88*8d67ca89SAndroid Build Coastguard Worker /*
89*8d67ca89SAndroid Build Coastguard Worker * Convert an encoded domain name to printable ascii as per RFC1035.
90*8d67ca89SAndroid Build Coastguard Worker * return:
91*8d67ca89SAndroid Build Coastguard Worker * Number of bytes written to buffer, or -1 (with errno set)
92*8d67ca89SAndroid Build Coastguard Worker *
93*8d67ca89SAndroid Build Coastguard Worker * notes:
94*8d67ca89SAndroid Build Coastguard Worker * The root is returned as "."
95*8d67ca89SAndroid Build Coastguard Worker * All other domains are returned in non absolute form
96*8d67ca89SAndroid Build Coastguard Worker */
97*8d67ca89SAndroid Build Coastguard Worker int
ns_name_ntop(const u_char * src,char * dst,size_t dstsiz)98*8d67ca89SAndroid Build Coastguard Worker ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
99*8d67ca89SAndroid Build Coastguard Worker {
100*8d67ca89SAndroid Build Coastguard Worker const u_char *cp;
101*8d67ca89SAndroid Build Coastguard Worker char *dn, *eom;
102*8d67ca89SAndroid Build Coastguard Worker u_char c;
103*8d67ca89SAndroid Build Coastguard Worker u_int n;
104*8d67ca89SAndroid Build Coastguard Worker int l;
105*8d67ca89SAndroid Build Coastguard Worker
106*8d67ca89SAndroid Build Coastguard Worker cp = src;
107*8d67ca89SAndroid Build Coastguard Worker dn = dst;
108*8d67ca89SAndroid Build Coastguard Worker eom = dst + dstsiz;
109*8d67ca89SAndroid Build Coastguard Worker
110*8d67ca89SAndroid Build Coastguard Worker while ((n = *cp++) != 0) {
111*8d67ca89SAndroid Build Coastguard Worker if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
112*8d67ca89SAndroid Build Coastguard Worker /* Some kind of compression pointer. */
113*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
114*8d67ca89SAndroid Build Coastguard Worker return (-1);
115*8d67ca89SAndroid Build Coastguard Worker }
116*8d67ca89SAndroid Build Coastguard Worker if (dn != dst) {
117*8d67ca89SAndroid Build Coastguard Worker if (dn >= eom) {
118*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
119*8d67ca89SAndroid Build Coastguard Worker return (-1);
120*8d67ca89SAndroid Build Coastguard Worker }
121*8d67ca89SAndroid Build Coastguard Worker *dn++ = '.';
122*8d67ca89SAndroid Build Coastguard Worker }
123*8d67ca89SAndroid Build Coastguard Worker if ((l = labellen(cp - 1)) < 0) {
124*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE; /* XXX */
125*8d67ca89SAndroid Build Coastguard Worker return(-1);
126*8d67ca89SAndroid Build Coastguard Worker }
127*8d67ca89SAndroid Build Coastguard Worker if (dn + l >= eom) {
128*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
129*8d67ca89SAndroid Build Coastguard Worker return (-1);
130*8d67ca89SAndroid Build Coastguard Worker }
131*8d67ca89SAndroid Build Coastguard Worker if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
132*8d67ca89SAndroid Build Coastguard Worker int m;
133*8d67ca89SAndroid Build Coastguard Worker
134*8d67ca89SAndroid Build Coastguard Worker if (n != DNS_LABELTYPE_BITSTRING) {
135*8d67ca89SAndroid Build Coastguard Worker /* XXX: labellen should reject this case */
136*8d67ca89SAndroid Build Coastguard Worker errno = EINVAL;
137*8d67ca89SAndroid Build Coastguard Worker return(-1);
138*8d67ca89SAndroid Build Coastguard Worker }
139*8d67ca89SAndroid Build Coastguard Worker if ((m = decode_bitstring(&cp, dn, eom)) < 0)
140*8d67ca89SAndroid Build Coastguard Worker {
141*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
142*8d67ca89SAndroid Build Coastguard Worker return(-1);
143*8d67ca89SAndroid Build Coastguard Worker }
144*8d67ca89SAndroid Build Coastguard Worker dn += m;
145*8d67ca89SAndroid Build Coastguard Worker continue;
146*8d67ca89SAndroid Build Coastguard Worker }
147*8d67ca89SAndroid Build Coastguard Worker for (; l > 0; l--) {
148*8d67ca89SAndroid Build Coastguard Worker c = *cp++;
149*8d67ca89SAndroid Build Coastguard Worker if (special(c)) {
150*8d67ca89SAndroid Build Coastguard Worker if (dn + 1 >= eom) {
151*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
152*8d67ca89SAndroid Build Coastguard Worker return (-1);
153*8d67ca89SAndroid Build Coastguard Worker }
154*8d67ca89SAndroid Build Coastguard Worker *dn++ = '\\';
155*8d67ca89SAndroid Build Coastguard Worker *dn++ = (char)c;
156*8d67ca89SAndroid Build Coastguard Worker } else if (!printable(c)) {
157*8d67ca89SAndroid Build Coastguard Worker if (dn + 3 >= eom) {
158*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
159*8d67ca89SAndroid Build Coastguard Worker return (-1);
160*8d67ca89SAndroid Build Coastguard Worker }
161*8d67ca89SAndroid Build Coastguard Worker *dn++ = '\\';
162*8d67ca89SAndroid Build Coastguard Worker *dn++ = digits[c / 100];
163*8d67ca89SAndroid Build Coastguard Worker *dn++ = digits[(c % 100) / 10];
164*8d67ca89SAndroid Build Coastguard Worker *dn++ = digits[c % 10];
165*8d67ca89SAndroid Build Coastguard Worker } else {
166*8d67ca89SAndroid Build Coastguard Worker if (dn >= eom) {
167*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
168*8d67ca89SAndroid Build Coastguard Worker return (-1);
169*8d67ca89SAndroid Build Coastguard Worker }
170*8d67ca89SAndroid Build Coastguard Worker *dn++ = (char)c;
171*8d67ca89SAndroid Build Coastguard Worker }
172*8d67ca89SAndroid Build Coastguard Worker }
173*8d67ca89SAndroid Build Coastguard Worker }
174*8d67ca89SAndroid Build Coastguard Worker if (dn == dst) {
175*8d67ca89SAndroid Build Coastguard Worker if (dn >= eom) {
176*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
177*8d67ca89SAndroid Build Coastguard Worker return (-1);
178*8d67ca89SAndroid Build Coastguard Worker }
179*8d67ca89SAndroid Build Coastguard Worker *dn++ = '.';
180*8d67ca89SAndroid Build Coastguard Worker }
181*8d67ca89SAndroid Build Coastguard Worker if (dn >= eom) {
182*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
183*8d67ca89SAndroid Build Coastguard Worker return (-1);
184*8d67ca89SAndroid Build Coastguard Worker }
185*8d67ca89SAndroid Build Coastguard Worker *dn++ = '\0';
186*8d67ca89SAndroid Build Coastguard Worker _DIAGASSERT(__type_fit(int, dn - dst));
187*8d67ca89SAndroid Build Coastguard Worker return (int)(dn - dst);
188*8d67ca89SAndroid Build Coastguard Worker }
189*8d67ca89SAndroid Build Coastguard Worker
190*8d67ca89SAndroid Build Coastguard Worker /*
191*8d67ca89SAndroid Build Coastguard Worker * Convert a ascii string into an encoded domain name as per RFC1035.
192*8d67ca89SAndroid Build Coastguard Worker *
193*8d67ca89SAndroid Build Coastguard Worker * return:
194*8d67ca89SAndroid Build Coastguard Worker *
195*8d67ca89SAndroid Build Coastguard Worker * -1 if it fails
196*8d67ca89SAndroid Build Coastguard Worker * 1 if string was fully qualified
197*8d67ca89SAndroid Build Coastguard Worker * 0 is string was not fully qualified
198*8d67ca89SAndroid Build Coastguard Worker *
199*8d67ca89SAndroid Build Coastguard Worker * notes:
200*8d67ca89SAndroid Build Coastguard Worker * Enforces label and domain length limits.
201*8d67ca89SAndroid Build Coastguard Worker */
202*8d67ca89SAndroid Build Coastguard Worker int
ns_name_pton(const char * src,u_char * dst,size_t dstsiz)203*8d67ca89SAndroid Build Coastguard Worker ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
204*8d67ca89SAndroid Build Coastguard Worker return (ns_name_pton2(src, dst, dstsiz, NULL));
205*8d67ca89SAndroid Build Coastguard Worker }
206*8d67ca89SAndroid Build Coastguard Worker
207*8d67ca89SAndroid Build Coastguard Worker /*
208*8d67ca89SAndroid Build Coastguard Worker * ns_name_pton2(src, dst, dstsiz, *dstlen)
209*8d67ca89SAndroid Build Coastguard Worker * Convert a ascii string into an encoded domain name as per RFC1035.
210*8d67ca89SAndroid Build Coastguard Worker * return:
211*8d67ca89SAndroid Build Coastguard Worker * -1 if it fails
212*8d67ca89SAndroid Build Coastguard Worker * 1 if string was fully qualified
213*8d67ca89SAndroid Build Coastguard Worker * 0 is string was not fully qualified
214*8d67ca89SAndroid Build Coastguard Worker * side effects:
215*8d67ca89SAndroid Build Coastguard Worker * fills in *dstlen (if non-NULL)
216*8d67ca89SAndroid Build Coastguard Worker * notes:
217*8d67ca89SAndroid Build Coastguard Worker * Enforces label and domain length limits.
218*8d67ca89SAndroid Build Coastguard Worker */
219*8d67ca89SAndroid Build Coastguard Worker
220*8d67ca89SAndroid Build Coastguard Worker int
ns_name_pton2(const char * src,u_char * dst,size_t dstsiz,size_t * dstlen)221*8d67ca89SAndroid Build Coastguard Worker ns_name_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen) {
222*8d67ca89SAndroid Build Coastguard Worker u_char *label, *bp, *eom;
223*8d67ca89SAndroid Build Coastguard Worker int c, n, escaped, e = 0;
224*8d67ca89SAndroid Build Coastguard Worker char *cp;
225*8d67ca89SAndroid Build Coastguard Worker
226*8d67ca89SAndroid Build Coastguard Worker escaped = 0;
227*8d67ca89SAndroid Build Coastguard Worker bp = dst;
228*8d67ca89SAndroid Build Coastguard Worker eom = dst + dstsiz;
229*8d67ca89SAndroid Build Coastguard Worker label = bp++;
230*8d67ca89SAndroid Build Coastguard Worker
231*8d67ca89SAndroid Build Coastguard Worker while ((c = *src++) != 0) {
232*8d67ca89SAndroid Build Coastguard Worker if (escaped) {
233*8d67ca89SAndroid Build Coastguard Worker if (c == '[') { /* start a bit string label */
234*8d67ca89SAndroid Build Coastguard Worker if ((cp = strchr(src, ']')) == NULL) {
235*8d67ca89SAndroid Build Coastguard Worker errno = EINVAL; /* ??? */
236*8d67ca89SAndroid Build Coastguard Worker return(-1);
237*8d67ca89SAndroid Build Coastguard Worker }
238*8d67ca89SAndroid Build Coastguard Worker if ((e = encode_bitsring(&src, cp + 2,
239*8d67ca89SAndroid Build Coastguard Worker &label, &bp, eom))
240*8d67ca89SAndroid Build Coastguard Worker != 0) {
241*8d67ca89SAndroid Build Coastguard Worker errno = e;
242*8d67ca89SAndroid Build Coastguard Worker return(-1);
243*8d67ca89SAndroid Build Coastguard Worker }
244*8d67ca89SAndroid Build Coastguard Worker escaped = 0;
245*8d67ca89SAndroid Build Coastguard Worker label = bp++;
246*8d67ca89SAndroid Build Coastguard Worker if ((c = *src++) == 0)
247*8d67ca89SAndroid Build Coastguard Worker goto done;
248*8d67ca89SAndroid Build Coastguard Worker else if (c != '.') {
249*8d67ca89SAndroid Build Coastguard Worker errno = EINVAL;
250*8d67ca89SAndroid Build Coastguard Worker return(-1);
251*8d67ca89SAndroid Build Coastguard Worker }
252*8d67ca89SAndroid Build Coastguard Worker continue;
253*8d67ca89SAndroid Build Coastguard Worker }
254*8d67ca89SAndroid Build Coastguard Worker else if ((cp = strchr(digits, c)) != NULL) {
255*8d67ca89SAndroid Build Coastguard Worker n = (int)(cp - digits) * 100;
256*8d67ca89SAndroid Build Coastguard Worker if ((c = *src++) == 0 ||
257*8d67ca89SAndroid Build Coastguard Worker (cp = strchr(digits, c)) == NULL) {
258*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
259*8d67ca89SAndroid Build Coastguard Worker return (-1);
260*8d67ca89SAndroid Build Coastguard Worker }
261*8d67ca89SAndroid Build Coastguard Worker n += (int)(cp - digits) * 10;
262*8d67ca89SAndroid Build Coastguard Worker if ((c = *src++) == 0 ||
263*8d67ca89SAndroid Build Coastguard Worker (cp = strchr(digits, c)) == NULL) {
264*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
265*8d67ca89SAndroid Build Coastguard Worker return (-1);
266*8d67ca89SAndroid Build Coastguard Worker }
267*8d67ca89SAndroid Build Coastguard Worker n += (int)(cp - digits);
268*8d67ca89SAndroid Build Coastguard Worker if (n > 255) {
269*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
270*8d67ca89SAndroid Build Coastguard Worker return (-1);
271*8d67ca89SAndroid Build Coastguard Worker }
272*8d67ca89SAndroid Build Coastguard Worker c = n;
273*8d67ca89SAndroid Build Coastguard Worker }
274*8d67ca89SAndroid Build Coastguard Worker escaped = 0;
275*8d67ca89SAndroid Build Coastguard Worker } else if (c == '\\') {
276*8d67ca89SAndroid Build Coastguard Worker escaped = 1;
277*8d67ca89SAndroid Build Coastguard Worker continue;
278*8d67ca89SAndroid Build Coastguard Worker } else if (c == '.') {
279*8d67ca89SAndroid Build Coastguard Worker c = (int)(bp - label - 1);
280*8d67ca89SAndroid Build Coastguard Worker if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
281*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
282*8d67ca89SAndroid Build Coastguard Worker return (-1);
283*8d67ca89SAndroid Build Coastguard Worker }
284*8d67ca89SAndroid Build Coastguard Worker if (label >= eom) {
285*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
286*8d67ca89SAndroid Build Coastguard Worker return (-1);
287*8d67ca89SAndroid Build Coastguard Worker }
288*8d67ca89SAndroid Build Coastguard Worker *label = c;
289*8d67ca89SAndroid Build Coastguard Worker /* Fully qualified ? */
290*8d67ca89SAndroid Build Coastguard Worker if (*src == '\0') {
291*8d67ca89SAndroid Build Coastguard Worker if (c != 0) {
292*8d67ca89SAndroid Build Coastguard Worker if (bp >= eom) {
293*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
294*8d67ca89SAndroid Build Coastguard Worker return (-1);
295*8d67ca89SAndroid Build Coastguard Worker }
296*8d67ca89SAndroid Build Coastguard Worker *bp++ = '\0';
297*8d67ca89SAndroid Build Coastguard Worker }
298*8d67ca89SAndroid Build Coastguard Worker if ((bp - dst) > MAXCDNAME) {
299*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
300*8d67ca89SAndroid Build Coastguard Worker return (-1);
301*8d67ca89SAndroid Build Coastguard Worker }
302*8d67ca89SAndroid Build Coastguard Worker if (dstlen != NULL)
303*8d67ca89SAndroid Build Coastguard Worker *dstlen = (bp - dst);
304*8d67ca89SAndroid Build Coastguard Worker return (1);
305*8d67ca89SAndroid Build Coastguard Worker }
306*8d67ca89SAndroid Build Coastguard Worker if (c == 0 || *src == '.') {
307*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
308*8d67ca89SAndroid Build Coastguard Worker return (-1);
309*8d67ca89SAndroid Build Coastguard Worker }
310*8d67ca89SAndroid Build Coastguard Worker label = bp++;
311*8d67ca89SAndroid Build Coastguard Worker continue;
312*8d67ca89SAndroid Build Coastguard Worker }
313*8d67ca89SAndroid Build Coastguard Worker if (bp >= eom) {
314*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
315*8d67ca89SAndroid Build Coastguard Worker return (-1);
316*8d67ca89SAndroid Build Coastguard Worker }
317*8d67ca89SAndroid Build Coastguard Worker *bp++ = (u_char)c;
318*8d67ca89SAndroid Build Coastguard Worker }
319*8d67ca89SAndroid Build Coastguard Worker c = (int)(bp - label - 1);
320*8d67ca89SAndroid Build Coastguard Worker if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
321*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
322*8d67ca89SAndroid Build Coastguard Worker return (-1);
323*8d67ca89SAndroid Build Coastguard Worker }
324*8d67ca89SAndroid Build Coastguard Worker done:
325*8d67ca89SAndroid Build Coastguard Worker if (label >= eom) {
326*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
327*8d67ca89SAndroid Build Coastguard Worker return (-1);
328*8d67ca89SAndroid Build Coastguard Worker }
329*8d67ca89SAndroid Build Coastguard Worker *label = c;
330*8d67ca89SAndroid Build Coastguard Worker if (c != 0) {
331*8d67ca89SAndroid Build Coastguard Worker if (bp >= eom) {
332*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
333*8d67ca89SAndroid Build Coastguard Worker return (-1);
334*8d67ca89SAndroid Build Coastguard Worker }
335*8d67ca89SAndroid Build Coastguard Worker *bp++ = 0;
336*8d67ca89SAndroid Build Coastguard Worker }
337*8d67ca89SAndroid Build Coastguard Worker if ((bp - dst) > MAXCDNAME) { /* src too big */
338*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
339*8d67ca89SAndroid Build Coastguard Worker return (-1);
340*8d67ca89SAndroid Build Coastguard Worker }
341*8d67ca89SAndroid Build Coastguard Worker if (dstlen != NULL)
342*8d67ca89SAndroid Build Coastguard Worker *dstlen = (bp - dst);
343*8d67ca89SAndroid Build Coastguard Worker return (0);
344*8d67ca89SAndroid Build Coastguard Worker }
345*8d67ca89SAndroid Build Coastguard Worker
346*8d67ca89SAndroid Build Coastguard Worker /*
347*8d67ca89SAndroid Build Coastguard Worker * Convert a network strings labels into all lowercase.
348*8d67ca89SAndroid Build Coastguard Worker *
349*8d67ca89SAndroid Build Coastguard Worker * return:
350*8d67ca89SAndroid Build Coastguard Worker * Number of bytes written to buffer, or -1 (with errno set)
351*8d67ca89SAndroid Build Coastguard Worker *
352*8d67ca89SAndroid Build Coastguard Worker * notes:
353*8d67ca89SAndroid Build Coastguard Worker * Enforces label and domain length limits.
354*8d67ca89SAndroid Build Coastguard Worker */
355*8d67ca89SAndroid Build Coastguard Worker
356*8d67ca89SAndroid Build Coastguard Worker int
ns_name_ntol(const u_char * src,u_char * dst,size_t dstsiz)357*8d67ca89SAndroid Build Coastguard Worker ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
358*8d67ca89SAndroid Build Coastguard Worker {
359*8d67ca89SAndroid Build Coastguard Worker const u_char *cp;
360*8d67ca89SAndroid Build Coastguard Worker u_char *dn, *eom;
361*8d67ca89SAndroid Build Coastguard Worker u_char c;
362*8d67ca89SAndroid Build Coastguard Worker u_int n;
363*8d67ca89SAndroid Build Coastguard Worker int l;
364*8d67ca89SAndroid Build Coastguard Worker
365*8d67ca89SAndroid Build Coastguard Worker cp = src;
366*8d67ca89SAndroid Build Coastguard Worker dn = dst;
367*8d67ca89SAndroid Build Coastguard Worker eom = dst + dstsiz;
368*8d67ca89SAndroid Build Coastguard Worker
369*8d67ca89SAndroid Build Coastguard Worker if (dn >= eom) {
370*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
371*8d67ca89SAndroid Build Coastguard Worker return (-1);
372*8d67ca89SAndroid Build Coastguard Worker }
373*8d67ca89SAndroid Build Coastguard Worker while ((n = *cp++) != 0) {
374*8d67ca89SAndroid Build Coastguard Worker if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
375*8d67ca89SAndroid Build Coastguard Worker /* Some kind of compression pointer. */
376*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
377*8d67ca89SAndroid Build Coastguard Worker return (-1);
378*8d67ca89SAndroid Build Coastguard Worker }
379*8d67ca89SAndroid Build Coastguard Worker *dn++ = n;
380*8d67ca89SAndroid Build Coastguard Worker if ((l = labellen(cp - 1)) < 0) {
381*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
382*8d67ca89SAndroid Build Coastguard Worker return (-1);
383*8d67ca89SAndroid Build Coastguard Worker }
384*8d67ca89SAndroid Build Coastguard Worker if (dn + l >= eom) {
385*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
386*8d67ca89SAndroid Build Coastguard Worker return (-1);
387*8d67ca89SAndroid Build Coastguard Worker }
388*8d67ca89SAndroid Build Coastguard Worker for (; l > 0; l--) {
389*8d67ca89SAndroid Build Coastguard Worker c = *cp++;
390*8d67ca89SAndroid Build Coastguard Worker if (isascii(c) && isupper(c))
391*8d67ca89SAndroid Build Coastguard Worker *dn++ = tolower(c);
392*8d67ca89SAndroid Build Coastguard Worker else
393*8d67ca89SAndroid Build Coastguard Worker *dn++ = c;
394*8d67ca89SAndroid Build Coastguard Worker }
395*8d67ca89SAndroid Build Coastguard Worker }
396*8d67ca89SAndroid Build Coastguard Worker *dn++ = '\0';
397*8d67ca89SAndroid Build Coastguard Worker _DIAGASSERT(__type_fit(int, dn - dst));
398*8d67ca89SAndroid Build Coastguard Worker return (int)(dn - dst);
399*8d67ca89SAndroid Build Coastguard Worker }
400*8d67ca89SAndroid Build Coastguard Worker
401*8d67ca89SAndroid Build Coastguard Worker /*
402*8d67ca89SAndroid Build Coastguard Worker * Unpack a domain name from a message, source may be compressed.
403*8d67ca89SAndroid Build Coastguard Worker *
404*8d67ca89SAndroid Build Coastguard Worker * return:
405*8d67ca89SAndroid Build Coastguard Worker * -1 if it fails, or consumed octets if it succeeds.
406*8d67ca89SAndroid Build Coastguard Worker */
407*8d67ca89SAndroid Build Coastguard Worker int
ns_name_unpack(const u_char * msg,const u_char * eom,const u_char * src,u_char * dst,size_t dstsiz)408*8d67ca89SAndroid Build Coastguard Worker ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
409*8d67ca89SAndroid Build Coastguard Worker u_char *dst, size_t dstsiz)
410*8d67ca89SAndroid Build Coastguard Worker {
411*8d67ca89SAndroid Build Coastguard Worker return (ns_name_unpack2(msg, eom, src, dst, dstsiz, NULL));
412*8d67ca89SAndroid Build Coastguard Worker }
413*8d67ca89SAndroid Build Coastguard Worker
414*8d67ca89SAndroid Build Coastguard Worker /*
415*8d67ca89SAndroid Build Coastguard Worker * ns_name_unpack2(msg, eom, src, dst, dstsiz, *dstlen)
416*8d67ca89SAndroid Build Coastguard Worker * Unpack a domain name from a message, source may be compressed.
417*8d67ca89SAndroid Build Coastguard Worker * return:
418*8d67ca89SAndroid Build Coastguard Worker * -1 if it fails, or consumed octets if it succeeds.
419*8d67ca89SAndroid Build Coastguard Worker * side effect:
420*8d67ca89SAndroid Build Coastguard Worker * fills in *dstlen (if non-NULL).
421*8d67ca89SAndroid Build Coastguard Worker */
422*8d67ca89SAndroid Build Coastguard Worker int
ns_name_unpack2(const u_char * msg,const u_char * eom,const u_char * src,u_char * dst,size_t dstsiz,size_t * dstlen)423*8d67ca89SAndroid Build Coastguard Worker ns_name_unpack2(const u_char *msg, const u_char *eom, const u_char *src,
424*8d67ca89SAndroid Build Coastguard Worker u_char *dst, size_t dstsiz, size_t *dstlen)
425*8d67ca89SAndroid Build Coastguard Worker {
426*8d67ca89SAndroid Build Coastguard Worker const u_char *srcp, *dstlim;
427*8d67ca89SAndroid Build Coastguard Worker u_char *dstp;
428*8d67ca89SAndroid Build Coastguard Worker int n, len, checked, l;
429*8d67ca89SAndroid Build Coastguard Worker
430*8d67ca89SAndroid Build Coastguard Worker len = -1;
431*8d67ca89SAndroid Build Coastguard Worker checked = 0;
432*8d67ca89SAndroid Build Coastguard Worker dstp = dst;
433*8d67ca89SAndroid Build Coastguard Worker srcp = src;
434*8d67ca89SAndroid Build Coastguard Worker dstlim = dst + dstsiz;
435*8d67ca89SAndroid Build Coastguard Worker if (srcp < msg || srcp >= eom) {
436*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
437*8d67ca89SAndroid Build Coastguard Worker return (-1);
438*8d67ca89SAndroid Build Coastguard Worker }
439*8d67ca89SAndroid Build Coastguard Worker /* Fetch next label in domain name. */
440*8d67ca89SAndroid Build Coastguard Worker while ((n = *srcp++) != 0) {
441*8d67ca89SAndroid Build Coastguard Worker /* Check for indirection. */
442*8d67ca89SAndroid Build Coastguard Worker switch (n & NS_CMPRSFLGS) {
443*8d67ca89SAndroid Build Coastguard Worker case 0:
444*8d67ca89SAndroid Build Coastguard Worker case NS_TYPE_ELT:
445*8d67ca89SAndroid Build Coastguard Worker /* Limit checks. */
446*8d67ca89SAndroid Build Coastguard Worker if ((l = labellen(srcp - 1)) < 0) {
447*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
448*8d67ca89SAndroid Build Coastguard Worker return(-1);
449*8d67ca89SAndroid Build Coastguard Worker }
450*8d67ca89SAndroid Build Coastguard Worker if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
451*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
452*8d67ca89SAndroid Build Coastguard Worker return (-1);
453*8d67ca89SAndroid Build Coastguard Worker }
454*8d67ca89SAndroid Build Coastguard Worker checked += l + 1;
455*8d67ca89SAndroid Build Coastguard Worker *dstp++ = n;
456*8d67ca89SAndroid Build Coastguard Worker memcpy(dstp, srcp, (size_t)l);
457*8d67ca89SAndroid Build Coastguard Worker dstp += l;
458*8d67ca89SAndroid Build Coastguard Worker srcp += l;
459*8d67ca89SAndroid Build Coastguard Worker break;
460*8d67ca89SAndroid Build Coastguard Worker
461*8d67ca89SAndroid Build Coastguard Worker case NS_CMPRSFLGS:
462*8d67ca89SAndroid Build Coastguard Worker if (srcp >= eom) {
463*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
464*8d67ca89SAndroid Build Coastguard Worker return (-1);
465*8d67ca89SAndroid Build Coastguard Worker }
466*8d67ca89SAndroid Build Coastguard Worker if (len < 0) {
467*8d67ca89SAndroid Build Coastguard Worker _DIAGASSERT(__type_fit(int, srcp - src + 1));
468*8d67ca89SAndroid Build Coastguard Worker len = (int)(srcp - src + 1);
469*8d67ca89SAndroid Build Coastguard Worker }
470*8d67ca89SAndroid Build Coastguard Worker // BEGIN android-changed: safer pointer overflow check
471*8d67ca89SAndroid Build Coastguard Worker l = (((n & 0x3f) << 8) | (*srcp & 0xff));
472*8d67ca89SAndroid Build Coastguard Worker if (l >= eom - msg) { /* Out of range. */
473*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
474*8d67ca89SAndroid Build Coastguard Worker return (-1);
475*8d67ca89SAndroid Build Coastguard Worker }
476*8d67ca89SAndroid Build Coastguard Worker srcp = msg + l;
477*8d67ca89SAndroid Build Coastguard Worker // END android-changed
478*8d67ca89SAndroid Build Coastguard Worker checked += 2;
479*8d67ca89SAndroid Build Coastguard Worker /*
480*8d67ca89SAndroid Build Coastguard Worker * Check for loops in the compressed name;
481*8d67ca89SAndroid Build Coastguard Worker * if we've looked at the whole message,
482*8d67ca89SAndroid Build Coastguard Worker * there must be a loop.
483*8d67ca89SAndroid Build Coastguard Worker */
484*8d67ca89SAndroid Build Coastguard Worker if (checked >= eom - msg) {
485*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
486*8d67ca89SAndroid Build Coastguard Worker return (-1);
487*8d67ca89SAndroid Build Coastguard Worker }
488*8d67ca89SAndroid Build Coastguard Worker break;
489*8d67ca89SAndroid Build Coastguard Worker
490*8d67ca89SAndroid Build Coastguard Worker default:
491*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
492*8d67ca89SAndroid Build Coastguard Worker return (-1); /* flag error */
493*8d67ca89SAndroid Build Coastguard Worker }
494*8d67ca89SAndroid Build Coastguard Worker }
495*8d67ca89SAndroid Build Coastguard Worker *dstp++ = 0;
496*8d67ca89SAndroid Build Coastguard Worker if (dstlen != NULL)
497*8d67ca89SAndroid Build Coastguard Worker *dstlen = dstp - dst;
498*8d67ca89SAndroid Build Coastguard Worker if (len < 0) {
499*8d67ca89SAndroid Build Coastguard Worker _DIAGASSERT(__type_fit(int, srcp - src));
500*8d67ca89SAndroid Build Coastguard Worker len = (int)(srcp - src);
501*8d67ca89SAndroid Build Coastguard Worker }
502*8d67ca89SAndroid Build Coastguard Worker return len;
503*8d67ca89SAndroid Build Coastguard Worker }
504*8d67ca89SAndroid Build Coastguard Worker
505*8d67ca89SAndroid Build Coastguard Worker /*
506*8d67ca89SAndroid Build Coastguard Worker * Pack domain name 'domain' into 'comp_dn'.
507*8d67ca89SAndroid Build Coastguard Worker *
508*8d67ca89SAndroid Build Coastguard Worker * return:
509*8d67ca89SAndroid Build Coastguard Worker * Size of the compressed name, or -1.
510*8d67ca89SAndroid Build Coastguard Worker *
511*8d67ca89SAndroid Build Coastguard Worker * notes:
512*8d67ca89SAndroid Build Coastguard Worker * 'dnptrs' is an array of pointers to previous compressed names.
513*8d67ca89SAndroid Build Coastguard Worker * dnptrs[0] is a pointer to the beginning of the message. The array
514*8d67ca89SAndroid Build Coastguard Worker * ends with NULL.
515*8d67ca89SAndroid Build Coastguard Worker * 'lastdnptr' is a pointer to the end of the array pointed to
516*8d67ca89SAndroid Build Coastguard Worker * by 'dnptrs'.
517*8d67ca89SAndroid Build Coastguard Worker *
518*8d67ca89SAndroid Build Coastguard Worker * Side effects:
519*8d67ca89SAndroid Build Coastguard Worker * The list of pointers in dnptrs is updated for labels inserted into
520*8d67ca89SAndroid Build Coastguard Worker * the message as we compress the name. If 'dnptr' is NULL, we don't
521*8d67ca89SAndroid Build Coastguard Worker * try to compress names. If 'lastdnptr' is NULL, we don't update the
522*8d67ca89SAndroid Build Coastguard Worker * list.
523*8d67ca89SAndroid Build Coastguard Worker */
524*8d67ca89SAndroid Build Coastguard Worker int
ns_name_pack(const u_char * src,u_char * dst,int dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)525*8d67ca89SAndroid Build Coastguard Worker ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
526*8d67ca89SAndroid Build Coastguard Worker const u_char **dnptrs, const u_char **lastdnptr)
527*8d67ca89SAndroid Build Coastguard Worker {
528*8d67ca89SAndroid Build Coastguard Worker u_char *dstp;
529*8d67ca89SAndroid Build Coastguard Worker const u_char **cpp, **lpp, *eob, *msg;
530*8d67ca89SAndroid Build Coastguard Worker const u_char *srcp;
531*8d67ca89SAndroid Build Coastguard Worker int n, l, first = 1;
532*8d67ca89SAndroid Build Coastguard Worker
533*8d67ca89SAndroid Build Coastguard Worker srcp = src;
534*8d67ca89SAndroid Build Coastguard Worker dstp = dst;
535*8d67ca89SAndroid Build Coastguard Worker eob = dstp + dstsiz;
536*8d67ca89SAndroid Build Coastguard Worker lpp = cpp = NULL;
537*8d67ca89SAndroid Build Coastguard Worker if (dnptrs != NULL) {
538*8d67ca89SAndroid Build Coastguard Worker if ((msg = *dnptrs++) != NULL) {
539*8d67ca89SAndroid Build Coastguard Worker for (cpp = dnptrs; *cpp != NULL; cpp++)
540*8d67ca89SAndroid Build Coastguard Worker continue;
541*8d67ca89SAndroid Build Coastguard Worker lpp = cpp; /* end of list to search */
542*8d67ca89SAndroid Build Coastguard Worker }
543*8d67ca89SAndroid Build Coastguard Worker } else
544*8d67ca89SAndroid Build Coastguard Worker msg = NULL;
545*8d67ca89SAndroid Build Coastguard Worker
546*8d67ca89SAndroid Build Coastguard Worker /* make sure the domain we are about to add is legal */
547*8d67ca89SAndroid Build Coastguard Worker l = 0;
548*8d67ca89SAndroid Build Coastguard Worker do {
549*8d67ca89SAndroid Build Coastguard Worker int l0;
550*8d67ca89SAndroid Build Coastguard Worker
551*8d67ca89SAndroid Build Coastguard Worker n = *srcp;
552*8d67ca89SAndroid Build Coastguard Worker if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
553*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
554*8d67ca89SAndroid Build Coastguard Worker return (-1);
555*8d67ca89SAndroid Build Coastguard Worker }
556*8d67ca89SAndroid Build Coastguard Worker if ((l0 = labellen(srcp)) < 0) {
557*8d67ca89SAndroid Build Coastguard Worker errno = EINVAL;
558*8d67ca89SAndroid Build Coastguard Worker return(-1);
559*8d67ca89SAndroid Build Coastguard Worker }
560*8d67ca89SAndroid Build Coastguard Worker l += l0 + 1;
561*8d67ca89SAndroid Build Coastguard Worker if (l > MAXCDNAME) {
562*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
563*8d67ca89SAndroid Build Coastguard Worker return (-1);
564*8d67ca89SAndroid Build Coastguard Worker }
565*8d67ca89SAndroid Build Coastguard Worker srcp += l0 + 1;
566*8d67ca89SAndroid Build Coastguard Worker } while (n != 0);
567*8d67ca89SAndroid Build Coastguard Worker
568*8d67ca89SAndroid Build Coastguard Worker /* from here on we need to reset compression pointer array on error */
569*8d67ca89SAndroid Build Coastguard Worker srcp = src;
570*8d67ca89SAndroid Build Coastguard Worker do {
571*8d67ca89SAndroid Build Coastguard Worker /* Look to see if we can use pointers. */
572*8d67ca89SAndroid Build Coastguard Worker n = *srcp;
573*8d67ca89SAndroid Build Coastguard Worker if (n != 0 && msg != NULL) {
574*8d67ca89SAndroid Build Coastguard Worker l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
575*8d67ca89SAndroid Build Coastguard Worker (const u_char * const *)lpp);
576*8d67ca89SAndroid Build Coastguard Worker if (l >= 0) {
577*8d67ca89SAndroid Build Coastguard Worker if (dstp + 1 >= eob) {
578*8d67ca89SAndroid Build Coastguard Worker goto cleanup;
579*8d67ca89SAndroid Build Coastguard Worker }
580*8d67ca89SAndroid Build Coastguard Worker *dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS;
581*8d67ca89SAndroid Build Coastguard Worker *dstp++ = l % 256;
582*8d67ca89SAndroid Build Coastguard Worker _DIAGASSERT(__type_fit(int, dstp - dst));
583*8d67ca89SAndroid Build Coastguard Worker return (int)(dstp - dst);
584*8d67ca89SAndroid Build Coastguard Worker }
585*8d67ca89SAndroid Build Coastguard Worker /* Not found, save it. */
586*8d67ca89SAndroid Build Coastguard Worker if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
587*8d67ca89SAndroid Build Coastguard Worker (dstp - msg) < 0x4000 && first) {
588*8d67ca89SAndroid Build Coastguard Worker *cpp++ = dstp;
589*8d67ca89SAndroid Build Coastguard Worker *cpp = NULL;
590*8d67ca89SAndroid Build Coastguard Worker first = 0;
591*8d67ca89SAndroid Build Coastguard Worker }
592*8d67ca89SAndroid Build Coastguard Worker }
593*8d67ca89SAndroid Build Coastguard Worker /* copy label to buffer */
594*8d67ca89SAndroid Build Coastguard Worker if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
595*8d67ca89SAndroid Build Coastguard Worker /* Should not happen. */
596*8d67ca89SAndroid Build Coastguard Worker goto cleanup;
597*8d67ca89SAndroid Build Coastguard Worker }
598*8d67ca89SAndroid Build Coastguard Worker n = labellen(srcp);
599*8d67ca89SAndroid Build Coastguard Worker if (dstp + 1 + n >= eob) {
600*8d67ca89SAndroid Build Coastguard Worker goto cleanup;
601*8d67ca89SAndroid Build Coastguard Worker }
602*8d67ca89SAndroid Build Coastguard Worker memcpy(dstp, srcp, (size_t)(n + 1));
603*8d67ca89SAndroid Build Coastguard Worker srcp += n + 1;
604*8d67ca89SAndroid Build Coastguard Worker dstp += n + 1;
605*8d67ca89SAndroid Build Coastguard Worker } while (n != 0);
606*8d67ca89SAndroid Build Coastguard Worker
607*8d67ca89SAndroid Build Coastguard Worker if (dstp > eob) {
608*8d67ca89SAndroid Build Coastguard Worker cleanup:
609*8d67ca89SAndroid Build Coastguard Worker if (msg != NULL)
610*8d67ca89SAndroid Build Coastguard Worker *lpp = NULL;
611*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
612*8d67ca89SAndroid Build Coastguard Worker return (-1);
613*8d67ca89SAndroid Build Coastguard Worker }
614*8d67ca89SAndroid Build Coastguard Worker _DIAGASSERT(__type_fit(int, dstp - dst));
615*8d67ca89SAndroid Build Coastguard Worker return (int)(dstp - dst);
616*8d67ca89SAndroid Build Coastguard Worker }
617*8d67ca89SAndroid Build Coastguard Worker
618*8d67ca89SAndroid Build Coastguard Worker /*
619*8d67ca89SAndroid Build Coastguard Worker * Expand compressed domain name to presentation format.
620*8d67ca89SAndroid Build Coastguard Worker *
621*8d67ca89SAndroid Build Coastguard Worker * return:
622*8d67ca89SAndroid Build Coastguard Worker * Number of bytes read out of `src', or -1 (with errno set).
623*8d67ca89SAndroid Build Coastguard Worker *
624*8d67ca89SAndroid Build Coastguard Worker * note:
625*8d67ca89SAndroid Build Coastguard Worker * Root domain returns as "." not "".
626*8d67ca89SAndroid Build Coastguard Worker */
627*8d67ca89SAndroid Build Coastguard Worker int
ns_name_uncompress(const u_char * msg,const u_char * eom,const u_char * src,char * dst,size_t dstsiz)628*8d67ca89SAndroid Build Coastguard Worker ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
629*8d67ca89SAndroid Build Coastguard Worker char *dst, size_t dstsiz)
630*8d67ca89SAndroid Build Coastguard Worker {
631*8d67ca89SAndroid Build Coastguard Worker u_char tmp[NS_MAXCDNAME];
632*8d67ca89SAndroid Build Coastguard Worker int n;
633*8d67ca89SAndroid Build Coastguard Worker
634*8d67ca89SAndroid Build Coastguard Worker if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
635*8d67ca89SAndroid Build Coastguard Worker return (-1);
636*8d67ca89SAndroid Build Coastguard Worker if (ns_name_ntop(tmp, dst, dstsiz) == -1)
637*8d67ca89SAndroid Build Coastguard Worker return (-1);
638*8d67ca89SAndroid Build Coastguard Worker return (n);
639*8d67ca89SAndroid Build Coastguard Worker }
640*8d67ca89SAndroid Build Coastguard Worker
641*8d67ca89SAndroid Build Coastguard Worker /*
642*8d67ca89SAndroid Build Coastguard Worker * Compress a domain name into wire format, using compression pointers.
643*8d67ca89SAndroid Build Coastguard Worker *
644*8d67ca89SAndroid Build Coastguard Worker * return:
645*8d67ca89SAndroid Build Coastguard Worker * Number of bytes consumed in `dst' or -1 (with errno set).
646*8d67ca89SAndroid Build Coastguard Worker *
647*8d67ca89SAndroid Build Coastguard Worker * notes:
648*8d67ca89SAndroid Build Coastguard Worker * 'dnptrs' is an array of pointers to previous compressed names.
649*8d67ca89SAndroid Build Coastguard Worker * dnptrs[0] is a pointer to the beginning of the message.
650*8d67ca89SAndroid Build Coastguard Worker * The list ends with NULL. 'lastdnptr' is a pointer to the end of the
651*8d67ca89SAndroid Build Coastguard Worker * array pointed to by 'dnptrs'. Side effect is to update the list of
652*8d67ca89SAndroid Build Coastguard Worker * pointers for labels inserted into the message as we compress the name.
653*8d67ca89SAndroid Build Coastguard Worker * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
654*8d67ca89SAndroid Build Coastguard Worker * is NULL, we don't update the list.
655*8d67ca89SAndroid Build Coastguard Worker */
656*8d67ca89SAndroid Build Coastguard Worker int
ns_name_compress(const char * src,u_char * dst,size_t dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)657*8d67ca89SAndroid Build Coastguard Worker ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
658*8d67ca89SAndroid Build Coastguard Worker const u_char **dnptrs, const u_char **lastdnptr)
659*8d67ca89SAndroid Build Coastguard Worker {
660*8d67ca89SAndroid Build Coastguard Worker u_char tmp[NS_MAXCDNAME];
661*8d67ca89SAndroid Build Coastguard Worker
662*8d67ca89SAndroid Build Coastguard Worker if (ns_name_pton(src, tmp, sizeof tmp) == -1)
663*8d67ca89SAndroid Build Coastguard Worker return (-1);
664*8d67ca89SAndroid Build Coastguard Worker return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr));
665*8d67ca89SAndroid Build Coastguard Worker }
666*8d67ca89SAndroid Build Coastguard Worker
667*8d67ca89SAndroid Build Coastguard Worker /*
668*8d67ca89SAndroid Build Coastguard Worker * Reset dnptrs so that there are no active references to pointers at or
669*8d67ca89SAndroid Build Coastguard Worker * after src.
670*8d67ca89SAndroid Build Coastguard Worker */
671*8d67ca89SAndroid Build Coastguard Worker void
ns_name_rollback(const u_char * src,const u_char ** dnptrs,const u_char ** lastdnptr)672*8d67ca89SAndroid Build Coastguard Worker ns_name_rollback(const u_char *src, const u_char **dnptrs,
673*8d67ca89SAndroid Build Coastguard Worker const u_char **lastdnptr)
674*8d67ca89SAndroid Build Coastguard Worker {
675*8d67ca89SAndroid Build Coastguard Worker while (dnptrs < lastdnptr && *dnptrs != NULL) {
676*8d67ca89SAndroid Build Coastguard Worker if (*dnptrs >= src) {
677*8d67ca89SAndroid Build Coastguard Worker *dnptrs = NULL;
678*8d67ca89SAndroid Build Coastguard Worker break;
679*8d67ca89SAndroid Build Coastguard Worker }
680*8d67ca89SAndroid Build Coastguard Worker dnptrs++;
681*8d67ca89SAndroid Build Coastguard Worker }
682*8d67ca89SAndroid Build Coastguard Worker }
683*8d67ca89SAndroid Build Coastguard Worker
684*8d67ca89SAndroid Build Coastguard Worker /*
685*8d67ca89SAndroid Build Coastguard Worker * Advance *ptrptr to skip over the compressed name it points at.
686*8d67ca89SAndroid Build Coastguard Worker *
687*8d67ca89SAndroid Build Coastguard Worker * return:
688*8d67ca89SAndroid Build Coastguard Worker * 0 on success, -1 (with errno set) on failure.
689*8d67ca89SAndroid Build Coastguard Worker */
690*8d67ca89SAndroid Build Coastguard Worker int
ns_name_skip(const u_char ** ptrptr,const u_char * eom)691*8d67ca89SAndroid Build Coastguard Worker ns_name_skip(const u_char **ptrptr, const u_char *eom)
692*8d67ca89SAndroid Build Coastguard Worker {
693*8d67ca89SAndroid Build Coastguard Worker const u_char *cp;
694*8d67ca89SAndroid Build Coastguard Worker u_int n;
695*8d67ca89SAndroid Build Coastguard Worker int l=0;
696*8d67ca89SAndroid Build Coastguard Worker
697*8d67ca89SAndroid Build Coastguard Worker cp = *ptrptr;
698*8d67ca89SAndroid Build Coastguard Worker while (cp < eom && (n = *cp++) != 0) {
699*8d67ca89SAndroid Build Coastguard Worker /* Check for indirection. */
700*8d67ca89SAndroid Build Coastguard Worker switch (n & NS_CMPRSFLGS) {
701*8d67ca89SAndroid Build Coastguard Worker case 0: /* normal case, n == len */
702*8d67ca89SAndroid Build Coastguard Worker cp += n;
703*8d67ca89SAndroid Build Coastguard Worker continue;
704*8d67ca89SAndroid Build Coastguard Worker case NS_TYPE_ELT: /* EDNS0 extended label */
705*8d67ca89SAndroid Build Coastguard Worker if (cp < eom && (l = labellen(cp - 1)) < 0) {
706*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE; /* XXX */
707*8d67ca89SAndroid Build Coastguard Worker return(-1);
708*8d67ca89SAndroid Build Coastguard Worker }
709*8d67ca89SAndroid Build Coastguard Worker cp += l;
710*8d67ca89SAndroid Build Coastguard Worker continue;
711*8d67ca89SAndroid Build Coastguard Worker case NS_CMPRSFLGS: /* indirection */
712*8d67ca89SAndroid Build Coastguard Worker cp++;
713*8d67ca89SAndroid Build Coastguard Worker break;
714*8d67ca89SAndroid Build Coastguard Worker default: /* illegal type */
715*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
716*8d67ca89SAndroid Build Coastguard Worker return (-1);
717*8d67ca89SAndroid Build Coastguard Worker }
718*8d67ca89SAndroid Build Coastguard Worker break;
719*8d67ca89SAndroid Build Coastguard Worker }
720*8d67ca89SAndroid Build Coastguard Worker if (cp > eom) {
721*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
722*8d67ca89SAndroid Build Coastguard Worker return (-1);
723*8d67ca89SAndroid Build Coastguard Worker }
724*8d67ca89SAndroid Build Coastguard Worker *ptrptr = cp;
725*8d67ca89SAndroid Build Coastguard Worker return (0);
726*8d67ca89SAndroid Build Coastguard Worker }
727*8d67ca89SAndroid Build Coastguard Worker
728*8d67ca89SAndroid Build Coastguard Worker /* Find the number of octets an nname takes up, including the root label.
729*8d67ca89SAndroid Build Coastguard Worker * (This is basically ns_name_skip() without compression-pointer support.)
730*8d67ca89SAndroid Build Coastguard Worker * ((NOTE: can only return zero if passed-in namesiz argument is zero.))
731*8d67ca89SAndroid Build Coastguard Worker */
732*8d67ca89SAndroid Build Coastguard Worker ssize_t
ns_name_length(ns_nname_ct nname,size_t namesiz)733*8d67ca89SAndroid Build Coastguard Worker ns_name_length(ns_nname_ct nname, size_t namesiz) {
734*8d67ca89SAndroid Build Coastguard Worker ns_nname_ct orig = nname;
735*8d67ca89SAndroid Build Coastguard Worker u_int n;
736*8d67ca89SAndroid Build Coastguard Worker
737*8d67ca89SAndroid Build Coastguard Worker while (namesiz-- > 0 && (n = *nname++) != 0) {
738*8d67ca89SAndroid Build Coastguard Worker if ((n & NS_CMPRSFLGS) != 0) {
739*8d67ca89SAndroid Build Coastguard Worker errno = EISDIR;
740*8d67ca89SAndroid Build Coastguard Worker return (-1);
741*8d67ca89SAndroid Build Coastguard Worker }
742*8d67ca89SAndroid Build Coastguard Worker if (n > namesiz) {
743*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
744*8d67ca89SAndroid Build Coastguard Worker return (-1);
745*8d67ca89SAndroid Build Coastguard Worker }
746*8d67ca89SAndroid Build Coastguard Worker nname += n;
747*8d67ca89SAndroid Build Coastguard Worker namesiz -= n;
748*8d67ca89SAndroid Build Coastguard Worker }
749*8d67ca89SAndroid Build Coastguard Worker return (nname - orig);
750*8d67ca89SAndroid Build Coastguard Worker }
751*8d67ca89SAndroid Build Coastguard Worker
752*8d67ca89SAndroid Build Coastguard Worker /* Compare two nname's for equality. Return -1 on error (setting errno).
753*8d67ca89SAndroid Build Coastguard Worker */
754*8d67ca89SAndroid Build Coastguard Worker int
ns_name_eq(ns_nname_ct a,size_t as,ns_nname_ct b,size_t bs)755*8d67ca89SAndroid Build Coastguard Worker ns_name_eq(ns_nname_ct a, size_t as, ns_nname_ct b, size_t bs) {
756*8d67ca89SAndroid Build Coastguard Worker ns_nname_ct ae = a + as, be = b + bs;
757*8d67ca89SAndroid Build Coastguard Worker int ac, bc;
758*8d67ca89SAndroid Build Coastguard Worker
759*8d67ca89SAndroid Build Coastguard Worker while (ac = *a, bc = *b, ac != 0 && bc != 0) {
760*8d67ca89SAndroid Build Coastguard Worker if ((ac & NS_CMPRSFLGS) != 0 || (bc & NS_CMPRSFLGS) != 0) {
761*8d67ca89SAndroid Build Coastguard Worker errno = EISDIR;
762*8d67ca89SAndroid Build Coastguard Worker return (-1);
763*8d67ca89SAndroid Build Coastguard Worker }
764*8d67ca89SAndroid Build Coastguard Worker if (a + ac >= ae || b + bc >= be) {
765*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
766*8d67ca89SAndroid Build Coastguard Worker return (-1);
767*8d67ca89SAndroid Build Coastguard Worker }
768*8d67ca89SAndroid Build Coastguard Worker if (ac != bc || strncasecmp((const char *) ++a,
769*8d67ca89SAndroid Build Coastguard Worker (const char *) ++b,
770*8d67ca89SAndroid Build Coastguard Worker (size_t)ac) != 0)
771*8d67ca89SAndroid Build Coastguard Worker return (0);
772*8d67ca89SAndroid Build Coastguard Worker a += ac, b += bc;
773*8d67ca89SAndroid Build Coastguard Worker }
774*8d67ca89SAndroid Build Coastguard Worker return (ac == 0 && bc == 0);
775*8d67ca89SAndroid Build Coastguard Worker }
776*8d67ca89SAndroid Build Coastguard Worker
777*8d67ca89SAndroid Build Coastguard Worker /* Is domain "A" owned by (at or below) domain "B"?
778*8d67ca89SAndroid Build Coastguard Worker */
779*8d67ca89SAndroid Build Coastguard Worker int
ns_name_owned(ns_namemap_ct a,int an,ns_namemap_ct b,int bn)780*8d67ca89SAndroid Build Coastguard Worker ns_name_owned(ns_namemap_ct a, int an, ns_namemap_ct b, int bn) {
781*8d67ca89SAndroid Build Coastguard Worker /* If A is shorter, it cannot be owned by B. */
782*8d67ca89SAndroid Build Coastguard Worker if (an < bn)
783*8d67ca89SAndroid Build Coastguard Worker return (0);
784*8d67ca89SAndroid Build Coastguard Worker
785*8d67ca89SAndroid Build Coastguard Worker /* If they are unequal before the length of the shorter, A cannot... */
786*8d67ca89SAndroid Build Coastguard Worker while (bn > 0) {
787*8d67ca89SAndroid Build Coastguard Worker if (a->len != b->len ||
788*8d67ca89SAndroid Build Coastguard Worker strncasecmp((const char *) a->base,
789*8d67ca89SAndroid Build Coastguard Worker (const char *) b->base, (size_t)a->len) != 0)
790*8d67ca89SAndroid Build Coastguard Worker return (0);
791*8d67ca89SAndroid Build Coastguard Worker a++, an--;
792*8d67ca89SAndroid Build Coastguard Worker b++, bn--;
793*8d67ca89SAndroid Build Coastguard Worker }
794*8d67ca89SAndroid Build Coastguard Worker
795*8d67ca89SAndroid Build Coastguard Worker /* A might be longer or not, but either way, B owns it. */
796*8d67ca89SAndroid Build Coastguard Worker return (1);
797*8d67ca89SAndroid Build Coastguard Worker }
798*8d67ca89SAndroid Build Coastguard Worker
799*8d67ca89SAndroid Build Coastguard Worker /* Build an array of <base,len> tuples from an nname, top-down order.
800*8d67ca89SAndroid Build Coastguard Worker * Return the number of tuples (labels) thus discovered.
801*8d67ca89SAndroid Build Coastguard Worker */
802*8d67ca89SAndroid Build Coastguard Worker int
ns_name_map(ns_nname_ct nname,size_t namelen,ns_namemap_t map,int mapsize)803*8d67ca89SAndroid Build Coastguard Worker ns_name_map(ns_nname_ct nname, size_t namelen, ns_namemap_t map, int mapsize) {
804*8d67ca89SAndroid Build Coastguard Worker u_int n;
805*8d67ca89SAndroid Build Coastguard Worker int l;
806*8d67ca89SAndroid Build Coastguard Worker
807*8d67ca89SAndroid Build Coastguard Worker n = *nname++;
808*8d67ca89SAndroid Build Coastguard Worker namelen--;
809*8d67ca89SAndroid Build Coastguard Worker
810*8d67ca89SAndroid Build Coastguard Worker /* Root zone? */
811*8d67ca89SAndroid Build Coastguard Worker if (n == 0) {
812*8d67ca89SAndroid Build Coastguard Worker /* Extra data follows name? */
813*8d67ca89SAndroid Build Coastguard Worker if (namelen > 0) {
814*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
815*8d67ca89SAndroid Build Coastguard Worker return (-1);
816*8d67ca89SAndroid Build Coastguard Worker }
817*8d67ca89SAndroid Build Coastguard Worker return (0);
818*8d67ca89SAndroid Build Coastguard Worker }
819*8d67ca89SAndroid Build Coastguard Worker
820*8d67ca89SAndroid Build Coastguard Worker /* Compression pointer? */
821*8d67ca89SAndroid Build Coastguard Worker if ((n & NS_CMPRSFLGS) != 0) {
822*8d67ca89SAndroid Build Coastguard Worker errno = EISDIR;
823*8d67ca89SAndroid Build Coastguard Worker return (-1);
824*8d67ca89SAndroid Build Coastguard Worker }
825*8d67ca89SAndroid Build Coastguard Worker
826*8d67ca89SAndroid Build Coastguard Worker /* Label too long? */
827*8d67ca89SAndroid Build Coastguard Worker if (n > namelen) {
828*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
829*8d67ca89SAndroid Build Coastguard Worker return (-1);
830*8d67ca89SAndroid Build Coastguard Worker }
831*8d67ca89SAndroid Build Coastguard Worker
832*8d67ca89SAndroid Build Coastguard Worker /* Recurse to get rest of name done first. */
833*8d67ca89SAndroid Build Coastguard Worker l = ns_name_map(nname + n, namelen - n, map, mapsize);
834*8d67ca89SAndroid Build Coastguard Worker if (l < 0)
835*8d67ca89SAndroid Build Coastguard Worker return (-1);
836*8d67ca89SAndroid Build Coastguard Worker
837*8d67ca89SAndroid Build Coastguard Worker /* Too many labels? */
838*8d67ca89SAndroid Build Coastguard Worker if (l >= mapsize) {
839*8d67ca89SAndroid Build Coastguard Worker errno = ENAMETOOLONG;
840*8d67ca89SAndroid Build Coastguard Worker return (-1);
841*8d67ca89SAndroid Build Coastguard Worker }
842*8d67ca89SAndroid Build Coastguard Worker
843*8d67ca89SAndroid Build Coastguard Worker /* We're on our way back up-stack, store current map data. */
844*8d67ca89SAndroid Build Coastguard Worker map[l].base = nname;
845*8d67ca89SAndroid Build Coastguard Worker map[l].len = n;
846*8d67ca89SAndroid Build Coastguard Worker return (l + 1);
847*8d67ca89SAndroid Build Coastguard Worker }
848*8d67ca89SAndroid Build Coastguard Worker
849*8d67ca89SAndroid Build Coastguard Worker /* Count the labels in a domain name. Root counts, so COM. has two. This
850*8d67ca89SAndroid Build Coastguard Worker * is to make the result comparable to the result of ns_name_map().
851*8d67ca89SAndroid Build Coastguard Worker */
852*8d67ca89SAndroid Build Coastguard Worker int
ns_name_labels(ns_nname_ct nname,size_t namesiz)853*8d67ca89SAndroid Build Coastguard Worker ns_name_labels(ns_nname_ct nname, size_t namesiz) {
854*8d67ca89SAndroid Build Coastguard Worker int ret = 0;
855*8d67ca89SAndroid Build Coastguard Worker u_int n;
856*8d67ca89SAndroid Build Coastguard Worker
857*8d67ca89SAndroid Build Coastguard Worker while (namesiz-- > 0 && (n = *nname++) != 0) {
858*8d67ca89SAndroid Build Coastguard Worker if ((n & NS_CMPRSFLGS) != 0) {
859*8d67ca89SAndroid Build Coastguard Worker errno = EISDIR;
860*8d67ca89SAndroid Build Coastguard Worker return (-1);
861*8d67ca89SAndroid Build Coastguard Worker }
862*8d67ca89SAndroid Build Coastguard Worker if (n > namesiz) {
863*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
864*8d67ca89SAndroid Build Coastguard Worker return (-1);
865*8d67ca89SAndroid Build Coastguard Worker }
866*8d67ca89SAndroid Build Coastguard Worker nname += n;
867*8d67ca89SAndroid Build Coastguard Worker namesiz -= n;
868*8d67ca89SAndroid Build Coastguard Worker ret++;
869*8d67ca89SAndroid Build Coastguard Worker }
870*8d67ca89SAndroid Build Coastguard Worker return (ret + 1);
871*8d67ca89SAndroid Build Coastguard Worker }
872*8d67ca89SAndroid Build Coastguard Worker /* Private. */
873*8d67ca89SAndroid Build Coastguard Worker
874*8d67ca89SAndroid Build Coastguard Worker /*
875*8d67ca89SAndroid Build Coastguard Worker * Thinking in noninternationalized USASCII (per the DNS spec),
876*8d67ca89SAndroid Build Coastguard Worker * is this characted special ("in need of quoting") ?
877*8d67ca89SAndroid Build Coastguard Worker *
878*8d67ca89SAndroid Build Coastguard Worker * return:
879*8d67ca89SAndroid Build Coastguard Worker * boolean.
880*8d67ca89SAndroid Build Coastguard Worker */
881*8d67ca89SAndroid Build Coastguard Worker static int
special(int ch)882*8d67ca89SAndroid Build Coastguard Worker special(int ch) {
883*8d67ca89SAndroid Build Coastguard Worker switch (ch) {
884*8d67ca89SAndroid Build Coastguard Worker case 0x22: /* '"' */
885*8d67ca89SAndroid Build Coastguard Worker case 0x2E: /* '.' */
886*8d67ca89SAndroid Build Coastguard Worker case 0x3B: /* ';' */
887*8d67ca89SAndroid Build Coastguard Worker case 0x5C: /* '\\' */
888*8d67ca89SAndroid Build Coastguard Worker case 0x28: /* '(' */
889*8d67ca89SAndroid Build Coastguard Worker case 0x29: /* ')' */
890*8d67ca89SAndroid Build Coastguard Worker /* Special modifiers in zone files. */
891*8d67ca89SAndroid Build Coastguard Worker case 0x40: /* '@' */
892*8d67ca89SAndroid Build Coastguard Worker case 0x24: /* '$' */
893*8d67ca89SAndroid Build Coastguard Worker return (1);
894*8d67ca89SAndroid Build Coastguard Worker default:
895*8d67ca89SAndroid Build Coastguard Worker return (0);
896*8d67ca89SAndroid Build Coastguard Worker }
897*8d67ca89SAndroid Build Coastguard Worker }
898*8d67ca89SAndroid Build Coastguard Worker
899*8d67ca89SAndroid Build Coastguard Worker /*
900*8d67ca89SAndroid Build Coastguard Worker * Thinking in noninternationalized USASCII (per the DNS spec),
901*8d67ca89SAndroid Build Coastguard Worker * is this character visible and not a space when printed ?
902*8d67ca89SAndroid Build Coastguard Worker *
903*8d67ca89SAndroid Build Coastguard Worker * return:
904*8d67ca89SAndroid Build Coastguard Worker * boolean.
905*8d67ca89SAndroid Build Coastguard Worker */
906*8d67ca89SAndroid Build Coastguard Worker static int
printable(int ch)907*8d67ca89SAndroid Build Coastguard Worker printable(int ch) {
908*8d67ca89SAndroid Build Coastguard Worker return (ch > 0x20 && ch < 0x7f);
909*8d67ca89SAndroid Build Coastguard Worker }
910*8d67ca89SAndroid Build Coastguard Worker
911*8d67ca89SAndroid Build Coastguard Worker /*
912*8d67ca89SAndroid Build Coastguard Worker * Thinking in noninternationalized USASCII (per the DNS spec),
913*8d67ca89SAndroid Build Coastguard Worker * convert this character to lower case if it's upper case.
914*8d67ca89SAndroid Build Coastguard Worker */
915*8d67ca89SAndroid Build Coastguard Worker static int
mklower(int ch)916*8d67ca89SAndroid Build Coastguard Worker mklower(int ch) {
917*8d67ca89SAndroid Build Coastguard Worker if (ch >= 0x41 && ch <= 0x5A)
918*8d67ca89SAndroid Build Coastguard Worker return (ch + 0x20);
919*8d67ca89SAndroid Build Coastguard Worker return (ch);
920*8d67ca89SAndroid Build Coastguard Worker }
921*8d67ca89SAndroid Build Coastguard Worker
922*8d67ca89SAndroid Build Coastguard Worker /*
923*8d67ca89SAndroid Build Coastguard Worker * Search for the counted-label name in an array of compressed names.
924*8d67ca89SAndroid Build Coastguard Worker *
925*8d67ca89SAndroid Build Coastguard Worker * return:
926*8d67ca89SAndroid Build Coastguard Worker * offset from msg if found, or -1.
927*8d67ca89SAndroid Build Coastguard Worker *
928*8d67ca89SAndroid Build Coastguard Worker * notes:
929*8d67ca89SAndroid Build Coastguard Worker * dnptrs is the pointer to the first name on the list,
930*8d67ca89SAndroid Build Coastguard Worker * not the pointer to the start of the message.
931*8d67ca89SAndroid Build Coastguard Worker */
932*8d67ca89SAndroid Build Coastguard Worker static int
dn_find(const u_char * domain,const u_char * msg,const u_char * const * dnptrs,const u_char * const * lastdnptr)933*8d67ca89SAndroid Build Coastguard Worker dn_find(const u_char *domain, const u_char *msg,
934*8d67ca89SAndroid Build Coastguard Worker const u_char * const *dnptrs,
935*8d67ca89SAndroid Build Coastguard Worker const u_char * const *lastdnptr)
936*8d67ca89SAndroid Build Coastguard Worker {
937*8d67ca89SAndroid Build Coastguard Worker const u_char *dn, *cp, *sp;
938*8d67ca89SAndroid Build Coastguard Worker const u_char * const *cpp;
939*8d67ca89SAndroid Build Coastguard Worker u_int n;
940*8d67ca89SAndroid Build Coastguard Worker
941*8d67ca89SAndroid Build Coastguard Worker for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
942*8d67ca89SAndroid Build Coastguard Worker sp = *cpp;
943*8d67ca89SAndroid Build Coastguard Worker /*
944*8d67ca89SAndroid Build Coastguard Worker * terminate search on:
945*8d67ca89SAndroid Build Coastguard Worker * root label
946*8d67ca89SAndroid Build Coastguard Worker * compression pointer
947*8d67ca89SAndroid Build Coastguard Worker * unusable offset
948*8d67ca89SAndroid Build Coastguard Worker */
949*8d67ca89SAndroid Build Coastguard Worker while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
950*8d67ca89SAndroid Build Coastguard Worker (sp - msg) < 0x4000) {
951*8d67ca89SAndroid Build Coastguard Worker dn = domain;
952*8d67ca89SAndroid Build Coastguard Worker cp = sp;
953*8d67ca89SAndroid Build Coastguard Worker while ((n = *cp++) != 0) {
954*8d67ca89SAndroid Build Coastguard Worker /*
955*8d67ca89SAndroid Build Coastguard Worker * check for indirection
956*8d67ca89SAndroid Build Coastguard Worker */
957*8d67ca89SAndroid Build Coastguard Worker switch (n & NS_CMPRSFLGS) {
958*8d67ca89SAndroid Build Coastguard Worker case 0: /* normal case, n == len */
959*8d67ca89SAndroid Build Coastguard Worker n = labellen(cp - 1); /* XXX */
960*8d67ca89SAndroid Build Coastguard Worker
961*8d67ca89SAndroid Build Coastguard Worker if (n != *dn++)
962*8d67ca89SAndroid Build Coastguard Worker goto next;
963*8d67ca89SAndroid Build Coastguard Worker
964*8d67ca89SAndroid Build Coastguard Worker for (; n > 0; n--)
965*8d67ca89SAndroid Build Coastguard Worker if (mklower(*dn++) !=
966*8d67ca89SAndroid Build Coastguard Worker mklower(*cp++))
967*8d67ca89SAndroid Build Coastguard Worker goto next;
968*8d67ca89SAndroid Build Coastguard Worker /* Is next root for both ? */
969*8d67ca89SAndroid Build Coastguard Worker if (*dn == '\0' && *cp == '\0') {
970*8d67ca89SAndroid Build Coastguard Worker _DIAGASSERT(__type_fit(int,
971*8d67ca89SAndroid Build Coastguard Worker sp - msg));
972*8d67ca89SAndroid Build Coastguard Worker return (int)(sp - msg);
973*8d67ca89SAndroid Build Coastguard Worker }
974*8d67ca89SAndroid Build Coastguard Worker if (*dn)
975*8d67ca89SAndroid Build Coastguard Worker continue;
976*8d67ca89SAndroid Build Coastguard Worker goto next;
977*8d67ca89SAndroid Build Coastguard Worker case NS_CMPRSFLGS: /* indirection */
978*8d67ca89SAndroid Build Coastguard Worker cp = msg + (((n & 0x3f) << 8) | *cp);
979*8d67ca89SAndroid Build Coastguard Worker break;
980*8d67ca89SAndroid Build Coastguard Worker
981*8d67ca89SAndroid Build Coastguard Worker default: /* illegal type */
982*8d67ca89SAndroid Build Coastguard Worker errno = EMSGSIZE;
983*8d67ca89SAndroid Build Coastguard Worker return (-1);
984*8d67ca89SAndroid Build Coastguard Worker }
985*8d67ca89SAndroid Build Coastguard Worker }
986*8d67ca89SAndroid Build Coastguard Worker next: ;
987*8d67ca89SAndroid Build Coastguard Worker sp += *sp + 1;
988*8d67ca89SAndroid Build Coastguard Worker }
989*8d67ca89SAndroid Build Coastguard Worker }
990*8d67ca89SAndroid Build Coastguard Worker errno = ENOENT;
991*8d67ca89SAndroid Build Coastguard Worker return (-1);
992*8d67ca89SAndroid Build Coastguard Worker }
993*8d67ca89SAndroid Build Coastguard Worker
994*8d67ca89SAndroid Build Coastguard Worker static int
decode_bitstring(const unsigned char ** cpp,char * dn,const char * eom)995*8d67ca89SAndroid Build Coastguard Worker decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
996*8d67ca89SAndroid Build Coastguard Worker {
997*8d67ca89SAndroid Build Coastguard Worker const unsigned char *cp = *cpp;
998*8d67ca89SAndroid Build Coastguard Worker char *beg = dn, tc;
999*8d67ca89SAndroid Build Coastguard Worker int b, blen, plen, i;
1000*8d67ca89SAndroid Build Coastguard Worker
1001*8d67ca89SAndroid Build Coastguard Worker if ((blen = (*cp & 0xff)) == 0)
1002*8d67ca89SAndroid Build Coastguard Worker blen = 256;
1003*8d67ca89SAndroid Build Coastguard Worker plen = (blen + 3) / 4;
1004*8d67ca89SAndroid Build Coastguard Worker plen += (int)sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
1005*8d67ca89SAndroid Build Coastguard Worker if (dn + plen >= eom)
1006*8d67ca89SAndroid Build Coastguard Worker return(-1);
1007*8d67ca89SAndroid Build Coastguard Worker
1008*8d67ca89SAndroid Build Coastguard Worker cp++;
1009*8d67ca89SAndroid Build Coastguard Worker i = snprintf(dn, eom - dn, "\\[x");
1010*8d67ca89SAndroid Build Coastguard Worker if (i < 0)
1011*8d67ca89SAndroid Build Coastguard Worker return (-1);
1012*8d67ca89SAndroid Build Coastguard Worker dn += i;
1013*8d67ca89SAndroid Build Coastguard Worker for (b = blen; b > 7; b -= 8, cp++) {
1014*8d67ca89SAndroid Build Coastguard Worker i = snprintf(dn, eom - dn, "%02x", *cp & 0xff);
1015*8d67ca89SAndroid Build Coastguard Worker if (i < 0)
1016*8d67ca89SAndroid Build Coastguard Worker return (-1);
1017*8d67ca89SAndroid Build Coastguard Worker dn += i;
1018*8d67ca89SAndroid Build Coastguard Worker }
1019*8d67ca89SAndroid Build Coastguard Worker if (b > 4) {
1020*8d67ca89SAndroid Build Coastguard Worker tc = *cp++;
1021*8d67ca89SAndroid Build Coastguard Worker i = snprintf(dn, eom - dn, "%02x", tc & (0xff << (8 - b)));
1022*8d67ca89SAndroid Build Coastguard Worker if (i < 0)
1023*8d67ca89SAndroid Build Coastguard Worker return (-1);
1024*8d67ca89SAndroid Build Coastguard Worker dn += i;
1025*8d67ca89SAndroid Build Coastguard Worker } else if (b > 0) {
1026*8d67ca89SAndroid Build Coastguard Worker tc = *cp++;
1027*8d67ca89SAndroid Build Coastguard Worker i = snprintf(dn, eom - dn, "%1x",
1028*8d67ca89SAndroid Build Coastguard Worker (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b)));
1029*8d67ca89SAndroid Build Coastguard Worker if (i < 0)
1030*8d67ca89SAndroid Build Coastguard Worker return (-1);
1031*8d67ca89SAndroid Build Coastguard Worker dn += i;
1032*8d67ca89SAndroid Build Coastguard Worker }
1033*8d67ca89SAndroid Build Coastguard Worker i = snprintf(dn, eom - dn, "/%d]", blen);
1034*8d67ca89SAndroid Build Coastguard Worker if (i < 0)
1035*8d67ca89SAndroid Build Coastguard Worker return (-1);
1036*8d67ca89SAndroid Build Coastguard Worker dn += i;
1037*8d67ca89SAndroid Build Coastguard Worker
1038*8d67ca89SAndroid Build Coastguard Worker *cpp = cp;
1039*8d67ca89SAndroid Build Coastguard Worker _DIAGASSERT(__type_fit(int, dn - beg));
1040*8d67ca89SAndroid Build Coastguard Worker return (int)(dn - beg);
1041*8d67ca89SAndroid Build Coastguard Worker }
1042*8d67ca89SAndroid Build Coastguard Worker
1043*8d67ca89SAndroid Build Coastguard Worker static int
encode_bitsring(const char ** bp,const char * end,unsigned char ** labelp,unsigned char ** dst,unsigned const char * eom)1044*8d67ca89SAndroid Build Coastguard Worker encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
1045*8d67ca89SAndroid Build Coastguard Worker unsigned char ** dst, unsigned const char *eom)
1046*8d67ca89SAndroid Build Coastguard Worker {
1047*8d67ca89SAndroid Build Coastguard Worker int afterslash = 0;
1048*8d67ca89SAndroid Build Coastguard Worker const char *cp = *bp;
1049*8d67ca89SAndroid Build Coastguard Worker unsigned char *tp;
1050*8d67ca89SAndroid Build Coastguard Worker char c;
1051*8d67ca89SAndroid Build Coastguard Worker const char *beg_blen;
1052*8d67ca89SAndroid Build Coastguard Worker char *end_blen = NULL;
1053*8d67ca89SAndroid Build Coastguard Worker int value = 0, count = 0, tbcount = 0, blen = 0;
1054*8d67ca89SAndroid Build Coastguard Worker
1055*8d67ca89SAndroid Build Coastguard Worker beg_blen = end_blen = NULL;
1056*8d67ca89SAndroid Build Coastguard Worker
1057*8d67ca89SAndroid Build Coastguard Worker /* a bitstring must contain at least 2 characters */
1058*8d67ca89SAndroid Build Coastguard Worker if (end - cp < 2)
1059*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1060*8d67ca89SAndroid Build Coastguard Worker
1061*8d67ca89SAndroid Build Coastguard Worker /* XXX: currently, only hex strings are supported */
1062*8d67ca89SAndroid Build Coastguard Worker if (*cp++ != 'x')
1063*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1064*8d67ca89SAndroid Build Coastguard Worker if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */
1065*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1066*8d67ca89SAndroid Build Coastguard Worker
1067*8d67ca89SAndroid Build Coastguard Worker for (tp = *dst + 1; cp < end && tp < eom; cp++) {
1068*8d67ca89SAndroid Build Coastguard Worker switch((c = *cp)) {
1069*8d67ca89SAndroid Build Coastguard Worker case ']': /* end of the bitstring */
1070*8d67ca89SAndroid Build Coastguard Worker if (afterslash) {
1071*8d67ca89SAndroid Build Coastguard Worker if (beg_blen == NULL)
1072*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1073*8d67ca89SAndroid Build Coastguard Worker blen = (int)strtol(beg_blen, &end_blen, 10);
1074*8d67ca89SAndroid Build Coastguard Worker if (*end_blen != ']')
1075*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1076*8d67ca89SAndroid Build Coastguard Worker }
1077*8d67ca89SAndroid Build Coastguard Worker if (count)
1078*8d67ca89SAndroid Build Coastguard Worker *tp++ = ((value << 4) & 0xff);
1079*8d67ca89SAndroid Build Coastguard Worker cp++; /* skip ']' */
1080*8d67ca89SAndroid Build Coastguard Worker goto done;
1081*8d67ca89SAndroid Build Coastguard Worker case '/':
1082*8d67ca89SAndroid Build Coastguard Worker afterslash = 1;
1083*8d67ca89SAndroid Build Coastguard Worker break;
1084*8d67ca89SAndroid Build Coastguard Worker default:
1085*8d67ca89SAndroid Build Coastguard Worker if (afterslash) {
1086*8d67ca89SAndroid Build Coastguard Worker if (!isdigit(c&0xff))
1087*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1088*8d67ca89SAndroid Build Coastguard Worker if (beg_blen == NULL) {
1089*8d67ca89SAndroid Build Coastguard Worker
1090*8d67ca89SAndroid Build Coastguard Worker if (c == '0') {
1091*8d67ca89SAndroid Build Coastguard Worker /* blen never begings with 0 */
1092*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1093*8d67ca89SAndroid Build Coastguard Worker }
1094*8d67ca89SAndroid Build Coastguard Worker beg_blen = cp;
1095*8d67ca89SAndroid Build Coastguard Worker }
1096*8d67ca89SAndroid Build Coastguard Worker } else {
1097*8d67ca89SAndroid Build Coastguard Worker if (!isxdigit(c&0xff))
1098*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1099*8d67ca89SAndroid Build Coastguard Worker value <<= 4;
1100*8d67ca89SAndroid Build Coastguard Worker value += digitvalue[(int)c];
1101*8d67ca89SAndroid Build Coastguard Worker count += 4;
1102*8d67ca89SAndroid Build Coastguard Worker tbcount += 4;
1103*8d67ca89SAndroid Build Coastguard Worker if (tbcount > 256)
1104*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1105*8d67ca89SAndroid Build Coastguard Worker if (count == 8) {
1106*8d67ca89SAndroid Build Coastguard Worker *tp++ = value;
1107*8d67ca89SAndroid Build Coastguard Worker count = 0;
1108*8d67ca89SAndroid Build Coastguard Worker }
1109*8d67ca89SAndroid Build Coastguard Worker }
1110*8d67ca89SAndroid Build Coastguard Worker break;
1111*8d67ca89SAndroid Build Coastguard Worker }
1112*8d67ca89SAndroid Build Coastguard Worker }
1113*8d67ca89SAndroid Build Coastguard Worker done:
1114*8d67ca89SAndroid Build Coastguard Worker if (cp >= end || tp >= eom)
1115*8d67ca89SAndroid Build Coastguard Worker return(EMSGSIZE);
1116*8d67ca89SAndroid Build Coastguard Worker
1117*8d67ca89SAndroid Build Coastguard Worker /*
1118*8d67ca89SAndroid Build Coastguard Worker * bit length validation:
1119*8d67ca89SAndroid Build Coastguard Worker * If a <length> is present, the number of digits in the <bit-data>
1120*8d67ca89SAndroid Build Coastguard Worker * MUST be just sufficient to contain the number of bits specified
1121*8d67ca89SAndroid Build Coastguard Worker * by the <length>. If there are insignificant bits in a final
1122*8d67ca89SAndroid Build Coastguard Worker * hexadecimal or octal digit, they MUST be zero.
1123*8d67ca89SAndroid Build Coastguard Worker * RFC 2673, Section 3.2.
1124*8d67ca89SAndroid Build Coastguard Worker */
1125*8d67ca89SAndroid Build Coastguard Worker if (blen > 0) {
1126*8d67ca89SAndroid Build Coastguard Worker int traillen;
1127*8d67ca89SAndroid Build Coastguard Worker
1128*8d67ca89SAndroid Build Coastguard Worker if (((blen + 3) & ~3) != tbcount)
1129*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1130*8d67ca89SAndroid Build Coastguard Worker traillen = tbcount - blen; /* between 0 and 3 */
1131*8d67ca89SAndroid Build Coastguard Worker if (((value << (8 - traillen)) & 0xff) != 0)
1132*8d67ca89SAndroid Build Coastguard Worker return(EINVAL);
1133*8d67ca89SAndroid Build Coastguard Worker }
1134*8d67ca89SAndroid Build Coastguard Worker else
1135*8d67ca89SAndroid Build Coastguard Worker blen = tbcount;
1136*8d67ca89SAndroid Build Coastguard Worker if (blen == 256)
1137*8d67ca89SAndroid Build Coastguard Worker blen = 0;
1138*8d67ca89SAndroid Build Coastguard Worker
1139*8d67ca89SAndroid Build Coastguard Worker /* encode the type and the significant bit fields */
1140*8d67ca89SAndroid Build Coastguard Worker **labelp = DNS_LABELTYPE_BITSTRING;
1141*8d67ca89SAndroid Build Coastguard Worker **dst = blen;
1142*8d67ca89SAndroid Build Coastguard Worker
1143*8d67ca89SAndroid Build Coastguard Worker *bp = cp;
1144*8d67ca89SAndroid Build Coastguard Worker *dst = tp;
1145*8d67ca89SAndroid Build Coastguard Worker
1146*8d67ca89SAndroid Build Coastguard Worker return(0);
1147*8d67ca89SAndroid Build Coastguard Worker }
1148*8d67ca89SAndroid Build Coastguard Worker
1149*8d67ca89SAndroid Build Coastguard Worker static int
labellen(const u_char * lp)1150*8d67ca89SAndroid Build Coastguard Worker labellen(const u_char *lp)
1151*8d67ca89SAndroid Build Coastguard Worker {
1152*8d67ca89SAndroid Build Coastguard Worker int bitlen;
1153*8d67ca89SAndroid Build Coastguard Worker u_char l = *lp;
1154*8d67ca89SAndroid Build Coastguard Worker
1155*8d67ca89SAndroid Build Coastguard Worker if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
1156*8d67ca89SAndroid Build Coastguard Worker /* should be avoided by the caller */
1157*8d67ca89SAndroid Build Coastguard Worker return(-1);
1158*8d67ca89SAndroid Build Coastguard Worker }
1159*8d67ca89SAndroid Build Coastguard Worker
1160*8d67ca89SAndroid Build Coastguard Worker if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
1161*8d67ca89SAndroid Build Coastguard Worker if (l == DNS_LABELTYPE_BITSTRING) {
1162*8d67ca89SAndroid Build Coastguard Worker if ((bitlen = *(lp + 1)) == 0)
1163*8d67ca89SAndroid Build Coastguard Worker bitlen = 256;
1164*8d67ca89SAndroid Build Coastguard Worker return((bitlen + 7 ) / 8 + 1);
1165*8d67ca89SAndroid Build Coastguard Worker }
1166*8d67ca89SAndroid Build Coastguard Worker return(-1); /* unknwon ELT */
1167*8d67ca89SAndroid Build Coastguard Worker }
1168*8d67ca89SAndroid Build Coastguard Worker return(l);
1169*8d67ca89SAndroid Build Coastguard Worker }
1170