Print this page
7126 NSS_XbyY_FINI has too much logic for a function-like macro
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libc/port/gen/nss_common.c
+++ new/usr/src/lib/libc/port/gen/nss_common.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Shared code used by the name-service-switch frontends (e.g. getpwnam_r())
29 29 */
30 30
31 31 #include "lint.h"
32 32 #include <mtlib.h>
33 33 #include <dlfcn.h>
34 34 #include <atomic.h>
35 35
36 36 #define __NSS_PRIVATE_INTERFACE
37 37 #include "nsswitch_priv.h"
38 38 #undef __NSS_PRIVATE_INTERFACE
39 39
40 40 #include <nss_common.h>
41 41 #include <nss_dbdefs.h>
42 42 #include <unistd.h>
43 43 #include <stdlib.h>
44 44 #include <stdio.h>
45 45 #include <string.h>
46 46 #include <thread.h>
47 47 #include <synch.h>
48 48 #include <pthread.h>
49 49 #include <sys/types.h>
50 50 #include <sys/mman.h>
51 51 #include <errno.h>
52 52 #include "libc.h"
53 53 #include "tsd.h"
54 54
55 55 #include <getxby_door.h>
56 56
57 57 /*
58 58 * configurable values for default buffer sizes
59 59 */
60 60
61 61 /*
62 62 * PSARC/2005/133 updated the buffering mechanisms to handle
63 63 * up to 2^64 buffering. But sets a practical limit of 512*1024.
64 64 * The expectation is the practical limit will be dynamic from
65 65 * nscd. For now, set the group limit to this value.
66 66 */
67 67
68 68 #define NSS_BUFLEN_PRACTICAL (512*1024)
69 69
70 70 static size_t __nss_buflen_group = NSS_BUFLEN_PRACTICAL;
71 71 static size_t __nss_buflen_default = NSS_BUFLEN_DOOR;
72 72
73 73 /*
74 74 * policy component function interposing definitions:
75 75 * nscd if so desired can interpose it's own switch functions over
76 76 * the internal unlocked counterparts. This will allow nscd to replace
77 77 * the switch policy state engine with one that uses it's internal
78 78 * components.
79 79 * Only nscd can change this through it's use of nss_config.
80 80 * The golden rule is: ptr == NULL checking is used in the switch to
81 81 * see if a function was interposed. But nscd is responsible for seeing
82 82 * that mutex locking to change the values are observed when the data is
83 83 * changed. Especially if it happens > once. The switch does not lock
84 84 * the pointer with mutexs.
85 85 */
86 86
87 87 typedef struct {
88 88 void *p;
89 89 #if 0
90 90 void (*nss_delete_fp)(nss_db_root_t *rootp);
91 91 nss_status_t (*nss_search_fp)(nss_db_root_t *rootp,
92 92 nss_db_initf_t initf, int search_fnum,
93 93 void *search_args);
94 94 void (*nss_setent_u_fp)(nss_db_root_t *,
95 95 nss_db_initf_t, nss_getent_t *);
96 96 nss_status_t (*nss_getent_u_fp)(nss_db_root_t *,
97 97 nss_db_initf_t, nss_getent_t *, void *);
98 98 void (*nss_endent_u_fp)(nss_db_root_t *,
99 99 nss_db_initf_t, nss_getent_t *);
100 100 void (*end_iter_u_fp)(nss_db_root_t *rootp,
101 101 struct nss_getent_context *contextp);
102 102 #endif
103 103 } nss_policyf_t;
104 104
105 105 static mutex_t nss_policyf_lock = DEFAULTMUTEX;
106 106 static nss_policyf_t nss_policyf_ptrs =
107 107 { (void *)NULL };
108 108
109 109 /*
110 110 * nsswitch db_root state machine definitions:
111 111 * The golden rule is: if you hold a pointer to an nss_db_state struct and
112 112 * you don't hold the lock, you'd better have incremented the refcount
113 113 * while you held the lock; otherwise, it may vanish or change
114 114 * significantly when you least expect it.
115 115 *
116 116 * The pointer in nss_db_root_t is one such, so the reference count >= 1.
117 117 * Ditto the pointer in struct nss_getent_context.
118 118 */
119 119
120 120 /*
121 121 * State for one nsswitch database (e.g. "passwd", "hosts")
122 122 */
123 123 struct nss_db_state {
124 124 nss_db_root_t orphan_root; /* XXX explain */
125 125 unsigned refcount; /* One for the pointer in */
126 126 /* nss_db_root_t, plus one */
127 127 /* for each active thread. */
128 128 nss_db_params_t p;
129 129 struct __nsw_switchconfig_v1 *config;
130 130 int max_src; /* is == config->num_lookups */
131 131 struct nss_src_state *src; /* Pointer to array[max_src] */
132 132 };
133 133
134 134 /*
135 135 * State for one of the sources (e.g. "nis", "compat") for a database
136 136 */
137 137 struct nss_src_state {
138 138 struct __nsw_lookup_v1 *lkp;
139 139 int n_active;
140 140 int n_dormant;
141 141 int n_waiting; /* ... on wanna_be */
142 142 cond_t wanna_be;
143 143 union {
144 144 nss_backend_t *single; /* Efficiency hack for common case */
145 145 /* when limit_dead_backends == 1 */
146 146 nss_backend_t **multi; /* array[limit_dead_backends] of */
147 147 } dormant; /* pointers to dormant backends */
148 148 nss_backend_constr_t be_constr;
149 149 nss_backend_finder_t *finder;
150 150 void *finder_priv;
151 151 };
152 152
153 153 static struct nss_db_state *_nss_db_state_constr(nss_db_initf_t);
154 154 void _nss_db_state_destr(struct nss_db_state *);
155 155
156 156 /* ==== null definitions if !MTSAFE? Ditto lock field in nss_db_root_t */
157 157
158 158 #define NSS_ROOTLOCK(r, sp) (cancel_safe_mutex_lock(&(r)->lock), \
159 159 *(sp) = (r)->s)
160 160
161 161 #define NSS_UNLOCK(r) (cancel_safe_mutex_unlock(&(r)->lock))
162 162
163 163 #define NSS_CHECKROOT(rp, s) ((s) != (*(rp))->s && \
164 164 (cancel_safe_mutex_unlock(&(*(rp))->lock), \
165 165 cancel_safe_mutex_lock(&(s)->orphan_root.lock), \
166 166 *(rp) = &(s)->orphan_root))
167 167
168 168 #define NSS_RELOCK(rp, s) (cancel_safe_mutex_lock(&(*(rp))->lock), \
169 169 NSS_CHECKROOT(rp, s))
170 170
171 171 #define NSS_STATE_REF_u(s) (++(s)->refcount)
172 172
173 173 #define NSS_UNREF_UNLOCK(r, s) (--(s)->refcount != 0 \
174 174 ? ((void)NSS_UNLOCK(r)) \
175 175 : ((void)NSS_UNLOCK(r), (void)_nss_db_state_destr(s)))
176 176
177 177 #define NSS_LOCK_CHECK(r, f, sp) (NSS_ROOTLOCK((r), (sp)), \
178 178 *(sp) == 0 && \
179 179 (r->s = *(sp) = _nss_db_state_constr(f)))
180 180 /* === In the future, NSS_LOCK_CHECK() may also have to check that */
181 181 /* === the config info hasn't changed (by comparing version numbers) */
182 182
183 183
184 184 /*
185 185 * NSS_OPTIONS/NIS_OPTIONS environment varibles data definitions:
186 186 * This remains for backwards compatibility. But generally nscd will
187 187 * decide if/how this gets used.
188 188 */
189 189 static int checked_env = 0; /* protected by "rootlock" */
190 190
191 191 /* allowing __nss_debug_file to be set could be a security hole. */
192 192 FILE *__nss_debug_file = stdout;
193 193 int __nss_debug_eng_loop;
194 194
195 195 /* NIS_OPTIONS infrastructure (from linbsl/nis/cache/cache_api.cc) */
196 196 /* allowing __nis_debug_file to be set could be a security hole. */
197 197 FILE *__nis_debug_file = stdout;
198 198 int __nis_debug_bind;
199 199 int __nis_debug_rpc;
200 200 int __nis_debug_calls;
201 201 char *__nis_prefsrv;
202 202 char *__nis_preftype;
203 203 char *__nis_server; /* if set, use only this server for binding */
204 204
205 205 #define OPT_INT 1
206 206 #define OPT_STRING 2
207 207 #ifdef DEBUG
208 208 #define OPT_FILE 3
209 209 #endif
210 210
211 211 struct option {
212 212 char *name;
213 213 int type;
214 214 void *address;
215 215 };
216 216
217 217 static struct option nss_options[] = {
218 218 #ifdef DEBUG
219 219 /* allowing __nss_debug_file to be set could be a security hole. */
220 220 { "debug_file", OPT_FILE, &__nss_debug_file },
221 221 #endif
222 222 { "debug_eng_loop", OPT_INT, &__nss_debug_eng_loop },
223 223 { 0, 0, 0 },
224 224 };
225 225
226 226 static struct option nis_options[] = {
227 227 #ifdef DEBUG
228 228 /* allowing __nis_debug_file to be set could be a security hole. */
229 229 { "debug_file", OPT_FILE, &__nis_debug_file },
230 230 #endif
231 231 { "debug_bind", OPT_INT, &__nis_debug_bind },
232 232 { "debug_rpc", OPT_INT, &__nis_debug_rpc },
233 233 { "debug_calls", OPT_INT, &__nis_debug_calls },
234 234 { "server", OPT_STRING, &__nis_server },
235 235 { "pref_srvr", OPT_STRING, &__nis_prefsrv },
236 236 { "pref_type", OPT_STRING, &__nis_preftype },
237 237 { 0, 0, 0 },
238 238 };
239 239
240 240 /*
241 241 * switch configuration parameter "database" definitions:
242 242 * The switch maintains a simmple read/write parameter database
243 243 * that nscd and the switch components can use to communicate
244 244 * nscd data to other components for configuration or out of band
245 245 * [IE no in the context of a getXbyY or putXbyY operation] data.
246 246 * The data passed are pointers to a lock data buffer and a length.
247 247 * Use of this is treated as SunwPrivate between nscd and the switch
248 248 * unless other wise stated.
249 249 */
250 250
251 251 typedef struct nss_cfgparam {
252 252 char *name;
253 253 mutex_t *lock;
254 254 void *buffer;
255 255 size_t length;
256 256 } nss_cfgparam_t;
257 257
258 258 typedef struct nss_cfglist {
259 259 char *name;
260 260 nss_cfgparam_t *list;
261 261 int count;
262 262 int max;
263 263 } nss_cfglist_t;
264 264
265 265 #define NSS_CFG_INCR 16
266 266
267 267 static nss_cfglist_t *nss_cfg = NULL;
268 268 static int nss_cfgcount = 0;
269 269 static int nss_cfgmax = 0;
270 270 static mutex_t nss_cfglock = DEFAULTMUTEX;
271 271
272 272 static int nss_cfg_policy_init();
273 273
274 274 /*
275 275 * A config parameters are in the form component:parameter
276 276 * as in: nss:parameter - switch (internal FE/policy/BE) parameter
277 277 * nscd:param - nscd application parameter
278 278 * ldap:param - nss_ldap BE parameter
279 279 * passwd:param - get/put passwd FE parameter
280 280 */
281 281
282 282 #define NSS_CONFIG_BRK ':'
283 283
284 284 /*
285 285 * The policy components initial parameter list
286 286 */
287 287 static nss_config_t nss_policy_params[] = {
288 288 { "nss:policyfunc", NSS_CONFIG_ADD, &nss_policyf_lock,
289 289 (void *)&nss_policyf_ptrs, (size_t)sizeof (nss_policyf_t) },
290 290 { NULL, NSS_CONFIG_ADD, (mutex_t *)NULL, (void *)NULL, (size_t)0 },
291 291 };
292 292
293 293 /*
294 294 * NSS parameter configuration routines
295 295 */
296 296
297 297 /* compare config name (component:parameter) to a component name */
298 298 static int
299 299 nss_cfgcn_cmp(const char *cfgname, const char *compname)
300 300 {
301 301 char *c;
302 302 size_t len, len2;
303 303
304 304 /* this code assumes valid pointers */
305 305 if ((c = strchr(cfgname, NSS_CONFIG_BRK)) == NULL)
306 306 return (-1);
307 307 len = (size_t)(c - cfgname);
308 308 len2 = strlen(compname);
309 309 if (len2 != len)
310 310 return (-1);
311 311 return (strncmp(cfgname, compname, len));
312 312 }
313 313
314 314 /* init configuration arena */
315 315 static int
316 316 nss_cfg_init()
317 317 {
318 318 nss_cfglist_t *cfg;
319 319 int i;
320 320
321 321 /* First time caller? */
322 322 if (nss_cfg != NULL) {
323 323 membar_consumer();
324 324 return (0);
325 325 }
326 326
327 327 /* Initialize internal tables */
328 328 lmutex_lock(&nss_cfglock);
329 329 if (nss_cfg != NULL) {
330 330 lmutex_unlock(&nss_cfglock);
331 331 membar_consumer();
332 332 return (0);
333 333 }
334 334 cfg = libc_malloc(NSS_CFG_INCR * sizeof (nss_cfglist_t));
335 335 if (cfg == NULL) {
336 336 errno = ENOMEM;
337 337 lmutex_unlock(&nss_cfglock);
338 338 return (-1);
339 339 }
340 340 for (i = 0; i < NSS_CFG_INCR; i++) {
341 341 cfg[i].list = libc_malloc(
342 342 NSS_CFG_INCR * sizeof (nss_cfgparam_t));
343 343 if (cfg[i].list == NULL) {
344 344 while (--i >= 0)
345 345 libc_free(cfg[i].list);
346 346 libc_free(cfg);
347 347 errno = ENOMEM;
348 348 lmutex_unlock(&nss_cfglock);
349 349 return (-1);
350 350 }
351 351 cfg[i].max = NSS_CFG_INCR;
352 352 }
353 353 nss_cfgmax = NSS_CFG_INCR;
354 354 membar_producer();
355 355 nss_cfg = cfg;
356 356 lmutex_unlock(&nss_cfglock);
357 357
358 358 /* Initialize Policy Engine values */
359 359 if (nss_cfg_policy_init() < 0) {
360 360 return (-1);
361 361 }
362 362 return (0);
363 363 }
364 364
365 365 /* find the name'd component list - create it if non-existent */
366 366 static nss_cfglist_t *
367 367 nss_cfgcomp_get(char *name, int add)
368 368 {
369 369 nss_cfglist_t *next;
370 370 char *c;
371 371 int i, len;
372 372 size_t nsize;
373 373
374 374 /* Make sure system is init'd */
375 375 if (nss_cfg_init() < 0)
376 376 return ((nss_cfglist_t *)NULL);
377 377
378 378 /* and check component:name validity */
379 379 if (name == NULL || (c = strchr(name, NSS_CONFIG_BRK)) == NULL)
380 380 return ((nss_cfglist_t *)NULL);
381 381
382 382 lmutex_lock(&nss_cfglock);
383 383 next = nss_cfg;
384 384 for (i = 0; i < nss_cfgcount; i++) {
385 385 if (next->name && nss_cfgcn_cmp(name, next->name) == 0) {
386 386 lmutex_unlock(&nss_cfglock);
387 387 return (next);
388 388 }
389 389 next++;
390 390 }
391 391 if (!add) {
392 392 lmutex_unlock(&nss_cfglock);
393 393 return (NULL);
394 394 }
395 395
396 396 /* not found, create a fresh one */
397 397 if (nss_cfgcount >= nss_cfgmax) {
398 398 /* realloc first */
399 399 nsize = (nss_cfgmax + NSS_CFG_INCR) * sizeof (nss_cfgparam_t);
400 400 next = (nss_cfglist_t *)libc_realloc(nss_cfg, nsize);
401 401 if (next == NULL) {
402 402 errno = ENOMEM;
403 403 lmutex_unlock(&nss_cfglock);
404 404 return ((nss_cfglist_t *)NULL);
405 405 }
406 406 (void) memset((void *)(next + nss_cfgcount), '\0',
407 407 NSS_CFG_INCR * sizeof (nss_cfglist_t));
408 408 nss_cfgmax += NSS_CFG_INCR;
409 409 nss_cfg = next;
410 410 }
411 411 next = nss_cfg + nss_cfgcount;
412 412 len = (size_t)(c - name) + 1;
413 413 if ((next->name = libc_malloc(len)) == NULL) {
414 414 errno = ENOMEM;
415 415 lmutex_unlock(&nss_cfglock);
416 416 return ((nss_cfglist_t *)NULL);
417 417 }
418 418 nss_cfgcount++;
419 419 (void) strlcpy(next->name, name, len);
420 420 lmutex_unlock(&nss_cfglock);
421 421 return (next);
422 422 }
423 423
424 424 /* find the name'd parameter - create it if non-existent */
425 425 static nss_cfgparam_t *
426 426 nss_cfgparam_get(char *name, int add)
427 427 {
428 428 nss_cfglist_t *comp;
429 429 nss_cfgparam_t *next;
430 430 int count, i;
431 431 size_t nsize;
432 432
433 433 if ((comp = nss_cfgcomp_get(name, add)) == NULL)
434 434 return ((nss_cfgparam_t *)NULL);
435 435 lmutex_lock(&nss_cfglock);
436 436 count = comp->count;
437 437 next = comp->list;
438 438 for (i = 0; i < count; i++) {
439 439 if (next->name && strcmp(name, next->name) == 0) {
440 440 lmutex_unlock(&nss_cfglock);
441 441 return (next);
442 442 }
443 443 next++;
444 444 }
445 445 if (!add) {
446 446 lmutex_unlock(&nss_cfglock);
447 447 return (NULL);
448 448 }
449 449
450 450 /* not found, create a fresh one */
451 451 if (count >= comp->max) {
452 452 /* realloc first */
453 453 nsize = (comp->max + NSS_CFG_INCR) * sizeof (nss_cfgparam_t);
454 454 next = (nss_cfgparam_t *)libc_realloc(comp->list, nsize);
455 455 if (next == NULL) {
456 456 errno = ENOMEM;
457 457 lmutex_unlock(&nss_cfglock);
458 458 return ((nss_cfgparam_t *)NULL);
459 459 }
460 460 comp->max += NSS_CFG_INCR;
461 461 comp->list = next;
462 462 }
463 463 next = comp->list + comp->count;
464 464 if ((next->name = libc_strdup(name)) == NULL) {
465 465 errno = ENOMEM;
466 466 lmutex_unlock(&nss_cfglock);
467 467 return ((nss_cfgparam_t *)NULL);
468 468 }
469 469 comp->count++;
470 470 lmutex_unlock(&nss_cfglock);
471 471 return (next);
472 472 }
473 473
474 474 /* find the name'd parameter - delete it if it exists */
475 475 static void
476 476 nss_cfg_del(nss_config_t *cfgp)
477 477 {
478 478 char *name;
479 479 nss_cfglist_t *comp;
480 480 nss_cfgparam_t *next, *cur;
481 481 int count, i, j;
482 482
483 483 /* exit if component name does not already exist */
484 484 if ((name = cfgp->name) == NULL ||
485 485 (comp = nss_cfgcomp_get(name, 0)) == NULL)
486 486 return;
487 487
488 488 /* find it */
489 489 lmutex_lock(&nss_cfglock);
490 490 count = comp->count;
491 491 next = comp->list;
492 492 for (i = 0; i < count; i++) {
493 493 if (next->name && strcmp(name, next->name) == 0) {
494 494 break; /* found it... */
495 495 }
496 496 next++;
497 497 }
498 498 if (i >= count) {
499 499 /* not found, already deleted */
500 500 lmutex_unlock(&nss_cfglock);
501 501 return;
502 502 }
503 503
504 504 /* copy down the remaining parameters, and clean up */
505 505 /* don't try to clean up component tables */
506 506 cur = next;
507 507 next++;
508 508 for (j = i+1; j < count; j++) {
509 509 *cur = *next;
510 510 cur++;
511 511 next++;
512 512 }
513 513 /* erase the last one */
514 514 if (cur->name) {
515 515 libc_free(cur->name);
516 516 cur->name = (char *)NULL;
517 517 }
518 518 cur->lock = (mutex_t *)NULL;
519 519 cur->buffer = (void *)NULL;
520 520 cur->length = 0;
521 521 comp->count--;
522 522 lmutex_unlock(&nss_cfglock);
523 523 }
524 524
525 525 static int
526 526 nss_cfg_get(nss_config_t *next)
527 527 {
528 528 nss_cfgparam_t *param;
529 529
530 530 errno = 0;
531 531 if ((param = nss_cfgparam_get(next->name, 0)) == NULL)
532 532 return (-1);
533 533 next->lock = param->lock;
534 534 next->buffer = param->buffer;
535 535 next->length = param->length;
536 536 return (0);
537 537 }
538 538
539 539 static int
540 540 nss_cfg_put(nss_config_t *next, int add)
541 541 {
542 542 nss_cfgparam_t *param;
543 543
544 544 errno = 0;
545 545 if ((param = nss_cfgparam_get(next->name, add)) == NULL)
546 546 return (-1);
547 547 param->lock = next->lock;
548 548 param->buffer = next->buffer;
549 549 param->length = next->length;
550 550 return (0);
551 551 }
552 552
553 553 /*
554 554 * Policy engine configurator - set and get interface
555 555 * argument is a NULL terminated list of set/get requests
556 556 * with input/result buffers and lengths. nss_cname is the
557 557 * specifier of a set or get operation and the property being
558 558 * managed. The intent is limited functions and expandability.
559 559 */
560 560
561 561 nss_status_t
562 562 nss_config(nss_config_t **plist, int cnt)
563 563 {
564 564 nss_config_t *next;
565 565 int i;
566 566
567 567 /* interface is only available to nscd */
568 568 if (_nsc_proc_is_cache() <= 0) {
569 569 return (NSS_UNAVAIL);
570 570 }
571 571 if (plist == NULL || cnt <= 0)
572 572 return (NSS_SUCCESS);
573 573 for (i = 0; i < cnt; i++) {
574 574 next = plist[i];
575 575 if (next == NULL)
576 576 break;
577 577 if (next->name == NULL) {
578 578 errno = EFAULT;
579 579 return (NSS_ERROR);
580 580 }
581 581 switch (next->cop) {
582 582 case NSS_CONFIG_GET:
583 583 /* get current lock/buffer/length fields */
584 584 if (nss_cfg_get(next) < 0) {
585 585 return (NSS_ERROR);
586 586 }
587 587 break;
588 588 case NSS_CONFIG_PUT:
589 589 /* set new lock/buffer/length fields */
590 590 if (nss_cfg_put(next, 0) < 0) {
591 591 return (NSS_ERROR);
592 592 }
593 593 break;
594 594 case NSS_CONFIG_ADD:
595 595 /* add parameter & set new lock/buffer/length fields */
596 596 if (nss_cfg_put(next, 1) < 0) {
597 597 return (NSS_ERROR);
598 598 }
599 599 break;
600 600 case NSS_CONFIG_DELETE:
601 601 /* delete parameter - should always work... */
602 602 nss_cfg_del(next);
603 603 break;
604 604 case NSS_CONFIG_LIST:
605 605 break;
606 606 default:
607 607 continue;
608 608 }
609 609 }
610 610 return (NSS_SUCCESS);
611 611 }
612 612
613 613 /*
614 614 * This routine is called immediately after nss_cfg_init but prior to
615 615 * any commands from nscd being processed. The intent here is to
616 616 * initialize the nss:* parameters allowed by the policy component
617 617 * so that nscd can then proceed and modify them if so desired.
618 618 *
619 619 * We know we can only get here if we are nscd so we can skip the
620 620 * preliminaries.
621 621 */
622 622
623 623 static int
624 624 nss_cfg_policy_init()
625 625 {
626 626 nss_config_t *next = &nss_policy_params[0];
627 627
628 628 for (; next && next->name != NULL; next++) {
629 629 if (nss_cfg_put(next, 1) < 0)
630 630 return (-1);
631 631 }
632 632 return (0);
633 633 }
634 634
635 635 /*
636 636 * NSS_OPTION & NIS_OPTION environment variable functions
637 637 */
638 638
639 639 static
640 640 void
641 641 set_option(struct option *opt, char *name, char *val)
642 642 {
643 643 int n;
644 644 char *p;
645 645 #ifdef DEBUG
646 646 FILE *fp;
647 647 #endif
648 648
649 649 for (; opt->name; opt++) {
650 650 if (strcmp(name, opt->name) == 0) {
651 651 switch (opt->type) {
652 652 case OPT_STRING:
653 653 p = libc_strdup(val);
654 654 *((char **)opt->address) = p;
655 655 break;
656 656
657 657 case OPT_INT:
658 658 if (strcmp(val, "") == 0)
659 659 n = 1;
660 660 else
661 661 n = atoi(val);
662 662 *((int *)opt->address) = n;
663 663 break;
664 664 #ifdef DEBUG
665 665 case OPT_FILE:
666 666 fp = fopen(val, "wF");
667 667 *((FILE **)opt->address) = fp;
668 668 break;
669 669 #endif
670 670 }
671 671 break;
672 672 }
673 673 }
674 674 }
675 675
676 676 static
677 677 void
678 678 __parse_environment(struct option *opt, char *p)
679 679 {
680 680 char *base;
681 681 char optname[100];
682 682 char optval[100];
683 683
684 684 while (*p) {
685 685 while (isspace(*p))
686 686 p++;
687 687 if (*p == '\0')
688 688 break;
689 689
690 690 base = p;
691 691 while (*p && *p != '=' && !isspace(*p))
692 692 p++;
693 693 /*
694 694 * play it safe and keep it simple, bail if an opt name
695 695 * is too long.
696 696 */
697 697 if ((p-base) >= sizeof (optname))
698 698 return;
699 699
700 700 (void) strncpy(optname, base, p-base);
701 701 optname[p-base] = '\0';
702 702
703 703 if (*p == '=') {
704 704 p++;
705 705 base = p;
706 706 while (*p && !isspace(*p))
707 707 p++;
708 708 /*
709 709 * play it safe and keep it simple, bail if an opt
710 710 * value is too long.
711 711 */
712 712 if ((p-base) >= sizeof (optval))
713 713 return;
714 714
715 715 (void) strncpy(optval, base, p-base);
716 716 optval[p-base] = '\0';
717 717 } else {
718 718 optval[0] = '\0';
719 719 }
720 720
721 721 set_option(opt, optname, optval);
722 722 }
723 723 }
724 724
725 725 static
726 726 void
727 727 nss_get_environment()
728 728 {
729 729 char *p;
730 730
731 731 /* NSS_OPTIONS is undocumented and should be used without nscd running. */
732 732 p = getenv("NSS_OPTIONS");
733 733 if (p == NULL)
734 734 return;
735 735 __parse_environment(nss_options, p);
736 736 }
737 737
738 738 /*
739 739 * sole external routine called from libnsl/nis/cache/cache_api.cc in the
740 740 * routines _nis_CacheInit/__nis_CacheLocalInit/__nis_CacheMgrInit_discard
741 741 * Only after checking "checked_env" (which must be done with mutex
742 742 * "cur_cache_lock" held) and is done once, (then "checked_env" is set)
743 743 */
744 744 void
745 745 __nis_get_environment()
746 746 {
747 747 char *p;
748 748
749 749 p = getenv("NIS_OPTIONS");
750 750 if (p == NULL)
751 751 return;
752 752 __parse_environment(nis_options, p);
753 753 }
754 754
755 755
756 756 /*
757 757 * Switch policy component backend state machine functions
758 758 */
759 759
760 760 static nss_backend_t *
761 761 nss_get_backend_u(nss_db_root_t **rootpp, struct nss_db_state *s, int n_src)
762 762 {
763 763 struct nss_src_state *src = &s->src[n_src];
764 764 nss_backend_t *be;
765 765 int cancel_state;
766 766
767 767 for (;;) {
768 768 if (src->n_dormant > 0) {
769 769 src->n_dormant--;
770 770 src->n_active++;
771 771 if (s->p.max_dormant_per_src == 1) {
772 772 be = src->dormant.single;
773 773 } else {
774 774 be = src->dormant.multi[src->n_dormant];
775 775 }
776 776 break;
777 777 }
778 778
779 779 if (src->be_constr == 0) {
780 780 nss_backend_finder_t *bf;
781 781
782 782 for (bf = s->p.finders; bf != 0; bf = bf->next) {
783 783 nss_backend_constr_t c;
784 784
785 785 c = (*bf->lookup) (bf->lookup_priv, s->p.name,
786 786 src->lkp->service_name, &src->finder_priv);
787 787 if (c != 0) {
788 788 src->be_constr = c;
789 789 src->finder = bf;
790 790 break;
791 791 }
792 792 }
793 793 if (src->be_constr == 0) {
794 794 /* Couldn't find the backend anywhere */
795 795 be = 0;
796 796 break;
797 797 }
798 798 }
799 799
800 800 if (src->n_active < s->p.max_active_per_src) {
801 801 be = (*src->be_constr)(s->p.name,
802 802 src->lkp->service_name, 0 /* === unimplemented */);
803 803 if (be != 0) {
804 804 src->n_active++;
805 805 break;
806 806 } else if (src->n_active == 0) {
807 807 /* Something's wrong; we should be */
808 808 /* able to create at least one */
809 809 /* instance of the backend */
810 810 break;
811 811 }
812 812 /*
813 813 * Else it's odd that we can't create another backend
814 814 * instance, but don't sweat it; instead, queue for
815 815 * an existing backend instance.
816 816 */
817 817 }
818 818
819 819 src->n_waiting++;
820 820 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,
821 821 &cancel_state);
822 822 (void) cond_wait(&src->wanna_be, &(*rootpp)->lock);
823 823 (void) pthread_setcancelstate(cancel_state, NULL);
824 824 NSS_CHECKROOT(rootpp, s);
825 825 src->n_waiting--;
826 826
827 827 /*
828 828 * Loop and see whether things got better for us, or whether
829 829 * someone else got scheduled first and we have to try
830 830 * this again.
831 831 *
832 832 * === ?? Should count iterations, assume bug if many ??
833 833 */
834 834 }
835 835 return (be);
836 836 }
837 837
838 838 static void
839 839 nss_put_backend_u(struct nss_db_state *s, int n_src, nss_backend_t *be)
840 840 {
841 841 struct nss_src_state *src = &s->src[n_src];
842 842
843 843 if (be == 0) {
844 844 return;
845 845 }
846 846
847 847 src->n_active--;
848 848
849 849 if (src->n_dormant < s->p.max_dormant_per_src) {
850 850 if (s->p.max_dormant_per_src == 1) {
851 851 src->dormant.single = be;
852 852 src->n_dormant++;
853 853 } else if (src->dormant.multi != 0 ||
854 854 (src->dormant.multi =
855 855 libc_malloc(s->p.max_dormant_per_src *
856 856 sizeof (nss_backend_t *))) != NULL) {
857 857 src->dormant.multi[src->n_dormant] = be;
858 858 src->n_dormant++;
859 859 } else {
860 860 /* Can't store it, so toss it */
861 861 (void) NSS_INVOKE_DBOP(be, NSS_DBOP_DESTRUCTOR, 0);
862 862 }
863 863 } else {
864 864 /* We've stored as many as we want, so toss it */
865 865 (void) NSS_INVOKE_DBOP(be, NSS_DBOP_DESTRUCTOR, 0);
866 866 }
867 867 if (src->n_waiting > 0) {
868 868 (void) cond_signal(&src->wanna_be);
869 869 }
870 870 }
871 871
872 872 static struct nss_db_state *
873 873 _nss_db_state_constr(nss_db_initf_t initf)
874 874 {
875 875 struct nss_db_state *s;
876 876 struct __nsw_switchconfig_v1 *config = 0;
877 877 struct __nsw_lookup_v1 *lkp;
878 878 enum __nsw_parse_err err;
879 879 const char *config_name;
880 880 int n_src;
881 881
882 882 if ((s = libc_malloc(sizeof (*s))) == 0) {
883 883 return (0);
884 884 }
885 885 (void) mutex_init(&s->orphan_root.lock, USYNC_THREAD, 0);
886 886
887 887 s->p.max_active_per_src = 10;
888 888 s->p.max_dormant_per_src = 1;
889 889 s->p.finders = nss_default_finders;
890 890 (*initf)(&s->p);
891 891 if (s->p.name == 0) {
892 892 _nss_db_state_destr(s);
893 893 return (0);
894 894 }
895 895
896 896 if (!checked_env) {
897 897 /* NSS_OPTIONS is undocumented and should be used without nscd running. */
898 898 nss_get_environment();
899 899 checked_env = 1;
900 900 }
901 901
902 902 config_name = s->p.config_name ? s->p.config_name : s->p.name;
903 903 if (! (s->p.flags & NSS_USE_DEFAULT_CONFIG)) {
904 904 config = __nsw_getconfig_v1(config_name, &err);
905 905 /* === ? test err ? */
906 906 }
907 907 if (config == 0) {
908 908 /* getconfig failed, or frontend demanded default config */
909 909
910 910 char *str; /* _nsw_getoneconfig() clobbers its argument */
911 911
912 912 if ((str = libc_strdup(s->p.default_config)) != 0) {
913 913 config = _nsw_getoneconfig_v1(config_name, str, &err);
914 914 libc_free(str);
915 915 }
916 916 if (config == 0) {
917 917 _nss_db_state_destr(s);
918 918 return (0);
919 919 }
920 920 }
921 921 s->config = config;
922 922 if ((s->max_src = config->num_lookups) <= 0 ||
923 923 (s->src = libc_malloc(s->max_src * sizeof (*s->src))) == 0) {
924 924 _nss_db_state_destr(s);
925 925 return (0);
926 926 }
927 927 for (n_src = 0, lkp = config->lookups;
928 928 n_src < s->max_src; n_src++, lkp = lkp->next) {
929 929 s->src[n_src].lkp = lkp;
930 930 (void) cond_init(&s->src[n_src].wanna_be, USYNC_THREAD, 0);
931 931 }
932 932 s->refcount = 1;
933 933 return (s);
934 934 }
935 935
936 936 void
937 937 _nss_src_state_destr(struct nss_src_state *src, int max_dormant)
938 938 {
939 939 if (max_dormant == 1) {
940 940 if (src->n_dormant != 0) {
941 941 (void) NSS_INVOKE_DBOP(src->dormant.single,
942 942 NSS_DBOP_DESTRUCTOR, 0);
943 943 };
944 944 } else if (src->dormant.multi != 0) {
945 945 int n;
946 946
947 947 for (n = 0; n < src->n_dormant; n++) {
948 948 (void) NSS_INVOKE_DBOP(src->dormant.multi[n],
949 949 NSS_DBOP_DESTRUCTOR, 0);
950 950 }
951 951 libc_free(src->dormant.multi);
952 952 }
953 953
954 954 /* cond_destroy(&src->wanna_be); */
955 955
956 956 if (src->finder != 0) {
957 957 (*src->finder->delete)(src->finder_priv, src->be_constr);
958 958 }
959 959 }
960 960
961 961 /*
962 962 * _nss_db_state_destr() -- used by NSS_UNREF_UNLOCK() to free the entire
963 963 * nss_db_state structure.
964 964 * Assumes that s has been ref-counted down to zero (in particular,
965 965 * rootp->s has already been dealt with).
966 966 *
967 967 * Nobody else holds a pointer to *s (if they did, refcount != 0),
968 968 * so we can clean up state *after* we drop the lock (also, by the
969 969 * time we finish freeing the state structures, the lock may have
970 970 * ceased to exist -- if we were using the orphan_root).
971 971 */
972 972
973 973 void
974 974 _nss_db_state_destr(struct nss_db_state *s)
975 975 {
976 976
977 977 if (s == NULL)
978 978 return;
979 979
980 980 /* === mutex_destroy(&s->orphan_root.lock); */
981 981 if (s->p.cleanup != 0) {
982 982 (*s->p.cleanup)(&s->p);
983 983 }
984 984 if (s->config != 0) {
985 985 (void) __nsw_freeconfig_v1(s->config);
986 986 }
987 987 if (s->src != 0) {
988 988 int n_src;
989 989
990 990 for (n_src = 0; n_src < s->max_src; n_src++) {
991 991 _nss_src_state_destr(&s->src[n_src],
992 992 s->p.max_dormant_per_src);
993 993 }
994 994 libc_free(s->src);
995 995 }
996 996 libc_free(s);
997 997 }
998 998
999 999
1000 1000 /*
1001 1001 * _nss_status_vec() returns a bit vector of all status codes returned during
1002 1002 * the most recent call to nss_search().
1003 1003 * _nss_status_vec_p() returns a pointer to this bit vector, or NULL on
1004 1004 * failure.
1005 1005 * These functions are private. Don't use them externally without discussing
1006 1006 * it with the switch maintainers.
1007 1007 */
1008 1008 static uint_t *
1009 1009 _nss_status_vec_p()
1010 1010 {
1011 1011 return (tsdalloc(_T_NSS_STATUS_VEC, sizeof (uint_t), NULL));
1012 1012 }
1013 1013
1014 1014 unsigned int
1015 1015 _nss_status_vec(void)
1016 1016 {
↓ open down ↓ |
1016 lines elided |
↑ open up ↑ |
1017 1017 unsigned int *status_vec_p = _nss_status_vec_p();
1018 1018
1019 1019 return ((status_vec_p != NULL) ? *status_vec_p : (1 << NSS_UNAVAIL));
1020 1020 }
1021 1021
1022 1022 static void
1023 1023 output_loop_diag_a(
1024 1024 int n,
1025 1025 char *dbase,
1026 1026 struct __nsw_lookup_v1 *lkp)
1027 -
1028 1027 {
1029 1028 (void) fprintf(__nss_debug_file,
1030 - "NSS_retry(%d): '%s': trying '%s' ... ",
1031 - n, dbase, lkp->service_name);
1029 + "NSS_retry(%d): '%s': trying '%s' ... ",
1030 + n, dbase, lkp->service_name);
1032 1031 (void) fflush(__nss_debug_file);
1033 1032
1034 1033 }
1035 1034
1036 1035 static void
1037 1036 output_loop_diag_b(
1038 1037 nss_status_t res,
1039 1038 struct __nsw_lookup_v1 *lkp)
1040 -
1041 1039 {
1042 1040 (void) fprintf(__nss_debug_file, "result=");
1043 1041 switch (res) {
1044 1042 case NSS_SUCCESS:
1045 1043 (void) fprintf(__nss_debug_file, "SUCCESS");
1046 1044 break;
1047 1045 case NSS_NOTFOUND:
1048 1046 (void) fprintf(__nss_debug_file, "NOTFOUND");
1049 1047 break;
1050 1048 case NSS_UNAVAIL:
1051 1049 (void) fprintf(__nss_debug_file, "UNAVAIL");
1052 1050 break;
1053 1051 case NSS_TRYAGAIN:
1054 1052 (void) fprintf(__nss_debug_file, "TRYAGAIN");
1055 1053 break;
1056 1054 case NSS_NISSERVDNS_TRYAGAIN:
1057 1055 (void) fprintf(__nss_debug_file, "NISSERVDNS_TRYAGAIN");
1058 1056 break;
1059 1057 default:
1060 1058 (void) fprintf(__nss_debug_file, "undefined");
1061 1059 }
1062 1060 (void) fprintf(__nss_debug_file, ", action=");
1063 1061 switch (lkp->actions[res]) {
1064 1062 case __NSW_CONTINUE:
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
1065 1063 (void) fprintf(__nss_debug_file, "CONTINUE");
1066 1064 break;
1067 1065 case __NSW_RETURN:
1068 1066 (void) fprintf(__nss_debug_file, "RETURN");
1069 1067 break;
1070 1068 case __NSW_TRYAGAIN_FOREVER:
1071 1069 (void) fprintf(__nss_debug_file, "TRYAGAIN_FOREVER");
1072 1070 break;
1073 1071 case __NSW_TRYAGAIN_NTIMES:
1074 1072 (void) fprintf(__nss_debug_file, "TRYAGAIN_NTIMES (N=%d)",
1075 - lkp->max_retries);
1073 + lkp->max_retries);
1076 1074 break;
1077 1075 case __NSW_TRYAGAIN_PAUSED:
1078 1076 (void) fprintf(__nss_debug_file, "TRYAGAIN_PAUSED");
1079 1077 break;
1080 1078 default:
1081 1079 (void) fprintf(__nss_debug_file, "undefined");
1082 1080 }
1083 1081 (void) fprintf(__nss_debug_file, "\n");
1084 1082 }
1085 1083
1086 1084 #define NSS_BACKOFF(n, b, t) \
1087 1085 ((n) > ((b) + 3) ? t : (1 << ((n) - ((b) + 1))))
1088 1086
1089 1087 static int
1090 1088 retry_test(nss_status_t res, int n, struct __nsw_lookup_v1 *lkp)
1091 1089 {
1092 1090 if (res != NSS_TRYAGAIN && res != NSS_NISSERVDNS_TRYAGAIN) {
1093 1091 if (res == NSS_SUCCESS) {
1094 1092 __NSW_UNPAUSE_ACTION(lkp->actions[__NSW_TRYAGAIN]);
1095 1093 __NSW_UNPAUSE_ACTION(
1096 1094 lkp->actions[__NSW_NISSERVDNS_TRYAGAIN]);
1097 1095 }
1098 1096 return (0);
1099 1097 }
1100 1098
1101 1099 if ((res == NSS_TRYAGAIN &&
1102 1100 lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_FOREVER) ||
1103 1101 (res == NSS_NISSERVDNS_TRYAGAIN &&
1104 1102 lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] == __NSW_TRYAGAIN_FOREVER))
1105 1103 return (1);
1106 1104
1107 1105 if (res == NSS_TRYAGAIN &&
1108 1106 lkp->actions[__NSW_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES)
1109 1107 if (n <= lkp->max_retries)
1110 1108 return (1);
1111 1109 else {
1112 1110 lkp->actions[__NSW_TRYAGAIN] = __NSW_TRYAGAIN_PAUSED;
1113 1111 return (0);
1114 1112 }
1115 1113
1116 1114 if (res == NSS_NISSERVDNS_TRYAGAIN &&
1117 1115 lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] == __NSW_TRYAGAIN_NTIMES)
1118 1116 if (n <= lkp->max_retries)
1119 1117 return (1);
1120 1118 else {
1121 1119 lkp->actions[__NSW_NISSERVDNS_TRYAGAIN] =
1122 1120 __NSW_TRYAGAIN_PAUSED;
1123 1121 return (0);
1124 1122 }
1125 1123
1126 1124 return (0);
1127 1125 }
1128 1126
1129 1127 /*
1130 1128 * Switch policy component functional interfaces
1131 1129 */
1132 1130
1133 1131 void
1134 1132 nss_delete(nss_db_root_t *rootp)
1135 1133 {
1136 1134 struct nss_db_state *s;
1137 1135
1138 1136 /* no name service cache daemon divert here */
1139 1137 /* local nss_delete decrements state reference counts */
1140 1138 /* and may free up opened switch resources. */
1141 1139
1142 1140 NSS_ROOTLOCK(rootp, &s);
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
1143 1141 if (s == 0) {
1144 1142 NSS_UNLOCK(rootp);
1145 1143 } else {
1146 1144 rootp->s = 0;
1147 1145 NSS_UNREF_UNLOCK(rootp, s);
1148 1146 }
1149 1147 }
1150 1148
1151 1149 nss_status_t
1152 1150 nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum,
1153 - void *search_args)
1151 + void *search_args)
1154 1152 {
1155 1153 nss_status_t res = NSS_UNAVAIL;
1156 1154 struct nss_db_state *s;
1157 1155 int n_src;
1158 1156 unsigned int *status_vec_p;
1159 1157
1160 1158 /* name service cache daemon divert */
1161 1159 res = _nsc_search(rootp, initf, search_fnum, search_args);
1162 1160 if (res != NSS_TRYLOCAL)
1163 1161 return (res);
1164 1162
1165 1163 /* fall through - process locally */
1166 1164 errno = 0; /* just in case ... */
1167 1165 res = NSS_UNAVAIL;
1168 1166 status_vec_p = _nss_status_vec_p();
1169 1167
1170 1168 if (status_vec_p == NULL) {
1171 1169 return (NSS_UNAVAIL);
1172 1170 }
1173 1171 *status_vec_p = 0;
1174 1172
1175 1173 NSS_LOCK_CHECK(rootp, initf, &s);
1176 1174 if (s == 0) {
1177 1175 NSS_UNLOCK(rootp);
1178 1176 return (res);
1179 1177 }
1180 1178 NSS_STATE_REF_u(s);
1181 1179
1182 1180 for (n_src = 0; n_src < s->max_src; n_src++) {
1183 1181 nss_backend_t *be;
1184 1182 nss_backend_op_t funcp;
1185 1183
1186 1184 res = NSS_UNAVAIL;
1187 1185 if ((be = nss_get_backend_u(&rootp, s, n_src)) != 0) {
1188 1186 if ((funcp = NSS_LOOKUP_DBOP(be, search_fnum)) != 0) {
1189 1187 int n_loop = 0;
1190 1188 int no_backoff = 19;
1191 1189 int max_backoff = 5; /* seconds */
1192 1190
1193 1191 do {
1194 1192 /*
1195 1193 * Backend operation may take a while;
1196 1194 * drop the lock so we don't serialize
1197 1195 * more than necessary.
1198 1196 */
1199 1197 NSS_UNLOCK(rootp);
1200 1198
1201 1199 /* After several tries, backoff... */
1202 1200 if (n_loop > no_backoff) {
1203 1201 if (__nss_debug_eng_loop > 1)
1204 1202 (void) fprintf(
1205 1203 __nss_debug_file,
1206 1204 "NSS: loop: "
1207 1205 "sleeping %d ...\n",
1208 1206 NSS_BACKOFF(n_loop,
1209 1207 no_backoff,
1210 1208 max_backoff));
1211 1209
1212 1210 (void) sleep(NSS_BACKOFF(n_loop,
1213 1211 no_backoff, max_backoff));
1214 1212 }
1215 1213
1216 1214 if (__nss_debug_eng_loop)
1217 1215 output_loop_diag_a(n_loop,
1218 1216 s->config->dbase,
1219 1217 s->src[n_src].lkp);
1220 1218
1221 1219
1222 1220 res = (*funcp)(be, search_args);
1223 1221 NSS_RELOCK(&rootp, s);
1224 1222 n_loop++;
1225 1223 if (__nss_debug_eng_loop)
1226 1224 output_loop_diag_b(res,
1227 1225 s->src[n_src].lkp);
1228 1226 } while (retry_test(res, n_loop,
1229 1227 s->src[n_src].lkp));
1230 1228 }
1231 1229 nss_put_backend_u(s, n_src, be);
1232 1230 }
1233 1231 *status_vec_p |= (1 << res);
1234 1232 if (__NSW_ACTION_V1(s->src[n_src].lkp, res) == __NSW_RETURN) {
1235 1233 if (__nss_debug_eng_loop)
1236 1234 (void) fprintf(__nss_debug_file,
1237 1235 "NSS: '%s': return.\n",
1238 1236 s->config->dbase);
1239 1237 break;
1240 1238 } else
1241 1239 if (__nss_debug_eng_loop)
1242 1240 (void) fprintf(__nss_debug_file,
1243 1241 "NSS: '%s': continue ...\n",
1244 1242 s->config->dbase);
1245 1243 }
1246 1244 NSS_UNREF_UNLOCK(rootp, s);
1247 1245 return (res);
1248 1246 }
1249 1247
1250 1248
1251 1249 /*
1252 1250 * Start of nss_{setent|getent|endent}
1253 1251 */
1254 1252
1255 1253 /*
1256 1254 * State (here called "context") for one setent/getent.../endent sequence.
1257 1255 * In principle there could be multiple contexts active for a single
1258 1256 * database; in practice, since Posix and UI have helpfully said that
1259 1257 * getent() state is global rather than, say, per-thread or user-supplied,
1260 1258 * we have at most one of these per nss_db_state.
1261 1259 * XXX ? Is this statement still true?
1262 1260 *
1263 1261 * NSS2 - a client's context is maintained as a cookie delivered by and
1264 1262 * passed to nscd. The cookie is a 64 bit (nssuint_t) unique opaque value
1265 1263 * created by nscd.
1266 1264 * cookie states:
1267 1265 * NSCD_NEW_COOKIE - cookie value uninitialized
1268 1266 * NSCD_LOCAL_COOKIE - setent is a local setent
1269 1267 * all other - NSCD unique opaque id for this setent
1270 1268 * A client's context is also associated with a seq_num. This is a nscd
1271 1269 * opaque 64 bit (nssuint_t) value passed with a cookie, and used to by nscd
1272 1270 * to validate the sequencing of the context. The client treats this as
1273 1271 * a pass through value.
1274 1272 *
1275 1273 * XXX ?? Use Cookie as cross-check info so that we can detect an
1276 1274 * nss_context that missed an nss_delete() or similar.
1277 1275 */
1278 1276
1279 1277 struct nss_getent_context {
1280 1278 int n_src; /* >= max_src ==> end of sequence */
1281 1279 nss_backend_t *be;
1282 1280 struct nss_db_state *s;
1283 1281 nssuint_t cookie;
1284 1282 nssuint_t seq_num;
1285 1283 nssuint_t cookie_setent;
1286 1284 nss_db_params_t param;
1287 1285 };
1288 1286
1289 1287 static void nss_setent_u(nss_db_root_t *,
1290 1288 nss_db_initf_t,
1291 1289 nss_getent_t *);
1292 1290 static nss_status_t nss_getent_u(nss_db_root_t *,
1293 1291 nss_db_initf_t,
1294 1292 nss_getent_t *,
1295 1293 void *);
1296 1294 static void nss_endent_u(nss_db_root_t *,
1297 1295 nss_db_initf_t,
1298 1296 nss_getent_t *);
1299 1297
1300 1298 void
1301 1299 nss_setent(nss_db_root_t *rootp, nss_db_initf_t initf, nss_getent_t *contextpp)
1302 1300 {
↓ open down ↓ |
139 lines elided |
↑ open up ↑ |
1303 1301 if (contextpp == 0) {
1304 1302 return;
1305 1303 }
1306 1304 cancel_safe_mutex_lock(&contextpp->lock);
1307 1305 nss_setent_u(rootp, initf, contextpp);
1308 1306 cancel_safe_mutex_unlock(&contextpp->lock);
1309 1307 }
1310 1308
1311 1309 nss_status_t
1312 1310 nss_getent(nss_db_root_t *rootp, nss_db_initf_t initf, nss_getent_t *contextpp,
1313 - void *args)
1311 + void *args)
1314 1312 {
1315 1313 nss_status_t status;
1316 1314
1317 1315 if (contextpp == 0) {
1318 1316 return (NSS_UNAVAIL);
1319 1317 }
1320 1318 cancel_safe_mutex_lock(&contextpp->lock);
1321 1319 status = nss_getent_u(rootp, initf, contextpp, args);
1322 1320 cancel_safe_mutex_unlock(&contextpp->lock);
1323 1321 return (status);
1324 1322 }
1325 1323
1326 1324 void
1327 1325 nss_endent(nss_db_root_t *rootp, nss_db_initf_t initf, nss_getent_t *contextpp)
1328 1326 {
1329 1327 if (contextpp == 0) {
1330 1328 return;
1331 1329 }
1332 1330 cancel_safe_mutex_lock(&contextpp->lock);
1333 1331 nss_endent_u(rootp, initf, contextpp);
1334 1332 cancel_safe_mutex_unlock(&contextpp->lock);
1335 1333 }
1336 1334
1337 1335 /*
1338 1336 * Each of the _u versions of the nss interfaces assume that the context
1339 1337 * lock is held. No need to divert to nscd. Private to local sequencing.
1340 1338 */
1341 1339
1342 1340 static void
1343 1341 end_iter_u(nss_db_root_t *rootp, struct nss_getent_context *contextp)
1344 1342 {
1345 1343 struct nss_db_state *s;
1346 1344 nss_backend_t *be;
1347 1345 int n_src;
1348 1346
1349 1347 s = contextp->s;
1350 1348 n_src = contextp->n_src;
1351 1349 be = contextp->be;
1352 1350
1353 1351 if (s != 0) {
1354 1352 if (n_src < s->max_src && be != 0) {
1355 1353 (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0);
1356 1354 NSS_RELOCK(&rootp, s);
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
1357 1355 nss_put_backend_u(s, n_src, be);
1358 1356 contextp->be = 0; /* Should be unnecessary, but hey */
1359 1357 NSS_UNREF_UNLOCK(rootp, s);
1360 1358 }
1361 1359 contextp->s = 0;
1362 1360 }
1363 1361 }
1364 1362
1365 1363 static void
1366 1364 nss_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
1367 - nss_getent_t *contextpp)
1365 + nss_getent_t *contextpp)
1368 1366 {
1369 1367 nss_status_t status;
1370 1368 struct nss_db_state *s;
1371 1369 struct nss_getent_context *contextp;
1372 1370 nss_backend_t *be;
1373 1371 int n_src;
1374 1372
1375 1373 /* setup process wide context while locked */
1376 1374 if ((contextp = contextpp->ctx) == 0) {
1377 1375 if ((contextp = libc_malloc(sizeof (*contextp))) == 0) {
1378 1376 return;
1379 1377 }
1380 1378 contextpp->ctx = contextp;
1381 1379 contextp->cookie = NSCD_NEW_COOKIE; /* cookie init */
1382 1380 contextp->seq_num = 0; /* seq_num init */
1383 1381 s = 0;
1384 1382 } else {
1385 1383 s = contextp->s;
1386 1384 if (contextp->cookie != NSCD_LOCAL_COOKIE)
1387 1385 contextp->cookie = NSCD_NEW_COOKIE;
1388 1386 }
1389 1387
1390 1388 /* name service cache daemon divert */
1391 1389 if (contextp->cookie == NSCD_NEW_COOKIE) {
1392 1390 status = _nsc_setent_u(rootp, initf, contextpp);
1393 1391 if (status != NSS_TRYLOCAL)
1394 1392 return;
1395 1393 }
1396 1394
1397 1395 /* fall through - process locally */
1398 1396 if (s == 0) {
1399 1397 NSS_LOCK_CHECK(rootp, initf, &s);
1400 1398 if (s == 0) {
1401 1399 /* Couldn't set up state, so quit */
1402 1400 NSS_UNLOCK(rootp);
1403 1401 /* ==== is there any danger of not having done an */
1404 1402 /* end_iter() here, and hence of losing backends? */
1405 1403 contextpp->ctx = 0;
1406 1404 libc_free(contextp);
1407 1405 return;
1408 1406 }
1409 1407 NSS_STATE_REF_u(s);
1410 1408 contextp->s = s;
1411 1409 } else {
1412 1410 s = contextp->s;
1413 1411 n_src = contextp->n_src;
1414 1412 be = contextp->be;
1415 1413 if (n_src == 0 && be != 0) {
1416 1414 /*
1417 1415 * Optimization: don't do endent, don't change
1418 1416 * backends, just do the setent. Look Ma, no locks
1419 1417 * (nor any context that needs updating).
1420 1418 */
1421 1419 (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0);
1422 1420 return;
1423 1421 }
1424 1422 if (n_src < s->max_src && be != 0) {
1425 1423 (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0);
1426 1424 NSS_RELOCK(&rootp, s);
1427 1425 nss_put_backend_u(s, n_src, be);
1428 1426 contextp->be = 0; /* Play it safe */
1429 1427 } else {
1430 1428 NSS_RELOCK(&rootp, s);
1431 1429 }
1432 1430 }
1433 1431 for (n_src = 0, be = 0; n_src < s->max_src &&
1434 1432 (be = nss_get_backend_u(&rootp, s, n_src)) == 0; n_src++) {
1435 1433 ;
1436 1434 }
1437 1435 NSS_UNLOCK(rootp);
1438 1436
1439 1437 contextp->n_src = n_src;
1440 1438 contextp->be = be;
1441 1439
↓ open down ↓ |
64 lines elided |
↑ open up ↑ |
1442 1440 if (be == 0) {
1443 1441 /* Things are broken enough that we can't do setent/getent */
1444 1442 nss_endent_u(rootp, initf, contextpp);
1445 1443 return;
1446 1444 }
1447 1445 (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0);
1448 1446 }
1449 1447
1450 1448 static nss_status_t
1451 1449 nss_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
1452 - nss_getent_t *contextpp, void *args)
1450 + nss_getent_t *contextpp, void *args)
1453 1451 {
1454 1452 nss_status_t status;
1455 1453 struct nss_db_state *s;
1456 1454 struct nss_getent_context *contextp;
1457 1455 int n_src;
1458 1456 nss_backend_t *be;
1459 1457
1460 1458 if ((contextp = contextpp->ctx) == 0) {
1461 1459 nss_setent_u(rootp, initf, contextpp);
1462 1460 if ((contextp = contextpp->ctx) == 0) {
1463 1461 /* Give up */
1464 1462 return (NSS_UNAVAIL);
1465 1463 }
1466 1464 }
1467 1465 /* name service cache daemon divert */
1468 1466 status = _nsc_getent_u(rootp, initf, contextpp, args);
1469 1467 if (status != NSS_TRYLOCAL)
1470 1468 return (status);
1471 1469
1472 1470 /* fall through - process locally */
1473 1471 s = contextp->s;
1474 1472 n_src = contextp->n_src;
1475 1473 be = contextp->be;
1476 1474
1477 1475 if (s == 0) {
1478 1476 /*
1479 1477 * We've done an end_iter() and haven't done nss_setent()
1480 1478 * or nss_endent() since; we should stick in this state
1481 1479 * until the caller invokes one of those two routines.
1482 1480 */
1483 1481 return (NSS_SUCCESS);
1484 1482 }
1485 1483
1486 1484 while (n_src < s->max_src) {
1487 1485 nss_status_t res;
1488 1486
1489 1487 if (be == 0) {
1490 1488 /* If it's null it's a bug, but let's play safe */
1491 1489 res = NSS_UNAVAIL;
1492 1490 } else {
1493 1491 res = NSS_INVOKE_DBOP(be, NSS_DBOP_GETENT, args);
1494 1492 }
1495 1493
1496 1494 if (__NSW_ACTION_V1(s->src[n_src].lkp, res) == __NSW_RETURN) {
1497 1495 if (res != __NSW_SUCCESS) {
1498 1496 end_iter_u(rootp, contextp);
1499 1497 }
1500 1498 return (res);
1501 1499 }
1502 1500 (void) NSS_INVOKE_DBOP(be, NSS_DBOP_ENDENT, 0);
1503 1501 NSS_RELOCK(&rootp, s);
1504 1502 nss_put_backend_u(s, n_src, be);
1505 1503 do {
1506 1504 n_src++;
1507 1505 } while (n_src < s->max_src &&
1508 1506 (be = nss_get_backend_u(&rootp, s, n_src)) == 0);
1509 1507 contextp->be = be;
1510 1508 if (be == 0) {
1511 1509 /*
1512 1510 * This is the case where we failed to get the backend
1513 1511 * for the last source. We exhausted all sources.
1514 1512 *
1515 1513 * We need to do cleanup ourselves because end_iter_u()
1516 1514 * does not do it for be == 0.
1517 1515 */
1518 1516 NSS_UNREF_UNLOCK(rootp, s);
1519 1517 contextp->s = 0;
1520 1518 break;
1521 1519 } else {
1522 1520 NSS_UNLOCK(rootp);
1523 1521 contextp->n_src = n_src;
1524 1522 (void) NSS_INVOKE_DBOP(be, NSS_DBOP_SETENT, 0);
1525 1523 }
↓ open down ↓ |
63 lines elided |
↑ open up ↑ |
1526 1524 }
1527 1525 /* Got to the end of the sources without finding another entry */
1528 1526 end_iter_u(rootp, contextp);
1529 1527 return (NSS_SUCCESS);
1530 1528 /* success is either a successful entry or end of the sources */
1531 1529 }
1532 1530
1533 1531 /*ARGSUSED*/
1534 1532 static void
1535 1533 nss_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
1536 - nss_getent_t *contextpp)
1534 + nss_getent_t *contextpp)
1537 1535 {
1538 1536 nss_status_t status;
1539 1537 struct nss_getent_context *contextp;
1540 1538
1541 1539 if ((contextp = contextpp->ctx) == 0) {
1542 1540 /* nss_endent() on an unused context is a no-op */
1543 1541 return;
1544 1542 }
1545 1543
1546 1544 /* notify name service cache daemon */
1547 1545 status = _nsc_endent_u(rootp, initf, contextpp);
1548 1546 if (status != NSS_TRYLOCAL) {
1549 1547 /* clean up */
1550 1548 libc_free(contextp);
1551 1549 contextpp->ctx = 0;
1552 1550 return;
1553 1551 }
1554 1552
1555 1553 /* fall through - process locally */
1556 1554
1557 1555 /*
1558 1556 * Existing code (BSD, SunOS) works in such a way that getXXXent()
1559 1557 * following an endXXXent() behaves as though the user had invoked
1560 1558 * setXXXent(), i.e. it iterates properly from the beginning.
1561 1559 * We'd better not break this, so our choices are
1562 1560 * (1) leave the context structure around, and do nss_setent or
1563 1561 * something equivalent,
1564 1562 * or (2) free the context completely, and rely on the code in
1565 1563 * nss_getent() that makes getXXXent() do the right thing
1566 1564 * even without a preceding setXXXent().
1567 1565 * The code below does (2), which frees up resources nicely but will
1568 1566 * cost more if the user then does more getXXXent() operations.
1569 1567 * Moral: for efficiency, don't call endXXXent() prematurely.
1570 1568 */
1571 1569 end_iter_u(rootp, contextp);
1572 1570 libc_free(contextp);
1573 1571 contextpp->ctx = 0;
1574 1572 }
1575 1573
1576 1574 /*
1577 1575 * pack dbd data into header
1578 1576 * Argment pointers assumed valid.
1579 1577 * poff offset position pointer
1580 1578 * IN = starting offset for dbd header
1581 1579 * OUT = starting offset for next section
1582 1580 */
1583 1581
1584 1582 static nss_status_t
1585 1583 nss_pack_dbd(void *buffer, size_t bufsize, nss_db_params_t *p, size_t *poff)
1586 1584 {
1587 1585 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1588 1586 nss_dbd_t *pdbd;
1589 1587 size_t off = *poff;
1590 1588 size_t len, blen;
1591 1589 size_t n, nc, dc;
1592 1590 char *bptr;
1593 1591
1594 1592 pbuf->dbd_off = (nssuint_t)off;
1595 1593 bptr = (char *)buffer + off;
1596 1594 blen = bufsize - off;
1597 1595 len = sizeof (nss_dbd_t);
1598 1596
1599 1597 n = nc = dc = 0;
1600 1598 if (p->name == NULL) {
1601 1599 errno = ERANGE; /* actually EINVAL */
1602 1600 return (NSS_ERROR);
1603 1601 }
1604 1602
1605 1603 /* if default config not specified, the flag should be reset */
1606 1604 if (p->default_config == NULL) {
1607 1605 p->default_config = "<NULL>";
1608 1606 p->flags = p->flags & ~NSS_USE_DEFAULT_CONFIG;
1609 1607 }
1610 1608
1611 1609 n = strlen(p->name) + 1;
1612 1610 dc = strlen(p->default_config) + 1;
1613 1611 if (n < 2 || dc < 2) { /* What no DB? */
1614 1612 errno = ERANGE; /* actually EINVAL */
1615 1613 return (NSS_ERROR);
1616 1614 }
1617 1615 if (p->config_name != NULL) {
1618 1616 nc = strlen(p->config_name) + 1;
1619 1617 }
1620 1618 if ((len + n + nc + dc) >= blen) {
1621 1619 errno = ERANGE; /* actually EINVAL */
1622 1620 return (NSS_ERROR);
1623 1621 }
1624 1622
1625 1623 pdbd = (nss_dbd_t *)((void *)bptr);
1626 1624 bptr += len;
1627 1625 pdbd->flags = p->flags;
1628 1626 pdbd->o_name = len;
1629 1627 (void) strlcpy(bptr, p->name, n);
1630 1628 len += n;
1631 1629 bptr += n;
1632 1630 if (nc == 0) {
1633 1631 pdbd->o_config_name = 0;
1634 1632 } else {
1635 1633 pdbd->o_config_name = len;
1636 1634 (void) strlcpy(bptr, p->config_name, nc);
1637 1635 bptr += nc;
1638 1636 len += nc;
1639 1637 }
1640 1638 pdbd->o_default_config = len;
1641 1639 (void) strlcpy(bptr, p->default_config, dc);
1642 1640 len += dc;
1643 1641 pbuf->dbd_len = (nssuint_t)len;
1644 1642 off += ROUND_UP(len, sizeof (nssuint_t));
1645 1643 *poff = off;
1646 1644 return (NSS_SUCCESS);
↓ open down ↓ |
100 lines elided |
↑ open up ↑ |
1647 1645 }
1648 1646
1649 1647 /*
1650 1648 * Switch packed and _nsc (switch->nscd) interfaces
1651 1649 * Return: NSS_SUCCESS (OK to proceed), NSS_ERROR, NSS_NOTFOUND
1652 1650 */
1653 1651
1654 1652 /*ARGSUSED*/
1655 1653 nss_status_t
1656 1654 nss_pack(void *buffer, size_t bufsize, nss_db_root_t *rootp,
1657 - nss_db_initf_t initf, int search_fnum, void *search_args)
1655 + nss_db_initf_t initf, int search_fnum, void *search_args)
1658 1656 {
1659 1657 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1660 1658 nss_XbyY_args_t *in = (nss_XbyY_args_t *)search_args;
1661 1659 nss_db_params_t tparam = { 0 };
1662 1660 nss_status_t ret = NSS_ERROR;
1663 1661 const char *dbn;
1664 1662 size_t blen, len, off = 0;
1665 1663 char *bptr;
1666 1664 struct nss_groupsbymem *gbm;
1667 1665
1668 1666 if (pbuf == NULL || in == NULL || initf == (nss_db_initf_t)NULL) {
1669 1667 errno = ERANGE; /* actually EINVAL */
1670 1668 return (ret);
1671 1669 }
1672 1670 tparam.cleanup = NULL;
1673 1671 (*initf)(&tparam);
1674 1672 if ((dbn = tparam.name) == 0) {
1675 1673 if (tparam.cleanup != 0)
1676 1674 (tparam.cleanup)(&tparam);
1677 1675 errno = ERANGE; /* actually EINVAL */
1678 1676 return (ret);
1679 1677 }
1680 1678
1681 1679 /* init buffer header */
1682 1680 pbuf->pbufsiz = (nssuint_t)bufsize;
1683 1681 pbuf->p_ruid = (uint32_t)getuid();
1684 1682 pbuf->p_euid = (uint32_t)geteuid();
1685 1683 pbuf->p_version = NSCD_HEADER_REV;
1686 1684 pbuf->p_status = 0;
1687 1685 pbuf->p_errno = 0;
1688 1686 pbuf->p_herrno = 0;
1689 1687
1690 1688 /* possible audituser init */
1691 1689 if (strcmp(dbn, NSS_DBNAM_AUTHATTR) == 0 && in->h_errno != 0)
1692 1690 pbuf->p_herrno = (uint32_t)in->h_errno;
1693 1691
1694 1692 pbuf->libpriv = 0;
1695 1693
1696 1694 off = sizeof (nss_pheader_t);
1697 1695
1698 1696 /* setup getXbyY operation - database and sub function */
1699 1697 pbuf->nss_dbop = (uint32_t)search_fnum;
1700 1698 ret = nss_pack_dbd(buffer, bufsize, &tparam, &off);
1701 1699 if (ret != NSS_SUCCESS) {
1702 1700 errno = ERANGE; /* actually EINVAL */
1703 1701 return (ret);
1704 1702 }
1705 1703 ret = NSS_ERROR;
1706 1704 /* setup request key */
1707 1705 pbuf->key_off = (nssuint_t)off;
1708 1706 bptr = (char *)buffer + off;
1709 1707 blen = bufsize - off;
1710 1708 /* use key2str if provided, else call default getXbyY packer */
1711 1709 if (strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) {
1712 1710 /* This has to run locally due to backend knowledge */
1713 1711 if (search_fnum == NSS_DBOP_NETGROUP_SET) {
1714 1712 errno = 0;
1715 1713 return (NSS_TRYLOCAL);
1716 1714 }
1717 1715 /* use default packer for known getXbyY ops */
1718 1716 ret = nss_default_key2str(bptr, blen, in, dbn,
1719 1717 search_fnum, &len);
1720 1718 } else if (in->key2str == NULL ||
1721 1719 (search_fnum == NSS_DBOP_GROUP_BYMEMBER &&
1722 1720 strcmp(dbn, NSS_DBNAM_GROUP) == 0)) {
1723 1721 /* use default packer for known getXbyY ops */
1724 1722 ret = nss_default_key2str(bptr, blen, in, dbn,
1725 1723 search_fnum, &len);
1726 1724 } else {
1727 1725 ret = (*in->key2str)(bptr, blen, &in->key, &len);
1728 1726 }
1729 1727 if (tparam.cleanup != 0)
1730 1728 (tparam.cleanup)(&tparam);
1731 1729 if (ret != NSS_SUCCESS) {
1732 1730 errno = ERANGE; /* actually ENOMEM */
1733 1731 return (ret);
1734 1732 }
1735 1733 pbuf->key_len = (nssuint_t)len;
1736 1734 off += ROUND_UP(len, sizeof (nssuint_t));
1737 1735
1738 1736 pbuf->data_off = (nssuint_t)off;
1739 1737 pbuf->data_len = (nssuint_t)(bufsize - off);
1740 1738 /*
1741 1739 * Prime data return with first result if
1742 1740 * the first result is passed in
1743 1741 * [_getgroupsbymember oddness]
1744 1742 */
1745 1743 gbm = (struct nss_groupsbymem *)search_args;
1746 1744 if (search_fnum == NSS_DBOP_GROUP_BYMEMBER &&
1747 1745 strcmp(dbn, NSS_DBNAM_GROUP) == 0 && gbm->numgids == 1) {
1748 1746 gid_t *gidp;
1749 1747 gidp = (gid_t *)((void *)((char *)buffer + off));
1750 1748 *gidp = gbm->gid_array[0];
1751 1749 }
1752 1750
1753 1751 errno = 0; /* just in case ... */
1754 1752 return (NSS_SUCCESS);
↓ open down ↓ |
87 lines elided |
↑ open up ↑ |
1755 1753 }
1756 1754
1757 1755 /*
1758 1756 * Switch packed and _nsc (switch->nscd) {set/get/end}ent interfaces
1759 1757 * Return: NSS_SUCCESS (OK to proceed), NSS_ERROR, NSS_NOTFOUND
1760 1758 */
1761 1759
1762 1760 /*ARGSUSED*/
1763 1761 nss_status_t
1764 1762 nss_pack_ent(void *buffer, size_t bufsize, nss_db_root_t *rootp,
1765 - nss_db_initf_t initf, nss_getent_t *contextpp)
1763 + nss_db_initf_t initf, nss_getent_t *contextpp)
1766 1764 {
1767 1765 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1768 1766 struct nss_getent_context *contextp = contextpp->ctx;
1769 1767 nss_status_t ret = NSS_ERROR;
1770 1768 size_t blen, len = 0, off = 0;
1771 1769 char *bptr;
1772 1770 nssuint_t *nptr;
1773 1771
1774 1772 if (pbuf == NULL || initf == (nss_db_initf_t)NULL) {
1775 1773 errno = ERANGE; /* actually EINVAL */
1776 1774 return (ret);
1777 1775 }
1778 1776
1779 1777 /* init buffer header */
1780 1778 pbuf->pbufsiz = (nssuint_t)bufsize;
1781 1779 pbuf->p_ruid = (uint32_t)getuid();
1782 1780 pbuf->p_euid = (uint32_t)geteuid();
1783 1781 pbuf->p_version = NSCD_HEADER_REV;
1784 1782 pbuf->p_status = 0;
1785 1783 pbuf->p_errno = 0;
1786 1784 pbuf->p_herrno = 0;
1787 1785 pbuf->libpriv = 0;
1788 1786
1789 1787 off = sizeof (nss_pheader_t);
1790 1788
1791 1789 /* setup getXXXent operation - database and sub function */
1792 1790 pbuf->nss_dbop = (uint32_t)0; /* iterators have no dbop */
1793 1791 ret = nss_pack_dbd(buffer, bufsize, &contextp->param, &off);
1794 1792 if (ret != NSS_SUCCESS) {
1795 1793 errno = ERANGE; /* actually EINVAL */
1796 1794 return (ret);
1797 1795 }
1798 1796 ret = NSS_ERROR;
1799 1797 off += ROUND_UP(len, sizeof (nssuint_t));
1800 1798
1801 1799 pbuf->key_off = (nssuint_t)off;
1802 1800 bptr = (char *)buffer + off;
1803 1801 blen = bufsize - off;
1804 1802 len = (size_t)(sizeof (nssuint_t) * 2);
1805 1803 if (len >= blen) {
1806 1804 errno = ERANGE; /* actually EINVAL */
1807 1805 return (ret);
1808 1806 }
1809 1807 nptr = (nssuint_t *)((void *)bptr);
1810 1808 *nptr++ = contextp->cookie;
1811 1809 *nptr = contextp->seq_num;
1812 1810 pbuf->key_len = (nssuint_t)len;
1813 1811
1814 1812 off += len;
1815 1813 pbuf->data_off = (nssuint_t)off;
1816 1814 pbuf->data_len = (nssuint_t)(bufsize - off);
1817 1815 return (NSS_SUCCESS);
1818 1816 }
1819 1817
1820 1818 /*
1821 1819 * Unpack packed arguments buffer
1822 1820 * Return: status, errnos and results from requested operation.
1823 1821 *
1824 1822 * NOTES: When getgroupsbymember is being processed in the NSCD backend,
1825 1823 * or via the backwards compatibility interfaces then the standard
1826 1824 * str2group API is used in conjunction with process_cstr. When,
1827 1825 * processing a returned buffer, in NSS2 the return results are the
1828 1826 * already digested groups array. Therefore, unpack the digested results
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
1829 1827 * back to the return buffer.
1830 1828 *
1831 1829 * Note: the digested results are nssuint_t quantities. _getgroupsbymember
1832 1830 * digests int quantities. Therefore convert. Assume input is in nssuint_t
1833 1831 * quantities. Store in an int array... Assume gid's are <= 32 bits...
1834 1832 */
1835 1833
1836 1834 /*ARGSUSED*/
1837 1835 nss_status_t
1838 1836 nss_unpack(void *buffer, size_t bufsize, nss_db_root_t *rootp,
1839 - nss_db_initf_t initf, int search_fnum, void *search_args)
1837 + nss_db_initf_t initf, int search_fnum, void *search_args)
1840 1838 {
1841 1839 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1842 1840 nss_XbyY_args_t *in = (nss_XbyY_args_t *)search_args;
1843 1841 nss_dbd_t *pdbd;
1844 1842 char *dbn;
1845 1843 nss_status_t status;
1846 1844 char *buf;
1847 1845 int len;
1848 1846 int ret;
1849 1847 int i;
1850 1848 int fmt_type;
1851 1849 gid_t *gidp;
1852 1850 gid_t *gptr;
1853 1851 struct nss_groupsbymem *arg;
1854 1852
1855 1853
1856 1854 if (pbuf == NULL || in == NULL)
1857 1855 return (-1);
1858 1856 status = pbuf->p_status;
1859 1857 /* Identify odd cases */
1860 1858 pdbd = (nss_dbd_t *)((void *)((char *)buffer + pbuf->dbd_off));
1861 1859 dbn = (char *)pdbd + pdbd->o_name;
1862 1860 fmt_type = 0; /* nss_XbyY_args_t */
1863 1861 if (search_fnum == NSS_DBOP_GROUP_BYMEMBER &&
1864 1862 strcmp(dbn, NSS_DBNAM_GROUP) == 0)
1865 1863 fmt_type = 1; /* struct nss_groupsbymem */
1866 1864 else if (search_fnum == NSS_DBOP_NETGROUP_IN &&
1867 1865 strcmp(dbn, NSS_DBNAM_NETGROUP) == 0)
1868 1866 fmt_type = 2; /* struct nss_innetgr_args */
1869 1867
1870 1868 /* if error - door's switch error */
1871 1869 /* extended data could contain additional information? */
1872 1870 if (status != NSS_SUCCESS) {
1873 1871 if (fmt_type == 0) {
1874 1872 in->h_errno = (int)pbuf->p_herrno;
1875 1873 if (pbuf->p_errno == ERANGE)
1876 1874 in->erange = 1;
1877 1875 }
1878 1876 return (status);
1879 1877 }
1880 1878
1881 1879 if (pbuf->data_off == 0 || pbuf->data_len == 0)
1882 1880 return (NSS_NOTFOUND);
1883 1881
1884 1882 buf = (char *)buffer + pbuf->data_off;
1885 1883 len = pbuf->data_len;
1886 1884
1887 1885 /* sidestep odd cases */
1888 1886 if (fmt_type == 1) {
1889 1887 arg = (struct nss_groupsbymem *)in;
1890 1888 /* copy returned gid array from returned nscd buffer */
1891 1889 i = len / sizeof (gid_t);
1892 1890 /* not enough buffer */
1893 1891 if (i > arg->maxgids) {
1894 1892 i = arg->maxgids;
1895 1893 }
1896 1894 arg->numgids = i;
1897 1895 gidp = arg->gid_array;
1898 1896 gptr = (gid_t *)((void *)buf);
1899 1897 (void) memcpy(gidp, gptr, len);
1900 1898 return (NSS_SUCCESS);
1901 1899 }
1902 1900 if (fmt_type == 2) {
1903 1901 struct nss_innetgr_args *arg = (struct nss_innetgr_args *)in;
1904 1902
1905 1903 if (pbuf->p_status == NSS_SUCCESS) {
1906 1904 arg->status = NSS_NETGR_FOUND;
1907 1905 return (NSS_SUCCESS);
1908 1906 } else {
1909 1907 arg->status = NSS_NETGR_NO;
1910 1908 return (NSS_NOTFOUND);
1911 1909 }
1912 1910 }
1913 1911
1914 1912 /* process the normal cases */
1915 1913 /* marshall data directly into users buffer */
1916 1914 ret = (*in->str2ent)(buf, len, in->buf.result, in->buf.buffer,
1917 1915 in->buf.buflen);
1918 1916 if (ret == NSS_STR_PARSE_ERANGE) {
1919 1917 in->returnval = 0;
1920 1918 in->returnlen = 0;
1921 1919 in->erange = 1;
1922 1920 ret = NSS_NOTFOUND;
1923 1921 } else if (ret == NSS_STR_PARSE_SUCCESS) {
1924 1922 in->returnval = in->buf.result;
1925 1923 in->returnlen = len;
1926 1924 ret = NSS_SUCCESS;
1927 1925 }
1928 1926 in->h_errno = (int)pbuf->p_herrno;
1929 1927 return ((nss_status_t)ret);
↓ open down ↓ |
80 lines elided |
↑ open up ↑ |
1930 1928 }
1931 1929
1932 1930 /*
1933 1931 * Unpack a returned packed {set,get,end}ent arguments buffer
1934 1932 * Return: status, errnos, cookie info and results from requested operation.
1935 1933 */
1936 1934
1937 1935 /*ARGSUSED*/
1938 1936 nss_status_t
1939 1937 nss_unpack_ent(void *buffer, size_t bufsize, nss_db_root_t *rootp,
1940 - nss_db_initf_t initf, nss_getent_t *contextpp, void *args)
1938 + nss_db_initf_t initf, nss_getent_t *contextpp, void *args)
1941 1939 {
1942 1940 nss_pheader_t *pbuf = (nss_pheader_t *)buffer;
1943 1941 nss_XbyY_args_t *in = (nss_XbyY_args_t *)args;
1944 1942 struct nss_getent_context *contextp = contextpp->ctx;
1945 1943 nssuint_t *nptr;
1946 1944 nssuint_t cookie;
1947 1945 nss_status_t status;
1948 1946 char *buf;
1949 1947 int len;
1950 1948 int ret;
1951 1949
1952 1950 if (pbuf == NULL)
1953 1951 return (-1);
1954 1952 status = pbuf->p_status;
1955 1953 /* if error - door's switch error */
1956 1954 /* extended data could contain additional information? */
1957 1955 if (status != NSS_SUCCESS)
1958 1956 return (status);
1959 1957
1960 1958 /* unpack assigned cookie from SET/GET/END request */
1961 1959 if (pbuf->key_off == 0 ||
1962 1960 pbuf->key_len != (sizeof (nssuint_t) * 2))
1963 1961 return (NSS_NOTFOUND);
1964 1962
1965 1963 nptr = (nssuint_t *)((void *)((char *)buffer + pbuf->key_off));
1966 1964 cookie = contextp->cookie;
1967 1965 if (cookie != NSCD_NEW_COOKIE && cookie != contextp->cookie_setent &&
1968 1966 cookie != *nptr) {
1969 1967 /*
1970 1968 * Should either be new, or the cookie returned by the last
1971 1969 * setent (i.e., this is the first getent after the setent)
1972 1970 * or a match, else error
1973 1971 */
1974 1972 return (NSS_NOTFOUND);
1975 1973 }
1976 1974 /* save away for the next ent request */
1977 1975 contextp->cookie = *nptr++;
1978 1976 contextp->seq_num = *nptr;
1979 1977
1980 1978 /* All done if no marshalling is expected {set,end}ent */
1981 1979 if (args == NULL)
1982 1980 return (NSS_SUCCESS);
1983 1981
1984 1982 /* unmarshall the data */
1985 1983 if (pbuf->data_off == 0 || pbuf->data_len == 0)
1986 1984 return (NSS_NOTFOUND);
1987 1985 buf = (char *)buffer + pbuf->data_off;
1988 1986
1989 1987 len = pbuf->data_len;
1990 1988
1991 1989 /* marshall data directly into users buffer */
1992 1990 ret = (*in->str2ent)(buf, len, in->buf.result, in->buf.buffer,
1993 1991 in->buf.buflen);
1994 1992 if (ret == NSS_STR_PARSE_ERANGE) {
1995 1993 in->returnval = 0;
1996 1994 in->returnlen = 0;
1997 1995 in->erange = 1;
1998 1996 } else if (ret == NSS_STR_PARSE_SUCCESS) {
1999 1997 in->returnval = in->buf.result;
2000 1998 in->returnlen = len;
2001 1999 }
↓ open down ↓ |
51 lines elided |
↑ open up ↑ |
2002 2000 in->h_errno = (int)pbuf->p_herrno;
2003 2001 return ((nss_status_t)ret);
2004 2002 }
2005 2003
2006 2004 /*
2007 2005 * Start of _nsc_{search|setent_u|getent_u|endent_u} NSCD interposition funcs
2008 2006 */
2009 2007
2010 2008 nss_status_t
2011 2009 _nsc_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum,
2012 - void *search_args)
2010 + void *search_args)
2013 2011 {
2014 2012 nss_pheader_t *pbuf;
2015 2013 void *doorptr = NULL;
2016 2014 size_t bufsize = 0;
2017 2015 size_t datasize = 0;
2018 2016 nss_status_t status;
2019 2017
2020 2018 if (_nsc_proc_is_cache() > 0) {
2021 2019 /* internal nscd call - don't use the door */
2022 2020 return (NSS_TRYLOCAL);
2023 2021 }
2024 2022
2025 2023 /* standard client calls nscd code */
2026 2024 if (search_args == NULL)
2027 2025 return (NSS_NOTFOUND);
2028 2026
2029 2027 /* get the door buffer & configured size */
2030 2028 bufsize = ((nss_XbyY_args_t *)search_args)->buf.buflen;
2031 2029 if (_nsc_getdoorbuf(&doorptr, &bufsize) != 0)
2032 2030 return (NSS_TRYLOCAL);
2033 2031 if (doorptr == NULL || bufsize == 0)
2034 2032 return (NSS_TRYLOCAL);
2035 2033
2036 2034 pbuf = (nss_pheader_t *)doorptr;
2037 2035 /* pack argument and request into door buffer */
2038 2036 pbuf->nsc_callnumber = NSCD_SEARCH;
2039 2037 /* copy relevant door request info into door buffer */
2040 2038 status = nss_pack((void *)pbuf, bufsize, rootp,
2041 2039 initf, search_fnum, search_args);
2042 2040
2043 2041 /* Packing error return error results */
2044 2042 if (status != NSS_SUCCESS)
2045 2043 return (status);
2046 2044
2047 2045 /* transfer packed switch request to nscd via door */
2048 2046 /* data_off can be used because it is header+dbd_len+key_len */
2049 2047 datasize = pbuf->data_off;
2050 2048 status = _nsc_trydoorcall_ext(&doorptr, &bufsize, &datasize);
2051 2049
2052 2050 /* If unsuccessful fallback to standard nss logic */
2053 2051 if (status != NSS_SUCCESS) {
2054 2052 /*
2055 2053 * check if doors reallocated the memory underneath us
2056 2054 * if they did munmap it or suffer a memory leak
2057 2055 */
2058 2056 if (doorptr != (void *)pbuf) {
2059 2057 _nsc_resizedoorbuf(bufsize);
2060 2058 (void) munmap((void *)doorptr, bufsize);
2061 2059 }
2062 2060 return (NSS_TRYLOCAL);
2063 2061 }
2064 2062
2065 2063 /* unpack and marshall data/errors to user structure */
2066 2064 /* set any error conditions */
2067 2065 status = nss_unpack((void *)doorptr, bufsize, rootp, initf,
2068 2066 search_fnum, search_args);
2069 2067 /*
2070 2068 * check if doors reallocated the memory underneath us
2071 2069 * if they did munmap it or suffer a memory leak
2072 2070 */
2073 2071 if (doorptr != (void *)pbuf) {
2074 2072 _nsc_resizedoorbuf(bufsize);
2075 2073 (void) munmap((void *)doorptr, bufsize);
2076 2074 }
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
2077 2075 return (status);
2078 2076 }
2079 2077
2080 2078 /*
2081 2079 * contact nscd for a cookie or to reset an existing cookie
2082 2080 * if nscd fails (NSS_TRYLOCAL) then set cookie to -1 and
2083 2081 * continue diverting to local
2084 2082 */
2085 2083 nss_status_t
2086 2084 _nsc_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
2087 - nss_getent_t *contextpp)
2085 + nss_getent_t *contextpp)
2088 2086 {
2089 2087 nss_status_t status = NSS_TRYLOCAL;
2090 2088 struct nss_getent_context *contextp = contextpp->ctx;
2091 2089 nss_pheader_t *pbuf;
2092 2090 void *doorptr = NULL;
2093 2091 size_t bufsize = 0;
2094 2092 size_t datasize = 0;
2095 2093
2096 2094 /* return if already in local mode */
2097 2095 if (contextp->cookie == NSCD_LOCAL_COOKIE)
2098 2096 return (NSS_TRYLOCAL);
2099 2097
2100 2098 if (_nsc_proc_is_cache() > 0) {
2101 2099 /* internal nscd call - don't try to use the door */
2102 2100 contextp->cookie = NSCD_LOCAL_COOKIE;
2103 2101 return (NSS_TRYLOCAL);
2104 2102 }
2105 2103
2106 2104 /* get the door buffer & configured size */
2107 2105 if (_nsc_getdoorbuf(&doorptr, &bufsize) != 0) {
2108 2106 contextp->cookie = NSCD_LOCAL_COOKIE;
2109 2107 return (NSS_TRYLOCAL);
2110 2108 }
2111 2109 if (doorptr == NULL || bufsize == 0) {
2112 2110 contextp->cookie = NSCD_LOCAL_COOKIE;
2113 2111 return (NSS_TRYLOCAL);
2114 2112 }
2115 2113
2116 2114 pbuf = (nss_pheader_t *)doorptr;
2117 2115 pbuf->nsc_callnumber = NSCD_SETENT;
2118 2116
2119 2117 contextp->param.cleanup = NULL;
2120 2118 (*initf)(&contextp->param);
2121 2119 if (contextp->param.name == 0) {
2122 2120 if (contextp->param.cleanup != 0)
2123 2121 (contextp->param.cleanup)(&contextp->param);
2124 2122 errno = ERANGE; /* actually EINVAL */
2125 2123 return (NSS_ERROR);
2126 2124 }
2127 2125
2128 2126 /* pack relevant setent request info into door buffer */
2129 2127 status = nss_pack_ent((void *)pbuf, bufsize, rootp, initf, contextpp);
2130 2128 if (status != NSS_SUCCESS)
2131 2129 return (status);
2132 2130
2133 2131 /* transfer packed switch request to nscd via door */
2134 2132 /* data_off can be used because it is header+dbd_len+key_len */
2135 2133 datasize = pbuf->data_off;
2136 2134 status = _nsc_trydoorcall_ext(&doorptr, &bufsize, &datasize);
2137 2135
2138 2136 /* If fallback to standard nss logic (door failure) if possible */
2139 2137 if (status != NSS_SUCCESS) {
2140 2138 if (contextp->cookie == NSCD_NEW_COOKIE) {
2141 2139 contextp->cookie = NSCD_LOCAL_COOKIE;
2142 2140 return (NSS_TRYLOCAL);
2143 2141 }
2144 2142 return (NSS_UNAVAIL);
2145 2143 }
2146 2144 /* unpack returned cookie stash it away */
2147 2145 status = nss_unpack_ent((void *)doorptr, bufsize, rootp,
2148 2146 initf, contextpp, NULL);
2149 2147 /* save the setent cookie for later use */
2150 2148 contextp->cookie_setent = contextp->cookie;
2151 2149 /*
2152 2150 * check if doors reallocated the memory underneath us
2153 2151 * if they did munmap it or suffer a memory leak
↓ open down ↓ |
56 lines elided |
↑ open up ↑ |
2154 2152 */
2155 2153 if (doorptr != (void *)pbuf) {
2156 2154 _nsc_resizedoorbuf(bufsize);
2157 2155 (void) munmap((void *)doorptr, bufsize);
2158 2156 }
2159 2157 return (status);
2160 2158 }
2161 2159
2162 2160 nss_status_t
2163 2161 _nsc_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
2164 - nss_getent_t *contextpp, void *args)
2162 + nss_getent_t *contextpp, void *args)
2165 2163 {
2166 2164 nss_status_t status = NSS_TRYLOCAL;
2167 2165 struct nss_getent_context *contextp = contextpp->ctx;
2168 2166 nss_pheader_t *pbuf;
2169 2167 void *doorptr = NULL;
2170 2168 size_t bufsize = 0;
2171 2169 size_t datasize = 0;
2172 2170
2173 2171 /* return if already in local mode */
2174 2172 if (contextp->cookie == NSCD_LOCAL_COOKIE)
2175 2173 return (NSS_TRYLOCAL);
2176 2174
2177 2175 /* _nsc_setent_u already checked for nscd local case ... proceed */
2178 2176 if (args == NULL)
2179 2177 return (NSS_NOTFOUND);
2180 2178
2181 2179 /* get the door buffer & configured size */
2182 2180 bufsize = ((nss_XbyY_args_t *)args)->buf.buflen;
2183 2181 if (_nsc_getdoorbuf(&doorptr, &bufsize) != 0)
2184 2182 return (NSS_UNAVAIL);
2185 2183 if (doorptr == NULL || bufsize == 0)
2186 2184 return (NSS_UNAVAIL);
2187 2185
2188 2186 pbuf = (nss_pheader_t *)doorptr;
2189 2187 pbuf->nsc_callnumber = NSCD_GETENT;
2190 2188
2191 2189 /* pack relevant setent request info into door buffer */
2192 2190 status = nss_pack_ent((void *)pbuf, bufsize, rootp, initf, contextpp);
2193 2191 if (status != NSS_SUCCESS)
2194 2192 return (status);
2195 2193
2196 2194 /* transfer packed switch request to nscd via door */
2197 2195 /* data_off can be used because it is header+dbd_len+key_len */
2198 2196 datasize = pbuf->data_off;
2199 2197 status = _nsc_trydoorcall_ext(&doorptr, &bufsize, &datasize);
2200 2198
2201 2199 /* If fallback to standard nss logic (door failure) if possible */
2202 2200 if (status != NSS_SUCCESS) {
2203 2201 if (status == NSS_TRYLOCAL ||
2204 2202 contextp->cookie == NSCD_NEW_COOKIE) {
2205 2203 contextp->cookie = NSCD_LOCAL_COOKIE;
2206 2204
2207 2205 /* init the local cookie */
2208 2206 nss_setent_u(rootp, initf, contextpp);
2209 2207 if (contextpp->ctx == 0)
2210 2208 return (NSS_UNAVAIL);
2211 2209 return (NSS_TRYLOCAL);
2212 2210 }
2213 2211 return (NSS_UNAVAIL);
2214 2212 }
2215 2213 /* check error, unpack and process results */
2216 2214 status = nss_unpack_ent((void *)doorptr, bufsize, rootp,
2217 2215 initf, contextpp, args);
2218 2216 /*
2219 2217 * check if doors reallocated the memory underneath us
2220 2218 * if they did munmap it or suffer a memory leak
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
2221 2219 */
2222 2220 if (doorptr != (void *)pbuf) {
2223 2221 _nsc_resizedoorbuf(bufsize);
2224 2222 (void) munmap((void *)doorptr, bufsize);
2225 2223 }
2226 2224 return (status);
2227 2225 }
2228 2226
2229 2227 nss_status_t
2230 2228 _nsc_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf,
2231 - nss_getent_t *contextpp)
2229 + nss_getent_t *contextpp)
2232 2230 {
2233 2231 nss_status_t status = NSS_TRYLOCAL;
2234 2232 struct nss_getent_context *contextp = contextpp->ctx;
2235 2233 nss_pheader_t *pbuf;
2236 2234 void *doorptr = NULL;
2237 2235 size_t bufsize = 0;
2238 2236 size_t datasize = 0;
2239 2237
2240 2238 /* return if already in local mode */
2241 2239 if (contextp->cookie == NSCD_LOCAL_COOKIE)
2242 2240 return (NSS_TRYLOCAL);
2243 2241
2244 2242 /* _nsc_setent_u already checked for nscd local case ... proceed */
2245 2243
2246 2244 /* get the door buffer & configured size */
2247 2245 if (_nsc_getdoorbuf(&doorptr, &bufsize) != 0)
2248 2246 return (NSS_UNAVAIL);
2249 2247 if (doorptr == NULL || bufsize == 0)
2250 2248 return (NSS_UNAVAIL);
2251 2249
2252 2250 /* pack up a NSCD_ENDGET request passing in the cookie */
2253 2251 pbuf = (nss_pheader_t *)doorptr;
2254 2252 pbuf->nsc_callnumber = NSCD_ENDENT;
2255 2253
2256 2254 /* pack relevant setent request info into door buffer */
2257 2255 status = nss_pack_ent((void *)pbuf, bufsize, rootp, initf, contextpp);
2258 2256 if (status != NSS_SUCCESS)
2259 2257 return (status);
2260 2258
2261 2259 /* transfer packed switch request to nscd via door */
2262 2260 /* data_off can be used because it is header+dbd_len+key_len */
2263 2261 datasize = pbuf->data_off;
2264 2262 (void) _nsc_trydoorcall_ext(&doorptr, &bufsize, &datasize);
2265 2263
2266 2264 /* error codes & unpacking ret values don't matter. We're done */
2267 2265
2268 2266 /*
2269 2267 * check if doors reallocated the memory underneath us
2270 2268 * if they did munmap it or suffer a memory leak
2271 2269 */
2272 2270 if (doorptr != (void *)pbuf) {
2273 2271 _nsc_resizedoorbuf(bufsize);
2274 2272 (void) munmap((void *)doorptr, bufsize);
2275 2273 }
2276 2274
2277 2275 /* clean up initf setup */
2278 2276 if (contextp->param.cleanup != 0)
2279 2277 (contextp->param.cleanup)(&contextp->param);
2280 2278 contextp->param.cleanup = NULL;
2281 2279
2282 2280 /* clear cookie */
2283 2281 contextp->cookie = NSCD_NEW_COOKIE;
2284 2282 return (NSS_SUCCESS);
2285 2283 }
2286 2284
2287 2285 /*
2288 2286 * Internal private API to return default suggested buffer sizes
2289 2287 * for nsswitch API requests.
2290 2288 */
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
2291 2289
2292 2290 size_t
2293 2291 _nss_get_bufsizes(int arg)
2294 2292 {
2295 2293 switch (arg) {
2296 2294 case _SC_GETGR_R_SIZE_MAX:
2297 2295 return (__nss_buflen_group);
2298 2296 }
2299 2297 return (__nss_buflen_default);
2300 2298 }
2299 +
2300 +void *
2301 +_nss_XbyY_fini(nss_XbyY_args_t *args)
2302 +{
2303 + if ((args->returnval == NULL) && (args->erange != 0))
2304 + errno = ERANGE;
2305 + return (args->returnval);
2306 +}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX