11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* $NetBSD: ns_name.c,v 1.3 2004/11/07 02:19:49 christos Exp $ */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1996,1999 by Internet Software Consortium. 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this software for any 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * purpose with or without fee is hereby granted, provided that the above 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copyright notice and this permission notice appear in all copies. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h> 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef lint 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef notdef 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char rcsid[] = "Id: ns_name.c,v 1.3.2.4.4.2 2004/05/04 03:27:47 marka Exp"; 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__RCSID("$NetBSD: ns_name.c,v 1.3 2004/11/07 02:19:49 christos Exp $"); 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h> 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h> 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "arpa_nameser.h" 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ANDROID_CHANGES 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h" 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <resolv.h> 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h> 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <ctype.h> 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h> 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <limits.h> 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef SPRINTF_CHAR 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define SPRINTF(x) strlen(sprintf/**/x) 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define SPRINTF(x) ((size_t)sprintf x) 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */ 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DNS_LABELTYPE_BITSTRING 0x41 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Data. */ 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char digits[] = "0123456789"; 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char digitvalue[256] = { 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Forward. */ 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int special(int); 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int printable(int); 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int dn_find(const u_char *, const u_char *, 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *, 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *); 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int encode_bitsring(const char **, const char *, 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned char **, unsigned char **, 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned const char *); 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int labellen(const u_char *); 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int decode_bitstring(const unsigned char **, 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *, const char *); 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Public. */ 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_ntop(src, dst, dstsiz) 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Convert an encoded domain name to printable ascii as per RFC1035. 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Number of bytes written to buffer, or -1 (with errno set) 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The root is returned as "." 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All other domains are returned in non absolute form 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_ntop(const u_char *src, char *dst, size_t dstsiz) 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *cp; 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *dn, *eom; 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char c; 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int n; 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int l; 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = src; 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn = dst; 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eom = dst + dstsiz; 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((n = *cp++) != 0) { 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Some kind of compression pointer. */ 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn != dst) { 1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '.'; 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l = labellen(cp - 1)) < 0) { 1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; /* XXX */ 1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + l >= eom) { 1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int m; 1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n != DNS_LABELTYPE_BITSTRING) { 1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX: labellen should reject this case */ 1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((m = decode_bitstring(&cp, dn, eom)) < 0) 1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += m; 1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (; l > 0; l--) { 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project c = *cp++; 1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (special(c)) { 1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + 1 >= eom) { 1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '\\'; 1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = (char)c; 1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (!printable(c)) { 1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + 3 >= eom) { 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '\\'; 1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = digits[c / 100]; 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = digits[(c % 100) / 10]; 1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = digits[c % 10]; 1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = (char)c; 1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn == dst) { 1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '.'; 1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '\0'; 1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (dn - dst); 1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_pton(src, dst, dstsiz) 1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Convert a ascii string into an encoded domain name as per RFC1035. 1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * -1 if it fails 1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1 if string was fully qualified 2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 0 is string was not fully qualified 2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Enforces label and domain length limits. 2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_pton(const char *src, u_char *dst, size_t dstsiz) 2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *label, *bp, *eom; 2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int c, n, escaped, e = 0; 2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *cp; 2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project escaped = 0; 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp = dst; 2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eom = dst + dstsiz; 2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project label = bp++; 2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((c = *src++) != 0) { 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (escaped) { 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c == '[') { /* start a bit string label */ 2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((cp = strchr(src, ']')) == NULL) { 2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; /* ??? */ 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((e = encode_bitsring(&src, cp + 2, 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project &label, &bp, eom)) 2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project != 0) { 2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = e; 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project escaped = 0; 2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project label = bp++; 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c = *src++) == 0) 2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto done; 2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if (c != '.') { 2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if ((cp = strchr(digits, c)) != NULL) { 2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = (cp - digits) * 100; 2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c = *src++) == 0 || 2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (cp = strchr(digits, c)) == NULL) { 2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n += (cp - digits) * 10; 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c = *src++) == 0 || 2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (cp = strchr(digits, c)) == NULL) { 2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n += (cp - digits); 2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n > 255) { 2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project c = n; 2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project escaped = 0; 2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (c == '\\') { 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project escaped = 1; 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (c == '.') { 2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project c = (bp - label - 1); 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ 2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (label >= eom) { 2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *label = c; 2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Fully qualified ? */ 2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*src == '\0') { 2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c != 0) { 2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bp >= eom) { 2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *bp++ = '\0'; 2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((bp - dst) > MAXCDNAME) { 2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (1); 2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c == 0 || *src == '.') { 2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project label = bp++; 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bp >= eom) { 2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *bp++ = (u_char)c; 3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project c = (bp - label - 1); 3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ 3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project done: 3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (label >= eom) { 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *label = c; 3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c != 0) { 3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bp >= eom) { 3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *bp++ = 0; 3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((bp - dst) > MAXCDNAME) { /* src too big */ 3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_ntol(src, dst, dstsiz) 3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Convert a network strings labels into all lowercase. 3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Number of bytes written to buffer, or -1 (with errno set) 3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Enforces label and domain length limits. 3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) 3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *cp; 3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *dn, *eom; 3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char c; 3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int n; 3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int l; 3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = src; 3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn = dst; 3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eom = dst + dstsiz; 3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((n = *cp++) != 0) { 3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Some kind of compression pointer. */ 3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = n; 3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l = labellen(cp - 1)) < 0) { 3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + l >= eom) { 3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (; l > 0; l--) { 3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project c = *cp++; 3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (isupper(c)) 3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = tolower(c); 3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = c; 3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '\0'; 3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (dn - dst); 3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 3821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_unpack(msg, eom, src, dst, dstsiz) 3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Unpack a domain name from a message, source may be compressed. 3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * -1 if it fails, or consumed octets if it succeeds. 3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 3881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, 3891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *dst, size_t dstsiz) 3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *srcp, *dstlim; 3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *dstp; 3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n, len, checked, l; 3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project len = -1; 3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project checked = 0; 3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstp = dst; 3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp = src; 3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstlim = dst + dstsiz; 4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (srcp < msg || srcp >= eom) { 4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Fetch next label in domain name. */ 4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((n = *srcp++) != 0) { 4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Check for indirection. */ 4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (n & NS_CMPRSFLGS) { 4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0: 4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_TYPE_ELT: 4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Limit checks. */ 4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l = labellen(srcp - 1)) < 0) { 4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 4141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dstp + l + 1 >= dstlim || srcp + l >= eom) { 4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project checked += l + 1; 4201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dstp++ = n; 4211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(dstp, srcp, (size_t)l); 4221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstp += l; 4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp += l; 4241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_CMPRSFLGS: 4271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (srcp >= eom) { 4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (len < 0) 4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project len = srcp - src + 1; 4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); 4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (srcp < msg || srcp >= eom) { /* Out of range. */ 4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project checked += 2; 4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Check for loops in the compressed name; 4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we've looked at the whole message, 4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * there must be a loop. 4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (checked >= eom - msg) { 4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); /* flag error */ 4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dstp = '\0'; 4561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (len < 0) 4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project len = srcp - src; 4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (len); 4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) 4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Pack domain name 'domain' into 'comp_dn'. 4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Size of the compressed name, or -1. 4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 'dnptrs' is an array of pointers to previous compressed names. 4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * dnptrs[0] is a pointer to the beginning of the message. The array 4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ends with NULL. 4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 'lastdnptr' is a pointer to the end of the array pointed to 4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * by 'dnptrs'. 4721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Side effects: 4731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The list of pointers in dnptrs is updated for labels inserted into 4741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the message as we compress the name. If 'dnptr' is NULL, we don't 4751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * try to compress names. If 'lastdnptr' is NULL, we don't update the 4761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * list. 4771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 4781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_pack(const u_char *src, u_char *dst, int dstsiz, 4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char **dnptrs, const u_char **lastdnptr) 4811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 4821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *dstp; 4831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char **cpp, **lpp, *eob, *msg; 4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *srcp; 4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n, l, first = 1; 4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp = src; 4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstp = dst; 4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eob = dstp + dstsiz; 4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lpp = cpp = NULL; 4911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dnptrs != NULL) { 4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((msg = *dnptrs++) != NULL) { 4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cpp = dnptrs; *cpp != NULL; cpp++) 4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ; 4951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lpp = cpp; /* end of list to search */ 4961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 4981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project msg = NULL; 4991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* make sure the domain we are about to add is legal */ 5011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project l = 0; 5021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { 5031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int l0; 5041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = *srcp; 5061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 5071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 5081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 5091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l0 = labellen(srcp)) < 0) { 5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 5121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 5131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project l += l0 + 1; 5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (l > MAXCDNAME) { 5161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp += l0 + 1; 5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } while (n != 0); 5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* from here on we need to reset compression pointer array on error */ 5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp = src; 5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { 5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Look to see if we can use pointers. */ 5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = *srcp; 5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n != 0 && msg != NULL) { 5281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project l = dn_find(srcp, msg, (const u_char * const *)dnptrs, 5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (const u_char * const *)lpp); 5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (l >= 0) { 5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dstp + 1 >= eob) { 5321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto cleanup; 5331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS; 5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dstp++ = l % 256; 5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (dstp - dst); 5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Not found, save it. */ 5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (lastdnptr != NULL && cpp < lastdnptr - 1 && 5401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (dstp - msg) < 0x4000 && first) { 5411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cpp++ = dstp; 5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cpp = NULL; 5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project first = 0; 5441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* copy label to buffer */ 5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 5481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Should not happen. */ 5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto cleanup; 5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = labellen(srcp); 5521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dstp + 1 + n >= eob) { 5531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto cleanup; 5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(dstp, srcp, (size_t)(n + 1)); 5561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp += n + 1; 5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstp += n + 1; 5581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } while (n != 0); 5591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dstp > eob) { 5611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectcleanup: 5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (msg != NULL) 5631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *lpp = NULL; 5641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 5651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 5661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (dstp - dst); 5681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 5691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 5711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_uncompress(msg, eom, src, dst, dstsiz) 5721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Expand compressed domain name to presentation format. 5731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 5741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Number of bytes read out of `src', or -1 (with errno set). 5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * note: 5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Root domain returns as "." not "". 5771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 5791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, 5801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *dst, size_t dstsiz) 5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 5821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char tmp[NS_MAXCDNAME]; 5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n; 5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) 5861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ns_name_ntop(tmp, dst, dstsiz) == -1) 5881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 5891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (n); 5901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) 5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Compress a domain name into wire format, using compression pointers. 5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Number of bytes consumed in `dst' or -1 (with errno set). 5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 'dnptrs' is an array of pointers to previous compressed names. 5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * dnptrs[0] is a pointer to the beginning of the message. 6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The list ends with NULL. 'lastdnptr' is a pointer to the end of the 6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * array pointed to by 'dnptrs'. Side effect is to update the list of 6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * pointers for labels inserted into the message as we compress the name. 6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' 6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is NULL, we don't update the list. 6051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_compress(const char *src, u_char *dst, size_t dstsiz, 6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char **dnptrs, const u_char **lastdnptr) 6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char tmp[NS_MAXCDNAME]; 6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ns_name_pton(src, tmp, sizeof tmp) == -1) 6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr)); 6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Reset dnptrs so that there are no active references to pointers at or 6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * after src. 6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_rollback(const u_char *src, const u_char **dnptrs, 6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char **lastdnptr) 6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (dnptrs < lastdnptr && *dnptrs != NULL) { 6261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*dnptrs >= src) { 6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dnptrs = NULL; 6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dnptrs++; 6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ns_name_skip(ptrptr, eom) 6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Advance *ptrptr to skip over the compressed name it points at. 6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 0 on success, -1 (with errno set) on failure. 6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_skip(const u_char **ptrptr, const u_char *eom) 6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *cp; 6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int n; 6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int l; 6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = *ptrptr; 6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cp < eom && (n = *cp++) != 0) { 6491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Check for indirection. */ 6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (n & NS_CMPRSFLGS) { 6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0: /* normal case, n == len */ 6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_TYPE_ELT: /* EDNS0 extended label */ 6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l = labellen(cp - 1)) < 0) { 6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; /* XXX */ 6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += l; 6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_CMPRSFLGS: /* indirection */ 6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp++; 6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: /* illegal type */ 6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cp > eom) { 6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *ptrptr = cp; 6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Private. */ 6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * special(ch) 6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Thinking in noninternationalized USASCII (per the DNS spec), 6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is this characted special ("in need of quoting") ? 6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * boolean. 6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectspecial(int ch) { 6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ch) { 6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x22: /* '"' */ 6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x2E: /* '.' */ 6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x3B: /* ';' */ 6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x5C: /* '\\' */ 6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x28: /* '(' */ 6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x29: /* ')' */ 6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Special modifiers in zone files. */ 6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x40: /* '@' */ 6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x24: /* '$' */ 6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (1); 7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * printable(ch) 7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Thinking in noninternationalized USASCII (per the DNS spec), 7081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is this character visible and not a space when printed ? 7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * boolean. 7111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectprintable(int ch) { 7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ch > 0x20 && ch < 0x7f); 7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Thinking in noninternationalized USASCII (per the DNS spec), 7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * convert this character to lower case if it's upper case. 7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectmklower(int ch) { 7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ch >= 0x41 && ch <= 0x5A) 7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ch + 0x20); 7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ch); 7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * dn_find(domain, msg, dnptrs, lastdnptr) 7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Search for the counted-label name in an array of compressed names. 7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * offset from msg if found, or -1. 7331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 7341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * dnptrs is the pointer to the first name on the list, 7351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * not the pointer to the start of the message. 7361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 7381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdn_find(const u_char *domain, const u_char *msg, 7391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *dnptrs, 7401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *lastdnptr) 7411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 7421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *dn, *cp, *sp; 7431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *cpp; 7441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int n; 7451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cpp = dnptrs; cpp < lastdnptr; cpp++) { 7471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sp = *cpp; 7481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * terminate search on: 7501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * root label 7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * compression pointer 7521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * unusable offset 7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && 7551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (sp - msg) < 0x4000) { 7561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn = domain; 7571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = sp; 7581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((n = *cp++) != 0) { 7591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 7601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * check for indirection 7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (n & NS_CMPRSFLGS) { 7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0: /* normal case, n == len */ 7641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = labellen(cp - 1); /* XXX */ 7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n != *dn++) 7671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto next; 7681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (; n > 0; n--) 7701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (mklower(*dn++) != 7711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project mklower(*cp++)) 7721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto next; 7731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Is next root for both ? */ 7741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*dn == '\0' && *cp == '\0') 7751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (sp - msg); 7761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*dn) 7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto next; 7791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_CMPRSFLGS: /* indirection */ 7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = msg + (((n & 0x3f) << 8) | *cp); 7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 7821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: /* illegal type */ 7841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 7851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 7861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project next: ; 7891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sp += *sp + 1; 7901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = ENOENT; 7931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 7941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 7971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdecode_bitstring(const unsigned char **cpp, char *dn, const char *eom) 7981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 7991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const unsigned char *cp = *cpp; 8001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *beg = dn, tc; 8011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int b, blen, plen, i; 8021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((blen = (*cp & 0xff)) == 0) 8041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blen = 256; 8051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project plen = (blen + 3) / 4; 8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); 8071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + plen >= eom) 8081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 8091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp++; 8111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "\\[x")); 8121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 8131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 8141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 8151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (b = blen; b > 7; b -= 8, cp++) { 8161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "%02x", *cp & 0xff)); 8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 8191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 8201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 8211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (b > 4) { 8221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tc = *cp++; 8231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b)))); 8241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 8251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 8261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 8271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (b > 0) { 8281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tc = *cp++; 8291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "%1x", 8301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b)))); 8311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 8321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 8331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 8341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 8351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "/%d]", blen)); 8361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 8371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 8381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 8391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cpp = cp; 8411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(dn - beg); 8421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 8431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 8451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectencode_bitsring(const char **bp, const char *end, unsigned char **labelp, 8461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned char ** dst, unsigned const char *eom) 8471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 8481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int afterslash = 0; 8491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *cp = *bp; 8501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned char *tp; 8511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char c; 8521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *beg_blen; 8531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *end_blen = NULL; 8541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int value = 0, count = 0, tbcount = 0, blen = 0; 8551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project beg_blen = end_blen = NULL; 8571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* a bitstring must contain at least 2 characters */ 8591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (end - cp < 2) 8601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 8611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX: currently, only hex strings are supported */ 8631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*cp++ != 'x') 8641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 8651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */ 8661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 8671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (tp = *dst + 1; cp < end && tp < eom; cp++) { 8691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch((c = *cp)) { 8701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case ']': /* end of the bitstring */ 8711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afterslash) { 8721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (beg_blen == NULL) 8731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 8741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blen = (int)strtol(beg_blen, &end_blen, 10); 8751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*end_blen != ']') 8761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 8771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (count) 8791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *tp++ = ((value << 4) & 0xff); 8801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp++; /* skip ']' */ 8811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto done; 8821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case '/': 8831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afterslash = 1; 8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afterslash) { 8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!isdigit(c&0xff)) 8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (beg_blen == NULL) { 8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c == '0') { 8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* blen never begings with 0 */ 8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project beg_blen = cp; 8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!isxdigit(c&0xff)) 8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project value <<= 4; 9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project value += digitvalue[(int)c]; 9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project count += 4; 9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tbcount += 4; 9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (tbcount > 256) 9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (count == 8) { 9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *tp++ = value; 9081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project count = 0; 9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project done: 9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cp >= end || tp >= eom) 9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EMSGSIZE); 9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * bit length validation: 9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If a <length> is present, the number of digits in the <bit-data> 9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * MUST be just sufficient to contain the number of bits specified 9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * by the <length>. If there are insignificant bits in a final 9231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * hexadecimal or octal digit, they MUST be zero. 9241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * RFC 2673, Section 3.2. 9251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (blen > 0) { 9271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int traillen; 9281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (((blen + 3) & ~3) != tbcount) 9301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 9311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project traillen = tbcount - blen; /* between 0 and 3 */ 9321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (((value << (8 - traillen)) & 0xff) != 0) 9331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 9341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 9361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blen = tbcount; 9371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (blen == 256) 9381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blen = 0; 9391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* encode the type and the significant bit fields */ 9411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project **labelp = DNS_LABELTYPE_BITSTRING; 9421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project **dst = blen; 9431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *bp = cp; 9451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dst = tp; 9461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(0); 9481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 9491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 9511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlabellen(const u_char *lp) 9521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 9531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int bitlen; 9541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char l = *lp; 9551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 9571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* should be avoided by the caller */ 9581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { 9621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (l == DNS_LABELTYPE_BITSTRING) { 9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((bitlen = *(lp + 1)) == 0) 9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bitlen = 256; 9651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return((bitlen + 7 ) / 8 + 1); 9661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); /* unknwon ELT */ 9681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(l); 9701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 971