1 /* 2 * Copyright (c) 1996 by Internet Software Consortium. 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 15 * SOFTWARE. 16 */ 17 18 /* 19 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 20 * Use is subject to license terms. 21 */ 22 23 #include "lint.h" 24 25 #include <sys/socket.h> 26 27 #include <arpa/inet.h> 28 #include <netinet/in.h> 29 30 #include <ctype.h> 31 #include <errno.h> 32 #include <netdb.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <strings.h> 37 38 static int inet_pton4(const char *src, uchar_t *dst); 39 static int inet_pton6(const char *src, uchar_t *dst); 40 41 /* 42 * int 43 * inet_pton(af, src, dst) 44 * convert from presentation format (which usually means ASCII printable) 45 * to network format (which is usually some kind of binary format). 46 * return: 47 * 1 if the address was valid for the specified address family 48 * 0 if the address wasn't valid (`dst' is untouched in this case) 49 * -1 if some other error occurred (`dst' is untouched in this case, too) 50 * author: 51 * Paul Vixie, 1996. Taken from on297-gate:dns stuff 52 */ 53 int 54 inet_pton(int af, const char *src, void *dst) 55 { 56 switch (af) { 57 case AF_INET: 58 return (inet_pton4(src, dst)); 59 case AF_INET6: 60 return (inet_pton6(src, dst)); 61 default: 62 errno = EAFNOSUPPORT; 63 return (-1); 64 } 65 /* NOTREACHED */ 66 } 67 68 /* 69 * int 70 * inet_pton4(src, dst) 71 * like inet_aton() but without all the hexadecimal and shorthand. 72 * return: 73 * 1 if `src' is a valid dotted quad, else 0. 74 * notice: 75 * does not touch `dst' unless it's returning 1. 76 * 77 */ 78 #define INADDRSZ 4 79 #define IN6ADDRSZ 16 80 #define INT16SZ 2 81 82 static int 83 inet_pton4(const char *src, uchar_t *dst) 84 { 85 static const char digits[] = "0123456789"; 86 int saw_digit, octets, ch; 87 uchar_t tmp[INADDRSZ], *tp; 88 89 saw_digit = 0; 90 octets = 0; 91 *(tp = tmp) = 0; 92 while ((ch = *src++) != '\0') { 93 const char *pch; 94 95 if ((pch = strchr(digits, ch)) != NULL) { 96 uint_t new = *tp * 10 + (pch - digits); 97 98 if (new > 255) 99 return (0); 100 *tp = new; 101 if (!saw_digit) { 102 if (++octets > 4) 103 return (0); 104 saw_digit = 1; 105 } 106 } else if (ch == '.' && saw_digit) { 107 if (octets == 4) 108 return (0); 109 *++tp = 0; 110 saw_digit = 0; 111 } else 112 return (0); 113 } 114 if (octets < 4) 115 return (0); 116 117 (void) memcpy(dst, tmp, INADDRSZ); 118 return (1); 119 } 120 121 122 /* 123 * int 124 * inet_pton6(src, dst) 125 * convert presentation level address to network order binary form. 126 * return: 127 * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 128 * notice: 129 * (1) does not touch `dst' unless it's returning 1. 130 * (2) :: in a full address is silently ignored. 131 * credit: 132 * inspired by Mark Andrews. 133 * 134 */ 135 static int 136 inet_pton6(const char *src, uchar_t *dst) 137 { 138 static const char xdigits_l[] = "0123456789abcdef"; 139 static const char 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