#
# 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
+#
-PostgreSQL type extensions for IP and MAC addresses.
----------------------------------------------------
-
-$Id: README,v 1.2 1998/02/14 17:58:03 scrappy 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).
+
+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.
+
+To see the description of macaddr type, read README.ORIG file.
+To see the description of ipaddr type, read ipaddr.html file.
+ ^^^^^^^^^^^
+
+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.
+
+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);
+
+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.
+
+And then, I add ipi.sql setup script and test1.sql + test2.sql test
+scripts to allow and test indexing by this new class.
+
+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.
+
+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.
+==========================================================================================
--- /dev/null
+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).
/*
* 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>
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))
}
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);
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
{
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.
*/
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);
};
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);
}
/*
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:
*/
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
*/
--- /dev/null
+--
+-- 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