sctp: enable udp tunneling socks

This patch is to enable udp tunneling socks by calling
sctp_udp_sock_start() in sctp_ctrlsock_init(), and
sctp_udp_sock_stop() in sctp_ctrlsock_exit().

Also add sysctl udp_port to allow changing the listening
sock's port by users.

Wit this patch, the whole sctp over udp feature can be
enabled and used.

v1->v2:
  - Also update ctl_sock udp_port in proc_sctp_do_udp_port()
    where netns udp_port gets changed.
v2->v3:
  - Call htons() when setting sk udp_port from netns udp_port.
v3->v4:
  - Not call sctp_udp_sock_start() when new_value is 0.
  - Add udp_port entry in ip-sysctl.rst.
v4->v5:
  - Not call sctp_udp_sock_start/stop() in sctp_ctrlsock_init/exit().
  - Improve the description of udp_port in ip-sysctl.rst.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Xin Long 2020-10-29 15:05:10 +08:00 committed by Jakub Kicinski
parent 1c16a18625
commit 046c052b47
2 changed files with 67 additions and 0 deletions

View file

@ -2642,6 +2642,21 @@ addr_scope_policy - INTEGER
Default: 1
udp_port - INTEGER
The listening port for the local UDP tunneling sock. Normally it's
using the IANA-assigned UDP port number 9899 (sctp-tunneling).
This UDP sock is used for processing the incoming UDP-encapsulated
SCTP packets (from RFC6951), and shared by all applications in the
same net namespace. This UDP sock will be closed when the value is
set to 0.
The value will also be used to set the src port of the UDP header
for the outgoing UDP-encapsulated SCTP packets. For the dest port,
please refer to 'encap_port' below.
Default: 0
encap_port - INTEGER
The default remote UDP encapsulation port.

View file

@ -49,6 +49,8 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);
static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, void *buffer,
size_t *lenp, loff_t *ppos);
static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, void *buffer,
size_t *lenp, loff_t *ppos);
static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos);
static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
@ -291,6 +293,15 @@ static struct ctl_table sctp_net_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "udp_port",
.data = &init_net.sctp.udp_port,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_sctp_do_udp_port,
.extra1 = SYSCTL_ZERO,
.extra2 = &udp_port_max,
},
{
.procname = "encap_port",
.data = &init_net.sctp.encap_port,
@ -487,6 +498,47 @@ static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
return ret;
}
static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
struct net *net = current->nsproxy->net_ns;
unsigned int min = *(unsigned int *)ctl->extra1;
unsigned int max = *(unsigned int *)ctl->extra2;
struct ctl_table tbl;
int ret, new_value;
memset(&tbl, 0, sizeof(struct ctl_table));
tbl.maxlen = sizeof(unsigned int);
if (write)
tbl.data = &new_value;
else
tbl.data = &net->sctp.udp_port;
ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
if (write && ret == 0) {
struct sock *sk = net->sctp.ctl_sock;
if (new_value > max || new_value < min)
return -EINVAL;
net->sctp.udp_port = new_value;
sctp_udp_sock_stop(net);
if (new_value) {
ret = sctp_udp_sock_start(net);
if (ret)
net->sctp.udp_port = 0;
}
/* Update the value in the control socket */
lock_sock(sk);
sctp_sk(sk)->udp_port = htons(net->sctp.udp_port);
release_sock(sk);
}
return ret;
}
int sctp_sysctl_net_register(struct net *net)
{
struct ctl_table *table;