diff --git a/configure b/configure
index 5c6022903d..a8c5923118 100755
--- a/configure
+++ b/configure
@@ -18852,8 +18852,7 @@ fi
 
 
 
-
-for ac_func in cbrt dlopen fcvt fdatasync getifaddrs getpeereid getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l
+for ac_func in cbrt dlopen fcvt fdatasync getifaddrs getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l
 do
 as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -20424,7 +20423,8 @@ LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
 
 
 
-for ac_func in crypt erand48 getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul
+
+for ac_func in crypt erand48 getopt getpeereid getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul
 do
 as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
diff --git a/configure.in b/configure.in
index ed2d17d219..6a7278aefe 100644
--- a/configure.in
+++ b/configure.in
@@ -1191,7 +1191,7 @@ PGAC_VAR_INT_TIMEZONE
 AC_FUNC_ACCEPT_ARGTYPES
 PGAC_FUNC_GETTIMEOFDAY_1ARG
 
-AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getifaddrs getpeereid getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l])
+AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getifaddrs getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l])
 
 AC_REPLACE_FUNCS(fseeko)
 case $host_os in
@@ -1310,7 +1310,7 @@ fi
 pgac_save_LIBS="$LIBS"
 LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
 
-AC_REPLACE_FUNCS([crypt erand48 getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul])
+AC_REPLACE_FUNCS([crypt erand48 getopt getpeereid getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul])
 
 case $host_os in
 
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index dc7ad2cadf..f4099ac234 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -17,12 +17,6 @@
 
 #include <sys/param.h>
 #include <sys/socket.h>
-#ifdef HAVE_UCRED_H
-#include <ucred.h>
-#endif
-#ifdef HAVE_SYS_UCRED_H
-#include <sys/ucred.h>
-#endif
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <unistd.h>
@@ -1756,84 +1750,24 @@ static int
 auth_peer(hbaPort *port)
 {
 	char		ident_user[IDENT_USERNAME_MAX + 1];
-	uid_t		uid = 0;
-	struct passwd *pass;
-
-#if defined(HAVE_GETPEEREID)
-	/* Most BSDen, including OS X: use getpeereid() */
+	uid_t		uid;
 	gid_t		gid;
+	struct passwd *pass;
 
 	errno = 0;
 	if (getpeereid(port->sock, &uid, &gid) != 0)
 	{
-		/* We didn't get a valid credentials struct. */
-		ereport(LOG,
-				(errcode_for_socket_access(),
-				 errmsg("could not get peer credentials: %m")));
+		/* Provide special error message if getpeereid is a stub */
+		if (errno == ENOSYS)
+			ereport(LOG,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("peer authentication is not supported on this platform")));
+		else
+			ereport(LOG,
+					(errcode_for_socket_access(),
+					 errmsg("could not get peer credentials: %m")));
 		return STATUS_ERROR;
 	}
-#elif defined(SO_PEERCRED)
-	/* Linux: use getsockopt(SO_PEERCRED) */
-	struct ucred peercred;
-	ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
-
-	errno = 0;
-	if (getsockopt(port->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
-		so_len != sizeof(peercred))
-	{
-		/* We didn't get a valid credentials struct. */
-		ereport(LOG,
-				(errcode_for_socket_access(),
-				 errmsg("could not get peer credentials: %m")));
-		return STATUS_ERROR;
-	}
-	uid = peercred.uid;
-#elif defined(LOCAL_PEERCRED)
-	/* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
-	struct xucred peercred;
-	ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
-
-	errno = 0;
-	if (getsockopt(port->sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
-		so_len != sizeof(peercred) ||
-		peercred.cr_version != XUCRED_VERSION)
-	{
-		/* We didn't get a valid credentials struct. */
-		ereport(LOG,
-				(errcode_for_socket_access(),
-				 errmsg("could not get peer credentials: %m")));
-		return STATUS_ERROR;
-	}
-	uid = peercred.cr_uid;
-#elif defined(HAVE_GETPEERUCRED)
-	/* Solaris: use getpeerucred() */
-	ucred_t    *ucred;
-
-	ucred = NULL;				/* must be initialized to NULL */
-	if (getpeerucred(port->sock, &ucred) == -1)
-	{
-		ereport(LOG,
-				(errcode_for_socket_access(),
-				 errmsg("could not get peer credentials: %m")));
-		return STATUS_ERROR;
-	}
-
-	if ((uid = ucred_geteuid(ucred)) == -1)
-	{
-		ereport(LOG,
-				(errcode_for_socket_access(),
-		   errmsg("could not get effective UID from peer credentials: %m")));
-		return STATUS_ERROR;
-	}
-
-	ucred_free(ucred);
-#else
-	ereport(LOG,
-			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-			 errmsg("Peer authentication is not supported on local connections on this platform")));
-
-	return STATUS_ERROR;
-#endif
 
 	pass = getpwuid(uid);
 
