diff options
author | dwitte%mozilla.com <devnull@localhost> | 2009-12-18 22:11:48 +0000 |
---|---|---|
committer | dwitte%mozilla.com <devnull@localhost> | 2009-12-18 22:11:48 +0000 |
commit | 5343f0476b2fd096a8bc49178b04067fb0c40255 (patch) | |
tree | 25ea62b7a2678cc81375b0bfcfb95e62b50be101 | |
parent | 7eca596050407588eede1712506fd63b2f37dbce (diff) | |
parent | bc6cf8ae0b2580e1745fac833ee3cd379730f51d (diff) | |
download | nspr-hg-5343f0476b2fd096a8bc49178b04067fb0c40255.tar.gz |
Bug 344809 - numerous platform inconsistencies of PR_StringToNetAddr for IPv4 addresses. r=nelsonNSPR_HEAD_20091218
-rw-r--r-- | pr/src/Makefile.in | 1 | ||||
-rw-r--r-- | pr/src/misc/Makefile.in | 1 | ||||
-rw-r--r-- | pr/src/misc/aton.c | 198 | ||||
-rw-r--r-- | pr/src/misc/prnetdb.c | 82 |
4 files changed, 227 insertions, 55 deletions
diff --git a/pr/src/Makefile.in b/pr/src/Makefile.in index 99f67c67..0c43af3f 100644 --- a/pr/src/Makefile.in +++ b/pr/src/Makefile.in @@ -257,6 +257,7 @@ OBJS = \ misc/$(OBJDIR)/prlog2.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prlong.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prnetdb.$(OBJ_SUFFIX) \ + misc/$(OBJDIR)/aton.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prolock.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prrng.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prsystem.$(OBJ_SUFFIX) \ diff --git a/pr/src/misc/Makefile.in b/pr/src/misc/Makefile.in index 79dc59ed..2e5fa4d5 100644 --- a/pr/src/misc/Makefile.in +++ b/pr/src/misc/Makefile.in @@ -61,6 +61,7 @@ CSRCS = \ prlog2.c \ prlong.c \ prnetdb.c \ + aton.c \ prolock.c \ prrng.c \ prsystem.c \ diff --git a/pr/src/misc/aton.c b/pr/src/misc/aton.c new file mode 100644 index 00000000..bff0cd15 --- /dev/null +++ b/pr/src/misc/aton.c @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/******************************************************************************* + * The following function pr_inet_aton is based on the BSD function inet_aton + * with some modifications. The license and copyright notices applying to this + * function appear below. Modifications are also according to the license below. + ******************************************************************************/ + +#include "prnetdb.h" + +/* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define XX 127 +static const unsigned char index_hex[256] = { + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,XX,XX, XX,XX,XX,XX, + XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, +}; + +static PRBool _isdigit(char c) { return c >= '0' && c <= '9'; } +static PRBool _isxdigit(char c) { return index_hex[(unsigned char) c] != XX; } +static PRBool _isspace(char c) { return c == ' ' || (c >= '\t' && c <= '\r'); } +#undef XX + +int +pr_inet_aton(const char *cp, PRUint32 *addr) +{ + PRUint32 val; + int base, n; + char c; + PRUint8 parts[4]; + PRUint8 *pp = parts; + int digit; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!_isdigit(c)) + return (0); + val = 0; base = 10; digit = 0; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else { + base = 8; + digit = 1; + } + } + for (;;) { + if (_isdigit(c)) { + if (base == 8 && (c == '8' || c == '9')) + return (0); + val = (val * base) + (c - '0'); + c = *++cp; + digit = 1; + } else if (base == 16 && _isxdigit(c)) { + val = (val << 4) + index_hex[(unsigned char) c]; + c = *++cp; + digit = 1; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3 || val > 0xffU) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && !_isspace(c)) + return (0); + /* + * Did we get a valid digit? + */ + if (!digit) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + case 1: /*%< a -- 32 bits */ + break; + + case 2: /*%< a.b -- 8.24 bits */ + if (val > 0xffffffU) + return (0); + val |= parts[0] << 24; + break; + + case 3: /*%< a.b.c -- 8.8.16 bits */ + if (val > 0xffffU) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /*%< a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xffU) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + *addr = PR_htonl(val); + return (1); +} + diff --git a/pr/src/misc/prnetdb.c b/pr/src/misc/prnetdb.c index c8c1a628..8a2a00c4 100644 --- a/pr/src/misc/prnetdb.c +++ b/pr/src/misc/prnetdb.c @@ -1535,7 +1535,8 @@ PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val) return PR_FALSE; } -#ifndef _PR_HAVE_INET_NTOP +extern int pr_inet_aton(const char *cp, PRUint32 *addr); + #define XX 127 static const unsigned char index_hex[256] = { XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, @@ -1668,7 +1669,8 @@ static int StringToV6Addr(const char *string, PRIPv6Addr *addr) return 1; } #undef XX - + +#ifndef _PR_HAVE_INET_NTOP static const char *basis_hex = "0123456789abcdef"; /* @@ -1774,7 +1776,6 @@ static const char *V6AddrToString( return bufcopy; #undef STUFF } - #endif /* !_PR_HAVE_INET_NTOP */ /* @@ -2141,12 +2142,6 @@ static PRStatus pr_StringToNetAddrGAI(const char *string, PRNetAddr *addr) PRNetAddr laddr; PRStatus status = PR_SUCCESS; - if (NULL == addr) - { - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - return PR_FAILURE; - } - memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = AF_UNSPEC; @@ -2183,65 +2178,43 @@ static PRStatus pr_StringToNetAddrGAI(const char *string, PRNetAddr *addr) } #endif /* _PR_HAVE_GETADDRINFO */ -#if !defined(_PR_HAVE_GETADDRINFO) || defined(_PR_INET6_PROBE) || defined(DARWIN) static PRStatus pr_StringToNetAddrFB(const char *string, PRNetAddr *addr) { - PRStatus status = PR_SUCCESS; PRIntn rv; -#if defined(_PR_HAVE_INET_NTOP) - rv = inet_pton(AF_INET6, string, &addr->ipv6.ip); + rv = pr_inet_aton(string, &addr->inet.ip); if (1 == rv) { - addr->raw.family = PR_AF_INET6; - } - else - { - PR_ASSERT(0 == rv); - /* clean up after the failed inet_pton() call */ - memset(&addr->ipv6.ip, 0, sizeof(addr->ipv6.ip)); - rv = inet_pton(AF_INET, string, &addr->inet.ip); - if (1 == rv) - { - addr->raw.family = AF_INET; - } - else - { - PR_ASSERT(0 == rv); - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - status = PR_FAILURE; - } - } -#else /* _PR_HAVE_INET_NTOP */ - rv = StringToV6Addr(string, &addr->ipv6.ip); - if (1 == rv) { - addr->raw.family = PR_AF_INET6; + addr->raw.family = AF_INET; return PR_SUCCESS; } + PR_ASSERT(0 == rv); - /* clean up after the failed StringToV6Addr() call */ - memset(&addr->ipv6.ip, 0, sizeof(addr->ipv6.ip)); + /* clean up after the failed call */ + memset(&addr->inet.ip, 0, sizeof(addr->inet.ip)); - addr->inet.family = AF_INET; - addr->inet.ip = inet_addr(string); - if ((PRUint32) -1 == addr->inet.ip) + rv = StringToV6Addr(string, &addr->ipv6.ip); + if (1 == rv) { - /* - * The string argument is a malformed address string. - */ - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - status = PR_FAILURE; + addr->raw.family = PR_AF_INET6; + return PR_SUCCESS; } -#endif /* _PR_HAVE_INET_NTOP */ - return status; + PR_ASSERT(0 == rv); + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return PR_FAILURE; } -#endif /* !_PR_HAVE_GETADDRINFO || _PR_INET6_PROBE || DARWIN */ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) { if (!_pr_initialized) _PR_ImplicitInitialization(); + if (!addr || !string || !*string) + { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return PR_FAILURE; + } + #if !defined(_PR_HAVE_GETADDRINFO) return pr_StringToNetAddrFB(string, addr); #else @@ -2249,16 +2222,15 @@ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) if (!_pr_ipv6_is_present()) return pr_StringToNetAddrFB(string, addr); #endif -#if defined(DARWIN) /* - * On Mac OS X, getaddrinfo with AI_NUMERICHOST is slow. - * So we only use it to convert literal IP addresses that - * contain IPv6 scope IDs, which pr_StringToNetAddrFB - * cannot convert. (See bug 404399.) + * getaddrinfo with AI_NUMERICHOST is much slower than pr_inet_aton on some + * platforms, such as Mac OS X (bug 404399), Linux glibc 2.10 (bug 344809), + * and most likely others. So we only use it to convert literal IP addresses + * that contain IPv6 scope IDs, which pr_inet_aton cannot convert. */ if (!strchr(string, '%')) return pr_StringToNetAddrFB(string, addr); -#endif + return pr_StringToNetAddrGAI(string, addr); #endif } |