提交 2d69fd90 编写于 作者: B Bruce Momjian

Integrate new IP type from Tom Ivar Helbekkmo.

上级 607cd930
......@@ -31,10 +31,6 @@ int8 -
64-bit integer arithmetic for Postgres
by Thomas G. Lockhart <Thomas.Lockhart@jpl.nasa.gov>
ip_and_mac -
PostgreSQL type extensions for IP and MAC addresses
by Tom Ivar Helbekkmo <tih@Hamartun.Priv.NO>
isbn_issn -
PostgreSQL type extensions for ISBN (books) and ISSN (serials)
by Garrett A. Wollman <wollman@khavrinen.lcs.mit.edu>
......
#
# PostgreSQL types for IP and MAC addresses
#
# $Id: Makefile,v 1.5 1998/06/16 05:35:10 momjian Exp $
all: ip.so mac.so
ip.so: ip.o
ld -Bshareable -o ip.so ip.o
ip.o: ip.c
cc -g -O -fPIC -I/usr/local/pgsql/include -c ip.c
mac.so: mac.o
ld -Bshareable -o mac.so mac.o
mac.o: mac.c mac.h
cc -g -O -fPIC -I/usr/local/pgsql/include -c mac.c
install: ip.so mac.so
install -c ip.so mac.so /usr/local/pgsql/contrib/ip_and_macs
clean:
rm -f *.o *.so *.b
#
# eof
#
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.
==========================================================================================
/*
* PostgreSQL type definitions for IP addresses.
*
* $Id: ip.c,v 1.5 1998/06/16 05:35:10 momjian Exp $
*/
#include <stdio.h>
#include <postgres.h>
#include <utils/palloc.h>
/*
* This is the internal storage format for IP addresses:
*/
typedef struct ipaddr
{
uint32 address;
int16 width;
} ipaddr;
/*
* Various forward declarations:
*/
ipaddr *ipaddr_in(char *str);
char *ipaddr_out(ipaddr * addr);
bool ipaddr_lt(ipaddr * a1, ipaddr * a2);
bool ipaddr_le(ipaddr * a1, ipaddr * a2);
bool ipaddr_eq(ipaddr * a1, ipaddr * a2);
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_in_net(ipaddr * a1, ipaddr * a2);
ipaddr *ipaddr_mask(ipaddr * a);
ipaddr *ipaddr_bcast(ipaddr * a);
/*
* Build a mask of a given width:
*/
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()
* is used to determine whether the mask size was specified.
*/
ipaddr *
ipaddr_in(char *str)
{
int a,
b,
c,
d,
w;
ipaddr *result;
int count;
if (strlen(str) > 0)
{
count = sscanf(str, "%d.%d.%d.%d/%d", &a, &b, &c, &d, &w);
if (count < 4)
{
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))
{
elog(ERROR, "ipaddr_in: illegal address \"%s\"", str);
return (NULL);
}
}
else
{
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->width = w;
return (result);
}
/*
* IP address output function. Note mask size specification
* generated only for subnets, not for plain host addresses.
*/
char *
ipaddr_out(ipaddr * addr)
{
char *result;
int a, b, c, d, w;
if (addr == NULL)
return (NULL);
result = (char *) palloc(32);
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 )
{
/* 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",a,b,c,d,w);
}
else
{
result[0] = 0; /* special case for missing address */
}
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);
};
/*
* Comparison function for sorting:
*/
int4
ipaddr_cmp(ipaddr * a1, ipaddr * a2)
{
if (a1->address < a2->address)
return -1;
else if (a1->address > a2->address)
return 1;
else
{
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);
}
/*
* Test whether an address is within a given subnet:
*/
bool
ipaddr_in_net(ipaddr * a1, ipaddr * a2)
{
uint32 maskbits;
if (a1->width < a2->width)
return FALSE;
if ((a1->width == 32) && (a2->width == 32))
return ipaddr_eq(a1, a2);
maskbits = build_mask(a2->width);
if ((a1->address & maskbits) == (a2->address & maskbits))
return TRUE;
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:
*/
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;
}
/*
* 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
*/
--
-- PostgreSQL code for IP addresses.
--
-- $Id: ip.sql,v 1.5 1998/06/16 05:35:10 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/contrib/ip_and_macs/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/contrib/ip_and_macs/ip.so'
language 'c';
create function ipaddr_out(opaque)
returns opaque
as '/usr/local/pgsql/contrib/ip_and_macs/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/contrib/ip_and_macs/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/contrib/ip_and_macs/ip.so'
language 'c';
create function ipaddr_le(ipaddr, ipaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/ip.so'
language 'c';
create function ipaddr_eq(ipaddr, ipaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/ip.so'
language 'c';
create function ipaddr_ge(ipaddr, ipaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/ip.so'
language 'c';
create function ipaddr_gt(ipaddr, ipaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/ip.so'
language 'c';
create function ipaddr_ne(ipaddr, ipaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/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/contrib/ip_and_macs/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/contrib/ip_and_macs/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/contrib/ip_and_macs/ip.so'
language 'c';
--
-- Return the number of the hosts in the network
--
create function ipaddr_len(ipaddr)
returns int4
as '/usr/local/pgsql/contrib/ip_and_macs/ip.so'
language 'c';
--
-- Return the prefix length of the network
--
create function ipaddr_pref(ipaddr)
returns int4
as '/usr/local/pgsql/contrib/ip_and_macs/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/contrib/ip_and_macs/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/contrib/ip_and_macs/ip.so'
language 'c';
--
-- Return MASK for the network
--
create function ipaddr_mask(ipaddr)
returns ipaddr
as '/usr/local/pgsql/contrib/ip_and_macs/ip.so'
language 'c';
--
-- Return BROADCAST address for the network
--
create function ipaddr_bcast(ipaddr)
returns ipaddr
as '/usr/local/pgsql/contrib/ip_and_macs/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/contrib/ip_and_macs/ip.so'
language 'c';
--
-- Plus and Minus operators
--
create function ipaddr_plus(ipaddr,int4)
returns ipaddr
as '/usr/local/pgsql/contrib/ip_and_macs/ip.so'
language 'c';
create function ipaddr_minus(ipaddr,int4)
returns ipaddr
as '/usr/local/pgsql/contrib/ip_and_macs/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
/*
* PostgreSQL type definitions for IP addresses.
*
* $Id: ip_orig.c,v 1.1 1998/06/16 05:35:11 momjian Exp $
*/
#include <stdio.h>
#include <postgres.h>
#include <utils/palloc.h>
/*
* This is the internal storage format for IP addresses:
*/
typedef struct ipaddr
{
uint32 address;
int16 width;
} ipaddr;
/*
* Various forward declarations:
*/
ipaddr *ipaddr_in(char *str);
char *ipaddr_out(ipaddr * addr);
bool ipaddr_lt(ipaddr * a1, ipaddr * a2);
bool ipaddr_le(ipaddr * a1, ipaddr * a2);
bool ipaddr_eq(ipaddr * a1, ipaddr * a2);
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_in_net(ipaddr * a1, ipaddr * a2);
ipaddr *ipaddr_mask(ipaddr * a);
ipaddr *ipaddr_bcast(ipaddr * a);
/*
* Build a mask of a given width:
*/
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()
* is used to determine whether the mask size was specified.
*/
ipaddr *
ipaddr_in(char *str)
{
int a,
b,
c,
d,
w;
ipaddr *result;
int count;
if (strlen(str) > 0)
{
count = sscanf(str, "%d.%d.%d.%d/%d", &a, &b, &c, &d, &w);
if (count < 4)
{
elog(ERROR, "ipaddr_in: error in parsing \"%s\"", str);
return (NULL);
}
if (count == 4)
w = 32;
if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
(c < 0) || (c > 255) || (d < 0) || (d > 255) ||
(w < 0) || (w > 32))
{
elog(ERROR, "ipaddr_in: illegal address \"%s\"", str);
return (NULL);
}
}
else
{
a = b = c = d = w = 0; /* 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);
}
/*
* IP address output function. Note mask size specification
* generated only for subnets, not for plain host addresses.
*/
char *
ipaddr_out(ipaddr * addr)
{
char *result;
if (addr == NULL)
return (NULL);
result = (char *) palloc(32);
if (addr->address > 0)
{
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);
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);
}
else
{
result[0] = 0; /* special case for missing address */
}
return (result);
}
/*
* Boolean tests for magnitude.
*/
bool
ipaddr_lt(ipaddr * a1, ipaddr * a2)
{
return (a1->address < a2->address);
};
bool
ipaddr_le(ipaddr * a1, ipaddr * a2)
{
return (a1->address <= a2->address);
};
bool
ipaddr_eq(ipaddr * a1, ipaddr * a2)
{
return (a1->address == a2->address);
};
bool
ipaddr_ge(ipaddr * a1, ipaddr * a2)
{
return (a1->address >= a2->address);
};
bool
ipaddr_gt(ipaddr * a1, ipaddr * a2)
{
return (a1->address > a2->address);
};
bool
ipaddr_ne(ipaddr * a1, ipaddr * a2)
{
return (a1->address != a2->address);
};
/*
* Comparison function for sorting:
*/
int4
ipaddr_cmp(ipaddr * a1, ipaddr * a2)
{
if (a1->address < a2->address)
return -1;
else if (a1->address > a2->address)
return 1;
else
return 0;
}
/*
* Test whether an address is within a given subnet:
*/
bool
ipaddr_in_net(ipaddr * a1, ipaddr * a2)
{
uint32 maskbits;
if (a1->width < a2->width)
return FALSE;
if ((a1->width == 32) && (a2->width == 32))
return ipaddr_eq(a1, a2);
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
*/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE></TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; FreeBSD 2.2.5-RELEASE i386) [Netscape]">
</HEAD>
<BODY>
<H2>New object class for the IP ADDRESSES manipulations.</H2>
<H3>1. Description:</H3>
<UL>
<P>Type name: <B>ipaddr<BR>
</B>Data lenght: <B>6 bytes<BR>
</B>Data context: <B>ip address and prefix length</B></P>
</UL>
<H3><B>2. How to install:</B></H3>
<UL>
<P>Use script <B>ip.sql </B>to add new type, new functions and operators
to the data base.</P>
<P>Use script <B>ipi.sql </B>to add new type and new operator class ipaddr_ops
to the index system and allow indexing by this new type (with search by
'<B>&gt;</B>', '<B>&gt;=</B>', '<B>&lt;</B>', '<B>&lt;=</B>', '<B>=</B>'
boolean operators).</P>
<P>Use scripts '<B>test1.sql'</B> and '<B>test2.sql'</B> (edit second script
first) to check if indexing work properly.</P>
</UL>
<H3>3. Input / output formsts.</H3>
<P>New type stores IP address and IP prefix in the single data attribute.
To input data, you should use the form</P>
<UL>
<P><B><I>DDD</I>.<I>DDD</I>.<I>DDD</I>.<I>DDD</I>/<I>P</I>P</B></P>
</UL>
<P>for the address <B>DDD.DDD.DDD.DDD</B> and prefix <B>PP</B> (prefix
is len from 0 (for 0.0.0.0) to 32 (for 255.255.255.255)). You can miss
/PP n two cases:</P>
<UL>
<LI>You enter host address (this means /32 prefix) and this is not the
address of the natural class A, B or C network.</LI>
<LI>You enter natural class A, B, C network with the /8, /16 and /24 prefix.</LI>
</UL>
<P>For example, <B>193.124.23.0</B> should be read as '<B>193.124.23.0/24</B>'
network, and '<B>193.124.23.1</B>' should be read as <B>/32 </B>host address.
To enter interface address <B>193.124.23.6/24</B>, you should use exact
form '<B>193.124.23.6/24'</B>.</P>
<P>The address '0.0.0.0' means '0.0.0.0/0', this is <B>default</B> in terms
of routers.</P>
<P><B>ipaddr</B> type data are printed just in the same form (to allow
input/output compatibility) - <B>193.124.23.0/24</B> should be printed
as '<B>193.124.23.0</B>' and '<B>193.124.23.1/32</B>' should be printed
as '<B>193.124.23.1</B>'.</P>
<P>There is special function to convert ipaddr data into string by the
format:</P>
<UL>
<P>char ipaddr_print(ipaddr,format)</P>
</UL>
<P>format consist of plain text and %C special characters:</P>
<UL>
<P><B>%A</B> - address in form ddd.ddd.ddd.ddd,<BR>
<B>%M </B>- network mask in form ddd.ddd.ddd.ddd,<BR>
<B>%B </B>- negated mask ('0.0.0.7' for '/29' prefix, for example),<BR>
<B>%P</B> - prefix (withouth '/' delimiter).</P>
</UL>
<H3>4. Operators.</H3>
<TABLE ALIGN=ABSCENTER BORDER=2 CELLSPACING=0 CELLPADDING=0 >
<TR>
<TD>Left argument<BR>
A1</TD>
<TD>Op</TD>
<TD>Right argument<BR>
A2</TD>
<TD>Result<BR>
R</TD>
<TD>Description</TD>
</TR>
<TR>
<TD>ipaddr</TD>
<TD>&lt;</TD>
<TD>ipaddr</TD>
<TD>boolean</TD>
<TD>Compare addresses, if they are equal, compare prefixes,</TD>
</TR>
<TR>
<TD>ipaddr</TD>
<TD>&lt;=</TD>
<TD>ipaddr</TD>
<TD>boolean</TD>
<TD>Compare addresses, if they are equal, compare prefixes,</TD>
</TR>
<TR>
<TD>ipaddr</TD>
<TD>=</TD>
<TD>ipaddr</TD>
<TD>boolean</TD>
<TD>Compare addresses, if they are equal, compare prefixes,</TD>
</TR>
<TR>
<TD>ipaddr</TD>
<TD>&gt;=</TD>
<TD>ipaddr</TD>
<TD>boolean</TD>
<TD>Compare addresses, if they are equal, compare prefixes,</TD>
</TR>
<TR>
<TD>ipaddr</TD>
<TD>&gt;</TD>
<TD>ipaddr</TD>
<TD>boolean</TD>
<TD>Compare addresses, if they are equal, compare prefixes,</TD>
</TR>
<TR>
<TD>ipaddr</TD>
<TD>&lt;&gt;</TD>
<TD>ipaddr</TD>
<TD>boolean</TD>
<TD>Compare addresses, if they are equal, compare prefixes,</TD>
</TR>
<TR>
<TD>ipaddr</TD>
<TD>@</TD>
<TD>ipaddr</TD>
<TD>boolean</TD>
<TD>True if A1 is the part of network (subnetwork) A2 or if A1 = A2</TD>
</TR>
<TR>
<TD>ipaddr</TD>
<TD>+</TD>
<TD>int4</TD>
<TD>ipaddr</TD>
<TD>Increase address A1 on A2 value (A2 is integer).</TD>
</TR>
<TR>
<TD>ipaddr </TD>
<TD>-</TD>
<TD>int4</TD>
<TD>ipaddr</TD>
<TD>Decrease address A1 on A2.</TD>
</TR>
</TABLE>
<H3>5. Functions.</H3>
<P>There is a lot of functions defined for new ipaddr data type. Some of
them are duplicated by operators described above, some are not. </P>
<TABLE ALIGN=ABSCENTER BORDER=2 CELLSPACING=0 CELLPADDING=0 >
<TR>
<TD>Function(arguments)</TD>
<TD>Function type</TD>
<TD>Description</TD>
<TD>Operator</TD>
</TR>
<TR>
<TD>ipaddr_print(ipaddr, text)</TD>
<TD>text</TD>
<TD>Converts ipaddr to the text string by format from the second argument.
Format can contain %A - address, %M - mask, %B - reversed mask, %P - prefix,
and any other characters.</TD>
<TD></TD>
</TR>
<TR>
<TD>ipaddr_lt(ipaddr, ipaddr)</TD>
<TD>boolean</TD>
<TD>Compare by '&lt;'</TD>
<TD>&lt;</TD>
</TR>
<TR>
<TD>ipaddr_le(ipaddr,ipaddr)</TD>
<TD>boolean</TD>
<TD>Compare by '&lt;='</TD>
<TD>&lt;=</TD>
</TR>
<TR>
<TD>ipaddr_eq(ipaddr, ipaddr)</TD>
<TD>boolean</TD>
<TD>Compare by '='</TD>
<TD>=</TD>
</TR>
<TR>
<TD>ipaddr_ne(ipaddr, ipaddr)</TD>
<TD>boolean</TD>
<TD>Compare by '&lt;&gt;'</TD>
<TD>&lt;&gt;</TD>
</TR>
<TR>
<TD>ipaddr_ge(ipaddr, ipaddr)</TD>
<TD>boolean</TD>
<TD>Compare by '&gt;='</TD>
<TD>&gt;=</TD>
</TR>
<TR>
<TD>ipaddr_gt(ipaddr, ipaddr)</TD>
<TD>boolean</TD>
<TD>Compare by '&gt;'</TD>
<TD>&gt;</TD>
</TR>
<TR>
<TD>ipaddr_in_net(ipaddr, ipaddr)</TD>
<TD>boolean</TD>
<TD><B>True</B> if fisrt argument is the host or subnetwork of the second
argument (first address is equal or included into the second one)</TD>
<TD>@</TD>
</TR>
<TR>
<TD>ipaddr_net(ipaddr)</TD>
<TD>ipaddr</TD>
<TD>Return the network (with the 0 in host bits) for the argument; for
example ipaddr_net('193.124.23.1/24') = '193.124.23.0';</TD>
<TD></TD>
</TR>
<TR>
<TD>ipaddr_bcast(ipaddr)</TD>
<TD>ipaddr</TD>
<TD>Return broadcast address (with the /32 prefix) for the network described
by argument.</TD>
<TD></TD>
</TR>
<TR>
<TD>ipaddr_is_net(ipaddr)</TD>
<TD>boolean</TD>
<TD><B>True</B> if ipaddr is network address; <B>false</B> if its' the
host in the network. For the /32 addresses, returns <B>false</B>.</TD>
<TD></TD>
</TR>
<TR>
<TD>ipaddr_mask(ipaddr)</TD>
<TD>ipaddr</TD>
<TD>Return netmask (with /32 prefix) for the network.</TD>
<TD></TD>
</TR>
<TR>
<TD>ipaddr_prefix(ipaddr)</TD>
<TD>int4</TD>
<TD>Return the prefix size (from 0 to 32).</TD>
<TD></TD>
</TR>
<TR>
<TD>ipaddr_len(ipaddr)</TD>
<TD>int4</TD>
<TD>Return the number of addresses in the particular network (for example,
256 for /24 prefix).</TD>
<TD></TD>
</TR>
<TR>
<TD>ipaddr_integer(ipaddr)</TD>
<TD>int4</TD>
<TD>Return IP address (withouth the prefix) as integer.</TD>
<TD></TD>
</TR>
<TR>
<TD>ipaddr_compose(int4,int4)</TD>
<TD>ipaddr</TD>
<TD>Compose ipaddr object from ip address (first argument) and prefix lenght
(second argument). ipaddr_compose(ipaddr_integer(a),ipaddr_prefix(a)) =
a.</TD>
<TD></TD>
</TR>
<TR>
<TD>ipaddr_plus(ipaddr, int4)</TD>
<TD>ipaddr</TD>
<TD>Operator PLUS (addres increased, prefix does not changed)</TD>
<TD>+</TD>
</TR>
<TR>
<TD>ipaddr_minus(ipaddr, int4)</TD>
<TD>ipaddr</TD>
<TD>Operator MINUS (address decreased, prefix does not changed).</TD>
<TD>-</TD>
</TR>
<TR>
<TD>ipaddr_cmp(ipaddr, ipaddr)</TD>
<TD>int4</TD>
<TD>Compare it's arguments and return -1, 0 or +1.</TD>
<TD></TD>
</TR>
</TABLE>
<H3>5. Usage.</H3>
<P>New type opens many interesting futures for the ip routing or ip accounting
networks. For example, you can search all interfaces connected to the same
phisical network by comparing ipaddr_net(interface_address) /if you store
address as address/prefix pair in the single attribute, and so on.</P>
<P>Unfortunately, I had not time (and was not too familiar with RTree ideas
used in Postgres) to check if it's possible to use RTree indexing for the
fast routing lookups by data base. It's important task because usial usage
of this future is _determine the nearest network the particular address
contain to, and link the accounting record to this network_. And so on.</P>
<P>Write any questions or wishes to me by e-mail. This is BETA version
of this package for now, because we are building our IP routing data base
just now and did not tested all this fucntions under heavy conditions;
through I hope this functions are too simple for the hidden bugs, and they
was tested carefully at the simple tests.</P>
<H3>6. Installation.</H3>
<OL>
<LI>Translate shared library ip.so:<BR>
make</LI>
<LI>Install shared library to the proper place (/usr/local/pgsql/contrib/ip_and_macs)<BR>
make install<BR>
(in case if your system is not FreeBSD, it can be nessesary modify 'Makefile'
before).</LI>
<LI>Public to the accessible place scripts ip.sql (installation of data
type), ipi.sql (describing of this data type for the proper indexing),
test1.sql, test2.sql, test.DATA (test and data). Modify test1.sql in accordance
to real location of the data files.</LI>
<LI>To add new data type into your data base, exec scripts in this data
base:<BR>
psql DATA_BASE<BR>
\i ip.sql -- change this to the real location<BR>
\i ipi.sql -- change this to the real location</LI>
<LI>To test this data type, exec test1.sql and test2.sql SQL scripts.</LI>
</OL>
<H3>7. Download.</H3>
<P>You can download this data type from <B>http://relcom.EU.net/ip_class.tar.gz</B></P>
<H3><BR>
</H3>
<P>
<HR WIDTH="100%"></P>
<P>Aleksei Roudnev, The Network Operation Centre, Relcom Network; Moscow,
Russia.</P>
<UL><B></B></UL>
<UL></UL>
</BODY>
</HTML>
begin;
select pgam.oid from pg_am pgam
where amname = 'btree';
--
-- Temporary oper table
--
-- drop table tmp_op;
create table tmp_op ( oprname name, opi int2);
--
-- Fill in this table
--
insert into tmp_op values('<','1');
insert into tmp_op values('<=','2');
insert into tmp_op values('=','3');
insert into tmp_op values('>=','4');
insert into tmp_op values('>','5');
select * from tmp_op;
--
-- Add record to the pg_opclass
--
DELETE FROM pg_opclass WHERE opcname = 'ipaddr_ops';
INSERT INTO pg_opclass (opcname,opcdeftype)
select 'ipaddr_ops',oid from pg_type where typname = 'ipaddr';
--
-- And determine oid
--
SELECT opc.oid,opc.opcname
FROM pg_opclass opc
WHERE opc.opcname = 'ipaddr_ops';
--
SELECT o.oid AS opoid, o.oprname
INTO TABLE ipaddr_tmp
FROM pg_operator o, pg_type t
WHERE o.oprleft = t.oid and o.oprright = t.oid and t.typname = 'ipaddr';
SELECT * FROM ipaddr_tmp;
--
INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, amopselect, amopnpages)
SELECT am.oid,opcl.oid,c.opoid,t.opi,'btreesel'::regproc, 'btreenpage'::regproc
FROM pg_am am, pg_opclass opcl, ipaddr_tmp c, tmp_op t
WHERE t.oprname = c.oprname
and amname = 'btree'
and opcname = 'ipaddr_ops';
--
SELECT prc.oid, prc.proname FROM pg_proc prc
WHERE prc.proname = 'ipaddr_cmp';
--
INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
SELECT pgam.oid, opc.oid,prc.oid,'1'::int2
FROM pg_am pgam,
pg_opclass opc,
pg_proc prc
WHERE prc.proname = 'ipaddr_cmp'
and pgam.amname = 'btree'
and opc.opcname = 'ipaddr_ops';
drop table tmp_op;
DROP TABLE ipaddr_tmp;
COMMIT;
-- *****************************************************************
-- * Now you should test this by running test1.sql and test2.sql *
-- * In test2, be sure the 'explain' operator show you *
-- * search by index in the last line of output *
-- *****************************************************************
/*
* PostgreSQL type definitions for MAC addresses.
*
* $Id: mac.h,v 1.3 1998/02/26 04:27:50 momjian Exp $
*/
typedef struct manufacturer
{
unsigned char a;
unsigned char b;
unsigned char c;
char *name;
} manufacturer;
manufacturer manufacturers[] = {
{0x00, 0x00, 0x0C, "Cisco"},
{0x00, 0x00, 0x0E, "Fujitsu"},
{0x00, 0x00, 0x0F, "NeXT"},
{0x00, 0x00, 0x10, "Sytek"},
{0x00, 0x00, 0x1D, "Cabletron"},
{0x00, 0x00, 0x20, "DIAB"},
{0x00, 0x00, 0x22, "Visual Technology"},
{0x00, 0x00, 0x2A, "TRW"},
{0x00, 0x00, 0x32, "GPT Limited"},
{0x00, 0x00, 0x5A, "S & Koch"},
{0x00, 0x00, 0x5E, "IANA"},
{0x00, 0x00, 0x65, "Network General"},
{0x00, 0x00, 0x6B, "MIPS"},
{0x00, 0x00, 0x77, "MIPS"},
{0x00, 0x00, 0x7A, "Ardent"},
{0x00, 0x00, 0x89, "Cayman Systems"},
{0x00, 0x00, 0x93, "Proteon"},
{0x00, 0x00, 0x9F, "Ameristar Technology"},
{0x00, 0x00, 0xA2, "Wellfleet"},
{0x00, 0x00, 0xA3, "Network Application Technology"},
{0x00, 0x00, 0xA6, "Network General"},
{0x00, 0x00, 0xA7, "NCD"},
{0x00, 0x00, 0xA9, "Network Systems"},
{0x00, 0x00, 0xAA, "Xerox"},
{0x00, 0x00, 0xB3, "CIMLinc"},
{0x00, 0x00, 0xB7, "Dove Fastnet"},
{0x00, 0x00, 0xBC, "Allen-Bradley"},
{0x00, 0x00, 0xC0, "Western Digital"},
{0x00, 0x00, 0xC5, "Farallon"},
{0x00, 0x00, 0xC6, "Hewlett-Packard"},
{0x00, 0x00, 0xC8, "Altos"},
{0x00, 0x00, 0xC9, "Emulex"},
{0x00, 0x00, 0xD7, "Dartmouth College"},
{0x00, 0x00, 0xD8, "3Com (?)"},
{0x00, 0x00, 0xDD, "Gould"},
{0x00, 0x00, 0xDE, "Unigraph"},
{0x00, 0x00, 0xE2, "Acer Counterpoint"},
{0x00, 0x00, 0xEF, "Alantec"},
{0x00, 0x00, 0xFD, "High Level Hardware"},
{0x00, 0x01, 0x02, "BBN internal usage"},
{0x00, 0x20, 0xAF, "3Com"},
{0x00, 0x17, 0x00, "Kabel"},
{0x00, 0x80, 0x64, "Wyse Technology"},
{0x00, 0x80, 0x2B, "IMAC (?)"},
{0x00, 0x80, 0x2D, "Xylogics, Inc."},
{0x00, 0x80, 0x8C, "Frontier Software Development"},
{0x00, 0x80, 0xC2, "IEEE 802.1 Committee"},
{0x00, 0x80, 0xD3, "Shiva"},
{0x00, 0xAA, 0x00, "Intel"},
{0x00, 0xDD, 0x00, "Ungermann-Bass"},
{0x00, 0xDD, 0x01, "Ungermann-Bass"},
{0x02, 0x07, 0x01, "Racal InterLan"},
{0x02, 0x04, 0x06, "BBN internal usage"},
{0x02, 0x60, 0x86, "Satelcom MegaPac"},
{0x02, 0x60, 0x8C, "3Com"},
{0x02, 0xCF, 0x1F, "CMC"},
{0x08, 0x00, 0x02, "3Com"},
{0x08, 0x00, 0x03, "ACC"},
{0x08, 0x00, 0x05, "Symbolics"},
{0x08, 0x00, 0x08, "BBN"},
{0x08, 0x00, 0x09, "Hewlett-Packard"},
{0x08, 0x00, 0x0A, "Nestar Systems"},
{0x08, 0x00, 0x0B, "Unisys"},
{0x08, 0x00, 0x11, "Tektronix"},
{0x08, 0x00, 0x14, "Excelan"},
{0x08, 0x00, 0x17, "NSC"},
{0x08, 0x00, 0x1A, "Data General"},
{0x08, 0x00, 0x1B, "Data General"},
{0x08, 0x00, 0x1E, "Apollo"},
{0x08, 0x00, 0x20, "Sun"},
{0x08, 0x00, 0x22, "NBI"},
{0x08, 0x00, 0x25, "CDC"},
{0x08, 0x00, 0x26, "Norsk Data"},
{0x08, 0x00, 0x27, "PCS Computer Systems GmbH"},
{0x08, 0x00, 0x28, "Texas Instruments"},
{0x08, 0x00, 0x2B, "DEC"},
{0x08, 0x00, 0x2E, "Metaphor"},
{0x08, 0x00, 0x2F, "Prime Computer"},
{0x08, 0x00, 0x36, "Intergraph"},
{0x08, 0x00, 0x37, "Fujitsu-Xerox"},
{0x08, 0x00, 0x38, "Bull"},
{0x08, 0x00, 0x39, "Spider Systems"},
{0x08, 0x00, 0x41, "DCA Digital Comm. Assoc."},
{0x08, 0x00, 0x45, "Xylogics (?)"},
{0x08, 0x00, 0x46, "Sony"},
{0x08, 0x00, 0x47, "Sequent"},
{0x08, 0x00, 0x49, "Univation"},
{0x08, 0x00, 0x4C, "Encore"},
{0x08, 0x00, 0x4E, "BICC"},
{0x08, 0x00, 0x56, "Stanford University"},
{0x08, 0x00, 0x58, "DECsystem 20 (?)"},
{0x08, 0x00, 0x5A, "IBM"},
{0x08, 0x00, 0x67, "Comdesign"},
{0x08, 0x00, 0x68, "Ridge"},
{0x08, 0x00, 0x69, "Silicon Graphics"},
{0x08, 0x00, 0x6E, "Concurrent"},
{0x08, 0x00, 0x75, "DDE"},
{0x08, 0x00, 0x7C, "Vitalink"},
{0x08, 0x00, 0x80, "XIOS"},
{0x08, 0x00, 0x86, "Imagen/QMS"},
{0x08, 0x00, 0x87, "Xyplex"},
{0x08, 0x00, 0x89, "Kinetics"},
{0x08, 0x00, 0x8B, "Pyramid"},
{0x08, 0x00, 0x8D, "XyVision"},
{0x08, 0x00, 0x90, "Retix Inc"},
{0x48, 0x44, 0x53, "HDS (?)"},
{0x80, 0x00, 0x10, "AT&T"},
{0xAA, 0x00, 0x00, "DEC"},
{0xAA, 0x00, 0x01, "DEC"},
{0xAA, 0x00, 0x02, "DEC"},
{0xAA, 0x00, 0x03, "DEC"},
{0xAA, 0x00, 0x04, "DEC"},
{0x00, 0x00, 0x00, NULL}
};
/*
* eof
*/
--
-- PostgreSQL code for MAC addresses.
--
-- $Id: mac.sql,v 1.4 1998/06/16 05:35:11 momjian Exp $
--
load '/usr/local/pgsql/contrib/ip_and_macs/mac.so';
--
-- Input and output functions and the type itself:
--
create function macaddr_in(opaque)
returns opaque
as '/usr/local/pgsql/contrib/ip_and_macs/mac.so'
language 'c';
create function macaddr_out(opaque)
returns opaque
as '/usr/local/pgsql/contrib/ip_and_macs/mac.so'
language 'c';
create type macaddr (
internallength = 6,
externallength = variable,
input = macaddr_in,
output = macaddr_out
);
--
-- The boolean tests:
--
create function macaddr_lt(macaddr, macaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/mac.so'
language 'c';
create function macaddr_le(macaddr, macaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/mac.so'
language 'c';
create function macaddr_eq(macaddr, macaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/mac.so'
language 'c';
create function macaddr_ge(macaddr, macaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/mac.so'
language 'c';
create function macaddr_gt(macaddr, macaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/mac.so'
language 'c';
create function macaddr_ne(macaddr, macaddr)
returns bool
as '/usr/local/pgsql/contrib/ip_and_macs/mac.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.
--
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,
commutator = =,
-- negator = <>,
procedure = macaddr_eq
);
create operator >= (
leftarg = macaddr,
rightarg = macaddr,
negator = <,
procedure = macaddr_ge
);
create operator > (
leftarg = macaddr,
rightarg = macaddr,
negator = <=,
procedure = macaddr_gt
);
create operator <> (
leftarg = macaddr,
rightarg = macaddr,
negator = =,
procedure = macaddr_ne
);
--
-- Finally, the special manufacurer matching function:
--
create function macaddr_manuf(macaddr)
returns text
as '/usr/local/pgsql/contrib/ip_and_macs/mac.so'
language 'c';
--
-- eof
--
insert into xx values('193.124.23.2','host2');
insert into xx values('193.124.23.3','host3');
insert into xx values('193.124.22.1','host4');
insert into xx values('193.124.22.2','host5');
insert into xx values('193.124.22.3','host6');
此差异已折叠。
--
-- A quick test of the IP address code
--
-- $Id: test.sql,v 1.2 1998/06/16 05:35:12 momjian Exp $
-- This is original test (it was written before my changes in this class). alex.
-- 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
--
drop table stat_t;
create table stat_t(i1 ipaddr, i2 ipaddr, p int4, b int4);
create index stat_i1 on stat_t using btree (i1 ipaddr_ops);
create index stat_i2 on stat_t using btree (i2 ipaddr_ops);
copy stat_t from '/v/noc/src/ip_class/test.DATA' using delimiters ' ';
--
-- Please, check if your test data are not in /v/noc/src/ip_class/test.DATA file,
-- edit test1.sql file and repeatr it.
--
-- If everything is OK, you should run test2.sql now
--
vacuum verbose analyze stat_t (i1,i2);
--
--
select i2,sum(b) as b
into tmp
from stat_t
where i1 >= '144.206.0.0' and i1 <= '144.206.255.255'
group by i2;
insert into tmp
select '0.0.0.0' as i2,sum(b) as k
from tmp
where b < 10 * 1024;
delete from tmp
where b < 10 * 1024 and i2 <> '0.0.0.0';
select i2,b / 1024 as k from tmp
order by k desc;
select ipaddr_print(i2,'%A/%P'),b from tmp where i2 = '0.0.0.0';
drop table tmp;
explain select i2,sum(b) as b
into tmp
from stat_t
where i1 >= '144.206.0.0' and i1 <= '144.206.255.255'
group by i2;
-- ********************************************************
-- * Now remove test table by 'drop table stat_t' command *
-- ********************************************************
PostgreSQL type extensions for IP and MAC addresses.
---------------------------------------------------
$Id: README.ORIG,v 1.2 1998/06/16 05:35:10 momjian Exp $
$Id: README.ipaddr,v 1.1 1998/10/03 05:40:41 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'.
as a very simple example of how to do this sort of thing, so I
submitted it to the PostgreSQL project for inclusion in the contrib
directory. Since then, that directory has been modified to contain
Aleksei Roudnev's implementation, which is based on mine.
For those who have seen my previous contribution of these types, note
that much has changed: I've modified the IP address type to work the
way Paul Vixie did with his CIDR type. In fact, I've pretty much just
stolen his solution, modifying it into my framework in such a way as
to facilitate the addition of IPV6 handling code in the future. I've
pretty much ignored Aleksei's C code, but I've added his SQL code to
enter the necessary operators into the various system tables needed to
make the types indexable.
IP addresses are implemented as a struct of fixed in-memory length,
but variable on-disk storage size. For IPV4, it contains the address
family (AF_INET), the CIDR prefix length and four byte address. For
IPV6, the address family will be different, and the address longer.
The external representation of an IP address generally looks like
'158.37.96.15/32'. 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 '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).
addition, there are operators to check for networks or addresses being
subnets of or addresses contained within other networks. << tests
whether the left operand is contained within the right, <<= includes
equality, >> and >>= do the same things the opposite way.
The input and output functions use routines from Paul Vixie's BIND,
and I've snarfed the source files inet_net_ntop.c and inet_net_pton.c
directly from a recent distribution of that code. They are included
here to avoid the need to fetch and install the BIND libraries to be
able to use this code. IANAL, but it looks from the copyright
messages in the files as if this should be acceptable. Read the
documentation in inet_net_pton.c to see the legal input formats.
MAC level ethernet addresses are implemented as a 6 byte struct that
contains the address as unsigned chars. Several input forms are
......@@ -42,15 +61,14 @@ 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!)
manufacturer there.
Many thanks to Aleksei Roudnev and Paul Vixie for their fine work!
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!
system: fix the path names in 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).
Bergen, Norway, 1998-08-09, Tom Ivar Helbekkmo (tih@nhh.no).
此差异已折叠。
......@@ -4,7 +4,7 @@
# Makefile for utils/adt
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.17 1998/08/24 01:38:04 momjian Exp $
# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.18 1998/10/03 05:40:47 momjian Exp $
#
#-------------------------------------------------------------------------
......@@ -23,7 +23,8 @@ OBJS = acl.o arrayfuncs.o arrayutils.o bool.o cash.o char.o chunk.o \
misc.o nabstime.o name.o not_in.o numutils.o \
oid.o oracle_compat.o \
regexp.o regproc.o ruleutils.o selfuncs.o sets.o \
tid.o timestamp.o varchar.o varlena.o version.o
tid.o timestamp.o varchar.o varlena.o version.o \
ip.o mac.o inet_net_ntop.o inet_net_pton.o
all: SUBSYS.o
......
/*
* Copyright (c) 1996 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.1 1998/10/03 05:40:48 momjian Exp $";
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef SPRINTF_CHAR
#define SPRINTF(x) strlen(sprintf/**/x)
#else
#define SPRINTF(x) ((size_t)sprintf x)
#endif
static char *inet_net_ntop_ipv4(const u_char *src, int bits,
char *dst, size_t size);
/*
* char *
* inet_net_ntop(af, src, bits, dst, size)
* convert network number from network to presentation format.
* generates CIDR style result always.
* return:
* pointer to dst, or NULL if an error occurred (check errno).
* author:
* Paul Vixie (ISC), July 1996
*/
char *
inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
{
switch (af)
{
case AF_INET:
return (inet_net_ntop_ipv4(src, bits, dst, size));
default:
errno = EAFNOSUPPORT;
return (NULL);
}
}
/*
* static char *
* inet_net_ntop_ipv4(src, bits, dst, size)
* convert IPv4 network number from network to presentation format.
* generates CIDR style result always.
* return:
* pointer to dst, or NULL if an error occurred (check errno).
* note:
* network byte order assumed. this means 192.5.5.240/28 has
* 0x11110000 in its fourth octet.
* author:
* Paul Vixie (ISC), July 1996
*/
static char *
inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
{
char *odst = dst;
char *t;
u_int m;
int b;
if (bits < 0 || bits > 32)
{
errno = EINVAL;
return (NULL);
}
if (bits == 0)
{
if (size < sizeof "0")
goto emsgsize;
*dst++ = '0';
*dst = '\0';
}
/* Format whole octets. */
for (b = bits / 8; b > 0; b--)
{
if (size < sizeof "255.")
goto emsgsize;
t = dst;
dst += SPRINTF((dst, "%u", *src++));
if (b > 1)
{
*dst++ = '.';
*dst = '\0';
}
size -= (size_t) (dst - t);
}
/* Format partial octet. */
b = bits % 8;
if (b > 0)
{
if (size < sizeof ".255")
goto emsgsize;
t = dst;
if (dst != odst)
*dst++ = '.';
m = ((1 << b) - 1) << (8 - b);
dst += SPRINTF((dst, "%u", *src & m));
size -= (size_t) (dst - t);
}
/* Format CIDR /width. */
if (size < sizeof "/32")
goto emsgsize;
dst += SPRINTF((dst, "/%u", bits));
return (odst);
emsgsize:
errno = EMSGSIZE;
return (NULL);
}
/*
* Copyright (c) 1996 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] = "$Id: inet_net_pton.c,v 1.1 1998/10/03 05:40:49 momjian Exp $";
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef SPRINTF_CHAR
#define SPRINTF(x) strlen(sprintf/**/x)
#else
#define SPRINTF(x) ((size_t)sprintf x)
#endif
static int inet_net_pton_ipv4(const char *src, u_char *dst, size_t size);
/*
* static int
* inet_net_pton(af, src, dst, size)
* convert network number from presentation to network format.
* accepts hex octets, hex strings, decimal octets, and /CIDR.
* "size" is in bytes and describes "dst".
* return:
* number of bits, either imputed classfully or specified with /CIDR,
* or -1 if some failure occurred (check errno). ENOENT means it was
* not a valid network specification.
* author:
* Paul Vixie (ISC), June 1996
*/
int
inet_net_pton(int af, const char *src, void *dst, size_t size)
{
switch (af)
{
case AF_INET:
return (inet_net_pton_ipv4(src, dst, size));
default:
errno = EAFNOSUPPORT;
return (-1);
}
}
/*
* static int
* inet_net_pton_ipv4(src, dst, size)
* convert IPv4 network number from presentation to network format.
* accepts hex octets, hex strings, decimal octets, and /CIDR.
* "size" is in bytes and describes "dst".
* return:
* number of bits, either imputed classfully or specified with /CIDR,
* or -1 if some failure occurred (check errno). ENOENT means it was
* not an IPv4 network specification.
* note:
* network byte order assumed. this means 192.5.5.240/28 has
* 0x11110000 in its fourth octet.
* author:
* Paul Vixie (ISC), June 1996
*/
static int
inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
{
static const char
xdigits[] = "0123456789abcdef",
digits[] = "0123456789";
int n,
ch,
tmp,
dirty,
bits;
const u_char *odst = dst;
ch = *src++;
if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
&& isascii(src[1]) && isxdigit(src[1]))
{
/* Hexadecimal: Eat nybble string. */
if (size <= 0)
goto emsgsize;
*dst = 0, dirty = 0;
src++; /* skip x or X. */
while ((ch = *src++) != '\0' &&
isascii(ch) && isxdigit(ch))
{
if (isupper(ch))
ch = tolower(ch);
n = strchr(xdigits, ch) - xdigits;
assert(n >= 0 && n <= 15);
*dst |= n;
if (!dirty++)
*dst <<= 4;
else if (size-- > 0)
*++dst = 0, dirty = 0;
else
goto emsgsize;
}
if (dirty)
size--;
}
else if (isascii(ch) && isdigit(ch))
{
/* Decimal: eat dotted digit string. */
for (;;)
{
tmp = 0;
do
{
n = strchr(digits, ch) - digits;
assert(n >= 0 && n <= 9);
tmp *= 10;
tmp += n;
if (tmp > 255)
goto enoent;
} while ((ch = *src++) != '\0' &&
isascii(ch) && isdigit(ch));
if (size-- <= 0)
goto emsgsize;
*dst++ = (u_char) tmp;
if (ch == '\0' || ch == '/')
break;
if (ch != '.')
goto enoent;
ch = *src++;
if (!isascii(ch) || !isdigit(ch))
goto enoent;
}
}
else
goto enoent;
bits = -1;
if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst)
{
/* CIDR width specifier. Nothing can follow it. */
ch = *src++; /* Skip over the /. */
bits = 0;
do
{
n = strchr(digits, ch) - digits;
assert(n >= 0 && n <= 9);
bits *= 10;
bits += n;
} while ((ch = *src++) != '\0' &&
isascii(ch) && isdigit(ch));
if (ch != '\0')
goto enoent;
if (bits > 32)
goto emsgsize;
}
/* Firey death and destruction unless we prefetched EOS. */
if (ch != '\0')
goto enoent;
/* If nothing was written to the destination, we found no address. */
if (dst == odst)
goto enoent;
/* If no CIDR spec was given, infer width from net class. */
if (bits == -1)
{
if (*odst >= 240) /* Class E */
bits = 32;
else if (*odst >= 224) /* Class D */
bits = 4;
else if (*odst >= 192) /* Class C */
bits = 24;
else if (*odst >= 128) /* Class B */
bits = 16;
else
/* Class A */
bits = 8;
/* If imputed mask is narrower than specified octets, widen. */
if (bits >= 8 && bits < ((dst - odst) * 8))
bits = (dst - odst) * 8;
}
/* Extend network to cover the actual mask. */
while (bits > ((dst - odst) * 8))
{
if (size-- <= 0)
goto emsgsize;
*dst++ = '\0';
}
return (bits);
enoent:
errno = ENOENT;
return (-1);
emsgsize:
errno = EMSGSIZE;
return (-1);
}
/*
* PostgreSQL type definitions for IP addresses. This
* is for IP V4 CIDR notation, but prepared for V6: just
* add the necessary bits where the comments indicate.
*
* $Id: ip.c,v 1.1 1998/10/03 05:40:49 momjian Exp $
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <postgres.h>
#include <utils/palloc.h>
#include <utils/mac.h>
/*
* Access macros. Add IPV6 support.
*/
#define ip_addrsize(ipaddrptr) \
(((ipaddr_struct *)VARDATA(ipaddrptr))->family == AF_INET ? 4 : -1)
#define ip_family(ipaddrptr) \
(((ipaddr_struct *)VARDATA(ipaddrptr))->family)
#define ip_bits(ipaddrptr) \
(((ipaddr_struct *)VARDATA(ipaddrptr))->bits)
#define ip_v4addr(ipaddrptr) \
(((ipaddr_struct *)VARDATA(ipaddrptr))->addr.ipv4_addr)
/*
* IP address reader.
*/
ipaddr *
ipaddr_in(char *src)
{
int bits;
ipaddr *dst;
dst = palloc(VARHDRSZ + sizeof(ipaddr_struct));
if (dst == NULL)
{
elog(ERROR, "unable to allocate memory in ipaddr_in()");
return (NULL);
}
/* First, try for an IP V4 address: */
ip_family(dst) = AF_INET;
bits = inet_net_pton(ip_family(dst), src, &ip_v4addr(dst), ip_addrsize(dst));
if ((bits < 0) || (bits > 32))
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "could not parse \"%s\"", src);
pfree(dst);
return (NULL);
}
VARSIZE(dst) = VARHDRSZ
+ ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
ip_bits(dst) = bits;
return (dst);
}
/*
* IP address output function.
*/
char *
ipaddr_out(ipaddr *src)
{
char *dst,
tmp[sizeof("255.255.255.255/32")];
if (ip_family(src) == AF_INET)
{
/* It's an IP V4 address: */
if (inet_net_ntop(AF_INET, &ip_v4addr(src), ip_bits(src),
tmp, sizeof(tmp)) < 0)
{
elog(ERROR, "unable to print address (%s)", strerror(errno));
return (NULL);
}
}
else
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "unknown address family (%d)", ip_family(src));
return (NULL);
}
dst = palloc(strlen(tmp) + 1);
if (dst == NULL)
{
elog(ERROR, "unable to allocate memory in ipaddr_out()");
return (NULL);
}
strcpy(dst, tmp);
return (dst);
}
/*
* Boolean tests for magnitude. Add V4/V6 testing!
*/
bool
ipaddr_lt(ipaddr *a1, ipaddr *a2)
{
if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
int order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
return ((order < 0) || ((order == 0) && (ip_bits(a1) < ip_bits(a2))));
}
else
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "cannot compare address families %d and %d",
ip_family(a1), ip_family(a2));
return (FALSE);
}
}
bool
ipaddr_le(ipaddr *a1, ipaddr *a2)
{
return (ipaddr_lt(a1, a2) || ipaddr_eq(a1, a2));
}
bool
ipaddr_eq(ipaddr *a1, ipaddr *a2)
{
if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
return ((ip_bits(a1) == ip_bits(a2))
&& (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
}
else
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "cannot compare address families %d and %d",
ip_family(a1), ip_family(a2));
return (FALSE);
}
}
bool
ipaddr_ge(ipaddr *a1, ipaddr *a2)
{
return (ipaddr_gt(a1, a2) || ipaddr_eq(a1, a2));
}
bool
ipaddr_gt(ipaddr *a1, ipaddr *a2)
{
if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
int order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
return ((order > 0) || ((order == 0) && (ip_bits(a1) > ip_bits(a2))));
}
else
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "cannot compare address families %d and %d",
ip_family(a1), ip_family(a2));
return (FALSE);
}
}
bool
ipaddr_ne(ipaddr *a1, ipaddr *a2)
{
return (!ipaddr_eq(a1, a2));
}
bool
ipaddr_sub(ipaddr *a1, ipaddr *a2)
{
if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
return ((ip_bits(a1) > ip_bits(a2))
&& (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0));
}
else
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "cannot compare address families %d and %d",
ip_family(a1), ip_family(a2));
return (FALSE);
}
}
bool
ipaddr_subeq(ipaddr *a1, ipaddr *a2)
{
if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
return ((ip_bits(a1) >= ip_bits(a2))
&& (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0));
}
else
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "cannot compare address families %d and %d",
ip_family(a1), ip_family(a2));
return (FALSE);
}
}
bool
ipaddr_sup(ipaddr *a1, ipaddr *a2)
{
if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
return ((ip_bits(a1) < ip_bits(a2))
&& (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
}
else
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "cannot compare address families %d and %d",
ip_family(a1), ip_family(a2));
return (FALSE);
}
}
bool
ipaddr_supeq(ipaddr *a1, ipaddr *a2)
{
if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
{
return ((ip_bits(a1) <= ip_bits(a2))
&& (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
}
else
{
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "cannot compare address families %d and %d",
ip_family(a1), ip_family(a2));
return (FALSE);
}
}
/*
* Comparison function for sorting. Add V4/V6 testing!
*/
int4
ipaddr_cmp(ipaddr *a1, ipaddr *a2)
{
if (ntohl(ip_v4addr(a1)) < ntohl(ip_v4addr(a2)))
return (-1);
else if (ntohl(ip_v4addr(a1)) > ntohl(ip_v4addr(a2)))
return (1);
return 0;
}
/*
* Bitwise comparison for V4 addresses. Add V6 implementation!
*/
int
v4bitncmp(u_int32_t a1, u_int32_t a2, int bits)
{
unsigned long mask = 0;
int i;
for (i = 0; i < bits; i++)
mask = (mask >> 1) | 0x80000000;
a1 = ntohl(a1);
a2 = ntohl(a2);
if ((a1 & mask) < (a2 & mask))
return (-1);
else if ((a1 & mask) > (a2 & mask))
return (1);
return (0);
}
/*
* PostgreSQL type definitions for MAC addresses.
*
* $Id: mac.c,v 1.3 1998/02/26 04:27:44 momjian Exp $
* $Id: mac.c,v 1.1 1998/10/03 05:40:50 momjian Exp $
*/
#include <stdio.h>
......@@ -9,40 +9,123 @@
#include <postgres.h>
#include <utils/palloc.h>
#include "mac.h"
/*
* This is the internal storage format for MAC addresses:
*/
typedef struct macaddr
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
unsigned char e;
unsigned char f;
} macaddr;
/*
* Various forward declarations:
*/
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);
text *macaddr_manuf(macaddr * addr);
#include <utils/mac.h>
manufacturer manufacturers[] = {
{0x00, 0x00, 0x0C, "Cisco"},
{0x00, 0x00, 0x0E, "Fujitsu"},
{0x00, 0x00, 0x0F, "NeXT"},
{0x00, 0x00, 0x10, "Sytek"},
{0x00, 0x00, 0x1D, "Cabletron"},
{0x00, 0x00, 0x20, "DIAB"},
{0x00, 0x00, 0x22, "Visual Technology"},
{0x00, 0x00, 0x2A, "TRW"},
{0x00, 0x00, 0x32, "GPT Limited"},
{0x00, 0x00, 0x5A, "S & Koch"},
{0x00, 0x00, 0x5E, "IANA"},
{0x00, 0x00, 0x65, "Network General"},
{0x00, 0x00, 0x6B, "MIPS"},
{0x00, 0x00, 0x77, "MIPS"},
{0x00, 0x00, 0x7A, "Ardent"},
{0x00, 0x00, 0x89, "Cayman Systems"},
{0x00, 0x00, 0x93, "Proteon"},
{0x00, 0x00, 0x9F, "Ameristar Technology"},
{0x00, 0x00, 0xA2, "Wellfleet"},
{0x00, 0x00, 0xA3, "Network Application Technology"},
{0x00, 0x00, 0xA6, "Network General"},
{0x00, 0x00, 0xA7, "NCD"},
{0x00, 0x00, 0xA9, "Network Systems"},
{0x00, 0x00, 0xAA, "Xerox"},
{0x00, 0x00, 0xB3, "CIMLinc"},
{0x00, 0x00, 0xB7, "Dove Fastnet"},
{0x00, 0x00, 0xBC, "Allen-Bradley"},
{0x00, 0x00, 0xC0, "Western Digital"},
{0x00, 0x00, 0xC5, "Farallon"},
{0x00, 0x00, 0xC6, "Hewlett-Packard"},
{0x00, 0x00, 0xC8, "Altos"},
{0x00, 0x00, 0xC9, "Emulex"},
{0x00, 0x00, 0xD7, "Dartmouth College"},
{0x00, 0x00, 0xD8, "3Com (?)"},
{0x00, 0x00, 0xDD, "Gould"},
{0x00, 0x00, 0xDE, "Unigraph"},
{0x00, 0x00, 0xE2, "Acer Counterpoint"},
{0x00, 0x00, 0xEF, "Alantec"},
{0x00, 0x00, 0xFD, "High Level Hardware"},
{0x00, 0x01, 0x02, "BBN internal usage"},
{0x00, 0x20, 0xAF, "3Com"},
{0x00, 0x17, 0x00, "Kabel"},
{0x00, 0x80, 0x64, "Wyse Technology"},
{0x00, 0x80, 0x2B, "IMAC (?)"},
{0x00, 0x80, 0x2D, "Xylogics, Inc."},
{0x00, 0x80, 0x8C, "Frontier Software Development"},
{0x00, 0x80, 0xC2, "IEEE 802.1 Committee"},
{0x00, 0x80, 0xD3, "Shiva"},
{0x00, 0xAA, 0x00, "Intel"},
{0x00, 0xDD, 0x00, "Ungermann-Bass"},
{0x00, 0xDD, 0x01, "Ungermann-Bass"},
{0x02, 0x07, 0x01, "Racal InterLan"},
{0x02, 0x04, 0x06, "BBN internal usage"},
{0x02, 0x60, 0x86, "Satelcom MegaPac"},
{0x02, 0x60, 0x8C, "3Com"},
{0x02, 0xCF, 0x1F, "CMC"},
{0x08, 0x00, 0x02, "3Com"},
{0x08, 0x00, 0x03, "ACC"},
{0x08, 0x00, 0x05, "Symbolics"},
{0x08, 0x00, 0x08, "BBN"},
{0x08, 0x00, 0x09, "Hewlett-Packard"},
{0x08, 0x00, 0x0A, "Nestar Systems"},
{0x08, 0x00, 0x0B, "Unisys"},
{0x08, 0x00, 0x11, "Tektronix"},
{0x08, 0x00, 0x14, "Excelan"},
{0x08, 0x00, 0x17, "NSC"},
{0x08, 0x00, 0x1A, "Data General"},
{0x08, 0x00, 0x1B, "Data General"},
{0x08, 0x00, 0x1E, "Apollo"},
{0x08, 0x00, 0x20, "Sun"},
{0x08, 0x00, 0x22, "NBI"},
{0x08, 0x00, 0x25, "CDC"},
{0x08, 0x00, 0x26, "Norsk Data"},
{0x08, 0x00, 0x27, "PCS Computer Systems GmbH"},
{0x08, 0x00, 0x28, "Texas Instruments"},
{0x08, 0x00, 0x2B, "DEC"},
{0x08, 0x00, 0x2E, "Metaphor"},
{0x08, 0x00, 0x2F, "Prime Computer"},
{0x08, 0x00, 0x36, "Intergraph"},
{0x08, 0x00, 0x37, "Fujitsu-Xerox"},
{0x08, 0x00, 0x38, "Bull"},
{0x08, 0x00, 0x39, "Spider Systems"},
{0x08, 0x00, 0x41, "DCA Digital Comm. Assoc."},
{0x08, 0x00, 0x45, "Xylogics (?)"},
{0x08, 0x00, 0x46, "Sony"},
{0x08, 0x00, 0x47, "Sequent"},
{0x08, 0x00, 0x49, "Univation"},
{0x08, 0x00, 0x4C, "Encore"},
{0x08, 0x00, 0x4E, "BICC"},
{0x08, 0x00, 0x56, "Stanford University"},
{0x08, 0x00, 0x58, "DECsystem 20 (?)"},
{0x08, 0x00, 0x5A, "IBM"},
{0x08, 0x00, 0x67, "Comdesign"},
{0x08, 0x00, 0x68, "Ridge"},
{0x08, 0x00, 0x69, "Silicon Graphics"},
{0x08, 0x00, 0x6E, "Concurrent"},
{0x08, 0x00, 0x75, "DDE"},
{0x08, 0x00, 0x7C, "Vitalink"},
{0x08, 0x00, 0x80, "XIOS"},
{0x08, 0x00, 0x86, "Imagen/QMS"},
{0x08, 0x00, 0x87, "Xyplex"},
{0x08, 0x00, 0x89, "Kinetics"},
{0x08, 0x00, 0x8B, "Pyramid"},
{0x08, 0x00, 0x8D, "XyVision"},
{0x08, 0x00, 0x90, "Retix Inc"},
{0x48, 0x44, 0x53, "HDS (?)"},
{0x80, 0x00, 0x10, "AT&T"},
{0xAA, 0x00, 0x00, "DEC"},
{0xAA, 0x00, 0x01, "DEC"},
{0xAA, 0x00, 0x02, "DEC"},
{0xAA, 0x00, 0x03, "DEC"},
{0xAA, 0x00, 0x04, "DEC"},
{0x00, 0x00, 0x00, NULL}
};
/*
* Utility macros used for sorting and comparing:
......@@ -120,7 +203,7 @@ macaddr_in(char *str)
*/
char *
macaddr_out(macaddr * addr)
macaddr_out(macaddr *addr)
{
char *result;
......@@ -146,41 +229,41 @@ macaddr_out(macaddr * addr)
*/
bool
macaddr_lt(macaddr * a1, macaddr * a2)
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)
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)
macaddr_eq(macaddr *a1, macaddr *a2)
{
return ((hibits(a1) == hibits(a2)) && (lobits(a1) == lobits(a2)));
};
bool
macaddr_ge(macaddr * a1, macaddr * a2)
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)
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)
macaddr_ne(macaddr *a1, macaddr *a2)
{
return ((hibits(a1) != hibits(a2)) || (lobits(a1) != lobits(a2)));
};
......@@ -190,7 +273,7 @@ macaddr_ne(macaddr * a1, macaddr * a2)
*/
int4
macaddr_cmp(macaddr * a1, macaddr * a2)
macaddr_cmp(macaddr *a1, macaddr *a2)
{
if (hibits(a1) < hibits(a2))
return -1;
......@@ -209,7 +292,7 @@ macaddr_cmp(macaddr * a1, macaddr * a2)
*/
text *
macaddr_manuf(macaddr * addr)
macaddr_manuf(macaddr *addr)
{
manufacturer *manuf;
int length;
......@@ -238,7 +321,3 @@ macaddr_manuf(macaddr * addr)
}
return result;
}
/*
* eof
*/
......@@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_amop.h,v 1.15 1998/09/01 04:34:48 momjian Exp $
* $Id: pg_amop.h,v 1.16 1998/10/03 05:40:51 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -298,6 +298,26 @@ DATA(insert OID = 0 ( 403 1313 1330 3 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 1313 1335 4 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 1313 1334 5 btreesel btreenpage ));
/*
* nbtree macaddr
*/
DATA(insert OID = 0 ( 403 810 1222 1 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 810 1223 2 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 810 1220 3 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 810 1225 4 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 810 1224 5 btreesel btreenpage ));
/*
* nbtree ip
*/
DATA(insert OID = 0 ( 403 935 1203 1 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 935 1204 2 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 935 1201 3 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 935 1206 4 btreesel btreenpage ));
DATA(insert OID = 0 ( 403 935 1205 5 btreesel btreenpage ));
/*
* hash table _ops
*/
......
......@@ -9,7 +9,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_amproc.h,v 1.10 1998/09/01 04:34:49 momjian Exp $
* $Id: pg_amproc.h,v 1.11 1998/10/03 05:40:52 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -99,6 +99,8 @@ DATA(insert OID = 0 (403 1115 1107 1));
DATA(insert OID = 0 (403 1181 359 1));
DATA(insert OID = 0 (403 1312 1314 1));
DATA(insert OID = 0 (403 1313 1315 1));
DATA(insert OID = 0 (403 810 836 1));
DATA(insert OID = 0 (403 935 926 1));
/* hash */
......
......@@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_opclass.h,v 1.11 1998/09/01 04:35:06 momjian Exp $
* $Id: pg_opclass.h,v 1.12 1998/10/03 05:40:54 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -107,5 +107,9 @@ DATA(insert OID = 1312 ( datetime_ops 1184 ));
DESCR("");
DATA(insert OID = 1313 ( timespan_ops 1186 ));
DESCR("");
DATA(insert OID = 810 ( macaddr_ops 829 ));
DESCR("");
DATA(insert OID = 935 ( ipaddr_ops 869 ));
DESCR("");
#endif /* PG_OPCLASS_H */
......@@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_operator.h,v 1.38 1998/09/14 01:14:48 momjian Exp $
* $Id: pg_operator.h,v 1.39 1998/10/03 05:40:55 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -466,7 +466,7 @@ DATA(insert OID = 1094 ( "<>" PGUID 0 b t f 1082 1082 16 1094 1093 0 0 da
DATA(insert OID = 1095 ( "<" PGUID 0 b t f 1082 1082 16 1097 1098 0 0 date_lt intltsel intltjoinsel ));
DATA(insert OID = 1096 ( "<=" PGUID 0 b t f 1082 1082 16 1098 1097 0 0 date_le intltsel intltjoinsel ));
DATA(insert OID = 1097 ( ">" PGUID 0 b t f 1082 1082 16 1095 1096 0 0 date_gt intltsel intltjoinsel ));
DATA(insert OID = 1098 ( ">=" PGUID 0 b t f 1082 1082 16 1096 1065 0 0 date_ge intltsel intltjoinsel ));
DATA(insert OID = 1098 ( ">=" PGUID 0 b t f 1082 1082 16 1096 1095 0 0 date_ge intltsel intltjoinsel ));
DATA(insert OID = 1099 ( "-" PGUID 0 b t f 1082 1082 23 0 0 0 0 date_mi - - ));
DATA(insert OID = 1100 ( "+" PGUID 0 b t f 1082 23 1082 0 0 0 0 date_pli - - ));
DATA(insert OID = 1101 ( "-" PGUID 0 b t f 1082 23 1082 0 0 0 0 date_mii - - ));
......@@ -477,7 +477,7 @@ DATA(insert OID = 1109 ( "<>" PGUID 0 b t f 1083 1083 16 1109 1108 0 0 time
DATA(insert OID = 1110 ( "<" PGUID 0 b t f 1083 1083 16 1112 1113 0 0 time_lt intltsel intltjoinsel ));
DATA(insert OID = 1111 ( "<=" PGUID 0 b t f 1083 1083 16 1113 1112 0 0 time_le intltsel intltjoinsel ));
DATA(insert OID = 1112 ( ">" PGUID 0 b t f 1083 1083 16 1110 1111 0 0 time_gt intltsel intltjoinsel ));
DATA(insert OID = 1113 ( ">=" PGUID 0 b t f 1083 1083 16 1111 1065 0 0 time_ge intltsel intltjoinsel ));
DATA(insert OID = 1113 ( ">=" PGUID 0 b t f 1083 1083 16 1111 1110 0 0 time_ge intltsel intltjoinsel ));
/* float48 operators */
DATA(insert OID = 1116 ( "+" PGUID 0 b t f 700 701 701 1116 0 0 0 float48pl - - ));
......@@ -538,10 +538,10 @@ DATA(insert OID = 1305 ( ">=" PGUID 0 b t f 1296 1296 16 1304 1302 0 0 timest
/* name, owner, prec, kind, isleft, canhash, left, right, result, com, negate, lsortop, rsortop, oprcode, operrest, oprjoin */
DATA(insert OID = 1320 ( "=" PGUID 0 b t t 1184 1184 16 1320 1321 1322 1322 datetime_eq eqsel eqjoinsel ));
DATA(insert OID = 1321 ( "<>" PGUID 0 b t f 1184 1184 16 1321 1320 0 0 datetime_ne neqsel neqjoinsel ));
DATA(insert OID = 1322 ( "<" PGUID 0 b t f 1184 1184 16 1325 1325 0 0 datetime_lt intltsel intltjoinsel ));
DATA(insert OID = 1323 ( "<=" PGUID 0 b t f 1184 1184 16 1324 1324 0 0 datetime_le intltsel intltjoinsel ));
DATA(insert OID = 1324 ( ">" PGUID 0 b t f 1184 1184 16 1323 1323 0 0 datetime_gt intltsel intltjoinsel ));
DATA(insert OID = 1325 ( ">=" PGUID 0 b t f 1184 1184 16 1322 1322 0 0 datetime_ge intltsel intltjoinsel ));
DATA(insert OID = 1322 ( "<" PGUID 0 b t f 1184 1184 16 1324 1325 0 0 datetime_lt intltsel intltjoinsel ));
DATA(insert OID = 1323 ( "<=" PGUID 0 b t f 1184 1184 16 1325 1324 0 0 datetime_le intltsel intltjoinsel ));
DATA(insert OID = 1324 ( ">" PGUID 0 b t f 1184 1184 16 1322 1323 0 0 datetime_gt intltsel intltjoinsel ));
DATA(insert OID = 1325 ( ">=" PGUID 0 b t f 1184 1184 16 1323 1322 0 0 datetime_ge intltsel intltjoinsel ));
DATA(insert OID = 1327 ( "+" PGUID 0 b t f 1184 1186 1184 1327 0 0 0 datetime_pl_span - - ));
DATA(insert OID = 1328 ( "-" PGUID 0 b t f 1184 1184 1186 0 0 0 0 datetime_mi - - ));
......@@ -550,10 +550,10 @@ DATA(insert OID = 1329 ( "-" PGUID 0 b t f 1184 1186 1184 0 0 0 0 datetim
/* timespan operators */
DATA(insert OID = 1330 ( "=" PGUID 0 b t t 1186 1186 16 1330 1331 1332 1332 timespan_eq eqsel eqjoinsel ));
DATA(insert OID = 1331 ( "<>" PGUID 0 b t f 1186 1186 16 1331 1330 0 0 timespan_ne neqsel neqjoinsel ));
DATA(insert OID = 1332 ( "<" PGUID 0 b t f 1186 1186 16 1335 1335 0 0 timespan_lt intltsel intltjoinsel ));
DATA(insert OID = 1333 ( "<=" PGUID 0 b t f 1186 1186 16 1334 1334 0 0 timespan_le intltsel intltjoinsel ));
DATA(insert OID = 1334 ( ">" PGUID 0 b t f 1186 1186 16 1333 1333 0 0 timespan_gt intltsel intltjoinsel ));
DATA(insert OID = 1335 ( ">=" PGUID 0 b t f 1186 1186 16 1332 1332 0 0 timespan_ge intltsel intltjoinsel ));
DATA(insert OID = 1332 ( "<" PGUID 0 b t f 1186 1186 16 1334 1335 0 0 timespan_lt intltsel intltjoinsel ));
DATA(insert OID = 1333 ( "<=" PGUID 0 b t f 1186 1186 16 1335 1334 0 0 timespan_le intltsel intltjoinsel ));
DATA(insert OID = 1334 ( ">" PGUID 0 b t f 1186 1186 16 1332 1333 0 0 timespan_gt intltsel intltjoinsel ));
DATA(insert OID = 1335 ( ">=" PGUID 0 b t f 1186 1186 16 1333 1332 0 0 timespan_ge intltsel intltjoinsel ));
DATA(insert OID = 1336 ( "-" PGUID 0 l t f 0 1186 1186 0 0 0 0 timespan_um 0 0 ));
DATA(insert OID = 1337 ( "+" PGUID 0 b t f 1186 1186 1186 1337 0 0 0 timespan_pl - - ));
......@@ -563,10 +563,10 @@ DATA(insert OID = 1338 ( "-" PGUID 0 b t f 1186 1186 1186 0 0 0 0 timespa
DATA(insert OID = 1420 ( "@@" PGUID 0 l t f 0 718 600 0 0 0 0 circle_center - - ));
DATA(insert OID = 1500 ( "=" PGUID 0 b t t 718 718 16 1500 1501 1502 1502 circle_eq eqsel eqjoinsel ));
DATA(insert OID = 1501 ( "<>" PGUID 0 b t f 718 718 16 1501 1500 0 0 circle_ne neqsel neqjoinsel ));
DATA(insert OID = 1502 ( "<" PGUID 0 b t f 718 718 16 0 0 0 0 circle_lt areasel areajoinsel ));
DATA(insert OID = 1503 ( ">" PGUID 0 b t f 718 718 16 0 0 0 0 circle_gt areasel areajoinsel ));
DATA(insert OID = 1504 ( "<=" PGUID 0 b t f 718 718 16 0 0 0 0 circle_le areasel areajoinsel ));
DATA(insert OID = 1505 ( ">=" PGUID 0 b t f 718 718 16 0 0 0 0 circle_ge areasel areajoinsel ));
DATA(insert OID = 1502 ( "<" PGUID 0 b t f 718 718 16 1503 1505 0 0 circle_lt areasel areajoinsel ));
DATA(insert OID = 1503 ( ">" PGUID 0 b t f 718 718 16 1502 1504 0 0 circle_gt areasel areajoinsel ));
DATA(insert OID = 1504 ( "<=" PGUID 0 b t f 718 718 16 1505 1503 0 0 circle_le areasel areajoinsel ));
DATA(insert OID = 1505 ( ">=" PGUID 0 b t f 718 718 16 1504 1502 0 0 circle_ge areasel areajoinsel ));
DATA(insert OID = 1506 ( "<<" PGUID 0 b t f 718 718 16 0 0 0 0 circle_left intltsel intltjoinsel ));
DATA(insert OID = 1507 ( "&<" PGUID 0 b t f 718 718 16 0 0 0 0 circle_overleft intltsel intltjoinsel ));
......@@ -635,6 +635,27 @@ DATA(insert OID = 1615 ( "?|" PGUID 0 l t f 0 628 16 1615 0 0 0 line_ver
DATA(insert OID = 1616 ( "=" PGUID 0 b t f 628 628 16 1616 0 0 0 line_eq intltsel - ));
DATA(insert OID = 1617 ( "#" PGUID 0 b t f 628 628 600 1617 0 0 0 line_interpt - - ));
/* MAC type */
DATA(insert OID = 1220 ( "=" PGUID 0 b t t 829 829 16 1220 1221 0 0 macaddr_eq eqsel eqjoinsel ));
DATA(insert OID = 1221 ( "<>" PGUID 0 b t f 829 829 16 1221 1220 0 0 macaddr_ne neqsel neqjoinsel ));
DATA(insert OID = 1222 ( "<" PGUID 0 b t f 829 829 16 1224 1225 0 0 macaddr_lt intltsel intltjoinsel ));
DATA(insert OID = 1223 ( "<=" PGUID 0 b t f 829 829 16 1225 1224 0 0 macaddr_le intltsel intltjoinsel ));
DATA(insert OID = 1224 ( ">" PGUID 0 b t f 829 829 16 1222 1223 0 0 macaddr_gt intltsel intltjoinsel ));
DATA(insert OID = 1225 ( ">=" PGUID 0 b t f 829 829 16 1223 1222 0 0 macaddr_ge intltsel intltjoinsel ));
/* IP type */
DATA(insert OID = 1201 ( "=" PGUID 0 b t t 869 869 16 1201 1202 0 0 ipaddr_eq eqsel eqjoinsel ));
DATA(insert OID = 1202 ( "<>" PGUID 0 b t f 869 869 16 1202 1201 0 0 ipaddr_ne neqsel neqjoinsel ));
DATA(insert OID = 1203 ( "<" PGUID 0 b t f 869 869 16 1205 1206 0 0 ipaddr_lt intltsel intltjoinsel ));
DATA(insert OID = 1204 ( "<=" PGUID 0 b t f 869 869 16 1206 1205 0 0 ipaddr_le intltsel intltjoinsel ));
DATA(insert OID = 1205 ( ">" PGUID 0 b t f 869 869 16 1203 1204 0 0 ipaddr_gt intltsel intltjoinsel ));
DATA(insert OID = 1206 ( ">=" PGUID 0 b t f 869 869 16 1204 1203 0 0 ipaddr_ge intltsel intltjoinsel ));
DATA(insert OID = 931 ( "<<" PGUID 0 b t f 869 869 16 933 934 0 0 ipaddr_sub intltsel intltjoinsel ));
DATA(insert OID = 932 ( "<<=" PGUID 0 b t f 869 869 16 934 933 0 0 ipaddr_subeq intltsel intltjoinsel ));
DATA(insert OID = 933 ( ">>" PGUID 0 b t f 869 869 16 931 932 0 0 ipaddr_sup intltsel intltjoinsel ));
DATA(insert OID = 934 ( ">>=" PGUID 0 b t f 869 869 16 932 931 0 0 ipaddr_supeq intltsel intltjoinsel ));
/*
* function prototypes
*/
......
......@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_proc.h,v 1.70 1998/10/02 16:27:55 momjian Exp $
* $Id: pg_proc.h,v 1.71 1998/10/03 05:40:56 momjian Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -2045,6 +2045,59 @@ DESCR("user name by UID (with fallback)");
DATA(insert OID = 1643 ( pg_get_indexdef PGUID 11 f t f 1 f 25 "26" 100 0 0 100 foo bar ));
DESCR("index description");
/* for mac type support */
DATA(insert OID = 436 ( macaddr_in PGUID 11 f t f 1 f 829 "0" 100 0 0 100 foo bar ));
DESCR("(internal)");
DATA(insert OID = 437 ( macaddr_out PGUID 11 f t f 1 f 23 "0" 100 0 0 100 foo bar ));
DESCR("(internal)");
DATA(insert OID = 830 ( macaddr_eq PGUID 11 f t f 2 f 16 "829 829" 100 0 0 100 foo bar ));
DESCR("equal");
DATA(insert OID = 831 ( macaddr_lt PGUID 11 f t f 2 f 16 "829 829" 100 0 0 100 foo bar ));
DESCR("less-than");
DATA(insert OID = 832 ( macaddr_le PGUID 11 f t f 2 f 16 "829 829" 100 0 0 100 foo bar ));
DESCR("less-than-or-equal");
DATA(insert OID = 833 ( macaddr_gt PGUID 11 f t f 2 f 16 "829 829" 100 0 0 100 foo bar ));
DESCR("greater-than");
DATA(insert OID = 834 ( macaddr_ge PGUID 11 f t f 2 f 16 "829 829" 100 0 0 100 foo bar ));
DESCR("greater-than-or-equal");
DATA(insert OID = 835 ( macaddr_ne PGUID 11 f t f 2 f 16 "829 829" 100 0 0 100 foo bar ));
DESCR("not equal");
DATA(insert OID = 836 ( macaddr_cmp PGUID 11 f t f 2 f 23 "829 829" 100 0 0 100 foo bar ));
DESCR("less-equal-greater");
DATA(insert OID = 837 ( macaddr_manuf PGUID 11 f t f 1 f 25 "829" 100 0 0 100 foo bar ));
DESCR("MAC manufacturer");
/* for ip type support */
DATA(insert OID = 910 ( ipaddr_in PGUID 11 f t f 1 f 869 "0" 100 0 0 100 foo bar ));
DESCR("(internal)");
DATA(insert OID = 911 ( ipaddr_out PGUID 11 f t f 1 f 23 "0" 100 0 0 100 foo bar ));
DESCR("(internal)");
DATA(insert OID = 920 ( ipaddr_eq PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("equal");
DATA(insert OID = 921 ( ipaddr_lt PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("less-than");
DATA(insert OID = 922 ( ipaddr_le PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("less-than-or-equal");
DATA(insert OID = 923 ( ipaddr_gt PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("greater-than");
DATA(insert OID = 924 ( ipaddr_ge PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("greater-than-or-equal");
DATA(insert OID = 925 ( ipaddr_ne PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("not equal");
DATA(insert OID = 926 ( ipaddr_cmp PGUID 11 f t f 2 f 23 "869 869" 100 0 0 100 foo bar ));
DESCR("less-equal-greater");
DATA(insert OID = 927 ( ipaddr_sub PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("is-subnet");
DATA(insert OID = 928 ( ipaddr_subeq PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("is-subnet-or-equal");
DATA(insert OID = 929 ( ipaddr_sup PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("is-supernet");
DATA(insert OID = 930 ( ipaddr_supeq PGUID 11 f t f 2 f 16 "869 869" 100 0 0 100 foo bar ));
DESCR("is-supernet-or-equal");
/*
* prototypes for functions pg_proc.c
*/
......
......@@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_type.h,v 1.47 1998/09/01 04:35:18 momjian Exp $
* $Id: pg_type.h,v 1.48 1998/10/03 05:40:58 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -298,6 +298,10 @@ DESCR("money '$d,ddd.cc'");
DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i _null_ ));
/* OIDS 800 - 899 */
DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i _null_ ));
DESCR("MAC address");
DATA(insert OID = 869 ( ipaddr PGUID -1 -1 f b t \054 0 0 ipaddr_in ipaddr_out ipaddr_in ipaddr_out i _null_ ));
DESCR("IP address");
/* OIDS 900 - 999 */
......@@ -333,8 +337,9 @@ DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array
/* Note: the size of an aclitem needs to match sizeof(AclItem) in acl.h */
DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i _null_ ));
DESCR("access control list");
DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i _null_ ));
DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i _null_ ));
DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i _null_ ));
DATA(insert OID = 1041 ( _ipaddr PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i _null_ ));
DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 18 bpcharin bpcharout bpcharin bpcharout i _null_ ));
DESCR("blank-padded characters, length specifed when created");
#define BPCHAROID 1042
......
......@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.55 1998/09/22 20:28:13 momjian Exp $
* $Id: builtins.h,v 1.56 1998/10/03 05:40:59 momjian Exp $
*
* NOTES
* This should normally only be included by fmgr.h.
......@@ -28,6 +28,7 @@
#include <utils/nabstime.h>
#include <utils/int8.h>
#include <utils/cash.h>
#include <utils/mac.h>
#include <utils/rel.h>
/*
......@@ -511,4 +512,40 @@ extern text *translate(text *string, char from, char to);
/* acl.c */
/* inet_net_ntop.c */
char *inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size);
/* inet_net_pton.c */
int inet_net_pton(int af, const char *src, void *dst, size_t size);
/* ip.c */
ipaddr *ipaddr_in(char *str);
char *ipaddr_out(ipaddr * addr);
bool ipaddr_lt(ipaddr * a1, ipaddr * a2);
bool ipaddr_le(ipaddr * a1, ipaddr * a2);
bool ipaddr_eq(ipaddr * a1, ipaddr * a2);
bool ipaddr_ge(ipaddr * a1, ipaddr * a2);
bool ipaddr_gt(ipaddr * a1, ipaddr * a2);
bool ipaddr_ne(ipaddr * a1, ipaddr * a2);
bool ipaddr_sub(ipaddr * a1, ipaddr * a2);
bool ipaddr_subeq(ipaddr * a1, ipaddr * a2);
bool ipaddr_sup(ipaddr * a1, ipaddr * a2);
bool ipaddr_supeq(ipaddr * a1, ipaddr * a2);
int4 ipaddr_cmp(ipaddr * a1, ipaddr * a2);
int v4bitncmp(u_int32_t a1, u_int32_t a2, int bits);
/* mac.c */
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);
text *macaddr_manuf(macaddr * addr);
#endif /* BUILTINS_H */
/*-------------------------------------------------------------------------
*
* builtins.h--
* Declarations for operations on built-in types.
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: mac.h,v 1.1 1998/10/03 05:41:01 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef MAC_H
#define MAC_H
/*
* This is the internal storage format for IP addresses:
*/
typedef struct
{
unsigned char family;
unsigned char bits;
union
{
u_int32_t ipv4_addr; /* network byte order */
/* add IPV6 address type here */
} addr;
} ipaddr_struct;
typedef struct varlena ipaddr;
/*
* This is the internal storage format for MAC addresses:
*/
typedef struct macaddr
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
unsigned char e;
unsigned char f;
} macaddr;
typedef struct manufacturer
{
unsigned char a;
unsigned char b;
unsigned char c;
char *name;
} manufacturer;
extern manufacturer manufacturers[];
#endif /* MAC_H */
......@@ -786,6 +786,8 @@ do
-Tword8 \
-Tyy_size_t \
-Tyy_state_type \
-Tipaddr \
-Tmacaddr \
/tmp/$$a >/tmp/$$ 2>&1
if [ "$?" -ne 0 -o -s /tmp/$$ ]
then echo "$FILE"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册