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