+static void slap_free_listener_addresses(struct sockaddr **sal)
+{
+ struct sockaddr **sap;
+
+ if (sal == NULL) {
+ return;
+ }
+
+ for (sap = sal; *sap != NULL; sap++) {
+ ch_free(*sap);
+ }
+
+ ch_free(sal);
+}
+
+#ifdef LDAP_PF_LOCAL
+static int get_url_perms(
+ char **exts,
+ mode_t *perms,
+ int *crit )
+{
+ int i;
+
+ assert( exts );
+ assert( perms );
+ assert( crit );
+
+ *crit = 0;
+ for ( i = 0; exts[ i ]; i++ ) {
+ char *type = exts[ i ];
+ int c = 0;
+
+ if ( type[ 0 ] == '!' ) {
+ c = 1;
+ type++;
+ }
+
+ if ( strncasecmp( type, LDAPI_MOD_URLEXT "=", sizeof(LDAPI_MOD_URLEXT "=") - 1 ) == 0 ) {
+ char *value = type + sizeof(LDAPI_MOD_URLEXT "=") - 1;
+ mode_t p = 0;
+
+#if 0
+ if ( strlen( value ) != 9 ) {
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 0 ] ) {
+ case 'r':
+ p |= S_IRUSR;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 1 ] ) {
+ case 'w':
+ p |= S_IWUSR;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 2 ] ) {
+ case 'x':
+ p |= S_IXUSR;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 3 ] ) {
+ case 'r':
+ p |= S_IRGRP;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 4 ] ) {
+ case 'w':
+ p |= S_IWGRP;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 5 ] ) {
+ case 'x':
+ p |= S_IXGRP;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 6 ] ) {
+ case 'r':
+ p |= S_IROTH;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 7 ] ) {
+ case 'w':
+ p |= S_IWOTH;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 8 ] ) {
+ case 'x':
+ p |= S_IXOTH;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+#else
+ if ( strlen(value) != 3 ) {
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 0 ] ) {
+ case 'w':
+ p |= S_IRWXU;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 1 ] ) {
+ case 'w':
+ p |= S_IRWXG;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+
+ switch ( value[ 2 ] ) {
+ case 'w':
+ p |= S_IRWXO;
+ break;
+ case '-':
+ break;
+ default:
+ return LDAP_OTHER;
+ }
+#endif
+
+ *crit = c;
+ *perms = p;
+
+ return LDAP_SUCCESS;
+ }
+ }
+}
+#endif /* LDAP_PF_LOCAL */
+
+/* port = 0 indicates AF_LOCAL */
+static int slap_get_listener_addresses(
+ const char *host,
+ unsigned short port,
+ struct sockaddr ***sal)
+{
+ 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) ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
+ "slap_get_listener_addresses: domain socket path (%s) too long in URL\n",
+ host ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: domain socket path (%s) too long in URL",
+ host, 0, 0);
+#endif
+ 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
+ {
+#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 = AF_UNSPEC;
+ snprintf(serv, sizeof serv, "%d", port);
+
+ if ( (err = getaddrinfo(host, serv, &hints, &res)) ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
+ "slap_get_listener_addresses: getaddrinfo failed: %s\n",
+ AC_GAI_STRERROR(err) ));
+#else
+ Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo failed: %s\n",
+ AC_GAI_STRERROR(err), 0, 0);
+#endif
+ 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 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
+ "slap_get_listener_addresses: "
+ "getaddrinfo ai_addr is NULL?\n" ));
+#else
+ Debug( LDAP_DEBUG_ANY, "slap_get_listener_addresses: "
+ "getaddrinfo ai_addr is NULL?\n", 0, 0, 0 );
+#endif
+ 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
+ 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
+ struct in_addr in;
+
+ if ( host == NULL ) {
+ in.s_addr = htonl(INADDR_ANY);
+
+ } else if ( !inet_aton( host, &in ) ) {
+ struct hostent *he = gethostbyname( host );
+ if( he == NULL ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
+ "slap_get_listener_addresses: invalid host %s\n",
+ host ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "daemon: invalid host %s", host, 0, 0);
+#endif
+ return -1;
+ }
+ AC_MEMCPY( &in, he->h_addr, sizeof( in ) );
+ }
+
+ *sal = ch_malloc(2 * sizeof(void *));
+ if (*sal == NULL) {
+ return -1;
+ }
+
+ sap = *sal;
+ *sap = ch_malloc(sizeof(struct sockaddr_in));
+ if (*sap == NULL) {
+ goto errexit;
+ }
+ sap[1] = NULL;
+
+ (void)memset( (void *)*sap, '\0', sizeof(struct sockaddr_in) );
+ (*sap)->sa_family = AF_INET;
+ ((struct sockaddr_in *)*sap)->sin_port = htons(port);
+ ((struct sockaddr_in *)*sap)->sin_addr = in;
+#endif
+ }
+
+ return 0;