2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (c) 1996,1999 by Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * src/backend/utils/adt/inet_net_pton.c
20#if defined(LIBC_SCCS) && !defined(lint)
21static const char rcsid[] =
"Id: inet_net_pton.c,v 1.4.2.3 2004年03月17日 00:40:11 marka Exp $";
44 * pg_inet_net_pton(af, src, dst, size)
45 * convert network number from presentation to network format.
46 * accepts hex octets, hex strings, decimal octets, and /CIDR.
47 * "size" is in bytes and describes "dst".
49 * number of bits, either imputed classfully or specified with /CIDR,
50 * or -1 if some failure occurred (check errno). ENOENT means it was
51 * not a valid network specification.
53 * Paul Vixie (ISC), June 1996
56 * I added the inet_cidr_pton function (also from Paul) and changed
57 * the names to reflect their current use.
81 * inet_cidr_pton_ipv4(src, dst, size)
82 * convert IPv4 network number from presentation to network format.
83 * accepts hex octets, hex strings, decimal octets, and /CIDR.
84 * "size" is in bytes and describes "dst".
86 * number of bits, either imputed classfully or specified with /CIDR,
87 * or -1 if some failure occurred (check errno). ENOENT means it was
88 * not an IPv4 network specification.
90 * network byte order assumed. this means 192.5.5.240/28 has
91 * 0b11110000 in its fourth octet.
93 * Paul Vixie (ISC), June 1996
98 static const char xdigits[] =
"0123456789abcdef";
99 static const char digits[] =
"0123456789";
105 const u_char *odst = dst;
108 if (ch ==
'0' && (src[0] ==
'x' || src[0] ==
'X')
109 && isxdigit((
unsigned char) src[1]))
111 /* Hexadecimal: Eat nybble string. */
115 src++;
/* skip x or X. */
116 while ((ch = *src++) !=
'0円' && isxdigit((
unsigned char) ch))
119 n = strchr(xdigits, ch) - xdigits;
120 assert(n >= 0 && n <= 15);
124 tmp = (tmp << 4) | n;
129 *dst++ = (u_char) tmp;
134 {
/* Odd trailing nybble? */
137 *dst++ = (u_char) (tmp << 4);
140 else if (isdigit((
unsigned char) ch))
142 /* Decimal: eat dotted digit string. */
154 }
while ((ch = *src++) !=
'0円' &&
155 isdigit((
unsigned char) ch));
158 *dst++ = (u_char) tmp;
159 if (ch ==
'0円' || ch ==
'/')
164 if (!isdigit((
unsigned char) ch))
172 if (ch ==
'/' && isdigit((
unsigned char) src[0]) && dst > odst)
174 /* CIDR width specifier. Nothing can follow it. */
175 ch = *src++;
/* Skip over the /. */
183 }
while ((ch = *src++) !=
'0円' && isdigit((
unsigned char) ch));
190 /* Fiery death and destruction unless we prefetched EOS. */
194 /* If nothing was written to the destination, we found no address. */
197 /* If no CIDR spec was given, infer width from net class. */
200 if (*odst >= 240)
/* Class E */
202 else if (*odst >= 224)
/* Class D */
204 else if (*odst >= 192)
/* Class C */
206 else if (*odst >= 128)
/* Class B */
211 /* If imputed mask is narrower than specified octets, widen. */
212 if (bits < ((dst - odst) * 8))
213 bits = (dst - odst) * 8;
216 * If there are no additional bits specified for a class D address
219 if (bits == 8 && *odst == 224)
222 /* Extend network to cover the actual mask. */
223 while (bits > ((dst - odst) * 8))
242 * inet_net_pton_ipv4(af, src, dst, *bits)
243 * convert network address from presentation to network format.
244 * accepts inet_pton()'s input for this "af" plus trailing "/CIDR".
245 * "dst" is assumed large enough for its "af". "bits" is set to the
246 * /CIDR prefix length, which can have defaults (like /32 for IPv4).
248 * -1 if an error occurred (inspect errno; ENOENT means bad format).
249 * 0 if successful conversion occurred.
251 * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
252 * as called for by inet_cidr_pton() but it can be a host address with
253 * an included netmask.
255 * Paul Vixie (ISC), October 1998
260 static const char digits[] =
"0123456789";
261 const u_char *odst = dst;
268 /* Get the mantissa. */
269 while (ch = *src++, isdigit((
unsigned char) ch))
280 }
while ((ch = *src++) !=
'0円' && isdigit((
unsigned char) ch));
283 *dst++ = (u_char) tmp;
284 if (ch ==
'0円' || ch ==
'/')
290 /* Get the prefix length if any. */
292 if (ch ==
'/' && isdigit((
unsigned char) src[0]) && dst > odst)
294 /* CIDR width specifier. Nothing can follow it. */
295 ch = *src++;
/* Skip over the /. */
303 }
while ((ch = *src++) !=
'0円' && isdigit((
unsigned char) ch));
310 /* Fiery death and destruction unless we prefetched EOS. */
314 /* Prefix length can default to /32 only if all four octets spec'd. */
323 /* If nothing was written to the destination, we found no address. */
327 /* If prefix length overspecifies mantissa, life is bad. */
328 if ((bits / 8) > (dst - odst))
331 /* Extend address to four octets. */
349 static const char digits[] =
"0123456789";
356 while ((ch = *src++) !=
'0円')
363 if (n++ != 0 &&
val == 0)
/* no leading zeros */
367 if (
val > 128)
/* range */
380 getv4(
const char *src, u_char *dst,
int *bitsp)
382 static const char digits[] =
"0123456789";
390 while ((ch = *src++) !=
'0円')
397 if (n++ != 0 &&
val == 0)
/* no leading zeros */
401 if (
val > 255)
/* range */
405 if (ch ==
'.' || ch ==
'/')
407 if (dst - odst > 3)
/* too many octets? */
420 if (dst - odst > 3)
/* too many octets? */
432 #define NS_IN6ADDRSZ 16
434 #define NS_INADDRSZ 4
439 static const char xdigits_l[] =
"0123456789abcdef",
440 xdigits_u[] =
"0123456789ABCDEF";
459 /* Leading :: requires some special handling. */
468 while ((ch = *src++) !=
'0円')
472 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
473 pch = strchr((xdigits = xdigits_u), ch);
477 val |= (pch - xdigits);
493 else if (*src ==
'0円')
497 *tp++ = (u_char) (
val >> 8) & 0xff;
498 *tp++ = (u_char)
val & 0xff;
505 getv4(curtok, tp, &bits) > 0)
509 break;
/* '0円' was seen by inet_pton4(). */
511 if (ch ==
'/' &&
getbits(src, &bits) > 0)
519 *tp++ = (u_char) (
val >> 8) & 0xff;
520 *tp++ = (u_char)
val & 0xff;
530 * Since some memmove()'s erroneously fail to handle overlapping
531 * regions, we'll do the shift by hand.
533 const int n = tp - colonp;
538 for (
i = 1;
i <= n;
i++)
540 endp[-
i] = colonp[n -
i];
549 * Copy out the result.
int pg_inet_net_pton(int af, const char *src, void *dst, size_t size)
static int inet_net_pton_ipv6(const char *src, u_char *dst)
static int inet_net_pton_ipv4(const char *src, u_char *dst)
static int getbits(const char *src, int *bitsp)
static int getv4(const char *src, u_char *dst, int *bitsp)
static int inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size)
static int inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size)
unsigned char pg_ascii_tolower(unsigned char ch)