+ if (*sap != NULL) {
+ (*sap)->sa_family = sai->ai_family;
+ sap++;
+ *sap = NULL;
+ }
+ }
+
+ freeaddrinfo(res);
+#else
+ 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 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, INFO,
+ "slap_get_listener_addresses: invalid host %s\n", host, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: invalid host %s", host, 0, 0);
+#endif
+ return -1;
+ }
+ for (n = 0; he->h_addr_list[n]; n++) ;
+ }
+
+ *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);
+ if (he) {
+ AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, he->h_addr_list[i], sizeof(struct in_addr) );
+ } else {
+ AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, &in, sizeof(struct in_addr) );
+ }
+ }
+ sap[i] = NULL;
+#endif
+ }
+
+ return 0;
+
+errexit:
+ slap_free_listener_addresses(*sal);
+ return -1;
+}
+
+static int slap_open_listener(
+ const char* url,
+ int *listeners,
+ int *cur
+ )
+{
+ 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 */
+
+#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 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, ERR,
+ "slap_open_listener: listen URL \"%s\" parse error %d\n",
+ url, rc , 0 );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: listen URL \"%s\" parse error=%d\n",
+ url, rc, 0 );
+#endif
+ return rc;
+ }
+
+ l.sl_url.bv_val = NULL;
+
+#ifndef HAVE_TLS
+ if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, INFO,
+ "slap_open_listener: TLS is not supported (%s)\n", url, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: TLS not supported (%s)\n",
+ url, 0, 0 );
+#endif
+ ldap_free_urldesc( lud );
+ return -1;
+ }
+
+ if(! lud->lud_port ) {
+ lud->lud_port = LDAP_PORT;
+ }
+
+#else
+ 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
+
+ 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
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, INFO,
+ "slap_open_listener: URL scheme is not supported: %s\n", url, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY, "daemon: URL scheme not supported: %s",
+ url, 0, 0);
+#endif
+ ldap_free_urldesc( lud );
+ return -1;
+#endif
+ } 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
+
+#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++ );
+ if ( num > 1 ) {
+ *listeners += num-1;
+ slap_listeners = ch_realloc( slap_listeners, (*listeners + 1) * sizeof(Listener *) );
+ }
+
+ psal = sal;
+ while ( *sal != NULL ) {
+ switch( (*sal)->sa_family ) {
+ case AF_INET:
+#ifdef LDAP_PF_INET6
+ case AF_INET6:
+#endif
+#ifdef LDAP_PF_LOCAL
+ case AF_LOCAL:
+#endif
+ break;
+ default:
+ sal++;
+ continue;
+ }
+#ifdef LDAP_CONNECTIONLESS
+ if( l.sl_is_udp ) socktype = SOCK_DGRAM;
+#endif
+ l.sl_sd = socket( (*sal)->sa_family, socktype, 0);
+ if ( l.sl_sd == AC_SOCKET_INVALID ) {
+ int err = sock_errno();
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, ERR,
+ "slap_open_listener: socket() failed errno=%d (%s)\n",
+ err, sock_errstr(err), 0 );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: socket() failed errno=%d (%s)\n", err,
+ sock_errstr(err), 0 );
+#endif
+ sal++;
+ continue;
+ }
+#ifndef HAVE_WINSOCK
+ if ( l.sl_sd >= dtblsize ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, ERR,
+ "slap_open_listener: listener descriptor %ld is too "
+ "great %ld\n", (long)l.sl_sd, (long)dtblsize, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: listener descriptor %ld is too great %ld\n",
+ (long) l.sl_sd, (long) dtblsize, 0 );
+#endif
+ tcp_close( l.sl_sd );
+ sal++;
+ continue;
+ }
+#endif
+#ifdef LDAP_PF_LOCAL
+ if ( (*sal)->sa_family == AF_LOCAL ) {
+ unlink ( ((struct sockaddr_un *)*sal)->sun_path );
+ } else
+#endif
+ {
+#ifdef SO_REUSEADDR
+ /* enable address reuse */
+ tmp = 1;
+ rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &tmp, sizeof(tmp) );
+ if ( rc == AC_SOCKET_ERROR ) {
+ int err = sock_errno();
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, INFO,
+ "slap_open_listener: setsockopt( %ld, SO_REUSEADDR ) "
+ "failed errno %d (%s)\n", (long)l.sl_sd, err,
+ sock_errstr(err) );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
+ (long) l.sl_sd, err, sock_errstr(err) );
+#endif
+ }
+#endif
+ }
+
+ 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( l.sl_sd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *) &tmp, sizeof(tmp) );
+ if ( rc == AC_SOCKET_ERROR ) {
+ int err = sock_errno();
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, INFO,
+ "slap_open_listener: setsockopt( %ld, IPV6_V6ONLY ) failed errno %d (%s)\n",
+ (long)l.sl_sd, err, sock_errstr(err) );
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "slapd(%ld): setsockopt(IPV6_V6ONLY) failed errno=%d (%s)\n",
+ (long) l.sl_sd, err, sock_errstr(err) );
+#endif
+ }
+#endif
+ addrlen = sizeof(struct sockaddr_in6);
+ break;
+#endif
+#ifdef LDAP_PF_LOCAL
+ case AF_LOCAL:
+ addrlen = sizeof(struct sockaddr_un);
+ break;
+#endif
+ }
+
+ if (bind(l.sl_sd, *sal, addrlen)) {
+ err = sock_errno();
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, INFO,
+ "slap_open_listener: bind(%ld) failed errno=%d (%s)\n",
+ (long)l.sl_sd, err, sock_errstr(err) );
+#else
+ Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
+ (long) l.sl_sd, err, sock_errstr(err) );
+#endif
+ tcp_close( l.sl_sd );
+ sal++;
+ continue;
+ }
+
+ switch ( (*sal)->sa_family ) {
+#ifdef LDAP_PF_LOCAL
+ case AF_LOCAL: {
+ char *addr = ((struct sockaddr_un *)*sal)->sun_path;
+#if 0 /* don't muck with socket perms */
+ if ( chmod( addr, l.sl_perms ) < 0 && crit ) {
+ int err = sock_errno();
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, INFO,
+ "slap_open_listener: fchmod(%ld) failed errno=%d (%s)\n",
+ (long)l.sl_sd, err, sock_errstr(err) );
+#else
+ Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
+ (long) l.sl_sd, err, sock_errstr(err) );
+#endif
+ tcp_close( l.sl_sd );
+ slap_free_listener_addresses(psal);
+ return -1;
+ }
+#endif
+ l.sl_name.bv_len = strlen(addr) + sizeof("PATH=") - 1;
+ 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", addr );
+ } break;
+#endif /* LDAP_PF_LOCAL */
+
+ case AF_INET: {
+ char *s;
+#if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
+ char addr[INET_ADDRSTRLEN];
+ inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr,
+ addr, sizeof(addr) );
+ s = addr;
+#else
+ s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr );
+#endif
+ 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 != NULL ? s : SLAP_STRING_UNKNOWN, port );
+ l.sl_name.bv_len = strlen( l.sl_name.bv_val );
+ } break;
+
+#ifdef LDAP_PF_INET6
+ case AF_INET6: {
+ char addr[INET6_ADDRSTRLEN];
+ inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr,
+ addr, sizeof addr);
+ port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port );
+ l.sl_name.bv_len = strlen(addr) + 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",
+ addr, port );
+ l.sl_name.bv_len = strlen( l.sl_name.bv_val );
+ } break;
+#endif /* LDAP_PF_INET6 */
+
+ default:
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, INFO,
+ "slap_open_listener: unsupported address family (%d)\n",
+ (int)(*sal)->sa_family, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n",
+ (int) (*sal)->sa_family, 0, 0 );
+#endif
+ 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++;
+
+ } /* while ( *sal != NULL ) */
+
+ slap_free_listener_addresses(psal);
+
+ if ( l.sl_url.bv_val == NULL )
+ {
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, RESULTS,
+ "slap_open_listener: failed on %s\n", url, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "slap_open_listener: failed on %s\n", url, 0, 0 );
+#endif
+ return -1;
+ }
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, RESULTS,
+ "slap_open_listener: daemon initialized %s\n",
+ l.sl_url.bv_val, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
+ l.sl_url.bv_val, 0, 0 );
+#endif
+ return 0;
+}
+
+static int sockinit(void);
+static int sockdestroy(void);
+
+int slapd_daemon_init( const char *urls )
+{
+ int i, j, n, rc;
+ char **u;
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( CONNECTION, ARGS,
+ "slapd_daemon_init: %s\n", urls ? urls : "<null>", 0, 0 );
+#else
+ Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
+ urls ? urls : "<null>", 0, 0 );
+#endif
+ if( (rc = sockinit()) != 0 ) {
+ return rc;
+ }