/* This is from the BIND 4.9.4 release, modified to compile by itself */ /* Copyright (c) 1996 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM 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. */ #include "setup.h" #ifndef HAVE_INET_PTON #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_ARPA_INET_H #include #endif #include #include #include "inet_pton.h" #define IN6ADDRSZ 16 #define INADDRSZ 4 #define INT16SZ 2 #ifdef WIN32 #define EAFNOSUPPORT WSAEAFNOSUPPORT #endif /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ static int inet_pton4( const char *src, unsigned char *dst ); #ifdef ENABLE_IPV6 static int inet_pton6( const char *src, unsigned char *dst ); #endif /* int * inet_pton(af, src, dst) * convert from presentation format (which usually means ASCII printable) * to network format (which is usually some kind of binary format). * return: * 1 if the address was valid for the specified address family * 0 if the address wasn't valid (`dst' is untouched in this case) * -1 if some other error occurred (`dst' is untouched in this case, too) * author: * Paul Vixie, 1996. */ int Curl_inet_pton( int af, const char *src, void *dst ) { switch ( af ) { case AF_INET: return ( inet_pton4( src, dst ) ); #ifdef ENABLE_IPV6 #ifndef AF_INET6 #define AF_INET6 AF_MAX + 1 /* just to let this compile */ #endif case AF_INET6: return ( inet_pton6( src, dst ) ); #endif default: errno = EAFNOSUPPORT; return ( -1 ); } /* NOTREACHED */ } /* int * inet_pton4(src, dst) * like inet_aton() but without all the hexadecimal and shorthand. * return: * 1 if `src' is a valid dotted quad, else 0. * notice: * does not touch `dst' unless it's returning 1. * author: * Paul Vixie, 1996. */ static int inet_pton4( const char *src, unsigned char *dst ) { static const char digits[] = "0123456789"; int saw_digit, octets, ch; unsigned char tmp[INADDRSZ], *tp; saw_digit = 0; octets = 0; tp = tmp; *tp = 0; while ( ( ch = *src++ ) != '\0' ) { const char *pch; if ( ( pch = strchr( digits, ch ) ) != NULL ) { u_int new = *tp * 10 + ( pch - digits ); if ( new > 255 ) { return ( 0 ); } *tp = new; if ( !saw_digit ) { if ( ++octets > 4 ) { return ( 0 ); } saw_digit = 1; } } else if ( ch == '.' && saw_digit ) { if ( octets == 4 ) { return ( 0 ); } *++tp = 0; saw_digit = 0; } else { return ( 0 ); } } if ( octets < 4 ) { return ( 0 ); } /* bcopy(tmp, dst, INADDRSZ); */ memcpy( dst, tmp, INADDRSZ ); return ( 1 ); } #ifdef ENABLE_IPV6 /* int * inet_pton6(src, dst) * convert presentation level address to network order binary form. * return: * 1 if `src' is a valid [RFC1884 2.2] address, else 0. * notice: * (1) does not touch `dst' unless it's returning 1. * (2) :: in a full address is silently ignored. * credit: * inspired by Mark Andrews. * author: * Paul Vixie, 1996. */ static int inet_pton6( const char *src, unsigned char *dst ) { static const char xdigits_l[] = "0123456789abcdef", xdigits_u[] = "0123456789ABCDEF"; unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; const char *xdigits, *curtok; int ch, saw_xdigit; u_int val; memset( ( tp = tmp ), 0, IN6ADDRSZ ); endp = tp + IN6ADDRSZ; colonp = NULL; /* Leading :: requires some special handling. */ if ( *src == ':' ) { if ( *++src != ':' ) { return ( 0 ); } } curtok = src; saw_xdigit = 0; val = 0; while ( ( ch = *src++ ) != '\0' ) { const char *pch; if ( ( pch = strchr( ( xdigits = xdigits_l ), ch ) ) == NULL ) { pch = strchr( ( xdigits = xdigits_u ), ch ); } if ( pch != NULL ) { val <<= 4; val |= ( pch - xdigits ); if ( val > 0xffff ) { return ( 0 ); } saw_xdigit = 1; continue; } if ( ch == ':' ) { curtok = src; if ( !saw_xdigit ) { if ( colonp ) { return ( 0 ); } colonp = tp; continue; } if ( tp + INT16SZ > endp ) { return ( 0 ); } *tp++ = ( unsigned char )( val >> 8 ) & 0xff; *tp++ = (unsigned char) val & 0xff; saw_xdigit = 0; val = 0; continue; } if ( ch == '.' && ( ( tp + INADDRSZ ) <= endp ) && inet_pton4( curtok, tp ) > 0 ) { tp += INADDRSZ; saw_xdigit = 0; break; /* '\0' was seen by inet_pton4(). */ } return ( 0 ); } if ( saw_xdigit ) { if ( tp + INT16SZ > endp ) { return ( 0 ); } *tp++ = ( unsigned char )( val >> 8 ) & 0xff; *tp++ = (unsigned char) val & 0xff; } if ( colonp != NULL ) { /* * Since some memmove()'s erroneously fail to handle * overlapping regions, we'll do the shift by hand. */ const int n = tp - colonp; int i; for ( i = 1; i <= n; i++ ) { endp[-i] = colonp[n - i]; colonp[n - i] = 0; } tp = endp; } if ( tp != endp ) { return ( 0 ); } /* bcopy(tmp, dst, IN6ADDRSZ); */ memcpy( dst, tmp, IN6ADDRSZ ); return ( 1 ); } #endif /* ENABLE_IPV6 */ #endif /* HAVE_INET_PTON */