nscache.c revision 158115
1158115Sume/*- 2158115Sume * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru> 3158115Sume * All rights reserved. 4158115Sume * 5158115Sume * Redistribution and use in source and binary forms, with or without 6158115Sume * modification, are permitted provided that the following conditions 7158115Sume * are met: 8158115Sume * 1. Redistributions of source code must retain the above copyright 9158115Sume * notice, this list of conditions and the following disclaimer. 10158115Sume * 2. Redistributions in binary form must reproduce the above copyright 11158115Sume * notice, this list of conditions and the following disclaimer in the 12158115Sume * documentation and/or other materials provided with the distribution. 13158115Sume * 14158115Sume * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15158115Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16158115Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17158115Sume * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18158115Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19158115Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20158115Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21158115Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22158115Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23158115Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24158115Sume * SUCH DAMAGE. 25158115Sume * 26158115Sume */ 27158115Sume 28158115Sume#include <sys/cdefs.h> 29158115Sume__FBSDID("$FreeBSD: head/lib/libc/net/nscache.c 158115 2006-04-28 12:03:38Z ume $"); 30158115Sume 31158115Sume#include "namespace.h" 32158115Sume#include <nsswitch.h> 33158115Sume#include <stdlib.h> 34158115Sume#include <string.h> 35158115Sume#include "un-namespace.h" 36158115Sume#include "nscachedcli.h" 37158115Sume#include "nscache.h" 38158115Sume 39158115Sume#define NSS_CACHE_KEY_INITIAL_SIZE (256) 40158115Sume#define NSS_CACHE_KEY_SIZE_LIMIT (NSS_CACHE_KEY_INITIAL_SIZE << 4) 41158115Sume 42158115Sume#define NSS_CACHE_BUFFER_INITIAL_SIZE (1024) 43158115Sume#define NSS_CACHE_BUFFER_SIZE_LIMIT (NSS_CACHE_BUFFER_INITIAL_SIZE << 8) 44158115Sume 45158115Sume#define CACHED_SOCKET_PATH "/var/run/cached" 46158115Sume 47158115Sumeint 48158115Sume__nss_cache_handler(void *retval, void *mdata, va_list ap) 49158115Sume{ 50158115Sume return (NS_UNAVAIL); 51158115Sume} 52158115Sume 53158115Sumeint 54158115Sume__nss_common_cache_read(void *retval, void *mdata, va_list ap) 55158115Sume{ 56158115Sume struct cached_connection_params params; 57158115Sume cached_connection connection; 58158115Sume 59158115Sume char *buffer; 60158115Sume size_t buffer_size, size; 61158115Sume 62158115Sume nss_cache_info const *cache_info; 63158115Sume nss_cache_data *cache_data; 64158115Sume va_list ap_new; 65158115Sume int res; 66158115Sume 67158115Sume cache_data = (nss_cache_data *)mdata; 68158115Sume cache_info = cache_data->info; 69158115Sume 70158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 71158115Sume params.socket_path = CACHED_SOCKET_PATH; 72158115Sume 73158115Sume cache_data->key = (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE); 74158115Sume memset(cache_data->key, 0, NSS_CACHE_KEY_INITIAL_SIZE); 75158115Sume cache_data->key_size = NSS_CACHE_KEY_INITIAL_SIZE; 76158115Sume va_copy(ap_new, ap); 77158115Sume 78158115Sume do { 79158115Sume size = cache_data->key_size; 80158115Sume res = cache_info->id_func(cache_data->key, &size, ap_new, 81158115Sume cache_info->mdata); 82158115Sume va_end(ap_new); 83158115Sume if (res == NS_RETURN) { 84158115Sume if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT) 85158115Sume break; 86158115Sume 87158115Sume cache_data->key_size <<= 1; 88158115Sume cache_data->key = realloc(cache_data->key, 89158115Sume cache_data->key_size); 90158115Sume memset(cache_data->key, 0, cache_data->key_size); 91158115Sume va_copy(ap_new, ap); 92158115Sume } 93158115Sume } while (res == NS_RETURN); 94158115Sume 95158115Sume if (res != NS_SUCCESS) { 96158115Sume free(cache_data->key); 97158115Sume cache_data->key = NULL; 98158115Sume cache_data->key_size = 0; 99158115Sume return (res); 100158115Sume } else 101158115Sume cache_data->key_size = size; 102158115Sume 103158115Sume buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE; 104158115Sume buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE); 105158115Sume memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE); 106158115Sume 107158115Sume do { 108158115Sume connection = __open_cached_connection(¶ms); 109158115Sume if (connection == NULL) { 110158115Sume res = -1; 111158115Sume break; 112158115Sume } 113158115Sume res = __cached_read(connection, cache_info->entry_name, 114158115Sume cache_data->key, cache_data->key_size, buffer, 115158115Sume &buffer_size); 116158115Sume __close_cached_connection(connection); 117158115Sume if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) { 118158115Sume buffer = (char *)realloc(buffer, buffer_size); 119158115Sume memset(buffer, 0, buffer_size); 120158115Sume } 121158115Sume } while (res == -2); 122158115Sume 123158115Sume if (res == 0) { 124158115Sume if (buffer_size == 0) { 125158115Sume free(buffer); 126158115Sume free(cache_data->key); 127158115Sume cache_data->key = NULL; 128158115Sume cache_data->key_size = 0; 129158115Sume return (NS_RETURN); 130158115Sume } 131158115Sume 132158115Sume va_copy(ap_new, ap); 133158115Sume res = cache_info->unmarshal_func(buffer, buffer_size, retval, 134158115Sume ap_new, cache_info->mdata); 135158115Sume va_end(ap_new); 136158115Sume 137158115Sume if (res != NS_SUCCESS) { 138158115Sume free(buffer); 139158115Sume free(cache_data->key); 140158115Sume cache_data->key = NULL; 141158115Sume cache_data->key_size = 0; 142158115Sume return (res); 143158115Sume } else 144158115Sume res = 0; 145158115Sume } 146158115Sume 147158115Sume if (res == 0) { 148158115Sume free(cache_data->key); 149158115Sume cache_data->key = NULL; 150158115Sume cache_data->key_size = 0; 151158115Sume } 152158115Sume 153158115Sume free(buffer); 154158115Sume return (res == 0 ? NS_SUCCESS : NS_NOTFOUND); 155158115Sume} 156158115Sume 157158115Sumeint 158158115Sume__nss_common_cache_write(void *retval, void *mdata, va_list ap) 159158115Sume{ 160158115Sume struct cached_connection_params params; 161158115Sume cached_connection connection; 162158115Sume 163158115Sume char *buffer; 164158115Sume size_t buffer_size; 165158115Sume 166158115Sume nss_cache_info const *cache_info; 167158115Sume nss_cache_data *cache_data; 168158115Sume va_list ap_new; 169158115Sume int res; 170158115Sume 171158115Sume cache_data = (nss_cache_data *)mdata; 172158115Sume cache_info = cache_data->info; 173158115Sume 174158115Sume if (cache_data->key == NULL) 175158115Sume return (NS_UNAVAIL); 176158115Sume 177158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 178158115Sume params.socket_path = CACHED_SOCKET_PATH; 179158115Sume 180158115Sume connection = __open_cached_connection(¶ms); 181158115Sume if (connection == NULL) { 182158115Sume free(cache_data->key); 183158115Sume return (NS_UNAVAIL); 184158115Sume } 185158115Sume 186158115Sume buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE; 187158115Sume buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE); 188158115Sume memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE); 189158115Sume 190158115Sume do { 191158115Sume size_t size; 192158115Sume 193158115Sume size = buffer_size; 194158115Sume va_copy(ap_new, ap); 195158115Sume res = cache_info->marshal_func(buffer, &size, retval, ap_new, 196158115Sume cache_info->mdata); 197158115Sume va_end(ap_new); 198158115Sume 199158115Sume if (res == NS_RETURN) { 200158115Sume if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT) 201158115Sume break; 202158115Sume 203158115Sume buffer_size <<= 1; 204158115Sume buffer = (char *)realloc(buffer, buffer_size); 205158115Sume memset(buffer, 0, buffer_size); 206158115Sume } 207158115Sume } while (res == NS_RETURN); 208158115Sume 209158115Sume if (res != NS_SUCCESS) { 210158115Sume __close_cached_connection(connection); 211158115Sume free(cache_data->key); 212158115Sume free(buffer); 213158115Sume return (res); 214158115Sume } 215158115Sume 216158115Sume res = __cached_write(connection, cache_info->entry_name, 217158115Sume cache_data->key, cache_data->key_size, buffer, buffer_size); 218158115Sume __close_cached_connection(connection); 219158115Sume 220158115Sume free(cache_data->key); 221158115Sume free(buffer); 222158115Sume 223158115Sume return (res == 0 ? NS_SUCCESS : NS_UNAVAIL); 224158115Sume} 225158115Sume 226158115Sumeint 227158115Sume__nss_common_cache_write_negative(void *mdata) 228158115Sume{ 229158115Sume struct cached_connection_params params; 230158115Sume cached_connection connection; 231158115Sume int res; 232158115Sume 233158115Sume nss_cache_info const *cache_info; 234158115Sume nss_cache_data *cache_data; 235158115Sume 236158115Sume cache_data = (nss_cache_data *)mdata; 237158115Sume cache_info = cache_data->info; 238158115Sume 239158115Sume if (cache_data->key == NULL) 240158115Sume return (NS_UNAVAIL); 241158115Sume 242158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 243158115Sume params.socket_path = CACHED_SOCKET_PATH; 244158115Sume 245158115Sume connection = __open_cached_connection(¶ms); 246158115Sume if (connection == NULL) { 247158115Sume free(cache_data->key); 248158115Sume return (NS_UNAVAIL); 249158115Sume } 250158115Sume 251158115Sume res = __cached_write(connection, cache_info->entry_name, 252158115Sume cache_data->key, cache_data->key_size, NULL, 0); 253158115Sume __close_cached_connection(connection); 254158115Sume 255158115Sume free(cache_data->key); 256158115Sume return (res == 0 ? NS_SUCCESS : NS_UNAVAIL); 257158115Sume} 258158115Sume 259158115Sumeint 260158115Sume__nss_mp_cache_read(void *retval, void *mdata, va_list ap) 261158115Sume{ 262158115Sume struct cached_connection_params params; 263158115Sume cached_mp_read_session rs; 264158115Sume 265158115Sume char *buffer; 266158115Sume size_t buffer_size; 267158115Sume 268158115Sume nss_cache_info const *cache_info; 269158115Sume nss_cache_data *cache_data; 270158115Sume va_list ap_new; 271158115Sume int res; 272158115Sume 273158115Sume cache_data = (nss_cache_data *)mdata; 274158115Sume cache_info = cache_data->info; 275158115Sume 276158115Sume if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION) 277158115Sume return (NS_UNAVAIL); 278158115Sume 279158115Sume rs = cache_info->get_mp_rs_func(); 280158115Sume if (rs == INVALID_CACHED_MP_READ_SESSION) { 281158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 282158115Sume params.socket_path = CACHED_SOCKET_PATH; 283158115Sume 284158115Sume rs = __open_cached_mp_read_session(¶ms, 285158115Sume cache_info->entry_name); 286158115Sume if (rs == INVALID_CACHED_MP_READ_SESSION) 287158115Sume return (NS_UNAVAIL); 288158115Sume 289158115Sume cache_info->set_mp_rs_func(rs); 290158115Sume } 291158115Sume 292158115Sume buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE; 293158115Sume buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE); 294158115Sume memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE); 295158115Sume 296158115Sume do { 297158115Sume res = __cached_mp_read(rs, buffer, &buffer_size); 298158115Sume if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) { 299158115Sume buffer = (char *)realloc(buffer, buffer_size); 300158115Sume memset(buffer, 0, buffer_size); 301158115Sume } 302158115Sume } while (res == -2); 303158115Sume 304158115Sume if (res == 0) { 305158115Sume va_copy(ap_new, ap); 306158115Sume res = cache_info->unmarshal_func(buffer, buffer_size, retval, 307158115Sume ap_new, cache_info->mdata); 308158115Sume va_end(ap_new); 309158115Sume 310158115Sume if (res != NS_SUCCESS) { 311158115Sume free(buffer); 312158115Sume return (res); 313158115Sume } else 314158115Sume res = 0; 315158115Sume } else { 316158115Sume free(buffer); 317158115Sume __close_cached_mp_read_session(rs); 318158115Sume rs = INVALID_CACHED_MP_READ_SESSION; 319158115Sume cache_info->set_mp_rs_func(rs); 320158115Sume return (res == -1 ? NS_RETURN : NS_UNAVAIL); 321158115Sume } 322158115Sume 323158115Sume free(buffer); 324158115Sume return (res == 0 ? NS_SUCCESS : NS_NOTFOUND); 325158115Sume} 326158115Sume 327158115Sumeint 328158115Sume__nss_mp_cache_write(void *retval, void *mdata, va_list ap) 329158115Sume{ 330158115Sume struct cached_connection_params params; 331158115Sume cached_mp_write_session ws; 332158115Sume 333158115Sume char *buffer; 334158115Sume size_t buffer_size; 335158115Sume 336158115Sume nss_cache_info const *cache_info; 337158115Sume nss_cache_data *cache_data; 338158115Sume va_list ap_new; 339158115Sume int res; 340158115Sume 341158115Sume cache_data = (nss_cache_data *)mdata; 342158115Sume cache_info = cache_data->info; 343158115Sume 344158115Sume ws = cache_info->get_mp_ws_func(); 345158115Sume if (ws == INVALID_CACHED_MP_WRITE_SESSION) { 346158115Sume memset(¶ms, 0, sizeof(struct cached_connection_params)); 347158115Sume params.socket_path = CACHED_SOCKET_PATH; 348158115Sume 349158115Sume ws = __open_cached_mp_write_session(¶ms, 350158115Sume cache_info->entry_name); 351158115Sume if (ws == INVALID_CACHED_MP_WRITE_SESSION) 352158115Sume return (NS_UNAVAIL); 353158115Sume 354158115Sume cache_info->set_mp_ws_func(ws); 355158115Sume } 356158115Sume 357158115Sume buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE; 358158115Sume buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE); 359158115Sume memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE); 360158115Sume 361158115Sume do { 362158115Sume size_t size; 363158115Sume 364158115Sume size = buffer_size; 365158115Sume va_copy(ap_new, ap); 366158115Sume res = cache_info->marshal_func(buffer, &size, retval, ap_new, 367158115Sume cache_info->mdata); 368158115Sume va_end(ap_new); 369158115Sume 370158115Sume if (res == NS_RETURN) { 371158115Sume if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT) 372158115Sume break; 373158115Sume 374158115Sume buffer_size <<= 1; 375158115Sume buffer = (char *)realloc(buffer, buffer_size); 376158115Sume memset(buffer, 0, buffer_size); 377158115Sume } 378158115Sume } while (res == NS_RETURN); 379158115Sume 380158115Sume if (res != NS_SUCCESS) { 381158115Sume free(buffer); 382158115Sume return (res); 383158115Sume } 384158115Sume 385158115Sume res = __cached_mp_write(ws, buffer, buffer_size); 386158115Sume 387158115Sume free(buffer); 388158115Sume return (res == 0 ? NS_SUCCESS : NS_UNAVAIL); 389158115Sume} 390158115Sume 391158115Sumeint 392158115Sume__nss_mp_cache_write_submit(void *retval, void *mdata, va_list ap) 393158115Sume{ 394158115Sume cached_mp_write_session ws; 395158115Sume 396158115Sume nss_cache_info const *cache_info; 397158115Sume nss_cache_data *cache_data; 398158115Sume 399158115Sume cache_data = (nss_cache_data *)mdata; 400158115Sume cache_info = cache_data->info; 401158115Sume 402158115Sume ws = cache_info->get_mp_ws_func(); 403158115Sume if (ws != INVALID_CACHED_MP_WRITE_SESSION) { 404158115Sume __close_cached_mp_write_session(ws); 405158115Sume ws = INVALID_CACHED_MP_WRITE_SESSION; 406158115Sume cache_info->set_mp_ws_func(ws); 407158115Sume } 408158115Sume return (NS_UNAVAIL); 409158115Sume} 410158115Sume 411158115Sumeint 412158115Sume__nss_mp_cache_end(void *retval, void *mdata, va_list ap) 413158115Sume{ 414158115Sume cached_mp_write_session ws; 415158115Sume cached_mp_read_session rs; 416158115Sume 417158115Sume nss_cache_info const *cache_info; 418158115Sume nss_cache_data *cache_data; 419158115Sume 420158115Sume cache_data = (nss_cache_data *)mdata; 421158115Sume cache_info = cache_data->info; 422158115Sume 423158115Sume ws = cache_info->get_mp_ws_func(); 424158115Sume if (ws != INVALID_CACHED_MP_WRITE_SESSION) { 425158115Sume __abandon_cached_mp_write_session(ws); 426158115Sume ws = INVALID_CACHED_MP_WRITE_SESSION; 427158115Sume cache_info->set_mp_ws_func(ws); 428158115Sume } 429158115Sume 430158115Sume rs = cache_info->get_mp_rs_func(); 431158115Sume if (rs != INVALID_CACHED_MP_READ_SESSION) { 432158115Sume __close_cached_mp_read_session(rs); 433158115Sume rs = INVALID_CACHED_MP_READ_SESSION; 434158115Sume cache_info->set_mp_rs_func(rs); 435158115Sume } 436158115Sume 437158115Sume return (NS_UNAVAIL); 438158115Sume} 439