taskqueue.9: Do some mdoc cleanup & add missing MLINKS.
[dragonfly.git] / lib / libc / net / nscache.c
blob81baa4df97cdd2db6e86bcb914d1cbc29bd96359
1 /*-
2 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
24 * SUCH DAMAGE.
26 * $FreeBSD: src/lib/libc/net/nscache.c,v 1.2 2007/10/17 23:20:49 tmclaugh Exp $
29 #include "namespace.h"
30 #include <nsswitch.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include "un-namespace.h"
34 #include "nscachedcli.h"
35 #include "nscache.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"
45 int
46 __nss_cache_handler(void *retval, void *mdata, va_list ap)
48 return (NS_UNAVAIL);
51 int
52 __nss_common_cache_read(void *retval, void *mdata, va_list ap)
54 struct cached_connection_params params;
55 cached_connection connection;
57 char *buffer;
58 size_t buffer_size, size;
60 nss_cache_info const *cache_info;
61 nss_cache_data *cache_data;
62 va_list ap_new;
63 int res;
65 cache_data = (nss_cache_data *)mdata;
66 cache_info = cache_data->info;
68 memset(&params, 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;
74 va_copy(ap_new, ap);
76 do {
77 size = cache_data->key_size;
78 res = cache_info->id_func(cache_data->key, &size, ap_new,
79 cache_info->mdata);
80 va_end(ap_new);
81 if (res == NS_RETURN) {
82 if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT)
83 break;
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);
89 va_copy(ap_new, ap);
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;
97 return (res);
98 } else
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);
105 do {
106 connection = __open_cached_connection(&params);
107 if (connection == NULL) {
108 res = -1;
109 break;
111 res = __cached_read(connection, cache_info->entry_name,
112 cache_data->key, cache_data->key_size, buffer,
113 &buffer_size);
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);
119 } while (res == -2);
121 if (res == 0) {
122 if (buffer_size == 0) {
123 free(buffer);
124 free(cache_data->key);
125 cache_data->key = NULL;
126 cache_data->key_size = 0;
127 return (NS_RETURN);
130 va_copy(ap_new, ap);
131 res = cache_info->unmarshal_func(buffer, buffer_size, retval,
132 ap_new, cache_info->mdata);
133 va_end(ap_new);
135 if (res != NS_SUCCESS) {
136 free(buffer);
137 free(cache_data->key);
138 cache_data->key = NULL;
139 cache_data->key_size = 0;
140 return (res);
141 } else
142 res = 0;
145 if (res == 0) {
146 free(cache_data->key);
147 cache_data->key = NULL;
148 cache_data->key_size = 0;
151 free(buffer);
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;
161 char *buffer;
162 size_t buffer_size;
164 nss_cache_info const *cache_info;
165 nss_cache_data *cache_data;
166 va_list ap_new;
167 int res;
169 cache_data = (nss_cache_data *)mdata;
170 cache_info = cache_data->info;
172 if (cache_data->key == NULL)
173 return (NS_UNAVAIL);
175 memset(&params, 0, sizeof(struct cached_connection_params));
176 params.socket_path = CACHED_SOCKET_PATH;
178 connection = __open_cached_connection(&params);
179 if (connection == NULL) {
180 free(cache_data->key);
181 return (NS_UNAVAIL);
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);
188 do {
189 size_t size;
191 size = buffer_size;
192 va_copy(ap_new, ap);
193 res = cache_info->marshal_func(buffer, &size, retval, ap_new,
194 cache_info->mdata);
195 va_end(ap_new);
197 if (res == NS_RETURN) {
198 if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
199 break;
201 buffer_size <<= 1;
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);
210 free(buffer);
211 return (res);
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);
219 free(buffer);
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;
229 int res;
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)
238 return (NS_UNAVAIL);
240 memset(&params, 0, sizeof(struct cached_connection_params));
241 params.socket_path = CACHED_SOCKET_PATH;
243 connection = __open_cached_connection(&params);
244 if (connection == NULL) {
245 free(cache_data->key);
246 return (NS_UNAVAIL);
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;
263 char *buffer;
264 size_t buffer_size;
266 nss_cache_info const *cache_info;
267 nss_cache_data *cache_data;
268 va_list ap_new;
269 int res;
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)
275 return (NS_UNAVAIL);
277 rs = cache_info->get_mp_rs_func();
278 if (rs == INVALID_CACHED_MP_READ_SESSION) {
279 memset(&params, 0, sizeof(struct cached_connection_params));
280 params.socket_path = CACHED_SOCKET_PATH;
282 rs = __open_cached_mp_read_session(&params,
283 cache_info->entry_name);
284 if (rs == INVALID_CACHED_MP_READ_SESSION)
285 return (NS_UNAVAIL);
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);
294 do {
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);
300 } while (res == -2);
302 if (res == 0) {
303 va_copy(ap_new, ap);
304 res = cache_info->unmarshal_func(buffer, buffer_size, retval,
305 ap_new, cache_info->mdata);
306 va_end(ap_new);
308 if (res != NS_SUCCESS) {
309 free(buffer);
310 return (res);
311 } else
312 res = 0;
313 } else {
314 free(buffer);
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);
321 free(buffer);
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;
331 char *buffer;
332 size_t buffer_size;
334 nss_cache_info const *cache_info;
335 nss_cache_data *cache_data;
336 va_list ap_new;
337 int res;
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(&params, 0, sizeof(struct cached_connection_params));
345 params.socket_path = CACHED_SOCKET_PATH;
347 ws = __open_cached_mp_write_session(&params,
348 cache_info->entry_name);
349 if (ws == INVALID_CACHED_MP_WRITE_SESSION)
350 return (NS_UNAVAIL);
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);
359 do {
360 size_t size;
362 size = buffer_size;
363 va_copy(ap_new, ap);
364 res = cache_info->marshal_func(buffer, &size, retval, ap_new,
365 cache_info->mdata);
366 va_end(ap_new);
368 if (res == NS_RETURN) {
369 if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
370 break;
372 buffer_size <<= 1;
373 buffer = (char *)realloc(buffer, buffer_size);
374 memset(buffer, 0, buffer_size);
376 } while (res == NS_RETURN);
378 if (res != NS_SUCCESS) {
379 free(buffer);
380 return (res);
383 res = __cached_mp_write(ws, buffer, buffer_size);
385 free(buffer);
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);
406 return (NS_UNAVAIL);
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);
435 return (NS_UNAVAIL);