Обсуждение: CIDR type and functions

Поиск
Список
Период
Сортировка

CIDR type and functions

От
darcy@druid.net (D'Arcy J.M. Cain)
Дата:
Just curious, what functions did we finally settle on for this type?
I ask because I just thought of another function that might be useful.

select block(cidr1, cidr2);

to return 1 if cidr2 is part of the cidr1 block, -1 if cidr1 is part
of the cidr2 block and 0 if neither.

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

Re: [HACKERS] CIDR type and functions

От
Bruce Momjian
Дата:
> Just curious, what functions did we finally settle on for this type?
> I ask because I just thought of another function that might be useful.
>
> select block(cidr1, cidr2);
>
> to return 1 if cidr2 is part of the cidr1 block, -1 if cidr1 is part
> of the cidr2 block and 0 if neither.
>

Check \df and \fo.  There is a >> and << operators that do subnet
testing.


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


Re: [HACKERS] CIDR type and functions

От
darcy@druid.net (D'Arcy J.M. Cain)
Дата:
Thus spake Bruce Momjian
> Check \df and \fo.  There is a >> and << operators that do subnet
> testing.

[I assume you meant \do]

Cool.  I checked out what other functions as well.  I don't see a couple
that were discussed early on though.  Specifically, how about functions
to extract the  host, the network or the netmask from an address?

Here are the functions I had suggested.

    netmask('192.3.4.5/24::cidr') == 255.255.255.0
    masklen('192.3.4.5/24::cidr') == 24
    host('192.3.4.5/24::cidr') == 192.3.4.5
    network('192.3.4.5/24::cidr') == 192.3.4.0

and perhaps;

    class('192.3.4.5/24::cidr') == C
    classnet('192.3.4.5/24::cidr') == 192.3.4

Can I help code up some of this stuff?

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

Re: [HACKERS] CIDR type and functions

От
Bruce Momjian
Дата:
> Thus spake Bruce Momjian
> > Check \df and \fo.  There is a >> and << operators that do subnet
> > testing.
>
> [I assume you meant \do]
>
> Cool.  I checked out what other functions as well.  I don't see a couple
> that were discussed early on though.  Specifically, how about functions
> to extract the  host, the network or the netmask from an address?
>
> Here are the functions I had suggested.
>
>     netmask('192.3.4.5/24::cidr') == 255.255.255.0
>     masklen('192.3.4.5/24::cidr') == 24
>     host('192.3.4.5/24::cidr') == 192.3.4.5
>     network('192.3.4.5/24::cidr') == 192.3.4.0
>
> and perhaps;
>
>     class('192.3.4.5/24::cidr') == C
>     classnet('192.3.4.5/24::cidr') == 192.3.4
>
> Can I help code up some of this stuff?

Yes, we need those.  Code them up, and I will add them as standard
types.


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


Re: [HACKERS] CIDR type and functions

От
darcy@druid.net (D'Arcy J.M. Cain)
Дата:
Thus spake Bruce Momjian
> > Here are the functions I had suggested.
> >
> >     netmask('192.3.4.5/24::cidr') == 255.255.255.0
> >     masklen('192.3.4.5/24::cidr') == 24
> >     host('192.3.4.5/24::cidr') == 192.3.4.5
> >     network('192.3.4.5/24::cidr') == 192.3.4.0

I forgot
        broadcast('192.3.4.5/24::cidr') == 192.3.4.255

> > and perhaps;
> >
> >     class('192.3.4.5/24::cidr') == C
> >     classnet('192.3.4.5/24::cidr') == 192.3.4

I'll leave these for the moment as I'm not sure what to do with invalid
classful addresses such as 192.3.4.5/16.  I'll bring it up again after
6.4 is released.

> > Can I help code up some of this stuff?
>
> Yes, we need those.  Code them up, and I will add them as standard
> types.

OK, I started but I could use a small change to inet_net_ntop.c which
I think impliments something we discussed anyway.  I just need to know
if this is going to affect anything else.  Basically it allows for
the number of bits to be -1 which is interpreted as a host with
unspecified netmask.  The changes cause all outputs to leave of
the netmask part if it is -1.  I realize that I will have to change
some of the other functions in inet.c but is there anything else
that might bite me?

If there is no problem I'll resubmit this to the patches list.

*** ../src.original/./backend/utils/adt/inet_net_ntop.c    Fri Oct  9 17:37:27 1998
--- ./backend/utils/adt/inet_net_ntop.c    Fri Oct  9 17:39:05 1998
***************
*** 85,90 ****
--- 85,97 ----
      char       *t;
      u_int        m;
      int            b;
+     int            print_bits = 1;
+
+     if (bits == -1)
+     {
+         bits = 32;
+         print_bits = 0;
+     }

      if (bits < 0 || bits > 32)
      {
***************
*** 129,137 ****
      }

      /* Format CIDR /width. */
!     if (size < sizeof "/32")
!         goto emsgsize;
!     dst += SPRINTF((dst, "/%u", bits));
      return (odst);

  emsgsize:
--- 136,147 ----
      }

      /* Format CIDR /width. */
!     if (print_bits)
!     {
!         if (size < sizeof "/32")
!             goto emsgsize;
!         dst += SPRINTF((dst, "/%u", bits));
!     }
      return (odst);

  emsgsize:


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

Re: [HACKERS] CIDR type and functions

От
Tom Ivar Helbekkmo
Дата:
D'Arcy J.M. Cain:

>     netmask('192.3.4.5/24::cidr') == 255.255.255.0
>     masklen('192.3.4.5/24::cidr') == 24
>     host('192.3.4.5/24::cidr') == 192.3.4.5
>     network('192.3.4.5/24::cidr') == 192.3.4.0
>     broadcast('192.3.4.5/24::cidr') == 192.3.4.255
> and perhaps;
>     class('192.3.4.5/24::cidr') == C
>     classnet('192.3.4.5/24::cidr') == 192.3.4

Bruce Momjian:

> Yes, we need those.  Code them up, and I will add them as standard
> types.

This is really all contrary to the concept of CIDR notation.  While I
did end up calling the type INET instead of CIDR (which seemed to be
the consensus when the discussion was going on, because INET would be
more intuitively understandable by users than CIDR), I still stuck to
the behavior that Paul Vixie wanted: CIDR notation and representation.
It seemed to me that this was a good compromise, as it gives us a
clean, standards-based notation where host addresses are a functioning
special case.  However, networks, netmasks, broadcast addresses and
interface addresses all need to be stored in separate INET values.

If what we actually want is what D'Arcy shows above, then we should
drop CIDR notation, stop using Paul Vixie's functions for dealing with
the same, and change the storage format to include more information,
and a different and more flexible input format.  Just off the top of
my head, 'inet 158.37.96.1 netmask 0xffffff00 broadcast 158.37.96.255'
would be a cool input (and output) format to support.  :-)

D'Arcy J.M. Cain:

> OK, I started but I could use a small change to inet_net_ntop.c [...]

I have to side with Paul on this one: that file and its companion with
the similar name were pulled in from the BIND distribution simply for
convenience, so we wouldn't have to insist that people must install
BIND from source to be able to install PostgreSQL.  We really, really
shouldn't change them.  If what we want is not what they implement, we
should drop them and implement what we want.

My vote (surprise! surprise!) goes toward keeping what we've got right
now.  As Paul says, there's an RFC describing the behavior of the data
type as it now stands, and it's not as if it were difficult to do all
the other things one might want to do with it.

However, adding utility functions to do some of the things D'Arcy
suggests sounds good.  I would think that they should be defined to
take INET parameters and return INET results, and the most useful ones
seem to me to be the following three (shown with various inputs):

netmask('158.37.96')        ==> '255.255.255.0/32'
netmask('158.37.96/21')        ==> '255.255.248.0/32'
broadcast('158.37')        ==> '158.37.255.255/32'
broadcast('158.37.96')        ==> '158.37.96.255/32'
broadcast('158.37.96/21')    ==> '158.37.103.255/32'
network('158.37.96.15')        ==> '158.37/16'

Note that the last one has to assume the old class A/B/C/D/E stuff.

-tih
--
Popularity is the hallmark of mediocrity.  --Niles Crane, "Frasier"

Re: [HACKERS] CIDR type and functions

От
darcy@druid.net (D'Arcy J.M. Cain)
Дата:
Thus spake Tom Ivar Helbekkmo
> D'Arcy J.M. Cain:
> >     netmask('192.3.4.5/24::cidr') == 255.255.255.0
> >     masklen('192.3.4.5/24::cidr') == 24
> >     host('192.3.4.5/24::cidr') == 192.3.4.5
> >     network('192.3.4.5/24::cidr') == 192.3.4.0
> >     broadcast('192.3.4.5/24::cidr') == 192.3.4.255
> > and perhaps;
> >     class('192.3.4.5/24::cidr') == C
> >     classnet('192.3.4.5/24::cidr') == 192.3.4
>
> Bruce Momjian:
>
> > Yes, we need those.  Code them up, and I will add them as standard
> > types.
>
> This is really all contrary to the concept of CIDR notation.  While I
> did end up calling the type INET instead of CIDR (which seemed to be
> the consensus when the discussion was going on, because INET would be
> more intuitively understandable by users than CIDR), I still stuck to

I thought there was also a suggestion that it would handle more than
just straight CIDR.

> the behavior that Paul Vixie wanted: CIDR notation and representation.
> It seemed to me that this was a good compromise, as it gives us a
> clean, standards-based notation where host addresses are a functioning
> special case.  However, networks, netmasks, broadcast addresses and
> interface addresses all need to be stored in separate INET values.

If you mean that a particular column in a table can only hold one
of the above types, I agree.  However, I see no problem with a basic
type that can handle conceptually different objects.  I made an analogy
in an earlier post to integers.  They can be ordinals (ID, part number,
etc.) or they can be cardinals such as quantity.  We would never
consider creating a field that sometimes has a part number and sometimes
has a quantity but the same base type can be used for both.  Similarly,
there should be a type that handles different types associated with
IP numbers.

> If what we actually want is what D'Arcy shows above, then we should
> drop CIDR notation, stop using Paul Vixie's functions for dealing with
> the same, and change the storage format to include more information,
> and a different and more flexible input format.  Just off the top of
> my head, 'inet 158.37.96.1 netmask 0xffffff00 broadcast 158.37.96.255'
> would be a cool input (and output) format to support.  :-)

I'm not sure I understand this.  Given a host and a netmask I can infer
the network and the broadcast.  Why specify them separately?  That's
what my functions were for.

> D'Arcy J.M. Cain:
> > OK, I started but I could use a small change to inet_net_ntop.c [...]
> I have to side with Paul on this one: that file and its companion with
> the similar name were pulled in from the BIND distribution simply for
> convenience, so we wouldn't have to insist that people must install
> BIND from source to be able to install PostgreSQL.  We really, really
> shouldn't change them.  If what we want is not what they implement, we
> should drop them and implement what we want.

Or impliment both.

> My vote (surprise! surprise!) goes toward keeping what we've got right
> now.  As Paul says, there's an RFC describing the behavior of the data
> type as it now stands, and it's not as if it were difficult to do all
> the other things one might want to do with it.
>
> However, adding utility functions to do some of the things D'Arcy
> suggests sounds good.  I would think that they should be defined to
> take INET parameters and return INET results, and the most useful ones
> seem to me to be the following three (shown with various inputs):
>
> netmask('158.37.96')        ==> '255.255.255.0/32'
> netmask('158.37.96/21')        ==> '255.255.248.0/32'
> broadcast('158.37')        ==> '158.37.255.255/32'
> broadcast('158.37.96')        ==> '158.37.96.255/32'
> broadcast('158.37.96/21')    ==> '158.37.103.255/32'
> network('158.37.96.15')        ==> '158.37/16'

I'm not sure why the /32 on the end of the netmask and broadcast functions.
These are convenience functions I thought.  Of course, I am also assuming
that an unspecified netmask has a special desigation (-1) so it would
be possible to convert back and forth.

The two you left out (ignoring class functions for the moment) are
simple convenience functions too.  The masklen function simply pulls
the bits value out of the underlying structure and the host function
drops the netmask part of the output.  I suppose there should also be
a function like this.

combine('158.37.96', 24)    ==> '158.37.96/24'

It would be nice if this also worked.

combine('158.37.96', '255.255.255.0')    ==> '158.37.96/24'

But we have to decide what to do with invalid inputs like '255.255.0.255'.
Do we raise an exception, treat it as /16 or something else?

Assuming that casting would make the following coercions, the rest, other
than the last one, should work as I envision it.

'158.37.96'       ==> '158.37.96.0/24'
'158.37.96/21'    ==> '158.37.96.0/21'
'158.37'          ==> '158.37.0.0/16'
'158.37.96'       ==> '158.37.96.0/24'
'158.37.96/21'    ==> '158.37.96.0/21'

The coercion rule is pretty simple.  If there are less than 4 octets
then pad it out to zeros and make the masklen 32 - (8 * X) where X
is the number of zeroes added.

Hmm.  There's one place that separate types for networks and hosts
would be useful.  You could disallow those coercions on the host type,
That way you catch errors like people entering '158.37.11' when they
meant to type '158.37.1.1' but otherwise they would be treated the
same.

> Note that the last one has to assume the old class A/B/C/D/E stuff.

Not unreasonable.  I was simply going to ignore class specific stuff
until after 6.4.  However, I don't see a big problem with it.  Assume
the following coercion.

'158.37.96.15'   ==> '158.37.96.15/-1'

Then we make the network function use the old classful rules when the
mask length is unspecified (-1.)

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