Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / isc / inet_pton.c
blob1521b4302bc148b957d5526a7e58c2bcf74ba48d
1 /* $NetBSD: inet_pton.c,v 1.6 2014/12/10 04:37:59 christos Exp $ */
3 /*
4 * Copyright (C) 2004, 2005, 2007, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1996-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /*! \file */
22 #if defined(LIBC_SCCS) && !defined(lint)
23 static char rcsid[] =
24 "Id: inet_pton.c,v 1.19 2007/06/19 23:47:17 tbox Exp ";
25 #endif /* LIBC_SCCS and not lint */
27 #include <config.h>
29 #include <errno.h>
30 #include <string.h>
32 #include <isc/net.h>
34 /*% INT16 Size */
35 #define NS_INT16SZ 2
36 /*% IPv4 Address Size */
37 #define NS_INADDRSZ 4
38 /*% IPv6 Address Size */
39 #define NS_IN6ADDRSZ 16
42 * WARNING: Don't even consider trying to compile this on a system where
43 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
46 static int inet_pton4(const char *src, unsigned char *dst);
47 static int inet_pton6(const char *src, unsigned char *dst);
49 /*%
50 * convert from presentation format (which usually means ASCII printable)
51 * to network format (which is usually some kind of binary format).
52 * \return
53 * 1 if the address was valid for the specified address family
54 * 0 if the address wasn't valid (`dst' is untouched in this case)
55 * -1 if some other error occurred (`dst' is untouched in this case, too)
56 * \author
57 * Paul Vixie, 1996.
59 int
60 isc_net_pton(int af, const char *src, void *dst) {
61 switch (af) {
62 case AF_INET:
63 return (inet_pton4(src, dst));
64 case AF_INET6:
65 return (inet_pton6(src, dst));
66 default:
67 errno = EAFNOSUPPORT;
68 return (-1);
70 /* NOTREACHED */
73 /*!\fn static int inet_pton4(const char *src, unsigned char *dst)
74 * \brief
75 * like inet_aton() but without all the hexadecimal and shorthand.
76 * \return
77 * 1 if `src' is a valid dotted quad, else 0.
78 * \note
79 * does not touch `dst' unless it's returning 1.
80 * \author
81 * Paul Vixie, 1996.
83 static int
84 inet_pton4(const char *src, unsigned char *dst) {
85 static const char digits[] = "0123456789";
86 int saw_digit, octets, ch;
87 unsigned char tmp[NS_INADDRSZ], *tp;
89 saw_digit = 0;
90 octets = 0;
91 *(tp = tmp) = 0;
92 while ((ch = *src++) != '\0') {
93 const char *pch;
95 if ((pch = strchr(digits, ch)) != NULL) {
96 unsigned int new = *tp * 10;
98 new += (int)(pch - digits);
99 if (saw_digit && *tp == 0)
100 return (0);
101 if (new > 255)
102 return (0);
103 *tp = new;
104 if (!saw_digit) {
105 if (++octets > 4)
106 return (0);
107 saw_digit = 1;
109 } else if (ch == '.' && saw_digit) {
110 if (octets == 4)
111 return (0);
112 *++tp = 0;
113 saw_digit = 0;
114 } else
115 return (0);
117 if (octets < 4)
118 return (0);
119 memmove(dst, tmp, NS_INADDRSZ);
120 return (1);
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 * \note
128 * (1) does not touch `dst' unless it's returning 1.
129 * \note
130 * (2) :: in a full address is silently ignored.
131 * \author
132 * inspired by Mark Andrews.
133 * \author
134 * Paul Vixie, 1996.
136 static int
137 inet_pton6(const char *src, unsigned char *dst) {
138 static const char xdigits_l[] = "0123456789abcdef",
139 xdigits_u[] = "0123456789ABCDEF";
140 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
141 const char *xdigits, *curtok;
142 int ch, seen_xdigits;
143 unsigned int val;
145 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
146 endp = tp + NS_IN6ADDRSZ;
147 colonp = NULL;
148 /* Leading :: requires some special handling. */
149 if (*src == ':')
150 if (*++src != ':')
151 return (0);
152 curtok = src;
153 seen_xdigits = 0;
154 val = 0;
155 while ((ch = *src++) != '\0') {
156 const char *pch;
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 (++seen_xdigits > 4)
164 return (0);
165 continue;
167 if (ch == ':') {
168 curtok = src;
169 if (!seen_xdigits) {
170 if (colonp)
171 return (0);
172 colonp = tp;
173 continue;
175 if (tp + NS_INT16SZ > endp)
176 return (0);
177 *tp++ = (unsigned char) (val >> 8) & 0xff;
178 *tp++ = (unsigned char) val & 0xff;
179 seen_xdigits = 0;
180 val = 0;
181 continue;
183 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
184 inet_pton4(curtok, tp) > 0) {
185 tp += NS_INADDRSZ;
186 seen_xdigits = 0;
187 break; /* '\0' was seen by inet_pton4(). */
189 return (0);
191 if (seen_xdigits) {
192 if (tp + NS_INT16SZ > endp)
193 return (0);
194 *tp++ = (unsigned char) (val >> 8) & 0xff;
195 *tp++ = (unsigned char) val & 0xff;
197 if (colonp != NULL) {
199 * Since some memmove()'s erroneously fail to handle
200 * overlapping regions, we'll do the shift by hand.
202 const int n = (int)(tp - colonp);
203 int i;
205 if (tp == endp)
206 return (0);
207 for (i = 1; i <= n; i++) {
208 endp[- i] = colonp[n - i];
209 colonp[n - i] = 0;
211 tp = endp;
213 if (tp != endp)
214 return (0);
215 memmove(dst, tmp, NS_IN6ADDRSZ);
216 return (1);