diff options
author | Jim Garlick <garlick@llnl.gov> | 2013-05-29 15:15:07 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2013-07-07 22:59:54 -0400 |
commit | 2f28c8b31dc501027d9aa6acf496c5941736312b (patch) | |
tree | 30c8060085b6bb41d07534431b00d9733c78665a | |
parent | 2315cb14010c4cb0eb7c1d19fcf90475e4688207 (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.h | 3 | ||||
-rw-r--r-- | net/9p/trans_fd.c | 40 |
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 { | |||
87 | enum { | 88 | enum { |
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 | ||
92 | static const match_table_t tokens = { | 95 | static 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); | |||
161 | static LIST_HEAD(p9_poll_pending_list); | 165 | static LIST_HEAD(p9_poll_pending_list); |
162 | static DECLARE_WORK(p9_poll_work, p9_poll_workfn); | 166 | static DECLARE_WORK(p9_poll_work, p9_poll_workfn); |
163 | 167 | ||
168 | static unsigned int p9_ipport_resv_min = P9_DEF_MIN_RESVPORT; | ||
169 | static unsigned int p9_ipport_resv_max = P9_DEF_MAX_RESVPORT; | ||
170 | |||
164 | static void p9_mux_poll_stop(struct p9_conn *m) | 171 | static 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 | ||
911 | static 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 | |||
901 | static int | 929 | static int |
902 | p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) | 930 | p9_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); |