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