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