113498266Sopenharmony_ci/* This is from the BIND 4.9.4 release, modified to compile by itself */ 213498266Sopenharmony_ci 313498266Sopenharmony_ci/* Copyright (c) Internet Software Consortium. 413498266Sopenharmony_ci * 513498266Sopenharmony_ci * Permission to use, copy, modify, and distribute this software for any 613498266Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 713498266Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 813498266Sopenharmony_ci * 913498266Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 1013498266Sopenharmony_ci * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 1113498266Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 1213498266Sopenharmony_ci * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 1313498266Sopenharmony_ci * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 1413498266Sopenharmony_ci * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 1513498266Sopenharmony_ci * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 1613498266Sopenharmony_ci * SOFTWARE. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * SPDX-License-Identifier: ISC 1913498266Sopenharmony_ci */ 2013498266Sopenharmony_ci 2113498266Sopenharmony_ci#include "curl_setup.h" 2213498266Sopenharmony_ci 2313498266Sopenharmony_ci#ifndef HAVE_INET_PTON 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci#ifdef HAVE_SYS_PARAM_H 2613498266Sopenharmony_ci#include <sys/param.h> 2713498266Sopenharmony_ci#endif 2813498266Sopenharmony_ci#ifdef HAVE_NETINET_IN_H 2913498266Sopenharmony_ci#include <netinet/in.h> 3013498266Sopenharmony_ci#endif 3113498266Sopenharmony_ci#ifdef HAVE_ARPA_INET_H 3213498266Sopenharmony_ci#include <arpa/inet.h> 3313498266Sopenharmony_ci#endif 3413498266Sopenharmony_ci 3513498266Sopenharmony_ci#include "inet_pton.h" 3613498266Sopenharmony_ci 3713498266Sopenharmony_ci#define IN6ADDRSZ 16 3813498266Sopenharmony_ci#define INADDRSZ 4 3913498266Sopenharmony_ci#define INT16SZ 2 4013498266Sopenharmony_ci 4113498266Sopenharmony_ci/* 4213498266Sopenharmony_ci * If ENABLE_IPV6 is disabled, we still want to parse IPv6 addresses, so make 4313498266Sopenharmony_ci * sure we have _some_ value for AF_INET6 without polluting our fake value 4413498266Sopenharmony_ci * everywhere. 4513498266Sopenharmony_ci */ 4613498266Sopenharmony_ci#if !defined(ENABLE_IPV6) && !defined(AF_INET6) 4713498266Sopenharmony_ci#define AF_INET6 (AF_INET + 1) 4813498266Sopenharmony_ci#endif 4913498266Sopenharmony_ci 5013498266Sopenharmony_ci/* 5113498266Sopenharmony_ci * WARNING: Don't even consider trying to compile this on a system where 5213498266Sopenharmony_ci * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 5313498266Sopenharmony_ci */ 5413498266Sopenharmony_ci 5513498266Sopenharmony_cistatic int inet_pton4(const char *src, unsigned char *dst); 5613498266Sopenharmony_cistatic int inet_pton6(const char *src, unsigned char *dst); 5713498266Sopenharmony_ci 5813498266Sopenharmony_ci/* int 5913498266Sopenharmony_ci * inet_pton(af, src, dst) 6013498266Sopenharmony_ci * convert from presentation format (which usually means ASCII printable) 6113498266Sopenharmony_ci * to network format (which is usually some kind of binary format). 6213498266Sopenharmony_ci * return: 6313498266Sopenharmony_ci * 1 if the address was valid for the specified address family 6413498266Sopenharmony_ci * 0 if the address wasn't valid (`dst' is untouched in this case) 6513498266Sopenharmony_ci * -1 if some other error occurred (`dst' is untouched in this case, too) 6613498266Sopenharmony_ci * notice: 6713498266Sopenharmony_ci * On Windows we store the error in the thread errno, not 6813498266Sopenharmony_ci * in the winsock error code. This is to avoid losing the 6913498266Sopenharmony_ci * actual last winsock error. So when this function returns 7013498266Sopenharmony_ci * -1, check errno not SOCKERRNO. 7113498266Sopenharmony_ci * author: 7213498266Sopenharmony_ci * Paul Vixie, 1996. 7313498266Sopenharmony_ci */ 7413498266Sopenharmony_ciint 7513498266Sopenharmony_ciCurl_inet_pton(int af, const char *src, void *dst) 7613498266Sopenharmony_ci{ 7713498266Sopenharmony_ci switch(af) { 7813498266Sopenharmony_ci case AF_INET: 7913498266Sopenharmony_ci return (inet_pton4(src, (unsigned char *)dst)); 8013498266Sopenharmony_ci case AF_INET6: 8113498266Sopenharmony_ci return (inet_pton6(src, (unsigned char *)dst)); 8213498266Sopenharmony_ci default: 8313498266Sopenharmony_ci errno = EAFNOSUPPORT; 8413498266Sopenharmony_ci return (-1); 8513498266Sopenharmony_ci } 8613498266Sopenharmony_ci /* NOTREACHED */ 8713498266Sopenharmony_ci} 8813498266Sopenharmony_ci 8913498266Sopenharmony_ci/* int 9013498266Sopenharmony_ci * inet_pton4(src, dst) 9113498266Sopenharmony_ci * like inet_aton() but without all the hexadecimal and shorthand. 9213498266Sopenharmony_ci * return: 9313498266Sopenharmony_ci * 1 if `src' is a valid dotted quad, else 0. 9413498266Sopenharmony_ci * notice: 9513498266Sopenharmony_ci * does not touch `dst' unless it's returning 1. 9613498266Sopenharmony_ci * author: 9713498266Sopenharmony_ci * Paul Vixie, 1996. 9813498266Sopenharmony_ci */ 9913498266Sopenharmony_cistatic int 10013498266Sopenharmony_ciinet_pton4(const char *src, unsigned char *dst) 10113498266Sopenharmony_ci{ 10213498266Sopenharmony_ci static const char digits[] = "0123456789"; 10313498266Sopenharmony_ci int saw_digit, octets, ch; 10413498266Sopenharmony_ci unsigned char tmp[INADDRSZ], *tp; 10513498266Sopenharmony_ci 10613498266Sopenharmony_ci saw_digit = 0; 10713498266Sopenharmony_ci octets = 0; 10813498266Sopenharmony_ci tp = tmp; 10913498266Sopenharmony_ci *tp = 0; 11013498266Sopenharmony_ci while((ch = *src++) != '\0') { 11113498266Sopenharmony_ci const char *pch; 11213498266Sopenharmony_ci 11313498266Sopenharmony_ci pch = strchr(digits, ch); 11413498266Sopenharmony_ci if(pch) { 11513498266Sopenharmony_ci unsigned int val = (unsigned int)(*tp * 10) + 11613498266Sopenharmony_ci (unsigned int)(pch - digits); 11713498266Sopenharmony_ci 11813498266Sopenharmony_ci if(saw_digit && *tp == 0) 11913498266Sopenharmony_ci return (0); 12013498266Sopenharmony_ci if(val > 255) 12113498266Sopenharmony_ci return (0); 12213498266Sopenharmony_ci *tp = (unsigned char)val; 12313498266Sopenharmony_ci if(!saw_digit) { 12413498266Sopenharmony_ci if(++octets > 4) 12513498266Sopenharmony_ci return (0); 12613498266Sopenharmony_ci saw_digit = 1; 12713498266Sopenharmony_ci } 12813498266Sopenharmony_ci } 12913498266Sopenharmony_ci else if(ch == '.' && saw_digit) { 13013498266Sopenharmony_ci if(octets == 4) 13113498266Sopenharmony_ci return (0); 13213498266Sopenharmony_ci *++tp = 0; 13313498266Sopenharmony_ci saw_digit = 0; 13413498266Sopenharmony_ci } 13513498266Sopenharmony_ci else 13613498266Sopenharmony_ci return (0); 13713498266Sopenharmony_ci } 13813498266Sopenharmony_ci if(octets < 4) 13913498266Sopenharmony_ci return (0); 14013498266Sopenharmony_ci memcpy(dst, tmp, INADDRSZ); 14113498266Sopenharmony_ci return (1); 14213498266Sopenharmony_ci} 14313498266Sopenharmony_ci 14413498266Sopenharmony_ci/* int 14513498266Sopenharmony_ci * inet_pton6(src, dst) 14613498266Sopenharmony_ci * convert presentation level address to network order binary form. 14713498266Sopenharmony_ci * return: 14813498266Sopenharmony_ci * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 14913498266Sopenharmony_ci * notice: 15013498266Sopenharmony_ci * (1) does not touch `dst' unless it's returning 1. 15113498266Sopenharmony_ci * (2) :: in a full address is silently ignored. 15213498266Sopenharmony_ci * credit: 15313498266Sopenharmony_ci * inspired by Mark Andrews. 15413498266Sopenharmony_ci * author: 15513498266Sopenharmony_ci * Paul Vixie, 1996. 15613498266Sopenharmony_ci */ 15713498266Sopenharmony_cistatic int 15813498266Sopenharmony_ciinet_pton6(const char *src, unsigned char *dst) 15913498266Sopenharmony_ci{ 16013498266Sopenharmony_ci static const char xdigits_l[] = "0123456789abcdef", 16113498266Sopenharmony_ci xdigits_u[] = "0123456789ABCDEF"; 16213498266Sopenharmony_ci unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; 16313498266Sopenharmony_ci const char *curtok; 16413498266Sopenharmony_ci int ch, saw_xdigit; 16513498266Sopenharmony_ci size_t val; 16613498266Sopenharmony_ci 16713498266Sopenharmony_ci memset((tp = tmp), 0, IN6ADDRSZ); 16813498266Sopenharmony_ci endp = tp + IN6ADDRSZ; 16913498266Sopenharmony_ci colonp = NULL; 17013498266Sopenharmony_ci /* Leading :: requires some special handling. */ 17113498266Sopenharmony_ci if(*src == ':') 17213498266Sopenharmony_ci if(*++src != ':') 17313498266Sopenharmony_ci return (0); 17413498266Sopenharmony_ci curtok = src; 17513498266Sopenharmony_ci saw_xdigit = 0; 17613498266Sopenharmony_ci val = 0; 17713498266Sopenharmony_ci while((ch = *src++) != '\0') { 17813498266Sopenharmony_ci const char *xdigits; 17913498266Sopenharmony_ci const char *pch; 18013498266Sopenharmony_ci 18113498266Sopenharmony_ci pch = strchr((xdigits = xdigits_l), ch); 18213498266Sopenharmony_ci if(!pch) 18313498266Sopenharmony_ci pch = strchr((xdigits = xdigits_u), ch); 18413498266Sopenharmony_ci if(pch) { 18513498266Sopenharmony_ci val <<= 4; 18613498266Sopenharmony_ci val |= (pch - xdigits); 18713498266Sopenharmony_ci if(++saw_xdigit > 4) 18813498266Sopenharmony_ci return (0); 18913498266Sopenharmony_ci continue; 19013498266Sopenharmony_ci } 19113498266Sopenharmony_ci if(ch == ':') { 19213498266Sopenharmony_ci curtok = src; 19313498266Sopenharmony_ci if(!saw_xdigit) { 19413498266Sopenharmony_ci if(colonp) 19513498266Sopenharmony_ci return (0); 19613498266Sopenharmony_ci colonp = tp; 19713498266Sopenharmony_ci continue; 19813498266Sopenharmony_ci } 19913498266Sopenharmony_ci if(tp + INT16SZ > endp) 20013498266Sopenharmony_ci return (0); 20113498266Sopenharmony_ci *tp++ = (unsigned char) ((val >> 8) & 0xff); 20213498266Sopenharmony_ci *tp++ = (unsigned char) (val & 0xff); 20313498266Sopenharmony_ci saw_xdigit = 0; 20413498266Sopenharmony_ci val = 0; 20513498266Sopenharmony_ci continue; 20613498266Sopenharmony_ci } 20713498266Sopenharmony_ci if(ch == '.' && ((tp + INADDRSZ) <= endp) && 20813498266Sopenharmony_ci inet_pton4(curtok, tp) > 0) { 20913498266Sopenharmony_ci tp += INADDRSZ; 21013498266Sopenharmony_ci saw_xdigit = 0; 21113498266Sopenharmony_ci break; /* '\0' was seen by inet_pton4(). */ 21213498266Sopenharmony_ci } 21313498266Sopenharmony_ci return (0); 21413498266Sopenharmony_ci } 21513498266Sopenharmony_ci if(saw_xdigit) { 21613498266Sopenharmony_ci if(tp + INT16SZ > endp) 21713498266Sopenharmony_ci return (0); 21813498266Sopenharmony_ci *tp++ = (unsigned char) ((val >> 8) & 0xff); 21913498266Sopenharmony_ci *tp++ = (unsigned char) (val & 0xff); 22013498266Sopenharmony_ci } 22113498266Sopenharmony_ci if(colonp) { 22213498266Sopenharmony_ci /* 22313498266Sopenharmony_ci * Since some memmove()'s erroneously fail to handle 22413498266Sopenharmony_ci * overlapping regions, we'll do the shift by hand. 22513498266Sopenharmony_ci */ 22613498266Sopenharmony_ci const ssize_t n = tp - colonp; 22713498266Sopenharmony_ci ssize_t i; 22813498266Sopenharmony_ci 22913498266Sopenharmony_ci if(tp == endp) 23013498266Sopenharmony_ci return (0); 23113498266Sopenharmony_ci for(i = 1; i <= n; i++) { 23213498266Sopenharmony_ci *(endp - i) = *(colonp + n - i); 23313498266Sopenharmony_ci *(colonp + n - i) = 0; 23413498266Sopenharmony_ci } 23513498266Sopenharmony_ci tp = endp; 23613498266Sopenharmony_ci } 23713498266Sopenharmony_ci if(tp != endp) 23813498266Sopenharmony_ci return (0); 23913498266Sopenharmony_ci memcpy(dst, tmp, IN6ADDRSZ); 24013498266Sopenharmony_ci return (1); 24113498266Sopenharmony_ci} 24213498266Sopenharmony_ci 24313498266Sopenharmony_ci#endif /* HAVE_INET_PTON */ 244