contrib/xinetops for 8.1 "patch" - Mailing list pgsql-patches
From | Stephen R. van den Berg |
---|---|
Subject | contrib/xinetops for 8.1 "patch" |
Date | |
Msg-id | 20051113115228.GA22593@cuci.nl Whole thread Raw |
Responses |
Re: contrib/xinetops for 8.1 "patch"
|
List | pgsql-patches |
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. <srb@cuci.nl> 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. + <srb@cuci.nl> + +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 + * <srb@cuci.nl> + * + * 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 +-- <srb@cuci.nl> +-- +-- 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, srb@cuci.nl Stephen R. van den Berg (AKA BuGless). Skiing beyond this point may result in death and/or loss of skiing privileges.
pgsql-patches by date: