*** 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,16669 ----
  </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
***************
*** 948,950 **** RETURNS jsonb
--- 948,959 ----
  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 _text,
+ 	OUT user_name _text, 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,46 ----
  #include <arpa/inet.h>
  #include <unistd.h>
  
+ #include "access/htup_details.h"
  #include "catalog/pg_collation.h"
+ #include "catalog/pg_type.h"
+ #include "catalog/objectaddress.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 ****
--- 59,67 ----
  #define MAX_TOKEN	256
  #define MAX_LINE	8192
  
+ #define NUM_PG_HBA_CONF_ATTS   10
+ #define MAX_LEN_OF_NON_MATCH_HBA_ENTRY_REASON 256
+ 
  /* callback data for check_network_callback */
  typedef struct check_network_data
  {
***************
*** 99,104 **** static List *tokenize_inc_file(List *tokens, const char *outer_filename,
--- 109,122 ----
  				  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_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 Jsonb *gethba_options(HbaLine *hba);
+ static void fill_hbaline(HbaLine *hba, TupleDesc tupdesc, Tuplestorestate *tuple_store,
+ 			 char *reason);
  
  /*
   * isblank() exists in the ISO C99 spec, but it's not very portable yet,
***************
*** 1640,1646 **** parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
   *	request.
   */
  static void
! check_hba(hbaPort *port)
  {
  	Oid			roleid;
  	ListCell   *line;
--- 1658,1664 ----
   *	request.
   */
  static void
! check_hba(hbaPort *port, TupleDesc tupdesc, Tuplestorestate *tuple_store)
  {
  	Oid			roleid;
  	ListCell   *line;
***************
*** 1657,1681 **** check_hba(hbaPort *port)
--- 1675,1711 ----
  		if (hba->conntype == ctLocal)
  		{
  			if (!IS_AF_UNIX(port->raddr.addr.ss_family))
+ 			{
+ 				fill_hbaline(hba, tupdesc, tuple_store, "non matching connection type");
  				continue;
+ 			}
  		}
  		else
  		{
  			if (IS_AF_UNIX(port->raddr.addr.ss_family))
+ 			{
+ 				fill_hbaline(hba, tupdesc, tuple_store, "non matching connection type");
  				continue;
+ 			}
  
  			/* Check SSL state */
  			if (port->ssl_in_use)
  			{
  				/* Connection is SSL, match both "host" and "hostssl" */
  				if (hba->conntype == ctHostNoSSL)
+ 				{
+ 					fill_hbaline(hba, tupdesc, tuple_store, "non matching connection type");
  					continue;
+ 				}
  			}
  			else
  			{
  				/* Connection is not SSL, match both "host" and "hostnossl" */
  				if (hba->conntype == ctHostSSL)
+ 				{
+ 					fill_hbaline(hba, tupdesc, tuple_store, "non matching connection type");
  					continue;
+ 				}
  			}
  
  			/* Check IP address */
***************
*** 1686,1699 **** check_hba(hbaPort *port)
--- 1716,1735 ----
  					{
  						if (!check_hostname(port,
  											hba->hostname))
+ 						{
+ 							fill_hbaline(hba, tupdesc, tuple_store, "non matching hostname");
  							continue;
+ 						}
  					}
  					else
  					{
  						if (!check_ip(&port->raddr,
  									  (struct sockaddr *) & hba->addr,
  									  (struct sockaddr *) & hba->mask))
+ 						{
+ 							fill_hbaline(hba, tupdesc, tuple_store, "non matching IP");
  							continue;
+ 						}
  					}
  					break;
  				case ipCmpAll:
***************
*** 1702,1708 **** check_hba(hbaPort *port)
--- 1738,1747 ----
  				case ipCmpSameNet:
  					if (!check_same_host_or_net(&port->raddr,
  												hba->ip_cmp_method))
+ 					{
+ 						fill_hbaline(hba, tupdesc, tuple_store, "non matching samehost/samenet");
  						continue;
+ 					}
  					break;
  				default:
  					/* shouldn't get here, but deem it no-match if so */
***************
*** 1713,1722 **** check_hba(hbaPort *port)
--- 1752,1769 ----
  		/* Check database and role */
  		if (!check_db(port->database_name, port->user_name, roleid,
  					  hba->databases))
+ 		{
+ 			fill_hbaline(hba, tupdesc, tuple_store, "non matching database name");
  			continue;
+ 		}
  
  		if (!check_role(port->user_name, roleid, hba->roles))
+ 		{
+ 			fill_hbaline(hba, tupdesc, tuple_store, "non matching user name");
  			continue;
+ 		}
+ 
+ 		fill_hbaline(hba, tupdesc, tuple_store, NULL);
  
  		/* Found a record that matched! */
  		port->hba = hba;
***************
*** 1755,1760 **** load_hba(void)
--- 1802,1808 ----
  	MemoryContext linecxt;
  	MemoryContext oldcxt;
  	MemoryContext hbacxt;
+ 	MemoryContext parentcxt = PostmasterContext ? PostmasterContext : CurrentMemoryContext;
  
  	file = AllocateFile(HbaFileName, "r");
  	if (file == NULL)
***************
*** 1770,1777 **** load_hba(void)
  	FreeFile(file);
  
  	/* Now parse all the lines */
! 	Assert(PostmasterContext);
! 	hbacxt = AllocSetContextCreate(PostmasterContext,
  								   "hba parser context",
  								   ALLOCSET_DEFAULT_MINSIZE,
  								   ALLOCSET_DEFAULT_MINSIZE,
--- 1818,1825 ----
  	FreeFile(file);
  
  	/* Now parse all the lines */
! 	Assert(parentcxt);
! 	hbacxt = AllocSetContextCreate(parentcxt,
  								   "hba parser context",
  								   ALLOCSET_DEFAULT_MINSIZE,
  								   ALLOCSET_DEFAULT_MINSIZE,
***************
*** 1828,1836 **** load_hba(void)
  		return false;
  	}
  
- 	/* Loaded new file successfully, replace the one we use */
- 	if (parsed_hba_context != NULL)
- 		MemoryContextDelete(parsed_hba_context);
  	parsed_hba_context = hbacxt;
  	parsed_hba_lines = new_parsed_lines;
  
--- 1876,1881 ----
***************
*** 2233,2237 **** load_ident(void)
  void
  hba_getauthmethod(hbaPort *port)
  {
! 	check_hba(port);
  }
--- 2278,2806 ----
  void
  hba_getauthmethod(hbaPort *port)
  {
! 	check_hba(port, NULL, NULL);
! }
! 
! /*
!  * 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_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);
! }
! 
! static Jsonb *
! gethba_options(HbaLine *hba)
! {
! 	JsonbParseState *parseState = NULL;
! 	JsonbValue *result;
! 
! 	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);
! 	return JsonbValueToJsonb(result);
! }
! 
! static void
! fill_hbaline(HbaLine *hba, TupleDesc tupdesc, Tuplestorestate *tuple_store,
! 			 char *reason)
! {
! 	Datum		values[NUM_PG_HBA_CONF_ATTS];
! 	bool		nulls[NUM_PG_HBA_CONF_ATTS];
! 	ListCell   *dbcell;
! 	char		buffer[NI_MAXHOST];
! 	HeapTuple	tuple;
! 	int			index;
! 	MemoryContext old_cxt;
! 	MemoryContext pg_hba_tuple_context;
! 
! 	if (tupdesc == NULL || tuple_store == NULL)
! 		return;
! 
! 	index = 0;
! 	memset(values, 0, sizeof(values));
! 	memset(nulls, 0, sizeof(nulls));
! 
! 	pg_hba_tuple_context = AllocSetContextCreate(CurrentMemoryContext,
! 												 "pg_hba_lookup tuple cxt",
! 												 ALLOCSET_DEFAULT_MINSIZE,
! 												 ALLOCSET_DEFAULT_INITSIZE,
! 												 ALLOCSET_DEFAULT_MAXSIZE);
! 
! 	old_cxt = MemoryContextSwitchTo(pg_hba_tuple_context);
! 
! 	/* line_number */
! 	values[index] = Int32GetDatum(hba->linenumber);
! 
! 	/* mode */
! 	index++;
! 	if (reason == NULL)
! 		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++;
! 	if (list_length(hba->databases) != 0)
! 	{
! 		List	   *names = NULL;
! 		HbaToken   *tok;
! 
! 		foreach(dbcell, hba->databases)
! 		{
! 			tok = lfirst(dbcell);
! 			names = lappend(names, tok->string);
! 		}
! 
! 		values[index] = PointerGetDatum(strlist_to_textarray(names));
! 	}
! 	else
! 		nulls[index] = true;
! 
! 	/* user */
! 	index++;
! 	if (list_length(hba->roles) != 0)
! 	{
! 		List	   *roles = NULL;
! 		HbaToken   *tok;
! 
! 		foreach(dbcell, hba->roles)
! 		{
! 			tok = lfirst(dbcell);
! 			roles = lappend(roles, tok->string);
! 		}
! 
! 		values[index] = PointerGetDatum(strlist_to_textarray(roles));
! 	}
! 	else
! 		nulls[index] = true;
! 
! 	/* 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++;
! 	values[index] = PointerGetDatum(gethba_options(hba));
! 
! 	/* reason */
! 	index++;
! 	if (reason)
! 		values[index] = CStringGetTextDatum(reason);
! 	else
! 		nulls[index] = true;
! 
! 	tuple = heap_form_tuple(tupdesc, values, nulls);
! 	tuplestore_puttuple(tuple_store, tuple);
! 
! 	MemoryContextSwitchTo(old_cxt);
! 	MemoryContextDelete(pg_hba_tuple_context);
! 	return;
! }
! 
! /*
!  * SQL-accessible SRF to return all the settings from the pg_hba.conf
!  * file.
!  */
! Datum
! pg_hba_lookup(PG_FUNCTION_ARGS)
! {
! 	hbaPort    *port;
! 	Tuplestorestate *tuple_store;
! 	TupleDesc	tupdesc;
! 	MemoryContext old_cxt;
! 
! 	/*
! 	 * 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")));
! 
! 	port = palloc0(sizeof(hbaPort));
! 
! 	if (PG_ARGISNULL(0))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
! 				 (errmsg("database name is required to match pg_hba configuration entry"))));
! 	else
! 		port->database_name = 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
! 		port->user_name = TextDatumGetCString(PG_GETARG_DATUM(1));
! 
! 
! 	if (!PG_ARGISNULL(2))
! 	{
! 		char	   *address = NULL;
! 		struct addrinfo *gai_result = NULL;
! 		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 = getaddrinfo(address, NULL, &hints, &gai_result);
! 		if (ret == 0 && gai_result)
! 			memcpy(&port->raddr.addr, gai_result->ai_addr, gai_result->ai_addrlen);
! 		else if (ret == EAI_NONAME)
! 		{
! 			struct addrinfo *gai_result2 = NULL;
! 
! 			port->remote_hostname = pstrdup(address);
! 
! 			ret = getaddrinfo(port->remote_hostname, NULL, NULL, &gai_result2);
! 			if (ret == 0 && gai_result2)
! 				memcpy(&port->raddr.addr, gai_result2->ai_addr, gai_result2->ai_addrlen);
! 			else
! 				ereport(ERROR,
! 				(errmsg("getaddrinfo failed to look into hostname \"%s\": %s",
! 						port->remote_hostname, gai_strerror(ret))));
! 
! 			if (gai_result2)
! 				freeaddrinfo(gai_result2);
! 		}
! 		else
! 			ereport(ERROR,
! 					(errmsg("invalid IP address \"%s\": %s",
! 							address, gai_strerror(ret))));
! 		if (gai_result)
! 			freeaddrinfo(gai_result);
! 	}
! 	else
! 		port->raddr.addr.ss_family = AF_UNIX;
! 
! 	port->ssl_in_use = DatumGetBool(PG_GETARG_DATUM(3));
! 
! 	rsi->returnMode = SFRM_Materialize;
! 
! 	if (!load_hba())
! 		ereport(ERROR,
! 			 (errmsg("There was some failure in loading pg_hba.conf file")));
! 
! 	/*
! 	 * 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",
! 					   TEXTARRAYOID, -1, 0);
! 	TupleDescInitEntry(tupdesc, (AttrNumber) 5, "user_name",
! 					   TEXTARRAYOID, -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);
! 
! 	check_hba(port, tupdesc, tuple_store);
! 
! 	rsi->setDesc = tupdesc;
! 	rsi->setResult = tuple_store;
! 
! 	MemoryContextDelete(parsed_hba_context);
! 	parsed_hba_context = NULL;
! 
! 	PG_RETURN_NULL();
  }
*** 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,1009,1009,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/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);
