1fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* $NetBSD: ns_name.c,v 1.9 2012/03/13 21:13:39 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 23fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlestatic const char rcsid[] = "Id: ns_name.c,v 1.11 2009/01/23 19:59:16 each Exp"; 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 25fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle__RCSID("$NetBSD: ns_name.c,v 1.9 2012/03/13 21:13:39 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> 32569fb9887d00104509df79fa77d92e3cf9afe7dbCalin Juravle#include <arpa/nameser.h> 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 34fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle#include <assert.h> 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ANDROID_CHANGES 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h" 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <resolv.h> 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h> 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <ctype.h> 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h> 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <limits.h> 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef SPRINTF_CHAR 47fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle# define SPRINTF(x) ((int)strlen(sprintf/**/x)) 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 49fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle# define SPRINTF(x) (sprintf x) 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */ 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DNS_LABELTYPE_BITSTRING 0x41 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Data. */ 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char digits[] = "0123456789"; 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char digitvalue[256] = { 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ 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, 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Forward. */ 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int special(int); 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int printable(int); 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int dn_find(const u_char *, const u_char *, 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *, 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *); 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int encode_bitsring(const char **, const char *, 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned char **, unsigned char **, 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned const char *); 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int labellen(const u_char *); 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int decode_bitstring(const unsigned char **, 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *, const char *); 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Public. */ 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 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) 98fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The root is returned as "." 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All other domains are returned in non absolute form 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_ntop(const u_char *src, char *dst, size_t dstsiz) 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *cp; 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *dn, *eom; 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char c; 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int n; 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int l; 1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = src; 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn = dst; 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eom = dst + dstsiz; 1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((n = *cp++) != 0) { 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Some kind of compression pointer. */ 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn != dst) { 1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '.'; 1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l = labellen(cp - 1)) < 0) { 1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; /* XXX */ 1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + l >= eom) { 1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { 1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int m; 1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n != DNS_LABELTYPE_BITSTRING) { 1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX: labellen should reject this case */ 1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((m = decode_bitstring(&cp, dn, eom)) < 0) 1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += m; 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (; l > 0; l--) { 1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project c = *cp++; 1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (special(c)) { 1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + 1 >= eom) { 1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '\\'; 1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = (char)c; 1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (!printable(c)) { 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + 3 >= eom) { 1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '\\'; 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = digits[c / 100]; 1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = digits[(c % 100) / 10]; 1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = digits[c % 10]; 1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = (char)c; 1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn == dst) { 1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '.'; 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '\0'; 192fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle _DIAGASSERT(__type_fit(int, dn - dst)); 193fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (int)(dn - dst); 194fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle} 195fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 196fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* 197fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * Convert a ascii string into an encoded domain name as per RFC1035. 198fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 199fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * return: 200fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 201fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * -1 if it fails 202fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 1 if string was fully qualified 203fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 0 is string was not fully qualified 204fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 205fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * notes: 206fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * Enforces label and domain length limits. 207fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */ 208fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint 209fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_pton(const char *src, u_char *dst, size_t dstsiz) { 210fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (ns_name_pton2(src, dst, dstsiz, NULL)); 2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 214fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * ns_name_pton2(src, dst, dstsiz, *dstlen) 2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Convert a ascii string into an encoded domain name as per RFC1035. 2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * -1 if it fails 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1 if string was fully qualified 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 0 is string was not fully qualified 220fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * side effects: 221fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * fills in *dstlen (if non-NULL) 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Enforces label and domain length limits. 2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 227fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen) { 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *label, *bp, *eom; 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int c, n, escaped, e = 0; 2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *cp; 2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project escaped = 0; 2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp = dst; 2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eom = dst + dstsiz; 2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project label = bp++; 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((c = *src++) != 0) { 2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (escaped) { 2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c == '[') { /* start a bit string label */ 2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((cp = strchr(src, ']')) == NULL) { 2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; /* ??? */ 2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((e = encode_bitsring(&src, cp + 2, 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project &label, &bp, eom)) 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project != 0) { 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = e; 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project escaped = 0; 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project label = bp++; 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c = *src++) == 0) 2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto done; 2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if (c != '.') { 2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if ((cp = strchr(digits, c)) != NULL) { 261fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle n = (int)(cp - digits) * 100; 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c = *src++) == 0 || 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (cp = strchr(digits, c)) == NULL) { 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 267fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle n += (int)(cp - digits) * 10; 2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c = *src++) == 0 || 2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (cp = strchr(digits, c)) == NULL) { 2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 273fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle n += (int)(cp - digits); 2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n > 255) { 2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project c = n; 2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project escaped = 0; 2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (c == '\\') { 2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project escaped = 1; 2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (c == '.') { 285fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle c = (int)(bp - label - 1); 2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ 2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (label >= eom) { 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 = c; 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Fully qualified ? */ 2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*src == '\0') { 2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c != 0) { 2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bp >= eom) { 2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *bp++ = '\0'; 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((bp - dst) > MAXCDNAME) { 3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 308fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (dstlen != NULL) 309fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *dstlen = (bp - dst); 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (1); 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c == 0 || *src == '.') { 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project label = bp++; 3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bp >= eom) { 3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *bp++ = (u_char)c; 3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 325fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle c = (int)(bp - label - 1); 3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ 3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project done: 3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (label >= eom) { 3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *label = c; 3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c != 0) { 3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (bp >= eom) { 3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *bp++ = 0; 3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((bp - dst) > MAXCDNAME) { /* src too big */ 3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 347fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (dstlen != NULL) 348fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *dstlen = (bp - dst); 3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Convert a network strings labels into all lowercase. 354fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Number of bytes written to buffer, or -1 (with errno set) 357fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Enforces label and domain length limits. 3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) 3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *cp; 3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *dn, *eom; 3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char c; 3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int n; 3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int l; 3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = src; 3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn = dst; 3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eom = dst + dstsiz; 3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn >= eom) { 3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((n = *cp++) != 0) { 3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Some kind of compression pointer. */ 3821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = n; 3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l = labellen(cp - 1)) < 0) { 3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + l >= eom) { 3911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (; l > 0; l--) { 3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project c = *cp++; 396fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (isascii(c) && isupper(c)) 3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = tolower(c); 3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = c; 4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dn++ = '\0'; 403fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle _DIAGASSERT(__type_fit(int, dn - dst)); 404fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (int)(dn - dst); 4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Unpack a domain name from a message, source may be compressed. 409fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * -1 if it fails, or consumed octets if it succeeds. 4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 4131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 4141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, 4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *dst, size_t dstsiz) 4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 417fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (ns_name_unpack2(msg, eom, src, dst, dstsiz, NULL)); 418fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle} 419fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 420fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* 421fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * ns_name_unpack2(msg, eom, src, dst, dstsiz, *dstlen) 422fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * Unpack a domain name from a message, source may be compressed. 423fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * return: 424fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * -1 if it fails, or consumed octets if it succeeds. 425fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * side effect: 426fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * fills in *dstlen (if non-NULL). 427fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */ 428fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint 429fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_unpack2(const u_char *msg, const u_char *eom, const u_char *src, 430fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle u_char *dst, size_t dstsiz, size_t *dstlen) 431fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle{ 4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *srcp, *dstlim; 4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *dstp; 4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n, len, checked, l; 4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project len = -1; 4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project checked = 0; 4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstp = dst; 4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp = src; 4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstlim = dst + dstsiz; 4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (srcp < msg || srcp >= eom) { 4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Fetch next label in domain name. */ 4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((n = *srcp++) != 0) { 4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Check for indirection. */ 4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (n & NS_CMPRSFLGS) { 4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0: 4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_TYPE_ELT: 4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Limit checks. */ 4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l = labellen(srcp - 1)) < 0) { 4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dstp + l + 1 >= dstlim || srcp + l >= eom) { 4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project checked += l + 1; 4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dstp++ = n; 4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(dstp, srcp, (size_t)l); 4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstp += l; 4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp += l; 4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_CMPRSFLGS: 4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (srcp >= eom) { 4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 472fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (len < 0) { 473fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle _DIAGASSERT(__type_fit(int, srcp - src + 1)); 474fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle len = (int)(srcp - src + 1); 475fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 47685c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle // BEGIN android-changed: safer pointer overflow check 47785c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle l = (((n & 0x3f) << 8) | (*srcp & 0xff)); 47885c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle if (l >= eom - msg) { /* Out of range. */ 4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 48285c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle srcp = msg + l; 48385c5202a64e3cb63e54550fca7bb11f24b9d12ccCalin Juravle // END android-changed 4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project checked += 2; 4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Check for loops in the compressed name; 4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we've looked at the whole message, 4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * there must be a loop. 4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (checked >= eom - msg) { 4911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 4951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 4971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 4981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); /* flag error */ 4991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 501fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *dstp++ = 0; 502fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (dstlen != NULL) 503fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle *dstlen = dstp - dst; 504fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (len < 0) { 505fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle _DIAGASSERT(__type_fit(int, srcp - src)); 506fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle len = (int)(srcp - src); 507fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 508fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return len; 5091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 5121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Pack domain name 'domain' into 'comp_dn'. 513fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Size of the compressed name, or -1. 516fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 'dnptrs' is an array of pointers to previous compressed names. 5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * dnptrs[0] is a pointer to the beginning of the message. The array 5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ends with NULL. 5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 'lastdnptr' is a pointer to the end of the array pointed to 5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * by 'dnptrs'. 523fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Side effects: 5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The list of pointers in dnptrs is updated for labels inserted into 5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the message as we compress the name. If 'dnptr' is NULL, we don't 5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * try to compress names. If 'lastdnptr' is NULL, we don't update the 5281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * list. 5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_pack(const u_char *src, u_char *dst, int dstsiz, 5321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char **dnptrs, const u_char **lastdnptr) 5331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 5341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *dstp; 5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char **cpp, **lpp, *eob, *msg; 5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *srcp; 5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n, l, first = 1; 5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp = src; 5401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstp = dst; 5411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eob = dstp + dstsiz; 5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lpp = cpp = NULL; 5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dnptrs != NULL) { 5441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((msg = *dnptrs++) != NULL) { 5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cpp = dnptrs; *cpp != NULL; cpp++) 546fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle continue; 5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lpp = cpp; /* end of list to search */ 5481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project msg = NULL; 5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* make sure the domain we are about to add is legal */ 5531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project l = 0; 5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { 5551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int l0; 5561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = *srcp; 5581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 5591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 5601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 5611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l0 = labellen(srcp)) < 0) { 5631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 5641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 5651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project l += l0 + 1; 5671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (l > MAXCDNAME) { 5681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 5691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 5701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp += l0 + 1; 5721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } while (n != 0); 5731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* from here on we need to reset compression pointer array on error */ 5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp = src; 5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { 5771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Look to see if we can use pointers. */ 5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = *srcp; 5791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n != 0 && msg != NULL) { 5801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project l = dn_find(srcp, msg, (const u_char * const *)dnptrs, 5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (const u_char * const *)lpp); 5821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (l >= 0) { 5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dstp + 1 >= eob) { 5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto cleanup; 5851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dstp++ = ((u_int32_t)l >> 8) | NS_CMPRSFLGS; 5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dstp++ = l % 256; 588fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle _DIAGASSERT(__type_fit(int, dstp - dst)); 589fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (int)(dstp - dst); 5901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Not found, save it. */ 5921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (lastdnptr != NULL && cpp < lastdnptr - 1 && 5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (dstp - msg) < 0x4000 && first) { 5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cpp++ = dstp; 5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cpp = NULL; 5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project first = 0; 5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* copy label to buffer */ 6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Should not happen. */ 6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto cleanup; 6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = labellen(srcp); 6051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dstp + 1 + n >= eob) { 6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto cleanup; 6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(dstp, srcp, (size_t)(n + 1)); 6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project srcp += n + 1; 6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dstp += n + 1; 6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } while (n != 0); 6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dstp > eob) { 6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectcleanup: 6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (msg != NULL) 6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *lpp = NULL; 6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 620fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle _DIAGASSERT(__type_fit(int, dstp - dst)); 621fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (int)(dstp - dst); 6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Expand compressed domain name to presentation format. 626fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Number of bytes read out of `src', or -1 (with errno set). 629fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * note: 6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Root domain returns as "." not "". 6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, 6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *dst, size_t dstsiz) 6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char tmp[NS_MAXCDNAME]; 6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n; 6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) 6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ns_name_ntop(tmp, dst, dstsiz) == -1) 6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (n); 6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Compress a domain name into wire format, using compression pointers. 649fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Number of bytes consumed in `dst' or -1 (with errno set). 652fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 'dnptrs' is an array of pointers to previous compressed names. 6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * dnptrs[0] is a pointer to the beginning of the message. 6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The list ends with NULL. 'lastdnptr' is a pointer to the end of the 6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * array pointed to by 'dnptrs'. Side effect is to update the list of 6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * pointers for labels inserted into the message as we compress the name. 6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' 6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is NULL, we don't update the list. 6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_compress(const char *src, u_char *dst, size_t dstsiz, 6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char **dnptrs, const u_char **lastdnptr) 6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char tmp[NS_MAXCDNAME]; 6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ns_name_pton(src, tmp, sizeof tmp) == -1) 6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr)); 6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Reset dnptrs so that there are no active references to pointers at or 6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * after src. 6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_rollback(const u_char *src, const u_char **dnptrs, 6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char **lastdnptr) 6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (dnptrs < lastdnptr && *dnptrs != NULL) { 6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*dnptrs >= src) { 6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dnptrs = NULL; 6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dnptrs++; 6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Advance *ptrptr to skip over the compressed name it points at. 692fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 0 on success, -1 (with errno set) on failure. 6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectns_name_skip(const u_char **ptrptr, const u_char *eom) 6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *cp; 7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int n; 7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int l; 7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = *ptrptr; 7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cp < eom && (n = *cp++) != 0) { 7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Check for indirection. */ 7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (n & NS_CMPRSFLGS) { 7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0: /* normal case, n == len */ 7081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_TYPE_ELT: /* EDNS0 extended label */ 7111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l = labellen(cp - 1)) < 0) { 7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; /* XXX */ 7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += l; 7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_CMPRSFLGS: /* indirection */ 7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp++; 7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: /* illegal type */ 7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cp > eom) { 7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *ptrptr = cp; 7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 734fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Find the number of octets an nname takes up, including the root label. 735fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * (This is basically ns_name_skip() without compression-pointer support.) 736fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * ((NOTE: can only return zero if passed-in namesiz argument is zero.)) 737fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */ 738fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlessize_t 739fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_length(ns_nname_ct nname, size_t namesiz) { 740fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle ns_nname_ct orig = nname; 741fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle u_int n; 742fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 743fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle while (namesiz-- > 0 && (n = *nname++) != 0) { 744fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if ((n & NS_CMPRSFLGS) != 0) { 745fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = EISDIR; 746fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 747fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 748fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (n > namesiz) { 749fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = EMSGSIZE; 750fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 751fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 752fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle nname += n; 753fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle namesiz -= n; 754fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 755fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (nname - orig); 756fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle} 757fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 758fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Compare two nname's for equality. Return -1 on error (setting errno). 759fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */ 760fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint 761fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_eq(ns_nname_ct a, size_t as, ns_nname_ct b, size_t bs) { 762fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle ns_nname_ct ae = a + as, be = b + bs; 763fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle int ac, bc; 764fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 765fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle while (ac = *a, bc = *b, ac != 0 && bc != 0) { 766fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if ((ac & NS_CMPRSFLGS) != 0 || (bc & NS_CMPRSFLGS) != 0) { 767fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = EISDIR; 768fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 769fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 770fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (a + ac >= ae || b + bc >= be) { 771fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = EMSGSIZE; 772fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 773fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 774fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (ac != bc || strncasecmp((const char *) ++a, 775fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle (const char *) ++b, 776fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle (size_t)ac) != 0) 777fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (0); 778fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle a += ac, b += bc; 779fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 780fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (ac == 0 && bc == 0); 781fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle} 782fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 783fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Is domain "A" owned by (at or below) domain "B"? 784fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */ 785fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint 786fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_owned(ns_namemap_ct a, int an, ns_namemap_ct b, int bn) { 787fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* If A is shorter, it cannot be owned by B. */ 788fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (an < bn) 789fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (0); 790fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 791fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* If they are unequal before the length of the shorter, A cannot... */ 792fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle while (bn > 0) { 793fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (a->len != b->len || 794fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle strncasecmp((const char *) a->base, 795fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle (const char *) b->base, (size_t)a->len) != 0) 796fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (0); 797fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle a++, an--; 798fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle b++, bn--; 799fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 800fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 801fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* A might be longer or not, but either way, B owns it. */ 802fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (1); 803fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle} 804fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 805fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Build an array of <base,len> tuples from an nname, top-down order. 806fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * Return the number of tuples (labels) thus discovered. 807fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */ 808fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint 809fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_map(ns_nname_ct nname, size_t namelen, ns_namemap_t map, int mapsize) { 810fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle u_int n; 811fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle int l; 812fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 813fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle n = *nname++; 814fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle namelen--; 815fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 816fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* Root zone? */ 817fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (n == 0) { 818fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* Extra data follows name? */ 819fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (namelen > 0) { 820fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = EMSGSIZE; 821fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 822fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 823fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (0); 824fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 825fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 826fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* Compression pointer? */ 827fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if ((n & NS_CMPRSFLGS) != 0) { 828fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = EISDIR; 829fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 830fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 831fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 832fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* Label too long? */ 833fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (n > namelen) { 834fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = EMSGSIZE; 835fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 836fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 837fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 838fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* Recurse to get rest of name done first. */ 839fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle l = ns_name_map(nname + n, namelen - n, map, mapsize); 840fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (l < 0) 841fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 842fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 843fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* Too many labels? */ 844fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (l >= mapsize) { 845fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = ENAMETOOLONG; 846fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 847fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 848fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 849fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle /* We're on our way back up-stack, store current map data. */ 850fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle map[l].base = nname; 851fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle map[l].len = n; 852fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (l + 1); 853fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle} 854fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 855fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle/* Count the labels in a domain name. Root counts, so COM. has two. This 856fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * is to make the result comparable to the result of ns_name_map(). 857fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle */ 858fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravleint 859fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravlens_name_labels(ns_nname_ct nname, size_t namesiz) { 860fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle int ret = 0; 861fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle u_int n; 862fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle 863fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle while (namesiz-- > 0 && (n = *nname++) != 0) { 864fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if ((n & NS_CMPRSFLGS) != 0) { 865fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = EISDIR; 866fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 867fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 868fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (n > namesiz) { 869fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle errno = EMSGSIZE; 870fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (-1); 871fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 872fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle nname += n; 873fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle namesiz -= n; 874fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle ret++; 875fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 876fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (ret + 1); 877fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle} 8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Private. */ 8791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 8811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Thinking in noninternationalized USASCII (per the DNS spec), 8821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is this characted special ("in need of quoting") ? 883fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * boolean. 8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectspecial(int ch) { 8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ch) { 8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x22: /* '"' */ 8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x2E: /* '.' */ 8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x3B: /* ';' */ 8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x5C: /* '\\' */ 8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x28: /* '(' */ 8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x29: /* ')' */ 8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Special modifiers in zone files. */ 8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x40: /* '@' */ 8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x24: /* '$' */ 8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (1); 9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Thinking in noninternationalized USASCII (per the DNS spec), 9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is this character visible and not a space when printed ? 908fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * boolean. 9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectprintable(int ch) { 9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ch > 0x20 && ch < 0x7f); 9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Thinking in noninternationalized USASCII (per the DNS spec), 9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * convert this character to lower case if it's upper case. 9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectmklower(int ch) { 9231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ch >= 0x41 && ch <= 0x5A) 9241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ch + 0x20); 9251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ch); 9261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 9271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 9291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Search for the counted-label name in an array of compressed names. 930fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 9311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 9321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * offset from msg if found, or -1. 933fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle * 9341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notes: 9351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * dnptrs is the pointer to the first name on the list, 9361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * not the pointer to the start of the message. 9371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 9391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdn_find(const u_char *domain, const u_char *msg, 9401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *dnptrs, 9411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *lastdnptr) 9421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 9431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *dn, *cp, *sp; 9441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char * const *cpp; 9451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int n; 9461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cpp = dnptrs; cpp < lastdnptr; cpp++) { 9481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sp = *cpp; 9491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 9501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * terminate search on: 9511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * root label 9521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * compression pointer 9531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * unusable offset 9541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && 9561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (sp - msg) < 0x4000) { 9571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn = domain; 9581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = sp; 9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((n = *cp++) != 0) { 9601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 9611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * check for indirection 9621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (n & NS_CMPRSFLGS) { 9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0: /* normal case, n == len */ 9651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = labellen(cp - 1); /* XXX */ 9661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n != *dn++) 9681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto next; 9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (; n > 0; n--) 9711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (mklower(*dn++) != 9721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project mklower(*cp++)) 9731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto next; 9741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Is next root for both ? */ 975fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle if (*dn == '\0' && *cp == '\0') { 976fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle _DIAGASSERT(__type_fit(int, 977fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle sp - msg)); 978fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (int)(sp - msg); 979fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle } 9801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*dn) 9811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 9821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto next; 9831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_CMPRSFLGS: /* indirection */ 9841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = msg + (((n & 0x3f) << 8) | *cp); 9851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 9861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: /* illegal type */ 9881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EMSGSIZE; 9891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 9901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project next: ; 9931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sp += *sp + 1; 9941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = ENOENT; 9971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 9981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 9991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 10011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdecode_bitstring(const unsigned char **cpp, char *dn, const char *eom) 10021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 10031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const unsigned char *cp = *cpp; 10041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *beg = dn, tc; 10051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int b, blen, plen, i; 10061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((blen = (*cp & 0xff)) == 0) 10081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blen = 256; 10091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project plen = (blen + 3) / 4; 1010fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle plen += (int)sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); 10111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dn + plen >= eom) 10121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 10131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp++; 10151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "\\[x")); 10161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 10171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 10181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 10191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (b = blen; b > 7; b -= 8, cp++) { 10201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "%02x", *cp & 0xff)); 10211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 10221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 10231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 10241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (b > 4) { 10261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tc = *cp++; 10271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b)))); 10281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 10291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 10301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 10311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (b > 0) { 10321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tc = *cp++; 10331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "%1x", 10341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (((u_int32_t)tc >> 4) & 0x0f) & (0x0f << (4 - b)))); 10351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 10361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 10371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 10381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = SPRINTF((dn, "/%d]", blen)); 10401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (i < 0) 10411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 10421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dn += i; 10431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cpp = cp; 1045fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle _DIAGASSERT(__type_fit(int, dn - beg)); 1046fcb502e3ec032497bba7f8634fb214e0c05394d8Calin Juravle return (int)(dn - beg); 10471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 10481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 10501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectencode_bitsring(const char **bp, const char *end, unsigned char **labelp, 10511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned char ** dst, unsigned const char *eom) 10521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 10531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int afterslash = 0; 10541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *cp = *bp; 10551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned char *tp; 10561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char c; 10571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *beg_blen; 10581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *end_blen = NULL; 10591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int value = 0, count = 0, tbcount = 0, blen = 0; 10601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project beg_blen = end_blen = NULL; 10621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* a bitstring must contain at least 2 characters */ 10641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (end - cp < 2) 10651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 10661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX: currently, only hex strings are supported */ 10681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*cp++ != 'x') 10691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 10701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */ 10711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 10721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (tp = *dst + 1; cp < end && tp < eom; cp++) { 10741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch((c = *cp)) { 10751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case ']': /* end of the bitstring */ 10761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afterslash) { 10771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (beg_blen == NULL) 10781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 10791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blen = (int)strtol(beg_blen, &end_blen, 10); 10801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*end_blen != ']') 10811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 10821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (count) 10841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *tp++ = ((value << 4) & 0xff); 10851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp++; /* skip ']' */ 10861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto done; 10871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case '/': 10881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afterslash = 1; 10891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 10901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 10911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afterslash) { 10921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!isdigit(c&0xff)) 10931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 10941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (beg_blen == NULL) { 10951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (c == '0') { 10971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* blen never begings with 0 */ 10981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 10991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project beg_blen = cp; 11011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 11031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!isxdigit(c&0xff)) 11041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 11051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project value <<= 4; 11061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project value += digitvalue[(int)c]; 11071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project count += 4; 11081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tbcount += 4; 11091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (tbcount > 256) 11101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 11111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (count == 8) { 11121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *tp++ = value; 11131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project count = 0; 11141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 11171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project done: 11201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cp >= end || tp >= eom) 11211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EMSGSIZE); 11221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 11241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * bit length validation: 11251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If a <length> is present, the number of digits in the <bit-data> 11261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * MUST be just sufficient to contain the number of bits specified 11271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * by the <length>. If there are insignificant bits in a final 11281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * hexadecimal or octal digit, they MUST be zero. 11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * RFC 2673, Section 3.2. 11301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 11311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (blen > 0) { 11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int traillen; 11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (((blen + 3) & ~3) != tbcount) 11351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project traillen = tbcount - blen; /* between 0 and 3 */ 11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (((value << (8 - traillen)) & 0xff) != 0) 11381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EINVAL); 11391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 11411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blen = tbcount; 11421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (blen == 256) 11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blen = 0; 11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* encode the type and the significant bit fields */ 11461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project **labelp = DNS_LABELTYPE_BITSTRING; 11471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project **dst = blen; 11481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *bp = cp; 11501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *dst = tp; 11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(0); 11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 11561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlabellen(const u_char *lp) 11571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int bitlen; 11591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char l = *lp; 11601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 11621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* should be avoided by the caller */ 11631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); 11641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { 11671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (l == DNS_LABELTYPE_BITSTRING) { 11681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((bitlen = *(lp + 1)) == 0) 11691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bitlen = 256; 11701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return((bitlen + 7 ) / 8 + 1); 11711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(-1); /* unknwon ELT */ 11731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(l); 11751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1176