Re: [HACKERS] Re: inet/cidr/bind

Поиск
Список
Период
Сортировка
От darcy@druid.net (D'Arcy J.M. Cain)
Тема Re: [HACKERS] Re: inet/cidr/bind
Дата
Msg-id m0zVT8o-0000emC@druid.net
обсуждение исходный текст
Ответ на Re: [HACKERS] Re: inet/cidr/bind  (Bruce Momjian <maillist@candle.pha.pa.us>)
Ответы Re: [HACKERS] Re: inet/cidr/bind
Список pgsql-hackers
Thus spake Bruce Momjian
> If you define a fuction that can take inet or cidr type, I recommend you
> define a typedef called something like "inet_or_cidr" that is the same
> as inet, and use that in functions that can take either type.

Perhaps.  We can look at that 6.4++.  For now there will be redundancy.
Afterwards we'll look at how to fold them.

> passed, but it may not matter, or you may be able to figure out what to
> do based on the data inside the type.

Ultimately, I think the latter.

> Also, D'Arcy, the pressure is on.  There will not be a lot of time for
> debugging and redesign.  I am here if you need help.

The minute that Paul's code is in the tree, I'm there.  However, if it
helps, here is cidr.c which is just the original inet.c with substitutions.
There may be minor changes when I see Paul's functions so I won't submit it
to patches yet but if someone wants to review it early, here it is.


/**    PostgreSQL type definitions for the CIDR type.  This*    is for IP V4 CIDR notation, but prepared for V6: just*
 add the necessary bits where the comments indicate.**    $Id$*/
 

#include <sys/types.h>
#include <sys/socket.h>

#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <postgres.h>
#include <utils/palloc.h>
#include <utils/builtins.h>
#include <utils/inet.h>

static int v4bitncmp(unsigned int a1, unsigned int a2, int bits);

/**    Access macros.    Add IPV6 support.*/

#define ip_addrsize(inetptr) \(((inet_struct *)VARDATA(inetptr))->family == AF_INET ? 4 : -1)

#define ip_family(inetptr) \(((inet_struct *)VARDATA(inetptr))->family)

#define ip_bits(inetptr) \(((inet_struct *)VARDATA(inetptr))->bits)

#define ip_v4addr(inetptr) \(((inet_struct *)VARDATA(inetptr))->addr.ipv4_addr)

/**    IP address reader.*/

inet *
cidr_in(char *src)
{int            bits;inet       *dst;
dst = palloc(VARHDRSZ + sizeof(inet_struct));if (dst == NULL){    elog(ERROR, "unable to allocate memory in
cidr_in()");   return (NULL);}/* First, try for an IP V4 address: */ip_family(dst) = AF_INET;bits =
inet_cidr_pton(ip_family(dst),src, &ip_v4addr(dst), ip_addrsize(dst));if ((bits < 0) || (bits > 32)){    /* Go for an
IPV6address here, before faulting out: */    elog(ERROR, "could not parse \"%s\"", src);    pfree(dst);    return
(NULL);}VARSIZE(dst)= VARHDRSZ    + ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))    +
ip_addrsize(dst);ip_bits(dst)= bits;return (dst);
 
}

/**    IP address output function.*/

char *
cidr_out(inet *src)
{char       *dst,            tmp[sizeof("255.255.255.255/32")];
if (ip_family(src) == AF_INET){    /* It's an IP V4 address: */    if (inet_cidr_ntop(AF_INET, &ip_v4addr(src),
ip_addrsize(src),ip_bits(src),                      tmp, sizeof(tmp)) < 0)    {        elog(ERROR, "unable to print
address(%s)", strerror(errno));        return (NULL);    }}else{    /* Go for an IPV6 address here, before faulting
out:*/    elog(ERROR, "unknown address family (%d)", ip_family(src));    return (NULL);}dst = palloc(strlen(tmp) +
1);if(dst == NULL){    elog(ERROR, "unable to allocate memory in cidr_out()");    return (NULL);}strcpy(dst,
tmp);return(dst);
 
}

/**    Boolean tests for magnitude.  Add V4/V6 testing!*/

bool
cidr_lt(inet *a1, inet *a2)
{if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET)){    int            order = v4bitncmp(ip_v4addr(a1),
ip_v4addr(a2),ip_bits(a2));
 
    return ((order < 0) || ((order == 0) && (ip_bits(a1) < ip_bits(a2))));}else{    /* Go for an IPV6 address here,
beforefaulting out: */    elog(ERROR, "cannot compare address families %d and %d",         ip_family(a1),
ip_family(a2));   return (FALSE);}
 
}

bool
cidr_le(inet *a1, inet *a2)
{return (inet_lt(a1, a2) || inet_eq(a1, a2));
}

bool
cidr_eq(inet *a1, inet *a2)
{if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET)){    return ((ip_bits(a1) == ip_bits(a2))     &&
(v4bitncmp(ip_v4addr(a1),ip_v4addr(a2), ip_bits(a1)) == 0));}else{    /* Go for an IPV6 address here, before faulting
out:*/    elog(ERROR, "cannot compare address families %d and %d",         ip_family(a1), ip_family(a2));    return
(FALSE);}
}

