138494Sobrien/* 2174313Sobrien * Copyright (c) 1997-2006 Erez Zadok 338494Sobrien * Copyright (c) 1989 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1989 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1989 The Regents of the University of California. 638494Sobrien * All rights reserved. 738494Sobrien * 838494Sobrien * This code is derived from software contributed to Berkeley by 938494Sobrien * Jan-Simon Pendry at Imperial College, London. 1038494Sobrien * 1138494Sobrien * Redistribution and use in source and binary forms, with or without 1238494Sobrien * modification, are permitted provided that the following conditions 1338494Sobrien * are met: 1438494Sobrien * 1. Redistributions of source code must retain the above copyright 1538494Sobrien * notice, this list of conditions and the following disclaimer. 1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1738494Sobrien * notice, this list of conditions and the following disclaimer in the 1838494Sobrien * documentation and/or other materials provided with the distribution. 1938494Sobrien * 3. All advertising materials mentioning features or use of this software 2042629Sobrien * must display the following acknowledgment: 2138494Sobrien * This product includes software developed by the University of 2238494Sobrien * California, Berkeley and its contributors. 2338494Sobrien * 4. Neither the name of the University nor the names of its contributors 2438494Sobrien * may be used to endorse or promote products derived from this software 2538494Sobrien * without specific prior written permission. 2638494Sobrien * 2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3038494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3738494Sobrien * SUCH DAMAGE. 3838494Sobrien * 3938494Sobrien * 40174313Sobrien * File: am-utils/amd/nfs_prot_svc.c 4138494Sobrien * 4238494Sobrien */ 4338494Sobrien 4438494Sobrien#ifdef HAVE_CONFIG_H 4538494Sobrien# include <config.h> 4638494Sobrien#endif /* HAVE_CONFIG_H */ 4738494Sobrien#include <am_defs.h> 4838494Sobrien#include <amd.h> 4938494Sobrien 5038494Sobrien/* external definitions */ 5138494Sobrienextern voidp nfsproc_null_2_svc(voidp, struct svc_req *); 5282794Sobrienextern nfsattrstat *nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *); 5382794Sobrienextern nfsattrstat *nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *); 5438494Sobrienextern voidp nfsproc_root_2_svc(voidp, struct svc_req *); 5582794Sobrienextern nfsdiropres *nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *); 5682794Sobrienextern nfsreadlinkres *nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *); 5782794Sobrienextern nfsreadres *nfsproc_read_2_svc(nfsreadargs *, struct svc_req *); 5838494Sobrienextern voidp nfsproc_writecache_2_svc(voidp, struct svc_req *); 5982794Sobrienextern nfsattrstat *nfsproc_write_2_svc(nfswriteargs *, struct svc_req *); 6082794Sobrienextern nfsdiropres *nfsproc_create_2_svc(nfscreateargs *, struct svc_req *); 6182794Sobrienextern nfsstat *nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *); 6282794Sobrienextern nfsstat *nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *); 6382794Sobrienextern nfsstat *nfsproc_link_2_svc(nfslinkargs *, struct svc_req *); 6482794Sobrienextern nfsstat *nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *); 6582794Sobrienextern nfsdiropres *nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *); 6682794Sobrienextern nfsstat *nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *); 6782794Sobrienextern nfsreaddirres *nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *); 6882794Sobrienextern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *); 6938494Sobrien 7038494Sobrien/* global variables */ 71174313SobrienSVCXPRT *current_transp; 7238494Sobrien 7338494Sobrien/* typedefs */ 7438494Sobrientypedef char *(*nfssvcproc_t)(voidp, struct svc_req *); 7538494Sobrien 7638494Sobrien 7738494Sobrienvoid 7838494Sobriennfs_program_2(struct svc_req *rqstp, SVCXPRT *transp) 7938494Sobrien{ 8038494Sobrien union { 8138494Sobrien am_nfs_fh nfsproc_getattr_2_arg; 8238494Sobrien nfssattrargs nfsproc_setattr_2_arg; 8338494Sobrien nfsdiropargs nfsproc_lookup_2_arg; 8438494Sobrien am_nfs_fh nfsproc_readlink_2_arg; 8538494Sobrien nfsreadargs nfsproc_read_2_arg; 8638494Sobrien nfswriteargs nfsproc_write_2_arg; 8738494Sobrien nfscreateargs nfsproc_create_2_arg; 8838494Sobrien nfsdiropargs nfsproc_remove_2_arg; 8938494Sobrien nfsrenameargs nfsproc_rename_2_arg; 9038494Sobrien nfslinkargs nfsproc_link_2_arg; 9138494Sobrien nfssymlinkargs nfsproc_symlink_2_arg; 9238494Sobrien nfscreateargs nfsproc_mkdir_2_arg; 9338494Sobrien nfsdiropargs fsproc_rmdir_2_arg; 9438494Sobrien nfsreaddirargs nfsproc_readdir_2_arg; 9538494Sobrien am_nfs_fh nfsproc_statfs_2_arg; 9638494Sobrien } argument; 9738494Sobrien char *result; 9838494Sobrien xdrproc_t xdr_argument, xdr_result; 9938494Sobrien nfssvcproc_t local; 100174313Sobrien 101174313Sobrien#ifdef HAVE_TRANSPORT_TYPE_TLI 102174313Sobrien /* 103174313Sobrien * On TLI systems we don't use an INET network type, but a "ticlts" (see 104174313Sobrien * /etc/netconfig and conf/transp_tli.c:create_nfs_service). This means 105174313Sobrien * that packets could only come from the loopback interface, and we don't 106174313Sobrien * need to check them and filter possibly spoofed packets. Therefore we 107174313Sobrien * only need to check if the UID caller is correct. 108174313Sobrien */ 109174313Sobrien# ifdef HAVE___RPC_GET_LOCAL_UID 110174313Sobrien uid_t u; 111174313Sobrien /* extern definition for an internal libnsl function */ 112174313Sobrien extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid); 113174313Sobrien if (__rpc_get_local_uid(transp, &u) >= 0 && u != 0) { 114174313Sobrien plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u); 115174313Sobrien return; 116174313Sobrien } 117174313Sobrien# else /* not HAVE___RPC_GET_LOCAL_UID */ 118174313Sobrien dlog("cannot verify local uid for rpc request"); 119174313Sobrien# endif /* HAVE___RPC_GET_LOCAL_UID */ 120174313Sobrien#else /* not HAVE_TRANPORT_TYPE_TLI */ 12151292Sobrien struct sockaddr_in *sinp; 12251292Sobrien char dq[20], dq2[28]; 12351292Sobrien sinp = amu_svc_getcaller(rqstp->rq_xprt); 124174313Sobrien# ifdef MNT2_NFS_OPT_RESVPORT 12551292Sobrien /* Verify that the request comes from a reserved port */ 126174313Sobrien if (sinp && 127174313Sobrien ntohs(sinp->sin_port) >= IPPORT_RESERVED && 128131702Smbr !(gopt.flags & CFM_NFS_INSECURE_PORT)) { 12951292Sobrien plog(XLOG_WARNING, "ignoring request from %s:%u, port not reserved", 130174313Sobrien inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr), 13151292Sobrien ntohs(sinp->sin_port)); 13251292Sobrien return; 13351292Sobrien } 134174313Sobrien# endif /* MNT2_NFS_OPT_RESVPORT */ 13551292Sobrien /* if the address does not match, ignore the request */ 136174313Sobrien if (sinp && (sinp->sin_addr.s_addr != myipaddr.s_addr)) { 137174313Sobrien if (gopt.flags & CFM_NFS_ANY_INTERFACE) { 138174313Sobrien if (!is_interface_local(sinp->sin_addr.s_addr)) { 139174313Sobrien plog(XLOG_WARNING, "ignoring request from %s:%u, not a local interface", 140174313Sobrien inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr), 141174313Sobrien ntohs(sinp->sin_port)); 142174313Sobrien } 143174313Sobrien } else { 144174313Sobrien plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s", 145174313Sobrien inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr), 146174313Sobrien ntohs(sinp->sin_port), 147174313Sobrien inet_dquad(dq2, sizeof(dq2), myipaddr.s_addr)); 148174313Sobrien return; 149174313Sobrien } 15051292Sobrien } 151174313Sobrien#endif /* not HAVE_TRANPORT_TYPE_TLI */ 15251292Sobrien 153174313Sobrien current_transp = NULL; 15438494Sobrien 15538494Sobrien switch (rqstp->rq_proc) { 15638494Sobrien 15738494Sobrien case NFSPROC_NULL: 15838494Sobrien xdr_argument = (xdrproc_t) xdr_void; 15938494Sobrien xdr_result = (xdrproc_t) xdr_void; 16038494Sobrien local = (nfssvcproc_t) nfsproc_null_2_svc; 16138494Sobrien break; 16238494Sobrien 16338494Sobrien case NFSPROC_GETATTR: 16438494Sobrien xdr_argument = (xdrproc_t) xdr_nfs_fh; 16538494Sobrien xdr_result = (xdrproc_t) xdr_attrstat; 16638494Sobrien local = (nfssvcproc_t) nfsproc_getattr_2_svc; 16738494Sobrien break; 16838494Sobrien 16938494Sobrien case NFSPROC_SETATTR: 17038494Sobrien xdr_argument = (xdrproc_t) xdr_sattrargs; 17138494Sobrien xdr_result = (xdrproc_t) xdr_attrstat; 17238494Sobrien local = (nfssvcproc_t) nfsproc_setattr_2_svc; 17338494Sobrien break; 17438494Sobrien 17538494Sobrien case NFSPROC_ROOT: 17638494Sobrien xdr_argument = (xdrproc_t) xdr_void; 17738494Sobrien xdr_result = (xdrproc_t) xdr_void; 17838494Sobrien local = (nfssvcproc_t) nfsproc_root_2_svc; 17938494Sobrien break; 18038494Sobrien 18138494Sobrien case NFSPROC_LOOKUP: 18238494Sobrien xdr_argument = (xdrproc_t) xdr_diropargs; 18338494Sobrien xdr_result = (xdrproc_t) xdr_diropres; 18438494Sobrien local = (nfssvcproc_t) nfsproc_lookup_2_svc; 18538494Sobrien /* 18638494Sobrien * Cheap way to pass transp down to amfs_auto_lookuppn so it can 18738494Sobrien * be stored in the am_node structure and later used for 18838494Sobrien * quick_reply(). 18938494Sobrien */ 190174313Sobrien current_transp = transp; 19138494Sobrien break; 19238494Sobrien 19338494Sobrien case NFSPROC_READLINK: 19438494Sobrien xdr_argument = (xdrproc_t) xdr_nfs_fh; 19538494Sobrien xdr_result = (xdrproc_t) xdr_readlinkres; 19638494Sobrien local = (nfssvcproc_t) nfsproc_readlink_2_svc; 19738494Sobrien break; 19838494Sobrien 19938494Sobrien case NFSPROC_READ: 20038494Sobrien xdr_argument = (xdrproc_t) xdr_readargs; 20138494Sobrien xdr_result = (xdrproc_t) xdr_readres; 20238494Sobrien local = (nfssvcproc_t) nfsproc_read_2_svc; 20338494Sobrien break; 20438494Sobrien 20538494Sobrien case NFSPROC_WRITECACHE: 20638494Sobrien xdr_argument = (xdrproc_t) xdr_void; 20738494Sobrien xdr_result = (xdrproc_t) xdr_void; 20838494Sobrien local = (nfssvcproc_t) nfsproc_writecache_2_svc; 20938494Sobrien break; 21038494Sobrien 21138494Sobrien case NFSPROC_WRITE: 21238494Sobrien xdr_argument = (xdrproc_t) xdr_writeargs; 21338494Sobrien xdr_result = (xdrproc_t) xdr_attrstat; 21438494Sobrien local = (nfssvcproc_t) nfsproc_write_2_svc; 21538494Sobrien break; 21638494Sobrien 21738494Sobrien case NFSPROC_CREATE: 21838494Sobrien xdr_argument = (xdrproc_t) xdr_createargs; 21938494Sobrien xdr_result = (xdrproc_t) xdr_diropres; 22038494Sobrien local = (nfssvcproc_t) nfsproc_create_2_svc; 22138494Sobrien break; 22238494Sobrien 22338494Sobrien case NFSPROC_REMOVE: 22438494Sobrien xdr_argument = (xdrproc_t) xdr_diropargs; 22538494Sobrien xdr_result = (xdrproc_t) xdr_nfsstat; 22638494Sobrien local = (nfssvcproc_t) nfsproc_remove_2_svc; 22738494Sobrien break; 22838494Sobrien 22938494Sobrien case NFSPROC_RENAME: 23038494Sobrien xdr_argument = (xdrproc_t) xdr_renameargs; 23138494Sobrien xdr_result = (xdrproc_t) xdr_nfsstat; 23238494Sobrien local = (nfssvcproc_t) nfsproc_rename_2_svc; 23338494Sobrien break; 23438494Sobrien 23538494Sobrien case NFSPROC_LINK: 23638494Sobrien xdr_argument = (xdrproc_t) xdr_linkargs; 23738494Sobrien xdr_result = (xdrproc_t) xdr_nfsstat; 23838494Sobrien local = (nfssvcproc_t) nfsproc_link_2_svc; 23938494Sobrien break; 24038494Sobrien 24138494Sobrien case NFSPROC_SYMLINK: 24238494Sobrien xdr_argument = (xdrproc_t) xdr_symlinkargs; 24338494Sobrien xdr_result = (xdrproc_t) xdr_nfsstat; 24438494Sobrien local = (nfssvcproc_t) nfsproc_symlink_2_svc; 24538494Sobrien break; 24638494Sobrien 24738494Sobrien case NFSPROC_MKDIR: 24838494Sobrien xdr_argument = (xdrproc_t) xdr_createargs; 24938494Sobrien xdr_result = (xdrproc_t) xdr_diropres; 25038494Sobrien local = (nfssvcproc_t) nfsproc_mkdir_2_svc; 25138494Sobrien break; 25238494Sobrien 25338494Sobrien case NFSPROC_RMDIR: 25438494Sobrien xdr_argument = (xdrproc_t) xdr_diropargs; 25538494Sobrien xdr_result = (xdrproc_t) xdr_nfsstat; 25638494Sobrien local = (nfssvcproc_t) nfsproc_rmdir_2_svc; 25738494Sobrien break; 25838494Sobrien 25938494Sobrien case NFSPROC_READDIR: 26038494Sobrien xdr_argument = (xdrproc_t) xdr_readdirargs; 26138494Sobrien xdr_result = (xdrproc_t) xdr_readdirres; 26238494Sobrien local = (nfssvcproc_t) nfsproc_readdir_2_svc; 26338494Sobrien break; 26438494Sobrien 26538494Sobrien case NFSPROC_STATFS: 26638494Sobrien xdr_argument = (xdrproc_t) xdr_nfs_fh; 26738494Sobrien xdr_result = (xdrproc_t) xdr_statfsres; 26838494Sobrien local = (nfssvcproc_t) nfsproc_statfs_2_svc; 26938494Sobrien break; 27038494Sobrien 27138494Sobrien default: 27238494Sobrien svcerr_noproc(transp); 27338494Sobrien return; 27438494Sobrien } 27538494Sobrien 27638494Sobrien memset((char *) &argument, 0, sizeof(argument)); 27738494Sobrien if (!svc_getargs(transp, 27838494Sobrien (XDRPROC_T_TYPE) xdr_argument, 27938494Sobrien (SVC_IN_ARG_TYPE) &argument)) { 28038494Sobrien plog(XLOG_ERROR, 28138494Sobrien "NFS xdr decode failed for %d %d %d", 28251292Sobrien (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc); 28338494Sobrien svcerr_decode(transp); 28438494Sobrien return; 28538494Sobrien } 28638494Sobrien result = (*local) (&argument, rqstp); 28738494Sobrien 288174313Sobrien current_transp = NULL; 28938494Sobrien 29038494Sobrien if (result != NULL && !svc_sendreply(transp, 29138494Sobrien (XDRPROC_T_TYPE) xdr_result, 29238494Sobrien result)) { 29338494Sobrien svcerr_systemerr(transp); 29438494Sobrien } 29538494Sobrien if (!svc_freeargs(transp, 29638494Sobrien (XDRPROC_T_TYPE) xdr_argument, 29738494Sobrien (SVC_IN_ARG_TYPE) & argument)) { 29838494Sobrien plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_2"); 29938494Sobrien going_down(1); 30038494Sobrien } 30138494Sobrien} 302