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