Skip to content

Commit 7b405b3

Browse files
committed
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
1 parent f2e016f commit 7b405b3

File tree

2 files changed

+33
-81
lines changed

2 files changed

+33
-81
lines changed

src/backend/utils/adt/network.c

Lines changed: 29 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -268,41 +268,15 @@ Datum
268268
inet_to_cidr(PG_FUNCTION_ARGS)
269269
{
270270
inet *src = PG_GETARG_INET_PP(0);
271-
inet *dst;
272271
int bits;
273-
int byte;
274-
int nbits;
275-
int maxbytes;
276272

277273
bits = ip_bits(src);
278274

279275
/* safety check */
280276
if ((bits < 0) || (bits > ip_maxbits(src)))
281277
elog(ERROR, "invalid inet bit length: %d", bits);
282278

283-
/* clone the original data */
284-
dst = (inet *) palloc(VARSIZE_ANY(src));
285-
memcpy(dst, src, VARSIZE_ANY(src));
286-
287-
/* zero out any bits to the right of the netmask */
288-
byte = bits / 8;
289-
290-
nbits = bits % 8;
291-
/* clear the first byte, this might be a partial byte */
292-
if (nbits != 0)
293-
{
294-
ip_addr(dst)[byte] &= ~(0xFF >> nbits);
295-
byte++;
296-
}
297-
/* clear remaining bytes */
298-
maxbytes = ip_addrsize(dst);
299-
while (byte < maxbytes)
300-
{
301-
ip_addr(dst)[byte] = 0;
302-
byte++;
303-
}
304-
305-
PG_RETURN_INET_P(dst);
279+
PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
306280
}
307281

308282
Datum
@@ -334,10 +308,6 @@ cidr_set_masklen(PG_FUNCTION_ARGS)
334308
{
335309
inet *src = PG_GETARG_INET_PP(0);
336310
int bits = PG_GETARG_INT32(1);
337-
inet *dst;
338-
int byte;
339-
int nbits;
340-
int maxbytes;
341311

342312
if (bits == -1)
343313
bits = ip_maxbits(src);
@@ -347,31 +317,36 @@ cidr_set_masklen(PG_FUNCTION_ARGS)
347317
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
348318
errmsg("invalid mask length: %d", bits)));
349319

350-
/* clone the original data */
351-
dst = (inet *) palloc(VARSIZE_ANY(src));
352-
memcpy(dst, src, VARSIZE_ANY(src));
320+
PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
321+
}
353322

354-
ip_bits(dst) = bits;
323+
/*
324+
* Copy src and set mask length to 'bits' (which must be valid for the family)
325+
*/
326+
inet *
327+
cidr_set_masklen_internal(const inet *src, int bits)
328+
{
329+
inet *dst = (inet *) palloc0(sizeof(inet));
355330

356-
/* zero out any bits to the right of the new netmask */
357-
byte = bits / 8;
331+
ip_family(dst) = ip_family(src);
332+
ip_bits(dst) = bits;
358333

359-
nbits = bits % 8;
360-
/* clear the first byte, this might be a partial byte */
361-
if (nbits != 0)
334+
if (bits > 0)
362335
{
363-
ip_addr(dst)[byte] &= ~(0xFF >> nbits);
364-
byte++;
365-
}
366-
/* clear remaining bytes */
367-
maxbytes = ip_addrsize(dst);
368-
while (byte < maxbytes)
369-
{
370-
ip_addr(dst)[byte] = 0;
371-
byte++;
336+
Assert(bits <= ip_maxbits(dst));
337+
338+
/* Clone appropriate bytes of the address, leaving the rest 0 */
339+
memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
340+
341+
/* Clear any unwanted bits in the last partial byte */
342+
if (bits % 8)
343+
ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
372344
}
373345

374-
PG_RETURN_INET_P(dst);
346+
/* Set varlena header correctly */
347+
SET_INET_VARSIZE(dst);
348+
349+
return dst;
375350
}
376351

377352
/*
@@ -719,11 +694,7 @@ network_broadcast(PG_FUNCTION_ARGS)
719694
/* make sure any unused bits are zeroed */
720695
dst = (inet *) palloc0(sizeof(inet));
721696

722-
if (ip_family(ip) == PGSQL_AF_INET)
723-
maxbytes = 4;
724-
else
725-
maxbytes = 16;
726-
697+
maxbytes = ip_addrsize(ip);
727698
bits = ip_bits(ip);
728699
a = ip_addr(ip);
729700
b = ip_addr(dst);
@@ -853,11 +824,7 @@ network_hostmask(PG_FUNCTION_ARGS)
853824
/* make sure any unused bits are zeroed */
854825
dst = (inet *) palloc0(sizeof(inet));
855826

856-
if (ip_family(ip) == PGSQL_AF_INET)
857-
maxbytes = 4;
858-
else
859-
maxbytes = 16;
860-
827+
maxbytes = ip_addrsize(ip);
861828
bits = ip_maxbits(ip) - ip_bits(ip);
862829
b = ip_addr(dst);
863830

@@ -907,8 +874,7 @@ Datum
907874
inet_merge(PG_FUNCTION_ARGS)
908875
{
909876
inet *a1 = PG_GETARG_INET_PP(0),
910-
*a2 = PG_GETARG_INET_PP(1),
911-
*result;
877+
*a2 = PG_GETARG_INET_PP(1);
912878
int commonbits;
913879

914880
if (ip_family(a1) != ip_family(a2))
@@ -919,24 +885,7 @@ inet_merge(PG_FUNCTION_ARGS)
919885
commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
920886
Min(ip_bits(a1), ip_bits(a2)));
921887

922-
/* Make sure any unused bits are zeroed. */
923-
result = (inet *) palloc0(sizeof(inet));
924-
925-
ip_family(result) = ip_family(a1);
926-
ip_bits(result) = commonbits;
927-
928-
/* Clone appropriate bytes of the address. */
929-
if (commonbits > 0)
930-
memcpy(ip_addr(result), ip_addr(a1), (commonbits + 7) / 8);
931-
932-
/* Clean any unwanted bits in the last partial byte. */
933-
if (commonbits % 8 != 0)
934-
ip_addr(result)[commonbits / 8] &= ~(0xFF >> (commonbits % 8));
935-
936-
/* Set varlena header correctly. */
937-
SET_INET_VARSIZE(result);
938-
939-
PG_RETURN_INET_P(result);
888+
PG_RETURN_INET_P(cidr_set_masklen_internal(a1, commonbits));
940889
}
941890

942891
/*

src/include/utils/inet.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ typedef struct
2828
} inet_struct;
2929

3030
/*
31+
* We use these values for the "family" field.
32+
*
3133
* Referencing all of the non-AF_INET types to AF_INET lets us work on
3234
* machines which may not have the appropriate address family (like
3335
* inet6 addresses when AF_INET6 isn't present) but doesn't cause a
34-
* dump/reload requirement. Existing databases used AF_INET for the family
36+
* dump/reload requirement. Pre-7.4 databases used AF_INET for the family
3537
* type on disk.
3638
*/
3739
#define PGSQL_AF_INET (AF_INET + 0)
@@ -117,6 +119,7 @@ typedef struct macaddr
117119
/*
118120
* Support functions in network.c
119121
*/
122+
extern inet *cidr_set_masklen_internal(const inet *src, int bits);
120123
extern int bitncmp(const unsigned char *l, const unsigned char *r, int n);
121124
extern int bitncommon(const unsigned char *l, const unsigned char *r, int n);
122125

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy