Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jim Garlick and committed by
Eric Van Hensbergen
2f28c8b3 2315cb14

+42 -1
+3
include/net/9p/transport.h
··· 26 26 #ifndef NET_9P_TRANSPORT_H 27 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 33 * struct p9_trans_module - transport module interface 31 34 * @list: used to maintain a list of currently available transports
+39 -1
net/9p/trans_fd.c
··· 63 63 int rfd; 64 64 int wfd; 65 65 u16 port; 66 + int privport; 66 67 }; 67 68 68 69 /** ··· 88 87 enum { 89 88 /* Options that take integer arguments */ 90 89 Opt_port, Opt_rfdno, Opt_wfdno, Opt_err, 90 + /* Options that take no arguments */ 91 + Opt_privport, 91 92 }; 92 93 93 94 static const match_table_t tokens = { 94 95 {Opt_port, "port=%u"}, 95 96 {Opt_rfdno, "rfdno=%u"}, 96 97 {Opt_wfdno, "wfdno=%u"}, 98 + {Opt_privport, "privport"}, 97 99 {Opt_err, NULL}, 98 100 }; 99 101 ··· 164 160 static DEFINE_SPINLOCK(p9_poll_lock); 165 161 static LIST_HEAD(p9_poll_pending_list); 166 162 static DECLARE_WORK(p9_poll_work, p9_poll_workfn); 163 + 164 + static unsigned int p9_ipport_resv_min = P9_DEF_MIN_RESVPORT; 165 + static unsigned int p9_ipport_resv_max = P9_DEF_MAX_RESVPORT; 167 166 168 167 static void p9_mux_poll_stop(struct p9_conn *m) 169 168 { ··· 748 741 if (!*p) 749 742 continue; 750 743 token = match_token(p, tokens, args); 751 - if (token != Opt_err) { 744 + if ((token != Opt_err) && (token != Opt_privport)) { 752 745 r = match_int(&args[0], &option); 753 746 if (r < 0) { 754 747 p9_debug(P9_DEBUG_ERROR, ··· 765 758 break; 766 759 case Opt_wfdno: 767 760 opts->wfd = option; 761 + break; 762 + case Opt_privport: 763 + opts->privport = 1; 768 764 break; 769 765 default: 770 766 continue; ··· 908 898 return 0; 909 899 } 910 900 901 + static int p9_bind_privport(struct socket *sock) 902 + { 903 + struct sockaddr_in cl; 904 + int port, err = -EINVAL; 905 + 906 + memset(&cl, 0, sizeof(cl)); 907 + cl.sin_family = AF_INET; 908 + cl.sin_addr.s_addr = INADDR_ANY; 909 + for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) { 910 + cl.sin_port = htons((ushort)port); 911 + err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl)); 912 + if (err != -EADDRINUSE) 913 + break; 914 + } 915 + return err; 916 + } 917 + 918 + 911 919 static int 912 920 p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) 913 921 { ··· 952 924 pr_err("%s (%d): problem creating socket\n", 953 925 __func__, task_pid_nr(current)); 954 926 return err; 927 + } 928 + 929 + if (opts.privport) { 930 + err = p9_bind_privport(csocket); 931 + if (err < 0) { 932 + pr_err("%s (%d): problem binding to privport\n", 933 + __func__, task_pid_nr(current)); 934 + sock_release(csocket); 935 + return err; 936 + } 955 937 } 956 938 957 939 err = csocket->ops->connect(csocket,