Index: doc/src/sgml/datatype.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/datatype.sgml,v
retrieving revision 1.116
diff -c -c -r1.116 datatype.sgml
*** doc/src/sgml/datatype.sgml 13 Mar 2003 01:30:27 -0000 1.116
--- doc/src/sgml/datatype.sgml 12 Jun 2003 05:13:12 -0000
***************
*** 100,106 ****
cidr
! IP network address
--- 100,106 ----
cidr
! IPv4 or IPc6 network address
***************
*** 124,130 ****
inet
! IP host address
--- 124,130 ----
inet
! IPv4 or IPv6 host address
***************
*** 2394,2400 ****
! PostgreSQL> offers data types to store IP and MAC
addresses, shown in . It
is preferable to use these types over plain text types, because
these types offer input error checking and several specialized
--- 2394,2400 ----
! PostgreSQL> offers data types to store IPv4, IPv6, and MAC
addresses, shown in . It
is preferable to use these types over plain text types, because
these types offer input error checking and several specialized
***************
*** 2415,2428 ****
cidr
! 12 bytes
! IPv4 networks
inet
! 12 bytes
! IPv4 hosts and networks
--- 2415,2428 ----
cidr
! 12 or 24 bytes
! valid IPv4 or IPv6 networks
inet
! 12 or 24 bytes
! valid IPv4 or IPv6 hosts or networks
***************
*** 2436,2442 ****
! IPv6 is not yet supported.
--- 2436,2445 ----
! When sorting inet or cidr data types,
! IPv4 addresses will always sort before IPv6 addresses, including
! IPv4 addresses encapsulated or mapped into IPv6 addresses, such as
! ::10.2.3.4 or ::ffff::10.4.3.2.
***************
*** 2448,2473 ****
! The inet type holds an IP host address, and
optionally the identity of the subnet it is in, all in one field.
! The subnet identity is represented by stating how many bits of
! the host address represent the network address (the
! netmask
). If the netmask is 32, then the value
! does not indicate a subnet, only a single host. Note that if you
! want to accept networks only, you should use the
cidr type rather than inet.
! The input format for this type is x.x.x.x/y where x.x.x.x is an IP address and
! y is the number of
! bits in the netmask. If the /y part is left off, then the
! netmask is 32, and the value represents just a single host.
! On display, the /y
! portion is suppressed if the netmask is 32.
--- 2451,2481 ----
! The inet type holds an IPv4 or IPv6 host address, and
optionally the identity of the subnet it is in, all in one field.
! The subnet identity is represented by stating how many bits of the
! the host address represent the network address
! (the netmask
). If the netmask is 32 and the address is
! IPv4, then the value does not indicate a subnet, only a single host.
! In IPv6, the address length is 128 bits.
! Note that if you want to accept networks only, you should use the
cidr type rather than inet.
! The input format for this type is
! address/y
! where
! address
! is an IPv4 or IPv6 address and
! y
! is the number of bits in the netmask. If the
! /y
! part is left off, then the
! netmask is 32 for IPv4 and 128 for IPv6, and the value represents
! just a single host. On display, the
! /y
! portion is suppressed if the netmask specifies a single host.
***************
*** 2479,2490 ****
! The cidr type holds an IP network specification.
Input and output formats follow Classless Internet Domain Routing
conventions.
The format for specifying networks is x.x.x.x/y> where x.x.x.x> is the network and y> is the number of bits in the netmask. If
y> is omitted, it is calculated
using assumptions from the older classful network numbering system, except
--- 2487,2499 ----
! The cidr type holds an IPv4 or IPv6 network specification.
Input and output formats follow Classless Internet Domain Routing
conventions.
The format for specifying networks is address/y> where address> is the network represented as an
! IPv4 or IPv6 address, and y> is the number of bits in the netmask. If
y> is omitted, it is calculated
using assumptions from the older classful network numbering system, except
***************
*** 2563,2568 ****
--- 2572,2599 ----
10.0.0.0/8
10/8
+
+ 10.1.2.3/32
+ 10.1.2.3/32
+ 10.1.2.3/32
+
+ 2001:4f8:3:ba::/64
+ 2001:4f8:3:ba::/64
+ 2001:4f8:3:ba::/64
+
+
+ 2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128
+ 2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128
+ 2001:4f8:3:ba:2e0:81ff:fe22:d1f1
+
+
+ ::ffff:1.2.3.0/120
+ ::ffff:1.2.3.0/120
+ ::ffff:1.2.3/120
+
+ ::ffff:1.2.3.0/128
+ ::ffff:1.2.3.0/128
+ ::ffff:1.2.3.0/128
Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/func.sgml,v
retrieving revision 1.154
diff -c -c -r1.154 func.sgml
*** doc/src/sgml/func.sgml 5 May 2003 15:08:49 -0000 1.154
--- doc/src/sgml/func.sgml 12 Jun 2003 05:13:18 -0000
***************
*** 5804,5809 ****
--- 5804,5814 ----
inet '192.168.1.5' < inet '192.168.1.6'
+ <
+ Less than
+ inet '1111::2222' < inet '2222::1111'
+
+
<=
is less than or equal
inet '192.168.1.5' <= inet '192.168.1.5'
Index: src/backend/utils/adt/inet_net_ntop.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/inet_net_ntop.c,v
retrieving revision 1.12
diff -c -c -r1.12 inet_net_ntop.c
*** src/backend/utils/adt/inet_net_ntop.c 2 Sep 2002 02:47:04 -0000 1.12
--- src/backend/utils/adt/inet_net_ntop.c 12 Jun 2003 05:13:19 -0000
***************
*** 27,34 ****
--- 27,38 ----
#include
+ #include "utils/inet.h"
#include "utils/builtins.h"
+ #define NS_IN6ADDRSZ 16
+ #define NS_INT16SZ 2
+
#ifdef SPRINTF_CHAR
#define SPRINTF(x) strlen(sprintf/**/x)
#else
***************
*** 36,44 ****
#endif
static char *inet_net_ntop_ipv4(const u_char *src, int bits,
! char *dst, size_t size);
static char *inet_cidr_ntop_ipv4(const u_char *src, int bits,
! char *dst, size_t size);
/*
* char *
--- 40,52 ----
#endif
static char *inet_net_ntop_ipv4(const u_char *src, int bits,
! char *dst, size_t size);
static char *inet_cidr_ntop_ipv4(const u_char *src, int bits,
! char *dst, size_t size);
! static char *inet_net_ntop_ipv6(const u_char *src, int bits,
! char *dst, size_t size);
! static char *inet_cidr_ntop_ipv6(const u_char *src, int bits,
! char *dst, size_t size);
/*
* char *
***************
*** 55,62 ****
{
switch (af)
{
! case AF_INET:
return (inet_cidr_ntop_ipv4(src, bits, dst, size));
default:
errno = EAFNOSUPPORT;
return (NULL);
--- 63,72 ----
{
switch (af)
{
! case PGSQL_AF_INET:
return (inet_cidr_ntop_ipv4(src, bits, dst, size));
+ case PGSQL_AF_INET6:
+ return (inet_cidr_ntop_ipv6(src, bits, dst, size));
default:
errno = EAFNOSUPPORT;
return (NULL);
***************
*** 136,141 ****
--- 146,293 ----
return (NULL);
}
+ /*
+ * static char *
+ * inet_net_ntop_ipv6(src, bits, fakebits, dst, size)
+ * convert IPv6 network number from network to presentation format.
+ * generates CIDR style result always. Picks the shortest representation
+ * unless the IP is really IPv4.
+ * always prints specified number of bits (bits).
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0x11110000 in its fourth octet.
+ * author:
+ * Vadim Kogan (UCB), June 2001
+ * Original version (IPv4) by Paul Vixie (ISC), July 1996
+ */
+
+ static char *
+ inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
+ {
+ u_int m;
+ int b;
+ int p;
+ int zero_s, zero_l, tmp_zero_s, tmp_zero_l;
+ int i;
+ int is_ipv4 = 0;
+ int double_colon = 0;
+ unsigned char inbuf[16];
+ char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
+ char *cp;
+ int words;
+ u_char *s;
+
+ if (bits < 0 || bits > 128) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ cp = outbuf;
+ double_colon = 0;
+
+ if (bits == 0) {
+ *cp++ = ':';
+ *cp++ = ':';
+ *cp = '\0';
+ double_colon = 1;
+ } else {
+ /* Copy src to private buffer. Zero host part. */
+ p = (bits + 7) / 8;
+ memcpy(inbuf, src, p);
+ memset(inbuf + p, 0, 16 - p);
+ b = bits % 8;
+ if (b != 0) {
+ m = ~0 << (8 - b);
+ inbuf[p-1] &= m;
+ }
+
+ s = inbuf;
+
+ /* how many words need to be displayed in output */
+ words = (bits + 15) / 16;
+ if (words == 1)
+ words = 2;
+
+ /* Find the longest substring of zero's */
+ zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
+ for (i = 0; i < (words * 2); i += 2) {
+ if ((s[i] | s[i+1]) == 0) {
+ if (tmp_zero_l == 0)
+ tmp_zero_s = i / 2;
+ tmp_zero_l++;
+ } else {
+ if (tmp_zero_l && zero_l < tmp_zero_l) {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ tmp_zero_l = 0;
+ }
+ }
+ }
+
+ if (tmp_zero_l && zero_l < tmp_zero_l) {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ }
+
+ if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
+ ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
+ ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
+ is_ipv4 = 1;
+
+ /* Format whole words. */
+ for (p = 0; p < words; p++) {
+ if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) {
+ /* Time to skip some zeros */
+ if (p == zero_s)
+ *cp++ = ':';
+ if (p == words - 1) {
+ *cp++ = ':';
+ double_colon = 1;
+ }
+ s++;
+ s++;
+ continue;
+ }
+
+ if (is_ipv4 && p > 5 ) {
+ *cp++ = (p == 6) ? ':' : '.';
+ cp += SPRINTF((cp, "%u", *s++));
+ /* we can potentially drop the last octet */
+ if (p != 7 || bits > 120) {
+ *cp++ = '.';
+ cp += SPRINTF((cp, "%u", *s++));
+ }
+ } else {
+ if (cp != outbuf)
+ *cp++ = ':';
+ cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
+ s += 2;
+ }
+ }
+ }
+
+ if (!double_colon) {
+ if (bits < 128 - 32)
+ cp += SPRINTF((cp, "::", bits));
+ else if (bits < 128 - 16)
+ cp += SPRINTF((cp, ":0", bits));
+ }
+
+ /* Format CIDR /width. */
+ SPRINTF((cp, "/%u", bits));
+
+ if (strlen(outbuf) + 1 > size)
+ goto emsgsize;
+ strcpy(dst, outbuf);
+
+ return (dst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+ }
/*
* char *
***************
*** 156,163 ****
{
switch (af)
{
! case AF_INET:
return (inet_net_ntop_ipv4(src, bits, dst, size));
default:
errno = EAFNOSUPPORT;
return (NULL);
--- 308,317 ----
{
switch (af)
{
! case PGSQL_AF_INET:
return (inet_net_ntop_ipv4(src, bits, dst, size));
+ case PGSQL_AF_INET6:
+ return (inet_net_ntop_ipv6(src, bits, dst, size));
default:
errno = EAFNOSUPPORT;
return (NULL);
***************
*** 216,219 ****
--- 370,497 ----
emsgsize:
errno = EMSGSIZE;
return (NULL);
+ }
+
+ static int
+ decoct(const u_char *src, int bytes, char *dst, size_t size) {
+ char *odst = dst;
+ char *t;
+ int b;
+
+ for (b = 1; b <= bytes; b++) {
+ if (size < sizeof "255.")
+ return (0);
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b != bytes) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - t);
+ }
+ return (dst - odst);
+ }
+
+ static char *
+ inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
+ {
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
+ char *tp;
+ struct { int base, len; } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ if ((bits < -1) || (bits > 128)) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ int n;
+
+ n = decoct(src+12, 4, tp, sizeof tmp - (tp - tmp));
+ if (n == 0) {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ tp += strlen(tp);
+ break;
+ }
+ tp += SPRINTF((tp, "%x", words[i]));
+ }
+
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp = '\0';
+
+ if (bits != -1 && bits != 128)
+ tp += SPRINTF((tp, "/%u", bits));
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
}
Index: src/backend/utils/adt/inet_net_pton.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/inet_net_pton.c,v
retrieving revision 1.14
diff -c -c -r1.14 inet_net_pton.c
*** src/backend/utils/adt/inet_net_pton.c 2 Sep 2002 02:47:04 -0000 1.14
--- src/backend/utils/adt/inet_net_pton.c 12 Jun 2003 05:13:19 -0000
***************
*** 29,44 ****
#include
#include
! #include "utils/builtins.h"
! #ifdef SPRINTF_CHAR
! #define SPRINTF(x) strlen(sprintf/**/x)
! #else
! #define SPRINTF(x) ((size_t)sprintf x)
! #endif
static int inet_net_pton_ipv4(const char *src, u_char *dst);
static int inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size);
/*
* static int
--- 29,42 ----
#include
#include
! #include "utils/inet.h"
! #include "utils/builtins.h"
static int inet_net_pton_ipv4(const char *src, u_char *dst);
static int inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size);
+ static int inet_net_pton_ipv6(const char *src, u_char *dst);
+ static int inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size);
/*
* static int
***************
*** 63,72 ****
{
switch (af)
{
! case AF_INET:
return size == -1 ?
inet_net_pton_ipv4(src, dst) :
inet_cidr_pton_ipv4(src, dst, size);
default:
errno = EAFNOSUPPORT;
return (-1);
--- 61,74 ----
{
switch (af)
{
! case PGSQL_AF_INET:
return size == -1 ?
inet_net_pton_ipv4(src, dst) :
inet_cidr_pton_ipv4(src, dst, size);
+ case PGSQL_AF_INET6:
+ return size == -1 ?
+ inet_net_pton_ipv6(src, dst) :
+ inet_cidr_pton_ipv6(src, dst, size);
default:
errno = EAFNOSUPPORT;
return (-1);
***************
*** 332,337 ****
--- 334,535 ----
return (-1);
emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+ }
+
+ static int
+ getbits(const char *src, int *bitsp) {
+ static const char digits[] = "0123456789";
+ int n;
+ int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ if (n++ != 0 && val == 0) /* no leading zeros */
+ return (0);
+ val *= 10;
+ val += (pch - digits);
+ if (val > 128) /* range */
+ return (0);
+ continue;
+ }
+ return (0);
+ }
+ if (n == 0)
+ return (0);
+ *bitsp = val;
+ return (1);
+ }
+
+ static int
+ getv4(const char *src, u_char *dst, int *bitsp) {
+ static const char digits[] = "0123456789";
+ u_char *odst = dst;
+ int n;
+ u_int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ if (n++ != 0 && val == 0) /* no leading zeros */
+ return (0);
+ val *= 10;
+ val += (pch - digits);
+ if (val > 255) /* range */
+ return (0);
+ continue;
+ }
+ if (ch == '.' || ch == '/') {
+ if (dst - odst > 3) /* too many octets? */
+ return (0);
+ *dst++ = val;
+ if (ch == '/')
+ return (getbits(src, bitsp));
+ val = 0;
+ n = 0;
+ continue;
+ }
+ return (0);
+ }
+ if (n == 0)
+ return (0);
+ if (dst - odst > 3) /* too many octets? */
+ return (0);
+ *dst++ = val;
+ return (1);
+ }
+
+ static int
+ inet_net_pton_ipv6(const char *src, u_char *dst)
+ {
+ return inet_cidr_pton_ipv6(src, dst, 16);
+ }
+
+ #define NS_IN6ADDRSZ 16
+ #define NS_INT16SZ 2
+ #define NS_INADDRSZ 4
+
+ static int
+ inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+ int digits;
+ int bits;
+
+ if (size < NS_IN6ADDRSZ)
+ goto emsgsize;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ goto enoent;
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ digits = 0;
+ bits = -1;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (++digits > 4)
+ goto enoent;
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ goto enoent;
+ colonp = tp;
+ continue;
+ } else if (*src == '\0')
+ goto enoent;
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ digits = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ getv4(curtok, tp, &bits) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ if (ch == '/' && getbits(src, &bits) > 0)
+ break;
+ goto enoent;
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ goto enoent;
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (bits == -1)
+ bits = 128;
+
+ endp = tmp + 16;
+
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ goto enoent;
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ goto enoent;
+
+ /*
+ * Copy out the result.
+ */
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
errno = EMSGSIZE;
return (-1);
}
Index: src/backend/utils/adt/network.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/network.c,v
retrieving revision 1.41
diff -c -c -r1.41 network.c
*** src/backend/utils/adt/network.c 13 May 2003 18:03:07 -0000 1.41
--- src/backend/utils/adt/network.c 12 Jun 2003 05:13:20 -0000
***************
*** 1,7 ****
/*
! * PostgreSQL type definitions for the INET type. This
! * is for IP V4 CIDR notation, but prepared for V6: just
! * add the necessary bits where the comments indicate.
*
* $Header: /cvsroot/pgsql-server/src/backend/utils/adt/network.c,v 1.41 2003/05/13 18:03:07 tgl Exp $
*
--- 1,5 ----
/*
! * PostgreSQL type definitions for the INET and CIDR types.
*
* $Header: /cvsroot/pgsql-server/src/backend/utils/adt/network.c,v 1.41 2003/05/13 18:03:07 tgl Exp $
*
***************
*** 15,38 ****
#include
#include
#include "catalog/pg_type.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/inet.h"
-
static Datum text_network(text *src, int type);
static int32 network_cmp_internal(inet *a1, inet *a2);
! static int v4bitncmp(unsigned long a1, unsigned long a2, int bits);
! static bool v4addressOK(unsigned long a1, int bits);
/*
! * Access macros. Add IPV6 support.
*/
- #define ip_addrsize(inetptr) \
- (((inet_struct *)VARDATA(inetptr))->family == AF_INET ? 4 : -1)
-
#define ip_family(inetptr) \
(((inet_struct *)VARDATA(inetptr))->family)
--- 13,35 ----
#include
#include
+ #include
+
#include "catalog/pg_type.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/inet.h"
static Datum text_network(text *src, int type);
static int32 network_cmp_internal(inet *a1, inet *a2);
! static int bitncmp(void *l, void *r, int n);
! static bool addressOK(unsigned char *a, int bits, int family);
! static int ip_addrsize(inet *inetptr);
/*
! * Access macros.
*/
#define ip_family(inetptr) \
(((inet_struct *)VARDATA(inetptr))->family)
***************
*** 42,83 ****
#define ip_type(inetptr) \
(((inet_struct *)VARDATA(inetptr))->type)
! #define ip_v4addr(inetptr) \
! (((inet_struct *)VARDATA(inetptr))->addr.ipv4_addr)
/* Common input routine */
static inet *
network_in(char *src, int type)
{
! int bits;
inet *dst;
/* make sure any unused bits in a CIDR value are zeroed */
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
! /* First, try for an IP V4 address: */
! ip_family(dst) = AF_INET;
! bits = inet_net_pton(ip_family(dst), src, &ip_v4addr(dst),
! type ? ip_addrsize(dst) : -1);
! if ((bits < 0) || (bits > 32))
! {
! /* Go for an IPV6 address here, before faulting out: */
! elog(ERROR, "invalid %s value '%s'",
! type ? "CIDR" : "INET", src);
}
/*
! * Error check: CIDR values must not have any bits set beyond the
! * masklen. XXX this code is not IPV6 ready.
*/
if (type)
{
! if (!v4addressOK(ip_v4addr(dst), bits))
elog(ERROR, "invalid CIDR value '%s': has bits set to right of mask", src);
}
VARATT_SIZEP(dst) = VARHDRSZ
! + ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
ip_bits(dst) = bits;
ip_type(dst) = type;
--- 39,107 ----
#define ip_type(inetptr) \
(((inet_struct *)VARDATA(inetptr))->type)
! #define ip_addr(inetptr) \
! (((inet_struct *)VARDATA(inetptr))->ip_addr)
!
! #define ip_maxbits(inetptr) \
! (ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)
!
! /*
! * Now, as a function!
! * Return the number of bytes of storage needed for this data type.
! */
! static int
! ip_addrsize(inet *inetptr)
! {
! switch (ip_family(inetptr)) {
! case PGSQL_AF_INET:
! return 4;
! case PGSQL_AF_INET6:
! return 16;
! default:
! return -1;
! }
! }
/* Common input routine */
static inet *
network_in(char *src, int type)
{
! int bits;
inet *dst;
/* make sure any unused bits in a CIDR value are zeroed */
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
! /*
! * First, check to see if this is an IPv6 or IPv4 address. IPv6
! * addresses will have a : somewhere in them (several, in fact) so
! * if there is one present, assume it's V6, otherwise assume it's V4.
! */
!
! if (strchr(src, ':') != NULL) {
! ip_family(dst) = PGSQL_AF_INET6;
! } else {
! ip_family(dst) = PGSQL_AF_INET;
}
+ bits = inet_net_pton(ip_family(dst), src, ip_addr(dst),
+ type ? ip_addrsize(dst) : -1);
+ if ((bits < 0) || (bits > ip_maxbits(dst)))
+ elog(ERROR, "invalid %s value '%s'",
+ type ? "CIDR" : "INET", src);
+
/*
! * Error check: CIDR values must not have any bits set beyond
! * the masklen.
*/
if (type)
{
! if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
elog(ERROR, "invalid CIDR value '%s': has bits set to right of mask", src);
}
VARATT_SIZEP(dst) = VARHDRSZ
! + ((char *) &ip_addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
ip_bits(dst) = bits;
ip_type(dst) = type;
***************
*** 110,141 ****
inet_out(PG_FUNCTION_ARGS)
{
inet *src = PG_GETARG_INET_P(0);
! char tmp[sizeof("255.255.255.255/32")];
char *dst;
int len;
! if (ip_family(src) == AF_INET)
{
! /* It's an IP V4 address: */
!
! /*
! * Use inet style for both inet and cidr, since we don't want
! * abbreviated CIDR style here.
! */
! dst = inet_net_ntop(AF_INET, &ip_v4addr(src), ip_bits(src),
! tmp, sizeof(tmp));
! if (dst == NULL)
! elog(ERROR, "unable to print address (%s)", strerror(errno));
! /* For CIDR, add /n if not present */
! if (ip_type(src) && strchr(tmp, '/') == NULL)
! {
! len = strlen(tmp);
! snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
! }
}
- else
- /* Go for an IPV6 address here, before faulting out: */
- elog(ERROR, "unknown address family (%d)", ip_family(src));
PG_RETURN_CSTRING(pstrdup(tmp));
}
--- 134,153 ----
inet_out(PG_FUNCTION_ARGS)
{
inet *src = PG_GETARG_INET_P(0);
! char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
char *dst;
int len;
! dst = inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
! tmp, sizeof(tmp));
! if (dst == NULL)
! elog(ERROR, "unable to print address (%s)", strerror(errno));
! /* For CIDR, add /n if not present */
! if (ip_type(src) && strchr(tmp, '/') == NULL)
{
! len = strlen(tmp);
! snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
}
PG_RETURN_CSTRING(pstrdup(tmp));
}
***************
*** 257,262 ****
--- 269,275 ----
PG_RETURN_INET_P(network_in(str, type));
}
+
Datum
text_cidr(PG_FUNCTION_ARGS)
{
***************
*** 276,283 ****
int bits = PG_GETARG_INT32(1);
inet *dst;
! if ((bits < 0) || (bits > 32)) /* no support for v6 yet */
! elog(ERROR, "set_masklen - invalid value '%d'", bits);
/* clone the original data */
dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
--- 289,299 ----
int bits = PG_GETARG_INT32(1);
inet *dst;
! if ( bits == -1 )
! bits = ip_maxbits(src);
!
! if ((bits < 0) || (bits > ip_maxbits(src)))
! elog(ERROR, "set_masklen - invalid value '%d'", bits);
/* clone the original data */
dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
***************
*** 302,327 ****
static int32
network_cmp_internal(inet *a1, inet *a2)
{
! if (ip_family(a1) == AF_INET && ip_family(a2) == AF_INET)
{
int order;
! order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2),
! Min(ip_bits(a1), ip_bits(a2)));
if (order != 0)
return order;
order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
if (order != 0)
return order;
! return v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), 32);
! }
! else
! {
! /* Go for an IPV6 address here, before faulting out: */
! elog(ERROR, "cannot compare address families %d and %d",
! ip_family(a1), ip_family(a2));
! return 0; /* keep compiler quiet */
}
}
Datum
--- 318,338 ----
static int32
network_cmp_internal(inet *a1, inet *a2)
{
! if (ip_family(a1) == ip_family(a2))
{
int order;
! order = bitncmp(ip_addr(a1), ip_addr(a2),
! Min(ip_bits(a1), ip_bits(a2)));
if (order != 0)
return order;
order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
if (order != 0)
return order;
! return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
}
+
+ return ip_family(a1) - ip_family(a2);
}
Datum
***************
*** 399,416 ****
inet *a1 = PG_GETARG_INET_P(0);
inet *a2 = PG_GETARG_INET_P(1);
! if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2)
! && v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0);
! }
! else
! {
! /* Go for an IPV6 address here, before faulting out: */
! elog(ERROR, "cannot compare address families %d and %d",
! ip_family(a1), ip_family(a2));
! PG_RETURN_BOOL(false);
}
}
Datum
--- 410,422 ----
inet *a1 = PG_GETARG_INET_P(0);
inet *a2 = PG_GETARG_INET_P(1);
! if (ip_family(a1) == ip_family(a2))
{
PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2)
! && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
}
+
+ PG_RETURN_BOOL(false);
}
Datum
***************
*** 419,436 ****
inet *a1 = PG_GETARG_INET_P(0);
inet *a2 = PG_GETARG_INET_P(1);
! if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2)
! && v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0);
! }
! else
! {
! /* Go for an IPV6 address here, before faulting out: */
! elog(ERROR, "cannot compare address families %d and %d",
! ip_family(a1), ip_family(a2));
! PG_RETURN_BOOL(false);
}
}
Datum
--- 425,437 ----
inet *a1 = PG_GETARG_INET_P(0);
inet *a2 = PG_GETARG_INET_P(1);
! if (ip_family(a1) == ip_family(a2))
{
PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2)
! && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
}
+
+ PG_RETURN_BOOL(false);
}
Datum
***************
*** 439,456 ****
inet *a1 = PG_GETARG_INET_P(0);
inet *a2 = PG_GETARG_INET_P(1);
! if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2)
! && v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0);
! }
! else
! {
! /* Go for an IPV6 address here, before faulting out: */
! elog(ERROR, "cannot compare address families %d and %d",
! ip_family(a1), ip_family(a2));
! PG_RETURN_BOOL(false);
}
}
Datum
--- 440,452 ----
inet *a1 = PG_GETARG_INET_P(0);
inet *a2 = PG_GETARG_INET_P(1);
! if (ip_family(a1) == ip_family(a2))
{
PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2)
! && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
}
+
+ PG_RETURN_BOOL(false);
}
Datum
***************
*** 459,476 ****
inet *a1 = PG_GETARG_INET_P(0);
inet *a2 = PG_GETARG_INET_P(1);
! if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2)
! && v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0);
! }
! else
! {
! /* Go for an IPV6 address here, before faulting out: */
! elog(ERROR, "cannot compare address families %d and %d",
! ip_family(a1), ip_family(a2));
! PG_RETURN_BOOL(false);
}
}
/*
--- 455,467 ----
inet *a1 = PG_GETARG_INET_P(0);
inet *a2 = PG_GETARG_INET_P(1);
! if (ip_family(a1) == ip_family(a2))
{
PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2)
! && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
}
+
+ PG_RETURN_BOOL(false);
}
/*
***************
*** 482,500 ****
inet *ip = PG_GETARG_INET_P(0);
text *ret;
int len;
! char *ptr,
! tmp[sizeof("255.255.255.255/32")];
! if (ip_family(ip) == AF_INET)
! {
! /* It's an IP V4 address: */
! /* force display of 32 bits, regardless of masklen... */
! if (inet_net_ntop(AF_INET, &ip_v4addr(ip), 32, tmp, sizeof(tmp)) == NULL)
! elog(ERROR, "unable to print host (%s)", strerror(errno));
! }
! else
! /* Go for an IPV6 address here, before faulting out: */
! elog(ERROR, "unknown address family (%d)", ip_family(ip));
/* Suppress /n if present (shouldn't happen now) */
if ((ptr = strchr(tmp, '/')) != NULL)
--- 473,485 ----
inet *ip = PG_GETARG_INET_P(0);
text *ret;
int len;
! char *ptr;
! char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
! /* force display of max bits, regardless of masklen... */
! if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
! tmp, sizeof(tmp)) == NULL)
! elog(ERROR, "unable to print host (%s)", strerror(errno));
/* Suppress /n if present (shouldn't happen now) */
if ((ptr = strchr(tmp, '/')) != NULL)
***************
*** 514,537 ****
inet *ip = PG_GETARG_INET_P(0);
text *ret;
int len;
! char tmp[sizeof("255.255.255.255/32")];
! if (ip_family(ip) == AF_INET)
{
! /* It's an IP V4 address: */
! /* force display of 32 bits, regardless of masklen... */
! if (inet_net_ntop(AF_INET, &ip_v4addr(ip), 32, tmp, sizeof(tmp)) == NULL)
! elog(ERROR, "unable to print host (%s)", strerror(errno));
! /* Add /n if not present (which it won't be) */
! if (strchr(tmp, '/') == NULL)
! {
! len = strlen(tmp);
! snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
! }
}
- else
- /* Go for an IPV6 address here, before faulting out: */
- elog(ERROR, "unknown address family (%d)", ip_family(ip));
/* Return string as a text datum */
len = strlen(tmp);
--- 499,515 ----
inet *ip = PG_GETARG_INET_P(0);
text *ret;
int len;
! char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
! if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
! tmp, sizeof(tmp)) == NULL)
! elog(ERROR, "unable to print host (%s)", strerror(errno));
! /* Add /n if not present (which it won't be) */
! if (strchr(tmp, '/') == NULL)
{
! len = strlen(tmp);
! snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
}
/* Return string as a text datum */
len = strlen(tmp);
***************
*** 548,571 ****
text *ret;
char *dst;
int len;
! char tmp[sizeof("255.255.255.255/32")];
! if (ip_family(ip) == AF_INET)
! {
! /* It's an IP V4 address: */
! if (ip_type(ip))
! dst = inet_cidr_ntop(AF_INET, &ip_v4addr(ip), ip_bits(ip),
! tmp, sizeof(tmp));
! else
! dst = inet_net_ntop(AF_INET, &ip_v4addr(ip), ip_bits(ip),
! tmp, sizeof(tmp));
!
! if (dst == NULL)
! elog(ERROR, "unable to print address (%s)", strerror(errno));
! }
! else
! /* Go for an IPV6 address here, before faulting out: */
! elog(ERROR, "unknown address family (%d)", ip_family(ip));
/* Return string as a text datum */
len = strlen(tmp);
--- 526,543 ----
text *ret;
char *dst;
int len;
! char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
! if (ip_type(ip))
! dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip),
! ip_bits(ip), tmp, sizeof(tmp));
! else
! dst = inet_net_ntop(ip_family(ip), ip_addr(ip),
! ip_bits(ip), tmp, sizeof(tmp));
!
! if (dst == NULL)
! elog(ERROR, "unable to print address (%s)",
! strerror(errno));
/* Return string as a text datum */
len = strlen(tmp);
***************
*** 584,622 ****
}
Datum
network_broadcast(PG_FUNCTION_ARGS)
{
inet *ip = PG_GETARG_INET_P(0);
inet *dst;
/* make sure any unused bits are zeroed */
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
! if (ip_family(ip) == AF_INET)
! {
! /* It's an IP V4 address: */
! unsigned long mask = 0xffffffff;
!
! /*
! * Shifting by 32 or more bits does not yield portable results, so
! * don't try it.
! */
! if (ip_bits(ip) < 32)
! mask >>= ip_bits(ip);
! else
! mask = 0;
!
! ip_v4addr(dst) = htonl(ntohl(ip_v4addr(ip)) | mask);
}
- else
- /* Go for an IPV6 address here, before faulting out: */
- elog(ERROR, "unknown address family (%d)", ip_family(ip));
ip_family(dst) = ip_family(ip);
ip_bits(dst) = ip_bits(ip);
ip_type(dst) = 0;
VARATT_SIZEP(dst) = VARHDRSZ
! + ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
PG_RETURN_INET_P(dst);
--- 556,621 ----
}
Datum
+ network_family(PG_FUNCTION_ARGS)
+ {
+ inet *ip = PG_GETARG_INET_P(0);
+
+ switch (ip_family(ip)) {
+ case PGSQL_AF_INET:
+ PG_RETURN_INT32(4);
+ break;
+ case PGSQL_AF_INET6:
+ PG_RETURN_INT32(6);
+ break;
+ default:
+ PG_RETURN_INT32(0);
+ break;
+ }
+ }
+
+ Datum
network_broadcast(PG_FUNCTION_ARGS)
{
inet *ip = PG_GETARG_INET_P(0);
inet *dst;
+ int byte;
+ int bits;
+ int maxbytes;
+ unsigned char mask;
+ unsigned char *a, *b;
/* make sure any unused bits are zeroed */
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
! if (ip_family(ip) == PGSQL_AF_INET) {
! maxbytes = 4;
! } else {
! maxbytes = 16;
! }
!
! bits = ip_bits(ip);
! a = ip_addr(ip);
! b = ip_addr(dst);
!
! for (byte = 0 ; byte < maxbytes ; byte++) {
! if (bits >= 8) {
! mask = 0x00;
! bits -= 8;
! } else if (bits == 0) {
! mask = 0xff;
! } else {
! mask = 0xff >> bits;
! bits = 0;
! }
!
! b[byte] = a[byte] | mask;
}
ip_family(dst) = ip_family(ip);
ip_bits(dst) = ip_bits(ip);
ip_type(dst) = 0;
VARATT_SIZEP(dst) = VARHDRSZ
! + ((char *)ip_addr(dst) - (char *)VARDATA(dst))
+ ip_addrsize(dst);
PG_RETURN_INET_P(dst);
***************
*** 627,661 ****
{
inet *ip = PG_GETARG_INET_P(0);
inet *dst;
/* make sure any unused bits are zeroed */
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
! if (ip_family(ip) == AF_INET)
! {
! /* It's an IP V4 address: */
! unsigned long mask = 0xffffffff;
!
! /*
! * Shifting by 32 or more bits does not yield portable results, so
! * don't try it.
! */
! if (ip_bits(ip) > 0)
! mask <<= (32 - ip_bits(ip));
! else
! mask = 0;
!
! ip_v4addr(dst) = htonl(ntohl(ip_v4addr(ip)) & mask);
}
- else
- /* Go for an IPV6 address here, before faulting out: */
- elog(ERROR, "unknown address family (%d)", ip_family(ip));
ip_family(dst) = ip_family(ip);
ip_bits(dst) = ip_bits(ip);
ip_type(dst) = 1;
VARATT_SIZEP(dst) = VARHDRSZ
! + ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
PG_RETURN_INET_P(dst);
--- 626,669 ----
{
inet *ip = PG_GETARG_INET_P(0);
inet *dst;
+ int byte;
+ int bits;
+ int maxbytes;
+ unsigned char mask;
+ unsigned char *a, *b;
/* make sure any unused bits are zeroed */
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
! if (ip_family(ip) == PGSQL_AF_INET) {
! maxbytes = 4;
! } else {
! maxbytes = 16;
! }
!
! bits = ip_bits(ip);
! a = ip_addr(ip);
! b = ip_addr(dst);
!
! byte = 0;
! while (bits) {
! if (bits >= 8) {
! mask = 0xff;
! bits -= 8;
! } else {
! mask = 0xff << (8 - bits);
! bits = 0;
! }
!
! b[byte] = a[byte] & mask;
! byte++;
}
ip_family(dst) = ip_family(ip);
ip_bits(dst) = ip_bits(ip);
ip_type(dst) = 1;
VARATT_SIZEP(dst) = VARHDRSZ
! + ((char *)ip_addr(dst) - (char *)VARDATA(dst))
+ ip_addrsize(dst);
PG_RETURN_INET_P(dst);
***************
*** 666,701 ****
{
inet *ip = PG_GETARG_INET_P(0);
inet *dst;
/* make sure any unused bits are zeroed */
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
! if (ip_family(ip) == AF_INET)
! {
! /* It's an IP V4 address: */
! unsigned long mask = 0xffffffff;
!
! /*
! * Shifting by 32 or more bits does not yield portable results, so
! * don't try it.
! */
! if (ip_bits(ip) > 0)
! mask <<= (32 - ip_bits(ip));
! else
! mask = 0;
!
! ip_v4addr(dst) = htonl(mask);
!
! ip_bits(dst) = 32;
}
- else
- /* Go for an IPV6 address here, before faulting out: */
- elog(ERROR, "unknown address family (%d)", ip_family(ip));
ip_family(dst) = ip_family(ip);
ip_type(dst) = 0;
VARATT_SIZEP(dst) = VARHDRSZ
! + ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
PG_RETURN_INET_P(dst);
--- 674,716 ----
{
inet *ip = PG_GETARG_INET_P(0);
inet *dst;
+ int byte;
+ int bits;
+ int maxbytes;
+ unsigned char mask;
+ unsigned char *b;
/* make sure any unused bits are zeroed */
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
! if (ip_family(ip) == PGSQL_AF_INET) {
! maxbytes = 4;
! } else {
! maxbytes = 16;
! }
!
! bits = ip_bits(ip);
! b = ip_addr(dst);
!
! byte = 0;
! while (bits) {
! if (bits >= 8) {
! mask = 0xff;
! bits -= 8;
! } else {
! mask = 0xff << (8 - bits);
! bits = 0;
! }
!
! b[byte] = mask;
! byte++;
}
ip_family(dst) = ip_family(ip);
+ ip_bits(dst) = ip_bits(ip);
ip_type(dst) = 0;
VARATT_SIZEP(dst) = VARHDRSZ
! + ((char *)ip_addr(dst) - (char *)VARDATA(dst))
+ ip_addrsize(dst);
PG_RETURN_INET_P(dst);
***************
*** 760,771 ****
case CIDROID:
{
inet *ip = DatumGetInetP(value);
!
! if (ip_family(ip) == AF_INET)
! return (double) ip_v4addr(ip);
else
! /* Go for an IPV6 address here, before faulting out: */
! elog(ERROR, "unknown address family (%d)", ip_family(ip));
break;
}
case MACADDROID:
--- 775,800 ----
case CIDROID:
{
inet *ip = DatumGetInetP(value);
! int len;
! double res;
! int i;
!
! /*
! * Note that we don't use the full address
! * here.
! */
! if (ip_family(ip) == PGSQL_AF_INET)
! len = 4;
else
! len = 5;
!
! res = ip_family(ip);
! for (i = 0 ; i < len ; i++) {
! res *= 256;
! res += ip_addr(ip)[i];
! }
! return res;
!
break;
}
case MACADDROID:
***************
*** 788,840 ****
return 0;
}
-
/*
! * Bitwise comparison for V4 addresses. Add V6 implementation!
*/
-
static int
! v4bitncmp(unsigned long a1, unsigned long a2, int bits)
{
! unsigned long mask;
! /*
! * Shifting by 32 or more bits does not yield portable results, so
! * don't try it.
! */
! if (bits > 0)
! mask = (0xFFFFFFFFL << (32 - bits)) & 0xFFFFFFFFL;
! else
! mask = 0;
! a1 = ntohl(a1);
! a2 = ntohl(a2);
! if ((a1 & mask) < (a2 & mask))
! return (-1);
! else if ((a1 & mask) > (a2 & mask))
! return (1);
return (0);
}
- /*
- * Returns true if given address fits fully within the specified bit width.
- */
static bool
! v4addressOK(unsigned long a1, int bits)
{
! unsigned long mask;
! /*
! * Shifting by 32 or more bits does not yield portable results, so
! * don't try it.
! */
! if (bits > 0)
! mask = (0xFFFFFFFFL << (32 - bits)) & 0xFFFFFFFFL;
! else
! mask = 0;
! a1 = ntohl(a1);
! if ((a1 & mask) == a1)
! return true;
! return false;
}
--- 817,894 ----
return 0;
}
/*
! * int
! * bitncmp(l, r, n)
! * compare bit masks l and r, for n bits.
! * return:
! * -1, 1, or 0 in the libc tradition.
! * note:
! * network byte order assumed. this means 192.5.5.240/28 has
! * 0x11110000 in its fourth octet.
! * author:
! * Paul Vixie (ISC), June 1996
*/
static int
! bitncmp(void *l, void *r, int n)
{
! u_int lb, rb;
! int x, b;
! b = n / 8;
! x = memcmp(l, r, b);
! if (x)
! return (x);
!
! lb = ((const u_char *)l)[b];
! rb = ((const u_char *)r)[b];
! for (b = n % 8; b > 0; b--) {
! if ((lb & 0x80) != (rb & 0x80)) {
! if (lb & 0x80)
! return (1);
! return (-1);
! }
! lb <<= 1;
! rb <<= 1;
! }
return (0);
}
static bool
! addressOK(unsigned char *a, int bits, int family)
{
! int byte;
! int nbits;
! int maxbits;
! int maxbytes;
! unsigned char mask;
!
! if (family == PGSQL_AF_INET) {
! maxbits = 32;
! maxbytes = 4;
! } else {
! maxbits = 128;
! maxbytes = 16;
! }
! assert(bits <= maxbits);
!
! if (bits == maxbits)
! return 1;
!
! byte = (bits + 7) / 8;
! nbits = bits % 8;
! mask = 0xff;
! if (bits != 0)
! mask >>= nbits;
!
! while (byte < maxbytes) {
! if ((a[byte] & mask) != 0)
! return 0;
! mask = 0xff;
! byte++;
! }
! return 1;
}
***************
*** 852,866 ****
/*
* return "last" IP on a given network. It's the broadcast address,
! * however, masklen has to be set to 32, since
* 192.168.0.255/24 is considered less than 192.168.0.255/32
*
! * NB: this is not IPv6 ready ...
*/
Datum
network_scan_last(Datum in)
{
return DirectFunctionCall2(inet_set_masklen,
DirectFunctionCall1(network_broadcast, in),
! Int32GetDatum(32));
}
--- 906,921 ----
/*
* return "last" IP on a given network. It's the broadcast address,
! * however, masklen has to be set to its max btis, since
* 192.168.0.255/24 is considered less than 192.168.0.255/32
*
! * inet_set_masklen() hacked to max out the masklength to 128 for IPv6
! * and 32 for IPv4 when given '-1' as argument.
*/
Datum
network_scan_last(Datum in)
{
return DirectFunctionCall2(inet_set_masklen,
DirectFunctionCall1(network_broadcast, in),
! Int32GetDatum(-1));
}
Index: src/include/catalog/catversion.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/catalog/catversion.h,v
retrieving revision 1.198
diff -c -c -r1.198 catversion.h
*** src/include/catalog/catversion.h 6 Jun 2003 15:04:02 -0000 1.198
--- src/include/catalog/catversion.h 12 Jun 2003 05:13:20 -0000
***************
*** 53,58 ****
*/
/* yyyymmddN */
! #define CATALOG_VERSION_NO 200306051
#endif
--- 53,58 ----
*/
/* yyyymmddN */
! #define CATALOG_VERSION_NO 200306121
#endif
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
retrieving revision 1.303
diff -c -c -r1.303 pg_proc.h
*** src/include/catalog/pg_proc.h 11 Jun 2003 09:23:55 -0000 1.303
--- src/include/catalog/pg_proc.h 12 Jun 2003 05:13:24 -0000
***************
*** 2377,2382 ****
--- 2377,2384 ----
DESCR("show address octets only");
DATA(insert OID = 730 ( text PGNSP PGUID 12 f f t f i 1 25 "869" network_show - _null_ ));
DESCR("show all parts of inet/cidr value");
+ DATA(insert OID = 715 ( family PGNSP PGUID 12 f f t f i 1 23 "869" network_family - _null_ ));
+ DESCR("return address family (4 for IPv4, 6 for IPv6)");
DATA(insert OID = 1362 ( hostmask PGNSP PGUID 12 f f t f i 1 869 "869" network_hostmask - _null_ ));
DESCR("hostmask of address");
DATA(insert OID = 1713 ( inet PGNSP PGUID 12 f f t f i 1 869 "25" text_inet - _null_ ));
Index: src/include/utils/builtins.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/utils/builtins.h,v
retrieving revision 1.219
diff -c -c -r1.219 builtins.h
*** src/include/utils/builtins.h 26 May 2003 00:11:28 -0000 1.219
--- src/include/utils/builtins.h 12 Jun 2003 05:13:25 -0000
***************
*** 644,649 ****
--- 644,650 ----
extern Datum network_netmask(PG_FUNCTION_ARGS);
extern Datum network_hostmask(PG_FUNCTION_ARGS);
extern Datum network_masklen(PG_FUNCTION_ARGS);
+ extern Datum network_family(PG_FUNCTION_ARGS);
extern Datum network_broadcast(PG_FUNCTION_ARGS);
extern Datum network_host(PG_FUNCTION_ARGS);
extern Datum network_show(PG_FUNCTION_ARGS);
Index: src/include/utils/inet.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/utils/inet.h,v
retrieving revision 1.13
diff -c -c -r1.13 inet.h
*** src/include/utils/inet.h 20 Jun 2002 20:29:53 -0000 1.13
--- src/include/utils/inet.h 12 Jun 2003 05:13:25 -0000
***************
*** 23,34 ****
unsigned char family;
unsigned char bits;
unsigned char type;
! union
! {
! unsigned int ipv4_addr; /* network byte order */
! /* add IPV6 address type here */
! } addr;
} inet_struct;
/*
* Both INET and CIDR addresses are represented within Postgres as varlena
--- 23,40 ----
unsigned char family;
unsigned char bits;
unsigned char type;
! unsigned char ip_addr[16]; /* 128 bits of address */
} inet_struct;
+
+ /*
+ * Referencing all of the non-AF_INET types to AF_INET lets us work on
+ * machines which may not have the appropriate address family (like
+ * inet6 addresses when AF_INET6 isn't present) but doesn't cause a
+ * dump/reload requirement. Existing databases used AF_INET for the family
+ * type on disk.
+ */
+ #define PGSQL_AF_INET (AF_INET + 0)
+ #define PGSQL_AF_INET6 (AF_INET + 1)
/*
* Both INET and CIDR addresses are represented within Postgres as varlena
Index: src/test/regress/expected/inet.out
===================================================================
RCS file: /cvsroot/pgsql-server/src/test/regress/expected/inet.out,v
retrieving revision 1.15
diff -c -c -r1.15 inet.out
*** src/test/regress/expected/inet.out 15 Jan 2003 20:01:01 -0000 1.15
--- src/test/regress/expected/inet.out 12 Jun 2003 05:13:26 -0000
***************
*** 19,128 ****
INSERT INTO INET_TBL (c, i) VALUES ('10', '10.1.2.3/8');
INSERT INTO INET_TBL (c, i) VALUES ('10', '11.1.2.3/8');
INSERT INTO INET_TBL (c, i) VALUES ('10', '9.1.2.3/8');
-- check that CIDR rejects invalid input:
INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/24', '192.168.1.226');
ERROR: invalid CIDR value '192.168.1.2/24': has bits set to right of mask
-- check that CIDR rejects invalid input when converting from text:
INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/24'), '192.168.1.226');
ERROR: invalid CIDR value '192.168.1.2/24': has bits set to right of mask
SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL;
! ten | cidr | inet
! -----+----------------+------------------
! | 192.168.1.0/24 | 192.168.1.226/24
! | 192.168.1.0/24 | 192.168.1.226
! | 192.168.1.0/24 | 192.168.1.0/24
! | 192.168.1.0/24 | 192.168.1.0/25
! | 192.168.1.0/24 | 192.168.1.255/24
! | 192.168.1.0/24 | 192.168.1.255/25
! | 10.0.0.0/8 | 10.1.2.3/8
! | 10.0.0.0/32 | 10.1.2.3/8
! | 10.1.2.3/32 | 10.1.2.3
! | 10.1.2.0/24 | 10.1.2.3/24
! | 10.1.0.0/16 | 10.1.2.3/16
! | 10.0.0.0/8 | 10.1.2.3/8
! | 10.0.0.0/8 | 11.1.2.3/8
! | 10.0.0.0/8 | 9.1.2.3/8
! (14 rows)
-- now test some support functions
! SELECT '' AS ten, i AS inet, host(i), text(i) FROM INET_TBL;
! ten | inet | host | text
! -----+------------------+---------------+------------------
! | 192.168.1.226/24 | 192.168.1.226 | 192.168.1.226/24
! | 192.168.1.226 | 192.168.1.226 | 192.168.1.226/32
! | 192.168.1.0/24 | 192.168.1.0 | 192.168.1.0/24
! | 192.168.1.0/25 | 192.168.1.0 | 192.168.1.0/25
! | 192.168.1.255/24 | 192.168.1.255 | 192.168.1.255/24
! | 192.168.1.255/25 | 192.168.1.255 | 192.168.1.255/25
! | 10.1.2.3/8 | 10.1.2.3 | 10.1.2.3/8
! | 10.1.2.3/8 | 10.1.2.3 | 10.1.2.3/8
! | 10.1.2.3 | 10.1.2.3 | 10.1.2.3/32
! | 10.1.2.3/24 | 10.1.2.3 | 10.1.2.3/24
! | 10.1.2.3/16 | 10.1.2.3 | 10.1.2.3/16
! | 10.1.2.3/8 | 10.1.2.3 | 10.1.2.3/8
! | 11.1.2.3/8 | 11.1.2.3 | 11.1.2.3/8
! | 9.1.2.3/8 | 9.1.2.3 | 9.1.2.3/8
! (14 rows)
SELECT '' AS ten, c AS cidr, broadcast(c),
i AS inet, broadcast(i) FROM INET_TBL;
! ten | cidr | broadcast | inet | broadcast
! -----+----------------+------------------+------------------+------------------
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.226/24 | 192.168.1.255/24
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.226 | 192.168.1.226
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.0/24 | 192.168.1.255/24
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.0/25 | 192.168.1.127/25
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.255/24 | 192.168.1.255/24
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.255/25 | 192.168.1.255/25
! | 10.0.0.0/8 | 10.255.255.255/8 | 10.1.2.3/8 | 10.255.255.255/8
! | 10.0.0.0/32 | 10.0.0.0 | 10.1.2.3/8 | 10.255.255.255/8
! | 10.1.2.3/32 | 10.1.2.3 | 10.1.2.3 | 10.1.2.3
! | 10.1.2.0/24 | 10.1.2.255/24 | 10.1.2.3/24 | 10.1.2.255/24
! | 10.1.0.0/16 | 10.1.255.255/16 | 10.1.2.3/16 | 10.1.255.255/16
! | 10.0.0.0/8 | 10.255.255.255/8 | 10.1.2.3/8 | 10.255.255.255/8
! | 10.0.0.0/8 | 10.255.255.255/8 | 11.1.2.3/8 | 11.255.255.255/8
! | 10.0.0.0/8 | 10.255.255.255/8 | 9.1.2.3/8 | 9.255.255.255/8
! (14 rows)
SELECT '' AS ten, c AS cidr, network(c) AS "network(cidr)",
i AS inet, network(i) AS "network(inet)" FROM INET_TBL;
! ten | cidr | network(cidr) | inet | network(inet)
! -----+----------------+----------------+------------------+------------------
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.226/24 | 192.168.1.0/24
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.226 | 192.168.1.226/32
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.0/24
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.0/25 | 192.168.1.0/25
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.0/24
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.255/25 | 192.168.1.128/25
! | 10.0.0.0/8 | 10.0.0.0/8 | 10.1.2.3/8 | 10.0.0.0/8
! | 10.0.0.0/32 | 10.0.0.0/32 | 10.1.2.3/8 | 10.0.0.0/8
! | 10.1.2.3/32 | 10.1.2.3/32 | 10.1.2.3 | 10.1.2.3/32
! | 10.1.2.0/24 | 10.1.2.0/24 | 10.1.2.3/24 | 10.1.2.0/24
! | 10.1.0.0/16 | 10.1.0.0/16 | 10.1.2.3/16 | 10.1.0.0/16
! | 10.0.0.0/8 | 10.0.0.0/8 | 10.1.2.3/8 | 10.0.0.0/8
! | 10.0.0.0/8 | 10.0.0.0/8 | 11.1.2.3/8 | 11.0.0.0/8
! | 10.0.0.0/8 | 10.0.0.0/8 | 9.1.2.3/8 | 9.0.0.0/8
! (14 rows)
SELECT '' AS ten, c AS cidr, masklen(c) AS "masklen(cidr)",
i AS inet, masklen(i) AS "masklen(inet)" FROM INET_TBL;
! ten | cidr | masklen(cidr) | inet | masklen(inet)
! -----+----------------+---------------+------------------+---------------
! | 192.168.1.0/24 | 24 | 192.168.1.226/24 | 24
! | 192.168.1.0/24 | 24 | 192.168.1.226 | 32
! | 192.168.1.0/24 | 24 | 192.168.1.0/24 | 24
! | 192.168.1.0/24 | 24 | 192.168.1.0/25 | 25
! | 192.168.1.0/24 | 24 | 192.168.1.255/24 | 24
! | 192.168.1.0/24 | 24 | 192.168.1.255/25 | 25
! | 10.0.0.0/8 | 8 | 10.1.2.3/8 | 8
! | 10.0.0.0/32 | 32 | 10.1.2.3/8 | 8
! | 10.1.2.3/32 | 32 | 10.1.2.3 | 32
! | 10.1.2.0/24 | 24 | 10.1.2.3/24 | 24
! | 10.1.0.0/16 | 16 | 10.1.2.3/16 | 16
! | 10.0.0.0/8 | 8 | 10.1.2.3/8 | 8
! | 10.0.0.0/8 | 8 | 11.1.2.3/8 | 8
! | 10.0.0.0/8 | 8 | 9.1.2.3/8 | 8
! (14 rows)
SELECT '' AS four, c AS cidr, masklen(c) AS "masklen(cidr)",
i AS inet, masklen(i) AS "masklen(inet)" FROM INET_TBL
--- 19,150 ----
INSERT INTO INET_TBL (c, i) VALUES ('10', '10.1.2.3/8');
INSERT INTO INET_TBL (c, i) VALUES ('10', '11.1.2.3/8');
INSERT INTO INET_TBL (c, i) VALUES ('10', '9.1.2.3/8');
+ INSERT INTO INET_TBL (c, i) VALUES ('10:23::f1', '10:23::f1/64');
+ INSERT INTO INET_TBL (c, i) VALUES ('10:23::8000/113', '10:23::ffff');
+ INSERT INTO INET_TBL (c, i) VALUES ('::ffff:1.2.3.4', '::4.3.2.1/24');
-- check that CIDR rejects invalid input:
INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/24', '192.168.1.226');
ERROR: invalid CIDR value '192.168.1.2/24': has bits set to right of mask
+ INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1.2.3.4');
+ ERROR: invalid CIDR value '1234::1234::1234'
-- check that CIDR rejects invalid input when converting from text:
INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/24'), '192.168.1.226');
ERROR: invalid CIDR value '192.168.1.2/24': has bits set to right of mask
+ INSERT INTO INET_TBL (c, i) VALUES (cidr('ffff:ffff:ffff:ffff::/24'), '::192.168.1.226');
+ ERROR: invalid CIDR value 'ffff:ffff:ffff:ffff::/24': has bits set to right of mask
SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL;
! ten | cidr | inet
! -----+--------------------+------------------
! | 192.168.1.0/24 | 192.168.1.226/24
! | 192.168.1.0/24 | 192.168.1.226
! | 192.168.1.0/24 | 192.168.1.0/24
! | 192.168.1.0/24 | 192.168.1.0/25
! | 192.168.1.0/24 | 192.168.1.255/24
! | 192.168.1.0/24 | 192.168.1.255/25
! | 10.0.0.0/8 | 10.1.2.3/8
! | 10.0.0.0/32 | 10.1.2.3/8
! | 10.1.2.3/32 | 10.1.2.3
! | 10.1.2.0/24 | 10.1.2.3/24
! | 10.1.0.0/16 | 10.1.2.3/16
! | 10.0.0.0/8 | 10.1.2.3/8
! | 10.0.0.0/8 | 11.1.2.3/8
! | 10.0.0.0/8 | 9.1.2.3/8
! | 10:23::f1/128 | 10:23::f1/64
! | 10:23::8000/113 | 10:23::ffff
! | ::ffff:1.2.3.4/128 | ::4.3.2.1/24
! (17 rows)
-- now test some support functions
! SELECT '' AS ten, i AS inet, host(i), text(i), family(i) FROM INET_TBL;
! ten | inet | host | text | family
! -----+------------------+---------------+------------------+--------
! | 192.168.1.226/24 | 192.168.1.226 | 192.168.1.226/24 | 4
! | 192.168.1.226 | 192.168.1.226 | 192.168.1.226/32 | 4
! | 192.168.1.0/24 | 192.168.1.0 | 192.168.1.0/24 | 4
! | 192.168.1.0/25 | 192.168.1.0 | 192.168.1.0/25 | 4
! | 192.168.1.255/24 | 192.168.1.255 | 192.168.1.255/24 | 4
! | 192.168.1.255/25 | 192.168.1.255 | 192.168.1.255/25 | 4
! | 10.1.2.3/8 | 10.1.2.3 | 10.1.2.3/8 | 4
! | 10.1.2.3/8 | 10.1.2.3 | 10.1.2.3/8 | 4
! | 10.1.2.3 | 10.1.2.3 | 10.1.2.3/32 | 4
! | 10.1.2.3/24 | 10.1.2.3 | 10.1.2.3/24 | 4
! | 10.1.2.3/16 | 10.1.2.3 | 10.1.2.3/16 | 4
! | 10.1.2.3/8 | 10.1.2.3 | 10.1.2.3/8 | 4
! | 11.1.2.3/8 | 11.1.2.3 | 11.1.2.3/8 | 4
! | 9.1.2.3/8 | 9.1.2.3 | 9.1.2.3/8 | 4
! | 10:23::f1/64 | 10:23::f1 | 10:23::f1/64 | 6
! | 10:23::ffff | 10:23::ffff | 10:23::ffff/128 | 6
! | ::4.3.2.1/24 | ::4.3.2.1 | ::4.3.2.1/24 | 6
! (17 rows)
SELECT '' AS ten, c AS cidr, broadcast(c),
i AS inet, broadcast(i) FROM INET_TBL;
! ten | cidr | broadcast | inet | broadcast
! -----+--------------------+------------------+------------------+---------------------------------------
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.226/24 | 192.168.1.255/24
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.226 | 192.168.1.226
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.0/24 | 192.168.1.255/24
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.0/25 | 192.168.1.127/25
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.255/24 | 192.168.1.255/24
! | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.255/25 | 192.168.1.255/25
! | 10.0.0.0/8 | 10.255.255.255/8 | 10.1.2.3/8 | 10.255.255.255/8
! | 10.0.0.0/32 | 10.0.0.0 | 10.1.2.3/8 | 10.255.255.255/8
! | 10.1.2.3/32 | 10.1.2.3 | 10.1.2.3 | 10.1.2.3
! | 10.1.2.0/24 | 10.1.2.255/24 | 10.1.2.3/24 | 10.1.2.255/24
! | 10.1.0.0/16 | 10.1.255.255/16 | 10.1.2.3/16 | 10.1.255.255/16
! | 10.0.0.0/8 | 10.255.255.255/8 | 10.1.2.3/8 | 10.255.255.255/8
! | 10.0.0.0/8 | 10.255.255.255/8 | 11.1.2.3/8 | 11.255.255.255/8
! | 10.0.0.0/8 | 10.255.255.255/8 | 9.1.2.3/8 | 9.255.255.255/8
! | 10:23::f1/128 | 10:23::f1 | 10:23::f1/64 | 10:23::ffff:ffff:ffff:ffff/64
! | 10:23::8000/113 | 10:23::ffff/113 | 10:23::ffff | 10:23::ffff
! | ::ffff:1.2.3.4/128 | ::ffff:1.2.3.4 | ::4.3.2.1/24 | 0:ff:ffff:ffff:ffff:ffff:ffff:ffff/24
! (17 rows)
SELECT '' AS ten, c AS cidr, network(c) AS "network(cidr)",
i AS inet, network(i) AS "network(inet)" FROM INET_TBL;
! ten | cidr | network(cidr) | inet | network(inet)
! -----+--------------------+--------------------+------------------+------------------
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.226/24 | 192.168.1.0/24
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.226 | 192.168.1.226/32
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.0/24
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.0/25 | 192.168.1.0/25
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.0/24
! | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.255/25 | 192.168.1.128/25
! | 10.0.0.0/8 | 10.0.0.0/8 | 10.1.2.3/8 | 10.0.0.0/8
! | 10.0.0.0/32 | 10.0.0.0/32 | 10.1.2.3/8 | 10.0.0.0/8
! | 10.1.2.3/32 | 10.1.2.3/32 | 10.1.2.3 | 10.1.2.3/32
! | 10.1.2.0/24 | 10.1.2.0/24 | 10.1.2.3/24 | 10.1.2.0/24
! | 10.1.0.0/16 | 10.1.0.0/16 | 10.1.2.3/16 | 10.1.0.0/16
! | 10.0.0.0/8 | 10.0.0.0/8 | 10.1.2.3/8 | 10.0.0.0/8
! | 10.0.0.0/8 | 10.0.0.0/8 | 11.1.2.3/8 | 11.0.0.0/8
! | 10.0.0.0/8 | 10.0.0.0/8 | 9.1.2.3/8 | 9.0.0.0/8
! | 10:23::f1/128 | 10:23::f1/128 | 10:23::f1/64 | 10:23::/64
! | 10:23::8000/113 | 10:23::8000/113 | 10:23::ffff | 10:23::ffff/128
! | ::ffff:1.2.3.4/128 | ::ffff:1.2.3.4/128 | ::4.3.2.1/24 | ::/24
! (17 rows)
SELECT '' AS ten, c AS cidr, masklen(c) AS "masklen(cidr)",
i AS inet, masklen(i) AS "masklen(inet)" FROM INET_TBL;
! ten | cidr | masklen(cidr) | inet | masklen(inet)
! -----+--------------------+---------------+------------------+---------------
! | 192.168.1.0/24 | 24 | 192.168.1.226/24 | 24
! | 192.168.1.0/24 | 24 | 192.168.1.226 | 32
! | 192.168.1.0/24 | 24 | 192.168.1.0/24 | 24
! | 192.168.1.0/24 | 24 | 192.168.1.0/25 | 25
! | 192.168.1.0/24 | 24 | 192.168.1.255/24 | 24
! | 192.168.1.0/24 | 24 | 192.168.1.255/25 | 25
! | 10.0.0.0/8 | 8 | 10.1.2.3/8 | 8
! | 10.0.0.0/32 | 32 | 10.1.2.3/8 | 8
! | 10.1.2.3/32 | 32 | 10.1.2.3 | 32
! | 10.1.2.0/24 | 24 | 10.1.2.3/24 | 24
! | 10.1.0.0/16 | 16 | 10.1.2.3/16 | 16
! | 10.0.0.0/8 | 8 | 10.1.2.3/8 | 8
! | 10.0.0.0/8 | 8 | 11.1.2.3/8 | 8
! | 10.0.0.0/8 | 8 | 9.1.2.3/8 | 8
! | 10:23::f1/128 | 128 | 10:23::f1/64 | 64
! | 10:23::8000/113 | 113 | 10:23::ffff | 128
! | ::ffff:1.2.3.4/128 | 128 | ::4.3.2.1/24 | 24
! (17 rows)
SELECT '' AS four, c AS cidr, masklen(c) AS "masklen(cidr)",
i AS inet, masklen(i) AS "masklen(inet)" FROM INET_TBL
***************
*** 149,171 ****
i << c AS sb, i <<= c AS sbe,
i >> c AS sup, i >>= c AS spe
FROM INET_TBL;
! ten | i | c | lt | le | eq | ge | gt | ne | sb | sbe | sup | spe
! -----+------------------+----------------+----+----+----+----+----+----+----+-----+-----+-----
! | 192.168.1.226/24 | 192.168.1.0/24 | f | f | f | t | t | t | f | t | f | t
! | 192.168.1.226 | 192.168.1.0/24 | f | f | f | t | t | t | t | t | f | f
! | 192.168.1.0/24 | 192.168.1.0/24 | f | t | t | t | f | f | f | t | f | t
! | 192.168.1.0/25 | 192.168.1.0/24 | f | f | f | t | t | t | t | t | f | f
! | 192.168.1.255/24 | 192.168.1.0/24 | f | f | f | t | t | t | f | t | f | t
! | 192.168.1.255/25 | 192.168.1.0/24 | f | f | f | t | t | t | t | t | f | f
! | 10.1.2.3/8 | 10.0.0.0/8 | f | f | f | t | t | t | f | t | f | t
! | 10.1.2.3/8 | 10.0.0.0/32 | t | t | f | f | f | t | f | f | t | t
! | 10.1.2.3 | 10.1.2.3/32 | f | t | t | t | f | f | f | t | f | t
! | 10.1.2.3/24 | 10.1.2.0/24 | f | f | f | t | t | t | f | t | f | t
! | 10.1.2.3/16 | 10.1.0.0/16 | f | f | f | t | t | t | f | t | f | t
! | 10.1.2.3/8 | 10.0.0.0/8 | f | f | f | t | t | t | f | t | f | t
! | 11.1.2.3/8 | 10.0.0.0/8 | f | f | f | t | t | t | f | f | f | f
! | 9.1.2.3/8 | 10.0.0.0/8 | t | t | f | f | f | t | f | f | f | f
! (14 rows)
-- check the conversion to/from text and set_netmask
SELECT '' AS ten, set_masklen(inet(text(i)), 24) FROM INET_TBL;
--- 171,196 ----
i << c AS sb, i <<= c AS sbe,
i >> c AS sup, i >>= c AS spe
FROM INET_TBL;
! ten | i | c | lt | le | eq | ge | gt | ne | sb | sbe | sup | spe
! -----+------------------+--------------------+----+----+----+----+----+----+----+-----+-----+-----
! | 192.168.1.226/24 | 192.168.1.0/24 | f | f | f | t | t | t | f | t | f | t
! | 192.168.1.226 | 192.168.1.0/24 | f | f | f | t | t | t | t | t | f | f
! | 192.168.1.0/24 | 192.168.1.0/24 | f | t | t | t | f | f | f | t | f | t
! | 192.168.1.0/25 | 192.168.1.0/24 | f | f | f | t | t | t | t | t | f | f
! | 192.168.1.255/24 | 192.168.1.0/24 | f | f | f | t | t | t | f | t | f | t
! | 192.168.1.255/25 | 192.168.1.0/24 | f | f | f | t | t | t | t | t | f | f
! | 10.1.2.3/8 | 10.0.0.0/8 | f | f | f | t | t | t | f | t | f | t
! | 10.1.2.3/8 | 10.0.0.0/32 | t | t | f | f | f | t | f | f | t | t
! | 10.1.2.3 | 10.1.2.3/32 | f | t | t | t | f | f | f | t | f | t
! | 10.1.2.3/24 | 10.1.2.0/24 | f | f | f | t | t | t | f | t | f | t
! | 10.1.2.3/16 | 10.1.0.0/16 | f | f | f | t | t | t | f | t | f | t
! | 10.1.2.3/8 | 10.0.0.0/8 | f | f | f | t | t | t | f | t | f | t
! | 11.1.2.3/8 | 10.0.0.0/8 | f | f | f | t | t | t | f | f | f | f
! | 9.1.2.3/8 | 10.0.0.0/8 | t | t | f | f | f | t | f | f | f | f
! | 10:23::f1/64 | 10:23::f1/128 | t | t | f | f | f | t | f | f | t | t
! | 10:23::ffff | 10:23::8000/113 | f | f | f | t | t | t | t | t | f | f
! | ::4.3.2.1/24 | ::ffff:1.2.3.4/128 | t | t | f | f | f | t | f | f | t | t
! (17 rows)
-- check the conversion to/from text and set_netmask
SELECT '' AS ten, set_masklen(inet(text(i)), 24) FROM INET_TBL;
***************
*** 185,191 ****
| 10.1.2.3/24
| 11.1.2.3/24
| 9.1.2.3/24
! (14 rows)
-- check that index works correctly
CREATE INDEX inet_idx1 ON inet_tbl(i);
--- 210,219 ----
| 10.1.2.3/24
| 11.1.2.3/24
| 9.1.2.3/24
! | 10:23::f1/24
! | 10:23::ffff/24
! | ::4.3.2.1/24
! (17 rows)
-- check that index works correctly
CREATE INDEX inet_idx1 ON inet_tbl(i);
Index: src/test/regress/sql/inet.sql
===================================================================
RCS file: /cvsroot/pgsql-server/src/test/regress/sql/inet.sql,v
retrieving revision 1.9
diff -c -c -r1.9 inet.sql
*** src/test/regress/sql/inet.sql 15 Jan 2003 20:01:01 -0000 1.9
--- src/test/regress/sql/inet.sql 12 Jun 2003 05:13:26 -0000
***************
*** 20,35 ****
INSERT INTO INET_TBL (c, i) VALUES ('10', '10.1.2.3/8');
INSERT INTO INET_TBL (c, i) VALUES ('10', '11.1.2.3/8');
INSERT INTO INET_TBL (c, i) VALUES ('10', '9.1.2.3/8');
-- check that CIDR rejects invalid input:
INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/24', '192.168.1.226');
-- check that CIDR rejects invalid input when converting from text:
INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/24'), '192.168.1.226');
!
SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL;
-- now test some support functions
! SELECT '' AS ten, i AS inet, host(i), text(i) FROM INET_TBL;
SELECT '' AS ten, c AS cidr, broadcast(c),
i AS inet, broadcast(i) FROM INET_TBL;
SELECT '' AS ten, c AS cidr, network(c) AS "network(cidr)",
--- 20,39 ----
INSERT INTO INET_TBL (c, i) VALUES ('10', '10.1.2.3/8');
INSERT INTO INET_TBL (c, i) VALUES ('10', '11.1.2.3/8');
INSERT INTO INET_TBL (c, i) VALUES ('10', '9.1.2.3/8');
+ INSERT INTO INET_TBL (c, i) VALUES ('10:23::f1', '10:23::f1/64');
+ INSERT INTO INET_TBL (c, i) VALUES ('10:23::8000/113', '10:23::ffff');
+ INSERT INTO INET_TBL (c, i) VALUES ('::ffff:1.2.3.4', '::4.3.2.1/24');
-- check that CIDR rejects invalid input:
INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/24', '192.168.1.226');
+ INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1.2.3.4');
-- check that CIDR rejects invalid input when converting from text:
INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/24'), '192.168.1.226');
! INSERT INTO INET_TBL (c, i) VALUES (cidr('ffff:ffff:ffff:ffff::/24'), '::192.168.1.226');
SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL;
-- now test some support functions
! SELECT '' AS ten, i AS inet, host(i), text(i), family(i) FROM INET_TBL;
SELECT '' AS ten, c AS cidr, broadcast(c),
i AS inet, broadcast(i) FROM INET_TBL;
SELECT '' AS ten, c AS cidr, network(c) AS "network(cidr)",