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