118099Spst/* 218099Spst * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 318099Spst * Copyright (c) 1996,1999 by Internet Software Consortium. 4151497Sru * 5151497Sru * Permission to use, copy, modify, and distribute this software for any 618099Spst * purpose with or without fee is hereby granted, provided that the above 718099Spst * copyright notice and this permission notice appear in all copies. 818099Spst * 918099Spst * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 1018099Spst * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1118099Spst * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 1218099Spst * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1318099Spst * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1418099Spst * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 1518099Spst * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1618099Spst */ 1718099Spst 1818099Spst#include <sys/param.h> 1918099Spst#include <sys/socket.h> 2018099Spst#include <sys/systm.h> 2118099Spst 2218099Spst#include <netinet/in.h> 2318099Spst 2418099Spst/*% 2518099Spst * WARNING: Don't even consider trying to compile this on a system where 2618099Spst * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 2718099Spst */ 2818099Spst 2918099Spststatic int inet_pton4(const char *src, u_char *dst); 3018099Spststatic int inet_pton6(const char *src, u_char *dst); 3118099Spst 3218099Spst/* int 3318099Spst * inet_pton(af, src, dst) 3418099Spst * convert from presentation format (which usually means ASCII printable) 3518099Spst * to network format (which is usually some kind of binary format). 3618099Spst * return: 3718099Spst * 1 if the address was valid for the specified address family 3818099Spst * 0 if the address wasn't valid (`dst' is untouched in this case) 3918099Spst * -1 if some other error occurred (`dst' is untouched in this case, too) 4018099Spst * author: 4118099Spst * Paul Vixie, 1996. 4218099Spst */ 4318099Spstint 4418099Spstinet_pton(int af, const char *src, void *dst) 4518099Spst{ 4618099Spst switch (af) { 4718099Spst case AF_INET: 4818099Spst return (inet_pton4(src, dst)); 4918099Spst case AF_INET6: 5018099Spst return (inet_pton6(src, dst)); 5118099Spst default: 5218099Spst return (-1); 5318099Spst } 5418099Spst /* NOTREACHED */ 5518099Spst} 5618099Spst 5718099Spst/* int 5818099Spst * inet_pton4(src, dst) 5918099Spst * like inet_aton() but without all the hexadecimal and shorthand. 6018099Spst * return: 6118099Spst * 1 if `src' is a valid dotted quad, else 0. 6218099Spst * notice: 6318099Spst * does not touch `dst' unless it's returning 1. 6418099Spst * author: 6518099Spst * Paul Vixie, 1996. 6618099Spst */ 6718099Spststatic int 6818099Spstinet_pton4(const char *src, u_char *dst) 6918099Spst{ 7018099Spst static const char digits[] = "0123456789"; 7118099Spst int saw_digit, octets, ch; 7218099Spst#define NS_INADDRSZ 4 7318099Spst u_char tmp[NS_INADDRSZ], *tp; 7418099Spst 7518099Spst saw_digit = 0; 7618099Spst octets = 0; 7718099Spst *(tp = tmp) = 0; 7818099Spst while ((ch = *src++) != '\0') { 7918099Spst const char *pch; 8018099Spst 8118099Spst if ((pch = strchr(digits, ch)) != NULL) { 8218099Spst u_int new = *tp * 10 + (pch - digits); 8318099Spst 8418099Spst if (saw_digit && *tp == 0) 8518099Spst return (0); 8618099Spst if (new > 255) 8718099Spst return (0); 8818099Spst *tp = new; 8918099Spst if (!saw_digit) { 9018099Spst if (++octets > 4) 9118099Spst return (0); 9218099Spst saw_digit = 1; 9318099Spst } 9418099Spst } else if (ch == '.' && saw_digit) { 9518099Spst if (octets == 4) 9618099Spst return (0); 9718099Spst *++tp = 0; 9818099Spst saw_digit = 0; 9918099Spst } else 10018099Spst return (0); 10118099Spst } 10218099Spst if (octets < 4) 10318099Spst return (0); 10418099Spst memcpy(dst, tmp, NS_INADDRSZ); 10518099Spst return (1); 10618099Spst} 10718099Spst 10818099Spst/* int 10918099Spst * inet_pton6(src, dst) 11018099Spst * convert presentation level address to network order binary form. 11118099Spst * return: 11218099Spst * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 11318099Spst * notice: 11418099Spst * (1) does not touch `dst' unless it's returning 1. 11518099Spst * (2) :: in a full address is silently ignored. 11618099Spst * credit: 11718099Spst * inspired by Mark Andrews. 11818099Spst * author: 11918099Spst * Paul Vixie, 1996. 12018099Spst */ 12118099Spststatic int 12218099Spstinet_pton6(const char *src, u_char *dst) 12318099Spst{ 12418099Spst static const char xdigits_l[] = "0123456789abcdef", 12518099Spst xdigits_u[] = "0123456789ABCDEF"; 12618099Spst#define NS_IN6ADDRSZ 16 12718099Spst#define NS_INT16SZ 2 12818099Spst u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; 12918099Spst const char *xdigits, *curtok; 13018099Spst int ch, seen_xdigits; 13118099Spst u_int val; 13218099Spst 13318099Spst memset((tp = tmp), '\0', NS_IN6ADDRSZ); 13418099Spst endp = tp + NS_IN6ADDRSZ; 13518099Spst colonp = NULL; 13618099Spst /* Leading :: requires some special handling. */ 13718099Spst if (*src == ':') 13818099Spst if (*++src != ':') 13918099Spst return (0); 14018099Spst curtok = src; 14118099Spst seen_xdigits = 0; 14218099Spst val = 0; 14318099Spst while ((ch = *src++) != '\0') { 14418099Spst const char *pch; 14518099Spst 14618099Spst if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 14718099Spst pch = strchr((xdigits = xdigits_u), ch); 14818099Spst if (pch != NULL) { 14918099Spst val <<= 4; 15018099Spst val |= (pch - xdigits); 15118099Spst if (++seen_xdigits > 4) 15218099Spst return (0); 15318099Spst continue; 15418099Spst } 15518099Spst if (ch == ':') { 15618099Spst curtok = src; 15718099Spst if (!seen_xdigits) { 15818099Spst if (colonp) 15918099Spst return (0); 16018099Spst colonp = tp; 16118099Spst continue; 16218099Spst } else if (*src == '\0') { 16318099Spst return (0); 16418099Spst } 16518099Spst if (tp + NS_INT16SZ > endp) 16618099Spst return (0); 16718099Spst *tp++ = (u_char) (val >> 8) & 0xff; 16818099Spst *tp++ = (u_char) val & 0xff; 16918099Spst seen_xdigits = 0; 17018099Spst val = 0; 17118099Spst continue; 17218099Spst } 17318099Spst if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && 17418099Spst inet_pton4(curtok, tp) > 0) { 17518099Spst tp += NS_INADDRSZ; 17618099Spst seen_xdigits = 0; 17718099Spst break; /*%< '\\0' was seen by inet_pton4(). */ 17818099Spst } 17918099Spst return (0); 18018099Spst } 18118099Spst if (seen_xdigits) { 18218099Spst if (tp + NS_INT16SZ > endp) 18318099Spst return (0); 18418099Spst *tp++ = (u_char) (val >> 8) & 0xff; 18518099Spst *tp++ = (u_char) val & 0xff; 18618099Spst } 18718099Spst if (colonp != NULL) { 18818099Spst /* 18918099Spst * Since some memmove()'s erroneously fail to handle 19018099Spst * overlapping regions, we'll do the shift by hand. 19118099Spst */ 19218099Spst const int n = tp - colonp; 19318099Spst int i; 19418099Spst 19518099Spst if (tp == endp) 19618099Spst return (0); 19718099Spst for (i = 1; i <= n; i++) { 19818099Spst endp[- i] = colonp[n - i]; 19918099Spst colonp[n - i] = 0; 20018099Spst } 20118099Spst tp = endp; 20218099Spst } 20318099Spst if (tp != endp) 20418099Spst return (0); 20518099Spst memcpy(dst, tmp, NS_IN6ADDRSZ); 20618099Spst return (1); 20718099Spst} 20818099Spst 20918099Spst/*! \file */ 21018099Spst