Commit 642ee6b2 authored by Trond Myklebust's avatar Trond Myklebust Committed by J. Bruce Fields

SUNRPC: Allow further customisation of RPC program registration

Add a callback to allow customisation of the rpcbind registration.
When clients have the ability to turn on and off version support,
we want to allow them to also prevent registration of those
versions with the rpc portmapper.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 4532608d
...@@ -809,4 +809,5 @@ static struct svc_program nlmsvc_program = { ...@@ -809,4 +809,5 @@ static struct svc_program nlmsvc_program = {
.pg_stats = &nlmsvc_stats, /* stats table */ .pg_stats = &nlmsvc_stats, /* stats table */
.pg_authenticate = &lockd_authenticate, /* export authentication */ .pg_authenticate = &lockd_authenticate, /* export authentication */
.pg_init_request = svc_generic_init_request, .pg_init_request = svc_generic_init_request,
.pg_rpcbind_set = svc_generic_rpcbind_set,
}; };
...@@ -458,4 +458,5 @@ static struct svc_program nfs4_callback_program = { ...@@ -458,4 +458,5 @@ static struct svc_program nfs4_callback_program = {
.pg_stats = &nfs4_callback_stats, .pg_stats = &nfs4_callback_stats,
.pg_authenticate = nfs_callback_authenticate, .pg_authenticate = nfs_callback_authenticate,
.pg_init_request = svc_generic_init_request, .pg_init_request = svc_generic_init_request,
.pg_rpcbind_set = svc_generic_rpcbind_set,
}; };
...@@ -87,6 +87,7 @@ static struct svc_program nfsd_acl_program = { ...@@ -87,6 +87,7 @@ static struct svc_program nfsd_acl_program = {
.pg_stats = &nfsd_acl_svcstats, .pg_stats = &nfsd_acl_svcstats,
.pg_authenticate = &svc_set_client, .pg_authenticate = &svc_set_client,
.pg_init_request = svc_generic_init_request, .pg_init_request = svc_generic_init_request,
.pg_rpcbind_set = svc_generic_rpcbind_set,
}; };
static struct svc_stat nfsd_acl_svcstats = { static struct svc_stat nfsd_acl_svcstats = {
...@@ -120,7 +121,7 @@ struct svc_program nfsd_program = { ...@@ -120,7 +121,7 @@ struct svc_program nfsd_program = {
.pg_stats = &nfsd_svcstats, /* version table */ .pg_stats = &nfsd_svcstats, /* version table */
.pg_authenticate = &svc_set_client, /* export authentication */ .pg_authenticate = &svc_set_client, /* export authentication */
.pg_init_request = svc_generic_init_request, .pg_init_request = svc_generic_init_request,
.pg_rpcbind_set = svc_generic_rpcbind_set,
}; };
static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = { static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = {
......
...@@ -410,6 +410,11 @@ struct svc_program { ...@@ -410,6 +410,11 @@ struct svc_program {
__be32 (*pg_init_request)(struct svc_rqst *, __be32 (*pg_init_request)(struct svc_rqst *,
const struct svc_program *, const struct svc_program *,
struct svc_process_info *); struct svc_process_info *);
int (*pg_rpcbind_set)(struct net *net,
const struct svc_program *,
u32 version, int family,
unsigned short proto,
unsigned short port);
}; };
/* /*
...@@ -522,6 +527,16 @@ __be32 svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err); ...@@ -522,6 +527,16 @@ __be32 svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err);
__be32 svc_generic_init_request(struct svc_rqst *rqstp, __be32 svc_generic_init_request(struct svc_rqst *rqstp,
const struct svc_program *progp, const struct svc_program *progp,
struct svc_process_info *procinfo); struct svc_process_info *procinfo);
int svc_generic_rpcbind_set(struct net *net,
const struct svc_program *progp,
u32 version, int family,
unsigned short proto,
unsigned short port);
int svc_rpcbind_set_version(struct net *net,
const struct svc_program *progp,
u32 version, int family,
unsigned short proto,
unsigned short port);
#define RPC_MAX_ADDRBUFLEN (63U) #define RPC_MAX_ADDRBUFLEN (63U)
......
...@@ -993,6 +993,58 @@ static int __svc_register(struct net *net, const char *progname, ...@@ -993,6 +993,58 @@ static int __svc_register(struct net *net, const char *progname,
return error; return error;
} }
int svc_rpcbind_set_version(struct net *net,
const struct svc_program *progp,
u32 version, int family,
unsigned short proto,
unsigned short port)
{
dprintk("svc: svc_register(%sv%d, %s, %u, %u)\n",
progp->pg_name, version,
proto == IPPROTO_UDP? "udp" : "tcp",
port, family);
return __svc_register(net, progp->pg_name, progp->pg_prog,
version, family, proto, port);
}
EXPORT_SYMBOL_GPL(svc_rpcbind_set_version);
int svc_generic_rpcbind_set(struct net *net,
const struct svc_program *progp,
u32 version, int family,
unsigned short proto,
unsigned short port)
{
const struct svc_version *vers = progp->pg_vers[version];
int error;
if (vers == NULL)
return 0;
if (vers->vs_hidden) {
dprintk("svc: svc_register(%sv%d, %s, %u, %u)"
" (but not telling portmap)\n",
progp->pg_name, version,
proto == IPPROTO_UDP? "udp" : "tcp",
port, family);
return 0;
}
/*
* Don't register a UDP port if we need congestion
* control.
*/
if (vers->vs_need_cong_ctrl && proto == IPPROTO_UDP)
return 0;
error = svc_rpcbind_set_version(net, progp, version,
family, proto, port);
return (vers->vs_rpcb_optnl) ? 0 : error;
}
EXPORT_SYMBOL_GPL(svc_generic_rpcbind_set);
/** /**
* svc_register - register an RPC service with the local portmapper * svc_register - register an RPC service with the local portmapper
* @serv: svc_serv struct for the service to register * @serv: svc_serv struct for the service to register
...@@ -1008,7 +1060,6 @@ int svc_register(const struct svc_serv *serv, struct net *net, ...@@ -1008,7 +1060,6 @@ int svc_register(const struct svc_serv *serv, struct net *net,
const unsigned short port) const unsigned short port)
{ {
struct svc_program *progp; struct svc_program *progp;
const struct svc_version *vers;
unsigned int i; unsigned int i;
int error = 0; int error = 0;
...@@ -1018,37 +1069,9 @@ int svc_register(const struct svc_serv *serv, struct net *net, ...@@ -1018,37 +1069,9 @@ int svc_register(const struct svc_serv *serv, struct net *net,
for (progp = serv->sv_program; progp; progp = progp->pg_next) { for (progp = serv->sv_program; progp; progp = progp->pg_next) {
for (i = 0; i < progp->pg_nvers; i++) { for (i = 0; i < progp->pg_nvers; i++) {
vers = progp->pg_vers[i];
if (vers == NULL)
continue;
dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n",
progp->pg_name,
i,
proto == IPPROTO_UDP? "udp" : "tcp",
port,
family,
vers->vs_hidden ?
" (but not telling portmap)" : "");
if (vers->vs_hidden)
continue;
/*
* Don't register a UDP port if we need congestion
* control.
*/
if (vers->vs_need_cong_ctrl && proto == IPPROTO_UDP)
continue;
error = __svc_register(net, progp->pg_name, progp->pg_prog,
i, family, proto, port);
if (vers->vs_rpcb_optnl) {
error = 0;
continue;
}
error = progp->pg_rpcbind_set(net, progp, i,
family, proto, port);
if (error < 0) { if (error < 0) {
printk(KERN_WARNING "svc: failed to register " printk(KERN_WARNING "svc: failed to register "
"%sv%u RPC service (errno %d).\n", "%sv%u RPC service (errno %d).\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment