diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index a95ba8b..31df9ee 100644 *** a/src/backend/utils/adt/pgstatfuncs.c --- b/src/backend/utils/adt/pgstatfuncs.c *************** extern Datum pg_stat_reset_shared(PG_FUN *** 107,112 **** --- 107,114 ---- extern Datum pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS); extern Datum pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS); + static void get_host_and_port(const SockAddr *addr, inet **host, int *port); + /* Global bgwriter statistics, from bgwriter.c */ extern PgStat_MsgBgWriter bgwriterStats; *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 571,577 **** bool nulls[11]; HeapTuple tuple; PgBackendStatus *beentry; - SockAddr zero_clientaddr; MemSet(values, 0, sizeof(values)); MemSet(nulls, 0, sizeof(nulls)); --- 573,578 ---- *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 612,617 **** --- 613,621 ---- /* Values only available to same user or superuser */ if (superuser() || beentry->st_userid == GetUserId()) { + inet *client_addr; + int client_port; + if (*(beentry->st_activity) == '\0') { values[4] = CStringGetTextDatum(""); *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 638,701 **** else nulls[8] = true; ! /* A zeroed client addr means we don't know */ ! memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); ! if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr, ! sizeof(zero_clientaddr) == 0)) ! { nulls[9] = true; ! nulls[10] = true; ! } else ! { ! if (beentry->st_clientaddr.addr.ss_family == AF_INET ! #ifdef HAVE_IPV6 ! || beentry->st_clientaddr.addr.ss_family == AF_INET6 ! #endif ! ) ! { ! char remote_host[NI_MAXHOST]; ! char remote_port[NI_MAXSERV]; ! int ret; ! ! remote_host[0] = '\0'; ! remote_port[0] = '\0'; ! ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr, ! beentry->st_clientaddr.salen, ! remote_host, sizeof(remote_host), ! remote_port, sizeof(remote_port), ! NI_NUMERICHOST | NI_NUMERICSERV); ! if (ret) ! { ! nulls[9] = true; ! nulls[10] = true; ! } ! else ! { ! clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host); ! values[9] = DirectFunctionCall1(inet_in, ! CStringGetDatum(remote_host)); ! values[10] = Int32GetDatum(atoi(remote_port)); ! } ! } ! else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX) ! { ! /* ! * Unix sockets always reports NULL for host and -1 for ! * port, so it's possible to tell the difference to ! * connections we have no permissions to view, or with ! * errors. ! */ ! nulls[9] = true; ! values[10] = DatumGetInt32(-1); ! } ! else ! { ! /* Unknown address type, should never happen */ ! nulls[9] = true; ! nulls[10] = true; ! } ! } } else { --- 642,656 ---- else nulls[8] = true; ! get_host_and_port(&beentry->st_clientaddr, &client_addr, &client_port); ! if (client_addr != NULL) ! values[9] = PointerGetDatum(client_addr); ! else nulls[9] = true; ! if (client_port != 0) ! values[10] = DatumGetInt32(client_port); else ! nulls[10] = true; } else { *************** pg_stat_get_backend_client_addr(PG_FUNCT *** 881,889 **** { int32 beid = PG_GETARG_INT32(0); PgBackendStatus *beentry; ! SockAddr zero_clientaddr; ! char remote_host[NI_MAXHOST]; ! int ret; if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); --- 836,842 ---- { int32 beid = PG_GETARG_INT32(0); PgBackendStatus *beentry; ! inet *client_addr; if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); *************** pg_stat_get_backend_client_addr(PG_FUNCT *** 891,926 **** if (!superuser() && beentry->st_userid != GetUserId()) PG_RETURN_NULL(); ! /* A zeroed client addr means we don't know */ ! memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); ! if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr, ! sizeof(zero_clientaddr) == 0)) ! PG_RETURN_NULL(); ! ! switch (beentry->st_clientaddr.addr.ss_family) ! { ! case AF_INET: ! #ifdef HAVE_IPV6 ! case AF_INET6: ! #endif ! break; ! default: ! PG_RETURN_NULL(); ! } ! ! remote_host[0] = '\0'; ! ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr, ! beentry->st_clientaddr.salen, ! remote_host, sizeof(remote_host), ! NULL, 0, ! NI_NUMERICHOST | NI_NUMERICSERV); ! if (ret) PG_RETURN_NULL(); - - clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host); - - PG_RETURN_INET_P(DirectFunctionCall1(inet_in, - CStringGetDatum(remote_host))); } Datum --- 844,854 ---- if (!superuser() && beentry->st_userid != GetUserId()) PG_RETURN_NULL(); ! get_host_and_port(&beentry->st_clientaddr, &client_addr, NULL); ! if (client_addr) ! PG_RETURN_INET_P(client_addr); ! else PG_RETURN_NULL(); } Datum *************** pg_stat_get_backend_client_port(PG_FUNCT *** 928,936 **** { int32 beid = PG_GETARG_INT32(0); PgBackendStatus *beentry; ! SockAddr zero_clientaddr; ! char remote_port[NI_MAXSERV]; ! int ret; if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); --- 856,862 ---- { int32 beid = PG_GETARG_INT32(0); PgBackendStatus *beentry; ! int client_port; if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL) PG_RETURN_NULL(); *************** pg_stat_get_backend_client_port(PG_FUNCT *** 938,973 **** if (!superuser() && beentry->st_userid != GetUserId()) PG_RETURN_NULL(); ! /* A zeroed client addr means we don't know */ ! memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); ! if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr, ! sizeof(zero_clientaddr) == 0)) ! PG_RETURN_NULL(); ! ! switch (beentry->st_clientaddr.addr.ss_family) ! { ! case AF_INET: ! #ifdef HAVE_IPV6 ! case AF_INET6: ! #endif ! break; ! case AF_UNIX: ! PG_RETURN_INT32(-1); ! default: ! PG_RETURN_NULL(); ! } ! ! remote_port[0] = '\0'; ! ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr, ! beentry->st_clientaddr.salen, ! NULL, 0, ! remote_port, sizeof(remote_port), ! NI_NUMERICHOST | NI_NUMERICSERV); ! if (ret) PG_RETURN_NULL(); - - PG_RETURN_DATUM(DirectFunctionCall1(int4in, - CStringGetDatum(remote_port))); } --- 864,874 ---- if (!superuser() && beentry->st_userid != GetUserId()) PG_RETURN_NULL(); ! get_host_and_port(&beentry->st_clientaddr, NULL, &client_port); ! if (client_port != 0) ! PG_RETURN_INT32(client_port); ! else PG_RETURN_NULL(); } *************** pg_stat_reset_single_function_counters(P *** 1515,1517 **** --- 1416,1485 ---- PG_RETURN_VOID(); } + + /* + * Get host and port in the SockAddr. Out parameters can be NULLs. + */ + static void + get_host_and_port(const SockAddr *addr, inet **host, int *port) + { + SockAddr zero_clientaddr; + + if (host) + *host = NULL; + if (port) + *port = 0; + + /* A zeroed client addr means we don't know */ + memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); + if (memcmp(addr, &zero_clientaddr, sizeof(zero_clientaddr)) == 0) + return; + + if (addr->addr.ss_family == AF_INET + #ifdef HAVE_IPV6 + || addr->addr.ss_family == AF_INET6 + #endif + ) + { + char remote_host[NI_MAXHOST]; + char remote_port[NI_MAXSERV]; + int ret; + + if (host) + remote_host[0] = '\0'; + if (port) + remote_port[0] = '\0'; + ret = pg_getnameinfo_all(&addr->addr, + addr->salen, + host ? remote_host : NULL, + host ? sizeof(remote_host) : 0, + port ? remote_port : NULL, + port ? sizeof(remote_port) : 0, + NI_NUMERICHOST | NI_NUMERICSERV); + if (ret == 0) + { + if (host) + { + clean_ipv6_addr(addr->addr.ss_family, remote_host); + *host = DatumGetInetP(DirectFunctionCall1(inet_in, + CStringGetDatum(remote_host))); + } + if (port) + *port = atoi(remote_port); + } + } + else if (addr->addr.ss_family == AF_UNIX) + { + /* + * Unix sockets always reports NULL for host and -1 for port, + * so it's possible to tell the difference to connections we + * have no permissions to view, or with errors. + */ + if (port) + *port = -1; + } + else + { + /* Unknown address type, should never happen */ + } + }