## New object class for the IP ADDRESSES manipulations.

### 1. Description:

Type name: ipaddr
Data lenght: 6 bytes
Data context: ip address and prefix length

### 2. How to install:

Use script ip.sql to add new type, new functions and operators to the data base.

Use script ipi.sql to add new type and new operator class ipaddr_ops to the index system and allow indexing by this new type (with search by '>', '>=', '<', '<=', '=' boolean operators).

Use scripts 'test1.sql' and 'test2.sql' (edit second script first) to check if indexing work properly.

### 3. Input / output formsts.

New type stores IP address and IP prefix in the single data attribute. To input data, you should use the form

DDD.DDD.DDD.DDD/PP

for the address DDD.DDD.DDD.DDD and prefix PP (prefix is len from 0 (for 0.0.0.0) to 32 (for 255.255.255.255)). You can miss /PP n two cases:

- You enter host address (this means /32 prefix) and this is not the address of the natural class A, B or C network.
- You enter natural class A, B, C network with the /8, /16 and /24 prefix.

For example, 193.124.23.0 should be read as '193.124.23.0/24' network, and '193.124.23.1' should be read as /32 host address. To enter interface address 193.124.23.6/24, you should use exact form '193.124.23.6/24'.

The address '0.0.0.0' means '0.0.0.0/0', this is default in terms of routers.

ipaddr type data are printed just in the same form (to allow input/output compatibility) - 193.124.23.0/24 should be printed as '193.124.23.0' and '193.124.23.1/32' should be printed as '193.124.23.1'.

There is special function to convert ipaddr data into string by the format:

char ipaddr_print(ipaddr,format)

format consist of plain text and %C special characters:

%A - address in form ddd.ddd.ddd.ddd,
%M - network mask in form ddd.ddd.ddd.ddd,
%B - negated mask ('0.0.0.7' for '/29' prefix, for example),
%P - prefix (withouth '/' delimiter).

### 4. Operators.

Left argument A1 | Op | Right argument A2 | Result R | Description
ipaddr | < | ipaddr | boolean | Compare addresses, if they are equal, compare prefixes,
ipaddr | <= | ipaddr | boolean | Compare addresses, if they are equal, compare prefixes,
ipaddr | = | ipaddr | boolean | Compare addresses, if they are equal, compare prefixes,
ipaddr | >= | ipaddr | boolean | Compare addresses, if they are equal, compare prefixes,
ipaddr | > | ipaddr | boolean | Compare addresses, if they are equal, compare prefixes,
ipaddr | <> | ipaddr | boolean | Compare addresses, if they are equal, compare prefixes,
ipaddr | @ | ipaddr | boolean | True if A1 is the part of network (subnetwork) A2 or if A1 = A2
ipaddr | + | int4 | ipaddr | Increase address A1 on A2 value (A2 is integer).
ipaddr | - | int4 | ipaddr | Decrease address A1 on A2.

### 5. Functions.

There is a lot of functions defined for new ipaddr data type. Some of them are duplicated by operators described above, some are not.

Function(arguments) | Function type | Description | Operator
ipaddr_print(ipaddr, text) | text | 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. |
ipaddr_lt(ipaddr, ipaddr) | boolean | Compare by '<' | <
ipaddr_le(ipaddr,ipaddr) | boolean | Compare by '<=' | <=
ipaddr_eq(ipaddr, ipaddr) | boolean | Compare by '=' | =
ipaddr_ne(ipaddr, ipaddr) | boolean | Compare by '<>' | <>
ipaddr_ge(ipaddr, ipaddr) | boolean | Compare by '>=' | >=
ipaddr_gt(ipaddr, ipaddr) | boolean | Compare by '>' | >
ipaddr_in_net(ipaddr, ipaddr) | boolean | True if fisrt argument is the host or subnetwork of the second argument (first address is equal or included into the second one) | @
ipaddr_net(ipaddr) | ipaddr | 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'; |
ipaddr_bcast(ipaddr) | ipaddr | Return broadcast address (with the /32 prefix) for the network described by argument. |
ipaddr_is_net(ipaddr) | boolean | True if ipaddr is network address; false if its' the host in the network. For the /32 addresses, returns false. |
ipaddr_mask(ipaddr) | ipaddr | Return netmask (with /32 prefix) for the network. |
ipaddr_prefix(ipaddr) | int4 | Return the prefix size (from 0 to 32). |
ipaddr_len(ipaddr) | int4 | Return the number of addresses in the particular network (for example, 256 for /24 prefix). |
ipaddr_integer(ipaddr) | int4 | Return IP address (withouth the prefix) as integer. |
ipaddr_compose(int4,int4) | ipaddr | Compose ipaddr object from ip address (first argument) and prefix lenght (second argument). ipaddr_compose(ipaddr_integer(a),ipaddr_prefix(a)) = a. |
ipaddr_plus(ipaddr, int4) | ipaddr | Operator PLUS (addres increased, prefix does not changed) | +
ipaddr_minus(ipaddr, int4) | ipaddr | Operator MINUS (address decreased, prefix does not changed). | -
ipaddr_cmp(ipaddr, ipaddr) | int4 | Compare it's arguments and return -1, 0 or +1. |

### 5. Usage.

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.

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.

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.

### 6. Installation.

1. Translate shared library ip.so:
   make
2. Install shared library to the proper place (/usr/local/pgsql/contrib/ip_and_macs)
   make install
   (in case if your system is not FreeBSD, it can be nessesary modify 'Makefile' before).
3. 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.
4. To add new data type into your data base, exec scripts in this data base:
   psql DATA_BASE
   \i ip.sql -- change this to the real location
   \i ipi.sql -- change this to the real location
5. To test this data type, exec test1.sql and test2.sql SQL scripts.

### 7. Download.

You can download this data type from http://relcom.EU.net/ip_class.tar.gz

###

Aleksei Roudnev, The Network Operation Centre, Relcom Network; Moscow, Russia.