diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index 1f8469a2cbcd222ed08f21ff29f1e7e78b778267..3f6987af0489b44bca1396a649ddeb0888772525 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -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));
+}
 
-	ip_bits(dst) = 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));
 
-	/* zero out any bits to the right of the new netmask */
-	byte = bits / 8;
+	ip_family(dst) = ip_family(src);
+	ip_bits(dst) = bits;
 
-	nbits = bits % 8;
-	/* clear the first byte, this might be a partial byte */
-	if (nbits != 0)
+	if (bits > 0)
 	{
-		ip_addr(dst)[byte] &= ~(0xFF >> nbits);
-		byte++;
-	}
-	/* clear remaining bytes */
-	maxbytes = ip_addrsize(dst);
-	while (byte < maxbytes)
-	{
-		ip_addr(dst)[byte] = 0;
-		byte++;
+		Assert(bits <= ip_maxbits(dst));
+
+		/* 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));
 }
 
 /*
diff --git a/src/include/utils/inet.h b/src/include/utils/inet.h
index 2fe3ca8c3c81d00ad3307c3a45308add7f62ef8d..dfa0b9f7113beda8ababb413dadeaf2175df2b1e 100644
--- a/src/include/utils/inet.h
+++ b/src/include/utils/inet.h
@@ -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);