xref: /freebsd/usr.sbin/nscd/config.c (revision 87959e27fd71e06cf4053d14a850dcd44ca42a5f)
106a99fe3SHajimu UMEMOTO /*-
206a99fe3SHajimu UMEMOTO  * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
306a99fe3SHajimu UMEMOTO  * All rights reserved.
406a99fe3SHajimu UMEMOTO  *
506a99fe3SHajimu UMEMOTO  * Redistribution and use in source and binary forms, with or without
606a99fe3SHajimu UMEMOTO  * modification, are permitted provided that the following conditions
706a99fe3SHajimu UMEMOTO  * are met:
806a99fe3SHajimu UMEMOTO  * 1. Redistributions of source code must retain the above copyright
906a99fe3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer.
1006a99fe3SHajimu UMEMOTO  * 2. Redistributions in binary form must reproduce the above copyright
1106a99fe3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer in the
1206a99fe3SHajimu UMEMOTO  *    documentation and/or other materials provided with the distribution.
1306a99fe3SHajimu UMEMOTO  *
1406a99fe3SHajimu UMEMOTO  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1506a99fe3SHajimu UMEMOTO  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1606a99fe3SHajimu UMEMOTO  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1706a99fe3SHajimu UMEMOTO  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1806a99fe3SHajimu UMEMOTO  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1906a99fe3SHajimu UMEMOTO  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2006a99fe3SHajimu UMEMOTO  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2106a99fe3SHajimu UMEMOTO  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2206a99fe3SHajimu UMEMOTO  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2306a99fe3SHajimu UMEMOTO  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2406a99fe3SHajimu UMEMOTO  * SUCH DAMAGE.
2506a99fe3SHajimu UMEMOTO  *
2606a99fe3SHajimu UMEMOTO  */
2706a99fe3SHajimu UMEMOTO 
2806a99fe3SHajimu UMEMOTO #include <sys/cdefs.h>
2906a99fe3SHajimu UMEMOTO __FBSDID("$FreeBSD$");
3006a99fe3SHajimu UMEMOTO 
3128f805ceSDag-Erling Smørgrav #include <sys/stat.h>
3228f805ceSDag-Erling Smørgrav #include <sys/time.h>
3328f805ceSDag-Erling Smørgrav 
3406a99fe3SHajimu UMEMOTO #include <assert.h>
3506a99fe3SHajimu UMEMOTO #include <math.h>
3628f805ceSDag-Erling Smørgrav #include <nsswitch.h>
3728f805ceSDag-Erling Smørgrav #include <pthread.h>
3806a99fe3SHajimu UMEMOTO #include <stdio.h>
3906a99fe3SHajimu UMEMOTO #include <stdlib.h>
4006a99fe3SHajimu UMEMOTO #include <string.h>
4128f805ceSDag-Erling Smørgrav 
4206a99fe3SHajimu UMEMOTO #include "config.h"
4306a99fe3SHajimu UMEMOTO #include "debug.h"
4406a99fe3SHajimu UMEMOTO #include "log.h"
4506a99fe3SHajimu UMEMOTO 
4606a99fe3SHajimu UMEMOTO /*
4706a99fe3SHajimu UMEMOTO  * Default entries, which always exist in the configuration
4806a99fe3SHajimu UMEMOTO  */
4906a99fe3SHajimu UMEMOTO const char *c_default_entries[6] = {
5006a99fe3SHajimu UMEMOTO 	NSDB_PASSWD,
5106a99fe3SHajimu UMEMOTO 	NSDB_GROUP,
5206a99fe3SHajimu UMEMOTO 	NSDB_HOSTS,
5306a99fe3SHajimu UMEMOTO 	NSDB_SERVICES,
5406a99fe3SHajimu UMEMOTO 	NSDB_PROTOCOLS,
5506a99fe3SHajimu UMEMOTO 	NSDB_RPC
5606a99fe3SHajimu UMEMOTO 	};
5706a99fe3SHajimu UMEMOTO 
5806a99fe3SHajimu UMEMOTO static int configuration_entry_cmp(const void *, const void *);
5906a99fe3SHajimu UMEMOTO static int configuration_entry_sort_cmp(const void *, const void *);
6006a99fe3SHajimu UMEMOTO static int configuration_entry_cache_mp_sort_cmp(const void *, const void *);
6106a99fe3SHajimu UMEMOTO static int configuration_entry_cache_mp_cmp(const void *, const void *);
6206a99fe3SHajimu UMEMOTO static int configuration_entry_cache_mp_part_cmp(const void *, const void *);
6306a99fe3SHajimu UMEMOTO static struct configuration_entry *create_configuration_entry(const char *,
6406a99fe3SHajimu UMEMOTO 	struct timeval const *, struct timeval const *,
6506a99fe3SHajimu UMEMOTO 	struct common_cache_entry_params const *,
6606a99fe3SHajimu UMEMOTO 	struct common_cache_entry_params const *,
6706a99fe3SHajimu UMEMOTO 	struct mp_cache_entry_params const *);
6806a99fe3SHajimu UMEMOTO 
6906a99fe3SHajimu UMEMOTO static int
7006a99fe3SHajimu UMEMOTO configuration_entry_sort_cmp(const void *e1, const void *e2)
7106a99fe3SHajimu UMEMOTO {
7206a99fe3SHajimu UMEMOTO 	return (strcmp((*((struct configuration_entry **)e1))->name,
7306a99fe3SHajimu UMEMOTO 		(*((struct configuration_entry **)e2))->name
7406a99fe3SHajimu UMEMOTO 		));
7506a99fe3SHajimu UMEMOTO }
7606a99fe3SHajimu UMEMOTO 
7706a99fe3SHajimu UMEMOTO static int
7806a99fe3SHajimu UMEMOTO configuration_entry_cmp(const void *e1, const void *e2)
7906a99fe3SHajimu UMEMOTO {
8006a99fe3SHajimu UMEMOTO 	return (strcmp((const char *)e1,
8106a99fe3SHajimu UMEMOTO 		(*((struct configuration_entry **)e2))->name
8206a99fe3SHajimu UMEMOTO 		));
8306a99fe3SHajimu UMEMOTO }
8406a99fe3SHajimu UMEMOTO 
8506a99fe3SHajimu UMEMOTO static int
8606a99fe3SHajimu UMEMOTO configuration_entry_cache_mp_sort_cmp(const void *e1, const void *e2)
8706a99fe3SHajimu UMEMOTO {
8806a99fe3SHajimu UMEMOTO 	return (strcmp((*((cache_entry *)e1))->params->entry_name,
8906a99fe3SHajimu UMEMOTO 		(*((cache_entry *)e2))->params->entry_name
9006a99fe3SHajimu UMEMOTO 		));
9106a99fe3SHajimu UMEMOTO }
9206a99fe3SHajimu UMEMOTO 
9306a99fe3SHajimu UMEMOTO static int
9406a99fe3SHajimu UMEMOTO configuration_entry_cache_mp_cmp(const void *e1, const void *e2)
9506a99fe3SHajimu UMEMOTO {
9606a99fe3SHajimu UMEMOTO 	return (strcmp((const char *)e1,
9706a99fe3SHajimu UMEMOTO 		(*((cache_entry *)e2))->params->entry_name
9806a99fe3SHajimu UMEMOTO 		));
9906a99fe3SHajimu UMEMOTO }
10006a99fe3SHajimu UMEMOTO 
10106a99fe3SHajimu UMEMOTO static int
10206a99fe3SHajimu UMEMOTO configuration_entry_cache_mp_part_cmp(const void *e1, const void *e2)
10306a99fe3SHajimu UMEMOTO {
10406a99fe3SHajimu UMEMOTO 	return (strncmp((const char *)e1,
10506a99fe3SHajimu UMEMOTO 		(*((cache_entry *)e2))->params->entry_name,
10606a99fe3SHajimu UMEMOTO 		strlen((const char *)e1)
10706a99fe3SHajimu UMEMOTO 		));
10806a99fe3SHajimu UMEMOTO }
10906a99fe3SHajimu UMEMOTO 
11006a99fe3SHajimu UMEMOTO static struct configuration_entry *
11106a99fe3SHajimu UMEMOTO create_configuration_entry(const char *name,
11206a99fe3SHajimu UMEMOTO 	struct timeval const *common_timeout,
11306a99fe3SHajimu UMEMOTO 	struct timeval const *mp_timeout,
11406a99fe3SHajimu UMEMOTO 	struct common_cache_entry_params const *positive_params,
11506a99fe3SHajimu UMEMOTO 	struct common_cache_entry_params const *negative_params,
11606a99fe3SHajimu UMEMOTO 	struct mp_cache_entry_params const *mp_params)
11706a99fe3SHajimu UMEMOTO {
11806a99fe3SHajimu UMEMOTO 	struct configuration_entry *retval;
11906a99fe3SHajimu UMEMOTO 	size_t	size;
12006a99fe3SHajimu UMEMOTO 	int res;
12106a99fe3SHajimu UMEMOTO 
12206a99fe3SHajimu UMEMOTO 	TRACE_IN(create_configuration_entry);
12306a99fe3SHajimu UMEMOTO 	assert(name != NULL);
12406a99fe3SHajimu UMEMOTO 	assert(positive_params != NULL);
12506a99fe3SHajimu UMEMOTO 	assert(negative_params != NULL);
12606a99fe3SHajimu UMEMOTO 	assert(mp_params != NULL);
12706a99fe3SHajimu UMEMOTO 
1288eeaaffaSDag-Erling Smørgrav 	retval = calloc(1,
1298eeaaffaSDag-Erling Smørgrav 		sizeof(*retval));
13006a99fe3SHajimu UMEMOTO 	assert(retval != NULL);
13106a99fe3SHajimu UMEMOTO 
13206a99fe3SHajimu UMEMOTO 	res = pthread_mutex_init(&retval->positive_cache_lock, NULL);
13306a99fe3SHajimu UMEMOTO 	if (res != 0) {
13406a99fe3SHajimu UMEMOTO 		free(retval);
13506a99fe3SHajimu UMEMOTO 		LOG_ERR_2("create_configuration_entry",
13606a99fe3SHajimu UMEMOTO 			"can't create positive cache lock");
13706a99fe3SHajimu UMEMOTO 		TRACE_OUT(create_configuration_entry);
13806a99fe3SHajimu UMEMOTO 		return (NULL);
13906a99fe3SHajimu UMEMOTO 	}
14006a99fe3SHajimu UMEMOTO 
14106a99fe3SHajimu UMEMOTO 	res = pthread_mutex_init(&retval->negative_cache_lock, NULL);
14206a99fe3SHajimu UMEMOTO 	if (res != 0) {
14306a99fe3SHajimu UMEMOTO 		pthread_mutex_destroy(&retval->positive_cache_lock);
14406a99fe3SHajimu UMEMOTO 		free(retval);
14506a99fe3SHajimu UMEMOTO 		LOG_ERR_2("create_configuration_entry",
14606a99fe3SHajimu UMEMOTO 			"can't create negative cache lock");
14706a99fe3SHajimu UMEMOTO 		TRACE_OUT(create_configuration_entry);
14806a99fe3SHajimu UMEMOTO 		return (NULL);
14906a99fe3SHajimu UMEMOTO 	}
15006a99fe3SHajimu UMEMOTO 
15106a99fe3SHajimu UMEMOTO 	res = pthread_mutex_init(&retval->mp_cache_lock, NULL);
15206a99fe3SHajimu UMEMOTO 	if (res != 0) {
15306a99fe3SHajimu UMEMOTO 		pthread_mutex_destroy(&retval->positive_cache_lock);
15406a99fe3SHajimu UMEMOTO 		pthread_mutex_destroy(&retval->negative_cache_lock);
15506a99fe3SHajimu UMEMOTO 		free(retval);
15606a99fe3SHajimu UMEMOTO 		LOG_ERR_2("create_configuration_entry",
15706a99fe3SHajimu UMEMOTO 			"can't create negative cache lock");
15806a99fe3SHajimu UMEMOTO 		TRACE_OUT(create_configuration_entry);
15906a99fe3SHajimu UMEMOTO 		return (NULL);
16006a99fe3SHajimu UMEMOTO 	}
16106a99fe3SHajimu UMEMOTO 
16206a99fe3SHajimu UMEMOTO 	memcpy(&retval->positive_cache_params, positive_params,
16306a99fe3SHajimu UMEMOTO 		sizeof(struct common_cache_entry_params));
16406a99fe3SHajimu UMEMOTO 	memcpy(&retval->negative_cache_params, negative_params,
16506a99fe3SHajimu UMEMOTO 		sizeof(struct common_cache_entry_params));
16606a99fe3SHajimu UMEMOTO 	memcpy(&retval->mp_cache_params, mp_params,
16706a99fe3SHajimu UMEMOTO 		sizeof(struct mp_cache_entry_params));
16806a99fe3SHajimu UMEMOTO 
16906a99fe3SHajimu UMEMOTO 	size = strlen(name);
1708eeaaffaSDag-Erling Smørgrav 	retval->name = calloc(1, size + 1);
17106a99fe3SHajimu UMEMOTO 	assert(retval->name != NULL);
17206a99fe3SHajimu UMEMOTO 	memcpy(retval->name, name, size);
17306a99fe3SHajimu UMEMOTO 
17406a99fe3SHajimu UMEMOTO 	memcpy(&retval->common_query_timeout, common_timeout,
17506a99fe3SHajimu UMEMOTO 		sizeof(struct timeval));
17606a99fe3SHajimu UMEMOTO 	memcpy(&retval->mp_query_timeout, mp_timeout,
17706a99fe3SHajimu UMEMOTO 		sizeof(struct timeval));
17806a99fe3SHajimu UMEMOTO 
17927f2bc9eSDag-Erling Smørgrav 	asprintf(&retval->positive_cache_params.cep.entry_name, "%s+", name);
18027f2bc9eSDag-Erling Smørgrav 	assert(retval->positive_cache_params.cep.entry_name != NULL);
18106a99fe3SHajimu UMEMOTO 
18227f2bc9eSDag-Erling Smørgrav 	asprintf(&retval->negative_cache_params.cep.entry_name, "%s-", name);
18327f2bc9eSDag-Erling Smørgrav 	assert(retval->negative_cache_params.cep.entry_name != NULL);
18406a99fe3SHajimu UMEMOTO 
18527f2bc9eSDag-Erling Smørgrav 	asprintf(&retval->mp_cache_params.cep.entry_name, "%s*", name);
18627f2bc9eSDag-Erling Smørgrav 	assert(retval->mp_cache_params.cep.entry_name != NULL);
18706a99fe3SHajimu UMEMOTO 
18806a99fe3SHajimu UMEMOTO 	TRACE_OUT(create_configuration_entry);
18906a99fe3SHajimu UMEMOTO 	return (retval);
19006a99fe3SHajimu UMEMOTO }
19106a99fe3SHajimu UMEMOTO 
19206a99fe3SHajimu UMEMOTO /*
19306a99fe3SHajimu UMEMOTO  * Creates configuration entry and fills it with default values
19406a99fe3SHajimu UMEMOTO  */
19506a99fe3SHajimu UMEMOTO struct configuration_entry *
19606a99fe3SHajimu UMEMOTO create_def_configuration_entry(const char *name)
19706a99fe3SHajimu UMEMOTO {
19806a99fe3SHajimu UMEMOTO 	struct common_cache_entry_params positive_params, negative_params;
19906a99fe3SHajimu UMEMOTO 	struct mp_cache_entry_params mp_params;
20006a99fe3SHajimu UMEMOTO 	struct timeval default_common_timeout, default_mp_timeout;
20106a99fe3SHajimu UMEMOTO 
20206a99fe3SHajimu UMEMOTO 	struct configuration_entry *res = NULL;
20306a99fe3SHajimu UMEMOTO 
20406a99fe3SHajimu UMEMOTO 	TRACE_IN(create_def_configuration_entry);
20506a99fe3SHajimu UMEMOTO 	memset(&positive_params, 0,
20606a99fe3SHajimu UMEMOTO 		sizeof(struct common_cache_entry_params));
20727f2bc9eSDag-Erling Smørgrav 	positive_params.cep.entry_type = CET_COMMON;
20806a99fe3SHajimu UMEMOTO 	positive_params.cache_entries_size = DEFAULT_CACHE_HT_SIZE;
20906a99fe3SHajimu UMEMOTO 	positive_params.max_elemsize = DEFAULT_POSITIVE_ELEMENTS_SIZE;
21006a99fe3SHajimu UMEMOTO 	positive_params.satisf_elemsize = DEFAULT_POSITIVE_ELEMENTS_SIZE / 2;
21106a99fe3SHajimu UMEMOTO 	positive_params.max_lifetime.tv_sec = DEFAULT_POSITIVE_LIFETIME;
212a397989dSStefan Eßer 	positive_params.confidence_threshold = DEFAULT_POSITIVE_CONF_THRESH;
21306a99fe3SHajimu UMEMOTO 	positive_params.policy = CPT_LRU;
21406a99fe3SHajimu UMEMOTO 
21506a99fe3SHajimu UMEMOTO 	memcpy(&negative_params, &positive_params,
21606a99fe3SHajimu UMEMOTO 		sizeof(struct common_cache_entry_params));
21706a99fe3SHajimu UMEMOTO 	negative_params.max_elemsize = DEFAULT_NEGATIVE_ELEMENTS_SIZE;
21806a99fe3SHajimu UMEMOTO 	negative_params.satisf_elemsize = DEFAULT_NEGATIVE_ELEMENTS_SIZE / 2;
21906a99fe3SHajimu UMEMOTO 	negative_params.max_lifetime.tv_sec = DEFAULT_NEGATIVE_LIFETIME;
220a397989dSStefan Eßer 	negative_params.confidence_threshold = DEFAULT_NEGATIVE_CONF_THRESH;
22106a99fe3SHajimu UMEMOTO 	negative_params.policy = CPT_FIFO;
22206a99fe3SHajimu UMEMOTO 
22306a99fe3SHajimu UMEMOTO 	memset(&default_common_timeout, 0, sizeof(struct timeval));
22406a99fe3SHajimu UMEMOTO 	default_common_timeout.tv_sec = DEFAULT_COMMON_ENTRY_TIMEOUT;
22506a99fe3SHajimu UMEMOTO 
22606a99fe3SHajimu UMEMOTO 	memset(&default_mp_timeout, 0, sizeof(struct timeval));
22706a99fe3SHajimu UMEMOTO 	default_mp_timeout.tv_sec = DEFAULT_MP_ENTRY_TIMEOUT;
22806a99fe3SHajimu UMEMOTO 
22906a99fe3SHajimu UMEMOTO 	memset(&mp_params, 0,
23006a99fe3SHajimu UMEMOTO 		sizeof(struct mp_cache_entry_params));
23127f2bc9eSDag-Erling Smørgrav 	mp_params.cep.entry_type = CET_MULTIPART;
23206a99fe3SHajimu UMEMOTO 	mp_params.max_elemsize = DEFAULT_MULTIPART_ELEMENTS_SIZE;
23306a99fe3SHajimu UMEMOTO 	mp_params.max_sessions = DEFAULT_MULITPART_SESSIONS_SIZE;
23406a99fe3SHajimu UMEMOTO 	mp_params.max_lifetime.tv_sec = DEFAULT_MULITPART_LIFETIME;
23506a99fe3SHajimu UMEMOTO 
23606a99fe3SHajimu UMEMOTO 	res = create_configuration_entry(name, &default_common_timeout,
23706a99fe3SHajimu UMEMOTO 		&default_mp_timeout, &positive_params, &negative_params,
23806a99fe3SHajimu UMEMOTO 		&mp_params);
23906a99fe3SHajimu UMEMOTO 
24006a99fe3SHajimu UMEMOTO 	TRACE_OUT(create_def_configuration_entry);
24106a99fe3SHajimu UMEMOTO 	return (res);
24206a99fe3SHajimu UMEMOTO }
24306a99fe3SHajimu UMEMOTO 
24406a99fe3SHajimu UMEMOTO void
24506a99fe3SHajimu UMEMOTO destroy_configuration_entry(struct configuration_entry *entry)
24606a99fe3SHajimu UMEMOTO {
24706a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_configuration_entry);
24806a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
24906a99fe3SHajimu UMEMOTO 	pthread_mutex_destroy(&entry->positive_cache_lock);
25006a99fe3SHajimu UMEMOTO 	pthread_mutex_destroy(&entry->negative_cache_lock);
25106a99fe3SHajimu UMEMOTO 	pthread_mutex_destroy(&entry->mp_cache_lock);
25206a99fe3SHajimu UMEMOTO 	free(entry->name);
25327f2bc9eSDag-Erling Smørgrav 	free(entry->positive_cache_params.cep.entry_name);
25427f2bc9eSDag-Erling Smørgrav 	free(entry->negative_cache_params.cep.entry_name);
25527f2bc9eSDag-Erling Smørgrav 	free(entry->mp_cache_params.cep.entry_name);
25606a99fe3SHajimu UMEMOTO 	free(entry->mp_cache_entries);
25706a99fe3SHajimu UMEMOTO 	free(entry);
25806a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_configuration_entry);
25906a99fe3SHajimu UMEMOTO }
26006a99fe3SHajimu UMEMOTO 
26106a99fe3SHajimu UMEMOTO int
26206a99fe3SHajimu UMEMOTO add_configuration_entry(struct configuration *config,
26306a99fe3SHajimu UMEMOTO 	struct configuration_entry *entry)
26406a99fe3SHajimu UMEMOTO {
26506a99fe3SHajimu UMEMOTO 	TRACE_IN(add_configuration_entry);
26606a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
26706a99fe3SHajimu UMEMOTO 	assert(entry->name != NULL);
26806a99fe3SHajimu UMEMOTO 	if (configuration_find_entry(config, entry->name) != NULL) {
26906a99fe3SHajimu UMEMOTO 		TRACE_OUT(add_configuration_entry);
27006a99fe3SHajimu UMEMOTO 		return (-1);
27106a99fe3SHajimu UMEMOTO 	}
27206a99fe3SHajimu UMEMOTO 
27306a99fe3SHajimu UMEMOTO 	if (config->entries_size == config->entries_capacity) {
27406a99fe3SHajimu UMEMOTO 		struct configuration_entry **new_entries;
27506a99fe3SHajimu UMEMOTO 
27606a99fe3SHajimu UMEMOTO 		config->entries_capacity *= 2;
277*87959e27SPedro F. Giffuni 		new_entries = calloc(config->entries_capacity,
278*87959e27SPedro F. Giffuni 			sizeof(*new_entries));
27906a99fe3SHajimu UMEMOTO 		assert(new_entries != NULL);
28006a99fe3SHajimu UMEMOTO 		memcpy(new_entries, config->entries,
28106a99fe3SHajimu UMEMOTO 			sizeof(struct configuration_entry *) *
28206a99fe3SHajimu UMEMOTO 		        config->entries_size);
28306a99fe3SHajimu UMEMOTO 
28406a99fe3SHajimu UMEMOTO 		free(config->entries);
28506a99fe3SHajimu UMEMOTO 		config->entries = new_entries;
28606a99fe3SHajimu UMEMOTO 	}
28706a99fe3SHajimu UMEMOTO 
28806a99fe3SHajimu UMEMOTO 	config->entries[config->entries_size++] = entry;
28906a99fe3SHajimu UMEMOTO 	qsort(config->entries, config->entries_size,
29006a99fe3SHajimu UMEMOTO 		sizeof(struct configuration_entry *),
29106a99fe3SHajimu UMEMOTO 		configuration_entry_sort_cmp);
29206a99fe3SHajimu UMEMOTO 
29306a99fe3SHajimu UMEMOTO 	TRACE_OUT(add_configuration_entry);
29406a99fe3SHajimu UMEMOTO 	return (0);
29506a99fe3SHajimu UMEMOTO }
29606a99fe3SHajimu UMEMOTO 
29706a99fe3SHajimu UMEMOTO size_t
29806a99fe3SHajimu UMEMOTO configuration_get_entries_size(struct configuration *config)
29906a99fe3SHajimu UMEMOTO {
30006a99fe3SHajimu UMEMOTO 	TRACE_IN(configuration_get_entries_size);
30106a99fe3SHajimu UMEMOTO 	assert(config != NULL);
30206a99fe3SHajimu UMEMOTO 	TRACE_OUT(configuration_get_entries_size);
30306a99fe3SHajimu UMEMOTO 	return (config->entries_size);
30406a99fe3SHajimu UMEMOTO }
30506a99fe3SHajimu UMEMOTO 
30606a99fe3SHajimu UMEMOTO struct configuration_entry *
30706a99fe3SHajimu UMEMOTO configuration_get_entry(struct configuration *config, size_t index)
30806a99fe3SHajimu UMEMOTO {
30906a99fe3SHajimu UMEMOTO 	TRACE_IN(configuration_get_entry);
31006a99fe3SHajimu UMEMOTO 	assert(config != NULL);
31106a99fe3SHajimu UMEMOTO 	assert(index < config->entries_size);
31206a99fe3SHajimu UMEMOTO 	TRACE_OUT(configuration_get_entry);
31306a99fe3SHajimu UMEMOTO 	return (config->entries[index]);
31406a99fe3SHajimu UMEMOTO }
31506a99fe3SHajimu UMEMOTO 
31606a99fe3SHajimu UMEMOTO struct configuration_entry *
31706a99fe3SHajimu UMEMOTO configuration_find_entry(struct configuration *config,
31806a99fe3SHajimu UMEMOTO 	const char *name)
31906a99fe3SHajimu UMEMOTO {
32006a99fe3SHajimu UMEMOTO 	struct configuration_entry	**retval;
32106a99fe3SHajimu UMEMOTO 
32206a99fe3SHajimu UMEMOTO 	TRACE_IN(configuration_find_entry);
32306a99fe3SHajimu UMEMOTO 
32406a99fe3SHajimu UMEMOTO 	retval = bsearch(name, config->entries, config->entries_size,
32506a99fe3SHajimu UMEMOTO 		sizeof(struct configuration_entry *), configuration_entry_cmp);
32606a99fe3SHajimu UMEMOTO 	TRACE_OUT(configuration_find_entry);
32706a99fe3SHajimu UMEMOTO 
32806a99fe3SHajimu UMEMOTO 	return ((retval != NULL) ? *retval : NULL);
32906a99fe3SHajimu UMEMOTO }
33006a99fe3SHajimu UMEMOTO 
33106a99fe3SHajimu UMEMOTO /*
33206a99fe3SHajimu UMEMOTO  * All multipart cache entries are stored in the configuration_entry in the
33306a99fe3SHajimu UMEMOTO  * sorted array (sorted by names). The 3 functions below manage this array.
33406a99fe3SHajimu UMEMOTO  */
33506a99fe3SHajimu UMEMOTO 
33606a99fe3SHajimu UMEMOTO int
33706a99fe3SHajimu UMEMOTO configuration_entry_add_mp_cache_entry(struct configuration_entry *config_entry,
33806a99fe3SHajimu UMEMOTO 	cache_entry c_entry)
33906a99fe3SHajimu UMEMOTO {
34006a99fe3SHajimu UMEMOTO 	cache_entry *new_mp_entries, *old_mp_entries;
34106a99fe3SHajimu UMEMOTO 
34206a99fe3SHajimu UMEMOTO 	TRACE_IN(configuration_entry_add_mp_cache_entry);
34306a99fe3SHajimu UMEMOTO 	++config_entry->mp_cache_entries_size;
3448eeaaffaSDag-Erling Smørgrav 	new_mp_entries = malloc(sizeof(*new_mp_entries) *
34506a99fe3SHajimu UMEMOTO 		config_entry->mp_cache_entries_size);
34606a99fe3SHajimu UMEMOTO 	assert(new_mp_entries != NULL);
34706a99fe3SHajimu UMEMOTO 	new_mp_entries[0] = c_entry;
34806a99fe3SHajimu UMEMOTO 
34906a99fe3SHajimu UMEMOTO 	if (config_entry->mp_cache_entries_size - 1 > 0) {
35006a99fe3SHajimu UMEMOTO 		memcpy(new_mp_entries + 1,
35106a99fe3SHajimu UMEMOTO 		    config_entry->mp_cache_entries,
35206a99fe3SHajimu UMEMOTO 		    (config_entry->mp_cache_entries_size - 1) *
35306a99fe3SHajimu UMEMOTO 		    sizeof(cache_entry));
35406a99fe3SHajimu UMEMOTO 	}
35506a99fe3SHajimu UMEMOTO 
35606a99fe3SHajimu UMEMOTO 	old_mp_entries = config_entry->mp_cache_entries;
35706a99fe3SHajimu UMEMOTO 	config_entry->mp_cache_entries = new_mp_entries;
35806a99fe3SHajimu UMEMOTO 	free(old_mp_entries);
35906a99fe3SHajimu UMEMOTO 
36006a99fe3SHajimu UMEMOTO 	qsort(config_entry->mp_cache_entries,
36106a99fe3SHajimu UMEMOTO 		config_entry->mp_cache_entries_size,
36206a99fe3SHajimu UMEMOTO 		sizeof(cache_entry),
36306a99fe3SHajimu UMEMOTO 		configuration_entry_cache_mp_sort_cmp);
36406a99fe3SHajimu UMEMOTO 
36506a99fe3SHajimu UMEMOTO 	TRACE_OUT(configuration_entry_add_mp_cache_entry);
36606a99fe3SHajimu UMEMOTO 	return (0);
36706a99fe3SHajimu UMEMOTO }
36806a99fe3SHajimu UMEMOTO 
36906a99fe3SHajimu UMEMOTO cache_entry
37006a99fe3SHajimu UMEMOTO configuration_entry_find_mp_cache_entry(
37106a99fe3SHajimu UMEMOTO 	struct configuration_entry *config_entry, const char *mp_name)
37206a99fe3SHajimu UMEMOTO {
37306a99fe3SHajimu UMEMOTO 	cache_entry *result;
37406a99fe3SHajimu UMEMOTO 
37506a99fe3SHajimu UMEMOTO 	TRACE_IN(configuration_entry_find_mp_cache_entry);
37606a99fe3SHajimu UMEMOTO 	result = bsearch(mp_name, config_entry->mp_cache_entries,
37706a99fe3SHajimu UMEMOTO 		config_entry->mp_cache_entries_size,
37806a99fe3SHajimu UMEMOTO 		sizeof(cache_entry), configuration_entry_cache_mp_cmp);
37906a99fe3SHajimu UMEMOTO 
38006a99fe3SHajimu UMEMOTO 	if (result == NULL) {
38106a99fe3SHajimu UMEMOTO 		TRACE_OUT(configuration_entry_find_mp_cache_entry);
38206a99fe3SHajimu UMEMOTO 		return (NULL);
38306a99fe3SHajimu UMEMOTO 	} else {
38406a99fe3SHajimu UMEMOTO 		TRACE_OUT(configuration_entry_find_mp_cache_entry);
38506a99fe3SHajimu UMEMOTO 		return (*result);
38606a99fe3SHajimu UMEMOTO 	}
38706a99fe3SHajimu UMEMOTO }
38806a99fe3SHajimu UMEMOTO 
38906a99fe3SHajimu UMEMOTO /*
39006a99fe3SHajimu UMEMOTO  * Searches for all multipart entries with names starting with mp_name.
39106a99fe3SHajimu UMEMOTO  * Needed for cache flushing.
39206a99fe3SHajimu UMEMOTO  */
39306a99fe3SHajimu UMEMOTO int
39406a99fe3SHajimu UMEMOTO configuration_entry_find_mp_cache_entries(
39506a99fe3SHajimu UMEMOTO 	struct configuration_entry *config_entry, const char *mp_name,
39606a99fe3SHajimu UMEMOTO 	cache_entry **start, cache_entry **finish)
39706a99fe3SHajimu UMEMOTO {
39806a99fe3SHajimu UMEMOTO 	cache_entry *result;
39906a99fe3SHajimu UMEMOTO 
40006a99fe3SHajimu UMEMOTO 	TRACE_IN(configuration_entry_find_mp_cache_entries);
40106a99fe3SHajimu UMEMOTO 	result = bsearch(mp_name, config_entry->mp_cache_entries,
40206a99fe3SHajimu UMEMOTO 		config_entry->mp_cache_entries_size,
40306a99fe3SHajimu UMEMOTO 		sizeof(cache_entry), configuration_entry_cache_mp_part_cmp);
40406a99fe3SHajimu UMEMOTO 
40506a99fe3SHajimu UMEMOTO 	if (result == NULL) {
40606a99fe3SHajimu UMEMOTO 		TRACE_OUT(configuration_entry_find_mp_cache_entries);
40706a99fe3SHajimu UMEMOTO 		return (-1);
40806a99fe3SHajimu UMEMOTO 	}
40906a99fe3SHajimu UMEMOTO 
41006a99fe3SHajimu UMEMOTO 	*start = result;
41106a99fe3SHajimu UMEMOTO 	*finish = result + 1;
41206a99fe3SHajimu UMEMOTO 
41306a99fe3SHajimu UMEMOTO 	while (*start != config_entry->mp_cache_entries) {
41406a99fe3SHajimu UMEMOTO 	    if (configuration_entry_cache_mp_part_cmp(mp_name, *start - 1) == 0)
41506a99fe3SHajimu UMEMOTO 		*start = *start - 1;
41606a99fe3SHajimu UMEMOTO 	    else
41706a99fe3SHajimu UMEMOTO 		break;
41806a99fe3SHajimu UMEMOTO 	}
41906a99fe3SHajimu UMEMOTO 
42006a99fe3SHajimu UMEMOTO 	while (*finish != config_entry->mp_cache_entries +
42106a99fe3SHajimu UMEMOTO 		config_entry->mp_cache_entries_size) {
42206a99fe3SHajimu UMEMOTO 
42306a99fe3SHajimu UMEMOTO 	    if (configuration_entry_cache_mp_part_cmp(
42406a99fe3SHajimu UMEMOTO 		mp_name, *finish) == 0)
42506a99fe3SHajimu UMEMOTO 	    	*finish = *finish + 1;
42606a99fe3SHajimu UMEMOTO 	    else
42706a99fe3SHajimu UMEMOTO 		break;
42806a99fe3SHajimu UMEMOTO 	}
42906a99fe3SHajimu UMEMOTO 
43006a99fe3SHajimu UMEMOTO 	TRACE_OUT(configuration_entry_find_mp_cache_entries);
43106a99fe3SHajimu UMEMOTO 	return (0);
43206a99fe3SHajimu UMEMOTO }
43306a99fe3SHajimu UMEMOTO 
43406a99fe3SHajimu UMEMOTO /*
43506a99fe3SHajimu UMEMOTO  * Configuration entry uses rwlock to handle access to its fields.
43606a99fe3SHajimu UMEMOTO  */
43706a99fe3SHajimu UMEMOTO void
43806a99fe3SHajimu UMEMOTO configuration_lock_rdlock(struct configuration *config)
43906a99fe3SHajimu UMEMOTO {
44006a99fe3SHajimu UMEMOTO     TRACE_IN(configuration_lock_rdlock);
44106a99fe3SHajimu UMEMOTO     pthread_rwlock_rdlock(&config->rwlock);
44206a99fe3SHajimu UMEMOTO     TRACE_OUT(configuration_lock_rdlock);
44306a99fe3SHajimu UMEMOTO }
44406a99fe3SHajimu UMEMOTO 
44506a99fe3SHajimu UMEMOTO void
44606a99fe3SHajimu UMEMOTO configuration_lock_wrlock(struct configuration *config)
44706a99fe3SHajimu UMEMOTO {
44806a99fe3SHajimu UMEMOTO     TRACE_IN(configuration_lock_wrlock);
44906a99fe3SHajimu UMEMOTO     pthread_rwlock_wrlock(&config->rwlock);
45006a99fe3SHajimu UMEMOTO     TRACE_OUT(configuration_lock_wrlock);
45106a99fe3SHajimu UMEMOTO }
45206a99fe3SHajimu UMEMOTO 
45306a99fe3SHajimu UMEMOTO void
45406a99fe3SHajimu UMEMOTO configuration_unlock(struct configuration *config)
45506a99fe3SHajimu UMEMOTO {
45606a99fe3SHajimu UMEMOTO     TRACE_IN(configuration_unlock);
45706a99fe3SHajimu UMEMOTO     pthread_rwlock_unlock(&config->rwlock);
45806a99fe3SHajimu UMEMOTO     TRACE_OUT(configuration_unlock);
45906a99fe3SHajimu UMEMOTO }
46006a99fe3SHajimu UMEMOTO 
46106a99fe3SHajimu UMEMOTO /*
46206a99fe3SHajimu UMEMOTO  * Configuration entry uses 3 mutexes to handle cache operations. They are
46306a99fe3SHajimu UMEMOTO  * acquired by configuration_lock_entry and configuration_unlock_entry
46406a99fe3SHajimu UMEMOTO  * functions.
46506a99fe3SHajimu UMEMOTO  */
46606a99fe3SHajimu UMEMOTO void
46706a99fe3SHajimu UMEMOTO configuration_lock_entry(struct configuration_entry *entry,
46806a99fe3SHajimu UMEMOTO 	enum config_entry_lock_type lock_type)
46906a99fe3SHajimu UMEMOTO {
47006a99fe3SHajimu UMEMOTO 	TRACE_IN(configuration_lock_entry);
47106a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
47206a99fe3SHajimu UMEMOTO 
47306a99fe3SHajimu UMEMOTO 	switch (lock_type) {
47406a99fe3SHajimu UMEMOTO 	case CELT_POSITIVE:
47506a99fe3SHajimu UMEMOTO 		pthread_mutex_lock(&entry->positive_cache_lock);
47606a99fe3SHajimu UMEMOTO 		break;
47706a99fe3SHajimu UMEMOTO 	case CELT_NEGATIVE:
47806a99fe3SHajimu UMEMOTO 		pthread_mutex_lock(&entry->negative_cache_lock);
47906a99fe3SHajimu UMEMOTO 		break;
48006a99fe3SHajimu UMEMOTO 	case CELT_MULTIPART:
48106a99fe3SHajimu UMEMOTO 		pthread_mutex_lock(&entry->mp_cache_lock);
48206a99fe3SHajimu UMEMOTO 		break;
48306a99fe3SHajimu UMEMOTO 	default:
48406a99fe3SHajimu UMEMOTO 		/* should be unreachable */
48506a99fe3SHajimu UMEMOTO 		break;
48606a99fe3SHajimu UMEMOTO 	}
48706a99fe3SHajimu UMEMOTO 	TRACE_OUT(configuration_lock_entry);
48806a99fe3SHajimu UMEMOTO }
48906a99fe3SHajimu UMEMOTO 
49006a99fe3SHajimu UMEMOTO void
49106a99fe3SHajimu UMEMOTO configuration_unlock_entry(struct configuration_entry *entry,
49206a99fe3SHajimu UMEMOTO 	enum config_entry_lock_type lock_type)
49306a99fe3SHajimu UMEMOTO {
49406a99fe3SHajimu UMEMOTO 	TRACE_IN(configuration_unlock_entry);
49506a99fe3SHajimu UMEMOTO 	assert(entry != NULL);
49606a99fe3SHajimu UMEMOTO 
49706a99fe3SHajimu UMEMOTO 	switch (lock_type) {
49806a99fe3SHajimu UMEMOTO 	case CELT_POSITIVE:
49906a99fe3SHajimu UMEMOTO 		pthread_mutex_unlock(&entry->positive_cache_lock);
50006a99fe3SHajimu UMEMOTO 		break;
50106a99fe3SHajimu UMEMOTO 	case CELT_NEGATIVE:
50206a99fe3SHajimu UMEMOTO 		pthread_mutex_unlock(&entry->negative_cache_lock);
50306a99fe3SHajimu UMEMOTO 		break;
50406a99fe3SHajimu UMEMOTO 	case CELT_MULTIPART:
50506a99fe3SHajimu UMEMOTO 		pthread_mutex_unlock(&entry->mp_cache_lock);
50606a99fe3SHajimu UMEMOTO 		break;
50706a99fe3SHajimu UMEMOTO 	default:
50806a99fe3SHajimu UMEMOTO 		/* should be unreachable */
50906a99fe3SHajimu UMEMOTO 		break;
51006a99fe3SHajimu UMEMOTO 	}
51106a99fe3SHajimu UMEMOTO 	TRACE_OUT(configuration_unlock_entry);
51206a99fe3SHajimu UMEMOTO }
51306a99fe3SHajimu UMEMOTO 
51406a99fe3SHajimu UMEMOTO struct configuration *
51506a99fe3SHajimu UMEMOTO init_configuration(void)
51606a99fe3SHajimu UMEMOTO {
51706a99fe3SHajimu UMEMOTO 	struct configuration	*retval;
51806a99fe3SHajimu UMEMOTO 
51906a99fe3SHajimu UMEMOTO 	TRACE_IN(init_configuration);
5208eeaaffaSDag-Erling Smørgrav 	retval = calloc(1, sizeof(*retval));
52106a99fe3SHajimu UMEMOTO 	assert(retval != NULL);
52206a99fe3SHajimu UMEMOTO 
52306a99fe3SHajimu UMEMOTO 	retval->entries_capacity = INITIAL_ENTRIES_CAPACITY;
524*87959e27SPedro F. Giffuni 	retval->entries = calloc(retval->entries_capacity,
525*87959e27SPedro F. Giffuni 		sizeof(*retval->entries));
52606a99fe3SHajimu UMEMOTO 	assert(retval->entries != NULL);
52706a99fe3SHajimu UMEMOTO 
52806a99fe3SHajimu UMEMOTO 	pthread_rwlock_init(&retval->rwlock, NULL);
52906a99fe3SHajimu UMEMOTO 
53006a99fe3SHajimu UMEMOTO 	TRACE_OUT(init_configuration);
53106a99fe3SHajimu UMEMOTO 	return (retval);
53206a99fe3SHajimu UMEMOTO }
53306a99fe3SHajimu UMEMOTO 
53406a99fe3SHajimu UMEMOTO void
53506a99fe3SHajimu UMEMOTO fill_configuration_defaults(struct configuration *config)
53606a99fe3SHajimu UMEMOTO {
53706a99fe3SHajimu UMEMOTO 	size_t	len, i;
53806a99fe3SHajimu UMEMOTO 
53906a99fe3SHajimu UMEMOTO 	TRACE_IN(fill_configuration_defaults);
54006a99fe3SHajimu UMEMOTO 	assert(config != NULL);
54106a99fe3SHajimu UMEMOTO 
54206a99fe3SHajimu UMEMOTO 	if (config->socket_path != NULL)
54306a99fe3SHajimu UMEMOTO 		free(config->socket_path);
54406a99fe3SHajimu UMEMOTO 
54506a99fe3SHajimu UMEMOTO 	len = strlen(DEFAULT_SOCKET_PATH);
5468eeaaffaSDag-Erling Smørgrav 	config->socket_path = calloc(1, len + 1);
54706a99fe3SHajimu UMEMOTO 	assert(config->socket_path != NULL);
54806a99fe3SHajimu UMEMOTO 	memcpy(config->socket_path, DEFAULT_SOCKET_PATH, len);
54906a99fe3SHajimu UMEMOTO 
55006a99fe3SHajimu UMEMOTO 	len = strlen(DEFAULT_PIDFILE_PATH);
5518eeaaffaSDag-Erling Smørgrav 	config->pidfile_path = calloc(1, len + 1);
55206a99fe3SHajimu UMEMOTO 	assert(config->pidfile_path != NULL);
55306a99fe3SHajimu UMEMOTO 	memcpy(config->pidfile_path, DEFAULT_PIDFILE_PATH, len);
55406a99fe3SHajimu UMEMOTO 
55506a99fe3SHajimu UMEMOTO 	config->socket_mode =  S_IFSOCK | S_IRUSR | S_IWUSR |
55606a99fe3SHajimu UMEMOTO 		S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
55706a99fe3SHajimu UMEMOTO 	config->force_unlink = 1;
55806a99fe3SHajimu UMEMOTO 
55906a99fe3SHajimu UMEMOTO 	config->query_timeout = DEFAULT_QUERY_TIMEOUT;
56006a99fe3SHajimu UMEMOTO 	config->threads_num = DEFAULT_THREADS_NUM;
56106a99fe3SHajimu UMEMOTO 
56206a99fe3SHajimu UMEMOTO 	for (i = 0; i < config->entries_size; ++i)
56306a99fe3SHajimu UMEMOTO 		destroy_configuration_entry(config->entries[i]);
56406a99fe3SHajimu UMEMOTO 	config->entries_size = 0;
56506a99fe3SHajimu UMEMOTO 
56606a99fe3SHajimu UMEMOTO 	TRACE_OUT(fill_configuration_defaults);
56706a99fe3SHajimu UMEMOTO }
56806a99fe3SHajimu UMEMOTO 
56906a99fe3SHajimu UMEMOTO void
57006a99fe3SHajimu UMEMOTO destroy_configuration(struct configuration *config)
57106a99fe3SHajimu UMEMOTO {
57251d6ddb5SDag-Erling Smørgrav 	unsigned int i;
57351d6ddb5SDag-Erling Smørgrav 
57406a99fe3SHajimu UMEMOTO 	TRACE_IN(destroy_configuration);
57506a99fe3SHajimu UMEMOTO 	assert(config != NULL);
57606a99fe3SHajimu UMEMOTO 	free(config->pidfile_path);
57706a99fe3SHajimu UMEMOTO 	free(config->socket_path);
57806a99fe3SHajimu UMEMOTO 
57906a99fe3SHajimu UMEMOTO 	for (i = 0; i < config->entries_size; ++i)
58006a99fe3SHajimu UMEMOTO 		destroy_configuration_entry(config->entries[i]);
58106a99fe3SHajimu UMEMOTO 	free(config->entries);
58206a99fe3SHajimu UMEMOTO 
58306a99fe3SHajimu UMEMOTO 	pthread_rwlock_destroy(&config->rwlock);
58406a99fe3SHajimu UMEMOTO 	free(config);
58506a99fe3SHajimu UMEMOTO 	TRACE_OUT(destroy_configuration);
58606a99fe3SHajimu UMEMOTO }
587