Back to index

openldap  2.4.31
Classes | Defines | Typedefs | Functions | Variables
daemon.c File Reference
#include "portable.h"
#include <stdio.h>
#include <ac/ctype.h>
#include <ac/errno.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ac/unistd.h>
#include "slap.h"
#include "ldap_pvt_thread.h"
#include "lutil.h"
#include "ldap_rq.h"

Go to the source code of this file.

Classes

struct  slap_daemon_st

Defines

#define MAX_DAEMON_THREADS   16
#define SLAPD_LISTEN_BACKLOG   1024
#define DAEMON_ID(fd)   (fd & slapd_daemon_mask)
#define WAKE_LISTENER(l, w)
#define SLAP_EVENT_FNAME   "select"
#define SLAP_EVENTS_ARE_INDEXED   1
#define SLAP_EVENT_DECL   fd_set readfds, writefds
#define SLAP_EVENT_INIT(t)
#define SLAP_SELECT_CHK_SETSIZE   do { ; } while (0)
#define SLAP_SOCK_INIT(t)
#define SLAP_SOCK_DESTROY(t)
#define SLAP_SOCK_IS_ACTIVE(t, fd)   FD_ISSET((fd), &slap_daemon[t].sd_actives)
#define SLAP_SOCK_IS_READ(t, fd)   FD_ISSET((fd), &slap_daemon[t].sd_readers)
#define SLAP_SOCK_IS_WRITE(t, fd)   FD_ISSET((fd), &slap_daemon[t].sd_writers)
#define SLAP_SOCK_NOT_ACTIVE(t, fd)
#define SLAP_SOCK_SET_READ(t, fd)   FD_SET((fd), &slap_daemon[t].sd_readers)
#define SLAP_SOCK_SET_WRITE(t, fd)   FD_SET((fd), &slap_daemon[t].sd_writers)
#define SLAP_EVENT_MAX(t)   slap_daemon[t].sd_nfds
#define SLAP_SELECT_ADDTEST(t, s)
#define SLAP_SOCK_CLR_READ(t, fd)   FD_CLR((fd), &slap_daemon[t].sd_readers)
#define SLAP_SOCK_CLR_WRITE(t, fd)   FD_CLR((fd), &slap_daemon[t].sd_writers)
#define SLAP_SOCK_ADD(t, s, l)
#define SLAP_SOCK_DEL(t, s)
#define SLAP_EVENT_IS_READ(fd)   FD_ISSET((fd), &readfds)
#define SLAP_EVENT_IS_WRITE(fd)   FD_ISSET((fd), &writefds)
#define SLAP_EVENT_CLR_READ(fd)   FD_CLR((fd), &readfds)
#define SLAP_EVENT_CLR_WRITE(fd)   FD_CLR((fd), &writefds)
#define SLAP_EVENT_WAIT(t, tvp, nsp)
#define SLAPD_IDLE_CHECK_LIMIT   4
#define SLAPD_EBADF_LIMIT   16

Typedefs

typedef struct slap_daemon_st slap_daemon_st

Functions

static void slapd_add (ber_socket_t s, int isactive, Listener *sl, int id)
void slapd_remove (ber_socket_t s, Sockbuf *sb, int wasactive, int wake, int locked)
void slapd_clr_write (ber_socket_t s, int wake)
void slapd_set_write (ber_socket_t s, int wake)
int slapd_clr_read (ber_socket_t s, int wake)
void slapd_set_read (ber_socket_t s, int wake)
time_t slapd_get_writetime ()
void slapd_clr_writetime (time_t old)
static void slapd_close (ber_socket_t s)
static void slap_free_listener_addresses (struct sockaddr **sal)
static int slap_get_listener_addresses (const char *host, unsigned short port, struct sockaddr ***sal)
static int slap_open_listener (const char *url, int *listeners, int *cur)
static int sockinit (void)
static int sockdestroy (void)
int slapd_daemon_init (const char *urls)
int slapd_daemon_destroy (void)
static void close_listeners (int remove)
static void destroy_listeners (void)
static int slap_listener (Listener *sl)
static voidslap_listener_thread (void *ctx, void *ptr)
static int slap_listener_activate (Listener *sl)
static voidslapd_daemon_task (void *ptr)
int slapd_daemon (void)
RETSIGTYPE slap_sig_shutdown (int sig)
RETSIGTYPE slap_sig_wake (int sig)
void slapd_add_internal (ber_socket_t s, int isactive)
Listener ** slapd_get_listeners (void)
void slap_suspend_listeners (void)
void slap_resume_listeners (void)
void slap_wake_listener ()

Variables

int slap_inet4or6 = AF_INET
time_t starttime
ber_socket_t dtblsize
slap_ssf_t local_ssf = LDAP_PVT_SASL_LOCAL_SSF
int slapd_daemon_threads = 1
int slapd_daemon_mask
Listener ** slap_listeners = NULL
static volatile sig_atomic_t listening = 1
static ldap_pvt_thread_tlistener_tid
static ber_socket_t wake_sds [MAX_DAEMON_THREADS][2]
static int emfile
static time_t chk_writetime
static volatile int waking
volatile sig_atomic_t slapd_shutdown = 0
volatile sig_atomic_t slapd_gentle_shutdown = 0
volatile sig_atomic_t slapd_abrupt_shutdown = 0
static slap_daemon_st slap_daemon [MAX_DAEMON_THREADS]
static int daemon_inited = 0

Class Documentation

struct slap_daemon_st

Definition at line 132 of file daemon.c.

Class Members
fd_set sd_actives
ldap_pvt_thread_mutex_t sd_mutex
ber_socket_t sd_nactives
int sd_nfds
int sd_nwriters
fd_set sd_readers
fd_set sd_writers

Define Documentation

#define DAEMON_ID (   fd)    (fd & slapd_daemon_mask)

Definition at line 93 of file daemon.c.

#define MAX_DAEMON_THREADS   16

Definition at line 76 of file daemon.c.

#define SLAP_EVENT_CLR_READ (   fd)    FD_CLR((fd), &readfds)

Definition at line 667 of file daemon.c.

#define SLAP_EVENT_CLR_WRITE (   fd)    FD_CLR((fd), &writefds)

Definition at line 668 of file daemon.c.

#define SLAP_EVENT_DECL   fd_set readfds, writefds

Definition at line 606 of file daemon.c.

#define SLAP_EVENT_FNAME   "select"

Definition at line 603 of file daemon.c.

#define SLAP_EVENT_INIT (   t)
Value:
do { \
       AC_MEMCPY( &readfds, &slap_daemon[t].sd_readers, sizeof(fd_set) );    \
       if ( nwriters )      { \
              AC_MEMCPY( &writefds, &slap_daemon[t].sd_writers, sizeof(fd_set) ); \
       } else { \
              FD_ZERO( &writefds ); \
       } \
} while (0)

Definition at line 608 of file daemon.c.

#define SLAP_EVENT_IS_READ (   fd)    FD_ISSET((fd), &readfds)

Definition at line 664 of file daemon.c.

#define SLAP_EVENT_IS_WRITE (   fd)    FD_ISSET((fd), &writefds)

Definition at line 665 of file daemon.c.

#define SLAP_EVENT_MAX (   t)    slap_daemon[t].sd_nfds

Definition at line 644 of file daemon.c.

#define SLAP_EVENT_WAIT (   t,
  tvp,
  nsp 
)
Value:
do { \
       *(nsp) = select( SLAP_EVENT_MAX(t), &readfds, \
              nwriters > 0 ? &writefds : NULL, NULL, (tvp) ); \
} while (0)

Definition at line 670 of file daemon.c.

#define SLAP_EVENTS_ARE_INDEXED   1

Definition at line 605 of file daemon.c.

#define SLAP_SELECT_ADDTEST (   t,
  s 
)
Value:
do { \
       if ((s) >= slap_daemon[t].sd_nfds) slap_daemon[t].sd_nfds = (s)+1; \
} while (0)

Definition at line 645 of file daemon.c.

#define SLAP_SELECT_CHK_SETSIZE   do { ; } while (0)

Definition at line 622 of file daemon.c.

#define SLAP_SOCK_ADD (   t,
  s,
  l 
)
Value:
do { \
       SLAP_SELECT_ADDTEST(t,(s)); \
       FD_SET((s), &slap_daemon[t].sd_actives); \
       FD_SET((s), &slap_daemon[t].sd_readers); \
} while (0)

Definition at line 652 of file daemon.c.

#define SLAP_SOCK_CLR_READ (   t,
  fd 
)    FD_CLR((fd), &slap_daemon[t].sd_readers)

Definition at line 649 of file daemon.c.

#define SLAP_SOCK_CLR_WRITE (   t,
  fd 
)    FD_CLR((fd), &slap_daemon[t].sd_writers)

Definition at line 650 of file daemon.c.

#define SLAP_SOCK_DEL (   t,
  s 
)
Value:
do { \
       FD_CLR((s), &slap_daemon[t].sd_actives); \
       FD_CLR((s), &slap_daemon[t].sd_readers); \
       FD_CLR((s), &slap_daemon[t].sd_writers); \
} while (0)

Definition at line 658 of file daemon.c.

#define SLAP_SOCK_DESTROY (   t)

Definition at line 632 of file daemon.c.

#define SLAP_SOCK_INIT (   t)
Value:
do { \
       SLAP_SELECT_CHK_SETSIZE; \
       FD_ZERO(&slap_daemon[t].sd_actives); \
       FD_ZERO(&slap_daemon[t].sd_readers); \
       FD_ZERO(&slap_daemon[t].sd_writers); \
} while (0)

Definition at line 625 of file daemon.c.

#define SLAP_SOCK_IS_ACTIVE (   t,
  fd 
)    FD_ISSET((fd), &slap_daemon[t].sd_actives)

Definition at line 634 of file daemon.c.

#define SLAP_SOCK_IS_READ (   t,
  fd 
)    FD_ISSET((fd), &slap_daemon[t].sd_readers)

Definition at line 635 of file daemon.c.

#define SLAP_SOCK_IS_WRITE (   t,
  fd 
)    FD_ISSET((fd), &slap_daemon[t].sd_writers)

Definition at line 636 of file daemon.c.

#define SLAP_SOCK_NOT_ACTIVE (   t,
  fd 
)
Value:

Definition at line 638 of file daemon.c.

