1156952Sume/* 2156952Sume * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3156952Sume * Copyright (c) 1996,1999 by Internet Software Consortium. 4156952Sume * 5156952Sume * Permission to use, copy, modify, and distribute this software for any 6156952Sume * purpose with or without fee is hereby granted, provided that the above 7156952Sume * copyright notice and this permission notice appear in all copies. 8156952Sume * 9156952Sume * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10156952Sume * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11156952Sume * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12156952Sume * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13156952Sume * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14156952Sume * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15156952Sume * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16156952Sume */ 17156952Sume 18156952Sume#if defined(LIBC_SCCS) && !defined(lint) 19170244Sumestatic const char rcsid[] = "$Id: inet_pton.c,v 1.3.18.2 2005/07/28 07:38:07 marka Exp $"; 20156952Sume#endif /* LIBC_SCCS and not lint */ 21156956Sume#include <sys/cdefs.h> 22156956Sume__FBSDID("$FreeBSD$"); 23156952Sume 24156952Sume#include "port_before.h" 25156952Sume#include <sys/param.h> 26156952Sume#include <sys/types.h> 27156952Sume#include <sys/socket.h> 28156952Sume#include <netinet/in.h> 29156952Sume#include <arpa/inet.h> 30156952Sume#include <arpa/nameser.h> 31156952Sume#include <string.h> 32156952Sume#include <errno.h> 33156952Sume#include "port_after.h" 34156952Sume 35170244Sume/*% 36156952Sume * WARNING: Don't even consider trying to compile this on a system where 37156952Sume * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 38156952Sume */ 39156952Sume 40156956Sumestatic int inet_pton4(const char *src, u_char *dst); 41156956Sumestatic int inet_pton6(const char *src, u_char *dst); 42156952Sume 43156952Sume/* int 44156952Sume * inet_pton(af, src, dst) 45156952Sume * convert from presentation format (which usually means ASCII printable) 46156952Sume * to network format (which is usually some kind of binary format). 47156952Sume * return: 48156952Sume * 1 if the address was valid for the specified address family 49156952Sume * 0 if the address wasn't valid (`dst' is untouched in this case) 50156952Sume * -1 if some other error occurred (`dst' is untouched in this case, too) 51156952Sume * author: 52156952Sume * Paul Vixie, 1996. 53156952Sume */ 54156952Sumeint 55156956Sumeinet_pton(int af, const char * __restrict src, void * __restrict dst) 56156952Sume{ 57156952Sume switch (af) { 58156952Sume case AF_INET: 59156952Sume return (inet_pton4(src, dst)); 60156952Sume case AF_INET6: 61156952Sume return (inet_pton6(src, dst)); 62156952Sume default: 63156952Sume errno = EAFNOSUPPORT; 64156952Sume return (-1); 65156952Sume } 66156952Sume /* NOTREACHED */ 67156952Sume} 68156952Sume 69156952Sume/* int 70156952Sume * inet_pton4(src, dst) 71156952Sume * like inet_aton() but without all the hexadecimal and shorthand. 72156952Sume * return: 73156952Sume * 1 if `src' is a valid dotted quad, else 0. 74156952Sume * notice: 75156952Sume * does not touch `dst' unless it's returning 1. 76156952Sume * author: 77156952Sume * Paul Vixie, 1996. 78156952Sume */ 79156952Sumestatic int 80156956Sumeinet_pton4(const char *src, u_char *dst) 81156952Sume{ 82156952Sume static const char digits[] = "0123456789"; 83156952Sume int saw_digit, octets, ch; 84156952Sume u_char tmp[NS_INADDRSZ], *tp; 85156952Sume 86156952Sume saw_digit = 0; 87156952Sume octets = 0; 88156952Sume *(tp = tmp) = 0; 89156952Sume while ((ch = *src++) != '\0') { 90156952Sume const char *pch; 91156952Sume 92156952Sume if ((pch = strchr(digits, ch)) != NULL) { 93156952Sume u_int new = *tp * 10 + (pch - digits); 94156952Sume 95156952Sume if (saw_digit && *tp == 0) 96156952Sume return (0); 97156952Sume if (new > 255) 98156952Sume return (0); 99156952Sume *tp = new; 100156952Sume if (!saw_digit) { 101156952Sume if (++octets > 4) 102156952Sume return (0); 103156952Sume saw_digit = 1; 104156952Sume } 105156952Sume } else if (ch == '.' && saw_digit) { 106156952Sume if (octets == 4) 107156952Sume return (0); 108156952Sume *++tp = 0; 109156952Sume saw_digit = 0; 110156952Sume } else 111156952Sume return (0); 112156952Sume } 113156952Sume if (octets < 4) 114156952Sume return (0); 115156952Sume memcpy(dst, tmp, NS_INADDRSZ); 116156952Sume return (1); 117156952Sume} 118156952Sume 119156952Sume/* int 120156952Sume * inet_pton6(src, dst) 121156952Sume * convert presentation level address to network order binary form. 122156952Sume * return: 123156952Sume * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 124156952Sume * notice: 125156952Sume * (1) does not touch `dst' unless it's returning 1. 126156952Sume * (2) :: in a full address is silently ignored. 127156952Sume * credit: 128156952Sume * inspired by Mark Andrews. 129156952Sume * author: 130156952Sume * Paul Vixie, 1996. 131156952Sume */ 132156952Sumestatic int 133156956Sumeinet_pton6(const char *src, u_char *dst) 134156952Sume{ 135156952Sume static const char xdigits_l[] = "0123456789abcdef", 136156952Sume xdigits_u[] = "0123456789ABCDEF"; 137156952Sume u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; 138156952Sume const char *xdigits, *curtok; 139156952Sume int ch, seen_xdigits; 140156952Sume u_int val; 141156952Sume 142156952Sume memset((tp = tmp), '\0', NS_IN6ADDRSZ); 143156952Sume endp = tp + NS_IN6ADDRSZ; 144156952Sume colonp = NULL; 145156952Sume /* Leading :: requires some special handling. */ 146156952Sume if (*src == ':') 147156952Sume if (*++src != ':') 148156952Sume return (0); 149156952Sume curtok = src; 150156952Sume seen_xdigits = 0; 151156952Sume val = 0; 152156952Sume while ((ch = *src++) != '\0') { 153156952Sume const char *pch; 154156952Sume 155156952Sume if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 156156952Sume pch = strchr((xdigits = xdigits_u), ch); 157156952Sume if (pch != NULL) { 158156952Sume val <<= 4; 159156952Sume val |= (pch - xdigits); 160156952Sume if (++seen_xdigits > 4) 161156952Sume return (0); 162156952Sume continue; 163156952Sume } 164156952Sume if (ch == ':') { 165156952Sume curtok = src; 166156952Sume if (!seen_xdigits) { 167156952Sume if (colonp) 168156952Sume return (0); 169156952Sume colonp = tp; 170156952Sume continue; 171156952Sume } else if (*src == '\0') { 172156952Sume return (0); 173156952Sume } 174156952Sume if (tp + NS_INT16SZ > endp) 175156952Sume return (0); 176156952Sume *tp++ = (u_char) (val >> 8) & 0xff; 177156952Sume *tp++ = (u_char) val & 0xff; 178156952Sume seen_xdigits = 0; 179156952Sume val = 0; 180156952Sume continue; 181156952Sume } 182156952Sume if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && 183156952Sume inet_pton4(curtok, tp) > 0) { 184156952Sume tp += NS_INADDRSZ; 185156952Sume seen_xdigits = 0; 186170244Sume break; /*%< '\\0' was seen by inet_pton4(). */ 187156952Sume } 188156952Sume return (0); 189156952Sume } 190156952Sume if (seen_xdigits) { 191156952Sume if (tp + NS_INT16SZ > endp) 192156952Sume return (0); 193156952Sume *tp++ = (u_char) (val >> 8) & 0xff; 194156952Sume *tp++ = (u_char) val & 0xff; 195156952Sume } 196156952Sume if (colonp != NULL) { 197156952Sume /* 198156952Sume * Since some memmove()'s erroneously fail to handle 199156952Sume * overlapping regions, we'll do the shift by hand. 200156952Sume */ 201156952Sume const int n = tp - colonp; 202156952Sume int i; 203156952Sume 204156952Sume if (tp == endp) 205156952Sume return (0); 206156952Sume for (i = 1; i <= n; i++) { 207156952Sume endp[- i] = colonp[n - i]; 208156952Sume colonp[n - i] = 0; 209156952Sume } 210156952Sume tp = endp; 211156952Sume } 212156952Sume if (tp != endp) 213156952Sume return (0); 214156952Sume memcpy(dst, tmp, NS_IN6ADDRSZ); 215156952Sume return (1); 216156952Sume} 217156956Sume 218156956Sume/* 219156956Sume * Weak aliases for applications that use certain private entry points, 220156956Sume * and fail to include <arpa/inet.h>. 221156956Sume */ 222156956Sume#undef inet_pton 223156956Sume__weak_reference(__inet_pton, inet_pton); 224170244Sume 225170244Sume/*! \file */ 226