inet increment w/ int8

From: "Ilya A(dot) Kovalenko" <shadow(at)oganer(dot)net>
To: pgsql-hackers(at)postgresql(dot)org
Subject: inet increment w/ int8
Date: 2005-04-17 20:25:34
Message-ID: 17534258300.20050418042534@oganer.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Greetings,

I suggest function for "inet" increment w/ int8 (signed).

FUNCTION inet_inc(int, int8) RETURNS inet

Function, useful for making address pools (using also
existing "inet" compare functions to trap boundaries).

Notes:
This version lets address wrap around 0-*ff boundary.
Uses couple of non-POSIX functions - betoh64() and htobe64()
Tested on i386 with OpenBSD 3.7
PostgreSQL 8.0.2

-----------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "postgres.h" /* general Postgres declarations */

#include "fmgr.h" /* for argument/result macros */
#include "utils/inet.h"

Datum inet_inc(PG_FUNCTION_ARGS);

//------ stolen from backend/utils/adt/network.c --------

#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)
#define ip_maxbits(inetptr) \
(ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)

static int
ip_addrsize(inet *inetptr)
{
switch (ip_family(inetptr))
{
case PGSQL_AF_INET:
return 4;
case PGSQL_AF_INET6:
return 16;
default:
return 0;
}
}
//-------------------------------------------------------

PG_FUNCTION_INFO_V1(inet_inc);

Datum
inet_inc(PG_FUNCTION_ARGS)
{
inet *src = PG_GETARG_INET_P(0);
int64 arg = PG_GETARG_INT64(1);
inet *dst;
uint64 wsp;

// allocate destination structure
dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));

// copy to destination
*((inet_struct *)VARDATA(dst)) = *((inet_struct *)VARDATA(src));

if (ip_family(dst) == PGSQL_AF_INET)
{
// Increment v4 address w/ item truncated to 32 bits
*((uint32*)(ip_addr(dst))) =
htonl(ntohl(*((int32*)(ip_addr(dst)))) + (int32)arg);
}
else
{
// Increment v6 address low qword (store to workspace)
wsp = htobe64(betoh64(*((int64*)(ip_addr(dst) + 8))) + arg);
*((uint64*)(ip_addr(dst) + 8)) = wsp;

// Carry/borrow high qword
if ( arg > 0 && wsp < *((uint64*)(ip_addr(src) + 8)) )
{ *((int64*)(ip_addr(dst))) =
htobe64(betoh64(*((int64*)(ip_addr(dst)))) + 1);
}
else
if ( arg < 0 && wsp > *((uint64*)(ip_addr(src) + 8)) )
{ *((int64*)(ip_addr(dst))) =
htobe64(betoh64(*((int64*)(ip_addr(dst)))) - 1);
}
}

// Return result
VARATT_SIZEP(dst) = VARHDRSZ
+ ((char *) ip_addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);

PG_RETURN_INET_P(dst);

}
-----------------------------------------------------

Thank you

Ilya A. Kovalenko (mailto:shadow(at)oganer(dot)net)
SpecialEQ SW section
JSC Oganer-Service

P.S. Treat as Public Domain

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Chuck McDevitt 2005-04-17 20:28:11 Re: argtype_inherit() is dead code
Previous Message elein 2005-04-17 18:27:52 Re: argtype_inherit() is dead code