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