nscache.c revision 172730
1158115Sume/*-
2158115Sume * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3158115Sume * All rights reserved.
4158115Sume *
5158115Sume * Redistribution and use in source and binary forms, with or without
6158115Sume * modification, are permitted provided that the following conditions
7158115Sume * are met:
8158115Sume * 1. Redistributions of source code must retain the above copyright
9158115Sume *    notice, this list of conditions and the following disclaimer.
10158115Sume * 2. Redistributions in binary form must reproduce the above copyright
11158115Sume *    notice, this list of conditions and the following disclaimer in the
12158115Sume *    documentation and/or other materials provided with the distribution.
13158115Sume *
14158115Sume * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15158115Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16158115Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17158115Sume * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18158115Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19158115Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20158115Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21158115Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22158115Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23158115Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24158115Sume * SUCH DAMAGE.
25158115Sume *
26158115Sume */
27158115Sume
28158115Sume#include <sys/cdefs.h>
29158115Sume__FBSDID("$FreeBSD: head/lib/libc/net/nscache.c 172730 2007-10-17 23:20:49Z tmclaugh $");
30158115Sume
31158115Sume#include "namespace.h"
32158115Sume#include <nsswitch.h>
33158115Sume#include <stdlib.h>
34158115Sume#include <string.h>
35158115Sume#include "un-namespace.h"
36158115Sume#include "nscachedcli.h"
37158115Sume#include "nscache.h"
38158115Sume
39158115Sume#define NSS_CACHE_KEY_INITIAL_SIZE	(256)
40158115Sume#define NSS_CACHE_KEY_SIZE_LIMIT	(NSS_CACHE_KEY_INITIAL_SIZE << 4)
41158115Sume
42158115Sume#define NSS_CACHE_BUFFER_INITIAL_SIZE	(1024)
43158115Sume#define NSS_CACHE_BUFFER_SIZE_LIMIT	(NSS_CACHE_BUFFER_INITIAL_SIZE << 8)
44158115Sume
45172730Stmclaugh#define CACHED_SOCKET_PATH 		"/var/run/nscd"
46158115Sume
47158115Sumeint
48158115Sume__nss_cache_handler(void *retval, void *mdata, va_list ap)
49158115Sume{
50158115Sume	return (NS_UNAVAIL);
51158115Sume}
52158115Sume
53158115Sumeint
54158115Sume__nss_common_cache_read(void *retval, void *mdata, va_list ap)
55158115Sume{
56158115Sume	struct cached_connection_params params;
57158115Sume	cached_connection connection;
58158115Sume
59158115Sume	char *buffer;
60158115Sume	size_t buffer_size, size;
61158115Sume
62158115Sume	nss_cache_info const *cache_info;
63158115Sume	nss_cache_data *cache_data;
64158115Sume	va_list ap_new;
65158115Sume	int res;
66158115Sume
67158115Sume	cache_data = (nss_cache_data *)mdata;
68158115Sume	cache_info = cache_data->info;
69158115Sume
70158115Sume	memset(&params, 0, sizeof(struct cached_connection_params));
71158115Sume	params.socket_path = CACHED_SOCKET_PATH;
72158115Sume
73158115Sume	cache_data->key = (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE);
74158115Sume	memset(cache_data->key, 0, NSS_CACHE_KEY_INITIAL_SIZE);
75158115Sume	cache_data->key_size = NSS_CACHE_KEY_INITIAL_SIZE;
76158115Sume	va_copy(ap_new, ap);
77158115Sume
78158115Sume	do {
79158115Sume		size = cache_data->key_size;
80158115Sume		res = cache_info->id_func(cache_data->key, &size, ap_new,
81158115Sume		    cache_info->mdata);
82158115Sume		va_end(ap_new);
83158115Sume		if (res == NS_RETURN) {
84158115Sume			if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT)
85158115Sume				break;
86158115Sume
87158115Sume			cache_data->key_size <<= 1;
88158115Sume			cache_data->key = realloc(cache_data->key,
89158115Sume			    cache_data->key_size);
90158115Sume			memset(cache_data->key, 0, cache_data->key_size);
91158115Sume			va_copy(ap_new, ap);
92158115Sume		}
93158115Sume	} while (res == NS_RETURN);
94158115Sume
95158115Sume	if (res != NS_SUCCESS) {
96158115Sume		free(cache_data->key);
97158115Sume		cache_data->key = NULL;
98158115Sume		cache_data->key_size = 0;
99158115Sume		return (res);
100158115Sume	} else
101158115Sume		cache_data->key_size = size;
102158115Sume
103158115Sume	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
104158115Sume	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
105158115Sume	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
106158115Sume
107158115Sume	do {
108158115Sume		connection = __open_cached_connection(&params);
109158115Sume		if (connection == NULL) {
110158115Sume			res = -1;
111158115Sume			break;
112158115Sume		}
113158115Sume		res = __cached_read(connection, cache_info->entry_name,
114158115Sume		    cache_data->key, cache_data->key_size, buffer,
115158115Sume		    &buffer_size);
116158115Sume		__close_cached_connection(connection);
117158115Sume		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
118158115Sume			buffer = (char *)realloc(buffer, buffer_size);
119158115Sume			memset(buffer, 0, buffer_size);
120158115Sume		}
121158115Sume	} while (res == -2);
122158115Sume
123158115Sume	if (res == 0) {
124158115Sume		if (buffer_size == 0) {
125158115Sume			free(buffer);
126158115Sume			free(cache_data->key);
127158115Sume			cache_data->key = NULL;
128158115Sume			cache_data->key_size = 0;
129158115Sume			return (NS_RETURN);
130158115Sume		}
131158115Sume
132158115Sume		va_copy(ap_new, ap);
133158115Sume		res = cache_info->unmarshal_func(buffer, buffer_size, retval,
134158115Sume		    ap_new, cache_info->mdata);
135158115Sume		va_end(ap_new);
136158115Sume
137158115Sume		if (res != NS_SUCCESS) {
138158115Sume			free(buffer);
139158115Sume			free(cache_data->key);
140158115Sume			cache_data->key = NULL;
141158115Sume			cache_data->key_size = 0;
142158115Sume			return (res);
143158115Sume		} else
144158115Sume			res = 0;
145158115Sume	}
146158115Sume
147158115Sume	if (res == 0) {
148158115Sume		free(cache_data->key);
149158115Sume		cache_data->key = NULL;
150158115Sume		cache_data->key_size = 0;
151158115Sume	}
152158115Sume
153158115Sume	free(buffer);
154158115Sume	return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
155158115Sume}
156158115Sume
157158115Sumeint
158158115Sume__nss_common_cache_write(void *retval, void *mdata, va_list ap)
159158115Sume{
160158115Sume	struct cached_connection_params params;
161158115Sume	cached_connection connection;
162158115Sume
163158115Sume	char *buffer;
164158115Sume	size_t buffer_size;
165158115Sume
166158115Sume	nss_cache_info const *cache_info;
167158115Sume	nss_cache_data *cache_data;
168158115Sume	va_list ap_new;
169158115Sume	int res;
170158115Sume
171158115Sume	cache_data = (nss_cache_data *)mdata;
172158115Sume	cache_info = cache_data->info;
173158115Sume
174158115Sume	if (cache_data->key == NULL)
175158115Sume		return (NS_UNAVAIL);
176158115Sume
177158115Sume	memset(&params, 0, sizeof(struct cached_connection_params));
178158115Sume	params.socket_path = CACHED_SOCKET_PATH;
179158115Sume
180158115Sume	connection = __open_cached_connection(&params);
181158115Sume	if (connection == NULL) {
182158115Sume		free(cache_data->key);
183158115Sume		return (NS_UNAVAIL);
184158115Sume	}
185158115Sume
186158115Sume	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
187158115Sume	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
188158115Sume	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
189158115Sume
190158115Sume	do {
191158115Sume		size_t size;
192158115Sume
193158115Sume		size = buffer_size;
194158115Sume		va_copy(ap_new, ap);
195158115Sume		res = cache_info->marshal_func(buffer, &size, retval, ap_new,
196158115Sume		    cache_info->mdata);
197158115Sume		va_end(ap_new);
198158115Sume
199158115Sume		if (res == NS_RETURN) {
200158115Sume			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
201158115Sume				break;
202158115Sume
203158115Sume			buffer_size <<= 1;
204158115Sume			buffer = (char *)realloc(buffer, buffer_size);
205158115Sume			memset(buffer, 0, buffer_size);
206158115Sume		}
207158115Sume	} while (res == NS_RETURN);
208158115Sume
209158115Sume	if (res != NS_SUCCESS) {
210158115Sume		__close_cached_connection(connection);
211158115Sume		free(cache_data->key);
212158115Sume		free(buffer);
213158115Sume		return (res);
214158115Sume	}
215158115Sume
216158115Sume	res = __cached_write(connection, cache_info->entry_name,
217158115Sume	    cache_data->key, cache_data->key_size, buffer, buffer_size);
218158115Sume	__close_cached_connection(connection);
219158115Sume
220158115Sume	free(cache_data->key);
221158115Sume	free(buffer);
222158115Sume
223158115Sume	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
224158115Sume}
225158115Sume
226158115Sumeint
227158115Sume__nss_common_cache_write_negative(void *mdata)
228158115Sume{
229158115Sume	struct cached_connection_params params;
230158115Sume	cached_connection connection;
231158115Sume	int res;
232158115Sume
233158115Sume	nss_cache_info const *cache_info;
234158115Sume	nss_cache_data *cache_data;
235158115Sume
236158115Sume	cache_data = (nss_cache_data *)mdata;
237158115Sume	cache_info = cache_data->info;
238158115Sume
239158115Sume	if (cache_data->key == NULL)
240158115Sume		return (NS_UNAVAIL);
241158115Sume
242158115Sume	memset(&params, 0, sizeof(struct cached_connection_params));
243158115Sume	params.socket_path = CACHED_SOCKET_PATH;
244158115Sume
245158115Sume	connection = __open_cached_connection(&params);
246158115Sume	if (connection == NULL) {
247158115Sume		free(cache_data->key);
248158115Sume		return (NS_UNAVAIL);
249158115Sume	}
250158115Sume
251158115Sume	res = __cached_write(connection, cache_info->entry_name,
252158115Sume	    cache_data->key, cache_data->key_size, NULL, 0);
253158115Sume	__close_cached_connection(connection);
254158115Sume
255158115Sume	free(cache_data->key);
256158115Sume	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
257158115Sume}
258158115Sume
259158115Sumeint
260158115Sume__nss_mp_cache_read(void *retval, void *mdata, va_list ap)
261158115Sume{
262158115Sume	struct cached_connection_params params;
263158115Sume	cached_mp_read_session rs;
264158115Sume
265158115Sume	char *buffer;
266158115Sume	size_t buffer_size;
267158115Sume
268158115Sume	nss_cache_info const *cache_info;
269158115Sume	nss_cache_data *cache_data;
270158115Sume	va_list ap_new;
271158115Sume	int res;
272158115Sume
273158115Sume	cache_data = (nss_cache_data *)mdata;
274158115Sume	cache_info = cache_data->info;
275158115Sume
276158115Sume	if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION)
277158115Sume		return (NS_UNAVAIL);
278158115Sume
279158115Sume	rs = cache_info->get_mp_rs_func();
280158115Sume	if (rs == INVALID_CACHED_MP_READ_SESSION) {
281158115Sume		memset(&params, 0, sizeof(struct cached_connection_params));
282158115Sume		params.socket_path = CACHED_SOCKET_PATH;
283158115Sume
284158115Sume		rs = __open_cached_mp_read_session(&params,
285158115Sume		    cache_info->entry_name);
286158115Sume		if (rs == INVALID_CACHED_MP_READ_SESSION)
287158115Sume			return (NS_UNAVAIL);
288158115Sume
289158115Sume		cache_info->set_mp_rs_func(rs);
290158115Sume	}
291158115Sume
292158115Sume	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
293158115Sume	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
294158115Sume	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
295158115Sume
296158115Sume	do {
297158115Sume		res = __cached_mp_read(rs, buffer, &buffer_size);
298158115Sume		if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
299158115Sume			buffer = (char *)realloc(buffer, buffer_size);
300158115Sume			memset(buffer, 0, buffer_size);
301158115Sume		}
302158115Sume	} while (res == -2);
303158115Sume
304158115Sume	if (res == 0) {
305158115Sume		va_copy(ap_new, ap);
306158115Sume		res = cache_info->unmarshal_func(buffer, buffer_size, retval,
307158115Sume		    ap_new, cache_info->mdata);
308158115Sume		va_end(ap_new);
309158115Sume
310158115Sume		if (res != NS_SUCCESS) {
311158115Sume			free(buffer);
312158115Sume			return (res);
313158115Sume		} else
314158115Sume			res = 0;
315158115Sume	} else {
316158115Sume		free(buffer);
317158115Sume		__close_cached_mp_read_session(rs);
318158115Sume		rs = INVALID_CACHED_MP_READ_SESSION;
319158115Sume		cache_info->set_mp_rs_func(rs);
320158115Sume		return (res == -1 ? NS_RETURN : NS_UNAVAIL);
321158115Sume	}
322158115Sume
323158115Sume	free(buffer);
324158115Sume	return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
325158115Sume}
326158115Sume
327158115Sumeint
328158115Sume__nss_mp_cache_write(void *retval, void *mdata, va_list ap)
329158115Sume{
330158115Sume	struct cached_connection_params params;
331158115Sume	cached_mp_write_session ws;
332158115Sume
333158115Sume	char *buffer;
334158115Sume	size_t buffer_size;
335158115Sume
336158115Sume	nss_cache_info const *cache_info;
337158115Sume	nss_cache_data *cache_data;
338158115Sume	va_list ap_new;
339158115Sume	int res;
340158115Sume
341158115Sume	cache_data = (nss_cache_data *)mdata;
342158115Sume	cache_info = cache_data->info;
343158115Sume
344158115Sume	ws = cache_info->get_mp_ws_func();
345158115Sume	if (ws == INVALID_CACHED_MP_WRITE_SESSION) {
346158115Sume		memset(&params, 0, sizeof(struct cached_connection_params));
347158115Sume		params.socket_path = CACHED_SOCKET_PATH;
348158115Sume
349158115Sume		ws = __open_cached_mp_write_session(&params,
350158115Sume		    cache_info->entry_name);
351158115Sume		if (ws == INVALID_CACHED_MP_WRITE_SESSION)
352158115Sume			return (NS_UNAVAIL);
353158115Sume
354158115Sume		cache_info->set_mp_ws_func(ws);
355158115Sume	}
356158115Sume
357158115Sume	buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
358158115Sume	buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
359158115Sume	memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
360158115Sume
361158115Sume	do {
362158115Sume		size_t size;
363158115Sume
364158115Sume		size = buffer_size;
365158115Sume		va_copy(ap_new, ap);
366158115Sume		res = cache_info->marshal_func(buffer, &size, retval, ap_new,
367158115Sume		    cache_info->mdata);
368158115Sume		va_end(ap_new);
369158115Sume
370158115Sume		if (res == NS_RETURN) {
371158115Sume			if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
372158115Sume				break;
373158115Sume
374158115Sume			buffer_size <<= 1;
375158115Sume			buffer = (char *)realloc(buffer, buffer_size);
376158115Sume			memset(buffer, 0, buffer_size);
377158115Sume		}
378158115Sume	} while (res == NS_RETURN);
379158115Sume
380158115Sume	if (res != NS_SUCCESS) {
381158115Sume		free(buffer);
382158115Sume		return (res);
383158115Sume	}
384158115Sume
385158115Sume	res = __cached_mp_write(ws, buffer, buffer_size);
386158115Sume
387158115Sume	free(buffer);
388158115Sume	return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
389158115Sume}
390158115Sume
391158115Sumeint
392158115Sume__nss_mp_cache_write_submit(void *retval, void *mdata, va_list ap)
393158115Sume{
394158115Sume	cached_mp_write_session ws;
395158115Sume
396158115Sume	nss_cache_info const *cache_info;
397158115Sume	nss_cache_data *cache_data;
398158115Sume
399158115Sume	cache_data = (nss_cache_data *)mdata;
400158115Sume	cache_info = cache_data->info;
401158115Sume
402158115Sume	ws = cache_info->get_mp_ws_func();
403158115Sume	if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
404158115Sume		__close_cached_mp_write_session(ws);
405158115Sume		ws = INVALID_CACHED_MP_WRITE_SESSION;
406158115Sume		cache_info->set_mp_ws_func(ws);
407158115Sume	}
408158115Sume	return (NS_UNAVAIL);
409158115Sume}
410158115Sume
411158115Sumeint
412158115Sume__nss_mp_cache_end(void *retval, void *mdata, va_list ap)
413158115Sume{
414158115Sume	cached_mp_write_session ws;
415158115Sume	cached_mp_read_session rs;
416158115Sume
417158115Sume	nss_cache_info const *cache_info;
418158115Sume	nss_cache_data *cache_data;
419158115Sume
420158115Sume	cache_data = (nss_cache_data *)mdata;
421158115Sume	cache_info = cache_data->info;
422158115Sume
423158115Sume	ws = cache_info->get_mp_ws_func();
424158115Sume	if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
425158115Sume		__abandon_cached_mp_write_session(ws);
426158115Sume		ws = INVALID_CACHED_MP_WRITE_SESSION;
427158115Sume		cache_info->set_mp_ws_func(ws);
428158115Sume	}
429158115Sume
430158115Sume	rs = cache_info->get_mp_rs_func();
431158115Sume	if (rs != INVALID_CACHED_MP_READ_SESSION) {
432158115Sume		__close_cached_mp_read_session(rs);
433158115Sume		rs = INVALID_CACHED_MP_READ_SESSION;
434158115Sume		cache_info->set_mp_rs_func(rs);
435158115Sume	}
436158115Sume
437158115Sume	return (NS_UNAVAIL);
438158115Sume}
439