/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")4* Copyright (c) 1996,1999 by Internet Software Consortium.5*6* Permission to use, copy, modify, and distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES11* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF12* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR13* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES14* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN15* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT16* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.17*/1819#include "port_before.h"20#include <sys/param.h>21#include <sys/socket.h>22#include <netinet/in.h>23#include <arpa/inet.h>24#include <arpa/nameser.h>25#include <string.h>26#include <errno.h>27#include "port_after.h"2829/*%30* WARNING: Don't even consider trying to compile this on a system where31* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.32*/3334static int inet_pton4(const char *src, u_char *dst);35static int inet_pton6(const char *src, u_char *dst);3637/* int38* inet_pton(af, src, dst)39* convert from presentation format (which usually means ASCII printable)40* to network format (which is usually some kind of binary format).41* return:42* 1 if the address was valid for the specified address family43* 0 if the address wasn't valid (`dst' is untouched in this case)44* -1 if some other error occurred (`dst' is untouched in this case, too)45* author:46* Paul Vixie, 1996.47*/48int49inet_pton(int af, const char * __restrict src, void * __restrict dst)50{51switch (af) {52case AF_INET:53return (inet_pton4(src, dst));54case AF_INET6:55return (inet_pton6(src, dst));56default:57errno = EAFNOSUPPORT;58return (-1);59}60/* NOTREACHED */61}6263/* int64* inet_pton4(src, dst)65* like inet_aton() but without all the hexadecimal and shorthand.66* return:67* 1 if `src' is a valid dotted quad, else 0.68* notice:69* does not touch `dst' unless it's returning 1.70* author:71* Paul Vixie, 1996.72*/73static int74inet_pton4(const char *src, u_char *dst)75{76static const char digits[] = "0123456789";77int saw_digit, octets, ch;78u_char tmp[NS_INADDRSZ], *tp;7980saw_digit = 0;81octets = 0;82*(tp = tmp) = 0;83while ((ch = *src++) != '\0') {84const char *pch;8586if ((pch = strchr(digits, ch)) != NULL) {87u_int new = *tp * 10 + (pch - digits);8889if (saw_digit && *tp == 0)90return (0);91if (new > 255)92return (0);93*tp = new;94if (!saw_digit) {95if (++octets > 4)96return (0);97saw_digit = 1;98}99} else if (ch == '.' && saw_digit) {100if (octets == 4)101return (0);102*++tp = 0;103saw_digit = 0;104} else105return (0);106}107if (octets < 4)108return (0);109memcpy(dst, tmp, NS_INADDRSZ);110return (1);111}112113/* int114* inet_pton6(src, dst)115* convert presentation level address to network order binary form.116* return:117* 1 if `src' is a valid [RFC1884 2.2] address, else 0.118* notice:119* (1) does not touch `dst' unless it's returning 1.120* (2) :: in a full address is silently ignored.121* credit:122* inspired by Mark Andrews.123* author:124* Paul Vixie, 1996.125*/126static int127inet_pton6(const char *src, u_char *dst)128{129static const char xdigits_l[] = "0123456789abcdef",130xdigits_u[] = "0123456789ABCDEF";131u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;132const char *xdigits, *curtok;133int ch, seen_xdigits;134u_int val;135136memset((tp = tmp), '\0', NS_IN6ADDRSZ);137endp = tp + NS_IN6ADDRSZ;138colonp = NULL;139/* Leading :: requires some special handling. */140if (*src == ':')141if (*++src != ':')142return (0);143curtok = src;144seen_xdigits = 0;145val = 0;146while ((ch = *src++) != '\0') {147const char *pch;148149if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)150pch = strchr((xdigits = xdigits_u), ch);151if (pch != NULL) {152val <<= 4;153val |= (pch - xdigits);154if (++seen_xdigits > 4)155return (0);156continue;157}158if (ch == ':') {159curtok = src;160if (!seen_xdigits) {161if (colonp)162return (0);163colonp = tp;164continue;165} else if (*src == '\0') {166return (0);167}168if (tp + NS_INT16SZ > endp)169return (0);170*tp++ = (u_char) (val >> 8) & 0xff;171*tp++ = (u_char) val & 0xff;172seen_xdigits = 0;173val = 0;174continue;175}176if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&177inet_pton4(curtok, tp) > 0) {178tp += NS_INADDRSZ;179seen_xdigits = 0;180break; /*%< '\\0' was seen by inet_pton4(). */181}182return (0);183}184if (seen_xdigits) {185if (tp + NS_INT16SZ > endp)186return (0);187*tp++ = (u_char) (val >> 8) & 0xff;188*tp++ = (u_char) val & 0xff;189}190if (colonp != NULL) {191/*192* Since some memmove()'s erroneously fail to handle193* overlapping regions, we'll do the shift by hand.194*/195const int n = tp - colonp;196int i;197198if (tp == endp)199return (0);200for (i = 1; i <= n; i++) {201endp[- i] = colonp[n - i];202colonp[n - i] = 0;203}204tp = endp;205}206if (tp != endp)207return (0);208memcpy(dst, tmp, NS_IN6ADDRSZ);209return (1);210}211212/*213* Weak aliases for applications that use certain private entry points,214* and fail to include <arpa/inet.h>.215*/216#undef inet_pton217__weak_reference(__inet_pton, inet_pton);218219/*! \file */220221222