17c478bd9Sstevel@tonic-gate /* 2*9525b14bSRao Shoaib * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 37c478bd9Sstevel@tonic-gate * Copyright (c) 1996,1999 by Internet Software Consortium. 47c478bd9Sstevel@tonic-gate * 57c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 67c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 77c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 87c478bd9Sstevel@tonic-gate * 9*9525b14bSRao Shoaib * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10*9525b14bSRao Shoaib * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*9525b14bSRao Shoaib * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12*9525b14bSRao Shoaib * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*9525b14bSRao Shoaib * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*9525b14bSRao Shoaib * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15*9525b14bSRao Shoaib * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 167c478bd9Sstevel@tonic-gate */ 177c478bd9Sstevel@tonic-gate 187c478bd9Sstevel@tonic-gate #ifndef lint 19*9525b14bSRao Shoaib static const char rcsid[] = "$Id: ns_name.c,v 1.11 2009/01/23 19:59:16 each Exp $"; 207c478bd9Sstevel@tonic-gate #endif 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate #include "port_before.h" 237c478bd9Sstevel@tonic-gate 247c478bd9Sstevel@tonic-gate #include <sys/types.h> 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <netinet/in.h> 277c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <errno.h> 307c478bd9Sstevel@tonic-gate #include <resolv.h> 317c478bd9Sstevel@tonic-gate #include <string.h> 327c478bd9Sstevel@tonic-gate #include <ctype.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <limits.h> 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include "port_after.h" 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #ifdef SPRINTF_CHAR 397c478bd9Sstevel@tonic-gate # define SPRINTF(x) strlen(sprintf/**/x) 407c478bd9Sstevel@tonic-gate #else 417c478bd9Sstevel@tonic-gate # define SPRINTF(x) ((size_t)sprintf x) 427c478bd9Sstevel@tonic-gate #endif 437c478bd9Sstevel@tonic-gate 44*9525b14bSRao Shoaib #define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */ 457c478bd9Sstevel@tonic-gate #define DNS_LABELTYPE_BITSTRING 0x41 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* Data. */ 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate static const char digits[] = "0123456789"; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static const char digitvalue[256] = { 527c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ 537c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ 547c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ 557c478bd9Sstevel@tonic-gate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ 567c478bd9Sstevel@tonic-gate -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ 577c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ 587c478bd9Sstevel@tonic-gate -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ 597c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ 607c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 617c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 627c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 637c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 647c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 657c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 667c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 677c478bd9Sstevel@tonic-gate -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ 687c478bd9Sstevel@tonic-gate }; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* Forward. */ 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate static int special(int); 737c478bd9Sstevel@tonic-gate static int printable(int); 747c478bd9Sstevel@tonic-gate static int dn_find(const u_char *, const u_char *, 757c478bd9Sstevel@tonic-gate const u_char * const *, 767c478bd9Sstevel@tonic-gate const u_char * const *); 777c478bd9Sstevel@tonic-gate static int encode_bitsring(const char **, const char *, 78*9525b14bSRao Shoaib unsigned char **, unsigned char **, 79*9525b14bSRao Shoaib unsigned const char *); 807c478bd9Sstevel@tonic-gate static int labellen(const u_char *); 81*9525b14bSRao Shoaib static int decode_bitstring(const unsigned char **, 82*9525b14bSRao Shoaib char *, const char *); 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* Public. */ 857c478bd9Sstevel@tonic-gate 86*9525b14bSRao Shoaib /*% 877c478bd9Sstevel@tonic-gate * Convert an encoded domain name to printable ascii as per RFC1035. 88*9525b14bSRao Shoaib 897c478bd9Sstevel@tonic-gate * return: 90*9525b14bSRao Shoaib *\li Number of bytes written to buffer, or -1 (with errno set) 91*9525b14bSRao Shoaib * 927c478bd9Sstevel@tonic-gate * notes: 93*9525b14bSRao Shoaib *\li The root is returned as "." 94*9525b14bSRao Shoaib *\li All other domains are returned in non absolute form 957c478bd9Sstevel@tonic-gate */ 967c478bd9Sstevel@tonic-gate int 977c478bd9Sstevel@tonic-gate ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) 987c478bd9Sstevel@tonic-gate { 997c478bd9Sstevel@tonic-gate const u_char *cp; 1007c478bd9Sstevel@tonic-gate char *dn, *eom; 1017c478bd9Sstevel@tonic-gate u_char c; 1027c478bd9Sstevel@tonic-gate u_int n; 1037c478bd9Sstevel@tonic-gate int l; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate cp = src; 1067c478bd9Sstevel@tonic-gate dn = dst; 1077c478bd9Sstevel@tonic-gate eom = dst + dstsiz; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate while ((n = *cp++) != 0) { 1107c478bd9Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 1117c478bd9Sstevel@tonic-gate /* Some kind of compression pointer. */ 1127c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 1137c478bd9Sstevel@tonic-gate return (-1); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate if (dn != dst) { 1167c478bd9Sstevel@tonic-gate if (dn >= eom) { 1177c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 1187c478bd9Sstevel@tonic-gate return (-1); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate *dn++ = '.'; 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate if ((l = labellen(cp - 1)) < 0) { 123*9525b14bSRao Shoaib errno = EMSGSIZE; /*%< XXX */ 1247c478bd9Sstevel@tonic-gate return (-1); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate if (dn + l >= eom) { 1277c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 1287c478bd9Sstevel@tonic-gate return (-1); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { 1317c478bd9Sstevel@tonic-gate int m; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if (n != DNS_LABELTYPE_BITSTRING) { 1347c478bd9Sstevel@tonic-gate /* XXX: labellen should reject this case */ 1357c478bd9Sstevel@tonic-gate errno = EINVAL; 1367c478bd9Sstevel@tonic-gate return (-1); 1377c478bd9Sstevel@tonic-gate } 138*9525b14bSRao Shoaib if ((m = decode_bitstring(&cp, dn, eom)) < 0) 1397c478bd9Sstevel@tonic-gate { 1407c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 1417c478bd9Sstevel@tonic-gate return (-1); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate dn += m; 1447c478bd9Sstevel@tonic-gate continue; 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate for ((void)NULL; l > 0; l--) { 1477c478bd9Sstevel@tonic-gate c = *cp++; 1487c478bd9Sstevel@tonic-gate if (special(c)) { 1497c478bd9Sstevel@tonic-gate if (dn + 1 >= eom) { 1507c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 1517c478bd9Sstevel@tonic-gate return (-1); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate *dn++ = '\\'; 1547c478bd9Sstevel@tonic-gate *dn++ = (char)c; 1557c478bd9Sstevel@tonic-gate } else if (!printable(c)) { 1567c478bd9Sstevel@tonic-gate if (dn + 3 >= eom) { 1577c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 1587c478bd9Sstevel@tonic-gate return (-1); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate *dn++ = '\\'; 1617c478bd9Sstevel@tonic-gate *dn++ = digits[c / 100]; 1627c478bd9Sstevel@tonic-gate *dn++ = digits[(c % 100) / 10]; 1637c478bd9Sstevel@tonic-gate *dn++ = digits[c % 10]; 1647c478bd9Sstevel@tonic-gate } else { 1657c478bd9Sstevel@tonic-gate if (dn >= eom) { 1667c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 1677c478bd9Sstevel@tonic-gate return (-1); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate *dn++ = (char)c; 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate if (dn == dst) { 1747c478bd9Sstevel@tonic-gate if (dn >= eom) { 1757c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 1767c478bd9Sstevel@tonic-gate return (-1); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate *dn++ = '.'; 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate if (dn >= eom) { 1817c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 1827c478bd9Sstevel@tonic-gate return (-1); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate *dn++ = '\0'; 1857c478bd9Sstevel@tonic-gate return (dn - dst); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 188*9525b14bSRao Shoaib /*% 189*9525b14bSRao Shoaib * Convert a ascii string into an encoded domain name as per RFC1035. 190*9525b14bSRao Shoaib * 191*9525b14bSRao Shoaib * return: 192*9525b14bSRao Shoaib * 193*9525b14bSRao Shoaib *\li -1 if it fails 194*9525b14bSRao Shoaib *\li 1 if string was fully qualified 195*9525b14bSRao Shoaib *\li 0 is string was not fully qualified 196*9525b14bSRao Shoaib * 197*9525b14bSRao Shoaib * notes: 198*9525b14bSRao Shoaib *\li Enforces label and domain length limits. 199*9525b14bSRao Shoaib */ 200*9525b14bSRao Shoaib int 201*9525b14bSRao Shoaib ns_name_pton(const char *src, u_char *dst, size_t dstsiz) { 202*9525b14bSRao Shoaib return (ns_name_pton2(src, dst, dstsiz, NULL)); 203*9525b14bSRao Shoaib } 204*9525b14bSRao Shoaib 2057c478bd9Sstevel@tonic-gate /* 206*9525b14bSRao Shoaib * ns_name_pton2(src, dst, dstsiz, *dstlen) 2077c478bd9Sstevel@tonic-gate * Convert a ascii string into an encoded domain name as per RFC1035. 2087c478bd9Sstevel@tonic-gate * return: 2097c478bd9Sstevel@tonic-gate * -1 if it fails 2107c478bd9Sstevel@tonic-gate * 1 if string was fully qualified 2117c478bd9Sstevel@tonic-gate * 0 is string was not fully qualified 212*9525b14bSRao Shoaib * side effects: 213*9525b14bSRao Shoaib * fills in *dstlen (if non-NULL) 2147c478bd9Sstevel@tonic-gate * notes: 2157c478bd9Sstevel@tonic-gate * Enforces label and domain length limits. 2167c478bd9Sstevel@tonic-gate */ 2177c478bd9Sstevel@tonic-gate int 218*9525b14bSRao Shoaib ns_name_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen) { 2197c478bd9Sstevel@tonic-gate u_char *label, *bp, *eom; 2207c478bd9Sstevel@tonic-gate int c, n, escaped, e = 0; 2217c478bd9Sstevel@tonic-gate char *cp; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate escaped = 0; 2247c478bd9Sstevel@tonic-gate bp = dst; 2257c478bd9Sstevel@tonic-gate eom = dst + dstsiz; 2267c478bd9Sstevel@tonic-gate label = bp++; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate while ((c = *src++) != 0) { 2297c478bd9Sstevel@tonic-gate if (escaped) { 230*9525b14bSRao Shoaib if (c == '[') { /*%< start a bit string label */ 2317c478bd9Sstevel@tonic-gate if ((cp = strchr(src, ']')) == NULL) { 232*9525b14bSRao Shoaib errno = EINVAL; /*%< ??? */ 2337c478bd9Sstevel@tonic-gate return (-1); 2347c478bd9Sstevel@tonic-gate } 235*9525b14bSRao Shoaib if ((e = encode_bitsring(&src, cp + 2, 236*9525b14bSRao Shoaib &label, &bp, eom)) 2377c478bd9Sstevel@tonic-gate != 0) { 2387c478bd9Sstevel@tonic-gate errno = e; 2397c478bd9Sstevel@tonic-gate return (-1); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate escaped = 0; 2427c478bd9Sstevel@tonic-gate label = bp++; 2437c478bd9Sstevel@tonic-gate if ((c = *src++) == 0) 2447c478bd9Sstevel@tonic-gate goto done; 2457c478bd9Sstevel@tonic-gate else if (c != '.') { 2467c478bd9Sstevel@tonic-gate errno = EINVAL; 2477c478bd9Sstevel@tonic-gate return (-1); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate continue; 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate else if ((cp = strchr(digits, c)) != NULL) { 2527c478bd9Sstevel@tonic-gate n = (cp - digits) * 100; 2537c478bd9Sstevel@tonic-gate if ((c = *src++) == 0 || 2547c478bd9Sstevel@tonic-gate (cp = strchr(digits, c)) == NULL) { 2557c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 2567c478bd9Sstevel@tonic-gate return (-1); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate n += (cp - digits) * 10; 2597c478bd9Sstevel@tonic-gate if ((c = *src++) == 0 || 2607c478bd9Sstevel@tonic-gate (cp = strchr(digits, c)) == NULL) { 2617c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 2627c478bd9Sstevel@tonic-gate return (-1); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate n += (cp - digits); 2657c478bd9Sstevel@tonic-gate if (n > 255) { 2667c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 2677c478bd9Sstevel@tonic-gate return (-1); 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate c = n; 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate escaped = 0; 2727c478bd9Sstevel@tonic-gate } else if (c == '\\') { 2737c478bd9Sstevel@tonic-gate escaped = 1; 2747c478bd9Sstevel@tonic-gate continue; 2757c478bd9Sstevel@tonic-gate } else if (c == '.') { 2767c478bd9Sstevel@tonic-gate c = (bp - label - 1); 277*9525b14bSRao Shoaib if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ 2787c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 2797c478bd9Sstevel@tonic-gate return (-1); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate if (label >= eom) { 2827c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 2837c478bd9Sstevel@tonic-gate return (-1); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate *label = c; 2867c478bd9Sstevel@tonic-gate /* Fully qualified ? */ 2877c478bd9Sstevel@tonic-gate if (*src == '\0') { 2887c478bd9Sstevel@tonic-gate if (c != 0) { 2897c478bd9Sstevel@tonic-gate if (bp >= eom) { 2907c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 2917c478bd9Sstevel@tonic-gate return (-1); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate *bp++ = '\0'; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate if ((bp - dst) > MAXCDNAME) { 2967c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 2977c478bd9Sstevel@tonic-gate return (-1); 2987c478bd9Sstevel@tonic-gate } 299*9525b14bSRao Shoaib if (dstlen != NULL) 300*9525b14bSRao Shoaib *dstlen = (bp - dst); 3017c478bd9Sstevel@tonic-gate return (1); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate if (c == 0 || *src == '.') { 3047c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3057c478bd9Sstevel@tonic-gate return (-1); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate label = bp++; 3087c478bd9Sstevel@tonic-gate continue; 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate if (bp >= eom) { 3117c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3127c478bd9Sstevel@tonic-gate return (-1); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate *bp++ = (u_char)c; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate c = (bp - label - 1); 317*9525b14bSRao Shoaib if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ 3187c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3197c478bd9Sstevel@tonic-gate return (-1); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate done: 3227c478bd9Sstevel@tonic-gate if (label >= eom) { 3237c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3247c478bd9Sstevel@tonic-gate return (-1); 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate *label = c; 3277c478bd9Sstevel@tonic-gate if (c != 0) { 3287c478bd9Sstevel@tonic-gate if (bp >= eom) { 3297c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3307c478bd9Sstevel@tonic-gate return (-1); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate *bp++ = 0; 3337c478bd9Sstevel@tonic-gate } 334*9525b14bSRao Shoaib if ((bp - dst) > MAXCDNAME) { /*%< src too big */ 3357c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3367c478bd9Sstevel@tonic-gate return (-1); 3377c478bd9Sstevel@tonic-gate } 338*9525b14bSRao Shoaib if (dstlen != NULL) 339*9525b14bSRao Shoaib *dstlen = (bp - dst); 3407c478bd9Sstevel@tonic-gate return (0); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 343*9525b14bSRao Shoaib /*% 3447c478bd9Sstevel@tonic-gate * Convert a network strings labels into all lowercase. 345*9525b14bSRao Shoaib * 3467c478bd9Sstevel@tonic-gate * return: 347*9525b14bSRao Shoaib *\li Number of bytes written to buffer, or -1 (with errno set) 348*9525b14bSRao Shoaib * 3497c478bd9Sstevel@tonic-gate * notes: 350*9525b14bSRao Shoaib *\li Enforces label and domain length limits. 3517c478bd9Sstevel@tonic-gate */ 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate int 3547c478bd9Sstevel@tonic-gate ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate const u_char *cp; 3577c478bd9Sstevel@tonic-gate u_char *dn, *eom; 3587c478bd9Sstevel@tonic-gate u_char c; 3597c478bd9Sstevel@tonic-gate u_int n; 3607c478bd9Sstevel@tonic-gate int l; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate cp = src; 3637c478bd9Sstevel@tonic-gate dn = dst; 3647c478bd9Sstevel@tonic-gate eom = dst + dstsiz; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if (dn >= eom) { 3677c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3687c478bd9Sstevel@tonic-gate return (-1); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate while ((n = *cp++) != 0) { 3717c478bd9Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 3727c478bd9Sstevel@tonic-gate /* Some kind of compression pointer. */ 3737c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3747c478bd9Sstevel@tonic-gate return (-1); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate *dn++ = n; 3777c478bd9Sstevel@tonic-gate if ((l = labellen(cp - 1)) < 0) { 3787c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3797c478bd9Sstevel@tonic-gate return (-1); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate if (dn + l >= eom) { 3827c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 3837c478bd9Sstevel@tonic-gate return (-1); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate for ((void)NULL; l > 0; l--) { 3867c478bd9Sstevel@tonic-gate c = *cp++; 387*9525b14bSRao Shoaib if (isascii(c) && isupper(c)) 3887c478bd9Sstevel@tonic-gate *dn++ = tolower(c); 3897c478bd9Sstevel@tonic-gate else 3907c478bd9Sstevel@tonic-gate *dn++ = c; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate *dn++ = '\0'; 3947c478bd9Sstevel@tonic-gate return (dn - dst); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 397*9525b14bSRao Shoaib /*% 3987c478bd9Sstevel@tonic-gate * Unpack a domain name from a message, source may be compressed. 399*9525b14bSRao Shoaib * 4007c478bd9Sstevel@tonic-gate * return: 401*9525b14bSRao Shoaib *\li -1 if it fails, or consumed octets if it succeeds. 4027c478bd9Sstevel@tonic-gate */ 4037c478bd9Sstevel@tonic-gate int 4047c478bd9Sstevel@tonic-gate ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, 4057c478bd9Sstevel@tonic-gate u_char *dst, size_t dstsiz) 4067c478bd9Sstevel@tonic-gate { 407*9525b14bSRao Shoaib return (ns_name_unpack2(msg, eom, src, dst, dstsiz, NULL)); 408*9525b14bSRao Shoaib } 409*9525b14bSRao Shoaib 410*9525b14bSRao Shoaib /* 411*9525b14bSRao Shoaib * ns_name_unpack2(msg, eom, src, dst, dstsiz, *dstlen) 412*9525b14bSRao Shoaib * Unpack a domain name from a message, source may be compressed. 413*9525b14bSRao Shoaib * return: 414*9525b14bSRao Shoaib * -1 if it fails, or consumed octets if it succeeds. 415*9525b14bSRao Shoaib * side effect: 416*9525b14bSRao Shoaib * fills in *dstlen (if non-NULL). 417*9525b14bSRao Shoaib */ 418*9525b14bSRao Shoaib int 419*9525b14bSRao Shoaib ns_name_unpack2(const u_char *msg, const u_char *eom, const u_char *src, 420*9525b14bSRao Shoaib u_char *dst, size_t dstsiz, size_t *dstlen) 421*9525b14bSRao Shoaib { 4227c478bd9Sstevel@tonic-gate const u_char *srcp, *dstlim; 4237c478bd9Sstevel@tonic-gate u_char *dstp; 4247c478bd9Sstevel@tonic-gate int n, len, checked, l; 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate len = -1; 4277c478bd9Sstevel@tonic-gate checked = 0; 4287c478bd9Sstevel@tonic-gate dstp = dst; 4297c478bd9Sstevel@tonic-gate srcp = src; 4307c478bd9Sstevel@tonic-gate dstlim = dst + dstsiz; 4317c478bd9Sstevel@tonic-gate if (srcp < msg || srcp >= eom) { 4327c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4337c478bd9Sstevel@tonic-gate return (-1); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate /* Fetch next label in domain name. */ 4367c478bd9Sstevel@tonic-gate while ((n = *srcp++) != 0) { 4377c478bd9Sstevel@tonic-gate /* Check for indirection. */ 4387c478bd9Sstevel@tonic-gate switch (n & NS_CMPRSFLGS) { 4397c478bd9Sstevel@tonic-gate case 0: 4407c478bd9Sstevel@tonic-gate case NS_TYPE_ELT: 4417c478bd9Sstevel@tonic-gate /* Limit checks. */ 4427c478bd9Sstevel@tonic-gate if ((l = labellen(srcp - 1)) < 0) { 4437c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4447c478bd9Sstevel@tonic-gate return (-1); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate if (dstp + l + 1 >= dstlim || srcp + l >= eom) { 4477c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4487c478bd9Sstevel@tonic-gate return (-1); 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate checked += l + 1; 4517c478bd9Sstevel@tonic-gate *dstp++ = n; 4527c478bd9Sstevel@tonic-gate memcpy(dstp, srcp, l); 4537c478bd9Sstevel@tonic-gate dstp += l; 4547c478bd9Sstevel@tonic-gate srcp += l; 4557c478bd9Sstevel@tonic-gate break; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate case NS_CMPRSFLGS: 4587c478bd9Sstevel@tonic-gate if (srcp >= eom) { 4597c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4607c478bd9Sstevel@tonic-gate return (-1); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate if (len < 0) 4637c478bd9Sstevel@tonic-gate len = srcp - src + 1; 4647c478bd9Sstevel@tonic-gate srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); 465*9525b14bSRao Shoaib if (srcp < msg || srcp >= eom) { /*%< Out of range. */ 4667c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4677c478bd9Sstevel@tonic-gate return (-1); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate checked += 2; 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * Check for loops in the compressed name; 4727c478bd9Sstevel@tonic-gate * if we've looked at the whole message, 4737c478bd9Sstevel@tonic-gate * there must be a loop. 4747c478bd9Sstevel@tonic-gate */ 4757c478bd9Sstevel@tonic-gate if (checked >= eom - msg) { 4767c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 4777c478bd9Sstevel@tonic-gate return (-1); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate break; 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate default: 4827c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 483*9525b14bSRao Shoaib return (-1); /*%< flag error */ 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate } 486*9525b14bSRao Shoaib *dstp++ = 0; 487*9525b14bSRao Shoaib if (dstlen != NULL) 488*9525b14bSRao Shoaib *dstlen = dstp - dst; 4897c478bd9Sstevel@tonic-gate if (len < 0) 4907c478bd9Sstevel@tonic-gate len = srcp - src; 4917c478bd9Sstevel@tonic-gate return (len); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 494*9525b14bSRao Shoaib /*% 4957c478bd9Sstevel@tonic-gate * Pack domain name 'domain' into 'comp_dn'. 496*9525b14bSRao Shoaib * 4977c478bd9Sstevel@tonic-gate * return: 498*9525b14bSRao Shoaib *\li Size of the compressed name, or -1. 499*9525b14bSRao Shoaib * 5007c478bd9Sstevel@tonic-gate * notes: 501*9525b14bSRao Shoaib *\li 'dnptrs' is an array of pointers to previous compressed names. 502*9525b14bSRao Shoaib *\li dnptrs[0] is a pointer to the beginning of the message. The array 5037c478bd9Sstevel@tonic-gate * ends with NULL. 504*9525b14bSRao Shoaib *\li 'lastdnptr' is a pointer to the end of the array pointed to 5057c478bd9Sstevel@tonic-gate * by 'dnptrs'. 506*9525b14bSRao Shoaib * 5077c478bd9Sstevel@tonic-gate * Side effects: 508*9525b14bSRao Shoaib *\li The list of pointers in dnptrs is updated for labels inserted into 5097c478bd9Sstevel@tonic-gate * the message as we compress the name. If 'dnptr' is NULL, we don't 5107c478bd9Sstevel@tonic-gate * try to compress names. If 'lastdnptr' is NULL, we don't update the 5117c478bd9Sstevel@tonic-gate * list. 5127c478bd9Sstevel@tonic-gate */ 5137c478bd9Sstevel@tonic-gate int 5147c478bd9Sstevel@tonic-gate ns_name_pack(const u_char *src, u_char *dst, int dstsiz, 5157c478bd9Sstevel@tonic-gate const u_char **dnptrs, const u_char **lastdnptr) 5167c478bd9Sstevel@tonic-gate { 5177c478bd9Sstevel@tonic-gate u_char *dstp; 5187c478bd9Sstevel@tonic-gate const u_char **cpp, **lpp, *eob, *msg; 5197c478bd9Sstevel@tonic-gate const u_char *srcp; 5207c478bd9Sstevel@tonic-gate int n, l, first = 1; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate srcp = src; 5237c478bd9Sstevel@tonic-gate dstp = dst; 5247c478bd9Sstevel@tonic-gate eob = dstp + dstsiz; 5257c478bd9Sstevel@tonic-gate lpp = cpp = NULL; 5267c478bd9Sstevel@tonic-gate if (dnptrs != NULL) { 5277c478bd9Sstevel@tonic-gate if ((msg = *dnptrs++) != NULL) { 5287c478bd9Sstevel@tonic-gate for (cpp = dnptrs; *cpp != NULL; cpp++) 5297c478bd9Sstevel@tonic-gate (void)NULL; 530*9525b14bSRao Shoaib lpp = cpp; /*%< end of list to search */ 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate } else 5337c478bd9Sstevel@tonic-gate msg = NULL; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate /* make sure the domain we are about to add is legal */ 5367c478bd9Sstevel@tonic-gate l = 0; 5377c478bd9Sstevel@tonic-gate do { 5387c478bd9Sstevel@tonic-gate int l0; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate n = *srcp; 5417c478bd9Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 5427c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 5437c478bd9Sstevel@tonic-gate return (-1); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate if ((l0 = labellen(srcp)) < 0) { 5467c478bd9Sstevel@tonic-gate errno = EINVAL; 5477c478bd9Sstevel@tonic-gate return (-1); 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate l += l0 + 1; 5507c478bd9Sstevel@tonic-gate if (l > MAXCDNAME) { 5517c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 5527c478bd9Sstevel@tonic-gate return (-1); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate srcp += l0 + 1; 5557c478bd9Sstevel@tonic-gate } while (n != 0); 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate /* from here on we need to reset compression pointer array on error */ 5587c478bd9Sstevel@tonic-gate srcp = src; 5597c478bd9Sstevel@tonic-gate do { 5607c478bd9Sstevel@tonic-gate /* Look to see if we can use pointers. */ 5617c478bd9Sstevel@tonic-gate n = *srcp; 5627c478bd9Sstevel@tonic-gate if (n != 0 && msg != NULL) { 5637c478bd9Sstevel@tonic-gate l = dn_find(srcp, msg, (const u_char * const *)dnptrs, 5647c478bd9Sstevel@tonic-gate (const u_char * const *)lpp); 5657c478bd9Sstevel@tonic-gate if (l >= 0) { 5667c478bd9Sstevel@tonic-gate if (dstp + 1 >= eob) { 5677c478bd9Sstevel@tonic-gate goto cleanup; 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate *dstp++ = (l >> 8) | NS_CMPRSFLGS; 5707c478bd9Sstevel@tonic-gate *dstp++ = l % 256; 5717c478bd9Sstevel@tonic-gate return (dstp - dst); 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate /* Not found, save it. */ 5747c478bd9Sstevel@tonic-gate if (lastdnptr != NULL && cpp < lastdnptr - 1 && 5757c478bd9Sstevel@tonic-gate (dstp - msg) < 0x4000 && first) { 5767c478bd9Sstevel@tonic-gate *cpp++ = dstp; 5777c478bd9Sstevel@tonic-gate *cpp = NULL; 5787c478bd9Sstevel@tonic-gate first = 0; 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate /* copy label to buffer */ 5827c478bd9Sstevel@tonic-gate if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 5837c478bd9Sstevel@tonic-gate /* Should not happen. */ 5847c478bd9Sstevel@tonic-gate goto cleanup; 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate n = labellen(srcp); 5877c478bd9Sstevel@tonic-gate if (dstp + 1 + n >= eob) { 5887c478bd9Sstevel@tonic-gate goto cleanup; 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate memcpy(dstp, srcp, n + 1); 5917c478bd9Sstevel@tonic-gate srcp += n + 1; 5927c478bd9Sstevel@tonic-gate dstp += n + 1; 5937c478bd9Sstevel@tonic-gate } while (n != 0); 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate if (dstp > eob) { 5967c478bd9Sstevel@tonic-gate cleanup: 5977c478bd9Sstevel@tonic-gate if (msg != NULL) 5987c478bd9Sstevel@tonic-gate *lpp = NULL; 5997c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 6007c478bd9Sstevel@tonic-gate return (-1); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate return (dstp - dst); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 605*9525b14bSRao Shoaib /*% 6067c478bd9Sstevel@tonic-gate * Expand compressed domain name to presentation format. 607*9525b14bSRao Shoaib * 6087c478bd9Sstevel@tonic-gate * return: 609*9525b14bSRao Shoaib *\li Number of bytes read out of `src', or -1 (with errno set). 610*9525b14bSRao Shoaib * 6117c478bd9Sstevel@tonic-gate * note: 612*9525b14bSRao Shoaib *\li Root domain returns as "." not "". 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate int 6157c478bd9Sstevel@tonic-gate ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, 6167c478bd9Sstevel@tonic-gate char *dst, size_t dstsiz) 6177c478bd9Sstevel@tonic-gate { 6187c478bd9Sstevel@tonic-gate u_char tmp[NS_MAXCDNAME]; 6197c478bd9Sstevel@tonic-gate int n; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) 6227c478bd9Sstevel@tonic-gate return (-1); 6237c478bd9Sstevel@tonic-gate if (ns_name_ntop(tmp, dst, dstsiz) == -1) 6247c478bd9Sstevel@tonic-gate return (-1); 6257c478bd9Sstevel@tonic-gate return (n); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 628*9525b14bSRao Shoaib /*% 6297c478bd9Sstevel@tonic-gate * Compress a domain name into wire format, using compression pointers. 630*9525b14bSRao Shoaib * 6317c478bd9Sstevel@tonic-gate * return: 632*9525b14bSRao Shoaib *\li Number of bytes consumed in `dst' or -1 (with errno set). 633*9525b14bSRao Shoaib * 6347c478bd9Sstevel@tonic-gate * notes: 635*9525b14bSRao Shoaib *\li 'dnptrs' is an array of pointers to previous compressed names. 636*9525b14bSRao Shoaib *\li dnptrs[0] is a pointer to the beginning of the message. 637*9525b14bSRao Shoaib *\li The list ends with NULL. 'lastdnptr' is a pointer to the end of the 6387c478bd9Sstevel@tonic-gate * array pointed to by 'dnptrs'. Side effect is to update the list of 6397c478bd9Sstevel@tonic-gate * pointers for labels inserted into the message as we compress the name. 640*9525b14bSRao Shoaib *\li If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' 6417c478bd9Sstevel@tonic-gate * is NULL, we don't update the list. 6427c478bd9Sstevel@tonic-gate */ 6437c478bd9Sstevel@tonic-gate int 6447c478bd9Sstevel@tonic-gate ns_name_compress(const char *src, u_char *dst, size_t dstsiz, 6457c478bd9Sstevel@tonic-gate const u_char **dnptrs, const u_char **lastdnptr) 6467c478bd9Sstevel@tonic-gate { 6477c478bd9Sstevel@tonic-gate u_char tmp[NS_MAXCDNAME]; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate if (ns_name_pton(src, tmp, sizeof tmp) == -1) 6507c478bd9Sstevel@tonic-gate return (-1); 6517c478bd9Sstevel@tonic-gate return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 654*9525b14bSRao Shoaib /*% 6557c478bd9Sstevel@tonic-gate * Reset dnptrs so that there are no active references to pointers at or 6567c478bd9Sstevel@tonic-gate * after src. 6577c478bd9Sstevel@tonic-gate */ 6587c478bd9Sstevel@tonic-gate void 6597c478bd9Sstevel@tonic-gate ns_name_rollback(const u_char *src, const u_char **dnptrs, 6607c478bd9Sstevel@tonic-gate const u_char **lastdnptr) 6617c478bd9Sstevel@tonic-gate { 6627c478bd9Sstevel@tonic-gate while (dnptrs < lastdnptr && *dnptrs != NULL) { 6637c478bd9Sstevel@tonic-gate if (*dnptrs >= src) { 6647c478bd9Sstevel@tonic-gate *dnptrs = NULL; 6657c478bd9Sstevel@tonic-gate break; 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate dnptrs++; 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 671*9525b14bSRao Shoaib /*% 6727c478bd9Sstevel@tonic-gate * Advance *ptrptr to skip over the compressed name it points at. 673*9525b14bSRao Shoaib * 6747c478bd9Sstevel@tonic-gate * return: 675*9525b14bSRao Shoaib *\li 0 on success, -1 (with errno set) on failure. 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate int 6787c478bd9Sstevel@tonic-gate ns_name_skip(const u_char **ptrptr, const u_char *eom) 6797c478bd9Sstevel@tonic-gate { 6807c478bd9Sstevel@tonic-gate const u_char *cp; 6817c478bd9Sstevel@tonic-gate u_int n; 6827c478bd9Sstevel@tonic-gate int l; 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate cp = *ptrptr; 6857c478bd9Sstevel@tonic-gate while (cp < eom && (n = *cp++) != 0) { 6867c478bd9Sstevel@tonic-gate /* Check for indirection. */ 6877c478bd9Sstevel@tonic-gate switch (n & NS_CMPRSFLGS) { 688*9525b14bSRao Shoaib case 0: /*%< normal case, n == len */ 6897c478bd9Sstevel@tonic-gate cp += n; 6907c478bd9Sstevel@tonic-gate continue; 691*9525b14bSRao Shoaib case NS_TYPE_ELT: /*%< EDNS0 extended label */ 6927c478bd9Sstevel@tonic-gate if ((l = labellen(cp - 1)) < 0) { 693*9525b14bSRao Shoaib errno = EMSGSIZE; /*%< XXX */ 6947c478bd9Sstevel@tonic-gate return (-1); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate cp += l; 6977c478bd9Sstevel@tonic-gate continue; 698*9525b14bSRao Shoaib case NS_CMPRSFLGS: /*%< indirection */ 6997c478bd9Sstevel@tonic-gate cp++; 7007c478bd9Sstevel@tonic-gate break; 701*9525b14bSRao Shoaib default: /*%< illegal type */ 7027c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 7037c478bd9Sstevel@tonic-gate return (-1); 7047c478bd9Sstevel@tonic-gate } 7057c478bd9Sstevel@tonic-gate break; 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate if (cp > eom) { 7087c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 7097c478bd9Sstevel@tonic-gate return (-1); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate *ptrptr = cp; 7127c478bd9Sstevel@tonic-gate return (0); 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 715*9525b14bSRao Shoaib /* Find the number of octets an nname takes up, including the root label. 716*9525b14bSRao Shoaib * (This is basically ns_name_skip() without compression-pointer support.) 717*9525b14bSRao Shoaib * ((NOTE: can only return zero if passed-in namesiz argument is zero.)) 718*9525b14bSRao Shoaib */ 719*9525b14bSRao Shoaib ssize_t 720*9525b14bSRao Shoaib ns_name_length(ns_nname_ct nname, size_t namesiz) { 721*9525b14bSRao Shoaib ns_nname_ct orig = nname; 722*9525b14bSRao Shoaib u_int n; 723*9525b14bSRao Shoaib 724*9525b14bSRao Shoaib while (namesiz-- > 0 && (n = *nname++) != 0) { 725*9525b14bSRao Shoaib if ((n & NS_CMPRSFLGS) != 0) { 726*9525b14bSRao Shoaib errno = EISDIR; 727*9525b14bSRao Shoaib return (-1); 728*9525b14bSRao Shoaib } 729*9525b14bSRao Shoaib if (n > namesiz) { 730*9525b14bSRao Shoaib errno = EMSGSIZE; 731*9525b14bSRao Shoaib return (-1); 732*9525b14bSRao Shoaib } 733*9525b14bSRao Shoaib nname += n; 734*9525b14bSRao Shoaib namesiz -= n; 735*9525b14bSRao Shoaib } 736*9525b14bSRao Shoaib return (nname - orig); 737*9525b14bSRao Shoaib } 738*9525b14bSRao Shoaib 739*9525b14bSRao Shoaib /* Compare two nname's for equality. Return -1 on error (setting errno). 740*9525b14bSRao Shoaib */ 741*9525b14bSRao Shoaib int 742*9525b14bSRao Shoaib ns_name_eq(ns_nname_ct a, size_t as, ns_nname_ct b, size_t bs) { 743*9525b14bSRao Shoaib ns_nname_ct ae = a + as, be = b + bs; 744*9525b14bSRao Shoaib int ac, bc; 745*9525b14bSRao Shoaib 746*9525b14bSRao Shoaib while (ac = *a, bc = *b, ac != 0 && bc != 0) { 747*9525b14bSRao Shoaib if ((ac & NS_CMPRSFLGS) != 0 || (bc & NS_CMPRSFLGS) != 0) { 748*9525b14bSRao Shoaib errno = EISDIR; 749*9525b14bSRao Shoaib return (-1); 750*9525b14bSRao Shoaib } 751*9525b14bSRao Shoaib if (a + ac >= ae || b + bc >= be) { 752*9525b14bSRao Shoaib errno = EMSGSIZE; 753*9525b14bSRao Shoaib return (-1); 754*9525b14bSRao Shoaib } 755*9525b14bSRao Shoaib if (ac != bc || strncasecmp((const char *) ++a, 756*9525b14bSRao Shoaib (const char *) ++b, ac) != 0) 757*9525b14bSRao Shoaib return (0); 758*9525b14bSRao Shoaib a += ac, b += bc; 759*9525b14bSRao Shoaib } 760*9525b14bSRao Shoaib return (ac == 0 && bc == 0); 761*9525b14bSRao Shoaib } 762*9525b14bSRao Shoaib 763*9525b14bSRao Shoaib /* Is domain "A" owned by (at or below) domain "B"? 764*9525b14bSRao Shoaib */ 765*9525b14bSRao Shoaib int 766*9525b14bSRao Shoaib ns_name_owned(ns_namemap_ct a, int an, ns_namemap_ct b, int bn) { 767*9525b14bSRao Shoaib /* If A is shorter, it cannot be owned by B. */ 768*9525b14bSRao Shoaib if (an < bn) 769*9525b14bSRao Shoaib return (0); 770*9525b14bSRao Shoaib 771*9525b14bSRao Shoaib /* If they are unequal before the length of the shorter, A cannot... */ 772*9525b14bSRao Shoaib while (bn > 0) { 773*9525b14bSRao Shoaib if (a->len != b->len || 774*9525b14bSRao Shoaib strncasecmp((const char *) a->base, 775*9525b14bSRao Shoaib (const char *) b->base, a->len) != 0) 776*9525b14bSRao Shoaib return (0); 777*9525b14bSRao Shoaib a++, an--; 778*9525b14bSRao Shoaib b++, bn--; 779*9525b14bSRao Shoaib } 780*9525b14bSRao Shoaib 781*9525b14bSRao Shoaib /* A might be longer or not, but either way, B owns it. */ 782*9525b14bSRao Shoaib return (1); 783*9525b14bSRao Shoaib } 784*9525b14bSRao Shoaib 785*9525b14bSRao Shoaib /* Build an array of <base,len> tuples from an nname, top-down order. 786*9525b14bSRao Shoaib * Return the number of tuples (labels) thus discovered. 787*9525b14bSRao Shoaib */ 788*9525b14bSRao Shoaib int 789*9525b14bSRao Shoaib ns_name_map(ns_nname_ct nname, size_t namelen, ns_namemap_t map, int mapsize) { 790*9525b14bSRao Shoaib u_int n; 791*9525b14bSRao Shoaib int l; 792*9525b14bSRao Shoaib 793*9525b14bSRao Shoaib n = *nname++; 794*9525b14bSRao Shoaib namelen--; 795*9525b14bSRao Shoaib 796*9525b14bSRao Shoaib /* Root zone? */ 797*9525b14bSRao Shoaib if (n == 0) { 798*9525b14bSRao Shoaib /* Extra data follows name? */ 799*9525b14bSRao Shoaib if (namelen > 0) { 800*9525b14bSRao Shoaib errno = EMSGSIZE; 801*9525b14bSRao Shoaib return (-1); 802*9525b14bSRao Shoaib } 803*9525b14bSRao Shoaib return (0); 804*9525b14bSRao Shoaib } 805*9525b14bSRao Shoaib 806*9525b14bSRao Shoaib /* Compression pointer? */ 807*9525b14bSRao Shoaib if ((n & NS_CMPRSFLGS) != 0) { 808*9525b14bSRao Shoaib errno = EISDIR; 809*9525b14bSRao Shoaib return (-1); 810*9525b14bSRao Shoaib } 811*9525b14bSRao Shoaib 812*9525b14bSRao Shoaib /* Label too long? */ 813*9525b14bSRao Shoaib if (n > namelen) { 814*9525b14bSRao Shoaib errno = EMSGSIZE; 815*9525b14bSRao Shoaib return (-1); 816*9525b14bSRao Shoaib } 817*9525b14bSRao Shoaib 818*9525b14bSRao Shoaib /* Recurse to get rest of name done first. */ 819*9525b14bSRao Shoaib l = ns_name_map(nname + n, namelen - n, map, mapsize); 820*9525b14bSRao Shoaib if (l < 0) 821*9525b14bSRao Shoaib return (-1); 822*9525b14bSRao Shoaib 823*9525b14bSRao Shoaib /* Too many labels? */ 824*9525b14bSRao Shoaib if (l >= mapsize) { 825*9525b14bSRao Shoaib errno = ENAMETOOLONG; 826*9525b14bSRao Shoaib return (-1); 827*9525b14bSRao Shoaib } 828*9525b14bSRao Shoaib 829*9525b14bSRao Shoaib /* We're on our way back up-stack, store current map data. */ 830*9525b14bSRao Shoaib map[l].base = nname; 831*9525b14bSRao Shoaib map[l].len = n; 832*9525b14bSRao Shoaib return (l + 1); 833*9525b14bSRao Shoaib } 834*9525b14bSRao Shoaib 835*9525b14bSRao Shoaib /* Count the labels in a domain name. Root counts, so COM. has two. This 836*9525b14bSRao Shoaib * is to make the result comparable to the result of ns_name_map(). 837*9525b14bSRao Shoaib */ 838*9525b14bSRao Shoaib int 839*9525b14bSRao Shoaib ns_name_labels(ns_nname_ct nname, size_t namesiz) { 840*9525b14bSRao Shoaib int ret = 0; 841*9525b14bSRao Shoaib u_int n; 842*9525b14bSRao Shoaib 843*9525b14bSRao Shoaib while (namesiz-- > 0 && (n = *nname++) != 0) { 844*9525b14bSRao Shoaib if ((n & NS_CMPRSFLGS) != 0) { 845*9525b14bSRao Shoaib errno = EISDIR; 846*9525b14bSRao Shoaib return (-1); 847*9525b14bSRao Shoaib } 848*9525b14bSRao Shoaib if (n > namesiz) { 849*9525b14bSRao Shoaib errno = EMSGSIZE; 850*9525b14bSRao Shoaib return (-1); 851*9525b14bSRao Shoaib } 852*9525b14bSRao Shoaib nname += n; 853*9525b14bSRao Shoaib namesiz -= n; 854*9525b14bSRao Shoaib ret++; 855*9525b14bSRao Shoaib } 856*9525b14bSRao Shoaib return (ret + 1); 857*9525b14bSRao Shoaib } 858*9525b14bSRao Shoaib 8597c478bd9Sstevel@tonic-gate /* Private. */ 8607c478bd9Sstevel@tonic-gate 861*9525b14bSRao Shoaib /*% 8627c478bd9Sstevel@tonic-gate * Thinking in noninternationalized USASCII (per the DNS spec), 8637c478bd9Sstevel@tonic-gate * is this characted special ("in need of quoting") ? 864*9525b14bSRao Shoaib * 8657c478bd9Sstevel@tonic-gate * return: 866*9525b14bSRao Shoaib *\li boolean. 8677c478bd9Sstevel@tonic-gate */ 8687c478bd9Sstevel@tonic-gate static int 8697c478bd9Sstevel@tonic-gate special(int ch) { 8707c478bd9Sstevel@tonic-gate switch (ch) { 871*9525b14bSRao Shoaib case 0x22: /*%< '"' */ 872*9525b14bSRao Shoaib case 0x2E: /*%< '.' */ 873*9525b14bSRao Shoaib case 0x3B: /*%< ';' */ 874*9525b14bSRao Shoaib case 0x5C: /*%< '\\' */ 875*9525b14bSRao Shoaib case 0x28: /*%< '(' */ 876*9525b14bSRao Shoaib case 0x29: /*%< ')' */ 8777c478bd9Sstevel@tonic-gate /* Special modifiers in zone files. */ 878*9525b14bSRao Shoaib case 0x40: /*%< '@' */ 879*9525b14bSRao Shoaib case 0x24: /*%< '$' */ 8807c478bd9Sstevel@tonic-gate return (1); 8817c478bd9Sstevel@tonic-gate default: 8827c478bd9Sstevel@tonic-gate return (0); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate } 8857c478bd9Sstevel@tonic-gate 886*9525b14bSRao Shoaib /*% 8877c478bd9Sstevel@tonic-gate * Thinking in noninternationalized USASCII (per the DNS spec), 8887c478bd9Sstevel@tonic-gate * is this character visible and not a space when printed ? 889*9525b14bSRao Shoaib * 8907c478bd9Sstevel@tonic-gate * return: 891*9525b14bSRao Shoaib *\li boolean. 8927c478bd9Sstevel@tonic-gate */ 8937c478bd9Sstevel@tonic-gate static int 8947c478bd9Sstevel@tonic-gate printable(int ch) { 8957c478bd9Sstevel@tonic-gate return (ch > 0x20 && ch < 0x7f); 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate 898*9525b14bSRao Shoaib /*% 8997c478bd9Sstevel@tonic-gate * Thinking in noninternationalized USASCII (per the DNS spec), 9007c478bd9Sstevel@tonic-gate * convert this character to lower case if it's upper case. 9017c478bd9Sstevel@tonic-gate */ 9027c478bd9Sstevel@tonic-gate static int 9037c478bd9Sstevel@tonic-gate mklower(int ch) { 9047c478bd9Sstevel@tonic-gate if (ch >= 0x41 && ch <= 0x5A) 9057c478bd9Sstevel@tonic-gate return (ch + 0x20); 9067c478bd9Sstevel@tonic-gate return (ch); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate 909*9525b14bSRao Shoaib /*% 9107c478bd9Sstevel@tonic-gate * Search for the counted-label name in an array of compressed names. 911*9525b14bSRao Shoaib * 9127c478bd9Sstevel@tonic-gate * return: 913*9525b14bSRao Shoaib *\li offset from msg if found, or -1. 914*9525b14bSRao Shoaib * 9157c478bd9Sstevel@tonic-gate * notes: 916*9525b14bSRao Shoaib *\li dnptrs is the pointer to the first name on the list, 917*9525b14bSRao Shoaib *\li not the pointer to the start of the message. 9187c478bd9Sstevel@tonic-gate */ 9197c478bd9Sstevel@tonic-gate static int 9207c478bd9Sstevel@tonic-gate dn_find(const u_char *domain, const u_char *msg, 9217c478bd9Sstevel@tonic-gate const u_char * const *dnptrs, 9227c478bd9Sstevel@tonic-gate const u_char * const *lastdnptr) 9237c478bd9Sstevel@tonic-gate { 9247c478bd9Sstevel@tonic-gate const u_char *dn, *cp, *sp; 9257c478bd9Sstevel@tonic-gate const u_char * const *cpp; 9267c478bd9Sstevel@tonic-gate u_int n; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate for (cpp = dnptrs; cpp < lastdnptr; cpp++) { 9297c478bd9Sstevel@tonic-gate sp = *cpp; 9307c478bd9Sstevel@tonic-gate /* 9317c478bd9Sstevel@tonic-gate * terminate search on: 9327c478bd9Sstevel@tonic-gate * root label 9337c478bd9Sstevel@tonic-gate * compression pointer 9347c478bd9Sstevel@tonic-gate * unusable offset 9357c478bd9Sstevel@tonic-gate */ 9367c478bd9Sstevel@tonic-gate while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && 9377c478bd9Sstevel@tonic-gate (sp - msg) < 0x4000) { 9387c478bd9Sstevel@tonic-gate dn = domain; 9397c478bd9Sstevel@tonic-gate cp = sp; 9407c478bd9Sstevel@tonic-gate while ((n = *cp++) != 0) { 9417c478bd9Sstevel@tonic-gate /* 9427c478bd9Sstevel@tonic-gate * check for indirection 9437c478bd9Sstevel@tonic-gate */ 9447c478bd9Sstevel@tonic-gate switch (n & NS_CMPRSFLGS) { 945*9525b14bSRao Shoaib case 0: /*%< normal case, n == len */ 946*9525b14bSRao Shoaib n = labellen(cp - 1); /*%< XXX */ 9477c478bd9Sstevel@tonic-gate if (n != *dn++) 9487c478bd9Sstevel@tonic-gate goto next; 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate for ((void)NULL; n > 0; n--) 9517c478bd9Sstevel@tonic-gate if (mklower(*dn++) != 9527c478bd9Sstevel@tonic-gate mklower(*cp++)) 9537c478bd9Sstevel@tonic-gate goto next; 9547c478bd9Sstevel@tonic-gate /* Is next root for both ? */ 9557c478bd9Sstevel@tonic-gate if (*dn == '\0' && *cp == '\0') 9567c478bd9Sstevel@tonic-gate return (sp - msg); 9577c478bd9Sstevel@tonic-gate if (*dn) 9587c478bd9Sstevel@tonic-gate continue; 9597c478bd9Sstevel@tonic-gate goto next; 960*9525b14bSRao Shoaib case NS_CMPRSFLGS: /*%< indirection */ 9617c478bd9Sstevel@tonic-gate cp = msg + (((n & 0x3f) << 8) | *cp); 9627c478bd9Sstevel@tonic-gate break; 9637c478bd9Sstevel@tonic-gate 964*9525b14bSRao Shoaib default: /*%< illegal type */ 9657c478bd9Sstevel@tonic-gate errno = EMSGSIZE; 9667c478bd9Sstevel@tonic-gate return (-1); 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate next: ; 9707c478bd9Sstevel@tonic-gate sp += *sp + 1; 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate errno = ENOENT; 9747c478bd9Sstevel@tonic-gate return (-1); 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate static int 978*9525b14bSRao Shoaib decode_bitstring(const unsigned char **cpp, char *dn, const char *eom) 9797c478bd9Sstevel@tonic-gate { 980*9525b14bSRao Shoaib const unsigned char *cp = *cpp; 9817c478bd9Sstevel@tonic-gate char *beg = dn, tc; 9827c478bd9Sstevel@tonic-gate int b, blen, plen, i; 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate if ((blen = (*cp & 0xff)) == 0) 9857c478bd9Sstevel@tonic-gate blen = 256; 9867c478bd9Sstevel@tonic-gate plen = (blen + 3) / 4; 9877c478bd9Sstevel@tonic-gate plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); 9887c478bd9Sstevel@tonic-gate if (dn + plen >= eom) 9897c478bd9Sstevel@tonic-gate return (-1); 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate cp++; 9927c478bd9Sstevel@tonic-gate i = SPRINTF((dn, "\\[x")); 9937c478bd9Sstevel@tonic-gate if (i < 0) 9947c478bd9Sstevel@tonic-gate return (-1); 9957c478bd9Sstevel@tonic-gate dn += i; 9967c478bd9Sstevel@tonic-gate for (b = blen; b > 7; b -= 8, cp++) { 9977c478bd9Sstevel@tonic-gate i = SPRINTF((dn, "%02x", *cp & 0xff)); 9987c478bd9Sstevel@tonic-gate if (i < 0) 9997c478bd9Sstevel@tonic-gate return (-1); 10007c478bd9Sstevel@tonic-gate dn += i; 10017c478bd9Sstevel@tonic-gate } 10027c478bd9Sstevel@tonic-gate if (b > 4) { 10037c478bd9Sstevel@tonic-gate tc = *cp++; 10047c478bd9Sstevel@tonic-gate i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b)))); 10057c478bd9Sstevel@tonic-gate if (i < 0) 10067c478bd9Sstevel@tonic-gate return (-1); 10077c478bd9Sstevel@tonic-gate dn += i; 10087c478bd9Sstevel@tonic-gate } else if (b > 0) { 10097c478bd9Sstevel@tonic-gate tc = *cp++; 10107c478bd9Sstevel@tonic-gate i = SPRINTF((dn, "%1x", 10117c478bd9Sstevel@tonic-gate ((tc >> 4) & 0x0f) & (0x0f << (4 - b)))); 10127c478bd9Sstevel@tonic-gate if (i < 0) 10137c478bd9Sstevel@tonic-gate return (-1); 10147c478bd9Sstevel@tonic-gate dn += i; 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate i = SPRINTF((dn, "/%d]", blen)); 10177c478bd9Sstevel@tonic-gate if (i < 0) 10187c478bd9Sstevel@tonic-gate return (-1); 10197c478bd9Sstevel@tonic-gate dn += i; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate *cpp = cp; 10227c478bd9Sstevel@tonic-gate return (dn - beg); 10237c478bd9Sstevel@tonic-gate } 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate static int 1026*9525b14bSRao Shoaib encode_bitsring(const char **bp, const char *end, unsigned char **labelp, 1027*9525b14bSRao Shoaib unsigned char ** dst, unsigned const char *eom) 10287c478bd9Sstevel@tonic-gate { 10297c478bd9Sstevel@tonic-gate int afterslash = 0; 10307c478bd9Sstevel@tonic-gate const char *cp = *bp; 1031*9525b14bSRao Shoaib unsigned char *tp; 1032*9525b14bSRao Shoaib char c; 10337c478bd9Sstevel@tonic-gate const char *beg_blen; 10347c478bd9Sstevel@tonic-gate char *end_blen = NULL; 10357c478bd9Sstevel@tonic-gate int value = 0, count = 0, tbcount = 0, blen = 0; 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate beg_blen = end_blen = NULL; 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate /* a bitstring must contain at least 2 characters */ 10407c478bd9Sstevel@tonic-gate if (end - cp < 2) 10417c478bd9Sstevel@tonic-gate return (EINVAL); 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate /* XXX: currently, only hex strings are supported */ 10447c478bd9Sstevel@tonic-gate if (*cp++ != 'x') 10457c478bd9Sstevel@tonic-gate return (EINVAL); 1046*9525b14bSRao Shoaib if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */ 10477c478bd9Sstevel@tonic-gate return (EINVAL); 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate for (tp = *dst + 1; cp < end && tp < eom; cp++) { 10507c478bd9Sstevel@tonic-gate switch((c = *cp)) { 1051*9525b14bSRao Shoaib case ']': /*%< end of the bitstring */ 10527c478bd9Sstevel@tonic-gate if (afterslash) { 10537c478bd9Sstevel@tonic-gate if (beg_blen == NULL) 10547c478bd9Sstevel@tonic-gate return (EINVAL); 10557c478bd9Sstevel@tonic-gate blen = (int)strtol(beg_blen, &end_blen, 10); 10567c478bd9Sstevel@tonic-gate if (*end_blen != ']') 10577c478bd9Sstevel@tonic-gate return (EINVAL); 10587c478bd9Sstevel@tonic-gate } 10597c478bd9Sstevel@tonic-gate if (count) 10607c478bd9Sstevel@tonic-gate *tp++ = ((value << 4) & 0xff); 1061*9525b14bSRao Shoaib cp++; /*%< skip ']' */ 10627c478bd9Sstevel@tonic-gate goto done; 10637c478bd9Sstevel@tonic-gate case '/': 10647c478bd9Sstevel@tonic-gate afterslash = 1; 10657c478bd9Sstevel@tonic-gate break; 10667c478bd9Sstevel@tonic-gate default: 10677c478bd9Sstevel@tonic-gate if (afterslash) { 10687c478bd9Sstevel@tonic-gate if (!isdigit(c&0xff)) 10697c478bd9Sstevel@tonic-gate return (EINVAL); 10707c478bd9Sstevel@tonic-gate if (beg_blen == NULL) { 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate if (c == '0') { 10737c478bd9Sstevel@tonic-gate /* blen never begings with 0 */ 10747c478bd9Sstevel@tonic-gate return (EINVAL); 10757c478bd9Sstevel@tonic-gate } 10767c478bd9Sstevel@tonic-gate beg_blen = cp; 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate } else { 10797c478bd9Sstevel@tonic-gate if (!isxdigit(c&0xff)) 10807c478bd9Sstevel@tonic-gate return (EINVAL); 10817c478bd9Sstevel@tonic-gate value <<= 4; 10827c478bd9Sstevel@tonic-gate value += digitvalue[(int)c]; 10837c478bd9Sstevel@tonic-gate count += 4; 10847c478bd9Sstevel@tonic-gate tbcount += 4; 10857c478bd9Sstevel@tonic-gate if (tbcount > 256) 10867c478bd9Sstevel@tonic-gate return (EINVAL); 10877c478bd9Sstevel@tonic-gate if (count == 8) { 10887c478bd9Sstevel@tonic-gate *tp++ = value; 10897c478bd9Sstevel@tonic-gate count = 0; 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate break; 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate done: 10967c478bd9Sstevel@tonic-gate if (cp >= end || tp >= eom) 10977c478bd9Sstevel@tonic-gate return (EMSGSIZE); 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate /* 11007c478bd9Sstevel@tonic-gate * bit length validation: 11017c478bd9Sstevel@tonic-gate * If a <length> is present, the number of digits in the <bit-data> 11027c478bd9Sstevel@tonic-gate * MUST be just sufficient to contain the number of bits specified 11037c478bd9Sstevel@tonic-gate * by the <length>. If there are insignificant bits in a final 11047c478bd9Sstevel@tonic-gate * hexadecimal or octal digit, they MUST be zero. 11057c478bd9Sstevel@tonic-gate * RFC2673, Section 3.2. 11067c478bd9Sstevel@tonic-gate */ 11077c478bd9Sstevel@tonic-gate if (blen > 0) { 11087c478bd9Sstevel@tonic-gate int traillen; 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate if (((blen + 3) & ~3) != tbcount) 11117c478bd9Sstevel@tonic-gate return (EINVAL); 1112*9525b14bSRao Shoaib traillen = tbcount - blen; /*%< between 0 and 3 */ 11137c478bd9Sstevel@tonic-gate if (((value << (8 - traillen)) & 0xff) != 0) 11147c478bd9Sstevel@tonic-gate return (EINVAL); 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate else 11177c478bd9Sstevel@tonic-gate blen = tbcount; 11187c478bd9Sstevel@tonic-gate if (blen == 256) 11197c478bd9Sstevel@tonic-gate blen = 0; 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate /* encode the type and the significant bit fields */ 11227c478bd9Sstevel@tonic-gate **labelp = DNS_LABELTYPE_BITSTRING; 11237c478bd9Sstevel@tonic-gate **dst = blen; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate *bp = cp; 11267c478bd9Sstevel@tonic-gate *dst = tp; 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate return (0); 11297c478bd9Sstevel@tonic-gate } 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate static int 11327c478bd9Sstevel@tonic-gate labellen(const u_char *lp) 11337c478bd9Sstevel@tonic-gate { 11347c478bd9Sstevel@tonic-gate int bitlen; 11357c478bd9Sstevel@tonic-gate u_char l = *lp; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 11387c478bd9Sstevel@tonic-gate /* should be avoided by the caller */ 11397c478bd9Sstevel@tonic-gate return (-1); 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { 11437c478bd9Sstevel@tonic-gate if (l == DNS_LABELTYPE_BITSTRING) { 11447c478bd9Sstevel@tonic-gate if ((bitlen = *(lp + 1)) == 0) 11457c478bd9Sstevel@tonic-gate bitlen = 256; 11467c478bd9Sstevel@tonic-gate return ((bitlen + 7 ) / 8 + 1); 11477c478bd9Sstevel@tonic-gate } 1148*9525b14bSRao Shoaib return (-1); /*%< unknwon ELT */ 11497c478bd9Sstevel@tonic-gate } 11507c478bd9Sstevel@tonic-gate return (l); 11517c478bd9Sstevel@tonic-gate } 1152*9525b14bSRao Shoaib 1153*9525b14bSRao Shoaib /*! \file */ 1154