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