diff options
author | Bruce Momjian <bruce@momjian.us> | 1998-06-16 04:34:30 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1998-06-16 04:34:30 +0000 |
commit | 92da1c3a6a78f9ae858e366b8187cdcf699dcad2 (patch) | |
tree | bb5509e83b1f673a3691e0a8ee118b51fcc20ee5 /contrib/ip_and_mac/ip.c | |
parent | 583891833ff102b805a752ded0ad38bb8087dcf9 (diff) | |
download | postgresql-92da1c3a6a78f9ae858e366b8187cdcf699dcad2.tar.gz postgresql-92da1c3a6a78f9ae858e366b8187cdcf699dcad2.zip |
I investigated carefully POSTGRES data base (in idea to use it for
our internal IP routing data base, and because I have participated
in Ingres development here in Russia in RUBIN/DEMOS project -
through it was not freeware work - and it was very interesting for
me too see such good freeware data base as PostgreSQL), and I
modified 'ipaddr' data type library in accordance to our requests
and to allow SQL do indexing over ipaddr objects.
You can read description at 'http://relcom.EU.net/ipaddr.html' and
get sources at 'http://relcom.EU.net/ip_class.tar.gz'. It contains
sources, sql scripts for incorporating new data type into postgres
(including ipaddr_ops operator class incorporation) and 20,000
records based data test for the indexing.
I am not sure if it's proper mail list for this information, and
if it's interesting for anyone except me to get full-functional
ipaddress class. I am ready to make all modifications, bug fixing
and documentation for this data class if it's nessesary for it's
contribution to the Postgres data base.
Anyway, all my work was based at original 'ip&mac data type'
contribution, written by Tom Ivar Helbekkmo.
Be free to write me any questions or requests about this work.
==============================================================
Aleksei Roudnev, Network Operations Center, Relcom, Moscow (+7 095)
194-19-95 (Network Operations Center Hot Line),(+7 095) 239-10-10,
N 13729 (pager) (+7 095) 196-72-12 (Support), (+7 095) 194-33-28
(Fax)
Diffstat (limited to 'contrib/ip_and_mac/ip.c')
-rw-r--r-- | contrib/ip_and_mac/ip.c | 231 |
1 files changed, 211 insertions, 20 deletions
diff --git a/contrib/ip_and_mac/ip.c b/contrib/ip_and_mac/ip.c index b0320bae38d..e9aaba3b8e3 100644 --- a/contrib/ip_and_mac/ip.c +++ b/contrib/ip_and_mac/ip.c @@ -1,7 +1,7 @@ /* * PostgreSQL type definitions for IP addresses. * - * $Id: ip.c,v 1.3 1998/02/26 04:27:37 momjian Exp $ + * $Id: ip.c,v 1.4 1998/06/16 04:34:29 momjian Exp $ */ #include <stdio.h> @@ -81,10 +81,18 @@ ipaddr_in(char *str) elog(ERROR, "ipaddr_in: error in parsing \"%s\"", str); return (NULL); } - + if ( count == 3 ) { + d = 0; + count = 4; + }; if (count == 4) + { w = 32; - + if ( a >= 192 && a < 224 && d == 0 ) w = 24; + if ( a >= 128 && a < 192 && d == 0 && c == 0 ) w = 16; + if ( a > 0 && a < 128 && c == 0 && b == 0 && a < 128 ) w = 8; + if ( a == 0 && b == 0 && c == 0 && d == 0 ) w = 0; + }; if ((a < 0) || (a > 255) || (b < 0) || (b > 255) || (c < 0) || (c > 255) || (d < 0) || (d > 255) || (w < 0) || (w > 32)) @@ -95,13 +103,12 @@ ipaddr_in(char *str) } else { - a = b = c = d = w = 0; /* special case for missing address */ + a = b = c = d = w = 255; /* special case for missing address */ } result = (ipaddr *) palloc(sizeof(ipaddr)); result->address = (uint32) ((a << 24) | (b << 16) | (c << 8) | d); - result->address &= build_mask(w); result->width = w; return (result); @@ -116,27 +123,30 @@ char * ipaddr_out(ipaddr * addr) { char *result; - + int a, b, c, d, w; if (addr == NULL) return (NULL); result = (char *) palloc(32); - if (addr->address > 0) + w = addr->width; + a = (addr->address >> 24) & 0xff; + b = (addr->address >> 16) & 0xff; + c = (addr->address >> 8) & 0xff; + d = (addr->address >> 0) & 0xff; + /* Check by missing address (w > 32 ) */ + if ( w >= 0 && w <= 32 ) { - if (addr->width == 32) - sprintf(result, "%d.%d.%d.%d", - (addr->address >> 24) & 0xff, - (addr->address >> 16) & 0xff, - (addr->address >> 8) & 0xff, - addr->address & 0xff); + /* In case of NATURAL network don't output the prefix */ + if ( (a == 0 && b == 0 && c == 0 && d == 0 && w == 0 ) || + (a < 128 && b == 0 && c == 0 && d == 0 && w == 8 ) || + (a < 192 && c == 0 && d == 0 && w == 16 ) || + (a < 224 && d == 0 && w == 24 ) || + ( d != 0 ) ) w = -1; + if (w == -1 ) + sprintf(result, "%d.%d.%d.%d",a,b,c,d); else - sprintf(result, "%d.%d.%d.%d/%d", - (addr->address >> 24) & 0xff, - (addr->address >> 16) & 0xff, - (addr->address >> 8) & 0xff, - addr->address & 0xff, - addr->width); + sprintf(result, "%d.%d.%d.%d/%d",a,b,c,d,w); } else { @@ -146,42 +156,109 @@ ipaddr_out(ipaddr * addr) } /* + * 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); }; @@ -197,7 +274,42 @@ ipaddr_cmp(ipaddr * a1, ipaddr * a2) else if (a1->address > a2->address) return 1; else - return 0; + { + if (a1->width < a2->width) + return -1; + else if (a1->width > a2->width) + return 1; + } + return 0; +} + +/* + * The number of hosts in the network + */ +int4 +ipaddr_len(ipaddr * a) +{ + if ( a->width > 32 || a->width < 0 ) return(0); + return(1 << (32 - a->width)); +} + +/* + * The number of network bits + */ +int4 +ipaddr_pref(ipaddr * a) +{ + if ( a->width > 32 || a->width < 0 ) return(0); + return(a->width); +} + +/* + * The host addr as an integer + */ +int4 +ipaddr_integer(ipaddr * a) +{ + return(a->address); } /* @@ -220,6 +332,23 @@ ipaddr_in_net(ipaddr * a1, ipaddr * a2) } /* + * 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: */ @@ -253,5 +382,67 @@ ipaddr_bcast(ipaddr * a) } /* + * 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 */ |