Re: IPv6 Support for INET/CIDR types. - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: IPv6 Support for INET/CIDR types. |
Date | |
Msg-id | 200110130107.f9D17aQ17607@candle.pha.pa.us Whole thread Raw |
In response to | Re: IPv6 Support for INET/CIDR types. (Paul A Vixie <vixie@vix.com>) |
Responses |
Re: IPv6 Support for INET/CIDR types.
Re: IPv6 Support for INET/CIDR types. |
List | pgsql-patches |
Seems this will have to wait for 7.3. > > What is that status of this patch? We are near beta. > > below please find a shar file containing: > > the latest patch to inet.h and network.c from vadim with a few tiny > changes to the comments from me; > > a patch bringing inet_net_pton.c and inet_net_ntop.c up to date with > respect to isc's changes to those files in the time since INET/CIDR > were added, plus isc's corrected version of vadim's ipv6 changes to > those files; > > the new files inet_cidr_pton.c and inet_cidr_ntop.c, containing isc's > fixed version of vadim's ipv6 support for this api. > > a patch to src/backend/utils/adt/Makefile to compile the above files. > > # This is a shell archive. Save it in a file, remove anything before > # this line, and then unpack it by entering "sh file". Note, it may > # create directories; files and directories will be owned by you and > # have default permissions. > # > # This archive contains: > # > # ipv6-patch > # inet_cidr_ntop.c > # inet_cidr_pton.c > # > echo x - ipv6-patch > sed 's/^X//' >ipv6-patch << 'END-of-ipv6-patch' > XIndex: src/backend/utils/adt/Makefile > X=================================================================== > XRCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/Makefile,v > Xretrieving revision 1.51 > Xdiff -u -r1.51 Makefile > X--- src/backend/utils/adt/Makefile 2001/10/04 04:13:40 1.51 > X+++ src/backend/utils/adt/Makefile 2001/10/05 08:31:17 > X@@ -22,7 +22,9 @@ > X oid.o oracle_compat.o \ > X regexp.o regproc.o ruleutils.o selfuncs.o sets.o \ > X tid.o timestamp.o varbit.o varchar.o varlena.o version.o \ > X- network.o mac.o inet_net_ntop.o inet_net_pton.o \ > X+ network.o mac.o \ > X+ inet_net_ntop.o inet_net_pton.o \ > X+ inet_cidr_ntop.o inet_cidr_pton.o \ > X ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \ > X ascii.o quote.o pgstatfuncs.o encode.o > X > XIndex: src/backend/utils/adt/inet_net_ntop.c > X=================================================================== > XRCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/inet_net_ntop.c,v > Xretrieving revision 1.10 > Xdiff -u -r1.10 inet_net_ntop.c > X--- src/backend/utils/adt/inet_net_ntop.c 2001/03/22 03:59:51 1.10 > X+++ src/backend/utils/adt/inet_net_ntop.c 2001/10/05 08:31:17 > X@@ -1,5 +1,5 @@ > X /* > X- * Copyright (c) 1996 by Internet Software Consortium. > X+ * Copyright (c) 1996,1999 by Internet Software Consortium. > X * > X * Permission to use, copy, modify, and distribute this software for any > X * purpose with or without fee is hereby granted, provided that the above > X@@ -16,34 +16,41 @@ > X */ > X > X #if defined(LIBC_SCCS) && !defined(lint) > X-static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.10 2001/03/22 03:59:51 momjian Exp $"; > X- > X+static const char isc_rcsid[] = "Id: inet_net_ntop.c,v 1.8 2001/09/27 15:08:36 marka Exp $"; > X+static const char rcsid[] = "$Id:$"; > X #endif > X > X+/*#include "port_before.h"*/ > X+ > X #include <sys/types.h> > X #include <sys/socket.h> > X #include <netinet/in.h> > X #include <arpa/inet.h> > X > X #include <errno.h> > X+#include <stdio.h> > X+#include <string.h> > X+#include <stdlib.h> > X+ > X+/*#include "port_after.h"*/ > X > X #include "postgres.h" > X #include "utils/builtins.h" > X > X #ifdef SPRINTF_CHAR > X-#define SPRINTF(x) strlen(sprintf/**/x) > X+# define SPRINTF(x) strlen(sprintf/**/x) > X #else > X-#define SPRINTF(x) ((size_t)sprintf x) > X+# define SPRINTF(x) ((size_t)sprintf x) > X #endif > X > X-static char *inet_net_ntop_ipv4(const u_char *src, int bits, > X- char *dst, size_t size); > X-static char *inet_cidr_ntop_ipv4(const u_char *src, int bits, > X+static char * inet_net_ntop_ipv4(const u_char *src, int bits, > X char *dst, size_t size); > X+static char * inet_net_ntop_ipv6(const u_char *src, int bits, > X+ char *dst, size_t size); > X > X /* > X * char * > X- * inet_cidr_ntop(af, src, bits, dst, size) > X+ * inet_net_ntop(af, src, bits, dst, size) > X * convert network number from network to presentation format. > X * generates CIDR style result always. > X * return: > X@@ -52,167 +59,221 @@ > X * Paul Vixie (ISC), July 1996 > X */ > X char * > X-inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) > X+inet_net_ntop(af, src, bits, dst, size) > X+ int af; > X+ const void *src; > X+ int bits; > X+ char *dst; > X+ size_t size; > X { > X- switch (af) > X- { > X- case AF_INET: > X- return (inet_cidr_ntop_ipv4(src, bits, dst, size)); > X- default: > X- errno = EAFNOSUPPORT; > X- return (NULL); > X+ switch (af) { > X+ case AF_INET: > X+ return (inet_net_ntop_ipv4(src, bits, dst, size)); > X+ case AF_INET6: > X+ return (inet_net_ntop_ipv6(src, bits, dst, size)); > X+ default: > X+ errno = EAFNOSUPPORT; > X+ return (NULL); > X } > X } > X > X- > X /* > X * static char * > X- * inet_cidr_ntop_ipv4(src, bits, dst, size) > X+ * inet_net_ntop_ipv4(src, bits, dst, size) > X * convert IPv4 network number from network to presentation format. > X * generates CIDR style result always. > X * return: > X * pointer to dst, or NULL if an error occurred (check errno). > X * note: > X * network byte order assumed. this means 192.5.5.240/28 has > X- * 0x11110000 in its fourth octet. > X+ * 0b11110000 in its fourth octet. > X * author: > X * Paul Vixie (ISC), July 1996 > X */ > X static char * > X-inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) > X+inet_net_ntop_ipv4(src, bits, dst, size) > X+ const u_char *src; > X+ int bits; > X+ char *dst; > X+ size_t size; > X { > X- char *odst = dst; > X- char *t; > X- u_int m; > X- int b; > X+ char *odst = dst; > X+ char *t; > X+ u_int m; > X+ int b; > X > X- if (bits < 0 || bits > 32) > X- { > X+ if (bits < 0 || bits > 32) { > X errno = EINVAL; > X return (NULL); > X } > X- if (bits == 0) > X- { > X+ > X+ if (bits == 0) { > X if (size < sizeof "0") > X goto emsgsize; > X *dst++ = '0'; > X+ size--; > X *dst = '\0'; > X } > X > X /* Format whole octets. */ > X- for (b = bits / 8; b > 0; b--) > X- { > X- if (size < sizeof ".255") > X+ for (b = bits / 8; b > 0; b--) { > X+ if (size <= sizeof "255.") > X goto emsgsize; > X t = dst; > X- if (dst != odst) > X- *dst++ = '.'; > X dst += SPRINTF((dst, "%u", *src++)); > X- size -= (size_t) (dst - t); > X+ if (b > 1) { > X+ *dst++ = '.'; > X+ *dst = '\0'; > X+ } > X+ size -= (size_t)(dst - t); > X } > X > X /* Format partial octet. */ > X b = bits % 8; > X- if (b > 0) > X- { > X- if (size < sizeof ".255") > X+ if (b > 0) { > X+ if (size <= sizeof ".255") > X goto emsgsize; > X t = dst; > X if (dst != odst) > X *dst++ = '.'; > X m = ((1 << b) - 1) << (8 - b); > X dst += SPRINTF((dst, "%u", *src & m)); > X- size -= (size_t) (dst - t); > X+ size -= (size_t)(dst - t); > X } > X > X /* Format CIDR /width. */ > X- if (size < sizeof "/32") > X+ if (size <= sizeof "/32") > X goto emsgsize; > X dst += SPRINTF((dst, "/%u", bits)); > X- > X return (odst); > X > X-emsgsize: > X+ emsgsize: > X errno = EMSGSIZE; > X return (NULL); > X } > X > X- > X /* > X- * char * > X- * inet_net_ntop(af, src, bits, dst, size) > X- * convert host/network address from network to presentation format. > X- * "src"'s size is determined from its "af". > X- * return: > X- * pointer to dst, or NULL if an error occurred (check errno). > X- * note: > X- * 192.5.5.1/28 has a nonzero host part, which means it isn't a network > X- * as called for by inet_net_pton() but it can be a host address with > X- * an included netmask. > X- * author: > X- * Paul Vixie (ISC), October 1998 > X- */ > X-char * > X-inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size) > X-{ > X- switch (af) > X- { > X- case AF_INET: > X- return (inet_net_ntop_ipv4(src, bits, dst, size)); > X- default: > X- errno = EAFNOSUPPORT; > X- return (NULL); > X- } > X-} > X- > X-/* > X * static char * > X- * inet_net_ntop_ipv4(src, bits, dst, size) > X- * convert IPv4 network address from network to presentation format. > X- * "src"'s size is determined from its "af". > X+ * inet_net_ntop_ipv6(src, bits, fakebits, dst, size) > X+ * convert IPv6 network number from network to presentation format. > X+ * generates CIDR style result always. Picks the shortest representation > X+ * unless the IP is really IPv4. > X+ * always prints specified number of bits (bits). > X * return: > X * pointer to dst, or NULL if an error occurred (check errno). > X * note: > X * network byte order assumed. this means 192.5.5.240/28 has > X- * 0b11110000 in its fourth octet. > X+ * 0x11110000 in its fourth octet. > X * author: > X- * Paul Vixie (ISC), October 1998 > X+ * Vadim Kogan (UCB), June 2001 > X+ * Original version (IPv4) by Paul Vixie (ISC), July 1996 > X */ > X+ > X static char * > X-inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) > X-{ > X- char *odst = dst; > X- char *t; > X- int len = 4; > X- int b; > X+inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { > X+ u_int m; > X+ int b; > X+ int p; > X+ int zero_s, zero_l, tmp_zero_s, tmp_zero_l; > X+ int i; > X+ int is_ipv4 = 0; > X+ unsigned char inbuf[16]; > X+ char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")]; > X+ char *cp; > X+ int words; > X+ u_char *s; > X > X- if (bits < 0 || bits > 32) > X- { > X+ if (bits < 0 || bits > 128) { > X errno = EINVAL; > X return (NULL); > X } > X > X- /* Always format all four octets, regardless of mask length. */ > X- for (b = len; b > 0; b--) > X- { > X- if (size < sizeof ".255") > X- goto emsgsize; > X- t = dst; > X- if (dst != odst) > X- *dst++ = '.'; > X- dst += SPRINTF((dst, "%u", *src++)); > X- size -= (size_t) (dst - t); > X- } > X+ cp = outbuf; > X > X- /* don't print masklen if 32 bits */ > X- if (bits != 32) > X- { > X- if (size < sizeof "/32") > X- goto emsgsize; > X- dst += SPRINTF((dst, "/%u", bits)); > X+ if (bits == 0) { > X+ *cp++ = ':'; > X+ *cp++ = ':'; > X+ *cp = '\0'; > X+ } else { > X+ /* Copy src to private buffer. Zero host part. */ > X+ p = (bits + 7) / 8; > X+ memcpy(inbuf, src, p); > X+ memset(inbuf + p, 0, 16 - p); > X+ b = bits % 8; > X+ if (b != 0) { > X+ m = ~0 << (8 - b); > X+ inbuf[p-1] &= m; > X+ } > X+ > X+ s = inbuf; > X+ > X+ /* how many words need to be displayed in output */ > X+ words = (bits + 15) / 16; > X+ if (words == 1) > X+ words = 2; > X+ > X+ /* Find the longest substring of zero's */ > X+ zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0; > X+ for (i = 0; i < (words * 2); i += 2) { > X+ if ((s[i] | s[i+1]) == 0) { > X+ if (tmp_zero_l == 0) > X+ tmp_zero_s = i / 2; > X+ tmp_zero_l++; > X+ } else { > X+ if (tmp_zero_l && zero_l < tmp_zero_l) { > X+ zero_s = tmp_zero_s; > X+ zero_l = tmp_zero_l; > X+ tmp_zero_l = 0; > X+ } > X+ } > X+ } > X+ > X+ if (tmp_zero_l && zero_l < tmp_zero_l) { > X+ zero_s = tmp_zero_s; > X+ zero_l = tmp_zero_l; > X+ } > X+ > X+ if (zero_l != words && zero_s == 0 && ((zero_l == 6) || > X+ ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) || > X+ ((zero_l == 7 && s[14] != 0 && s[15] != 1))))) > X+ is_ipv4 = 1; > X+ > X+ /* Format whole words. */ > X+ for (p = 0; p < words; p++) { > X+ if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) { > X+ /* Time to skip some zeros */ > X+ if (p == zero_s) > X+ *cp++ = ':'; > X+ if (p == words - 1) > X+ *cp++ = ':'; > X+ s++; > X+ s++; > X+ continue; > X+ } > X+ > X+ if (is_ipv4 && p > 5 ) { > X+ *cp++ = (p == 6) ? ':' : '.'; > X+ cp += SPRINTF((cp, "%u", *s++)); > X+ /* we can potentially drop the last octet */ > X+ if (p != 7 || bits > 120) { > X+ *cp++ = '.'; > X+ cp += SPRINTF((cp, "%u", *s++)); > X+ } > X+ } else { > X+ if (cp != outbuf) > X+ *cp++ = ':'; > X+ cp += SPRINTF((cp, "%x", *s * 256 + s[1])); > X+ s += 2; > X+ } > X+ } > X } > X- > X- return (odst); > X+ /* Format CIDR /width. */ > X+ SPRINTF((cp, "/%u", bits)); > X+ if (strlen(outbuf) + 1 > size) > X+ goto emsgsize; > X+ strcpy(dst, outbuf); > X+ > X+ return (dst); > X > X emsgsize: > X errno = EMSGSIZE; > XIndex: src/backend/utils/adt/inet_net_pton.c > X=================================================================== > XRCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/inet_net_pton.c,v > Xretrieving revision 1.12 > Xdiff -u -r1.12 inet_net_pton.c > X--- src/backend/utils/adt/inet_net_pton.c 2000/12/03 20:45:36 1.12 > X+++ src/backend/utils/adt/inet_net_pton.c 2001/10/05 08:31:17 > X@@ -1,5 +1,5 @@ > X /* > X- * Copyright (c) 1996 by Internet Software Consortium. > X+ * Copyright (c) 1996,1999 by Internet Software Consortium. > X * > X * Permission to use, copy, modify, and distribute this software for any > X * purpose with or without fee is hereby granted, provided that the above > X@@ -16,67 +16,40 @@ > X */ > X > X #if defined(LIBC_SCCS) && !defined(lint) > X-static const char rcsid[] = "$Id: inet_net_pton.c,v 1.12 2000/12/03 20:45:36 tgl Exp $"; > X- > X+static const char isc_rcsid[] = "Id: inet_net_pton.c,v 1.13 2001/09/27 15:08:38 marka Exp $"; > X+static const char rcsid[] = "$Id:$"; > X #endif > X > X+/*#include "port_before.h"*/ > X+ > X #include <sys/types.h> > X #include <sys/socket.h> > X #include <netinet/in.h> > X+#include <arpa/nameser.h> > X #include <arpa/inet.h> > X > X+/*#include <isc/assertions.h>*/ > X #include <assert.h> > X #include <ctype.h> > X #include <errno.h> > X+#include <stdio.h> > X+#include <string.h> > X+#include <stdlib.h> > X > X+/*#include "port_after.h"*/ > X+ > X #include "postgres.h" > X #include "utils/builtins.h" > X > X #ifdef SPRINTF_CHAR > X-#define SPRINTF(x) strlen(sprintf/**/x) > X+# define SPRINTF(x) strlen(sprintf/**/x) > X #else > X-#define SPRINTF(x) ((size_t)sprintf x) > X+# define SPRINTF(x) ((size_t)sprintf x) > X #endif > X > X-static int inet_net_pton_ipv4(const char *src, u_char *dst); > X-static int inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size); > X- > X /* > X * static int > X- * inet_net_pton(af, src, dst, size) > X- * convert network number from presentation to network format. > X- * accepts hex octets, hex strings, decimal octets, and /CIDR. > X- * "size" is in bytes and describes "dst". > X- * return: > X- * number of bits, either imputed classfully or specified with /CIDR, > X- * or -1 if some failure occurred (check errno). ENOENT means it was > X- * not a valid network specification. > X- * author: > X- * Paul Vixie (ISC), June 1996 > X- * > X- * Changes: > X- * I added the inet_cidr_pton function (also from Paul) and changed > X- * the names to reflect their current use. > X- * > X- */ > X-int > X-inet_net_pton(int af, const char *src, void *dst, size_t size) > X-{ > X- switch (af) > X- { > X- case AF_INET: > X- return size == -1 ? > X- inet_net_pton_ipv4(src, dst) : > X- inet_cidr_pton_ipv4(src, dst, size); > X- default: > X- errno = EAFNOSUPPORT; > X- return (-1); > X- } > X-} > X- > X-/* > X- * static int > X- * inet_cidr_pton_ipv4(src, dst, size) > X+ * inet_net_pton_ipv4(src, dst, size) > X * convert IPv4 network number from presentation to network format. > X * accepts hex octets, hex strings, decimal octets, and /CIDR. > X * "size" is in bytes and describes "dst". > X@@ -86,66 +59,52 @@ > X * not an IPv4 network specification. > X * note: > X * network byte order assumed. this means 192.5.5.240/28 has > X- * 0x11110000 in its fourth octet. > X+ * 0b11110000 in its fourth octet. > X * author: > X * Paul Vixie (ISC), June 1996 > X */ > X static int > X-inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size) > X-{ > X- static const char > X- xdigits[] = "0123456789abcdef", > X- digits[] = "0123456789"; > X- int n, > X- ch, > X- tmp, > X- dirty, > X- bits; > X+inet_net_pton_ipv4( const char *src, u_char *dst, size_t size) { > X+ static const char xdigits[] = "0123456789abcdef"; > X+ static const char digits[] = "0123456789"; > X+ int n, ch, tmp = 0, dirty, bits; > X const u_char *odst = dst; > X > X ch = *src++; > X if (ch == '0' && (src[0] == 'x' || src[0] == 'X') > X- && isxdigit((unsigned char) src[1])) > X- { > X+ && isascii((unsigned char)(src[1])) > X+ && isxdigit((unsigned char)(src[1]))) { > X /* Hexadecimal: Eat nybble string. */ > X if (size <= 0) > X goto emsgsize; > X dirty = 0; > X- tmp = 0; > X- src++; /* skip x or X. */ > X- while ((ch = *src++) != '\0' && isxdigit((unsigned char) ch)) > X- { > X- if (isupper((unsigned char) ch)) > X- ch = tolower((unsigned char) ch); > X+ src++; /* skip x or X. */ > X+ while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) { > X+ if (isupper(ch)) > X+ ch = tolower(ch); > X n = strchr(xdigits, ch) - xdigits; > X assert(n >= 0 && n <= 15); > X if (dirty == 0) > X tmp = n; > X else > X tmp = (tmp << 4) | n; > X- if (++dirty == 2) > X- { > X+ if (++dirty == 2) { > X if (size-- <= 0) > X goto emsgsize; > X *dst++ = (u_char) tmp; > X dirty = 0; > X } > X } > X- if (dirty) > X- { /* Odd trailing nybble? */ > X+ if (dirty) { /* Odd trailing nybble? */ > X if (size-- <= 0) > X goto emsgsize; > X *dst++ = (u_char) (tmp << 4); > X } > X- } > X- else if (isdigit((unsigned char) ch)) > X- { > X+ } else if (isascii(ch) && isdigit(ch)) { > X /* Decimal: eat dotted digit string. */ > X- for (;;) > X- { > X+ for (;;) { > X tmp = 0; > X- do > X- { > X+ do { > X n = strchr(digits, ch) - digits; > X assert(n >= 0 && n <= 9); > X tmp *= 10; > X@@ -153,7 +112,7 @@ > X if (tmp > 255) > X goto enoent; > X } while ((ch = *src++) != '\0' && > X- isdigit((unsigned char) ch)); > X+ isascii(ch) && isdigit(ch)); > X if (size-- <= 0) > X goto emsgsize; > X *dst++ = (u_char) tmp; > X@@ -162,26 +121,24 @@ > X if (ch != '.') > X goto enoent; > X ch = *src++; > X- if (!isdigit((unsigned char) ch)) > X+ if (!isascii(ch) || !isdigit(ch)) > X goto enoent; > X } > X- } > X- else > X+ } else > X goto enoent; > X > X bits = -1; > X- if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst) > X- { > X+ if (ch == '/' && isascii((unsigned char)(src[0])) && > X+ isdigit((unsigned char)(src[0])) && dst > odst) { > X /* CIDR width specifier. Nothing can follow it. */ > X- ch = *src++; /* Skip over the /. */ > X+ ch = *src++; /* Skip over the /. */ > X bits = 0; > X- do > X- { > X+ do { > X n = strchr(digits, ch) - digits; > X assert(n >= 0 && n <= 9); > X bits *= 10; > X bits += n; > X- } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch)); > X+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); > X if (ch != '\0') > X goto enoent; > X if (bits > 32) > X@@ -196,9 +153,8 @@ > X if (dst == odst) > X goto enoent; > X /* If no CIDR spec was given, infer width from net class. */ > X- if (bits == -1) > X- { > X- if (*odst >= 240) /* Class E */ > X+ if (bits == -1) { > X+ if (*odst >= 240) /* Class E */ > X bits = 32; > X else if (*odst >= 224) /* Class D */ > X bits = 4; > X@@ -206,133 +162,243 @@ > X bits = 24; > X else if (*odst >= 128) /* Class B */ > X bits = 16; > X- else > X-/* Class A */ > X+ else /* Class A */ > X bits = 8; > X /* If imputed mask is narrower than specified octets, widen. */ > X if (bits >= 8 && bits < ((dst - odst) * 8)) > X bits = (dst - odst) * 8; > X } > X /* Extend network to cover the actual mask. */ > X- while (bits > ((dst - odst) * 8)) > X- { > X+ while (bits > ((dst - odst) * 8)) { > X if (size-- <= 0) > X goto emsgsize; > X *dst++ = '\0'; > X } > X return (bits); > X > X-enoent: > X+ enoent: > X errno = ENOENT; > X return (-1); > X > X-emsgsize: > X+ emsgsize: > X errno = EMSGSIZE; > X return (-1); > X } > X > X-/* > X- * int > X- * inet_net_pton(af, src, dst, *bits) > X- * convert network address from presentation to network format. > X- * accepts inet_pton()'s input for this "af" plus trailing "/CIDR". > X- * "dst" is assumed large enough for its "af". "bits" is set to the > X- * /CIDR prefix length, which can have defaults (like /32 for IPv4). > X- * return: > X- * -1 if an error occurred (inspect errno; ENOENT means bad format). > X- * 0 if successful conversion occurred. > X- * note: > X- * 192.5.5.1/28 has a nonzero host part, which means it isn't a network > X- * as called for by inet_cidr_pton() but it can be a host address with > X- * an included netmask. > X- * author: > X- * Paul Vixie (ISC), October 1998 > X- */ > X static int > X-inet_net_pton_ipv4(const char *src, u_char *dst) > X-{ > X+getbits(const char *src, int *bitsp) { > X static const char digits[] = "0123456789"; > X- const u_char *odst = dst; > X- int n, > X- ch, > X- tmp, > X- bits; > X- size_t size = 4; > X- > X- /* Get the mantissa. */ > X- while (ch = *src++, isdigit((unsigned char) ch)) > X- { > X- tmp = 0; > X- do > X- { > X- n = strchr(digits, ch) - digits; > X- assert(n >= 0 && n <= 9); > X- tmp *= 10; > X- tmp += n; > X- if (tmp > 255) > X- goto enoent; > X- } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch)); > X- if (size-- == 0) > X- goto emsgsize; > X- *dst++ = (u_char) tmp; > X- if (ch == '\0' || ch == '/') > X- break; > X- if (ch != '.') > X- goto enoent; > X+ int n; > X+ int val; > X+ char ch; > X+ > X+ val = 0; > X+ n = 0; > X+ while ((ch = *src++) != '\0') { > X+ const char *pch; > X+ > X+ pch = strchr(digits, ch); > X+ if (pch != NULL) { > X+ if (n++ != 0 && val == 0) /* no leading zeros */ > X+ return (0); > X+ val *= 10; > X+ val += (pch - digits); > X+ if (val > 128) /* range */ > X+ return (0); > X+ continue; > X+ } > X+ return (0); > X } > X+ if (n == 0) > X+ return (0); > X+ *bitsp = val; > X+ return (1); > X+} > X > X- /* Get the prefix length if any. */ > X- bits = -1; > X- if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst) > X- { > X- /* CIDR width specifier. Nothing can follow it. */ > X- ch = *src++; /* Skip over the /. */ > X- bits = 0; > X- do > X- { > X- n = strchr(digits, ch) - digits; > X- assert(n >= 0 && n <= 9); > X- bits *= 10; > X- bits += n; > X- } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch)); > X- if (ch != '\0') > X- goto enoent; > X- if (bits > 32) > X- goto emsgsize; > X+static int > X+getv4(const char *src, u_char *dst, int *bitsp) { > X+ static const char digits[] = "0123456789"; > X+ u_char *odst = dst; > X+ int n; > X+ u_int val; > X+ char ch; > X+ > X+ val = 0; > X+ n = 0; > X+ while ((ch = *src++) != '\0') { > X+ const char *pch; > X+ > X+ pch = strchr(digits, ch); > X+ if (pch != NULL) { > X+ if (n++ != 0 && val == 0) /* no leading zeros */ > X+ return (0); > X+ val *= 10; > X+ val += (pch - digits); > X+ if (val > 255) /* range */ > X+ return (0); > X+ continue; > X+ } > X+ if (ch == '.' || ch == '/') { > X+ if (dst - odst > 3) /* too many octets? */ > X+ return (0); > X+ *dst++ = val; > X+ if (ch == '/') > X+ return (getbits(src, bitsp)); > X+ val = 0; > X+ n = 0; > X+ continue; > X+ } > X+ return (0); > X } > X+ if (n == 0) > X+ return (0); > X+ if (dst - odst > 3) /* too many octets? */ > X+ return (0); > X+ *dst++ = val; > X+ return (1); > X+} > X > X- /* Firey death and destruction unless we prefetched EOS. */ > X- if (ch != '\0') > X+static int > X+inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) { > X+ static const char xdigits_l[] = "0123456789abcdef", > X+ xdigits_u[] = "0123456789ABCDEF"; > X+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; > X+ const char *xdigits, *curtok; > X+ int ch, saw_xdigit; > X+ u_int val; > X+ int digits; > X+ int bits; > X+ size_t bytes; > X+ int words; > X+ int ipv4; > X+ > X+ memset((tp = tmp), '\0', NS_IN6ADDRSZ); > X+ endp = tp + NS_IN6ADDRSZ; > X+ colonp = NULL; > X+ /* Leading :: requires some special handling. */ > X+ if (*src == ':') > X+ if (*++src != ':') > X+ goto enoent; > X+ curtok = src; > X+ saw_xdigit = 0; > X+ val = 0; > X+ digits = 0; > X+ bits = -1; > X+ ipv4 = 0; > X+ while ((ch = *src++) != '\0') { > X+ const char *pch; > X+ > X+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) > X+ pch = strchr((xdigits = xdigits_u), ch); > X+ if (pch != NULL) { > X+ val <<= 4; > X+ val |= (pch - xdigits); > X+ if (++digits > 4) > X+ goto enoent; > X+ saw_xdigit = 1; > X+ continue; > X+ } > X+ if (ch == ':') { > X+ curtok = src; > X+ if (!saw_xdigit) { > X+ if (colonp) > X+ goto enoent; > X+ colonp = tp; > X+ continue; > X+ } else if (*src == '\0') > X+ goto enoent; > X+ if (tp + NS_INT16SZ > endp) > X+ return (0); > X+ *tp++ = (u_char) (val >> 8) & 0xff; > X+ *tp++ = (u_char) val & 0xff; > X+ saw_xdigit = 0; > X+ digits = 0; > X+ val = 0; > X+ continue; > X+ } > X+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && > X+ getv4(curtok, tp, &bits) > 0) { > X+ tp += NS_INADDRSZ; > X+ saw_xdigit = 0; > X+ ipv4 = 1; > X+ break; /* '\0' was seen by inet_pton4(). */ > X+ } > X+ if (ch == '/' && getbits(src, &bits) > 0) > X+ break; > X goto enoent; > X- > X- /* Prefix length can default to /32 only if all four octets spec'd. */ > X- if (bits == -1) > X- { > X- if (dst - odst == 4) > X- bits = 32; > X- else > X+ } > X+ if (saw_xdigit) { > X+ if (tp + NS_INT16SZ > endp) > X goto enoent; > X+ *tp++ = (u_char) (val >> 8) & 0xff; > X+ *tp++ = (u_char) val & 0xff; > X } > X+ if (bits == -1) > X+ bits = 128; > X > X- /* If nothing was written to the destination, we found no address. */ > X- if (dst == odst) > X- goto enoent; > X+ words = (bits + 15) / 16; > X+ if (words < 2) > X+ words = 2; > X+ if (ipv4) > X+ words = 8; > X+ endp = tmp + 2 * words; > X+ > X+ if (colonp != NULL) { > X+ /* > X+ * Since some memmove()'s erroneously fail to handle > X+ * overlapping regions, we'll do the shift by hand. > X+ */ > X+ const int n = tp - colonp; > X+ int i; > X > X- /* If prefix length overspecifies mantissa, life is bad. */ > X- if ((bits / 8) > (dst - odst)) > X+ if (tp == endp) > X+ goto enoent; > X+ for (i = 1; i <= n; i++) { > X+ endp[- i] = colonp[n - i]; > X+ colonp[n - i] = 0; > X+ } > X+ tp = endp; > X+ } > X+ if (tp != endp) > X goto enoent; > X- > X- /* Extend address to four octets. */ > X- while (size-- > 0) > X- *dst++ = 0; > X > X- return bits; > X+ bytes = (bits + 7) / 8; > X+ if (bytes > size) > X+ goto emsgsize; > X+ memcpy(dst, tmp, bytes); > X+ return (bits); > X > X-enoent: > X+ enoent: > X errno = ENOENT; > X return (-1); > X > X-emsgsize: > X+ emsgsize: > X errno = EMSGSIZE; > X return (-1); > X+} > X+ > X+/* > X+ * int > X+ * inet_net_pton(af, src, dst, size) > X+ * convert network number from presentation to network format. > X+ * accepts hex octets, hex strings, decimal octets, and /CIDR. > X+ * "size" is in bytes and describes "dst". > X+ * return: > X+ * number of bits, either imputed classfully or specified with /CIDR, > X+ * or -1 if some failure occurred (check errno). ENOENT means it was > X+ * not a valid network specification. > X+ * author: > X+ * Paul Vixie (ISC), June 1996 > X+ */ > X+int > X+inet_net_pton(int af, const char *src, void *dst, size_t size) { > X+ switch (af) { > X+ case AF_INET: > X+ return (inet_net_pton_ipv4(src, dst, size)); > X+ case AF_INET6: > X+ return (inet_net_pton_ipv6(src, dst, size)); > X+ default: > X+ errno = EAFNOSUPPORT; > X+ return (-1); > X+ } > X } > XIndex: src/backend/utils/adt/network.c > X=================================================================== > XRCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/network.c,v > Xretrieving revision 1.33 > Xdiff -u -r1.33 network.c > X--- src/backend/utils/adt/network.c 2001/08/27 20:03:38 1.33 > X+++ src/backend/utils/adt/network.c 2001/10/05 08:31:18 > X@@ -1,7 +1,5 @@ > X /* > X- * PostgreSQL type definitions for the INET type. This > X- * is for IP V4 CIDR notation, but prepared for V6: just > X- * add the necessary bits where the comments indicate. > X+ * PostgreSQL type definitions for the INET type. > X * > X * $Header: /projects/cvsroot/pgsql/src/backend/utils/adt/network.c,v 1.33 2001/08/27 20:03:38 tgl Exp $ > X * > X@@ -21,17 +19,26 @@ > X #include "utils/inet.h" > X > X > X+#ifndef INET6_ADDRSTRLEN > X+#define INET6_ADDRSTRLEN 46 > X+#endif > X+ > X+#define INET6_CIDRSTRLEN (INET6_ADDRSTRLEN + 4) > X+ > X static Datum text_network(text *src, int type); > X static int32 network_cmp_internal(inet *a1, inet *a2); > X static int v4bitncmp(unsigned long a1, unsigned long a2, int bits); > X static bool v4addressOK(unsigned long a1, int bits); > X+static int v6bitncmp(unsigned int *a1, unsigned int *a2, int bits); > X+static bool v6addressOK(unsigned int *a1, int bits); > X > X /* > X- * Access macros. Add IPV6 support. > X+ * Access macros. > X */ > X > X #define ip_addrsize(inetptr) \ > X- (((inet_struct *)VARDATA(inetptr))->family == AF_INET ? 4 : -1) > X+ (((inet_struct *)VARDATA(inetptr))->family == AF_INET ? 4 : \ > X+ (((inet_struct *)VARDATA(inetptr))->family == AF_INET6 ? 16 : -1 )) > X > X #define ip_family(inetptr) \ > X (((inet_struct *)VARDATA(inetptr))->family) > X@@ -39,12 +46,33 @@ > X #define ip_bits(inetptr) \ > X (((inet_struct *)VARDATA(inetptr))->bits) > X > X+#define ip_ipv4bits(inetptr) \ > X+ (ip_bits(inetptr) - (ip_family(inetptr) == AF_INET6 ? 96 : 0)) > X+ > X #define ip_type(inetptr) \ > X (((inet_struct *)VARDATA(inetptr))->type) > X > X #define ip_v4addr(inetptr) \ > X (((inet_struct *)VARDATA(inetptr))->addr.ipv4_addr) > X > X+#define ip_v6addr(inetptr) \ > X+ (((inet_struct *)VARDATA(inetptr))->addr.ipv6_addr) > X+ > X+#define ip_v4inv6addr(inetptr) \ > X+ (((inet_struct *)VARDATA(inetptr))->addr.ipv6_addr[ 3 ]) > X+ > X+#define ip_v4addr_always(inetptr) \ > X+ (ip_family(inetptr) == AF_INET ? ip_v4addr(inetptr) \ > X+ : ip_v4inv6addr(inetptr)) > X+ > X+#define ip_is_ipv4(inetptr) \ > X+ (ip_family(inetptr) == AF_INET || \ > X+ (ip_family(inetptr) == AF_INET6 && \ > X+ ip_v6addr(inetptr)[0] == 0 && \ > X+ ip_v6addr(inetptr)[1] == 0 && \ > X+ (ip_v6addr(inetptr)[2] == 0 || \ > X+ ntohl(ip_v6addr(inetptr)[2]) == 0xFFFF) )) > X+ > X /* Common input routine */ > X static inet * > X network_in(char *src, int type) > X@@ -63,17 +91,25 @@ > X if ((bits < 0) || (bits > 32)) > X { > X /* Go for an IPV6 address here, before faulting out: */ > X- elog(ERROR, "invalid %s value '%s'", > X- type ? "CIDR" : "INET", src); > X+ ip_family(dst) = AF_INET6; > X+ bits = inet_net_pton(ip_family(dst), src, &ip_v6addr(dst), > X+ type ? ip_addrsize(dst) : -1); > X+ if ((bits < 0) || (bits > 128)) { > X+ elog(ERROR, "invalid %s value '%s'", > X+ type ? "CIDR" : "INET", src); > X+ } > X } > X > X /* > X * Error check: CIDR values must not have any bits set beyond the > X- * masklen. XXX this code is not IPV6 ready. > X+ * masklen. > X */ > X if (type) > X { > X- if (!v4addressOK(ip_v4addr(dst), bits)) > X+ if ( > X+ !(ip_family(dst) == AF_INET && v4addressOK(ip_v4addr(dst), bits)) && > X+ !(ip_family(dst) == AF_INET6 && v6addressOK(ip_v6addr(dst), bits)) > X+ ) > X elog(ERROR, "invalid CIDR value '%s': has bits set to right of mask", src); > X } > X > X@@ -111,19 +147,17 @@ > X inet_out(PG_FUNCTION_ARGS) > X { > X inet *src = PG_GETARG_INET_P(0); > X- char tmp[sizeof("255.255.255.255/32")]; > X+ char tmp[INET6_CIDRSTRLEN]; > X char *dst; > X int len; > X > X- if (ip_family(src) == AF_INET) > X+ if (ip_family(src) == AF_INET || ip_family(src) == AF_INET6) > X { > X- /* It's an IP V4 address: */ > X- > X /* > X * Use inet style for both inet and cidr, since we don't want > X * abbreviated CIDR style here. > X */ > X- dst = inet_net_ntop(AF_INET, &ip_v4addr(src), ip_bits(src), > X+ dst = inet_net_ntop(ip_family(src), &ip_v4addr(src), ip_bits(src), > X tmp, sizeof(tmp)); > X if (dst == NULL) > X elog(ERROR, "unable to print address (%s)", strerror(errno)); > X@@ -135,7 +169,6 @@ > X } > X } > X else > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "unknown address family (%d)", ip_family(src)); > X > X PG_RETURN_CSTRING(pstrdup(tmp)); > X@@ -222,9 +255,55 @@ > X return order; > X return v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), 32); > X } > X+ else if (ip_family(a1) == AF_INET6 && ip_family(a2) == AF_INET6) > X+ { > X+ int order; > X+ > X+ order = v6bitncmp(ip_v6addr(a1), ip_v6addr(a2), > X+ Min(ip_bits(a1), ip_bits(a2))); > X+ if (order != 0) > X+ return order; > X+ order = ((int) ip_bits(a1)) - ((int) ip_bits(a2)); > X+ if (order != 0) > X+ return order; > X+ return v6bitncmp(ip_v6addr(a1), ip_v6addr(a2), 128); > X+ } > X+ else if (ip_is_ipv4(a1) && ip_is_ipv4(a2)) > X+ { > X+ /* Be smart and compare IP V4 with IP V6 */ > X+ int order; > X+ > X+ > X+ order = v4bitncmp(ip_v4addr_always(a1), ip_v4addr_always(a2), > X+ Min(ip_ipv4bits(a1), ip_ipv4bits(a2))); > X+ if (order != 0) > X+ return order; > X+ order = ((int) ip_ipv4bits(a1)) - ((int) ip_ipv4bits(a2)); > X+ if (order != 0) > X+ return order; > X+ return v4bitncmp(ip_v4addr_always(a1), ip_v4addr_always(a2), 32); > X+ } > X else > X { > X- /* Go for an IPV6 address here, before faulting out: */ > X+ elog( DEBUG, "----" ); > X+ if( ip_family(a1) == AF_INET ) > X+ elog( DEBUG, "Pure IPv4" ); > X+ else > X+ elog( DEBUG, "0: 0x%X, 1: 0x%X, 2: 0x%X, 3: 0x%X", > X+ ip_v6addr(a1)[0], > X+ ip_v6addr(a1)[1], > X+ ip_v6addr(a1)[2], > X+ ip_v6addr(a1)[3] ); > X+ > X+ if( ip_family(a2) == AF_INET ) > X+ elog( DEBUG, "Pure IPv4" ); > X+ else > X+ elog( DEBUG, "0: 0x%X, 1: 0x%X, 2: 0x%X, 3: 0x%X", > X+ ip_v6addr(a2)[0], > X+ ip_v6addr(a2)[1], > X+ ip_v6addr(a2)[2], > X+ ip_v6addr(a2)[3] ); > X+ > X elog(ERROR, "cannot compare address families %d and %d", > X ip_family(a1), ip_family(a2)); > X return 0; /* keep compiler quiet */ > X@@ -311,9 +390,18 @@ > X PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2) > X && v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0); > X } > X+ else if ((ip_family(a1) == AF_INET6) && (ip_family(a2) == AF_INET6)) > X+ { > X+ PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2) > X+ && v6bitncmp(ip_v6addr(a1), ip_v6addr(a2), ip_bits(a2)) == 0); > X+ } > X+ else if (ip_is_ipv4(a1) && ip_is_ipv4(a2)) > X+ { > X+ PG_RETURN_BOOL(ip_ipv4bits(a1) > ip_ipv4bits(a2) > X+ && v4bitncmp(ip_v4addr_always(a1), ip_v4addr_always(a2), ip_ipv4bits(a2)) == 0); > X+ } > X else > X { > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "cannot compare address families %d and %d", > X ip_family(a1), ip_family(a2)); > X PG_RETURN_BOOL(false); > X@@ -331,9 +419,18 @@ > X PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2) > X && v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0); > X } > X+ else if ((ip_family(a1) == AF_INET6) && (ip_family(a2) == AF_INET6)) > X+ { > X+ PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2) > X+ && v6bitncmp(ip_v6addr(a1), ip_v6addr(a2), ip_bits(a2)) == 0); > X+ } > X+ else if (ip_is_ipv4(a1) && ip_is_ipv4(a2)) > X+ { > X+ PG_RETURN_BOOL(ip_ipv4bits(a1) >= ip_ipv4bits(a2) > X+ && v4bitncmp(ip_v4addr_always(a1), ip_v4addr_always(a2), ip_ipv4bits(a2)) == 0); > X+ } > X else > X { > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "cannot compare address families %d and %d", > X ip_family(a1), ip_family(a2)); > X PG_RETURN_BOOL(false); > X@@ -351,9 +448,18 @@ > X PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2) > X && v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0); > X } > X+ else if ((ip_family(a1) == AF_INET6) && (ip_family(a2) == AF_INET6)) > X+ { > X+ PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2) > X+ && v6bitncmp(ip_v6addr(a1), ip_v6addr(a2), ip_bits(a2)) == 0); > X+ } > X+ else if (ip_is_ipv4(a1) && ip_is_ipv4(a2)) > X+ { > X+ PG_RETURN_BOOL(ip_ipv4bits(a1) < ip_ipv4bits(a2) > X+ && v4bitncmp(ip_v4addr_always(a1), ip_v4addr_always(a2), ip_ipv4bits(a1)) == 0); > X+ } > X else > X { > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "cannot compare address families %d and %d", > X ip_family(a1), ip_family(a2)); > X PG_RETURN_BOOL(false); > X@@ -371,9 +477,18 @@ > X PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2) > X && v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0); > X } > X+ else if ((ip_family(a1) == AF_INET6) && (ip_family(a2) == AF_INET6)) > X+ { > X+ PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2) > X+ && v6bitncmp(ip_v6addr(a1), ip_v6addr(a2), ip_bits(a2)) == 0); > X+ } > X+ else if (ip_is_ipv4(a1) && ip_is_ipv4(a2)) > X+ { > X+ PG_RETURN_BOOL(ip_ipv4bits(a1) <= ip_ipv4bits(a2) > X+ && v4bitncmp(ip_v4addr_always(a1), ip_v4addr_always(a2), ip_ipv4bits(a1)) == 0); > X+ } > X else > X { > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "cannot compare address families %d and %d", > X ip_family(a1), ip_family(a2)); > X PG_RETURN_BOOL(false); > X@@ -390,17 +505,17 @@ > X text *ret; > X int len; > X char *ptr, > X- tmp[sizeof("255.255.255.255/32")]; > X+ tmp[INET6_CIDRSTRLEN]; > X > X- if (ip_family(ip) == AF_INET) > X+ if (ip_family(ip) == AF_INET || ip_family(ip) == AF_INET6) > X { > X- /* It's an IP V4 address: */ > X- /* force display of 32 bits, regardless of masklen... */ > X- if (inet_net_ntop(AF_INET, &ip_v4addr(ip), 32, tmp, sizeof(tmp)) == NULL) > X+ /* force display of 32/128 bits, regardless of masklen... */ > X+ if (inet_net_ntop(ip_family(ip), &ip_v4addr(ip), > X+ (ip_family(ip) == AF_INET ? 32 : 128), > X+ tmp, sizeof(tmp)) == NULL) > X elog(ERROR, "unable to print host (%s)", strerror(errno)); > X } > X else > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "unknown address family (%d)", ip_family(ip)); > X > X /* Suppress /n if present (shouldn't happen now) */ > X@@ -421,13 +536,12 @@ > X inet *ip = PG_GETARG_INET_P(0); > X text *ret; > X int len; > X- char tmp[sizeof("255.255.255.255/32")]; > X+ char tmp[INET6_CIDRSTRLEN]; > X > X- if (ip_family(ip) == AF_INET) > X+ if (ip_family(ip) == AF_INET || ip_family(ip) == AF_INET6) > X { > X- /* It's an IP V4 address: */ > X- /* force display of 32 bits, regardless of masklen... */ > X- if (inet_net_ntop(AF_INET, &ip_v4addr(ip), 32, tmp, sizeof(tmp)) == NULL) > X+ /* force display of 32/128 bits, regardless of masklen... */ > X+ if (inet_net_ntop(ip_family(ip), &ip_v4addr(ip), (ip_family(ip) == AF_INET ? 32 : 128), tmp, sizeof(tmp)) ==NULL) > X elog(ERROR, "unable to print host (%s)", strerror(errno)); > X /* Add /n if not present (which it won't be) */ > X if (strchr(tmp, '/') == NULL) > X@@ -437,7 +551,6 @@ > X } > X } > X else > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "unknown address family (%d)", ip_family(ip)); > X > X /* Return string as a text datum */ > X@@ -455,23 +568,21 @@ > X text *ret; > X char *dst; > X int len; > X- char tmp[sizeof("255.255.255.255/32")]; > X+ char tmp[INET6_CIDRSTRLEN]; > X > X- if (ip_family(ip) == AF_INET) > X+ if (ip_family(ip) == AF_INET || ip_family(ip) == AF_INET6) > X { > X- /* It's an IP V4 address: */ > X if (ip_type(ip)) > X- dst = inet_cidr_ntop(AF_INET, &ip_v4addr(ip), ip_bits(ip), > X+ dst = inet_cidr_ntop(ip_family(ip), &ip_v4addr(ip), ip_bits(ip), > X tmp, sizeof(tmp)); > X else > X- dst = inet_net_ntop(AF_INET, &ip_v4addr(ip), ip_bits(ip), > X+ dst = inet_net_ntop(ip_family(ip), &ip_v4addr(ip), ip_bits(ip), > X tmp, sizeof(tmp)); > X > X if (dst == NULL) > X elog(ERROR, "unable to print address (%s)", strerror(errno)); > X } > X else > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "unknown address family (%d)", ip_family(ip)); > X > X /* Return string as a text datum */ > X@@ -516,8 +627,19 @@ > X > X ip_v4addr(dst) = htonl(ntohl(ip_v4addr(ip)) | mask); > X } > X+ else if (ip_family(ip) == AF_INET6) { > X+ /* It's an IP V6 address: */ > X+ > X+ /* "There are no broadcast addresses in IPv6, their function being > X+ superseded by multicast addresses." (RFC2373) */ > X+ /* I think use of solicited-node address (FF02:0:0:0:0:1:FFXX:XXXX) here is appropriate */ > X+ unsigned long mask = 0x00ffffff; > X+ ip_v6addr(dst)[0] = htonl(0xff02); > X+ ip_v6addr(dst)[1] = 0; > X+ ip_v6addr(dst)[2] = htonl(1); > X+ ip_v6addr(dst)[3] = htonl(0xff000000 | (ntohl(ip_v4addr_always(ip)) & mask)); > X+ } > X else > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "unknown address family (%d)", ip_family(ip)); > X > X ip_family(dst) = ip_family(ip); > X@@ -556,8 +678,41 @@ > X > X ip_v4addr(dst) = htonl(ntohl(ip_v4addr(ip)) & mask); > X } > X+ else if(ip_family(ip) == AF_INET6) { > X+ /* It's an IP V6 address: */ > X+ unsigned long mask = 0xffffffff; > X+ > X+ /* Ok, let's do this in 4 steps... */ > X+ if(ip_bits(ip) > 96) > X+ { > X+ mask <<= (128 - ip_bits(ip)); > X+ ip_v6addr(dst)[0] = htonl(ntohl(ip_v6addr(ip)[0]) & mask); > X+ memset(ip_v6addr(dst) + 1, 0, sizeof(int) * 3); > X+ } > X+ else if(ip_bits(ip) > 64) > X+ { > X+ ip_v6addr(dst)[0] = ip_v6addr(ip)[0]; > X+ mask <<= (96 - ip_bits(ip)); > X+ ip_v6addr(dst)[1] = htonl(ntohl(ip_v6addr(ip)[1]) & mask); > X+ memset(ip_v6addr(dst) + 2, 0, sizeof(int) * 2); > X+ } > X+ else if(ip_bits(ip) > 32) > X+ { > X+ memcpy(ip_v6addr(dst), ip_v6addr(ip), sizeof(int) * 2); > X+ mask <<= (64 - ip_bits(ip)); > X+ ip_v6addr(dst)[2] = htonl(ntohl(ip_v6addr(ip)[2]) & mask); > X+ ip_v6addr(dst)[3] = 0; > X+ } > X+ else if(ip_bits(ip) > 0 ) > X+ { > X+ memcpy(ip_v6addr(dst), ip_v6addr(ip), sizeof(int) * 3); > X+ mask <<= (32 - ip_bits(ip)); > X+ ip_v6addr(dst)[3] = htonl(ntohl(ip_v6addr(ip)[3]) & mask); > X+ } > X+ else > X+ memcpy(ip_v6addr(dst), ip_v6addr(ip), sizeof(int) * 4); > X+ } > X else > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "unknown address family (%d)", ip_family(ip)); > X > X ip_family(dst) = ip_family(ip); > X@@ -598,8 +753,44 @@ > X > X ip_bits(dst) = 32; > X } > X+ else if (ip_family(ip) == AF_INET6) > X+ { > X+ /* It's an IP V6 address: */ > X+ unsigned long mask = 0xffffffff; > X+ > X+ /* Ok, let's do this in 4 steps... */ > X+ if(ip_bits(ip) > 96) > X+ { > X+ mask <<= (128 - ip_bits(ip)); > X+ ip_v6addr(dst)[0] = htonl(mask); > X+ memset(ip_v6addr(dst) + 1, 0, sizeof(int) * 3); > X+ } > X+ else if(ip_bits(ip) > 64) > X+ { > X+ ip_v6addr(dst)[0] = 0xffffffff; > X+ mask <<= (96 - ip_bits(ip)); > X+ ip_v6addr(dst)[1] = htonl(mask); > X+ memset(ip_v6addr(dst) + 2, 0, sizeof(int) * 2); > X+ } > X+ else if(ip_bits(ip) > 32) > X+ { > X+ memset(ip_v6addr(dst), 0xff, sizeof(int) * 2); > X+ mask <<= (64 - ip_bits(ip)); > X+ ip_v6addr(dst)[2] = htonl(mask); > X+ ip_v6addr(dst)[3] = 0; > X+ } > X+ else if(ip_bits(ip) > 0 ) > X+ { > X+ memset(ip_v6addr(dst), 0xff, sizeof(int) * 3); > X+ mask <<= (32 - ip_bits(ip)); > X+ ip_v6addr(dst)[3] = htonl(mask); > X+ } > X+ else > X+ memset(ip_v6addr(dst), 0xff, sizeof(int) * 4); > X+ > X+ ip_bits(dst) = 128; > X+ } > X else > X- /* Go for an IPV6 address here, before faulting out: */ > X elog(ERROR, "unknown address family (%d)", ip_family(ip)); > X > X ip_family(dst) = ip_family(ip); > X@@ -661,7 +852,7 @@ > X > X > X /* > X- * Bitwise comparison for V4 addresses. Add V6 implementation! > X+ * Bitwise comparison for IP V4 addresses. > X */ > X > X static int > X@@ -687,6 +878,34 @@ > X } > X > X /* > X+ * Bitwise comparison for IP V6 addresses. > X+ */ > X+ > X+static int > X+v6bitncmp(unsigned int *a1, unsigned int *a2, int bits) > X+{ > X+ unsigned int mask; > X+ unsigned int tmp1, tmp2; > X+ int i; > X+ > X+ for( i = 0; bits > 0 && i < 4; i++, bits -= 32 ) { > X+ if( bits > 32 ) > X+ mask = 0xffffffff; > X+ else if( bits > 0 ) > X+ mask = 0xffffffff << (32 - bits); > X+ else > X+ mask = 0; > X+ tmp1 = ntohl(a1[i]); > X+ tmp2 = ntohl(a2[i]); > X+ if( ( tmp1 & mask ) < ( tmp2 & mask ) ) > X+ return -1; > X+ else if( ( tmp1 & mask ) > ( tmp2 & mask ) ) > X+ return 1; > X+ } > X+ return 0; > X+} > X+ > X+/* > X * Returns true if given address fits fully within the specified bit width. > X */ > X static bool > X@@ -706,6 +925,29 @@ > X if ((a1 & mask) == a1) > X return true; > X return false; > X+} > X+ > X+/* > X+ * Returns true if given address fits fully within the specified bit width. > X+ */ > X+static bool > X+v6addressOK(unsigned int *a1, int bits) > X+{ > X+ unsigned int tmp1, mask; > X+ int i; > X+ > X+ for( i = 0; bits > 0 && i < 4; i++, bits -= 32 ) { > X+ if( bits > 32 ) > X+ mask = 0xffffffff; > X+ else if( bits > 0 ) > X+ mask = 0xffffffff << (32 - bits); > X+ else > X+ mask = 0; > X+ tmp1 = ntohl(a1[i]); > X+ if( ( tmp1 & mask ) != tmp1 ) > X+ return false; > X+ } > X+ return true; > X } > X > X > XIndex: src/include/utils/inet.h > X=================================================================== > XRCS file: /projects/cvsroot/pgsql/src/include/utils/inet.h,v > Xretrieving revision 1.10 > Xdiff -u -r1.10 inet.h > X--- src/include/utils/inet.h 2001/03/22 04:01:12 1.10 > X+++ src/include/utils/inet.h 2001/10/05 08:31:25 > X@@ -25,8 +25,8 @@ > X unsigned char type; > X union > X { > X- unsigned int ipv4_addr; /* network byte order */ > X- /* add IPV6 address type here */ > X+ unsigned int ipv4_addr; /* network byte order */ > X+ unsigned int ipv6_addr[4]; /* network byte order */ > X } addr; > X } inet_struct; > X > END-of-ipv6-patch > echo x - inet_cidr_ntop.c > sed 's/^X//' >inet_cidr_ntop.c << 'END-of-inet_cidr_ntop.c' > X/* > X * Copyright (c) 1998,1999 by Internet Software Consortium. > X * > X * Permission to use, copy, modify, and distribute this software for any > X * purpose with or without fee is hereby granted, provided that the above > X * copyright notice and this permission notice appear in all copies. > X * > X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS > X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES > X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE > X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL > X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR > X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS > X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS > X * SOFTWARE. > X */ > X > X#if defined(LIBC_SCCS) && !defined(lint) > Xstatic const char isc_rcsid[] = "Id: inet_cidr_ntop.c,v 8.7 2001/09/28 05:19:36 marka Exp $"; > Xstatic const char rcsid[] = "$Id:$"; > X#endif > X > X/*#include "port_before.h"*/ > X > X#include <sys/types.h> > X#include <sys/socket.h> > X#include <netinet/in.h> > X#include <arpa/nameser.h> > X#include <arpa/inet.h> > X > X#include <errno.h> > X#include <stdio.h> > X#include <string.h> > X#include <stdlib.h> > X > X/*#include "port_after.h"*/ > X > X#include "postgres.h" > X#include "utils/builtins.h" > X > X#ifdef SPRINTF_CHAR > X# define SPRINTF(x) strlen(sprintf/**/x) > X#else > X# define SPRINTF(x) ((size_t)sprintf x) > X#endif > X > Xstatic char * inet_cidr_ntop_ipv4(const u_char *src, int bits, > X char *dst, size_t size); > Xstatic char * inet_cidr_ntop_ipv6(const u_char *src, int bits, > X char *dst, size_t size); > X > X/* > X * char * > X * inet_cidr_ntop(af, src, bits, dst, size) > X * convert network address from network to presentation format. > X * "src"'s size is determined from its "af". > X * return: > X * pointer to dst, or NULL if an error occurred (check errno). > X * note: > X * 192.5.5.1/28 has a nonzero host part, which means it isn't a network > X * as called for by inet_net_ntop() but it can be a host address with > X * an included netmask. > X * author: > X * Paul Vixie (ISC), October 1998 > X */ > Xchar * > Xinet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) { > X switch (af) { > X case AF_INET: > X return (inet_cidr_ntop_ipv4(src, bits, dst, size)); > X case AF_INET6: > X return (inet_cidr_ntop_ipv6(src, bits, dst, size)); > X default: > X errno = EAFNOSUPPORT; > X return (NULL); > X } > X} > X > Xstatic int > Xdecoct(const u_char *src, int bytes, char *dst, size_t size) { > X char *odst = dst; > X char *t; > X int b; > X > X for (b = 1; b <= bytes; b++) { > X if (size < sizeof "255.") > X return (0); > X t = dst; > X dst += SPRINTF((dst, "%u", *src++)); > X if (b != bytes) { > X *dst++ = '.'; > X *dst = '\0'; > X } > X size -= (size_t)(dst - t); > X } > X return (dst - odst); > X} > X > X/* > X * static char * > X * inet_cidr_ntop_ipv4(src, bits, dst, size) > X * convert IPv4 network address from network to presentation format. > X * "src"'s size is determined from its "af". > X * return: > X * pointer to dst, or NULL if an error occurred (check errno). > X * note: > X * network byte order assumed. this means 192.5.5.240/28 has > X * 0b11110000 in its fourth octet. > X * author: > X * Paul Vixie (ISC), October 1998 > X */ > Xstatic char * > Xinet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) { > X char *odst = dst; > X size_t len = 4; > X size_t b; > X size_t bytes; > X > X if ((bits < -1) || (bits > 32)) { > X errno = EINVAL; > X return (NULL); > X } > X > X /* Find number of significant bytes in address. */ > X if (bits == -1) > X len = 4; > X else > X for (len = 1, b = 1 ; b < 4; b++) > X if (*(src + b)) > X len = b + 1; > X > X /* Format whole octets plus nonzero trailing octets. */ > X bytes = (((bits <= 0) ? 1 : bits) + 7) / 8; > X if (len > bytes) > X bytes = len; > X b = decoct(src, bytes, dst, size); > X if (b == 0) > X goto emsgsize; > X dst += b; > X size -= b; > X > X if (bits != -1) { > X /* Format CIDR /width. */ > X if (size < sizeof "/32") > X goto emsgsize; > X dst += SPRINTF((dst, "/%u", bits)); > X } > X > X return (odst); > X > X emsgsize: > X errno = EMSGSIZE; > X return (NULL); > X} > X > Xstatic char * > Xinet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { > X /* > X * Note that int32_t and int16_t need only be "at least" large enough > X * to contain a value of the specified size. On some systems, like > X * Crays, there is no such thing as an integer variable with 16 bits. > X * Keep this in mind if you think this function should have been coded > X * to use pointer overlays. All the world's not a VAX. > X */ > X char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"]; > X char *tp; > X struct { int base, len; } best, cur; > X u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; > X int i; > X > X if ((bits < -1) || (bits > 128)) { > X errno = EINVAL; > X return (NULL); > X } > X > X /* > X * Preprocess: > X * Copy the input (bytewise) array into a wordwise array. > X * Find the longest run of 0x00's in src[] for :: shorthanding. > X */ > X memset(words, '\0', sizeof words); > X for (i = 0; i < NS_IN6ADDRSZ; i++) > X words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); > X best.base = -1; > X cur.base = -1; > X for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { > X if (words[i] == 0) { > X if (cur.base == -1) > X cur.base = i, cur.len = 1; > X else > X cur.len++; > X } else { > X if (cur.base != -1) { > X if (best.base == -1 || cur.len > best.len) > X best = cur; > X cur.base = -1; > X } > X } > X } > X if (cur.base != -1) { > X if (best.base == -1 || cur.len > best.len) > X best = cur; > X } > X if (best.base != -1 && best.len < 2) > X best.base = -1; > X > X /* > X * Format the result. > X */ > X tp = tmp; > X for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { > X /* Are we inside the best run of 0x00's? */ > X if (best.base != -1 && i >= best.base && > X i < (best.base + best.len)) { > X if (i == best.base) > X *tp++ = ':'; > X continue; > X } > X /* Are we following an initial run of 0x00s or any real hex? */ > X if (i != 0) > X *tp++ = ':'; > X /* Is this address an encapsulated IPv4? */ > X if (i == 6 && best.base == 0 && (best.len == 6 || > X (best.len == 7 && words[7] != 0x0001) || > X (best.len == 5 && words[5] == 0xffff))) { > X int n; > X > X if (src[15] || bits == -1 || bits > 120) > X n = 4; > X else if (src[14] || bits > 112) > X n = 3; > X else > X n = 2; > X n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp)); > X if (n == 0) { > X errno = EMSGSIZE; > X return (NULL); > X } > X tp += strlen(tp); > X break; > X } > X tp += SPRINTF((tp, "%x", words[i])); > X } > X > X /* Was it a trailing run of 0x00's? */ > X if (best.base != -1 && (best.base + best.len) == > X (NS_IN6ADDRSZ / NS_INT16SZ)) > X *tp++ = ':'; > X *tp = '\0'; > X > X if (bits != -1) > X tp += SPRINTF((tp, "/%u", bits)); > X > X /* > X * Check for overflow, copy, and we're done. > X */ > X if ((size_t)(tp - tmp) > size) { > X errno = EMSGSIZE; > X return (NULL); > X } > X strcpy(dst, tmp); > X return (dst); > X} > END-of-inet_cidr_ntop.c > echo x - inet_cidr_pton.c > sed 's/^X//' >inet_cidr_pton.c << 'END-of-inet_cidr_pton.c' > X/* > X * Copyright (c) 1998,1999 by Internet Software Consortium. > X * > X * Permission to use, copy, modify, and distribute this software for any > X * purpose with or without fee is hereby granted, provided that the above > X * copyright notice and this permission notice appear in all copies. > X * > X * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS > X * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES > X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE > X * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL > X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR > X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS > X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS > X * SOFTWARE. > X */ > X > X#if defined(LIBC_SCCS) && !defined(lint) > Xstatic const char isc_rcsid[] = "Id: inet_cidr_pton.c,v 8.7 2001/09/28 04:21:28 marka Exp $"; > Xstatic const char rcsid[] = "$Id:$"; > X#endif > X > X/*#include "port_before.h"*/ > X > X#include <sys/types.h> > X#include <sys/socket.h> > X#include <netinet/in.h> > X#include <arpa/nameser.h> > X#include <arpa/inet.h> > X > X/*#include <isc/assertions.h>*/ > X#include <assert.h> > X#include <ctype.h> > X#include <errno.h> > X#include <stdio.h> > X#include <string.h> > X#include <stdlib.h> > X > X/*#include "port_after.h"*/ > X > X#include "postgres.h" > X#include "utils/builtins.h" > X > X#ifdef SPRINTF_CHAR > X# define SPRINTF(x) strlen(sprintf/**/x) > X#else > X# define SPRINTF(x) ((size_t)sprintf x) > X#endif > X > Xstatic int inet_cidr_pton_ipv4(const char *src, u_char *dst, > X int *bits, int ipv6); > Xstatic int inet_cidr_pton_ipv6(const char *src, u_char *dst, > X int *bits); > X > Xstatic int getbits(const char *, int ipv6); > X > X/* > X * int > X * inet_cidr_pton(af, src, dst, *bits) > X * convert network address from presentation to network format. > X * accepts inet_pton()'s input for this "af" plus trailing "/CIDR". > X * "dst" is assumed large enough for its "af". "bits" is set to the > X * /CIDR prefix length, which can have defaults (like /32 for IPv4). > X * return: > X * -1 if an error occurred (inspect errno; ENOENT means bad format). > X * 0 if successful conversion occurred. > X * note: > X * 192.5.5.1/28 has a nonzero host part, which means it isn't a network > X * as called for by inet_net_pton() but it can be a host address with > X * an included netmask. > X * author: > X * Paul Vixie (ISC), October 1998 > X */ > Xint > Xinet_cidr_pton(int af, const char *src, void *dst, int *bits) { > X switch (af) { > X case AF_INET: > X return (inet_cidr_pton_ipv4(src, dst, bits, 0)); > X case AF_INET6: > X return (inet_cidr_pton_ipv6(src, dst, bits)); > X default: > X errno = EAFNOSUPPORT; > X return (-1); > X } > X} > X > Xstatic const char digits[] = "0123456789"; > X > Xstatic int > Xinet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) { > X const u_char *odst = dst; > X int n, ch, tmp, bits; > X size_t size = 4; > X > X /* Get the mantissa. */ > X while (ch = *src++, (isascii(ch) && isdigit(ch))) { > X tmp = 0; > X do { > X n = strchr(digits, ch) - digits; > X assert(n >= 0 && n <= 9); > X tmp *= 10; > X tmp += n; > X if (tmp > 255) > X goto enoent; > X } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); > X if (size-- == 0) > X goto emsgsize; > X *dst++ = (u_char) tmp; > X if (ch == '\0' || ch == '/') > X break; > X if (ch != '.') > X goto enoent; > X } > X > X /* Get the prefix length if any. */ > X bits = -1; > X if (ch == '/' && dst > odst) { > X bits = getbits(src, ipv6); > X if (bits == -2) > X goto enoent; > X } else if (ch != '\0') > X goto enoent; > X > X /* Prefix length can default to /32 only if all four octets spec'd. */ > X if (bits == -1) { > X if (dst - odst == 4) > X bits = ipv6 ? 128 : 32; > X else > X goto enoent; > X } > X > X /* If nothing was written to the destination, we found no address. */ > X if (dst == odst) > X goto enoent; > X > X /* If prefix length overspecifies mantissa, life is bad. */ > X if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst)) > X goto enoent; > X > X /* Extend address to four octets. */ > X while (size-- > 0) > X *dst++ = 0; > X > X *pbits = bits; > X return (0); > X > X enoent: > X errno = ENOENT; > X return (-1); > X > X emsgsize: > X errno = EMSGSIZE; > X return (-1); > X} > X > Xstatic int > Xinet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) { > X static const char xdigits_l[] = "0123456789abcdef", > X xdigits_u[] = "0123456789ABCDEF"; > X u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; > X const char *xdigits, *curtok; > X int ch, saw_xdigit; > X u_int val; > X int bits; > X > X memset((tp = tmp), '\0', NS_IN6ADDRSZ); > X endp = tp + NS_IN6ADDRSZ; > X colonp = NULL; > X /* Leading :: requires some special handling. */ > X if (*src == ':') > X if (*++src != ':') > X return (0); > X curtok = src; > X saw_xdigit = 0; > X val = 0; > X bits = -1; > X while ((ch = *src++) != '\0') { > X const char *pch; > X > X if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) > X pch = strchr((xdigits = xdigits_u), ch); > X if (pch != NULL) { > X val <<= 4; > X val |= (pch - xdigits); > X if (val > 0xffff) > X return (0); > X saw_xdigit = 1; > X continue; > X } > X if (ch == ':') { > X curtok = src; > X if (!saw_xdigit) { > X if (colonp) > X return (0); > X colonp = tp; > X continue; > X } else if (*src == '\0') { > X return (0); > X } > X if (tp + NS_INT16SZ > endp) > X return (0); > X *tp++ = (u_char) (val >> 8) & 0xff; > X *tp++ = (u_char) val & 0xff; > X saw_xdigit = 0; > X val = 0; > X continue; > X } > X if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && > X inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) { > X tp += NS_INADDRSZ; > X saw_xdigit = 0; > X break; /* '\0' was seen by inet_pton4(). */ > X } > X if (ch == '/') { > X bits = getbits(src, 1); > X if (bits == -2) > X goto enoent; > X break; > X } > X goto enoent; > X } > X if (saw_xdigit) { > X if (tp + NS_INT16SZ > endp) > X goto emsgsize; > X *tp++ = (u_char) (val >> 8) & 0xff; > X *tp++ = (u_char) val & 0xff; > X } > X if (colonp != NULL) { > X /* > X * Since some memmove()'s erroneously fail to handle > X * overlapping regions, we'll do the shift by hand. > X */ > X const int n = tp - colonp; > X int i; > X > X if (tp == endp) > X goto enoent; > X for (i = 1; i <= n; i++) { > X endp[- i] = colonp[n - i]; > X colonp[n - i] = 0; > X } > X tp = endp; > X } > X > X memcpy(dst, tmp, NS_IN6ADDRSZ); > X > X *pbits = bits; > X return (0); > X > X enoent: > X errno = ENOENT; > X return (-1); > X > X emsgsize: > X errno = EMSGSIZE; > X return (-1); > X} > X > Xint > Xgetbits(const char *src, int ipv6) { > X int bits = 0; > X char *cp, ch; > X > X if (*src == '\0') /* syntax */ > X return (-2); > X do { > X ch = *src++; > X cp = strchr(digits, ch); > X if (cp == NULL) /* syntax */ > X return (-2); > X bits *= 10; > X bits += cp - digits; > X if (bits == 0 && *src != '\0') /* no leading zeros */ > X return (-2); > X if (bits > (ipv6 ? 128 : 32)) /* range error */ > X return (-2); > X } while (*src != '\0'); > X > X return (bits); > X} > END-of-inet_cidr_pton.c > exit > > -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 853-3000 + If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania 19026
pgsql-patches by date: