I've been meaning to send it in for a while now, IMHO it could be
made part of the main distribution as well, but contrib is fine
if not everyone likes it.

I included the source in patch-format, since I didn't feel comfortable
attaching a tar.gz file on this list.
Below is an excerpt from the included README:
-------------------------------- cut here ---------------------------------
inet extended operations
~~~~~~~~~~~~~~~~~~~~~~~~

This directory contains definitions for extended operators on the
inet data type.

Operators available are:

   ~ & | + -

It supports the "natural" arithmetic with IP addresses and integers.
It is useful for applications which have to hand out and administer
ranges of IP-addresses (like a Radius or DHCP server).

Copyright (c) 2003-2006, Stephen R. van den Berg, The Netherlands.
                         <[EMAIL PROTECTED]>

This module is distributed under the same BSD license as PostgreSQL.
-------------------------------- cut here ---------------------------------

diff -ur xinetops.old/Makefile xinetops/Makefile
--- xinetops.old/Makefile       2005-11-13 12:36:39.000000000 +0100
+++ xinetops/Makefile   2005-11-13 12:45:04.000000000 +0100
@@ -0,0 +1,11 @@
+# $Id: Makefile 523 2005-11-13 11:29:44Z srb $
+
+subdir = contrib/xinetops
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+
+MODULES = xinetops
+DATA_built = xinetops.sql
+DOCS = README.xinetops
+
+include $(top_srcdir)/contrib/contrib-global.mk
diff -ur xinetops.old/README.xinetops xinetops/README.xinetops
--- xinetops.old/README.xinetops        2005-11-13 12:36:39.000000000 +0100
+++ xinetops/README.xinetops    2005-11-13 12:45:04.000000000 +0100
@@ -0,0 +1,19 @@
+
+inet extended operations
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+This directory contains definitions for extended operators on the
+inet data type.
+
+Operators available are:
+
+   ~ & | + -
+
+It supports the "natural" arithmetic with IP addresses and integers.
+It is useful for applications which have to hand out and administer
+ranges of IP-addresses (like a Radius or DHCP server).
+
+Copyright (c) 2003-2006, Stephen R. van den Berg, The Netherlands.
+                        <[EMAIL PROTECTED]>
+
+This module is distributed under the same BSD license as PostgreSQL.
diff -ur xinetops.old/xinetops.c xinetops/xinetops.c
--- xinetops.old/xinetops.c     2005-11-13 12:36:39.000000000 +0100
+++ xinetops/xinetops.c 2005-11-13 12:45:04.000000000 +0100
@@ -0,0 +1,254 @@
+/*
+ *     PostgreSQL type definitions for extended inet operations.
+ *     Copyright (c) 2003-2006, S.R. van den Berg, The Netherlands
+ *                              <[EMAIL PROTECTED]>
+ *
+ *      This module is distributed under the same BSD license as PostgreSQL.
+ *
+ *     $Id: xinetops.c 524 2005-11-13 11:44:43Z srb $
+ */
+
+#include "postgres.h"
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "catalog/pg_type.h"
+#include "utils/builtins.h"
+#include "utils/inet.h"
+
+#define ip_family(inetptr) \
+        (((inet_struct *)VARDATA(inetptr))->family)
+
+#define ip_bits(inetptr) \
+        (((inet_struct *)VARDATA(inetptr))->bits)
+
+#define ip_type(inetptr) \
+        (((inet_struct *)VARDATA(inetptr))->type)
+
+#define ip_addr(inetptr) \
+        (((inet_struct *)VARDATA(inetptr))->ipaddr)
+
+static int
+ip_addrsize(inet *inetptr)
+{
+        switch (ip_family(inetptr))
+        {
+                case PGSQL_AF_INET:
+                        return 4;
+                case PGSQL_AF_INET6:
+                        return 16;
+                default:
+                        return -1;
+        }
+}
+
+
+PG_FUNCTION_INFO_V1(inet_not);
+
+Datum
+inet_not(PG_FUNCTION_ARGS)
+{
+       inet       *ip = PG_GETARG_INET_P(0);
+       inet       *dst;
+
+       dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
+       /* make sure any unused bits are zeroed */
+       MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
+
+        {
+              int nb = ip_addrsize(ip);
+              unsigned char*pip = ip_addr(ip);
+              unsigned char*pdst = ip_addr(dst);
+
+              while (nb-->0)
+              {
+                   pdst[nb] = pip[nb];
+              }
+        }
+       ip_bits(dst) = ip_bits(ip);
+
+       ip_family(dst) = ip_family(ip);
+       ip_type(dst) = 0;
+       VARATT_SIZEP(dst) = VARHDRSZ
+               + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+               + ip_addrsize(dst);
+
+       PG_RETURN_INET_P(dst);
+}
+
+PG_FUNCTION_INFO_V1(inet_or);
+
+Datum
+inet_or(PG_FUNCTION_ARGS)
+{
+       inet       *ip = PG_GETARG_INET_P(0);
+       inet       *ip2 = PG_GETARG_INET_P(1);
+       inet       *dst;
+
+       dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
+       /* make sure any unused bits are zeroed */
+       MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
+
+       if (ip_family(ip) != ip_family(ip2))
+               elog(ERROR, "mismatch in address family (%d)!=(%d)",
+                               ip_family(ip), ip_family(ip2));
+       else
+        {
+              int nb = ip_addrsize(ip);
+              unsigned char*pip = ip_addr(ip);
+              unsigned char*pip2 = ip_addr(ip2);
+              unsigned char*pdst = ip_addr(dst);
+
+              while (nb-->0)
+              {
+                   pdst[nb] = pip[nb]|pip2[nb];
+              }
+        }
+       ip_bits(dst) = ip_bits(ip);
+       if (ip_bits(dst)<ip_bits(ip2))
+               ip_bits(dst) = ip_bits(ip2);
+
+       ip_family(dst) = ip_family(ip);
+       ip_type(dst) = 0;
+       VARATT_SIZEP(dst) = VARHDRSZ
+               + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+               + ip_addrsize(dst);
+
+       PG_RETURN_INET_P(dst);
+}
+
+PG_FUNCTION_INFO_V1(inet_and);
+
+Datum
+inet_and(PG_FUNCTION_ARGS)
+{
+       inet       *ip = PG_GETARG_INET_P(0);
+       inet       *ip2 = PG_GETARG_INET_P(1);
+       inet       *dst;
+
+       dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
+       /* make sure any unused bits are zeroed */
+       MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
+
+       if (ip_family(ip) != ip_family(ip2))
+               elog(ERROR, "mismatch in address family (%d)!=(%d)",
+                               ip_family(ip), ip_family(ip2));
+       else
+        {
+              int nb = ip_addrsize(ip);
+              unsigned char*pip = ip_addr(ip);
+              unsigned char*pip2 = ip_addr(ip2);
+              unsigned char*pdst = ip_addr(dst);
+
+              while (nb-->0)
+              {
+                   pdst[nb] = pip[nb]&pip2[nb];
+              }
+        }
+       ip_bits(dst) = ip_bits(ip);
+       if (ip_bits(dst)<ip_bits(ip2))
+               ip_bits(dst) = ip_bits(ip2);
+
+       ip_family(dst) = ip_family(ip);
+       ip_type(dst) = 0;
+       VARATT_SIZEP(dst) = VARHDRSZ
+               + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+               + ip_addrsize(dst);
+
+       PG_RETURN_INET_P(dst);
+}
+
+PG_FUNCTION_INFO_V1(inet_min);
+
+Datum
+inet_min(PG_FUNCTION_ARGS)
+{
+       inet       *ip = PG_GETARG_INET_P(0);
+       inet       *ip2 = PG_GETARG_INET_P(1);
+       int        res = 0;
+
+       if (ip_family(ip) != ip_family(ip2))
+               elog(ERROR, "mismatch in address family (%d)!=(%d)",
+                               ip_family(ip), ip_family(ip2));
+       else
+        {
+              int nb = ip_addrsize(ip);
+              unsigned char*pip = ip_addr(ip);
+              unsigned char*pip2 = ip_addr(ip2);
+              unsigned sh = 1;
+
+              while (nb-->0)
+              {
+                   res += sh*(pip[nb]-pip2[nb]);
+                   sh <<= 8;
+              }
+        }
+
+       PG_RETURN_INT32(res);
+}
+
+static Datum
+i_inet_plusi(inet *ip, int iarg)
+{
+       inet       *dst;
+
+       dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
+       /* make sure any unused bits are zeroed */
+       MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
+
+        {
+              int nb = ip_addrsize(ip);
+              unsigned char*pip = ip_addr(ip);
+              unsigned char*pdst = ip_addr(dst);
+              int carry = 0;
+
+              while (nb-->0)
+              {
+                   pdst[nb] = carry = pip[nb]+iarg+carry;
+                   iarg >>=8;
+                   carry >>=8;
+              }
+        }
+        ip_bits(dst) = ip_bits(ip);
+
+       ip_family(dst) = ip_family(ip);
+       ip_type(dst) = 0;
+       VARATT_SIZEP(dst) = VARHDRSZ
+               + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+               + ip_addrsize(dst);
+
+       PG_RETURN_INET_P(dst);
+}
+
+PG_FUNCTION_INFO_V1(inet_plusi);
+
+Datum
+inet_plusi(PG_FUNCTION_ARGS)
+{
+       inet       *ip = PG_GETARG_INET_P(0);
+       int        iarg = PG_GETARG_INT32(1);
+       return i_inet_plusi(ip,iarg);
+}
+
+PG_FUNCTION_INFO_V1(inet_iplus);
+
+Datum
+inet_iplus(PG_FUNCTION_ARGS)
+{
+       int        iarg = PG_GETARG_INT32(0);
+       inet       *ip = PG_GETARG_INET_P(1);
+       return i_inet_plusi(ip,iarg);
+}
+
+PG_FUNCTION_INFO_V1(inet_mini);
+
+Datum
+inet_mini(PG_FUNCTION_ARGS)
+{
+       inet       *ip = PG_GETARG_INET_P(0);
+       int        iarg = PG_GETARG_INT32(1);
+       return i_inet_plusi(ip,-iarg);
+}
diff -ur xinetops.old/xinetops.sql.in xinetops/xinetops.sql.in
--- xinetops.old/xinetops.sql.in        2005-11-13 12:36:39.000000000 +0100
+++ xinetops/xinetops.sql.in    2005-11-13 12:45:04.000000000 +0100
@@ -0,0 +1,104 @@
+--
+--     PostgreSQL type definitions for extended inet operations.
+--      Copyright (c) 2003-2006, S.R. van den Berg, The Netherlands
+--                               <[EMAIL PROTECTED]>
+--
+--      This module is distributed under the same BSD license as PostgreSQL.
+--
+--     $Id: xinetops.sql.in 524 2005-11-13 11:44:43Z srb $
+--
+
+-- Adjust this setting to control where the objects get created.
+SET search_path = public;
+
+SET autocommit TO 'on';
+
+--
+--     The various functions doing the work
+--
+
+CREATE FUNCTION inet_not(inet)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_or(inet, inet)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_and(inet, inet)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_plusi(inet, int)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_iplus(int, inet)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_mini(inet, int)
+RETURNS inet
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+CREATE FUNCTION inet_min(inet, inet)
+RETURNS int
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C';
+
+--
+--     Now the operators.
+--
+
+CREATE OPERATOR ~ (
+       RIGHTARG = inet,
+       PROCEDURE = inet_not
+);
+
+CREATE OPERATOR | (
+       LEFTARG = inet,
+       RIGHTARG = inet,
+       COMMUTATOR = |,
+       PROCEDURE = inet_or
+);
+
+CREATE OPERATOR & (
+       LEFTARG = inet,
+       RIGHTARG = inet,
+       COMMUTATOR = &,
+       PROCEDURE = inet_and
+);
+
+CREATE OPERATOR + (
+       LEFTARG = inet,
+       RIGHTARG = int,
+       COMMUTATOR = +,
+       PROCEDURE = inet_plusi
+);
+
+CREATE OPERATOR + (
+       LEFTARG = int,
+       RIGHTARG = inet,
+       COMMUTATOR = +,
+       PROCEDURE = inet_iplus
+);
+
+CREATE OPERATOR - (
+       LEFTARG = inet,
+       RIGHTARG = int,
+       COMMUTATOR = -,
+       PROCEDURE = inet_mini
+);
+
+CREATE OPERATOR - (
+       LEFTARG = inet,
+       RIGHTARG = inet,
+       COMMUTATOR = -,
+       PROCEDURE = inet_min
+);
-- 
Sincerely,                                                          [EMAIL 
PROTECTED]
           Stephen R. van den Berg (AKA BuGless).

Skiing beyond this point may result in death and/or loss of skiing privileges.

---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster

Reply via email to