/*1* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")2* Copyright (c) 1996,1999 by Internet Software Consortium.3*4* Permission to use, copy, modify, and distribute this software for any5* purpose with or without fee is hereby granted, provided that the above6* copyright notice and this permission notice appear in all copies.7*8* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES9* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR11* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN13* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT14* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15*/1617#include <sys/param.h>18#include <sys/socket.h>19#include <sys/systm.h>2021#include <netinet/in.h>2223/*%24* WARNING: Don't even consider trying to compile this on a system where25* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.26*/2728static int inet_pton4(const char *src, u_char *dst);29static int inet_pton6(const char *src, u_char *dst);3031/* int32* inet_pton(af, src, dst)33* convert from presentation format (which usually means ASCII printable)34* to network format (which is usually some kind of binary format).35* return:36* 1 if the address was valid for the specified address family37* 0 if the address wasn't valid (`dst' is untouched in this case)38* -1 if some other error occurred (`dst' is untouched in this case, too)39* author:40* Paul Vixie, 1996.41*/42int43inet_pton(int af, const char *src, void *dst)44{45switch (af) {46case AF_INET:47return (inet_pton4(src, dst));48case AF_INET6:49return (inet_pton6(src, dst));50default:51return (-1);52}53/* NOTREACHED */54}5556/* int57* inet_pton4(src, dst)58* like inet_aton() but without all the hexadecimal and shorthand.59* return:60* 1 if `src' is a valid dotted quad, else 0.61* notice:62* does not touch `dst' unless it's returning 1.63* author:64* Paul Vixie, 1996.65*/66static int67inet_pton4(const char *src, u_char *dst)68{69static const char digits[] = "0123456789";70int saw_digit, octets, ch;71#define NS_INADDRSZ 472u_char tmp[NS_INADDRSZ], *tp;7374saw_digit = 0;75octets = 0;76*(tp = tmp) = 0;77while ((ch = *src++) != '\0') {78const char *pch;7980if ((pch = strchr(digits, ch)) != NULL) {81u_int new = *tp * 10 + (pch - digits);8283if (saw_digit && *tp == 0)84return (0);85if (new > 255)86return (0);87*tp = new;88if (!saw_digit) {89if (++octets > 4)90return (0);91saw_digit = 1;92}93} else if (ch == '.' && saw_digit) {94if (octets == 4)95return (0);96*++tp = 0;97saw_digit = 0;98} else99return (0);100}101if (octets < 4)102return (0);103memcpy(dst, tmp, NS_INADDRSZ);104return (1);105}106107/* int108* inet_pton6(src, dst)109* convert presentation level address to network order binary form.110* return:111* 1 if `src' is a valid [RFC1884 2.2] address, else 0.112* notice:113* (1) does not touch `dst' unless it's returning 1.114* (2) :: in a full address is silently ignored.115* credit:116* inspired by Mark Andrews.117* author:118* Paul Vixie, 1996.119*/120static int121inet_pton6(const char *src, u_char *dst)122{123static const char xdigits_l[] = "0123456789abcdef",124xdigits_u[] = "0123456789ABCDEF";125#define NS_IN6ADDRSZ 16126#define NS_INT16SZ 2127u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;128const char *xdigits, *curtok;129int ch, seen_xdigits;130u_int val;131132memset((tp = tmp), '\0', NS_IN6ADDRSZ);133endp = tp + NS_IN6ADDRSZ;134colonp = NULL;135/* Leading :: requires some special handling. */136if (*src == ':')137if (*++src != ':')138return (0);139curtok = src;140seen_xdigits = 0;141val = 0;142while ((ch = *src++) != '\0') {143const char *pch;144145if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)146pch = strchr((xdigits = xdigits_u), ch);147if (pch != NULL) {148val <<= 4;149val |= (pch - xdigits);150if (++seen_xdigits > 4)151return (0);152continue;153}154if (ch == ':') {155curtok = src;156if (!seen_xdigits) {157if (colonp)158return (0);159colonp = tp;160continue;161} else if (*src == '\0') {162return (0);163}164if (tp + NS_INT16SZ > endp)165return (0);166*tp++ = (u_char) (val >> 8) & 0xff;167*tp++ = (u_char) val & 0xff;168seen_xdigits = 0;169val = 0;170continue;171}172if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&173inet_pton4(curtok, tp) > 0) {174tp += NS_INADDRSZ;175seen_xdigits = 0;176break; /*%< '\\0' was seen by inet_pton4(). */177}178return (0);179}180if (seen_xdigits) {181if (tp + NS_INT16SZ > endp)182return (0);183*tp++ = (u_char) (val >> 8) & 0xff;184*tp++ = (u_char) val & 0xff;185}186if (colonp != NULL) {187/*188* Since some memmove()'s erroneously fail to handle189* overlapping regions, we'll do the shift by hand.190*/191const int n = tp - colonp;192int i;193194if (tp == endp)195return (0);196for (i = 1; i <= n; i++) {197endp[- i] = colonp[n - i];198colonp[n - i] = 0;199}200tp = endp;201}202if (tp != endp)203return (0);204memcpy(dst, tmp, NS_IN6ADDRSZ);205return (1);206}207208/*! \file */209210211