mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-07 19:47:50 +08:00
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 *src = PG_GETARG_INET_PP(0);
|
||||
inet *dst;
|
||||
int bits;
|
||||
int byte;
|
||||
int nbits;
|
||||
int maxbytes;
|
||||
|
||||
bits = ip_bits(src);
|
||||
|
||||
@ -280,29 +276,7 @@ inet_to_cidr(PG_FUNCTION_ARGS)
|
||||
if ((bits < 0) || (bits > ip_maxbits(src)))
|
||||
elog(ERROR, "invalid inet bit length: %d", bits);
|
||||
|
||||
/* clone the original data */
|
||||
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);
|
||||
PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
|
||||
}
|
||||
|
||||
Datum
|
||||
@ -334,10 +308,6 @@ cidr_set_masklen(PG_FUNCTION_ARGS)
|
||||
{
|
||||
inet *src = PG_GETARG_INET_PP(0);
|
||||
int bits = PG_GETARG_INT32(1);
|
||||
inet *dst;
|
||||
int byte;
|
||||
int nbits;
|
||||
int maxbytes;
|
||||
|
||||
if (bits == -1)
|
||||
bits = ip_maxbits(src);
|
||||
@ -347,31 +317,36 @@ cidr_set_masklen(PG_FUNCTION_ARGS)
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("invalid mask length: %d", bits)));
|
||||
|
||||
/* clone the original data */
|
||||
dst = (inet *) palloc(VARSIZE_ANY(src));
|
||||
memcpy(dst, src, VARSIZE_ANY(src));
|
||||
PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* zero out any bits to the right of the new netmask */
|
||||
byte = bits / 8;
|
||||
if (bits > 0)
|
||||
{
|
||||
Assert(bits <= ip_maxbits(dst));
|
||||
|
||||
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++;
|
||||
/* Clone appropriate bytes of the address, leaving the rest 0 */
|
||||
memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
|
||||
|
||||
/* Clear any unwanted bits in the last partial byte */
|
||||
if (bits % 8)
|
||||
ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
|
||||
}
|
||||
|
||||
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 */
|
||||
dst = (inet *) palloc0(sizeof(inet));
|
||||
|
||||
if (ip_family(ip) == PGSQL_AF_INET)
|
||||
maxbytes = 4;
|
||||
else
|
||||
maxbytes = 16;
|
||||
|
||||
maxbytes = ip_addrsize(ip);
|
||||
bits = ip_bits(ip);
|
||||
a = ip_addr(ip);
|
||||
b = ip_addr(dst);
|
||||
@ -853,11 +824,7 @@ network_hostmask(PG_FUNCTION_ARGS)
|
||||
/* make sure any unused bits are zeroed */
|
||||
dst = (inet *) palloc0(sizeof(inet));
|
||||
|
||||
if (ip_family(ip) == PGSQL_AF_INET)
|
||||
maxbytes = 4;
|
||||
else
|
||||
maxbytes = 16;
|
||||
|
||||
maxbytes = ip_addrsize(ip);
|
||||
bits = ip_maxbits(ip) - ip_bits(ip);
|
||||
b = ip_addr(dst);
|
||||
|
||||
@ -907,8 +874,7 @@ Datum
|
||||
inet_merge(PG_FUNCTION_ARGS)
|
||||
{
|
||||
inet *a1 = PG_GETARG_INET_PP(0),
|
||||
*a2 = PG_GETARG_INET_PP(1),
|
||||
*result;
|
||||
*a2 = PG_GETARG_INET_PP(1);
|
||||
int commonbits;
|
||||
|
||||
if (ip_family(a1) != ip_family(a2))
|
||||
@ -919,24 +885,7 @@ inet_merge(PG_FUNCTION_ARGS)
|
||||
commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
|
||||
Min(ip_bits(a1), ip_bits(a2)));
|
||||
|
||||
/* Make sure any unused bits are zeroed. */
|
||||
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);
|
||||
PG_RETURN_INET_P(cidr_set_masklen_internal(a1, commonbits));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -28,10 +28,12 @@ typedef 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
|
||||
* machines which may not have the appropriate address family (like
|
||||
* 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.
|
||||
*/
|
||||
#define PGSQL_AF_INET (AF_INET + 0)
|
||||
@ -117,6 +119,7 @@ typedef struct macaddr
|
||||
/*
|
||||
* 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 bitncommon(const unsigned char *l, const unsigned char *r, int n);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user