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