1*83ee113eSDavid van Moolenbroek /* $NetBSD: ns_name.c,v 1.7 2014/07/12 12:09:37 spz Exp $ */
2*83ee113eSDavid van Moolenbroek /*
3*83ee113eSDavid van Moolenbroek * Copyright (c) 2004,2009 by Internet Systems Consortium, Inc. ("ISC")
4*83ee113eSDavid van Moolenbroek * Copyright (c) 1996-2003 by Internet Software Consortium
5*83ee113eSDavid van Moolenbroek *
6*83ee113eSDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any
7*83ee113eSDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
8*83ee113eSDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
9*83ee113eSDavid van Moolenbroek *
10*83ee113eSDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
11*83ee113eSDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*83ee113eSDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
13*83ee113eSDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*83ee113eSDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*83ee113eSDavid van Moolenbroek * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16*83ee113eSDavid van Moolenbroek * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*83ee113eSDavid van Moolenbroek *
18*83ee113eSDavid van Moolenbroek * Internet Systems Consortium, Inc.
19*83ee113eSDavid van Moolenbroek * 950 Charter Street
20*83ee113eSDavid van Moolenbroek * Redwood City, CA 94063
21*83ee113eSDavid van Moolenbroek * <info@isc.org>
22*83ee113eSDavid van Moolenbroek * http://www.isc.org/
23*83ee113eSDavid van Moolenbroek */
24*83ee113eSDavid van Moolenbroek
25*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
26*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: ns_name.c,v 1.7 2014/07/12 12:09:37 spz Exp $");
27*83ee113eSDavid van Moolenbroek
28*83ee113eSDavid van Moolenbroek #ifndef lint
29*83ee113eSDavid van Moolenbroek static const char rcsid[] = "Id: ns_name.c,v 1.2 2009/10/28 04:12:29 sar Exp ";
30*83ee113eSDavid van Moolenbroek #endif
31*83ee113eSDavid van Moolenbroek
32*83ee113eSDavid van Moolenbroek #include <sys/types.h>
33*83ee113eSDavid van Moolenbroek
34*83ee113eSDavid van Moolenbroek #include <netinet/in.h>
35*83ee113eSDavid van Moolenbroek #include <sys/socket.h>
36*83ee113eSDavid van Moolenbroek
37*83ee113eSDavid van Moolenbroek #include <errno.h>
38*83ee113eSDavid van Moolenbroek #include <string.h>
39*83ee113eSDavid van Moolenbroek #include <ctype.h>
40*83ee113eSDavid van Moolenbroek
41*83ee113eSDavid van Moolenbroek #include "minires.h"
42*83ee113eSDavid van Moolenbroek #include "arpa/nameser.h"
43*83ee113eSDavid van Moolenbroek
44*83ee113eSDavid van Moolenbroek /* Data. */
45*83ee113eSDavid van Moolenbroek
46*83ee113eSDavid van Moolenbroek static const char digits[] = "0123456789";
47*83ee113eSDavid van Moolenbroek
48*83ee113eSDavid van Moolenbroek /* Forward. */
49*83ee113eSDavid van Moolenbroek
50*83ee113eSDavid van Moolenbroek static int special(int);
51*83ee113eSDavid van Moolenbroek static int printable(int);
52*83ee113eSDavid van Moolenbroek static int dn_find(const u_char *, const u_char *,
53*83ee113eSDavid van Moolenbroek const u_char * const *,
54*83ee113eSDavid van Moolenbroek const u_char * const *);
55*83ee113eSDavid van Moolenbroek
56*83ee113eSDavid van Moolenbroek /* Public. */
57*83ee113eSDavid van Moolenbroek
58*83ee113eSDavid van Moolenbroek /*
59*83ee113eSDavid van Moolenbroek * MRns_name_ntop(src, dst, dstsiz)
60*83ee113eSDavid van Moolenbroek * Convert an encoded domain name to printable ascii as per RFC1035.
61*83ee113eSDavid van Moolenbroek * return:
62*83ee113eSDavid van Moolenbroek * Number of bytes written to buffer, or -1 (with errno set)
63*83ee113eSDavid van Moolenbroek * notes:
64*83ee113eSDavid van Moolenbroek * The root is returned as "."
65*83ee113eSDavid van Moolenbroek * All other domains are returned in non absolute form
66*83ee113eSDavid van Moolenbroek */
67*83ee113eSDavid van Moolenbroek int
MRns_name_ntop(const u_char * src,char * dst,size_t dstsiz)68*83ee113eSDavid van Moolenbroek MRns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
69*83ee113eSDavid van Moolenbroek const u_char *cp;
70*83ee113eSDavid van Moolenbroek char *dn, *eom;
71*83ee113eSDavid van Moolenbroek u_char c;
72*83ee113eSDavid van Moolenbroek u_int n;
73*83ee113eSDavid van Moolenbroek
74*83ee113eSDavid van Moolenbroek cp = src;
75*83ee113eSDavid van Moolenbroek dn = dst;
76*83ee113eSDavid van Moolenbroek eom = dst + dstsiz;
77*83ee113eSDavid van Moolenbroek
78*83ee113eSDavid van Moolenbroek while ((n = *cp++) != 0) {
79*83ee113eSDavid van Moolenbroek if ((n & NS_CMPRSFLGS) != 0) {
80*83ee113eSDavid van Moolenbroek /* Some kind of compression pointer. */
81*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
82*83ee113eSDavid van Moolenbroek return (-1);
83*83ee113eSDavid van Moolenbroek }
84*83ee113eSDavid van Moolenbroek if (dn != dst) {
85*83ee113eSDavid van Moolenbroek if (dn >= eom) {
86*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
87*83ee113eSDavid van Moolenbroek return (-1);
88*83ee113eSDavid van Moolenbroek }
89*83ee113eSDavid van Moolenbroek *dn++ = '.';
90*83ee113eSDavid van Moolenbroek }
91*83ee113eSDavid van Moolenbroek if (dn + n >= eom) {
92*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
93*83ee113eSDavid van Moolenbroek return (-1);
94*83ee113eSDavid van Moolenbroek }
95*83ee113eSDavid van Moolenbroek for ((void)NULL; n > 0; n--) {
96*83ee113eSDavid van Moolenbroek c = *cp++;
97*83ee113eSDavid van Moolenbroek if (special(c)) {
98*83ee113eSDavid van Moolenbroek if (dn + 1 >= eom) {
99*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
100*83ee113eSDavid van Moolenbroek return (-1);
101*83ee113eSDavid van Moolenbroek }
102*83ee113eSDavid van Moolenbroek *dn++ = '\\';
103*83ee113eSDavid van Moolenbroek *dn++ = (char)c;
104*83ee113eSDavid van Moolenbroek } else if (!printable(c)) {
105*83ee113eSDavid van Moolenbroek if (dn + 3 >= eom) {
106*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
107*83ee113eSDavid van Moolenbroek return (-1);
108*83ee113eSDavid van Moolenbroek }
109*83ee113eSDavid van Moolenbroek *dn++ = '\\';
110*83ee113eSDavid van Moolenbroek *dn++ = digits[c / 100];
111*83ee113eSDavid van Moolenbroek *dn++ = digits[(c % 100) / 10];
112*83ee113eSDavid van Moolenbroek *dn++ = digits[c % 10];
113*83ee113eSDavid van Moolenbroek } else {
114*83ee113eSDavid van Moolenbroek if (dn >= eom) {
115*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
116*83ee113eSDavid van Moolenbroek return (-1);
117*83ee113eSDavid van Moolenbroek }
118*83ee113eSDavid van Moolenbroek *dn++ = (char)c;
119*83ee113eSDavid van Moolenbroek }
120*83ee113eSDavid van Moolenbroek }
121*83ee113eSDavid van Moolenbroek }
122*83ee113eSDavid van Moolenbroek if (dn == dst) {
123*83ee113eSDavid van Moolenbroek if (dn >= eom) {
124*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
125*83ee113eSDavid van Moolenbroek return (-1);
126*83ee113eSDavid van Moolenbroek }
127*83ee113eSDavid van Moolenbroek *dn++ = '.';
128*83ee113eSDavid van Moolenbroek }
129*83ee113eSDavid van Moolenbroek if (dn >= eom) {
130*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
131*83ee113eSDavid van Moolenbroek return (-1);
132*83ee113eSDavid van Moolenbroek }
133*83ee113eSDavid van Moolenbroek *dn++ = '\0';
134*83ee113eSDavid van Moolenbroek return (dn - dst);
135*83ee113eSDavid van Moolenbroek }
136*83ee113eSDavid van Moolenbroek
137*83ee113eSDavid van Moolenbroek /*
138*83ee113eSDavid van Moolenbroek * MRns_name_pton(src, dst, dstsiz)
139*83ee113eSDavid van Moolenbroek * Convert a ascii string into an encoded domain name as per RFC1035.
140*83ee113eSDavid van Moolenbroek * return:
141*83ee113eSDavid van Moolenbroek * -1 if it fails
142*83ee113eSDavid van Moolenbroek * 1 if string was fully qualified
143*83ee113eSDavid van Moolenbroek * 0 is string was not fully qualified
144*83ee113eSDavid van Moolenbroek * notes:
145*83ee113eSDavid van Moolenbroek * Enforces label and domain length limits.
146*83ee113eSDavid van Moolenbroek */
147*83ee113eSDavid van Moolenbroek
148*83ee113eSDavid van Moolenbroek int
MRns_name_pton(const char * src,u_char * dst,size_t dstsiz)149*83ee113eSDavid van Moolenbroek MRns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
150*83ee113eSDavid van Moolenbroek u_char *label, *bp, *eom;
151*83ee113eSDavid van Moolenbroek int c, n, escaped;
152*83ee113eSDavid van Moolenbroek char *cp;
153*83ee113eSDavid van Moolenbroek
154*83ee113eSDavid van Moolenbroek escaped = 0;
155*83ee113eSDavid van Moolenbroek bp = dst;
156*83ee113eSDavid van Moolenbroek eom = dst + dstsiz;
157*83ee113eSDavid van Moolenbroek label = bp++;
158*83ee113eSDavid van Moolenbroek
159*83ee113eSDavid van Moolenbroek while ((c = *src++) != 0) {
160*83ee113eSDavid van Moolenbroek if (escaped) {
161*83ee113eSDavid van Moolenbroek if ((cp = strchr(digits, c)) != NULL) {
162*83ee113eSDavid van Moolenbroek n = (cp - digits) * 100;
163*83ee113eSDavid van Moolenbroek if ((c = *src++) == 0 ||
164*83ee113eSDavid van Moolenbroek (cp = strchr(digits, c)) == NULL) {
165*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
166*83ee113eSDavid van Moolenbroek return (-1);
167*83ee113eSDavid van Moolenbroek }
168*83ee113eSDavid van Moolenbroek n += (cp - digits) * 10;
169*83ee113eSDavid van Moolenbroek if ((c = *src++) == 0 ||
170*83ee113eSDavid van Moolenbroek (cp = strchr(digits, c)) == NULL) {
171*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
172*83ee113eSDavid van Moolenbroek return (-1);
173*83ee113eSDavid van Moolenbroek }
174*83ee113eSDavid van Moolenbroek n += (cp - digits);
175*83ee113eSDavid van Moolenbroek if (n > 255) {
176*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
177*83ee113eSDavid van Moolenbroek return (-1);
178*83ee113eSDavid van Moolenbroek }
179*83ee113eSDavid van Moolenbroek c = n;
180*83ee113eSDavid van Moolenbroek }
181*83ee113eSDavid van Moolenbroek escaped = 0;
182*83ee113eSDavid van Moolenbroek } else if (c == '\\') {
183*83ee113eSDavid van Moolenbroek escaped = 1;
184*83ee113eSDavid van Moolenbroek continue;
185*83ee113eSDavid van Moolenbroek } else if (c == '.') {
186*83ee113eSDavid van Moolenbroek c = (bp - label - 1);
187*83ee113eSDavid van Moolenbroek if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
188*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
189*83ee113eSDavid van Moolenbroek return (-1);
190*83ee113eSDavid van Moolenbroek }
191*83ee113eSDavid van Moolenbroek if (label >= eom) {
192*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
193*83ee113eSDavid van Moolenbroek return (-1);
194*83ee113eSDavid van Moolenbroek }
195*83ee113eSDavid van Moolenbroek *label = c;
196*83ee113eSDavid van Moolenbroek /* Fully qualified ? */
197*83ee113eSDavid van Moolenbroek if (*src == '\0') {
198*83ee113eSDavid van Moolenbroek if (c != 0) {
199*83ee113eSDavid van Moolenbroek if (bp >= eom) {
200*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
201*83ee113eSDavid van Moolenbroek return (-1);
202*83ee113eSDavid van Moolenbroek }
203*83ee113eSDavid van Moolenbroek *bp++ = '\0';
204*83ee113eSDavid van Moolenbroek }
205*83ee113eSDavid van Moolenbroek if ((bp - dst) > MAXCDNAME) {
206*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
207*83ee113eSDavid van Moolenbroek return (-1);
208*83ee113eSDavid van Moolenbroek }
209*83ee113eSDavid van Moolenbroek return (1);
210*83ee113eSDavid van Moolenbroek }
211*83ee113eSDavid van Moolenbroek if (c == 0 || *src == '.') {
212*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
213*83ee113eSDavid van Moolenbroek return (-1);
214*83ee113eSDavid van Moolenbroek }
215*83ee113eSDavid van Moolenbroek label = bp++;
216*83ee113eSDavid van Moolenbroek continue;
217*83ee113eSDavid van Moolenbroek }
218*83ee113eSDavid van Moolenbroek if (bp >= eom) {
219*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
220*83ee113eSDavid van Moolenbroek return (-1);
221*83ee113eSDavid van Moolenbroek }
222*83ee113eSDavid van Moolenbroek *bp++ = (u_char)c;
223*83ee113eSDavid van Moolenbroek }
224*83ee113eSDavid van Moolenbroek c = (bp - label - 1);
225*83ee113eSDavid van Moolenbroek if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
226*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
227*83ee113eSDavid van Moolenbroek return (-1);
228*83ee113eSDavid van Moolenbroek }
229*83ee113eSDavid van Moolenbroek if (label >= eom) {
230*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
231*83ee113eSDavid van Moolenbroek return (-1);
232*83ee113eSDavid van Moolenbroek }
233*83ee113eSDavid van Moolenbroek *label = c;
234*83ee113eSDavid van Moolenbroek if (c != 0) {
235*83ee113eSDavid van Moolenbroek if (bp >= eom) {
236*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
237*83ee113eSDavid van Moolenbroek return (-1);
238*83ee113eSDavid van Moolenbroek }
239*83ee113eSDavid van Moolenbroek *bp++ = 0;
240*83ee113eSDavid van Moolenbroek }
241*83ee113eSDavid van Moolenbroek if ((bp - dst) > MAXCDNAME) { /* src too big */
242*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
243*83ee113eSDavid van Moolenbroek return (-1);
244*83ee113eSDavid van Moolenbroek }
245*83ee113eSDavid van Moolenbroek return (0);
246*83ee113eSDavid van Moolenbroek }
247*83ee113eSDavid van Moolenbroek
248*83ee113eSDavid van Moolenbroek #ifdef notdef
249*83ee113eSDavid van Moolenbroek /*
250*83ee113eSDavid van Moolenbroek * MRns_name_ntol(src, dst, dstsiz)
251*83ee113eSDavid van Moolenbroek * Convert a network strings labels into all lowercase.
252*83ee113eSDavid van Moolenbroek * return:
253*83ee113eSDavid van Moolenbroek * Number of bytes written to buffer, or -1 (with errno set)
254*83ee113eSDavid van Moolenbroek * notes:
255*83ee113eSDavid van Moolenbroek * Enforces label and domain length limits.
256*83ee113eSDavid van Moolenbroek */
257*83ee113eSDavid van Moolenbroek
258*83ee113eSDavid van Moolenbroek int
MRns_name_ntol(const u_char * src,u_char * dst,size_t dstsiz)259*83ee113eSDavid van Moolenbroek MRns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) {
260*83ee113eSDavid van Moolenbroek const u_char *cp;
261*83ee113eSDavid van Moolenbroek u_char *dn, *eom;
262*83ee113eSDavid van Moolenbroek u_char c;
263*83ee113eSDavid van Moolenbroek u_int n;
264*83ee113eSDavid van Moolenbroek
265*83ee113eSDavid van Moolenbroek cp = src;
266*83ee113eSDavid van Moolenbroek dn = dst;
267*83ee113eSDavid van Moolenbroek eom = dst + dstsiz;
268*83ee113eSDavid van Moolenbroek
269*83ee113eSDavid van Moolenbroek if (dn >= eom) {
270*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
271*83ee113eSDavid van Moolenbroek return (-1);
272*83ee113eSDavid van Moolenbroek }
273*83ee113eSDavid van Moolenbroek while ((n = *cp++) != 0) {
274*83ee113eSDavid van Moolenbroek if ((n & NS_CMPRSFLGS) != 0) {
275*83ee113eSDavid van Moolenbroek /* Some kind of compression pointer. */
276*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
277*83ee113eSDavid van Moolenbroek return (-1);
278*83ee113eSDavid van Moolenbroek }
279*83ee113eSDavid van Moolenbroek *dn++ = n;
280*83ee113eSDavid van Moolenbroek if (dn + n >= eom) {
281*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
282*83ee113eSDavid van Moolenbroek return (-1);
283*83ee113eSDavid van Moolenbroek }
284*83ee113eSDavid van Moolenbroek for ((void)NULL; n > 0; n--) {
285*83ee113eSDavid van Moolenbroek c = *cp++;
286*83ee113eSDavid van Moolenbroek if (isupper(c))
287*83ee113eSDavid van Moolenbroek *dn++ = tolower(c);
288*83ee113eSDavid van Moolenbroek else
289*83ee113eSDavid van Moolenbroek *dn++ = c;
290*83ee113eSDavid van Moolenbroek }
291*83ee113eSDavid van Moolenbroek }
292*83ee113eSDavid van Moolenbroek *dn++ = '\0';
293*83ee113eSDavid van Moolenbroek return (dn - dst);
294*83ee113eSDavid van Moolenbroek }
295*83ee113eSDavid van Moolenbroek #endif
296*83ee113eSDavid van Moolenbroek
297*83ee113eSDavid van Moolenbroek /*
298*83ee113eSDavid van Moolenbroek * MRns_name_unpack(msg, eom, src, dst, dstsiz)
299*83ee113eSDavid van Moolenbroek * Unpack a domain name from a message, source may be compressed.
300*83ee113eSDavid van Moolenbroek * return:
301*83ee113eSDavid van Moolenbroek * -1 if it fails, or consumed octets if it succeeds.
302*83ee113eSDavid van Moolenbroek */
303*83ee113eSDavid van Moolenbroek int
MRns_name_unpack(const u_char * msg,const u_char * eom,const u_char * src,u_char * dst,size_t dstsiz)304*83ee113eSDavid van Moolenbroek MRns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
305*83ee113eSDavid van Moolenbroek u_char *dst, size_t dstsiz)
306*83ee113eSDavid van Moolenbroek {
307*83ee113eSDavid van Moolenbroek const u_char *srcp, *dstlim;
308*83ee113eSDavid van Moolenbroek u_char *dstp;
309*83ee113eSDavid van Moolenbroek unsigned n;
310*83ee113eSDavid van Moolenbroek int len;
311*83ee113eSDavid van Moolenbroek int checked;
312*83ee113eSDavid van Moolenbroek
313*83ee113eSDavid van Moolenbroek len = -1;
314*83ee113eSDavid van Moolenbroek checked = 0;
315*83ee113eSDavid van Moolenbroek dstp = dst;
316*83ee113eSDavid van Moolenbroek srcp = src;
317*83ee113eSDavid van Moolenbroek dstlim = dst + dstsiz;
318*83ee113eSDavid van Moolenbroek if (srcp < msg || srcp >= eom) {
319*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
320*83ee113eSDavid van Moolenbroek return (-1);
321*83ee113eSDavid van Moolenbroek }
322*83ee113eSDavid van Moolenbroek /* Fetch next label in domain name. */
323*83ee113eSDavid van Moolenbroek while ((n = *srcp++) != 0) {
324*83ee113eSDavid van Moolenbroek /* Check for indirection. */
325*83ee113eSDavid van Moolenbroek switch (n & NS_CMPRSFLGS) {
326*83ee113eSDavid van Moolenbroek case 0:
327*83ee113eSDavid van Moolenbroek /* Limit checks. */
328*83ee113eSDavid van Moolenbroek if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
329*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
330*83ee113eSDavid van Moolenbroek return (-1);
331*83ee113eSDavid van Moolenbroek }
332*83ee113eSDavid van Moolenbroek checked += n + 1;
333*83ee113eSDavid van Moolenbroek *dstp++ = n;
334*83ee113eSDavid van Moolenbroek memcpy(dstp, srcp, n);
335*83ee113eSDavid van Moolenbroek dstp += n;
336*83ee113eSDavid van Moolenbroek srcp += n;
337*83ee113eSDavid van Moolenbroek break;
338*83ee113eSDavid van Moolenbroek
339*83ee113eSDavid van Moolenbroek case NS_CMPRSFLGS:
340*83ee113eSDavid van Moolenbroek if (srcp >= eom) {
341*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
342*83ee113eSDavid van Moolenbroek return (-1);
343*83ee113eSDavid van Moolenbroek }
344*83ee113eSDavid van Moolenbroek if (len < 0)
345*83ee113eSDavid van Moolenbroek len = srcp - src + 1;
346*83ee113eSDavid van Moolenbroek n = ((n & 0x3f) << 8) | (*srcp & 0xff);
347*83ee113eSDavid van Moolenbroek if (n >= eom - msg) { /* Out of range. */
348*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
349*83ee113eSDavid van Moolenbroek return (-1);
350*83ee113eSDavid van Moolenbroek }
351*83ee113eSDavid van Moolenbroek srcp = msg + n;
352*83ee113eSDavid van Moolenbroek checked += 2;
353*83ee113eSDavid van Moolenbroek /*
354*83ee113eSDavid van Moolenbroek * Check for loops in the compressed name;
355*83ee113eSDavid van Moolenbroek * if we've looked at the whole message,
356*83ee113eSDavid van Moolenbroek * there must be a loop.
357*83ee113eSDavid van Moolenbroek */
358*83ee113eSDavid van Moolenbroek if (checked >= eom - msg) {
359*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
360*83ee113eSDavid van Moolenbroek return (-1);
361*83ee113eSDavid van Moolenbroek }
362*83ee113eSDavid van Moolenbroek break;
363*83ee113eSDavid van Moolenbroek
364*83ee113eSDavid van Moolenbroek default:
365*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
366*83ee113eSDavid van Moolenbroek return (-1); /* flag error */
367*83ee113eSDavid van Moolenbroek }
368*83ee113eSDavid van Moolenbroek }
369*83ee113eSDavid van Moolenbroek *dstp = '\0';
370*83ee113eSDavid van Moolenbroek if (len < 0)
371*83ee113eSDavid van Moolenbroek len = srcp - src;
372*83ee113eSDavid van Moolenbroek return (len);
373*83ee113eSDavid van Moolenbroek }
374*83ee113eSDavid van Moolenbroek
375*83ee113eSDavid van Moolenbroek /*
376*83ee113eSDavid van Moolenbroek * MRns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
377*83ee113eSDavid van Moolenbroek * Pack domain name 'domain' into 'comp_dn'.
378*83ee113eSDavid van Moolenbroek * return:
379*83ee113eSDavid van Moolenbroek * Size of the compressed name, or -1.
380*83ee113eSDavid van Moolenbroek * notes:
381*83ee113eSDavid van Moolenbroek * 'dnptrs' is an array of pointers to previous compressed names.
382*83ee113eSDavid van Moolenbroek * dnptrs[0] is a pointer to the beginning of the message. The array
383*83ee113eSDavid van Moolenbroek * ends with NULL.
384*83ee113eSDavid van Moolenbroek * 'lastdnptr' is a pointer to the end of the array pointed to
385*83ee113eSDavid van Moolenbroek * by 'dnptrs'.
386*83ee113eSDavid van Moolenbroek * Side effects:
387*83ee113eSDavid van Moolenbroek * The list of pointers in dnptrs is updated for labels inserted into
388*83ee113eSDavid van Moolenbroek * the message as we compress the name. If 'dnptr' is NULL, we don't
389*83ee113eSDavid van Moolenbroek * try to compress names. If 'lastdnptr' is NULL, we don't update the
390*83ee113eSDavid van Moolenbroek * list.
391*83ee113eSDavid van Moolenbroek */
392*83ee113eSDavid van Moolenbroek int
MRns_name_pack(const u_char * src,u_char * dst,unsigned dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)393*83ee113eSDavid van Moolenbroek MRns_name_pack(const u_char *src, u_char *dst, unsigned dstsiz,
394*83ee113eSDavid van Moolenbroek const u_char **dnptrs, const u_char **lastdnptr)
395*83ee113eSDavid van Moolenbroek {
396*83ee113eSDavid van Moolenbroek u_char *dstp;
397*83ee113eSDavid van Moolenbroek const u_char **cpp, **lpp, *eob, *msg;
398*83ee113eSDavid van Moolenbroek const u_char *srcp;
399*83ee113eSDavid van Moolenbroek unsigned n;
400*83ee113eSDavid van Moolenbroek int l;
401*83ee113eSDavid van Moolenbroek
402*83ee113eSDavid van Moolenbroek srcp = src;
403*83ee113eSDavid van Moolenbroek dstp = dst;
404*83ee113eSDavid van Moolenbroek eob = dstp + dstsiz;
405*83ee113eSDavid van Moolenbroek lpp = cpp = NULL;
406*83ee113eSDavid van Moolenbroek if (dnptrs != NULL) {
407*83ee113eSDavid van Moolenbroek if ((msg = *dnptrs++) != NULL) {
408*83ee113eSDavid van Moolenbroek for (cpp = dnptrs; *cpp != NULL; cpp++)
409*83ee113eSDavid van Moolenbroek (void)NULL;
410*83ee113eSDavid van Moolenbroek lpp = cpp; /* end of list to search */
411*83ee113eSDavid van Moolenbroek }
412*83ee113eSDavid van Moolenbroek } else
413*83ee113eSDavid van Moolenbroek msg = NULL;
414*83ee113eSDavid van Moolenbroek
415*83ee113eSDavid van Moolenbroek /* make sure the domain we are about to add is legal */
416*83ee113eSDavid van Moolenbroek l = 0;
417*83ee113eSDavid van Moolenbroek do {
418*83ee113eSDavid van Moolenbroek n = *srcp;
419*83ee113eSDavid van Moolenbroek if ((n & NS_CMPRSFLGS) != 0) {
420*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
421*83ee113eSDavid van Moolenbroek return (-1);
422*83ee113eSDavid van Moolenbroek }
423*83ee113eSDavid van Moolenbroek l += n + 1;
424*83ee113eSDavid van Moolenbroek if (l > MAXCDNAME) {
425*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
426*83ee113eSDavid van Moolenbroek return (-1);
427*83ee113eSDavid van Moolenbroek }
428*83ee113eSDavid van Moolenbroek srcp += n + 1;
429*83ee113eSDavid van Moolenbroek } while (n != 0);
430*83ee113eSDavid van Moolenbroek
431*83ee113eSDavid van Moolenbroek /* from here on we need to reset compression pointer array on error */
432*83ee113eSDavid van Moolenbroek srcp = src;
433*83ee113eSDavid van Moolenbroek do {
434*83ee113eSDavid van Moolenbroek /* Look to see if we can use pointers. */
435*83ee113eSDavid van Moolenbroek n = *srcp;
436*83ee113eSDavid van Moolenbroek if (n != 0 && msg != NULL) {
437*83ee113eSDavid van Moolenbroek l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
438*83ee113eSDavid van Moolenbroek (const u_char * const *)lpp);
439*83ee113eSDavid van Moolenbroek if (l >= 0) {
440*83ee113eSDavid van Moolenbroek if (dstp + 1 >= eob) {
441*83ee113eSDavid van Moolenbroek goto cleanup;
442*83ee113eSDavid van Moolenbroek }
443*83ee113eSDavid van Moolenbroek *dstp++ = (l >> 8) | NS_CMPRSFLGS;
444*83ee113eSDavid van Moolenbroek *dstp++ = l % 256;
445*83ee113eSDavid van Moolenbroek return (dstp - dst);
446*83ee113eSDavid van Moolenbroek }
447*83ee113eSDavid van Moolenbroek /* Not found, save it. */
448*83ee113eSDavid van Moolenbroek if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
449*83ee113eSDavid van Moolenbroek (dstp - msg) < 0x4000) {
450*83ee113eSDavid van Moolenbroek *cpp++ = dstp;
451*83ee113eSDavid van Moolenbroek *cpp = NULL;
452*83ee113eSDavid van Moolenbroek }
453*83ee113eSDavid van Moolenbroek }
454*83ee113eSDavid van Moolenbroek /* copy label to buffer */
455*83ee113eSDavid van Moolenbroek if (n & NS_CMPRSFLGS) { /* Should not happen. */
456*83ee113eSDavid van Moolenbroek goto cleanup;
457*83ee113eSDavid van Moolenbroek }
458*83ee113eSDavid van Moolenbroek if (dstp + 1 + n >= eob) {
459*83ee113eSDavid van Moolenbroek goto cleanup;
460*83ee113eSDavid van Moolenbroek }
461*83ee113eSDavid van Moolenbroek memcpy(dstp, srcp, n + 1);
462*83ee113eSDavid van Moolenbroek srcp += n + 1;
463*83ee113eSDavid van Moolenbroek dstp += n + 1;
464*83ee113eSDavid van Moolenbroek } while (n != 0);
465*83ee113eSDavid van Moolenbroek
466*83ee113eSDavid van Moolenbroek if (dstp > eob) {
467*83ee113eSDavid van Moolenbroek cleanup:
468*83ee113eSDavid van Moolenbroek if (msg != NULL)
469*83ee113eSDavid van Moolenbroek *lpp = NULL;
470*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
471*83ee113eSDavid van Moolenbroek return (-1);
472*83ee113eSDavid van Moolenbroek }
473*83ee113eSDavid van Moolenbroek return (dstp - dst);
474*83ee113eSDavid van Moolenbroek }
475*83ee113eSDavid van Moolenbroek
476*83ee113eSDavid van Moolenbroek #ifdef notdef
477*83ee113eSDavid van Moolenbroek /*
478*83ee113eSDavid van Moolenbroek * MRns_name_uncompress(msg, eom, src, dst, dstsiz)
479*83ee113eSDavid van Moolenbroek * Expand compressed domain name to presentation format.
480*83ee113eSDavid van Moolenbroek * return:
481*83ee113eSDavid van Moolenbroek * Number of bytes read out of `src', or -1 (with errno set).
482*83ee113eSDavid van Moolenbroek * note:
483*83ee113eSDavid van Moolenbroek * Root domain returns as "." not "".
484*83ee113eSDavid van Moolenbroek */
485*83ee113eSDavid van Moolenbroek int
MRns_name_uncompress(const u_char * msg,const u_char * eom,const u_char * src,char * dst,size_t dstsiz)486*83ee113eSDavid van Moolenbroek MRns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
487*83ee113eSDavid van Moolenbroek char *dst, size_t dstsiz)
488*83ee113eSDavid van Moolenbroek {
489*83ee113eSDavid van Moolenbroek u_char tmp[NS_MAXCDNAME];
490*83ee113eSDavid van Moolenbroek int n;
491*83ee113eSDavid van Moolenbroek
492*83ee113eSDavid van Moolenbroek if ((n = MRns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
493*83ee113eSDavid van Moolenbroek return (-1);
494*83ee113eSDavid van Moolenbroek if (MRns_name_ntop(tmp, dst, dstsiz) == -1)
495*83ee113eSDavid van Moolenbroek return (-1);
496*83ee113eSDavid van Moolenbroek return (n);
497*83ee113eSDavid van Moolenbroek }
498*83ee113eSDavid van Moolenbroek #endif
499*83ee113eSDavid van Moolenbroek
500*83ee113eSDavid van Moolenbroek /*
501*83ee113eSDavid van Moolenbroek * MRns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
502*83ee113eSDavid van Moolenbroek * Compress a domain name into wire format, using compression pointers.
503*83ee113eSDavid van Moolenbroek * return:
504*83ee113eSDavid van Moolenbroek * Number of bytes consumed in `dst' or -1 (with errno set).
505*83ee113eSDavid van Moolenbroek * notes:
506*83ee113eSDavid van Moolenbroek * 'dnptrs' is an array of pointers to previous compressed names.
507*83ee113eSDavid van Moolenbroek * dnptrs[0] is a pointer to the beginning of the message.
508*83ee113eSDavid van Moolenbroek * The list ends with NULL. 'lastdnptr' is a pointer to the end of the
509*83ee113eSDavid van Moolenbroek * array pointed to by 'dnptrs'. Side effect is to update the list of
510*83ee113eSDavid van Moolenbroek * pointers for labels inserted into the message as we compress the name.
511*83ee113eSDavid van Moolenbroek * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
512*83ee113eSDavid van Moolenbroek * is NULL, we don't update the list.
513*83ee113eSDavid van Moolenbroek */
514*83ee113eSDavid van Moolenbroek int
MRns_name_compress(const char * src,u_char * dst,size_t dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)515*83ee113eSDavid van Moolenbroek MRns_name_compress(const char *src, u_char *dst, size_t dstsiz,
516*83ee113eSDavid van Moolenbroek const u_char **dnptrs, const u_char **lastdnptr)
517*83ee113eSDavid van Moolenbroek {
518*83ee113eSDavid van Moolenbroek u_char tmp[NS_MAXCDNAME];
519*83ee113eSDavid van Moolenbroek
520*83ee113eSDavid van Moolenbroek if (MRns_name_pton(src, tmp, sizeof tmp) == -1)
521*83ee113eSDavid van Moolenbroek return (-1);
522*83ee113eSDavid van Moolenbroek return (MRns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
523*83ee113eSDavid van Moolenbroek }
524*83ee113eSDavid van Moolenbroek
525*83ee113eSDavid van Moolenbroek #ifdef notdef
526*83ee113eSDavid van Moolenbroek /*
527*83ee113eSDavid van Moolenbroek * MRns_name_skip(ptrptr, eom)
528*83ee113eSDavid van Moolenbroek * Advance *ptrptr to skip over the compressed name it points at.
529*83ee113eSDavid van Moolenbroek * return:
530*83ee113eSDavid van Moolenbroek * 0 on success, -1 (with errno set) on failure.
531*83ee113eSDavid van Moolenbroek */
532*83ee113eSDavid van Moolenbroek int
MRns_name_skip(const u_char ** ptrptr,const u_char * eom)533*83ee113eSDavid van Moolenbroek MRns_name_skip(const u_char **ptrptr, const u_char *eom) {
534*83ee113eSDavid van Moolenbroek const u_char *cp;
535*83ee113eSDavid van Moolenbroek u_int n;
536*83ee113eSDavid van Moolenbroek
537*83ee113eSDavid van Moolenbroek cp = *ptrptr;
538*83ee113eSDavid van Moolenbroek while (cp < eom && (n = *cp++) != 0) {
539*83ee113eSDavid van Moolenbroek /* Check for indirection. */
540*83ee113eSDavid van Moolenbroek switch (n & NS_CMPRSFLGS) {
541*83ee113eSDavid van Moolenbroek case 0: /* normal case, n == len */
542*83ee113eSDavid van Moolenbroek cp += n;
543*83ee113eSDavid van Moolenbroek continue;
544*83ee113eSDavid van Moolenbroek case NS_CMPRSFLGS: /* indirection */
545*83ee113eSDavid van Moolenbroek cp++;
546*83ee113eSDavid van Moolenbroek break;
547*83ee113eSDavid van Moolenbroek default: /* illegal type */
548*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
549*83ee113eSDavid van Moolenbroek return (-1);
550*83ee113eSDavid van Moolenbroek }
551*83ee113eSDavid van Moolenbroek break;
552*83ee113eSDavid van Moolenbroek }
553*83ee113eSDavid van Moolenbroek if (cp > eom) {
554*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
555*83ee113eSDavid van Moolenbroek return (-1);
556*83ee113eSDavid van Moolenbroek }
557*83ee113eSDavid van Moolenbroek *ptrptr = cp;
558*83ee113eSDavid van Moolenbroek return (0);
559*83ee113eSDavid van Moolenbroek }
560*83ee113eSDavid van Moolenbroek #endif
561*83ee113eSDavid van Moolenbroek
562*83ee113eSDavid van Moolenbroek /* Private. */
563*83ee113eSDavid van Moolenbroek
564*83ee113eSDavid van Moolenbroek /*
565*83ee113eSDavid van Moolenbroek * special(ch)
566*83ee113eSDavid van Moolenbroek * Thinking in noninternationalized USASCII (per the DNS spec),
567*83ee113eSDavid van Moolenbroek * is this characted special ("in need of quoting") ?
568*83ee113eSDavid van Moolenbroek * return:
569*83ee113eSDavid van Moolenbroek * boolean.
570*83ee113eSDavid van Moolenbroek */
571*83ee113eSDavid van Moolenbroek static int
special(int ch)572*83ee113eSDavid van Moolenbroek special(int ch) {
573*83ee113eSDavid van Moolenbroek switch (ch) {
574*83ee113eSDavid van Moolenbroek case 0x22: /* '"' */
575*83ee113eSDavid van Moolenbroek case 0x2E: /* '.' */
576*83ee113eSDavid van Moolenbroek case 0x3B: /* ';' */
577*83ee113eSDavid van Moolenbroek case 0x5C: /* '\\' */
578*83ee113eSDavid van Moolenbroek /* Special modifiers in zone files. */
579*83ee113eSDavid van Moolenbroek case 0x40: /* '@' */
580*83ee113eSDavid van Moolenbroek case 0x24: /* '$' */
581*83ee113eSDavid van Moolenbroek return (1);
582*83ee113eSDavid van Moolenbroek default:
583*83ee113eSDavid van Moolenbroek return (0);
584*83ee113eSDavid van Moolenbroek }
585*83ee113eSDavid van Moolenbroek }
586*83ee113eSDavid van Moolenbroek
587*83ee113eSDavid van Moolenbroek /*
588*83ee113eSDavid van Moolenbroek * printable(ch)
589*83ee113eSDavid van Moolenbroek * Thinking in noninternationalized USASCII (per the DNS spec),
590*83ee113eSDavid van Moolenbroek * is this character visible and not a space when printed ?
591*83ee113eSDavid van Moolenbroek * return:
592*83ee113eSDavid van Moolenbroek * boolean.
593*83ee113eSDavid van Moolenbroek */
594*83ee113eSDavid van Moolenbroek static int
printable(int ch)595*83ee113eSDavid van Moolenbroek printable(int ch) {
596*83ee113eSDavid van Moolenbroek return (ch > 0x20 && ch < 0x7f);
597*83ee113eSDavid van Moolenbroek }
598*83ee113eSDavid van Moolenbroek
599*83ee113eSDavid van Moolenbroek /*
600*83ee113eSDavid van Moolenbroek * Thinking in noninternationalized USASCII (per the DNS spec),
601*83ee113eSDavid van Moolenbroek * convert this character to lower case if it's upper case.
602*83ee113eSDavid van Moolenbroek */
603*83ee113eSDavid van Moolenbroek static int
mklower(int ch)604*83ee113eSDavid van Moolenbroek mklower(int ch) {
605*83ee113eSDavid van Moolenbroek if (ch >= 0x41 && ch <= 0x5A)
606*83ee113eSDavid van Moolenbroek return (ch + 0x20);
607*83ee113eSDavid van Moolenbroek return (ch);
608*83ee113eSDavid van Moolenbroek }
609*83ee113eSDavid van Moolenbroek
610*83ee113eSDavid van Moolenbroek /*
611*83ee113eSDavid van Moolenbroek * dn_find(domain, msg, dnptrs, lastdnptr)
612*83ee113eSDavid van Moolenbroek * Search for the counted-label name in an array of compressed names.
613*83ee113eSDavid van Moolenbroek * return:
614*83ee113eSDavid van Moolenbroek * offset from msg if found, or -1.
615*83ee113eSDavid van Moolenbroek * notes:
616*83ee113eSDavid van Moolenbroek * dnptrs is the pointer to the first name on the list,
617*83ee113eSDavid van Moolenbroek * not the pointer to the start of the message.
618*83ee113eSDavid van Moolenbroek */
619*83ee113eSDavid van Moolenbroek static int
dn_find(const u_char * domain,const u_char * msg,const u_char * const * dnptrs,const u_char * const * lastdnptr)620*83ee113eSDavid van Moolenbroek dn_find(const u_char *domain, const u_char *msg,
621*83ee113eSDavid van Moolenbroek const u_char * const *dnptrs,
622*83ee113eSDavid van Moolenbroek const u_char * const *lastdnptr)
623*83ee113eSDavid van Moolenbroek {
624*83ee113eSDavid van Moolenbroek const u_char *dn, *cp, *sp;
625*83ee113eSDavid van Moolenbroek const u_char * const *cpp;
626*83ee113eSDavid van Moolenbroek u_int n;
627*83ee113eSDavid van Moolenbroek
628*83ee113eSDavid van Moolenbroek for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
629*83ee113eSDavid van Moolenbroek dn = domain;
630*83ee113eSDavid van Moolenbroek sp = cp = *cpp;
631*83ee113eSDavid van Moolenbroek while ((n = *cp++) != 0) {
632*83ee113eSDavid van Moolenbroek /*
633*83ee113eSDavid van Moolenbroek * check for indirection
634*83ee113eSDavid van Moolenbroek */
635*83ee113eSDavid van Moolenbroek switch (n & NS_CMPRSFLGS) {
636*83ee113eSDavid van Moolenbroek case 0: /* normal case, n == len */
637*83ee113eSDavid van Moolenbroek if (n != *dn++)
638*83ee113eSDavid van Moolenbroek goto next;
639*83ee113eSDavid van Moolenbroek for ((void)NULL; n > 0; n--)
640*83ee113eSDavid van Moolenbroek if (mklower(*dn++) != mklower(*cp++))
641*83ee113eSDavid van Moolenbroek goto next;
642*83ee113eSDavid van Moolenbroek /* Is next root for both ? */
643*83ee113eSDavid van Moolenbroek if (*dn == '\0' && *cp == '\0')
644*83ee113eSDavid van Moolenbroek return (sp - msg);
645*83ee113eSDavid van Moolenbroek if (*dn)
646*83ee113eSDavid van Moolenbroek continue;
647*83ee113eSDavid van Moolenbroek goto next;
648*83ee113eSDavid van Moolenbroek
649*83ee113eSDavid van Moolenbroek case NS_CMPRSFLGS: /* indirection */
650*83ee113eSDavid van Moolenbroek cp = msg + (((n & 0x3f) << 8) | *cp);
651*83ee113eSDavid van Moolenbroek break;
652*83ee113eSDavid van Moolenbroek
653*83ee113eSDavid van Moolenbroek default: /* illegal type */
654*83ee113eSDavid van Moolenbroek errno = EMSGSIZE;
655*83ee113eSDavid van Moolenbroek return (-1);
656*83ee113eSDavid van Moolenbroek }
657*83ee113eSDavid van Moolenbroek }
658*83ee113eSDavid van Moolenbroek next: ;
659*83ee113eSDavid van Moolenbroek }
660*83ee113eSDavid van Moolenbroek errno = ENOENT;
661*83ee113eSDavid van Moolenbroek return (-1);
662*83ee113eSDavid van Moolenbroek }
663