Blah, well, guess I do need the server's address after all. The attached patch includes:

*) inet_(client|server)_(addr|port)() and necessary documentation for the four functions.
*) area(PATH) and documentation.
*) Checks for TEMP privs when creating objects in the temp schema (checks for any object created in a temp namespace).
*) With the above change, current_user is now being used to check if CREATE TEMP TABLE should succeed.
*) Now cleaning up failed getaddrinfo_all() calls.
*) The check for hintp being null has been removed, all calls to getaddrinfo_all() are passing non-null hintp's.
*) Changed some freeaddrinfo_all() calls to make sure that the addrinfo struct is non-null. getaddrinfo_all() can fail and return a null addrinfo struct and can fail with a non-null addrinfo struct.
*) Updated an error message to include the library path that failed (handy for debugging old configs that contain $lib instead of $libdir)
*) warn if getaddrinfo_all() fails on postmaster startup.
*) Functions have been updated to be inline with PostgreSQL's style too.


Comments or feedback?

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

test=# SELECT inet_client_port();
 inet_client_port
------------------
            52711
(1 row)

test=# SELECT inet_server_port();
 inet_server_port
------------------
             5432
(1 row)

test=# SELECT inet_server_addr();
 inet_server_addr
------------------
 127.0.0.1
(1 row)

Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/func.sgml,v
retrieving revision 1.202
diff -u -r1.202 func.sgml
--- doc/src/sgml/func.sgml      14 May 2004 21:42:27 -0000      1.202
+++ doc/src/sgml/func.sgml      18 May 2004 18:59:37 -0000
@@ -6593,6 +6593,30 @@
       </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>inet_client_port</function></entry>
+       <entry><type>int4</type></entry>
+       <entry>port of the remote connection</entry>
+      </row>
+
+      <row>
+       <entry><function>inet_server_addr</function></entry>
+       <entry><type>inet</type></entry>
+       <entry>address of the local connection</entry>
+      </row>
+
+      <row>
+       <entry><function>inet_server_port</function></entry>
+       <entry><type>int4</type></entry>
+       <entry>port of the local connection</entry>
+      </row>
+
+      <row>
        <entry><function>session_user</function></entry>
        <entry><type>name</type></entry>
        <entry>session user name</entry>
@@ -6646,6 +6670,17 @@
      they must be called without trailing parentheses.
     </para>
    </note>
+
+   <para>
+     <function>inet_client_addr</function> and
+     <function>inet_server_addr</function> return the IPv4 or IPv6 (if
+     configured) address of the remote or local host connecting to the
+     database, respectively.  <function>inet_client_port</function>
+     and <function>inet_server_port</function> return the port number
+     of the remote or local host connecting to the database,
+     respectively.  If the connection is not a network connection,
+     these functions will return <literal>NULL</literal>.
+   </para>
 
    <para>
     <function>current_schema</function> returns the name of the schema that is
Index: src/backend/catalog/aclchk.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/catalog/aclchk.c,v
retrieving revision 1.98
diff -u -r1.98 aclchk.c
--- src/backend/catalog/aclchk.c        11 May 2004 17:36:12 -0000      1.98
+++ src/backend/catalog/aclchk.c        18 May 2004 18:59:37 -0000
@@ -1342,16 +1342,26 @@
        bool            isNull;
        Acl                *acl;
 
-       /*
-        * If we have been assigned this namespace as a temp namespace, assume
-        * we have all grantable privileges on it.
-        */
-       if (isTempNamespace(nsp_oid))
-               return mask;
-
        /* Superusers bypass all permission checking. */
        if (superuser_arg(userid))
                return mask;
+
+       /*
+        * If we have been assigned this namespace as a temp
+        * namespace, check to make sure we have CREATE permissions on
+        * the database.
+        *
+        * Instead of returning ACLCHECK_NO_PRIV, should we return via
+        * ereport() with a message about trying to create an object
+        * in a TEMP namespace when GetUserId() doesn't have perms?
+        */
+       if (isTempNamespace(nsp_oid)) {
+         if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
+                                  ACL_CREATE_TEMP) == ACLCHECK_OK)
+           return ACLCHECK_OK;
+         else
+           return ACLCHECK_NO_PRIV;
+       }
 
        /*
         * Get the schema's ACL from pg_namespace
Index: src/backend/catalog/namespace.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/catalog/namespace.c,v
retrieving revision 1.63
diff -u -r1.63 namespace.c
--- src/backend/catalog/namespace.c     13 Feb 2004 01:08:20 -0000      1.63
+++ src/backend/catalog/namespace.c     18 May 2004 18:59:38 -0000
@@ -1640,11 +1640,11 @@
         * tables.      We use a nonstandard error message here since
         * "databasename: permission denied" might be a tad cryptic.
         *
-        * Note we apply the check to the session user, not the currently active
-        * userid, since we are not going to change our minds about temp table
-        * availability during the session.
+        * ACL_CREATE_TEMP perms are also checked in
+        * pg_namespace_aclcheck() that way only users who have TEMP
+        * perms can create objects.
         */
