Thread

  1. Re: [HACKERS] Re: inet/cidr/bind

    Paul Vixie <paul@vix.com> — 1998-10-19T19:07:30Z

    > A network can certainly have a netmask.  In fact, it always does.  It
    > can be implied in certain cases.  The following (if I understand Paul's
    > proposal - correct me if not) show the relationships.
    > 
    > Input            cidr output        inet output
    > =============    ================   ================
    > 192.63.91.234    192.63.91.234/32	192.63.91.234/32
    > 192.63.91        192.63.91/24       192.63.91.0/24
    > 192.63           192.63/16          192.63.0.0/16
    > 192              192/8              192.0.0.0/8
    > 
    > This look right to you, Paul?
    
    no.  the last three inputs are not valid where a host address is expected.
    
    > > If I am wrong about the above, I have one more question.  Would an
    > > atttypmod setting for each column help?  What about a compile-time
    > > define?
    > 
    > We discussed this at one point.  I think that is more useful for
    > specifying output formats.  For example, 192.63.91.234/24 is identical
    > to 192.63.91.234:255.255.255.0 (if we add that format) but I think
    > that's 6.4++ too.  I think it would also only apply to the inet type
    > but Paul should know.
    > 
    > > I know Paul is a big name, but are the duplicate types meaningful for
    > > ordinary users, or would they prefer just one type.  If they would
    > > prefer one type, we can do that, and make sure Paul gets what he wants
    > > too.
    > 
    > I understand why Paul needs his type but I think the inet type is
    > valuable too.  I think my suggestion above is a good compromise.
    
    bigness of names doesn't matter.  applications matter.  i can see a use for
    both types, but they are inherently different types.  a host that has a
    netmask which can be expressed in cidr notation is one such type.  a net
    that has a netmask which must be expressed in cidr notation is another such
    type.  the difference comes down to "host part must be zero" for the network
    type.  there are also some minor differences in the input/output formats,
    since a host address always has four octets on both input and output, while
    a network only prints as many octets as the cidr width specifies, and these
    are the only required octets on input (though extra .0's can be specified).
    
    > I think we are just about there.  If we go with my plan (completely
    > different functionality for now and fold it later) there should be
    > no API change later.  There will be code and catalogue changes but
    > they should be relatively painless.
    
    so shall i test the inet_cidr_ functions and punt them on in?
    
    
    
  2. RE: [HACKERS] Re: inet/cidr/bind

    Taral <taral@mail.utexas.edu> — 1998-10-19T19:43:17Z

    Can't we just use a CONSTRAINT where a host address is expected? That sounds
    easier than setting up two different types to me...
    
    Taral
    
    > -----Original Message-----
    > From: owner-pgsql-hackers@postgreSQL.org
    > [mailto:owner-pgsql-hackers@postgreSQL.org]On Behalf Of Paul A Vixie
    > Sent: Monday, October 19, 1998 2:08 PM
    > To: pgsql-hackers@postgreSQL.org
    > Subject: Re: [HACKERS] Re: inet/cidr/bind
    >
    >
    > > A network can certainly have a netmask.  In fact, it always does.  It
    > > can be implied in certain cases.  The following (if I understand Paul's
    > > proposal - correct me if not) show the relationships.
    > >
    > > Input            cidr output        inet output
    > > =============    ================   ================
    > > 192.63.91.234    192.63.91.234/32	192.63.91.234/32
    > > 192.63.91        192.63.91/24       192.63.91.0/24
    > > 192.63           192.63/16          192.63.0.0/16
    > > 192              192/8              192.0.0.0/8
    > >
    > > This look right to you, Paul?
    >
    > no.  the last three inputs are not valid where a host address is expected.
    >
    > > > If I am wrong about the above, I have one more question.  Would an
    > > > atttypmod setting for each column help?  What about a compile-time
    > > > define?
    > >
    > > We discussed this at one point.  I think that is more useful for
    > > specifying output formats.  For example, 192.63.91.234/24 is identical
    > > to 192.63.91.234:255.255.255.0 (if we add that format) but I think
    > > that's 6.4++ too.  I think it would also only apply to the inet type
    > > but Paul should know.
    > >
    > > > I know Paul is a big name, but are the duplicate types meaningful for
    > > > ordinary users, or would they prefer just one type.  If they would
    > > > prefer one type, we can do that, and make sure Paul gets what he wants
    > > > too.
    > >
    > > I understand why Paul needs his type but I think the inet type is
    > > valuable too.  I think my suggestion above is a good compromise.
    >
    > bigness of names doesn't matter.  applications matter.  i can see
    > a use for
    > both types, but they are inherently different types.  a host that has a
    > netmask which can be expressed in cidr notation is one such type.  a net
    > that has a netmask which must be expressed in cidr notation is
    > another such
    > type.  the difference comes down to "host part must be zero" for
    > the network
    > type.  there are also some minor differences in the input/output formats,
    > since a host address always has four octets on both input and
    > output, while
    > a network only prints as many octets as the cidr width specifies,
    > and these
    > are the only required octets on input (though extra .0's can be
    > specified).
    >
    > > I think we are just about there.  If we go with my plan (completely
    > > different functionality for now and fold it later) there should be
    > > no API change later.  There will be code and catalogue changes but
    > > they should be relatively painless.
    >
    > so shall i test the inet_cidr_ functions and punt them on in?
    >
    >
    
    
    
  3. Re: [HACKERS] Re: inet/cidr/bind

    D'Arcy J.M. Cain <darcy@druid.net> — 1998-10-19T19:56:10Z

    Thus spake Paul A Vixie
    > > Input            cidr output        inet output
    > > =============    ================   ================
    > > 192.63.91.234    192.63.91.234/32	192.63.91.234/32
    > > 192.63.91        192.63.91/24       192.63.91.0/24
    > > 192.63           192.63/16          192.63.0.0/16
    > > 192              192/8              192.0.0.0/8
    > > 
    > > This look right to you, Paul?
    > 
    > no.  the last three inputs are not valid where a host address is expected.
    
    Can you amplify?  Is it correct as far as cidr goes?  If so, I have no
    problem making it an error for the inet type.  My thinking was based
    on the earlier concept of having one type and accepting networks in it.
    If we have the separate cidr type then I guess inet should always require
    4 octets (until ipv6 anyway) and cidr should be used for networks.
    
    How about something like 192.63.0.0/16?  Should that be an error under the
    inet type since it is the network?  I am thinking not since technically
    192.63.0.0 is a valid host under 192.63/16 although it is generally
    avoided since there is still software that assumes that it is the
    network or even the broadcast.
    
    > > I understand why Paul needs his type but I think the inet type is
    > > valuable too.  I think my suggestion above is a good compromise.
    > 
    > bigness of names doesn't matter.  applications matter.  i can see a use for
    > both types, but they are inherently different types.  a host that has a
    
    I agree although I did change my mind somewhat based on these discussions.
    
    And besides:
    
        if (strlen("D'Arcy J.M. Cain") > strlen("Paul Vixie"))
            printf("Who's the big name now?  :-)\n");
    
    And look at all that StUdLy punctuation.  :-)
    
    > a network only prints as many octets as the cidr width specifies, and these
    > are the only required octets on input (though extra .0's can be specified).
    
    Cool.  You answered another question I had before I asked it.
    
    > > I think we are just about there.  If we go with my plan (completely
    > > different functionality for now and fold it later) there should be
    > > no API change later.  There will be code and catalogue changes but
    > > they should be relatively painless.
    > 
    > so shall i test the inet_cidr_ functions and punt them on in?
    
    Ok, before I have a reality shift, the inet_cidr_ functions are simply
    the original inet_net_ functions renamed, right?
    
    I so hate it when the universe does that stuttering thing.
    -- 
    D'Arcy J.M. Cain <darcy@{druid|vex}.net>   |  Democracy is three wolves
    http://www.druid.net/darcy/                |  and a sheep voting on
    +1 416 424 2871     (DoD#0082)    (eNTP)   |  what's for dinner.
    
    
  4. Re: [HACKERS] Re: inet/cidr/bind

    D'Arcy J.M. Cain <darcy@druid.net> — 1998-10-19T20:00:46Z

    Thus spake Taral
    > Can't we just use a CONSTRAINT where a host address is expected? That sounds
    > easier than setting up two different types to me...
    
    The constraint would be pretty complicated and it doesn't handle the
    different output rules.
    
    Don't worry.  After things settle down we'll fold things together so
    that there is two input wrapper functions and everything else will be
    handled by the same functions so you won't hardly know the difference.
    I too originally thought there should be one type but Paul has convinced
    me otherwise.
    
    -- 
    D'Arcy J.M. Cain <darcy@{druid|vex}.net>   |  Democracy is three wolves
    http://www.druid.net/darcy/                |  and a sheep voting on
    +1 416 424 2871     (DoD#0082)    (eNTP)   |  what's for dinner.
    
    
  5. Re: [HACKERS] Re: inet/cidr/bind

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-10-19T23:59:17Z

    > bigness of names doesn't matter.  applications matter.  i can see a use for
    > both types, but they are inherently different types.  a host that has a
    > netmask which can be expressed in cidr notation is one such type.  a net
    > that has a netmask which must be expressed in cidr notation is another such
    > type.  the difference comes down to "host part must be zero" for the network
    > type.  there are also some minor differences in the input/output formats,
    > since a host address always has four octets on both input and output, while
    > a network only prints as many octets as the cidr width specifies, and these
    > are the only required octets on input (though extra .0's can be specified).
    > 
    > > I think we are just about there.  If we go with my plan (completely
    > > different functionality for now and fold it later) there should be
    > > no API change later.  There will be code and catalogue changes but
    > > they should be relatively painless.
    > 
    > so shall i test the inet_cidr_ functions and punt them on in?
    
    Yep.  Those are good points.  Let's go.
    
    -- 
      Bruce Momjian                        |  http://www.op.net/~candle
      maillist@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
    
    
  6. Re: [HACKERS] Re: inet/cidr/bind

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-10-20T00:03:28Z

    > And besides:
    > 
    >     if (strlen("D'Arcy J.M. Cain") > strlen("Paul Vixie"))
    >         printf("Who's the big name now?  :-)\n");
    > 
    > And look at all that StUdLy punctuation.  :-)
    
    That was funny.
    
    > > > I think we are just about there.  If we go with my plan (completely
    > > > different functionality for now and fold it later) there should be
    > > > no API change later.  There will be code and catalogue changes but
    > > > they should be relatively painless.
    > > 
    > > so shall i test the inet_cidr_ functions and punt them on in?
    > 
    > Ok, before I have a reality shift, the inet_cidr_ functions are simply
    > the original inet_net_ functions renamed, right?
    > 
    > I so hate it when the universe does that stuttering thing.
    
    Just a clarification.  If you have function that can be called with
    either type, you can put two entries in pg_proc(or I can :-) ), and that
    way the one function can take two types as parameters.  Allows use to
    maintain the type easier, and less bloat.
    
    -- 
      Bruce Momjian                        |  http://www.op.net/~candle
      maillist@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
    
    
  7. Re: [HACKERS] Re: inet/cidr/bind

    D'Arcy J.M. Cain <darcy@druid.net> — 1998-10-20T02:17:27Z

    Thus spake Bruce Momjian
    > > > so shall i test the inet_cidr_ functions and punt them on in?
    > > 
    > > Ok, before I have a reality shift, the inet_cidr_ functions are simply
    > > the original inet_net_ functions renamed, right?
    > > 
    > > I so hate it when the universe does that stuttering thing.
    > 
    > Just a clarification.  If you have function that can be called with
    > either type, you can put two entries in pg_proc(or I can :-) ), and that
    > way the one function can take two types as parameters.  Allows use to
    > maintain the type easier, and less bloat.
    
    My idea is to add a flag to the inet structure that specifies whether
    the object is a cidr or an inet.  Then every function checks that to
    decide what action to perform (which might be to raise an exception,
    trying to apply the host function to a cidr type for example) with
    one exception, the input function.  I see this as the functions to
    do input.
    
    inet *
    inet_common_in(char *src, int flag);
    This takes the input string and a flag that says whether a cidr or
    an inet is being input.  It pallocs the structure, sets the flag and
    performs the conversion based the type.  returns the inet pointer.
    
    inet *
    inet_net_in(char *src)
    {
        return inet_common_in(src, 0);
    }
    
    inet *
    inet_cidr_in(char *src)
    {
        return inet_common_in(src, 1);
    }
    
    However, let's get the two types in right now with two separate groups
    of functions and fold them after the release.  It won't change the
    user interface.  Unless we think we can do it quickly.
    
    In any case, maybe we can add the flag now since we figure we'll need
    it later anyway.
    
    -- 
    D'Arcy J.M. Cain <darcy@{druid|vex}.net>   |  Democracy is three wolves
    http://www.druid.net/darcy/                |  and a sheep voting on
    +1 416 424 2871     (DoD#0082)    (eNTP)   |  what's for dinner.
    
    
  8. Re: [HACKERS] Re: inet/cidr/bind

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-10-20T03:00:20Z

    > Thus spake Taral
    > > Can't we just use a CONSTRAINT where a host address is expected? That sounds
    > > easier than setting up two different types to me...
    > 
    > The constraint would be pretty complicated and it doesn't handle the
    > different output rules.
    > 
    > Don't worry.  After things settle down we'll fold things together so
    > that there is two input wrapper functions and everything else will be
    > handled by the same functions so you won't hardly know the difference.
    > I too originally thought there should be one type but Paul has convinced
    > me otherwise.
    > 
    
    If you define a fuction that can take inet or cidr type, I recommend you
    define a typedef called something like "inet_or_cidr" that is the same
    as inet, and use that in functions that can take either type.
    
    You can then clearly see what functions can take either type.  Also, you
    will not know at the time you are called what type is really being
    passed, but it may not matter, or you may be able to figure out what to
    do based on the data inside the type.
    
    Also, D'Arcy, the pressure is on.  There will not be a lot of time for
    debugging and redesign.  I am here if you need help.
    
    -- 
      Bruce Momjian                        |  http://www.op.net/~candle
      maillist@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
    
    
  9. Re: [HACKERS] Re: inet/cidr/bind

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-10-20T03:56:47Z

    > However, let's get the two types in right now with two separate groups
    > of functions and fold them after the release.  It won't change the
    > user interface.  Unless we think we can do it quickly.
    > 
    > In any case, maybe we can add the flag now since we figure we'll need
    > it later anyway.
    
    Once we put entries in the system tables, those really are not going to
    change dramatically until 6.5.
    
    Also, at this point, the least amount of code that can be added, should
    be added.  We already _had_(broken) an inet type, and now we are going
    to be throwing a lot of duplicate code in there for a new type.
    
    There is already concern that we are too close to the 6.4 final date to
    do anything with the INET type.  I am hearing that from another
    developer.
    
    I am not sure what to advise, but adding a new type is not trivial.  It
    is going to require an initdb by everyone, because it is going to be in
    the regression test.
    
    New type is involved, especially if I have to add unique indexing
    functions and other stuff for the new type.
    
    If people really want the INET/CIDR type for 6.4, we are going to need
    tremendous effort to pull this off.  That means good, clean code,
    documenation, and testing, regression tests, and soon.
    
    We can not just throw this in, and we can't expect the entire tree to
    wait for a new type.
    
    My personal opinion is that I am not ready to add a new type, and new
    duplicate functions for that type, this close to final.  I can add the
    type, and the pg_proc/indexing pointers to link in the existing
    inet functions, but full type inclusion is too much, I think.
    
    For example, I have an inet_ops entry in pg_class.  I don't want to add
    an cidr_ops function that behaves exactly the same.  If we can't do this
    right, then we will not do it for 6.4.  My experience is that dumping
    partial solutions into 250k lines of code is a bad thing.
    
    So, if people really want it, it has to be _good_.  If is not that
    important, it can wait.
    
    These are my opinions, and of course, can be over-ruled.
    
    -- 
      Bruce Momjian                        |  http://www.op.net/~candle
      maillist@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
    
    
  10. Re: [HACKERS] Re: inet/cidr/bind

    D'Arcy J.M. Cain <darcy@druid.net> — 1998-10-20T04:11:26Z

    Thus spake Bruce Momjian
    > If you define a fuction that can take inet or cidr type, I recommend you
    > define a typedef called something like "inet_or_cidr" that is the same
    > as inet, and use that in functions that can take either type.
    
    Perhaps.  We can look at that 6.4++.  For now there will be redundancy.
    Afterwards we'll look at how to fold them.
    
    > passed, but it may not matter, or you may be able to figure out what to
    > do based on the data inside the type.
    
    Ultimately, I think the latter.
    
    > Also, D'Arcy, the pressure is on.  There will not be a lot of time for
    > debugging and redesign.  I am here if you need help.
    
    The minute that Paul's code is in the tree, I'm there.  However, if it
    helps, here is cidr.c which is just the original inet.c with substitutions.
    There may be minor changes when I see Paul's functions so I won't submit it
    to patches yet but if someone wants to review it early, here it is.
    
    
    /*
     *	PostgreSQL type definitions for the CIDR type.  This
     *	is for IP V4 CIDR notation, but prepared for V6: just
     *	add the necessary bits where the comments indicate.
     *
     *	$Id$
     */
    
    #include <sys/types.h>
    #include <sys/socket.h>
    
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #include <postgres.h>
    #include <utils/palloc.h>
    #include <utils/builtins.h>
    #include <utils/inet.h>
    
    static int v4bitncmp(unsigned int a1, unsigned int a2, int bits);
    
    /*
     *	Access macros.	Add IPV6 support.
     */
    
    #define ip_addrsize(inetptr) \
    	(((inet_struct *)VARDATA(inetptr))->family == AF_INET ? 4 : -1)
    
    #define ip_family(inetptr) \
    	(((inet_struct *)VARDATA(inetptr))->family)
    
    #define ip_bits(inetptr) \
    	(((inet_struct *)VARDATA(inetptr))->bits)
    
    #define ip_v4addr(inetptr) \
    	(((inet_struct *)VARDATA(inetptr))->addr.ipv4_addr)
    
    /*
     *	IP address reader.
     */
    
    inet *
    cidr_in(char *src)
    {
    	int			bits;
    	inet	   *dst;
    
    	dst = palloc(VARHDRSZ + sizeof(inet_struct));
    	if (dst == NULL)
    	{
    		elog(ERROR, "unable to allocate memory in cidr_in()");
    		return (NULL);
    	}
    	/* First, try for an IP V4 address: */
    	ip_family(dst) = AF_INET;
    	bits = inet_cidr_pton(ip_family(dst), src, &ip_v4addr(dst), ip_addrsize(dst));
    	if ((bits < 0) || (bits > 32))
    	{
    		/* Go for an IPV6 address here, before faulting out: */
    		elog(ERROR, "could not parse \"%s\"", src);
    		pfree(dst);
    		return (NULL);
    	}
    	VARSIZE(dst) = VARHDRSZ
    		+ ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
    		+ ip_addrsize(dst);
    	ip_bits(dst) = bits;
    	return (dst);
    }
    
    /*
     *	IP address output function.
     */
    
    char *
    cidr_out(inet *src)
    {
    	char	   *dst,
    				tmp[sizeof("255.255.255.255/32")];
    
    	if (ip_family(src) == AF_INET)
    	{
    		/* It's an IP V4 address: */
    		if (inet_cidr_ntop(AF_INET, &ip_v4addr(src), ip_addrsize(src), ip_bits(src),
    						  tmp, sizeof(tmp)) < 0)
    		{
    			elog(ERROR, "unable to print address (%s)", strerror(errno));
    			return (NULL);
    		}
    	}
    	else
    	{
    		/* Go for an IPV6 address here, before faulting out: */
    		elog(ERROR, "unknown address family (%d)", ip_family(src));
    		return (NULL);
    	}
    	dst = palloc(strlen(tmp) + 1);
    	if (dst == NULL)
    	{
    		elog(ERROR, "unable to allocate memory in cidr_out()");
    		return (NULL);
    	}
    	strcpy(dst, tmp);
    	return (dst);
    }
    
    /*
     *	Boolean tests for magnitude.  Add V4/V6 testing!
     */
    
    bool
    cidr_lt(inet *a1, inet *a2)
    {
    	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
    	{
    		int			order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
    
    		return ((order < 0) || ((order == 0) && (ip_bits(a1) < ip_bits(a2))));
    	}
    	else
    	{
    		/* Go for an IPV6 address here, before faulting out: */
    		elog(ERROR, "cannot compare address families %d and %d",
    			 ip_family(a1), ip_family(a2));
    		return (FALSE);
    	}
    }
    
    bool
    cidr_le(inet *a1, inet *a2)
    {
    	return (inet_lt(a1, a2) || inet_eq(a1, a2));
    }
    
    bool
    cidr_eq(inet *a1, inet *a2)
    {
    	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
    	{
    		return ((ip_bits(a1) == ip_bits(a2))
    		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
    	}
    	else
    	{
    		/* Go for an IPV6 address here, before faulting out: */
    		elog(ERROR, "cannot compare address families %d and %d",
    			 ip_family(a1), ip_family(a2));
    		return (FALSE);
    	}
    }
    
    bool
    cidr_ge(inet *a1, inet *a2)
    {
    	return (inet_gt(a1, a2) || inet_eq(a1, a2));
    }
    
    bool
    cidr_gt(inet *a1, inet *a2)
    {
    	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
    	{
    		int			order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
    
    		return ((order > 0) || ((order == 0) && (ip_bits(a1) > ip_bits(a2))));
    	}
    	else
    	{
    		/* Go for an IPV6 address here, before faulting out: */
    		elog(ERROR, "cannot compare address families %d and %d",
    			 ip_family(a1), ip_family(a2));
    		return (FALSE);
    	}
    }
    
    bool
    cidr_ne(inet *a1, inet *a2)
    {
    	return (!inet_eq(a1, a2));
    }
    
    bool
    cidr_sub(inet *a1, inet *a2)
    {
    	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
    	{
    		return ((ip_bits(a1) > ip_bits(a2))
    		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0));
    	}
    	else
    	{
    		/* Go for an IPV6 address here, before faulting out: */
    		elog(ERROR, "cannot compare address families %d and %d",
    			 ip_family(a1), ip_family(a2));
    		return (FALSE);
    	}
    }
    
    bool
    cidr_subeq(inet *a1, inet *a2)
    {
    	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
    	{
    		return ((ip_bits(a1) >= ip_bits(a2))
    		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0));
    	}
    	else
    	{
    		/* Go for an IPV6 address here, before faulting out: */
    		elog(ERROR, "cannot compare address families %d and %d",
    			 ip_family(a1), ip_family(a2));
    		return (FALSE);
    	}
    }
    
    bool
    cidr_sup(inet *a1, inet *a2)
    {
    	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
    	{
    		return ((ip_bits(a1) < ip_bits(a2))
    		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
    	}
    	else
    	{
    		/* Go for an IPV6 address here, before faulting out: */
    		elog(ERROR, "cannot compare address families %d and %d",
    			 ip_family(a1), ip_family(a2));
    		return (FALSE);
    	}
    }
    
    bool
    cidr_supeq(inet *a1, inet *a2)
    {
    	if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
    	{
    		return ((ip_bits(a1) <= ip_bits(a2))
    		 && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
    	}
    	else
    	{
    		/* Go for an IPV6 address here, before faulting out: */
    		elog(ERROR, "cannot compare address families %d and %d",
    			 ip_family(a1), ip_family(a2));
    		return (FALSE);
    	}
    }
    
    /*
     *	Comparison function for sorting.  Add V4/V6 testing!
     */
    
    int4
    cidr_cmp(inet *a1, inet *a2)
    {
    	if (ntohl(ip_v4addr(a1)) < ntohl(ip_v4addr(a2)))
    		return (-1);
    	else if (ntohl(ip_v4addr(a1)) > ntohl(ip_v4addr(a2)))
    		return (1);
    	return 0;
    }
    
    /*
     *	Bitwise comparison for V4 addresses.  Add V6 implementation!
     */
    
    static int
    v4bitncmp(unsigned int a1, unsigned int a2, int bits)
    {
    	unsigned long mask = 0;
    	int			i;
    
    	for (i = 0; i < bits; i++)
    		mask = (mask >> 1) | 0x80000000;
    	a1 = ntohl(a1);
    	a2 = ntohl(a2);
    	if ((a1 & mask) < (a2 & mask))
    		return (-1);
    	else if ((a1 & mask) > (a2 & mask))
    		return (1);
    	return (0);
    }
    
    
    
    -- 
    D'Arcy J.M. Cain <darcy@{druid|vex}.net>   |  Democracy is three wolves
    http://www.druid.net/darcy/                |  and a sheep voting on
    +1 416 424 2871     (DoD#0082)    (eNTP)   |  what's for dinner.
    
    
  11. Re: [HACKERS] Re: inet/cidr/bind

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-10-20T04:21:10Z

    > Thus spake Bruce Momjian
    > > If you define a fuction that can take inet or cidr type, I recommend you
    > > define a typedef called something like "inet_or_cidr" that is the same
    > > as inet, and use that in functions that can take either type.
    > 
    > Perhaps.  We can look at that 6.4++.  For now there will be redundancy.
    > Afterwards we'll look at how to fold them.
    
    I hope you realize that that 6.4++ would have to be 6.5.  We typically
    don't to system table changes as part of minor releases, unless there is
    a really good reason.  It is hard to do for us and for the users.
    
    -- 
      Bruce Momjian                        |  http://www.op.net/~candle
      maillist@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
    
    
  12. Re: [HACKERS] Re: inet/cidr/bind

    D'Arcy J.M. Cain <darcy@druid.net> — 1998-10-20T13:51:21Z

    Thus spake Bruce Momjian
    > > However, let's get the two types in right now with two separate groups
    > > of functions and fold them after the release.  It won't change the
    > > user interface.  Unless we think we can do it quickly.
    > > 
    > > In any case, maybe we can add the flag now since we figure we'll need
    > > it later anyway.
    > 
    > Once we put entries in the system tables, those really are not going to
    > change dramatically until 6.5.
    
    While I would like everything in there now, I can live with this as long
    as the user interface doesn't change.
    
    How about this?  We now have an inet type pretty much completed.  Let's
    put that back in right now.  copy all the files involved, substitute
    inet to cidr in the function names and make it the new cidr type.  Once
    we agree on which one is the host+netmask type add the extra functions
    for netmask, masklen, host, network_without_bits, network_with_bits and
    broadcast making them stubs if necessary.  I'll get my code into the
    right file as soon as possible.  Later we can fold things in better
    but we can do it without changing the catalogues.  If it makes it more
    efficient we can change the catalogue where 6.5 comes out.
    
    If we can do this right away I think we have a good chance of getting
    it into 6.4 properly anyway.
    
    > My personal opinion is that I am not ready to add a new type, and new
    > duplicate functions for that type, this close to final.  I can add the
    > type, and the pg_proc/indexing pointers to link in the existing
    > inet functions, but full type inclusion is too much, I think.
    > 
    > For example, I have an inet_ops entry in pg_class.  I don't want to add
    > an cidr_ops function that behaves exactly the same.  If we can't do this
    > right, then we will not do it for 6.4.  My experience is that dumping
    > partial solutions into 250k lines of code is a bad thing.
    
    Of course this is your decision.  We have the inet type now and as long
    as we know what that type is, we can always add the other for 6.5 if
    we can't get it in now.
    
    > So, if people really want it, it has to be _good_.  If is not that
    > important, it can wait.
    
    So far less than a half dozen people are really involved in this discussion.
    How about a quick straw poll of who really wants this in?
    
    > These are my opinions, and of course, can be over-ruled.
    
    Not if you need to do the work on the catalogues they can't.  :-)
    
    -- 
    D'Arcy J.M. Cain <darcy@{druid|vex}.net>   |  Democracy is three wolves
    http://www.druid.net/darcy/                |  and a sheep voting on
    +1 416 424 2871     (DoD#0082)    (eNTP)   |  what's for dinner.
    
    
    
  13. Re: [HACKERS] Re: inet/cidr/bind

    D'Arcy J.M. Cain <darcy@druid.net> — 1998-10-20T14:11:32Z

    Thus spake Bruce Momjian
    > If people really want the INET/CIDR type for 6.4, we are going to need
    > tremendous effort to pull this off.  That means good, clean code,
    > documenation, and testing, regression tests, and soon.
    
    Would it be helpful to discuss this in a more direct matter?  I am sitting
    in #postgreSQL on EFNet (IRC) if anyone wants to join me there.
    
    -- 
    D'Arcy J.M. Cain <darcy@{druid|vex}.net>   |  Democracy is three wolves
    http://www.druid.net/darcy/                |  and a sheep voting on
    +1 416 424 2871     (DoD#0082)    (eNTP)   |  what's for dinner.