1 /*-
2 * Copyright (c) 2009, Sun Microsystems, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of Sun Microsystems, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro
29 * $NetBSD: getrpcent.c,v 1.17 2000/01/22 22:19:17 mycroft Exp $
30 * $FreeBSD: src/lib/libc/rpc/getrpcent.c,v 1.16 2007/05/17 03:34:33 jon Exp $
31 */
32
33 /*
34 * Copyright (c) 1984 by Sun Microsystems, Inc.
35 */
36
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <arpa/inet.h>
41 #include <assert.h>
42 #include <errno.h>
43 #include <nsswitch.h>
44 #include <netinet/in.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdarg.h>
48 #include <stdlib.h>
49 #include <rpc/rpc.h>
50 #ifdef YP
51 #include <rpcsvc/yp_prot.h>
52 #include <rpcsvc/ypclnt.h>
53 #endif
54 #include <unistd.h>
55 #include "namespace.h"
56 #include "reentrant.h"
57 #include "un-namespace.h"
58 #include "libc_private.h"
59 #include "nss_tls.h"
60 #ifdef NS_CACHING
61 #include "nscache.h"
62 #endif
63
64 #define RPCDB "/etc/rpc"
65
66 /* nsswitch declarations */
67 enum constants
68 {
69 SETRPCENT = 1,
70 ENDRPCENT = 2,
71 RPCENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
72 RPCENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
73 };
74
75 static const ns_src defaultsrc[] = {
76 { NSSRC_FILES, NS_SUCCESS },
77 #ifdef YP
78 { NSSRC_NIS, NS_SUCCESS },
79 #endif
80 { NULL, 0 }
81 };
82
83 /* files backend declarations */
84 struct files_state {
85 FILE *fp;
86 int stayopen;
87 };
88
89 static int files_rpcent(void *, void *, va_list);
90 static int files_setrpcent(void *, void *, va_list);
91
92 static void files_endstate(void *);
93 NSS_TLS_HANDLING(files);
94
95 /* nis backend declarations */
96 #ifdef YP
97 struct nis_state {
98 char domain[MAXHOSTNAMELEN];
99 char *current;
100 int currentlen;
101 int stepping;
102 int no_name_map;
103 };
104
105 static int nis_rpcent(void *, void *, va_list);
106 static int nis_setrpcent(void *, void *, va_list);
107
108 static void nis_endstate(void *);
109 NSS_TLS_HANDLING(nis);
110 #endif
111
112 /* get** wrappers for get**_r functions declarations */
113 struct rpcent_state {
114 struct rpcent rpc;
115 char *buffer;
116 size_t bufsize;
117 };
118 static void rpcent_endstate(void *);
119 NSS_TLS_HANDLING(rpcent);
120
121 union key {
122 const char *name;
123 int number;
124 };
125
126 static int wrap_getrpcbyname_r(union key, struct rpcent *, char *,
127 size_t, struct rpcent **);
128 static int wrap_getrpcbynumber_r(union key, struct rpcent *, char *,
129 size_t, struct rpcent **);
130 static int wrap_getrpcent_r(union key, struct rpcent *, char *,
131 size_t, struct rpcent **);
132 static struct rpcent *getrpc(int (*fn)(union key, struct rpcent *, char *,
133 size_t, struct rpcent **), union key);
134
135 #ifdef NS_CACHING
136 static int rpc_id_func(char *, size_t *, va_list, void *);
137 static int rpc_marshal_func(char *, size_t *, void *, va_list, void *);
138 static int rpc_unmarshal_func(char *, size_t, void *, va_list, void *);
139 #endif
140
141 static int
rpcent_unpack(char * p,struct rpcent * rpc,char ** r_aliases,size_t aliases_size,int * errnop)142 rpcent_unpack(char *p, struct rpcent *rpc, char **r_aliases,
143 size_t aliases_size, int *errnop)
144 {
145 char *cp, **q;
146
147 assert(p != NULL);
148
149 if (*p == '#')
150 return (-1);
151 cp = strpbrk(p, "#\n");
152 if (cp == NULL)
153 return (-1);
154 *cp = '\0';
155 cp = strpbrk(p, " \t");
156 if (cp == NULL)
157 return (-1);
158 *cp++ = '\0';
159 /* THIS STUFF IS INTERNET SPECIFIC */
160 rpc->r_name = p;
161 while (*cp == ' ' || *cp == '\t')
162 cp++;
163 rpc->r_number = atoi(cp);
164 q = rpc->r_aliases = r_aliases;
165 cp = strpbrk(cp, " \t");
166 if (cp != NULL)
167 *cp++ = '\0';
168 while (cp && *cp) {
169 if (*cp == ' ' || *cp == '\t') {
170 cp++;
171 continue;
172 }
173 if (q < &(r_aliases[aliases_size - 1]))
174 *q++ = cp;
175 else {
176 *errnop = ERANGE;
177 return -1;
178 }
179
180 cp = strpbrk(cp, " \t");
181 if (cp != NULL)
182 *cp++ = '\0';
183 }
184 *q = NULL;
185 return 0;
186 }
187
188 /* files backend implementation */
189 static void
files_endstate(void * p)190 files_endstate(void *p)
191 {
192 FILE * f;
193
194 if (p == NULL)
195 return;
196
197 f = ((struct files_state *)p)->fp;
198 if (f != NULL)
199 fclose(f);
200
201 free(p);
202 }
203
204 static int
files_rpcent(void * retval,void * mdata,va_list ap)205 files_rpcent(void *retval, void *mdata, va_list ap)
206 {
207 char *name;
208 int number;
209 struct rpcent *rpc;
210 char *buffer;
211 size_t bufsize;
212 int *errnop;
213
214 char *line;
215 size_t linesize;
216 char **aliases;
217 int aliases_size;
218 char **rp;
219
220 struct files_state *st;
221 int rv;
222 int stayopen;
223 enum nss_lookup_type how;
224
225 how = (enum nss_lookup_type)mdata;
226 switch (how)
227 {
228 case nss_lt_name:
229 name = va_arg(ap, char *);
230 break;
231 case nss_lt_id:
232 number = va_arg(ap, int);
233 break;
234 case nss_lt_all:
235 break;
236 default:
237 return (NS_NOTFOUND);
238 }
239
240 rpc = va_arg(ap, struct rpcent *);
241 buffer = va_arg(ap, char *);
242 bufsize = va_arg(ap, size_t);
243 errnop = va_arg(ap, int *);
244
245 *errnop = files_getstate(&st);
246 if (*errnop != 0)
247 return (NS_UNAVAIL);
248
249 if (st->fp == NULL && (st->fp = fopen(RPCDB, "r")) == NULL) {
250 *errnop = errno;
251 return (NS_UNAVAIL);
252 }
253
254 if (how == nss_lt_all)
255 stayopen = 1;
256 else {
257 rewind(st->fp);
258 stayopen = st->stayopen;
259 }
260
261 do {
262 if ((line = fgetln(st->fp, &linesize)) == NULL) {
263 *errnop = errno;
264 rv = NS_RETURN;
265 break;
266 }
267
268 if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) {
269 *errnop = ERANGE;
270 rv = NS_RETURN;
271 break;
272 }
273
274 aliases = (char **)_ALIGN(&buffer[linesize+1]);
275 aliases_size = (buffer + bufsize -
276 (char *)aliases)/sizeof(char *);
277 if (aliases_size < 1) {
278 *errnop = ERANGE;
279 rv = NS_RETURN;
280 break;
281 }
282
283 memcpy(buffer, line, linesize);
284 buffer[linesize] = '\0';
285
286 rv = rpcent_unpack(buffer, rpc, aliases, aliases_size, errnop);
287 if (rv != 0) {
288 if (*errnop == 0) {
289 rv = NS_NOTFOUND;
290 continue;
291 }
292 else {
293 rv = NS_RETURN;
294 break;
295 }
296 }
297
298 switch (how)
299 {
300 case nss_lt_name:
301 if (strcmp(rpc->r_name, name) == 0)
302 goto done;
303 for (rp = rpc->r_aliases; *rp != NULL; rp++) {
304 if (strcmp(*rp, name) == 0)
305 goto done;
306 }
307 rv = NS_NOTFOUND;
308 continue;
309 done:
310 rv = NS_SUCCESS;
311 break;
312 case nss_lt_id:
313 rv = (rpc->r_number == number) ? NS_SUCCESS :
314 NS_NOTFOUND;
315 break;
316 case nss_lt_all:
317 rv = NS_SUCCESS;
318 break;
319 }
320
321 } while (!(rv & NS_TERMINATE));
322
323 if (!stayopen && st->fp!=NULL) {
324 fclose(st->fp);
325 st->fp = NULL;
326 }
327
328 if ((rv == NS_SUCCESS) && (retval != NULL))
329 *((struct rpcent **)retval) = rpc;
330
331 return (rv);
332 }
333
334 static int
files_setrpcent(void * retval __unused,void * mdata,va_list ap)335 files_setrpcent(void *retval __unused, void *mdata, va_list ap)
336 {
337 struct files_state *st;
338 int rv;
339 int f;
340
341 rv = files_getstate(&st);
342 if (rv != 0)
343 return (NS_UNAVAIL);
344
345 switch ((enum constants)mdata)
346 {
347 case SETRPCENT:
348 f = va_arg(ap,int);
349 if (st->fp == NULL)
350 st->fp = fopen(RPCDB, "r");
351 else
352 rewind(st->fp);
353 st->stayopen |= f;
354 break;
355 case ENDRPCENT:
356 if (st->fp != NULL) {
357 fclose(st->fp);
358 st->fp = NULL;
359 }
360 st->stayopen = 0;
361 break;
362 default:
363 break;
364 }
365
366 return (NS_UNAVAIL);
367 }
368
369 /* nis backend implementation */
370 #ifdef YP
371 static void
nis_endstate(void * p)372 nis_endstate(void *p)
373 {
374 if (p == NULL)
375 return;
376
377 free(((struct nis_state *)p)->current);
378 free(p);
379 }
380
381 static int
nis_rpcent(void * retval,void * mdata,va_list ap)382 nis_rpcent(void *retval, void *mdata, va_list ap)
383 {
384 char *name;
385 int number;
386 struct rpcent *rpc;
387 char *buffer;
388 size_t bufsize;
389 int *errnop;
390
391 char **rp;
392 char **aliases;
393 int aliases_size;
394
395 char *lastkey;
396 char *resultbuf;
397 int resultbuflen;
398 char buf[YPMAXRECORD + 2];
399
400 struct nis_state *st;
401 int rv;
402 enum nss_lookup_type how;
403 int no_name_active;
404
405 how = (enum nss_lookup_type)mdata;
406 switch (how)
407 {
408 case nss_lt_name:
409 name = va_arg(ap, char *);
410 break;
411 case nss_lt_id:
412 number = va_arg(ap, int);
413 break;
414 case nss_lt_all:
415 break;
416 default:
417 return (NS_NOTFOUND);
418 }
419
420 rpc = va_arg(ap, struct rpcent *);
421 buffer = va_arg(ap, char *);
422 bufsize = va_arg(ap, size_t);
423 errnop = va_arg(ap, int *);
424
425 *errnop = nis_getstate(&st);
426 if (*errnop != 0)
427 return (NS_UNAVAIL);
428
429 if (st->domain[0] == '\0') {
430 if (getdomainname(st->domain, sizeof(st->domain)) != 0) {
431 *errnop = errno;
432 return (NS_UNAVAIL);
433 }
434 }
435
436 no_name_active = 0;
437 do {
438 switch (how)
439 {
440 case nss_lt_name:
441 if (!st->no_name_map)
442 {
443 snprintf(buf, sizeof buf, "%s", name);
444 rv = yp_match(st->domain, "rpc.byname", buf,
445 strlen(buf), &resultbuf, &resultbuflen);
446
447 switch (rv) {
448 case 0:
449 break;
450 case YPERR_MAP:
451 st->stepping = 0;
452 no_name_active = 1;
453 how = nss_lt_all;
454
455 rv = NS_NOTFOUND;
456 continue;
457 default:
458 rv = NS_NOTFOUND;
459 goto fin;
460 }
461 } else {
462 st->stepping = 0;
463 no_name_active = 1;
464 how = nss_lt_all;
465
466 rv = NS_NOTFOUND;
467 continue;
468 }
469 break;
470 case nss_lt_id:
471 snprintf(buf, sizeof buf, "%d", number);
472 if (yp_match(st->domain, "rpc.bynumber", buf,
473 strlen(buf), &resultbuf, &resultbuflen)) {
474 rv = NS_NOTFOUND;
475 goto fin;
476 }
477 break;
478 case nss_lt_all:
479 if (!st->stepping) {
480 rv = yp_first(st->domain, "rpc.bynumber",
481 &st->current,
482 &st->currentlen, &resultbuf,
483 &resultbuflen);
484 if (rv) {
485 rv = NS_NOTFOUND;
486 goto fin;
487 }
488 st->stepping = 1;
489 } else {
490 lastkey = st->current;
491 rv = yp_next(st->domain, "rpc.bynumber",
492 st->current,
493 st->currentlen, &st->current,
494 &st->currentlen,
495 &resultbuf, &resultbuflen);
496 free(lastkey);
497 if (rv) {
498 st->stepping = 0;
499 rv = NS_NOTFOUND;
500 goto fin;
501 }
502 }
503 break;
504 }
505
506 /* we need a room for additional \n symbol */
507 if (bufsize <= resultbuflen + 1 + _ALIGNBYTES +
508 sizeof(char *)) {
509 *errnop = ERANGE;
510 rv = NS_RETURN;
511 break;
512 }
513
514 aliases=(char **)_ALIGN(&buffer[resultbuflen+2]);
515 aliases_size = (buffer + bufsize - (char *)aliases) /
516 sizeof(char *);
517 if (aliases_size < 1) {
518 *errnop = ERANGE;
519 rv = NS_RETURN;
520 break;
521 }
522
523 /*
524 * rpcent_unpack expects lines terminated with \n -- make it happy
525 */
526 memcpy(buffer, resultbuf, resultbuflen);
527 buffer[resultbuflen] = '\n';
528 buffer[resultbuflen+1] = '\0';
529 free(resultbuf);
530
531 if (rpcent_unpack(buffer, rpc, aliases, aliases_size,
532 errnop) != 0) {
533 if (*errnop == 0)
534 rv = NS_NOTFOUND;
535 else
536 rv = NS_RETURN;
537 } else {
538 if ((how == nss_lt_all) && (no_name_active != 0)) {
539 if (strcmp(rpc->r_name, name) == 0)
540 goto done;
541 for (rp = rpc->r_aliases; *rp != NULL; rp++) {
542 if (strcmp(*rp, name) == 0)
543 goto done;
544 }
545 rv = NS_NOTFOUND;
546 continue;
547 done:
548 rv = NS_SUCCESS;
549 } else
550 rv = NS_SUCCESS;
551 }
552
553 } while (!(rv & NS_TERMINATE) && (how == nss_lt_all));
554
555 fin:
556 if ((rv == NS_SUCCESS) && (retval != NULL))
557 *((struct rpcent **)retval) = rpc;
558
559 return (rv);
560 }
561
562 static int
nis_setrpcent(void * retval __unused,void * mdata,va_list ap __unused)563 nis_setrpcent(void *retval __unused, void *mdata, va_list ap __unused)
564 {
565 struct nis_state *st;
566 int rv;
567
568 rv = nis_getstate(&st);
569 if (rv != 0)
570 return (NS_UNAVAIL);
571
572 switch ((enum constants)mdata)
573 {
574 case SETRPCENT:
575 case ENDRPCENT:
576 free(st->current);
577 st->current = NULL;
578 st->stepping = 0;
579 break;
580 default:
581 break;
582 }
583
584 return (NS_UNAVAIL);
585 }
586 #endif
587
588 #ifdef NS_CACHING
589 static int
rpc_id_func(char * buffer,size_t * buffer_size,va_list ap,void * cache_mdata)590 rpc_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
591 {
592 char *name;
593 int rpc;
594
595 size_t desired_size, size;
596 enum nss_lookup_type lookup_type;
597 int res = NS_UNAVAIL;
598
599 lookup_type = (enum nss_lookup_type)cache_mdata;
600 switch (lookup_type) {
601 case nss_lt_name:
602 name = va_arg(ap, char *);
603
604 size = strlen(name);
605 desired_size = sizeof(enum nss_lookup_type) + size + 1;
606 if (desired_size > *buffer_size) {
607 res = NS_RETURN;
608 goto fin;
609 }
610
611 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
612 memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
613
614 res = NS_SUCCESS;
615 break;
616 case nss_lt_id:
617 rpc = va_arg(ap, int);
618
619 desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
620 if (desired_size > *buffer_size) {
621 res = NS_RETURN;
622 goto fin;
623 }
624
625 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
626 memcpy(buffer + sizeof(enum nss_lookup_type), &rpc,
627 sizeof(int));
628
629 res = NS_SUCCESS;
630 break;
631 default:
632 /* should be unreachable */
633 return (NS_UNAVAIL);
634 }
635
636 fin:
637 *buffer_size = desired_size;
638 return (res);
639 }
640
641 static int
rpc_marshal_func(char * buffer,size_t * buffer_size,void * retval __unused,va_list ap,void * cache_mdata)642 rpc_marshal_func(char *buffer, size_t *buffer_size, void *retval __unused,
643 va_list ap, void *cache_mdata)
644 {
645 char *name __unused;
646 int num __unused;
647 struct rpcent *rpc;
648 char *orig_buf __unused;
649 size_t orig_buf_size __unused;
650
651 struct rpcent new_rpc;
652 size_t desired_size, size, aliases_size;
653 char *p;
654 char **alias;
655
656 switch ((enum nss_lookup_type)cache_mdata) {
657 case nss_lt_name:
658 name = va_arg(ap, char *);
659 break;
660 case nss_lt_id:
661 num = va_arg(ap, int);
662 break;
663 case nss_lt_all:
664 break;
665 default:
666 /* should be unreachable */
667 return (NS_UNAVAIL);
668 }
669
670 rpc = va_arg(ap, struct rpcent *);
671 orig_buf = va_arg(ap, char *);
672 orig_buf_size = va_arg(ap, size_t);
673
674 desired_size = _ALIGNBYTES + sizeof(struct rpcent) + sizeof(char *);
675 if (rpc->r_name != NULL)
676 desired_size += strlen(rpc->r_name) + 1;
677
678 if (rpc->r_aliases != NULL) {
679 aliases_size = 0;
680 for (alias = rpc->r_aliases; *alias; ++alias) {
681 desired_size += strlen(*alias) + 1;
682 ++aliases_size;
683 }
684
685 desired_size += _ALIGNBYTES + (aliases_size + 1) *
686 sizeof(char *);
687 }
688
689 if (*buffer_size < desired_size) {
690 /* this assignment is here for future use */
691 *buffer_size = desired_size;
692 return (NS_RETURN);
693 }
694
695 memcpy(&new_rpc, rpc, sizeof(struct rpcent));
696
697 *buffer_size = desired_size;
698 memset(buffer, 0, desired_size);
699 p = buffer + sizeof(struct rpcent) + sizeof(char *);
700 memcpy(buffer + sizeof(struct rpcent), &p, sizeof(char *));
701 p = (char *)_ALIGN(p);
702
703 if (new_rpc.r_name != NULL) {
704 size = strlen(new_rpc.r_name);
705 memcpy(p, new_rpc.r_name, size);
706 new_rpc.r_name = p;
707 p += size + 1;
708 }
709
710 if (new_rpc.r_aliases != NULL) {
711 p = (char *)_ALIGN(p);
712 memcpy(p, new_rpc.r_aliases, sizeof(char *) * aliases_size);
713 new_rpc.r_aliases = (char **)p;
714 p += sizeof(char *) * (aliases_size + 1);
715
716 for (alias = new_rpc.r_aliases; *alias; ++alias) {
717 size = strlen(*alias);
718 memcpy(p, *alias, size);
719 *alias = p;
720 p += size + 1;
721 }
722 }
723
724 memcpy(buffer, &new_rpc, sizeof(struct rpcent));
725 return (NS_SUCCESS);
726 }
727
728 static int
rpc_unmarshal_func(char * buffer,size_t buffer_size,void * retval,va_list ap,void * cache_mdata)729 rpc_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
730 void *cache_mdata)
731 {
732 char *name __unused;
733 int num __unused;
734 struct rpcent *rpc;
735 char *orig_buf;
736 size_t orig_buf_size;
737 int *ret_errno;
738
739 char *p;
740 char **alias;
741
742 switch ((enum nss_lookup_type)cache_mdata) {
743 case nss_lt_name:
744 name = va_arg(ap, char *);
745 break;
746 case nss_lt_id:
747 num = va_arg(ap, int);
748 break;
749 case nss_lt_all:
750 break;
751 default:
752 /* should be unreachable */
753 return (NS_UNAVAIL);
754 }
755
756 rpc = va_arg(ap, struct rpcent *);
757 orig_buf = va_arg(ap, char *);
758 orig_buf_size = va_arg(ap, size_t);
759 ret_errno = va_arg(ap, int *);
760
761 if (orig_buf_size <
762 buffer_size - sizeof(struct rpcent) - sizeof(char *)) {
763 *ret_errno = ERANGE;
764 return (NS_RETURN);
765 }
766
767 memcpy(rpc, buffer, sizeof(struct rpcent));
768 memcpy(&p, buffer + sizeof(struct rpcent), sizeof(char *));
769
770 orig_buf = (char *)_ALIGN(orig_buf);
771 memcpy(orig_buf, buffer + sizeof(struct rpcent) + sizeof(char *) +
772 _ALIGN(p) - (size_t)p,
773 buffer_size - sizeof(struct rpcent) - sizeof(char *) -
774 _ALIGN(p) + (size_t)p);
775 p = (char *)_ALIGN(p);
776
777 NS_APPLY_OFFSET(rpc->r_name, orig_buf, p, char *);
778 if (rpc->r_aliases != NULL) {
779 NS_APPLY_OFFSET(rpc->r_aliases, orig_buf, p, char **);
780
781 for (alias = rpc->r_aliases ; *alias; ++alias)
782 NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
783 }
784
785 if (retval != NULL)
786 *((struct rpcent **)retval) = rpc;
787
788 return (NS_SUCCESS);
789 }
790
791 NSS_MP_CACHE_HANDLING(rpc);
792 #endif /* NS_CACHING */
793
794
795 /* get**_r functions implementation */
796 static int
getrpcbyname_r(const char * name,struct rpcent * rpc,char * buffer,size_t bufsize,struct rpcent ** result)797 getrpcbyname_r(const char *name, struct rpcent *rpc, char *buffer,
798 size_t bufsize, struct rpcent **result)
799 {
800 #ifdef NS_CACHING
801 static const nss_cache_info cache_info =
802 NS_COMMON_CACHE_INFO_INITIALIZER(
803 rpc, (void *)nss_lt_name,
804 rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
805 #endif
806 static const ns_dtab dtab[] = {
807 { NSSRC_FILES, files_rpcent, (void *)nss_lt_name },
808 #ifdef YP
809 { NSSRC_NIS, nis_rpcent, (void *)nss_lt_name },
810 #endif
811 #ifdef NS_CACHING
812 NS_CACHE_CB(&cache_info)
813 #endif
814 { NULL, NULL, NULL }
815 };
816 int rv, ret_errno;
817
818 ret_errno = 0;
819 *result = NULL;
820 rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbyname_r", defaultsrc,
821 name, rpc, buffer, bufsize, &ret_errno);
822
823 if (rv == NS_SUCCESS)
824 return (0);
825 else
826 return (ret_errno);
827 }
828
829 static int
getrpcbynumber_r(int number,struct rpcent * rpc,char * buffer,size_t bufsize,struct rpcent ** result)830 getrpcbynumber_r(int number, struct rpcent *rpc, char *buffer,
831 size_t bufsize, struct rpcent **result)
832 {
833 #ifdef NS_CACHING
834 static const nss_cache_info cache_info =
835 NS_COMMON_CACHE_INFO_INITIALIZER(
836 rpc, (void *)nss_lt_id,
837 rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
838 #endif
839 static const ns_dtab dtab[] = {
840 { NSSRC_FILES, files_rpcent, (void *)nss_lt_id },
841 #ifdef YP
842 { NSSRC_NIS, nis_rpcent, (void *)nss_lt_id },
843 #endif
844 #ifdef NS_CACHING
845 NS_CACHE_CB(&cache_info)
846 #endif
847 { NULL, NULL, NULL }
848 };
849 int rv, ret_errno;
850
851 ret_errno = 0;
852 *result = NULL;
853 rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbynumber_r", defaultsrc,
854 number, rpc, buffer, bufsize, &ret_errno);
855
856 if (rv == NS_SUCCESS)
857 return (0);
858 else
859 return (ret_errno);
860 }
861
862 static int
getrpcent_r(struct rpcent * rpc,char * buffer,size_t bufsize,struct rpcent ** result)863 getrpcent_r(struct rpcent *rpc, char *buffer, size_t bufsize,
864 struct rpcent **result)
865 {
866 #ifdef NS_CACHING
867 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
868 rpc, (void *)nss_lt_all,
869 rpc_marshal_func, rpc_unmarshal_func);
870 #endif
871 static const ns_dtab dtab[] = {
872 { NSSRC_FILES, files_rpcent, (void *)nss_lt_all },
873 #ifdef YP
874 { NSSRC_NIS, nis_rpcent, (void *)nss_lt_all },
875 #endif
876 #ifdef NS_CACHING
877 NS_CACHE_CB(&cache_info)
878 #endif
879 { NULL, NULL, NULL }
880 };
881 int rv, ret_errno;
882
883 ret_errno = 0;
884 *result = NULL;
885 rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcent_r", defaultsrc,
886 rpc, buffer, bufsize, &ret_errno);
887
888 if (rv == NS_SUCCESS)
889 return (0);
890 else
891 return (ret_errno);
892 }
893
894 /* get** wrappers for get**_r functions implementation */
895 static void
rpcent_endstate(void * p)896 rpcent_endstate(void *p)
897 {
898 if (p == NULL)
899 return;
900
901 free(((struct rpcent_state *)p)->buffer);
902 free(p);
903 }
904
905 static int
wrap_getrpcbyname_r(union key key,struct rpcent * rpc,char * buffer,size_t bufsize,struct rpcent ** res)906 wrap_getrpcbyname_r(union key key, struct rpcent *rpc, char *buffer,
907 size_t bufsize, struct rpcent **res)
908 {
909 return (getrpcbyname_r(key.name, rpc, buffer, bufsize, res));
910 }
911
912 static int
wrap_getrpcbynumber_r(union key key,struct rpcent * rpc,char * buffer,size_t bufsize,struct rpcent ** res)913 wrap_getrpcbynumber_r(union key key, struct rpcent *rpc, char *buffer,
914 size_t bufsize, struct rpcent **res)
915 {
916 return (getrpcbynumber_r(key.number, rpc, buffer, bufsize, res));
917 }
918
919 static int
wrap_getrpcent_r(union key key __unused,struct rpcent * rpc,char * buffer,size_t bufsize,struct rpcent ** res)920 wrap_getrpcent_r(union key key __unused, struct rpcent *rpc, char *buffer,
921 size_t bufsize, struct rpcent **res)
922 {
923 return (getrpcent_r(rpc, buffer, bufsize, res));
924 }
925
926 static struct rpcent *
getrpc(int (* fn)(union key,struct rpcent *,char *,size_t,struct rpcent **),union key key)927 getrpc(int (*fn)(union key, struct rpcent *, char *, size_t, struct rpcent **),
928 union key key)
929 {
930 int rv;
931 struct rpcent *res;
932 struct rpcent_state * st;
933
934 rv=rpcent_getstate(&st);
935 if (rv != 0) {
936 errno = rv;
937 return NULL;
938 }
939
940 if (st->buffer == NULL) {
941 st->buffer = malloc(RPCENT_STORAGE_INITIAL);
942 if (st->buffer == NULL)
943 return (NULL);
944 st->bufsize = RPCENT_STORAGE_INITIAL;
945 }
946 do {
947 rv = fn(key, &st->rpc, st->buffer, st->bufsize, &res);
948 if (res == NULL && rv == ERANGE) {
949 free(st->buffer);
950 if ((st->bufsize << 1) > RPCENT_STORAGE_MAX) {
951 st->buffer = NULL;
952 errno = ERANGE;
953 return (NULL);
954 }
955 st->bufsize <<= 1;
956 st->buffer = malloc(st->bufsize);
957 if (st->buffer == NULL)
958 return (NULL);
959 }
960 } while (res == NULL && rv == ERANGE);
961 if (rv != 0)
962 errno = rv;
963
964 return (res);
965 }
966
967 struct rpcent *
getrpcbyname(const char * name)968 getrpcbyname(const char *name)
969 {
970 union key key;
971
972 key.name = name;
973
974 return (getrpc(wrap_getrpcbyname_r, key));
975 }
976
977 struct rpcent *
getrpcbynumber(int number)978 getrpcbynumber(int number)
979 {
980 union key key;
981
982 key.number = number;
983
984 return (getrpc(wrap_getrpcbynumber_r, key));
985 }
986
987 struct rpcent *
getrpcent(void)988 getrpcent(void)
989 {
990 union key key;
991
992 key.number = 0; /* not used */
993
994 return (getrpc(wrap_getrpcent_r, key));
995 }
996
997 void
setrpcent(int stayopen)998 setrpcent(int stayopen)
999 {
1000 #ifdef NS_CACHING
1001 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1002 rpc, (void *)nss_lt_all,
1003 NULL, NULL);
1004 #endif
1005
1006 static const ns_dtab dtab[] = {
1007 { NSSRC_FILES, files_setrpcent, (void *)SETRPCENT },
1008 #ifdef YP
1009 { NSSRC_NIS, nis_setrpcent, (void *)SETRPCENT },
1010 #endif
1011 #ifdef NS_CACHING
1012 NS_CACHE_CB(&cache_info)
1013 #endif
1014 { NULL, NULL, NULL }
1015 };
1016
1017 nsdispatch(NULL, dtab, NSDB_RPC, "setrpcent", defaultsrc, stayopen);
1018 }
1019
1020 void
endrpcent(void)1021 endrpcent(void)
1022 {
1023 #ifdef NS_CACHING
1024 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
1025 rpc, (void *)nss_lt_all,
1026 NULL, NULL);
1027 #endif
1028
1029 static const ns_dtab dtab[] = {
1030 { NSSRC_FILES, files_setrpcent, (void *)ENDRPCENT },
1031 #ifdef YP
1032 { NSSRC_NIS, nis_setrpcent, (void *)ENDRPCENT },
1033 #endif
1034 #ifdef NS_CACHING
1035 NS_CACHE_CB(&cache_info)
1036 #endif
1037 { NULL, NULL, NULL }
1038 };
1039
1040 nsdispatch(NULL, dtab, NSDB_RPC, "endrpcent", defaultsrc);
1041 }
1042