diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index e8995f9..808c468 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -101,9 +101,9 @@
    A record can have one of the seven formats
 <synopsis>
 local      <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
-host       <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>CIDR-address</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
-hostssl    <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>CIDR-address</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
-hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>CIDR-address</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
+host       <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>address</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
+hostssl    <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>address</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
+hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>address</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
 host       <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>IP-address</replaceable>  <replaceable>IP-mask</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
 hostssl    <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>IP-address</replaceable>  <replaceable>IP-mask</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
 hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>  <replaceable>IP-address</replaceable>  <replaceable>IP-mask</replaceable>  <replaceable>auth-method</replaceable>  <optional><replaceable>auth-options</replaceable></optional>
@@ -218,12 +218,17 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
     </varlistentry>
 
     <varlistentry>
-     <term><replaceable>CIDR-address</replaceable></term>
+     <term><replaceable>address</replaceable></term>
      <listitem>
       <para>
        Specifies the client machine IP address range that this record
-       matches. This field contains an IP address in standard dotted decimal
-       notation and a <acronym>CIDR</> mask length. (IP addresses can only be
+       matches.  This field can contain either a host name, an IP
+       address range, one of the special key words mentioned below.
+      </para>
+
+      <para>
+       An IP address is specified in standard dotted decimal
+       notation with a <acronym>CIDR</> mask length. (IP addresses can only be
        specified numerically, not as domain or host names.)  The mask
        length indicates the number of high-order bits of the client
        IP address that must match.  Bits to the right of this must
@@ -233,14 +238,7 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
       </para>
 
       <para>
-       Instead of a <replaceable>CIDR-address</replaceable>, you can write
-       <literal>samehost</literal> to match any of the server's own IP
-       addresses, or <literal>samenet</literal> to match any address in any
-       subnet that the server is directly connected to.
-      </para>
-
-      <para>
-       Typical examples of a <replaceable>CIDR-address</replaceable> are
+       Typical examples of an IP address range specified this way are
        <literal>172.20.143.89/32</literal> for a single host, or
        <literal>172.20.143.0/24</literal> for a small network, or
        <literal>10.6.0.0/16</literal> for a larger one.
@@ -260,6 +258,24 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
       </para>
 
       <para>
+       You can also write
+       <literal>samehost</literal> to match any of the server's own IP
+       addresses, or <literal>samenet</literal> to match any address in any
+       subnet that the server is directly connected to.
+      </para>
+
+      <para>
+       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), a
+       reverse DNS lookup is performed on the client's IP address,
+       then a forward DNS lookup on the resulting name to check if it
+       matches the original IP address (that is, at least one of the
+       potentially many IP addresses matches the original one), and
+       the name found in the reverse lookup is compared with the
+       specified host name.
+      </para>
+
+      <para>
        This field only applies to <literal>host</literal>,
        <literal>hostssl</literal>, and <literal>hostnossl</> records.
       </para>
@@ -511,12 +527,12 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
 # any database user name using Unix-domain sockets (the default for local
 # connections).
 #
-# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
 local   all             all                                     trust
 
 # The same using local loopback TCP/IP connections.
 #
-# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
 host    all             all             127.0.0.1/32            trust
 
 # The same as the previous line, but using a separate netmask column
@@ -524,17 +540,27 @@ host    all             all             127.0.0.1/32            trust
 # TYPE  DATABASE        USER            IP-ADDRESS      IP-MASK             METHOD
 host    all             all             127.0.0.1       255.255.255.255     trust
 
+# The same over IPv6.
+#
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
+host    all             all             ::1/128                 trust
+
+# The same using a host name (would typically cover both IPv4 and IPv6).
+#
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
+host    all             all             localhost               trust
+
 # Allow any user from any host with IP address 192.168.93.x to connect
 # to database "postgres" as the same user name that ident reports for
 # the connection (typically the operating system user name).
 #
-# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
 host    postgres        all             192.168.93.0/24         ident
 
 # Allow any user from host 192.168.12.10 to connect to database
 # "postgres" if the user's password is correctly supplied.
 #
-# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
 host    postgres        all             192.168.12.10/32        md5
 
 # In the absence of preceding "host" lines, these two lines will
@@ -543,7 +569,7 @@ host    postgres        all             192.168.12.10/32        md5
 # on the Internet.  The zero mask causes no bits of the host IP
 # address to be considered, so it matches any host.
 #
-# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
 host    all             all             192.168.54.1/32         reject
 host    all             all             0.0.0.0/0               krb5
 
@@ -553,7 +579,7 @@ host    all             all             0.0.0.0/0               krb5
 # connection is allowed if there is an entry in pg_ident.conf for map
 # "omicron" that says "bryanh" is allowed to connect as "guest1".
 #
-# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
 host    all             all             192.168.0.0/16          ident map=omicron
 
 # If these are the only three lines for local connections, they will
@@ -563,7 +589,7 @@ host    all             all             192.168.0.0/16          ident map=omicro
 # $PGDATA/admins contains a list of names of administrators.  Passwords
 # are required in all cases.
 #
-# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
 local   sameuser        all                                     md5
 local   all             @admins                                 md5
 local   all             +support                                md5
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index aec12b0..b2ff30d 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -540,6 +540,99 @@ check_db(const char *dbname, const char *role, Oid roleid, char *param_str)
 	return false;
 }
 
+static bool
+ipv4eq(struct sockaddr_in *a, struct sockaddr_in *b)
+{
+	return (a->sin_addr.s_addr == b->sin_addr.s_addr);
+}
+
+static bool
+ipv6eq(struct sockaddr_in6 *a, struct sockaddr_in6 *b)
+{
+	int i;
+
+	for (i = 0; i < 16; i++)
+		if (a->sin6_addr.s6_addr[i] != b->sin6_addr.s6_addr[i])
+			return false;
+
+	return true;
+}
+
+/*
+ * Check to see if a connecting IP matches a given host name.
+ */
+static bool
+check_hostname(hbaPort *port, const char *hostname)
+{
+	struct addrinfo *gai_result, *gai;
+	int			ret;
+	bool		found;
+
+	/* Lookup remote host name if not already done */
+	if (!port->remote_hostname)
+	{
+		char		remote_hostname[NI_MAXHOST];
+
+		if (pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
+							   remote_hostname, sizeof(remote_hostname),
+							   NULL, 0,
+							   0))
+			return false;
+
+		port->remote_hostname = strdup(remote_hostname);
+	}
+
+	if (strcmp(port->remote_hostname, hostname) != 0)
+		return false;
+
+	/* Lookup IP from host name and check against original IP */
+
+	ret = getaddrinfo(port->remote_hostname, NULL, NULL, &gai_result);
+	if (ret != 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_CONFIG_FILE_ERROR),
+				 errmsg("getaddrinfo failed on \"%s\": %s",
+						port->remote_hostname, gai_strerror(ret))));
+
+	found = false;
+	for (gai = gai_result; gai; gai = gai->ai_next)
+	{
+		char		hostinfo[NI_MAXHOST];
+
+		getnameinfo(gai->ai_addr, gai->ai_addrlen,
+					hostinfo, sizeof(hostinfo),
+					NULL, 0,
+					NI_NUMERICHOST);
+
+		if (gai->ai_addr->sa_family == port->raddr.addr.ss_family)
+		{
+			if (gai->ai_addr->sa_family == AF_INET)
+			{
+				if (ipv4eq((struct sockaddr_in *) gai->ai_addr,
+						   (struct sockaddr_in *) &port->raddr.addr))
+				{
+					found = true;
+					break;
+				}
+			}
+			else if (gai->ai_addr->sa_family == AF_INET6)
+			{
+				if (ipv6eq((struct sockaddr_in6 *) gai->ai_addr,
+						   (struct sockaddr_in6 *) &port->raddr.addr))
+				{
+					found = true;
+					break;
+				}
+			}
+		}
+	}
+
+	if (gai_result)
+		freeaddrinfo(gai_result);
+
+	return found;
+}
+
 /*
  * Check to see if a connecting IP matches the given address and netmask.
  */
@@ -816,7 +909,12 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
 			hints.ai_next = NULL;
 
 			ret = pg_getaddrinfo_all(token, NULL, &hints, &gai_result);
-			if (ret || !gai_result)
+			if (ret == 0 && gai_result)
+				memcpy(&parsedline->addr, gai_result->ai_addr,
+					   gai_result->ai_addrlen);
+			else if (ret == EAI_NONAME)
+				parsedline->hostname = token;
+			else
 			{
 				ereport(LOG,
 						(errcode(ERRCODE_CONFIG_FILE_ERROR),
@@ -830,12 +928,10 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
 				return false;
 			}
 
-			memcpy(&parsedline->addr, gai_result->ai_addr,
-				   gai_result->ai_addrlen);
 			pg_freeaddrinfo_all(hints.ai_family, gai_result);
 
 			/* Get the netmask */
-			if (cidr_slash)
+			if (!parsedline->hostname && cidr_slash)
 			{
 				if (pg_sockaddr_cidr_mask(&parsedline->mask, cidr_slash + 1,
 										  parsedline->addr.ss_family) < 0)
@@ -852,7 +948,7 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
 				}
 				pfree(token);
 			}
-			else
+			else if (!parsedline->hostname)
 			{
 				/* Read the mask field. */
 				pfree(token);
@@ -1369,10 +1465,19 @@ check_hba(hbaPort *port)
 			switch (hba->ip_cmp_method)
 			{
 				case ipCmpMask:
-					if (!check_ip(&port->raddr,
-								  (struct sockaddr *) & hba->addr,
-								  (struct sockaddr *) & hba->mask))
-						continue;
+					if (hba->hostname)
+					{
+						if (!check_hostname(port,
+											hba->hostname))
+							continue;
+					}
+					else
+					{
+						if (!check_ip(&port->raddr,
+									  (struct sockaddr *) & hba->addr,
+									  (struct sockaddr *) & hba->mask))
+							continue;
+					}
 					break;
 				case ipCmpSameHost:
 				case ipCmpSameNet:
diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample
index e1017cf..65842ea 100644
--- a/src/backend/libpq/pg_hba.conf.sample
+++ b/src/backend/libpq/pg_hba.conf.sample
@@ -10,9 +10,9 @@
 # databases they can access.  Records take one of these forms:
 #
 # local      DATABASE  USER  METHOD  [OPTIONS]
-# host       DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
-# hostssl    DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
-# hostnossl  DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
+# host       DATABASE  USER  ADDRESS  METHOD  [OPTIONS]
+# hostssl    DATABASE  USER  ADDRESS  METHOD  [OPTIONS]
+# hostnossl  DATABASE  USER  ADDRESS  METHOD  [OPTIONS]
 #
 # (The uppercase items must be replaced by actual values.)
 #
@@ -29,7 +29,8 @@
 # you can also write a file name prefixed with "@" to include names
 # from a separate file.
 #
-# CIDR-ADDRESS specifies the set of hosts the record matches.  It is
+# ADDRESS specifies the set of hosts the record matches.  It can be a
+# host name, or it is
 # made up of an IP address and a CIDR mask that is an integer (between
 # 0 and 32 (IPv4) or 128 (IPv6) inclusive) that specifies the number
 # of significant bits in the mask.  Alternatively, you can write an IP
@@ -70,11 +71,9 @@
 
 @authcomment@
 
-# TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD
+# TYPE  DATABASE        USER            ADDRESS                 METHOD
 
 @remove-line-for-nolocal@# "local" is for Unix domain socket connections only
 @remove-line-for-nolocal@local   all             all                                     @authmethod@
-# IPv4 local connections:
-host    all             all             127.0.0.1/32            @authmethod@
-# IPv6 local connections:
-host    all             all             ::1/128                 @authmethod@
+# IPv4/6 local connections:
+host    all             all             localhost               @authmethod@
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index db61569..83182ac 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3407,6 +3407,8 @@ BackendInitialize(Port *port)
 	 */
 	port->remote_host = strdup(remote_host);
 	port->remote_port = strdup(remote_port);
+	if (log_hostname)
+		port->remote_hostname = port->remote_host;
 
 	/*
 	 * Ready to begin client interaction.  We will give up and exit(1) after a
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
index da3a2a3..97686ab 100644
--- a/src/include/libpq/hba.h
+++ b/src/include/libpq/hba.h
@@ -56,6 +56,7 @@ typedef struct
 	struct sockaddr_storage addr;
 	struct sockaddr_storage mask;
 	IPCompareMethod ip_cmp_method;
+	char	   *hostname;
 	UserAuth	auth_method;
 
 	char	   *usermap;
diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index 0a80f74..e364ff0 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -109,6 +109,7 @@ typedef struct Port
 	SockAddr	laddr;			/* local addr (postmaster) */
 	SockAddr	raddr;			/* remote addr (client) */
 	char	   *remote_host;	/* name (or ip addr) of remote host */
+	char	   *remote_hostname; /* name (not ip addr) of remote host, if available */
 	char	   *remote_port;	/* text rep of remote port */
 	CAC_state	canAcceptConnections;	/* postmaster connection status */
 
