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
|
||||
#define NET_9P_TRANSPORT_H
|
||||
|
||||
#define P9_DEF_MIN_RESVPORT (665U)
|
||||
#define P9_DEF_MAX_RESVPORT (1023U)
|
||||
|
||||
/**
|
||||
* struct p9_trans_module - transport module interface
|
||||
* @list: used to maintain a list of currently available transports
|
||||
|
|
|
@ -63,6 +63,7 @@ struct p9_fd_opts {
|
|||
int rfd;
|
||||
int wfd;
|
||||
u16 port;
|
||||
int privport;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -87,12 +88,15 @@ struct p9_trans_fd {
|
|||
enum {
|
||||
/* Options that take integer arguments */
|
||||
Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
|
||||
/* Options that take no arguments */
|
||||
Opt_privport,
|
||||
};
|
||||
|
||||
static const match_table_t tokens = {
|
||||
{Opt_port, "port=%u"},
|
||||
{Opt_rfdno, "rfdno=%u"},
|
||||
{Opt_wfdno, "wfdno=%u"},
|
||||
{Opt_privport, "privport"},
|
||||
{Opt_err, NULL},
|
||||
};
|
||||
|
||||
|
@ -161,6 +165,9 @@ static DEFINE_SPINLOCK(p9_poll_lock);
|
|||
static LIST_HEAD(p9_poll_pending_list);
|
||||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -741,7 +748,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
|
|||
if (!*p)
|
||||
continue;
|
||||
token = match_token(p, tokens, args);
|
||||
if (token != Opt_err) {
|
||||
if ((token != Opt_err) && (token != Opt_privport)) {
|
||||
r = match_int(&args[0], &option);
|
||||
if (r < 0) {
|
||||
p9_debug(P9_DEBUG_ERROR,
|
||||
|
@ -759,6 +766,9 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
|
|||
case Opt_wfdno:
|
||||
opts->wfd = option;
|
||||
break;
|
||||
case Opt_privport:
|
||||
opts->privport = 1;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
@ -898,6 +908,24 @@ static inline int valid_ipaddr4(const char *buf)
|
|||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
(struct sockaddr *)&sin_server,
|
||||
sizeof(struct sockaddr_in), 0);
|
||||
|
|
Loading…
Reference in New Issue