*/
struct sock *ctl_sock;
+ /* UDP tunneling listening sock. */
+ struct sock *udp4_sock;
+ /* UDP tunneling listening port. */
+ int udp_port;
+
/* This is the global local address list.
* We actively maintain this complete list of addresses on
* the system by catching address add/delete events.
struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
int sctp_register_pf(struct sctp_pf *, sa_family_t);
void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int);
+int sctp_udp_sock_start(struct net *net);
+void sctp_udp_sock_stop(struct net *net);
/*
* sctp/socket.c
#include <net/addrconf.h>
#include <net/inet_common.h>
#include <net/inet_ecn.h>
+#include <net/udp_tunnel.h>
#define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024)
return 0;
}
+static int sctp_udp_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ skb_set_transport_header(skb, sizeof(struct udphdr));
+ sctp_rcv(skb);
+ return 0;
+}
+
+int sctp_udp_sock_start(struct net *net)
+{
+ struct udp_tunnel_sock_cfg tuncfg = {NULL};
+ struct udp_port_cfg udp_conf = {0};
+ struct socket *sock;
+ int err;
+
+ udp_conf.family = AF_INET;
+ udp_conf.local_ip.s_addr = htonl(INADDR_ANY);
+ udp_conf.local_udp_port = htons(net->sctp.udp_port);
+ err = udp_sock_create(net, &udp_conf, &sock);
+ if (err) {
+ pr_err("Failed to create the SCTP UDP tunneling v4 sock\n");
+ return err;
+ }
+
+ tuncfg.encap_type = 1;
+ tuncfg.encap_rcv = sctp_udp_rcv;
+ setup_udp_tunnel_sock(net, sock, &tuncfg);
+ net->sctp.udp4_sock = sock->sk;
+
+ return 0;
+}
+
+void sctp_udp_sock_stop(struct net *net)
+{
+ if (net->sctp.udp4_sock) {
+ udp_tunnel_sock_release(net->sctp.udp4_sock->sk_socket);
+ net->sctp.udp4_sock = NULL;
+ }
+}
+
/* Register address family specific functions. */
int sctp_register_af(struct sctp_af *af)
{
/* Enable ECN by default. */
net->sctp.ecn_enable = 1;
+ /* Set UDP tunneling listening port to 0 by default */
+ net->sctp.udp_port = 0;
+
/* Set SCOPE policy to enabled */
net->sctp.scope_policy = SCTP_SCOPE_POLICY_ENABLE;