1b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes/* $NetBSD: inet_pton.c,v 1.6.10.1 2011/01/10 00:42:17 riz Exp $ */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes/* 4b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * 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 * 11b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include <sys/cdefs.h> 21b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#if defined(LIBC_SCCS) && !defined(lint) 22b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#if 0 23b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughesstatic const char rcsid[] = "Id: inet_pton.c,v 1.5 2005/07/28 06:51:47 marka Exp"; 24b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#else 25b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes__RCSID("$NetBSD: inet_pton.c,v 1.6.10.1 2011/01/10 00:42:17 riz Exp $"); 26b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#endif 27b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#endif /* LIBC_SCCS and not lint */ 28b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 29b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// BEGIN android-added 30b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#define _DIAGASSERT(exp) assert(exp) 31b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include "../private/arpa_nameser.h" 32b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// END android-added 33b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 34b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// android-removed: #include "port_before.h" 35b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 36b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// android-removed: #include "namespace.h" 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/param.h> 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h> 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h> 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h> 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <arpa/inet.h> 42b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include <arpa/nameser.h> 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h> 44b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include <assert.h> 45b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes#include <ctype.h> 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 48b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes// android-removed: #include "port_after.h" 49b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 503398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// BEGIN android-removed 513398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// #ifdef __weak_alias 523398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// __weak_alias(inet_pton,_inet_pton) 533398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// #endif 543398ee9c15278b90bc2934afca6bdf83b6b605e6Elliott Hughes// END android-removed 55b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 56b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes/*% 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WARNING: Don't even consider trying to compile this on a system where 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 61b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughesstatic int inet_pton4(const char *src, u_char *dst, int pton); 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int inet_pton6(const char *src, u_char *dst); 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * inet_pton(af, src, dst) 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * convert from presentation format (which usually means ASCII printable) 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * to network format (which is usually some kind of binary format). 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1 if the address was valid for the specified address family 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 0 if the address wasn't valid (`dst' is untouched in this case) 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * -1 if some other error occurred (`dst' is untouched in this case, too) 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author: 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Paul Vixie, 1996. 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectinet_pton(int af, const char *src, void *dst) 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 78b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 79b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes _DIAGASSERT(src != NULL); 80b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes _DIAGASSERT(dst != NULL); 81b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (af) { 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 84b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes return (inet_pton4(src, dst, 1)); 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (inet_pton6(src, dst)); 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EAFNOSUPPORT; 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* NOTREACHED */ 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int 95b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * inet_pton4(src, dst, pton) 96b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand. 97b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * when last arg is 1: inet_pton(). decimal dotted-quad only. 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 99b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * 1 if `src' is a valid input, else 0. 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice: 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * does not touch `dst' unless it's returning 1. 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author: 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Paul Vixie, 1996. 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 106b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughesinet_pton4(const char *src, u_char *dst, int pton) 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 108b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes u_int32_t val; 109b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes u_int digit, base; 110b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes int n; 111b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes unsigned char c; 112b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes u_int parts[4]; 113b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes register u_int *pp = parts; 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 115b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes _DIAGASSERT(src != NULL); 116b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes _DIAGASSERT(dst != NULL); 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 118b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes c = *src; 119b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes for (;;) { 120b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes /* 121b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * Collect number up to ``.''. 122b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * Values are specified as for C: 123b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * 0x=hex, 0=octal, isdigit=decimal. 124b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes */ 125b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (!isdigit(c)) 126b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes return (0); 127b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes val = 0; base = 10; 128b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (c == '0') { 129b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes c = *++src; 130b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (c == 'x' || c == 'X') 131b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes base = 16, c = *++src; 132b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes else if (isdigit(c) && c != '9') 133b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes base = 8; 134b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes } 135b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes /* inet_pton() takes decimal only */ 136b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (pton && base != 10) 137b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes return (0); 138b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes for (;;) { 139b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (isdigit(c)) { 140b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes digit = c - '0'; 141b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (digit >= base) 142b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes break; 143b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes val = (val * base) + digit; 144b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes c = *++src; 145b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes } else if (base == 16 && isxdigit(c)) { 146b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes digit = c + 10 - (islower(c) ? 'a' : 'A'); 147b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (digit >= 16) 148b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes break; 149b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes val = (val << 4) | digit; 150b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes c = *++src; 151b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes } else 152b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes break; 153b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes } 154b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (c == '.') { 155b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes /* 156b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * Internet format: 157b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * a.b.c.d 158b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * a.b.c (with c treated as 16 bits) 159b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * a.b (with b treated as 24 bits) 160b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * a (with a treated as 32 bits) 161b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes */ 162b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (pp >= parts + 3) 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 164b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes *pp++ = val; 165b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes c = *++src; 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 167b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes break; 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 169b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes /* 170b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * Check for trailing characters. 171b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes */ 172b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (c != '\0' && !isspace(c)) 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 174b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes /* 175b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * Concoct the address according to 176b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes * the number of parts specified. 177b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes */ 178b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes n = pp - parts + 1; 179b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes /* inet_pton() takes dotted-quad only. it does not take shorthand. */ 180b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (pton && n != 4) 181b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes return (0); 182b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes switch (n) { 183b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 184b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes case 0: 185b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes return (0); /* initial nondigit */ 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 187b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes case 1: /* a -- 32 bits */ 188b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes break; 189b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 190b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes case 2: /* a.b -- 8.24 bits */ 191b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (parts[0] > 0xff || val > 0xffffff) 192b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes return (0); 193b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes val |= parts[0] << 24; 194b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes break; 195b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 196b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes case 3: /* a.b.c -- 8.8.16 bits */ 197b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if ((parts[0] | parts[1]) > 0xff || val > 0xffff) 198b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes return (0); 199b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes val |= (parts[0] << 24) | (parts[1] << 16); 200b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes break; 201b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 202b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes case 4: /* a.b.c.d -- 8.8.8.8 bits */ 203b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if ((parts[0] | parts[1] | parts[2] | val) > 0xff) 204b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes return (0); 205b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 206b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes break; 207b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes } 208b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (dst) { 209b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes val = htonl(val); 210b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes memcpy(dst, &val, NS_INADDRSZ); 211b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes } 2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (1); 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int 2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * inet_pton6(src, dst) 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * convert presentation level address to network order binary form. 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * return: 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice: 2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (1) does not touch `dst' unless it's returning 1. 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (2) :: in a full address is silently ignored. 2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * credit: 2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * inspired by Mark Andrews. 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author: 2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Paul Vixie, 1996. 2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectinet_pton6(const char *src, u_char *dst) 2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project static const char xdigits_l[] = "0123456789abcdef", 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project xdigits_u[] = "0123456789ABCDEF"; 233b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; 2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *xdigits, *curtok; 235b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes int ch, seen_xdigits; 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int val; 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 238b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes _DIAGASSERT(src != NULL); 239b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes _DIAGASSERT(dst != NULL); 240b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 241b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes memset((tp = tmp), '\0', NS_IN6ADDRSZ); 242b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes endp = tp + NS_IN6ADDRSZ; 2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project colonp = NULL; 2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Leading :: requires some special handling. */ 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*src == ':') 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*++src != ':') 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project curtok = src; 249b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes seen_xdigits = 0; 2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project val = 0; 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((ch = *src++) != '\0') { 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *pch; 2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pch = strchr((xdigits = xdigits_u), ch); 2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pch != NULL) { 2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project val <<= 4; 2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project val |= (pch - xdigits); 259b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (++seen_xdigits > 4) 2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ch == ':') { 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project curtok = src; 265b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (!seen_xdigits) { 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (colonp) 2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project colonp = tp; 2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 270b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes } else if (*src == '\0') 2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 272b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (tp + NS_INT16SZ > endp) 2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *tp++ = (u_char) (val >> 8) & 0xff; 2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *tp++ = (u_char) val & 0xff; 276b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes seen_xdigits = 0; 2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project val = 0; 2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 280b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && 281b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes inet_pton4(curtok, tp, 1) > 0) { 282b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes tp += NS_INADDRSZ; 283b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes seen_xdigits = 0; 284b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes break; /*%< '\\0' was seen by inet_pton4(). */ 2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 288b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (seen_xdigits) { 289b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (tp + NS_INT16SZ > endp) 2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *tp++ = (u_char) (val >> 8) & 0xff; 2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *tp++ = (u_char) val & 0xff; 2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (colonp != NULL) { 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Since some memmove()'s erroneously fail to handle 2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * overlapping regions, we'll do the shift by hand. 2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const int n = tp - colonp; 3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int i; 3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 302b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes if (tp == endp) 303b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes return (0); 3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (i = 1; i <= n; i++) { 3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project endp[- i] = colonp[n - i]; 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project colonp[n - i] = 0; 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tp = endp; 3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (tp != endp) 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 312b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes memcpy(dst, tmp, NS_IN6ADDRSZ); 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (1); 3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 315b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes 316b1fd729d638d2646bdc915a7f4612fe85725a407Elliott Hughes/*! \file */ 317