Refactor some network.c code to create cidr_set_masklen_internal().
Merge several copies of "copy an inet value and adjust the mask length" code to create a single, conveniently C-callable function. This function is exported for future use by inet SPGiST support, but it's good cleanup anyway since we had three slightly-different-for-no-good-reason copies. (Extracted from a larger patch, to separate new code from refactoring of old code) Emre Hasegeli
This commit is contained in:
parent
f2e016f8d5
commit
7b405b3e04
@ -268,11 +268,7 @@ Datum
|
|||||||
inet_to_cidr(PG_FUNCTION_ARGS)
|
inet_to_cidr(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
inet *src = PG_GETARG_INET_PP(0);
|
inet *src = PG_GETARG_INET_PP(0);
|
||||||
inet *dst;
|
|
||||||
int bits;
|
int bits;
|
||||||
int byte;
|
|
||||||
int nbits;
|
|
||||||
int maxbytes;
|
|
||||||
|
|
||||||
bits = ip_bits(src);
|
bits = ip_bits(src);
|
||||||
|
|
||||||
@ -280,29 +276,7 @@ inet_to_cidr(PG_FUNCTION_ARGS)
|
|||||||
if ((bits < 0) || (bits > ip_maxbits(src)))
|
if ((bits < 0) || (bits > ip_maxbits(src)))
|
||||||
elog(ERROR, "invalid inet bit length: %d", bits);
|
elog(ERROR, "invalid inet bit length: %d", bits);
|
||||||
|
|
||||||
/* clone the original data */
|
PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
|
||||||
dst = (inet *) palloc(VARSIZE_ANY(src));
|
|
||||||
memcpy(dst, src, VARSIZE_ANY(src));
|
|
||||||
|
|
||||||
/* zero out any bits to the right of the netmask */
|
|
||||||
byte = bits / 8;
|
|
||||||
|
|
||||||
nbits = bits % 8;
|
|
||||||
/* clear the first byte, this might be a partial byte */
|
|
||||||
if (nbits != 0)
|
|
||||||
{
|
|
||||||
ip_addr(dst)[byte] &= ~(0xFF >> nbits);
|
|
||||||
byte++;
|
|
||||||
}
|
|
||||||
/* clear remaining bytes */
|
|
||||||
maxbytes = ip_addrsize(dst);
|
|
||||||
while (byte < maxbytes)
|
|
||||||
{
|
|
||||||
ip_addr(dst)[byte] = 0;
|
|
||||||
byte++;
|
|
||||||
}
|
|
||||||
|
|
||||||
PG_RETURN_INET_P(dst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -334,10 +308,6 @@ cidr_set_masklen(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
inet *src = PG_GETARG_INET_PP(0);
|
inet *src = PG_GETARG_INET_PP(0);
|
||||||
int bits = PG_GETARG_INT32(1);
|
int bits = PG_GETARG_INT32(1);
|
||||||
inet *dst;
|
|
||||||
int byte;
|
|
||||||
int nbits;
|
|
||||||
int maxbytes;
|
|
||||||
|
|
||||||
if (bits == -1)
|
if (bits == -1)
|
||||||
bits = ip_maxbits(src);
|
bits = ip_maxbits(src);
|
||||||
@ -347,31 +317,36 @@ cidr_set_masklen(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("invalid mask length: %d", bits)));
|
errmsg("invalid mask length: %d", bits)));
|
||||||
|
|
||||||
/* clone the original data */
|
PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
|
||||||
dst = (inet *) palloc(VARSIZE_ANY(src));
|
}
|
||||||
memcpy(dst, src, VARSIZE_ANY(src));
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy src and set mask length to 'bits' (which must be valid for the family)
|
||||||
|
*/
|
||||||
|
inet *
|
||||||
|
cidr_set_masklen_internal(const inet *src, int bits)
|
||||||
|
{
|
||||||
|
inet *dst = (inet *) palloc0(sizeof(inet));
|
||||||
|
|
||||||
|
ip_family(dst) = ip_family(src);
|
||||||
ip_bits(dst) = bits;
|
ip_bits(dst) = bits;
|
||||||
|
|
||||||
/* zero out any bits to the right of the new netmask */
|
if (bits > 0)
|
||||||
byte = bits / 8;
|
{
|
||||||
|
Assert(bits <= ip_maxbits(dst));
|
||||||
|
|
||||||
nbits = bits % 8;
|
/* Clone appropriate bytes of the address, leaving the rest 0 */
|
||||||
/* clear the first byte, this might be a partial byte */
|
memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
|
||||||
if (nbits != 0)
|
|
||||||
{
|
/* Clear any unwanted bits in the last partial byte */
|
||||||
ip_addr(dst)[byte] &= ~(0xFF >> nbits);
|
if (bits % 8)
|
||||||
byte++;
|
ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
|
||||||
}
|
|
||||||
/* clear remaining bytes */
|
|
||||||
maxbytes = ip_addrsize(dst);
|
|
||||||
while (byte < maxbytes)
|
|
||||||
{
|
|
||||||
ip_addr(dst)[byte] = 0;
|
|
||||||
byte++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_RETURN_INET_P(dst);
|
/* Set varlena header correctly */
|
||||||
|
SET_INET_VARSIZE(dst);
|
||||||
|
|
||||||
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -719,11 +694,7 @@ network_broadcast(PG_FUNCTION_ARGS)
|
|||||||
/* make sure any unused bits are zeroed */
|
/* make sure any unused bits are zeroed */
|
||||||
dst = (inet *) palloc0(sizeof(inet));
|
dst = (inet *) palloc0(sizeof(inet));
|
||||||
|
|
||||||
if (ip_family(ip) == PGSQL_AF_INET)
|
maxbytes = ip_addrsize(ip);
|
||||||
maxbytes = 4;
|
|
||||||
else
|
|
||||||
maxbytes = 16;
|
|
||||||
|
|
||||||
bits = ip_bits(ip);
|
bits = ip_bits(ip);
|
||||||
a = ip_addr(ip);
|
a = ip_addr(ip);
|
||||||
b = ip_addr(dst);
|
b = ip_addr(dst);
|
||||||
@ -853,11 +824,7 @@ network_hostmask(PG_FUNCTION_ARGS)
|
|||||||
/* make sure any unused bits are zeroed */
|
/* make sure any unused bits are zeroed */
|
||||||
dst = (inet *) palloc0(sizeof(inet));
|
dst = (inet *) palloc0(sizeof(inet));
|
||||||
|
|
||||||
if (ip_family(ip) == PGSQL_AF_INET)
|
maxbytes = ip_addrsize(ip);
|
||||||
maxbytes = 4;
|
|
||||||
else
|
|
||||||
maxbytes = 16;
|
|
||||||
|
|
||||||
bits = ip_maxbits(ip) - ip_bits(ip);
|
bits = ip_maxbits(ip) - ip_bits(ip);
|
||||||
b = ip_addr(dst);
|
b = ip_addr(dst);
|
||||||
|
|
||||||
@ -907,8 +874,7 @@ Datum
|
|||||||
inet_merge(PG_FUNCTION_ARGS)
|
inet_merge(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
inet *a1 = PG_GETARG_INET_PP(0),
|
inet *a1 = PG_GETARG_INET_PP(0),
|
||||||
*a2 = PG_GETARG_INET_PP(1),
|
*a2 = PG_GETARG_INET_PP(1);
|
||||||
*result;
|
|
||||||
int commonbits;
|
int commonbits;
|
||||||
|
|
||||||
if (ip_family(a1) != ip_family(a2))
|
if (ip_family(a1) != ip_family(a2))
|
||||||
@ -919,24 +885,7 @@ inet_merge(PG_FUNCTION_ARGS)
|
|||||||
commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
|
commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
|
||||||
Min(ip_bits(a1), ip_bits(a2)));
|
Min(ip_bits(a1), ip_bits(a2)));
|
||||||
|
|
||||||
/* Make sure any unused bits are zeroed. */
|
PG_RETURN_INET_P(cidr_set_masklen_internal(a1, commonbits));
|
||||||
result = (inet *) palloc0(sizeof(inet));
|
|
||||||
|
|
||||||
ip_family(result) = ip_family(a1);
|
|
||||||
ip_bits(result) = commonbits;
|
|
||||||
|
|
||||||
/* Clone appropriate bytes of the address. */
|
|
||||||
if (commonbits > 0)
|
|
||||||
memcpy(ip_addr(result), ip_addr(a1), (commonbits + 7) / 8);
|
|
||||||
|
|
||||||
/* Clean any unwanted bits in the last partial byte. */
|
|
||||||
if (commonbits % 8 != 0)
|
|
||||||
ip_addr(result)[commonbits / 8] &= ~(0xFF >> (commonbits % 8));
|
|
||||||
|
|
||||||
/* Set varlena header correctly. */
|
|
||||||
SET_INET_VARSIZE(result);
|
|
||||||
|
|
||||||
PG_RETURN_INET_P(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -28,10 +28,12 @@ typedef struct
|
|||||||
} inet_struct;
|
} inet_struct;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* We use these values for the "family" field.
|
||||||
|
*
|
||||||
* Referencing all of the non-AF_INET types to AF_INET lets us work on
|
* Referencing all of the non-AF_INET types to AF_INET lets us work on
|
||||||
* machines which may not have the appropriate address family (like
|
* machines which may not have the appropriate address family (like
|
||||||
* inet6 addresses when AF_INET6 isn't present) but doesn't cause a
|
* inet6 addresses when AF_INET6 isn't present) but doesn't cause a
|
||||||
* dump/reload requirement. Existing databases used AF_INET for the family
|
* dump/reload requirement. Pre-7.4 databases used AF_INET for the family
|
||||||
* type on disk.
|
* type on disk.
|
||||||
*/
|
*/
|
||||||
#define PGSQL_AF_INET (AF_INET + 0)
|
#define PGSQL_AF_INET (AF_INET + 0)
|
||||||
@ -117,6 +119,7 @@ typedef struct macaddr
|
|||||||
/*
|
/*
|
||||||
* Support functions in network.c
|
* Support functions in network.c
|
||||||
*/
|
*/
|
||||||
|
extern inet *cidr_set_masklen_internal(const inet *src, int bits);
|
||||||
extern int bitncmp(const unsigned char *l, const unsigned char *r, int n);
|
extern int bitncmp(const unsigned char *l, const unsigned char *r, int n);
|
||||||
extern int bitncommon(const unsigned char *l, const unsigned char *r, int n);
|
extern int bitncommon(const unsigned char *l, const unsigned char *r, int n);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user