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.
27 * Copyright 2017 Joyent Inc
29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 * The Regents of the University of California
36 * University Acknowledgment- Portions of this document are derived from
37 * software developed by the University of California, Berkeley, and its
43 * The commom server procedure for the rpcbind.
47 #include <sys/types.h>
54 #include <rpc/rpcb_prot.h>
55 #include <rpcsvc/svc_dg_priv.h>
56 #include <netconfig.h>
57 #include <sys/param.h>
61 #include <sys/stropts.h>
63 #include <netinet/in.h>
64 #include <rpc/pmap_prot.h>
72 #include <rpcsvc/yp_prot.h>
74 #include <nfs/nfs_acl.h>
75 #include <rpcsvc/mount.h>
76 #include <nfs/nfs_acl.h>
77 #include <rpc/key_prot.h>
78 #include <rpcsvc/yp_prot.h>
79 #include <rpcsvc/rquota.h>
80 #include <rpcsvc/yppasswd.h>
81 #include <rpcsvc/ypupd.h>
85 #include <sys/debug.h>
87 static struct finfo
*forward_register(ulong_t
, struct netbuf
*, int, char *);
88 static void forward_destroy(struct finfo
*);
89 static void handle_reply(svc_input_id_t
, int, unsigned int, void *);
90 static int netbufcmp(struct netbuf
*, struct netbuf
*);
91 static void netbuffree(struct netbuf
*);
92 static struct netbuf
*netbufdup(struct netbuf
*);
93 static void find_versions(rpcprog_t
, char *, rpcvers_t
*, rpcvers_t
*);
94 static rpcblist_ptr
find_service(ulong_t
, ulong_t
, char *);
96 static int add_pmaplist(RPCB
*);
102 * Set a mapping of program, version, netid
105 rpcbproc_set_com(RPCB
*regp
, bool_t
*result
, struct svc_req
*rqstp
,
110 *result
= map_set(regp
, getowner(rqstp
->rq_xprt
, owner
));
112 rpcbs_set(rpcbversnum
- PMAPVERS
, *result
);
118 map_set(RPCB
*regp
, char *owner
)
121 rpcblist_ptr rbl
, fnd
;
124 * check to see if already used
125 * find_service returns a hit even if
126 * the versions don't match, so check for it
128 (void) rw_wrlock(&list_rbl_lock
);
130 (void) rw_wrlock(&list_pml_lock
);
132 fnd
= find_service(regp
->r_prog
, regp
->r_vers
, regp
->r_netid
);
133 if (fnd
&& (fnd
->rpcb_map
.r_vers
== regp
->r_vers
)) {
134 if (strcmp(fnd
->rpcb_map
.r_addr
, regp
->r_addr
) == 0) {
136 * if these match then it is already
137 * registered so just say "OK".
140 (void) rw_unlock(&list_pml_lock
);
142 (void) rw_unlock(&list_rbl_lock
);
146 * Check if server is up. If so, return FALSE.
147 * If not, cleanup old registrations for the
148 * program and register the new server.
150 if (is_bound(fnd
->rpcb_map
.r_netid
,
151 fnd
->rpcb_map
.r_addr
)) {
153 (void) rw_unlock(&list_pml_lock
);
155 (void) rw_unlock(&list_rbl_lock
);
159 delete_prog(regp
->r_prog
);
164 (void) rw_unlock(&list_pml_lock
);
168 * add to the end of the list
170 rbl
= malloc(sizeof (RPCBLIST
));
172 (void) rw_unlock(&list_rbl_lock
);
176 a
->r_prog
= regp
->r_prog
;
177 a
->r_vers
= regp
->r_vers
;
178 a
->r_netid
= strdup(regp
->r_netid
);
179 a
->r_addr
= strdup(regp
->r_addr
);
180 a
->r_owner
= strdup(owner
);
181 if (a
->r_addr
== NULL
|| a
->r_netid
== NULL
|| a
->r_owner
== NULL
) {
182 (void) rw_unlock(&list_rbl_lock
);
186 rbl
->rpcb_next
= NULL
;
187 if (list_rbl
== NULL
) {
190 for (fnd
= list_rbl
; fnd
->rpcb_next
; fnd
= fnd
->rpcb_next
)
192 fnd
->rpcb_next
= rbl
;
196 (void) add_pmaplist(regp
);
198 (void) rw_unlock(&list_rbl_lock
);
203 * Unset a mapping of program, version, netid
206 rpcbproc_unset_com(RPCB
*regp
, bool_t
*result
, struct svc_req
*rqstp
,
211 *result
= map_unset(regp
, getowner(rqstp
->rq_xprt
, owner
));
213 rpcbs_unset(rpcbversnum
- PMAPVERS
, *result
);
219 map_unset(RPCB
*regp
, char *owner
)
224 rpcblist_ptr rbl
, next
, prev
= NULL
;
229 (void) rw_wrlock(&list_rbl_lock
);
230 for (rbl
= list_rbl
; rbl
!= NULL
; rbl
= next
) {
231 next
= rbl
->rpcb_next
;
233 if ((rbl
->rpcb_map
.r_prog
!= regp
->r_prog
) ||
234 (rbl
->rpcb_map
.r_vers
!= regp
->r_vers
) ||
235 (regp
->r_netid
[0] && strcasecmp(regp
->r_netid
,
236 rbl
->rpcb_map
.r_netid
))) {
237 /* prev moves forwards */
243 * Check whether appropriate uid. Unset only
244 * if superuser or the owner itself.
246 if (strcmp(owner
, "superuser") &&
247 strcmp(rbl
->rpcb_map
.r_owner
, owner
)) {
248 (void) rw_unlock(&list_rbl_lock
);
261 prev
->rpcb_next
= next
;
265 (void) rw_wrlock(&list_pml_lock
);
266 (void) del_pmaplist(regp
);
267 (void) rw_unlock(&list_pml_lock
);
270 (void) rw_unlock(&list_rbl_lock
);
273 * We return 1 either when the entry was not there or it
274 * was able to unset it. It can come to this point only if
275 * at least one of the conditions is true.
281 delete_rbl(rpcblist_ptr rbl
)
283 free(rbl
->rpcb_map
.r_addr
);
284 free(rbl
->rpcb_map
.r_netid
);
285 free(rbl
->rpcb_map
.r_owner
);
290 delete_prog(rpcprog_t prog
)
292 rpcblist_ptr rbl
, next
, prev
= NULL
;
294 assert(RW_WRITE_HELD(&list_rbl_lock
));
296 for (rbl
= list_rbl
; rbl
!= NULL
; rbl
= next
) {
297 next
= rbl
->rpcb_next
;
299 if (rbl
->rpcb_map
.r_prog
!= prog
||
300 is_bound(rbl
->rpcb_map
.r_netid
, rbl
->rpcb_map
.r_addr
)) {
306 (void) del_pmaplist(&rbl
->rpcb_map
);
313 prev
->rpcb_next
= next
;
318 * Lookup the mapping for a program, version and return its
319 * address. Assuming that the caller wants the address of the
320 * server running on the transport on which the request came.
322 * For RPCBPROC_GETVERSADDR it will return a service with the exact version
325 * Otherwise, even if a service with a different version number is available,
326 * it will return that address. The client should check with an
327 * clnt_call to verify whether the service is the one that is desired.
329 * We also try to resolve the universal address in terms of
330 * address of the caller.
333 rpcbproc_getaddr_com(RPCB
*regp
, char **result
, struct svc_req
*rqstp
,
338 struct netconfig
*trans_conf
; /* transport netconfig */
339 SVCXPRT
*transp
= rqstp
->rq_xprt
;
340 int verstype
= rqstp
->rq_proc
== RPCBPROC_GETVERSADDR
? RPCB_ONEVERS
:
342 bool_t pml_locked
= FALSE
;
345 * There is a potential window at startup during which rpcbind
346 * service has been established over IPv6 but not over IPv4. If an
347 * IPv4 request comes in during that window, the IP code will map
348 * it into IPv6. We could patch up the request so that it looks
349 * like IPv4 (so that rpcbind returns an IPv4 uaddr to the caller),
350 * but that requires some non-trivial code and it's hard to test.
351 * Instead, drop the request on the floor and force the caller to
352 * retransmit. By the time rpcbind sees the retransmission, IPv4
353 * service should be in place and it should see the request as
356 trans_conf
= rpcbind_get_conf(transp
->xp_netid
);
357 if (strcmp(trans_conf
->nc_protofmly
, NC_INET6
) == 0) {
358 struct sockaddr_in6
*rmtaddr
;
360 rmtaddr
= (struct sockaddr_in6
*)transp
->xp_rtaddr
.buf
;
361 if (IN6_IS_ADDR_V4MAPPED(&rmtaddr
->sin6_addr
)) {
363 "IPv4 GETADDR request mapped to IPv6: ignoring");
369 (void) rw_rdlock(&list_rbl_lock
);
371 fnd
= find_service(regp
->r_prog
, regp
->r_vers
, transp
->xp_netid
);
372 if (fnd
&& ((verstype
== RPCB_ALLVERS
) ||
373 (regp
->r_vers
== fnd
->rpcb_map
.r_vers
))) {
374 if (*(regp
->r_addr
) != '\0') { /* may contain a hint about */
375 saddr
= regp
->r_addr
; /* the interface that we */
377 if (!(*result
= mergeaddr(transp
, transp
->xp_netid
,
378 fnd
->rpcb_map
.r_addr
, saddr
))) {
379 /* Try whatever we have */
380 *result
= strdup(fnd
->rpcb_map
.r_addr
);
381 } else if (!(*result
)[0]) {
383 (void) rw_unlock(&list_rbl_lock
);
384 (void) rw_wrlock(&list_rbl_lock
);
386 (void) rw_wrlock(&list_pml_lock
);
392 * The server died. Unset all versions of this prog.
394 delete_prog(regp
->r_prog
);
402 (void) rw_unlock(&list_pml_lock
);
404 (void) rw_unlock(&list_rbl_lock
);
406 rpcbs_getaddr(rpcbversnum
- PMAPVERS
, regp
->r_prog
, regp
->r_vers
,
407 transp
->xp_netid
, *result
);
413 rpcbproc_dump_com(void *argp
, rpcblist_ptr
**result
)
416 * list_rbl_lock is unlocked in xdr_rpcblist_ptr_ptr()
418 (void) rw_rdlock(&list_rbl_lock
);
424 xdr_rpcblist_ptr_ptr(XDR
*xdrs
, rpcblist_ptr
**objp
)
426 if (xdrs
->x_op
== XDR_FREE
) {
428 * list_rbl_lock is locked in rpcbproc_dump_com()
430 rw_unlock(&list_rbl_lock
);
434 return (xdr_rpcblist_ptr(xdrs
, *objp
));
439 rpcbproc_gettime_com(void *argp
, ulong_t
*result
)
441 (void) time((time_t *)result
);
447 * Convert uaddr to taddr. Should be used only by
448 * local servers/clients. (kernel level stuff only)
451 rpcbproc_uaddr2taddr_com(char **uaddrp
, struct netbuf
*result
,
452 struct svc_req
*rqstp
)
454 struct netconfig
*nconf
;
455 struct netbuf
*taddr
;
457 if (((nconf
= rpcbind_get_conf(rqstp
->rq_xprt
->xp_netid
)) == NULL
) ||
458 ((taddr
= uaddr2taddr(nconf
, *uaddrp
)) == NULL
)) {
459 (void) memset(result
, 0, sizeof (*result
));
463 memcpy(result
, taddr
, sizeof (*result
));
470 * Convert taddr to uaddr. Should be used only by
471 * local servers/clients. (kernel level stuff only)
474 rpcbproc_taddr2uaddr_com(struct netbuf
*taddr
, char **result
,
475 struct svc_req
*rqstp
)
477 struct netconfig
*nconf
;
479 if ((nconf
= rpcbind_get_conf(rqstp
->rq_xprt
->xp_netid
)) == NULL
)
482 *result
= taddr2uaddr(nconf
, taddr
);
488 * Stuff for the rmtcall service
491 xdr_rpcb_rmtcallargs(XDR
*xdrs
, rpcb_rmtcallargs
*objp
)
493 if (!xdr_u_long(xdrs
, &objp
->prog
))
495 if (!xdr_u_long(xdrs
, &objp
->vers
))
497 if (!xdr_u_long(xdrs
, &objp
->proc
))
499 if (!xdr_bytes(xdrs
, (char **)&objp
->args
.args_val
,
500 (uint_t
*)&objp
->args
.args_len
, ~0))
507 xdr_rmtcallres(XDR
*xdrs
, rmtcallres
*objp
)
509 if (!xdr_u_long(xdrs
, &objp
->port
))
511 if (!xdr_bytes(xdrs
, (char **)&objp
->res
.res_val
,
512 (uint_t
*)&objp
->res
.res_len
, ~0))
519 xdr_rpcb_rmtcallres(XDR
*xdrs
, rpcb_rmtcallres
*objp
)
521 if (!xdr_string(xdrs
, &objp
->addr
, ~0))
523 if (!xdr_bytes(xdrs
, (char **)&objp
->results
.results_val
,
524 (uint_t
*)&objp
->results
.results_len
, ~0))
529 struct rmtcallfd_list
{
532 struct rmtcallfd_list
*next
;
535 static struct rmtcallfd_list
*rmthead
;
536 static struct rmtcallfd_list
*rmttail
;
538 #define MASKVAL (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)
541 create_rmtcall_fd(struct netconfig
*nconf
)
544 struct rmtcallfd_list
*rmt
;
546 if ((fd
= t_open(nconf
->nc_device
, O_RDWR
, NULL
)) == -1) {
548 fprintf(stderr
, "create_rmtcall_fd: couldn't open "
549 "\"%s\" (errno %d, t_errno %d)\n",
550 nconf
->nc_device
, errno
, t_errno
);
554 if (t_bind(fd
, NULL
, NULL
) == -1) {
556 fprintf(stderr
, "create_rmtcall_fd: couldn't bind to "
557 "fd for \"%s\" (errno %d, t_errno %d)\n",
558 nconf
->nc_device
, errno
, t_errno
);
562 rmt
= malloc(sizeof (struct rmtcallfd_list
));
564 syslog(LOG_ERR
, "create_rmtcall_fd: no memory!");
568 rmt
->netid
= strdup(nconf
->nc_netid
);
569 if (rmt
->netid
== NULL
) {
571 syslog(LOG_ERR
, "create_rmtcall_fd: no memory!");
575 if (svc_add_input(fd
, MASKVAL
, handle_reply
, rmt
->netid
) == -1) {
578 syslog(LOG_ERR
, "create_rmtcall_fd: svc_add_input() failed!");
584 if (rmthead
== NULL
) {
596 find_rmtcallfd_by_netid(char *netid
)
598 struct rmtcallfd_list
*rmt
;
600 for (rmt
= rmthead
; rmt
!= NULL
; rmt
= rmt
->next
) {
601 if (strcmp(netid
, rmt
->netid
) == 0) {
608 #define MAXTIME_OFF 300 /* 5 minutes timeout for rmtcalls */
614 #define FINFO_ACTIVE 0x1
616 struct netbuf
*caller_addr
;
620 struct t_unitdata
*reply_data
;
621 struct rpc_err reply_error
;
628 * finfo_lock protects rpcb_rmtcalls, rpcb_rmtcalls_max, lastxid,
629 * fihead, and fitail.
631 static mutex_t finfo_lock
= DEFAULTMUTEX
;
633 static int rpcb_rmtcalls
;
634 static int rpcb_rmtcalls_max
;
635 static ulong_t lastxid
;
636 static struct finfo
*fihead
;
637 static struct finfo
*fitail
;
640 set_rpcb_rmtcalls_max(int max
)
642 (void) mutex_lock(&finfo_lock
);
643 rpcb_rmtcalls_max
= max
;
644 if (rpcb_rmtcalls
> rpcb_rmtcalls_max
) {
645 assert(fitail
!= NULL
);
646 (void) cond_signal(&fitail
->cv
);
648 (void) mutex_unlock(&finfo_lock
);
652 * Call a remote procedure service. This procedure is very quiet when things
653 * go wrong. The proc is written to support broadcast rpc. In the broadcast
654 * case, a machine should shut-up instead of complain, lest the requestor be
655 * overrun with complaints at the expense of not hearing a valid reply.
656 * When receiving a request and verifying that the service exists, we
658 * receive the request
660 * open a new TLI endpoint on the same transport on which we received
661 * the original request
663 * remember the original request's XID (which requires knowing the format
664 * of the svc_dg_data structure)
666 * forward the request, with a new XID, to the requested service,
667 * remembering the XID used to send this request (for later use in
668 * reassociating the answer with the original request), the requestor's
669 * address, the file descriptor on which the forwarded request is
670 * made and the service's address
672 * wait for either the timeout or the condition variable is signalled from
675 * At some time in the future, a reply will be received from the service to
676 * which we forwarded the request. At that time, svc_run() detect that the
677 * socket used was for forwarding and call handle_reply() to
681 * bundle the reply, along with the service's universal address
683 * put the reply into the particular finfo
685 * signal the condition variable.
688 #define RPC_BUF_MAX 65536 /* can be raised if required */
691 * This is from ../ypcmd/yp_b.h
692 * It does not appear in <rpcsvc/yp_prot.h>
694 #define YPBINDPROG ((ulong_t)100007)
695 #define YPBINDPROC_SETDOM ((ulong_t)2)
698 * reply_type - which proc number
699 * versnum - which vers was called
702 rpcbproc_callit_com(struct svc_req
*rqstp
, SVCXPRT
*transp
, ulong_t reply_type
,
708 rpcb_rmtcallargs arg
;
711 struct netconfig
*nconf
;
712 struct netbuf
*caller
;
713 struct nd_mergearg ma
;
717 struct svc_dg_data
*bd
;
720 struct rpc_msg call_msg
;
721 char outbuf
[RPC_BUF_MAX
];
722 char *outbuf_alloc
= NULL
;
724 bool_t outxdr_created
= FALSE
;
728 struct t_unitdata tu_data
;
733 (void) mutex_lock(&finfo_lock
);
734 if (!allow_indirect
|| rpcb_rmtcalls_max
== 0) {
735 (void) mutex_unlock(&finfo_lock
);
738 (void) mutex_unlock(&finfo_lock
);
740 if (t_getinfo(transp
->xp_fd
, &tinfo
) == -1) {
741 if (reply_type
== RPCBPROC_INDIRECT
)
742 svcerr_systemerr(transp
);
745 if (tinfo
.servtype
!= T_CLTS
)
746 return; /* Only datagram type accepted */
748 sendsz
= __rpc_get_t_size(0, tinfo
.tsdu
);
749 if (sendsz
== 0) { /* data transfer not supported */
750 if (reply_type
== RPCBPROC_INDIRECT
)
751 svcerr_systemerr(transp
);
755 * Should be multiple of 4 for XDR.
757 sendsz
= ((sendsz
+ 3) / 4) * 4;
759 (void) memset((char *)&arg
, 0, sizeof (arg
));
760 if (!svc_getargs(transp
, xdr_rpcb_rmtcallargs
, (char *)&arg
)) {
761 if (reply_type
== RPCBPROC_INDIRECT
)
762 svcerr_decode(transp
);
765 "rpcbproc_callit_com: svc_getargs failed\n");
770 * Disallow calling rpcbind for certain procedures.
771 * Allow calling NULLPROC - per man page on rpcb_rmtcall().
772 * switch is in alphabetical order.
774 if (arg
.proc
!= NULLPROC
) {
779 "rpcbind: rejecting KEY_PROG(%d)\n",
783 if (arg
.proc
!= MOUNTPROC_MNT
)
786 * In Solaris 2.6, the host-based accesss control
787 * is done by the NFS server on each request.
788 * Prior to 2.6 we rely on mountd.
792 "rpcbind: rejecting MOUNTPROG(%d)\n",
795 case NFS_ACL_PROGRAM
:
798 "rpcbind: rejecting NFS_ACL_PROGRAM(%d)\n",
802 /* also NFS3_PROGRAM */
805 "rpcbind: rejecting NFS_PROGRAM(%d)\n",
810 * Disallow calling rpcbind for certain procedures.
811 * Luckily Portmap set/unset/callit also have same
812 * procedure numbers. So, will not check for those.
817 case RPCBPROC_CALLIT
:
818 case RPCBPROC_INDIRECT
:
819 if (reply_type
== RPCBPROC_INDIRECT
)
820 svcerr_weakauth(transp
); /* XXX */
822 fprintf(stderr
, "rpcbproc_callit_com: "
823 "calling RPCBPROG procs SET, "
824 "UNSET, CALLIT, or INDIRECT not "
829 * Ideally, we should have called rpcb_service()
830 * or pmap_service() with appropriate parameters
831 * instead of going about in a roundabout
832 * manner. Hopefully, this case should happen
841 "rpcbind: rejecting RQUOTAPROG(%d)\n",
847 "rpcbind: rejecting YPPASSWDPROG(%d)\n",
853 "rpcbind: rejecting YPU_PROG(%d)\n",
857 if (arg
.proc
!= YPBINDPROC_SETDOM
)
861 "rpcbind: rejecting YPBINDPROG(%d)\n",
872 "rpcbind: rejecting YPPROG(%d)\n",
884 (void) rw_rdlock(&list_rbl_lock
);
885 rbl
= find_service(arg
.prog
, arg
.vers
, transp
->xp_netid
);
887 rpcbs_rmtcall(versnum
- PMAPVERS
, reply_type
, arg
.prog
, arg
.vers
,
888 arg
.proc
, transp
->xp_netid
, rbl
);
891 (void) rw_unlock(&list_rbl_lock
);
892 if (reply_type
== RPCBPROC_INDIRECT
)
893 svcerr_noprog(transp
);
896 if (rbl
->rpcb_map
.r_vers
!= arg
.vers
) {
897 if (reply_type
== RPCBPROC_INDIRECT
) {
898 ulong_t vers_low
, vers_high
;
900 find_versions(arg
.prog
, transp
->xp_netid
,
901 &vers_low
, &vers_high
);
902 (void) rw_unlock(&list_rbl_lock
);
903 svcerr_progvers(transp
, vers_low
, vers_high
);
905 (void) rw_unlock(&list_rbl_lock
);
911 * Check whether this entry is valid and a server is present
912 * Mergeaddr() returns NULL if no such entry is present, and
913 * returns "" if the entry was present but the server is not
914 * present (i.e., it crashed).
916 if (reply_type
== RPCBPROC_INDIRECT
) {
917 char *uaddr
= mergeaddr(transp
, transp
->xp_netid
,
918 rbl
->rpcb_map
.r_addr
, NULL
);
919 if ((uaddr
== (char *)NULL
) || uaddr
[0] == '\0') {
920 (void) rw_unlock(&list_rbl_lock
);
921 svcerr_noprog(transp
);
928 nconf
= rpcbind_get_conf(transp
->xp_netid
);
930 (void) rw_unlock(&list_rbl_lock
);
931 if (reply_type
== RPCBPROC_INDIRECT
)
932 svcerr_systemerr(transp
);
935 "rpcbproc_callit_com: rpcbind_get_conf failed\n");
939 caller
= svc_getrpccaller(transp
);
940 ma
.c_uaddr
= taddr2uaddr(nconf
, caller
);
941 ma
.s_uaddr
= rbl
->rpcb_map
.r_addr
;
944 * A mergeaddr operation allocates a string, which it stores in
945 * ma.m_uaddr. It's passed to forward_register() and is
946 * eventually freed by forward_destroy().
948 stat
= netdir_options(nconf
, ND_MERGEADDR
, 0, (char *)&ma
);
949 (void) rw_unlock(&list_rbl_lock
);
952 (void) syslog(LOG_ERR
, "netdir_merge failed for %s: %s",
953 nconf
->nc_netid
, netdir_sperror());
955 if ((fd
= find_rmtcallfd_by_netid(nconf
->nc_netid
)) == -1) {
956 if (reply_type
== RPCBPROC_INDIRECT
)
957 svcerr_systemerr(transp
);
962 bd
= get_svc_dg_data(transp
);
964 assert(!MUTEX_HELD(&finfo_lock
));
965 fi
= forward_register(bd
->su_xid
, caller
, fd
, ma
.m_uaddr
);
967 /* forward_register failed. Perhaps no memory. */
971 "rpcbproc_callit_com: forward_register failed\n");
972 assert(!MUTEX_HELD(&finfo_lock
));
975 /* forward_register() returns with finfo_lock held when successful */
976 assert(MUTEX_HELD(&finfo_lock
));
978 if (fi
->flag
& FINFO_ACTIVE
) {
980 * A duplicate request for the slow server. Let's not
981 * beat on it any more.
983 (void) mutex_unlock(&finfo_lock
);
987 "rpcbproc_callit_com: duplicate request\n");
990 fi
->flag
|= FINFO_ACTIVE
;
992 call_msg
.rm_xid
= fi
->forward_xid
;
993 call_msg
.rm_direction
= CALL
;
994 call_msg
.rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
995 call_msg
.rm_call
.cb_prog
= arg
.prog
;
996 call_msg
.rm_call
.cb_vers
= arg
.vers
;
998 if (sendsz
> RPC_BUF_MAX
) {
999 outbuf_alloc
= malloc(sendsz
);
1000 if (outbuf_alloc
== NULL
) {
1001 forward_destroy(fi
);
1002 (void) mutex_unlock(&finfo_lock
);
1003 if (reply_type
== RPCBPROC_INDIRECT
)
1004 svcerr_systemerr(transp
);
1007 "rpcbproc_callit_com: No memory!\n");
1010 xdrmem_create(&outxdr
, outbuf_alloc
, sendsz
, XDR_ENCODE
);
1012 xdrmem_create(&outxdr
, outbuf
, sendsz
, XDR_ENCODE
);
1014 outxdr_created
= TRUE
;
1016 if (!xdr_callhdr(&outxdr
, &call_msg
)) {
1017 forward_destroy(fi
);
1018 (void) mutex_unlock(&finfo_lock
);
1019 if (reply_type
== RPCBPROC_INDIRECT
)
1020 svcerr_systemerr(transp
);
1023 "rpcbproc_callit_com: xdr_callhdr failed\n");
1027 if (!xdr_u_long(&outxdr
, &arg
.proc
)) {
1028 forward_destroy(fi
);
1029 (void) mutex_unlock(&finfo_lock
);
1030 if (reply_type
== RPCBPROC_INDIRECT
)
1031 svcerr_systemerr(transp
);
1034 "rpcbproc_callit_com: xdr_u_long failed\n");
1038 if (rqstp
->rq_cred
.oa_flavor
== AUTH_NULL
) {
1039 auth
= authnone_create();
1040 } else if (rqstp
->rq_cred
.oa_flavor
== AUTH_SYS
) {
1041 struct authsys_parms
*au
;
1043 CTASSERT(sizeof (struct authsys_parms
) <= RQCRED_SIZE
);
1044 au
= (struct authsys_parms
*)rqstp
->rq_clntcred
;
1045 auth
= authsys_create(au
->aup_machname
, au
->aup_uid
,
1046 au
->aup_gid
, au
->aup_len
, au
->aup_gids
);
1047 if (auth
== NULL
) /* fall back */
1048 auth
= authnone_create();
1050 /* we do not support any other authentication scheme */
1051 forward_destroy(fi
);
1052 (void) mutex_unlock(&finfo_lock
);
1053 if (reply_type
== RPCBPROC_INDIRECT
)
1054 svcerr_weakauth(transp
); /* XXX too strong.. */
1056 fprintf(stderr
, "rpcbproc_callit_com: oa_flavor != "
1057 "AUTH_NONE and oa_flavor != AUTH_SYS\n");
1061 forward_destroy(fi
);
1062 (void) mutex_unlock(&finfo_lock
);
1063 if (reply_type
== RPCBPROC_INDIRECT
)
1064 svcerr_systemerr(transp
);
1066 fprintf(stderr
, "rpcbproc_callit_com: "
1067 "authwhatever_create returned NULL\n");
1070 if (!AUTH_MARSHALL(auth
, &outxdr
)) {
1071 forward_destroy(fi
);
1072 (void) mutex_unlock(&finfo_lock
);
1073 if (reply_type
== RPCBPROC_INDIRECT
)
1074 svcerr_systemerr(transp
);
1078 "rpcbproc_callit_com: AUTH_MARSHALL failed\n");
1083 if (!xdr_opaque(&outxdr
, arg
.args
.args_val
, arg
.args
.args_len
)) {
1084 forward_destroy(fi
);
1085 (void) mutex_unlock(&finfo_lock
);
1086 if (reply_type
== RPCBPROC_INDIRECT
)
1087 svcerr_systemerr(transp
);
1090 "rpcbproc_callit_com: xdr_opaque failed\n");
1094 tu_data
.udata
.len
= XDR_GETPOS(&outxdr
);
1096 tu_data
.udata
.buf
= outbuf_alloc
;
1098 tu_data
.udata
.buf
= outbuf
;
1099 tu_data
.opt
.len
= 0;
1101 na
= uaddr2taddr(nconf
, ma
.m_uaddr
);
1103 forward_destroy(fi
);
1104 (void) mutex_unlock(&finfo_lock
);
1105 if (reply_type
== RPCBPROC_INDIRECT
)
1106 svcerr_systemerr(transp
);
1111 if (t_sndudata(fd
, &tu_data
) == -1) {
1113 forward_destroy(fi
);
1114 (void) mutex_unlock(&finfo_lock
);
1116 netdir_free((char *)na
, ND_ADDR
);
1118 if (reply_type
== RPCBPROC_INDIRECT
)
1119 svcerr_systemerr(transp
);
1122 "rpcbproc_callit_com: t_sndudata failed: "
1123 "t_errno %d, errno %d\n", t_errno
, err
);
1127 netdir_free((char *)na
, ND_ADDR
);
1128 xdr_destroy(&outxdr
);
1129 outxdr_created
= FALSE
;
1130 if (outbuf_alloc
!= NULL
) {
1132 outbuf_alloc
= NULL
;
1134 svc_freeargs(transp
, xdr_rpcb_rmtcallargs
, (char *)&arg
);
1136 to
.tv_sec
= time(NULL
) + MAXTIME_OFF
;
1139 while (fi
->reply_data
== NULL
&&
1140 cond_timedwait(&fi
->cv
, &finfo_lock
, &to
) != ETIME
)
1143 if (fi
->reply_data
== NULL
) {
1144 forward_destroy(fi
);
1145 (void) mutex_unlock(&finfo_lock
);
1147 if (reply_type
== RPCBPROC_INDIRECT
)
1148 svcerr_systemerr(transp
);
1150 (void) fprintf(stderr
,
1151 "rpcbproc_callit_com: timeout\n");
1155 if (fi
->reply_error
.re_status
!= RPC_SUCCESS
) {
1156 forward_destroy(fi
);
1157 (void) mutex_unlock(&finfo_lock
);
1159 if (reply_type
== RPCBPROC_INDIRECT
)
1160 svcerr_systemerr(transp
);
1162 (void) fprintf(stderr
,
1163 "rpcbproc_callit_com: error in reply: %s\n",
1164 clnt_sperrno(fi
->reply_error
.re_status
));
1173 int h1
, h2
, h3
, h4
, p1
, p2
;
1175 /* interpret the universal address for TCP/IP */
1176 if (sscanf(fi
->uaddr
, "%d.%d.%d.%d.%d.%d",
1177 &h1
, &h2
, &h3
, &h4
, &p1
, &p2
) != 6)
1180 result
.port
= ((p1
& 0xff) << 8) + (p2
& 0xff);
1181 result
.res
.res_len
= fi
->res_len
;
1182 result
.res
.res_val
= fi
->res_val
;
1184 svc_sendreply(transp
, xdr_rmtcallres
, (char *)&result
);
1191 rpcb_rmtcallres result
;
1193 result
.addr
= fi
->uaddr
;
1194 result
.results
.results_len
= fi
->res_len
;
1195 result
.results
.results_val
= fi
->res_val
;
1197 svc_sendreply(transp
, xdr_rpcb_rmtcallres
,
1203 forward_destroy(fi
);
1204 (void) mutex_unlock(&finfo_lock
);
1210 xdr_destroy(&outxdr
);
1212 svc_freeargs(transp
, xdr_rpcb_rmtcallargs
, (char *)&arg
);
1215 static struct finfo
*forward_find(ulong_t
, char *);
1218 * Adds an entry into the finfo list for the given request. Returns the finfo
1219 * and finfo_lock is left held. If duplicate request, returns finfo with
1220 * FINFO_ACTIVE, else returns finfo without FINFO_ACTIVE.
1221 * If failed, returns NULL and finfo_lock is left unheld.
1223 static struct finfo
*
1224 forward_register(ulong_t caller_xid
, struct netbuf
*caller_addr
, int forward_fd
,
1229 (void) mutex_lock(&finfo_lock
);
1230 if (rpcb_rmtcalls_max
== 0) {
1231 (void) mutex_unlock(&finfo_lock
);
1236 * initialization: once this has happened, lastxid will
1237 * never be 0 again, when entering or returning from this function.
1240 lastxid
= time(NULL
);
1243 * Check if it is an duplicate entry
1245 for (fi
= fihead
; fi
!= NULL
; fi
= fi
->next
) {
1246 if (fi
->caller_xid
== caller_xid
&&
1247 netbufcmp(fi
->caller_addr
, caller_addr
)) {
1248 assert(fi
->flag
& FINFO_ACTIVE
);
1253 fi
= malloc(sizeof (*fi
));
1255 (void) mutex_unlock(&finfo_lock
);
1259 if ((fi
->caller_addr
= netbufdup(caller_addr
)) == NULL
) {
1260 (void) mutex_unlock(&finfo_lock
);
1266 * Generate new xid and make sure it is unique.
1270 /* avoid lastxid wraparound to 0 */
1273 } while (forward_find(lastxid
, uaddr
) != NULL
);
1284 fi
->caller_xid
= caller_xid
;
1286 fi
->forward_xid
= lastxid
;
1287 fi
->forward_fd
= forward_fd
;
1290 * Though uaddr is not allocated here, it will still be freed
1291 * from forward_destroy().
1295 fi
->reply_data
= NULL
;
1296 (void) cond_init(&fi
->cv
, USYNC_THREAD
, NULL
);
1299 if (rpcb_rmtcalls
> rpcb_rmtcalls_max
) {
1300 assert(fitail
!= fi
);
1301 (void) cond_signal(&fitail
->cv
);
1308 forward_destroy(struct finfo
*fi
)
1310 assert(MUTEX_HELD(&finfo_lock
));
1311 assert(fi
->flag
& FINFO_ACTIVE
);
1314 assert(fi
->prev
== NULL
);
1317 fi
->prev
->next
= fi
->next
;
1321 assert(fi
->next
== NULL
);
1324 fi
->next
->prev
= fi
->prev
;
1327 netbuffree(fi
->caller_addr
);
1329 if (fi
->reply_data
!= NULL
)
1330 t_free((char *)fi
->reply_data
, T_UNITDATA
);
1331 (void) cond_destroy(&fi
->cv
);
1336 if (rpcb_rmtcalls
> rpcb_rmtcalls_max
) {
1337 assert(fitail
!= NULL
);
1338 (void) cond_signal(&fitail
->cv
);
1342 static struct finfo
*
1343 forward_find(ulong_t reply_xid
, char *uaddr
)
1347 assert(MUTEX_HELD(&finfo_lock
));
1349 for (fi
= fihead
; fi
!= NULL
; fi
= fi
->next
) {
1350 if (fi
->forward_xid
== reply_xid
&&
1351 strcmp(fi
->uaddr
, uaddr
) == 0)
1359 netbufcmp(struct netbuf
*n1
, struct netbuf
*n2
)
1361 return ((n1
->len
!= n2
->len
) || memcmp(n1
->buf
, n2
->buf
, n1
->len
));
1364 static struct netbuf
*
1365 netbufdup(struct netbuf
*ap
)
1369 np
= malloc(sizeof (struct netbuf
) + ap
->len
);
1371 np
->maxlen
= np
->len
= ap
->len
;
1372 np
->buf
= ((char *)np
) + sizeof (struct netbuf
);
1373 (void) memcpy(np
->buf
, ap
->buf
, ap
->len
);
1379 netbuffree(struct netbuf
*ap
)
1385 handle_reply(svc_input_id_t id
, int fd
, unsigned int events
, void *cookie
)
1387 struct t_unitdata
*tr_data
;
1394 struct rpc_msg reply_msg
;
1398 struct netconfig
*nconf
;
1403 tr_data
= (struct t_unitdata
*)t_alloc(fd
, T_UNITDATA
,
1405 if (tr_data
== NULL
) {
1406 syslog(LOG_ERR
, "handle_reply: t_alloc failed!");
1415 res
= t_rcvudata(fd
, tr_data
, &moreflag
);
1416 if (moreflag
& T_MORE
) {
1417 /* Drop this packet - we have no more space. */
1419 fprintf(stderr
, "handle_reply: recvd packet "
1420 "with T_MORE flag set\n");
1423 } while (res
< 0 && t_errno
== TSYSERR
&& errno
== EINTR
);
1427 fprintf(stderr
, "handle_reply: t_rcvudata returned "
1428 "%d, t_errno %d, errno %d\n", res
, t_errno
, errno
);
1430 if (t_errno
== TLOOK
)
1431 (void) t_rcvuderr(fd
, NULL
);
1436 inlen
= tr_data
->udata
.len
;
1437 buffer
= tr_data
->udata
.buf
;
1438 assert(buffer
!= NULL
);
1439 xdrmem_create(&reply_xdrs
, buffer
, inlen
, XDR_DECODE
);
1441 reply_msg
.acpted_rply
.ar_verf
= _null_auth
;
1442 reply_msg
.acpted_rply
.ar_results
.where
= 0;
1443 reply_msg
.acpted_rply
.ar_results
.proc
= (xdrproc_t
)xdr_void
;
1445 if (!xdr_replymsg(&reply_xdrs
, &reply_msg
)) {
1446 xdr_destroy(&reply_xdrs
);
1448 (void) fprintf(stderr
,
1449 "handle_reply: xdr_replymsg failed\n");
1452 pos
= XDR_GETPOS(&reply_xdrs
);
1453 xdr_destroy(&reply_xdrs
);
1457 nconf
= rpcbind_get_conf((char *)cookie
);
1458 if (nconf
== NULL
) {
1459 syslog(LOG_ERR
, "handle_reply: rpcbind_get_conf failed!");
1462 uaddr
= taddr2uaddr(nconf
, &tr_data
->addr
);
1463 if (uaddr
== NULL
) {
1464 syslog(LOG_ERR
, "handle_reply: taddr2uaddr failed!");
1468 (void) mutex_lock(&finfo_lock
);
1469 fi
= forward_find(reply_msg
.rm_xid
, uaddr
);
1471 (void) mutex_unlock(&finfo_lock
);
1475 fi
->reply_data
= tr_data
;
1478 __seterr_reply(&reply_msg
, &fi
->reply_error
);
1481 fi
->res_val
= &buffer
[pos
];
1483 (void) cond_signal(&fi
->cv
);
1484 (void) mutex_unlock(&finfo_lock
);
1489 t_free((char *)tr_data
, T_UNITDATA
);
1493 * prog: Program Number
1494 * netid: Transport Provider token
1495 * lowvp: Low version number
1496 * highvp: High version number
1499 find_versions(rpcprog_t prog
, char *netid
, rpcvers_t
*lowvp
, rpcvers_t
*highvp
)
1503 rpcvers_t highv
= 0;
1505 assert(RW_LOCK_HELD(&list_rbl_lock
));
1507 for (rbl
= list_rbl
; rbl
!= NULL
; rbl
= rbl
->rpcb_next
) {
1508 if ((rbl
->rpcb_map
.r_prog
!= prog
) ||
1509 (strcasecmp(rbl
->rpcb_map
.r_netid
, netid
) != 0))
1512 highv
= rbl
->rpcb_map
.r_vers
;
1514 } else if (rbl
->rpcb_map
.r_vers
< lowv
) {
1515 lowv
= rbl
->rpcb_map
.r_vers
;
1516 } else if (rbl
->rpcb_map
.r_vers
> highv
) {
1517 highv
= rbl
->rpcb_map
.r_vers
;
1526 * returns the item with the given program, version number and netid.
1527 * If that version number is not found, it returns the item with that
1528 * program number, so that address is now returned to the caller. The
1529 * caller when makes a call to this program, version number, the call
1530 * will fail and it will return with PROGVERS_MISMATCH. The user can
1531 * then determine the highest and the lowest version number for this
1532 * program using clnt_geterr() and use those program version numbers.
1534 * Returns the RPCBLIST for the given prog, vers and netid
1536 * prog: Program Number
1537 * vers: Version Number
1538 * netid: Transport Provider token
1541 find_service(rpcprog_t prog
, rpcvers_t vers
, char *netid
)
1543 rpcblist_ptr hit
= NULL
;
1546 assert(RW_LOCK_HELD(&list_rbl_lock
));
1548 for (rbl
= list_rbl
; rbl
!= NULL
; rbl
= rbl
->rpcb_next
) {
1549 if ((rbl
->rpcb_map
.r_prog
!= prog
) ||
1550 (strcasecmp(rbl
->rpcb_map
.r_netid
, netid
) != 0))
1553 if (rbl
->rpcb_map
.r_vers
== vers
)
1561 * If the caller is from our zone and we know
1562 * who it is, we return the uid.
1565 rpcb_caller_uid(SVCXPRT
*transp
)
1567 ucred_t
*uc
= alloca(ucred_size());
1569 if (svc_getcallerucred(transp
, &uc
) != 0 ||
1570 (ucred_getzoneid(uc
)) != myzone
) {
1573 return (ucred_geteuid(uc
));
1578 * Copies the name associated with the uid of the caller and returns
1579 * a pointer to it. Similar to getwd().
1582 getowner(SVCXPRT
*transp
, char *owner
)
1584 uid_t uid
= rpcb_caller_uid(transp
);
1588 return (strcpy(owner
, "unknown"));
1590 return (strcpy(owner
, "superuser"));
1592 (void) sprintf(owner
, "%u", uid
);
1599 * Add this to the pmap list only if it is UDP or TCP.
1602 add_pmaplist(RPCB
*arg
)
1606 int h1
, h2
, h3
, h4
, p1
, p2
;
1608 if (strcmp(arg
->r_netid
, udptrans
) == 0) {
1610 pmap
.pm_prot
= IPPROTO_UDP
;
1611 } else if (strcmp(arg
->r_netid
, tcptrans
) == 0) {
1613 pmap
.pm_prot
= IPPROTO_TCP
;
1615 /* Not a IP protocol */
1618 /* interpret the universal address for TCP/IP */
1619 if (sscanf(arg
->r_addr
, "%d.%d.%d.%d.%d.%d",
1620 &h1
, &h2
, &h3
, &h4
, &p1
, &p2
) != 6)
1622 pmap
.pm_port
= ((p1
& 0xff) << 8) + (p2
& 0xff);
1623 pmap
.pm_prog
= arg
->r_prog
;
1624 pmap
.pm_vers
= arg
->r_vers
;
1626 * add to END of list
1628 pml
= (pmaplist
*) malloc((uint_t
)sizeof (pmaplist
));
1630 (void) syslog(LOG_ERR
, "rpcbind: no memory!\n");
1633 pml
->pml_map
= pmap
;
1634 pml
->pml_next
= NULL
;
1636 (void) rw_wrlock(&list_pml_lock
);
1637 if (list_pml
== NULL
) {
1642 /* Attach to the end of the list */
1643 for (fnd
= list_pml
; fnd
->pml_next
; fnd
= fnd
->pml_next
)
1645 fnd
->pml_next
= pml
;
1647 (void) rw_unlock(&list_pml_lock
);
1653 * Delete this from the pmap list only if it is UDP or TCP.
1656 del_pmaplist(RPCB
*arg
)
1659 pmaplist
*prevpml
, *fnd
;
1662 if (strcmp(arg
->r_netid
, udptrans
) == 0) {
1665 } else if (strcmp(arg
->r_netid
, tcptrans
) == 0) {
1668 } else if (arg
->r_netid
[0] == '\0') {
1669 prot
= 0; /* Remove all occurrences */
1671 /* Not a IP protocol */
1675 assert(RW_WRITE_HELD(&list_pml_lock
));
1677 for (prevpml
= NULL
, pml
= list_pml
; pml
; /* cstyle */) {
1678 if ((pml
->pml_map
.pm_prog
!= arg
->r_prog
) ||
1679 (pml
->pml_map
.pm_vers
!= arg
->r_vers
) ||
1680 (prot
&& (pml
->pml_map
.pm_prot
!= prot
))) {
1681 /* both pml & prevpml move forwards */
1683 pml
= pml
->pml_next
;
1686 /* found it; pml moves forward, prevpml stays */
1688 pml
= pml
->pml_next
;
1689 if (prevpml
== NULL
)
1692 prevpml
->pml_next
= pml
;
1698 #endif /* PORTMAP */