netfilter: nf_conntrack: generalize nf_ct_l4proto_net
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / net / ipv6 / netfilter / nf_conntrack_proto_icmpv6.c
index 3e81904fbbcdf09b13c2b830bd40f0b2b7ed313a..2d54b2061d68ef3e947168b82a5b041f84ffea50 100644 (file)
 
 static unsigned int nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
 
+static inline struct nf_icmp_net *icmpv6_pernet(struct net *net)
+{
+       return &net->ct.nf_ct_proto.icmpv6;
+}
+
 static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb,
                                unsigned int dataoff,
                                struct nf_conntrack_tuple *tuple)
@@ -90,7 +95,7 @@ static int icmpv6_print_tuple(struct seq_file *s,
 
 static unsigned int *icmpv6_get_timeouts(struct net *net)
 {
-       return &nf_ct_icmpv6_timeout;
+       return &icmpv6_pernet(net)->timeout;
 }
 
 /* Returns verdict for packet, or -1 for invalid. */
@@ -281,16 +286,18 @@ static int icmpv6_nlattr_tuple_size(void)
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_cttimeout.h>
 
-static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
+static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[],
+                                       struct net *net, void *data)
 {
        unsigned int *timeout = data;
+       struct nf_icmp_net *in = icmpv6_pernet(net);
 
        if (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT]) {
                *timeout =
                    ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMPV6_TIMEOUT])) * HZ;
        } else {
                /* Set default ICMPv6 timeout. */
-               *timeout = nf_ct_icmpv6_timeout;
+               *timeout = in->timeout;
        }
        return 0;
 }
@@ -315,11 +322,9 @@ icmpv6_timeout_nla_policy[CTA_TIMEOUT_ICMPV6_MAX+1] = {
 #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 
 #ifdef CONFIG_SYSCTL
-static struct ctl_table_header *icmpv6_sysctl_header;
 static struct ctl_table icmpv6_sysctl_table[] = {
        {
                .procname       = "nf_conntrack_icmpv6_timeout",
-               .data           = &nf_ct_icmpv6_timeout,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
@@ -328,6 +333,36 @@ static struct ctl_table icmpv6_sysctl_table[] = {
 };
 #endif /* CONFIG_SYSCTL */
 
+static int icmpv6_kmemdup_sysctl_table(struct nf_proto_net *pn,
+                                      struct nf_icmp_net *in)
+{
+#ifdef CONFIG_SYSCTL
+       pn->ctl_table = kmemdup(icmpv6_sysctl_table,
+                               sizeof(icmpv6_sysctl_table),
+                               GFP_KERNEL);
+       if (!pn->ctl_table)
+               return -ENOMEM;
+
+       pn->ctl_table[0].data = &in->timeout;
+#endif
+       return 0;
+}
+
+static int icmpv6_init_net(struct net *net, u_int16_t proto)
+{
+       struct nf_icmp_net *in = icmpv6_pernet(net);
+       struct nf_proto_net *pn = &in->pn;
+
+       in->timeout = nf_ct_icmpv6_timeout;
+
+       return icmpv6_kmemdup_sysctl_table(pn, in);
+}
+
+static struct nf_proto_net *icmpv6_get_net_proto(struct net *net)
+{
+       return &net->ct.nf_ct_proto.icmpv6.pn;
+}
+
 struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
 {
        .l3proto                = PF_INET6,
@@ -355,8 +390,6 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
                .nla_policy     = icmpv6_timeout_nla_policy,
        },
 #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
-#ifdef CONFIG_SYSCTL
-       .ctl_table_header       = &icmpv6_sysctl_header,
-       .ctl_table              = icmpv6_sysctl_table,
-#endif
+       .init_net               = icmpv6_init_net,
+       .get_net_proto          = icmpv6_get_net_proto,
 };