mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-15 08:20:16 +08:00
I investigated carefully POSTGRES data base (in idea to use it for
our internal IP routing data base, and because I have participated in Ingres development here in Russia in RUBIN/DEMOS project - through it was not freeware work - and it was very interesting for me too see such good freeware data base as PostgreSQL), and I modified 'ipaddr' data type library in accordance to our requests and to allow SQL do indexing over ipaddr objects. You can read description at 'http://relcom.EU.net/ipaddr.html' and get sources at 'http://relcom.EU.net/ip_class.tar.gz'. It contains sources, sql scripts for incorporating new data type into postgres (including ipaddr_ops operator class incorporation) and 20,000 records based data test for the indexing. I am not sure if it's proper mail list for this information, and if it's interesting for anyone except me to get full-functional ipaddress class. I am ready to make all modifications, bug fixing and documentation for this data class if it's nessesary for it's contribution to the Postgres data base. Anyway, all my work was based at original 'ip&mac data type' contribution, written by Tom Ivar Helbekkmo. Be free to write me any questions or requests about this work. ============================================================== Aleksei Roudnev, Network Operations Center, Relcom, Moscow (+7 095) 194-19-95 (Network Operations Center Hot Line),(+7 095) 239-10-10, N 13729 (pager) (+7 095) 196-72-12 (Support), (+7 095) 194-33-28 (Fax)
This commit is contained in:
parent
583891833f
commit
92da1c3a6a
@ -1,37 +1,27 @@
|
||||
#
|
||||
# PostgreSQL types for IP and MAC addresses
|
||||
#
|
||||
# $Id: Makefile,v 1.3 1998/04/22 04:14:11 scrappy Exp $
|
||||
# $Id: Makefile,v 1.4 1998/06/16 04:34:29 momjian Exp $
|
||||
|
||||
SRCDIR= ../../src
|
||||
all: ip.so mac.so
|
||||
|
||||
include $(SRCDIR)/Makefile.global
|
||||
ip.so: ip.o
|
||||
ld -Bshareable -o ip.so ip.o
|
||||
|
||||
CONTRIBDIR=$(LIBDIR)/modules
|
||||
ip.o: ip.c
|
||||
cc -g -O -fPIC -I/usr/local/pgsql/include -c ip.c
|
||||
|
||||
CFLAGS+= $(CFLAGS_SL) -I$(SRCDIR)/include
|
||||
mac.so: mac.o
|
||||
ld -Bshareable -o mac.so mac.o
|
||||
|
||||
ifdef REFINT_VERBOSE
|
||||
CFLAGS+= -DREFINT_VERBOSE
|
||||
endif
|
||||
mac.o: mac.c mac.h
|
||||
cc -g -O -fPIC -I/usr/local/pgsql/include -c mac.c
|
||||
|
||||
TARGETS= ip$(DLSUFFIX) ip.sql mac$(DLSUFFIX) mac.sql
|
||||
install: ip.so mac.so
|
||||
install -c ip.so mac.so /usr/local/pgsql/modules
|
||||
|
||||
CLEANFILES+= $(TARGETS)
|
||||
|
||||
all:: $(TARGETS)
|
||||
|
||||
install:: all $(CONTRIBDIR)
|
||||
for f in *$(DLSUFFIX); do $(INSTALL) -c $$f $(CONTRIBDIR)/$$f; done
|
||||
|
||||
$(CONTRIBDIR):
|
||||
mkdir -p $(CONTRIBDIR)
|
||||
|
||||
%.sql: %.sql.in
|
||||
rm -f $@; \
|
||||
C=`pwd`; \
|
||||
sed -e "s:_OBJWD_:$(CONTRIBDIR):g" \
|
||||
-e "s:_DLSUFFIX_:$(DLSUFFIX):g" < $< > $@
|
||||
|
||||
clean:
|
||||
rm -f $(TARGETS) *.o
|
||||
clean:
|
||||
rm -f *.o *.so *.b
|
||||
#
|
||||
# eof
|
||||
#
|
||||
|
@ -1,56 +1,43 @@
|
||||
PostgreSQL type extensions for IP and MAC addresses.
|
||||
---------------------------------------------------
|
||||
|
||||
$Id: README,v 1.2 1998/02/14 17:58:03 scrappy Exp $
|
||||
This directory contain 2 new classes - macaddr to store mac addresses
|
||||
written by (Bergen, Norway, 1998-01-31, Tom Ivar Helbekkmo
|
||||
(tih@Hamartun.Priv.NO)), and ipaddr type and ipaddr_ops operator class,
|
||||
rewritten by me (alex@relcom.EU.net, Aleksei Roudnev, Moscow, Russia,
|
||||
25.05.98) and written first by Bergen.
|
||||
|
||||
I needed to record IP and MAC level ethernet addresses in a data
|
||||
base, and I really didn't want to store them as plain strings, with
|
||||
no enforced error checking, so I put together the accompanying code
|
||||
as my first experiment with adding a data type to PostgreSQL. I
|
||||
then thought that this might be useful to others, both directly and
|
||||
as a very simple example of how to do this sort of thing, so here
|
||||
it is, in the hope that it will be useful.
|
||||
To see the description of macaddr type, read README.ORIG file.
|
||||
To see the description of ipaddr type, read ipaddr.html file.
|
||||
^^^^^^^^^^^
|
||||
|
||||
IP addresses are implemented as a 6 byte struct (this may be 1 byte
|
||||
more than is useful, but I figured that since it has to be at least 5,
|
||||
it might as well be an even number of bytes) that contains the four
|
||||
byte address and a mask width. The external representation of an IP
|
||||
address looks like '158.37.96.15/32' (or just '158.37.96.15', which is
|
||||
understood to mean the same thing). This address happens to be part
|
||||
of a subnet where I work; '158.37.96.0/24', which itself is a part of
|
||||
the larger subnet allocated to our site, which is '158.37.96.0/21',
|
||||
which again, if you go by the old book, is part of the class "B" net
|
||||
called '158.37.0.0/16'.
|
||||
This ipaddr type differ slightly from the original one. First, if you
|
||||
input '193.124.23.0' it sets /24 prefix instead of /32 (this is in
|
||||
accordance to CISCO's notification and our internal data bases and
|
||||
records); if you input '0.0.0.0' it's '0.0.0.0/0' (default) but not NULL
|
||||
or NOADDR value.
|
||||
|
||||
Input and output functions are supplied, along with the "normal" <,
|
||||
<=, =, >=, > and <> operators, which all do what you expect. In
|
||||
addition, there is a function to check whether a given address is a
|
||||
member of a given subnet: ipaddr_in_net(addr, net), and functions to
|
||||
return the netmask and the broadcast address of a given network:
|
||||
ipaddr_mask(net) and ipaddr_bcast(net).
|
||||
Then, you can store ADDRESS/PREFIX pair, even if ADDRESS is not the
|
||||
subnet address (for example, you can store interface address and mask at
|
||||
the single attribute). This allow us to determine, for example, which
|
||||
interfaces/routers are accessible by connected network for our interface
|
||||
(select * from database where '193.124.23.4' @ interface_address);
|
||||
|
||||
MAC level ethernet addresses are implemented as a 6 byte struct that
|
||||
contains the address as unsigned chars. Several input forms are
|
||||
accepted; the following are all the same address: '08002b:010203',
|
||||
'08002b-010203', '0800.2b01.0203', '08-00-2b-01-02-03' and
|
||||
'08:00:2b:01:02:03'. Upper and lower case is accepted for the digits
|
||||
'a' through 'f'. Output is always in the latter of the given forms.
|
||||
Then, it have been written a few new functions and a few operators
|
||||
(addr1 @ addr - TRUE if addr1 is the part of subnet addr2);
|
||||
'ipaddr_print' function allow you to convert address to any form you
|
||||
want; and so on.
|
||||
|
||||
As with IP addresses, input and output functions are supplied as well
|
||||
as the "normal" operators, which do what you expect. As an extra
|
||||
feature, a function macaddr_manuf() is defined, which returns the name
|
||||
of the manufacturer as a string. This is currently held in a
|
||||
hard-coded struct internal to the C module -- it might be smarter to
|
||||
put this information into an actual data base table, and look up the
|
||||
manufacturer there. (Another TODO, for both new data types, is to
|
||||
interface them to indices. If anyone can explain this to me in a way
|
||||
that is easier to understand than the current documentation, I would
|
||||
be most grateful!)
|
||||
And then, I add ipi.sql setup script and test1.sql + test2.sql test
|
||||
scripts to allow and test indexing by this new class.
|
||||
|
||||
I don't know what changes are needed to the Makefile for other systems
|
||||
than the one I'm running (NetBSD 1.3), but anyway: to install on a BSD
|
||||
system: fix the path names in the SQL files and the Makefile if you
|
||||
need to, then make, make install, slurp the SQL files into psql or
|
||||
whatever, and you're off. Enjoy!
|
||||
This ipaddr type/opclass are used for our internal IP ROUTING and
|
||||
ACCOUNTING data base, and I hope it shpuld be usefull for more people.
|
||||
|
||||
Bergen, Norway, 1998-01-31, Tom Ivar Helbekkmo (tih@Hamartun.Priv.NO).
|
||||
For those who like crazy tasks, I propose to realise 'RTREE' indexing
|
||||
method to allow effectively use '@' operation for the binding statistic
|
||||
records to the customers etc networks. Note 'ipaddr' type can be written
|
||||
as 'start,end' coordination pair and it's possible to define all '<<,
|
||||
&<, @@, etc graphical operators over this type.
|
||||
|
||||
|
||||
25.05.1998, Aleksei Roudnev, alex@relcom.EU.net, Relcom, Moscow, Russia. /+7-095-194-1995.
|
||||
==========================================================================================
|
||||
|
56
contrib/ip_and_mac/README.ORIG
Normal file
56
contrib/ip_and_mac/README.ORIG
Normal file
@ -0,0 +1,56 @@
|
||||
PostgreSQL type extensions for IP and MAC addresses.
|
||||
---------------------------------------------------
|
||||
|
||||
$Id: README.ORIG,v 1.1 1998/06/16 04:34:29 momjian Exp $
|
||||
|
||||
I needed to record IP and MAC level ethernet addresses in a data
|
||||
base, and I really didn't want to store them as plain strings, with
|
||||
no enforced error checking, so I put together the accompanying code
|
||||
as my first experiment with adding a data type to PostgreSQL. I
|
||||
then thought that this might be useful to others, both directly and
|
||||
as a very simple example of how to do this sort of thing, so here
|
||||
it is, in the hope that it will be useful.
|
||||
|
||||
IP addresses are implemented as a 6 byte struct (this may be 1 byte
|
||||
more than is useful, but I figured that since it has to be at least 5,
|
||||
it might as well be an even number of bytes) that contains the four
|
||||
byte address and a mask width. The external representation of an IP
|
||||
address looks like '158.37.96.15/32' (or just '158.37.96.15', which is
|
||||
understood to mean the same thing). This address happens to be part
|
||||
of a subnet where I work; '158.37.96.0/24', which itself is a part of
|
||||
the larger subnet allocated to our site, which is '158.37.96.0/21',
|
||||
which again, if you go by the old book, is part of the class "B" net
|
||||
called '158.37.0.0/16'.
|
||||
|
||||
Input and output functions are supplied, along with the "normal" <,
|
||||
<=, =, >=, > and <> operators, which all do what you expect. In
|
||||
addition, there is a function to check whether a given address is a
|
||||
member of a given subnet: ipaddr_in_net(addr, net), and functions to
|
||||
return the netmask and the broadcast address of a given network:
|
||||
ipaddr_mask(net) and ipaddr_bcast(net).
|
||||
|
||||
MAC level ethernet addresses are implemented as a 6 byte struct that
|
||||
contains the address as unsigned chars. Several input forms are
|
||||
accepted; the following are all the same address: '08002b:010203',
|
||||
'08002b-010203', '0800.2b01.0203', '08-00-2b-01-02-03' and
|
||||
'08:00:2b:01:02:03'. Upper and lower case is accepted for the digits
|
||||
'a' through 'f'. Output is always in the latter of the given forms.
|
||||
|
||||
As with IP addresses, input and output functions are supplied as well
|
||||
as the "normal" operators, which do what you expect. As an extra
|
||||
feature, a function macaddr_manuf() is defined, which returns the name
|
||||
of the manufacturer as a string. This is currently held in a
|
||||
hard-coded struct internal to the C module -- it might be smarter to
|
||||
put this information into an actual data base table, and look up the
|
||||
manufacturer there. (Another TODO, for both new data types, is to
|
||||
interface them to indices. If anyone can explain this to me in a way
|
||||
that is easier to understand than the current documentation, I would
|
||||
be most grateful!)
|
||||
|
||||
I don't know what changes are needed to the Makefile for other systems
|
||||
than the one I'm running (NetBSD 1.3), but anyway: to install on a BSD
|
||||
system: fix the path names in the SQL files and the Makefile if you
|
||||
need to, then make, make install, slurp the SQL files into psql or
|
||||
whatever, and you're off. Enjoy!
|
||||
|
||||
Bergen, Norway, 1998-01-31, Tom Ivar Helbekkmo (tih@Hamartun.Priv.NO).
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* PostgreSQL type definitions for IP addresses.
|
||||
*
|
||||
* $Id: ip.c,v 1.3 1998/02/26 04:27:37 momjian Exp $
|
||||
* $Id: ip.c,v 1.4 1998/06/16 04:34:29 momjian Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -81,10 +81,18 @@ ipaddr_in(char *str)
|
||||
elog(ERROR, "ipaddr_in: error in parsing \"%s\"", str);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ( count == 3 ) {
|
||||
d = 0;
|
||||
count = 4;
|
||||
};
|
||||
if (count == 4)
|
||||
{
|
||||
w = 32;
|
||||
|
||||
if ( a >= 192 && a < 224 && d == 0 ) w = 24;
|
||||
if ( a >= 128 && a < 192 && d == 0 && c == 0 ) w = 16;
|
||||
if ( a > 0 && a < 128 && c == 0 && b == 0 && a < 128 ) w = 8;
|
||||
if ( a == 0 && b == 0 && c == 0 && d == 0 ) w = 0;
|
||||
};
|
||||
if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
|
||||
(c < 0) || (c > 255) || (d < 0) || (d > 255) ||
|
||||
(w < 0) || (w > 32))
|
||||
@ -95,13 +103,12 @@ ipaddr_in(char *str)
|
||||
}
|
||||
else
|
||||
{
|
||||
a = b = c = d = w = 0; /* special case for missing address */
|
||||
a = b = c = d = w = 255; /* special case for missing address */
|
||||
}
|
||||
|
||||
result = (ipaddr *) palloc(sizeof(ipaddr));
|
||||
|
||||
result->address = (uint32) ((a << 24) | (b << 16) | (c << 8) | d);
|
||||
result->address &= build_mask(w);
|
||||
result->width = w;
|
||||
|
||||
return (result);
|
||||
@ -116,27 +123,30 @@ char *
|
||||
ipaddr_out(ipaddr * addr)
|
||||
{
|
||||
char *result;
|
||||
|
||||
int a, b, c, d, w;
|
||||
if (addr == NULL)
|
||||
return (NULL);
|
||||
|
||||
result = (char *) palloc(32);
|
||||
|
||||
if (addr->address > 0)
|
||||
w = addr->width;
|
||||
a = (addr->address >> 24) & 0xff;
|
||||
b = (addr->address >> 16) & 0xff;
|
||||
c = (addr->address >> 8) & 0xff;
|
||||
d = (addr->address >> 0) & 0xff;
|
||||
/* Check by missing address (w > 32 ) */
|
||||
if ( w >= 0 && w <= 32 )
|
||||
{
|
||||
if (addr->width == 32)
|
||||
sprintf(result, "%d.%d.%d.%d",
|
||||
(addr->address >> 24) & 0xff,
|
||||
(addr->address >> 16) & 0xff,
|
||||
(addr->address >> 8) & 0xff,
|
||||
addr->address & 0xff);
|
||||
/* In case of NATURAL network don't output the prefix */
|
||||
if ( (a == 0 && b == 0 && c == 0 && d == 0 && w == 0 ) ||
|
||||
(a < 128 && b == 0 && c == 0 && d == 0 && w == 8 ) ||
|
||||
(a < 192 && c == 0 && d == 0 && w == 16 ) ||
|
||||
(a < 224 && d == 0 && w == 24 ) ||
|
||||
( d != 0 ) ) w = -1;
|
||||
if (w == -1 )
|
||||
sprintf(result, "%d.%d.%d.%d",a,b,c,d);
|
||||
else
|
||||
sprintf(result, "%d.%d.%d.%d/%d",
|
||||
(addr->address >> 24) & 0xff,
|
||||
(addr->address >> 16) & 0xff,
|
||||
(addr->address >> 8) & 0xff,
|
||||
addr->address & 0xff,
|
||||
addr->width);
|
||||
sprintf(result, "%d.%d.%d.%d/%d",a,b,c,d,w);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -145,6 +155,67 @@ ipaddr_out(ipaddr * addr)
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print ipaddr by format
|
||||
* %A - address
|
||||
* %M - maska
|
||||
* %P - prefix
|
||||
* %B - negated maska
|
||||
*/
|
||||
# define TXT_LEN_0 4
|
||||
text *
|
||||
ipaddr_print(ipaddr * addr, text *fmt)
|
||||
{
|
||||
text *result;
|
||||
char *p, *op;
|
||||
uint32 aaa;
|
||||
int a, b, c, d;
|
||||
if (addr == NULL)
|
||||
return (NULL);
|
||||
|
||||
result = (text *) palloc( sizeof(text) + 64 );
|
||||
|
||||
/* Check by missing address (w > 32 ) */
|
||||
for ( p = fmt->vl_dat, op = result->vl_dat; *p && (p - fmt->vl_dat) < (fmt->vl_len - TXT_LEN_0) && (op - result->vl_dat) < 48; p++) {
|
||||
if ( *p != '%' ) {
|
||||
*op++ = *p;
|
||||
continue;
|
||||
};
|
||||
p++;
|
||||
if ( *p == 'A' )
|
||||
{
|
||||
aaa = addr->address;
|
||||
goto pta;
|
||||
};
|
||||
if ( *p == 'M' ) {
|
||||
aaa = build_mask(addr->width);
|
||||
goto pta;
|
||||
}
|
||||
if ( *p == 'B' ) {
|
||||
aaa = build_mask(32 - addr->width) >> addr->width;
|
||||
goto pta;
|
||||
}
|
||||
if ( *p == 'P' ) {
|
||||
sprintf(op,"%d",addr->width);
|
||||
while ( *op) op++;
|
||||
continue;
|
||||
};
|
||||
*op++ = *p;
|
||||
continue;
|
||||
pta:
|
||||
a = (aaa >> 24) & 0xff;
|
||||
b = (aaa >> 16) & 0xff;
|
||||
c = (aaa >> 8) & 0xff;
|
||||
d = (aaa >> 0) & 0xff;
|
||||
sprintf(op, "%d.%d.%d.%d",a,b,c,d);
|
||||
while ( *op ) op++;
|
||||
continue;
|
||||
};
|
||||
*op = 0;
|
||||
result->vl_len = (op - result->vl_dat) + TXT_LEN_0;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Boolean tests for magnitude.
|
||||
*/
|
||||
@ -152,36 +223,42 @@ ipaddr_out(ipaddr * addr)
|
||||
bool
|
||||
ipaddr_lt(ipaddr * a1, ipaddr * a2)
|
||||
{
|
||||
if ( a1->address == a2->address ) return(a1->width < a2->width);
|
||||
return (a1->address < a2->address);
|
||||
};
|
||||
|
||||
bool
|
||||
ipaddr_le(ipaddr * a1, ipaddr * a2)
|
||||
{
|
||||
if ( a1->address == a2->address ) return(a1->width <= a2->width);
|
||||
return (a1->address <= a2->address);
|
||||
};
|
||||
|
||||
bool
|
||||
ipaddr_eq(ipaddr * a1, ipaddr * a2)
|
||||
{
|
||||
if ( a1->address == a2->address ) return(a1->width == a2->width);
|
||||
return (a1->address == a2->address);
|
||||
};
|
||||
|
||||
bool
|
||||
ipaddr_ge(ipaddr * a1, ipaddr * a2)
|
||||
{
|
||||
if ( a1->address == a2->address ) return(a1->width >= a2->width);
|
||||
return (a1->address >= a2->address);
|
||||
};
|
||||
|
||||
bool
|
||||
ipaddr_gt(ipaddr * a1, ipaddr * a2)
|
||||
{
|
||||
if ( a1->address == a2->address ) return(a1->width > a2->width);
|
||||
return (a1->address > a2->address);
|
||||
};
|
||||
|
||||
bool
|
||||
ipaddr_ne(ipaddr * a1, ipaddr * a2)
|
||||
{
|
||||
if ( a1->address == a2->address ) return(a1->width != a2->width);
|
||||
return (a1->address != a2->address);
|
||||
};
|
||||
|
||||
@ -197,7 +274,42 @@ ipaddr_cmp(ipaddr * a1, ipaddr * a2)
|
||||
else if (a1->address > a2->address)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
{
|
||||
if (a1->width < a2->width)
|
||||
return -1;
|
||||
else if (a1->width > a2->width)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The number of hosts in the network
|
||||
*/
|
||||
int4
|
||||
ipaddr_len(ipaddr * a)
|
||||
{
|
||||
if ( a->width > 32 || a->width < 0 ) return(0);
|
||||
return(1 << (32 - a->width));
|
||||
}
|
||||
|
||||
/*
|
||||
* The number of network bits
|
||||
*/
|
||||
int4
|
||||
ipaddr_pref(ipaddr * a)
|
||||
{
|
||||
if ( a->width > 32 || a->width < 0 ) return(0);
|
||||
return(a->width);
|
||||
}
|
||||
|
||||
/*
|
||||
* The host addr as an integer
|
||||
*/
|
||||
int4
|
||||
ipaddr_integer(ipaddr * a)
|
||||
{
|
||||
return(a->address);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -219,6 +331,23 @@ ipaddr_in_net(ipaddr * a1, ipaddr * a2)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether an address is the network or a host in the network:
|
||||
*/
|
||||
|
||||
bool
|
||||
ipaddr_is_net(ipaddr * a)
|
||||
{
|
||||
uint32 maskbits;
|
||||
|
||||
if (a->width == 32)
|
||||
return FALSE;
|
||||
maskbits = build_mask(a->width);
|
||||
if ( (a->address & maskbits) == a->address )
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick out just the mask of a network:
|
||||
*/
|
||||
@ -252,6 +381,68 @@ ipaddr_bcast(ipaddr * a)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the base network of the address/network:
|
||||
*/
|
||||
|
||||
ipaddr *
|
||||
ipaddr_net(ipaddr * a)
|
||||
{
|
||||
ipaddr *result;
|
||||
|
||||
result = (ipaddr *) palloc(sizeof(ipaddr));
|
||||
result->address = a->address;
|
||||
result->address &= build_mask(a->width);
|
||||
result->width = a->width;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compose ipaddr from ADDR and PREFIX
|
||||
*/
|
||||
ipaddr *
|
||||
ipaddr_compose(int4 addr, int4 pref)
|
||||
{
|
||||
ipaddr *result;
|
||||
|
||||
result = (ipaddr *) palloc(sizeof(ipaddr));
|
||||
if ( pref < 0 || pref > 32 ) {
|
||||
pref = 255;
|
||||
addr = 0;
|
||||
};
|
||||
result->address = addr;
|
||||
result->width = pref;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Plus and Minus operators
|
||||
*/
|
||||
ipaddr *
|
||||
ipaddr_plus(ipaddr * a, int4 i)
|
||||
{
|
||||
ipaddr *result;
|
||||
|
||||
result = (ipaddr *) palloc(sizeof(ipaddr));
|
||||
result->address = a->address + i;
|
||||
result->width = a->width;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ipaddr *
|
||||
ipaddr_minus(ipaddr * a, int4 i)
|
||||
{
|
||||
ipaddr *result;
|
||||
|
||||
result = (ipaddr *) palloc(sizeof(ipaddr));
|
||||
result->address = a->address - i;
|
||||
result->width = a->width;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* eof
|
||||
*/
|
||||
|
301
contrib/ip_and_mac/ip.sql
Normal file
301
contrib/ip_and_mac/ip.sql
Normal file
@ -0,0 +1,301 @@
|
||||
--
|
||||
-- PostgreSQL code for IP addresses.
|
||||
--
|
||||
-- $Id: ip.sql,v 1.4 1998/06/16 04:34:30 momjian Exp $
|
||||
-- Invoced from 1998/02/14 17:58:04 scrappy
|
||||
--
|
||||
-- New - INPUT/OUTPUT, functions, indexing by btree, test.
|
||||
-- PART # 1 - ip.sql - load new type, functions and operators.
|
||||
-- Then you should execute ipi.sql - add ipaddr_ops class to allow indexing.
|
||||
|
||||
load '/usr/local/pgsql/modules/ip.so';
|
||||
|
||||
--
|
||||
-- Input and output functions and the type itself:
|
||||
-- Note - we input 193.124.23.1 as /32, and 193.124.23.0 as /24.
|
||||
-- We output /24 network withouth /24 suffix, and /32 hosts wothouth suffixes
|
||||
-- if it is not '0' address of /24 network.
|
||||
-- Just the same, we threat 0.0.0.0 as 0.0.0.0/0 == DEFAULT.
|
||||
--
|
||||
|
||||
create function ipaddr_in(opaque)
|
||||
returns opaque
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
|
||||
|
||||
create function ipaddr_out(opaque)
|
||||
returns opaque
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
create type ipaddr (
|
||||
internallength = 6,
|
||||
externallength = variable,
|
||||
input = ipaddr_in,
|
||||
output = ipaddr_out
|
||||
);
|
||||
|
||||
--
|
||||
-- Print address by format
|
||||
-- %A - address
|
||||
-- %P - /Pref
|
||||
-- %M - maska
|
||||
-- %B - reversed maska
|
||||
drop function ipaddr_print;
|
||||
create function ipaddr_print(ipaddr, text)
|
||||
returns text
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
);
|
||||
|
||||
--
|
||||
-- The various boolean tests:
|
||||
-- In case if addresseas are equal, we compare prefix length
|
||||
-- It means 193.124.23.0/24 < 193.124.23.0/32
|
||||
--
|
||||
|
||||
create function ipaddr_lt(ipaddr, ipaddr)
|
||||
returns bool
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
create function ipaddr_le(ipaddr, ipaddr)
|
||||
returns bool
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
create function ipaddr_eq(ipaddr, ipaddr)
|
||||
returns bool
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
create function ipaddr_ge(ipaddr, ipaddr)
|
||||
returns bool
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
create function ipaddr_gt(ipaddr, ipaddr)
|
||||
returns bool
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
create function ipaddr_ne(ipaddr, ipaddr)
|
||||
returns bool
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Test if a1 is in net a2
|
||||
-- Return TRUE if a1 is IN a2 subnet or if a1 == a2
|
||||
--
|
||||
create function ipaddr_in_net(ipaddr, ipaddr)
|
||||
returns bool
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Return the network from the host/network address. This means
|
||||
-- 193.124.23.4/24 -> 193.124.23.0/24.
|
||||
-- This allow to use interface address (with the real netmask) to create
|
||||
-- network, and to link interfaces and addresses belongs to the same network.
|
||||
--
|
||||
|
||||
create function ipaddr_net(ipaddr)
|
||||
returns ipaddr
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Return TRUE if addr describe NETWORK, not host in the network
|
||||
-- It's equivalent to ipaddr_net(a) == a
|
||||
--
|
||||
|
||||
create function ipaddr_is_net(ipaddr)
|
||||
returns boolean
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Return the number of the hosts in the network
|
||||
--
|
||||
|
||||
create function ipaddr_len(ipaddr)
|
||||
returns int4
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Return the prefix length of the network
|
||||
--
|
||||
|
||||
create function ipaddr_pref(ipaddr)
|
||||
returns int4
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Convert network into the integer.
|
||||
-- Can be used for 'compose' function
|
||||
--
|
||||
|
||||
create function ipaddr_integer(ipaddr)
|
||||
returns int4
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Compose ipaddr from the ADDRESS and PREF
|
||||
-- ipaddr_compose(ipaddr_integer(a),ipaddr_pref(a)) == a
|
||||
--
|
||||
|
||||
create function ipaddr_compose(int4,int4)
|
||||
returns ipaddr
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Return MASK for the network
|
||||
--
|
||||
|
||||
create function ipaddr_mask(ipaddr)
|
||||
returns ipaddr
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Return BROADCAST address for the network
|
||||
--
|
||||
|
||||
create function ipaddr_bcast(ipaddr)
|
||||
returns ipaddr
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Compare 2 addresses. First, compare addresses, then, compare prefixes (if the addresses
|
||||
-- are the same).
|
||||
--
|
||||
|
||||
create function ipaddr_cmp(ipaddr,ipaddr)
|
||||
returns int4
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Plus and Minus operators
|
||||
--
|
||||
|
||||
create function ipaddr_plus(ipaddr,int4)
|
||||
returns ipaddr
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
create function ipaddr_minus(ipaddr,int4)
|
||||
returns ipaddr
|
||||
as '/usr/local/pgsql/modules/ip.so'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Now the operators. Note how some of the parameters to some
|
||||
-- of the 'create operator' commands are commented out. This
|
||||
-- is because they reference as yet undefined operators, and
|
||||
-- will be implicitly defined when those are, further down.
|
||||
--
|
||||
|
||||
-- drop operator < ( ipaddr, ipaddr);
|
||||
create operator < (
|
||||
leftarg = ipaddr,
|
||||
rightarg = ipaddr,
|
||||
-- negator = >=,
|
||||
procedure = ipaddr_lt,
|
||||
restrict = intltsel,
|
||||
join = intltjoinsel
|
||||
);
|
||||
|
||||
-- drop operator <= (ipaddr,ipaddr);
|
||||
create operator <= (
|
||||
leftarg = ipaddr,
|
||||
rightarg = ipaddr,
|
||||
-- negator = >,
|
||||
procedure = ipaddr_le,
|
||||
restrict = intltsel,
|
||||
join = intltjoinsel
|
||||
);
|
||||
|
||||
-- drop operator = (ipaddr,ipaddr);
|
||||
create operator = (
|
||||
leftarg = ipaddr,
|
||||
rightarg = ipaddr,
|
||||
commutator = =,
|
||||
-- negator = <>,
|
||||
restrict = eqsel,
|
||||
join = eqjoinsel,
|
||||
procedure = ipaddr_eq
|
||||
);
|
||||
|
||||
|
||||
-- drop operator >= (ipaddr,ipaddr);
|
||||
create operator >= (
|
||||
leftarg = ipaddr,
|
||||
rightarg = ipaddr,
|
||||
negator = <,
|
||||
procedure = ipaddr_ge,
|
||||
restrict = intgtsel,
|
||||
join = intgtjoinsel
|
||||
);
|
||||
|
||||
-- drop operator > (ipaddr,ipaddr);
|
||||
create operator > (
|
||||
leftarg = ipaddr,
|
||||
rightarg = ipaddr,
|
||||
negator = <=,
|
||||
procedure = ipaddr_gt,
|
||||
restrict = intgtsel,
|
||||
join = intgtjoinsel
|
||||
);
|
||||
|
||||
-- drop operator <> (ipaddr,ipaddr);
|
||||
create operator <> (
|
||||
leftarg = ipaddr,
|
||||
rightarg = ipaddr,
|
||||
negator = =,
|
||||
procedure = ipaddr_ne,
|
||||
restrict = neqsel,
|
||||
join = neqjoinsel
|
||||
);
|
||||
|
||||
create operator @ (
|
||||
leftarg = ipaddr,
|
||||
rightarg = ipaddr,
|
||||
procedure = ipaddr_in_net
|
||||
);
|
||||
|
||||
create operator + (
|
||||
leftarg = ipaddr,
|
||||
rightarg = int4,
|
||||
procedure = ipaddr_plus
|
||||
);
|
||||
|
||||
create operator - (
|
||||
leftarg = ipaddr,
|
||||
rightarg = int4,
|
||||
procedure = ipaddr_minus
|
||||
);
|
||||
|
||||
-- *****************************************************************************************
|
||||
-- * For now, you have: input/output (remember, '193.124.23.0' means /24 network, *
|
||||
-- * '193.124.23.1' means /32 host) *
|
||||
-- * <, <=, = <>, >=, > relational operations; host @ net (host is the part of the net) op *
|
||||
-- * varchar ipaddr_print(addr, '%A/%P %M %B') - print by pattern function *
|
||||
-- * ipaddr ipaddr_mask(a),ipaddr_bcast(a),ipaddr_net(a) functions (mask,bcast, start addr)*
|
||||
-- * int4 ipaddr_len(a) - lenght of subnet; ipaddr_pref(a) - prefix length, *
|
||||
-- * int4 ipaddr_integer(a) - integer value; ipaddr ipaddr_compose(integer_addr,pref_len) *
|
||||
-- * compose ipaddr from addr and mask *
|
||||
-- * '+' and '-' operators (ipaddr = ipaddr + integer),(ipaddr = ipaddr - integer) ops *
|
||||
-- *****************************************************************************************
|
||||
-- * R E A D T H I S T E X T B E F O R E E X I T I N G : *
|
||||
-- * Now you should execute ipi.sql to allow BTREE indexing on this class. *
|
||||
-- *****************************************************************************************
|
||||
-- eof
|
Loading…
Reference in New Issue
Block a user