diff --git a/src/include/port.h b/src/include/port.h
index 6ea681f16a..d7295e3132 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -395,6 +395,10 @@ extern void srand48(long seed);
 extern int	getopt(int nargc, char *const * nargv, const char *ostr);
 #endif
 
+#ifndef HAVE_GETPEEREID
+extern int	getpeereid(int sock, uid_t *uid, gid_t *gid);
+#endif
+
 #ifndef HAVE_ISINF
 extern int	isinf(double x);
 #endif
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 5a6502fff4..9aa6ca01eb 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -21,12 +21,6 @@
 #include <ctype.h>
 #include <time.h>
 #include <unistd.h>
-#ifdef HAVE_UCRED_H
-#include <ucred.h>
-#endif
-#ifdef HAVE_SYS_UCRED_H
-#include <sys/ucred.h>
-#endif
 
 #include "libpq-fe.h"
 #include "libpq-int.h"
@@ -1859,6 +1853,7 @@ keep_going:						/* We will come back to here until there is
 				char	   *startpacket;
 				int			packetlen;
 
+#ifdef HAVE_UNIX_SOCKETS
 				/*
 				 * Implement requirepeer check, if requested and it's a
 				 * Unix-domain socket.
@@ -1866,82 +1861,25 @@ keep_going:						/* We will come back to here until there is
 				if (conn->requirepeer && conn->requirepeer[0] &&
 					IS_AF_UNIX(conn->raddr.addr.ss_family))
 				{
-#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(LOCAL_PEERCRED) || defined(HAVE_GETPEERUCRED)
 					char		pwdbuf[BUFSIZ];
 					struct passwd pass_buf;
 					struct passwd *pass;
 					uid_t		uid;
-
-#if defined(HAVE_GETPEEREID)
-					/* Most BSDen, including OS X: use getpeereid() */
 					gid_t		gid;
 
 					errno = 0;
 					if (getpeereid(conn->sock, &uid, &gid) != 0)
 					{
-						appendPQExpBuffer(&conn->errorMessage,
-						libpq_gettext("could not get peer credentials: %s\n"),
-									pqStrerror(errno, sebuf, sizeof(sebuf)));
+						/* Provide special error message if getpeereid is a stub */
+						if (errno == ENOSYS)
+							appendPQExpBuffer(&conn->errorMessage,
+											  libpq_gettext("requirepeer parameter is not supported on this platform\n"));
+						else
+							appendPQExpBuffer(&conn->errorMessage,
+											  libpq_gettext("could not get peer credentials: %s\n"),
+											  pqStrerror(errno, sebuf, sizeof(sebuf)));
 						goto error_return;
 					}
