In stock PostgreSQL, you can get the database name, the username, but not the address that the client is connecting from (a very, very useful piece of data).

Function:               inet_client_addr()
Args:           none
Return type:    INET (null on AF_UNIX or some catastrophic failure)
IPv6 safe:      yes

The attached patch includes documentation and the relevant code. If there aren't any problems, I think this patch is ready to be committed.

If someone wants a way to return the path of AF_UNIX connections, I firmly believe that it should live in a similar, but different function, otherwise PL code (or whatever) will have to tease out whether it's a local or remote connection. Not that I think demand is there for it, but if need be, there should be two more functions written: unix_client_addr() and just client_addr(). unix_client_addr() returns TEXT and the path to the socket and client_addr() returns a TEXT wrapped version of whatever is in MyProcPort->remote_host. -sc

Index: src/backend/utils/adt/network.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/network.c,v
retrieving revision 1.49
diff -u -r1.49 network.c
--- src/backend/utils/adt/network.c     1 Dec 2003 18:50:19 -0000       1.49
+++ src/backend/utils/adt/network.c     14 May 2004 22:04:22 -0000
@@ -14,7 +14,9 @@
 #include <arpa/inet.h>
 
 #include "catalog/pg_type.h"
+#include "libpq/libpq-be.h"
 #include "libpq/pqformat.h"
+#include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/inet.h"
 
@@ -128,6 +130,26 @@
        char       *src = PG_GETARG_CSTRING(0);
 
        PG_RETURN_INET_P(network_in(src, 1));
+}
+
+/* INET that the client is connecting from */
+Datum
+inet_client_addr(PG_FUNCTION_ARGS)
+{
+  if (MyProcPort == NULL)
+    PG_RETURN_NULL();
+
+  switch (MyProcPort->raddr.addr.ss_family) {
+  case AF_INET:
+#ifdef HAVE_IPV6
+  case AF_INET6:
+#endif
+    break;
+  default:
+    PG_RETURN_NULL();
+  }
+
+  PG_RETURN_INET_P(network_in(MyProcPort->remote_host, 0));
 }
 
 /*
Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/func.sgml,v
retrieving revision 1.201
diff -u -r1.201 func.sgml
--- doc/src/sgml/func.sgml      10 May 2004 22:44:42 -0000      1.201
+++ doc/src/sgml/func.sgml      14 May 2004 22:04:23 -0000
@@ -6583,6 +6583,12 @@
       </row>
 
       <row>
+       <entry><function>inet_client_addr</function></entry>
+       <entry><type>inet</type></entry>
+       <entry>address of the remote connection</entry>
+      </row>
+
+      <row>
        <entry><function>session_user</function></entry>
        <entry><type>name</type></entry>
        <entry>session user name</entry>
@@ -6636,6 +6642,14 @@
      they must be called without trailing parentheses.
     </para>
    </note>
+
+   <para>
+     <function>inet_client_addr</function> returns the IPv4 or IPv6
+     (if configured) address of the host connecting to the database.
+     If the connection is local and not a network connection,
+     <function>inet_client_addr</function> returns
+     <literal>NULL</literal>.
+   </para>
 
    <para>
     <function>current_schema</function> returns the name of the schema that is
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
retrieving revision 1.328
diff -u -r1.328 pg_proc.h
--- src/include/catalog/pg_proc.h       7 May 2004 16:57:16 -0000       1.328
+++ src/include/catalog/pg_proc.h       14 May 2004 22:04:25 -0000
@@ -2343,6 +2343,8 @@
 DESCR("I/O");
 DATA(insert OID = 911 (  inet_out                      PGNSP PGUID 12 f f t f i 1 
2275 "869" _null_  inet_out - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 912 (  inet_client_addr              PGNSP PGUID 12 f f f f s 0 869 
"" _null_  inet_client_addr - _null_ ));
+DESCR("Returns the INET address of the client connected to the backend");
 
 /* for cidr type support */
 DATA(insert OID = 1267 (  cidr_in                      PGNSP PGUID 12 f f t f i 1 650 
"2275" _null_  cidr_in - _null_ ));
Index: src/include/utils/builtins.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/utils/builtins.h,v
retrieving revision 1.237
diff -u -r1.237 builtins.h
--- src/include/utils/builtins.h        5 May 2004 04:48:47 -0000       1.237
+++ src/include/utils/builtins.h        14 May 2004 22:04:25 -0000
@@ -645,6 +645,7 @@
                          void *dst, size_t size);
 
 /* network.c */
+extern Datum inet_client_addr(PG_FUNCTION_ARGS);
 extern Datum inet_in(PG_FUNCTION_ARGS);
 extern Datum inet_out(PG_FUNCTION_ARGS);
 extern Datum inet_recv(PG_FUNCTION_ARGS);


% psql -h 192.168.102.100 template1
template1=# SELECT inet_client_addr();
 inet_client_addr
------------------
 192.168.102.100
(1 row)

template1=# \q
% echo $PGHOST
tcsh: PGHOST: Undefined variable.
% psql template1
template1=# SELECT inet_client_addr();
 inet_client_addr
------------------

(1 row)

template1=# SELECT inet_client_addr() IS NULL;
 ?column?
----------
 t
(1 row)

template1=# \q
% psql -h 127.0.0.1 template1
template1=# SELECT inet_client_addr() IS NULL;
 ?column?
----------
 f
(1 row)

template1=# SELECT inet_client_addr();
 inet_client_addr
------------------
 127.0.0.1
(1 row)

template1=# \q
% psql -h localhost template1
template1=# SELECT inet_client_addr();
 inet_client_addr
------------------
 ::1
(1 row)

--
Sean Chittenden
---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend

Reply via email to