*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 16576,16581 **** SELECT collation for ('foo' COLLATE "de_DE");
--- 16576,16594 ----
         <entry><type>text</type></entry>
         <entry>set parameter and return new value</entry>
        </row>
+       <row>
+        <entry>
+         <indexterm>
+          <primary>pg_hba_lookup</primary>
+         </indexterm>
+         <literal><function>pg_hba_lookup(<parameter>database</> <type>text</>,
+                             <parameter>user_name</> <type>text</>
+                             [, <parameter>address</> <type>text</>]
+                             [, <parameter>ssl_inuse</> <type>text</>)</function></literal>
+        </entry>
+        <entry><type>record</type></entry>
+        <entry>Returns all row entries of pg_hba.conf till matching entry is found</entry>
+       </row>
       </tbody>
      </tgroup>
     </table>
***************
*** 16633,16638 **** SELECT set_config('log_statement_stats', 'off', false);
--- 16646,16668 ----
  </programlisting>
     </para>
  
+    <para>
+     <function>pg_hba_lookup</function> returns a set of records
+     containing the line number, mode, type, database, user_name,
+     address, hostname, method, options and reason. Typical usages
+     include:
+ <programlisting>
+ postgres=# select * from pg_hba_lookup('postgres','kommih', '::1');
+  line_number |  mode   | type  | database | user_name |  address  | hostname | method | options |     reason      
+ -------------+---------+-------+----------+-----------+-----------+----------+--------+---------+-----------------
+           84 | skipped | local | ["all"]  | ["all"]   |           |          | trust  | {}      | non matching IP
+           86 | skipped | host  | ["all"]  | ["all"]   | 127.0.0.1 |          | trust  | {}      | non matching IP
+           88 | matched | host  | ["all"]  | ["all"]   | ::1       |          | trust  | {}      | 
+ (3 rows)
+ </programlisting>
+     Only super user can access this function to view the pg_hba entries.
+    </para>
+    
    </sect2>
  
    <sect2 id="functions-admin-signal">
*** a/src/backend/catalog/system_views.sql
--- b/src/backend/catalog/system_views.sql
***************
*** 940,942 **** RETURNS jsonb
--- 940,951 ----
  LANGUAGE INTERNAL
  STRICT IMMUTABLE
  AS 'jsonb_set';
+ 
+ CREATE OR REPLACE FUNCTION pg_hba_lookup(IN database text, IN user_name text,
+     IN address text default NULL, IN ssl_inuse boolean default false,
+ 	OUT line_number int, OUT mode text, OUT type text, OUT database jsonb,
+ 	OUT user_name jsonb, OUT address inet,	OUT hostname text, OUT method text,
+ 	OUT options jsonb, OUT reason text)
+ RETURNS SETOF RECORD
+ LANGUAGE INTERNAL
+ AS 'pg_hba_lookup';
*** a/src/backend/libpq/hba.c
--- b/src/backend/libpq/hba.c
***************
*** 25,39 ****
--- 25,45 ----
  #include <arpa/inet.h>
  #include <unistd.h>
  
+ #include "access/htup_details.h"
  #include "catalog/pg_collation.h"
+ #include "catalog/pg_type.h"
+ #include "funcapi.h"
  #include "libpq/ip.h"
  #include "libpq/libpq.h"
+ #include "miscadmin.h"
  #include "postmaster/postmaster.h"
  #include "regex/regex.h"
  #include "replication/walsender.h"
  #include "storage/fd.h"
  #include "utils/acl.h"
+ #include "utils/builtins.h"
  #include "utils/guc.h"
+ #include "utils/jsonb.h"
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
  
***************
*** 52,57 ****
--- 58,65 ----
  #define MAX_TOKEN	256
  #define MAX_LINE	8192
  
+ #define MAX_LEN_OF_NON_MATCH_HBA_ENTRY_REASON 256
+ 
  /* callback data for check_network_callback */
  typedef struct check_network_data
  {
***************
*** 74,79 **** typedef struct HbaToken
--- 82,90 ----
  	bool		quoted;
  } HbaToken;
  
+ /* Flag to indicate the failure of reloading pg_hba.conf file */
+ bool		load_hba_failure = false;
+ 
  /*
   * pre-parsed content of HBA config file: list of HbaLine structs.
   * parsed_hba_context is the memory context where it lives.
***************
*** 99,104 **** static List *tokenize_inc_file(List *tokens, const char *outer_filename,
--- 110,127 ----
  				  const char *inc_filename);
  static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
  				   int line_num);
+ static Datum getauthmethod(UserAuth auth_method);
+ static void hba_add_jsonb_string_elem(JsonbParseState **pstate, char *string_elem);
+ static void hba_add_jsonb_string_key(JsonbParseState **pstate, char *string_key);
+ static void hba_add_jsonb_bool_value(JsonbParseState **pstate, bool bool_val);
+ static void hba_add_jsonb_int32_value(JsonbParseState **pstate, int32 int32_val);
+ static void hba_add_jsonb_string_value(JsonbParseState **pstate, char *string_value);
+ static void hba_getvalues_for_line(HbaLine *hba, Datum *values, bool *nulls,
+ 					   bool hba_match_result, char *reason);
+ static bool pg_hba_match(HbaLine *hba, char *user, char *database, struct sockaddr_storage * addr,
+ 			 char *hostname, bool ssl_inuse, char *reason);
+ static void pg_hba_lookup_internal(char *database, char *user, struct sockaddr_storage * addr,
+ 					   char *hostname, bool ssl_inuse, ReturnSetInfo *rsi);
  
  /*
   * isblank() exists in the ISO C99 spec, but it's not very portable yet,
***************
*** 2233,2235 **** hba_getauthmethod(hbaPort *port)
--- 2256,2900 ----
  {
  	check_hba(port);
  }
+ 
+ /*
+  * Returns the Text Datum representation of authentication method
+  */
+ static Datum
+ getauthmethod(UserAuth auth_method)
+ {
+ 	Datum		result;
+ 
+ 	switch (auth_method)
+ 	{
+ 		case uaReject:
+ 			result = CStringGetTextDatum("reject");
+ 			break;
+ 		case uaTrust:
+ 			result = CStringGetTextDatum("trust");
+ 			break;
+ 		case uaIdent:
+ 			result = CStringGetTextDatum("ident");
+ 			break;
+ 		case uaPassword:
+ 			result = CStringGetTextDatum("password");
+ 			break;
+ 		case uaMD5:
+ 			result = CStringGetTextDatum("md5");
+ 			break;
+ 		case uaGSS:
+ 			result = CStringGetTextDatum("gss");
+ 			break;
+ 		case uaSSPI:
+ 			result = CStringGetTextDatum("sspi");
+ 			break;
+ 		case uaPAM:
+ 			result = CStringGetTextDatum("pam");
+ 			break;
+ 		case uaLDAP:
+ 			result = CStringGetTextDatum("ldap");
+ 			break;
+ 		case uaCert:
+ 			result = CStringGetTextDatum("cert");
+ 			break;
+ 		case uaRADIUS:
+ 			result = CStringGetTextDatum("radius");
+ 			break;
+ 		case uaPeer:
+ 			result = CStringGetTextDatum("peer");
+ 			break;
+ 		default:
+ 			elog(ERROR, "unexpected authentication method in parsed HBA entry");
+ 			break;
+ 	}
+ 
+ 	return result;
+ }
+ 
+ static void
+ hba_add_jsonb_string_elem(JsonbParseState **pstate, char *string_elem)
+ {
+ 	JsonbValue	jb;
+ 
+ 	jb.type = jbvString;
+ 	jb.val.string.len = strlen(string_elem);
+ 	jb.val.string.val = pstrdup(string_elem);
+ 	pushJsonbValue(pstate, WJB_ELEM, &jb);
+ }
+ 
+ static void
+ hba_add_jsonb_string_key(JsonbParseState **pstate, char *string_key)
+ {
+ 	JsonbValue	jb;
+ 
+ 	jb.type = jbvString;
+ 	jb.val.string.len = strlen(string_key);
+ 	jb.val.string.val = pstrdup(string_key);
+ 	pushJsonbValue(pstate, WJB_KEY, &jb);
+ }
+ 
+ static void
+ hba_add_jsonb_bool_value(JsonbParseState **pstate, bool bool_val)
+ {
+ 	JsonbValue	jb;
+ 
+ 	jb.type = jbvBool;
+ 	jb.val.boolean = bool_val;
+ 
+ 	pushJsonbValue(pstate, WJB_VALUE, &jb);
+ }
+ 
+ static void
+ hba_add_jsonb_int32_value(JsonbParseState **pstate, int32 int32_val)
+ {
+ 	JsonbValue	jb;
+ 	char		outputstr[64];
+ 
+ 	sprintf(outputstr, "%d", int32_val);
+ 	jb.type = jbvNumeric;
+ 	jb.val.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(outputstr), 0, -1));
+ 
+ 	pushJsonbValue(pstate, WJB_VALUE, &jb);
+ }
+ 
+ static void
+ hba_add_jsonb_string_value(JsonbParseState **pstate, char *string_value)
+ {
+ 	JsonbValue	jb;
+ 
+ 	jb.type = jbvString;
+ 	jb.val.string.len = strlen(string_value);
+ 	jb.val.string.val = pstrdup(string_value);
+ 	pushJsonbValue(pstate, WJB_VALUE, &jb);
+ }
+ 
+ /*
+  * Fill in suitable values to build a tuple representing the
+  * HbaLine provided
+  */
+ static void
+ hba_getvalues_for_line(HbaLine *hba, Datum *values, bool *nulls, bool hba_match_result,
+ 					   char *reason)
+ {
+ 	ListCell   *dbcell;
+ 	char		buffer[NI_MAXHOST];
+ 	int			index = 0;
+ 	JsonbParseState *parseState = NULL;
+ 	JsonbValue *result;
+ 
+ 	/* line_number */
+ 	values[index] = Int32GetDatum(hba->linenumber);
+ 
+ 	/* mode */
+ 	index++;
+ 	if (hba_match_result)
+ 		values[index] = CStringGetTextDatum("matched");
+ 	else
+ 		values[index] = CStringGetTextDatum("skipped");
+ 
+ 	/* type */
+ 	index++;
+ 	switch (hba->conntype)
+ 	{
+ 		case ctLocal:
+ 			values[index] = CStringGetTextDatum("local");
+ 			break;
+ 		case ctHost:
+ 			values[index] = CStringGetTextDatum("host");
+ 			break;
+ 		case ctHostSSL:
+ 			values[index] = CStringGetTextDatum("hostssl");
+ 			break;
+ 		case ctHostNoSSL:
+ 			values[index] = CStringGetTextDatum("hostnossl");
+ 			break;
+ 		default:
+ 			elog(ERROR, "unexpected connection type in parsed HBA entry");
+ 			break;
+ 	}
+ 
+ 	/* database */
+ 	index++;
+ 	result = pushJsonbValue(&parseState, WJB_BEGIN_ARRAY, NULL);
+ 
+ 	if (list_length(hba->databases) != 0)
+ 	{
+ 		HbaToken   *tok;
+ 
+ 		foreach(dbcell, hba->databases)
+ 		{
+ 			tok = lfirst(dbcell);
+ 			hba_add_jsonb_string_elem(&parseState, tok->string);
+ 		}
+ 	}
+ 
+ 	result = pushJsonbValue(&parseState, WJB_END_ARRAY, NULL);
+ 	values[index] = PointerGetDatum(JsonbValueToJsonb(result));
+ 
+ 	/* user */
+ 	index++;
+ 	result = pushJsonbValue(&parseState, WJB_BEGIN_ARRAY, NULL);
+ 
+ 	if (list_length(hba->roles) != 0)
+ 	{
+ 		HbaToken   *tok;
+ 
+ 		foreach(dbcell, hba->roles)
+ 		{
+ 			tok = lfirst(dbcell);
+ 			hba_add_jsonb_string_elem(&parseState, tok->string);
+ 		}
+ 	}
+ 
+ 	result = pushJsonbValue(&parseState, WJB_END_ARRAY, NULL);
+ 	values[index] = PointerGetDatum(JsonbValueToJsonb(result));
+ 
+ 	/* address */
+ 	index++;
+ 	if (pg_getnameinfo_all(&hba->addr, sizeof(struct sockaddr_storage),
+ 						   buffer, sizeof(buffer),
+ 						   NULL, 0,
+ 						   NI_NUMERICHOST) == 0)
+ 	{
+ 		clean_ipv6_addr(hba->addr.ss_family, buffer);
+ 		values[index] = DirectFunctionCall1(inet_in, CStringGetDatum(buffer));
+ 	}
+ 	else
+ 		nulls[index] = true;
+ 
+ 	/* hostname */
+ 	index++;
+ 	if (hba->hostname)
+ 		values[index] = CStringGetTextDatum(hba->hostname);
+ 	else
+ 		nulls[index] = true;
+ 
+ 	/* method */
+ 	index++;
+ 	values[index] = getauthmethod(hba->auth_method);
+ 
+ 	/* options */
+ 	index++;
+ 	result = pushJsonbValue(&parseState, WJB_BEGIN_OBJECT, NULL);
+ 
+ 	if (hba->auth_method == uaGSS || hba->auth_method == uaSSPI)
+ 	{
+ 		if (hba->include_realm)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "include_realm");
+ 			hba_add_jsonb_bool_value(&parseState, true);
+ 		}
+ 
+ 		if (hba->krb_realm)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "krb_realm");
+ 			hba_add_jsonb_string_value(&parseState, hba->krb_realm);
+ 		}
+ 	}
+ 
+ 	if (hba->usermap)
+ 	{
+ 		hba_add_jsonb_string_key(&parseState, "map");
+ 		hba_add_jsonb_string_value(&parseState, hba->usermap);
+ 	}
+ 
+ 	if (hba->clientcert)
+ 	{
+ 		hba_add_jsonb_string_key(&parseState, "clientcert");
+ 		hba_add_jsonb_bool_value(&parseState, true);
+ 	}
+ 
+ 	if (hba->pamservice)
+ 	{
+ 		hba_add_jsonb_string_key(&parseState, "pamservice");
+ 		hba_add_jsonb_string_value(&parseState, hba->pamservice);
+ 	}
+ 
+ 	if (hba->auth_method == uaLDAP)
+ 	{
+ 		if (hba->ldapserver)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldapserver");
+ 			hba_add_jsonb_string_value(&parseState, hba->ldapserver);
+ 		}
+ 
+ 		if (hba->ldapport)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldapport");
+ 			hba_add_jsonb_int32_value(&parseState, hba->ldapport);
+ 		}
+ 
+ 		if (hba->ldaptls)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldaptls");
+ 			hba_add_jsonb_bool_value(&parseState, true);
+ 		}
+ 
+ 		if (hba->ldapprefix)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldapprefix");
+ 			hba_add_jsonb_string_value(&parseState, hba->ldapprefix);
+ 		}
+ 
+ 		if (hba->ldapsuffix)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldapsuffix");
+ 			hba_add_jsonb_string_value(&parseState, hba->ldapsuffix);
+ 		}
+ 
+ 		if (hba->ldapbasedn)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldapbasedn");
+ 			hba_add_jsonb_string_value(&parseState, hba->ldapbasedn);
+ 		}
+ 
+ 		if (hba->ldapbinddn)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldapbinddn");
+ 			hba_add_jsonb_string_value(&parseState, hba->ldapbinddn);
+ 		}
+ 
+ 		if (hba->ldapbindpasswd)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldapbindpasswd");
+ 			hba_add_jsonb_string_value(&parseState, hba->ldapbindpasswd);
+ 		}
+ 
+ 		if (hba->ldapsearchattribute)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldapsearchattribute");
+ 			hba_add_jsonb_string_value(&parseState, hba->ldapsearchattribute);
+ 		}
+ 
+ 		if (hba->ldapscope)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "ldapscope");
+ 			hba_add_jsonb_int32_value(&parseState, hba->ldapscope);
+ 		}
+ 	}
+ 
+ 	if (hba->auth_method == uaRADIUS)
+ 	{
+ 		if (hba->radiusserver)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "radiusserver");
+ 			hba_add_jsonb_string_value(&parseState, hba->radiusserver);
+ 		}
+ 
+ 		if (hba->radiussecret)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "radiussecret");
+ 			hba_add_jsonb_string_value(&parseState, hba->radiussecret);
+ 		}
+ 
+ 		if (hba->radiusidentifier)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "radiusidentifier");
+ 			hba_add_jsonb_string_value(&parseState, hba->radiusidentifier);
+ 		}
+ 
+ 		if (hba->radiusport)
+ 		{
+ 			hba_add_jsonb_string_key(&parseState, "radiusport");
+ 			hba_add_jsonb_int32_value(&parseState, hba->radiusport);
+ 		}
+ 	}
+ 
+ 	result = pushJsonbValue(&parseState, WJB_END_OBJECT, NULL);
+ 	values[index] = PointerGetDatum(JsonbValueToJsonb(result));
+ 
+ 	/* reason */
+ 	index++;
+ 	if (!hba_match_result)
+ 		values[index] = CStringGetTextDatum(reason);
+ 	else
+ 		nulls[index] = true;
+ }
+ 
+ static bool
+ pg_hba_match(HbaLine *hba, char *database, char *user, struct sockaddr_storage * addr,
+ 			 char *hostname, bool ssl_inuse, char *reason)
+ {
+ 	Oid			roleid;
+ 
+ 	if (ssl_inuse)
+ 	{
+ #ifdef USE_SSL
+ 		if (EnableSSL && hba->conntype != ctHostSSL)
+ 		{
+ 			strcpy(reason, "non SSL connection type");
+ 			return false;
+ 		}
+ 		else
+ 		{
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
+ 					 errmsg("hostssl requires SSL to be turned on"),
+ 					 errhint("Set ssl = on in postgresql.conf.")));
+ 			return false;
+ 		}
+ #else
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_CONFIG_FILE_ERROR),
+ 				 errmsg("hostssl is not supported by this build"),
+ 			errhint("Compile with --with-openssl to use SSL connections.")));
+ 		return false;
+ #endif
+ 	}
+ 
+ 	/* Get the target role's OID.  Note we do not error out for bad role. */
+ 	roleid = get_role_oid(user, true);
+ 
+ 	if (!check_db(database, user, roleid, hba->databases))
+ 	{
+ 		strcpy(reason, "non matching database");
+ 		return false;
+ 	}
+ 
+ 	if (!check_role(user, roleid, hba->roles))
+ 	{
+ 		strcpy(reason, "non matching role");
+ 		return false;
+ 	}
+ 
+ 	/* Check IP address */
+ 	switch (hba->ip_cmp_method)
+ 	{
+ 		case ipCmpMask:
+ 			if (hostname && hba->hostname)
+ 			{
+ 				if (!hostname_match(hostname, hba->hostname))
+ 				{
+ 					strcpy(reason, "non matching hostname");
+ 					return false;
+ 				}
+ 			}
+ 			else
+ 			{
+ 				if (addr && !check_ip((SockAddr *) addr,
+ 									  (struct sockaddr *) & hba->addr,
+ 									  (struct sockaddr *) & hba->mask))
+ 				{
+ 					strcpy(reason, "non matching IP");
+ 					return false;
+ 				}
+ 			}
+ 			break;
+ 		case ipCmpAll:
+ 			break;
+ 		case ipCmpSameHost:
+ 		case ipCmpSameNet:
+ 			if (addr && !check_same_host_or_net((SockAddr *) addr,
+ 												hba->ip_cmp_method))
+ 			{
+ 				strcpy(reason, "non matching SameHost/SameNet");
+ 				return false;
+ 			}
+ 			break;
+ 		default:				/* Not reachable case */
+ 			break;
+ 	}
+ 
+ 	return true;
+ }
+ 
+ 
+ #define NUM_PG_HBA_CONF_ATTS   10
+ 
+ static void
+ pg_hba_lookup_internal(char *database, char *user, struct sockaddr_storage * addr,
+ 					   char *hostname, bool ssl_inuse, ReturnSetInfo *rsi)
+ {
+ 	Tuplestorestate *tuple_store;
+ 	TupleDesc	tupdesc;
+ 	ListCell   *line;
+ 	MemoryContext old_cxt;
+ 	MemoryContext pg_hba_tuple_context;
+ 
+ 	/*
+ 	 * Create the tupledesc and tuplestore in the per_query context as
+ 	 * required for SFRM_Materialize.
+ 	 */
+ 	old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
+ 
+ 	tupdesc = CreateTemplateTupleDesc(NUM_PG_HBA_CONF_ATTS, false);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "line_number",
+ 					   INT4OID, -1, 0);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "mode",
+ 					   TEXTOID, -1, 0);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "type",
+ 					   TEXTOID, -1, 0);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 4, "database",
+ 					   JSONBOID, -1, 0);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 5, "user_name",
+ 					   JSONBOID, -1, 0);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 6, "address",
+ 					   INETOID, -1, 0);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 7, "hostname",
+ 					   TEXTOID, -1, 0);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 8, "method",
+ 					   TEXTOID, -1, 0);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 9, "options",
+ 					   JSONBOID, -1, 0);
+ 	TupleDescInitEntry(tupdesc, (AttrNumber) 10, "reason",
+ 					   TEXTOID, -1, 0);
+ 	BlessTupleDesc(tupdesc);
+ 
+ 	tuple_store =
+ 		tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
+ 							  false, work_mem);
+ 
+ 	MemoryContextSwitchTo(old_cxt);
+ 
+ 	pg_hba_tuple_context = AllocSetContextCreate(CurrentMemoryContext,
+ 												 "pg_hba_lookup tuple cxt",
+ 												 ALLOCSET_DEFAULT_MINSIZE,
+ 												 ALLOCSET_DEFAULT_INITSIZE,
+ 												 ALLOCSET_DEFAULT_MAXSIZE);
+ 
+ 	/*
+ 	 * Loop through the list and deparse each entry as it comes, storing it in
+ 	 * the tuplestore. Any temporary memory allocations here live only for the
+ 	 * function call lifetime.
+ 	 */
+ 	foreach(line, parsed_hba_lines)
+ 	{
+ 		HbaLine    *hba = (HbaLine *) lfirst(line);
+ 		Datum		values[NUM_PG_HBA_CONF_ATTS];
+ 		bool		nulls[NUM_PG_HBA_CONF_ATTS];
+ 		HeapTuple	tuple;
+ 		bool		hba_match_result;
+ 		char		reason[MAX_LEN_OF_NON_MATCH_HBA_ENTRY_REASON];
+ 
+ 		memset(values, 0, sizeof(values));
+ 		memset(nulls, 0, sizeof(nulls));
+ 
+ 		CHECK_FOR_INTERRUPTS();
+ 
+ 		MemoryContextReset(pg_hba_tuple_context);
+ 		old_cxt = MemoryContextSwitchTo(pg_hba_tuple_context);
+ 
+ 		hba_match_result = pg_hba_match(hba, database, user, addr, hostname,
+ 										ssl_inuse, reason);
+ 
+ 		/* Get the next parsed hba line values */
+ 		hba_getvalues_for_line(hba, values, nulls, hba_match_result, reason);
+ 
+ 		MemoryContextSwitchTo(old_cxt);
+ 
+ 		/* build a tuple */
+ 		tuple = heap_form_tuple(tupdesc, values, nulls);
+ 		tuplestore_puttuple(tuple_store, tuple);
+ 
+ 		/* Stop the loop processing, if matching entry is found */
+ 		if (hba_match_result)
+ 			break;
+ 	}
+ 
+ 	MemoryContextDelete(pg_hba_tuple_context);
+ 
+ 	rsi->setDesc = tupdesc;
+ 	rsi->setResult = tuple_store;
+ 	return;
+ }
+ 
+ /*
+  * SQL-accessible SRF to return all the settings from the pg_hba.conf
+  * file.
+  */
+ Datum
+ pg_hba_lookup(PG_FUNCTION_ARGS)
+ {
+ 	char	   *user;
+ 	char	   *database;
+ 	char	   *address = NULL;
+ 	char	   *hostname = NULL;
+ 	bool		ssl_inuse = false;
+ 	struct sockaddr_storage addr;
+ 	struct sockaddr_storage *addr_ptr = NULL;
+ 
+ 	/*
+ 	 * We must use the Materialize mode to be safe against HBA file reloads
+ 	 * while the cursor is open. It's also more efficient than having to look
+ 	 * up our current position in the parsed list every time.
+ 	 */
+ 	ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
+ 
+ 	if (!superuser())
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 				 (errmsg("must be superuser to view pg_hba.conf settings"))));
+ 
+ 	if (!rsi || !IsA(rsi, ReturnSetInfo) ||
+ 		(rsi->allowedModes & SFRM_Materialize) == 0)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 				 errmsg("set-valued function called in context that "
+ 						"cannot accept a set")));
+ 
+ 	if (PG_ARGISNULL(0))
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ 				 (errmsg("database name is required to match pg_hba configuration entry"))));
+ 	else
+ 		database = TextDatumGetCString(PG_GETARG_DATUM(0));
+ 
+ 	if (PG_ARGISNULL(1))
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ 				 (errmsg("user name is required to match pg_hba configuration entry"))));
+ 	else
+ 		user = TextDatumGetCString(PG_GETARG_DATUM(1));
+ 
+ 	if (!PG_ARGISNULL(2))
+ 	{
+ 		struct addrinfo *gai_result;
+ 		struct addrinfo hints;
+ 		int			ret;
+ 
+ 		address = TextDatumGetCString(PG_GETARG_DATUM(2));
+ 
+ 		/* Get the IP address either way */
+ 		hints.ai_flags = AI_NUMERICHOST;
+ 		hints.ai_family = AF_UNSPEC;
+ 		hints.ai_socktype = 0;
+ 		hints.ai_protocol = 0;
+ 		hints.ai_addrlen = 0;
+ 		hints.ai_canonname = NULL;
+ 		hints.ai_addr = NULL;
+ 		hints.ai_next = NULL;
+ 
+ 		ret = pg_getaddrinfo_all(address, NULL, &hints, &gai_result);
+ 		if (ret == 0 && gai_result)
+ 		{
+ 			memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen);
+ 			addr_ptr = &addr;
+ 		}
+ 		else if (ret == EAI_NONAME)
+ 			hostname = pstrdup(address);
+ 		else
+ 		{
+ 			ereport(ERROR,
+ 					(errmsg("invalid IP address \"%s\": %s",
+ 							address, gai_strerror(ret))));
+ 			if (gai_result)
+ 				pg_freeaddrinfo_all(hints.ai_family, gai_result);
+ 			return false;
+ 		}
+ 
+ 		pg_freeaddrinfo_all(hints.ai_family, gai_result);
+ 	}
+ 
+ 	ssl_inuse = DatumGetBool(PG_GETARG_DATUM(3));
+ 
+ 	if (load_hba_failure)
+ 		ereport(WARNING,
+ 			 (errmsg("There was some failure in reloading pg_hba.conf file. "
+ 		   "The pg_hba.conf settings data may contains stale information")));
+ 
+ 	rsi->returnMode = SFRM_Materialize;
+ 
+ 	pg_hba_lookup_internal(database, user, addr_ptr, hostname, ssl_inuse, rsi);
+ 
+ 	PG_RETURN_NULL();
+ }
*** a/src/backend/tcop/postgres.c
--- b/src/backend/tcop/postgres.c
***************
*** 4005,4010 **** PostgresMain(int argc, char *argv[],
--- 4005,4022 ----
  		{
  			got_SIGHUP = false;
  			ProcessConfigFile(PGC_SIGHUP);
+ 
+ 			/* 
+ 			 * Reload authentication config files too to refresh 
+ 			 * pg_hba_conf view data.
+ 			 */
+ 			load_hba_failure = false;
+ 			if (!load_hba())
+ 			{
+ 				ereport(DEBUG1,
+ 					(errmsg("Falure in reloading pg_hba.conf, pg_hba_conf view may show stale information")));
+ 				load_hba_failure = true;
+ 			}
  		}
  
  		/*
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 3079,3084 **** DATA(insert OID = 2084 (  pg_show_all_settings	PGNSP PGUID 12 1 1000 0 0 f f f f
--- 3079,3086 ----
  DESCR("SHOW ALL as a function");
  DATA(insert OID = 3329 (  pg_show_all_file_settings PGNSP PGUID 12 1 1000 0 0 f f f f t t v s 0 0 2249 "" "{25,23,23,25,25,16,25}" "{o,o,o,o,o,o,o}" "{sourcefile,sourceline,seqno,name,setting,applied,error}" _null_ _null_ show_all_file_settings _null_ _null_ _null_ ));
  DESCR("show config file settings");
+ DATA(insert OID = 3997 (pg_hba_lookup PGNSP PGUID 12 1 1000 0 0 f f f f f t v u 4 0 2249 "25 25 25 16" "{25,25,25,16,23,25,25,3802,3802,869,25,25,3802,25}" "{i,i,i,i,o,o,o,o,o,o,o,o,o,o}" "{database,user_name,address,ssl_inuse,line_number,mode,type,database,user_name,address,hostname,method,options,reason}" _null_ _null_ pg_hba_lookup _null_ _null_ _null_));
+ DESCR("view client authentication settings");
  DATA(insert OID = 1371 (  pg_lock_status   PGNSP PGUID 12 1 1000 0 0 f f f f t t v s 0 0 2249 "" "{25,26,26,23,21,25,28,26,26,21,25,23,25,16,16}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid,virtualtransaction,pid,mode,granted,fastpath}" _null_ _null_ pg_lock_status _null_ _null_ _null_ ));
  DESCR("view system lock information");
  DATA(insert OID = 1065 (  pg_prepared_xact PGNSP PGUID 12 1 1000 0 0 f f f f t t v s 0 0 2249 "" "{28,25,1184,26,26}" "{o,o,o,o,o}" "{transaction,gid,prepared,ownerid,dbid}" _null_ _null_ pg_prepared_xact _null_ _null_ _null_ ));
*** a/src/include/libpq/hba.h
--- b/src/include/libpq/hba.h
***************
*** 96,101 **** typedef struct IdentLine
--- 96,103 ----
  /* kluge to avoid including libpq/libpq-be.h here */
  typedef struct Port hbaPort;
  
+ extern bool load_hba_failure;
+ 
  extern bool load_hba(void);
  extern bool load_ident(void);
  extern void hba_getauthmethod(hbaPort *port);
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
***************
*** 1123,1128 **** extern Datum set_config_by_name(PG_FUNCTION_ARGS);
--- 1123,1131 ----
  extern Datum show_all_settings(PG_FUNCTION_ARGS);
  extern Datum show_all_file_settings(PG_FUNCTION_ARGS);
  
+ /* hba.c */
+ extern Datum pg_hba_lookup(PG_FUNCTION_ARGS);
+ 
  /* rls.c */
  extern Datum row_security_active(PG_FUNCTION_ARGS);
  extern Datum row_security_active_name(PG_FUNCTION_ARGS);
