diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 9fc583ce574..f390bca85c3 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -229,14 +229,15 @@ hostnossl database user
address
- Specifies the client machine addresses that this record
+ Specifies the client machine address(es) that this record
matches. This field can contain either a host name, an IP
address range, or one of the special key words mentioned below.
- An IP address is specified in standard dotted decimal
- notation with a CIDR> mask length. The mask
+ An IP address range is specified using standard numeric notation
+ for the range's starting address, then a slash (/)
+ and a CIDR> mask length. The mask
length indicates the number of high-order bits of the client
IP address that must match. Bits to the right of this should
be zero in the given IP address.
@@ -245,25 +246,27 @@ hostnossl database user
- Typical examples of an IP address range specified this way are
+ Typical examples of an IPv4 address range specified this way are
172.20.143.89/32 for a single host, or
172.20.143.0/24 for a small network, or
10.6.0.0/16 for a larger one.
+ An IPv6 address range might look like ::1/128
+ for a single host (in this case the IPv6 loopback address) or
+ fe80::7a31:c1ff:0000:0000/96 for a small
+ network.
0.0.0.0/0 represents all
- IPv4 addresses, and ::/0 represents
+ IPv4 addresses, and ::0/0 represents
all IPv6 addresses.
- To specify a single host, use a CIDR mask of 32 for IPv4 or
+ To specify a single host, use a mask length of 32 for IPv4 or
128 for IPv6. In a network address, do not omit trailing zeroes.
- An IP address given in IPv4 format will match IPv6 connections that
- have the corresponding address, for example 127.0.0.1>
- will match the IPv6 address ::ffff:127.0.0.1>. An entry
- given in IPv6 format will match only IPv6 connections, even if the
- represented address is in the IPv4-in-IPv6 range. Note that entries
- in IPv6 format will be rejected if the system's C library does not have
- support for IPv6 addresses.
+ An entry given in IPv4 format will match only IPv4 connections,
+ and an entry given in IPv6 format will match only IPv6 connections,
+ even if the represented address is in the IPv4-in-IPv6 range.
+ Note that entries in IPv6 format will be rejected if the system's
+ C library does not have support for IPv6 addresses.
@@ -275,7 +278,7 @@ hostnossl database user
If a host name is specified (anything that is not an IP address
- or a special key word is processed as a potential host name),
+ range or a special key word is treated as a host name),
that name is compared with the result of a reverse name
resolution of the client's IP address (e.g., reverse DNS
lookup, if DNS is used). Host name comparisons are case
@@ -353,8 +356,9 @@ hostnossl database user
IP-mask
- These fields can be used as an alternative to the
- CIDR-address notation. Instead of
+ These two fields can be used as an alternative to the
+ IP-address>/>mask-length>
+ notation. Instead of
specifying the mask length, the actual mask is specified in a
separate column. For example, 255.0.0.0> represents an IPv4
CIDR mask length of 8, and 255.255.255.255> represents a
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 51a859df285..e53fca3da74 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -680,42 +680,12 @@ check_hostname(hbaPort *port, const char *hostname)
static bool
check_ip(SockAddr *raddr, struct sockaddr * addr, struct sockaddr * mask)
{
- if (raddr->addr.ss_family == addr->sa_family)
- {
- /* Same address family */
- if (!pg_range_sockaddr(&raddr->addr,
- (struct sockaddr_storage *) addr,
- (struct sockaddr_storage *) mask))
- return false;
- }
-#ifdef HAVE_IPV6
- else if (addr->sa_family == AF_INET &&
- raddr->addr.ss_family == AF_INET6)
- {
- /*
- * If we're connected on IPv6 but the file specifies an IPv4 address
- * to match against, promote the latter to an IPv6 address before
- * trying to match the client's address.
- */
- struct sockaddr_storage addrcopy,
- maskcopy;
-
- memcpy(&addrcopy, addr, sizeof(addrcopy));
- memcpy(&maskcopy, mask, sizeof(maskcopy));
- pg_promote_v4_to_v6_addr(&addrcopy);
- pg_promote_v4_to_v6_mask(&maskcopy);
-
- if (!pg_range_sockaddr(&raddr->addr, &addrcopy, &maskcopy))
- return false;
- }
-#endif /* HAVE_IPV6 */
- else
- {
- /* Wrong address family, no IPV6 */
- return false;
- }
-
- return true;
+ if (raddr->addr.ss_family == addr->sa_family &&
+ pg_range_sockaddr(&raddr->addr,
+ (struct sockaddr_storage *) addr,
+ (struct sockaddr_storage *) mask))
+ return true;
+ return false;
}
/*
diff --git a/src/backend/libpq/ip.c b/src/backend/libpq/ip.c
index eb249e9df56..9c3e85bbf7f 100644
--- a/src/backend/libpq/ip.c
+++ b/src/backend/libpq/ip.c
@@ -407,79 +407,6 @@ pg_sockaddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family)
}
-#ifdef HAVE_IPV6
-
-/*
- * pg_promote_v4_to_v6_addr --- convert an AF_INET addr to AF_INET6, using
- * the standard convention for IPv4 addresses mapped into IPv6 world
- *
- * The passed addr is modified in place; be sure it is large enough to
- * hold the result! Note that we only worry about setting the fields
- * that pg_range_sockaddr will look at.
- */
-void
-pg_promote_v4_to_v6_addr(struct sockaddr_storage * addr)
-{
- struct sockaddr_in addr4;
- struct sockaddr_in6 addr6;
- uint32 ip4addr;
-
- memcpy(&addr4, addr, sizeof(addr4));
- ip4addr = ntohl(addr4.sin_addr.s_addr);
-
- memset(&addr6, 0, sizeof(addr6));
-
- addr6.sin6_family = AF_INET6;
-
- addr6.sin6_addr.s6_addr[10] = 0xff;
- addr6.sin6_addr.s6_addr[11] = 0xff;
- addr6.sin6_addr.s6_addr[12] = (ip4addr >> 24) & 0xFF;
- addr6.sin6_addr.s6_addr[13] = (ip4addr >> 16) & 0xFF;
- addr6.sin6_addr.s6_addr[14] = (ip4addr >> 8) & 0xFF;
- addr6.sin6_addr.s6_addr[15] = (ip4addr) & 0xFF;
-
- memcpy(addr, &addr6, sizeof(addr6));
-}
-
-/*
- * pg_promote_v4_to_v6_mask --- convert an AF_INET netmask to AF_INET6, using
- * the standard convention for IPv4 addresses mapped into IPv6 world
- *
- * This must be different from pg_promote_v4_to_v6_addr because we want to
- * set the high-order bits to 1's not 0's.
- *
- * The passed addr is modified in place; be sure it is large enough to
- * hold the result! Note that we only worry about setting the fields
- * that pg_range_sockaddr will look at.
- */
-void
-pg_promote_v4_to_v6_mask(struct sockaddr_storage * addr)
-{
- struct sockaddr_in addr4;
- struct sockaddr_in6 addr6;
- uint32 ip4addr;
- int i;
-
- memcpy(&addr4, addr, sizeof(addr4));
- ip4addr = ntohl(addr4.sin_addr.s_addr);
-
- memset(&addr6, 0, sizeof(addr6));
-
- addr6.sin6_family = AF_INET6;
-
- for (i = 0; i < 12; i++)
- addr6.sin6_addr.s6_addr[i] = 0xff;
-
- addr6.sin6_addr.s6_addr[12] = (ip4addr >> 24) & 0xFF;
- addr6.sin6_addr.s6_addr[13] = (ip4addr >> 16) & 0xFF;
- addr6.sin6_addr.s6_addr[14] = (ip4addr >> 8) & 0xFF;
- addr6.sin6_addr.s6_addr[15] = (ip4addr) & 0xFF;
-
- memcpy(addr, &addr6, sizeof(addr6));
-}
-#endif /* HAVE_IPV6 */
-
-
/*
* Run the callback function for the addr/mask, after making sure the
* mask is sane for the addr.
diff --git a/src/include/libpq/ip.h b/src/include/libpq/ip.h
index 65a7b46c301..1d9ab7d54a2 100644
--- a/src/include/libpq/ip.h
+++ b/src/include/libpq/ip.h
@@ -46,11 +46,6 @@ extern int pg_range_sockaddr(const struct sockaddr_storage * addr,
extern int pg_sockaddr_cidr_mask(struct sockaddr_storage * mask,
char *numbits, int family);
-#ifdef HAVE_IPV6
-extern void pg_promote_v4_to_v6_addr(struct sockaddr_storage * addr);
-extern void pg_promote_v4_to_v6_mask(struct sockaddr_storage * addr);
-#endif
-
extern int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data);
#endif /* IP_H */