-       if (pg_database_aclcheck(MyDatabaseId, GetSessionUserId(),
+       if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
                                                         ACL_CREATE_TEMP) != 
ACLCHECK_OK)
                ereport(ERROR,
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
Index: src/backend/libpq/hba.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/hba.c,v
retrieving revision 1.120
diff -u -r1.120 hba.c
--- src/backend/libpq/hba.c     2 Feb 2004 16:58:30 -0000       1.120
+++ src/backend/libpq/hba.c     18 May 2004 18:59:38 -0000
@@ -1296,8 +1296,11 @@
        hints.ai_addr = NULL;
        hints.ai_next = NULL;
        rc = getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
-       if (rc || !ident_serv)
+       if (rc || !ident_serv) {
+               if (ident_serv)
+                       freeaddrinfo_all(hints.ai_family, ident_serv);
                return false;                   /* we don't expect this to happen */
+       }
 
        hints.ai_flags = AI_NUMERICHOST;
        hints.ai_family = local_addr.addr.ss_family;
@@ -1308,8 +1311,11 @@
        hints.ai_addr = NULL;
        hints.ai_next = NULL;
        rc = getaddrinfo_all(local_addr_s, NULL, &hints, &la);
-       if (rc || !la)
+       if (rc || !la) {
+               if (la)
+                       freeaddrinfo_all(hints.ai_family, la);
                return false;                   /* we don't expect this to happen */
+       }
 
        sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
                                         ident_serv->ai_protocol);
Index: src/backend/libpq/ip.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/ip.c,v
retrieving revision 1.25
diff -u -r1.25 ip.c
--- src/backend/libpq/ip.c      24 Apr 2004 20:10:34 -0000      1.25
+++ src/backend/libpq/ip.c      18 May 2004 18:59:38 -0000
@@ -73,11 +73,11 @@
        *result = NULL;
 
 #ifdef HAVE_UNIX_SOCKETS
-       if (hintp != NULL && hintp->ai_family == AF_UNIX)
+       if (hintp->ai_family == AF_UNIX)
                return getaddrinfo_unix(servname, hintp, result);
 #endif
 
-       /* NULL has special meaning to getaddrinfo */
+       /* NULL has special meaning to getaddrinfo(). */
        return getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname,
                                           servname, hintp, result);
 }
Index: src/backend/libpq/pqcomm.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/pqcomm.c,v
retrieving revision 1.168
diff -u -r1.168 pqcomm.c
--- src/backend/libpq/pqcomm.c  12 Dec 2003 18:45:08 -0000      1.168
+++ src/backend/libpq/pqcomm.c  18 May 2004 18:59:38 -0000
@@ -251,7 +251,8 @@
                        ereport(LOG,
                         (errmsg("could not translate service \"%s\" to address: %s",
                                         service, gai_strerror(ret))));
-               freeaddrinfo_all(hint.ai_family, addrs);
+               if (addrs)
+                       freeaddrinfo_all(hint.ai_family, addrs);
                return STATUS_ERROR;
        }
 
Index: src/backend/utils/adt/geo_ops.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/geo_ops.c,v
retrieving revision 1.84
diff -u -r1.84 geo_ops.c
--- src/backend/utils/adt/geo_ops.c     12 May 2004 22:38:44 -0000      1.84
+++ src/backend/utils/adt/geo_ops.c     18 May 2004 18:59:40 -0000
@@ -1313,6 +1313,27 @@
  *---------------------------------------------------------*/
 
 Datum
+path_area(PG_FUNCTION_ARGS)
+{
+       PATH    *path = PG_GETARG_PATH_P(0);
+       double  area = 0.0;
+       int i,j;
+
+       if (!path->closed)
+               PG_RETURN_NULL();
+
+       for (i = 0; i < path->npts; i++) {
+               j = (i + 1) % path->npts;
+               area += path->p[i].x * path->p[j].y;
+               area -= path->p[i].y * path->p[j].x;
+       }
+
+       area *= 0.5;
+       PG_RETURN_FLOAT8(area < 0.0 ? -area : area);
+}
+
+
+Datum
 path_in(PG_FUNCTION_ARGS)
 {
        char       *str = PG_GETARG_CSTRING(0);
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     18 May 2004 18:59:40 -0000
@@ -14,7 +14,10 @@
 #include <arpa/inet.h>
 
 #include "catalog/pg_type.h"
+#include "libpq/ip.h"
+#include "libpq/libpq-be.h"
 #include "libpq/pqformat.h"
+#include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/inet.h"
 
@@ -129,6 +132,110 @@
 
        PG_RETURN_INET_P(network_in(src, 1));
 }
