net/9p: add privport option to 9p tcp transport
If the privport option is specified, the tcp transport binds local address to a reserved port before connecting to the 9p server. In some cases when 9P AUTH cannot be implemented, this is better than nothing. Signed-off-by: Jim Garlick <garlick@llnl.gov> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
This commit is contained in:
parent
2315cb1401
commit
2f28c8b31d
|
@ -26,6 +26,9 @@
|
||||||
#ifndef NET_9P_TRANSPORT_H
|
#ifndef NET_9P_TRANSPORT_H
|
||||||
#define NET_9P_TRANSPORT_H
|
#define NET_9P_TRANSPORT_H
|
||||||
|
|
||||||
|
#define P9_DEF_MIN_RESVPORT (665U)
|
||||||
|
#define P9_DEF_MAX_RESVPORT (1023U)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct p9_trans_module - transport module interface
|
* struct p9_trans_module - transport module interface
|
||||||
* @list: used to maintain a list of currently available transports
|
* @list: used to maintain a list of currently available transports
|
||||||
|
|
|
@ -63,6 +63,7 @@ struct p9_fd_opts {
|
||||||
int rfd;
|
int rfd;
|
||||||
int wfd;
|
int wfd;
|
||||||
u16 port;
|
u16 port;
|
||||||
|
int privport;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,12 +88,15 @@ struct p9_trans_fd {
|
||||||
enum {
|
enum {
|
||||||
/* Options that take integer arguments */
|
/* Options that take integer arguments */
|
||||||
Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
|
Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
|
||||||
|
/* Options that take no arguments */
|
||||||
|
Opt_privport,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const match_table_t tokens = {
|
static const match_table_t tokens = {
|
||||||
{Opt_port, "port=%u"},
|
{Opt_port, "port=%u"},
|
||||||
{Opt_rfdno, "rfdno=%u"},
|
{Opt_rfdno, "rfdno=%u"},
|
||||||
{Opt_wfdno, "wfdno=%u"},
|
{Opt_wfdno, "wfdno=%u"},
|
||||||
|
{Opt_privport, "privport"},
|
||||||
{Opt_err, NULL},
|
{Opt_err, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -161,6 +165,9 @@ static DEFINE_SPINLOCK(p9_poll_lock);
|
||||||
static LIST_HEAD(p9_poll_pending_list);
|
static LIST_HEAD(p9_poll_pending_list);
|
||||||
static DECLARE_WORK(p9_poll_work, p9_poll_workfn);
|
static DECLARE_WORK(p9_poll_work, p9_poll_workfn);
|
||||||
|
|
||||||
|
static unsigned int p9_ipport_resv_min = P9_DEF_MIN_RESVPORT;
|
||||||
|
static unsigned int p9_ipport_resv_max = P9_DEF_MAX_RESVPORT;
|
||||||
|
|
||||||
static void p9_mux_poll_stop(struct p9_conn *m)
|
static void p9_mux_poll_stop(struct p9_conn *m)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -741,7 +748,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
|
||||||
if (!*p)
|
if (!*p)
|
||||||
continue;
|
continue;
|
||||||
token = match_token(p, tokens, args);
|
token = match_token(p, tokens, args);
|
||||||
if (token != Opt_err) {
|
if ((token != Opt_err) && (token != Opt_privport)) {
|
||||||
r = match_int(&args[0], &option);
|
r = match_int(&args[0], &option);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
p9_debug(P9_DEBUG_ERROR,
|
p9_debug(P9_DEBUG_ERROR,
|
||||||
|
@ -759,6 +766,9 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
|
||||||
case Opt_wfdno:
|
case Opt_wfdno:
|
||||||
opts->wfd = option;
|
opts->wfd = option;
|
||||||
break;
|
break;
|
||||||
|
case Opt_privport:
|
||||||
|
opts->privport = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -898,6 +908,24 @@ static inline int valid_ipaddr4(const char *buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int p9_bind_privport(struct socket *sock)
|
||||||
|
{
|
||||||
|
struct sockaddr_in cl;
|
||||||
|
int port, err = -EINVAL;
|
||||||
|
|
||||||
|
memset(&cl, 0, sizeof(cl));
|
||||||
|
cl.sin_family = AF_INET;
|
||||||
|
cl.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) {
|
||||||
|
cl.sin_port = htons((ushort)port);
|
||||||
|
err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl));
|
||||||
|
if (err != -EADDRINUSE)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
|
p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
|
||||||
{
|
{
|
||||||
|
@ -926,6 +954,16 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts.privport) {
|
||||||
|
err = p9_bind_privport(csocket);
|
||||||
|
if (err < 0) {
|
||||||
|
pr_err("%s (%d): problem binding to privport\n",
|
||||||
|
__func__, task_pid_nr(current));
|
||||||
|
sock_release(csocket);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = csocket->ops->connect(csocket,
|
err = csocket->ops->connect(csocket,
|
||||||
(struct sockaddr *)&sin_server,
|
(struct sockaddr *)&sin_server,
|
||||||
sizeof(struct sockaddr_in), 0);
|
sizeof(struct sockaddr_in), 0);
|
||||||
|
|
Loading…
Reference in New Issue