Commit dbb76935 authored by Tom Lane's avatar Tom Lane

Temporary fix for the problem that pg_stat_activity, inet_client_addr(),

and inet_server_addr() fail if the client connected over a "scoped" IPv6
address.  In this case getnameinfo() will return a string ending with
a poorly-standardized "%something" zone specifier, which these functions
try to feed to network_in(), which won't take it.  So that we don't lose
functionality altogether, suppress the zone specifier before giving the
string to network_in().  Per report from Brian Hirt.

TODO: probably someday the inet type should support scoped IPv6 addresses,
and then this patch should be reverted.

Backpatch to 8.2 ... is it worth going further?
parent 3f186a20
/* /*
* PostgreSQL type definitions for the INET and CIDR types. * PostgreSQL type definitions for the INET and CIDR types.
* *
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.69 2007/04/06 04:21:43 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.70 2007/05/17 23:31:49 tgl Exp $
* *
* Jon Postel RIP 16 Oct 1998 * Jon Postel RIP 16 Oct 1998
*/ */
...@@ -1142,6 +1142,8 @@ inet_client_addr(PG_FUNCTION_ARGS) ...@@ -1142,6 +1142,8 @@ inet_client_addr(PG_FUNCTION_ARGS)
if (ret) if (ret)
PG_RETURN_NULL(); PG_RETURN_NULL();
clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
PG_RETURN_INET_P(network_in(remote_host, false)); PG_RETURN_INET_P(network_in(remote_host, false));
} }
...@@ -1216,6 +1218,8 @@ inet_server_addr(PG_FUNCTION_ARGS) ...@@ -1216,6 +1218,8 @@ inet_server_addr(PG_FUNCTION_ARGS)
if (ret) if (ret)
PG_RETURN_NULL(); PG_RETURN_NULL();
clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
PG_RETURN_INET_P(network_in(local_host, false)); PG_RETURN_INET_P(network_in(local_host, false));
} }
...@@ -1479,3 +1483,32 @@ inetmi(PG_FUNCTION_ARGS) ...@@ -1479,3 +1483,32 @@ inetmi(PG_FUNCTION_ARGS)
PG_RETURN_INT64(res); PG_RETURN_INT64(res);
} }
/*
* clean_ipv6_addr --- remove any '%zone' part from an IPv6 address string
*
* XXX This should go away someday!
*
* This is a kluge needed because we don't yet support zones in stored inet
* values. Since the result of getnameinfo() might include a zone spec,
* call this to remove it anywhere we want to feed getnameinfo's output to
* network_in. Beats failing entirely.
*
* An alternative approach would be to let network_in ignore %-parts for
* itself, but that would mean we'd silently drop zone specs in user input,
* which seems not such a good idea.
*/
void
clean_ipv6_addr(int addr_family, char *addr)
{
#ifdef HAVE_IPV6
if (addr_family == AF_INET6)
{
char *pct = strchr(addr, '%');
if (pct)
*pct = '\0';
}
#endif
}
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.41 2007/03/30 18:34:55 mha Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.42 2007/05/17 23:31:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -550,6 +550,8 @@ pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS) ...@@ -550,6 +550,8 @@ pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
if (ret) if (ret)
PG_RETURN_NULL(); PG_RETURN_NULL();
clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
PG_RETURN_INET_P(DirectFunctionCall1(inet_in, PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
CStringGetDatum(remote_host))); CStringGetDatum(remote_host)));
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.292 2007/05/08 18:56:48 neilc Exp $ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.293 2007/05/17 23:31:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -797,6 +797,7 @@ extern Datum inetor(PG_FUNCTION_ARGS); ...@@ -797,6 +797,7 @@ extern Datum inetor(PG_FUNCTION_ARGS);
extern Datum inetpl(PG_FUNCTION_ARGS); extern Datum inetpl(PG_FUNCTION_ARGS);
extern Datum inetmi_int8(PG_FUNCTION_ARGS); extern Datum inetmi_int8(PG_FUNCTION_ARGS);
extern Datum inetmi(PG_FUNCTION_ARGS); extern Datum inetmi(PG_FUNCTION_ARGS);
extern void clean_ipv6_addr(int addr_family, char *addr);
/* mac.c */ /* mac.c */
extern Datum macaddr_in(PG_FUNCTION_ARGS); extern Datum macaddr_in(PG_FUNCTION_ARGS);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment