Thread: IPv6 Support for INET/CIDR types.

IPv6 Support for INET/CIDR types.

From
Vadim Kogan
Date:
Attached is a patch that adds IPv6 support for inet and cidr datatypes. All
the functionality that was available for IPv4 is available for IPv6. In
addition comparison between IPv4 and IPv4-in-IPv6 addresses is available.

**** WARNING: THIS PATCH HAS NOT BEEN TESTED ENOUGH! ****
(There is still some minor debug stuff left and such)
The patch is not likely to kill any of your data, but it could crash your
backend.

Due to me being relatively busy lately, I was hoping that other people might
want to help me test the patch. If you have a problem, just email me what
you were doing and I will try to reproduce and fix it. Hopefully we can get
this small patch to the point of being stable soon enough and have it
included in the main tree.

Paul: I suppose you can take a look at inet_{net,cidr}_{pton,ntop} stuff,
test it and eventually include with your code. Sorry for the delay, I had
this part more or less ready a while back, but never had time to finish the
postgres-specific part...

Vadim.


Attachment

Re: IPv6 Support for INET/CIDR types.

From
Vadim Kogan
Date:
Ok, fine, I'm a retard. Sorry. This time there IS an attachment.

On Sun, Aug 05, 2001 at 11:27:07PM -0700, Vadim Kogan wrote:
> Attached is a patch that adds IPv6 support for inet and cidr datatypes. All
> the functionality that was available for IPv4 is available for IPv6. In
> addition comparison between IPv4 and IPv4-in-IPv6 addresses is available.
>
> **** WARNING: THIS PATCH HAS NOT BEEN TESTED ENOUGH! ****
> (There is still some minor debug stuff left and such)
> The patch is not likely to kill any of your data, but it could crash your
> backend.
>
> Due to me being relatively busy lately, I was hoping that other people might
> want to help me test the patch. If you have a problem, just email me what
> you were doing and I will try to reproduce and fix it. Hopefully we can get
> this small patch to the point of being stable soon enough and have it
> included in the main tree.
>
> Paul: I suppose you can take a look at inet_{net,cidr}_{pton,ntop} stuff,
> test it and eventually include with your code. Sorry for the delay, I had
> this part more or less ready a while back, but never had time to finish the
> postgres-specific part...
>
> Vadim.
>


>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org



Vadim.


Attachment

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
Can I have a version of this that can be applied?  7.2 beta will start
on Monday.


-- Start of PGP signed section.
> Attached is a patch that adds IPv6 support for inet and cidr datatypes. All
> the functionality that was available for IPv4 is available for IPv6. In
> addition comparison between IPv4 and IPv4-in-IPv6 addresses is available.
>
> **** WARNING: THIS PATCH HAS NOT BEEN TESTED ENOUGH! ****
> (There is still some minor debug stuff left and such)
> The patch is not likely to kill any of your data, but it could crash your
> backend.
>
> Due to me being relatively busy lately, I was hoping that other people might
> want to help me test the patch. If you have a problem, just email me what
> you were doing and I will try to reproduce and fix it. Hopefully we can get
> this small patch to the point of being stable soon enough and have it
> included in the main tree.
>
> Paul: I suppose you can take a look at inet_{net,cidr}_{pton,ntop} stuff,
> test it and eventually include with your code. Sorry for the delay, I had
> this part more or less ready a while back, but never had time to finish the
> postgres-specific part...
>
> Vadim.
>
-- End of PGP section.

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Vadim Kogan
Date:
There are bugs there! I know for sure.

I agree that the preferred way would be to have ISC release first and then
incorporate that. Once ISC releases the inet_* stuff, I can generate diff
based on that (with postgres-specific stuff).

I will try my best to send the latest version that I'm using. There are
still bugs there I think. But if enough people try enough random IPs/etc.
eventually all broken special cases will be fixed.

On Thu, Sep 06, 2001 at 02:10:37PM -0700, Paul A Vixie wrote:
> we're working this into a BIND release and will have the official ISC
> version of these diffs to the inet_*() functions within a day or so.
>
> the inet_*() functions are meant to be transitive, and the existing IPv4
> entry points all are, so we're changing these contributed IPv6 entry points
> to also be transitive, then we'll ship them.
>
> as soon as we have something we're happy with i'll drop you a copy.
>
> > From: Bruce Momjian <pgman@candle.pha.pa.us>
> > Message-Id: <200109062045.f86KjPV21792@candle.pha.pa.us>
> > Subject: Re: [PATCHES] IPv6 Support for INET/CIDR types.
> > In-Reply-To: <20010805232707.S32686@scam.xcf.berkeley.edu> "from Vadim Kogan
> >  at Aug 5, 2001 11:27:07 pm"
> > To: Vadim Kogan <vadim@xcf.berkeley.edu>
> > Date: Thu, 6 Sep 2001 16:45:25 -0400 (EDT)
> > CC: pgsql-patches@postgresql.org, Paul A Vixie <vixie@mfnx.net>
> > X-Mailer: ELM [version 2.4ME+ PL90 (25)]
> > MIME-Version: 1.0
> > Content-Transfer-Encoding: 7bit
> > Content-Type: text/plain; charset=US-ASCII
> >
> >
> > Can I have a version of this that can be applied?  7.2 beta will start
> > on Monday.
> >
> >
> > -- Start of PGP signed section.
> > > Attached is a patch that adds IPv6 support for inet and cidr datatypes. All
> > > the functionality that was available for IPv4 is available for IPv6. In
> > > addition comparison between IPv4 and IPv4-in-IPv6 addresses is available.
> > >
> > > **** WARNING: THIS PATCH HAS NOT BEEN TESTED ENOUGH! ****
> > > (There is still some minor debug stuff left and such)
> > > The patch is not likely to kill any of your data, but it could crash your
> > > backend.
> > >
> > > Due to me being relatively busy lately, I was hoping that other people might
> > > want to help me test the patch. If you have a problem, just email me what
> > > you were doing and I will try to reproduce and fix it. Hopefully we can get
> > > this small patch to the point of being stable soon enough and have it
> > > included in the main tree.
> > >
> > > Paul: I suppose you can take a look at inet_{net,cidr}_{pton,ntop} stuff,
> > > test it and eventually include with your code. Sorry for the delay, I had
> > > this part more or less ready a while back, but never had time to finish the
> > > postgres-specific part...
> > >
> > > Vadim.
> > >
> > -- End of PGP section.
> >
> > --
> >   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


