xref: /dragonfly/usr.sbin/rpcbind/rpcb_svc.c (revision 67640b13)
1 /*
2  * Copyright (c) 2009, Sun Microsystems, Inc.
3  * All rights reserved.
4  *
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.
15  *
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.
27  *
28  * @(#)rpcb_svc.c	1.16	93/07/05 SMI"
29  * $NetBSD: rpcb_svc.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $
30  * $FreeBSD: src/usr.sbin/rpcbind/rpcb_svc.c,v 1.3 2007/11/07 10:53:39 kevlo Exp $
31  */
32 /*
33  * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
34  */
35 
36 /*
37  * rpcb_svc.c
38  * The server procedure for the version 3 rpcbind (TLI).
39  *
40  * It maintains a separate list of all the registered services with the
41  * version 3 of rpcbind.
42  */
43 #include <sys/types.h>
44 #include <rpc/rpc.h>
45 #include <rpc/rpcb_prot.h>
46 #include <netconfig.h>
47 #include <syslog.h>
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 
52 #include "rpcbind.h"
53 
54 static void	*rpcbproc_getaddr_3_local(void *, struct svc_req *, SVCXPRT *,
55 					  rpcvers_t);
56 static void	*rpcbproc_dump_3_local(void *, struct svc_req *, SVCXPRT *,
57 				       rpcvers_t);
58 
59 /*
60  * Called by svc_getreqset. There is a separate server handle for
61  * every transport that it waits on.
62  */
63 void
64 rpcb_service_3(struct svc_req *rqstp, SVCXPRT *transp)
65 {
66 	union {
67 		RPCB rpcbproc_set_3_arg;
68 		RPCB rpcbproc_unset_3_arg;
69 		RPCB rpcbproc_getaddr_3_local_arg;
70 		struct rpcb_rmtcallargs rpcbproc_callit_3_arg;
71 		char *rpcbproc_uaddr2taddr_3_arg;
72 		struct netbuf rpcbproc_taddr2uaddr_3_arg;
73 	} argument;
74 	char *result;
75 	xdrproc_t xdr_argument, xdr_result;
76 	void *(*local)(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
77 
78 	rpcbs_procinfo(RPCBVERS_3_STAT, rqstp->rq_proc);
79 
80 	switch (rqstp->rq_proc) {
81 	case NULLPROC:
82 		/*
83 		 * Null proc call
84 		 */
85 #ifdef RPCBIND_DEBUG
86 		if (debugging)
87 			fprintf(stderr, "RPCBPROC_NULL\n");
88 #endif
89 		/* This call just logs, no actual checks */
90 		check_access(transp, rqstp->rq_proc, NULL, RPCBVERS);
91 		svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
92 		return;
93 
94 	case RPCBPROC_SET:
95 		xdr_argument = (xdrproc_t )xdr_rpcb;
96 		xdr_result = (xdrproc_t )xdr_bool;
97 		local = rpcbproc_set_com;
98 		break;
99 
100 	case RPCBPROC_UNSET:
101 		xdr_argument = (xdrproc_t)xdr_rpcb;
102 		xdr_result = (xdrproc_t)xdr_bool;
103 		local = rpcbproc_unset_com;
104 		break;
105 
106 	case RPCBPROC_GETADDR:
107 		xdr_argument = (xdrproc_t)xdr_rpcb;
108 		xdr_result = (xdrproc_t)xdr_wrapstring;
109 		local = rpcbproc_getaddr_3_local;
110 		break;
111 
112 	case RPCBPROC_DUMP:
113 #ifdef RPCBIND_DEBUG
114 		if (debugging)
115 			fprintf(stderr, "RPCBPROC_DUMP\n");
116 #endif
117 		xdr_argument = (xdrproc_t)xdr_void;
118 		xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
119 		local = rpcbproc_dump_3_local;
120 		break;
121 
122 	case RPCBPROC_CALLIT:
123 		rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS);
124 		return;
125 
126 	case RPCBPROC_GETTIME:
127 #ifdef RPCBIND_DEBUG
128 		if (debugging)
129 			fprintf(stderr, "RPCBPROC_GETTIME\n");
130 #endif
131 		xdr_argument = (xdrproc_t)xdr_void;
132 		xdr_result = (xdrproc_t)xdr_u_long;
133 		local = rpcbproc_gettime_com;
134 		break;
135 
136 	case RPCBPROC_UADDR2TADDR:
137 #ifdef RPCBIND_DEBUG
138 		if (debugging)
139 			fprintf(stderr, "RPCBPROC_UADDR2TADDR\n");
140 #endif
141 		xdr_argument = (xdrproc_t)xdr_wrapstring;
142 		xdr_result = (xdrproc_t)xdr_netbuf;
143 		local = rpcbproc_uaddr2taddr_com;
144 		break;
145 
146 	case RPCBPROC_TADDR2UADDR:
147 #ifdef RPCBIND_DEBUG
148 		if (debugging)
149 			fprintf(stderr, "RPCBPROC_TADDR2UADDR\n");
150 #endif
151 		xdr_argument = (xdrproc_t)xdr_netbuf;
152 		xdr_result = (xdrproc_t)xdr_wrapstring;
153 		local = rpcbproc_taddr2uaddr_com;
154 		break;
155 
156 	default:
157 		svcerr_noproc(transp);
158 		return;
159 	}
160 	memset((char *)&argument, 0, sizeof (argument));
161 	if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
162 				(char *) &argument)) {
163 		svcerr_decode(transp);
164 		if (debugging)
165 			fprintf(stderr, "rpcbind: could not decode\n");
166 		return;
167 	}
168 	if (!check_access(transp, rqstp->rq_proc, &argument, RPCBVERS)) {
169 		svcerr_weakauth(transp);
170 		goto done;
171 	}
172 	result = (*local)(&argument, rqstp, transp, RPCBVERS);
173 	if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result,
174 						result)) {
175 		svcerr_systemerr(transp);
176 		if (debugging) {
177 			fprintf(stderr, "rpcbind: svc_sendreply\n");
178 			if (doabort) {
179 				rpcbind_abort();
180 			}
181 		}
182 	}
183 done:
184 	if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *)
185 				&argument)) {
186 		if (debugging) {
187 			fprintf(stderr, "unable to free arguments\n");
188 			if (doabort) {
189 				rpcbind_abort();
190 			}
191 		}
192 	}
193 }
194 
195 /*
196  * Lookup the mapping for a program, version and return its
197  * address. Assuming that the caller wants the address of the
198  * server running on the transport on which the request came.
199  *
200  * We also try to resolve the universal address in terms of
201  * address of the caller.
202  */
203 /* ARGSUSED */
204 static void *
205 rpcbproc_getaddr_3_local(void *arg, struct svc_req *rqstp __unused,
206 			 SVCXPRT *transp __unused, rpcvers_t versnum __unused)
207 {
208 	RPCB *regp = (RPCB *)arg;
209 #ifdef RPCBIND_DEBUG
210 	if (debugging) {
211 		char *uaddr;
212 
213 		uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
214 			    svc_getrpccaller(transp));
215 		fprintf(stderr, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
216 		    (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
217 		    regp->r_netid, uaddr);
218 		free(uaddr);
219 	}
220 #endif
221 	return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS,
222 	    RPCB_ALLVERS));
223 }
224 
225 /* ARGSUSED */
226 static void *
227 rpcbproc_dump_3_local(void *arg __unused, struct svc_req *rqstp __unused,
228 		      SVCXPRT *transp __unused, rpcvers_t versnum __unused)
229 {
230 	return ((void *)&list_rbl);
231 }
232