#define SLAP_SOCK_SET_READ (   t,
  fd 
)    FD_SET((fd), &slap_daemon[t].sd_readers)

Definition at line 641 of file daemon.c.

#define SLAP_SOCK_SET_WRITE (   t,
  fd 
)    FD_SET((fd), &slap_daemon[t].sd_writers)

Definition at line 642 of file daemon.c.

#define SLAPD_EBADF_LIMIT   16
#define SLAPD_IDLE_CHECK_LIMIT   4
#define SLAPD_LISTEN_BACKLOG   1024

Definition at line 90 of file daemon.c.

#define WAKE_LISTENER (   l,
 
)
Value:
do { \
       if (w) { \
              tcp_write( SLAP_FD2SOCK(wake_sds[l][1]), "0", 1 ); \
       } \
} while (0)

Definition at line 108 of file daemon.c.


Typedef Documentation


Function Documentation

static void close_listeners ( int  remove) [static]

Definition at line 1740 of file daemon.c.

{
       int l;

       if ( !listening )
              return;
       listening = 0;

       for ( l = 0; slap_listeners[l] != NULL; l++ ) {
              Listener *lr = slap_listeners[l];

              if ( lr->sl_sd != AC_SOCKET_INVALID ) {
                     int s = lr->sl_sd;
                     lr->sl_sd = AC_SOCKET_INVALID;
                     if ( remove ) slapd_remove( s, NULL, 0, 0, 0 );

#ifdef LDAP_PF_LOCAL
                     if ( lr->sl_sa.sa_addr.sa_family == AF_LOCAL ) {
                            unlink( lr->sl_sa.sa_un_addr.sun_path );
                     }
#endif /* LDAP_PF_LOCAL */

                     slapd_close( s );
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void destroy_listeners ( void  ) [static]

Definition at line 1769 of file daemon.c.

{
       Listener *lr, **ll = slap_listeners;

       if ( ll == NULL )
              return;

       while ( (lr = *ll++) != NULL ) {
              if ( lr->sl_url.bv_val ) {
                     ber_memfree( lr->sl_url.bv_val );
              }

              if ( lr->sl_name.bv_val ) {
                     ber_memfree( lr->sl_name.bv_val );
              }

              free( lr );
       }

       free( slap_listeners );
       slap_listeners = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void slap_free_listener_addresses ( struct sockaddr **  sal) [static]

Definition at line 1043 of file daemon.c.

{
       struct sockaddr **sap;
       if (sal == NULL) return;
       for (sap = sal; *sap != NULL; sap++) ch_free(*sap);
       ch_free(sal);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int slap_get_listener_addresses ( const char *  host,
unsigned short  port,
struct sockaddr ***  sal 
) [static]

Definition at line 1134 of file daemon.c.

{
       struct sockaddr **sap;

#ifdef LDAP_PF_LOCAL
       if ( port == 0 ) {
              *sal = ch_malloc(2 * sizeof(void *));
              if (*sal == NULL) return -1;

              sap = *sal;
              *sap = ch_malloc(sizeof(struct sockaddr_un));
              if (*sap == NULL) goto errexit;
              sap[1] = NULL;

              if ( strlen(host) >
                     (sizeof(((struct sockaddr_un *)*sap)->sun_path) - 1) )
              {
                     Debug( LDAP_DEBUG_ANY,
                            "daemon: domain socket path (%s) too long in URL",
                            host, 0, 0);
                     goto errexit;
              }

              (void)memset( (void *)*sap, '\0', sizeof(struct sockaddr_un) );
              (*sap)->sa_family = AF_LOCAL;
              strcpy( ((struct sockaddr_un *)*sap)->sun_path, host );
       } else
#endif /* LDAP_PF_LOCAL */
       {
#ifdef HAVE_GETADDRINFO
              struct addrinfo hints, *res, *sai;
              int n, err;
              char serv[7];

              memset( &hints, '\0', sizeof(hints) );
              hints.ai_flags = AI_PASSIVE;
              hints.ai_socktype = SOCK_STREAM;
              hints.ai_family = slap_inet4or6;
              snprintf(serv, sizeof serv, "%d", port);

              if ( (err = getaddrinfo(host, serv, &hints, &res)) ) {
                     Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo() failed: %s\n",
                            AC_GAI_STRERROR(err), 0, 0);
                     return -1;
              }

              sai = res;
              for (n=2; (sai = sai->ai_next) != NULL; n++) {
                     /* EMPTY */ ;
              }
              *sal = ch_calloc(n, sizeof(void *));
              if (*sal == NULL) return -1;

              sap = *sal;
              *sap = NULL;

              for ( sai=res; sai; sai=sai->ai_next ) {
                     if( sai->ai_addr == NULL ) {
                            Debug( LDAP_DEBUG_ANY, "slap_get_listener_addresses: "
                                   "getaddrinfo ai_addr is NULL?\n", 0, 0, 0 );
                            freeaddrinfo(res);
                            goto errexit;
                     }

                     switch (sai->ai_family) {
#  ifdef LDAP_PF_INET6
                     case AF_INET6:
                            *sap = ch_malloc(sizeof(struct sockaddr_in6));
                            if (*sap == NULL) {
                                   freeaddrinfo(res);
                                   goto errexit;
                            }
                            *(struct sockaddr_in6 *)*sap =
                                   *((struct sockaddr_in6 *)sai->ai_addr);
                            break;
#  endif /* LDAP_PF_INET6 */
                     case AF_INET:
                            *sap = ch_malloc(sizeof(struct sockaddr_in));
                            if (*sap == NULL) {
                                   freeaddrinfo(res);
                                   goto errexit;
                            }
                            *(struct sockaddr_in *)*sap =
                                   *((struct sockaddr_in *)sai->ai_addr);
                            break;
                     default:
                            *sap = NULL;
                            break;
                     }

                     if (*sap != NULL) {
                            (*sap)->sa_family = sai->ai_family;
                            sap++;
                            *sap = NULL;
                     }
              }

              freeaddrinfo(res);

#else /* ! HAVE_GETADDRINFO */
              int i, n = 1;
              struct in_addr in;
              struct hostent *he = NULL;

              if ( host == NULL ) {
                     in.s_addr = htonl(INADDR_ANY);

              } else if ( !inet_aton( host, &in ) ) {
                     he = gethostbyname( host );
                     if( he == NULL ) {
                            Debug( LDAP_DEBUG_ANY,
                                   "daemon: invalid host %s", host, 0, 0);
                            return -1;
                     }
                     for (n = 0; he->h_addr_list[n]; n++) /* empty */;
              }

              *sal = ch_malloc((n+1) * sizeof(void *));
              if (*sal == NULL) return -1;

              sap = *sal;
              for ( i = 0; i<n; i++ ) {
                     sap[i] = ch_malloc(sizeof(struct sockaddr_in));
                     if (*sap == NULL) goto errexit;

                     (void)memset( (void *)sap[i], '\0', sizeof(struct sockaddr_in) );
                     sap[i]->sa_family = AF_INET;
                     ((struct sockaddr_in *)sap[i])->sin_port = htons(port);
                     AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr,
                            he ? (struct in_addr *)he->h_addr_list[i] : &in,
                            sizeof(struct in_addr) );
              }
              sap[i] = NULL;
#endif /* ! HAVE_GETADDRINFO */
       }

       return 0;

errexit:
       slap_free_listener_addresses(*sal);
       return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int slap_listener ( Listener sl) [static]

Definition at line 1793 of file daemon.c.

{
       Sockaddr             from;

       ber_socket_t s, sfd;
       ber_socklen_t len = sizeof(from);
       Connection *c;
       slap_ssf_t ssf = 0;
       struct berval authid = BER_BVNULL;
#ifdef SLAPD_RLOOKUPS
       char hbuf[NI_MAXHOST];
#endif /* SLAPD_RLOOKUPS */

       char   *dnsname = NULL;
       const char *peeraddr = NULL;
       /* we assume INET6_ADDRSTRLEN > INET_ADDRSTRLEN */
       char addr[INET6_ADDRSTRLEN];
#ifdef LDAP_PF_LOCAL
       char peername[MAXPATHLEN + sizeof("PATH=")];
#ifdef LDAP_PF_LOCAL_SENDMSG
       char peerbuf[8];
       struct berval peerbv = BER_BVNULL;
#endif
#elif defined(LDAP_PF_INET6)
       char peername[sizeof("IP=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535")];
#else /* ! LDAP_PF_LOCAL && ! LDAP_PF_INET6 */
       char peername[sizeof("IP=255.255.255.255:65336")];
#endif /* LDAP_PF_LOCAL */
       int cflag;
       int tid;

       Debug( LDAP_DEBUG_TRACE,
              ">>> slap_listener(%s)\n",
              sl->sl_url.bv_val, 0, 0 );

       peername[0] = '\0';

#ifdef LDAP_CONNECTIONLESS
       if ( sl->sl_is_udp ) return 1;
#endif /* LDAP_CONNECTIONLESS */

#  ifdef LDAP_PF_LOCAL
       /* FIXME: apparently accept doesn't fill
        * the sun_path sun_path member */
       from.sa_un_addr.sun_path[0] = '\0';
#  endif /* LDAP_PF_LOCAL */

       s = accept( SLAP_FD2SOCK( sl->sl_sd ), (struct sockaddr *) &from, &len );

       /* Resume the listener FD to allow concurrent-processing of
        * additional incoming connections.
        */
       sl->sl_busy = 0;
       WAKE_LISTENER(DAEMON_ID(sl->sl_sd),1);

       if ( s == AC_SOCKET_INVALID ) {
              int err = sock_errno();

              if(
#ifdef EMFILE
                  err == EMFILE ||
#endif /* EMFILE */
#ifdef ENFILE
                  err == ENFILE ||
#endif /* ENFILE */
                  0 )
              {
                     ldap_pvt_thread_mutex_lock( &slap_daemon[0].sd_mutex );
                     emfile++;
                     /* Stop listening until an existing session closes */
                     sl->sl_mute = 1;
                     ldap_pvt_thread_mutex_unlock( &slap_daemon[0].sd_mutex );
              }

              Debug( LDAP_DEBUG_ANY,
                     "daemon: accept(%ld) failed errno=%d (%s)\n",
                     (long) sl->sl_sd, err, sock_errstr(err) );
              ldap_pvt_thread_yield();
              return 0;
       }
       sfd = SLAP_SOCKNEW( s );

       /* make sure descriptor number isn't too great */
       if ( sfd >= dtblsize ) {
              Debug( LDAP_DEBUG_ANY,
                     "daemon: %ld beyond descriptor table size %ld\n",
                     (long) sfd, (long) dtblsize, 0 );

              tcp_close(s);
              ldap_pvt_thread_yield();
              return 0;
       }
       tid = DAEMON_ID(sfd);

#ifdef LDAP_DEBUG
       ldap_pvt_thread_mutex_lock( &slap_daemon[tid].sd_mutex );
       /* newly accepted stream should not be in any of the FD SETS */
       assert( SLAP_SOCK_NOT_ACTIVE( tid, sfd ));
       ldap_pvt_thread_mutex_unlock( &slap_daemon[tid].sd_mutex );
#endif /* LDAP_DEBUG */

#if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY )
#ifdef LDAP_PF_LOCAL
       /* for IPv4 and IPv6 sockets only */
       if ( from.sa_addr.sa_family != AF_LOCAL )
#endif /* LDAP_PF_LOCAL */
       {
              int rc;
              int tmp;
#ifdef SO_KEEPALIVE
              /* enable keep alives */
              tmp = 1;
              rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE,
                     (char *) &tmp, sizeof(tmp) );
              if ( rc == AC_SOCKET_ERROR ) {
                     int err = sock_errno();
                     Debug( LDAP_DEBUG_ANY,
                            "slapd(%ld): setsockopt(SO_KEEPALIVE) failed "
                            "errno=%d (%s)\n", (long) sfd, err, sock_errstr(err) );
              }
#endif /* SO_KEEPALIVE */
#ifdef TCP_NODELAY
              /* enable no delay */
              tmp = 1;
              rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
                     (char *)&tmp, sizeof(tmp) );
              if ( rc == AC_SOCKET_ERROR ) {
                     int err = sock_errno();
                     Debug( LDAP_DEBUG_ANY,
                            "slapd(%ld): setsockopt(TCP_NODELAY) failed "
                            "errno=%d (%s)\n", (long) sfd, err, sock_errstr(err) );
              }
#endif /* TCP_NODELAY */
       }
#endif /* SO_KEEPALIVE || TCP_NODELAY */

       Debug( LDAP_DEBUG_CONNS,
              "daemon: listen=%ld, new connection on %ld\n",
              (long) sl->sl_sd, (long) sfd, 0 );

       cflag = 0;
       switch ( from.sa_addr.sa_family ) {
#  ifdef LDAP_PF_LOCAL
       case AF_LOCAL:
              cflag |= CONN_IS_IPC;

              /* FIXME: apparently accept doesn't fill
               * the sun_path sun_path member */
              if ( from.sa_un_addr.sun_path[0] == '\0' ) {
                     AC_MEMCPY( from.sa_un_addr.sun_path,
                                   sl->sl_sa.sa_un_addr.sun_path,
                                   sizeof( from.sa_un_addr.sun_path ) );
              }

              sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
              ssf = local_ssf;
              {
                     uid_t uid;
                     gid_t gid;

#ifdef LDAP_PF_LOCAL_SENDMSG
                     peerbv.bv_val = peerbuf;
                     peerbv.bv_len = sizeof( peerbuf );
#endif
                     if( LUTIL_GETPEEREID( s, &uid, &gid, &peerbv ) == 0 ) {
                            authid.bv_val = ch_malloc(
                                   STRLENOF( "gidNumber=4294967295+uidNumber=4294967295,"
                                   "cn=peercred,cn=external,cn=auth" ) + 1 );
                            authid.bv_len = sprintf( authid.bv_val,
                                   "gidNumber=%d+uidNumber=%d,"
                                   "cn=peercred,cn=external,cn=auth",
                                   (int) gid, (int) uid );
                            assert( authid.bv_len <=
                                   STRLENOF( "gidNumber=4294967295+uidNumber=4294967295,"
                                   "cn=peercred,cn=external,cn=auth" ) );
                     }
              }
              dnsname = "local";
              break;
#endif /* LDAP_PF_LOCAL */

#  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;

       default:
              slapd_close(sfd);
              return 0;
       }

       if ( ( from.sa_addr.sa_family == AF_INET )
#ifdef LDAP_PF_INET6
              || ( from.sa_addr.sa_family == AF_INET6 )
#endif /* LDAP_PF_INET6 */
              )
       {
              dnsname = NULL;
#ifdef SLAPD_RLOOKUPS
              if ( use_reverse_lookup ) {
                     char *herr;
                     if (ldap_pvt_get_hname( (const struct sockaddr *)&from, len, hbuf,
                            sizeof(hbuf), &herr ) == 0) {
                            ldap_pvt_str2lower( hbuf );
                            dnsname = hbuf;
                     }
              }
#endif /* SLAPD_RLOOKUPS */

#ifdef HAVE_TCPD
              {
                     int rc;
                     ldap_pvt_thread_mutex_lock( &sd_tcpd_mutex );
                     rc = hosts_ctl("slapd",
                            dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
                            peeraddr,
                            SLAP_STRING_UNKNOWN );
                     ldap_pvt_thread_mutex_unlock( &sd_tcpd_mutex );
                     if ( !rc ) {
                            /* DENY ACCESS */
                            Statslog( LDAP_DEBUG_STATS,
                                   "fd=%ld DENIED from %s (%s)\n",
                                   (long) sfd,
                                   dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
                                   peeraddr, 0, 0 );
                            slapd_close(sfd);
                            return 0;
                     }
              }
#endif /* HAVE_TCPD */
       }

#ifdef HAVE_TLS
       if ( sl->sl_is_tls ) cflag |= CONN_IS_TLS;
#endif
       c = connection_init(sfd, sl,
              dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
              peername, cflag, ssf,
              authid.bv_val ? &authid : NULL
              LDAP_PF_LOCAL_SENDMSG_ARG(&peerbv));

       if( authid.bv_val ) ch_free(authid.bv_val);

       if( !c ) {
              Debug( LDAP_DEBUG_ANY,
                     "daemon: connection_init(%ld, %s, %s) failed.\n",
                     (long) sfd, peername, sl->sl_name.bv_val );
              slapd_close(sfd);
              return 0;
       }

       Statslog( LDAP_DEBUG_STATS,
              "conn=%ld fd=%ld ACCEPT from %s (%s)\n",
              c->c_connid, (long) sfd, peername, sl->sl_name.bv_val,
              0 );

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int slap_listener_activate ( Listener sl) [static]

Definition at line 2105 of file daemon.c.

{
       int rc;

       Debug( LDAP_DEBUG_TRACE, "slap_listener_activate(%d): %s\n",
              sl->sl_sd, sl->sl_busy ? "busy" : "", 0 );

       sl->sl_busy = 1;

       rc = ldap_pvt_thread_pool_submit( &connection_pool,
              slap_listener_thread, (void *) sl );

       if( rc != 0 ) {
              Debug( LDAP_DEBUG_ANY,
                     "slap_listener_activate(%d): submit failed (%d)\n",
                     sl->sl_sd, rc, 0 );
       }
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* slap_listener_thread ( void ctx,
void ptr 
) [static]

Definition at line 2086 of file daemon.c.

{
       int           rc;
       Listener      *sl = (Listener *)ptr;

       rc = slap_listener( sl );

       if( rc != LDAP_SUCCESS ) {
              Debug( LDAP_DEBUG_ANY,
                     "slap_listener_thread(%s): failed err=%d",
                     sl->sl_url.bv_val, rc, 0 );
       }

       return (void*)NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int slap_open_listener ( const char *  url,
int listeners,
int cur 
) [static]

Definition at line 1281 of file daemon.c.

{
       int    num, tmp, rc;
       Listener l;
       Listener *li;
       LDAPURLDesc *lud;
       unsigned short port;
       int err, addrlen = 0;
       struct sockaddr **sal, **psal;
       int socktype = SOCK_STREAM; /* default to COTS */
       ber_socket_t s;

#if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD)
       /*
        * use safe defaults
        */
       int    crit = 1;
#endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */

       rc = ldap_url_parse( url, &lud );

       if( rc != LDAP_URL_SUCCESS ) {
              Debug( LDAP_DEBUG_ANY,
                     "daemon: listen URL \"%s\" parse error=%d\n",
                     url, rc, 0 );
              return rc;
       }

       l.sl_url.bv_val = NULL;
       l.sl_mute = 0;
       l.sl_busy = 0;

#ifndef HAVE_TLS
       if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
              Debug( LDAP_DEBUG_ANY, "daemon: TLS not supported (%s)\n",
                     url, 0, 0 );
              ldap_free_urldesc( lud );
              return -1;
       }

       if(! lud->lud_port ) lud->lud_port = LDAP_PORT;

#else /* HAVE_TLS */
       l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme );

       if(! lud->lud_port ) {
              lud->lud_port = l.sl_is_tls ? LDAPS_PORT : LDAP_PORT;
       }
#endif /* HAVE_TLS */

#ifdef LDAP_TCP_BUFFER
       l.sl_tcp_rmem = 0;
       l.sl_tcp_wmem = 0;
#endif /* LDAP_TCP_BUFFER */

       port = (unsigned short) lud->lud_port;

       tmp = ldap_pvt_url_scheme2proto(lud->lud_scheme);
       if ( tmp == LDAP_PROTO_IPC ) {
#ifdef LDAP_PF_LOCAL
              if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
                     err = slap_get_listener_addresses(LDAPI_SOCK, 0, &sal);
              } else {
                     err = slap_get_listener_addresses(lud->lud_host, 0, &sal);
              }
#else /* ! LDAP_PF_LOCAL */

              Debug( LDAP_DEBUG_ANY, "daemon: URL scheme not supported: %s",
                     url, 0, 0);
              ldap_free_urldesc( lud );
              return -1;
#endif /* ! LDAP_PF_LOCAL */
       } else {
              if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
                     || strcmp(lud->lud_host, "*") == 0 )
              {
                     err = slap_get_listener_addresses(NULL, port, &sal);
              } else {
                     err = slap_get_listener_addresses(lud->lud_host, port, &sal);
              }
       }

#ifdef LDAP_CONNECTIONLESS
       l.sl_is_udp = ( tmp == LDAP_PROTO_UDP );
#endif /* LDAP_CONNECTIONLESS */

#if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD)
       if ( lud->lud_exts ) {
              err = get_url_perms( lud->lud_exts, &l.sl_perms, &crit );
       } else {
              l.sl_perms = S_IRWXU | S_IRWXO;
       }
#endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */

       ldap_free_urldesc( lud );
       if ( err ) return -1;

       /* If we got more than one address returned, we need to make space
        * for it in the slap_listeners array.
        */
       for ( num=0; sal[num]; num++ ) /* empty */;
       if ( num > 1 ) {
              *listeners += num-1;
              slap_listeners = ch_realloc( slap_listeners,
                     (*listeners + 1) * sizeof(Listener *) );
       }

       psal = sal;
       while ( *sal != NULL ) {
              char *af;
              switch( (*sal)->sa_family ) {
              case AF_INET:
                     af = "IPv4";
                     break;
#ifdef LDAP_PF_INET6
              case AF_INET6:
                     af = "IPv6";
                     break;
#endif /* LDAP_PF_INET6 */
#ifdef LDAP_PF_LOCAL
              case AF_LOCAL:
                     af = "Local";
                     break;
#endif /* LDAP_PF_LOCAL */
              default:
                     sal++;
                     continue;
              }

#ifdef LDAP_CONNECTIONLESS
              if( l.sl_is_udp ) socktype = SOCK_DGRAM;
#endif /* LDAP_CONNECTIONLESS */

              s = socket( (*sal)->sa_family, socktype, 0);
              if ( s == AC_SOCKET_INVALID ) {
                     int err = sock_errno();
                     Debug( LDAP_DEBUG_ANY,
                            "daemon: %s socket() failed errno=%d (%s)\n",
                            af, err, sock_errstr(err) );
                     sal++;
                     continue;
              }
              l.sl_sd = SLAP_SOCKNEW( s );

              if ( l.sl_sd >= dtblsize ) {
                     Debug( LDAP_DEBUG_ANY,
                            "daemon: listener descriptor %ld is too great %ld\n",
                            (long) l.sl_sd, (long) dtblsize, 0 );
                     tcp_close( s );
                     sal++;
                     continue;
              }

#ifdef LDAP_PF_LOCAL
              if ( (*sal)->sa_family == AF_LOCAL ) {
                     unlink( ((struct sockaddr_un *)*sal)->sun_path );
              } else
#endif /* LDAP_PF_LOCAL */
              {
#ifdef SO_REUSEADDR
                     /* enable address reuse */
                     tmp = 1;
                     rc = setsockopt( s, SOL_SOCKET, SO_REUSEADDR,
                            (char *) &tmp, sizeof(tmp) );
                     if ( rc == AC_SOCKET_ERROR ) {
                            int err = sock_errno();
                            Debug( LDAP_DEBUG_ANY, "slapd(%ld): "
                                   "setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
                                   (long) l.sl_sd, err, sock_errstr(err) );
                     }
#endif /* SO_REUSEADDR */
              }

              switch( (*sal)->sa_family ) {
              case AF_INET:
                     addrlen = sizeof(struct sockaddr_in);
                     break;
#ifdef LDAP_PF_INET6
              case AF_INET6:
#ifdef IPV6_V6ONLY
                     /* Try to use IPv6 sockets for IPv6 only */
                     tmp = 1;
                     rc = setsockopt( s , IPPROTO_IPV6, IPV6_V6ONLY,
                            (char *) &tmp, sizeof(tmp) );
                     if ( rc == AC_SOCKET_ERROR ) {
                            int err = sock_errno();
                            Debug( LDAP_DEBUG_ANY, "slapd(%ld): "
                                   "setsockopt(IPV6_V6ONLY) failed errno=%d (%s)\n",
                                   (long) l.sl_sd, err, sock_errstr(err) );
                     }
#endif /* IPV6_V6ONLY */
                     addrlen = sizeof(struct sockaddr_in6);
                     break;
#endif /* LDAP_PF_INET6 */

#ifdef LDAP_PF_LOCAL
              case AF_LOCAL:
#ifdef LOCAL_CREDS
                     {
                            int one = 1;
                            setsockopt( s, 0, LOCAL_CREDS, &one, sizeof( one ) );
                     }
#endif /* LOCAL_CREDS */

                     addrlen = sizeof( struct sockaddr_un );
                     break;
#endif /* LDAP_PF_LOCAL */
              }

#ifdef LDAP_PF_LOCAL
              /* create socket with all permissions set for those systems
               * that honor permissions on sockets (e.g. Linux); typically,
               * only write is required.  To exploit filesystem permissions,
               * place the socket in a directory and use directory's
               * permissions.  Need write perms to the directory to 
               * create/unlink the socket; likely need exec perms to access
               * the socket (ITS#4709) */
              {
                     mode_t old_umask = 0;

                     if ( (*sal)->sa_family == AF_LOCAL ) {
                            old_umask = umask( 0 );
                     }
#endif /* LDAP_PF_LOCAL */
                     rc = bind( s, *sal, addrlen );
#ifdef LDAP_PF_LOCAL
                     if ( old_umask != 0 ) {
                            umask( old_umask );
                     }
              }
#endif /* LDAP_PF_LOCAL */
              if ( rc ) {
                     err = sock_errno();
                     Debug( LDAP_DEBUG_ANY,
                            "daemon: bind(%ld) failed errno=%d (%s)\n",
                            (long)l.sl_sd, err, sock_errstr( err ) );
                     tcp_close( s );
                     sal++;
                     continue;
              }

              switch ( (*sal)->sa_family ) {
#ifdef LDAP_PF_LOCAL
              case AF_LOCAL: {
                     char *path = ((struct sockaddr_un *)*sal)->sun_path;
                     l.sl_name.bv_len = strlen(path) + STRLENOF("PATH=");
                     l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len + 1 );
                     snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1, 
                            "PATH=%s", path );
              } break;
#endif /* LDAP_PF_LOCAL */

              case AF_INET: {
                     char addr[INET_ADDRSTRLEN];
                     const char *s;
#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
                     s = inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr,
                            addr, sizeof(addr) );
#else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
                     s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr );
#endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
                     if (!s) s = SLAP_STRING_UNKNOWN;
                     port = ntohs( ((struct sockaddr_in *)*sal) ->sin_port );
                     l.sl_name.bv_val =
                            ber_memalloc( sizeof("IP=255.255.255.255:65535") );
                     snprintf( l.sl_name.bv_val, sizeof("IP=255.255.255.255:65535"),
                            "IP=%s:%d", s, port );
                     l.sl_name.bv_len = strlen( l.sl_name.bv_val );
              } break;