Vadim.


Attachment

Re: IPv6 Support for INET/CIDR types.

From
Paul A Vixie
Date:
we're working this into a BIND release and will have the official ISC
version of these diffs to the inet_*() functions within a day or so.

the inet_*() functions are meant to be transitive, and the existing IPv4
entry points all are, so we're changing these contributed IPv6 entry points
to also be transitive, then we'll ship them.

as soon as we have something we're happy with i'll drop you a copy.

> From: Bruce Momjian <pgman@candle.pha.pa.us>
> Message-Id: <200109062045.f86KjPV21792@candle.pha.pa.us>
> Subject: Re: [PATCHES] IPv6 Support for INET/CIDR types.
> In-Reply-To: <20010805232707.S32686@scam.xcf.berkeley.edu> "from Vadim Kogan
>  at Aug 5, 2001 11:27:07 pm"
> To: Vadim Kogan <vadim@xcf.berkeley.edu>
> Date: Thu, 6 Sep 2001 16:45:25 -0400 (EDT)
> CC: pgsql-patches@postgresql.org, Paul A Vixie <vixie@mfnx.net>
> X-Mailer: ELM [version 2.4ME+ PL90 (25)]
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Type: text/plain; charset=US-ASCII
>
>
> Can I have a version of this that can be applied?  7.2 beta will start
> on Monday.
>
>
> -- Start of PGP signed section.
> > Attached is a patch that adds IPv6 support for inet and cidr datatypes. All
> > the functionality that was available for IPv4 is available for IPv6. In
> > addition comparison between IPv4 and IPv4-in-IPv6 addresses is available.
> >
> > **** WARNING: THIS PATCH HAS NOT BEEN TESTED ENOUGH! ****
> > (There is still some minor debug stuff left and such)
> > The patch is not likely to kill any of your data, but it could crash your
> > backend.
> >
> > Due to me being relatively busy lately, I was hoping that other people might
> > want to help me test the patch. If you have a problem, just email me what
> > you were doing and I will try to reproduce and fix it. Hopefully we can get
> > this small patch to the point of being stable soon enough and have it
> > included in the main tree.
> >
> > Paul: I suppose you can take a look at inet_{net,cidr}_{pton,ntop} stuff,
> > test it and eventually include with your code. Sorry for the delay, I had
> > this part more or less ready a while back, but never had time to finish the
> > postgres-specific part...
> >
> > Vadim.
> >
> -- End of PGP section.
>
> --
>   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


Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
Do we have patch we can apply here?

