ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/vendor/NetBSD/tnftp/20141031/libnetbsd/inet_pton.c
Revision: 6902
Committed: Fri Oct 31 22:42:24 2014 UTC (9 years, 6 months ago) by laffer1
Content type: text/plain
File size: 7044 byte(s)
Log Message:
add tnftp vendor with 20141031 release

File Contents

# Content
1 /* $NetBSD: inet_pton.c,v 1.9 2007/07/23 11:45:52 lukem Exp $ */
2 /* from NetBSD: inet_pton.c,v 1.3 2006/09/26 05:59:18 lukem Exp */
3
4 /*
5 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
6 * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21 #include "tnftp.h"
22
23 #if defined(HAVE_ARPA_NAMESER_H)
24 # include <arpa/nameser.h>
25 #endif
26 #if !defined(NS_INADDRSZ)
27 # define NS_INADDRSZ 4
28 #endif
29 #if !defined(NS_IN6ADDRSZ)
30 # define NS_IN6ADDRSZ 16
31 #endif
32 #if !defined(NS_INT16SZ)
33 # define NS_INT16SZ 2
34 #endif
35
36 /*
37 * WARNING: Don't even consider trying to compile this on a system where
38 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
39 */
40
41 static int inet_pton4(const char *src, unsigned char *dst, int pton);
42 #ifdef INET6
43 static int inet_pton6(const char *src, unsigned char *dst);
44 #endif /* INET6 */
45
46 /* int
47 * inet_pton(af, src, dst)
48 * convert from presentation format (which usually means ASCII printable)
49 * to network format (which is usually some kind of binary format).
50 * return:
51 * 1 if the address was valid for the specified address family
52 * 0 if the address wasn't valid (`dst' is untouched in this case)
53 * -1 if some other error occurred (`dst' is untouched in this case, too)
54 * author:
55 * Paul Vixie, 1996.
56 */
57 int
58 inet_pton(int af, const char *src, void *dst)
59 {
60
61 switch (af) {
62 case AF_INET:
63 return (inet_pton4(src, dst, 1));
64 #ifdef INET6
65 case AF_INET6:
66 return (inet_pton6(src, dst));
67 #endif /* INET6 */
68 default:
69 errno = EAFNOSUPPORT;
70 return (-1);
71 }
72 /* NOTREACHED */
73 }
74
75 /* int
76 * inet_pton4(src, dst, pton)
77 * when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
78 * when last arg is 1: inet_pton(). decimal dotted-quad only.
79 * return:
80 * 1 if `src' is a valid input, else 0.
81 * notice:
82 * does not touch `dst' unless it's returning 1.
83 * author:
84 * Paul Vixie, 1996.
85 */
86 static int
87 inet_pton4(const char *src, unsigned char *dst, int pton)
88 {
89 uint32_t val;
90 unsigned int digit, base;
91 int n;
92 unsigned char c;
93 unsigned int parts[4];
94 register unsigned int *pp = parts;
95
96 c = *src;
97 for (;;) {
98 /*
99 * Collect number up to ``.''.
100 * Values are specified as for C:
101 * 0x=hex, 0=octal, isdigit=decimal.
102 */
103 if (!isdigit(c))
104 return (0);
105 val = 0; base = 10;
106 if (c == '0') {
107 c = *++src;
108 if (c == 'x' || c == 'X')
109 base = 16, c = *++src;
110 else if (isdigit(c) && c != '9')
111 base = 8;
112 }
113 /* inet_pton() takes decimal only */
114 if (pton && base != 10)
115 return (0);
116 for (;;) {
117 if (isdigit(c)) {
118 digit = c - '0';
119 if (digit >= base)
120 break;
121 val = (val * base) + digit;
122 c = *++src;
123 } else if (base == 16 && isxdigit(c)) {
124 digit = c + 10 - (islower(c) ? 'a' : 'A');
125 if (digit >= 16)
126 break;
127 val = (val << 4) | digit;
128 c = *++src;
129 } else
130 break;
131 }
132 if (c == '.') {
133 /*
134 * Internet format:
135 * a.b.c.d
136 * a.b.c (with c treated as 16 bits)
137 * a.b (with b treated as 24 bits)
138 * a (with a treated as 32 bits)
139 */
140 if (pp >= parts + 3)
141 return (0);
142 *pp++ = val;
143 c = *++src;
144 } else
145 break;
146 }
147 /*
148 * Check for trailing characters.
149 */
150 if (c != '\0' && !isspace(c))
151 return (0);
152 /*
153 * Concoct the address according to
154 * the number of parts specified.
155 */
156 n = pp - parts + 1;
157 /* inet_pton() takes dotted-quad only. it does not take shorthand. */
158 if (pton && n != 4)
159 return (0);
160 switch (n) {
161
162 case 0:
163 return (0); /* initial nondigit */
164
165 case 1: /* a -- 32 bits */
166 break;
167
168 case 2: /* a.b -- 8.24 bits */
169 if (parts[0] > 0xff || val > 0xffffff)
170 return (0);
171 val |= parts[0] << 24;
172 break;
173
174 case 3: /* a.b.c -- 8.8.16 bits */
175 if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
176 return (0);
177 val |= (parts[0] << 24) | (parts[1] << 16);
178 break;
179
180 case 4: /* a.b.c.d -- 8.8.8.8 bits */
181 if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
182 return (0);
183 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
184 break;
185 }
186 if (dst) {
187 val = htonl(val);
188 memcpy(dst, &val, NS_INADDRSZ);
189 }
190 return (1);
191 }
192
193 #ifdef INET6
194 /* int
195 * inet_pton6(src, dst)
196 * convert presentation level address to network order binary form.
197 * return:
198 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
199 * notice:
200 * (1) does not touch `dst' unless it's returning 1.
201 * (2) :: in a full address is silently ignored.
202 * credit:
203 * inspired by Mark Andrews.
204 * author:
205 * Paul Vixie, 1996.
206 */
207 static int
208 inet_pton6(const char *src, unsigned char *dst)
209 {
210 static const char xdigits_l[] = "0123456789abcdef",
211 xdigits_u[] = "0123456789ABCDEF";
212 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
213 const char *xdigits, *curtok;
214 int ch, saw_xdigit;
215 unsigned int val;
216
217 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
218 endp = tp + NS_IN6ADDRSZ;
219 colonp = NULL;
220 /* Leading :: requires some special handling. */
221 if (*src == ':')
222 if (*++src != ':')
223 return (0);
224 curtok = src;
225 saw_xdigit = 0;
226 val = 0;
227 while ((ch = *src++) != '\0') {
228 const char *pch;
229
230 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
231 pch = strchr((xdigits = xdigits_u), ch);
232 if (pch != NULL) {
233 val <<= 4;
234 val |= (pch - xdigits);
235 if (val > 0xffff)
236 return (0);
237 saw_xdigit = 1;
238 continue;
239 }
240 if (ch == ':') {
241 curtok = src;
242 if (!saw_xdigit) {
243 if (colonp)
244 return (0);
245 colonp = tp;
246 continue;
247 } else if (*src == '\0')
248 return (0);
249 if (tp + NS_INT16SZ > endp)
250 return (0);
251 *tp++ = (unsigned char) (val >> 8) & 0xff;
252 *tp++ = (unsigned char) val & 0xff;
253 saw_xdigit = 0;
254 val = 0;
255 continue;
256 }
257 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
258 inet_pton4(curtok, tp, 1) > 0) {
259 tp += NS_INADDRSZ;
260 saw_xdigit = 0;
261 break; /* '\0' was seen by inet_pton4(). */
262 }
263 return (0);
264 }
265 if (saw_xdigit) {
266 if (tp + NS_INT16SZ > endp)
267 return (0);
268 *tp++ = (unsigned char) (val >> 8) & 0xff;
269 *tp++ = (unsigned char) val & 0xff;
270 }
271 if (colonp != NULL) {
272 /*
273 * Since some memmove()'s erroneously fail to handle
274 * overlapping regions, we'll do the shift by hand.
275 */
276 const int n = tp - colonp;
277 int i;
278
279 if (tp == endp)
280 return (0);
281 for (i = 1; i <= n; i++) {
282 endp[- i] = colonp[n - i];
283 colonp[n - i] = 0;
284 }
285 tp = endp;
286 }
287 if (tp != endp)
288 return (0);
289 memcpy(dst, tmp, NS_IN6ADDRSZ);
290 return (1);
291 }
292 #endif /* INET6 */