xref: /dflybsd-src/lib/libc/net/nscache.c (revision a1ff66cb7764cf805b759f2c7bfc51a8a11cf1aa)
1ed5d5720SPeter Avalos /*-
2ed5d5720SPeter Avalos  * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3ed5d5720SPeter Avalos  * All rights reserved.
4ed5d5720SPeter Avalos  *
5ed5d5720SPeter Avalos  * Redistribution and use in source and binary forms, with or without
6ed5d5720SPeter Avalos  * modification, are permitted provided that the following conditions
7ed5d5720SPeter Avalos  * are met:
8ed5d5720SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
9ed5d5720SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
10ed5d5720SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
11ed5d5720SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
12ed5d5720SPeter Avalos  *    documentation and/or other materials provided with the distribution.
13ed5d5720SPeter Avalos  *
14ed5d5720SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15ed5d5720SPeter Avalos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16ed5d5720SPeter Avalos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17ed5d5720SPeter Avalos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18ed5d5720SPeter Avalos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19ed5d5720SPeter Avalos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20ed5d5720SPeter Avalos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21ed5d5720SPeter Avalos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22ed5d5720SPeter Avalos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23ed5d5720SPeter Avalos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24ed5d5720SPeter Avalos  * SUCH DAMAGE.
25ed5d5720SPeter Avalos  *
26ed5d5720SPeter Avalos  * $FreeBSD: src/lib/libc/net/nscache.c,v 1.2 2007/10/17 23:20:49 tmclaugh Exp $
27ed5d5720SPeter Avalos  */
28ed5d5720SPeter Avalos 
29ed5d5720SPeter Avalos #include "namespace.h"
30*a1ff66cbSSascha Wildner #define _NS_PRIVATE
31ed5d5720SPeter Avalos #include <nsswitch.h>
32ed5d5720SPeter Avalos #include <stdlib.h>
33ed5d5720SPeter Avalos #include <string.h>
34ed5d5720SPeter Avalos #include "un-namespace.h"
35ed5d5720SPeter Avalos #include "nscachedcli.h"
36ed5d5720SPeter Avalos #include "nscache.h"
37ed5d5720SPeter Avalos 
38ed5d5720SPeter Avalos #define NSS_CACHE_KEY_INITIAL_SIZE	(256)
39ed5d5720SPeter Avalos #define NSS_CACHE_KEY_SIZE_LIMIT	(NSS_CACHE_KEY_INITIAL_SIZE << 4)
40ed5d5720SPeter Avalos 
41ed5d5720SPeter Avalos #define NSS_CACHE_BUFFER_INITIAL_SIZE	(1024)
42ed5d5720SPeter Avalos #define NSS_CACHE_BUFFER_SIZE_LIMIT	(NSS_CACHE_BUFFER_INITIAL_SIZE << 8)
43ed5d5720SPeter Avalos 
44ed5d5720SPeter Avalos #define CACHED_SOCKET_PATH 		"/var/run/nscd"
45ed5d5720SPeter Avalos 
46ed5d5720SPeter Avalos int
__nss_cache_handler(void * retval __unused,void * mdata __unused,va_list ap __unused)476d7019e6SSascha Wildner __nss_cache_handler(void *retval __unused, void *mdata __unused,
486d7019e6SSascha Wildner     va_list ap __unused)
49ed5d5720SPeter Avalos {
50ed5d5720SPeter Avalos 	return (NS_UNAVAIL);
51ed5d5720SPeter Avalos }
52ed5d5720SPeter Avalos 
53ed5d5720SPeter Avalos int
__nss_common_cache_read(void * retval,void * mdata,va_list ap)54ed5d5720SPeter Avalos __nss_common_cache_read(void *retval, void *mdata, va_list ap)
55ed5d5720SPeter Avalos {
56ed5d5720SPeter Avalos 	struct cached_connection_params params;
57ed5d5720SPeter Avalos 	cached_connection connection;
58ed5d5720SPeter Avalos 
59ed5d5720SPeter Avalos 	char *buffer;
60ed5d5720SPeter Avalos 	size_t buffer_size, size;
61ed5d5720SPeter Avalos 
62ed5d5720SPeter Avalos 	nss_cache_info const *cache_info;
63ed5d5720SPeter Avalos 	nss_cache_data *cache_data;
64ed5d5720SPeter Avalos 	va_list ap_new;
65ed5d5720SPeter Avalos 	int res;
66ed5d5720SPeter Avalos 
67ed5d5720SPeter Avalos 	cache_data = (nss_cache_data *)mdata;
68ed5d5720SPeter Avalos 	cache_info = cache_data->info;
69ed5d5720SPeter Avalos 
70ed5d5720SPeter Avalos 	memset(&params, 0, sizeof(struct cached_connection_params));
71ed5d5720SPeter Avalos 	params.socket_path = CACHED_SOCKET_PATH;
72ed5d5720SPeter Avalos 
73ed5d5720SPeter Avalos 	cache_data->key = (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE);
74ed5d5720SPeter Avalos 	memset(cache_data->key, 0, NSS_CACHE_KEY_INITIAL_SIZE);
75ed5d5720SPeter Avalos 	cache_data->key_size = NSS_CACHE_KEY_INITIAL_SIZE;
76ed5d5720SPeter Avalos 	va_copy(ap_new, ap);
77ed5d5720SPeter Avalos 
78ed5d5720SPeter Avalos 	do {
79ed5d5720SPeter Avalos 		size = cache_data->key_size;
80ed5d5720SPeter Avalos 		res = cache_info->id_func(cache_data->key, &size, ap_new,
81ed5d5720SPeter Avalos 		    cache_info->mdata);
82ed5d5720SPeter Avalos 		va_end(ap_new);
83ed5d5720SPeter Avalos 		if (res == NS_RETURN) {
84ed5d5720SPeter Avalos 			if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT)
85ed5d5720SPeter Avalos 				break;
86ed5d5720SPeter Avalos 
87ed5d5720SPeter Avalos 			cache_data->key_size <<= 1;
88ed5d5720SPeter Avalos 			cache_data->key = realloc(cache_data->key,
89ed5d5720SPeter Avalos 			    cache_data->key_size);
90ed5d5720SPeter Avalos 			memset(cache_data->key, 0, cache_data->key_size);
91ed5d5720SPeter Avalos 			va_copy(ap_new, ap);
92ed5d5720SPeter Avalos 		}
93ed5d5720SPeter Avalos 	} while (res == NS_RETURN);
94ed5d5720SPeter Avalos 
95ed5d5720SPeter Avalos 	if (res != NS_SUCCESS) {
96ed5d5720SPeter Avalos 		free(cache_data->key);
97ed5d5720SPeter Avalos 		cache_data->key = NULL;
98ed5d5720SPeter Avalos 		cache_data->key_size = 0;
99ed5d5720SPeter Avalos 		return (res);
100ed5d5720SPeter Avalos 	} else
101ed5d5720SPeter Avalos 		cache_data->key_size = size;
102ed5d5720SPeter Avalos 
103ed5d5720SPeter Avalos 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
104ed5d5720SPeter Avalos 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
105ed5d5720SPeter Avalos 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
106ed5d5720SPeter Avalos 
107ed5d5720SPeter Avalos 	do {
108ed5d5720SPeter Avalos 		connection = __open_cached_connection(&params);
109ed5d5720SPeter Avalos 		if (connection == NULL) {
110ed5d5720SPeter Avalos 			res = -1;
111ed5d5720SPeter Avalos 			break;
112ed5d5720SPeter Avalos 		}
113ed5d5720SPeter Avalos 		res = __cached_read(connection, cache_info->entry_name,
114ed5d5720SPeter Avalos 		    cache_data->key, cache_data->key_size, buffer,
115ed5d5720SPeter Avalos 		    &buffer_size);
116ed5d5720SPeter Avalos 		__close_cached_connection(connection);
117ed5d5720SPeter Avalos 		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
118ed5d5720SPeter Avalos 			buffer = (char *)realloc(buffer, buffer_size);
119ed5d5720SPeter Avalos 			memset(buffer, 0, buffer_size);
120ed5d5720SPeter Avalos 		}
121ed5d5720SPeter Avalos 	} while (res == -2);
122ed5d5720SPeter Avalos 
123ed5d5720SPeter Avalos 	if (res == 0) {
124ed5d5720SPeter Avalos 		if (buffer_size == 0) {
125ed5d5720SPeter Avalos 			free(buffer);
126ed5d5720SPeter Avalos 			free(cache_data->key);
127ed5d5720SPeter Avalos 			cache_data->key = NULL;
128ed5d5720SPeter Avalos 			cache_data->key_size = 0;
129ed5d5720SPeter Avalos 			return (NS_RETURN);
130ed5d5720SPeter Avalos 		}
131ed5d5720SPeter Avalos 
132ed5d5720SPeter Avalos 		va_copy(ap_new, ap);
133ed5d5720SPeter Avalos 		res = cache_info->unmarshal_func(buffer, buffer_size, retval,
134ed5d5720SPeter Avalos 		    ap_new, cache_info->mdata);
135ed5d5720SPeter Avalos 		va_end(ap_new);
136ed5d5720SPeter Avalos 
137ed5d5720SPeter Avalos 		if (res != NS_SUCCESS) {
138ed5d5720SPeter Avalos 			free(buffer);
139ed5d5720SPeter Avalos 			free(cache_data->key);
140ed5d5720SPeter Avalos 			cache_data->key = NULL;
141ed5d5720SPeter Avalos 			cache_data->key_size = 0;
142ed5d5720SPeter Avalos 			return (res);
143ed5d5720SPeter Avalos 		} else
144ed5d5720SPeter Avalos 			res = 0;
145ed5d5720SPeter Avalos 	}
146ed5d5720SPeter Avalos 
147ed5d5720SPeter Avalos 	if (res == 0) {
148ed5d5720SPeter Avalos 		free(cache_data->key);
149ed5d5720SPeter Avalos 		cache_data->key = NULL;
150ed5d5720SPeter Avalos 		cache_data->key_size = 0;
151ed5d5720SPeter Avalos 	}
152ed5d5720SPeter Avalos 
153ed5d5720SPeter Avalos 	free(buffer);
154ed5d5720SPeter Avalos 	return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
155ed5d5720SPeter Avalos }
156ed5d5720SPeter Avalos 
157ed5d5720SPeter Avalos int
__nss_common_cache_write(void * retval,void * mdata,va_list ap)158ed5d5720SPeter Avalos __nss_common_cache_write(void *retval, void *mdata, va_list ap)
159ed5d5720SPeter Avalos {
160ed5d5720SPeter Avalos 	struct cached_connection_params params;
161ed5d5720SPeter Avalos 	cached_connection connection;
162ed5d5720SPeter Avalos 
163ed5d5720SPeter Avalos 	char *buffer;
164ed5d5720SPeter Avalos 	size_t buffer_size;
165ed5d5720SPeter Avalos 
166ed5d5720SPeter Avalos 	nss_cache_info const *cache_info;
167ed5d5720SPeter Avalos 	nss_cache_data *cache_data;
168ed5d5720SPeter Avalos 	va_list ap_new;
169ed5d5720SPeter Avalos 	int res;
170ed5d5720SPeter Avalos 
171ed5d5720SPeter Avalos 	cache_data = (nss_cache_data *)mdata;
172ed5d5720SPeter Avalos 	cache_info = cache_data->info;
173ed5d5720SPeter Avalos 
174ed5d5720SPeter Avalos 	if (cache_data->key == NULL)
175ed5d5720SPeter Avalos 		return (NS_UNAVAIL);
176ed5d5720SPeter Avalos 
177ed5d5720SPeter Avalos 	memset(&params, 0, sizeof(struct cached_connection_params));
178ed5d5720SPeter Avalos 	params.socket_path = CACHED_SOCKET_PATH;
179ed5d5720SPeter Avalos 
180ed5d5720SPeter Avalos 	connection = __open_cached_connection(&params);
181ed5d5720SPeter Avalos 	if (connection == NULL) {
182ed5d5720SPeter Avalos 		free(cache_data->key);
183ed5d5720SPeter Avalos 		return (NS_UNAVAIL);
184ed5d5720SPeter Avalos 	}
185ed5d5720SPeter Avalos 
186ed5d5720SPeter Avalos 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
187ed5d5720SPeter Avalos 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
188ed5d5720SPeter Avalos 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
189ed5d5720SPeter Avalos 
190ed5d5720SPeter Avalos 	do {
191ed5d5720SPeter Avalos 		size_t size;
192ed5d5720SPeter Avalos 
193ed5d5720SPeter Avalos 		size = buffer_size;
194ed5d5720SPeter Avalos 		va_copy(ap_new, ap);
195ed5d5720SPeter Avalos 		res = cache_info->marshal_func(buffer, &size, retval, ap_new,
196ed5d5720SPeter Avalos 		    cache_info->mdata);
197ed5d5720SPeter Avalos 		va_end(ap_new);
198ed5d5720SPeter Avalos 
199ed5d5720SPeter Avalos 		if (res == NS_RETURN) {
200ed5d5720SPeter Avalos 			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
201ed5d5720SPeter Avalos 				break;
202ed5d5720SPeter Avalos 
203ed5d5720SPeter Avalos 			buffer_size <<= 1;
204ed5d5720SPeter Avalos 			buffer = (char *)realloc(buffer, buffer_size);
205ed5d5720SPeter Avalos 			memset(buffer, 0, buffer_size);
206ed5d5720SPeter Avalos 		}
207ed5d5720SPeter Avalos 	} while (res == NS_RETURN);
208ed5d5720SPeter Avalos 
209ed5d5720SPeter Avalos 	if (res != NS_SUCCESS) {
210ed5d5720SPeter Avalos 		__close_cached_connection(connection);
211ed5d5720SPeter Avalos 		free(cache_data->key);
212ed5d5720SPeter Avalos 		free(buffer);
213ed5d5720SPeter Avalos 		return (res);
214ed5d5720SPeter Avalos 	}
215ed5d5720SPeter Avalos 
216ed5d5720SPeter Avalos 	res = __cached_write(connection, cache_info->entry_name,
217ed5d5720SPeter Avalos 	    cache_data->key, cache_data->key_size, buffer, buffer_size);
218ed5d5720SPeter Avalos 	__close_cached_connection(connection);
219ed5d5720SPeter Avalos 
220ed5d5720SPeter Avalos 	free(cache_data->key);
221ed5d5720SPeter Avalos 	free(buffer);
222ed5d5720SPeter Avalos 
223ed5d5720SPeter Avalos 	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
224ed5d5720SPeter Avalos }
225ed5d5720SPeter Avalos 
226ed5d5720SPeter Avalos int
__nss_common_cache_write_negative(void * mdata)227ed5d5720SPeter Avalos __nss_common_cache_write_negative(void *mdata)
228ed5d5720SPeter Avalos {
229ed5d5720SPeter Avalos 	struct cached_connection_params params;
230ed5d5720SPeter Avalos 	cached_connection connection;
231ed5d5720SPeter Avalos 	int res;
232ed5d5720SPeter Avalos 
233ed5d5720SPeter Avalos 	nss_cache_info const *cache_info;
234ed5d5720SPeter Avalos 	nss_cache_data *cache_data;
235ed5d5720SPeter Avalos 
236ed5d5720SPeter Avalos 	cache_data = (nss_cache_data *)mdata;
237ed5d5720SPeter Avalos 	cache_info = cache_data->info;
238ed5d5720SPeter Avalos 
239ed5d5720SPeter Avalos 	if (cache_data->key == NULL)
240ed5d5720SPeter Avalos 		return (NS_UNAVAIL);
241ed5d5720SPeter Avalos 
242ed5d5720SPeter Avalos 	memset(&params, 0, sizeof(struct cached_connection_params));
243ed5d5720SPeter Avalos 	params.socket_path = CACHED_SOCKET_PATH;
244ed5d5720SPeter Avalos 
245ed5d5720SPeter Avalos 	connection = __open_cached_connection(&params);
246ed5d5720SPeter Avalos 	if (connection == NULL) {
247ed5d5720SPeter Avalos 		free(cache_data->key);
248ed5d5720SPeter Avalos 		return (NS_UNAVAIL);
249ed5d5720SPeter Avalos 	}
250ed5d5720SPeter Avalos 
251ed5d5720SPeter Avalos 	res = __cached_write(connection, cache_info->entry_name,
252ed5d5720SPeter Avalos 	    cache_data->key, cache_data->key_size, NULL, 0);
253ed5d5720SPeter Avalos 	__close_cached_connection(connection);
254ed5d5720SPeter Avalos 
255ed5d5720SPeter Avalos 	free(cache_data->key);
256ed5d5720SPeter Avalos 	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
257ed5d5720SPeter Avalos }
258ed5d5720SPeter Avalos 
259ed5d5720SPeter Avalos int
__nss_mp_cache_read(void * retval,void * mdata,va_list ap)260ed5d5720SPeter Avalos __nss_mp_cache_read(void *retval, void *mdata, va_list ap)
261ed5d5720SPeter Avalos {
262ed5d5720SPeter Avalos 	struct cached_connection_params params;
263ed5d5720SPeter Avalos 	cached_mp_read_session rs;
264ed5d5720SPeter Avalos 
265ed5d5720SPeter Avalos 	char *buffer;
266ed5d5720SPeter Avalos 	size_t buffer_size;
267ed5d5720SPeter Avalos 
268ed5d5720SPeter Avalos 	nss_cache_info const *cache_info;
269ed5d5720SPeter Avalos 	nss_cache_data *cache_data;
270ed5d5720SPeter Avalos 	va_list ap_new;
271ed5d5720SPeter Avalos 	int res;
272ed5d5720SPeter Avalos 
273ed5d5720SPeter Avalos 	cache_data = (nss_cache_data *)mdata;
274ed5d5720SPeter Avalos 	cache_info = cache_data->info;
275ed5d5720SPeter Avalos 
276ed5d5720SPeter Avalos 	if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION)
277ed5d5720SPeter Avalos 		return (NS_UNAVAIL);
278ed5d5720SPeter Avalos 
279ed5d5720SPeter Avalos 	rs = cache_info->get_mp_rs_func();
280ed5d5720SPeter Avalos 	if (rs == INVALID_CACHED_MP_READ_SESSION) {
281ed5d5720SPeter Avalos 		memset(&params, 0, sizeof(struct cached_connection_params));
282ed5d5720SPeter Avalos 		params.socket_path = CACHED_SOCKET_PATH;
283ed5d5720SPeter Avalos 
284ed5d5720SPeter Avalos 		rs = __open_cached_mp_read_session(&params,
285ed5d5720SPeter Avalos 		    cache_info->entry_name);
286ed5d5720SPeter Avalos 		if (rs == INVALID_CACHED_MP_READ_SESSION)
287ed5d5720SPeter Avalos 			return (NS_UNAVAIL);
288ed5d5720SPeter Avalos 
289ed5d5720SPeter Avalos 		cache_info->set_mp_rs_func(rs);
290ed5d5720SPeter Avalos 	}
291ed5d5720SPeter Avalos 
292ed5d5720SPeter Avalos 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
293ed5d5720SPeter Avalos 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
294ed5d5720SPeter Avalos 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
295ed5d5720SPeter Avalos 
296ed5d5720SPeter Avalos 	do {
297ed5d5720SPeter Avalos 		res = __cached_mp_read(rs, buffer, &buffer_size);
298ed5d5720SPeter Avalos 		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
299ed5d5720SPeter Avalos 			buffer = (char *)realloc(buffer, buffer_size);
300ed5d5720SPeter Avalos 			memset(buffer, 0, buffer_size);
301ed5d5720SPeter Avalos 		}
302ed5d5720SPeter Avalos 	} while (res == -2);
303ed5d5720SPeter Avalos 
304ed5d5720SPeter Avalos 	if (res == 0) {
305ed5d5720SPeter Avalos 		va_copy(ap_new, ap);
306ed5d5720SPeter Avalos 		res = cache_info->unmarshal_func(buffer, buffer_size, retval,
307ed5d5720SPeter Avalos 		    ap_new, cache_info->mdata);
308ed5d5720SPeter Avalos 		va_end(ap_new);
309ed5d5720SPeter Avalos 
310ed5d5720SPeter Avalos 		if (res != NS_SUCCESS) {
311ed5d5720SPeter Avalos 			free(buffer);
312ed5d5720SPeter Avalos 			return (res);
313ed5d5720SPeter Avalos 		} else
314ed5d5720SPeter Avalos 			res = 0;
315ed5d5720SPeter Avalos 	} else {
316ed5d5720SPeter Avalos 		free(buffer);
317ed5d5720SPeter Avalos 		__close_cached_mp_read_session(rs);
318ed5d5720SPeter Avalos 		rs = INVALID_CACHED_MP_READ_SESSION;
319ed5d5720SPeter Avalos 		cache_info->set_mp_rs_func(rs);
320ed5d5720SPeter Avalos 		return (res == -1 ? NS_RETURN : NS_UNAVAIL);
321ed5d5720SPeter Avalos 	}
322ed5d5720SPeter Avalos 
323ed5d5720SPeter Avalos 	free(buffer);
324ed5d5720SPeter Avalos 	return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
325ed5d5720SPeter Avalos }
326ed5d5720SPeter Avalos 
327ed5d5720SPeter Avalos int
__nss_mp_cache_write(void * retval,void * mdata,va_list ap)328ed5d5720SPeter Avalos __nss_mp_cache_write(void *retval, void *mdata, va_list ap)
329ed5d5720SPeter Avalos {
330ed5d5720SPeter Avalos 	struct cached_connection_params params;
331ed5d5720SPeter Avalos 	cached_mp_write_session ws;
332ed5d5720SPeter Avalos 
333ed5d5720SPeter Avalos 	char *buffer;
334ed5d5720SPeter Avalos 	size_t buffer_size;
335ed5d5720SPeter Avalos 
336ed5d5720SPeter Avalos 	nss_cache_info const *cache_info;
337ed5d5720SPeter Avalos 	nss_cache_data *cache_data;
338ed5d5720SPeter Avalos 	va_list ap_new;
339ed5d5720SPeter Avalos 	int res;
340ed5d5720SPeter Avalos 
341ed5d5720SPeter Avalos 	cache_data = (nss_cache_data *)mdata;
342ed5d5720SPeter Avalos 	cache_info = cache_data->info;
343ed5d5720SPeter Avalos 
344ed5d5720SPeter Avalos 	ws = cache_info->get_mp_ws_func();
345ed5d5720SPeter Avalos 	if (ws == INVALID_CACHED_MP_WRITE_SESSION) {
346ed5d5720SPeter Avalos 		memset(&params, 0, sizeof(struct cached_connection_params));
347ed5d5720SPeter Avalos 		params.socket_path = CACHED_SOCKET_PATH;
348ed5d5720SPeter Avalos 
349ed5d5720SPeter Avalos 		ws = __open_cached_mp_write_session(&params,
350ed5d5720SPeter Avalos 		    cache_info->entry_name);
351ed5d5720SPeter Avalos 		if (ws == INVALID_CACHED_MP_WRITE_SESSION)
352ed5d5720SPeter Avalos 			return (NS_UNAVAIL);
353ed5d5720SPeter Avalos 
354ed5d5720SPeter Avalos 		cache_info->set_mp_ws_func(ws);
355ed5d5720SPeter Avalos 	}
356ed5d5720SPeter Avalos 
357ed5d5720SPeter Avalos 	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
358ed5d5720SPeter Avalos 	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
359ed5d5720SPeter Avalos 	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
360ed5d5720SPeter Avalos 
361ed5d5720SPeter Avalos 	do {
362ed5d5720SPeter Avalos 		size_t size;
363ed5d5720SPeter Avalos 
364ed5d5720SPeter Avalos 		size = buffer_size;
365ed5d5720SPeter Avalos 		va_copy(ap_new, ap);
366ed5d5720SPeter Avalos 		res = cache_info->marshal_func(buffer, &size, retval, ap_new,
367ed5d5720SPeter Avalos 		    cache_info->mdata);
368ed5d5720SPeter Avalos 		va_end(ap_new);
369ed5d5720SPeter Avalos 
370ed5d5720SPeter Avalos 		if (res == NS_RETURN) {
371ed5d5720SPeter Avalos 			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
372ed5d5720SPeter Avalos 				break;
373ed5d5720SPeter Avalos 
374ed5d5720SPeter Avalos 			buffer_size <<= 1;
375ed5d5720SPeter Avalos 			buffer = (char *)realloc(buffer, buffer_size);
376ed5d5720SPeter Avalos 			memset(buffer, 0, buffer_size);
377ed5d5720SPeter Avalos 		}
378ed5d5720SPeter Avalos 	} while (res == NS_RETURN);
379ed5d5720SPeter Avalos 
380ed5d5720SPeter Avalos 	if (res != NS_SUCCESS) {
381ed5d5720SPeter Avalos 		free(buffer);
382ed5d5720SPeter Avalos 		return (res);
383ed5d5720SPeter Avalos 	}
384ed5d5720SPeter Avalos 
385ed5d5720SPeter Avalos 	res = __cached_mp_write(ws, buffer, buffer_size);
386ed5d5720SPeter Avalos 
387ed5d5720SPeter Avalos 	free(buffer);
388ed5d5720SPeter Avalos 	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
389ed5d5720SPeter Avalos }
390ed5d5720SPeter Avalos 
391ed5d5720SPeter Avalos int
__nss_mp_cache_write_submit(void * retval __unused,void * mdata,va_list ap __unused)3926d7019e6SSascha Wildner __nss_mp_cache_write_submit(void *retval __unused, void *mdata,
3936d7019e6SSascha Wildner     va_list ap __unused)
394ed5d5720SPeter Avalos {
395ed5d5720SPeter Avalos 	cached_mp_write_session ws;
396ed5d5720SPeter Avalos 
397ed5d5720SPeter Avalos 	nss_cache_info const *cache_info;
398ed5d5720SPeter Avalos 	nss_cache_data *cache_data;
399ed5d5720SPeter Avalos 
400ed5d5720SPeter Avalos 	cache_data = (nss_cache_data *)mdata;
401ed5d5720SPeter Avalos 	cache_info = cache_data->info;
402ed5d5720SPeter Avalos 
403ed5d5720SPeter Avalos 	ws = cache_info->get_mp_ws_func();
404ed5d5720SPeter Avalos 	if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
405ed5d5720SPeter Avalos 		__close_cached_mp_write_session(ws);
406ed5d5720SPeter Avalos 		ws = INVALID_CACHED_MP_WRITE_SESSION;
407ed5d5720SPeter Avalos 		cache_info->set_mp_ws_func(ws);
408ed5d5720SPeter Avalos 	}
409ed5d5720SPeter Avalos 	return (NS_UNAVAIL);
410ed5d5720SPeter Avalos }
411ed5d5720SPeter Avalos 
412ed5d5720SPeter Avalos int
__nss_mp_cache_end(void * retval __unused,void * mdata,va_list ap __unused)4136d7019e6SSascha Wildner __nss_mp_cache_end(void *retval __unused, void *mdata, va_list ap __unused)
414ed5d5720SPeter Avalos {
415ed5d5720SPeter Avalos 	cached_mp_write_session ws;
416ed5d5720SPeter Avalos 	cached_mp_read_session rs;
417ed5d5720SPeter Avalos 
418ed5d5720SPeter Avalos 	nss_cache_info const *cache_info;
419ed5d5720SPeter Avalos 	nss_cache_data *cache_data;
420ed5d5720SPeter Avalos 
421ed5d5720SPeter Avalos 	cache_data = (nss_cache_data *)mdata;
422ed5d5720SPeter Avalos 	cache_info = cache_data->info;
423ed5d5720SPeter Avalos 
424ed5d5720SPeter Avalos 	ws = cache_info->get_mp_ws_func();
425ed5d5720SPeter Avalos 	if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
426ed5d5720SPeter Avalos 		__abandon_cached_mp_write_session(ws);
427ed5d5720SPeter Avalos 		ws = INVALID_CACHED_MP_WRITE_SESSION;
428ed5d5720SPeter Avalos 		cache_info->set_mp_ws_func(ws);
429ed5d5720SPeter Avalos 	}
430ed5d5720SPeter Avalos 
431ed5d5720SPeter Avalos 	rs = cache_info->get_mp_rs_func();
432ed5d5720SPeter Avalos 	if (rs != INVALID_CACHED_MP_READ_SESSION) {
433ed5d5720SPeter Avalos 		__close_cached_mp_read_session(rs);
434ed5d5720SPeter Avalos 		rs = INVALID_CACHED_MP_READ_SESSION;
435ed5d5720SPeter Avalos 		cache_info->set_mp_rs_func(rs);
436ed5d5720SPeter Avalos 	}
437ed5d5720SPeter Avalos 
438ed5d5720SPeter Avalos 	return (NS_UNAVAIL);
439ed5d5720SPeter Avalos }
440