> There are bugs there! I know for sure.
>
> I agree that the preferred way would be to have ISC release first and then
> incorporate that. Once ISC releases the inet_* stuff, I can generate diff
> based on that (with postgres-specific stuff).
>
> I will try my best to send the latest version that I'm using. There are
> still bugs there I think. But if enough people try enough random IPs/etc.
> eventually all broken special cases will be fixed.
>
> On Thu, Sep 06, 2001 at 02:10:37PM -0700, Paul A Vixie wrote:
> > we're working this into a BIND release and will have the official ISC
> > version of these diffs to the inet_*() functions within a day or so.
> >
> > the inet_*() functions are meant to be transitive, and the existing IPv4
> > entry points all are, so we're changing these contributed IPv6 entry points
> > to also be transitive, then we'll ship them.
> >
> > as soon as we have something we're happy with i'll drop you a copy.
> >
> > > From: Bruce Momjian <pgman@candle.pha.pa.us>
> > > Message-Id: <200109062045.f86KjPV21792@candle.pha.pa.us>
> > > Subject: Re: [PATCHES] IPv6 Support for INET/CIDR types.
> > > In-Reply-To: <20010805232707.S32686@scam.xcf.berkeley.edu> "from Vadim Kogan
> > >  at Aug 5, 2001 11:27:07 pm"
> > > To: Vadim Kogan <vadim@xcf.berkeley.edu>
> > > Date: Thu, 6 Sep 2001 16:45:25 -0400 (EDT)
> > > CC: pgsql-patches@postgresql.org, Paul A Vixie <vixie@mfnx.net>
> > > X-Mailer: ELM [version 2.4ME+ PL90 (25)]
> > > MIME-Version: 1.0
> > > Content-Transfer-Encoding: 7bit
> > > Content-Type: text/plain; charset=US-ASCII
> > >
> > >
> > > Can I have a version of this that can be applied?  7.2 beta will start
> > > on Monday.
> > >
> > >
> > > -- Start of PGP signed section.
> > > > Attached is a patch that adds IPv6 support for inet and cidr datatypes. All
> > > > the functionality that was available for IPv4 is available for IPv6. In
> > > > addition comparison between IPv4 and IPv4-in-IPv6 addresses is available.
> > > >
> > > > **** WARNING: THIS PATCH HAS NOT BEEN TESTED ENOUGH! ****
> > > > (There is still some minor debug stuff left and such)
> > > > The patch is not likely to kill any of your data, but it could crash your
> > > > backend.
> > > >
> > > > Due to me being relatively busy lately, I was hoping that other people might
> > > > want to help me test the patch. If you have a problem, just email me what
> > > > you were doing and I will try to reproduce and fix it. Hopefully we can get
> > > > this small patch to the point of being stable soon enough and have it
> > > > included in the main tree.
> > > >
> > > > Paul: I suppose you can take a look at inet_{net,cidr}_{pton,ntop} stuff,
> > > > test it and eventually include with your code. Sorry for the delay, I had
> > > > this part more or less ready a while back, but never had time to finish the
> > > > postgres-specific part...
> > > >
> > > > Vadim.
> > > >
> > > -- End of PGP section.
> > >
> > > --
> > >   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
>
>
> Vadim.
>
-- End of PGP section, PGP failed!

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
> yes.  is the cvs-pserver up to date wrt pre-7.2?

Yes, it should be.  There is a new path:

    :pserver:anoncvs@anoncvs.postgresql.org:/projects/cvsroot

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Paul A Vixie
Date:
yes.  is the cvs-pserver up to date wrt pre-7.2?

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
What is that status of this patch?  We are near beta.


> we're working this into a BIND release and will have the official ISC
> version of these diffs to the inet_*() functions within a day or so.
>
> the inet_*() functions are meant to be transitive, and the existing IPv4
> entry points all are, so we're changing these contributed IPv6 entry points
> to also be transitive, then we'll ship them.
>
> as soon as we have something we're happy with i'll drop you a copy.
>
> > From: Bruce Momjian <pgman@candle.pha.pa.us>
> > Message-Id: <200109062045.f86KjPV21792@candle.pha.pa.us>
> > Subject: Re: [PATCHES] IPv6 Support for INET/CIDR types.
> > In-Reply-To: <20010805232707.S32686@scam.xcf.berkeley.edu> "from Vadim Kogan
> >  at Aug 5, 2001 11:27:07 pm"
> > To: Vadim Kogan <vadim@xcf.berkeley.edu>
> > Date: Thu, 6 Sep 2001 16:45:25 -0400 (EDT)
> > CC: pgsql-patches@postgresql.org, Paul A Vixie <vixie@mfnx.net>
> > X-Mailer: ELM [version 2.4ME+ PL90 (25)]
> > MIME-Version: 1.0
> > Content-Transfer-Encoding: 7bit
> > Content-Type: text/plain; charset=US-ASCII
> >
> >
> > Can I have a version of this that can be applied?  7.2 beta will start
> > on Monday.
> >
> >
> > -- Start of PGP signed section.
> > > Attached is a patch that adds IPv6 support for inet and cidr datatypes. All
> > > the functionality that was available for IPv4 is available for IPv6. In
> > > addition comparison between IPv4 and IPv4-in-IPv6 addresses is available.
> > >
> > > **** WARNING: THIS PATCH HAS NOT BEEN TESTED ENOUGH! ****
> > > (There is still some minor debug stuff left and such)
> > > The patch is not likely to kill any of your data, but it could crash your
> > > backend.
> > >
> > > Due to me being relatively busy lately, I was hoping that other people might
> > > want to help me test the patch. If you have a problem, just email me what
> > > you were doing and I will try to reproduce and fix it. Hopefully we can get
> > > this small patch to the point of being stable soon enough and have it
> > > included in the main tree.
> > >
> > > Paul: I suppose you can take a look at inet_{net,cidr}_{pton,ntop} stuff,
> > > test it and eventually include with your code. Sorry for the delay, I had
> > > this part more or less ready a while back, but never had time to finish the
> > > postgres-specific part...
> > >
> > > Vadim.
> > >
> > -- End of PGP section.
> >
> > --
> >   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
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
> subscribe-nomail command to majordomo@postgresql.org so that your
> message can get through to the mailing list cleanly
>

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Paul A Vixie
Date:
> Does that mean that you'll send the whole thing and I shouldn't send anything?

i'd like to do it all from here if possible.

Re: IPv6 Support for INET/CIDR types.

From
Vadim Kogan
Date:
On Wed, Oct 03, 2001 at 03:31:49PM -0700, Paul A Vixie wrote:
> > Does that mean that you'll send the whole thing and I shouldn't send anything?
>
> i'd like to do it all from here if possible.

Ok, cool with me.

Vadim.


Attachment

Re: IPv6 Support for INET/CIDR types.

From
Paul A Vixie
Date:
we have a version of this code plus some bug fixes in bind 8.3.0-T2A,
which i'm about to submit to you along with the glue code.

