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
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include "namespace.h"
36 #include "un-namespace.h"
37 #include "nscachedcli.h"
40 #define NSS_CACHE_KEY_INITIAL_SIZE (256)
41 #define NSS_CACHE_KEY_SIZE_LIMIT (NSS_CACHE_KEY_INITIAL_SIZE << 4)
43 #define NSS_CACHE_BUFFER_INITIAL_SIZE (1024)
44 #define NSS_CACHE_BUFFER_SIZE_LIMIT (NSS_CACHE_BUFFER_INITIAL_SIZE << 8)
46 #define CACHED_SOCKET_PATH "/var/run/nscd"
49 __nss_cache_handler(void *retval
, void *mdata
, va_list ap
)
55 __nss_common_cache_read(void *retval
, void *mdata
, va_list ap
)
57 struct cached_connection_params params
;
58 cached_connection connection
;
61 size_t buffer_size
, size
;
63 nss_cache_info
const *cache_info
;
64 nss_cache_data
*cache_data
;
68 cache_data
= (nss_cache_data
*)mdata
;
69 cache_info
= cache_data
->info
;
71 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
72 params
.socket_path
= CACHED_SOCKET_PATH
;
74 cache_data
->key
= (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE
);
75 memset(cache_data
->key
, 0, NSS_CACHE_KEY_INITIAL_SIZE
);
76 cache_data
->key_size
= NSS_CACHE_KEY_INITIAL_SIZE
;
80 size
= cache_data
->key_size
;
81 res
= cache_info
->id_func(cache_data
->key
, &size
, ap_new
,
84 if (res
== NS_RETURN
) {
85 if (cache_data
->key_size
> NSS_CACHE_KEY_SIZE_LIMIT
)
88 cache_data
->key_size
<<= 1;
89 cache_data
->key
= realloc(cache_data
->key
,
90 cache_data
->key_size
);
91 memset(cache_data
->key
, 0, cache_data
->key_size
);
94 } while (res
== NS_RETURN
);
96 if (res
!= NS_SUCCESS
) {
97 free(cache_data
->key
);
98 cache_data
->key
= NULL
;
99 cache_data
->key_size
= 0;
102 cache_data
->key_size
= size
;
104 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
105 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
106 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
109 connection
= __open_cached_connection(¶ms
);
110 if (connection
== NULL
) {
114 res
= __cached_read(connection
, cache_info
->entry_name
,
115 cache_data
->key
, cache_data
->key_size
, buffer
,
117 __close_cached_connection(connection
);
118 if (res
== -2 && buffer_size
< NSS_CACHE_BUFFER_SIZE_LIMIT
) {
119 buffer
= (char *)realloc(buffer
, buffer_size
);
120 memset(buffer
, 0, buffer_size
);
125 if (buffer_size
== 0) {
127 free(cache_data
->key
);
128 cache_data
->key
= NULL
;
129 cache_data
->key_size
= 0;
134 res
= cache_info
->unmarshal_func(buffer
, buffer_size
, retval
,
135 ap_new
, cache_info
->mdata
);
138 if (res
!= NS_SUCCESS
) {
140 free(cache_data
->key
);
141 cache_data
->key
= NULL
;
142 cache_data
->key_size
= 0;
149 free(cache_data
->key
);
150 cache_data
->key
= NULL
;
151 cache_data
->key_size
= 0;
155 return (res
== 0 ? NS_SUCCESS
: NS_NOTFOUND
);
159 __nss_common_cache_write(void *retval
, void *mdata
, va_list ap
)
161 struct cached_connection_params params
;
162 cached_connection connection
;
167 nss_cache_info
const *cache_info
;
168 nss_cache_data
*cache_data
;
172 cache_data
= (nss_cache_data
*)mdata
;
173 cache_info
= cache_data
->info
;
175 if (cache_data
->key
== NULL
)
178 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
179 params
.socket_path
= CACHED_SOCKET_PATH
;
181 connection
= __open_cached_connection(¶ms
);
182 if (connection
== NULL
) {
183 free(cache_data
->key
);
187 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
188 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
189 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
196 res
= cache_info
->marshal_func(buffer
, &size
, retval
, ap_new
,
200 if (res
== NS_RETURN
) {
201 if (buffer_size
> NSS_CACHE_BUFFER_SIZE_LIMIT
)
205 buffer
= (char *)realloc(buffer
, buffer_size
);
206 memset(buffer
, 0, buffer_size
);
208 } while (res
== NS_RETURN
);
210 if (res
!= NS_SUCCESS
) {
211 __close_cached_connection(connection
);
212 free(cache_data
->key
);
217 res
= __cached_write(connection
, cache_info
->entry_name
,
218 cache_data
->key
, cache_data
->key_size
, buffer
, buffer_size
);
219 __close_cached_connection(connection
);
221 free(cache_data
->key
);
224 return (res
== 0 ? NS_SUCCESS
: NS_UNAVAIL
);
228 __nss_common_cache_write_negative(void *mdata
)
230 struct cached_connection_params params
;
231 cached_connection connection
;
234 nss_cache_info
const *cache_info
;
235 nss_cache_data
*cache_data
;
237 cache_data
= (nss_cache_data
*)mdata
;
238 cache_info
= cache_data
->info
;
240 if (cache_data
->key
== NULL
)
243 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
244 params
.socket_path
= CACHED_SOCKET_PATH
;
246 connection
= __open_cached_connection(¶ms
);
247 if (connection
== NULL
) {
248 free(cache_data
->key
);
252 res
= __cached_write(connection
, cache_info
->entry_name
,
253 cache_data
->key
, cache_data
->key_size
, NULL
, 0);
254 __close_cached_connection(connection
);
256 free(cache_data
->key
);
257 return (res
== 0 ? NS_SUCCESS
: NS_UNAVAIL
);
261 __nss_mp_cache_read(void *retval
, void *mdata
, va_list ap
)
263 struct cached_connection_params params
;
264 cached_mp_read_session rs
;
269 nss_cache_info
const *cache_info
;
270 nss_cache_data
*cache_data
;
274 cache_data
= (nss_cache_data
*)mdata
;
275 cache_info
= cache_data
->info
;
277 if (cache_info
->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION
)
280 rs
= cache_info
->get_mp_rs_func();
281 if (rs
== INVALID_CACHED_MP_READ_SESSION
) {
282 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
283 params
.socket_path
= CACHED_SOCKET_PATH
;
285 rs
= __open_cached_mp_read_session(¶ms
,
286 cache_info
->entry_name
);
287 if (rs
== INVALID_CACHED_MP_READ_SESSION
)
290 cache_info
->set_mp_rs_func(rs
);
293 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
294 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
295 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
298 res
= __cached_mp_read(rs
, buffer
, &buffer_size
);
299 if (res
== -2 && buffer_size
< NSS_CACHE_BUFFER_SIZE_LIMIT
) {
300 buffer
= (char *)realloc(buffer
, buffer_size
);
301 memset(buffer
, 0, buffer_size
);
307 res
= cache_info
->unmarshal_func(buffer
, buffer_size
, retval
,
308 ap_new
, cache_info
->mdata
);
311 if (res
!= NS_SUCCESS
) {
318 __close_cached_mp_read_session(rs
);
319 rs
= INVALID_CACHED_MP_READ_SESSION
;
320 cache_info
->set_mp_rs_func(rs
);
321 return (res
== -1 ? NS_RETURN
: NS_UNAVAIL
);
325 return (res
== 0 ? NS_SUCCESS
: NS_NOTFOUND
);
329 __nss_mp_cache_write(void *retval
, void *mdata
, va_list ap
)
331 struct cached_connection_params params
;
332 cached_mp_write_session ws
;
337 nss_cache_info
const *cache_info
;
338 nss_cache_data
*cache_data
;
342 cache_data
= (nss_cache_data
*)mdata
;
343 cache_info
= cache_data
->info
;
345 ws
= cache_info
->get_mp_ws_func();
346 if (ws
== INVALID_CACHED_MP_WRITE_SESSION
) {
347 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
348 params
.socket_path
= CACHED_SOCKET_PATH
;
350 ws
= __open_cached_mp_write_session(¶ms
,
351 cache_info
->entry_name
);
352 if (ws
== INVALID_CACHED_MP_WRITE_SESSION
)
355 cache_info
->set_mp_ws_func(ws
);
358 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
359 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
360 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
367 res
= cache_info
->marshal_func(buffer
, &size
, retval
, ap_new
,
371 if (res
== NS_RETURN
) {
372 if (buffer_size
> NSS_CACHE_BUFFER_SIZE_LIMIT
)
376 buffer
= (char *)realloc(buffer
, buffer_size
);
377 memset(buffer
, 0, buffer_size
);
379 } while (res
== NS_RETURN
);
381 if (res
!= NS_SUCCESS
) {
386 res
= __cached_mp_write(ws
, buffer
, buffer_size
);
389 return (res
== 0 ? NS_SUCCESS
: NS_UNAVAIL
);
393 __nss_mp_cache_write_submit(void *retval
, void *mdata
, va_list ap
)
395 cached_mp_write_session ws
;
397 nss_cache_info
const *cache_info
;
398 nss_cache_data
*cache_data
;
400 cache_data
= (nss_cache_data
*)mdata
;
401 cache_info
= cache_data
->info
;
403 ws
= cache_info
->get_mp_ws_func();
404 if (ws
!= INVALID_CACHED_MP_WRITE_SESSION
) {
405 __close_cached_mp_write_session(ws
);
406 ws
= INVALID_CACHED_MP_WRITE_SESSION
;
407 cache_info
->set_mp_ws_func(ws
);
413 __nss_mp_cache_end(void *retval
, void *mdata
, va_list ap
)
415 cached_mp_write_session ws
;
416 cached_mp_read_session rs
;
418 nss_cache_info
const *cache_info
;
419 nss_cache_data
*cache_data
;
421 cache_data
= (nss_cache_data
*)mdata
;
422 cache_info
= cache_data
->info
;
424 ws
= cache_info
->get_mp_ws_func();
425 if (ws
!= INVALID_CACHED_MP_WRITE_SESSION
) {
426 __abandon_cached_mp_write_session(ws
);
427 ws
= INVALID_CACHED_MP_WRITE_SESSION
;
428 cache_info
->set_mp_ws_func(ws
);
431 rs
= cache_info
->get_mp_rs_func();
432 if (rs
!= INVALID_CACHED_MP_READ_SESSION
) {
433 __close_cached_mp_read_session(rs
);
434 rs
= INVALID_CACHED_MP_READ_SESSION
;
435 cache_info
->set_mp_rs_func(rs
);