From ee8f0a7dffbd1cd6c829dd6509d7dba3c35727dc Mon Sep 17 00:00:00 2001 From: zoulasc Date: Thu, 3 Mar 2016 13:21:13 -0500 Subject: [PATCH] The nfs_quick_reply() functionality relies on taking a copy of the current transport for later use. The problem with this is the context of the RPC message is kept in the transport and if any RPC message arrives before nfs_quick_reply() is called that context will be corrupted. So add a function get_nfs_xprt() to replace the current transport with a new one returning the passed in transort so nfs_quick_reply() can use it later. A function put_nfs_xprt() is also added (although not really needed since it just destroys the now unused transport) for completeness. From: Ian Kent --- conf/transp/transp_sockets.c | 44 ++++++++++++++++++++++++++++++++++ conf/transp/transp_tli.c | 46 +++++++++++++++++++++++++++++++++++- include/am_utils.h | 2 ++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/conf/transp/transp_sockets.c b/conf/transp/transp_sockets.c index 63260071..98f79c8d 100644 --- a/conf/transp/transp_sockets.c +++ b/conf/transp/transp_sockets.c @@ -45,6 +45,7 @@ #include #include +static int soNFS = RPC_ANYSOCK; /* * find the IP address that can be used to connect to the local host @@ -273,9 +274,52 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (* return 3; } + soNFS = *soNFSp; + return 0; /* all is well */ } +/* + * Get a pointer to the current NFS SVCXPRT and replace it + * with a new one. + */ +SVCXPRT * +get_nfs_xprt(SVCXPRT *nfs_xprt) +{ + SVCXPRT *newxprt; + int newfd; + + if (!nfs_xprt || soNFS == RPC_ANYSOCK) + return NULL; + + newfd = dup(soNFS); + if (newfd < 0) + return NULL; + + xprt_unregister(nfs_xprt); + newxprt = svcudp_create(newfd); + if (!newxprt) { + plog(XLOG_FATAL, "Can't swicth to new transpot"); + xprt_register(nfs_xprt); + close(newfd); + return NULL; + } + + soNFS = newfd; + + return nfs_xprt; +} + +/* + * Destroy a transport previously obtained by get_nfs_xprt(). + */ +void put_nfs_xprt(SVCXPRT *nfs_xprt) +{ + if (!nfs_xprt || soNFS == RPC_ANYSOCK) + return; + + svc_destroy(nfs_xprt); +} /* * Create the amq service for amd (both TCP and UDP) diff --git a/conf/transp/transp_tli.c b/conf/transp/transp_tli.c index d26a511b..ea565cce 100644 --- a/conf/transp/transp_tli.c +++ b/conf/transp/transp_tli.c @@ -45,7 +45,8 @@ #include #include -struct netconfig *nfsncp; +struct netconfig *nfsncp = NULL; +static int soNFS = RPC_ANYSOCK; /* @@ -456,9 +457,52 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (* return 1; } + soNFS = *soNFSp; + return 0; /* all is well */ } +/* + * Get a pointer to the current NFS SVCXPRT and replace it + * with a new one. + */ +SVCXPRT * +get_nfs_xprt(SVCXPRT *nfs_xprt) +{ + SVCXPRT *newxprt; + int newfd; + + if (!nfs_xprt || soNFS == RPC_ANYSOCK) + return NULL; + + newfd = dup(soNFS); + if (newfd < 0) + return NULL; + + xprt_unregister(nfs_xprt); + newxprt = svc_tli_create(newfd, nfsncp, NULL, 0, 0); + if (!newxprt) { + plog(XLOG_FATAL, "Can't swicth to new transpot"); + xprt_register(nfs_xprt); + close(newfd); + return NULL; + } + + soNFS = newfd; + + return nfs_xprt; +} + +/* + * Destroy a transport previously obtained by get_nfs_xprt(). + */ +void put_nfs_xprt(SVCXPRT *nfs_xprt) +{ + if (!nfs_xprt || soNFS == RPC_ANYSOCK) + return; + + svc_destroy(nfs_xprt); +} /* * Bind to preferred AMQ port. diff --git a/include/am_utils.h b/include/am_utils.h index 0de881ad..ff13c266 100644 --- a/include/am_utils.h +++ b/include/am_utils.h @@ -378,6 +378,8 @@ extern void compute_nfs_args(void *nap, mntent_t *mntp, int genflags, struct net extern void destroy_nfs_args(void *nap, u_long nfs_version); extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp, u_short preferred_amq_port); extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version); +extern SVCXPRT *get_nfs_xprt(SVCXPRT *nfs_xprt); +extern void put_nfs_xprt(SVCXPRT *nfs_xprt); extern int amu_svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), u_long, struct netconfig *); #ifdef HAVE_TRANSPORT_TYPE_TLI -- 2.34.1