From a377ad58ea5ae12c644b94c2991b732a1f97af20 Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" Date: Sat, 14 Feb 1998 17:58:09 +0000 Subject: [PATCH] I'm including an update to my user defined IP and MAC address type implementation that's in contrib/ip_and_mac/. This one works right with 6.3, avoids the problems I ran into earlier with LIKE, and includes a bit of extra functionality. From: Tom I Helbekkmo --- contrib/ip_and_mac/Makefile | 7 +- contrib/ip_and_mac/README | 71 +++++++++-------- contrib/ip_and_mac/ip.c | 150 ++++++++++++++++++------------------ contrib/ip_and_mac/ip.sql | 40 +++++----- contrib/ip_and_mac/mac.c | 71 +++++++++-------- contrib/ip_and_mac/mac.h | 2 + contrib/ip_and_mac/mac.sql | 67 ++++++++++++---- contrib/ip_and_mac/test.sql | 71 +++++++++++++++++ 8 files changed, 303 insertions(+), 176 deletions(-) create mode 100644 contrib/ip_and_mac/test.sql diff --git a/contrib/ip_and_mac/Makefile b/contrib/ip_and_mac/Makefile index 924a20029e..773fdc24f9 100644 --- a/contrib/ip_and_mac/Makefile +++ b/contrib/ip_and_mac/Makefile @@ -1,4 +1,7 @@ -# PostgreSQL type definitions for IP and MAC addresses. +# +# PostgreSQL types for IP and MAC addresses +# +# $Id: Makefile,v 1.2 1998/02/14 17:58:02 scrappy Exp $ all: ip.so mac.so @@ -17,4 +20,6 @@ mac.o: mac.c mac.h install: ip.so mac.so install -c ip.so mac.so /usr/local/pgsql/modules +# # eof +# diff --git a/contrib/ip_and_mac/README b/contrib/ip_and_mac/README index a2da4fc46d..efa400fc7d 100644 --- a/contrib/ip_and_mac/README +++ b/contrib/ip_and_mac/README @@ -1,6 +1,8 @@ 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 @@ -9,43 +11,46 @@ 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 an 8 byte struct (this may well be +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 round well) that contains the four bytes of address -and a mask width. Thus, a node 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 institution, which is '158.37.96.0/21', which again, -if you go by the book, is part of the class "B" net '158.37.0.0/16'. +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, and the -similarity operator ~~, which checks whether two given addresses are -either the same, or, failing that, whether one is a subnet -specification and the other an address (or a smaller subnet) within -that. Good for picking out records with addresses in a given subnet: -note that '158.37.96.0/21' spans '158.37.96.0' to '158.37.103.255', -which is not all that easily handled in its external representation. - -MAC level ethernet addresses are also implemented as an 8 byte struct -(I wish I knew what alignment needs are actually present -- I'm just -not taking any chances here) 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. - -Input and output functions are supplied, along with the = and <> -operators, which do what you expect, and the similarity operator ~~, -which checks whether two given addresses belong to hardware from the -same manufacturer (first three bytes the same, that is). As an extra +<=, =, >=, > 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. +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!) -To install: 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 +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-11, Tom Ivar Helbekkmo (tih@Hamartun.Priv.NO). +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 de967aa8ed..d941c26742 100644 --- a/contrib/ip_and_mac/ip.c +++ b/contrib/ip_and_mac/ip.c @@ -1,5 +1,7 @@ /* * PostgreSQL type definitions for IP addresses. + * + * $Id: ip.c,v 1.2 1998/02/14 17:58:03 scrappy Exp $ */ #include @@ -12,13 +14,8 @@ */ typedef struct ipaddr { - unsigned char a; - unsigned char b; - unsigned char c; - unsigned char d; - unsigned char w; - unsigned char pad1; - short pad2; + uint32 address; + int16 width; } ipaddr; /* @@ -35,15 +32,24 @@ bool ipaddr_ge(ipaddr *a1, ipaddr *a2); bool ipaddr_gt(ipaddr *a1, ipaddr *a2); bool ipaddr_ne(ipaddr *a1, ipaddr *a2); + int4 ipaddr_cmp(ipaddr *a1, ipaddr *a2); -bool ipaddr_like(ipaddr *a1, ipaddr *a2); + +bool ipaddr_in_net(ipaddr *a1, ipaddr *a2); +ipaddr *ipaddr_mask(ipaddr *a); +ipaddr *ipaddr_bcast(ipaddr *a); /* - * A utility macro used for sorting addresses numerically: + * Build a mask of a given width: */ -#define Mag(addr) \ - ((unsigned long)((addr->a<<24)|(addr->b<<16)|(addr->c<<8)|(addr->d))) +unsigned long build_mask(unsigned char bits) { + unsigned long mask = 0; + int i; + for (i = 0; i < bits; i++) + mask = (mask >> 1) | 0x80000000; + return mask; +} /* * IP address reader. Note how the count returned by sscanf() @@ -79,11 +85,9 @@ ipaddr *ipaddr_in(char *str) { result = (ipaddr *)palloc(sizeof(ipaddr)); - result->a = a; - result->b = b; - result->c = c; - result->d = d; - result->w = w; + result->address = (uint32) ((a<<24)|(b<<16)|(c<<8)|d); + result->address &= build_mask(w); + result->width = w; return(result); } @@ -101,13 +105,20 @@ char *ipaddr_out(ipaddr *addr) { result = (char *)palloc(32); - if (Mag(addr) > 0) { - if (addr->w == 32) + if (addr->address > 0) { + if (addr->width == 32) sprintf(result, "%d.%d.%d.%d", - addr->a, addr->b, addr->c, addr->d); + (addr->address >> 24) & 0xff, + (addr->address >> 16) & 0xff, + (addr->address >> 8) & 0xff, + addr->address & 0xff); else sprintf(result, "%d.%d.%d.%d/%d", - addr->a, addr->b, addr->c, addr->d, addr->w); + (addr->address >> 24) & 0xff, + (addr->address >> 16) & 0xff, + (addr->address >> 8) & 0xff, + addr->address & 0xff, + addr->width); } else { result[0] = 0; /* special case for missing address */ } @@ -115,49 +126,31 @@ char *ipaddr_out(ipaddr *addr) { } /* - * Boolean tests. The Mag() macro was defined above. + * Boolean tests for magnitude. */ bool ipaddr_lt(ipaddr *a1, ipaddr *a2) { - unsigned long a1mag, a2mag; - a1mag = Mag(a1); - a2mag = Mag(a2); - return (a1mag < a2mag); + return (a1->address < a2->address); }; bool ipaddr_le(ipaddr *a1, ipaddr *a2) { - unsigned long a1mag, a2mag; - a1mag = Mag(a1); - a2mag = Mag(a2); - return (a1mag <= a2mag); + return (a1->address <= a2->address); }; bool ipaddr_eq(ipaddr *a1, ipaddr *a2) { - unsigned long a1mag, a2mag; - a1mag = Mag(a1); - a2mag = Mag(a2); - return ((a1mag == a2mag) && (a1->w == a2->w)); + return (a1->address == a2->address); }; bool ipaddr_ge(ipaddr *a1, ipaddr *a2) { - unsigned long a1mag, a2mag; - a1mag = Mag(a1); - a2mag = Mag(a2); - return (a1mag >= a2mag); + return (a1->address >= a2->address); }; bool ipaddr_gt(ipaddr *a1, ipaddr *a2) { - unsigned long a1mag, a2mag; - a1mag = Mag(a1); - a2mag = Mag(a2); - return (a1mag > a2mag); + return (a1->address > a2->address); }; bool ipaddr_ne(ipaddr *a1, ipaddr *a2) { - unsigned long a1mag, a2mag; - a1mag = Mag(a1); - a2mag = Mag(a2); - return ((a1mag != a2mag) || (a1->w != a2->w)); + return (a1->address != a2->address); }; /* @@ -165,48 +158,59 @@ bool ipaddr_ne(ipaddr *a1, ipaddr *a2) { */ int4 ipaddr_cmp(ipaddr *a1, ipaddr *a2) { - unsigned long a1mag = Mag(a1), a2mag = Mag(a2); - if (a1mag < a2mag) + if (a1->address < a2->address) return -1; - else if (a1mag > a2mag) + else if (a1->address > a2->address) return 1; else return 0; } /* - * Our "similarity" operator checks whether two addresses are - * either the same node address, or, failing that, whether one - * of them contains the other. This will be true if they have - * the same high bits down as far as the shortest mask reaches. + * Test whether an address is within a given subnet: */ -unsigned long build_mask(unsigned char bits) { - unsigned long mask = 0; - int i; - for (i = 0; i < bits; i++) - mask = (mask >> 1) | 0x80000000; - return mask; -} - -bool ipaddr_like(ipaddr *a1, ipaddr *a2) { - unsigned long a1bits, a2bits, maskbits; - if ((a1->w == 0) || (a2->w == 0)) +bool ipaddr_in_net(ipaddr *a1, ipaddr *a2) { + uint32 maskbits; + if (a1->width < a2->width) return FALSE; - if ((a1->w == 32) && (a2->w == 32)) + if ((a1->width == 32) && (a2->width == 32)) return ipaddr_eq(a1, a2); - a1bits = Mag(a1); - a2bits = Mag(a2); - if (a1->w > a2->w) { - maskbits = build_mask(a2->w); - return ((a1bits & maskbits) == (a2bits & maskbits)); - } else { - maskbits = build_mask(a1->w); - return ((a2bits & maskbits) == (a1bits & maskbits)); - } + maskbits = build_mask(a2->width); + if ((a1->address & maskbits) == (a2->address & maskbits)) + return TRUE; return FALSE; } +/* + * Pick out just the mask of a network: + */ + +ipaddr *ipaddr_mask(ipaddr *a) { + ipaddr *result; + + result = (ipaddr *)palloc(sizeof(ipaddr)); + result->address = build_mask(a->width); + result->width = 32; + + return result; +} + +/* + * Return the broadcast address of a network: + */ + +ipaddr *ipaddr_bcast(ipaddr *a) { + ipaddr *result; + + result = (ipaddr *)palloc(sizeof(ipaddr)); + result->address = a->address; + result->address |= (build_mask(32 - a->width) >> a->width); + result->width = 32; + + return result; +} + /* * eof */ diff --git a/contrib/ip_and_mac/ip.sql b/contrib/ip_and_mac/ip.sql index bcfe1a24d9..d5a695b691 100644 --- a/contrib/ip_and_mac/ip.sql +++ b/contrib/ip_and_mac/ip.sql @@ -1,6 +1,8 @@ -- -- PostgreSQL code for IP addresses. -- +-- $Id: ip.sql,v 1.2 1998/02/14 17:58:04 scrappy Exp $ +-- load '/usr/local/pgsql/modules/ip.so'; @@ -19,7 +21,7 @@ create function ipaddr_out(opaque) language 'c'; create type ipaddr ( - internallength = 8, + internallength = 6, externallength = variable, input = ipaddr_in, output = ipaddr_out @@ -59,11 +61,21 @@ create function ipaddr_ne(ipaddr, ipaddr) as '/usr/local/pgsql/modules/ip.so' language 'c'; -create function ipaddr_like(ipaddr, ipaddr) +create function ipaddr_in_net(ipaddr, ipaddr) returns bool as '/usr/local/pgsql/modules/ip.so' language 'c'; +create function ipaddr_mask(ipaddr) + returns ipaddr + as '/usr/local/pgsql/modules/ip.so' + language 'c'; + +create function ipaddr_bcast(ipaddr) + 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 @@ -71,20 +83,18 @@ create function ipaddr_like(ipaddr, ipaddr) -- will be implicitly defined when those are, further down. -- -create operator <= ( +create operator < ( leftarg = ipaddr, rightarg = ipaddr, --- commutator = >, --- negator = >, - procedure = ipaddr_le +-- negator = >=, + procedure = ipaddr_lt ); -create operator < ( +create operator <= ( leftarg = ipaddr, rightarg = ipaddr, --- commutator = >=, --- negator = >=, - procedure = ipaddr_lt +-- negator = >, + procedure = ipaddr_le ); create operator = ( @@ -98,7 +108,6 @@ create operator = ( create operator >= ( leftarg = ipaddr, rightarg = ipaddr, - commutator = <, negator = <, procedure = ipaddr_ge ); @@ -106,7 +115,6 @@ create operator >= ( create operator > ( leftarg = ipaddr, rightarg = ipaddr, - commutator = <=, negator = <=, procedure = ipaddr_gt ); @@ -114,18 +122,10 @@ create operator > ( create operator <> ( leftarg = ipaddr, rightarg = ipaddr, - commutator = <>, negator = =, procedure = ipaddr_ne ); -create operator ~~ ( - leftarg = ipaddr, - rightarg = ipaddr, - commutator = ~~, - procedure = ipaddr_like -); - -- -- eof -- diff --git a/contrib/ip_and_mac/mac.c b/contrib/ip_and_mac/mac.c index 3317eab24e..34aed59267 100644 --- a/contrib/ip_and_mac/mac.c +++ b/contrib/ip_and_mac/mac.c @@ -1,5 +1,7 @@ /* * PostgreSQL type definitions for MAC addresses. + * + * $Id: mac.c,v 1.2 1998/02/14 17:58:05 scrappy Exp $ */ #include @@ -20,7 +22,6 @@ typedef struct macaddr { unsigned char d; unsigned char e; unsigned char f; - short pad; } macaddr; /* @@ -30,21 +31,26 @@ typedef struct macaddr { macaddr *macaddr_in(char *str); char *macaddr_out(macaddr *addr); +bool macaddr_lt(macaddr *a1, macaddr *a2); +bool macaddr_le(macaddr *a1, macaddr *a2); bool macaddr_eq(macaddr *a1, macaddr *a2); +bool macaddr_ge(macaddr *a1, macaddr *a2); +bool macaddr_gt(macaddr *a1, macaddr *a2); + bool macaddr_ne(macaddr *a1, macaddr *a2); int4 macaddr_cmp(macaddr *a1, macaddr *a2); -bool macaddr_like(macaddr *a1, macaddr *a2); + text *macaddr_manuf(macaddr *addr); /* * Utility macros used for sorting and comparing: */ -#define MagM(addr) \ +#define hibits(addr) \ ((unsigned long)((addr->a<<16)|(addr->b<<8)|(addr->c))) -#define MagH(addr) \ +#define lobits(addr) \ ((unsigned long)((addr->c<<16)|(addr->e<<8)|(addr->f))) /* @@ -107,7 +113,7 @@ char *macaddr_out(macaddr *addr) { result = (char *)palloc(32); - if ((MagM(addr) > 0) || (MagH(addr) > 0)) { + if ((hibits(addr) > 0) || (lobits(addr) > 0)) { sprintf(result, "%02x:%02x:%02x:%02x:%02x:%02x", addr->a, addr->b, addr->c, addr->d, addr->e, addr->f); } else { @@ -120,16 +126,32 @@ char *macaddr_out(macaddr *addr) { * Boolean tests. */ +bool macaddr_lt(macaddr *a1, macaddr *a2) { + return((hibits(a1) < hibits(a2)) || + ((hibits(a1) == hibits(a2)) && lobits(a1) < lobits(a2))); +}; + +bool macaddr_le(macaddr *a1, macaddr *a2) { + return((hibits(a1) < hibits(a2)) || + ((hibits(a1) == hibits(a2)) && lobits(a1) <= lobits(a2))); +}; + bool macaddr_eq(macaddr *a1, macaddr *a2) { - return((a1->a == a2->a) && (a1->b == a2->b) && - (a1->c == a2->c) && (a1->d == a2->d) && - (a1->e == a2->e) && (a1->f == a2->f)); + return ((hibits(a1) == hibits(a2)) && (lobits(a1) == lobits(a2))); +}; + +bool macaddr_ge(macaddr *a1, macaddr *a2) { + return((hibits(a1) > hibits(a2)) || + ((hibits(a1) == hibits(a2)) && lobits(a1) >= lobits(a2))); +}; + +bool macaddr_gt(macaddr *a1, macaddr *a2) { + return((hibits(a1) > hibits(a2)) || + ((hibits(a1) == hibits(a2)) && lobits(a1) > lobits(a2))); }; bool macaddr_ne(macaddr *a1, macaddr *a2) { - return((a1->a != a2->a) || (a1->b != a2->b) || - (a1->c != a2->c) || (a1->d != a2->d) || - (a1->e != a2->e) || (a1->f != a2->f)); + return ((hibits(a1) != hibits(a2)) || (lobits(a1) != lobits(a2))); }; /* @@ -137,37 +159,18 @@ bool macaddr_ne(macaddr *a1, macaddr *a2) { */ int4 macaddr_cmp(macaddr *a1, macaddr *a2) { - unsigned long a1magm, a1magh, a2magm, a2magh; - a1magm = MagM(a1); - a1magh = MagH(a1); - a2magm = MagM(a2); - a2magh = MagH(a2); - if (a1magm < a2magm) + if (hibits(a1) < hibits(a2)) return -1; - else if (a1magm > a2magm) + else if (hibits(a1) > hibits(a2)) return 1; - else if (a1magh < a2magh) + else if (lobits(a1) < lobits(a2)) return -1; - else if (a1magh > a2magh) + else if (lobits(a1) > lobits(a2)) return 1; else return 0; } -/* - * Similarity means having the same manufacurer, which means - * having the same first three bytes of address: - */ - -bool macaddr_like(macaddr *a1, macaddr *a2) { - unsigned long a1magm, a2magm; - a1magm = MagM(a1); - a2magm = MagM(a2); - if ((a1magm == 0) || (a2magm == 0)) - return FALSE; - return (a1magm == a2magm); -} - /* * The special manufacturer fetching function. See "mac.h". */ diff --git a/contrib/ip_and_mac/mac.h b/contrib/ip_and_mac/mac.h index 39f12d83bb..27c4c1ec27 100644 --- a/contrib/ip_and_mac/mac.h +++ b/contrib/ip_and_mac/mac.h @@ -1,5 +1,7 @@ /* * PostgreSQL type definitions for MAC addresses. + * + * $Id: mac.h,v 1.2 1998/02/14 17:58:07 scrappy Exp $ */ typedef struct manufacturer { diff --git a/contrib/ip_and_mac/mac.sql b/contrib/ip_and_mac/mac.sql index 9e5ec61277..47c6b811c9 100644 --- a/contrib/ip_and_mac/mac.sql +++ b/contrib/ip_and_mac/mac.sql @@ -1,6 +1,8 @@ -- -- PostgreSQL code for MAC addresses. -- +-- $Id: mac.sql,v 1.2 1998/02/14 17:58:08 scrappy Exp $ +-- load '/usr/local/pgsql/modules/mac.so'; @@ -19,38 +21,67 @@ create function macaddr_out(opaque) language 'c'; create type macaddr ( - internallength = 8, + internallength = 6, externallength = variable, input = macaddr_in, output = macaddr_out ); -- --- The various boolean tests: +-- The boolean tests: -- +create function macaddr_lt(macaddr, macaddr) + returns bool + as '/usr/local/pgsql/modules/mac.so' + language 'c'; + +create function macaddr_le(macaddr, macaddr) + returns bool + as '/usr/local/pgsql/modules/mac.so' + language 'c'; + create function macaddr_eq(macaddr, macaddr) returns bool as '/usr/local/pgsql/modules/mac.so' language 'c'; -create function macaddr_ne(macaddr, macaddr) +create function macaddr_ge(macaddr, macaddr) + returns bool + as '/usr/local/pgsql/modules/mac.so' + language 'c'; + +create function macaddr_gt(macaddr, macaddr) returns bool as '/usr/local/pgsql/modules/mac.so' language 'c'; -create function macaddr_like(macaddr, macaddr) +create function macaddr_ne(macaddr, macaddr) returns bool as '/usr/local/pgsql/modules/mac.so' language 'c'; -- --- Now the operators. Note how the "negator = <>" in the --- definition of the equivalence operator is commented out. --- It gets defined implicitly when "<>" is defined, with --- "=" as its negator. +-- 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. -- +create operator < ( + leftarg = macaddr, + rightarg = macaddr, +-- negator = >=, + procedure = macaddr_lt +); + +create operator <= ( + leftarg = macaddr, + rightarg = macaddr, +-- negator = >, + procedure = macaddr_le +); + create operator = ( leftarg = macaddr, rightarg = macaddr, @@ -59,19 +90,25 @@ create operator = ( procedure = macaddr_eq ); -create operator <> ( +create operator >= ( leftarg = macaddr, rightarg = macaddr, - commutator = <>, - negator = =, - procedure = macaddr_ne + negator = <, + procedure = macaddr_ge +); + +create operator > ( + leftarg = macaddr, + rightarg = macaddr, + negator = <=, + procedure = macaddr_gt ); -create operator ~~ ( +create operator <> ( leftarg = macaddr, rightarg = macaddr, - commutator = ~~, - procedure = macaddr_like + negator = =, + procedure = macaddr_ne ); -- diff --git a/contrib/ip_and_mac/test.sql b/contrib/ip_and_mac/test.sql new file mode 100644 index 0000000000..296e1ebe94 --- /dev/null +++ b/contrib/ip_and_mac/test.sql @@ -0,0 +1,71 @@ +-- +-- A quick test of the IP address code +-- +-- $Id: test.sql,v 1.1 1998/02/14 17:58:09 scrappy Exp $ +-- + +-- temporary table: +create table addresses (address ipaddr); + +-- sample data from two subnets: +insert into addresses values ('158.37.96.15'); +insert into addresses values ('158.37.96.16'); +insert into addresses values ('158.37.96.17'); +insert into addresses values ('158.37.97.15'); +insert into addresses values ('158.37.97.16'); +insert into addresses values ('158.37.97.17'); +insert into addresses values ('158.37.98.15'); +insert into addresses values ('158.37.98.16'); +insert into addresses values ('158.37.98.17'); +insert into addresses values ('158.37.96.150'); +insert into addresses values ('158.37.96.160'); +insert into addresses values ('158.37.96.170'); +insert into addresses values ('158.37.97.150'); +insert into addresses values ('158.37.97.160'); +insert into addresses values ('158.37.97.170'); +insert into addresses values ('158.37.98.150'); +insert into addresses values ('158.37.98.160'); +insert into addresses values ('158.37.98.170'); + +-- show them all: +select * from addresses; + +-- select the ones in subnet 96: +select * from addresses where ipaddr_in_net(address, '158.37.96.0/24'); + +-- select the ones not in subnet 96: +select * from addresses where not ipaddr_in_net(address, '158.37.96.0/24'); + +-- select the ones in subnet 97: +select * from addresses where ipaddr_in_net(address, '158.37.97.0/24'); + +-- select the ones not in subnet 97: +select * from addresses where not ipaddr_in_net(address, '158.37.97.0/24'); + +-- select the ones in subnet 96 or 97, sorted: +select * from addresses where ipaddr_in_net(address, '158.37.96.0/23') + order by address; + +-- now some networks: +create table networks (network ipaddr); + +-- now the subnets mentioned above: +insert into networks values ('158.37.96.0/24'); +insert into networks values ('158.37.97.0/24'); +insert into networks values ('158.37.98.0/24'); + +-- select the netmasks of the net containing each: +select address, ipaddr_mask(network) from addresses, networks + where ipaddr_in_net(address, network); + +-- select the broadcast address of the net containing each: +select address, ipaddr_bcast(network) from addresses, networks + where ipaddr_in_net(address, network); + +-- tidy up: +drop table addresses; +drop table networks; + +-- +-- eof +-- -- GitLab