Re: IPv6 Support for INET/CIDR types.

From
Vadim Kogan
Date:
On Wed, Oct 03, 2001 at 01:53:58PM -0700, Paul A Vixie wrote:
> we have a version of this code plus some bug fixes in bind 8.3.0-T2A,
> which i'm about to submit to you along with the glue code.

Does that mean that you'll send the whole thing and I shouldn't send
anything?

Vadim.


Attachment

Re: IPv6 Support for INET/CIDR types.

From
Paul A Vixie
Date:
> 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


Re: IPv6 Support for INET/CIDR types.

From
Tom Lane
Date:
Paul A Vixie <vixie@vix.com> writes:
> below please find a shar file containing [ ipv6 support ]

Lovely!  Will review and commit this today if possible.

Could we trouble you for appropriate additions to the regression tests
and documentation, as well?

            regards, tom lane

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
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

Re: IPv6 Support for INET/CIDR types.

From
"Marc G. Fournier"
Date:
On Fri, 12 Oct 2001, Bruce Momjian wrote:

>
> Seems this will have to wait for 7.3.

Why?

and, to be a bit more riendly to those of us stuck on 56k lines, could you
avoid re-sending, repeatedly, large patch files?


Re: IPv6 Support for INET/CIDR types.

From
Paul A Vixie
Date:
> Seems this will have to wait for 7.3.

seems so.  i'm going to redo network.c.

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
> > > Seems this will have to wait for 7.3.
> >
> > Why?
>
> because i didn't get it fixed in time.
>
> > and, to be a bit more riendly to those of us stuck on 56k lines, could you
> > avoid re-sending, repeatedly, large patch files?
>
> sorry.

This was my fault.  In asking about the status of the patch I left the
entire patch attached to my message.

Paul, do you think I can take your patch and merge it in?  Can you give
me any guidance on that?

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Tom Lane
Date:
"Marc G. Fournier" <scrappy@hub.org> writes:
> On Fri, 12 Oct 2001, Bruce Momjian wrote:
>> Seems this will have to wait for 7.3.

> Why?

