xref: /freebsd/lib/libc/net/nscache.c (revision d915a14ef094c8dfc1a5aee70e135abfec01d0f1)
106a99fe3SHajimu UMEMOTO /*-
2*d915a14eSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*d915a14eSPedro F. Giffuni  *
406a99fe3SHajimu UMEMOTO  * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
506a99fe3SHajimu UMEMOTO  * All rights reserved.
606a99fe3SHajimu UMEMOTO  *
706a99fe3SHajimu UMEMOTO  * Redistribution and use in source and binary forms, with or without
806a99fe3SHajimu UMEMOTO  * modification, are permitted provided that the following conditions
906a99fe3SHajimu UMEMOTO  * are met:
1006a99fe3SHajimu UMEMOTO  * 1. Redistributions of source code must retain the above copyright
1106a99fe3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer.
1206a99fe3SHajimu UMEMOTO  * 2. Redistributions in binary form must reproduce the above copyright
1306a99fe3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer in the
1406a99fe3SHajimu UMEMOTO  *    documentation and/or other materials provided with the distribution.
1506a99fe3SHajimu UMEMOTO  *
1606a99fe3SHajimu UMEMOTO  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1706a99fe3SHajimu UMEMOTO  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1806a99fe3SHajimu UMEMOTO  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1906a99fe3SHajimu UMEMOTO  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2006a99fe3SHajimu UMEMOTO  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2106a99fe3SHajimu UMEMOTO  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2206a99fe3SHajimu UMEMOTO  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2306a99fe3SHajimu UMEMOTO  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2406a99fe3SHajimu UMEMOTO  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2506a99fe3SHajimu UMEMOTO  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2606a99fe3SHajimu UMEMOTO  * SUCH DAMAGE.
2706a99fe3SHajimu UMEMOTO  *
2806a99fe3SHajimu UMEMOTO  */
2906a99fe3SHajimu UMEMOTO 
3006a99fe3SHajimu UMEMOTO #include <sys/cdefs.h>
3106a99fe3SHajimu UMEMOTO __FBSDID("$FreeBSD$");
3206a99fe3SHajimu UMEMOTO 
3306a99fe3SHajimu UMEMOTO #include "namespace.h"
34ae274020SCraig Rodrigues #define _NS_PRIVATE
3506a99fe3SHajimu UMEMOTO #include <nsswitch.h>
3606a99fe3SHajimu UMEMOTO #include <stdlib.h>
3706a99fe3SHajimu UMEMOTO #include <string.h>
3806a99fe3SHajimu UMEMOTO #include "un-namespace.h"
3906a99fe3SHajimu UMEMOTO #include "nscachedcli.h"
4006a99fe3SHajimu UMEMOTO #include "nscache.h"
4106a99fe3SHajimu UMEMOTO 
4206a99fe3SHajimu UMEMOTO #define NSS_CACHE_KEY_INITIAL_SIZE	(256)
4306a99fe3SHajimu UMEMOTO #define NSS_CACHE_KEY_SIZE_LIMIT	(NSS_CACHE_KEY_INITIAL_SIZE << 4)
4406a99fe3SHajimu UMEMOTO 
4506a99fe3SHajimu UMEMOTO #define NSS_CACHE_BUFFER_INITIAL_SIZE	(1024)
4606a99fe3SHajimu UMEMOTO #define NSS_CACHE_BUFFER_SIZE_LIMIT	(NSS_CACHE_BUFFER_INITIAL_SIZE << 8)
4706a99fe3SHajimu UMEMOTO 
4890855671STom McLaughlin #define CACHED_SOCKET_PATH 		"/var/run/nscd"
4906a99fe3SHajimu UMEMOTO 
5006a99fe3SHajimu UMEMOTO int
5106a99fe3SHajimu UMEMOTO __nss_cache_handler(void *retval, void *mdata, va_list ap)
5206a99fe3SHajimu UMEMOTO {
5306a99fe3SHajimu UMEMOTO 	return (NS_UNAVAIL);
5406a99fe3SHajimu UMEMOTO }
5506a99fe3SHajimu UMEMOTO 
5606a99fe3SHajimu UMEMOTO int
5706a99fe3SHajimu UMEMOTO __nss_common_cache_read(void *retval, void *mdata, va_list ap)
5806a99fe3SHajimu UMEMOTO {
5906a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
6006a99fe3SHajimu UMEMOTO 	cached_connection connection;
6106a99fe3SHajimu UMEMOTO 
6206a99fe3SHajimu UMEMOTO 	char *buffer;
6306a99fe3SHajimu UMEMOTO 	size_t buffer_size, size;
6406a99fe3SHajimu UMEMOTO 
6506a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
6606a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
6706a99fe3SHajimu UMEMOTO 	va_list ap_new;
6806a99fe3SHajimu UMEMOTO 	int res;
6906a99fe3SHajimu UMEMOTO 
7006a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
7106a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
7206a99fe3SHajimu UMEMOTO 
7306a99fe3SHajimu UMEMOTO 	memset(&params, 0, sizeof(struct cached_connection_params));
7406a99fe3SHajimu UMEMOTO 	params.socket_path = CACHED_SOCKET_PATH;
7506a99fe3SHajimu UMEMOTO 
7606a99fe3SHajimu UMEMOTO 	cache_data->key = (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE);
7706a99fe3SHajimu UMEMOTO 	memset(cache_data->key, 0, NSS_CACHE_KEY_INITIAL_SIZE);
7806a99fe3SHajimu UMEMOTO 	cache_data->key_size = NSS_CACHE_KEY_INITIAL_SIZE;
7906a99fe3SHajimu UMEMOTO 	va_copy(ap_new, ap);
8006a99fe3SHajimu UMEMOTO 
8106a99fe3SHajimu UMEMOTO 	do {
8206a99fe3SHajimu UMEMOTO 		size = cache_data->key_size;
8306a99fe3SHajimu UMEMOTO 		res = cache_info->id_func(cache_data->key, &size, ap_new,
8406a99fe3SHajimu UMEMOTO 		    cache_info->mdata);
8506a99fe3SHajimu UMEMOTO 		va_end(ap_new);
8606a99fe3SHajimu UMEMOTO 		if (res == NS_RETURN) {
8706a99fe3SHajimu UMEMOTO 			if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT)
8806a99fe3SHajimu UMEMOTO 				break;
8906a99fe3SHajimu UMEMOTO 
9006a99fe3SHajimu UMEMOTO 			cache_data->key_size <<= 1;
9106a99fe3SHajimu UMEMOTO 			cache_data->key = realloc(cache_data->key,
9206a99fe3SHajimu UMEMOTO 			    cache_data->key_size);
9306a99fe3SHajimu UMEMOTO 			memset(cache_data->key, 0, cache_data->key_size);
9406a99fe3SHajimu UMEMOTO 			va_copy(ap_new, ap);
9506a99fe3SHajimu UMEMOTO 		}
9606a99fe3SHajimu UMEMOTO 	} while (res == NS_RETURN);
9706a99fe3SHajimu UMEMOTO 
9806a99fe3SHajimu UMEMOTO 	if (res != NS_SUCCESS) {
9906a99fe3SHajimu UMEMOTO 		free(cache_data->key);
10006a99fe3SHajimu UMEMOTO 		cache_data->key = NULL;
10106a99fe3SHajimu UMEMOTO 		cache_data->key_size = 0;
10206a99fe3SHajimu UMEMOTO 		return (res);
10306a99fe3SHajimu UMEMOTO 	} else
10406a99fe3SHajimu UMEMOTO 		cache_data->key_size = size;
10506a99fe3SHajimu UMEMOTO 
10606a99fe3SHajimu UMEMOTO 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
10706a99fe3SHajimu UMEMOTO 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
10806a99fe3SHajimu UMEMOTO 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
10906a99fe3SHajimu UMEMOTO 
11006a99fe3SHajimu UMEMOTO 	do {
11106a99fe3SHajimu UMEMOTO 		connection = __open_cached_connection(&params);
11206a99fe3SHajimu UMEMOTO 		if (connection == NULL) {
11306a99fe3SHajimu UMEMOTO 			res = -1;
11406a99fe3SHajimu UMEMOTO 			break;
11506a99fe3SHajimu UMEMOTO 		}
11606a99fe3SHajimu UMEMOTO 		res = __cached_read(connection, cache_info->entry_name,
11706a99fe3SHajimu UMEMOTO 		    cache_data->key, cache_data->key_size, buffer,
11806a99fe3SHajimu UMEMOTO 		    &buffer_size);
11906a99fe3SHajimu UMEMOTO 		__close_cached_connection(connection);
12006a99fe3SHajimu UMEMOTO 		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
12106a99fe3SHajimu UMEMOTO 			buffer = (char *)realloc(buffer, buffer_size);
12206a99fe3SHajimu UMEMOTO 			memset(buffer, 0, buffer_size);
12306a99fe3SHajimu UMEMOTO 		}
12406a99fe3SHajimu UMEMOTO 	} while (res == -2);
12506a99fe3SHajimu UMEMOTO 
12606a99fe3SHajimu UMEMOTO 	if (res == 0) {
12706a99fe3SHajimu UMEMOTO 		if (buffer_size == 0) {
12806a99fe3SHajimu UMEMOTO 			free(buffer);
12906a99fe3SHajimu UMEMOTO 			free(cache_data->key);
13006a99fe3SHajimu UMEMOTO 			cache_data->key = NULL;
13106a99fe3SHajimu UMEMOTO 			cache_data->key_size = 0;
13206a99fe3SHajimu UMEMOTO 			return (NS_RETURN);
13306a99fe3SHajimu UMEMOTO 		}
13406a99fe3SHajimu UMEMOTO 
13506a99fe3SHajimu UMEMOTO 		va_copy(ap_new, ap);
13606a99fe3SHajimu UMEMOTO 		res = cache_info->unmarshal_func(buffer, buffer_size, retval,
13706a99fe3SHajimu UMEMOTO 		    ap_new, cache_info->mdata);
13806a99fe3SHajimu UMEMOTO 		va_end(ap_new);
13906a99fe3SHajimu UMEMOTO 
14006a99fe3SHajimu UMEMOTO 		if (res != NS_SUCCESS) {
14106a99fe3SHajimu UMEMOTO 			free(buffer);
14206a99fe3SHajimu UMEMOTO 			free(cache_data->key);
14306a99fe3SHajimu UMEMOTO 			cache_data->key = NULL;
14406a99fe3SHajimu UMEMOTO 			cache_data->key_size = 0;
14506a99fe3SHajimu UMEMOTO 			return (res);
14606a99fe3SHajimu UMEMOTO 		} else
14706a99fe3SHajimu UMEMOTO 			res = 0;
14806a99fe3SHajimu UMEMOTO 	}
14906a99fe3SHajimu UMEMOTO 
15006a99fe3SHajimu UMEMOTO 	if (res == 0) {
15106a99fe3SHajimu UMEMOTO 		free(cache_data->key);
15206a99fe3SHajimu UMEMOTO 		cache_data->key = NULL;
15306a99fe3SHajimu UMEMOTO 		cache_data->key_size = 0;
15406a99fe3SHajimu UMEMOTO 	}
15506a99fe3SHajimu UMEMOTO 
15606a99fe3SHajimu UMEMOTO 	free(buffer);
15706a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
15806a99fe3SHajimu UMEMOTO }
15906a99fe3SHajimu UMEMOTO 
16006a99fe3SHajimu UMEMOTO int
16106a99fe3SHajimu UMEMOTO __nss_common_cache_write(void *retval, void *mdata, va_list ap)
16206a99fe3SHajimu UMEMOTO {
16306a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
16406a99fe3SHajimu UMEMOTO 	cached_connection connection;
16506a99fe3SHajimu UMEMOTO 
16606a99fe3SHajimu UMEMOTO 	char *buffer;
16706a99fe3SHajimu UMEMOTO 	size_t buffer_size;
16806a99fe3SHajimu UMEMOTO 
16906a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
17006a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
17106a99fe3SHajimu UMEMOTO 	va_list ap_new;
17206a99fe3SHajimu UMEMOTO 	int res;
17306a99fe3SHajimu UMEMOTO 
17406a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
17506a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
17606a99fe3SHajimu UMEMOTO 
17706a99fe3SHajimu UMEMOTO 	if (cache_data->key == NULL)
17806a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
17906a99fe3SHajimu UMEMOTO 
18006a99fe3SHajimu UMEMOTO 	memset(&params, 0, sizeof(struct cached_connection_params));
18106a99fe3SHajimu UMEMOTO 	params.socket_path = CACHED_SOCKET_PATH;
18206a99fe3SHajimu UMEMOTO 
18306a99fe3SHajimu UMEMOTO 	connection = __open_cached_connection(&params);
18406a99fe3SHajimu UMEMOTO 	if (connection == NULL) {
18506a99fe3SHajimu UMEMOTO 		free(cache_data->key);
18606a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
18706a99fe3SHajimu UMEMOTO 	}
18806a99fe3SHajimu UMEMOTO 
18906a99fe3SHajimu UMEMOTO 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
19006a99fe3SHajimu UMEMOTO 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
19106a99fe3SHajimu UMEMOTO 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
19206a99fe3SHajimu UMEMOTO 
19306a99fe3SHajimu UMEMOTO 	do {
19406a99fe3SHajimu UMEMOTO 		size_t size;
19506a99fe3SHajimu UMEMOTO 
19606a99fe3SHajimu UMEMOTO 		size = buffer_size;
19706a99fe3SHajimu UMEMOTO 		va_copy(ap_new, ap);
19806a99fe3SHajimu UMEMOTO 		res = cache_info->marshal_func(buffer, &size, retval, ap_new,
19906a99fe3SHajimu UMEMOTO 		    cache_info->mdata);
20006a99fe3SHajimu UMEMOTO 		va_end(ap_new);
20106a99fe3SHajimu UMEMOTO 
20206a99fe3SHajimu UMEMOTO 		if (res == NS_RETURN) {
20306a99fe3SHajimu UMEMOTO 			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
20406a99fe3SHajimu UMEMOTO 				break;
20506a99fe3SHajimu UMEMOTO 
20606a99fe3SHajimu UMEMOTO 			buffer_size <<= 1;
20706a99fe3SHajimu UMEMOTO 			buffer = (char *)realloc(buffer, buffer_size);
20806a99fe3SHajimu UMEMOTO 			memset(buffer, 0, buffer_size);
20906a99fe3SHajimu UMEMOTO 		}
21006a99fe3SHajimu UMEMOTO 	} while (res == NS_RETURN);
21106a99fe3SHajimu UMEMOTO 
21206a99fe3SHajimu UMEMOTO 	if (res != NS_SUCCESS) {
21306a99fe3SHajimu UMEMOTO 		__close_cached_connection(connection);
21406a99fe3SHajimu UMEMOTO 		free(cache_data->key);
21506a99fe3SHajimu UMEMOTO 		free(buffer);
21606a99fe3SHajimu UMEMOTO 		return (res);
21706a99fe3SHajimu UMEMOTO 	}
21806a99fe3SHajimu UMEMOTO 
21906a99fe3SHajimu UMEMOTO 	res = __cached_write(connection, cache_info->entry_name,
22006a99fe3SHajimu UMEMOTO 	    cache_data->key, cache_data->key_size, buffer, buffer_size);
22106a99fe3SHajimu UMEMOTO 	__close_cached_connection(connection);
22206a99fe3SHajimu UMEMOTO 
22306a99fe3SHajimu UMEMOTO 	free(cache_data->key);
22406a99fe3SHajimu UMEMOTO 	free(buffer);
22506a99fe3SHajimu UMEMOTO 
22606a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
22706a99fe3SHajimu UMEMOTO }
22806a99fe3SHajimu UMEMOTO 
22906a99fe3SHajimu UMEMOTO int
23006a99fe3SHajimu UMEMOTO __nss_common_cache_write_negative(void *mdata)
23106a99fe3SHajimu UMEMOTO {
23206a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
23306a99fe3SHajimu UMEMOTO 	cached_connection connection;
23406a99fe3SHajimu UMEMOTO 	int res;
23506a99fe3SHajimu UMEMOTO 
23606a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
23706a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
23806a99fe3SHajimu UMEMOTO 
23906a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
24006a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
24106a99fe3SHajimu UMEMOTO 
24206a99fe3SHajimu UMEMOTO 	if (cache_data->key == NULL)
24306a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
24406a99fe3SHajimu UMEMOTO 
24506a99fe3SHajimu UMEMOTO 	memset(&params, 0, sizeof(struct cached_connection_params));
24606a99fe3SHajimu UMEMOTO 	params.socket_path = CACHED_SOCKET_PATH;
24706a99fe3SHajimu UMEMOTO 
24806a99fe3SHajimu UMEMOTO 	connection = __open_cached_connection(&params);
24906a99fe3SHajimu UMEMOTO 	if (connection == NULL) {
25006a99fe3SHajimu UMEMOTO 		free(cache_data->key);
25106a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
25206a99fe3SHajimu UMEMOTO 	}
25306a99fe3SHajimu UMEMOTO 
25406a99fe3SHajimu UMEMOTO 	res = __cached_write(connection, cache_info->entry_name,
25506a99fe3SHajimu UMEMOTO 	    cache_data->key, cache_data->key_size, NULL, 0);
25606a99fe3SHajimu UMEMOTO 	__close_cached_connection(connection);
25706a99fe3SHajimu UMEMOTO 
25806a99fe3SHajimu UMEMOTO 	free(cache_data->key);
25906a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
26006a99fe3SHajimu UMEMOTO }
26106a99fe3SHajimu UMEMOTO 
26206a99fe3SHajimu UMEMOTO int
26306a99fe3SHajimu UMEMOTO __nss_mp_cache_read(void *retval, void *mdata, va_list ap)
26406a99fe3SHajimu UMEMOTO {
26506a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
26606a99fe3SHajimu UMEMOTO 	cached_mp_read_session rs;
26706a99fe3SHajimu UMEMOTO 
26806a99fe3SHajimu UMEMOTO 	char *buffer;
26906a99fe3SHajimu UMEMOTO 	size_t buffer_size;
27006a99fe3SHajimu UMEMOTO 
27106a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
27206a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
27306a99fe3SHajimu UMEMOTO 	va_list ap_new;
27406a99fe3SHajimu UMEMOTO 	int res;
27506a99fe3SHajimu UMEMOTO 
27606a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
27706a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
27806a99fe3SHajimu UMEMOTO 
27906a99fe3SHajimu UMEMOTO 	if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION)
28006a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
28106a99fe3SHajimu UMEMOTO 
28206a99fe3SHajimu UMEMOTO 	rs = cache_info->get_mp_rs_func();
28306a99fe3SHajimu UMEMOTO 	if (rs == INVALID_CACHED_MP_READ_SESSION) {
28406a99fe3SHajimu UMEMOTO 		memset(&params, 0, sizeof(struct cached_connection_params));
28506a99fe3SHajimu UMEMOTO 		params.socket_path = CACHED_SOCKET_PATH;
28606a99fe3SHajimu UMEMOTO 
28706a99fe3SHajimu UMEMOTO 		rs = __open_cached_mp_read_session(&params,
28806a99fe3SHajimu UMEMOTO 		    cache_info->entry_name);
28906a99fe3SHajimu UMEMOTO 		if (rs == INVALID_CACHED_MP_READ_SESSION)
29006a99fe3SHajimu UMEMOTO 			return (NS_UNAVAIL);
29106a99fe3SHajimu UMEMOTO 
29206a99fe3SHajimu UMEMOTO 		cache_info->set_mp_rs_func(rs);
29306a99fe3SHajimu UMEMOTO 	}
29406a99fe3SHajimu UMEMOTO 
29506a99fe3SHajimu UMEMOTO 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
29606a99fe3SHajimu UMEMOTO 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
29706a99fe3SHajimu UMEMOTO 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
29806a99fe3SHajimu UMEMOTO 
29906a99fe3SHajimu UMEMOTO 	do {
30006a99fe3SHajimu UMEMOTO 		res = __cached_mp_read(rs, buffer, &buffer_size);
30106a99fe3SHajimu UMEMOTO 		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
30206a99fe3SHajimu UMEMOTO 			buffer = (char *)realloc(buffer, buffer_size);
30306a99fe3SHajimu UMEMOTO 			memset(buffer, 0, buffer_size);
30406a99fe3SHajimu UMEMOTO 		}
30506a99fe3SHajimu UMEMOTO 	} while (res == -2);
30606a99fe3SHajimu UMEMOTO 
30706a99fe3SHajimu UMEMOTO 	if (res == 0) {
30806a99fe3SHajimu UMEMOTO 		va_copy(ap_new, ap);
30906a99fe3SHajimu UMEMOTO 		res = cache_info->unmarshal_func(buffer, buffer_size, retval,
31006a99fe3SHajimu UMEMOTO 		    ap_new, cache_info->mdata);
31106a99fe3SHajimu UMEMOTO 		va_end(ap_new);
31206a99fe3SHajimu UMEMOTO 
31306a99fe3SHajimu UMEMOTO 		if (res != NS_SUCCESS) {
31406a99fe3SHajimu UMEMOTO 			free(buffer);
31506a99fe3SHajimu UMEMOTO 			return (res);
31606a99fe3SHajimu UMEMOTO 		} else
31706a99fe3SHajimu UMEMOTO 			res = 0;
31806a99fe3SHajimu UMEMOTO 	} else {
31906a99fe3SHajimu UMEMOTO 		free(buffer);
32006a99fe3SHajimu UMEMOTO 		__close_cached_mp_read_session(rs);
32106a99fe3SHajimu UMEMOTO 		rs = INVALID_CACHED_MP_READ_SESSION;
32206a99fe3SHajimu UMEMOTO 		cache_info->set_mp_rs_func(rs);
32306a99fe3SHajimu UMEMOTO 		return (res == -1 ? NS_RETURN : NS_UNAVAIL);
32406a99fe3SHajimu UMEMOTO 	}
32506a99fe3SHajimu UMEMOTO 
32606a99fe3SHajimu UMEMOTO 	free(buffer);
32706a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
32806a99fe3SHajimu UMEMOTO }
32906a99fe3SHajimu UMEMOTO 
33006a99fe3SHajimu UMEMOTO int
33106a99fe3SHajimu UMEMOTO __nss_mp_cache_write(void *retval, void *mdata, va_list ap)
33206a99fe3SHajimu UMEMOTO {
33306a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
33406a99fe3SHajimu UMEMOTO 	cached_mp_write_session ws;
33506a99fe3SHajimu UMEMOTO 
33606a99fe3SHajimu UMEMOTO 	char *buffer;
33706a99fe3SHajimu UMEMOTO 	size_t buffer_size;
33806a99fe3SHajimu UMEMOTO 
33906a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
34006a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
34106a99fe3SHajimu UMEMOTO 	va_list ap_new;
34206a99fe3SHajimu UMEMOTO 	int res;
34306a99fe3SHajimu UMEMOTO 
34406a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
34506a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
34606a99fe3SHajimu UMEMOTO 
34706a99fe3SHajimu UMEMOTO 	ws = cache_info->get_mp_ws_func();
34806a99fe3SHajimu UMEMOTO 	if (ws == INVALID_CACHED_MP_WRITE_SESSION) {
34906a99fe3SHajimu UMEMOTO 		memset(&params, 0, sizeof(struct cached_connection_params));
35006a99fe3SHajimu UMEMOTO 		params.socket_path = CACHED_SOCKET_PATH;
35106a99fe3SHajimu UMEMOTO 
35206a99fe3SHajimu UMEMOTO 		ws = __open_cached_mp_write_session(&params,
35306a99fe3SHajimu UMEMOTO 		    cache_info->entry_name);
35406a99fe3SHajimu UMEMOTO 		if (ws == INVALID_CACHED_MP_WRITE_SESSION)
35506a99fe3SHajimu UMEMOTO 			return (NS_UNAVAIL);
35606a99fe3SHajimu UMEMOTO 
35706a99fe3SHajimu UMEMOTO 		cache_info->set_mp_ws_func(ws);
35806a99fe3SHajimu UMEMOTO 	}
35906a99fe3SHajimu UMEMOTO 
36006a99fe3SHajimu UMEMOTO 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
36106a99fe3SHajimu UMEMOTO 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
36206a99fe3SHajimu UMEMOTO 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
36306a99fe3SHajimu UMEMOTO 
36406a99fe3SHajimu UMEMOTO 	do {
36506a99fe3SHajimu UMEMOTO 		size_t size;
36606a99fe3SHajimu UMEMOTO 
36706a99fe3SHajimu UMEMOTO 		size = buffer_size;
36806a99fe3SHajimu UMEMOTO 		va_copy(ap_new, ap);
36906a99fe3SHajimu UMEMOTO 		res = cache_info->marshal_func(buffer, &size, retval, ap_new,
37006a99fe3SHajimu UMEMOTO 		    cache_info->mdata);
37106a99fe3SHajimu UMEMOTO 		va_end(ap_new);
37206a99fe3SHajimu UMEMOTO 
37306a99fe3SHajimu UMEMOTO 		if (res == NS_RETURN) {
37406a99fe3SHajimu UMEMOTO 			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
37506a99fe3SHajimu UMEMOTO 				break;
37606a99fe3SHajimu UMEMOTO 
37706a99fe3SHajimu UMEMOTO 			buffer_size <<= 1;
37806a99fe3SHajimu UMEMOTO 			buffer = (char *)realloc(buffer, buffer_size);
37906a99fe3SHajimu UMEMOTO 			memset(buffer, 0, buffer_size);
38006a99fe3SHajimu UMEMOTO 		}
38106a99fe3SHajimu UMEMOTO 	} while (res == NS_RETURN);
38206a99fe3SHajimu UMEMOTO 
38306a99fe3SHajimu UMEMOTO 	if (res != NS_SUCCESS) {
38406a99fe3SHajimu UMEMOTO 		free(buffer);
38506a99fe3SHajimu UMEMOTO 		return (res);
38606a99fe3SHajimu UMEMOTO 	}
38706a99fe3SHajimu UMEMOTO 
38806a99fe3SHajimu UMEMOTO 	res = __cached_mp_write(ws, buffer, buffer_size);
38906a99fe3SHajimu UMEMOTO 
39006a99fe3SHajimu UMEMOTO 	free(buffer);
39106a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
39206a99fe3SHajimu UMEMOTO }
39306a99fe3SHajimu UMEMOTO 
39406a99fe3SHajimu UMEMOTO int
39506a99fe3SHajimu UMEMOTO __nss_mp_cache_write_submit(void *retval, void *mdata, va_list ap)
39606a99fe3SHajimu UMEMOTO {
39706a99fe3SHajimu UMEMOTO 	cached_mp_write_session ws;
39806a99fe3SHajimu UMEMOTO 
39906a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
40006a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
40106a99fe3SHajimu UMEMOTO 
40206a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
40306a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
40406a99fe3SHajimu UMEMOTO 
40506a99fe3SHajimu UMEMOTO 	ws = cache_info->get_mp_ws_func();
40606a99fe3SHajimu UMEMOTO 	if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
40706a99fe3SHajimu UMEMOTO 		__close_cached_mp_write_session(ws);
40806a99fe3SHajimu UMEMOTO 		ws = INVALID_CACHED_MP_WRITE_SESSION;
40906a99fe3SHajimu UMEMOTO 		cache_info->set_mp_ws_func(ws);
41006a99fe3SHajimu UMEMOTO 	}
41106a99fe3SHajimu UMEMOTO 	return (NS_UNAVAIL);
41206a99fe3SHajimu UMEMOTO }
41306a99fe3SHajimu UMEMOTO 
41406a99fe3SHajimu UMEMOTO int
41506a99fe3SHajimu UMEMOTO __nss_mp_cache_end(void *retval, void *mdata, va_list ap)
41606a99fe3SHajimu UMEMOTO {
41706a99fe3SHajimu UMEMOTO 	cached_mp_write_session ws;
41806a99fe3SHajimu UMEMOTO 	cached_mp_read_session rs;
41906a99fe3SHajimu UMEMOTO 
42006a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
42106a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
42206a99fe3SHajimu UMEMOTO 
42306a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
42406a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
42506a99fe3SHajimu UMEMOTO 
42606a99fe3SHajimu UMEMOTO 	ws = cache_info->get_mp_ws_func();
42706a99fe3SHajimu UMEMOTO 	if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
42806a99fe3SHajimu UMEMOTO 		__abandon_cached_mp_write_session(ws);
42906a99fe3SHajimu UMEMOTO 		ws = INVALID_CACHED_MP_WRITE_SESSION;
43006a99fe3SHajimu UMEMOTO 		cache_info->set_mp_ws_func(ws);
43106a99fe3SHajimu UMEMOTO 	}
43206a99fe3SHajimu UMEMOTO 
43306a99fe3SHajimu UMEMOTO 	rs = cache_info->get_mp_rs_func();
43406a99fe3SHajimu UMEMOTO 	if (rs != INVALID_CACHED_MP_READ_SESSION) {
43506a99fe3SHajimu UMEMOTO 		__close_cached_mp_read_session(rs);
43606a99fe3SHajimu UMEMOTO 		rs = INVALID_CACHED_MP_READ_SESSION;
43706a99fe3SHajimu UMEMOTO 		cache_info->set_mp_rs_func(rs);
43806a99fe3SHajimu UMEMOTO 	}
43906a99fe3SHajimu UMEMOTO 
44006a99fe3SHajimu UMEMOTO 	return (NS_UNAVAIL);
44106a99fe3SHajimu UMEMOTO }
442