bool
cidr_ge(inet *a1, inet *a2)
{return (inet_gt(a1, a2) || inet_eq(a1, a2));
}

bool
cidr_gt(inet *a1, inet *a2)
{if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET)){    int            order = v4bitncmp(ip_v4addr(a1),
ip_v4addr(a2),ip_bits(a2));
 
    return ((order > 0) || ((order == 0) && (ip_bits(a1) > ip_bits(a2))));}else{    /* Go for an IPV6 address here,
beforefaulting out: */    elog(ERROR, "cannot compare address families %d and %d",         ip_family(a1),
ip_family(a2));   return (FALSE);}
 
}

bool
cidr_ne(inet *a1, inet *a2)
{return (!inet_eq(a1, a2));
}

bool
cidr_sub(inet *a1, inet *a2)
{if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET)){    return ((ip_bits(a1) > ip_bits(a2))     &&
(v4bitncmp(ip_v4addr(a1),ip_v4addr(a2), ip_bits(a2)) == 0));}else{    /* Go for an IPV6 address here, before faulting
out:*/    elog(ERROR, "cannot compare address families %d and %d",         ip_family(a1), ip_family(a2));    return
(FALSE);}
}

bool
cidr_subeq(inet *a1, inet *a2)
{if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET)){    return ((ip_bits(a1) >= ip_bits(a2))     &&
(v4bitncmp(ip_v4addr(a1),ip_v4addr(a2), ip_bits(a2)) == 0));}else{    /* Go for an IPV6 address here, before faulting
out:*/    elog(ERROR, "cannot compare address families %d and %d",         ip_family(a1), ip_family(a2));    return
(FALSE);}
}

bool
cidr_sup(inet *a1, inet *a2)
{if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET)){    return ((ip_bits(a1) < ip_bits(a2))     &&
(v4bitncmp(ip_v4addr(a1),ip_v4addr(a2), ip_bits(a1)) == 0));}else{    /* Go for an IPV6 address here, before faulting
out:*/    elog(ERROR, "cannot compare address families %d and %d",         ip_family(a1), ip_family(a2));    return
(FALSE);}
}

bool
cidr_supeq(inet *a1, inet *a2)
{if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET)){    return ((ip_bits(a1) <= ip_bits(a2))     &&
(v4bitncmp(ip_v4addr(a1),ip_v4addr(a2), ip_bits(a1)) == 0));}else{    /* Go for an IPV6 address here, before faulting
out:*/    elog(ERROR, "cannot compare address families %d and %d",         ip_family(a1), ip_family(a2));    return
(FALSE);}
}

/**    Comparison function for sorting.  Add V4/V6 testing!*/

int4
cidr_cmp(inet *a1, inet *a2)
{if (ntohl(ip_v4addr(a1)) < ntohl(ip_v4addr(a2)))    return (-1);else if (ntohl(ip_v4addr(a1)) > ntohl(ip_v4addr(a2)))
 return (1);return 0;
 
}

/**    Bitwise comparison for V4 addresses.  Add V6 implementation!*/

static int
v4bitncmp(unsigned int a1, unsigned int a2, int bits)
{unsigned long mask = 0;int            i;
for (i = 0; i < bits; i++)    mask = (mask >> 1) | 0x80000000;a1 = ntohl(a1);a2 = ntohl(a2);if ((a1 & mask) < (a2 &
mask))   return (-1);else if ((a1 & mask) > (a2 & mask))    return (1);return (0);
 
}



-- 
D'Arcy J.M. Cain <darcy@{druid|vex}.net>   |  Democracy is three wolves
http://www.druid.net/darcy/                |  and a sheep voting on
+1 416 424 2871     (DoD#0082)    (eNTP)   |  what's for dinner.


В списке pgsql-hackers по дате отправления:

Предыдущее
От: Tom
Дата:
Сообщение: Re: [HACKERS] Postgres - Y2K Compliant....Yes or No
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: [HACKERS] Re: inet/cidr/bind