diff --git a/doc/guide/admin/runningslapd.sdf b/doc/guide/admin/runningslapd.sdf
index 4964b1785a6be89f604c8f3bf62bb65744d4f703..831a12c61eb7772a8aac90c31918374ad39e7a22 100644
--- a/doc/guide/admin/runningslapd.sdf
+++ b/doc/guide/admin/runningslapd.sdf
@@ -36,13 +36,23 @@ This option specifies alternative listener configurations. The
default is {{EX:ldap:///}} which implies {{TERM:LDAP}} over
{{TERM:TCP}} on all interfaces on the default LDAP port 389. You
can specify specific host-port pairs or other protocol schemes (such
-as {{EX:ldaps://}} or {{EX:ldapi://}}).
+as {{EX:ldaps://}} or {{EX:ldapi://}}). slapd supports the HAProxy
+proxy protocol version 2, which allows a load balancer or proxy
+server to provide the remote client IP address to slapd to be used
+for access control or logging. Listeners configured using either
+{{EX:pldap:///}} or {{EX:pldaps:///}} URLS will only accept
+connections that include the necessary proxy protocol header.
+Connections to the ports used by these listeners should be restricted
+at the network level to only trusted load balancers or proxies to
+avoid spoofing of client IP addresses by third parties.
!block table
-URL Protocol Transport
-ldap:/// LDAP TCP port 389
-ldaps:/// LDAP over SSL TCP port 636
-ldapi:/// LDAP IPC (Unix-domain socket)
+URL Protocol Transport
+ldap:/// LDAP TCP port 389
+pldap:/// proxied LDAP TCP port 389
+ldaps:/// LDAP over SSL TCP port 636
+pldaps:/// proxied LDAP over SSL TCP port 636
+ldapi:/// LDAP IPC (Unix-domain socket)
!endblock
For example, {{EX:-h
diff --git a/doc/man/man8/slapd.8 b/doc/man/man8/slapd.8
index 6ef1925c7de4c92c212ba3edc994ccec70c0ffba..267188ee520a82279040001ffb30e9ac0dbb2140 100644
--- a/doc/man/man8/slapd.8
+++ b/doc/man/man8/slapd.8
@@ -185,13 +185,21 @@ For example, if slapd is given
it will listen on 127.0.0.1:9009 for LDAP, 0.0.0.0:636 for LDAP over TLS,
and LDAP over IPC (Unix domain sockets). Host 0.0.0.0 represents
INADDR_ANY (any interface).
-A space separated list of URLs is expected. The URLs should be of
-the LDAP, LDAPS, or LDAPI schemes, and generally
-without a DN or other optional parameters (excepting as discussed below).
-Support for the latter two schemes depends on selected configuration
-options. Hosts may be specified by name or IPv4 and IPv6 address formats.
-Ports, if specified, must be numeric. The default ldap:// port is \fB389\fP
-and the default ldaps:// port is \fB636\fP.
+A space separated list of URLs is expected. The URLs should be of the LDAP,
+PLDAP, LDAPS, PLDAPS, or LDAPI schemes, and generally without a DN or other
+optional parameters (excepting as discussed below). Support for the latter
+three schemes depends on selected configuration options. Hosts may be specified
+by name or IPv4 and IPv6 address formats. Ports, if specified, must be
+numeric. The default ldap:// port is \fB389\fP and the default ldaps:// port
+is \fB636\fP, same for the proxy enabled variants.
+
+The PLDAP and PLDAPS URL schemes provide support for the HAProxy proxy protocol
+version 2, which allows a load balancer or proxy server to provide the remote
+client IP address to slapd to be used for access control or logging. Ports
+configured for PLDAP or PLDAPS will only accept connections that include the
+necessary proxy protocol header. Connections to these ports should be
+restricted at the network level to only trusted load balancers or proxies to
+avoid spoofing of client IP addresses by third parties.
For LDAP over IPC,
.B name
diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h
index 716c1a90fda6dedde3dee93702302525e886ccff..d69782672cff3079272898fee39b375004196be7 100644
--- a/include/ldap_pvt.h
+++ b/include/ldap_pvt.h
@@ -32,6 +32,9 @@ ldap_pvt_url_scheme2proto LDAP_P((
LDAP_F ( int )
ldap_pvt_url_scheme2tls LDAP_P((
const char * ));
+LDAP_F ( int )
+ldap_pvt_url_scheme2proxied LDAP_P((
+ const char * ));
LDAP_F ( int )
ldap_pvt_url_scheme_port LDAP_P((
diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h
index 98ad4dc051afc7fc368868222cc6fb8141d9e6b1..16a527d405b8c5fe8d616c3ec93b04ea96624c53 100644
--- a/libraries/libldap/ldap-int.h
+++ b/libraries/libldap/ldap-int.h
@@ -107,8 +107,12 @@ LDAP_BEGIN_DECL
#define LDAP_URL_PREFIX "ldap://"
#define LDAP_URL_PREFIX_LEN STRLENOF(LDAP_URL_PREFIX)
+#define PLDAP_URL_PREFIX "pldap://"
+#define PLDAP_URL_PREFIX_LEN STRLENOF(PLDAP_URL_PREFIX)
#define LDAPS_URL_PREFIX "ldaps://"
#define LDAPS_URL_PREFIX_LEN STRLENOF(LDAPS_URL_PREFIX)
+#define PLDAPS_URL_PREFIX "pldaps://"
+#define PLDAPS_URL_PREFIX_LEN STRLENOF(PLDAPS_URL_PREFIX)
#define LDAPI_URL_PREFIX "ldapi://"
#define LDAPI_URL_PREFIX_LEN STRLENOF(LDAPI_URL_PREFIX)
#ifdef LDAP_CONNECTIONLESS
diff --git a/libraries/libldap/url.c b/libraries/libldap/url.c
index b39f70b97e30509e1c8b71a16c54f0dd0c82620c..6df729e08e7b1fa76a537726bca2cef58a1edefa 100644
--- a/libraries/libldap/url.c
+++ b/libraries/libldap/url.c
@@ -20,7 +20,7 @@
/*
* LDAP URLs look like this:
- * ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
+ * [p]ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
*
* where:
* attributes is a comma separated list
@@ -59,7 +59,7 @@ int ldap_pvt_url_scheme2proto( const char *scheme )
return -1;
}
- if( strcmp("ldap", scheme) == 0 ) {
+ if( strcmp("ldap", scheme) == 0 || strcmp("pldap", scheme) == 0 ) {
return LDAP_PROTO_TCP;
}
@@ -67,7 +67,7 @@ int ldap_pvt_url_scheme2proto( const char *scheme )
return LDAP_PROTO_IPC;
}
- if( strcmp("ldaps", scheme) == 0 ) {
+ if( strcmp("ldaps", scheme) == 0 || strcmp("pldaps", scheme) == 0 ) {
return LDAP_PROTO_TCP;
}
#ifdef LDAP_CONNECTIONLESS
@@ -86,7 +86,7 @@ int ldap_pvt_url_scheme_port( const char *scheme, int port )
if( port ) return port;
if( scheme == NULL ) return port;
- if( strcmp("ldap", scheme) == 0 ) {
+ if( strcmp("ldap", scheme) == 0 || strcmp("pldap", scheme) == 0 ) {
return LDAP_PORT;
}
@@ -94,7 +94,7 @@ int ldap_pvt_url_scheme_port( const char *scheme, int port )
return -1;
}
- if( strcmp("ldaps", scheme) == 0 ) {
+ if( strcmp("ldaps", scheme) == 0 || strcmp("pldaps", scheme) == 0 ) {
return LDAPS_PORT;
}
@@ -116,7 +116,19 @@ ldap_pvt_url_scheme2tls( const char *scheme )
return -1;
}
- return strcmp("ldaps", scheme) == 0;
+ return strcmp("ldaps", scheme) == 0 || strcmp("pldaps", scheme) == 0;
+}
+
+int
+ldap_pvt_url_scheme2proxied( const char *scheme )
+{
+ assert( scheme != NULL );
+
+ if( scheme == NULL ) {
+ return -1;
+ }
+
+ return strcmp("pldap", scheme) == 0 || strcmp("pldaps", scheme) == 0;
}
int
@@ -150,7 +162,7 @@ ldap_is_ldaps_url( LDAP_CONST char *url )
return 0;
}
- return strcmp(scheme, "ldaps") == 0;
+ return strcmp(scheme, "ldaps") == 0 || strcmp(scheme, "pldaps");
}
int
@@ -228,6 +240,14 @@ skip_url_prefix(
return( p );
}
+ /* check for "pldap://" prefix */
+ if ( strncasecmp( p, PLDAP_URL_PREFIX, PLDAP_URL_PREFIX_LEN ) == 0 ) {
+ /* skip over "pldap://" prefix and return success */
+ p += PLDAP_URL_PREFIX_LEN;
+ *scheme = "pldap";
+ return( p );
+ }
+
/* check for "ldaps://" prefix */
if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
/* skip over "ldaps://" prefix and return success */
@@ -236,6 +256,14 @@ skip_url_prefix(
return( p );
}
+ /* check for "pldaps://" prefix */
+ if ( strncasecmp( p, PLDAPS_URL_PREFIX, PLDAPS_URL_PREFIX_LEN ) == 0 ) {
+ /* skip over "pldaps://" prefix and return success */
+ p += PLDAPS_URL_PREFIX_LEN;
+ *scheme = "pldaps";
+ return( p );
+ }
+
/* check for "ldapi://" prefix */
if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
/* skip over "ldapi://" prefix and return success */
diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in
index afc992fb6b15a544afe4ee727fb725b35d682f42..36706c0995ee26bcff1ad8a7dc740228e4057ec5 100644
--- a/servers/slapd/Makefile.in
+++ b/servers/slapd/Makefile.in
@@ -29,7 +29,7 @@ SRCS = main.c globals.c bconfig.c config.c daemon.c \
dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
value.c ava.c bind.c unbind.c abandon.c filterentry.c \
phonetic.c acl.c str2filter.c aclparse.c init.c user.c \
- lock.c controls.c extended.c passwd.c \
+ lock.c controls.c extended.c passwd.c proxyp.c \
schema.c schema_check.c schema_init.c schema_prep.c \
schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \
oidm.c starttls.c index.c sets.c referral.c root_dse.c \
@@ -47,7 +47,7 @@ OBJS = main.o globals.o bconfig.o config.o daemon.o \
dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
value.o ava.o bind.o unbind.o abandon.o filterentry.o \
phonetic.o acl.o str2filter.o aclparse.o init.o user.o \
- lock.o controls.o extended.o passwd.o \
+ lock.o controls.o extended.o passwd.o proxyp.o \
schema.o schema_check.o schema_init.o schema_prep.o \
schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \
oidm.o starttls.o index.o sets.o referral.o root_dse.o \
diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c
index 50a13d1b4fb04b3dc3580c101c8040f9c0446328..1eca080a0c6e6ad524cd463a40ce9c7965b9b88e 100644
--- a/servers/slapd/daemon.c
+++ b/servers/slapd/daemon.c
@@ -1379,6 +1379,8 @@ slap_open_listener(
}
#endif /* HAVE_TLS */
+ l.sl_is_proxied = ldap_pvt_url_scheme2proxied( lud->lud_scheme );
+
#ifdef LDAP_TCP_BUFFER
l.sl_tcp_rmem = 0;
l.sl_tcp_wmem = 0;
@@ -2044,6 +2046,13 @@ slap_listener(
# ifdef LDAP_PF_INET6
case AF_INET6:
+ if ( sl->sl_is_proxied ) {
+ if ( !proxyp( sfd, &from ) ) {
+ Debug( LDAP_DEBUG_ANY, "slapd(%ld): proxyp failed\n", (long)sfd, 0, 0 );
+ slapd_close( sfd );
+ return 0;
+ }
+ }
if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) {
#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
peeraddr = inet_ntop( AF_INET,
@@ -2068,6 +2077,13 @@ slap_listener(
# endif /* LDAP_PF_INET6 */
case AF_INET: {
+ if ( sl->sl_is_proxied ) {
+ if ( !proxyp( sfd, &from ) ) {
+ Debug( LDAP_DEBUG_ANY, "slapd(%ld): proxyp failed\n", (long)sfd, 0, 0 );
+ slapd_close( sfd );
+ return 0;
+ }
+ }
#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
peeraddr = inet_ntop( AF_INET, &from.sa_in_addr.sin_addr,
addr, sizeof(addr) );
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 7f8e604fa70654408691984b9f1b9b4c14d23e90..b8bad03a1e09c42cb03e1656c13aacc651f37c02 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -1528,6 +1528,11 @@ LDAP_SLAPD_F (void) slap_passwd_init (void);
*/
LDAP_SLAPD_F (char *) phonetic LDAP_P(( char *s ));
+/*
+ * proxyp.c
+ */
+LDAP_SLAPD_F (int) proxyp LDAP_P((ber_socket_t sfd, Sockaddr *from));
+
/*
* referral.c
*/
diff --git a/servers/slapd/proxyp.c b/servers/slapd/proxyp.c
new file mode 100644
index 0000000000000000000000000000000000000000..dfed1f85e44381bd1849f74aa3733d826662930b
--- /dev/null
+++ b/servers/slapd/proxyp.c
@@ -0,0 +1,265 @@
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software .
+ *
+ * Copyright 2000-2020 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * .
+ */
+
+#include "portable.h"
+#include "slap.h"
+
+#ifdef HAVE_STDINT_H
+#include
+#endif
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include
+#include
+#include
+
+typedef struct {
+ uint8_t sig[12]; /* hex 0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a */
+ uint8_t ver_cmd; /* protocol version and command */
+ uint8_t fam; /* protocol family and address */
+ uint16_t len; /* length of address data */
+} proxyp_header;
+
+typedef union {
+ struct { /* for TCP/UDP over IPv4, len = 12 */
+ uint32_t src_addr;
+ uint32_t dst_addr;
+ uint16_t src_port;
+ uint16_t dst_port;
+ } ip4;
+ struct { /* for TCP/UDP over IPv6, len = 36 */
+ uint8_t src_addr[16];
+ uint8_t dst_addr[16];
+ uint16_t src_port;
+ uint16_t dst_port;
+ } ip6;
+ struct { /* for AF_UNIX sockets, len = 216 */
+ uint8_t src_addr[108];
+ uint8_t dst_addr[108];
+ } unx;
+} proxyp_addr;
+
+static const uint8_t proxyp_sig[12] = {
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x00, 0x0d, 0x0a, 0x51, 0x55, 0x49, 0x54, 0x0a,
+};
+
+int
+proxyp( ber_socket_t sfd, Sockaddr *from ) {
+ proxyp_header pph;
+ proxyp_addr ppa;
+ const char *peeraddr = NULL;
+ /* we assume INET6_ADDRSTRLEN > INET_ADDRSTRLEN */
+ char addr[INET6_ADDRSTRLEN];
+#if defined(LDAP_PF_INET6)
+ char peername[sizeof("IP=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535")];
+#else
+ char peername[sizeof("IP=255.255.255.255:65336")];
+#endif
+ /* Maximum size of header minus static component size is max option size */
+ uint8_t proxyp_options[536 - 16];
+ int pph_len;
+ int ret;
+
+ peername[0] = '\0';
+
+ do {
+ ret = tcp_read( SLAP_FD2SOCK( sfd ), &pph, sizeof(pph) );
+ } while ( ret == -1 && errno == EINTR );
+
+ if ( ret == -1 ) {
+ char ebuf[128];
+ int save_errno = errno;
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "header read failed %d (%s)\n",
+ (long)sfd, save_errno,
+ AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
+ return 0;
+ } else if ( ret != sizeof(pph) ) {
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "header read insufficient data %d\n",
+ (long)sfd, ret, 0 );
+ return 0;
+ }
+
+ if ( memcmp( pph.sig, proxyp_sig, 12 ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "invalid header signature\n", (long)sfd, 0, 0 );
+ return 0;
+ }
+
+ if ( ( pph.ver_cmd & 0xF0 ) != 0x20 ) {
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "invalid header version %x\n",
+ (long)sfd, pph.ver_cmd & 0xF0, 0 );
+ return 0;
+ }
+
+ pph_len = ntohs( pph.len );
+ if ( ( pph.ver_cmd & 0x0F ) == 0x01 ) { /* PROXY command */
+ int addr_len;
+ switch ( pph.fam ) {
+ case 0x11: /* TCPv4 */
+ addr_len = sizeof( ppa.ip4 );
+ break;
+ case 0x21: /* TCPv6 */
+ addr_len = sizeof( ppa.ip6 );
+ break;
+ default:
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "unsupported protocol %x\n",
+ (long)sfd, pph.fam, 0 );
+ return 0;
+ }
+
+ if ( pph_len < addr_len ) {
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "address length %d too small, expecting %d\n",
+ (long)sfd, pph_len, addr_len );
+ return 0;
+ }
+
+ do {
+ ret = tcp_read( SLAP_FD2SOCK (sfd), &ppa, addr_len );
+ } while ( ret == -1 && errno == EINTR );
+
+ if ( ret == -1 ) {
+ char ebuf[128];
+ int save_errno = errno;
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "address read failed %d (%s)\n",
+ (long)sfd, save_errno,
+ AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
+ return 0;
+ } else if ( ret != addr_len ) {
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "address read insufficient data, expecting %d, read %d\n",
+ (long)sfd, addr_len, ret );
+ return 0;
+ }
+
+ pph_len -= addr_len;
+ }
+
+ switch ( pph.ver_cmd & 0x0F ) {
+ case 0x01: /* PROXY command */
+ switch ( from->sa_addr.sa_family ) {
+#ifdef LDAP_PF_INET6
+ case AF_INET6:
+ if ( IN6_IS_ADDR_V4MAPPED(&from->sa_in6_addr.sin6_addr) ) {
+#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
+ peeraddr = inet_ntop( AF_INET,
+ ((struct in_addr *)&from->sa_in6_addr.sin6_addr.s6_addr[12]),
+ addr, sizeof(addr) );
+#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ peeraddr = inet_ntoa( *((struct in_addr *)
+ &from->sa_in6_addr.sin6_addr.s6_addr[12]) );
+#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ if ( !peeraddr ) peeraddr = SLAP_STRING_UNKNOWN;
+ sprintf( peername, "IP=%s:%d", peeraddr,
+ (unsigned) ntohs( from->sa_in6_addr.sin6_port ) );
+ } else {
+ peeraddr = inet_ntop( AF_INET6,
+ &from->sa_in6_addr.sin6_addr,
+ addr, sizeof addr );
+ if ( !peeraddr ) peeraddr = SLAP_STRING_UNKNOWN;
+ sprintf( peername, "IP=[%s]:%d", peeraddr,
+ (unsigned) ntohs( from->sa_in6_addr.sin6_port ) );
+ }
+ break;
+#endif /* LDAP_PF_INET6 */
+ case AF_INET:
+#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
+ peeraddr = inet_ntop( AF_INET, &from->sa_in_addr.sin_addr,
+ addr, sizeof(addr) );
+#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ peeraddr = inet_ntoa( from->sa_in_addr.sin_addr );
+#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
+ if ( !peeraddr ) peeraddr = SLAP_STRING_UNKNOWN;
+ sprintf( peername, "IP=%s:%d", peeraddr,
+ (unsigned) ntohs( from->sa_in_addr.sin_port ) );
+ break;
+ }
+ Debug( LDAP_DEBUG_STATS, "proxyp(%ld): via %s\n",
+ (long)sfd, peername, 0 );
+
+ switch ( pph.fam ) {
+ case 0x11: /* TCPv4 */
+ from->sa_in_addr.sin_family = AF_INET;
+ from->sa_in_addr.sin_addr.s_addr = ppa.ip4.src_addr;
+ from->sa_in_addr.sin_port = ppa.ip4.src_port;
+ break;
+
+ case 0x21: /* TCPv6 */
+#ifdef LDAP_PF_INET6
+ from->sa_in6_addr.sin6_family = AF_INET6;
+ memcpy( &from->sa_in6_addr.sin6_addr, ppa.ip6.src_addr,
+ sizeof(ppa.ip6.src_addr) );
+ from->sa_in6_addr.sin6_port = ppa.ip6.src_port;
+#else
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "IPv6 proxied addresses disabled, \n",
+ (long)sfd, 0, 0 );
+ return 0;
+#endif
+ break;
+ }
+
+ break;
+
+ case 0x00: /* LOCAL command */
+ Debug( LDAP_DEBUG_CONNS, "proxyp(%ld): "
+ "local connection, ignoring proxy data\n",
+ (long)sfd, 0, 0 );
+ break;
+
+ default:
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): invalid command %x\n",
+ (long)sfd, pph.ver_cmd & 0x0F, 0 );
+ return 0;
+ }
+
+ /* Clear out any options left in proxy packet */
+ if ( pph_len > 0 ) {
+ if (pph_len > sizeof( proxyp_options ) ) {
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "options size %d too big\n",
+ (long)sfd, pph_len, 0 );
+ return 0;
+ }
+
+ do {
+ ret = tcp_read( SLAP_FD2SOCK (sfd), &proxyp_options, pph_len );
+ } while ( ret == -1 && errno == EINTR );
+
+ if ( ret == -1 ) {
+ char ebuf[128];
+ int save_errno = errno;
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "options read failed %d (%s)\n",
+ (long)sfd, save_errno,
+ AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
+ return 0;
+ } else if ( ret != pph_len ) {
+ Debug( LDAP_DEBUG_ANY, "proxyp(%ld): "
+ "options read insufficient data, expecting %d, read %d\n",
+ (long)sfd, pph_len, ret );
+ return 0;
+ }
+ }
+
+ return 1;
+}
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 7581967be59793d25d53b68e5d84d37babe1a948..165160a390052ec07b1de260a334274173316aa9 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -2988,6 +2988,7 @@ struct Listener {
#ifdef LDAP_CONNECTIONLESS
int sl_is_udp; /* UDP listener is also data port */
#endif
+ int sl_is_proxied;
int sl_mute; /* Listener is temporarily disabled due to emfile */
int sl_busy; /* Listener is busy (accept thread activated) */
ber_socket_t sl_sd;