1/* $NetBSD: inet_pton.c,v 1.1.1.1 2009/04/12 15:33:35 christos Exp $ */ 2 3/* 4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (c) 1996,1999 by Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#if defined(LIBC_SCCS) && !defined(lint) 21static const char rcsid[] = "Id: inet_pton.c,v 1.5 2005/07/28 06:51:47 marka Exp"; 22#endif /* LIBC_SCCS and not lint */ 23 24#include "port_before.h" 25#include <sys/param.h> 26#include <sys/types.h> 27#include <sys/socket.h> 28#include <netinet/in.h> 29#include <arpa/inet.h> 30#include <arpa/nameser.h> 31#include <string.h> 32#include <errno.h> 33#include "port_after.h" 34 35/*% 36 * WARNING: Don't even consider trying to compile this on a system where 37 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 38 */ 39 40static int inet_pton4 __P((const char *src, u_char *dst)); 41static int inet_pton6 __P((const char *src, u_char *dst)); 42 43/* int 44 * inet_pton(af, src, dst) 45 * convert from presentation format (which usually means ASCII printable) 46 * to network format (which is usually some kind of binary format). 47 * return: 48 * 1 if the address was valid for the specified address family 49 * 0 if the address wasn't valid (`dst' is untouched in this case) 50 * -1 if some other error occurred (`dst' is untouched in this case, too) 51 * author: 52 * Paul Vixie, 1996. 53 */ 54int 55inet_pton(af, src, dst) 56 int af; 57 const char *src; 58 void *dst; 59{ 60 switch (af) { 61 case AF_INET: 62 return (inet_pton4(src, dst)); 63 case AF_INET6: 64 return (inet_pton6(src, dst)); 65 default: 66 errno = EAFNOSUPPORT; 67 return (-1); 68 } 69 /* NOTREACHED */ 70} 71 72/* int 73 * inet_pton4(src, dst) 74 * like inet_aton() but without all the hexadecimal and shorthand. 75 * return: 76 * 1 if `src' is a valid dotted quad, else 0. 77 * notice: 78 * does not touch `dst' unless it's returning 1. 79 * author: 80 * Paul Vixie, 1996. 81 */ 82static int 83inet_pton4(src, dst) 84 const char *src; 85 u_char *dst; 86{ 87 static const char digits[] = "0123456789"; 88 int saw_digit, octets, ch; 89 u_char tmp[NS_INADDRSZ], *tp; 90 91 saw_digit = 0; 92 octets = 0; 93 *(tp = tmp) = 0; 94 while ((ch = *src++) != '\0') { 95 const char *pch; 96 97 if ((pch = strchr(digits, ch)) != NULL) { 98 u_int new = *tp * 10 + (pch - digits); 99 100 if (saw_digit && *tp == 0) 101 return (0); 102 if (new > 255) 103 return (0); 104 *tp = new; 105 if (!saw_digit) { 106 if (++octets > 4) 107 return (0); 108 saw_digit = 1; 109 } 110 } else if (ch == '.' && saw_digit) { 111 if (octets == 4) 112 return (0); 113 *++tp = 0; 114 saw_digit = 0; 115 } else 116 return (0); 117 } 118 if (octets < 4) 119 return (0); 120 memcpy(dst, tmp, NS_INADDRSZ); 121 return (1); 122} 123 124/* int 125 * inet_pton6(src, dst) 126 * convert presentation level address to network order binary form. 127 * return: 128 * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 129 * notice: 130 * (1) does not touch `dst' unless it's returning 1. 131 * (2) :: in a full address is silently ignored. 132 * credit: 133 * inspired by Mark Andrews. 134 * author: 135 * Paul Vixie, 1996. 136 */ 137static int 138inet_pton6(src, dst) 139 const char *src; 140 u_char *dst; 141{ 142 static const char xdigits_l[] = "0123456789abcdef", 143 xdigits_u[] = "0123456789ABCDEF"; 144 u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; 145 const char *xdigits, *curtok; 146 int ch, seen_xdigits; 147 u_int val; 148 149 memset((tp = tmp), '\0', NS_IN6ADDRSZ); 150 endp = tp + NS_IN6ADDRSZ; 151 colonp = NULL; 152 /* Leading :: requires some special handling. */ 153 if (*src == ':') 154 if (*++src != ':') 155 return (0); 156 curtok = src; 157 seen_xdigits = 0; 158 val = 0; 159 while ((ch = *src++) != '\0') { 160 const char *pch; 161 162 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 163 pch = strchr((xdigits = xdigits_u), ch); 164 if (pch != NULL) { 165 val <<= 4; 166 val |= (pch - xdigits); 167 if (++seen_xdigits > 4) 168 return (0); 169 continue; 170 } 171 if (ch == ':') { 172 curtok = src; 173 if (!seen_xdigits) { 174 if (colonp) 175 return (0); 176 colonp = tp; 177 continue; 178 } else if (*src == '\0') { 179 return (0); 180 } 181 if (tp + NS_INT16SZ > endp) 182 return (0); 183 *tp++ = (u_char) (val >> 8) & 0xff; 184 *tp++ = (u_char) val & 0xff; 185 seen_xdigits = 0; 186 val = 0; 187 continue; 188 } 189 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && 190 inet_pton4(curtok, tp) > 0) { 191 tp += NS_INADDRSZ; 192 seen_xdigits = 0; 193 break; /*%< '\\0' was seen by inet_pton4(). */ 194 } 195 return (0); 196 } 197 if (seen_xdigits) { 198 if (tp + NS_INT16SZ > endp) 199 return (0); 200 *tp++ = (u_char) (val >> 8) & 0xff; 201 *tp++ = (u_char) val & 0xff; 202 } 203 if (colonp != NULL) { 204 /* 205 * Since some memmove()'s erroneously fail to handle 206 * overlapping regions, we'll do the shift by hand. 207 */ 208 const int n = tp - colonp; 209 int i; 210 211 if (tp == endp) 212 return (0); 213 for (i = 1; i <= n; i++) { 214 endp[- i] = colonp[n - i]; 215 colonp[n - i] = 0; 216 } 217 tp = endp; 218 } 219 if (tp != endp) 220 return (0); 221 memcpy(dst, tmp, NS_IN6ADDRSZ); 222 return (1); 223} 224 225/*! \file */ 226