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