diff --git a/contrib/ip_and_mac/Makefile b/contrib/ip_and_mac/Makefile index 3ec9c3f59aa..1af72338749 100644 --- a/contrib/ip_and_mac/Makefile +++ b/contrib/ip_and_mac/Makefile @@ -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 +# diff --git a/contrib/ip_and_mac/README b/contrib/ip_and_mac/README index efa400fc7db..15b763a4d3c 100644 --- a/contrib/ip_and_mac/README +++ b/contrib/ip_and_mac/README @@ -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. +========================================================================================== diff --git a/contrib/ip_and_mac/README.ORIG b/contrib/ip_and_mac/README.ORIG new file mode 100644 index 00000000000..b43da8eab15 --- /dev/null +++ b/contrib/ip_and_mac/README.ORIG @@ -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). diff --git a/contrib/ip_and_mac/ip.c b/contrib/ip_and_mac/ip.c index b0320bae38d..e9aaba3b8e3 100644 --- a/contrib/ip_and_mac/ip.c +++ b/contrib/ip_and_mac/ip.c @@ -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 @@ -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 */ diff --git a/contrib/ip_and_mac/ip.sql b/contrib/ip_and_mac/ip.sql new file mode 100644 index 00000000000..082e42fff5a --- /dev/null +++ b/contrib/ip_and_mac/ip.sql @@ -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