aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Garlick <garlick@llnl.gov>2013-05-29 15:15:07 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2013-07-07 22:59:54 -0400
commit2f28c8b31dc501027d9aa6acf496c5941736312b (patch)
tree30c8060085b6bb41d07534431b00d9733c78665a
parent2315cb14010c4cb0eb7c1d19fcf90475e4688207 (diff)
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>
-rw-r--r--include/net/9p/transport.h3
-rw-r--r--net/9p/trans_fd.c40
2 files changed, 42 insertions, 1 deletions
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index adcbb20f6511..9a36d9297114 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -26,6 +26,9 @@
26#ifndef NET_9P_TRANSPORT_H 26#ifndef NET_9P_TRANSPORT_H
27#define NET_9P_TRANSPORT_H 27#define NET_9P_TRANSPORT_H
28 28
29#define P9_DEF_MIN_RESVPORT (665U)
30#define P9_DEF_MAX_RESVPORT (1023U)
31
29/** 32/**
30 * struct p9_trans_module - transport module interface 33 * struct p9_trans_module - transport module interface
31 * @list: used to maintain a list of currently available transports 34 * @list: used to maintain a list of currently available transports
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 02efb25c2957..3ffda1b3799b 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -63,6 +63,7 @@ struct p9_fd_opts {
63 int rfd; 63 int rfd;
64 int wfd; 64 int wfd;
65 u16 port; 65 u16 port;
66 int privport;
66}; 67};
67 68
68/** 69/**
@@ -87,12 +88,15 @@ struct p9_trans_fd {
87enum { 88enum {
88 /* Options that take integer arguments */ 89 /* Options that take integer arguments */
89 Opt_port, Opt_rfdno, Opt_wfdno, Opt_err, 90 Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
91 /* Options that take no arguments */
92 Opt_privport,
90}; 93};
91 94
92static const match_table_t tokens = { 95static const match_table_t tokens = {
93 {Opt_port, "port=%u"}, 96 {Opt_port, "port=%u"},
94 {Opt_rfdno, "rfdno=%u"}, 97 {Opt_rfdno, "rfdno=%u"},
95 {Opt_wfdno, "wfdno=%u"}, 98 {Opt_wfdno, "wfdno=%u"},
99 {Opt_privport, "privport"},
96 {Opt_err, NULL}, 100 {Opt_err, NULL},
97}; 101};
98 102
@@ -161,6 +165,9 @@ static DEFINE_SPINLOCK(p9_poll_lock);
161static LIST_HEAD(p9_poll_pending_list); 165static LIST_HEAD(p9_poll_pending_list);
162static DECLARE_WORK(p9_poll_work, p9_poll_workfn); 166static DECLARE_WORK(p9_poll_work, p9_poll_workfn);
163 167
168static unsigned int p9_ipport_resv_min = P9_DEF_MIN_RESVPORT;
169static unsigned int p9_ipport_resv_max = P9_DEF_MAX_RESVPORT;
170
164static void p9_mux_poll_stop(struct p9_conn *m) 171static void p9_mux_poll_stop(struct p9_conn *m)
165{ 172{
166 unsigned long flags; 173 unsigned long flags;
@@ -741,7 +748,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
741 if (!*p) 748 if (!*p)
742 continue; 749 continue;
743 token = match_token(p, tokens, args); 750 token = match_token(p, tokens, args);
744 if (token != Opt_err) { 751 if ((token != Opt_err) && (token != Opt_privport)) {
745 r = match_int(&args[0], &option); 752 r = match_int(&args[0], &option);
746 if (r < 0) { 753 if (r < 0) {
747 p9_debug(P9_DEBUG_ERROR, 754 p9_debug(P9_DEBUG_ERROR,
@@ -759,6 +766,9 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
759 case Opt_wfdno: 766 case Opt_wfdno:
760 opts->wfd = option; 767 opts->wfd = option;
761 break; 768 break;
769 case Opt_privport:
770 opts->privport = 1;
771 break;
762 default: 772 default:
763 continue; 773 continue;
764 } 774 }
@@ -898,6 +908,24 @@ static inline int valid_ipaddr4(const char *buf)
898 return 0; 908 return 0;
899} 909}
900 910
911static int p9_bind_privport(struct socket *sock)
912{
913 struct sockaddr_in cl;
914 int port, err = -EINVAL;
915
916 memset(&cl, 0, sizeof(cl));
917 cl.sin_family = AF_INET;
918 cl.sin_addr.s_addr = INADDR_ANY;
919 for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) {
920 cl.sin_port = htons((ushort)port);
921 err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl));
922 if (err != -EADDRINUSE)
923 break;
924 }
925 return err;
926}
927
928
901static int 929static int
902p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) 930p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
903{ 931{
@@ -926,6 +954,16 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
926 return err; 954 return err;
927 } 955 }
928 956
957 if (opts.privport) {
958 err = p9_bind_privport(csocket);
959 if (err < 0) {
960 pr_err("%s (%d): problem binding to privport\n",
961 __func__, task_pid_nr(current));
962 sock_release(csocket);
963 return err;
964 }
965 }
966
929 err = csocket->ops->connect(csocket, 967 err = csocket->ops->connect(csocket,
930 (struct sockaddr *)&sin_server, 968 (struct sockaddr *)&sin_server,
931 sizeof(struct sockaddr_in), 0); 969 sizeof(struct sockaddr_in), 0);