2 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/lib/libc/net/nscache.c,v 1.2 2007/10/17 23:20:49 tmclaugh Exp $
29 #include "namespace.h"
33 #include "un-namespace.h"
34 #include "nscachedcli.h"
37 #define NSS_CACHE_KEY_INITIAL_SIZE (256)
38 #define NSS_CACHE_KEY_SIZE_LIMIT (NSS_CACHE_KEY_INITIAL_SIZE << 4)
40 #define NSS_CACHE_BUFFER_INITIAL_SIZE (1024)
41 #define NSS_CACHE_BUFFER_SIZE_LIMIT (NSS_CACHE_BUFFER_INITIAL_SIZE << 8)
43 #define CACHED_SOCKET_PATH "/var/run/nscd"
46 __nss_cache_handler(void *retval __unused
, void *mdata __unused
,
53 __nss_common_cache_read(void *retval
, void *mdata
, va_list ap
)
55 struct cached_connection_params params
;
56 cached_connection connection
;
59 size_t buffer_size
, size
;
61 nss_cache_info
const *cache_info
;
62 nss_cache_data
*cache_data
;
66 cache_data
= (nss_cache_data
*)mdata
;
67 cache_info
= cache_data
->info
;
69 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
70 params
.socket_path
= CACHED_SOCKET_PATH
;
72 cache_data
->key
= (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE
);
73 memset(cache_data
->key
, 0, NSS_CACHE_KEY_INITIAL_SIZE
);
74 cache_data
->key_size
= NSS_CACHE_KEY_INITIAL_SIZE
;
78 size
= cache_data
->key_size
;
79 res
= cache_info
->id_func(cache_data
->key
, &size
, ap_new
,
82 if (res
== NS_RETURN
) {
83 if (cache_data
->key_size
> NSS_CACHE_KEY_SIZE_LIMIT
)
86 cache_data
->key_size
<<= 1;
87 cache_data
->key
= realloc(cache_data
->key
,
88 cache_data
->key_size
);
89 memset(cache_data
->key
, 0, cache_data
->key_size
);
92 } while (res
== NS_RETURN
);
94 if (res
!= NS_SUCCESS
) {
95 free(cache_data
->key
);
96 cache_data
->key
= NULL
;
97 cache_data
->key_size
= 0;
100 cache_data
->key_size
= size
;
102 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
103 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
104 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
107 connection
= __open_cached_connection(¶ms
);
108 if (connection
== NULL
) {
112 res
= __cached_read(connection
, cache_info
->entry_name
,
113 cache_data
->key
, cache_data
->key_size
, buffer
,
115 __close_cached_connection(connection
);
116 if (res
== -2 && buffer_size
< NSS_CACHE_BUFFER_SIZE_LIMIT
) {
117 buffer
= (char *)realloc(buffer
, buffer_size
);
118 memset(buffer
, 0, buffer_size
);
123 if (buffer_size
== 0) {
125 free(cache_data
->key
);
126 cache_data
->key
= NULL
;
127 cache_data
->key_size
= 0;
132 res
= cache_info
->unmarshal_func(buffer
, buffer_size
, retval
,
133 ap_new
, cache_info
->mdata
);
136 if (res
!= NS_SUCCESS
) {
138 free(cache_data
->key
);
139 cache_data
->key
= NULL
;
140 cache_data
->key_size
= 0;
147 free(cache_data
->key
);
148 cache_data
->key
= NULL
;
149 cache_data
->key_size
= 0;
153 return (res
== 0 ? NS_SUCCESS
: NS_NOTFOUND
);
157 __nss_common_cache_write(void *retval
, void *mdata
, va_list ap
)
159 struct cached_connection_params params
;
160 cached_connection connection
;
165 nss_cache_info
const *cache_info
;
166 nss_cache_data
*cache_data
;
170 cache_data
= (nss_cache_data
*)mdata
;
171 cache_info
= cache_data
->info
;
173 if (cache_data
->key
== NULL
)
176 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
177 params
.socket_path
= CACHED_SOCKET_PATH
;
179 connection
= __open_cached_connection(¶ms
);
180 if (connection
== NULL
) {
181 free(cache_data
->key
);
185 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
186 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
187 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
194 res
= cache_info
->marshal_func(buffer
, &size
, retval
, ap_new
,
198 if (res
== NS_RETURN
) {
199 if (buffer_size
> NSS_CACHE_BUFFER_SIZE_LIMIT
)
203 buffer
= (char *)realloc(buffer
, buffer_size
);
204 memset(buffer
, 0, buffer_size
);
206 } while (res
== NS_RETURN
);
208 if (res
!= NS_SUCCESS
) {
209 __close_cached_connection(connection
);
210 free(cache_data
->key
);
215 res
= __cached_write(connection
, cache_info
->entry_name
,
216 cache_data
->key
, cache_data
->key_size
, buffer
, buffer_size
);
217 __close_cached_connection(connection
);
219 free(cache_data
->key
);
222 return (res
== 0 ? NS_SUCCESS
: NS_UNAVAIL
);
226 __nss_common_cache_write_negative(void *mdata
)
228 struct cached_connection_params params
;
229 cached_connection connection
;
232 nss_cache_info
const *cache_info
;
233 nss_cache_data
*cache_data
;
235 cache_data
= (nss_cache_data
*)mdata
;
236 cache_info
= cache_data
->info
;
238 if (cache_data
->key
== NULL
)
241 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
242 params
.socket_path
= CACHED_SOCKET_PATH
;
244 connection
= __open_cached_connection(¶ms
);
245 if (connection
== NULL
) {
246 free(cache_data
->key
);
250 res
= __cached_write(connection
, cache_info
->entry_name
,
251 cache_data
->key
, cache_data
->key_size
, NULL
, 0);
252 __close_cached_connection(connection
);
254 free(cache_data
->key
);
255 return (res
== 0 ? NS_SUCCESS
: NS_UNAVAIL
);
259 __nss_mp_cache_read(void *retval
, void *mdata
, va_list ap
)
261 struct cached_connection_params params
;
262 cached_mp_read_session rs
;
267 nss_cache_info
const *cache_info
;
268 nss_cache_data
*cache_data
;
272 cache_data
= (nss_cache_data
*)mdata
;
273 cache_info
= cache_data
->info
;
275 if (cache_info
->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION
)
278 rs
= cache_info
->get_mp_rs_func();
279 if (rs
== INVALID_CACHED_MP_READ_SESSION
) {
280 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
281 params
.socket_path
= CACHED_SOCKET_PATH
;
283 rs
= __open_cached_mp_read_session(¶ms
,
284 cache_info
->entry_name
);
285 if (rs
== INVALID_CACHED_MP_READ_SESSION
)
288 cache_info
->set_mp_rs_func(rs
);
291 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
292 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
293 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
296 res
= __cached_mp_read(rs
, buffer
, &buffer_size
);
297 if (res
== -2 && buffer_size
< NSS_CACHE_BUFFER_SIZE_LIMIT
) {
298 buffer
= (char *)realloc(buffer
, buffer_size
);
299 memset(buffer
, 0, buffer_size
);
305 res
= cache_info
->unmarshal_func(buffer
, buffer_size
, retval
,
306 ap_new
, cache_info
->mdata
);
309 if (res
!= NS_SUCCESS
) {
316 __close_cached_mp_read_session(rs
);
317 rs
= INVALID_CACHED_MP_READ_SESSION
;
318 cache_info
->set_mp_rs_func(rs
);
319 return (res
== -1 ? NS_RETURN
: NS_UNAVAIL
);
323 return (res
== 0 ? NS_SUCCESS
: NS_NOTFOUND
);
327 __nss_mp_cache_write(void *retval
, void *mdata
, va_list ap
)
329 struct cached_connection_params params
;
330 cached_mp_write_session ws
;
335 nss_cache_info
const *cache_info
;
336 nss_cache_data
*cache_data
;
340 cache_data
= (nss_cache_data
*)mdata
;
341 cache_info
= cache_data
->info
;
343 ws
= cache_info
->get_mp_ws_func();
344 if (ws
== INVALID_CACHED_MP_WRITE_SESSION
) {
345 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
346 params
.socket_path
= CACHED_SOCKET_PATH
;
348 ws
= __open_cached_mp_write_session(¶ms
,
349 cache_info
->entry_name
);
350 if (ws
== INVALID_CACHED_MP_WRITE_SESSION
)
353 cache_info
->set_mp_ws_func(ws
);
356 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
357 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
358 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
365 res
= cache_info
->marshal_func(buffer
, &size
, retval
, ap_new
,
369 if (res
== NS_RETURN
) {
370 if (buffer_size
> NSS_CACHE_BUFFER_SIZE_LIMIT
)
374 buffer
= (char *)realloc(buffer
, buffer_size
);
375 memset(buffer
, 0, buffer_size
);
377 } while (res
== NS_RETURN
);
379 if (res
!= NS_SUCCESS
) {
384 res
= __cached_mp_write(ws
, buffer
, buffer_size
);
387 return (res
== 0 ? NS_SUCCESS
: NS_UNAVAIL
);
391 __nss_mp_cache_write_submit(void *retval __unused
, void *mdata
,
394 cached_mp_write_session ws
;
396 nss_cache_info
const *cache_info
;
397 nss_cache_data
*cache_data
;
399 cache_data
= (nss_cache_data
*)mdata
;
400 cache_info
= cache_data
->info
;
402 ws
= cache_info
->get_mp_ws_func();
403 if (ws
!= INVALID_CACHED_MP_WRITE_SESSION
) {
404 __close_cached_mp_write_session(ws
);
405 ws
= INVALID_CACHED_MP_WRITE_SESSION
;
406 cache_info
->set_mp_ws_func(ws
);
412 __nss_mp_cache_end(void *retval __unused
, void *mdata
, va_list ap __unused
)
414 cached_mp_write_session ws
;
415 cached_mp_read_session rs
;
417 nss_cache_info
const *cache_info
;
418 nss_cache_data
*cache_data
;
420 cache_data
= (nss_cache_data
*)mdata
;
421 cache_info
= cache_data
->info
;
423 ws
= cache_info
->get_mp_ws_func();
424 if (ws
!= INVALID_CACHED_MP_WRITE_SESSION
) {
425 __abandon_cached_mp_write_session(ws
);
426 ws
= INVALID_CACHED_MP_WRITE_SESSION
;
427 cache_info
->set_mp_ws_func(ws
);
430 rs
= cache_info
->get_mp_rs_func();
431 if (rs
!= INVALID_CACHED_MP_READ_SESSION
) {
432 __close_cached_mp_read_session(rs
);
433 rs
= INVALID_CACHED_MP_READ_SESSION
;
434 cache_info
->set_mp_rs_func(rs
);