#ifdef LDAP_PF_INET6
              case AF_INET6: {
                     char addr[INET6_ADDRSTRLEN];
                     const char *s;
                     s = inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr,
                            addr, sizeof addr);
                     if (!s) s = SLAP_STRING_UNKNOWN;
                     port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port );
                     l.sl_name.bv_len = strlen(s) + sizeof("IP=[]:65535");
                     l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len );
                     snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=[%s]:%d", 
                            s, port );
                     l.sl_name.bv_len = strlen( l.sl_name.bv_val );
              } break;
#endif /* LDAP_PF_INET6 */

              default:
                     Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n",
                            (int) (*sal)->sa_family, 0, 0 );
                     break;
              }

              AC_MEMCPY(&l.sl_sa, *sal, addrlen);
              ber_str2bv( url, 0, 1, &l.sl_url);
              li = ch_malloc( sizeof( Listener ) );
              *li = l;
              slap_listeners[*cur] = li;
              (*cur)++;
              sal++;
       }

       slap_free_listener_addresses(psal);

       if ( l.sl_url.bv_val == NULL ) {
              Debug( LDAP_DEBUG_TRACE,
                     "slap_open_listener: failed on %s\n", url, 0, 0 );
              return -1;
       }

       Debug( LDAP_DEBUG_TRACE, "daemon: listener initialized %s\n",
              l.sl_url.bv_val, 0, 0 );
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3073 of file daemon.c.

{
       int i;
       for (i=0; slap_listeners[i]; i++) {
              slap_listeners[i]->sl_mute = 0;
              listen( slap_listeners[i]->sl_sd, SLAPD_LISTEN_BACKLOG );
       }
}

Here is the caller graph for this function:

RETSIGTYPE slap_sig_shutdown ( int  sig)

Definition at line 2991 of file daemon.c.

{
       int save_errno = errno;
       int i;

#if 0
       Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
#endif

       /*
        * If the NT Service Manager is controlling the server, we don't
        * want SIGBREAK to kill the server. For some strange reason,
        * SIGBREAK is generated when a user logs out.
        */

#if defined(HAVE_NT_SERVICE_MANAGER) && defined(SIGBREAK)
       if (is_NT_Service && sig == SIGBREAK) {
              /* empty */;
       } else
#endif /* HAVE_NT_SERVICE_MANAGER && SIGBREAK */
#ifdef SIGHUP
       if (sig == SIGHUP && global_gentlehup && slapd_gentle_shutdown == 0) {
              slapd_gentle_shutdown = 1;
       } else
#endif /* SIGHUP */
       {
              slapd_shutdown = 1;
       }

       for (i=0; i<slapd_daemon_threads; i++) {
              WAKE_LISTENER(i,1);
       }

       /* reinstall self */
       (void) SIGNAL_REINSTALL( sig, slap_sig_shutdown );

       errno = save_errno;
}

Here is the call graph for this function:

Here is the caller graph for this function:

RETSIGTYPE slap_sig_wake ( int  sig)

Definition at line 3031 of file daemon.c.