Because Paul's not yet responded to my gripes of (now) 10 days ago.
The patch as given reverts the I/O behavior of the inet datatypes
to what it originally was, rather than the compromise behavior that
was hammered out at great length before 7.1.  (I'd give a link to
those discussions if fts.postgresql.org were working :-()

> and, to be a bit more riendly to those of us stuck on 56k lines, could you
> avoid re-sending, repeatedly, large patch files?

I agree on that one ...

            regards, tom lane

Re: IPv6 Support for INET/CIDR types.

From
Paul A Vixie
Date:
> > Seems this will have to wait for 7.3.
>
> Why?

because i didn't get it fixed in time.

> and, to be a bit more riendly to those of us stuck on 56k lines, could you
> avoid re-sending, repeatedly, large patch files?

sorry.



Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
Paul A Vixie wrote:
> > > Seems this will have to wait for 7.3.
> >
> > Why?
>
> because i didn't get it fixed in time.
>
> > and, to be a bit more riendly to those of us stuck on 56k lines, could you
> > avoid re-sending, repeatedly, large patch files?
>
> sorry.

Paul, do you have an updated patch that can be applied to 7.3?

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
OK, I have forwarded my saved emails to Paul.  Paul, there was great
confusion over how these data types show display addresses and masks,
and a compromise was hammered out that we are reluctant to throw out.

I wish our email archives where searchable online and I could point you
to the issues.  Can someone summarize the issues, specifically how did
we change what Paul originally gave us so it can be done again?   All I
have for detail is this from Tom Lane:

    The patch as given reverts the I/O behavior of the inet datatypes
    to what it originally was, rather than the compromise behavior that
    was hammered out at great length before 7.1.  (I'd give a link to
    those discussions if fts.postgresql.org were working :-()

Seems the archives were down back then in October too.  :-(


---------------------------------------------------------------------------

Paul Vixie wrote:
> here's the problem.  i want to replace the inet_{net_}{ntop,pton}
> functions in postgres with the real ones from bind.  however, your
> versions have been patched.  so before i can replace them i need
> to understand exactly what you've patched and move that logic to
> the part of postgres that calls these functions.  then i can import
> the real versions, which include vadim's ipv6 logic.  then i can
> work on changing postgres to use the new ipv6 logic in these functions.
>
> any help with that first step would be appreciated.
>
> > From: Bruce Momjian <pgman@candle.pha.pa.us>
> > Message-Id: <200202221810.g1MIA6C29715@candle.pha.pa.us>
> > Subject: Re: [PATCHES] IPv6 Support for INET/CIDR types.
> > In-Reply-To: <200110161420.f9GEKZH87408@as.vix.com>
> > To: Paul A Vixie <paul@vix.com>
> > Date: Fri, 22 Feb 2002 13:10:06 -0500 (EST)
> > Cc: "Marc G. Fournier" <scrappy@hub.org>,
> >     Vadim Kogan <vadim@xcf.berkeley.edu>, pgsql-patches@postgresql.org
> > X-Mailer: ELM [version 2.4ME+ PL96 (25)]
> > MIME-Version: 1.0
> > Content-Transfer-Encoding: 7bit
> > Content-Type: text/plain; charset=US-ASCII
> >
> > Paul A Vixie wrote:
> > > > > Seems this will have to wait for 7.3.
> > > >
> > > > Why?
> > >
> > > because i didn't get it fixed in time.
> > >
> > > > and, to be a bit more riendly to those of us stuck on 56k lines, could you
> > > > avoid re-sending, repeatedly, large patch files?
> > >
> > > sorry.
> >
> > Paul, do you have an updated patch that can be applied to 7.3?
> >
> > --
> >   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
>
>

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
Vadim Kogan wrote:

Checking application/pgp-signature: FAILURE
-- Start of PGP signed section.
> Ok. I've been a little bit out of the loop lately.
>
> a) The original changes I had were made out of two parts:
>     - inet_*_* part
>     - postgres-specific part
> b) I have made some choices there as to how to show/input things.
>    Basically, any valid representation is understood. The output
>    is as close as possible to the similar IPv4 outputs. Also, the
>    the most compact version is used (but that's in inet_*_*).
>
> If somebody has my original patches (WITH postgres-specific stuff), that'd
> probably be a good starting point. In any case, I will try to produce
> another diff today or sometime during this weekend. I will omit any changes
> to inet_*_*, since bind now has proper version (and moreover, that version
> is not the same as mine, since Paul rewrote some of the stuff).

Vadim, I just sent over the patch Paul submitted.  Is that it?  If not,
was your patch ever applied to the PostgreSQL CVS?  If so, I can find it
using cvs diff -c and send it to you.  Do you remember a rough date or
release?

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
Paul Vixie wrote:
> > Vadim, I just sent over the patch Paul submitted.  Is that it?  If not,
> > was your patch ever applied to the PostgreSQL CVS?  If so, I can find it
> > using cvs diff -c and send it to you.  Do you remember a rough date or
> > release?
>
> i strongly recommend against applying the original patch.  vadim's
> changes to the BIND library code have been accepted by BIND, and we
> should find a way to use it there.

I knew the patch shouldn't be applied.  I was just trying to give Vadim
what he needed.  I am not even sure if I succeeded.

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
Paul Vixie wrote:
> > I don't believe the original patch ever made it into anything.
>
> vadim's original patch was the basis for BIND's ipv6 support in the
> set of functions that pgsql borrows from BIND.  so, it did make it
> into _something_ just not the modified pgsql mirrors of these functions.
>
> my proposal is that we do away with the modified pgsql mirrors of these
> functions and teach the INET and CIDR handlers to "wrap" the BIND functions
> in a way that modifies the presentation format to be postgres-compatible.
> that way postgres can import new versions of, or use LIBC versions of,
> the BIND functions without having to worry about local modifications to them.

Are we sure the Bind library versions are going to be on all the OS's we
support?

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
Paul Vixie wrote:
> > > my proposal is that we do away with the modified pgsql mirrors of these
> > > functions and teach the INET and CIDR handlers to "wrap" the BIND functions
> > > in a way that modifies the presentation format to be postgres-compatible.
> > > that way postgres can import new versions of, or use LIBC versions of,
> > > the BIND functions without having to worry about local modifications to them.
> >
> > Are we sure the Bind library versions are going to be on all the OS's we
> > support?
>
> no.  that's why there should be a copy in the postgres sources, just in case.
> and that's why "./configure" has to learn how to choose whether to use the
> system supplied versions or the internal bootstrapping versions.

Oh, I get it.  I am on the same planet now.  :-)

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Larry Rosenman
Date:
* Bruce Momjian <pgman@candle.pha.pa.us> [020222 13:56]:
>
> OK, I have forwarded my saved emails to Paul.  Paul, there was great
> confusion over how these data types show display addresses and masks,
> and a compromise was hammered out that we are reluctant to throw out.
>
> I wish our email archives where searchable online and I could point you
> to the issues.  Can someone summarize the issues, specifically how did
> we change what Paul originally gave us so it can be done again?   All I
> have for detail is this from Tom Lane:
>
>     The patch as given reverts the I/O behavior of the inet datatypes
>     to what it originally was, rather than the compromise behavior that
>     was hammered out at great length before 7.1.  (I'd give a link to
>     those discussions if fts.postgresql.org were working :-()
>
> Seems the archives were down back then in October too.  :-(
Please do *NOT* revert the output functions.  One of the MAJOR reasons
for the change was to ALWAYS print ALL 4 octets of an IPv4 address in
the default case.

You (Paul) were part of that discussion.  I was one of the instigators
of it.

LER

>
>
> ---------------------------------------------------------------------------
>
> Paul Vixie wrote:
> > here's the problem.  i want to replace the inet_{net_}{ntop,pton}
> > functions in postgres with the real ones from bind.  however, your
> > versions have been patched.  so before i can replace them i need
> > to understand exactly what you've patched and move that logic to
> > the part of postgres that calls these functions.  then i can import
> > the real versions, which include vadim's ipv6 logic.  then i can
> > work on changing postgres to use the new ipv6 logic in these functions.
> >
> > any help with that first step would be appreciated.
> >
> > > From: Bruce Momjian <pgman@candle.pha.pa.us>
> > > Message-Id: <200202221810.g1MIA6C29715@candle.pha.pa.us>
> > > Subject: Re: [PATCHES] IPv6 Support for INET/CIDR types.
> > > In-Reply-To: <200110161420.f9GEKZH87408@as.vix.com>
> > > To: Paul A Vixie <paul@vix.com>
> > > Date: Fri, 22 Feb 2002 13:10:06 -0500 (EST)
> > > Cc: "Marc G. Fournier" <scrappy@hub.org>,
> > >     Vadim Kogan <vadim@xcf.berkeley.edu>, pgsql-patches@postgresql.org
> > > X-Mailer: ELM [version 2.4ME+ PL96 (25)]
> > > MIME-Version: 1.0
> > > Content-Transfer-Encoding: 7bit
> > > Content-Type: text/plain; charset=US-ASCII
> > >
> > > Paul A Vixie wrote:
> > > > > > Seems this will have to wait for 7.3.
> > > > >
> > > > > Why?
> > > >
> > > > because i didn't get it fixed in time.
> > > >
> > > > > and, to be a bit more riendly to those of us stuck on 56k lines, could you
> > > > > avoid re-sending, repeatedly, large patch files?
> > > >
> > > > sorry.
> > >
> > > Paul, do you have an updated patch that can be applied to 7.3?
> > >
> > > --
> > >   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
> >
> >
>
> --
>   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
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html

--
Larry Rosenman                     http://www.lerctr.org/~ler
Phone: +1 972-414-9812                 E-Mail: ler@lerctr.org
US Mail: 1905 Steamboat Springs Drive, Garland, TX 75044-6749

Re: IPv6 Support for INET/CIDR types.

From
Paul Vixie
Date:
i completely respect postgres's need for consistency in the appearance
of these presentation formats.  if they are different from bind's then
i, as a consumer of postgresql, will learn to live with those differences.
i do not, in other words, need to be convinced at all.  you guys found a
format you like, and i will do everything i can to support it.

i just want the support to occur in the postgres source code rather than
in the bind source code.  there is an inet_*_*.c source file in the
postgres sources which was originally a copy of bind's, but which has
been modified to produce a different output format.  i (as an occasional
contributor to postgres's development) propose that it would be easier
to just import a new version of bind's inet_*_*.c file occasionally,
and even teach "./configure" to note that it's already in libc (if it is)
and if so use the libc version rather than the internal version.

this implies that the part of postgres that calls this part of bind's
library should "fix up" the return value to convert it to "postgres style."

again, i am in complete support of postgres having its own style.  i just
don't think postgres should have an incompatible variant of a BIND library
function.  the stylistic variance should be applied in the postgres source,
not to a copy of the BIND source.

my problem is, i don't know exactly what the stylistic difference is,
nor do i know how to "post-apply" it to the returned result from the BIND
library, nor how to change "./configure" to notice and use the LIBC
(or -lbind) version of these functions if they exist.  if someone else
could take care of those deeper matters, then i would be completely happy
to integrate vadim's ipv6 changes to the INET and CIDR data types.

Re: IPv6 Support for INET/CIDR types.

From
Paul Vixie
Date:
here's the problem.  i want to replace the inet_{net_}{ntop,pton}
functions in postgres with the real ones from bind.  however, your
versions have been patched.  so before i can replace them i need
to understand exactly what you've patched and move that logic to
the part of postgres that calls these functions.  then i can import
the real versions, which include vadim's ipv6 logic.  then i can
work on changing postgres to use the new ipv6 logic in these functions.

any help with that first step would be appreciated.

> From: Bruce Momjian <pgman@candle.pha.pa.us>
> Message-Id: <200202221810.g1MIA6C29715@candle.pha.pa.us>
> Subject: Re: [PATCHES] IPv6 Support for INET/CIDR types.
> In-Reply-To: <200110161420.f9GEKZH87408@as.vix.com>
> To: Paul A Vixie <paul@vix.com>
> Date: Fri, 22 Feb 2002 13:10:06 -0500 (EST)
> Cc: "Marc G. Fournier" <scrappy@hub.org>,
>     Vadim Kogan <vadim@xcf.berkeley.edu>, pgsql-patches@postgresql.org
> X-Mailer: ELM [version 2.4ME+ PL96 (25)]
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Type: text/plain; charset=US-ASCII
>
> Paul A Vixie wrote:
> > > > Seems this will have to wait for 7.3.
> > >
> > > Why?
> >
> > because i didn't get it fixed in time.
> >
> > > and, to be a bit more riendly to those of us stuck on 56k lines, could you
> > > avoid re-sending, repeatedly, large patch files?
> >
> > sorry.
>
> Paul, do you have an updated patch that can be applied to 7.3?
>
> --
>   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


Re: IPv6 Support for INET/CIDR types.

From
Vadim Kogan
Date:
I don't believe the original patch ever made it into anything. But the patch
that Paul just sent is what you should try instead.

On Fri, Feb 22, 2002 at 02:40:48PM -0500, Bruce Momjian wrote:
> Paul Vixie wrote:
> > > Vadim, I just sent over the patch Paul submitted.  Is that it?  If not,
> > > was your patch ever applied to the PostgreSQL CVS?  If so, I can find it
> > > using cvs diff -c and send it to you.  Do you remember a rough date or
> > > release?
> >
> > i strongly recommend against applying the original patch.  vadim's
> > changes to the BIND library code have been accepted by BIND, and we
> > should find a way to use it there.
>
> I knew the patch shouldn't be applied.  I was just trying to give Vadim
> what he needed.  I am not even sure if I succeeded.
>
> --
>   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


Vadim.


Attachment

Re: IPv6 Support for INET/CIDR types.

From
Paul Vixie
Date:
> Vadim, I just sent over the patch Paul submitted.  Is that it?  If not,
> was your patch ever applied to the PostgreSQL CVS?  If so, I can find it
> using cvs diff -c and send it to you.  Do you remember a rough date or
> release?

i strongly recommend against applying the original patch.  vadim's
changes to the BIND library code have been accepted by BIND, and we
should find a way to use it there.

Re: IPv6 Support for INET/CIDR types.

From
Vadim Kogan
Date:
This looks about right. I'm not 100% sure this is the latest version, but
I'll have to wait 'till later to look at it in details. Nevertheless, this
is definitely the right starting point. Since this patch has ISC's version
of inet_*_*, this is the one that should be used.

I suggest that if you were to try this patch right away, you make a few
simple tests to make sure border cases are handled right.


On Fri, Oct 05, 2001 at 01:38:53AM -0700, Paul A Vixie wrote:
> > 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.
>

Vadim.


Attachment

Re: IPv6 Support for INET/CIDR types.

From
Paul Vixie
Date:
> I don't believe the original patch ever made it into anything.

vadim's original patch was the basis for BIND's ipv6 support in the
set of functions that pgsql borrows from BIND.  so, it did make it
into _something_ just not the modified pgsql mirrors of these functions.

my proposal is that we do away with the modified pgsql mirrors of these
functions and teach the INET and CIDR handlers to "wrap" the BIND functions
in a way that modifies the presentation format to be postgres-compatible.
that way postgres can import new versions of, or use LIBC versions of,
the BIND functions without having to worry about local modifications to them.

Re: IPv6 Support for INET/CIDR types.

From
Vadim Kogan
Date:
Ok. I've been a little bit out of the loop lately.

a) The original changes I had were made out of two parts:
    - inet_*_* part
    - postgres-specific part
b) I have made some choices there as to how to show/input things.
   Basically, any valid representation is understood. The output
   is as close as possible to the similar IPv4 outputs. Also, the
   the most compact version is used (but that's in inet_*_*).

If somebody has my original patches (WITH postgres-specific stuff), that'd
probably be a good starting point. In any case, I will try to produce
another diff today or sometime during this weekend. I will omit any changes
to inet_*_*, since bind now has proper version (and moreover, that version
is not the same as mine, since Paul rewrote some of the stuff).

Does anybody have a pointer to info on how to grow the second head? Or at
least one more hand...


On Fri, Feb 22, 2002 at 10:38:12AM -0800, Paul Vixie wrote:
> i completely respect postgres's need for consistency in the appearance
> of these presentation formats.  if they are different from bind's then
> i, as a consumer of postgresql, will learn to live with those differences.
> i do not, in other words, need to be convinced at all.  you guys found a
> format you like, and i will do everything i can to support it.
>
> i just want the support to occur in the postgres source code rather than
> in the bind source code.  there is an inet_*_*.c source file in the
> postgres sources which was originally a copy of bind's, but which has
> been modified to produce a different output format.  i (as an occasional
> contributor to postgres's development) propose that it would be easier
> to just import a new version of bind's inet_*_*.c file occasionally,
> and even teach "./configure" to note that it's already in libc (if it is)
> and if so use the libc version rather than the internal version.
>
> this implies that the part of postgres that calls this part of bind's
> library should "fix up" the return value to convert it to "postgres style."
>
> again, i am in complete support of postgres having its own style.  i just
> don't think postgres should have an incompatible variant of a BIND library
> function.  the stylistic variance should be applied in the postgres source,
> not to a copy of the BIND source.
>
> my problem is, i don't know exactly what the stylistic difference is,
> nor do i know how to "post-apply" it to the returned result from the BIND
> library, nor how to change "./configure" to notice and use the LIBC
> (or -lbind) version of these functions if they exist.  if someone else
> could take care of those deeper matters, then i would be completely happy
> to integrate vadim's ipv6 changes to the INET and CIDR data types.


Vadim.


Attachment

Re: IPv6 Support for INET/CIDR types.

From
Paul Vixie
Date:
> > my proposal is that we do away with the modified pgsql mirrors of these
> > functions and teach the INET and CIDR handlers to "wrap" the BIND functions
> > in a way that modifies the presentation format to be postgres-compatible.
> > that way postgres can import new versions of, or use LIBC versions of,
> > the BIND functions without having to worry about local modifications to them.
>
> Are we sure the Bind library versions are going to be on all the OS's we
> support?

no.  that's why there should be a copy in the postgres sources, just in case.
and that's why "./configure" has to learn how to choose whether to use the
system supplied versions or the internal bootstrapping versions.

Re: IPv6 Support for INET/CIDR types.

From
Vadim Kogan
Date:
On Fri, Feb 22, 2002 at 02:59:34PM -0500, Bruce Momjian wrote:
> Paul Vixie wrote:
> > > I don't believe the original patch ever made it into anything.
> >
> > vadim's original patch was the basis for BIND's ipv6 support in the
> > set of functions that pgsql borrows from BIND.  so, it did make it
> > into _something_ just not the modified pgsql mirrors of these functions.
> >
> > my proposal is that we do away with the modified pgsql mirrors of these
> > functions and teach the INET and CIDR handlers to "wrap" the BIND functions
> > in a way that modifies the presentation format to be postgres-compatible.
> > that way postgres can import new versions of, or use LIBC versions of,
> > the BIND functions without having to worry about local modifications to them.
>
> Are we sure the Bind library versions are going to be on all the OS's we
> support?

Eventually they will. I think that for now it's reasonable to

a) make sure that the files in postgres are _exact_ copies of those in BIND.

b) check to see whether the host provides the functionality, and if it does,
use whatever host gives us, instead of local version

c) At some point remove the local version alltogether.

Vadim.


Attachment

Re: IPv6 Support for INET/CIDR types.

From
Tom Lane
Date:
Larry Rosenman <ler@lerctr.org> writes:
> Please do *NOT* revert the output functions.  One of the MAJOR reasons
> for the change was to ALWAYS print ALL 4 octets of an IPv4 address in
> the default case.

AFAICT, Paul is not objecting to our adjustments to the I/O conventions.
What he wants is to find a way for the inner inet_{net_}{ntop,pton}
functions to remain identical to the ones in BIND, and do the
adjustments in the Postgres-specific wrapper routines.  I'm not sure how
important that is in reality, but I have no problem with trying...

            regards, tom lane

Re: IPv6 Support for INET/CIDR types.

From
Bruce Momjian
Date:
I would like to see some activity on this item soon.  Historically, the
CIDR stuff has arrived during beta when we can't apply any major
changes.

---------------------------------------------------------------------------

Vadim Kogan wrote:

Checking application/pgp-signature: FAILURE
-- Start of PGP signed section.
> On Fri, Feb 22, 2002 at 02:59:34PM -0500, Bruce Momjian wrote:
> > Paul Vixie wrote:
> > > > I don't believe the original patch ever made it into anything.
> > >
> > > vadim's original patch was the basis for BIND's ipv6 support in the
> > > set of functions that pgsql borrows from BIND.  so, it did make it
> > > into _something_ just not the modified pgsql mirrors of these functions.
> > >
> > > my proposal is that we do away with the modified pgsql mirrors of these
> > > functions and teach the INET and CIDR handlers to "wrap" the BIND functions
> > > in a way that modifies the presentation format to be postgres-compatible.
> > > that way postgres can import new versions of, or use LIBC versions of,
> > > the BIND functions without having to worry about local modifications to them.
> >
> > Are we sure the Bind library versions are going to be on all the OS's we
> > support?
>
> Eventually they will. I think that for now it's reasonable to
>
> a) make sure that the files in postgres are _exact_ copies of those in BIND.
>
> b) check to see whether the host provides the functionality, and if it does,
> use whatever host gives us, instead of local version
>
> c) At some point remove the local version alltogether.
>
> Vadim.
>
-- End of PGP section, PGP failed!