-#elif defined(SO_PEERCRED)
-					/* Linux: use getsockopt(SO_PEERCRED) */
-					struct ucred peercred;
-					ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
-
-					errno = 0;
-					if (getsockopt(conn->sock, SOL_SOCKET, SO_PEERCRED,
-								   &peercred, &so_len) != 0 ||
-						so_len != sizeof(peercred))
-					{
-						appendPQExpBuffer(&conn->errorMessage,
-						libpq_gettext("could not get peer credentials: %s\n"),
-									pqStrerror(errno, sebuf, sizeof(sebuf)));
-						goto error_return;
-					}
-					uid = peercred.uid;
-#elif defined(LOCAL_PEERCRED)
-					/* Debian with FreeBSD kernel: use LOCAL_PEERCRED */
-					struct xucred peercred;
-					ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
-
-					errno = 0;
-					if (getsockopt(conn->sock, 0, LOCAL_PEERCRED,
-								   &peercred, &so_len) != 0 ||
-						so_len != sizeof(peercred) ||
-						peercred.cr_version != XUCRED_VERSION)
-					{
-						appendPQExpBuffer(&conn->errorMessage,
-						libpq_gettext("could not get peer credentials: %s\n"),
-									pqStrerror(errno, sebuf, sizeof(sebuf)));
-						goto error_return;
-					}
-					uid = peercred.cr_uid;
-#elif defined(HAVE_GETPEERUCRED)
-					/* Solaris: use getpeerucred() */
-					ucred_t    *ucred;
-
-					ucred = NULL;		/* must be initialized to NULL */
-					if (getpeerucred(conn->sock, &ucred) == -1)
-					{
-						appendPQExpBuffer(&conn->errorMessage,
-						libpq_gettext("could not get peer credentials: %s\n"),
-									pqStrerror(errno, sebuf, sizeof(sebuf)));
-						goto error_return;
-					}
-
-					if ((uid = ucred_geteuid(ucred)) == -1)
-					{
-						appendPQExpBuffer(&conn->errorMessage,
-										  libpq_gettext("could not get effective UID from peer credentials: %s\n"),
-									pqStrerror(errno, sebuf, sizeof(sebuf)));
-						ucred_free(ucred);
-						goto error_return;
-					}
-					ucred_free(ucred);
-#else
-#error missing implementation method for requirepeer
-#endif
 
 					pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
 
@@ -1960,12 +1898,8 @@ keep_going:						/* We will come back to here until there is
 										  conn->requirepeer, pass->pw_name);
 						goto error_return;
 					}
-#else							/* can't support requirepeer */
-					appendPQExpBuffer(&conn->errorMessage,
-									  libpq_gettext("requirepeer parameter is not supported on this platform\n"));
-					goto error_return;
-#endif
 				}
+#endif /* HAVE_UNIX_SOCKETS */
 
 #ifdef USE_SSL
 
diff --git a/src/port/getpeereid.c b/src/port/getpeereid.c
new file mode 100644
index 0000000000..3b826f01e8
--- /dev/null
+++ b/src/port/getpeereid.c
@@ -0,0 +1,80 @@
+/*-------------------------------------------------------------------------
+ *
+ * getpeereid.c
+ *		get peer userid for UNIX-domain socket connection
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *	  src/port/getpeereid.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+
+
+/*
+ * BSD-style getpeereid() for platforms that lack it.
+ */
+int
+getpeereid(int sock, uid_t *uid, gid_t *gid)
+{
+#if defined(SO_PEERCRED)
+	/* Linux: use getsockopt(SO_PEERCRED) */
+	struct ucred peercred;
+	ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+
+	if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
+		so_len != sizeof(peercred))
+		return -1;
+	*uid = peercred.uid;
+	*gid = peercred.gid;
+	return 0;
+#elif defined(LOCAL_PEERCRED)
+	/* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
+	struct xucred peercred;
+	ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+
+	if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
+		so_len != sizeof(peercred) ||
+		peercred.cr_version != XUCRED_VERSION)
+		return -1;
+	*uid = peercred.cr_uid;
+	*gid = peercred.cr_gid;
+	return 0;
+#elif defined(HAVE_GETPEERUCRED)
+	/* Solaris: use getpeerucred() */
+	ucred_t    *ucred;
+
+	ucred = NULL;				/* must be initialized to NULL */
+	if (getpeerucred(sock, &ucred) == -1)
+		return -1;
+
+	*uid = ucred_geteuid(ucred);
+	*gid = ucred_getegid(ucred);
+	ucred_free(ucred);
+
+	if (*uid == (pid_t)(-1) || *gid == (gid_t)(-1))
+		return -1;
+	return 0;
+#else
+	/* No implementation available on this platform */
+	errno = ENOSYS;
+	return -1;
+#endif
+}