]> git.ipfire.org Git - thirdparty/squid.git/blob - compat/inet_pton.cc
SourceFormat Enforcement
[thirdparty/squid.git] / compat / inet_pton.cc
1 /*
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /*
10 * Shamelessly duplicated from the bind9 public sources
11 * for use by the Squid Project under ISC written permission
12 * included "as found" below.
13 *
14 * Update/Maintenance History:
15 *
16 * 24-Sep-2007 : Copied from bind 9.3.3
17 * - Added protection around libray headers
18 * - Altered configure checks to import
19 *
20 * 06-Oct-2007 : Various fixes to allow the build on MinGW
21 *
22 * 28-Oct-2007: drop some dead code. now tested working without.
23 *
24 * Original License and code follows.
25 */
26
27 #include "squid.h"
28
29 #if !HAVE_DECL_INET_PTON
30
31 /*
32 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
33 * Copyright (c) 1996,1999 by Internet Software Consortium.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies.
38 *
39 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
40 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
41 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
42 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
43 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
44 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
45 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46 */
47
48 #if defined(LIBC_SCCS) && !defined(lint)
49 static const char rcsid[] = "inet_pton.c,v 1.2.206.2 2005/07/28 07:43:18 marka Exp";
50 #endif /* LIBC_SCCS and not lint */
51
52 #if HAVE_SYS_PARAM_H
53 #include <sys/param.h>
54 #endif
55 #if HAVE_SYS_TYPES_H
56 #include <sys/types.h>
57 #endif
58 #if HAVE_SYS_SOCKET_H
59 #include <sys/socket.h>
60 #endif
61 #if HAVE_NETINET_IN_H
62 #include <netinet/in.h>
63 #endif
64 #if ARPA_INET_H
65 #include <arpa/inet.h>
66 #endif
67 #if HAVE_ARPA_NAMESER_H
68 #include <arpa/nameser.h>
69 #endif
70 #if HAVE_STRING_H
71 #include <string.h>
72 #endif
73 #if HAVE_ERRNO_H
74 #include <errno.h>
75 #endif
76
77 #if ! defined(NS_INADDRSZ)
78 #define NS_INADDRSZ 4
79 #endif
80 #if ! defined(NS_IN6ADDRSZ)
81 #define NS_IN6ADDRSZ 16
82 #endif
83 #if ! defined(NS_INT16SZ)
84 #define NS_INT16SZ 2
85 #endif
86
87 /*
88 * WARNING: Don't even consider trying to compile this on a system where
89 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
90 */
91
92 static int inet_pton4 (const char *src, u_char *dst);
93 static int inet_pton6 (const char *src, u_char *dst);
94
95 /* int
96 * inet_pton(af, src, dst)
97 * convert from presentation format (which usually means ASCII printable)
98 * to network format (which is usually some kind of binary format).
99 * return:
100 * 1 if the address was valid for the specified address family
101 * 0 if the address wasn't valid (`dst' is untouched in this case)
102 * -1 if some other error occurred (`dst' is untouched in this case, too)
103 * author:
104 * Paul Vixie, 1996.
105 */
106 int
107 xinet_pton(af, src, dst)
108 int af;
109 const char *src;
110 void *dst;
111 {
112 switch (af) {
113 case AF_INET:
114 return (inet_pton4(src, dst));
115 case AF_INET6:
116 return (inet_pton6(src, dst));
117 default:
118 errno = EAFNOSUPPORT;
119 return (-1);
120 }
121 /* NOTREACHED */
122 }
123
124 /* int
125 * inet_pton4(src, dst)
126 * like inet_aton() but without all the hexadecimal and shorthand.
127 * return:
128 * 1 if `src' is a valid dotted quad, else 0.
129 * notice:
130 * does not touch `dst' unless it's returning 1.
131 * author:
132 * Paul Vixie, 1996.
133 */
134 static int
135 inet_pton4(src, dst)
136 const char *src;
137 u_char *dst;
138 {
139 static const char digits[] = "0123456789";
140 int saw_digit, octets, ch;
141 u_char tmp[NS_INADDRSZ], *tp;
142
143 saw_digit = 0;
144 octets = 0;
145 *(tp = tmp) = 0;
146 while ((ch = *src++) != '\0') {
147 const char *pch;
148
149 if ((pch = strchr(digits, ch)) != NULL) {
150 u_int new = *tp * 10 + (pch - digits);
151
152 if (saw_digit && *tp == 0)
153 return (0);
154 if (new > 255)
155 return (0);
156 *tp = new;
157 if (!saw_digit) {
158 if (++octets > 4)
159 return (0);
160 saw_digit = 1;
161 }
162 } else if (ch == '.' && saw_digit) {
163 if (octets == 4)
164 return (0);
165 *++tp = 0;
166 saw_digit = 0;
167 } else
168 return (0);
169 }
170 if (octets < 4)
171 return (0);
172 memcpy(dst, tmp, NS_INADDRSZ);
173 return (1);
174 }
175
176 /* int
177 * inet_pton6(src, dst)
178 * convert presentation level address to network order binary form.
179 * return:
180 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
181 * notice:
182 * (1) does not touch `dst' unless it's returning 1.
183 * (2) :: in a full address is silently ignored.
184 * credit:
185 * inspired by Mark Andrews.
186 * author:
187 * Paul Vixie, 1996.
188 */
189 static int
190 inet_pton6(src, dst)
191 const char *src;
192 u_char *dst;
193 {
194 static const char xdigits_l[] = "0123456789abcdef",
195 xdigits_u[] = "0123456789ABCDEF";
196 u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
197 const char *xdigits, *curtok;
198 int ch, seen_xdigits;
199 u_int val;
200
201 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
202 endp = tp + NS_IN6ADDRSZ;
203 colonp = NULL;
204 /* Leading :: requires some special handling. */
205 if (*src == ':')
206 if (*++src != ':')
207 return (0);
208 curtok = src;
209 seen_xdigits = 0;
210 val = 0;
211 while ((ch = *src++) != '\0') {
212 const char *pch;
213
214 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
215 pch = strchr((xdigits = xdigits_u), ch);
216 if (pch != NULL) {
217 val <<= 4;
218 val |= (pch - xdigits);
219 if (++seen_xdigits > 4)
220 return (0);
221 continue;
222 }
223 if (ch == ':') {
224 curtok = src;
225 if (!seen_xdigits) {
226 if (colonp)
227 return (0);
228 colonp = tp;
229 continue;
230 } else if (*src == '\0') {
231 return (0);
232 }
233 if (tp + NS_INT16SZ > endp)
234 return (0);
235 *tp++ = (u_char) (val >> 8) & 0xff;
236 *tp++ = (u_char) val & 0xff;
237 seen_xdigits = 0;
238 val = 0;
239 continue;
240 }
241 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
242 inet_pton4(curtok, tp) > 0) {
243 tp += NS_INADDRSZ;
244 seen_xdigits = 0;
245 break; /* '\0' was seen by inet_pton4(). */
246 }
247 return (0);
248 }
249 if (seen_xdigits) {
250 if (tp + NS_INT16SZ > endp)
251 return (0);
252 *tp++ = (u_char) (val >> 8) & 0xff;
253 *tp++ = (u_char) val & 0xff;
254 }
255 if (colonp != NULL) {
256 /*
257 * Since some memmove()'s erroneously fail to handle
258 * overlapping regions, we'll do the shift by hand.
259 */
260 const int n = tp - colonp;
261 int i;
262
263 if (tp == endp)
264 return (0);
265 for (i = 1; i <= n; i++) {
266 endp[- i] = colonp[n - i];
267 colonp[n - i] = 0;
268 }
269 tp = endp;
270 }
271 if (tp != endp)
272 return (0);
273 memcpy(dst, tmp, NS_IN6ADDRSZ);
274 return (1);
275 }
276
277 #endif /* HAVE_DECL_INET_PTON */
278