Home | History | Annotate | Line # | Download | only in amd
      1 /*	$NetBSD: nfs_prot_svc.c,v 1.1.1.3 2015/01/17 16:34:15 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997-2014 Erez Zadok
      5  * Copyright (c) 1989 Jan-Simon Pendry
      6  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
      7  * Copyright (c) 1989 The Regents of the University of California.
      8  * All rights reserved.
      9  *
     10  * This code is derived from software contributed to Berkeley by
     11  * Jan-Simon Pendry at Imperial College, London.
     12  *
     13  * Redistribution and use in source and binary forms, with or without
     14  * modification, are permitted provided that the following conditions
     15  * are met:
     16  * 1. Redistributions of source code must retain the above copyright
     17  *    notice, this list of conditions and the following disclaimer.
     18  * 2. Redistributions in binary form must reproduce the above copyright
     19  *    notice, this list of conditions and the following disclaimer in the
     20  *    documentation and/or other materials provided with the distribution.
     21  * 3. Neither the name of the University nor the names of its contributors
     22  *    may be used to endorse or promote products derived from this software
     23  *    without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35  * SUCH DAMAGE.
     36  *
     37  *
     38  * File: am-utils/amd/nfs_prot_svc.c
     39  *
     40  */
     41 
     42 #ifdef HAVE_CONFIG_H
     43 # include <config.h>
     44 #endif /* HAVE_CONFIG_H */
     45 #include <am_defs.h>
     46 #include <amd.h>
     47 
     48 /* external definitions */
     49 extern voidp nfsproc_null_2_svc(voidp, struct svc_req *);
     50 extern nfsattrstat *nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *);
     51 extern nfsattrstat *nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *);
     52 extern voidp nfsproc_root_2_svc(voidp, struct svc_req *);
     53 extern nfsdiropres *nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *);
     54 extern nfsreadlinkres *nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *);
     55 extern nfsreadres *nfsproc_read_2_svc(nfsreadargs *, struct svc_req *);
     56 extern voidp nfsproc_writecache_2_svc(voidp, struct svc_req *);
     57 extern nfsattrstat *nfsproc_write_2_svc(nfswriteargs *, struct svc_req *);
     58 extern nfsdiropres *nfsproc_create_2_svc(nfscreateargs *, struct svc_req *);
     59 extern nfsstat *nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *);
     60 extern nfsstat *nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *);
     61 extern nfsstat *nfsproc_link_2_svc(nfslinkargs *, struct svc_req *);
     62 extern nfsstat *nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *);
     63 extern nfsdiropres *nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *);
     64 extern nfsstat *nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *);
     65 extern nfsreaddirres *nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
     66 extern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
     67 
     68 /* global variables */
     69 SVCXPRT *current_transp;
     70 dispatcher_t nfs_dispatcher = nfs_program_2;
     71 
     72 /* typedefs */
     73 typedef char *(*nfssvcproc_t)(voidp, struct svc_req *);
     74 
     75 
     76 void
     77 nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
     78 {
     79   union {
     80     am_nfs_fh		nfsproc_getattr_2_arg;
     81     nfssattrargs	nfsproc_setattr_2_arg;
     82     nfsdiropargs	nfsproc_lookup_2_arg;
     83     am_nfs_fh		nfsproc_readlink_2_arg;
     84     nfsreadargs		nfsproc_read_2_arg;
     85     nfswriteargs	nfsproc_write_2_arg;
     86     nfscreateargs	nfsproc_create_2_arg;
     87     nfsdiropargs	nfsproc_remove_2_arg;
     88     nfsrenameargs	nfsproc_rename_2_arg;
     89     nfslinkargs		nfsproc_link_2_arg;
     90     nfssymlinkargs	nfsproc_symlink_2_arg;
     91     nfscreateargs	nfsproc_mkdir_2_arg;
     92     nfsdiropargs	fsproc_rmdir_2_arg;
     93     nfsreaddirargs	nfsproc_readdir_2_arg;
     94     am_nfs_fh		nfsproc_statfs_2_arg;
     95   } argument;
     96   char *result;
     97   xdrproc_t xdr_argument, xdr_result;
     98   nfssvcproc_t local;
     99 
    100 #ifdef HAVE_TRANSPORT_TYPE_TLI
    101   /*
    102    * On TLI systems we don't use an INET network type, but a "ticlts" (see
    103    * /etc/netconfig and conf/transp_tli.c:create_nfs_service).  This means
    104    * that packets could only come from the loopback interface, and we don't
    105    * need to check them and filter possibly spoofed packets.  Therefore we
    106    * only need to check if the UID caller is correct.
    107    */
    108 # ifdef HAVE___RPC_GET_LOCAL_UID
    109   uid_t u;
    110   /* extern definition for an internal libnsl function */
    111   extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid);
    112   if (__rpc_get_local_uid(transp, &u) >= 0  &&  u != 0) {
    113     plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u);
    114     return;
    115   }
    116 # else /* not HAVE___RPC_GET_LOCAL_UID */
    117   dlog("cannot verify local uid for rpc request");
    118 # endif /* HAVE___RPC_GET_LOCAL_UID */
    119 #else /* not HAVE_TRANPORT_TYPE_TLI */
    120   struct sockaddr_in *sinp;
    121   char dq[20], dq2[28];
    122   sinp = amu_svc_getcaller(rqstp->rq_xprt);
    123 # ifdef MNT2_NFS_OPT_RESVPORT
    124   /* Verify that the request comes from a reserved port */
    125   if (sinp &&
    126       ntohs(sinp->sin_port) >= IPPORT_RESERVED &&
    127       !(gopt.flags & CFM_NFS_INSECURE_PORT)) {
    128     plog(XLOG_WARNING, "ignoring request from %s:%u, port not reserved",
    129 	 inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
    130 	 ntohs(sinp->sin_port));
    131     return;
    132   }
    133 # endif /* MNT2_NFS_OPT_RESVPORT */
    134   /* if the address does not match, ignore the request */
    135   if (sinp && (sinp->sin_addr.s_addr != myipaddr.s_addr)) {
    136     if (gopt.flags & CFM_NFS_ANY_INTERFACE) {
    137       if (!is_interface_local(sinp->sin_addr.s_addr)) {
    138 	plog(XLOG_WARNING, "ignoring request from %s:%u, not a local interface",
    139 	     inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
    140 	     ntohs(sinp->sin_port));
    141       }
    142     } else {
    143       plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
    144 	   inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
    145 	   ntohs(sinp->sin_port),
    146 	   inet_dquad(dq2, sizeof(dq2), myipaddr.s_addr));
    147       return;
    148     }
    149   }
    150 #endif /* not HAVE_TRANPORT_TYPE_TLI */
    151 
    152   current_transp = NULL;
    153 
    154   switch (rqstp->rq_proc) {
    155 
    156   case NFSPROC_NULL:
    157     xdr_argument = (xdrproc_t) xdr_void;
    158     xdr_result = (xdrproc_t) xdr_void;
    159     local = (nfssvcproc_t) nfsproc_null_2_svc;
    160     break;
    161 
    162   case NFSPROC_GETATTR:
    163     xdr_argument = (xdrproc_t) xdr_nfs_fh;
    164     xdr_result = (xdrproc_t) xdr_attrstat;
    165     local = (nfssvcproc_t) nfsproc_getattr_2_svc;
    166     break;
    167 
    168   case NFSPROC_SETATTR:
    169     xdr_argument = (xdrproc_t) xdr_sattrargs;
    170     xdr_result = (xdrproc_t) xdr_attrstat;
    171     local = (nfssvcproc_t) nfsproc_setattr_2_svc;
    172     break;
    173 
    174   case NFSPROC_ROOT:
    175     xdr_argument = (xdrproc_t) xdr_void;
    176     xdr_result = (xdrproc_t) xdr_void;
    177     local = (nfssvcproc_t) nfsproc_root_2_svc;
    178     break;
    179 
    180   case NFSPROC_LOOKUP:
    181     xdr_argument = (xdrproc_t) xdr_diropargs;
    182     xdr_result = (xdrproc_t) xdr_diropres;
    183     local = (nfssvcproc_t) nfsproc_lookup_2_svc;
    184     /*
    185      * Cheap way to pass transp down to amfs_auto_lookuppn so it can
    186      * be stored in the am_node structure and later used for
    187      * quick_reply().
    188      */
    189     current_transp = transp;
    190     break;
    191 
    192   case NFSPROC_READLINK:
    193     xdr_argument = (xdrproc_t) xdr_nfs_fh;
    194     xdr_result = (xdrproc_t) xdr_readlinkres;
    195     local = (nfssvcproc_t) nfsproc_readlink_2_svc;
    196     break;
    197 
    198   case NFSPROC_READ:
    199     xdr_argument = (xdrproc_t) xdr_readargs;
    200     xdr_result = (xdrproc_t) xdr_readres;
    201     local = (nfssvcproc_t) nfsproc_read_2_svc;
    202     break;
    203 
    204   case NFSPROC_WRITECACHE:
    205     xdr_argument = (xdrproc_t) xdr_void;
    206     xdr_result = (xdrproc_t) xdr_void;
    207     local = (nfssvcproc_t) nfsproc_writecache_2_svc;
    208     break;
    209 
    210   case NFSPROC_WRITE:
    211     xdr_argument = (xdrproc_t) xdr_writeargs;
    212     xdr_result = (xdrproc_t) xdr_attrstat;
    213     local = (nfssvcproc_t) nfsproc_write_2_svc;
    214     break;
    215 
    216   case NFSPROC_CREATE:
    217     xdr_argument = (xdrproc_t) xdr_createargs;
    218     xdr_result = (xdrproc_t) xdr_diropres;
    219     local = (nfssvcproc_t) nfsproc_create_2_svc;
    220     break;
    221 
    222   case NFSPROC_REMOVE:
    223     xdr_argument = (xdrproc_t) xdr_diropargs;
    224     xdr_result = (xdrproc_t) xdr_nfsstat;
    225     local = (nfssvcproc_t) nfsproc_remove_2_svc;
    226     break;
    227 
    228   case NFSPROC_RENAME:
    229     xdr_argument = (xdrproc_t) xdr_renameargs;
    230     xdr_result = (xdrproc_t) xdr_nfsstat;
    231     local = (nfssvcproc_t) nfsproc_rename_2_svc;
    232     break;
    233 
    234   case NFSPROC_LINK:
    235     xdr_argument = (xdrproc_t) xdr_linkargs;
    236     xdr_result = (xdrproc_t) xdr_nfsstat;
    237     local = (nfssvcproc_t) nfsproc_link_2_svc;
    238     break;
    239 
    240   case NFSPROC_SYMLINK:
    241     xdr_argument = (xdrproc_t) xdr_symlinkargs;
    242     xdr_result = (xdrproc_t) xdr_nfsstat;
    243     local = (nfssvcproc_t) nfsproc_symlink_2_svc;
    244     break;
    245 
    246   case NFSPROC_MKDIR:
    247     xdr_argument = (xdrproc_t) xdr_createargs;
    248     xdr_result = (xdrproc_t) xdr_diropres;
    249     local = (nfssvcproc_t) nfsproc_mkdir_2_svc;
    250     break;
    251 
    252   case NFSPROC_RMDIR:
    253     xdr_argument = (xdrproc_t) xdr_diropargs;
    254     xdr_result = (xdrproc_t) xdr_nfsstat;
    255     local = (nfssvcproc_t) nfsproc_rmdir_2_svc;
    256     break;
    257 
    258   case NFSPROC_READDIR:
    259     xdr_argument = (xdrproc_t) xdr_readdirargs;
    260     xdr_result = (xdrproc_t) xdr_readdirres;
    261     local = (nfssvcproc_t) nfsproc_readdir_2_svc;
    262     break;
    263 
    264   case NFSPROC_STATFS:
    265     xdr_argument = (xdrproc_t) xdr_nfs_fh;
    266     xdr_result = (xdrproc_t) xdr_statfsres;
    267     local = (nfssvcproc_t) nfsproc_statfs_2_svc;
    268     break;
    269 
    270   default:
    271     svcerr_noproc(transp);
    272     return;
    273   }
    274 
    275   memset((char *) &argument, 0, sizeof(argument));
    276   if (!svc_getargs(transp,
    277 		   (XDRPROC_T_TYPE) xdr_argument,
    278 		   (SVC_IN_ARG_TYPE) &argument)) {
    279     plog(XLOG_ERROR,
    280 	 "NFS xdr decode failed for %d %d %d",
    281 	 (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
    282     svcerr_decode(transp);
    283     return;
    284   }
    285   result = (*local) (&argument, rqstp);
    286 
    287   current_transp = NULL;
    288 
    289   if (result != NULL && !svc_sendreply(transp,
    290 				       (XDRPROC_T_TYPE) xdr_result,
    291 				       result)) {
    292     svcerr_systemerr(transp);
    293   }
    294   if (!svc_freeargs(transp,
    295 		    (XDRPROC_T_TYPE) xdr_argument,
    296 		    (SVC_IN_ARG_TYPE) & argument)) {
    297     plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_2");
    298     going_down(1);
    299   }
    300 }
    301 
    302 void
    303 nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
    304 {
    305   union {
    306     am_GETATTR3args am_nfs3_getattr_3_arg;
    307     am_SETATTR3args am_nfs3_setattr_3_arg;
    308     am_LOOKUP3args am_nfs3_lookup_3_arg;
    309     am_ACCESS3args am_nfs3_access_3_arg;
    310     am_READLINK3args am_nfs3_readlink_3_arg;
    311     am_READ3args am_nfs3_read_3_arg;
    312     am_WRITE3args am_nfs3_write_3_arg;
    313     am_CREATE3args am_nfs3_create_3_arg;
    314     am_MKDIR3args am_nfs3_mkdir_3_arg;
    315     am_SYMLINK3args am_nfs3_symlink_3_arg;
    316     am_MKNOD3args am_nfs3_mknod_3_arg;
    317     am_REMOVE3args am_nfs3_remove_3_arg;
    318     am_RMDIR3args am_nfs3_rmdir_3_arg;
    319     am_RENAME3args am_nfs3_rename_3_arg;
    320     am_LINK3args am_nfs3_link_3_arg;
    321     am_READDIR3args am_nfs3_readdir_3_arg;
    322     am_READDIRPLUS3args am_nfs3_readdirplus_3_arg;
    323     am_FSSTAT3args am_nfs3_fsstat_3_arg;
    324     am_FSINFO3args am_nfs3_fsinfo_3_arg;
    325     am_PATHCONF3args am_nfs3_pathconf_3_arg;
    326     am_COMMIT3args am_nfs3_commit_3_arg;
    327   } argument;
    328   char *result;
    329   xdrproc_t _xdr_argument, _xdr_result;
    330   nfssvcproc_t local;
    331 
    332   switch (rqstp->rq_proc) {
    333   case AM_NFS3_NULL:
    334     _xdr_argument = (xdrproc_t) xdr_void;
    335     _xdr_result = (xdrproc_t) xdr_void;
    336     local = (nfssvcproc_t) am_nfs3_null_3_svc;
    337     break;
    338 
    339   case AM_NFS3_GETATTR:
    340     _xdr_argument = (xdrproc_t) xdr_am_GETATTR3args;
    341     _xdr_result = (xdrproc_t) xdr_am_GETATTR3res;
    342     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_getattr_3_svc;
    343     break;
    344 
    345   case AM_NFS3_SETATTR:
    346     _xdr_argument = (xdrproc_t) xdr_am_SETATTR3args;
    347     _xdr_result = (xdrproc_t) xdr_am_SETATTR3res;
    348     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_setattr_3_svc;
    349     break;
    350 
    351   case AM_NFS3_LOOKUP:
    352     _xdr_argument = (xdrproc_t) xdr_am_LOOKUP3args;
    353     _xdr_result = (xdrproc_t) xdr_am_LOOKUP3res;
    354     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_lookup_3_svc;
    355     break;
    356 
    357   case AM_NFS3_ACCESS:
    358     _xdr_argument = (xdrproc_t) xdr_am_ACCESS3args;
    359     _xdr_result = (xdrproc_t) xdr_am_ACCESS3res;
    360     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_access_3_svc;
    361     break;
    362 
    363   case AM_NFS3_READLINK:
    364     _xdr_argument = (xdrproc_t) xdr_am_READLINK3args;
    365     _xdr_result = (xdrproc_t) xdr_am_READLINK3res;
    366     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readlink_3_svc;
    367     break;
    368 
    369   case AM_NFS3_READ:
    370     _xdr_argument = (xdrproc_t) xdr_am_READ3args;
    371     _xdr_result = (xdrproc_t) xdr_am_READ3res;
    372     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_read_3_svc;
    373     break;
    374 
    375   case AM_NFS3_WRITE:
    376     _xdr_argument = (xdrproc_t) xdr_am_WRITE3args;
    377     _xdr_result = (xdrproc_t) xdr_am_WRITE3res;
    378     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_write_3_svc;
    379     break;
    380 
    381   case AM_NFS3_CREATE:
    382     _xdr_argument = (xdrproc_t) xdr_am_CREATE3args;
    383     _xdr_result = (xdrproc_t) xdr_am_CREATE3res;
    384     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_create_3_svc;
    385     break;
    386 
    387   case AM_NFS3_MKDIR:
    388     _xdr_argument = (xdrproc_t) xdr_am_MKDIR3args;
    389     _xdr_result = (xdrproc_t) xdr_am_MKDIR3res;
    390     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mkdir_3_svc;
    391     break;
    392 
    393   case AM_NFS3_SYMLINK:
    394     _xdr_argument = (xdrproc_t) xdr_am_SYMLINK3args;
    395     _xdr_result = (xdrproc_t) xdr_am_SYMLINK3res;
    396     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_symlink_3_svc;
    397     break;
    398 
    399   case AM_NFS3_MKNOD:
    400     _xdr_argument = (xdrproc_t) xdr_am_MKNOD3args;
    401     _xdr_result = (xdrproc_t) xdr_am_MKNOD3res;
    402     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mknod_3_svc;
    403     break;
    404 
    405   case AM_NFS3_REMOVE:
    406     _xdr_argument = (xdrproc_t) xdr_am_REMOVE3args;
    407     _xdr_result = (xdrproc_t) xdr_am_REMOVE3res;
    408     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_remove_3_svc;
    409     break;
    410 
    411   case AM_NFS3_RMDIR:
    412     _xdr_argument = (xdrproc_t) xdr_am_RMDIR3args;
    413     _xdr_result = (xdrproc_t) xdr_am_RMDIR3res;
    414     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rmdir_3_svc;
    415     break;
    416 
    417   case AM_NFS3_RENAME:
    418     _xdr_argument = (xdrproc_t) xdr_am_RENAME3args;
    419     _xdr_result = (xdrproc_t) xdr_am_RENAME3res;
    420     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rename_3_svc;
    421     break;
    422 
    423   case AM_NFS3_LINK:
    424     _xdr_argument = (xdrproc_t) xdr_am_LINK3args;
    425     _xdr_result = (xdrproc_t) xdr_am_LINK3res;
    426     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_link_3_svc;
    427     break;
    428 
    429   case AM_NFS3_READDIR:
    430     _xdr_argument = (xdrproc_t) xdr_am_READDIR3args;
    431     _xdr_result = (xdrproc_t) xdr_am_READDIR3res;
    432     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdir_3_svc;
    433     break;
    434 
    435   case AM_NFS3_READDIRPLUS:
    436     _xdr_argument = (xdrproc_t) xdr_am_READDIRPLUS3args;
    437     _xdr_result = (xdrproc_t) xdr_am_READDIRPLUS3res;
    438     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdirplus_3_svc;
    439     break;
    440 
    441   case AM_NFS3_FSSTAT:
    442     _xdr_argument = (xdrproc_t) xdr_am_FSSTAT3args;
    443     _xdr_result = (xdrproc_t) xdr_am_FSSTAT3res;
    444     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsstat_3_svc;
    445     break;
    446 
    447   case AM_NFS3_FSINFO:
    448     _xdr_argument = (xdrproc_t) xdr_am_FSINFO3args;
    449     _xdr_result = (xdrproc_t) xdr_am_FSINFO3res;
    450     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsinfo_3_svc;
    451     break;
    452 
    453   case AM_NFS3_PATHCONF:
    454     _xdr_argument = (xdrproc_t) xdr_am_PATHCONF3args;
    455     _xdr_result = (xdrproc_t) xdr_am_PATHCONF3res;
    456     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_pathconf_3_svc;
    457     break;
    458 
    459   case AM_NFS3_COMMIT:
    460     _xdr_argument = (xdrproc_t) xdr_am_COMMIT3args;
    461     _xdr_result = (xdrproc_t) xdr_am_COMMIT3res;
    462     local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_commit_3_svc;
    463     break;
    464 
    465   default:
    466     svcerr_noproc (transp);
    467     return;
    468   }
    469 
    470   memset ((char *)&argument, 0, sizeof (argument));
    471 
    472   if (!svc_getargs(transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
    473     plog(XLOG_ERROR,
    474 	 "NFS xdr decode failed for %d %d %d",
    475 	 (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
    476     svcerr_decode(transp);
    477     return;
    478   }
    479 
    480   result = (*local) (&argument, rqstp);
    481   if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
    482     svcerr_systemerr (transp);
    483   }
    484 
    485   if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
    486     plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_3");
    487     going_down(1);
    488   }
    489   return;
    490 }
    491