1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/android/ns_name.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,987 @@ 1.4 +/* $NetBSD: ns_name.c,v 1.3 2004/11/07 02:19:49 christos Exp $ */ 1.5 + 1.6 +/* 1.7 + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 1.8 + * Copyright (c) 1996,1999 by Internet Software Consortium. 1.9 + * 1.10 + * Permission to use, copy, modify, and distribute this software for any 1.11 + * purpose with or without fee is hereby granted, provided that the above 1.12 + * copyright notice and this permission notice appear in all copies. 1.13 + * 1.14 + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 1.15 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1.16 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 1.17 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.18 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1.19 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 1.20 + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1.21 + */ 1.22 + 1.23 +/* 1.24 + * This version of this file is derived from Android 2.3 "Gingerbread", 1.25 + * which contains uncredited changes by Android/Google developers. It has 1.26 + * been modified in 2011 for use in the Android build of Mozilla Firefox by 1.27 + * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>, 1.28 + * and Steve Workman <sjhworkman@gmail.com>). 1.29 + * These changes are offered under the same license as the original NetBSD 1.30 + * file, whose copyright and license are unchanged above. 1.31 + */ 1.32 + 1.33 +#define ANDROID_CHANGES 1 1.34 +#define MOZILLA_NECKO_EXCLUDE_CODE 1 1.35 + 1.36 +#include <sys/cdefs.h> 1.37 +#ifndef lint 1.38 +#ifdef notdef 1.39 +static const char rcsid[] = "Id: ns_name.c,v 1.3.2.4.4.2 2004/05/04 03:27:47 marka Exp"; 1.40 +#else 1.41 +__RCSID("$NetBSD: ns_name.c,v 1.3 2004/11/07 02:19:49 christos Exp $"); 1.42 +#endif 1.43 +#endif 1.44 + 1.45 +#include <sys/types.h> 1.46 + 1.47 +#include <netinet/in.h> 1.48 +#include "arpa_nameser.h" 1.49 + 1.50 +#include <errno.h> 1.51 +#ifdef ANDROID_CHANGES 1.52 +#include "resolv_private.h" 1.53 +#else 1.54 +#include <resolv.h> 1.55 +#endif 1.56 +#include <string.h> 1.57 +#include <ctype.h> 1.58 +#include <stdlib.h> 1.59 +#include <limits.h> 1.60 + 1.61 +#ifdef SPRINTF_CHAR 1.62 +# define SPRINTF(x) strlen(sprintf/**/x) 1.63 +#else 1.64 +# define SPRINTF(x) ((size_t)sprintf x) 1.65 +#endif 1.66 + 1.67 +#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */ 1.68 +#define DNS_LABELTYPE_BITSTRING 0x41 1.69 + 1.70 +/* Data. */ 1.71 + 1.72 +static const char digits[] = "0123456789"; 1.73 + 1.74 +static const char digitvalue[256] = { 1.75 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ 1.76 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ 1.77 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ 1.78 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ 1.79 + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ 1.80 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ 1.81 + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ 1.82 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ 1.83 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.84 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.85 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.86 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.87 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.88 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.89 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.90 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ 1.91 +}; 1.92 + 1.93 +/* Forward. */ 1.94 + 1.95 +static int special(int); 1.96 +static int printable(int); 1.97 +static int dn_find(const u_char *, const u_char *, 1.98 + const u_char * const *, 1.99 + const u_char * const *); 1.100 +static int encode_bitsring(const char **, const char *, 1.101 + unsigned char **, unsigned char **, 1.102 + unsigned const char *); 1.103 +static int labellen(const u_char *); 1.104 +static int decode_bitstring(const unsigned char **, 1.105 + char *, const char *); 1.106 + 1.107 +/* Public. */ 1.108 + 1.109 +/* 1.110 + * ns_name_ntop(src, dst, dstsiz) 1.111 + * Convert an encoded domain name to printable ascii as per RFC1035. 1.112 + * return: 1.113 + * Number of bytes written to buffer, or -1 (with errno set) 1.114 + * notes: 1.115 + * The root is returned as "." 1.116 + * All other domains are returned in non absolute form 1.117 + */ 1.118 +int 1.119 +ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) 1.120 +{ 1.121 + const u_char *cp; 1.122 + char *dn, *eom; 1.123 + u_char c; 1.124 + u_int n; 1.125 + int l; 1.126 + 1.127 + cp = src; 1.128 + dn = dst; 1.129 + eom = dst + dstsiz; 1.130 + 1.131 + while ((n = *cp++) != 0) { 1.132 + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 1.133 + /* Some kind of compression pointer. */ 1.134 + errno = EMSGSIZE; 1.135 + return (-1); 1.136 + } 1.137 + if (dn != dst) { 1.138 + if (dn >= eom) { 1.139 + errno = EMSGSIZE; 1.140 + return (-1); 1.141 + } 1.142 + *dn++ = '.'; 1.143 + } 1.144 + if ((l = labellen(cp - 1)) < 0) { 1.145 + errno = EMSGSIZE; /* XXX */ 1.146 + return(-1); 1.147 + } 1.148 + if (dn + l >= eom) { 1.149 + errno = EMSGSIZE; 1.150 + return (-1); 1.151 + } 1.152 + if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { 1.153 + int m; 1.154 + 1.155 + if (n != DNS_LABELTYPE_BITSTRING) { 1.156 + /* XXX: labellen should reject this case */ 1.157 + errno = EINVAL; 1.158 + return(-1); 1.159 + } 1.160 + if ((m = decode_bitstring(&cp, dn, eom)) < 0) 1.161 + { 1.162 + errno = EMSGSIZE; 1.163 + return(-1); 1.164 + } 1.165 + dn += m; 1.166 + continue; 1.167 + } 1.168 + for (; l > 0; l--) { 1.169 + c = *cp++; 1.170 + if (special(c)) { 1.171 + if (dn + 1 >= eom) { 1.172 + errno = EMSGSIZE; 1.173 + return (-1); 1.174 + } 1.175 + *dn++ = '\\'; 1.176 + *dn++ = (char)c; 1.177 + } else if (!printable(c)) { 1.178 + if (dn + 3 >= eom) { 1.179 + errno = EMSGSIZE; 1.180 + return (-1); 1.181 + } 1.182 + *dn++ = '\\'; 1.183 + *dn++ = digits[c / 100]; 1.184 + *dn++ = digits[(c % 100) / 10]; 1.185 + *dn++ = digits[c % 10]; 1.186 + } else { 1.187 + if (dn >= eom) { 1.188 + errno = EMSGSIZE; 1.189 + return (-1); 1.190 + } 1.191 + *dn++ = (char)c; 1.192 + } 1.193 + } 1.194 + } 1.195 + if (dn == dst) { 1.196 + if (dn >= eom) { 1.197 + errno = EMSGSIZE; 1.198 + return (-1); 1.199 + } 1.200 + *dn++ = '.'; 1.201 + } 1.202 + if (dn >= eom) { 1.203 + errno = EMSGSIZE; 1.204 + return (-1); 1.205 + } 1.206 + *dn++ = '\0'; 1.207 + return (dn - dst); 1.208 +} 1.209 + 1.210 +/* 1.211 + * ns_name_pton(src, dst, dstsiz) 1.212 + * Convert a ascii string into an encoded domain name as per RFC1035. 1.213 + * return: 1.214 + * -1 if it fails 1.215 + * 1 if string was fully qualified 1.216 + * 0 is string was not fully qualified 1.217 + * notes: 1.218 + * Enforces label and domain length limits. 1.219 + */ 1.220 + 1.221 +int 1.222 +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) 1.223 +{ 1.224 + u_char *label, *bp, *eom; 1.225 + int c, n, escaped, e = 0; 1.226 + char *cp; 1.227 + 1.228 + escaped = 0; 1.229 + bp = dst; 1.230 + eom = dst + dstsiz; 1.231 + label = bp++; 1.232 + 1.233 + while ((c = *src++) != 0) { 1.234 + if (escaped) { 1.235 + if (c == '[') { /* start a bit string label */ 1.236 + if ((cp = strchr(src, ']')) == NULL) { 1.237 + errno = EINVAL; /* ??? */ 1.238 + return(-1); 1.239 + } 1.240 + if ((e = encode_bitsring(&src, cp + 2, 1.241 + &label, &bp, eom)) 1.242 + != 0) { 1.243 + errno = e; 1.244 + return(-1); 1.245 + } 1.246 + escaped = 0; 1.247 + label = bp++; 1.248 + if ((c = *src++) == 0) 1.249 + goto done; 1.250 + else if (c != '.') { 1.251 + errno = EINVAL; 1.252 + return(-1); 1.253 + } 1.254 + continue; 1.255 + } 1.256 + else if ((cp = strchr(digits, c)) != NULL) { 1.257 + n = (cp - digits) * 100; 1.258 + if ((c = *src++) == 0 || 1.259 + (cp = strchr(digits, c)) == NULL) { 1.260 + errno = EMSGSIZE; 1.261 + return (-1); 1.262 + } 1.263 + n += (cp - digits) * 10; 1.264 + if ((c = *src++) == 0 || 1.265 + (cp = strchr(digits, c)) == NULL) { 1.266 + errno = EMSGSIZE; 1.267 + return (-1); 1.268 + } 1.269 + n += (cp - digits); 1.270 + if (n > 255) { 1.271 + errno = EMSGSIZE; 1.272 + return (-1); 1.273 + } 1.274 + c = n; 1.275 + } 1.276 + escaped = 0; 1.277 + } else if (c == '\\') { 1.278 + escaped = 1; 1.279 + continue; 1.280 + } else if (c == '.') { 1.281 + c = (bp - label - 1); 1.282 + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ 1.283 + errno = EMSGSIZE; 1.284 + return (-1); 1.285 + } 1.286 + if (label >= eom) { 1.287 + errno = EMSGSIZE; 1.288 + return (-1); 1.289 + } 1.290 + *label = c; 1.291 + /* Fully qualified ? */ 1.292 + if (*src == '\0') { 1.293 + if (c != 0) { 1.294 + if (bp >= eom) { 1.295 + errno = EMSGSIZE; 1.296 + return (-1); 1.297 + } 1.298 + *bp++ = '\0'; 1.299 + } 1.300 + if ((bp - dst) > MAXCDNAME) { 1.301 + errno = EMSGSIZE; 1.302 + return (-1); 1.303 + } 1.304 + return (1); 1.305 + } 1.306 + if (c == 0 || *src == '.') { 1.307 + errno = EMSGSIZE; 1.308 + return (-1); 1.309 + } 1.310 + label = bp++; 1.311 + continue; 1.312 + } 1.313 + if (bp >= eom) { 1.314 + errno = EMSGSIZE; 1.315 + return (-1); 1.316 + } 1.317 + *bp++ = (u_char)c; 1.318 + } 1.319 + c = (bp - label - 1); 1.320 + if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ 1.321 + errno = EMSGSIZE; 1.322 + return (-1); 1.323 + } 1.324 + done: 1.325 + if (label >= eom) { 1.326 + errno = EMSGSIZE; 1.327 + return (-1); 1.328 + } 1.329 + *label = c; 1.330 + if (c != 0) { 1.331 + if (bp >= eom) { 1.332 + errno = EMSGSIZE; 1.333 + return (-1); 1.334 + } 1.335 + *bp++ = 0; 1.336 + } 1.337 + if ((bp - dst) > MAXCDNAME) { /* src too big */ 1.338 + errno = EMSGSIZE; 1.339 + return (-1); 1.340 + } 1.341 + return (0); 1.342 +} 1.343 + 1.344 +#ifndef MOZILLA_NECKO_EXCLUDE_CODE 1.345 +/* 1.346 + * ns_name_ntol(src, dst, dstsiz) 1.347 + * Convert a network strings labels into all lowercase. 1.348 + * return: 1.349 + * Number of bytes written to buffer, or -1 (with errno set) 1.350 + * notes: 1.351 + * Enforces label and domain length limits. 1.352 + */ 1.353 + 1.354 +int 1.355 +ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) 1.356 +{ 1.357 + const u_char *cp; 1.358 + u_char *dn, *eom; 1.359 + u_char c; 1.360 + u_int n; 1.361 + int l; 1.362 + 1.363 + cp = src; 1.364 + dn = dst; 1.365 + eom = dst + dstsiz; 1.366 + 1.367 + if (dn >= eom) { 1.368 + errno = EMSGSIZE; 1.369 + return (-1); 1.370 + } 1.371 + while ((n = *cp++) != 0) { 1.372 + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 1.373 + /* Some kind of compression pointer. */ 1.374 + errno = EMSGSIZE; 1.375 + return (-1); 1.376 + } 1.377 + *dn++ = n; 1.378 + if ((l = labellen(cp - 1)) < 0) { 1.379 + errno = EMSGSIZE; 1.380 + return (-1); 1.381 + } 1.382 + if (dn + l >= eom) { 1.383 + errno = EMSGSIZE; 1.384 + return (-1); 1.385 + } 1.386 + for (; l > 0; l--) { 1.387 + c = *cp++; 1.388 + if (isupper(c)) 1.389 + *dn++ = tolower(c); 1.390 + else 1.391 + *dn++ = c; 1.392 + } 1.393 + } 1.394 + *dn++ = '\0'; 1.395 + return (dn - dst); 1.396 +} 1.397 +#endif 1.398 + 1.399 +/* 1.400 + * ns_name_unpack(msg, eom, src, dst, dstsiz) 1.401 + * Unpack a domain name from a message, source may be compressed. 1.402 + * return: 1.403 + * -1 if it fails, or consumed octets if it succeeds. 1.404 + */ 1.405 +int 1.406 +ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, 1.407 + u_char *dst, size_t dstsiz) 1.408 +{ 1.409 + const u_char *srcp, *dstlim; 1.410 + u_char *dstp; 1.411 + int n, len, checked, l; 1.412 + 1.413 + len = -1; 1.414 + checked = 0; 1.415 + dstp = dst; 1.416 + srcp = src; 1.417 + dstlim = dst + dstsiz; 1.418 + if (srcp < msg || srcp >= eom) { 1.419 + errno = EMSGSIZE; 1.420 + return (-1); 1.421 + } 1.422 + /* Fetch next label in domain name. */ 1.423 + while ((n = *srcp++) != 0) { 1.424 + /* Check for indirection. */ 1.425 + switch (n & NS_CMPRSFLGS) { 1.426 + case 0: 1.427 + case NS_TYPE_ELT: 1.428 + /* Limit checks. */ 1.429 + if ((l = labellen(srcp - 1)) < 0) { 1.430 + errno = EMSGSIZE; 1.431 + return(-1); 1.432 + } 1.433 + if (dstp + l + 1 >= dstlim || srcp + l >= eom) { 1.434 + errno = EMSGSIZE; 1.435 + return (-1); 1.436 + } 1.437 + checked += l + 1; 1.438 + *dstp++ = n; 1.439 + memcpy(dstp, srcp, (size_t)l); 1.440 + dstp += l; 1.441 + srcp += l; 1.442 + break; 1.443 + 1.444 + case NS_CMPRSFLGS: 1.445 + if (srcp >= eom) { 1.446 + errno = EMSGSIZE; 1.447 + return (-1); 1.448 + } 1.449 + if (len < 0) 1.450 + len = srcp - src + 1; 1.451 + srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); 1.452 + if (srcp < msg || srcp >= eom) { /* Out of range. */ 1.453 + errno = EMSGSIZE; 1.454 + return (-1); 1.455 + } 1.456 + checked += 2; 1.457 + /* 1.458 + * Check for loops in the compressed name; 1.459 + * if we've looked at the whole message, 1.460 + * there must be a loop. 1.461 + */ 1.462 + if (checked >= eom - msg) { 1.463 + errno = EMSGSIZE; 1.464 + return (-1); 1.465 + } 1.466 + break; 1.467 + 1.468 + default: 1.469 + errno = EMSGSIZE; 1.470 + return (-1); /* flag error */ 1.471 + } 1.472 + } 1.473 + *dstp = '\0'; 1.474 + if (len < 0) 1.475 + len = srcp - src; 1.476 + return (len); 1.477 +} 1.478 + 1.479 +/* 1.480 + * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) 1.481 + * Pack domain name 'domain' into 'comp_dn'. 1.482 + * return: 1.483 + * Size of the compressed name, or -1. 1.484 + * notes: 1.485 + * 'dnptrs' is an array of pointers to previous compressed names. 1.486 + * dnptrs[0] is a pointer to the beginning of the message. The array 1.487 + * ends with NULL. 1.488 + * 'lastdnptr' is a pointer to the end of the array pointed to 1.489 + * by 'dnptrs'. 1.490 + * Side effects: 1.491 + * The list of pointers in dnptrs is updated for labels inserted into 1.492 + * the message as we compress the name. If 'dnptr' is NULL, we don't 1.493 + * try to compress names. If 'lastdnptr' is NULL, we don't update the 1.494 + * list. 1.495 + */ 1.496 +int 1.497 +ns_name_pack(const u_char *src, u_char *dst, int dstsiz, 1.498 + const u_char **dnptrs, const u_char **lastdnptr) 1.499 +{ 1.500 + u_char *dstp; 1.501 + const u_char **cpp, **lpp, *eob, *msg; 1.502 + const u_char *srcp; 1.503 + int n, l, first = 1; 1.504 + 1.505 + srcp = src; 1.506 + dstp = dst; 1.507 + eob = dstp + dstsiz; 1.508 + lpp = cpp = NULL; 1.509 + if (dnptrs != NULL) { 1.510 + if ((msg = *dnptrs++) != NULL) { 1.511 + for (cpp = dnptrs; *cpp != NULL; cpp++) 1.512 + ; 1.513 + lpp = cpp; /* end of list to search */ 1.514 + } 1.515 + } else 1.516 + msg = NULL; 1.517 + 1.518 + /* make sure the domain we are about to add is legal */ 1.519 + l = 0; 1.520 + do { 1.521 + int l0; 1.522 + 1.523 + n = *srcp; 1.524 + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 1.525 + errno = EMSGSIZE; 1.526 + return (-1); 1.527 + } 1.528 + if ((l0 = labellen(srcp)) < 0) { 1.529 + errno = EINVAL; 1.530 + return(-1); 1.531 + } 1.532 + l += l0 + 1; 1.533 + if (l > MAXCDNAME) { 1.534 + errno = EMSGSIZE; 1.535 + return (-1); 1.536 + } 1.537 + srcp += l0 + 1; 1.538 + } while (n != 0); 1.539 + 1.540 + /* from here on we need to reset compression pointer array on error */ 1.541 + srcp = src; 1.542 + do { 1.543 + /* Look to see if we can use pointers. */ 1.544 + n = *srcp; 1.545 + if (n != 0 && msg != NULL) { 1.546 + l = dn_find(srcp, msg, (const u_char * const *)dnptrs, 1.547 + (const u_char * const *)lpp); 1.548 + if (l >= 0) { 1.549 + if (dstp + 1 >= eob) { 1.550 + goto cleanup; 1.551 + } 1.552 + *dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS; 1.553 + *dstp++ = l % 256; 1.554 + return (dstp - dst); 1.555 + } 1.556 + /* Not found, save it. */ 1.557 + if (lastdnptr != NULL && cpp < lastdnptr - 1 && 1.558 + (dstp - msg) < 0x4000 && first) { 1.559 + *cpp++ = dstp; 1.560 + *cpp = NULL; 1.561 + first = 0; 1.562 + } 1.563 + } 1.564 + /* copy label to buffer */ 1.565 + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 1.566 + /* Should not happen. */ 1.567 + goto cleanup; 1.568 + } 1.569 + n = labellen(srcp); 1.570 + if (dstp + 1 + n >= eob) { 1.571 + goto cleanup; 1.572 + } 1.573 + memcpy(dstp, srcp, (size_t)(n + 1)); 1.574 + srcp += n + 1; 1.575 + dstp += n + 1; 1.576 + } while (n != 0); 1.577 + 1.578 + if (dstp > eob) { 1.579 +cleanup: 1.580 + if (msg != NULL) 1.581 + *lpp = NULL; 1.582 + errno = EMSGSIZE; 1.583 + return (-1); 1.584 + } 1.585 + return (dstp - dst); 1.586 +} 1.587 + 1.588 +/* 1.589 + * ns_name_uncompress(msg, eom, src, dst, dstsiz) 1.590 + * Expand compressed domain name to presentation format. 1.591 + * return: 1.592 + * Number of bytes read out of `src', or -1 (with errno set). 1.593 + * note: 1.594 + * Root domain returns as "." not "". 1.595 + */ 1.596 +int 1.597 +ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, 1.598 + char *dst, size_t dstsiz) 1.599 +{ 1.600 + u_char tmp[NS_MAXCDNAME]; 1.601 + int n; 1.602 + 1.603 + if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) 1.604 + return (-1); 1.605 + if (ns_name_ntop(tmp, dst, dstsiz) == -1) 1.606 + return (-1); 1.607 + return (n); 1.608 +} 1.609 + 1.610 +/* 1.611 + * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) 1.612 + * Compress a domain name into wire format, using compression pointers. 1.613 + * return: 1.614 + * Number of bytes consumed in `dst' or -1 (with errno set). 1.615 + * notes: 1.616 + * 'dnptrs' is an array of pointers to previous compressed names. 1.617 + * dnptrs[0] is a pointer to the beginning of the message. 1.618 + * The list ends with NULL. 'lastdnptr' is a pointer to the end of the 1.619 + * array pointed to by 'dnptrs'. Side effect is to update the list of 1.620 + * pointers for labels inserted into the message as we compress the name. 1.621 + * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' 1.622 + * is NULL, we don't update the list. 1.623 + */ 1.624 +int 1.625 +ns_name_compress(const char *src, u_char *dst, size_t dstsiz, 1.626 + const u_char **dnptrs, const u_char **lastdnptr) 1.627 +{ 1.628 + u_char tmp[NS_MAXCDNAME]; 1.629 + 1.630 + if (ns_name_pton(src, tmp, sizeof tmp) == -1) 1.631 + return (-1); 1.632 + return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr)); 1.633 +} 1.634 + 1.635 +#ifndef MOZILLA_NECKO_EXCLUDE_CODE 1.636 +/* 1.637 + * Reset dnptrs so that there are no active references to pointers at or 1.638 + * after src. 1.639 + */ 1.640 +void 1.641 +ns_name_rollback(const u_char *src, const u_char **dnptrs, 1.642 + const u_char **lastdnptr) 1.643 +{ 1.644 + while (dnptrs < lastdnptr && *dnptrs != NULL) { 1.645 + if (*dnptrs >= src) { 1.646 + *dnptrs = NULL; 1.647 + break; 1.648 + } 1.649 + dnptrs++; 1.650 + } 1.651 +} 1.652 +#endif 1.653 + 1.654 +/* 1.655 + * ns_name_skip(ptrptr, eom) 1.656 + * Advance *ptrptr to skip over the compressed name it points at. 1.657 + * return: 1.658 + * 0 on success, -1 (with errno set) on failure. 1.659 + */ 1.660 +int 1.661 +ns_name_skip(const u_char **ptrptr, const u_char *eom) 1.662 +{ 1.663 + const u_char *cp; 1.664 + u_int n; 1.665 + int l; 1.666 + 1.667 + cp = *ptrptr; 1.668 + while (cp < eom && (n = *cp++) != 0) { 1.669 + /* Check for indirection. */ 1.670 + switch (n & NS_CMPRSFLGS) { 1.671 + case 0: /* normal case, n == len */ 1.672 + cp += n; 1.673 + continue; 1.674 + case NS_TYPE_ELT: /* EDNS0 extended label */ 1.675 + if ((l = labellen(cp - 1)) < 0) { 1.676 + errno = EMSGSIZE; /* XXX */ 1.677 + return(-1); 1.678 + } 1.679 + cp += l; 1.680 + continue; 1.681 + case NS_CMPRSFLGS: /* indirection */ 1.682 + cp++; 1.683 + break; 1.684 + default: /* illegal type */ 1.685 + errno = EMSGSIZE; 1.686 + return (-1); 1.687 + } 1.688 + break; 1.689 + } 1.690 + if (cp > eom) { 1.691 + errno = EMSGSIZE; 1.692 + return (-1); 1.693 + } 1.694 + *ptrptr = cp; 1.695 + return (0); 1.696 +} 1.697 + 1.698 +/* Private. */ 1.699 + 1.700 +/* 1.701 + * special(ch) 1.702 + * Thinking in noninternationalized USASCII (per the DNS spec), 1.703 + * is this characted special ("in need of quoting") ? 1.704 + * return: 1.705 + * boolean. 1.706 + */ 1.707 +static int 1.708 +special(int ch) { 1.709 + switch (ch) { 1.710 + case 0x22: /* '"' */ 1.711 + case 0x2E: /* '.' */ 1.712 + case 0x3B: /* ';' */ 1.713 + case 0x5C: /* '\\' */ 1.714 + case 0x28: /* '(' */ 1.715 + case 0x29: /* ')' */ 1.716 + /* Special modifiers in zone files. */ 1.717 + case 0x40: /* '@' */ 1.718 + case 0x24: /* '$' */ 1.719 + return (1); 1.720 + default: 1.721 + return (0); 1.722 + } 1.723 +} 1.724 + 1.725 +/* 1.726 + * printable(ch) 1.727 + * Thinking in noninternationalized USASCII (per the DNS spec), 1.728 + * is this character visible and not a space when printed ? 1.729 + * return: 1.730 + * boolean. 1.731 + */ 1.732 +static int 1.733 +printable(int ch) { 1.734 + return (ch > 0x20 && ch < 0x7f); 1.735 +} 1.736 + 1.737 +/* 1.738 + * Thinking in noninternationalized USASCII (per the DNS spec), 1.739 + * convert this character to lower case if it's upper case. 1.740 + */ 1.741 +static int 1.742 +mklower(int ch) { 1.743 + if (ch >= 0x41 && ch <= 0x5A) 1.744 + return (ch + 0x20); 1.745 + return (ch); 1.746 +} 1.747 + 1.748 +/* 1.749 + * dn_find(domain, msg, dnptrs, lastdnptr) 1.750 + * Search for the counted-label name in an array of compressed names. 1.751 + * return: 1.752 + * offset from msg if found, or -1. 1.753 + * notes: 1.754 + * dnptrs is the pointer to the first name on the list, 1.755 + * not the pointer to the start of the message. 1.756 + */ 1.757 +static int 1.758 +dn_find(const u_char *domain, const u_char *msg, 1.759 + const u_char * const *dnptrs, 1.760 + const u_char * const *lastdnptr) 1.761 +{ 1.762 + const u_char *dn, *cp, *sp; 1.763 + const u_char * const *cpp; 1.764 + u_int n; 1.765 + 1.766 + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { 1.767 + sp = *cpp; 1.768 + /* 1.769 + * terminate search on: 1.770 + * root label 1.771 + * compression pointer 1.772 + * unusable offset 1.773 + */ 1.774 + while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && 1.775 + (sp - msg) < 0x4000) { 1.776 + dn = domain; 1.777 + cp = sp; 1.778 + while ((n = *cp++) != 0) { 1.779 + /* 1.780 + * check for indirection 1.781 + */ 1.782 + switch (n & NS_CMPRSFLGS) { 1.783 + case 0: /* normal case, n == len */ 1.784 + n = labellen(cp - 1); /* XXX */ 1.785 + 1.786 + if (n != *dn++) 1.787 + goto next; 1.788 + 1.789 + for (; n > 0; n--) 1.790 + if (mklower(*dn++) != 1.791 + mklower(*cp++)) 1.792 + goto next; 1.793 + /* Is next root for both ? */ 1.794 + if (*dn == '\0' && *cp == '\0') 1.795 + return (sp - msg); 1.796 + if (*dn) 1.797 + continue; 1.798 + goto next; 1.799 + case NS_CMPRSFLGS: /* indirection */ 1.800 + cp = msg + (((n & 0x3f) << 8) | *cp); 1.801 + break; 1.802 + 1.803 + default: /* illegal type */ 1.804 + errno = EMSGSIZE; 1.805 + return (-1); 1.806 + } 1.807 + } 1.808 + next: ; 1.809 + sp += *sp + 1; 1.810 + } 1.811 + } 1.812 + errno = ENOENT; 1.813 + return (-1); 1.814 +} 1.815 + 1.816 +static int 1.817 +decode_bitstring(const unsigned char **cpp, char *dn, const char *eom) 1.818 +{ 1.819 + const unsigned char *cp = *cpp; 1.820 + char *beg = dn, tc; 1.821 + int b, blen, plen, i; 1.822 + 1.823 + if ((blen = (*cp & 0xff)) == 0) 1.824 + blen = 256; 1.825 + plen = (blen + 3) / 4; 1.826 + plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); 1.827 + if (dn + plen >= eom) 1.828 + return(-1); 1.829 + 1.830 + cp++; 1.831 + i = SPRINTF((dn, "\\[x")); 1.832 + if (i < 0) 1.833 + return (-1); 1.834 + dn += i; 1.835 + for (b = blen; b > 7; b -= 8, cp++) { 1.836 + i = SPRINTF((dn, "%02x", *cp & 0xff)); 1.837 + if (i < 0) 1.838 + return (-1); 1.839 + dn += i; 1.840 + } 1.841 + if (b > 4) { 1.842 + tc = *cp++; 1.843 + i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b)))); 1.844 + if (i < 0) 1.845 + return (-1); 1.846 + dn += i; 1.847 + } else if (b > 0) { 1.848 + tc = *cp++; 1.849 + i = SPRINTF((dn, "%1x", 1.850 + (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b)))); 1.851 + if (i < 0) 1.852 + return (-1); 1.853 + dn += i; 1.854 + } 1.855 + i = SPRINTF((dn, "/%d]", blen)); 1.856 + if (i < 0) 1.857 + return (-1); 1.858 + dn += i; 1.859 + 1.860 + *cpp = cp; 1.861 + return(dn - beg); 1.862 +} 1.863 + 1.864 +static int 1.865 +encode_bitsring(const char **bp, const char *end, unsigned char **labelp, 1.866 + unsigned char ** dst, unsigned const char *eom) 1.867 +{ 1.868 + int afterslash = 0; 1.869 + const char *cp = *bp; 1.870 + unsigned char *tp; 1.871 + char c; 1.872 + const char *beg_blen; 1.873 + char *end_blen = NULL; 1.874 + int value = 0, count = 0, tbcount = 0, blen = 0; 1.875 + 1.876 + beg_blen = end_blen = NULL; 1.877 + 1.878 + /* a bitstring must contain at least 2 characters */ 1.879 + if (end - cp < 2) 1.880 + return(EINVAL); 1.881 + 1.882 + /* XXX: currently, only hex strings are supported */ 1.883 + if (*cp++ != 'x') 1.884 + return(EINVAL); 1.885 + if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */ 1.886 + return(EINVAL); 1.887 + 1.888 + for (tp = *dst + 1; cp < end && tp < eom; cp++) { 1.889 + switch((c = *cp)) { 1.890 + case ']': /* end of the bitstring */ 1.891 + if (afterslash) { 1.892 + if (beg_blen == NULL) 1.893 + return(EINVAL); 1.894 + blen = (int)strtol(beg_blen, &end_blen, 10); 1.895 + if (*end_blen != ']') 1.896 + return(EINVAL); 1.897 + } 1.898 + if (count) 1.899 + *tp++ = ((value << 4) & 0xff); 1.900 + cp++; /* skip ']' */ 1.901 + goto done; 1.902 + case '/': 1.903 + afterslash = 1; 1.904 + break; 1.905 + default: 1.906 + if (afterslash) { 1.907 + if (!isdigit(c&0xff)) 1.908 + return(EINVAL); 1.909 + if (beg_blen == NULL) { 1.910 + 1.911 + if (c == '0') { 1.912 + /* blen never begings with 0 */ 1.913 + return(EINVAL); 1.914 + } 1.915 + beg_blen = cp; 1.916 + } 1.917 + } else { 1.918 + if (!isxdigit(c&0xff)) 1.919 + return(EINVAL); 1.920 + value <<= 4; 1.921 + value += digitvalue[(int)c]; 1.922 + count += 4; 1.923 + tbcount += 4; 1.924 + if (tbcount > 256) 1.925 + return(EINVAL); 1.926 + if (count == 8) { 1.927 + *tp++ = value; 1.928 + count = 0; 1.929 + } 1.930 + } 1.931 + break; 1.932 + } 1.933 + } 1.934 + done: 1.935 + if (cp >= end || tp >= eom) 1.936 + return(EMSGSIZE); 1.937 + 1.938 + /* 1.939 + * bit length validation: 1.940 + * If a <length> is present, the number of digits in the <bit-data> 1.941 + * MUST be just sufficient to contain the number of bits specified 1.942 + * by the <length>. If there are insignificant bits in a final 1.943 + * hexadecimal or octal digit, they MUST be zero. 1.944 + * RFC 2673, Section 3.2. 1.945 + */ 1.946 + if (blen > 0) { 1.947 + int traillen; 1.948 + 1.949 + if (((blen + 3) & ~3) != tbcount) 1.950 + return(EINVAL); 1.951 + traillen = tbcount - blen; /* between 0 and 3 */ 1.952 + if (((value << (8 - traillen)) & 0xff) != 0) 1.953 + return(EINVAL); 1.954 + } 1.955 + else 1.956 + blen = tbcount; 1.957 + if (blen == 256) 1.958 + blen = 0; 1.959 + 1.960 + /* encode the type and the significant bit fields */ 1.961 + **labelp = DNS_LABELTYPE_BITSTRING; 1.962 + **dst = blen; 1.963 + 1.964 + *bp = cp; 1.965 + *dst = tp; 1.966 + 1.967 + return(0); 1.968 +} 1.969 + 1.970 +static int 1.971 +labellen(const u_char *lp) 1.972 +{ 1.973 + int bitlen; 1.974 + u_char l = *lp; 1.975 + 1.976 + if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 1.977 + /* should be avoided by the caller */ 1.978 + return(-1); 1.979 + } 1.980 + 1.981 + if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { 1.982 + if (l == DNS_LABELTYPE_BITSTRING) { 1.983 + if ((bitlen = *(lp + 1)) == 0) 1.984 + bitlen = 256; 1.985 + return((bitlen + 7 ) / 8 + 1); 1.986 + } 1.987 + return(-1); /* unknwon ELT */ 1.988 + } 1.989 + return(l); 1.990 +}