10Sstevel@tonic-gate /*
2*11038SRao.Shoaib@Sun.COM * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
30Sstevel@tonic-gate * Copyright (c) 1996,1999 by Internet Software Consortium.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any
60Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above
70Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies.
80Sstevel@tonic-gate *
9*11038SRao.Shoaib@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10*11038SRao.Shoaib@Sun.COM * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*11038SRao.Shoaib@Sun.COM * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12*11038SRao.Shoaib@Sun.COM * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*11038SRao.Shoaib@Sun.COM * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*11038SRao.Shoaib@Sun.COM * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15*11038SRao.Shoaib@Sun.COM * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
160Sstevel@tonic-gate */
170Sstevel@tonic-gate
180Sstevel@tonic-gate #ifndef lint
19*11038SRao.Shoaib@Sun.COM static const char rcsid[] = "$Id: ns_name.c,v 1.11 2009/01/23 19:59:16 each Exp $";
200Sstevel@tonic-gate #endif
210Sstevel@tonic-gate
220Sstevel@tonic-gate #include "port_before.h"
230Sstevel@tonic-gate
240Sstevel@tonic-gate #include <sys/types.h>
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <netinet/in.h>
270Sstevel@tonic-gate #include <arpa/nameser.h>
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <errno.h>
300Sstevel@tonic-gate #include <resolv.h>
310Sstevel@tonic-gate #include <string.h>
320Sstevel@tonic-gate #include <ctype.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <limits.h>
350Sstevel@tonic-gate
360Sstevel@tonic-gate #include "port_after.h"
370Sstevel@tonic-gate
380Sstevel@tonic-gate #ifdef SPRINTF_CHAR
390Sstevel@tonic-gate # define SPRINTF(x) strlen(sprintf/**/x)
400Sstevel@tonic-gate #else
410Sstevel@tonic-gate # define SPRINTF(x) ((size_t)sprintf x)
420Sstevel@tonic-gate #endif
430Sstevel@tonic-gate
44*11038SRao.Shoaib@Sun.COM #define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */
450Sstevel@tonic-gate #define DNS_LABELTYPE_BITSTRING 0x41
460Sstevel@tonic-gate
470Sstevel@tonic-gate /* Data. */
480Sstevel@tonic-gate
490Sstevel@tonic-gate static const char digits[] = "0123456789";
500Sstevel@tonic-gate
510Sstevel@tonic-gate static const char digitvalue[256] = {
520Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
530Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
540Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
550Sstevel@tonic-gate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
560Sstevel@tonic-gate -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
570Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
580Sstevel@tonic-gate -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
590Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
600Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
610Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
620Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
630Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
640Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
650Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
660Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
670Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
680Sstevel@tonic-gate };
690Sstevel@tonic-gate
700Sstevel@tonic-gate /* Forward. */
710Sstevel@tonic-gate
720Sstevel@tonic-gate static int special(int);
730Sstevel@tonic-gate static int printable(int);
740Sstevel@tonic-gate static int dn_find(const u_char *, const u_char *,
750Sstevel@tonic-gate const u_char * const *,
760Sstevel@tonic-gate const u_char * const *);
770Sstevel@tonic-gate static int encode_bitsring(const char **, const char *,
78*11038SRao.Shoaib@Sun.COM unsigned char **, unsigned char **,
79*11038SRao.Shoaib@Sun.COM unsigned const char *);
800Sstevel@tonic-gate static int labellen(const u_char *);
81*11038SRao.Shoaib@Sun.COM static int decode_bitstring(const unsigned char **,
82*11038SRao.Shoaib@Sun.COM char *, const char *);
830Sstevel@tonic-gate
840Sstevel@tonic-gate /* Public. */
850Sstevel@tonic-gate
86*11038SRao.Shoaib@Sun.COM /*%
870Sstevel@tonic-gate * Convert an encoded domain name to printable ascii as per RFC1035.
88*11038SRao.Shoaib@Sun.COM
890Sstevel@tonic-gate * return:
90*11038SRao.Shoaib@Sun.COM *\li Number of bytes written to buffer, or -1 (with errno set)
91*11038SRao.Shoaib@Sun.COM *
920Sstevel@tonic-gate * notes:
93*11038SRao.Shoaib@Sun.COM *\li The root is returned as "."
94*11038SRao.Shoaib@Sun.COM *\li All other domains are returned in non absolute form
950Sstevel@tonic-gate */
960Sstevel@tonic-gate int
ns_name_ntop(const u_char * src,char * dst,size_t dstsiz)970Sstevel@tonic-gate ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
980Sstevel@tonic-gate {
990Sstevel@tonic-gate const u_char *cp;
1000Sstevel@tonic-gate char *dn, *eom;
1010Sstevel@tonic-gate u_char c;
1020Sstevel@tonic-gate u_int n;
1030Sstevel@tonic-gate int l;
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate cp = src;
1060Sstevel@tonic-gate dn = dst;
1070Sstevel@tonic-gate eom = dst + dstsiz;
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate while ((n = *cp++) != 0) {
1100Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
1110Sstevel@tonic-gate /* Some kind of compression pointer. */
1120Sstevel@tonic-gate errno = EMSGSIZE;
1130Sstevel@tonic-gate return (-1);
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate if (dn != dst) {
1160Sstevel@tonic-gate if (dn >= eom) {
1170Sstevel@tonic-gate errno = EMSGSIZE;
1180Sstevel@tonic-gate return (-1);
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate *dn++ = '.';
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate if ((l = labellen(cp - 1)) < 0) {
123*11038SRao.Shoaib@Sun.COM errno = EMSGSIZE; /*%< XXX */
124*11038SRao.Shoaib@Sun.COM return (-1);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate if (dn + l >= eom) {
1270Sstevel@tonic-gate errno = EMSGSIZE;
1280Sstevel@tonic-gate return (-1);
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
1310Sstevel@tonic-gate int m;
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate if (n != DNS_LABELTYPE_BITSTRING) {
1340Sstevel@tonic-gate /* XXX: labellen should reject this case */
1350Sstevel@tonic-gate errno = EINVAL;
136*11038SRao.Shoaib@Sun.COM return (-1);
1370Sstevel@tonic-gate }
138*11038SRao.Shoaib@Sun.COM if ((m = decode_bitstring(&cp, dn, eom)) < 0)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate errno = EMSGSIZE;
141*11038SRao.Shoaib@Sun.COM return (-1);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate dn += m;
1440Sstevel@tonic-gate continue;
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate for ((void)NULL; l > 0; l--) {
1470Sstevel@tonic-gate c = *cp++;
1480Sstevel@tonic-gate if (special(c)) {
1490Sstevel@tonic-gate if (dn + 1 >= eom) {
1500Sstevel@tonic-gate errno = EMSGSIZE;
1510Sstevel@tonic-gate return (-1);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate *dn++ = '\\';
1540Sstevel@tonic-gate *dn++ = (char)c;
1550Sstevel@tonic-gate } else if (!printable(c)) {
1560Sstevel@tonic-gate if (dn + 3 >= eom) {
1570Sstevel@tonic-gate errno = EMSGSIZE;
1580Sstevel@tonic-gate return (-1);
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate *dn++ = '\\';
1610Sstevel@tonic-gate *dn++ = digits[c / 100];
1620Sstevel@tonic-gate *dn++ = digits[(c % 100) / 10];
1630Sstevel@tonic-gate *dn++ = digits[c % 10];
1640Sstevel@tonic-gate } else {
1650Sstevel@tonic-gate if (dn >= eom) {
1660Sstevel@tonic-gate errno = EMSGSIZE;
1670Sstevel@tonic-gate return (-1);
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate *dn++ = (char)c;
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate if (dn == dst) {
1740Sstevel@tonic-gate if (dn >= eom) {
1750Sstevel@tonic-gate errno = EMSGSIZE;
1760Sstevel@tonic-gate return (-1);
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate *dn++ = '.';
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate if (dn >= eom) {
1810Sstevel@tonic-gate errno = EMSGSIZE;
1820Sstevel@tonic-gate return (-1);
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate *dn++ = '\0';
1850Sstevel@tonic-gate return (dn - dst);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate
188*11038SRao.Shoaib@Sun.COM /*%
189*11038SRao.Shoaib@Sun.COM * Convert a ascii string into an encoded domain name as per RFC1035.
190*11038SRao.Shoaib@Sun.COM *
191*11038SRao.Shoaib@Sun.COM * return:
192*11038SRao.Shoaib@Sun.COM *
193*11038SRao.Shoaib@Sun.COM *\li -1 if it fails
194*11038SRao.Shoaib@Sun.COM *\li 1 if string was fully qualified
195*11038SRao.Shoaib@Sun.COM *\li 0 is string was not fully qualified
196*11038SRao.Shoaib@Sun.COM *
197*11038SRao.Shoaib@Sun.COM * notes:
198*11038SRao.Shoaib@Sun.COM *\li Enforces label and domain length limits.
199*11038SRao.Shoaib@Sun.COM */
200*11038SRao.Shoaib@Sun.COM int
ns_name_pton(const char * src,u_char * dst,size_t dstsiz)201*11038SRao.Shoaib@Sun.COM ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
202*11038SRao.Shoaib@Sun.COM return (ns_name_pton2(src, dst, dstsiz, NULL));
203*11038SRao.Shoaib@Sun.COM }
204*11038SRao.Shoaib@Sun.COM
2050Sstevel@tonic-gate /*
206*11038SRao.Shoaib@Sun.COM * ns_name_pton2(src, dst, dstsiz, *dstlen)
2070Sstevel@tonic-gate * Convert a ascii string into an encoded domain name as per RFC1035.
2080Sstevel@tonic-gate * return:
2090Sstevel@tonic-gate * -1 if it fails
2100Sstevel@tonic-gate * 1 if string was fully qualified
2110Sstevel@tonic-gate * 0 is string was not fully qualified
212*11038SRao.Shoaib@Sun.COM * side effects:
213*11038SRao.Shoaib@Sun.COM * fills in *dstlen (if non-NULL)
2140Sstevel@tonic-gate * notes:
2150Sstevel@tonic-gate * Enforces label and domain length limits.
2160Sstevel@tonic-gate */
2170Sstevel@tonic-gate int
ns_name_pton2(const char * src,u_char * dst,size_t dstsiz,size_t * dstlen)218*11038SRao.Shoaib@Sun.COM ns_name_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen) {
2190Sstevel@tonic-gate u_char *label, *bp, *eom;
2200Sstevel@tonic-gate int c, n, escaped, e = 0;
2210Sstevel@tonic-gate char *cp;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate escaped = 0;
2240Sstevel@tonic-gate bp = dst;
2250Sstevel@tonic-gate eom = dst + dstsiz;
2260Sstevel@tonic-gate label = bp++;
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate while ((c = *src++) != 0) {
2290Sstevel@tonic-gate if (escaped) {
230*11038SRao.Shoaib@Sun.COM if (c == '[') { /*%< start a bit string label */
2310Sstevel@tonic-gate if ((cp = strchr(src, ']')) == NULL) {
232*11038SRao.Shoaib@Sun.COM errno = EINVAL; /*%< ??? */
233*11038SRao.Shoaib@Sun.COM return (-1);
2340Sstevel@tonic-gate }
235*11038SRao.Shoaib@Sun.COM if ((e = encode_bitsring(&src, cp + 2,
236*11038SRao.Shoaib@Sun.COM &label, &bp, eom))
2370Sstevel@tonic-gate != 0) {
2380Sstevel@tonic-gate errno = e;
239*11038SRao.Shoaib@Sun.COM return (-1);
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate escaped = 0;
2420Sstevel@tonic-gate label = bp++;
2430Sstevel@tonic-gate if ((c = *src++) == 0)
2440Sstevel@tonic-gate goto done;
2450Sstevel@tonic-gate else if (c != '.') {
2460Sstevel@tonic-gate errno = EINVAL;
247*11038SRao.Shoaib@Sun.COM return (-1);
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate continue;
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate else if ((cp = strchr(digits, c)) != NULL) {
2520Sstevel@tonic-gate n = (cp - digits) * 100;
2530Sstevel@tonic-gate if ((c = *src++) == 0 ||
2540Sstevel@tonic-gate (cp = strchr(digits, c)) == NULL) {
2550Sstevel@tonic-gate errno = EMSGSIZE;
2560Sstevel@tonic-gate return (-1);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate n += (cp - digits) * 10;
2590Sstevel@tonic-gate if ((c = *src++) == 0 ||
2600Sstevel@tonic-gate (cp = strchr(digits, c)) == NULL) {
2610Sstevel@tonic-gate errno = EMSGSIZE;
2620Sstevel@tonic-gate return (-1);
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate n += (cp - digits);
2650Sstevel@tonic-gate if (n > 255) {
2660Sstevel@tonic-gate errno = EMSGSIZE;
2670Sstevel@tonic-gate return (-1);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate c = n;
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate escaped = 0;
2720Sstevel@tonic-gate } else if (c == '\\') {
2730Sstevel@tonic-gate escaped = 1;
2740Sstevel@tonic-gate continue;
2750Sstevel@tonic-gate } else if (c == '.') {
2760Sstevel@tonic-gate c = (bp - label - 1);
277*11038SRao.Shoaib@Sun.COM if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
2780Sstevel@tonic-gate errno = EMSGSIZE;
2790Sstevel@tonic-gate return (-1);
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate if (label >= eom) {
2820Sstevel@tonic-gate errno = EMSGSIZE;
2830Sstevel@tonic-gate return (-1);
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate *label = c;
2860Sstevel@tonic-gate /* Fully qualified ? */
2870Sstevel@tonic-gate if (*src == '\0') {
2880Sstevel@tonic-gate if (c != 0) {
2890Sstevel@tonic-gate if (bp >= eom) {
2900Sstevel@tonic-gate errno = EMSGSIZE;
2910Sstevel@tonic-gate return (-1);
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate *bp++ = '\0';
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate if ((bp - dst) > MAXCDNAME) {
2960Sstevel@tonic-gate errno = EMSGSIZE;
2970Sstevel@tonic-gate return (-1);
2980Sstevel@tonic-gate }
299*11038SRao.Shoaib@Sun.COM if (dstlen != NULL)
300*11038SRao.Shoaib@Sun.COM *dstlen = (bp - dst);
3010Sstevel@tonic-gate return (1);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate if (c == 0 || *src == '.') {
3040Sstevel@tonic-gate errno = EMSGSIZE;
3050Sstevel@tonic-gate return (-1);
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate label = bp++;
3080Sstevel@tonic-gate continue;
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate if (bp >= eom) {
3110Sstevel@tonic-gate errno = EMSGSIZE;
3120Sstevel@tonic-gate return (-1);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate *bp++ = (u_char)c;
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate c = (bp - label - 1);
317*11038SRao.Shoaib@Sun.COM if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
3180Sstevel@tonic-gate errno = EMSGSIZE;
3190Sstevel@tonic-gate return (-1);
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate done:
3220Sstevel@tonic-gate if (label >= eom) {
3230Sstevel@tonic-gate errno = EMSGSIZE;
3240Sstevel@tonic-gate return (-1);
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate *label = c;
3270Sstevel@tonic-gate if (c != 0) {
3280Sstevel@tonic-gate if (bp >= eom) {
3290Sstevel@tonic-gate errno = EMSGSIZE;
3300Sstevel@tonic-gate return (-1);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate *bp++ = 0;
3330Sstevel@tonic-gate }
334*11038SRao.Shoaib@Sun.COM if ((bp - dst) > MAXCDNAME) { /*%< src too big */
3350Sstevel@tonic-gate errno = EMSGSIZE;
3360Sstevel@tonic-gate return (-1);
3370Sstevel@tonic-gate }
338*11038SRao.Shoaib@Sun.COM if (dstlen != NULL)
339*11038SRao.Shoaib@Sun.COM *dstlen = (bp - dst);
3400Sstevel@tonic-gate return (0);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate
343*11038SRao.Shoaib@Sun.COM /*%
3440Sstevel@tonic-gate * Convert a network strings labels into all lowercase.
345*11038SRao.Shoaib@Sun.COM *
3460Sstevel@tonic-gate * return:
347*11038SRao.Shoaib@Sun.COM *\li Number of bytes written to buffer, or -1 (with errno set)
348*11038SRao.Shoaib@Sun.COM *
3490Sstevel@tonic-gate * notes:
350*11038SRao.Shoaib@Sun.COM *\li Enforces label and domain length limits.
3510Sstevel@tonic-gate */
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate int
ns_name_ntol(const u_char * src,u_char * dst,size_t dstsiz)3540Sstevel@tonic-gate ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
3550Sstevel@tonic-gate {
3560Sstevel@tonic-gate const u_char *cp;
3570Sstevel@tonic-gate u_char *dn, *eom;
3580Sstevel@tonic-gate u_char c;
3590Sstevel@tonic-gate u_int n;
3600Sstevel@tonic-gate int l;
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate cp = src;
3630Sstevel@tonic-gate dn = dst;
3640Sstevel@tonic-gate eom = dst + dstsiz;
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate if (dn >= eom) {
3670Sstevel@tonic-gate errno = EMSGSIZE;
3680Sstevel@tonic-gate return (-1);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate while ((n = *cp++) != 0) {
3710Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
3720Sstevel@tonic-gate /* Some kind of compression pointer. */
3730Sstevel@tonic-gate errno = EMSGSIZE;
3740Sstevel@tonic-gate return (-1);
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate *dn++ = n;
3770Sstevel@tonic-gate if ((l = labellen(cp - 1)) < 0) {
3780Sstevel@tonic-gate errno = EMSGSIZE;
3790Sstevel@tonic-gate return (-1);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate if (dn + l >= eom) {
3820Sstevel@tonic-gate errno = EMSGSIZE;
3830Sstevel@tonic-gate return (-1);
3840Sstevel@tonic-gate }
3850Sstevel@tonic-gate for ((void)NULL; l > 0; l--) {
3860Sstevel@tonic-gate c = *cp++;
387*11038SRao.Shoaib@Sun.COM if (isascii(c) && isupper(c))
3880Sstevel@tonic-gate *dn++ = tolower(c);
3890Sstevel@tonic-gate else
3900Sstevel@tonic-gate *dn++ = c;
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate *dn++ = '\0';
3940Sstevel@tonic-gate return (dn - dst);
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate
397*11038SRao.Shoaib@Sun.COM /*%
3980Sstevel@tonic-gate * Unpack a domain name from a message, source may be compressed.
399*11038SRao.Shoaib@Sun.COM *
4000Sstevel@tonic-gate * return:
401*11038SRao.Shoaib@Sun.COM *\li -1 if it fails, or consumed octets if it succeeds.
4020Sstevel@tonic-gate */
4030Sstevel@tonic-gate int
ns_name_unpack(const u_char * msg,const u_char * eom,const u_char * src,u_char * dst,size_t dstsiz)4040Sstevel@tonic-gate ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
4050Sstevel@tonic-gate u_char *dst, size_t dstsiz)
4060Sstevel@tonic-gate {
407*11038SRao.Shoaib@Sun.COM return (ns_name_unpack2(msg, eom, src, dst, dstsiz, NULL));
408*11038SRao.Shoaib@Sun.COM }
409*11038SRao.Shoaib@Sun.COM
410*11038SRao.Shoaib@Sun.COM /*
411*11038SRao.Shoaib@Sun.COM * ns_name_unpack2(msg, eom, src, dst, dstsiz, *dstlen)
412*11038SRao.Shoaib@Sun.COM * Unpack a domain name from a message, source may be compressed.
413*11038SRao.Shoaib@Sun.COM * return:
414*11038SRao.Shoaib@Sun.COM * -1 if it fails, or consumed octets if it succeeds.
415*11038SRao.Shoaib@Sun.COM * side effect:
416*11038SRao.Shoaib@Sun.COM * fills in *dstlen (if non-NULL).
417*11038SRao.Shoaib@Sun.COM */
418*11038SRao.Shoaib@Sun.COM 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)419*11038SRao.Shoaib@Sun.COM ns_name_unpack2(const u_char *msg, const u_char *eom, const u_char *src,
420*11038SRao.Shoaib@Sun.COM u_char *dst, size_t dstsiz, size_t *dstlen)
421*11038SRao.Shoaib@Sun.COM {
4220Sstevel@tonic-gate const u_char *srcp, *dstlim;
4230Sstevel@tonic-gate u_char *dstp;
4240Sstevel@tonic-gate int n, len, checked, l;
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate len = -1;
4270Sstevel@tonic-gate checked = 0;
4280Sstevel@tonic-gate dstp = dst;
4290Sstevel@tonic-gate srcp = src;
4300Sstevel@tonic-gate dstlim = dst + dstsiz;
4310Sstevel@tonic-gate if (srcp < msg || srcp >= eom) {
4320Sstevel@tonic-gate errno = EMSGSIZE;
4330Sstevel@tonic-gate return (-1);
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate /* Fetch next label in domain name. */
4360Sstevel@tonic-gate while ((n = *srcp++) != 0) {
4370Sstevel@tonic-gate /* Check for indirection. */
4380Sstevel@tonic-gate switch (n & NS_CMPRSFLGS) {
4390Sstevel@tonic-gate case 0:
4400Sstevel@tonic-gate case NS_TYPE_ELT:
4410Sstevel@tonic-gate /* Limit checks. */
4420Sstevel@tonic-gate if ((l = labellen(srcp - 1)) < 0) {
4430Sstevel@tonic-gate errno = EMSGSIZE;
444*11038SRao.Shoaib@Sun.COM return (-1);
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
4470Sstevel@tonic-gate errno = EMSGSIZE;
4480Sstevel@tonic-gate return (-1);
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate checked += l + 1;
4510Sstevel@tonic-gate *dstp++ = n;
4520Sstevel@tonic-gate memcpy(dstp, srcp, l);
4530Sstevel@tonic-gate dstp += l;
4540Sstevel@tonic-gate srcp += l;
4550Sstevel@tonic-gate break;
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate case NS_CMPRSFLGS:
4580Sstevel@tonic-gate if (srcp >= eom) {
4590Sstevel@tonic-gate errno = EMSGSIZE;
4600Sstevel@tonic-gate return (-1);
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate if (len < 0)
4630Sstevel@tonic-gate len = srcp - src + 1;
4640Sstevel@tonic-gate srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
465*11038SRao.Shoaib@Sun.COM if (srcp < msg || srcp >= eom) { /*%< Out of range. */
4660Sstevel@tonic-gate errno = EMSGSIZE;
4670Sstevel@tonic-gate return (-1);
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate checked += 2;
4700Sstevel@tonic-gate /*
4710Sstevel@tonic-gate * Check for loops in the compressed name;
4720Sstevel@tonic-gate * if we've looked at the whole message,
4730Sstevel@tonic-gate * there must be a loop.
4740Sstevel@tonic-gate */
4750Sstevel@tonic-gate if (checked >= eom - msg) {
4760Sstevel@tonic-gate errno = EMSGSIZE;
4770Sstevel@tonic-gate return (-1);
4780Sstevel@tonic-gate }
4790Sstevel@tonic-gate break;
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate default:
4820Sstevel@tonic-gate errno = EMSGSIZE;
483*11038SRao.Shoaib@Sun.COM return (-1); /*%< flag error */
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate }
486*11038SRao.Shoaib@Sun.COM *dstp++ = 0;
487*11038SRao.Shoaib@Sun.COM if (dstlen != NULL)
488*11038SRao.Shoaib@Sun.COM *dstlen = dstp - dst;
4890Sstevel@tonic-gate if (len < 0)
4900Sstevel@tonic-gate len = srcp - src;
4910Sstevel@tonic-gate return (len);
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate
494*11038SRao.Shoaib@Sun.COM /*%
4950Sstevel@tonic-gate * Pack domain name 'domain' into 'comp_dn'.
496*11038SRao.Shoaib@Sun.COM *
4970Sstevel@tonic-gate * return:
498*11038SRao.Shoaib@Sun.COM *\li Size of the compressed name, or -1.
499*11038SRao.Shoaib@Sun.COM *
5000Sstevel@tonic-gate * notes:
501*11038SRao.Shoaib@Sun.COM *\li 'dnptrs' is an array of pointers to previous compressed names.
502*11038SRao.Shoaib@Sun.COM *\li dnptrs[0] is a pointer to the beginning of the message. The array
5030Sstevel@tonic-gate * ends with NULL.
504*11038SRao.Shoaib@Sun.COM *\li 'lastdnptr' is a pointer to the end of the array pointed to
5050Sstevel@tonic-gate * by 'dnptrs'.
506*11038SRao.Shoaib@Sun.COM *
5070Sstevel@tonic-gate * Side effects:
508*11038SRao.Shoaib@Sun.COM *\li The list of pointers in dnptrs is updated for labels inserted into
5090Sstevel@tonic-gate * the message as we compress the name. If 'dnptr' is NULL, we don't
5100Sstevel@tonic-gate * try to compress names. If 'lastdnptr' is NULL, we don't update the
5110Sstevel@tonic-gate * list.
5120Sstevel@tonic-gate */
5130Sstevel@tonic-gate int
ns_name_pack(const u_char * src,u_char * dst,int dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)5140Sstevel@tonic-gate ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
5150Sstevel@tonic-gate const u_char **dnptrs, const u_char **lastdnptr)
5160Sstevel@tonic-gate {
5170Sstevel@tonic-gate u_char *dstp;
5180Sstevel@tonic-gate const u_char **cpp, **lpp, *eob, *msg;
5190Sstevel@tonic-gate const u_char *srcp;
5200Sstevel@tonic-gate int n, l, first = 1;
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate srcp = src;
5230Sstevel@tonic-gate dstp = dst;
5240Sstevel@tonic-gate eob = dstp + dstsiz;
5250Sstevel@tonic-gate lpp = cpp = NULL;
5260Sstevel@tonic-gate if (dnptrs != NULL) {
5270Sstevel@tonic-gate if ((msg = *dnptrs++) != NULL) {
5280Sstevel@tonic-gate for (cpp = dnptrs; *cpp != NULL; cpp++)
5290Sstevel@tonic-gate (void)NULL;
530*11038SRao.Shoaib@Sun.COM lpp = cpp; /*%< end of list to search */
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate } else
5330Sstevel@tonic-gate msg = NULL;
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate /* make sure the domain we are about to add is legal */
5360Sstevel@tonic-gate l = 0;
5370Sstevel@tonic-gate do {
5380Sstevel@tonic-gate int l0;
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate n = *srcp;
5410Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
5420Sstevel@tonic-gate errno = EMSGSIZE;
5430Sstevel@tonic-gate return (-1);
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate if ((l0 = labellen(srcp)) < 0) {
5460Sstevel@tonic-gate errno = EINVAL;
547*11038SRao.Shoaib@Sun.COM return (-1);
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate l += l0 + 1;
5500Sstevel@tonic-gate if (l > MAXCDNAME) {
5510Sstevel@tonic-gate errno = EMSGSIZE;
5520Sstevel@tonic-gate return (-1);
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate srcp += l0 + 1;
5550Sstevel@tonic-gate } while (n != 0);
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate /* from here on we need to reset compression pointer array on error */
5580Sstevel@tonic-gate srcp = src;
5590Sstevel@tonic-gate do {
5600Sstevel@tonic-gate /* Look to see if we can use pointers. */
5610Sstevel@tonic-gate n = *srcp;
5620Sstevel@tonic-gate if (n != 0 && msg != NULL) {
5630Sstevel@tonic-gate l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
5640Sstevel@tonic-gate (const u_char * const *)lpp);
5650Sstevel@tonic-gate if (l >= 0) {
5660Sstevel@tonic-gate if (dstp + 1 >= eob) {
5670Sstevel@tonic-gate goto cleanup;
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate *dstp++ = (l >> 8) | NS_CMPRSFLGS;
5700Sstevel@tonic-gate *dstp++ = l % 256;
5710Sstevel@tonic-gate return (dstp - dst);
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate /* Not found, save it. */
5740Sstevel@tonic-gate if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
5750Sstevel@tonic-gate (dstp - msg) < 0x4000 && first) {
5760Sstevel@tonic-gate *cpp++ = dstp;
5770Sstevel@tonic-gate *cpp = NULL;
5780Sstevel@tonic-gate first = 0;
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate /* copy label to buffer */
5820Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
5830Sstevel@tonic-gate /* Should not happen. */
5840Sstevel@tonic-gate goto cleanup;
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate n = labellen(srcp);
5870Sstevel@tonic-gate if (dstp + 1 + n >= eob) {
5880Sstevel@tonic-gate goto cleanup;
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate memcpy(dstp, srcp, n + 1);
5910Sstevel@tonic-gate srcp += n + 1;
5920Sstevel@tonic-gate dstp += n + 1;
5930Sstevel@tonic-gate } while (n != 0);
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate if (dstp > eob) {
5960Sstevel@tonic-gate cleanup:
5970Sstevel@tonic-gate if (msg != NULL)
5980Sstevel@tonic-gate *lpp = NULL;
5990Sstevel@tonic-gate errno = EMSGSIZE;
6000Sstevel@tonic-gate return (-1);
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate return (dstp - dst);
6030Sstevel@tonic-gate }
6040Sstevel@tonic-gate
605*11038SRao.Shoaib@Sun.COM /*%
6060Sstevel@tonic-gate * Expand compressed domain name to presentation format.
607*11038SRao.Shoaib@Sun.COM *
6080Sstevel@tonic-gate * return:
609*11038SRao.Shoaib@Sun.COM *\li Number of bytes read out of `src', or -1 (with errno set).
610*11038SRao.Shoaib@Sun.COM *
6110Sstevel@tonic-gate * note:
612*11038SRao.Shoaib@Sun.COM *\li Root domain returns as "." not "".
6130Sstevel@tonic-gate */
6140Sstevel@tonic-gate int
ns_name_uncompress(const u_char * msg,const u_char * eom,const u_char * src,char * dst,size_t dstsiz)6150Sstevel@tonic-gate ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
6160Sstevel@tonic-gate char *dst, size_t dstsiz)
6170Sstevel@tonic-gate {
6180Sstevel@tonic-gate u_char tmp[NS_MAXCDNAME];
6190Sstevel@tonic-gate int n;
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
6220Sstevel@tonic-gate return (-1);
6230Sstevel@tonic-gate if (ns_name_ntop(tmp, dst, dstsiz) == -1)
6240Sstevel@tonic-gate return (-1);
6250Sstevel@tonic-gate return (n);
6260Sstevel@tonic-gate }
6270Sstevel@tonic-gate
628*11038SRao.Shoaib@Sun.COM /*%
6290Sstevel@tonic-gate * Compress a domain name into wire format, using compression pointers.
630*11038SRao.Shoaib@Sun.COM *
6310Sstevel@tonic-gate * return:
632*11038SRao.Shoaib@Sun.COM *\li Number of bytes consumed in `dst' or -1 (with errno set).
633*11038SRao.Shoaib@Sun.COM *
6340Sstevel@tonic-gate * notes:
635*11038SRao.Shoaib@Sun.COM *\li 'dnptrs' is an array of pointers to previous compressed names.
636*11038SRao.Shoaib@Sun.COM *\li dnptrs[0] is a pointer to the beginning of the message.
637*11038SRao.Shoaib@Sun.COM *\li The list ends with NULL. 'lastdnptr' is a pointer to the end of the
6380Sstevel@tonic-gate * array pointed to by 'dnptrs'. Side effect is to update the list of
6390Sstevel@tonic-gate * pointers for labels inserted into the message as we compress the name.
640*11038SRao.Shoaib@Sun.COM *\li If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
6410Sstevel@tonic-gate * is NULL, we don't update the list.
6420Sstevel@tonic-gate */
6430Sstevel@tonic-gate int
ns_name_compress(const char * src,u_char * dst,size_t dstsiz,const u_char ** dnptrs,const u_char ** lastdnptr)6440Sstevel@tonic-gate ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
6450Sstevel@tonic-gate const u_char **dnptrs, const u_char **lastdnptr)
6460Sstevel@tonic-gate {
6470Sstevel@tonic-gate u_char tmp[NS_MAXCDNAME];
6480Sstevel@tonic-gate
6490Sstevel@tonic-gate if (ns_name_pton(src, tmp, sizeof tmp) == -1)
6500Sstevel@tonic-gate return (-1);
6510Sstevel@tonic-gate return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate
654*11038SRao.Shoaib@Sun.COM /*%
6550Sstevel@tonic-gate * Reset dnptrs so that there are no active references to pointers at or
6560Sstevel@tonic-gate * after src.
6570Sstevel@tonic-gate */
6580Sstevel@tonic-gate void
ns_name_rollback(const u_char * src,const u_char ** dnptrs,const u_char ** lastdnptr)6590Sstevel@tonic-gate ns_name_rollback(const u_char *src, const u_char **dnptrs,
6600Sstevel@tonic-gate const u_char **lastdnptr)
6610Sstevel@tonic-gate {
6620Sstevel@tonic-gate while (dnptrs < lastdnptr && *dnptrs != NULL) {
6630Sstevel@tonic-gate if (*dnptrs >= src) {
6640Sstevel@tonic-gate *dnptrs = NULL;
6650Sstevel@tonic-gate break;
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate dnptrs++;
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate
671*11038SRao.Shoaib@Sun.COM /*%
6720Sstevel@tonic-gate * Advance *ptrptr to skip over the compressed name it points at.
673*11038SRao.Shoaib@Sun.COM *
6740Sstevel@tonic-gate * return:
675*11038SRao.Shoaib@Sun.COM *\li 0 on success, -1 (with errno set) on failure.
6760Sstevel@tonic-gate */
6770Sstevel@tonic-gate int
ns_name_skip(const u_char ** ptrptr,const u_char * eom)6780Sstevel@tonic-gate ns_name_skip(const u_char **ptrptr, const u_char *eom)
6790Sstevel@tonic-gate {
6800Sstevel@tonic-gate const u_char *cp;
6810Sstevel@tonic-gate u_int n;
6820Sstevel@tonic-gate int l;
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate cp = *ptrptr;
6850Sstevel@tonic-gate while (cp < eom && (n = *cp++) != 0) {
6860Sstevel@tonic-gate /* Check for indirection. */
6870Sstevel@tonic-gate switch (n & NS_CMPRSFLGS) {
688*11038SRao.Shoaib@Sun.COM case 0: /*%< normal case, n == len */
6890Sstevel@tonic-gate cp += n;
6900Sstevel@tonic-gate continue;
691*11038SRao.Shoaib@Sun.COM case NS_TYPE_ELT: /*%< EDNS0 extended label */
6920Sstevel@tonic-gate if ((l = labellen(cp - 1)) < 0) {
693*11038SRao.Shoaib@Sun.COM errno = EMSGSIZE; /*%< XXX */
694*11038SRao.Shoaib@Sun.COM return (-1);
6950Sstevel@tonic-gate }
6960Sstevel@tonic-gate cp += l;
6970Sstevel@tonic-gate continue;
698*11038SRao.Shoaib@Sun.COM case NS_CMPRSFLGS: /*%< indirection */
6990Sstevel@tonic-gate cp++;
7000Sstevel@tonic-gate break;
701*11038SRao.Shoaib@Sun.COM default: /*%< illegal type */
7020Sstevel@tonic-gate errno = EMSGSIZE;
7030Sstevel@tonic-gate return (-1);
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate break;
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate if (cp > eom) {
7080Sstevel@tonic-gate errno = EMSGSIZE;
7090Sstevel@tonic-gate return (-1);
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate *ptrptr = cp;
7120Sstevel@tonic-gate return (0);
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate
715*11038SRao.Shoaib@Sun.COM /* Find the number of octets an nname takes up, including the root label.
716*11038SRao.Shoaib@Sun.COM * (This is basically ns_name_skip() without compression-pointer support.)
717*11038SRao.Shoaib@Sun.COM * ((NOTE: can only return zero if passed-in namesiz argument is zero.))
718*11038SRao.Shoaib@Sun.COM */
719*11038SRao.Shoaib@Sun.COM ssize_t
ns_name_length(ns_nname_ct nname,size_t namesiz)720*11038SRao.Shoaib@Sun.COM ns_name_length(ns_nname_ct nname, size_t namesiz) {
721*11038SRao.Shoaib@Sun.COM ns_nname_ct orig = nname;
722*11038SRao.Shoaib@Sun.COM u_int n;
723*11038SRao.Shoaib@Sun.COM
724*11038SRao.Shoaib@Sun.COM while (namesiz-- > 0 && (n = *nname++) != 0) {
725*11038SRao.Shoaib@Sun.COM if ((n & NS_CMPRSFLGS) != 0) {
726*11038SRao.Shoaib@Sun.COM errno = EISDIR;
727*11038SRao.Shoaib@Sun.COM return (-1);
728*11038SRao.Shoaib@Sun.COM }
729*11038SRao.Shoaib@Sun.COM if (n > namesiz) {
730*11038SRao.Shoaib@Sun.COM errno = EMSGSIZE;
731*11038SRao.Shoaib@Sun.COM return (-1);
732*11038SRao.Shoaib@Sun.COM }
733*11038SRao.Shoaib@Sun.COM nname += n;
734*11038SRao.Shoaib@Sun.COM namesiz -= n;
735*11038SRao.Shoaib@Sun.COM }
736*11038SRao.Shoaib@Sun.COM return (nname - orig);
737*11038SRao.Shoaib@Sun.COM }
738*11038SRao.Shoaib@Sun.COM
739*11038SRao.Shoaib@Sun.COM /* Compare two nname's for equality. Return -1 on error (setting errno).
740*11038SRao.Shoaib@Sun.COM */
741*11038SRao.Shoaib@Sun.COM int
ns_name_eq(ns_nname_ct a,size_t as,ns_nname_ct b,size_t bs)742*11038SRao.Shoaib@Sun.COM ns_name_eq(ns_nname_ct a, size_t as, ns_nname_ct b, size_t bs) {
743*11038SRao.Shoaib@Sun.COM ns_nname_ct ae = a + as, be = b + bs;
744*11038SRao.Shoaib@Sun.COM int ac, bc;
745*11038SRao.Shoaib@Sun.COM
746*11038SRao.Shoaib@Sun.COM while (ac = *a, bc = *b, ac != 0 && bc != 0) {
747*11038SRao.Shoaib@Sun.COM if ((ac & NS_CMPRSFLGS) != 0 || (bc & NS_CMPRSFLGS) != 0) {
748*11038SRao.Shoaib@Sun.COM errno = EISDIR;
749*11038SRao.Shoaib@Sun.COM return (-1);
750*11038SRao.Shoaib@Sun.COM }
751*11038SRao.Shoaib@Sun.COM if (a + ac >= ae || b + bc >= be) {
752*11038SRao.Shoaib@Sun.COM errno = EMSGSIZE;
753*11038SRao.Shoaib@Sun.COM return (-1);
754*11038SRao.Shoaib@Sun.COM }
755*11038SRao.Shoaib@Sun.COM if (ac != bc || strncasecmp((const char *) ++a,
756*11038SRao.Shoaib@Sun.COM (const char *) ++b, ac) != 0)
757*11038SRao.Shoaib@Sun.COM return (0);
758*11038SRao.Shoaib@Sun.COM a += ac, b += bc;
759*11038SRao.Shoaib@Sun.COM }
760*11038SRao.Shoaib@Sun.COM return (ac == 0 && bc == 0);
761*11038SRao.Shoaib@Sun.COM }
762*11038SRao.Shoaib@Sun.COM
763*11038SRao.Shoaib@Sun.COM /* Is domain "A" owned by (at or below) domain "B"?
764*11038SRao.Shoaib@Sun.COM */
765*11038SRao.Shoaib@Sun.COM int
ns_name_owned(ns_namemap_ct a,int an,ns_namemap_ct b,int bn)766*11038SRao.Shoaib@Sun.COM ns_name_owned(ns_namemap_ct a, int an, ns_namemap_ct b, int bn) {
767*11038SRao.Shoaib@Sun.COM /* If A is shorter, it cannot be owned by B. */
768*11038SRao.Shoaib@Sun.COM if (an < bn)
769*11038SRao.Shoaib@Sun.COM return (0);
770*11038SRao.Shoaib@Sun.COM
771*11038SRao.Shoaib@Sun.COM /* If they are unequal before the length of the shorter, A cannot... */
772*11038SRao.Shoaib@Sun.COM while (bn > 0) {
773*11038SRao.Shoaib@Sun.COM if (a->len != b->len ||
774*11038SRao.Shoaib@Sun.COM strncasecmp((const char *) a->base,
775*11038SRao.Shoaib@Sun.COM (const char *) b->base, a->len) != 0)
776*11038SRao.Shoaib@Sun.COM return (0);
777*11038SRao.Shoaib@Sun.COM a++, an--;
778*11038SRao.Shoaib@Sun.COM b++, bn--;
779*11038SRao.Shoaib@Sun.COM }
780*11038SRao.Shoaib@Sun.COM
781*11038SRao.Shoaib@Sun.COM /* A might be longer or not, but either way, B owns it. */
782*11038SRao.Shoaib@Sun.COM return (1);
783*11038SRao.Shoaib@Sun.COM }
784*11038SRao.Shoaib@Sun.COM
785*11038SRao.Shoaib@Sun.COM /* Build an array of <base,len> tuples from an nname, top-down order.
786*11038SRao.Shoaib@Sun.COM * Return the number of tuples (labels) thus discovered.
787*11038SRao.Shoaib@Sun.COM */
788*11038SRao.Shoaib@Sun.COM int
ns_name_map(ns_nname_ct nname,size_t namelen,ns_namemap_t map,int mapsize)789*11038SRao.Shoaib@Sun.COM ns_name_map(ns_nname_ct nname, size_t namelen, ns_namemap_t map, int mapsize) {
790*11038SRao.Shoaib@Sun.COM u_int n;
791*11038SRao.Shoaib@Sun.COM int l;
792*11038SRao.Shoaib@Sun.COM
793*11038SRao.Shoaib@Sun.COM n = *nname++;
794*11038SRao.Shoaib@Sun.COM namelen--;
795*11038SRao.Shoaib@Sun.COM
796*11038SRao.Shoaib@Sun.COM /* Root zone? */
797*11038SRao.Shoaib@Sun.COM if (n == 0) {
798*11038SRao.Shoaib@Sun.COM /* Extra data follows name? */
799*11038SRao.Shoaib@Sun.COM if (namelen > 0) {
800*11038SRao.Shoaib@Sun.COM errno = EMSGSIZE;
801*11038SRao.Shoaib@Sun.COM return (-1);
802*11038SRao.Shoaib@Sun.COM }
803*11038SRao.Shoaib@Sun.COM return (0);
804*11038SRao.Shoaib@Sun.COM }
805*11038SRao.Shoaib@Sun.COM
806*11038SRao.Shoaib@Sun.COM /* Compression pointer? */
807*11038SRao.Shoaib@Sun.COM if ((n & NS_CMPRSFLGS) != 0) {
808*11038SRao.Shoaib@Sun.COM errno = EISDIR;
809*11038SRao.Shoaib@Sun.COM return (-1);
810*11038SRao.Shoaib@Sun.COM }
811*11038SRao.Shoaib@Sun.COM
812*11038SRao.Shoaib@Sun.COM /* Label too long? */
813*11038SRao.Shoaib@Sun.COM if (n > namelen) {
814*11038SRao.Shoaib@Sun.COM errno = EMSGSIZE;
815*11038SRao.Shoaib@Sun.COM return (-1);
816*11038SRao.Shoaib@Sun.COM }
817*11038SRao.Shoaib@Sun.COM
818*11038SRao.Shoaib@Sun.COM /* Recurse to get rest of name done first. */
819*11038SRao.Shoaib@Sun.COM l = ns_name_map(nname + n, namelen - n, map, mapsize);
820*11038SRao.Shoaib@Sun.COM if (l < 0)
821*11038SRao.Shoaib@Sun.COM return (-1);
822*11038SRao.Shoaib@Sun.COM
823*11038SRao.Shoaib@Sun.COM /* Too many labels? */
824*11038SRao.Shoaib@Sun.COM if (l >= mapsize) {
825*11038SRao.Shoaib@Sun.COM errno = ENAMETOOLONG;
826*11038SRao.Shoaib@Sun.COM return (-1);
827*11038SRao.Shoaib@Sun.COM }
828*11038SRao.Shoaib@Sun.COM
829*11038SRao.Shoaib@Sun.COM /* We're on our way back up-stack, store current map data. */
830*11038SRao.Shoaib@Sun.COM map[l].base = nname;
831*11038SRao.Shoaib@Sun.COM map[l].len = n;
832*11038SRao.Shoaib@Sun.COM return (l + 1);
833*11038SRao.Shoaib@Sun.COM }
834*11038SRao.Shoaib@Sun.COM
835*11038SRao.Shoaib@Sun.COM /* Count the labels in a domain name. Root counts, so COM. has two. This
836*11038SRao.Shoaib@Sun.COM * is to make the result comparable to the result of ns_name_map().
837*11038SRao.Shoaib@Sun.COM */
838*11038SRao.Shoaib@Sun.COM int
ns_name_labels(ns_nname_ct nname,size_t namesiz)839*11038SRao.Shoaib@Sun.COM ns_name_labels(ns_nname_ct nname, size_t namesiz) {
840*11038SRao.Shoaib@Sun.COM int ret = 0;
841*11038SRao.Shoaib@Sun.COM u_int n;
842*11038SRao.Shoaib@Sun.COM
843*11038SRao.Shoaib@Sun.COM while (namesiz-- > 0 && (n = *nname++) != 0) {
844*11038SRao.Shoaib@Sun.COM if ((n & NS_CMPRSFLGS) != 0) {
845*11038SRao.Shoaib@Sun.COM errno = EISDIR;
846*11038SRao.Shoaib@Sun.COM return (-1);
847*11038SRao.Shoaib@Sun.COM }
848*11038SRao.Shoaib@Sun.COM if (n > namesiz) {
849*11038SRao.Shoaib@Sun.COM errno = EMSGSIZE;
850*11038SRao.Shoaib@Sun.COM return (-1);
851*11038SRao.Shoaib@Sun.COM }
852*11038SRao.Shoaib@Sun.COM nname += n;
853*11038SRao.Shoaib@Sun.COM namesiz -= n;
854*11038SRao.Shoaib@Sun.COM ret++;
855*11038SRao.Shoaib@Sun.COM }
856*11038SRao.Shoaib@Sun.COM return (ret + 1);
857*11038SRao.Shoaib@Sun.COM }
858*11038SRao.Shoaib@Sun.COM
8590Sstevel@tonic-gate /* Private. */
8600Sstevel@tonic-gate
861*11038SRao.Shoaib@Sun.COM /*%
8620Sstevel@tonic-gate * Thinking in noninternationalized USASCII (per the DNS spec),
8630Sstevel@tonic-gate * is this characted special ("in need of quoting") ?
864*11038SRao.Shoaib@Sun.COM *
8650Sstevel@tonic-gate * return:
866*11038SRao.Shoaib@Sun.COM *\li boolean.
8670Sstevel@tonic-gate */
8680Sstevel@tonic-gate static int
special(int ch)8690Sstevel@tonic-gate special(int ch) {
8700Sstevel@tonic-gate switch (ch) {
871*11038SRao.Shoaib@Sun.COM case 0x22: /*%< '"' */
872*11038SRao.Shoaib@Sun.COM case 0x2E: /*%< '.' */
873*11038SRao.Shoaib@Sun.COM case 0x3B: /*%< ';' */
874*11038SRao.Shoaib@Sun.COM case 0x5C: /*%< '\\' */
875*11038SRao.Shoaib@Sun.COM case 0x28: /*%< '(' */
876*11038SRao.Shoaib@Sun.COM case 0x29: /*%< ')' */
8770Sstevel@tonic-gate /* Special modifiers in zone files. */
878*11038SRao.Shoaib@Sun.COM case 0x40: /*%< '@' */
879*11038SRao.Shoaib@Sun.COM case 0x24: /*%< '$' */
8800Sstevel@tonic-gate return (1);
8810Sstevel@tonic-gate default:
8820Sstevel@tonic-gate return (0);
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate }
8850Sstevel@tonic-gate
886*11038SRao.Shoaib@Sun.COM /*%
8870Sstevel@tonic-gate * Thinking in noninternationalized USASCII (per the DNS spec),
8880Sstevel@tonic-gate * is this character visible and not a space when printed ?
889*11038SRao.Shoaib@Sun.COM *
8900Sstevel@tonic-gate * return:
891*11038SRao.Shoaib@Sun.COM *\li boolean.
8920Sstevel@tonic-gate */
8930Sstevel@tonic-gate static int
printable(int ch)8940Sstevel@tonic-gate printable(int ch) {
8950Sstevel@tonic-gate return (ch > 0x20 && ch < 0x7f);
8960Sstevel@tonic-gate }
8970Sstevel@tonic-gate
898*11038SRao.Shoaib@Sun.COM /*%
8990Sstevel@tonic-gate * Thinking in noninternationalized USASCII (per the DNS spec),
9000Sstevel@tonic-gate * convert this character to lower case if it's upper case.
9010Sstevel@tonic-gate */
9020Sstevel@tonic-gate static int
mklower(int ch)9030Sstevel@tonic-gate mklower(int ch) {
9040Sstevel@tonic-gate if (ch >= 0x41 && ch <= 0x5A)
9050Sstevel@tonic-gate return (ch + 0x20);
9060Sstevel@tonic-gate return (ch);
9070Sstevel@tonic-gate }
9080Sstevel@tonic-gate
909*11038SRao.Shoaib@Sun.COM /*%
9100Sstevel@tonic-gate * Search for the counted-label name in an array of compressed names.
911*11038SRao.Shoaib@Sun.COM *
9120Sstevel@tonic-gate * return:
913*11038SRao.Shoaib@Sun.COM *\li offset from msg if found, or -1.
914*11038SRao.Shoaib@Sun.COM *
9150Sstevel@tonic-gate * notes:
916*11038SRao.Shoaib@Sun.COM *\li dnptrs is the pointer to the first name on the list,
917*11038SRao.Shoaib@Sun.COM *\li not the pointer to the start of the message.
9180Sstevel@tonic-gate */
9190Sstevel@tonic-gate static int
dn_find(const u_char * domain,const u_char * msg,const u_char * const * dnptrs,const u_char * const * lastdnptr)9200Sstevel@tonic-gate dn_find(const u_char *domain, const u_char *msg,
9210Sstevel@tonic-gate const u_char * const *dnptrs,
9220Sstevel@tonic-gate const u_char * const *lastdnptr)
9230Sstevel@tonic-gate {
9240Sstevel@tonic-gate const u_char *dn, *cp, *sp;
9250Sstevel@tonic-gate const u_char * const *cpp;
9260Sstevel@tonic-gate u_int n;
9270Sstevel@tonic-gate
9280Sstevel@tonic-gate for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
9290Sstevel@tonic-gate sp = *cpp;
9300Sstevel@tonic-gate /*
9310Sstevel@tonic-gate * terminate search on:
9320Sstevel@tonic-gate * root label
9330Sstevel@tonic-gate * compression pointer
9340Sstevel@tonic-gate * unusable offset
9350Sstevel@tonic-gate */
9360Sstevel@tonic-gate while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
9370Sstevel@tonic-gate (sp - msg) < 0x4000) {
9380Sstevel@tonic-gate dn = domain;
9390Sstevel@tonic-gate cp = sp;
9400Sstevel@tonic-gate while ((n = *cp++) != 0) {
9410Sstevel@tonic-gate /*
9420Sstevel@tonic-gate * check for indirection
9430Sstevel@tonic-gate */
9440Sstevel@tonic-gate switch (n & NS_CMPRSFLGS) {
945*11038SRao.Shoaib@Sun.COM case 0: /*%< normal case, n == len */
946*11038SRao.Shoaib@Sun.COM n = labellen(cp - 1); /*%< XXX */
9470Sstevel@tonic-gate if (n != *dn++)
9480Sstevel@tonic-gate goto next;
9490Sstevel@tonic-gate
9500Sstevel@tonic-gate for ((void)NULL; n > 0; n--)
9510Sstevel@tonic-gate if (mklower(*dn++) !=
9520Sstevel@tonic-gate mklower(*cp++))
9530Sstevel@tonic-gate goto next;
9540Sstevel@tonic-gate /* Is next root for both ? */
9550Sstevel@tonic-gate if (*dn == '\0' && *cp == '\0')
9560Sstevel@tonic-gate return (sp - msg);
9570Sstevel@tonic-gate if (*dn)
9580Sstevel@tonic-gate continue;
9590Sstevel@tonic-gate goto next;
960*11038SRao.Shoaib@Sun.COM case NS_CMPRSFLGS: /*%< indirection */
9610Sstevel@tonic-gate cp = msg + (((n & 0x3f) << 8) | *cp);
9620Sstevel@tonic-gate break;
9630Sstevel@tonic-gate
964*11038SRao.Shoaib@Sun.COM default: /*%< illegal type */
9650Sstevel@tonic-gate errno = EMSGSIZE;
9660Sstevel@tonic-gate return (-1);
9670Sstevel@tonic-gate }
9680Sstevel@tonic-gate }
9690Sstevel@tonic-gate next: ;
9700Sstevel@tonic-gate sp += *sp + 1;
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate }
9730Sstevel@tonic-gate errno = ENOENT;
9740Sstevel@tonic-gate return (-1);
9750Sstevel@tonic-gate }
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate static int
decode_bitstring(const unsigned char ** cpp,char * dn,const char * eom)978*11038SRao.Shoaib@Sun.COM decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
9790Sstevel@tonic-gate {
980*11038SRao.Shoaib@Sun.COM const unsigned char *cp = *cpp;
9810Sstevel@tonic-gate char *beg = dn, tc;
9820Sstevel@tonic-gate int b, blen, plen, i;
9830Sstevel@tonic-gate
9840Sstevel@tonic-gate if ((blen = (*cp & 0xff)) == 0)
9850Sstevel@tonic-gate blen = 256;
9860Sstevel@tonic-gate plen = (blen + 3) / 4;
9870Sstevel@tonic-gate plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
9880Sstevel@tonic-gate if (dn + plen >= eom)
989*11038SRao.Shoaib@Sun.COM return (-1);
9900Sstevel@tonic-gate
9910Sstevel@tonic-gate cp++;
9920Sstevel@tonic-gate i = SPRINTF((dn, "\\[x"));
9930Sstevel@tonic-gate if (i < 0)
9940Sstevel@tonic-gate return (-1);
9950Sstevel@tonic-gate dn += i;
9960Sstevel@tonic-gate for (b = blen; b > 7; b -= 8, cp++) {
9970Sstevel@tonic-gate i = SPRINTF((dn, "%02x", *cp & 0xff));
9980Sstevel@tonic-gate if (i < 0)
9990Sstevel@tonic-gate return (-1);
10000Sstevel@tonic-gate dn += i;
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate if (b > 4) {
10030Sstevel@tonic-gate tc = *cp++;
10040Sstevel@tonic-gate i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
10050Sstevel@tonic-gate if (i < 0)
10060Sstevel@tonic-gate return (-1);
10070Sstevel@tonic-gate dn += i;
10080Sstevel@tonic-gate } else if (b > 0) {
10090Sstevel@tonic-gate tc = *cp++;
10100Sstevel@tonic-gate i = SPRINTF((dn, "%1x",
10110Sstevel@tonic-gate ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
10120Sstevel@tonic-gate if (i < 0)
10130Sstevel@tonic-gate return (-1);
10140Sstevel@tonic-gate dn += i;
10150Sstevel@tonic-gate }
10160Sstevel@tonic-gate i = SPRINTF((dn, "/%d]", blen));
10170Sstevel@tonic-gate if (i < 0)
10180Sstevel@tonic-gate return (-1);
10190Sstevel@tonic-gate dn += i;
10200Sstevel@tonic-gate
10210Sstevel@tonic-gate *cpp = cp;
1022*11038SRao.Shoaib@Sun.COM return (dn - beg);
10230Sstevel@tonic-gate }
10240Sstevel@tonic-gate
10250Sstevel@tonic-gate static int
encode_bitsring(const char ** bp,const char * end,unsigned char ** labelp,unsigned char ** dst,unsigned const char * eom)1026*11038SRao.Shoaib@Sun.COM encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
1027*11038SRao.Shoaib@Sun.COM unsigned char ** dst, unsigned const char *eom)
10280Sstevel@tonic-gate {
10290Sstevel@tonic-gate int afterslash = 0;
10300Sstevel@tonic-gate const char *cp = *bp;
1031*11038SRao.Shoaib@Sun.COM unsigned char *tp;
1032*11038SRao.Shoaib@Sun.COM char c;
10330Sstevel@tonic-gate const char *beg_blen;
10340Sstevel@tonic-gate char *end_blen = NULL;
10350Sstevel@tonic-gate int value = 0, count = 0, tbcount = 0, blen = 0;
10360Sstevel@tonic-gate
10370Sstevel@tonic-gate beg_blen = end_blen = NULL;
10380Sstevel@tonic-gate
10390Sstevel@tonic-gate /* a bitstring must contain at least 2 characters */
10400Sstevel@tonic-gate if (end - cp < 2)
1041*11038SRao.Shoaib@Sun.COM return (EINVAL);
10420Sstevel@tonic-gate
10430Sstevel@tonic-gate /* XXX: currently, only hex strings are supported */
10440Sstevel@tonic-gate if (*cp++ != 'x')
1045*11038SRao.Shoaib@Sun.COM return (EINVAL);
1046*11038SRao.Shoaib@Sun.COM if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */
1047*11038SRao.Shoaib@Sun.COM return (EINVAL);
10480Sstevel@tonic-gate
10490Sstevel@tonic-gate for (tp = *dst + 1; cp < end && tp < eom; cp++) {
10500Sstevel@tonic-gate switch((c = *cp)) {
1051*11038SRao.Shoaib@Sun.COM case ']': /*%< end of the bitstring */
10520Sstevel@tonic-gate if (afterslash) {
10530Sstevel@tonic-gate if (beg_blen == NULL)
1054*11038SRao.Shoaib@Sun.COM return (EINVAL);
10550Sstevel@tonic-gate blen = (int)strtol(beg_blen, &end_blen, 10);
10560Sstevel@tonic-gate if (*end_blen != ']')
1057*11038SRao.Shoaib@Sun.COM return (EINVAL);
10580Sstevel@tonic-gate }
10590Sstevel@tonic-gate if (count)
10600Sstevel@tonic-gate *tp++ = ((value << 4) & 0xff);
1061*11038SRao.Shoaib@Sun.COM cp++; /*%< skip ']' */
10620Sstevel@tonic-gate goto done;
10630Sstevel@tonic-gate case '/':
10640Sstevel@tonic-gate afterslash = 1;
10650Sstevel@tonic-gate break;
10660Sstevel@tonic-gate default:
10670Sstevel@tonic-gate if (afterslash) {
10680Sstevel@tonic-gate if (!isdigit(c&0xff))
1069*11038SRao.Shoaib@Sun.COM return (EINVAL);
10700Sstevel@tonic-gate if (beg_blen == NULL) {
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate if (c == '0') {
10730Sstevel@tonic-gate /* blen never begings with 0 */
1074*11038SRao.Shoaib@Sun.COM return (EINVAL);
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate beg_blen = cp;
10770Sstevel@tonic-gate }
10780Sstevel@tonic-gate } else {
10790Sstevel@tonic-gate if (!isxdigit(c&0xff))
1080*11038SRao.Shoaib@Sun.COM return (EINVAL);
10810Sstevel@tonic-gate value <<= 4;
10820Sstevel@tonic-gate value += digitvalue[(int)c];
10830Sstevel@tonic-gate count += 4;
10840Sstevel@tonic-gate tbcount += 4;
10850Sstevel@tonic-gate if (tbcount > 256)
1086*11038SRao.Shoaib@Sun.COM return (EINVAL);
10870Sstevel@tonic-gate if (count == 8) {
10880Sstevel@tonic-gate *tp++ = value;
10890Sstevel@tonic-gate count = 0;
10900Sstevel@tonic-gate }
10910Sstevel@tonic-gate }
10920Sstevel@tonic-gate break;
10930Sstevel@tonic-gate }
10940Sstevel@tonic-gate }
10950Sstevel@tonic-gate done:
10960Sstevel@tonic-gate if (cp >= end || tp >= eom)
1097*11038SRao.Shoaib@Sun.COM return (EMSGSIZE);
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate /*
11000Sstevel@tonic-gate * bit length validation:
11010Sstevel@tonic-gate * If a <length> is present, the number of digits in the <bit-data>
11020Sstevel@tonic-gate * MUST be just sufficient to contain the number of bits specified
11030Sstevel@tonic-gate * by the <length>. If there are insignificant bits in a final
11040Sstevel@tonic-gate * hexadecimal or octal digit, they MUST be zero.
1105*11038SRao.Shoaib@Sun.COM * RFC2673, Section 3.2.
11060Sstevel@tonic-gate */
11070Sstevel@tonic-gate if (blen > 0) {
11080Sstevel@tonic-gate int traillen;
11090Sstevel@tonic-gate
11100Sstevel@tonic-gate if (((blen + 3) & ~3) != tbcount)
1111*11038SRao.Shoaib@Sun.COM return (EINVAL);
1112*11038SRao.Shoaib@Sun.COM traillen = tbcount - blen; /*%< between 0 and 3 */
11130Sstevel@tonic-gate if (((value << (8 - traillen)) & 0xff) != 0)
1114*11038SRao.Shoaib@Sun.COM return (EINVAL);
11150Sstevel@tonic-gate }
11160Sstevel@tonic-gate else
11170Sstevel@tonic-gate blen = tbcount;
11180Sstevel@tonic-gate if (blen == 256)
11190Sstevel@tonic-gate blen = 0;
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate /* encode the type and the significant bit fields */
11220Sstevel@tonic-gate **labelp = DNS_LABELTYPE_BITSTRING;
11230Sstevel@tonic-gate **dst = blen;
11240Sstevel@tonic-gate
11250Sstevel@tonic-gate *bp = cp;
11260Sstevel@tonic-gate *dst = tp;
11270Sstevel@tonic-gate
1128*11038SRao.Shoaib@Sun.COM return (0);
11290Sstevel@tonic-gate }
11300Sstevel@tonic-gate
11310Sstevel@tonic-gate static int
labellen(const u_char * lp)11320Sstevel@tonic-gate labellen(const u_char *lp)
11330Sstevel@tonic-gate {
11340Sstevel@tonic-gate int bitlen;
11350Sstevel@tonic-gate u_char l = *lp;
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
11380Sstevel@tonic-gate /* should be avoided by the caller */
1139*11038SRao.Shoaib@Sun.COM return (-1);
11400Sstevel@tonic-gate }
11410Sstevel@tonic-gate
11420Sstevel@tonic-gate if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
11430Sstevel@tonic-gate if (l == DNS_LABELTYPE_BITSTRING) {
11440Sstevel@tonic-gate if ((bitlen = *(lp + 1)) == 0)
11450Sstevel@tonic-gate bitlen = 256;
1146*11038SRao.Shoaib@Sun.COM return ((bitlen + 7 ) / 8 + 1);
11470Sstevel@tonic-gate }
1148*11038SRao.Shoaib@Sun.COM return (-1); /*%< unknwon ELT */
11490Sstevel@tonic-gate }
1150*11038SRao.Shoaib@Sun.COM return (l);
11510Sstevel@tonic-gate }
1152*11038SRao.Shoaib@Sun.COM
1153*11038SRao.Shoaib@Sun.COM /*! \file */
1154