xref: /freebsd/lib/libc/net/nscache.c (revision 559a218c9b257775fb249b67945fe4a05b7a6b9f)
106a99fe3SHajimu UMEMOTO /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3d915a14eSPedro 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 "namespace.h"
31ae274020SCraig Rodrigues #define _NS_PRIVATE
3206a99fe3SHajimu UMEMOTO #include <nsswitch.h>
3306a99fe3SHajimu UMEMOTO #include <stdlib.h>
3406a99fe3SHajimu UMEMOTO #include <string.h>
3506a99fe3SHajimu UMEMOTO #include "un-namespace.h"
3606a99fe3SHajimu UMEMOTO #include "nscachedcli.h"
3706a99fe3SHajimu UMEMOTO #include "nscache.h"
3806a99fe3SHajimu UMEMOTO 
3906a99fe3SHajimu UMEMOTO #define NSS_CACHE_KEY_INITIAL_SIZE	(256)
4006a99fe3SHajimu UMEMOTO #define NSS_CACHE_KEY_SIZE_LIMIT	(NSS_CACHE_KEY_INITIAL_SIZE << 4)
4106a99fe3SHajimu UMEMOTO 
4206a99fe3SHajimu UMEMOTO #define NSS_CACHE_BUFFER_INITIAL_SIZE	(1024)
4306a99fe3SHajimu UMEMOTO #define NSS_CACHE_BUFFER_SIZE_LIMIT	(NSS_CACHE_BUFFER_INITIAL_SIZE << 8)
4406a99fe3SHajimu UMEMOTO 
4590855671STom McLaughlin #define CACHED_SOCKET_PATH 		"/var/run/nscd"
4606a99fe3SHajimu UMEMOTO 
4706a99fe3SHajimu UMEMOTO int
__nss_cache_handler(void * retval,void * mdata,va_list ap)4806a99fe3SHajimu UMEMOTO __nss_cache_handler(void *retval, void *mdata, va_list ap)
4906a99fe3SHajimu UMEMOTO {
5006a99fe3SHajimu UMEMOTO 	return (NS_UNAVAIL);
5106a99fe3SHajimu UMEMOTO }
5206a99fe3SHajimu UMEMOTO 
5306a99fe3SHajimu UMEMOTO int
__nss_common_cache_read(void * retval,void * mdata,va_list ap)5406a99fe3SHajimu UMEMOTO __nss_common_cache_read(void *retval, void *mdata, va_list ap)
5506a99fe3SHajimu UMEMOTO {
5606a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
5706a99fe3SHajimu UMEMOTO 	cached_connection connection;
5806a99fe3SHajimu UMEMOTO 
5906a99fe3SHajimu UMEMOTO 	char *buffer;
6006a99fe3SHajimu UMEMOTO 	size_t buffer_size, size;
6106a99fe3SHajimu UMEMOTO 
6206a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
6306a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
6406a99fe3SHajimu UMEMOTO 	va_list ap_new;
6506a99fe3SHajimu UMEMOTO 	int res;
6606a99fe3SHajimu UMEMOTO 
6706a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
6806a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
6906a99fe3SHajimu UMEMOTO 
7006a99fe3SHajimu UMEMOTO 	memset(&params, 0, sizeof(struct cached_connection_params));
7106a99fe3SHajimu UMEMOTO 	params.socket_path = CACHED_SOCKET_PATH;
7206a99fe3SHajimu UMEMOTO 
7306a99fe3SHajimu UMEMOTO 	cache_data->key = (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE);
7406a99fe3SHajimu UMEMOTO 	memset(cache_data->key, 0, NSS_CACHE_KEY_INITIAL_SIZE);
7506a99fe3SHajimu UMEMOTO 	cache_data->key_size = NSS_CACHE_KEY_INITIAL_SIZE;
7606a99fe3SHajimu UMEMOTO 	va_copy(ap_new, ap);
7706a99fe3SHajimu UMEMOTO 
7806a99fe3SHajimu UMEMOTO 	do {
7906a99fe3SHajimu UMEMOTO 		size = cache_data->key_size;
8006a99fe3SHajimu UMEMOTO 		res = cache_info->id_func(cache_data->key, &size, ap_new,
8106a99fe3SHajimu UMEMOTO 		    cache_info->mdata);
8206a99fe3SHajimu UMEMOTO 		va_end(ap_new);
8306a99fe3SHajimu UMEMOTO 		if (res == NS_RETURN) {
8406a99fe3SHajimu UMEMOTO 			if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT)
8506a99fe3SHajimu UMEMOTO 				break;
8606a99fe3SHajimu UMEMOTO 
8706a99fe3SHajimu UMEMOTO 			cache_data->key_size <<= 1;
8806a99fe3SHajimu UMEMOTO 			cache_data->key = realloc(cache_data->key,
8906a99fe3SHajimu UMEMOTO 			    cache_data->key_size);
9006a99fe3SHajimu UMEMOTO 			memset(cache_data->key, 0, cache_data->key_size);
9106a99fe3SHajimu UMEMOTO 			va_copy(ap_new, ap);
9206a99fe3SHajimu UMEMOTO 		}
9306a99fe3SHajimu UMEMOTO 	} while (res == NS_RETURN);
9406a99fe3SHajimu UMEMOTO 
9506a99fe3SHajimu UMEMOTO 	if (res != NS_SUCCESS) {
9606a99fe3SHajimu UMEMOTO 		free(cache_data->key);
9706a99fe3SHajimu UMEMOTO 		cache_data->key = NULL;
9806a99fe3SHajimu UMEMOTO 		cache_data->key_size = 0;
9906a99fe3SHajimu UMEMOTO 		return (res);
10006a99fe3SHajimu UMEMOTO 	} else
10106a99fe3SHajimu UMEMOTO 		cache_data->key_size = size;
10206a99fe3SHajimu UMEMOTO 
10306a99fe3SHajimu UMEMOTO 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
10406a99fe3SHajimu UMEMOTO 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
10506a99fe3SHajimu UMEMOTO 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
10606a99fe3SHajimu UMEMOTO 
10706a99fe3SHajimu UMEMOTO 	do {
10806a99fe3SHajimu UMEMOTO 		connection = __open_cached_connection(&params);
10906a99fe3SHajimu UMEMOTO 		if (connection == NULL) {
11006a99fe3SHajimu UMEMOTO 			res = -1;
11106a99fe3SHajimu UMEMOTO 			break;
11206a99fe3SHajimu UMEMOTO 		}
11306a99fe3SHajimu UMEMOTO 		res = __cached_read(connection, cache_info->entry_name,
11406a99fe3SHajimu UMEMOTO 		    cache_data->key, cache_data->key_size, buffer,
11506a99fe3SHajimu UMEMOTO 		    &buffer_size);
11606a99fe3SHajimu UMEMOTO 		__close_cached_connection(connection);
11706a99fe3SHajimu UMEMOTO 		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
11806a99fe3SHajimu UMEMOTO 			buffer = (char *)realloc(buffer, buffer_size);
11906a99fe3SHajimu UMEMOTO 			memset(buffer, 0, buffer_size);
12006a99fe3SHajimu UMEMOTO 		}
12106a99fe3SHajimu UMEMOTO 	} while (res == -2);
12206a99fe3SHajimu UMEMOTO 
12306a99fe3SHajimu UMEMOTO 	if (res == 0) {
12406a99fe3SHajimu UMEMOTO 		if (buffer_size == 0) {
12506a99fe3SHajimu UMEMOTO 			free(buffer);
12606a99fe3SHajimu UMEMOTO 			free(cache_data->key);
12706a99fe3SHajimu UMEMOTO 			cache_data->key = NULL;
12806a99fe3SHajimu UMEMOTO 			cache_data->key_size = 0;
12906a99fe3SHajimu UMEMOTO 			return (NS_RETURN);
13006a99fe3SHajimu UMEMOTO 		}
13106a99fe3SHajimu UMEMOTO 
13206a99fe3SHajimu UMEMOTO 		va_copy(ap_new, ap);
13306a99fe3SHajimu UMEMOTO 		res = cache_info->unmarshal_func(buffer, buffer_size, retval,
13406a99fe3SHajimu UMEMOTO 		    ap_new, cache_info->mdata);
13506a99fe3SHajimu UMEMOTO 		va_end(ap_new);
13606a99fe3SHajimu UMEMOTO 
13706a99fe3SHajimu UMEMOTO 		if (res != NS_SUCCESS) {
13806a99fe3SHajimu UMEMOTO 			free(buffer);
13906a99fe3SHajimu UMEMOTO 			free(cache_data->key);
14006a99fe3SHajimu UMEMOTO 			cache_data->key = NULL;
14106a99fe3SHajimu UMEMOTO 			cache_data->key_size = 0;
14206a99fe3SHajimu UMEMOTO 			return (res);
14306a99fe3SHajimu UMEMOTO 		} else
14406a99fe3SHajimu UMEMOTO 			res = 0;
14506a99fe3SHajimu UMEMOTO 	}
14606a99fe3SHajimu UMEMOTO 
14706a99fe3SHajimu UMEMOTO 	if (res == 0) {
14806a99fe3SHajimu UMEMOTO 		free(cache_data->key);
14906a99fe3SHajimu UMEMOTO 		cache_data->key = NULL;
15006a99fe3SHajimu UMEMOTO 		cache_data->key_size = 0;
15106a99fe3SHajimu UMEMOTO 	}
15206a99fe3SHajimu UMEMOTO 
15306a99fe3SHajimu UMEMOTO 	free(buffer);
15406a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
15506a99fe3SHajimu UMEMOTO }
15606a99fe3SHajimu UMEMOTO 
15706a99fe3SHajimu UMEMOTO int
__nss_common_cache_write(void * retval,void * mdata,va_list ap)15806a99fe3SHajimu UMEMOTO __nss_common_cache_write(void *retval, void *mdata, va_list ap)
15906a99fe3SHajimu UMEMOTO {
16006a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
16106a99fe3SHajimu UMEMOTO 	cached_connection connection;
16206a99fe3SHajimu UMEMOTO 
16306a99fe3SHajimu UMEMOTO 	char *buffer;
16406a99fe3SHajimu UMEMOTO 	size_t buffer_size;
16506a99fe3SHajimu UMEMOTO 
16606a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
16706a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
16806a99fe3SHajimu UMEMOTO 	va_list ap_new;
16906a99fe3SHajimu UMEMOTO 	int res;
17006a99fe3SHajimu UMEMOTO 
17106a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
17206a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
17306a99fe3SHajimu UMEMOTO 
17406a99fe3SHajimu UMEMOTO 	if (cache_data->key == NULL)
17506a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
17606a99fe3SHajimu UMEMOTO 
17706a99fe3SHajimu UMEMOTO 	memset(&params, 0, sizeof(struct cached_connection_params));
17806a99fe3SHajimu UMEMOTO 	params.socket_path = CACHED_SOCKET_PATH;
17906a99fe3SHajimu UMEMOTO 
18006a99fe3SHajimu UMEMOTO 	connection = __open_cached_connection(&params);
18106a99fe3SHajimu UMEMOTO 	if (connection == NULL) {
18206a99fe3SHajimu UMEMOTO 		free(cache_data->key);
18306a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
18406a99fe3SHajimu UMEMOTO 	}
18506a99fe3SHajimu UMEMOTO 
18606a99fe3SHajimu UMEMOTO 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
18706a99fe3SHajimu UMEMOTO 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
18806a99fe3SHajimu UMEMOTO 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
18906a99fe3SHajimu UMEMOTO 
19006a99fe3SHajimu UMEMOTO 	do {
19106a99fe3SHajimu UMEMOTO 		size_t size;
19206a99fe3SHajimu UMEMOTO 
19306a99fe3SHajimu UMEMOTO 		size = buffer_size;
19406a99fe3SHajimu UMEMOTO 		va_copy(ap_new, ap);
19506a99fe3SHajimu UMEMOTO 		res = cache_info->marshal_func(buffer, &size, retval, ap_new,
19606a99fe3SHajimu UMEMOTO 		    cache_info->mdata);
19706a99fe3SHajimu UMEMOTO 		va_end(ap_new);
19806a99fe3SHajimu UMEMOTO 
19906a99fe3SHajimu UMEMOTO 		if (res == NS_RETURN) {
20006a99fe3SHajimu UMEMOTO 			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
20106a99fe3SHajimu UMEMOTO 				break;
20206a99fe3SHajimu UMEMOTO 
20306a99fe3SHajimu UMEMOTO 			buffer_size <<= 1;
20406a99fe3SHajimu UMEMOTO 			buffer = (char *)realloc(buffer, buffer_size);
20506a99fe3SHajimu UMEMOTO 			memset(buffer, 0, buffer_size);
20606a99fe3SHajimu UMEMOTO 		}
20706a99fe3SHajimu UMEMOTO 	} while (res == NS_RETURN);
20806a99fe3SHajimu UMEMOTO 
20906a99fe3SHajimu UMEMOTO 	if (res != NS_SUCCESS) {
21006a99fe3SHajimu UMEMOTO 		__close_cached_connection(connection);
21106a99fe3SHajimu UMEMOTO 		free(cache_data->key);
21206a99fe3SHajimu UMEMOTO 		free(buffer);
21306a99fe3SHajimu UMEMOTO 		return (res);
21406a99fe3SHajimu UMEMOTO 	}
21506a99fe3SHajimu UMEMOTO 
21606a99fe3SHajimu UMEMOTO 	res = __cached_write(connection, cache_info->entry_name,
21706a99fe3SHajimu UMEMOTO 	    cache_data->key, cache_data->key_size, buffer, buffer_size);
21806a99fe3SHajimu UMEMOTO 	__close_cached_connection(connection);
21906a99fe3SHajimu UMEMOTO 
22006a99fe3SHajimu UMEMOTO 	free(cache_data->key);
22106a99fe3SHajimu UMEMOTO 	free(buffer);
22206a99fe3SHajimu UMEMOTO 
22306a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
22406a99fe3SHajimu UMEMOTO }
22506a99fe3SHajimu UMEMOTO 
22606a99fe3SHajimu UMEMOTO int
__nss_common_cache_write_negative(void * mdata)22706a99fe3SHajimu UMEMOTO __nss_common_cache_write_negative(void *mdata)
22806a99fe3SHajimu UMEMOTO {
22906a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
23006a99fe3SHajimu UMEMOTO 	cached_connection connection;
23106a99fe3SHajimu UMEMOTO 	int res;
23206a99fe3SHajimu UMEMOTO 
23306a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
23406a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
23506a99fe3SHajimu UMEMOTO 
23606a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
23706a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
23806a99fe3SHajimu UMEMOTO 
23906a99fe3SHajimu UMEMOTO 	if (cache_data->key == NULL)
24006a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
24106a99fe3SHajimu UMEMOTO 
24206a99fe3SHajimu UMEMOTO 	memset(&params, 0, sizeof(struct cached_connection_params));
24306a99fe3SHajimu UMEMOTO 	params.socket_path = CACHED_SOCKET_PATH;
24406a99fe3SHajimu UMEMOTO 
24506a99fe3SHajimu UMEMOTO 	connection = __open_cached_connection(&params);
24606a99fe3SHajimu UMEMOTO 	if (connection == NULL) {
24706a99fe3SHajimu UMEMOTO 		free(cache_data->key);
24806a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
24906a99fe3SHajimu UMEMOTO 	}
25006a99fe3SHajimu UMEMOTO 
25106a99fe3SHajimu UMEMOTO 	res = __cached_write(connection, cache_info->entry_name,
25206a99fe3SHajimu UMEMOTO 	    cache_data->key, cache_data->key_size, NULL, 0);
25306a99fe3SHajimu UMEMOTO 	__close_cached_connection(connection);
25406a99fe3SHajimu UMEMOTO 
25506a99fe3SHajimu UMEMOTO 	free(cache_data->key);
25606a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
25706a99fe3SHajimu UMEMOTO }
25806a99fe3SHajimu UMEMOTO 
25906a99fe3SHajimu UMEMOTO int
__nss_mp_cache_read(void * retval,void * mdata,va_list ap)26006a99fe3SHajimu UMEMOTO __nss_mp_cache_read(void *retval, void *mdata, va_list ap)
26106a99fe3SHajimu UMEMOTO {
26206a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
26306a99fe3SHajimu UMEMOTO 	cached_mp_read_session rs;
26406a99fe3SHajimu UMEMOTO 
26506a99fe3SHajimu UMEMOTO 	char *buffer;
26606a99fe3SHajimu UMEMOTO 	size_t buffer_size;
26706a99fe3SHajimu UMEMOTO 
26806a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
26906a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
27006a99fe3SHajimu UMEMOTO 	va_list ap_new;
27106a99fe3SHajimu UMEMOTO 	int res;
27206a99fe3SHajimu UMEMOTO 
27306a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
27406a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
27506a99fe3SHajimu UMEMOTO 
27606a99fe3SHajimu UMEMOTO 	if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION)
27706a99fe3SHajimu UMEMOTO 		return (NS_UNAVAIL);
27806a99fe3SHajimu UMEMOTO 
27906a99fe3SHajimu UMEMOTO 	rs = cache_info->get_mp_rs_func();
28006a99fe3SHajimu UMEMOTO 	if (rs == INVALID_CACHED_MP_READ_SESSION) {
28106a99fe3SHajimu UMEMOTO 		memset(&params, 0, sizeof(struct cached_connection_params));
28206a99fe3SHajimu UMEMOTO 		params.socket_path = CACHED_SOCKET_PATH;
28306a99fe3SHajimu UMEMOTO 
28406a99fe3SHajimu UMEMOTO 		rs = __open_cached_mp_read_session(&params,
28506a99fe3SHajimu UMEMOTO 		    cache_info->entry_name);
28606a99fe3SHajimu UMEMOTO 		if (rs == INVALID_CACHED_MP_READ_SESSION)
28706a99fe3SHajimu UMEMOTO 			return (NS_UNAVAIL);
28806a99fe3SHajimu UMEMOTO 
28906a99fe3SHajimu UMEMOTO 		cache_info->set_mp_rs_func(rs);
29006a99fe3SHajimu UMEMOTO 	}
29106a99fe3SHajimu UMEMOTO 
29206a99fe3SHajimu UMEMOTO 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
29306a99fe3SHajimu UMEMOTO 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
29406a99fe3SHajimu UMEMOTO 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
29506a99fe3SHajimu UMEMOTO 
29606a99fe3SHajimu UMEMOTO 	do {
29706a99fe3SHajimu UMEMOTO 		res = __cached_mp_read(rs, buffer, &buffer_size);
29806a99fe3SHajimu UMEMOTO 		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
29906a99fe3SHajimu UMEMOTO 			buffer = (char *)realloc(buffer, buffer_size);
30006a99fe3SHajimu UMEMOTO 			memset(buffer, 0, buffer_size);
30106a99fe3SHajimu UMEMOTO 		}
30206a99fe3SHajimu UMEMOTO 	} while (res == -2);
30306a99fe3SHajimu UMEMOTO 
30406a99fe3SHajimu UMEMOTO 	if (res == 0) {
30506a99fe3SHajimu UMEMOTO 		va_copy(ap_new, ap);
30606a99fe3SHajimu UMEMOTO 		res = cache_info->unmarshal_func(buffer, buffer_size, retval,
30706a99fe3SHajimu UMEMOTO 		    ap_new, cache_info->mdata);
30806a99fe3SHajimu UMEMOTO 		va_end(ap_new);
30906a99fe3SHajimu UMEMOTO 
31006a99fe3SHajimu UMEMOTO 		if (res != NS_SUCCESS) {
31106a99fe3SHajimu UMEMOTO 			free(buffer);
31206a99fe3SHajimu UMEMOTO 			return (res);
31306a99fe3SHajimu UMEMOTO 		} else
31406a99fe3SHajimu UMEMOTO 			res = 0;
31506a99fe3SHajimu UMEMOTO 	} else {
31606a99fe3SHajimu UMEMOTO 		free(buffer);
31706a99fe3SHajimu UMEMOTO 		__close_cached_mp_read_session(rs);
31806a99fe3SHajimu UMEMOTO 		rs = INVALID_CACHED_MP_READ_SESSION;
31906a99fe3SHajimu UMEMOTO 		cache_info->set_mp_rs_func(rs);
32006a99fe3SHajimu UMEMOTO 		return (res == -1 ? NS_RETURN : NS_UNAVAIL);
32106a99fe3SHajimu UMEMOTO 	}
32206a99fe3SHajimu UMEMOTO 
32306a99fe3SHajimu UMEMOTO 	free(buffer);
32406a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
32506a99fe3SHajimu UMEMOTO }
32606a99fe3SHajimu UMEMOTO 
32706a99fe3SHajimu UMEMOTO int
__nss_mp_cache_write(void * retval,void * mdata,va_list ap)32806a99fe3SHajimu UMEMOTO __nss_mp_cache_write(void *retval, void *mdata, va_list ap)
32906a99fe3SHajimu UMEMOTO {
33006a99fe3SHajimu UMEMOTO 	struct cached_connection_params params;
33106a99fe3SHajimu UMEMOTO 	cached_mp_write_session ws;
33206a99fe3SHajimu UMEMOTO 
33306a99fe3SHajimu UMEMOTO 	char *buffer;
33406a99fe3SHajimu UMEMOTO 	size_t buffer_size;
33506a99fe3SHajimu UMEMOTO 
33606a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
33706a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
33806a99fe3SHajimu UMEMOTO 	va_list ap_new;
33906a99fe3SHajimu UMEMOTO 	int res;
34006a99fe3SHajimu UMEMOTO 
34106a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
34206a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
34306a99fe3SHajimu UMEMOTO 
34406a99fe3SHajimu UMEMOTO 	ws = cache_info->get_mp_ws_func();
34506a99fe3SHajimu UMEMOTO 	if (ws == INVALID_CACHED_MP_WRITE_SESSION) {
34606a99fe3SHajimu UMEMOTO 		memset(&params, 0, sizeof(struct cached_connection_params));
34706a99fe3SHajimu UMEMOTO 		params.socket_path = CACHED_SOCKET_PATH;
34806a99fe3SHajimu UMEMOTO 
34906a99fe3SHajimu UMEMOTO 		ws = __open_cached_mp_write_session(&params,
35006a99fe3SHajimu UMEMOTO 		    cache_info->entry_name);
35106a99fe3SHajimu UMEMOTO 		if (ws == INVALID_CACHED_MP_WRITE_SESSION)
35206a99fe3SHajimu UMEMOTO 			return (NS_UNAVAIL);
35306a99fe3SHajimu UMEMOTO 
35406a99fe3SHajimu UMEMOTO 		cache_info->set_mp_ws_func(ws);
35506a99fe3SHajimu UMEMOTO 	}
35606a99fe3SHajimu UMEMOTO 
35706a99fe3SHajimu UMEMOTO 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
35806a99fe3SHajimu UMEMOTO 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
35906a99fe3SHajimu UMEMOTO 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
36006a99fe3SHajimu UMEMOTO 
36106a99fe3SHajimu UMEMOTO 	do {
36206a99fe3SHajimu UMEMOTO 		size_t size;
36306a99fe3SHajimu UMEMOTO 
36406a99fe3SHajimu UMEMOTO 		size = buffer_size;
36506a99fe3SHajimu UMEMOTO 		va_copy(ap_new, ap);
36606a99fe3SHajimu UMEMOTO 		res = cache_info->marshal_func(buffer, &size, retval, ap_new,
36706a99fe3SHajimu UMEMOTO 		    cache_info->mdata);
36806a99fe3SHajimu UMEMOTO 		va_end(ap_new);
36906a99fe3SHajimu UMEMOTO 
37006a99fe3SHajimu UMEMOTO 		if (res == NS_RETURN) {
37106a99fe3SHajimu UMEMOTO 			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
37206a99fe3SHajimu UMEMOTO 				break;
37306a99fe3SHajimu UMEMOTO 
37406a99fe3SHajimu UMEMOTO 			buffer_size <<= 1;
37506a99fe3SHajimu UMEMOTO 			buffer = (char *)realloc(buffer, buffer_size);
37606a99fe3SHajimu UMEMOTO 			memset(buffer, 0, buffer_size);
37706a99fe3SHajimu UMEMOTO 		}
37806a99fe3SHajimu UMEMOTO 	} while (res == NS_RETURN);
37906a99fe3SHajimu UMEMOTO 
38006a99fe3SHajimu UMEMOTO 	if (res != NS_SUCCESS) {
38106a99fe3SHajimu UMEMOTO 		free(buffer);
38206a99fe3SHajimu UMEMOTO 		return (res);
38306a99fe3SHajimu UMEMOTO 	}
38406a99fe3SHajimu UMEMOTO 
38506a99fe3SHajimu UMEMOTO 	res = __cached_mp_write(ws, buffer, buffer_size);
38606a99fe3SHajimu UMEMOTO 
38706a99fe3SHajimu UMEMOTO 	free(buffer);
38806a99fe3SHajimu UMEMOTO 	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
38906a99fe3SHajimu UMEMOTO }
39006a99fe3SHajimu UMEMOTO 
39106a99fe3SHajimu UMEMOTO int
__nss_mp_cache_write_submit(void * retval,void * mdata,va_list ap)39206a99fe3SHajimu UMEMOTO __nss_mp_cache_write_submit(void *retval, void *mdata, va_list ap)
39306a99fe3SHajimu UMEMOTO {
39406a99fe3SHajimu UMEMOTO 	cached_mp_write_session ws;
39506a99fe3SHajimu UMEMOTO 
39606a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
39706a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
39806a99fe3SHajimu UMEMOTO 
39906a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
40006a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
40106a99fe3SHajimu UMEMOTO 
40206a99fe3SHajimu UMEMOTO 	ws = cache_info->get_mp_ws_func();
40306a99fe3SHajimu UMEMOTO 	if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
40406a99fe3SHajimu UMEMOTO 		__close_cached_mp_write_session(ws);
40506a99fe3SHajimu UMEMOTO 		ws = INVALID_CACHED_MP_WRITE_SESSION;
40606a99fe3SHajimu UMEMOTO 		cache_info->set_mp_ws_func(ws);
40706a99fe3SHajimu UMEMOTO 	}
40806a99fe3SHajimu UMEMOTO 	return (NS_UNAVAIL);
40906a99fe3SHajimu UMEMOTO }
41006a99fe3SHajimu UMEMOTO 
41106a99fe3SHajimu UMEMOTO int
__nss_mp_cache_end(void * retval,void * mdata,va_list ap)41206a99fe3SHajimu UMEMOTO __nss_mp_cache_end(void *retval, void *mdata, va_list ap)
41306a99fe3SHajimu UMEMOTO {
41406a99fe3SHajimu UMEMOTO 	cached_mp_write_session ws;
41506a99fe3SHajimu UMEMOTO 	cached_mp_read_session rs;
41606a99fe3SHajimu UMEMOTO 
41706a99fe3SHajimu UMEMOTO 	nss_cache_info const *cache_info;
41806a99fe3SHajimu UMEMOTO 	nss_cache_data *cache_data;
41906a99fe3SHajimu UMEMOTO 
42006a99fe3SHajimu UMEMOTO 	cache_data = (nss_cache_data *)mdata;
42106a99fe3SHajimu UMEMOTO 	cache_info = cache_data->info;
42206a99fe3SHajimu UMEMOTO 
42306a99fe3SHajimu UMEMOTO 	ws = cache_info->get_mp_ws_func();
42406a99fe3SHajimu UMEMOTO 	if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
42506a99fe3SHajimu UMEMOTO 		__abandon_cached_mp_write_session(ws);
42606a99fe3SHajimu UMEMOTO 		ws = INVALID_CACHED_MP_WRITE_SESSION;
42706a99fe3SHajimu UMEMOTO 		cache_info->set_mp_ws_func(ws);
42806a99fe3SHajimu UMEMOTO 	}
42906a99fe3SHajimu UMEMOTO 
43006a99fe3SHajimu UMEMOTO 	rs = cache_info->get_mp_rs_func();
43106a99fe3SHajimu UMEMOTO 	if (rs != INVALID_CACHED_MP_READ_SESSION) {
43206a99fe3SHajimu UMEMOTO 		__close_cached_mp_read_session(rs);
43306a99fe3SHajimu UMEMOTO 		rs = INVALID_CACHED_MP_READ_SESSION;
43406a99fe3SHajimu UMEMOTO 		cache_info->set_mp_rs_func(rs);
43506a99fe3SHajimu UMEMOTO 	}
43606a99fe3SHajimu UMEMOTO 
43706a99fe3SHajimu UMEMOTO 	return (NS_UNAVAIL);
43806a99fe3SHajimu UMEMOTO }
439