Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
+39 −1
Original line number Diff line number Diff line
@@ -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);