Commit 2f28c8b3 authored by Jim Garlick's avatar Jim Garlick Committed by Eric Van Hensbergen

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: default avatarJim Garlick <garlick@llnl.gov>
Signed-off-by: default avatarEric Van Hensbergen <ericvh@gmail.com>
parent 2315cb14
...@@ -26,6 +26,9 @@ ...@@ -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 { ...@@ -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 { ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
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