OSDN Git Service

sctp: create udp6 sock and set its encap_rcv
authorXin Long <lucien.xin@gmail.com>
Thu, 29 Oct 2020 07:04:59 +0000 (15:04 +0800)
committerJakub Kicinski <kuba@kernel.org>
Fri, 30 Oct 2020 22:23:56 +0000 (15:23 -0700)
This patch is to add the udp6 sock part in sctp_udp_sock_start/stop().
udp_conf.use_udp6_rx_checksums is set to true, as:

   "The SCTP checksum MUST be computed for IPv4 and IPv6, and the UDP
    checksum SHOULD be computed for IPv4 and IPv6"

says in rfc6951#section-5.3.

v1->v2:
  - Add pr_err() when fails to create udp v6 sock.
  - Add #if IS_ENABLED(CONFIG_IPV6) not to create v6 sock when ipv6 is
    disabled.

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>
include/net/netns/sctp.h
net/sctp/protocol.c

index 8cc9aff..247b401 100644 (file)
@@ -24,6 +24,7 @@ struct netns_sctp {
 
        /* UDP tunneling listening sock. */
        struct sock *udp4_sock;
+       struct sock *udp6_sock;
        /* UDP tunneling listening port. */
        int udp_port;
 
index 0f79334..8410c9a 100644 (file)
@@ -869,6 +869,28 @@ int sctp_udp_sock_start(struct net *net)
        setup_udp_tunnel_sock(net, sock, &tuncfg);
        net->sctp.udp4_sock = sock->sk;
 
+#if IS_ENABLED(CONFIG_IPV6)
+       memset(&udp_conf, 0, sizeof(udp_conf));
+
+       udp_conf.family = AF_INET6;
+       udp_conf.local_ip6 = in6addr_any;
+       udp_conf.local_udp_port = htons(net->sctp.udp_port);
+       udp_conf.use_udp6_rx_checksums = true;
+       udp_conf.ipv6_v6only = true;
+       err = udp_sock_create(net, &udp_conf, &sock);
+       if (err) {
+               pr_err("Failed to create the SCTP UDP tunneling v6 sock\n");
+               udp_tunnel_sock_release(net->sctp.udp4_sock->sk_socket);
+               net->sctp.udp4_sock = NULL;
+               return err;
+       }
+
+       tuncfg.encap_type = 1;
+       tuncfg.encap_rcv = sctp_udp_rcv;
+       setup_udp_tunnel_sock(net, sock, &tuncfg);
+       net->sctp.udp6_sock = sock->sk;
+#endif
+
        return 0;
 }
 
@@ -878,6 +900,10 @@ void sctp_udp_sock_stop(struct net *net)
                udp_tunnel_sock_release(net->sctp.udp4_sock->sk_socket);
                net->sctp.udp4_sock = NULL;
        }
+       if (net->sctp.udp6_sock) {
+               udp_tunnel_sock_release(net->sctp.udp6_sock->sk_socket);
+               net->sctp.udp6_sock = NULL;
+       }
 }
 
 /* Register address family specific functions. */