2 * Copyright (c) 2009, Sun Microsystems, Inc.
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.
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.
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 $
34 * Copyright (c) 1984 by Sun Microsystems, Inc.
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <arpa/inet.h>
44 #include <netinet/in.h>
51 #include <rpcsvc/yp_prot.h>
52 #include <rpcsvc/ypclnt.h>
55 #include "namespace.h"
56 #include "reentrant.h"
57 #include "un-namespace.h"
58 #include "libc_private.h"
64 #define RPCDB "/etc/rpc"
66 /* nsswitch declarations */
71 RPCENT_STORAGE_INITIAL
= 1 << 10, /* 1 KByte */
72 RPCENT_STORAGE_MAX
= 1 << 20, /* 1 MByte */
75 static const ns_src defaultsrc
[] = {
76 { NSSRC_FILES
, NS_SUCCESS
},
78 { NSSRC_NIS
, NS_SUCCESS
},
83 /* files backend declarations */
89 static int files_rpcent(void *, void *, va_list);
90 static int files_setrpcent(void *, void *, va_list);
92 static void files_endstate(void *);
93 NSS_TLS_HANDLING(files
);
95 /* nis backend declarations */
98 char domain
[MAXHOSTNAMELEN
];
105 static int nis_rpcent(void *, void *, va_list);
106 static int nis_setrpcent(void *, void *, va_list);
108 static void nis_endstate(void *);
109 NSS_TLS_HANDLING(nis
);
112 /* get** wrappers for get**_r functions declarations */
113 struct rpcent_state
{
118 static void rpcent_endstate(void *);
119 NSS_TLS_HANDLING(rpcent
);
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
);
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 *);
142 rpcent_unpack(char *p
, struct rpcent
*rpc
, char **r_aliases
,
143 size_t aliases_size
, int *errnop
)
151 cp
= strpbrk(p
, "#\n");
155 cp
= strpbrk(p
, " \t");
159 /* THIS STUFF IS INTERNET SPECIFIC */
161 while (*cp
== ' ' || *cp
== '\t')
163 rpc
->r_number
= atoi(cp
);
164 q
= rpc
->r_aliases
= r_aliases
;
165 cp
= strpbrk(cp
, " \t");
169 if (*cp
== ' ' || *cp
== '\t') {
173 if (q
< &(r_aliases
[aliases_size
- 1]))
180 cp
= strpbrk(cp
, " \t");
188 /* files backend implementation */
190 files_endstate(void *p
)
197 f
= ((struct files_state
*)p
)->fp
;
205 files_rpcent(void *retval
, void *mdata
, va_list ap
)
220 struct files_state
*st
;
223 enum nss_lookup_type how
;
225 how
= (enum nss_lookup_type
)mdata
;
229 name
= va_arg(ap
, char *);
232 number
= va_arg(ap
, int);
237 return (NS_NOTFOUND
);
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 *);
245 *errnop
= files_getstate(&st
);
249 if (st
->fp
== NULL
&& (st
->fp
= fopen(RPCDB
, "r")) == NULL
) {
254 if (how
== nss_lt_all
)
258 stayopen
= st
->stayopen
;
262 if ((line
= fgetln(st
->fp
, &linesize
)) == NULL
) {
268 if (bufsize
<= linesize
+ _ALIGNBYTES
+ sizeof(char *)) {
274 aliases
= (char **)_ALIGN(&buffer
[linesize
+1]);
275 aliases_size
= (buffer
+ bufsize
-
276 (char *)aliases
)/sizeof(char *);
277 if (aliases_size
< 1) {
283 memcpy(buffer
, line
, linesize
);
284 buffer
[linesize
] = '\0';
286 rv
= rpcent_unpack(buffer
, rpc
, aliases
, aliases_size
, errnop
);
301 if (strcmp(rpc
->r_name
, name
) == 0)
303 for (rp
= rpc
->r_aliases
; *rp
!= NULL
; rp
++) {
304 if (strcmp(*rp
, name
) == 0)
313 rv
= (rpc
->r_number
== number
) ? NS_SUCCESS
:
321 } while (!(rv
& NS_TERMINATE
));
323 if (!stayopen
&& st
->fp
!=NULL
) {
328 if ((rv
== NS_SUCCESS
) && (retval
!= NULL
))
329 *((struct rpcent
**)retval
) = rpc
;
335 files_setrpcent(void *retval __unused
, void *mdata
, va_list ap
)
337 struct files_state
*st
;
341 rv
= files_getstate(&st
);
345 switch ((enum constants
)mdata
)
350 st
->fp
= fopen(RPCDB
, "r");
356 if (st
->fp
!= NULL
) {
369 /* nis backend implementation */
372 nis_endstate(void *p
)
377 free(((struct nis_state
*)p
)->current
);
382 nis_rpcent(void *retval
, void *mdata
, va_list ap
)
398 char buf
[YPMAXRECORD
+ 2];
400 struct nis_state
*st
;
402 enum nss_lookup_type how
;
405 how
= (enum nss_lookup_type
)mdata
;
409 name
= va_arg(ap
, char *);
412 number
= va_arg(ap
, int);
417 return (NS_NOTFOUND
);
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 *);
425 *errnop
= nis_getstate(&st
);
429 if (st
->domain
[0] == '\0') {
430 if (getdomainname(st
->domain
, sizeof(st
->domain
)) != 0) {
441 if (!st
->no_name_map
)
443 snprintf(buf
, sizeof buf
, "%s", name
);
444 rv
= yp_match(st
->domain
, "rpc.byname", buf
,
445 strlen(buf
), &resultbuf
, &resultbuflen
);
471 snprintf(buf
, sizeof buf
, "%d", number
);
472 if (yp_match(st
->domain
, "rpc.bynumber", buf
,
473 strlen(buf
), &resultbuf
, &resultbuflen
)) {
480 rv
= yp_first(st
->domain
, "rpc.bynumber",
482 &st
->currentlen
, &resultbuf
,
490 lastkey
= st
->current
;
491 rv
= yp_next(st
->domain
, "rpc.bynumber",
493 st
->currentlen
, &st
->current
,
495 &resultbuf
, &resultbuflen
);
506 /* we need a room for additional \n symbol */
507 if (bufsize
<= resultbuflen
+ 1 + _ALIGNBYTES
+
514 aliases
=(char **)_ALIGN(&buffer
[resultbuflen
+2]);
515 aliases_size
= (buffer
+ bufsize
- (char *)aliases
) /
517 if (aliases_size
< 1) {
524 * rpcent_unpack expects lines terminated with \n -- make it happy
526 memcpy(buffer
, resultbuf
, resultbuflen
);
527 buffer
[resultbuflen
] = '\n';
528 buffer
[resultbuflen
+1] = '\0';
531 if (rpcent_unpack(buffer
, rpc
, aliases
, aliases_size
,
538 if ((how
== nss_lt_all
) && (no_name_active
!= 0)) {
539 if (strcmp(rpc
->r_name
, name
) == 0)
541 for (rp
= rpc
->r_aliases
; *rp
!= NULL
; rp
++) {
542 if (strcmp(*rp
, name
) == 0)
553 } while (!(rv
& NS_TERMINATE
) && (how
== nss_lt_all
));
556 if ((rv
== NS_SUCCESS
) && (retval
!= NULL
))
557 *((struct rpcent
**)retval
) = rpc
;
563 nis_setrpcent(void *retval __unused
, void *mdata
, va_list ap __unused
)
565 struct nis_state
*st
;
568 rv
= nis_getstate(&st
);
572 switch ((enum constants
)mdata
)
590 rpc_id_func(char *buffer
, size_t *buffer_size
, va_list ap
, void *cache_mdata
)
595 size_t desired_size
, size
;
596 enum nss_lookup_type lookup_type
;
597 int res
= NS_UNAVAIL
;
599 lookup_type
= (enum nss_lookup_type
)cache_mdata
;
600 switch (lookup_type
) {
602 name
= va_arg(ap
, char *);
605 desired_size
= sizeof(enum nss_lookup_type
) + size
+ 1;
606 if (desired_size
> *buffer_size
) {
611 memcpy(buffer
, &lookup_type
, sizeof(enum nss_lookup_type
));
612 memcpy(buffer
+ sizeof(enum nss_lookup_type
), name
, size
+ 1);
617 rpc
= va_arg(ap
, int);
619 desired_size
= sizeof(enum nss_lookup_type
) + sizeof(int);
620 if (desired_size
> *buffer_size
) {
625 memcpy(buffer
, &lookup_type
, sizeof(enum nss_lookup_type
));
626 memcpy(buffer
+ sizeof(enum nss_lookup_type
), &rpc
,
632 /* should be unreachable */
637 *buffer_size
= desired_size
;
642 rpc_marshal_func(char *buffer
, size_t *buffer_size
, void *retval __unused
,
643 va_list ap
, void *cache_mdata
)
648 char *orig_buf __unused
;
649 size_t orig_buf_size __unused
;
651 struct rpcent new_rpc
;
652 size_t desired_size
, size
, aliases_size
;
656 switch ((enum nss_lookup_type
)cache_mdata
) {
658 name
= va_arg(ap
, char *);
661 num
= va_arg(ap
, int);
666 /* should be unreachable */
670 rpc
= va_arg(ap
, struct rpcent
*);
671 orig_buf
= va_arg(ap
, char *);
672 orig_buf_size
= va_arg(ap
, size_t);
674 desired_size
= _ALIGNBYTES
+ sizeof(struct rpcent
) + sizeof(char *);
675 if (rpc
->r_name
!= NULL
)
676 desired_size
+= strlen(rpc
->r_name
) + 1;
678 if (rpc
->r_aliases
!= NULL
) {
680 for (alias
= rpc
->r_aliases
; *alias
; ++alias
) {
681 desired_size
+= strlen(*alias
) + 1;
685 desired_size
+= _ALIGNBYTES
+ (aliases_size
+ 1) *
689 if (*buffer_size
< desired_size
) {
690 /* this assignment is here for future use */
691 *buffer_size
= desired_size
;
695 memcpy(&new_rpc
, rpc
, sizeof(struct rpcent
));
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
);
703 if (new_rpc
.r_name
!= NULL
) {
704 size
= strlen(new_rpc
.r_name
);
705 memcpy(p
, new_rpc
.r_name
, size
);
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);
716 for (alias
= new_rpc
.r_aliases
; *alias
; ++alias
) {
717 size
= strlen(*alias
);
718 memcpy(p
, *alias
, size
);
724 memcpy(buffer
, &new_rpc
, sizeof(struct rpcent
));
729 rpc_unmarshal_func(char *buffer
, size_t buffer_size
, void *retval
, va_list ap
,
736 size_t orig_buf_size
;
742 switch ((enum nss_lookup_type
)cache_mdata
) {
744 name
= va_arg(ap
, char *);
747 num
= va_arg(ap
, int);
752 /* should be unreachable */
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 *);
762 buffer_size
- sizeof(struct rpcent
) - sizeof(char *)) {
767 memcpy(rpc
, buffer
, sizeof(struct rpcent
));
768 memcpy(&p
, buffer
+ sizeof(struct rpcent
), sizeof(char *));
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
);
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 **);
781 for (alias
= rpc
->r_aliases
; *alias
; ++alias
)
782 NS_APPLY_OFFSET(*alias
, orig_buf
, p
, char *);
786 *((struct rpcent
**)retval
) = rpc
;
791 NSS_MP_CACHE_HANDLING(rpc
);
792 #endif /* NS_CACHING */
795 /* get**_r functions implementation */
797 getrpcbyname_r(const char *name
, struct rpcent
*rpc
, char *buffer
,
798 size_t bufsize
, struct rpcent
**result
)
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
);
806 static const ns_dtab dtab
[] = {
807 { NSSRC_FILES
, files_rpcent
, (void *)nss_lt_name
},
809 { NSSRC_NIS
, nis_rpcent
, (void *)nss_lt_name
},
812 NS_CACHE_CB(&cache_info
)
820 rv
= nsdispatch(result
, dtab
, NSDB_RPC
, "getrpcbyname_r", defaultsrc
,
821 name
, rpc
, buffer
, bufsize
, &ret_errno
);
823 if (rv
== NS_SUCCESS
)
830 getrpcbynumber_r(int number
, struct rpcent
*rpc
, char *buffer
,
831 size_t bufsize
, struct rpcent
**result
)
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
);
839 static const ns_dtab dtab
[] = {
840 { NSSRC_FILES
, files_rpcent
, (void *)nss_lt_id
},
842 { NSSRC_NIS
, nis_rpcent
, (void *)nss_lt_id
},
845 NS_CACHE_CB(&cache_info
)
853 rv
= nsdispatch(result
, dtab
, NSDB_RPC
, "getrpcbynumber_r", defaultsrc
,
854 number
, rpc
, buffer
, bufsize
, &ret_errno
);
856 if (rv
== NS_SUCCESS
)
863 getrpcent_r(struct rpcent
*rpc
, char *buffer
, size_t bufsize
,
864 struct rpcent
**result
)
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
);
871 static const ns_dtab dtab
[] = {
872 { NSSRC_FILES
, files_rpcent
, (void *)nss_lt_all
},
874 { NSSRC_NIS
, nis_rpcent
, (void *)nss_lt_all
},
877 NS_CACHE_CB(&cache_info
)
885 rv
= nsdispatch(result
, dtab
, NSDB_RPC
, "getrpcent_r", defaultsrc
,
886 rpc
, buffer
, bufsize
, &ret_errno
);
888 if (rv
== NS_SUCCESS
)
894 /* get** wrappers for get**_r functions implementation */
896 rpcent_endstate(void *p
)
901 free(((struct rpcent_state
*)p
)->buffer
);
906 wrap_getrpcbyname_r(union key key
, struct rpcent
*rpc
, char *buffer
,
907 size_t bufsize
, struct rpcent
**res
)
909 return (getrpcbyname_r(key
.name
, rpc
, buffer
, bufsize
, res
));
913 wrap_getrpcbynumber_r(union key key
, struct rpcent
*rpc
, char *buffer
,
914 size_t bufsize
, struct rpcent
**res
)
916 return (getrpcbynumber_r(key
.number
, rpc
, buffer
, bufsize
, res
));
920 wrap_getrpcent_r(union key key __unused
, struct rpcent
*rpc
, char *buffer
,
921 size_t bufsize
, struct rpcent
**res
)
923 return (getrpcent_r(rpc
, buffer
, bufsize
, res
));
926 static struct rpcent
*
927 getrpc(int (*fn
)(union key
, struct rpcent
*, char *, size_t, struct rpcent
**),
932 struct rpcent_state
* st
;
934 rv
=rpcent_getstate(&st
);
940 if (st
->buffer
== NULL
) {
941 st
->buffer
= malloc(RPCENT_STORAGE_INITIAL
);
942 if (st
->buffer
== NULL
)
944 st
->bufsize
= RPCENT_STORAGE_INITIAL
;
947 rv
= fn(key
, &st
->rpc
, st
->buffer
, st
->bufsize
, &res
);
948 if (res
== NULL
&& rv
== ERANGE
) {
950 if ((st
->bufsize
<< 1) > RPCENT_STORAGE_MAX
) {
956 st
->buffer
= malloc(st
->bufsize
);
957 if (st
->buffer
== NULL
)
960 } while (res
== NULL
&& rv
== ERANGE
);
968 getrpcbyname(const char *name
)
974 return (getrpc(wrap_getrpcbyname_r
, key
));
978 getrpcbynumber(int number
)
984 return (getrpc(wrap_getrpcbynumber_r
, key
));
992 key
.number
= 0; /* not used */
994 return (getrpc(wrap_getrpcent_r
, key
));
998 setrpcent(int stayopen
)
1001 static const nss_cache_info cache_info
= NS_MP_CACHE_INFO_INITIALIZER(
1002 rpc
, (void *)nss_lt_all
,
1006 static const ns_dtab dtab
[] = {
1007 { NSSRC_FILES
, files_setrpcent
, (void *)SETRPCENT
},
1009 { NSSRC_NIS
, nis_setrpcent
, (void *)SETRPCENT
},
1012 NS_CACHE_CB(&cache_info
)
1014 { NULL
, NULL
, NULL
}
1017 nsdispatch(NULL
, dtab
, NSDB_RPC
, "setrpcent", defaultsrc
, stayopen
);
1024 static const nss_cache_info cache_info
= NS_MP_CACHE_INFO_INITIALIZER(
1025 rpc
, (void *)nss_lt_all
,
1029 static const ns_dtab dtab
[] = {
1030 { NSSRC_FILES
, files_setrpcent
, (void *)ENDRPCENT
},
1032 { NSSRC_NIS
, nis_setrpcent
, (void *)ENDRPCENT
},
1035 NS_CACHE_CB(&cache_info
)
1037 { NULL
, NULL
, NULL
}
1040 nsdispatch(NULL
, dtab
, NSDB_RPC
, "endrpcent", defaultsrc
);