{
       int save_errno = errno;

       WAKE_LISTENER(0,1);

       /* reinstall self */
       (void) SIGNAL_REINSTALL( sig, slap_sig_wake );

       errno = save_errno;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3062 of file daemon.c.

{
       int i;
       for (i=0; slap_listeners[i]; i++) {
              slap_listeners[i]->sl_mute = 1;
              listen( slap_listeners[i]->sl_sd, 0 );
       }
}

Here is the caller graph for this function:

Definition at line 3083 of file daemon.c.

{
       WAKE_LISTENER(0,1);
}

Here is the caller graph for this function:

static void slapd_add ( ber_socket_t  s,
int  isactive,
Listener sl,
int  id 
) [static]

Definition at line 851 of file daemon.c.

{
       if (id < 0)
              id = DAEMON_ID(s);
       ldap_pvt_thread_mutex_lock( &slap_daemon[id].sd_mutex );

       assert( SLAP_SOCK_NOT_ACTIVE(id, s) );

       if ( isactive ) slap_daemon[id].sd_nactives++;

       SLAP_SOCK_ADD(id, s, sl);

       Debug( LDAP_DEBUG_CONNS, "daemon: added %ldr%s listener=%p\n",
              (long) s, isactive ? " (active)" : "", (void *)sl );

       ldap_pvt_thread_mutex_unlock( &slap_daemon[id].sd_mutex );

       WAKE_LISTENER(id,1);
}

Here is the caller graph for this function:

void slapd_add_internal ( ber_socket_t  s,
int  isactive 
)

Definition at line 3045 of file daemon.c.

{
       slapd_add( s, isactive, NULL, -1 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void slapd_close ( ber_socket_t  s) [static]

Definition at line 1032 of file daemon.c.

{
       Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
              (long) s, 0, 0 );
       tcp_close( SLAP_FD2SOCK(s) );
#ifdef HAVE_WINSOCK
       slapd_sockdel( s );
#endif
}

Here is the caller graph for this function:

int slapd_clr_read ( ber_socket_t  s,
int  wake 
)

Definition at line 979 of file daemon.c.

{
       int rc = 1;
       int id = DAEMON_ID(s);
       ldap_pvt_thread_mutex_lock( &slap_daemon[id].sd_mutex );

       if ( SLAP_SOCK_IS_ACTIVE( id, s )) {
              SLAP_SOCK_CLR_READ( id, s );
              rc = 0;
       }
       ldap_pvt_thread_mutex_unlock( &slap_daemon[id].sd_mutex );
       if ( !rc )
              WAKE_LISTENER(id,wake);
       return rc;
}

Here is the caller graph for this function:

void slapd_clr_write ( ber_socket_t  s,
int  wake 
)

Definition at line 937 of file daemon.c.

{
       int id = DAEMON_ID(s);
       ldap_pvt_thread_mutex_lock( &slap_daemon[id].sd_mutex );

       if ( SLAP_SOCK_IS_WRITE( id, s )) {
              assert( SLAP_SOCK_IS_ACTIVE( id, s ));

              SLAP_SOCK_CLR_WRITE( id, s );
              slap_daemon[id].sd_nwriters--;
       }

       ldap_pvt_thread_mutex_unlock( &slap_daemon[id].sd_mutex );
       WAKE_LISTENER(id,wake);
}

Here is the caller graph for this function:

void slapd_clr_writetime ( time_t  old)

Definition at line 1023 of file daemon.c.

{
       ldap_pvt_thread_mutex_lock( &slap_daemon[0].sd_mutex );
       if ( chk_writetime == old )
              chk_writetime = 0;
       ldap_pvt_thread_mutex_unlock( &slap_daemon[0].sd_mutex );
}

Here is the caller graph for this function:

Definition at line 2890 of file daemon.c.

{
       int i, rc;

#ifdef LDAP_CONNECTIONLESS
       connectionless_init();
#endif /* LDAP_CONNECTIONLESS */

       listener_tid = ch_malloc(slapd_daemon_threads * sizeof(ldap_pvt_thread_t));

       /* daemon_init only inits element 0 */
       for ( i=1; i<slapd_daemon_threads; i++ )
       {
              ldap_pvt_thread_mutex_init( &slap_daemon[i].sd_mutex );

              if( (rc = lutil_pair( wake_sds[i] )) < 0 ) {
                     Debug( LDAP_DEBUG_ANY,
                            "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
                     return rc;
              }
              ber_pvt_socket_set_nonblock( wake_sds[i][1], 1 );

              SLAP_SOCK_INIT(i);
       }

       for ( i=0; i<slapd_daemon_threads; i++ )
       {
              /* listener as a separate THREAD */
              rc = ldap_pvt_thread_create( &listener_tid[i],
                     0, slapd_daemon_task, &listener_tid[i] );

              if ( rc != 0 ) {
                     Debug( LDAP_DEBUG_ANY,
                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
                     return rc;
              }
       }

       /* wait for the listener threads to complete */
       for ( i=0; i<slapd_daemon_threads; i++ )
              ldap_pvt_thread_join( listener_tid[i], (void *)NULL );

       destroy_listeners();
       ch_free( listener_tid );
       listener_tid = NULL;

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1702 of file daemon.c.

{
       connections_destroy();
       if ( daemon_inited ) {
              int i;

              for ( i=0; i<slapd_daemon_threads; i++ ) {
#ifdef HAVE_WINSOCK
                     if ( wake_sds[i][1] != INVALID_SOCKET &&
                            SLAP_FD2SOCK( wake_sds[i][1] ) != SLAP_FD2SOCK( wake_sds[i][0] ))
#endif /* HAVE_WINSOCK */
                            tcp_close( SLAP_FD2SOCK(wake_sds[i][1]) );
#ifdef HAVE_WINSOCK
                     if ( wake_sds[i][0] != INVALID_SOCKET )
#endif /* HAVE_WINSOCK */
                            tcp_close( SLAP_FD2SOCK(wake_sds[i][0]) );
                     ldap_pvt_thread_mutex_destroy( &slap_daemon[i].sd_mutex );
                     SLAP_SOCK_DESTROY(i);
              }
              daemon_inited = 0;
#ifdef HAVE_TCPD
              ldap_pvt_thread_mutex_destroy( &sd_tcpd_mutex );
#endif /* TCP Wrappers */
       }
       sockdestroy();

#ifdef HAVE_SLP
       if( slapd_register_slp ) {
              slapd_slp_dereg();
              slapd_slp_deinit();
       }
#endif /* HAVE_SLP */

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int slapd_daemon_init ( const char *  urls)

Definition at line 1604 of file daemon.c.

{
       int i, j, n, rc;
       char **u;

       Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
              urls ? urls : "<null>", 0, 0 );

       for ( i=0; i<MAX_DAEMON_THREADS; i++ ) {
              wake_sds[i][0] = AC_SOCKET_INVALID;
              wake_sds[i][1] = AC_SOCKET_INVALID;
       }

       ldap_pvt_thread_mutex_init( &slap_daemon[0].sd_mutex );
#ifdef HAVE_TCPD
       ldap_pvt_thread_mutex_init( &sd_tcpd_mutex );
#endif /* TCP Wrappers */

       daemon_inited = 1;

       if( (rc = sockinit()) != 0 ) return rc;

#ifdef HAVE_SYSCONF
       dtblsize = sysconf( _SC_OPEN_MAX );
#elif defined(HAVE_GETDTABLESIZE)
       dtblsize = getdtablesize();
#else /* ! HAVE_SYSCONF && ! HAVE_GETDTABLESIZE */
       dtblsize = FD_SETSIZE;
#endif /* ! HAVE_SYSCONF && ! HAVE_GETDTABLESIZE */

       /* open a pipe (or something equivalent connected to itself).
        * we write a byte on this fd whenever we catch a signal. The main
        * loop will be select'ing on this socket, and will wake up when
        * this byte arrives.
        */
       if( (rc = lutil_pair( wake_sds[0] )) < 0 ) {
              Debug( LDAP_DEBUG_ANY,
                     "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
              return rc;
       }
       ber_pvt_socket_set_nonblock( wake_sds[0][1], 1 );

       SLAP_SOCK_INIT(0);

       if( urls == NULL ) urls = "ldap:///";

       u = ldap_str2charray( urls, " " );

       if( u == NULL || u[0] == NULL ) {
              Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
                     urls, 0, 0 );
              if ( u )
                     ldap_charray_free( u );
              return -1;
       }

       for( i=0; u[i] != NULL; i++ ) {
              Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
                     u[i], 0, 0 );
       }

       if( i == 0 ) {
              Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
                     urls, 0, 0 );
              ldap_charray_free( u );
              return -1;
       }

       Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
              i, 0, 0 );
       slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );

       for(n = 0, j = 0; u[n]; n++ ) {
              if ( slap_open_listener( u[n], &i, &j ) ) {
                     ldap_charray_free( u );
                     return -1;
              }
       }
       slap_listeners[j] = NULL;

       Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
              i, 0, 0 );


#ifdef HAVE_SLP
       if( slapd_register_slp ) {
              slapd_slp_init( urls );
              slapd_slp_reg();
       }
#endif /* HAVE_SLP */

       ldap_charray_free( u );

       return !i;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* slapd_daemon_task ( void ptr) [static]

Definition at line 2127 of file daemon.c.

{
       int l;
       time_t last_idle_check = 0;
       int ebadf = 0;
       int tid = (ldap_pvt_thread_t *) ptr - listener_tid;

#define SLAPD_IDLE_CHECK_LIMIT 4

       slapd_add( wake_sds[tid][0], 0, NULL, tid );
       if ( tid )
              goto loop;

       /* Init stuff done only by thread 0 */

       last_idle_check = slap_get_time();

       for ( l = 0; slap_listeners[l] != NULL; l++ ) {
              if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue;

#ifdef LDAP_CONNECTIONLESS
              /* Since this is connectionless, the data port is the
               * listening port. The listen() and accept() calls
               * are unnecessary.
               */
              if ( slap_listeners[l]->sl_is_udp )
                     continue;
#endif /* LDAP_CONNECTIONLESS */

              /* FIXME: TCP-only! */
#ifdef LDAP_TCP_BUFFER
              if ( 1 ) {
                     int origsize, size, realsize, rc;
                     socklen_t optlen;
                     char buf[ SLAP_TEXT_BUFLEN ];

                     size = 0;
                     if ( slap_listeners[l]->sl_tcp_rmem > 0 ) {
                            size = slap_listeners[l]->sl_tcp_rmem;
                     } else if ( slapd_tcp_rmem > 0 ) {
                            size = slapd_tcp_rmem;
                     }

                     if ( size > 0 ) {
                            optlen = sizeof( origsize );
                            rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
                                   SOL_SOCKET,
                                   SO_RCVBUF,
                                   (void *)&origsize,
                                   &optlen );

                            if ( rc ) {
                                   int err = sock_errno();
                                   Debug( LDAP_DEBUG_ANY,
                                          "slapd_daemon_task: getsockopt(SO_RCVBUF) failed errno=%d (%s)\n",
                                          err, sock_errstr(err), 0 );
                            }

                            optlen = sizeof( size );
                            rc = setsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
                                   SOL_SOCKET,
                                   SO_RCVBUF,
                                   (const void *)&size,
                                   optlen );

                            if ( rc ) {
                                   int err = sock_errno();
                                   Debug( LDAP_DEBUG_ANY,
                                          "slapd_daemon_task: setsockopt(SO_RCVBUF) failed errno=%d (%s)\n",
                                          err, sock_errstr(err), 0 );
                            }

                            optlen = sizeof( realsize );
                            rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
                                   SOL_SOCKET,
                                   SO_RCVBUF,
                                   (void *)&realsize,
                                   &optlen );

                            if ( rc ) {
                                   int err = sock_errno();
                                   Debug( LDAP_DEBUG_ANY,
                                          "slapd_daemon_task: getsockopt(SO_RCVBUF) failed errno=%d (%s)\n",
                                          err, sock_errstr(err), 0 );
                            }

                            snprintf( buf, sizeof( buf ),
                                   "url=%s (#%d) RCVBUF original size=%d requested size=%d real size=%d", 
                                   slap_listeners[l]->sl_url.bv_val, l, origsize, size, realsize );
                            Debug( LDAP_DEBUG_ANY,
                                   "slapd_daemon_task: %s\n",
                                   buf, 0, 0 );
                     }

                     size = 0;
                     if ( slap_listeners[l]->sl_tcp_wmem > 0 ) {
                            size = slap_listeners[l]->sl_tcp_wmem;
                     } else if ( slapd_tcp_wmem > 0 ) {
                            size = slapd_tcp_wmem;
                     }

                     if ( size > 0 ) {
                            optlen = sizeof( origsize );
                            rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
                                   SOL_SOCKET,
                                   SO_SNDBUF,
                                   (void *)&origsize,
                                   &optlen );

                            if ( rc ) {
                                   int err = sock_errno();
                                   Debug( LDAP_DEBUG_ANY,
                                          "slapd_daemon_task: getsockopt(SO_SNDBUF) failed errno=%d (%s)\n",
                                          err, sock_errstr(err), 0 );
                            }

                            optlen = sizeof( size );
                            rc = setsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
                                   SOL_SOCKET,
                                   SO_SNDBUF,
                                   (const void *)&size,
                                   optlen );

                            if ( rc ) {
                                   int err = sock_errno();
                                   Debug( LDAP_DEBUG_ANY,
                                          "slapd_daemon_task: setsockopt(SO_SNDBUF) failed errno=%d (%s)",
                                          err, sock_errstr(err), 0 );
                            }

                            optlen = sizeof( realsize );
                            rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
                                   SOL_SOCKET,
                                   SO_SNDBUF,
                                   (void *)&realsize,
                                   &optlen );

                            if ( rc ) {
                                   int err = sock_errno();
                                   Debug( LDAP_DEBUG_ANY,
                                          "slapd_daemon_task: getsockopt(SO_SNDBUF) failed errno=%d (%s)\n",
                                          err, sock_errstr(err), 0 );
                            }

                            snprintf( buf, sizeof( buf ),
                                   "url=%s (#%d) SNDBUF original size=%d requested size=%d real size=%d", 
                                   slap_listeners[l]->sl_url.bv_val, l, origsize, size, realsize );
                            Debug( LDAP_DEBUG_ANY,
                                   "slapd_daemon_task: %s\n",
                                   buf, 0, 0 );
                     }
              }
