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
, void *mdata
, va_list ap
)
52 __nss_common_cache_read(void *retval
, void *mdata
, va_list ap
)
54 struct cached_connection_params params
;
55 cached_connection connection
;
58 size_t buffer_size
, size
;
60 nss_cache_info
const *cache_info
;
61 nss_cache_data
*cache_data
;
65 cache_data
= (nss_cache_data
*)mdata
;
66 cache_info
= cache_data
->info
;
68 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
69 params
.socket_path
= CACHED_SOCKET_PATH
;
71 cache_data
->key
= (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE
);
72 memset(cache_data
->key
, 0, NSS_CACHE_KEY_INITIAL_SIZE
);
73 cache_data
->key_size
= NSS_CACHE_KEY_INITIAL_SIZE
;
77 size
= cache_data
->key_size
;
78 res
= cache_info
->id_func(cache_data
->key
, &size
, ap_new
,
81 if (res
== NS_RETURN
) {
82 if (cache_data
->key_size
> NSS_CACHE_KEY_SIZE_LIMIT
)
85 cache_data
->key_size
<<= 1;
86 cache_data
->key
= realloc(cache_data
->key
,
87 cache_data
->key_size
);
88 memset(cache_data
->key
, 0, cache_data
->key_size
);
91 } while (res
== NS_RETURN
);
93 if (res
!= NS_SUCCESS
) {
94 free(cache_data
->key
);
95 cache_data
->key
= NULL
;
96 cache_data
->key_size
= 0;
99 cache_data
->key_size
= size
;
101 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
102 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
103 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
106 connection
= __open_cached_connection(¶ms
);
107 if (connection
== NULL
) {
111 res
= __cached_read(connection
, cache_info
->entry_name
,
112 cache_data
->key
, cache_data
->key_size
, buffer
,
114 __close_cached_connection(connection
);
115 if (res
== -2 && buffer_size
< NSS_CACHE_BUFFER_SIZE_LIMIT
) {
116 buffer
= (char *)realloc(buffer
, buffer_size
);
117 memset(buffer
, 0, buffer_size
);
122 if (buffer_size
== 0) {
124 free(cache_data
->key
);
125 cache_data
->key
= NULL
;
126 cache_data
->key_size
= 0;
131 res
= cache_info
->unmarshal_func(buffer
, buffer_size
, retval
,
132 ap_new
, cache_info
->mdata
);
135 if (res
!= NS_SUCCESS
) {
137 free(cache_data
->key
);
138 cache_data
->key
= NULL
;
139 cache_data
->key_size
= 0;
146 free(cache_data
->key
);
147 cache_data
->key
= NULL
;
148 cache_data
->key_size
= 0;
152 return (res
== 0 ? NS_SUCCESS
: NS_NOTFOUND
);
156 __nss_common_cache_write(void *retval
, void *mdata
, va_list ap
)
158 struct cached_connection_params params
;
159 cached_connection connection
;
164 nss_cache_info
const *cache_info
;
165 nss_cache_data
*cache_data
;
169 cache_data
= (nss_cache_data
*)mdata
;
170 cache_info
= cache_data
->info
;
172 if (cache_data
->key
== NULL
)
175 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
176 params
.socket_path
= CACHED_SOCKET_PATH
;
178 connection
= __open_cached_connection(¶ms
);
179 if (connection
== NULL
) {
180 free(cache_data
->key
);
184 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
185 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
186 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
193 res
= cache_info
->marshal_func(buffer
, &size
, retval
, ap_new
,
197 if (res
== NS_RETURN
) {
198 if (buffer_size
> NSS_CACHE_BUFFER_SIZE_LIMIT
)
202 buffer
= (char *)realloc(buffer
, buffer_size
);
203 memset(buffer
, 0, buffer_size
);
205 } while (res
== NS_RETURN
);
207 if (res
!= NS_SUCCESS
) {
208 __close_cached_connection(connection
);
209 free(cache_data
->key
);
214 res
= __cached_write(connection
, cache_info
->entry_name
,
215 cache_data
->key
, cache_data
->key_size
, buffer
, buffer_size
);
216 __close_cached_connection(connection
);
218 free(cache_data
->key
);
221 return (res
== 0 ? NS_SUCCESS
: NS_UNAVAIL
);
225 __nss_common_cache_write_negative(void *mdata
)
227 struct cached_connection_params params
;
228 cached_connection connection
;
231 nss_cache_info
const *cache_info
;
232 nss_cache_data
*cache_data
;
234 cache_data
= (nss_cache_data
*)mdata
;
235 cache_info
= cache_data
->info
;
237 if (cache_data
->key
== NULL
)
240 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
241 params
.socket_path
= CACHED_SOCKET_PATH
;
243 connection
= __open_cached_connection(¶ms
);
244 if (connection
== NULL
) {
245 free(cache_data
->key
);
249 res
= __cached_write(connection
, cache_info
->entry_name
,
250 cache_data
->key
, cache_data
->key_size
, NULL
, 0);
251 __close_cached_connection(connection
);
253 free(cache_data
->key
);
254 return (res
== 0 ? NS_SUCCESS
: NS_UNAVAIL
);
258 __nss_mp_cache_read(void *retval
, void *mdata
, va_list ap
)
260 struct cached_connection_params params
;
261 cached_mp_read_session rs
;
266 nss_cache_info
const *cache_info
;
267 nss_cache_data
*cache_data
;
271 cache_data
= (nss_cache_data
*)mdata
;
272 cache_info
= cache_data
->info
;
274 if (cache_info
->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION
)
277 rs
= cache_info
->get_mp_rs_func();
278 if (rs
== INVALID_CACHED_MP_READ_SESSION
) {
279 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
280 params
.socket_path
= CACHED_SOCKET_PATH
;
282 rs
= __open_cached_mp_read_session(¶ms
,
283 cache_info
->entry_name
);
284 if (rs
== INVALID_CACHED_MP_READ_SESSION
)
287 cache_info
->set_mp_rs_func(rs
);
290 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
291 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
292 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
295 res
= __cached_mp_read(rs
, buffer
, &buffer_size
);
296 if (res
== -2 && buffer_size
< NSS_CACHE_BUFFER_SIZE_LIMIT
) {
297 buffer
= (char *)realloc(buffer
, buffer_size
);
298 memset(buffer
, 0, buffer_size
);
304 res
= cache_info
->unmarshal_func(buffer
, buffer_size
, retval
,
305 ap_new
, cache_info
->mdata
);
308 if (res
!= NS_SUCCESS
) {
315 __close_cached_mp_read_session(rs
);
316 rs
= INVALID_CACHED_MP_READ_SESSION
;
317 cache_info
->set_mp_rs_func(rs
);
318 return (res
== -1 ? NS_RETURN
: NS_UNAVAIL
);
322 return (res
== 0 ? NS_SUCCESS
: NS_NOTFOUND
);
326 __nss_mp_cache_write(void *retval
, void *mdata
, va_list ap
)
328 struct cached_connection_params params
;
329 cached_mp_write_session ws
;
334 nss_cache_info
const *cache_info
;
335 nss_cache_data
*cache_data
;
339 cache_data
= (nss_cache_data
*)mdata
;
340 cache_info
= cache_data
->info
;
342 ws
= cache_info
->get_mp_ws_func();
343 if (ws
== INVALID_CACHED_MP_WRITE_SESSION
) {
344 memset(¶ms
, 0, sizeof(struct cached_connection_params
));
345 params
.socket_path
= CACHED_SOCKET_PATH
;
347 ws
= __open_cached_mp_write_session(¶ms
,
348 cache_info
->entry_name
);
349 if (ws
== INVALID_CACHED_MP_WRITE_SESSION
)
352 cache_info
->set_mp_ws_func(ws
);
355 buffer_size
= NSS_CACHE_BUFFER_INITIAL_SIZE
;
356 buffer
= (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE
);
357 memset(buffer
, 0, NSS_CACHE_BUFFER_INITIAL_SIZE
);
364 res
= cache_info
->marshal_func(buffer
, &size
, retval
, ap_new
,
368 if (res
== NS_RETURN
) {
369 if (buffer_size
> NSS_CACHE_BUFFER_SIZE_LIMIT
)
373 buffer
= (char *)realloc(buffer
, buffer_size
);
374 memset(buffer
, 0, buffer_size
);
376 } while (res
== NS_RETURN
);
378 if (res
!= NS_SUCCESS
) {
383 res
= __cached_mp_write(ws
, buffer
, buffer_size
);
386 return (res
== 0 ? NS_SUCCESS
: NS_UNAVAIL
);
390 __nss_mp_cache_write_submit(void *retval
, void *mdata
, va_list ap
)
392 cached_mp_write_session ws
;
394 nss_cache_info
const *cache_info
;
395 nss_cache_data
*cache_data
;
397 cache_data
= (nss_cache_data
*)mdata
;
398 cache_info
= cache_data
->info
;
400 ws
= cache_info
->get_mp_ws_func();
401 if (ws
!= INVALID_CACHED_MP_WRITE_SESSION
) {
402 __close_cached_mp_write_session(ws
);
403 ws
= INVALID_CACHED_MP_WRITE_SESSION
;
404 cache_info
->set_mp_ws_func(ws
);
410 __nss_mp_cache_end(void *retval
, void *mdata
, va_list ap
)
412 cached_mp_write_session ws
;
413 cached_mp_read_session rs
;
415 nss_cache_info
const *cache_info
;
416 nss_cache_data
*cache_data
;
418 cache_data
= (nss_cache_data
*)mdata
;
419 cache_info
= cache_data
->info
;
421 ws
= cache_info
->get_mp_ws_func();
422 if (ws
!= INVALID_CACHED_MP_WRITE_SESSION
) {
423 __abandon_cached_mp_write_session(ws
);
424 ws
= INVALID_CACHED_MP_WRITE_SESSION
;
425 cache_info
->set_mp_ws_func(ws
);
428 rs
= cache_info
->get_mp_rs_func();
429 if (rs
!= INVALID_CACHED_MP_READ_SESSION
) {
430 __close_cached_mp_read_session(rs
);
431 rs
= INVALID_CACHED_MP_READ_SESSION
;
432 cache_info
->set_mp_rs_func(rs
);