4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
42 * The commom server procedure for the rpcbind.
46 #include <sys/types.h>
53 #include <rpc/rpcb_prot.h>
54 #include <rpcsvc/svc_dg_priv.h>
55 #include <netconfig.h>
56 #include <sys/param.h>
60 #include <sys/stropts.h>
62 #include <netinet/in.h>
63 #include <rpc/pmap_prot.h>
71 #include <rpcsvc/yp_prot.h>
73 #include <nfs/nfs_acl.h>
74 #include <rpcsvc/mount.h>
75 #include <nfs/nfs_acl.h>
76 #include <rpc/key_prot.h>
77 #include <rpcsvc/yp_prot.h>
78 #include <rpcsvc/rquota.h>
79 #include <rpcsvc/yppasswd.h>
80 #include <rpcsvc/ypupd.h>
85 static struct finfo
*forward_register(ulong_t
, struct netbuf
*, int, char *);
86 static void forward_destroy(struct finfo
*);
87 static void handle_reply(svc_input_id_t
, int, unsigned int, void *);
88 static int netbufcmp(struct netbuf
*, struct netbuf
*);
89 static void netbuffree(struct netbuf
*);
90 static struct netbuf
*netbufdup(struct netbuf
*);
91 static void find_versions(rpcprog_t
, char *, rpcvers_t
*, rpcvers_t
*);
92 static rpcblist_ptr
find_service(ulong_t
, ulong_t
, char *);
94 static int add_pmaplist(RPCB
*);
100 * Set a mapping of program, version, netid
103 rpcbproc_set_com(RPCB
*regp
, bool_t
*result
, struct svc_req
*rqstp
,
108 *result
= map_set(regp
, getowner(rqstp
->rq_xprt
, owner
));
110 rpcbs_set(rpcbversnum
- PMAPVERS
, *result
);
116 map_set(RPCB
*regp
, char *owner
)
119 rpcblist_ptr rbl
, fnd
;
122 * check to see if already used
123 * find_service returns a hit even if
124 * the versions don't match, so check for it
126 (void) rw_wrlock(&list_rbl_lock
);
128 (void) rw_wrlock(&list_pml_lock
);
130 fnd
= find_service(regp
->r_prog
, regp
->r_vers
, regp
->r_netid
);
131 if (fnd
&& (fnd
->rpcb_map
.r_vers
== regp
->r_vers
)) {
132 if (strcmp(fnd
->rpcb_map
.r_addr
, regp
->r_addr
) == 0) {
134 * if these match then it is already
135 * registered so just say "OK".
138 (void) rw_unlock(&list_pml_lock
);
140 (void) rw_unlock(&list_rbl_lock
);
144 * Check if server is up. If so, return FALSE.
145 * If not, cleanup old registrations for the
146 * program and register the new server.
148 if (is_bound(fnd
->rpcb_map
.r_netid
,
149 fnd
->rpcb_map
.r_addr
)) {
151 (void) rw_unlock(&list_pml_lock
);
153 (void) rw_unlock(&list_rbl_lock
);
157 delete_prog(regp
->r_prog
);
162 (void) rw_unlock(&list_pml_lock
);
166 * add to the end of the list
168 rbl
= malloc(sizeof (RPCBLIST
));
170 (void) rw_unlock(&list_rbl_lock
);
174 a
->r_prog
= regp
->r_prog
;
175 a
->r_vers
= regp
->r_vers
;
176 a
->r_netid
= strdup(regp
->r_netid
);
177 a
->r_addr
= strdup(regp
->r_addr
);
178 a
->r_owner
= strdup(owner
);
179 if (a
->r_addr
== NULL
|| a
->r_netid
== NULL
|| a
->r_owner
== NULL
) {
180 (void) rw_unlock(&list_rbl_lock
);
184 rbl
->rpcb_next
= NULL
;
185 if (list_rbl
== NULL
) {
188 for (fnd
= list_rbl
; fnd
->rpcb_next
; fnd
= fnd
->rpcb_next
)
190 fnd
->rpcb_next
= rbl
;
194 (void) add_pmaplist(regp
);
196 (void) rw_unlock(&list_rbl_lock
);
201 * Unset a mapping of program, version, netid
204 rpcbproc_unset_com(RPCB
*regp
, bool_t
*result
, struct svc_req
*rqstp
,
209 *result
= map_unset(regp
, getowner(rqstp
->rq_xprt
, owner
));
211 rpcbs_unset(rpcbversnum
- PMAPVERS
, *result
);
217 map_unset(RPCB
*regp
, char *owner
)
222 rpcblist_ptr rbl
, next
, prev
= NULL
;
227 (void) rw_wrlock(&list_rbl_lock
);
228 for (rbl
= list_rbl
; rbl
!= NULL
; rbl
= next
) {
229 next
= rbl
->rpcb_next
;
231 if ((rbl
->rpcb_map
.r_prog
!= regp
->r_prog
) ||
232 (rbl
->rpcb_map
.r_vers
!= regp
->r_vers
) ||
233 (regp
->r_netid
[0] && strcasecmp(regp
->r_netid
,
234 rbl
->rpcb_map
.r_netid
))) {
235 /* prev moves forwards */
241 * Check whether appropriate uid. Unset only
242 * if superuser or the owner itself.
244 if (strcmp(owner
, "superuser") &&
245 strcmp(rbl
->rpcb_map
.r_owner
, owner
)) {
246 (void) rw_unlock(&list_rbl_lock
);
259 prev
->rpcb_next
= next
;
263 (void) rw_wrlock(&list_pml_lock
);
264 (void) del_pmaplist(regp
);
265 (void) rw_unlock(&list_pml_lock
);
268 (void) rw_unlock(&list_rbl_lock
);
271 * We return 1 either when the entry was not there or it
272 * was able to unset it. It can come to this point only if
273 * at least one of the conditions is true.
279 delete_rbl(rpcblist_ptr rbl
)
281 free(rbl
->rpcb_map
.r_addr
);
282 free(rbl
->rpcb_map
.r_netid
);
283 free(rbl
->rpcb_map
.r_owner
);
288 delete_prog(rpcprog_t prog
)
290 rpcblist_ptr rbl
, next
, prev
= NULL
;
292 assert(RW_WRITE_HELD(&list_rbl_lock
));
294 for (rbl
= list_rbl
; rbl
!= NULL
; rbl
= next
) {
295 next
= rbl
->rpcb_next
;
297 if (rbl
->rpcb_map
.r_prog
!= prog
||
298 is_bound(rbl
->rpcb_map
.r_netid
, rbl
->rpcb_map
.r_addr
)) {
304 (void) del_pmaplist(&rbl
->rpcb_map
);
311 prev
->rpcb_next
= next
;
316 * Lookup the mapping for a program, version and return its
317 * address. Assuming that the caller wants the address of the
318 * server running on the transport on which the request came.
320 * For RPCBPROC_GETVERSADDR it will return a service with the exact version
323 * Otherwise, even if a service with a different version number is available,
324 * it will return that address. The client should check with an
325 * clnt_call to verify whether the service is the one that is desired.
327 * We also try to resolve the universal address in terms of
328 * address of the caller.
331 rpcbproc_getaddr_com(RPCB
*regp
, char **result
, struct svc_req
*rqstp
,
336 struct netconfig
*trans_conf
; /* transport netconfig */
337 SVCXPRT
*transp
= rqstp
->rq_xprt
;
338 int verstype
= rqstp
->rq_proc
== RPCBPROC_GETVERSADDR
? RPCB_ONEVERS
:
340 bool_t pml_locked
= FALSE
;
343 * There is a potential window at startup during which rpcbind
344 * service has been established over IPv6 but not over IPv4. If an
345 * IPv4 request comes in during that window, the IP code will map
346 * it into IPv6. We could patch up the request so that it looks
347 * like IPv4 (so that rpcbind returns an IPv4 uaddr to the caller),
348 * but that requires some non-trivial code and it's hard to test.
349 * Instead, drop the request on the floor and force the caller to
350 * retransmit. By the time rpcbind sees the retransmission, IPv4
351 * service should be in place and it should see the request as
354 trans_conf
= rpcbind_get_conf(transp
->xp_netid
);
355 if (strcmp(trans_conf
->nc_protofmly
, NC_INET6
) == 0) {
356 struct sockaddr_in6
*rmtaddr
;
358 rmtaddr
= (struct sockaddr_in6
*)transp
->xp_rtaddr
.buf
;
359 if (IN6_IS_ADDR_V4MAPPED(&rmtaddr
->sin6_addr
)) {
361 "IPv4 GETADDR request mapped to IPv6: ignoring");
367 (void) rw_rdlock(&list_rbl_lock
);
369 fnd
= find_service(regp
->r_prog
, regp
->r_vers
, transp
->xp_netid
);
370 if (fnd
&& ((verstype
== RPCB_ALLVERS
) ||
371 (regp
->r_vers
== fnd
->rpcb_map
.r_vers
))) {
372 if (*(regp
->r_addr
) != '\0') { /* may contain a hint about */
373 saddr
= regp
->r_addr
; /* the interface that we */
375 if (!(*result
= mergeaddr(transp
, transp
->xp_netid
,
376 fnd
->rpcb_map
.r_addr
, saddr
))) {
377 /* Try whatever we have */
378 *result
= strdup(fnd
->rpcb_map
.r_addr
);
379 } else if (!(*result
)[0]) {
381 (void) rw_unlock(&list_rbl_lock
);
382 (void) rw_wrlock(&list_rbl_lock
);
384 (void) rw_wrlock(&list_pml_lock
);
390 * The server died. Unset all versions of this prog.
392 delete_prog(regp
->r_prog
);
400 (void) rw_unlock(&list_pml_lock
);
402 (void) rw_unlock(&list_rbl_lock
);
404 rpcbs_getaddr(rpcbversnum
- PMAPVERS
, regp
->r_prog
, regp
->r_vers
,
405 transp
->xp_netid
, *result
);
411 rpcbproc_dump_com(void *argp
, rpcblist_ptr
**result
)
414 * list_rbl_lock is unlocked in xdr_rpcblist_ptr_ptr()
416 (void) rw_rdlock(&list_rbl_lock
);
422 xdr_rpcblist_ptr_ptr(XDR
*xdrs
, rpcblist_ptr
**objp
)
424 if (xdrs
->x_op
== XDR_FREE
) {
426 * list_rbl_lock is locked in rpcbproc_dump_com()
428 rw_unlock(&list_rbl_lock
);
432 return (xdr_rpcblist_ptr(xdrs
, *objp
));
437 rpcbproc_gettime_com(void *argp
, ulong_t
*result
)
439 (void) time((time_t *)result
);
445 * Convert uaddr to taddr. Should be used only by
446 * local servers/clients. (kernel level stuff only)
449 rpcbproc_uaddr2taddr_com(char **uaddrp
, struct netbuf
*result
,
450 struct svc_req
*rqstp
)
452 struct netconfig
*nconf
;
453 struct netbuf
*taddr
;
455 if (((nconf
= rpcbind_get_conf(rqstp
->rq_xprt
->xp_netid
)) == NULL
) ||
456 ((taddr
= uaddr2taddr(nconf
, *uaddrp
)) == NULL
)) {
457 (void) memset(result
, 0, sizeof (*result
));
461 memcpy(result
, taddr
, sizeof (*result
));
468 * Convert taddr to uaddr. Should be used only by
469 * local servers/clients. (kernel level stuff only)
472 rpcbproc_taddr2uaddr_com(struct netbuf
*taddr
, char **result
,
473 struct svc_req
*rqstp
)
475 struct netconfig
*nconf
;
477 if ((nconf
= rpcbind_get_conf(rqstp
->rq_xprt
->xp_netid
)) == NULL
)
480 *result
= taddr2uaddr(nconf
, taddr
);
486 * Stuff for the rmtcall service
489 xdr_rpcb_rmtcallargs(XDR
*xdrs
, rpcb_rmtcallargs
*objp
)
491 if (!xdr_u_long(xdrs
, &objp
->prog
))
493 if (!xdr_u_long(xdrs
, &objp
->vers
))
495 if (!xdr_u_long(xdrs
, &objp
->proc
))
497 if (!xdr_bytes(xdrs
, (char **)&objp
->args
.args_val
,
498 (uint_t
*)&objp
->args
.args_len
, ~0))
505 xdr_rmtcallres(XDR
*xdrs
, rmtcallres
*objp
)
507 if (!xdr_u_long(xdrs
, &objp
->port
))
509 if (!xdr_bytes(xdrs
, (char **)&objp
->res
.res_val
,
510 (uint_t
*)&objp
->res
.res_len
, ~0))
517 xdr_rpcb_rmtcallres(XDR
*xdrs
, rpcb_rmtcallres
*objp
)
519 if (!xdr_string(xdrs
, &objp
->addr
, ~0))
521 if (!xdr_bytes(xdrs
, (char **)&objp
->results
.results_val
,
522 (uint_t
*)&objp
->results
.results_len
, ~0))
527 struct rmtcallfd_list
{
530 struct rmtcallfd_list
*next
;
533 static struct rmtcallfd_list
*rmthead
;
534 static struct rmtcallfd_list
*rmttail
;
536 #define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)
539 create_rmtcall_fd(struct netconfig
*nconf
)
542 struct rmtcallfd_list
*rmt
;
544 if ((fd
= t_open(nconf
->nc_device
, O_RDWR
, NULL
)) == -1) {
546 fprintf(stderr
, "create_rmtcall_fd: couldn't open "
547 "\"%s\" (errno %d, t_errno %d)\n",
548 nconf
->nc_device
, errno
, t_errno
);
552 if (t_bind(fd
, NULL
, NULL
) == -1) {
554 fprintf(stderr
, "create_rmtcall_fd: couldn't bind to "
555 "fd for \"%s\" (errno %d, t_errno %d)\n",
556 nconf
->nc_device
, errno
, t_errno
);
560 rmt
= malloc(sizeof (struct rmtcallfd_list
));
562 syslog(LOG_ERR
, "create_rmtcall_fd: no memory!");
566 rmt
->netid
= strdup(nconf
->nc_netid
);
567 if (rmt
->netid
== NULL
) {
569 syslog(LOG_ERR
, "create_rmtcall_fd: no memory!");
573 if (svc_add_input(fd
, MASKVAL
, handle_reply
, rmt
->netid
) == -1) {
576 syslog(LOG_ERR
, "create_rmtcall_fd: svc_add_input() failed!");
582 if (rmthead
== NULL
) {
594 find_rmtcallfd_by_netid(char *netid
)
596 struct rmtcallfd_list
*rmt
;
598 for (rmt
= rmthead
; rmt
!= NULL
; rmt
= rmt
->next
) {
599 if (strcmp(netid
, rmt
->netid
) == 0) {
606 #define MAXTIME_OFF 300 /* 5 minutes timeout for rmtcalls */
612 #define FINFO_ACTIVE 0x1
614 struct netbuf
*caller_addr
;
618 struct t_unitdata
*reply_data
;
619 struct rpc_err reply_error
;
626 * finfo_lock protects rpcb_rmtcalls, rpcb_rmtcalls_max, lastxid,
627 * fihead, and fitail.
629 static mutex_t finfo_lock
= DEFAULTMUTEX
;
631 static int rpcb_rmtcalls
;
632 static int rpcb_rmtcalls_max
;
633 static ulong_t lastxid
;
634 static struct finfo
*fihead
;
635 static struct finfo
*fitail
;
638 set_rpcb_rmtcalls_max(int max
)
640 (void) mutex_lock(&finfo_lock
);
641 rpcb_rmtcalls_max
= max
;
642 if (rpcb_rmtcalls
> rpcb_rmtcalls_max
) {
643 assert(fitail
!= NULL
);
644 (void) cond_signal(&fitail
->cv
);
646 (void) mutex_unlock(&finfo_lock
);
650 * Call a remote procedure service. This procedure is very quiet when things
651 * go wrong. The proc is written to support broadcast rpc. In the broadcast
652 * case, a machine should shut-up instead of complain, lest the requestor be
653 * overrun with complaints at the expense of not hearing a valid reply.
654 * When receiving a request and verifying that the service exists, we
656 * receive the request
658 * open a new TLI endpoint on the same transport on which we received
659 * the original request
661 * remember the original request's XID (which requires knowing the format
662 * of the svc_dg_data structure)
664 * forward the request, with a new XID, to the requested service,
665 * remembering the XID used to send this request (for later use in
666 * reassociating the answer with the original request), the requestor's
667 * address, the file descriptor on which the forwarded request is
668 * made and the service's address
670 * wait for either the timeout or the condition variable is signalled from
673 * At some time in the future, a reply will be received from the service to
674 * which we forwarded the request. At that time, svc_run() detect that the
675 * socket used was for forwarding and call handle_reply() to
679 * bundle the reply, along with the service's universal address
681 * put the reply into the particular finfo
683 * signal the condition variable.
686 #define RPC_BUF_MAX 65536 /* can be raised if required */
689 * This is from ../ypcmd/yp_b.h
690 * It does not appear in <rpcsvc/yp_prot.h>
692 #define YPBINDPROG ((ulong_t)100007)
693 #define YPBINDPROC_SETDOM ((ulong_t)2)
696 * reply_type - which proc number
697 * versnum - which vers was called
700 rpcbproc_callit_com(struct svc_req
*rqstp
, SVCXPRT
*transp
, ulong_t reply_type
,
706 rpcb_rmtcallargs arg
;
709 struct netconfig
*nconf
;
710 struct netbuf
*caller
;
711 struct nd_mergearg ma
;
715 struct svc_dg_data
*bd
;
718 struct rpc_msg call_msg
;
719 char outbuf
[RPC_BUF_MAX
];
720 char *outbuf_alloc
= NULL
;
722 bool_t outxdr_created
= FALSE
;
726 struct t_unitdata tu_data
;
731 (void) mutex_lock(&finfo_lock
);
732 if (!allow_indirect
|| rpcb_rmtcalls_max
== 0) {
733 (void) mutex_unlock(&finfo_lock
);
736 (void) mutex_unlock(&finfo_lock
);
738 if (t_getinfo(transp
->xp_fd
, &tinfo
) == -1) {
739 if (reply_type
== RPCBPROC_INDIRECT
)
740 svcerr_systemerr(transp
);
743 if (tinfo
.servtype
!= T_CLTS
)
744 return; /* Only datagram type accepted */
746 sendsz
= __rpc_get_t_size(0, tinfo
.tsdu
);
747 if (sendsz
== 0) { /* data transfer not supported */
748 if (reply_type
== RPCBPROC_INDIRECT
)
749 svcerr_systemerr(transp
);
753 * Should be multiple of 4 for XDR.
755 sendsz
= ((sendsz
+ 3) / 4) * 4;
757 (void) memset((char *)&arg
, 0, sizeof (arg
));
758 if (!svc_getargs(transp
, xdr_rpcb_rmtcallargs
, (char *)&arg
)) {
759 if (reply_type
== RPCBPROC_INDIRECT
)
760 svcerr_decode(transp
);
763 "rpcbproc_callit_com: svc_getargs failed\n");
768 * Disallow calling rpcbind for certain procedures.
769 * Allow calling NULLPROC - per man page on rpcb_rmtcall().
770 * switch is in alphabetical order.
772 if (arg
.proc
!= NULLPROC
) {
777 "rpcbind: rejecting KEY_PROG(%d)\n",
781 if (arg
.proc
!= MOUNTPROC_MNT
)
784 * In Solaris 2.6, the host-based accesss control
785 * is done by the NFS server on each request.
786 * Prior to 2.6 we rely on mountd.
790 "rpcbind: rejecting MOUNTPROG(%d)\n",
793 case NFS_ACL_PROGRAM
:
796 "rpcbind: rejecting NFS_ACL_PROGRAM(%d)\n",
800 /* also NFS3_PROGRAM */
803 "rpcbind: rejecting NFS_PROGRAM(%d)\n",
808 * Disallow calling rpcbind for certain procedures.
809 * Luckily Portmap set/unset/callit also have same
810 * procedure numbers. So, will not check for those.
815 case RPCBPROC_CALLIT
:
816 case RPCBPROC_INDIRECT
:
817 if (reply_type
== RPCBPROC_INDIRECT
)
818 svcerr_weakauth(transp
); /* XXX */
820 fprintf(stderr
, "rpcbproc_callit_com: "
821 "calling RPCBPROG procs SET, "
822 "UNSET, CALLIT, or INDIRECT not "
827 * Ideally, we should have called rpcb_service()
828 * or pmap_service() with appropriate parameters
829 * instead of going about in a roundabout
830 * manner. Hopefully, this case should happen
839 "rpcbind: rejecting RQUOTAPROG(%d)\n",
845 "rpcbind: rejecting YPPASSWDPROG(%d)\n",
851 "rpcbind: rejecting YPU_PROG(%d)\n",
855 if (arg
.proc
!= YPBINDPROC_SETDOM
)
859 "rpcbind: rejecting YPBINDPROG(%d)\n",
870 "rpcbind: rejecting YPPROG(%d)\n",
882 (void) rw_rdlock(&list_rbl_lock
);
883 rbl
= find_service(arg
.prog
, arg
.vers
, transp
->xp_netid
);
885 rpcbs_rmtcall(versnum
- PMAPVERS
, reply_type
, arg
.prog
, arg
.vers
,
886 arg
.proc
, transp
->xp_netid
, rbl
);
889 (void) rw_unlock(&list_rbl_lock
);
890 if (reply_type
== RPCBPROC_INDIRECT
)
891 svcerr_noprog(transp
);
894 if (rbl
->rpcb_map
.r_vers
!= arg
.vers
) {
895 if (reply_type
== RPCBPROC_INDIRECT
) {
896 ulong_t vers_low
, vers_high
;
898 find_versions(arg
.prog
, transp
->xp_netid
,
899 &vers_low
, &vers_high
);
900 (void) rw_unlock(&list_rbl_lock
);
901 svcerr_progvers(transp
, vers_low
, vers_high
);
903 (void) rw_unlock(&list_rbl_lock
);
909 * Check whether this entry is valid and a server is present
910 * Mergeaddr() returns NULL if no such entry is present, and
911 * returns "" if the entry was present but the server is not
912 * present (i.e., it crashed).
914 if (reply_type
== RPCBPROC_INDIRECT
) {
915 char *uaddr
= mergeaddr(transp
, transp
->xp_netid
,
916 rbl
->rpcb_map
.r_addr
, NULL
);
917 if ((uaddr
== (char *)NULL
) || uaddr
[0] == '\0') {
918 (void) rw_unlock(&list_rbl_lock
);
919 svcerr_noprog(transp
);
926 nconf
= rpcbind_get_conf(transp
->xp_netid
);
928 (void) rw_unlock(&list_rbl_lock
);
929 if (reply_type
== RPCBPROC_INDIRECT
)
930 svcerr_systemerr(transp
);
933 "rpcbproc_callit_com: rpcbind_get_conf failed\n");
937 caller
= svc_getrpccaller(transp
);
938 ma
.c_uaddr
= taddr2uaddr(nconf
, caller
);
939 ma
.s_uaddr
= rbl
->rpcb_map
.r_addr
;
942 * A mergeaddr operation allocates a string, which it stores in
943 * ma.m_uaddr. It's passed to forward_register() and is
944 * eventually freed by forward_destroy().
946 stat
= netdir_options(nconf
, ND_MERGEADDR
, 0, (char *)&ma
);
947 (void) rw_unlock(&list_rbl_lock
);
950 (void) syslog(LOG_ERR
, "netdir_merge failed for %s: %s",
951 nconf
->nc_netid
, netdir_sperror());
953 if ((fd
= find_rmtcallfd_by_netid(nconf
->nc_netid
)) == -1) {
954 if (reply_type
== RPCBPROC_INDIRECT
)
955 svcerr_systemerr(transp
);
960 bd
= get_svc_dg_data(transp
);
962 assert(!MUTEX_HELD(&finfo_lock
));
963 fi
= forward_register(bd
->su_xid
, caller
, fd
, ma
.m_uaddr
);
965 /* forward_register failed. Perhaps no memory. */
969 "rpcbproc_callit_com: forward_register failed\n");
970 assert(!MUTEX_HELD(&finfo_lock
));
973 /* forward_register() returns with finfo_lock held when successful */
974 assert(MUTEX_HELD(&finfo_lock
));
976 if (fi
->flag
& FINFO_ACTIVE
) {
978 * A duplicate request for the slow server. Let's not
979 * beat on it any more.
981 (void) mutex_unlock(&finfo_lock
);
985 "rpcbproc_callit_com: duplicate request\n");
988 fi
->flag
|= FINFO_ACTIVE
;
990 call_msg
.rm_xid
= fi
->forward_xid
;
991 call_msg
.rm_direction
= CALL
;
992 call_msg
.rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
993 call_msg
.rm_call
.cb_prog
= arg
.prog
;
994 call_msg
.rm_call
.cb_vers
= arg
.vers
;
996 if (sendsz
> RPC_BUF_MAX
) {
997 outbuf_alloc
= malloc(sendsz
);
998 if (outbuf_alloc
== NULL
) {
1000 (void) mutex_unlock(&finfo_lock
);
1001 if (reply_type
== RPCBPROC_INDIRECT
)
1002 svcerr_systemerr(transp
);
1005 "rpcbproc_callit_com: No memory!\n");
1008 xdrmem_create(&outxdr
, outbuf_alloc
, sendsz
, XDR_ENCODE
);
1010 xdrmem_create(&outxdr
, outbuf
, sendsz
, XDR_ENCODE
);
1012 outxdr_created
= TRUE
;
1014 if (!xdr_callhdr(&outxdr
, &call_msg
)) {
1015 forward_destroy(fi
);
1016 (void) mutex_unlock(&finfo_lock
);
1017 if (reply_type
== RPCBPROC_INDIRECT
)
1018 svcerr_systemerr(transp
);
1021 "rpcbproc_callit_com: xdr_callhdr failed\n");
1025 if (!xdr_u_long(&outxdr
, &arg
.proc
)) {
1026 forward_destroy(fi
);
1027 (void) mutex_unlock(&finfo_lock
);
1028 if (reply_type
== RPCBPROC_INDIRECT
)
1029 svcerr_systemerr(transp
);
1032 "rpcbproc_callit_com: xdr_u_long failed\n");
1036 if (rqstp
->rq_cred
.oa_flavor
== AUTH_NULL
) {
1037 auth
= authnone_create();
1038 } else if (rqstp
->rq_cred
.oa_flavor
== AUTH_SYS
) {
1039 struct authsys_parms
*au
;
1041 au
= (struct authsys_parms
*)rqstp
->rq_clntcred
;
1042 auth
= authsys_create(au
->aup_machname
, au
->aup_uid
,
1043 au
->aup_gid
, au
->aup_len
, au
->aup_gids
);
1044 if (auth
== NULL
) /* fall back */
1045 auth
= authnone_create();
1047 /* we do not support any other authentication scheme */
1048 forward_destroy(fi
);
1049 (void) mutex_unlock(&finfo_lock
);
1050 if (reply_type
== RPCBPROC_INDIRECT
)
1051 svcerr_weakauth(transp
); /* XXX too strong.. */
1053 fprintf(stderr
, "rpcbproc_callit_com: oa_flavor != "
1054 "AUTH_NONE and oa_flavor != AUTH_SYS\n");
1058 forward_destroy(fi
);
1059 (void) mutex_unlock(&finfo_lock
);
1060 if (reply_type
== RPCBPROC_INDIRECT
)
1061 svcerr_systemerr(transp
);
1063 fprintf(stderr
, "rpcbproc_callit_com: "
1064 "authwhatever_create returned NULL\n");
1067 if (!AUTH_MARSHALL(auth
, &outxdr
)) {
1068 forward_destroy(fi
);
1069 (void) mutex_unlock(&finfo_lock
);
1070 if (reply_type
== RPCBPROC_INDIRECT
)
1071 svcerr_systemerr(transp
);
1075 "rpcbproc_callit_com: AUTH_MARSHALL failed\n");
1080 if (!xdr_opaque(&outxdr
, arg
.args
.args_val
, arg
.args
.args_len
)) {
1081 forward_destroy(fi
);
1082 (void) mutex_unlock(&finfo_lock
);
1083 if (reply_type
== RPCBPROC_INDIRECT
)
1084 svcerr_systemerr(transp
);
1087 "rpcbproc_callit_com: xdr_opaque failed\n");
1091 tu_data
.udata
.len
= XDR_GETPOS(&outxdr
);
1093 tu_data
.udata
.buf
= outbuf_alloc
;
1095 tu_data
.udata
.buf
= outbuf
;
1096 tu_data
.opt
.len
= 0;
1098 na
= uaddr2taddr(nconf
, ma
.m_uaddr
);
1100 forward_destroy(fi
);
1101 (void) mutex_unlock(&finfo_lock
);
1102 if (reply_type
== RPCBPROC_INDIRECT
)
1103 svcerr_systemerr(transp
);
1108 if (t_sndudata(fd
, &tu_data
) == -1) {
1110 forward_destroy(fi
);
1111 (void) mutex_unlock(&finfo_lock
);
1113 netdir_free((char *)na
, ND_ADDR
);
1115 if (reply_type
== RPCBPROC_INDIRECT
)
1116 svcerr_systemerr(transp
);
1119 "rpcbproc_callit_com: t_sndudata failed: "
1120 "t_errno %d, errno %d\n", t_errno
, err
);
1124 netdir_free((char *)na
, ND_ADDR
);
1125 xdr_destroy(&outxdr
);
1126 outxdr_created
= FALSE
;
1127 if (outbuf_alloc
!= NULL
) {
1129 outbuf_alloc
= NULL
;
1131 svc_freeargs(transp
, xdr_rpcb_rmtcallargs
, (char *)&arg
);
1133 to
.tv_sec
= time(NULL
) + MAXTIME_OFF
;
1136 while (fi
->reply_data
== NULL
&&
1137 cond_timedwait(&fi
->cv
, &finfo_lock
, &to
) != ETIME
)
1140 if (fi
->reply_data
== NULL
) {
1141 forward_destroy(fi
);
1142 (void) mutex_unlock(&finfo_lock
);
1144 if (reply_type
== RPCBPROC_INDIRECT
)
1145 svcerr_systemerr(transp
);
1147 (void) fprintf(stderr
,
1148 "rpcbproc_callit_com: timeout\n");
1152 if (fi
->reply_error
.re_status
!= RPC_SUCCESS
) {
1153 forward_destroy(fi
);
1154 (void) mutex_unlock(&finfo_lock
);
1156 if (reply_type
== RPCBPROC_INDIRECT
)
1157 svcerr_systemerr(transp
);
1159 (void) fprintf(stderr
,
1160 "rpcbproc_callit_com: error in reply: %s\n",
1161 clnt_sperrno(fi
->reply_error
.re_status
));
1170 int h1
, h2
, h3
, h4
, p1
, p2
;
1172 /* interpret the universal address for TCP/IP */
1173 if (sscanf(fi
->uaddr
, "%d.%d.%d.%d.%d.%d",
1174 &h1
, &h2
, &h3
, &h4
, &p1
, &p2
) != 6)
1177 result
.port
= ((p1
& 0xff) << 8) + (p2
& 0xff);
1178 result
.res
.res_len
= fi
->res_len
;
1179 result
.res
.res_val
= fi
->res_val
;
1181 svc_sendreply(transp
, xdr_rmtcallres
, (char *)&result
);
1188 rpcb_rmtcallres result
;
1190 result
.addr
= fi
->uaddr
;
1191 result
.results
.results_len
= fi
->res_len
;
1192 result
.results
.results_val
= fi
->res_val
;
1194 svc_sendreply(transp
, xdr_rpcb_rmtcallres
,
1200 forward_destroy(fi
);
1201 (void) mutex_unlock(&finfo_lock
);
1207 xdr_destroy(&outxdr
);
1209 svc_freeargs(transp
, xdr_rpcb_rmtcallargs
, (char *)&arg
);
1212 static struct finfo
*forward_find(ulong_t
, char *);
1215 * Adds an entry into the finfo list for the given request. Returns the finfo
1216 * and finfo_lock is left held. If duplicate request, returns finfo with
1217 * FINFO_ACTIVE, else returns finfo without FINFO_ACTIVE.
1218 * If failed, returns NULL and finfo_lock is left unheld.
1220 static struct finfo
*
1221 forward_register(ulong_t caller_xid
, struct netbuf
*caller_addr
, int forward_fd
,
1226 (void) mutex_lock(&finfo_lock
);
1227 if (rpcb_rmtcalls_max
== 0) {
1228 (void) mutex_unlock(&finfo_lock
);
1233 * initialization: once this has happened, lastxid will
1234 * never be 0 again, when entering or returning from this function.
1237 lastxid
= time(NULL
);
1240 * Check if it is an duplicate entry
1242 for (fi
= fihead
; fi
!= NULL
; fi
= fi
->next
) {
1243 if (fi
->caller_xid
== caller_xid
&&
1244 netbufcmp(fi
->caller_addr
, caller_addr
)) {
1245 assert(fi
->flag
& FINFO_ACTIVE
);
1250 fi
= malloc(sizeof (*fi
));
1252 (void) mutex_unlock(&finfo_lock
);
1256 if ((fi
->caller_addr
= netbufdup(caller_addr
)) == NULL
) {
1257 (void) mutex_unlock(&finfo_lock
);
1263 * Generate new xid and make sure it is unique.
1267 /* avoid lastxid wraparound to 0 */
1270 } while (forward_find(lastxid
, uaddr
) != NULL
);
1281 fi
->caller_xid
= caller_xid
;
1283 fi
->forward_xid
= lastxid
;
1284 fi
->forward_fd
= forward_fd
;
1287 * Though uaddr is not allocated here, it will still be freed
1288 * from forward_destroy().
1292 fi
->reply_data
= NULL
;
1293 (void) cond_init(&fi
->cv
, USYNC_THREAD
, NULL
);
1296 if (rpcb_rmtcalls
> rpcb_rmtcalls_max
) {
1297 assert(fitail
!= fi
);
1298 (void) cond_signal(&fitail
->cv
);
1305 forward_destroy(struct finfo
*fi
)
1307 assert(MUTEX_HELD(&finfo_lock
));
1308 assert(fi
->flag
& FINFO_ACTIVE
);
1311 assert(fi
->prev
== NULL
);
1314 fi
->prev
->next
= fi
->next
;
1318 assert(fi
->next
== NULL
);
1321 fi
->next
->prev
= fi
->prev
;
1324 netbuffree(fi
->caller_addr
);
1326 if (fi
->reply_data
!= NULL
)
1327 t_free((char *)fi
->reply_data
, T_UNITDATA
);
1328 (void) cond_destroy(&fi
->cv
);
1333 if (rpcb_rmtcalls
> rpcb_rmtcalls_max
) {
1334 assert(fitail
!= NULL
);
1335 (void) cond_signal(&fitail
->cv
);
1339 static struct finfo
*
1340 forward_find(ulong_t reply_xid
, char *uaddr
)
1344 assert(MUTEX_HELD(&finfo_lock
));
1346 for (fi
= fihead
; fi
!= NULL
; fi
= fi
->next
) {
1347 if (fi
->forward_xid
== reply_xid
&&
1348 strcmp(fi
->uaddr
, uaddr
) == 0)
1356 netbufcmp(struct netbuf
*n1
, struct netbuf
*n2
)
1358 return ((n1
->len
!= n2
->len
) || memcmp(n1
->buf
, n2
->buf
, n1
->len
));
1361 static struct netbuf
*
1362 netbufdup(struct netbuf
*ap
)
1366 np
= malloc(sizeof (struct netbuf
) + ap
->len
);
1368 np
->maxlen
= np
->len
= ap
->len
;
1369 np
->buf
= ((char *)np
) + sizeof (struct netbuf
);
1370 (void) memcpy(np
->buf
, ap
->buf
, ap
->len
);
1376 netbuffree(struct netbuf
*ap
)
1382 handle_reply(svc_input_id_t id
, int fd
, unsigned int events
, void *cookie
)
1384 struct t_unitdata
*tr_data
;
1391 struct rpc_msg reply_msg
;
1395 struct netconfig
*nconf
;
1400 tr_data
= (struct t_unitdata
*)t_alloc(fd
, T_UNITDATA
,
1402 if (tr_data
== NULL
) {
1403 syslog(LOG_ERR
, "handle_reply: t_alloc failed!");
1412 res
= t_rcvudata(fd
, tr_data
, &moreflag
);
1413 if (moreflag
& T_MORE
) {
1414 /* Drop this packet - we have no more space. */
1416 fprintf(stderr
, "handle_reply: recvd packet "
1417 "with T_MORE flag set\n");
1420 } while (res
< 0 && t_errno
== TSYSERR
&& errno
== EINTR
);
1424 fprintf(stderr
, "handle_reply: t_rcvudata returned "
1425 "%d, t_errno %d, errno %d\n", res
, t_errno
, errno
);
1427 if (t_errno
== TLOOK
)
1428 (void) t_rcvuderr(fd
, NULL
);
1433 inlen
= tr_data
->udata
.len
;
1434 buffer
= tr_data
->udata
.buf
;
1435 assert(buffer
!= NULL
);
1436 xdrmem_create(&reply_xdrs
, buffer
, inlen
, XDR_DECODE
);
1438 reply_msg
.acpted_rply
.ar_verf
= _null_auth
;
1439 reply_msg
.acpted_rply
.ar_results
.where
= 0;
1440 reply_msg
.acpted_rply
.ar_results
.proc
= (xdrproc_t
)xdr_void
;
1442 if (!xdr_replymsg(&reply_xdrs
, &reply_msg
)) {
1443 xdr_destroy(&reply_xdrs
);
1445 (void) fprintf(stderr
,
1446 "handle_reply: xdr_replymsg failed\n");
1449 pos
= XDR_GETPOS(&reply_xdrs
);
1450 xdr_destroy(&reply_xdrs
);
1454 nconf
= rpcbind_get_conf((char *)cookie
);
1455 if (nconf
== NULL
) {
1456 syslog(LOG_ERR
, "handle_reply: rpcbind_get_conf failed!");
1459 uaddr
= taddr2uaddr(nconf
, &tr_data
->addr
);
1460 if (uaddr
== NULL
) {
1461 syslog(LOG_ERR
, "handle_reply: taddr2uaddr failed!");
1465 (void) mutex_lock(&finfo_lock
);
1466 fi
= forward_find(reply_msg
.rm_xid
, uaddr
);
1468 (void) mutex_unlock(&finfo_lock
);
1472 fi
->reply_data
= tr_data
;
1475 __seterr_reply(&reply_msg
, &fi
->reply_error
);
1478 fi
->res_val
= &buffer
[pos
];
1480 (void) cond_signal(&fi
->cv
);
1481 (void) mutex_unlock(&finfo_lock
);
1486 t_free((char *)tr_data
, T_UNITDATA
);
1490 * prog: Program Number
1491 * netid: Transport Provider token
1492 * lowvp: Low version number
1493 * highvp: High version number
1496 find_versions(rpcprog_t prog
, char *netid
, rpcvers_t
*lowvp
, rpcvers_t
*highvp
)
1500 rpcvers_t highv
= 0;
1502 assert(RW_LOCK_HELD(&list_rbl_lock
));
1504 for (rbl
= list_rbl
; rbl
!= NULL
; rbl
= rbl
->rpcb_next
) {
1505 if ((rbl
->rpcb_map
.r_prog
!= prog
) ||
1506 (strcasecmp(rbl
->rpcb_map
.r_netid
, netid
) != 0))
1509 highv
= rbl
->rpcb_map
.r_vers
;
1511 } else if (rbl
->rpcb_map
.r_vers
< lowv
) {
1512 lowv
= rbl
->rpcb_map
.r_vers
;
1513 } else if (rbl
->rpcb_map
.r_vers
> highv
) {
1514 highv
= rbl
->rpcb_map
.r_vers
;
1523 * returns the item with the given program, version number and netid.
1524 * If that version number is not found, it returns the item with that
1525 * program number, so that address is now returned to the caller. The
1526 * caller when makes a call to this program, version number, the call
1527 * will fail and it will return with PROGVERS_MISMATCH. The user can
1528 * then determine the highest and the lowest version number for this
1529 * program using clnt_geterr() and use those program version numbers.
1531 * Returns the RPCBLIST for the given prog, vers and netid
1533 * prog: Program Number
1534 * vers: Version Number
1535 * netid: Transport Provider token
1538 find_service(rpcprog_t prog
, rpcvers_t vers
, char *netid
)
1540 rpcblist_ptr hit
= NULL
;
1543 assert(RW_LOCK_HELD(&list_rbl_lock
));
1545 for (rbl
= list_rbl
; rbl
!= NULL
; rbl
= rbl
->rpcb_next
) {
1546 if ((rbl
->rpcb_map
.r_prog
!= prog
) ||
1547 (strcasecmp(rbl
->rpcb_map
.r_netid
, netid
) != 0))
1550 if (rbl
->rpcb_map
.r_vers
== vers
)
1558 * If the caller is from our zone and we know
1559 * who it is, we return the uid.
1562 rpcb_caller_uid(SVCXPRT
*transp
)
1564 ucred_t
*uc
= alloca(ucred_size());
1566 if (svc_getcallerucred(transp
, &uc
) != 0 ||
1567 (ucred_getzoneid(uc
)) != myzone
) {
1570 return (ucred_geteuid(uc
));
1575 * Copies the name associated with the uid of the caller and returns
1576 * a pointer to it. Similar to getwd().
1579 getowner(SVCXPRT
*transp
, char *owner
)
1581 uid_t uid
= rpcb_caller_uid(transp
);
1585 return (strcpy(owner
, "unknown"));
1587 return (strcpy(owner
, "superuser"));
1589 (void) sprintf(owner
, "%u", uid
);
1596 * Add this to the pmap list only if it is UDP or TCP.
1599 add_pmaplist(RPCB
*arg
)
1603 int h1
, h2
, h3
, h4
, p1
, p2
;
1605 if (strcmp(arg
->r_netid
, udptrans
) == 0) {
1607 pmap
.pm_prot
= IPPROTO_UDP
;
1608 } else if (strcmp(arg
->r_netid
, tcptrans
) == 0) {
1610 pmap
.pm_prot
= IPPROTO_TCP
;
1612 /* Not a IP protocol */
1615 /* interpret the universal address for TCP/IP */
1616 if (sscanf(arg
->r_addr
, "%d.%d.%d.%d.%d.%d",
1617 &h1
, &h2
, &h3
, &h4
, &p1
, &p2
) != 6)
1619 pmap
.pm_port
= ((p1
& 0xff) << 8) + (p2
& 0xff);
1620 pmap
.pm_prog
= arg
->r_prog
;
1621 pmap
.pm_vers
= arg
->r_vers
;
1623 * add to END of list
1625 pml
= (pmaplist
*) malloc((uint_t
)sizeof (pmaplist
));
1627 (void) syslog(LOG_ERR
, "rpcbind: no memory!\n");
1630 pml
->pml_map
= pmap
;
1631 pml
->pml_next
= NULL
;
1633 (void) rw_wrlock(&list_pml_lock
);
1634 if (list_pml
== NULL
) {
1639 /* Attach to the end of the list */
1640 for (fnd
= list_pml
; fnd
->pml_next
; fnd
= fnd
->pml_next
)
1642 fnd
->pml_next
= pml
;
1644 (void) rw_unlock(&list_pml_lock
);
1650 * Delete this from the pmap list only if it is UDP or TCP.
1653 del_pmaplist(RPCB
*arg
)
1656 pmaplist
*prevpml
, *fnd
;
1659 if (strcmp(arg
->r_netid
, udptrans
) == 0) {
1662 } else if (strcmp(arg
->r_netid
, tcptrans
) == 0) {
1665 } else if (arg
->r_netid
[0] == '\0') {
1666 prot
= 0; /* Remove all occurrences */
1668 /* Not a IP protocol */
1672 assert(RW_WRITE_HELD(&list_pml_lock
));
1674 for (prevpml
= NULL
, pml
= list_pml
; pml
; /* cstyle */) {
1675 if ((pml
->pml_map
.pm_prog
!= arg
->r_prog
) ||
1676 (pml
->pml_map
.pm_vers
!= arg
->r_vers
) ||
1677 (prot
&& (pml
->pml_map
.pm_prot
!= prot
))) {
1678 /* both pml & prevpml move forwards */
1680 pml
= pml
->pml_next
;
1683 /* found it; pml moves forward, prevpml stays */
1685 pml
= pml
->pml_next
;
1686 if (prevpml
== NULL
)
1689 prevpml
->pml_next
= pml
;
1695 #endif /* PORTMAP */