--
  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

Re: IPv6 Support for INET/CIDR types.

From
Paul Vixie
Date:
> I would like to see some activity on this item soon.  Historically, the
> CIDR stuff has arrived during beta when we can't apply any major changes.

to reiterate... i am able to fix up the postgres "inet" and "cidr" types
to make them ipv6-capable, if someone who knows the current system can do
two things:

1. import the current bind versions of inet_{net,}_{pton,ntop}.c and
move the pgsql-specific logic out of the current modified versions of
those files and up into some other part of postgres.  this will keep
the current type behaviour but remove the "modified bind" versions of
some critical library functions.

2. change the build system to only use the "postgres" versions of these
functions if the system libraries (libc and libbind, mostly) don't have
them.  this will ensure that bugfixes and enhancements to the BIND
versions of these files are not obscured by postgres's own versions.

if those two things were done (presumably #1 by the person who integrated
my original CIDR type and #2 by someone who knows the postgres build
system) then i would immediately do #3:

3. change the INET and CIDR type support to include IPv6.

re:

> ---------------------------------------------------------------------------
>
> Vadim Kogan wrote:
>
> Checking application/pgp-signature: FAILURE
> -- Start of PGP signed section.
> > On Fri, Feb 22, 2002 at 02:59:34PM -0500, Bruce Momjian wrote:
> > > Paul Vixie wrote:
> > > > > I don't believe the original patch ever made it into anything.
> > > >
> > > > vadim's original patch was the basis for BIND's ipv6 support in the
> > > > set of functions that pgsql borrows from BIND.  so, it did make it
> > > > into _something_ just not the modified pgsql mirrors of these functions.
> > > >
> > > > my proposal is that we do away with the modified pgsql mirrors of these
> > > > functions and teach the INET and CIDR handlers to "wrap" the BIND functions
> > > > in a way that modifies the presentation format to be postgres-compatible.
> > > > that way postgres can import new versions of, or use LIBC versions of,
> > > > the BIND functions without having to worry about local modifications to them.
> > >
> > > Are we sure the Bind library versions are going to be on all the OS's we
> > > support?
> >
> > Eventually they will. I think that for now it's reasonable to
> >
> > a) make sure that the files in postgres are _exact_ copies of those in BIND.
> >
> > b) check to see whether the host provides the functionality, and if it does,
> > use whatever host gives us, instead of local version
> >
> > c) At some point remove the local version alltogether.
> >
> > Vadim.
> >
> -- End of PGP section, PGP failed!
>
> --
>   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