+
+/* INET that the client is connecting from */
+Datum
+inet_client_addr(PG_FUNCTION_ARGS)
+{
+       Port *port = MyProcPort;
+
+       if (port == NULL)
+               PG_RETURN_NULL();
+
+       switch (port->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(port->remote_host, 0));
+}
+
+
+/* port that the client is connecting from */
+Datum
+inet_client_port(PG_FUNCTION_ARGS)
+{
+       Port *port = MyProcPort;
+
+       if (port == NULL)
+               PG_RETURN_NULL();
+
+       PG_RETURN_INT32(DirectFunctionCall1(int4in, 
CStringGetDatum(port->remote_port)));
+}
+
+
+/* server INET that the client connected to */
+Datum
+inet_server_addr(PG_FUNCTION_ARGS)
+{
+       Port *port = MyProcPort;
+       char    local_host[NI_MAXHOST];
+       int     ret;
+
+       if (port == NULL)
+               PG_RETURN_NULL();
+
+       switch (port->laddr.addr.ss_family) {
+       case AF_INET:
+#ifdef HAVE_IPV6
+       case AF_INET6:
+#endif
+         break;
+       default:
+               PG_RETURN_NULL();
+       }
+
+       local_host[0] = '\0';
+
+       ret = getnameinfo_all(&port->laddr.addr, port->laddr.salen,
+                             local_host, sizeof(local_host),
+                             NULL, 0,
+                             NI_NUMERICHOST | NI_NUMERICSERV);
+       if (ret)
+               PG_RETURN_NULL();
+
+       PG_RETURN_INET_P(network_in(local_host, 0));
+}
+
+
+/* port that the server accepted the connection on */
+Datum
+inet_server_port(PG_FUNCTION_ARGS)
+{
+       Port *port = MyProcPort;
+       char    local_port[NI_MAXSERV];
+       int     ret;
+
+       if (port == NULL)
+               PG_RETURN_NULL();
+
+       switch (port->laddr.addr.ss_family) {
+       case AF_INET:
+#ifdef HAVE_IPV6
+       case AF_INET6:
+#endif
+         break;
+       default:
+               PG_RETURN_NULL();
+       }
+
+       local_port[0] = '\0';
+
+       ret = getnameinfo_all(&port->laddr.addr, port->laddr.salen,
+                             NULL, 0,
+                             local_port, sizeof(local_port),
+                             NI_NUMERICHOST | NI_NUMERICSERV);
+       if (ret)
+               PG_RETURN_NULL();
+
+       PG_RETURN_INT32(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
+}
+
 
 /*
  *     INET address output function.
Index: src/backend/utils/fmgr/dfmgr.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/fmgr/dfmgr.c,v
retrieving revision 1.72
diff -u -r1.72 dfmgr.c
--- src/backend/utils/fmgr/dfmgr.c      17 May 2004 14:35:31 -0000      1.72
+++ src/backend/utils/fmgr/dfmgr.c      18 May 2004 18:59:40 -0000
@@ -350,7 +350,7 @@
                strncmp(name, "$libdir", strlen("$libdir")) != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_NAME),
-                                errmsg("invalid macro name in dynamic library 
path")));
+                                errmsg("invalid macro name in dynamic library path: 
%s", name)));
 
        ret = palloc(strlen(pkglib_path) + strlen(sep_ptr) + 1);
 
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
retrieving revision 1.329
diff -u -r1.329 pg_proc.h
--- src/include/catalog/pg_proc.h       14 May 2004 21:42:28 -0000      1.329
+++ src/include/catalog/pg_proc.h       18 May 2004 18:59:41 -0000
@@ -1259,6 +1259,8 @@
 DESCR("box height");
 DATA(insert OID = 978 (  box_distance     PGNSP PGUID 12 f f t f i 2 701 "603 603" 
_null_  box_distance - _null_ ));
 DESCR("distance between boxes");
+DATA(insert OID = 979 (  area                     PGNSP PGUID 12 f f t f i 1 701 
"602" _null_  path_area - _null_ ));
+DESCR("area of a closed path");
 DATA(insert OID = 980 (  box_intersect    PGNSP PGUID 12 f f t f i 2 603 "603 603" 
_null_  box_intersect - _null_ ));
 DESCR("box intersection (another box)");
 DATA(insert OID = 981 (  diagonal                 PGNSP PGUID 12 f f t f i 1 601 
"603" _null_  box_diagonal - _null_ ));
@@ -2343,6 +2345,15 @@
 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");
+DATA(insert OID = 913 (  inet_client_port              PGNSP PGUID 12 f f f f s 0 23 
"" _null_  inet_client_port - _null_ ));
+DESCR("Returns the client's port number for this connection");
+DATA(insert OID = 914 (  inet_server_addr              PGNSP PGUID 12 f f f f s 0 869 
"" _null_  inet_server_addr - _null_ ));
+DESCR("Returns the INET address that the backend is using to service the connection");
+DATA(insert OID = 915 (  inet_server_port              PGNSP PGUID 12 f f f f s 0 23 
"" _null_  inet_server_port - _null_ ));
+DESCR("Returns the servers's port number for this connection");
 
 /* 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.238
diff -u -r1.238 builtins.h
--- src/include/utils/builtins.h        14 May 2004 21:42:30 -0000      1.238
+++ src/include/utils/builtins.h        18 May 2004 18:59:41 -0000
@@ -645,6 +645,10 @@
                          void *dst, size_t size);
 
 /* network.c */
+extern Datum inet_client_addr(PG_FUNCTION_ARGS);
+extern Datum inet_client_port(PG_FUNCTION_ARGS);
+extern Datum inet_server_addr(PG_FUNCTION_ARGS);
+extern Datum inet_server_port(PG_FUNCTION_ARGS);
 extern Datum inet_in(PG_FUNCTION_ARGS);
 extern Datum inet_out(PG_FUNCTION_ARGS);
 extern Datum inet_recv(PG_FUNCTION_ARGS);
Index: src/include/utils/geo_decls.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/utils/geo_decls.h,v
retrieving revision 1.43
diff -u -r1.43 geo_decls.h
--- src/include/utils/geo_decls.h       29 Nov 2003 22:41:15 -0000      1.43
+++ src/include/utils/geo_decls.h       18 May 2004 18:59:41 -0000
@@ -305,6 +305,7 @@
 extern Datum box_div(PG_FUNCTION_ARGS);
 
 /* public path routines */
+extern Datum path_area(PG_FUNCTION_ARGS);
 extern Datum path_in(PG_FUNCTION_ARGS);
 extern Datum path_out(PG_FUNCTION_ARGS);
 extern Datum path_recv(PG_FUNCTION_ARGS);
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.269
diff -u -r1.269 fe-connect.c
--- src/interfaces/libpq/fe-connect.c   24 Mar 2004 03:44:59 -0000      1.269
+++ src/interfaces/libpq/fe-connect.c   18 May 2004 18:59:42 -0000
@@ -945,7 +945,8 @@
                        printfPQExpBuffer(&conn->errorMessage,
                                                          libpq_gettext("could not 
translate Unix-domain socket path \"%s\" to address: %s\n"),
                                                          portstr, gai_strerror(ret));
-               freeaddrinfo_all(hint.ai_family, addrs);
+               if (addrs)
+                       freeaddrinfo_all(hint.ai_family, addrs);
                goto connect_errReturn;
        }
 
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v
retrieving revision 1.388
diff -u -r1.388 postmaster.c
--- src/backend/postmaster/postmaster.c 17 May 2004 14:35:29 -0000      1.388
+++ src/backend/postmaster/postmaster.c 18 May 2004 19:24:37 -0000
@@ -2471,10 +2471,14 @@
                                                remote_port, sizeof(remote_port),
                                   (log_hostname ? 0 : NI_NUMERICHOST) | 
NI_NUMERICSERV))
        {
-               getnameinfo_all(&port->raddr.addr, port->raddr.salen,
+               int ret = getnameinfo_all(&port->raddr.addr, port->raddr.salen,
                                                remote_host, sizeof(remote_host),
                                                remote_port, sizeof(remote_port),
                                                NI_NUMERICHOST | NI_NUMERICSERV);
+               if (ret)
+                       ereport(WARNING,
+                               (errmsg("getnameinfo_all() failed: %s",
+                                       gai_strerror(ret))));
        }
        snprintf(remote_ps_data, sizeof(remote_ps_data),
                         remote_port[0] == '\0' ? "%s" : "%s(%s)",

-- Sean Chittenden
---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faqs/FAQ.html

Reply via email to