Add nfsport/mountport arguments

Add two arguments to set which port to use for MOUNT (only used in NFSv3)
as well as for the NFS protocols.
When set to non-zero libnfs will connect directly to that port and bypass
the use of portmapper completely.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
libnfs-4.0.0-vitalif
Ronnie Sahlberg 2018-04-08 14:36:37 +10:00
parent 54405d994e
commit b54fc96e00
8 changed files with 155 additions and 6 deletions

4
README
View File

@ -69,6 +69,10 @@ Arguments supported by libnfs are :
version=<3|4> : NFS Version. Default is 3.
This is just a placeholder for now. NFSv4 support is not
yet functional.
nfsport=<port> : Use this port for NFS instead of using the portmapper.
mountport=<port> : Use this port for the MOUNT protocol instead of
using portmapper. This argument is ignored for NFSv4
as it does not use the MOUNT protocol.
Auto_traverse_mounts
====================

View File

@ -287,7 +287,9 @@ struct nfs_context {
int auto_traverse_mounts;
struct nested_mounts *nested_mounts;
int version;
int version;
int nfsport;
int mountport;
/* NFSv4 specific fields */
verifier4 verifier;

View File

@ -218,6 +218,30 @@ EXTERN int rpc_connect_program_async(struct rpc_context *rpc,
int program, int version,
rpc_cb cb, void *private_data);
/*
* Async function to connect to a specific RPC program/version.
* This connects directly to the specified port without using portmapper.
*
* Function returns
* 0 : The connection was initiated. The callback will be invoked once the
* connection establish finishes.
* <0 : An error occured when trying to set up the connection.
* The callback will not be invoked.
*
* When the callback is invoked, status indicates the result:
* RPC_STATUS_SUCCESS : The tcp connection was successfully established.
* data is NULL.
* RPC_STATUS_ERROR : The connection failed to establish.
* data is the error string.
* RPC_STATUS_CANCEL : The connection attempt was aborted before it could
* complete.
* : data is NULL.
*/
EXTERN int rpc_connect_port_async(struct rpc_context *rpc, const char *server,
int port,
int program, int version,
rpc_cb cb, void *private_data);
/*
* When disconnecting a connection all commands in flight will be
* called with a callback status RPC_STATUS_ERROR. Data will be the

View File

@ -206,6 +206,10 @@ EXTERN void nfs_destroy_context(struct nfs_context *nfs);
* to the application.
* version=<3|4> : NFS version. Default is 3.
* Version 4 is not yet functional. Do not use.
* nfsport=<port> : Use this port for NFS instead of using the portmapper.
* mountport=<port> : Use this port for the MOUNT protocol instead of
* using portmapper. This argument is ignored for NFSv4
* as it does not use the MOUNT protocol.
*/
/*
* Parse a complete NFS URL including, server, path and

View File

@ -116,6 +116,8 @@ nfs4_set_client_name
nfs4_set_verifier
win32_poll
rpc_connect_async
rpc_connect_port_async
rpc_connect_program_async
rpc_destroy_context
rpc_disconnect
rpc_get_error

View File

@ -274,6 +274,10 @@ nfs_set_context_args(struct nfs_context *nfs, const char *arg, const char *val)
atoi(val));
return -1;
}
} else if (!strcmp(arg, "nfsport")) {
nfs->nfsport = atoi(val);
} else if (!strcmp(arg, "mountport")) {
nfs->mountport = atoi(val);
}
return 0;
}
@ -540,6 +544,9 @@ void free_rpc_cb_data(struct rpc_cb_data *data)
free(data);
}
static int
rpc_connect_port_internal(struct rpc_context *rpc, int port, struct rpc_cb_data *data);
static void
rpc_connect_program_5_cb(struct rpc_context *rpc, int status,
void *command_data, void *private_data)
@ -636,12 +643,12 @@ rpc_connect_program_3_cb(struct rpc_context *rpc, int status,
}
rpc_disconnect(rpc, "normal disconnect");
if (rpc_connect_async(rpc, data->server, rpc_port,
rpc_connect_program_4_cb, data) != 0) {
data->cb(rpc, RPC_STATUS_ERROR, command_data, data->private_data);
if (rpc_connect_port_internal(rpc, rpc_port, data)) {
data->cb(rpc, RPC_STATUS_ERROR, command_data,
data->private_data);
free_rpc_cb_data(data);
return;
}
return;
}
}
static void
@ -724,6 +731,46 @@ rpc_connect_program_1_cb(struct rpc_context *rpc, int status,
}
}
static int
rpc_connect_port_internal(struct rpc_context *rpc, int port, struct rpc_cb_data *data)
{
if (rpc_connect_async(rpc, data->server, port,
rpc_connect_program_4_cb, data) != 0) {
return -1;
}
return 0;
}
int
rpc_connect_port_async(struct rpc_context *rpc, const char *server,
int port,
int program, int version,
rpc_cb cb, void *private_data)
{
struct rpc_cb_data *data;
data = malloc(sizeof(struct rpc_cb_data));
if (data == NULL) {
return -1;
}
memset(data, 0, sizeof(struct rpc_cb_data));
data->server = strdup(server);
data->program = program;
data->version = version;
data->cb = cb;
data->private_data = private_data;
if (rpc_connect_port_internal(rpc, port, data)) {
rpc_set_error(rpc, "Failed to start connection. %s",
rpc_get_error(rpc));
free_rpc_cb_data(data);
return -1;
}
return 0;
}
int
rpc_connect_program_async(struct rpc_context *rpc, const char *server,
int program, int version,

View File

@ -854,6 +854,21 @@ finished:
return;
}
if (nfs->nfsport) {
if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport,
NFS_PROGRAM, NFS_V3,
nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__,
nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs),
data->private_data);
free(md_cb);
free_nfs_cb_data(data);
return;
}
return;
}
if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM,
NFS_V3, nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs));
@ -961,6 +976,20 @@ nfs3_mount_3_cb(struct rpc_context *rpc, int status, void *command_data,
*/
rpc_disconnect(rpc, "normal disconnect");
if (nfs->nfsport) {
if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport,
NFS_PROGRAM, NFS_V3,
nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__,
nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs),
data->private_data);
free_nfs_cb_data(data);
return;
}
return;
}
if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM,
NFS_V3, nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__, nfs_get_error(nfs));
@ -1024,6 +1053,19 @@ nfs3_mount_2_cb(struct rpc_context *rpc, int status, void *command_data,
}
rpc_disconnect(rpc, "normal disconnect");
if (nfs->nfsport) {
if (rpc_connect_port_async(nfs->rpc, nfs->server, nfs->nfsport,
NFS_PROGRAM, NFS_V3,
nfs3_mount_5_cb, data) != 0) {
nfs_set_error(nfs, "%s: %s", __FUNCTION__,
nfs_get_error(nfs));
data->cb(-ENOMEM, nfs, nfs_get_error(nfs),
data->private_data);
free_nfs_cb_data(data);
return;
}
return;
}
if (rpc_connect_program_async(nfs->rpc, nfs->server, NFS_PROGRAM,
NFS_V3, nfs3_mount_5_cb, data) != 0) {
@ -1086,6 +1128,18 @@ nfs3_mount_async(struct nfs_context *nfs, const char *server,
data->cb = cb;
data->private_data = private_data;
if (nfs->mountport) {
if (rpc_connect_port_async(nfs->rpc, server, nfs->mountport,
MOUNT_PROGRAM, MOUNT_V3,
nfs3_mount_1_cb, data) != 0) {
nfs_set_error(nfs, "Failed to start connection. %s",
nfs_get_error(nfs));
free_nfs_cb_data(data);
return -1;
}
return 0;
}
if (rpc_connect_program_async(nfs->rpc, server,
MOUNT_PROGRAM, MOUNT_V3,
nfs3_mount_1_cb, data) != 0) {

View File

@ -1612,6 +1612,18 @@ nfs4_mount_async(struct nfs_context *nfs, const char *server,
data->private_data = private_data;
data->path = strdup(new_export);
if (nfs->nfsport) {
if (rpc_connect_port_async(nfs->rpc, server, nfs->nfsport,
NFS4_PROGRAM, NFS_V4,
nfs4_mount_1_cb, data) != 0) {
nfs_set_error(nfs, "Failed to start connection. %s",
nfs_get_error(nfs));
free_nfs4_cb_data(data);
return -1;
}
return 0;
}
if (rpc_connect_program_async(nfs->rpc, server,
NFS4_PROGRAM, NFS_V4,
nfs4_mount_1_cb, data) != 0) {