#endif /* LDAP_TCP_BUFFER */

              if ( listen( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ), SLAPD_LISTEN_BACKLOG ) == -1 ) {
                     int err = sock_errno();

#ifdef LDAP_PF_INET6
                     /* If error is EADDRINUSE, we are trying to listen to INADDR_ANY and
                      * we are already listening to in6addr_any, then we want to ignore
                      * this and continue.
                      */
                     if ( err == EADDRINUSE ) {
                            int i;
                            struct sockaddr_in sa = slap_listeners[l]->sl_sa.sa_in_addr;
                            struct sockaddr_in6 sa6;
                            
                            if ( sa.sin_family == AF_INET &&
                                 sa.sin_addr.s_addr == htonl(INADDR_ANY) ) {
                                   for ( i = 0 ; i < l; i++ ) {
                                          sa6 = slap_listeners[i]->sl_sa.sa_in6_addr;
                                          if ( sa6.sin6_family == AF_INET6 &&
                                               !memcmp( &sa6.sin6_addr, &in6addr_any,
                                                        sizeof(struct in6_addr) ) )
                                          {
                                                 break;
                                          }
                                   }

                                   if ( i < l ) {
                                          /* We are already listening to in6addr_any */
                                          Debug( LDAP_DEBUG_CONNS,
                                                 "daemon: Attempt to listen to 0.0.0.0 failed, "
                                                 "already listening on ::, assuming IPv4 included\n",
                                                 0, 0, 0 );
                                          slapd_close( slap_listeners[l]->sl_sd );
                                          slap_listeners[l]->sl_sd = AC_SOCKET_INVALID;
                                          continue;
                                   }
                            }
                     }
#endif /* LDAP_PF_INET6 */
                     Debug( LDAP_DEBUG_ANY,
                            "daemon: listen(%s, 5) failed errno=%d (%s)\n",
                                   slap_listeners[l]->sl_url.bv_val, err,
                                   sock_errstr(err) );
                     return (void*)-1;
              }

              /* make the listening socket non-blocking */
              if ( ber_pvt_socket_set_nonblock( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ), 1 ) < 0 ) {
                     Debug( LDAP_DEBUG_ANY, "slapd_daemon_task: "
                            "set nonblocking on a listening socket failed\n",
                            0, 0, 0 );
                     slapd_shutdown = 2;
                     return (void*)-1;
              }

              slapd_add( slap_listeners[l]->sl_sd, 0, slap_listeners[l], -1 );
       }

#ifdef HAVE_NT_SERVICE_MANAGER
       if ( started_event != NULL ) {
              ldap_pvt_thread_cond_signal( &started_event );
       }
#endif /* HAVE_NT_SERVICE_MANAGER */

loop:

       /* initialization complete. Here comes the loop. */

       while ( !slapd_shutdown ) {
              ber_socket_t         i;
              int                  ns, nwriters;
              int                  at;
              ber_socket_t         nfds;
#if SLAP_EVENTS_ARE_INDEXED
              ber_socket_t         nrfds, nwfds;
#endif /* SLAP_EVENTS_ARE_INDEXED */
#define SLAPD_EBADF_LIMIT 16

              time_t               now;

              SLAP_EVENT_DECL;

              struct timeval              tv;
              struct timeval              *tvp;

              struct timeval              cat;
              time_t               tdelta = 1;
              struct re_s*         rtask;

              now = slap_get_time();

              if ( !tid && ( global_idletimeout > 0 || chk_writetime )) {
                     int check = 0;
                     /* Set the select timeout.
                      * Don't just truncate, preserve the fractions of
                      * seconds to prevent sleeping for zero time.
                      */
                     if ( chk_writetime ) {
                            tv.tv_sec = global_writetimeout;
                            tv.tv_usec = 0;
                            if ( difftime( chk_writetime, now ) < 0 )
                                   check = 2;
                     } else {
                            tv.tv_sec = global_idletimeout / SLAPD_IDLE_CHECK_LIMIT;
                            tv.tv_usec = global_idletimeout - \
                                   ( tv.tv_sec * SLAPD_IDLE_CHECK_LIMIT );
                            tv.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT;
                            if ( difftime( last_idle_check +
                                   global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 )
                                   check = 1;
                     }
                     if ( check ) {
                            connections_timeout_idle( now );
                            last_idle_check = now;
                     }
              } else {
                     tv.tv_sec = 0;
                     tv.tv_usec = 0;
              }

#ifdef SIGHUP
              if ( slapd_gentle_shutdown ) {
                     ber_socket_t active;

                     if ( !tid && slapd_gentle_shutdown == 1 ) {
                            BackendDB *be;
                            Debug( LDAP_DEBUG_ANY, "slapd gentle shutdown\n", 0, 0, 0 );
                            close_listeners( 1 );
                            frontendDB->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
                            LDAP_STAILQ_FOREACH(be, &backendDB, be_next) {
                                   be->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
                            }
                            slapd_gentle_shutdown = 2;
                     }

                     ldap_pvt_thread_mutex_lock( &slap_daemon[tid].sd_mutex );
                     active = slap_daemon[tid].sd_nactives;
                     ldap_pvt_thread_mutex_unlock( &slap_daemon[tid].sd_mutex );

                     if ( active == 0 ) {
                            if ( !tid ) {
                                   for ( l=1; l<slapd_daemon_threads; l++ ) {
                                          ldap_pvt_thread_mutex_lock( &slap_daemon[l].sd_mutex );
                                          active += slap_daemon[l].sd_nactives;
                                          ldap_pvt_thread_mutex_unlock( &slap_daemon[l].sd_mutex );
                                   }
                                   if ( !active )
                                          slapd_shutdown = 1;
                            }
                            if ( !active )
                                   break;
                     }
              }
#endif /* SIGHUP */
              at = 0;

              ldap_pvt_thread_mutex_lock( &slap_daemon[tid].sd_mutex );

              nwriters = slap_daemon[tid].sd_nwriters;

              if ( listening )
              for ( l = 0; slap_listeners[l] != NULL; l++ ) {
                     Listener *lr = slap_listeners[l];

                     if ( lr->sl_sd == AC_SOCKET_INVALID ) continue;
                     if ( DAEMON_ID( lr->sl_sd ) != tid ) continue;

                     if ( lr->sl_mute || lr->sl_busy )
                     {
                            SLAP_SOCK_CLR_READ( tid, lr->sl_sd );
                     } else {
                            SLAP_SOCK_SET_READ( tid, lr->sl_sd );
                     }
              }

              SLAP_EVENT_INIT(tid);

              nfds = SLAP_EVENT_MAX(tid);

              if (( chk_writetime || global_idletimeout ) && slap_daemon[tid].sd_nactives ) at = 1;

              ldap_pvt_thread_mutex_unlock( &slap_daemon[tid].sd_mutex );

              if ( at 
#if defined(HAVE_YIELDING_SELECT) || defined(NO_THREADS)
                     &&  ( tv.tv_sec || tv.tv_usec )
#endif /* HAVE_YIELDING_SELECT || NO_THREADS */
                     )
              {
                     tvp = &tv;
              } else {
                     tvp = NULL;
              }

              /* Only thread 0 handles runqueue */
              if ( !tid ) {
                     ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
                     rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat );
                     while ( rtask && cat.tv_sec && cat.tv_sec <= now ) {
                            if ( ldap_pvt_runqueue_isrunning( &slapd_rq, rtask )) {
                                   ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
                            } else {
                                   ldap_pvt_runqueue_runtask( &slapd_rq, rtask );
                                   ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
                                   ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
                                   ldap_pvt_thread_pool_submit( &connection_pool,
                                          rtask->routine, (void *) rtask );
                                   ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
                            }
                            rtask = ldap_pvt_runqueue_next_sched( &slapd_rq, &cat );
                     }
                     ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );

                     if ( rtask && cat.tv_sec ) {
                            /* NOTE: diff __should__ always be >= 0,
                             * AFAI understand; however (ITS#4872),
                             * time_t might be unsigned in some systems,
                             * while difftime() returns a double */
                            double diff = difftime( cat.tv_sec, now );
                            if ( diff <= 0 ) {
                                   diff = tdelta;
                            }
                            if ( tvp == NULL || diff < tv.tv_sec ) {
                                   tv.tv_sec = diff;
                                   tv.tv_usec = 0;
                                   tvp = &tv;
                            }
                     }
              }

              for ( l = 0; slap_listeners[l] != NULL; l++ ) {
                     Listener *lr = slap_listeners[l];

                     if ( lr->sl_sd == AC_SOCKET_INVALID ) {
                            continue;
                     }

                     if ( lr->sl_mute ) {
                            Debug( LDAP_DEBUG_CONNS,
                                   "daemon: " SLAP_EVENT_FNAME ": "
                                   "listen=%d muted\n",
                                   lr->sl_sd, 0, 0 );
                            continue;
                     }

                     if ( lr->sl_busy ) {
                            Debug( LDAP_DEBUG_CONNS,
                                   "daemon: " SLAP_EVENT_FNAME ": "
                                   "listen=%d busy\n",
                                   lr->sl_sd, 0, 0 );
                            continue;
                     }

                     Debug( LDAP_DEBUG_CONNS,
                            "daemon: " SLAP_EVENT_FNAME ": "
                            "listen=%d active_threads=%d tvp=%s\n",
                            lr->sl_sd, at, tvp == NULL ? "NULL" : "zero" );
              }

              SLAP_EVENT_WAIT( tid, tvp, &ns );
              switch ( ns ) {
              case -1: {    /* failure - try again */
                            int err = sock_errno();

                            if ( err != EINTR ) {
                                   ebadf++;

                                   /* Don't log unless we got it twice in a row */
                                   if ( !( ebadf & 1 ) ) {
                                          Debug( LDAP_DEBUG_ANY,
                                                 "daemon: "
                                                 SLAP_EVENT_FNAME
                                                 " failed count %d "
                                                 "err (%d): %s\n",
                                                 ebadf, err,
                                                 sock_errstr( err ) );
                                   }
                                   if ( ebadf >= SLAPD_EBADF_LIMIT ) {
                                          slapd_shutdown = 2;
                                   }
                            }
                     }
                     continue;

              case 0:              /* timeout - let threads run */
                     ebadf = 0;
#ifndef HAVE_YIELDING_SELECT
                     Debug( LDAP_DEBUG_CONNS, "daemon: " SLAP_EVENT_FNAME
                            "timeout - yielding\n",
                            0, 0, 0 );

                     ldap_pvt_thread_yield();
#endif /* ! HAVE_YIELDING_SELECT */
                     continue;

              default:      /* something happened - deal with it */
                     if ( slapd_shutdown ) continue;

                     ebadf = 0;
                     Debug( LDAP_DEBUG_CONNS,
                            "daemon: activity on %d descriptor%s\n",
                            ns, ns != 1 ? "s" : "", 0 );
                     /* FALL THRU */
              }

#if SLAP_EVENTS_ARE_INDEXED
              if ( SLAP_EVENT_IS_READ( wake_sds[tid][0] ) ) {
                     char c[BUFSIZ];
                     SLAP_EVENT_CLR_READ( wake_sds[tid][0] );
                     waking = 0;
                     tcp_read( SLAP_FD2SOCK(wake_sds[tid][0]), c, sizeof(c) );
                     Debug( LDAP_DEBUG_CONNS, "daemon: waked\n", 0, 0, 0 );
                     continue;
              }

              /* The event slot equals the descriptor number - this is
               * true for Unix select and poll. We treat Windows select
               * like this too, even though it's a kludge.
               */
              if ( listening )
              for ( l = 0; slap_listeners[l] != NULL; l++ ) {
                     int rc;

                     if ( ns <= 0 ) break;
                     if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue;
#ifdef LDAP_CONNECTIONLESS
                     if ( slap_listeners[l]->sl_is_udp ) continue;
#endif /* LDAP_CONNECTIONLESS */
                     if ( !SLAP_EVENT_IS_READ( slap_listeners[l]->sl_sd ) ) continue;
                     
                     /* clear events */
                     SLAP_EVENT_CLR_READ( slap_listeners[l]->sl_sd );
                     SLAP_EVENT_CLR_WRITE( slap_listeners[l]->sl_sd );
                     ns--;

                     rc = slap_listener_activate( slap_listeners[l] );
              }

              /* bypass the following tests if no descriptors left */
              if ( ns <= 0 ) {
#ifndef HAVE_YIELDING_SELECT
                     ldap_pvt_thread_yield();
#endif /* HAVE_YIELDING_SELECT */
                     continue;
              }

              Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
              nrfds = 0;
              nwfds = 0;
              for ( i = 0; i < nfds; i++ ) {
                     int    r, w;

                     r = SLAP_EVENT_IS_READ( i );
                     /* writefds was not initialized if nwriters was zero */
                     w = nwriters ? SLAP_EVENT_IS_WRITE( i ) : 0;
                     if ( r || w ) {
                            Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
                                r ? "r" : "", w ? "w" : "" );
                            if ( r ) {
                                   nrfds++;
                                   ns--;
                            }
                            if ( w ) {
                                   nwfds++;
                                   ns--;
                            }
                     }
                     if ( ns <= 0 ) break;
              }
              Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );

              /* loop through the writers */
              for ( i = 0; nwfds > 0; i++ ) {
                     ber_socket_t wd;
                     if ( ! SLAP_EVENT_IS_WRITE( i ) ) continue;
                     wd = i;

                     SLAP_EVENT_CLR_WRITE( wd );
                     nwfds--;

                     Debug( LDAP_DEBUG_CONNS,
                            "daemon: write active on %d\n",
                            wd, 0, 0 );

                     /*
                      * NOTE: it is possible that the connection was closed
                      * and that the stream is now inactive.
                      * connection_write() must validate the stream is still
                      * active.
                      *
                      * ITS#4338: if the stream is invalid, there is no need to
                      * close it here. It has already been closed in connection.c.
                      */
                     if ( connection_write( wd ) < 0 ) {
                            if ( SLAP_EVENT_IS_READ( wd ) ) {
                                   SLAP_EVENT_CLR_READ( (unsigned) wd );
                                   nrfds--;
                            }
                     }
              }

              for ( i = 0; nrfds > 0; i++ ) {
                     ber_socket_t rd;
                     if ( ! SLAP_EVENT_IS_READ( i ) ) continue;
                     rd = i;
                     SLAP_EVENT_CLR_READ( rd );
                     nrfds--;

                     Debug ( LDAP_DEBUG_CONNS,
                            "daemon: read activity on %d\n", rd, 0, 0 );
                     /*
                      * NOTE: it is possible that the connection was closed
                      * and that the stream is now inactive.
                      * connection_read() must valid the stream is still
                      * active.
                      */

                     connection_read_activate( rd );
              }
#else  /* !SLAP_EVENTS_ARE_INDEXED */
       /* FIXME */
       /* The events are returned in an arbitrary list. This is true
        * for /dev/poll, epoll and kqueue. In order to prioritize things
        * so that we can handle wake_sds first, listeners second, and then
        * all other connections last (as we do for select), we would need
        * to use multiple event handles and cascade them.
        *
        * That seems like a bit of hassle. So the wake_sds check has been
        * skipped. For epoll and kqueue we can associate arbitrary data with
        * an event, so we could use pointers to the listener structure
        * instead of just the file descriptor. For /dev/poll we have to
        * search the listeners array for a matching descriptor.
        *
        * We now handle wake events when we see them; they are not given
        * higher priority.
        */
#ifdef LDAP_DEBUG
              Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );

              for ( i = 0; i < ns; i++ ) {
                     int    r, w, fd;

                     /* Don't log listener events */
                     if ( SLAP_EVENT_IS_LISTENER( tid, i )
#ifdef LDAP_CONNECTIONLESS
                            && !( (SLAP_EVENT_LISTENER( tid, i ))->sl_is_udp )
#endif /* LDAP_CONNECTIONLESS */
                            )
                     {
                            continue;
                     }

                     fd = SLAP_EVENT_FD( tid, i );
                     /* Don't log internal wake events */
                     if ( fd == wake_sds[tid][0] ) continue;

                     r = SLAP_EVENT_IS_READ( i );
                     w = SLAP_EVENT_IS_WRITE( i );
                     if ( r || w ) {
                            Debug( LDAP_DEBUG_CONNS, " %d%s%s", fd,
                                r ? "r" : "", w ? "w" : "" );
                     }
              }
              Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
#endif /* LDAP_DEBUG */

              for ( i = 0; i < ns; i++ ) {
                     int rc = 1, fd, w = 0, r = 0;

                     if ( SLAP_EVENT_IS_LISTENER( tid, i ) ) {
                            rc = slap_listener_activate( SLAP_EVENT_LISTENER( tid, i ) );
                     }

                     /* If we found a regular listener, rc is now zero, and we
                      * can skip the data portion. But if it was a UDP listener
                      * then rc is still 1, and we want to handle the data.
                      */
                     if ( rc ) {
                            fd = SLAP_EVENT_FD( tid, i );

                            /* Handle wake events */
                            if ( fd == wake_sds[tid][0] ) {
                                   char c[BUFSIZ];
                                   waking = 0;
                                   tcp_read( SLAP_FD2SOCK(wake_sds[tid][0]), c, sizeof(c) );
                                   continue;
                            }

                            if ( SLAP_EVENT_IS_WRITE( i ) ) {
                                   Debug( LDAP_DEBUG_CONNS,
                                          "daemon: write active on %d\n",
                                          fd, 0, 0 );

                                   SLAP_EVENT_CLR_WRITE( i );
                                   w = 1;

                                   /*
                                    * NOTE: it is possible that the connection was closed
                                    * and that the stream is now inactive.
                                    * connection_write() must valid the stream is still
                                    * active.
                                    */
                                   if ( connection_write( fd ) < 0 ) {
                                          continue;
                                   }
                            }
                            /* If event is a read */
                            if ( SLAP_EVENT_IS_READ( i )) {
                                   r = 1;
                                   Debug( LDAP_DEBUG_CONNS,
                                          "daemon: read active on %d\n",
                                          fd, 0, 0 );

                                   SLAP_EVENT_CLR_READ( i );
                                   connection_read_activate( fd );
                            } else if ( !w ) {
#ifdef HAVE_EPOLL
                                   /* Don't keep reporting the hangup
                                    */
                                   if ( SLAP_SOCK_IS_ACTIVE( tid, fd )) {
                                          SLAP_EPOLL_SOCK_SET( tid, fd, EPOLLET );
                                   }
#endif
                            }
                     }
              }
#endif /* SLAP_EVENTS_ARE_INDEXED */

#ifndef HAVE_YIELDING_SELECT
              ldap_pvt_thread_yield();
#endif /* ! HAVE_YIELDING_SELECT */
       }

       /* Only thread 0 handles shutdown */
       if ( tid )
              return NULL;

       if ( slapd_shutdown == 1 ) {
              Debug( LDAP_DEBUG_ANY,
                     "daemon: shutdown requested and initiated.\n",
                     0, 0, 0 );

       } else if ( slapd_shutdown == 2 ) {
#ifdef HAVE_NT_SERVICE_MANAGER
                     Debug( LDAP_DEBUG_ANY,
                            "daemon: shutdown initiated by Service Manager.\n",
                            0, 0, 0);
#else /* !HAVE_NT_SERVICE_MANAGER */
                     Debug( LDAP_DEBUG_ANY,
                            "daemon: abnormal condition, shutdown initiated.\n",
                            0, 0, 0 );
#endif /* !HAVE_NT_SERVICE_MANAGER */
       } else {
              Debug( LDAP_DEBUG_ANY,
                     "daemon: no active streams, shutdown initiated.\n",
                     0, 0, 0 );
       }

       close_listeners( 0 );

       if ( !slapd_gentle_shutdown ) {
              slapd_abrupt_shutdown = 1;
              connections_shutdown();
       }

       if ( LogTest( LDAP_DEBUG_ANY )) {
              int t = ldap_pvt_thread_pool_backload( &connection_pool );
              Debug( LDAP_DEBUG_ANY,
                     "slapd shutdown: waiting for %d operations/tasks to finish\n",
                     t, 0, 0 );
       }
       ldap_pvt_thread_pool_destroy( &connection_pool, 1 );

       return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3051 of file daemon.c.

{
       /* Could return array with no listeners if !listening, but current
        * callers mostly look at the URLs.  E.g. syncrepl uses this to
        * identify the server, which means it wants the startup arguments.
        */
       return slap_listeners;
}

Here is the caller graph for this function:

time_t slapd_get_writetime ( )

Definition at line 1013 of file daemon.c.

{
       time_t cur;
       ldap_pvt_thread_mutex_lock( &slap_daemon[0].sd_mutex );
       cur = chk_writetime;
       ldap_pvt_thread_mutex_unlock( &slap_daemon[0].sd_mutex );
       return cur;
}

Here is the caller graph for this function:

void slapd_remove ( ber_socket_t  s,
Sockbuf *  sb,
int  wasactive,
int  wake,
int  locked 
)

Definition at line 875 of file daemon.c.

{
       int waswriter;
       int wasreader;
       int id = DAEMON_ID(s);

       if ( !locked )
              ldap_pvt_thread_mutex_lock( &slap_daemon[id].sd_mutex );

       assert( SLAP_SOCK_IS_ACTIVE( id, s ));

       if ( wasactive ) slap_daemon[id].sd_nactives--;

       waswriter = SLAP_SOCK_IS_WRITE(id, s);
       wasreader = SLAP_SOCK_IS_READ(id, s);

       Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
              (long) s,
              wasreader ? "r" : "",
              waswriter ? "w" : "" );

       if ( waswriter ) slap_daemon[id].sd_nwriters--;

       SLAP_SOCK_DEL(id, s);

       if ( sb )
              ber_sockbuf_free(sb);

       /* If we ran out of file descriptors, we dropped a listener from
        * the select() loop. Now that we're removing a session from our
        * control, we can try to resume a dropped listener to use.
        */
       if ( emfile && listening ) {
              int i;
              for ( i = 0; slap_listeners[i] != NULL; i++ ) {
                     Listener *lr = slap_listeners[i];

                     if ( lr->sl_sd == AC_SOCKET_INVALID ) continue;
                     if ( lr->sl_sd == s ) continue;
                     if ( lr->sl_mute ) {
                            lr->sl_mute = 0;
                            emfile--;
                            if ( DAEMON_ID(lr->sl_sd) != id )
                                   WAKE_LISTENER(DAEMON_ID(lr->sl_sd), wake);
                            break;
                     }
              }
              /* Walked the entire list without enabling anything; emfile
               * counter is stale. Reset it.
               */
              if ( slap_listeners[i] == NULL ) emfile = 0;
       }
       ldap_pvt_thread_mutex_unlock( &slap_daemon[id].sd_mutex );
       WAKE_LISTENER(id, wake || slapd_gentle_shutdown == 2);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void slapd_set_read ( ber_socket_t  s,
int  wake 
)

Definition at line 996 of file daemon.c.

{
       int do_wake = 1;
       int id = DAEMON_ID(s);
       ldap_pvt_thread_mutex_lock( &slap_daemon[id].sd_mutex );

       if( SLAP_SOCK_IS_ACTIVE( id, s ) && !SLAP_SOCK_IS_READ( id, s )) {
              SLAP_SOCK_SET_READ( id, s );
       } else {
              do_wake = 0;
       }
       ldap_pvt_thread_mutex_unlock( &slap_daemon[id].sd_mutex );
       if ( do_wake )
              WAKE_LISTENER(id,wake);
}

Here is the caller graph for this function:

void slapd_set_write ( ber_socket_t  s,
int  wake 
)

Definition at line 954 of file daemon.c.

{
       int id = DAEMON_ID(s);
       ldap_pvt_thread_mutex_lock( &slap_daemon[id].sd_mutex );

       assert( SLAP_SOCK_IS_ACTIVE( id, s ));

       if ( !SLAP_SOCK_IS_WRITE( id, s )) {
              SLAP_SOCK_SET_WRITE( id, s );
              slap_daemon[id].sd_nwriters++;
       }
       if (( wake & 2 ) && global_writetimeout && !chk_writetime ) {
              if (id)
                     ldap_pvt_thread_mutex_lock( &slap_daemon[0].sd_mutex );
              if (!chk_writetime)
                     chk_writetime = slap_get_time();
              if (id)
                     ldap_pvt_thread_mutex_unlock( &slap_daemon[0].sd_mutex );
       }

       ldap_pvt_thread_mutex_unlock( &slap_daemon[id].sd_mutex );
       WAKE_LISTENER(id,wake);
}

Here is the caller graph for this function:

static int sockdestroy ( void  ) [static]

Definition at line 2981 of file daemon.c.

{
#if defined( HAVE_WINSOCK2 ) || defined( HAVE_WINSOCK )
       WSACleanup();
#endif /* HAVE_WINSOCK2 || HAVE_WINSOCK */

       return 0;
}

Here is the caller graph for this function:

static int sockinit ( void  ) [static]

Definition at line 2940 of file daemon.c.

{
#if defined( HAVE_WINSOCK2 )
       WORD wVersionRequested;
       WSADATA wsaData;
       int err;

       wVersionRequested = MAKEWORD( 2, 0 );

       err = WSAStartup( wVersionRequested, &wsaData );
       if ( err != 0 ) {
              /* Tell the user that we couldn't find a usable */
              /* WinSock DLL.                                   */
              return -1;
       }

       /* Confirm that the WinSock DLL supports 2.0.*/
       /* Note that if the DLL supports versions greater    */
       /* than 2.0 in addition to 2.0, it will still return */
       /* 2.0 in wVersion since that is the version we       */
       /* requested.                                  */

       if ( LOBYTE( wsaData.wVersion ) != 2 ||
              HIBYTE( wsaData.wVersion ) != 0 )
       {
           /* Tell the user that we couldn't find a usable */
           /* WinSock DLL.                            */
           WSACleanup();
           return -1;
       }

       /* The WinSock DLL is acceptable. Proceed. */
#elif defined( HAVE_WINSOCK )
       WSADATA wsaData;
       if ( WSAStartup( 0x0101, &wsaData ) != 0 ) return -1;
#endif /* ! HAVE_WINSOCK2 && ! HAVE_WINSOCK */

       return 0;
}

Here is the caller graph for this function:


Variable Documentation

time_t chk_writetime [static]

Definition at line 98 of file daemon.c.

int daemon_inited = 0 [static]

Definition at line 1601 of file daemon.c.

ber_socket_t dtblsize

Definition at line 72 of file daemon.c.

int emfile [static]

Definition at line 96 of file daemon.c.

Definition at line 87 of file daemon.c.

volatile sig_atomic_t listening = 1 [static]

Definition at line 86 of file daemon.c.

Definition at line 73 of file daemon.c.

Definition at line 161 of file daemon.c.

int slap_inet4or6 = AF_INET

Definition at line 67 of file daemon.c.

Definition at line 85 of file daemon.c.

volatile sig_atomic_t slapd_abrupt_shutdown = 0

Definition at line 117 of file daemon.c.

Definition at line 78 of file daemon.c.

Definition at line 77 of file daemon.c.

volatile sig_atomic_t slapd_gentle_shutdown = 0

Definition at line 116 of file daemon.c.

volatile sig_atomic_t slapd_shutdown = 0

Definition at line 115 of file daemon.c.

time_t starttime

Definition at line 71 of file daemon.c.

ber_socket_t wake_sds[MAX_DAEMON_THREADS][2] [static]

Definition at line 95 of file daemon.c.

volatile int waking [static]

Definition at line 100 of file daemon.c.