1 /* 2 * Copyright 2006 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 "mt.h" 26 #include <stdlib.h> 27 #include <ctype.h> 28 #include <string.h> 29 #include <strings.h> 30 #include <netdb.h> 31 #include <stdio.h> 32 #include <arpa/inet.h> 33 #include <netinet/in.h> 34 #include <sys/socket.h> 35 #include <errno.h> 36 37 static int inet_pton4(const char *src, uchar_t *dst); 38 static int inet_pton6(const char *src, uchar_t *dst); 39 40 /* 41 * int 42 * inet_pton(af, src, dst) 43 * convert from presentation format (which usually means ASCII printable) 44 * to network format (which is usually some kind of binary format). 45 * return: 46 * 1 if the address was valid for the specified address family 47 * 0 if the address wasn't valid (`dst' is untouched in this case) 48 * -1 if some other error occurred (`dst' is untouched in this case, too) 49 * author: 50 * Paul Vixie, 1996. Taken from on297-gate:dns stuff 51 */ 52 int 53 inet_pton(int af, const char *src, void *dst) 54 { 55 switch (af) { 56 case AF_INET: 57 return (inet_pton4(src, dst)); 58 case AF_INET6: 59 return (inet_pton6(src, dst)); 60 default: 61 errno = EAFNOSUPPORT; 62 return (-1); 63 } 64 /* NOTREACHED */ 65 } 66 67 /* 68 * int 69 * inet_pton4(src, dst) 70 * like inet_aton() but without all the hexadecimal and shorthand. 71 * return: 72 * 1 if `src' is a valid dotted quad, else 0. 73 * notice: 74 * does not touch `dst' unless it's returning 1. 75 * 76 */ 77 #define INADDRSZ 4 78 #define IN6ADDRSZ 16 79 #define INT16SZ 2 80 81 static int 82 inet_pton4(const char *src, uchar_t *dst) 83 { 84 static const char digits[] = "0123456789"; 85 int saw_digit, octets, ch; 86 uchar_t tmp[INADDRSZ], *tp; 87 88 saw_digit = 0; 89 octets = 0; 90 *(tp = tmp) = 0; 91 while ((ch = *src++) != '\0') { 92 const char *pch; 93 94 if ((pch = strchr(digits, ch)) != NULL) { 95 uint_t new = *tp * 10 + (pch - digits); 96 97 if (new > 255) 98 return (0); 99 *tp = new; 100 if (!saw_digit) { 101 if (++octets > 4) 102 return (0); 103 saw_digit = 1; 104 } 105 } else if (ch == '.' && saw_digit) { 106 if (octets == 4) 107 return (0); 108 *++tp = 0; 109 saw_digit = 0; 110 } else 111 return (0); 112 } 113 if (octets < 4) 114 return (0); 115 116 (void) memcpy(dst, tmp, INADDRSZ); 117 return (1); 118 } 119 120 121 /* 122 * int 123 * inet_pton6(src, dst) 124 * convert presentation level address to network order binary form. 125 * return: 126 * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 127 * notice: 128 * (1) does not touch `dst' unless it's returning 1. 129 * (2) :: in a full address is silently ignored. 130 * credit: 131 * inspired by Mark Andrews. 132 * 133 */ 134 135 136 static int 137 inet_pton6(const char *src, uchar_t *dst) 138 { 139 static const char xdigits_l[] = "0123456789abcdef", 140 xdigits_u[] = "0123456789ABCDEF"; 141 uchar_t tmp[IN6ADDRSZ], *tp, *endp, *colonp; 142 const char *xdigits, *curtok; 143 int ch, saw_xdigit; 144 uint_t val; 145 146 (void) 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++ = (uchar_t)(val >> 8) & 0xff; 182 *tp++ = (uchar_t)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++ = (uchar_t)(val >> 8) & 0xff; 199 *tp++ = (uchar_t)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 (void) memcpy(dst, tmp, IN6ADDRSZ); 220 return (1); 221 } 222