2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include "namespace.h"
38 #include "un-namespace.h"
39 #include "nscachedcli.h"
42 #define NSS_CACHE_KEY_INITIAL_SIZE (256)
43 #define NSS_CACHE_KEY_SIZE_LIMIT (NSS_CACHE_KEY_INITIAL_SIZE << 4)
45 #define NSS_CACHE_BUFFER_INITIAL_SIZE (1024)
46 #define NSS_CACHE_BUFFER_SIZE_LIMIT (NSS_CACHE_BUFFER_INITIAL_SIZE << 8)
48 #define CACHED_SOCKET_PATH "/var/run/nscd"
51 __nss_cache_handler(void *retval, void *mdata, va_list ap)
57 __nss_common_cache_read(void *retval, void *mdata, va_list ap)
59 struct cached_connection_params params;
60 cached_connection connection;
63 size_t buffer_size, size;
65 nss_cache_info const *cache_info;
66 nss_cache_data *cache_data;
70 cache_data = (nss_cache_data *)mdata;
71 cache_info = cache_data->info;
73 memset(¶ms, 0, sizeof(struct cached_connection_params));
74 params.socket_path = CACHED_SOCKET_PATH;
76 cache_data->key = (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE);
77 memset(cache_data->key, 0, NSS_CACHE_KEY_INITIAL_SIZE);
78 cache_data->key_size = NSS_CACHE_KEY_INITIAL_SIZE;
82 size = cache_data->key_size;
83 res = cache_info->id_func(cache_data->key, &size, ap_new,
86 if (res == NS_RETURN) {
87 if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT)
90 cache_data->key_size <<= 1;
91 cache_data->key = realloc(cache_data->key,
92 cache_data->key_size);
93 memset(cache_data->key, 0, cache_data->key_size);
96 } while (res == NS_RETURN);
98 if (res != NS_SUCCESS) {
99 free(cache_data->key);
100 cache_data->key = NULL;
101 cache_data->key_size = 0;
104 cache_data->key_size = size;
106 buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
107 buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
108 memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
111 connection = __open_cached_connection(¶ms);
112 if (connection == NULL) {
116 res = __cached_read(connection, cache_info->entry_name,
117 cache_data->key, cache_data->key_size, buffer,
119 __close_cached_connection(connection);
120 if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
121 buffer = (char *)realloc(buffer, buffer_size);
122 memset(buffer, 0, buffer_size);
127 if (buffer_size == 0) {
129 free(cache_data->key);
130 cache_data->key = NULL;
131 cache_data->key_size = 0;
136 res = cache_info->unmarshal_func(buffer, buffer_size, retval,
137 ap_new, cache_info->mdata);
140 if (res != NS_SUCCESS) {
142 free(cache_data->key);
143 cache_data->key = NULL;
144 cache_data->key_size = 0;
151 free(cache_data->key);
152 cache_data->key = NULL;
153 cache_data->key_size = 0;
157 return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
161 __nss_common_cache_write(void *retval, void *mdata, va_list ap)
163 struct cached_connection_params params;
164 cached_connection connection;
169 nss_cache_info const *cache_info;
170 nss_cache_data *cache_data;
174 cache_data = (nss_cache_data *)mdata;
175 cache_info = cache_data->info;
177 if (cache_data->key == NULL)
180 memset(¶ms, 0, sizeof(struct cached_connection_params));
181 params.socket_path = CACHED_SOCKET_PATH;
183 connection = __open_cached_connection(¶ms);
184 if (connection == NULL) {
185 free(cache_data->key);
189 buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
190 buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
191 memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
198 res = cache_info->marshal_func(buffer, &size, retval, ap_new,
202 if (res == NS_RETURN) {
203 if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
207 buffer = (char *)realloc(buffer, buffer_size);
208 memset(buffer, 0, buffer_size);
210 } while (res == NS_RETURN);
212 if (res != NS_SUCCESS) {
213 __close_cached_connection(connection);
214 free(cache_data->key);
219 res = __cached_write(connection, cache_info->entry_name,
220 cache_data->key, cache_data->key_size, buffer, buffer_size);
221 __close_cached_connection(connection);
223 free(cache_data->key);
226 return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
230 __nss_common_cache_write_negative(void *mdata)
232 struct cached_connection_params params;
233 cached_connection connection;
236 nss_cache_info const *cache_info;
237 nss_cache_data *cache_data;
239 cache_data = (nss_cache_data *)mdata;
240 cache_info = cache_data->info;
242 if (cache_data->key == NULL)
245 memset(¶ms, 0, sizeof(struct cached_connection_params));
246 params.socket_path = CACHED_SOCKET_PATH;
248 connection = __open_cached_connection(¶ms);
249 if (connection == NULL) {
250 free(cache_data->key);
254 res = __cached_write(connection, cache_info->entry_name,
255 cache_data->key, cache_data->key_size, NULL, 0);
256 __close_cached_connection(connection);
258 free(cache_data->key);
259 return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
263 __nss_mp_cache_read(void *retval, void *mdata, va_list ap)
265 struct cached_connection_params params;
266 cached_mp_read_session rs;
271 nss_cache_info const *cache_info;
272 nss_cache_data *cache_data;
276 cache_data = (nss_cache_data *)mdata;
277 cache_info = cache_data->info;
279 if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION)
282 rs = cache_info->get_mp_rs_func();
283 if (rs == INVALID_CACHED_MP_READ_SESSION) {
284 memset(¶ms, 0, sizeof(struct cached_connection_params));
285 params.socket_path = CACHED_SOCKET_PATH;
287 rs = __open_cached_mp_read_session(¶ms,
288 cache_info->entry_name);
289 if (rs == INVALID_CACHED_MP_READ_SESSION)
292 cache_info->set_mp_rs_func(rs);
295 buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
296 buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
297 memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
300 res = __cached_mp_read(rs, buffer, &buffer_size);
301 if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
302 buffer = (char *)realloc(buffer, buffer_size);
303 memset(buffer, 0, buffer_size);
309 res = cache_info->unmarshal_func(buffer, buffer_size, retval,
310 ap_new, cache_info->mdata);
313 if (res != NS_SUCCESS) {
320 __close_cached_mp_read_session(rs);
321 rs = INVALID_CACHED_MP_READ_SESSION;
322 cache_info->set_mp_rs_func(rs);
323 return (res == -1 ? NS_RETURN : NS_UNAVAIL);
327 return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
331 __nss_mp_cache_write(void *retval, void *mdata, va_list ap)
333 struct cached_connection_params params;
334 cached_mp_write_session ws;
339 nss_cache_info const *cache_info;
340 nss_cache_data *cache_data;
344 cache_data = (nss_cache_data *)mdata;
345 cache_info = cache_data->info;
347 ws = cache_info->get_mp_ws_func();
348 if (ws == INVALID_CACHED_MP_WRITE_SESSION) {
349 memset(¶ms, 0, sizeof(struct cached_connection_params));
350 params.socket_path = CACHED_SOCKET_PATH;
352 ws = __open_cached_mp_write_session(¶ms,
353 cache_info->entry_name);
354 if (ws == INVALID_CACHED_MP_WRITE_SESSION)
357 cache_info->set_mp_ws_func(ws);
360 buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
361 buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
362 memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
369 res = cache_info->marshal_func(buffer, &size, retval, ap_new,
373 if (res == NS_RETURN) {
374 if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
378 buffer = (char *)realloc(buffer, buffer_size);
379 memset(buffer, 0, buffer_size);
381 } while (res == NS_RETURN);
383 if (res != NS_SUCCESS) {
388 res = __cached_mp_write(ws, buffer, buffer_size);
391 return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
395 __nss_mp_cache_write_submit(void *retval, void *mdata, va_list ap)
397 cached_mp_write_session ws;
399 nss_cache_info const *cache_info;
400 nss_cache_data *cache_data;
402 cache_data = (nss_cache_data *)mdata;
403 cache_info = cache_data->info;
405 ws = cache_info->get_mp_ws_func();
406 if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
407 __close_cached_mp_write_session(ws);
408 ws = INVALID_CACHED_MP_WRITE_SESSION;
409 cache_info->set_mp_ws_func(ws);
415 __nss_mp_cache_end(void *retval, void *mdata, va_list ap)
417 cached_mp_write_session ws;
418 cached_mp_read_session rs;
420 nss_cache_info const *cache_info;
421 nss_cache_data *cache_data;
423 cache_data = (nss_cache_data *)mdata;
424 cache_info = cache_data->info;
426 ws = cache_info->get_mp_ws_func();
427 if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
428 __abandon_cached_mp_write_session(ws);
429 ws = INVALID_CACHED_MP_WRITE_SESSION;
430 cache_info->set_mp_ws_func(ws);
433 rs = cache_info->get_mp_rs_func();
434 if (rs != INVALID_CACHED_MP_READ_SESSION) {
435 __close_cached_mp_read_session(rs);
436 rs = INVALID_CACHED_MP_READ_SESSION;
437 cache_info->set_mp_rs_func(rs);