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