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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors