]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/netfilter/nf_conntrack_proto_gre.c
checkpatch: allow simple character constants in #defines
[mirror_ubuntu-artful-kernel.git] / net / netfilter / nf_conntrack_proto_gre.c
index f0338791b822d238d926486e78084afe5089b1a5..659648c4b14ad50331c996ab6a401e379b23b700 100644 (file)
 #include <linux/netfilter/nf_conntrack_proto_gre.h>
 #include <linux/netfilter/nf_conntrack_pptp.h>
 
-#define GRE_TIMEOUT            (30 * HZ)
-#define GRE_STREAM_TIMEOUT     (180 * HZ)
+enum grep_conntrack {
+       GRE_CT_UNREPLIED,
+       GRE_CT_REPLIED,
+       GRE_CT_MAX
+};
+
+static unsigned int gre_timeouts[GRE_CT_MAX] = {
+       [GRE_CT_UNREPLIED]      = 30*HZ,
+       [GRE_CT_REPLIED]        = 180*HZ,
+};
 
 static int proto_gre_net_id __read_mostly;
 struct netns_proto_gre {
@@ -227,13 +235,19 @@ static int gre_print_conntrack(struct seq_file *s, struct nf_conn *ct)
                          (ct->proto.gre.stream_timeout / HZ));
 }
 
+static unsigned int *gre_get_timeouts(struct net *net)
+{
+       return gre_timeouts;
+}
+
 /* Returns verdict for packet, and may modify conntrack */
 static int gre_packet(struct nf_conn *ct,
                      const struct sk_buff *skb,
                      unsigned int dataoff,
                      enum ip_conntrack_info ctinfo,
                      u_int8_t pf,
-                     unsigned int hooknum)
+                     unsigned int hooknum,
+                     unsigned int *timeouts)
 {
        /* If we've seen traffic both ways, this is a GRE connection.
         * Extend timeout. */
@@ -252,15 +266,15 @@ static int gre_packet(struct nf_conn *ct,
 
 /* Called when a new connection for this protocol found. */
 static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb,
-                   unsigned int dataoff)
+                   unsigned int dataoff, unsigned int *timeouts)
 {
        pr_debug(": ");
        nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 
        /* initialize to sane value.  Ideally a conntrack helper
         * (e.g. in case of pptp) is increasing them */
-       ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
-       ct->proto.gre.timeout = GRE_TIMEOUT;
+       ct->proto.gre.stream_timeout = timeouts[GRE_CT_REPLIED];
+       ct->proto.gre.timeout = timeouts[GRE_CT_UNREPLIED];
 
        return true;
 }
@@ -278,6 +292,52 @@ static void gre_destroy(struct nf_conn *ct)
                nf_ct_gre_keymap_destroy(master);
 }
 
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_cttimeout.h>
+
+static int gre_timeout_nlattr_to_obj(struct nlattr *tb[], void *data)
+{
+       unsigned int *timeouts = data;
+
+       /* set default timeouts for GRE. */
+       timeouts[GRE_CT_UNREPLIED] = gre_timeouts[GRE_CT_UNREPLIED];
+       timeouts[GRE_CT_REPLIED] = gre_timeouts[GRE_CT_REPLIED];
+
+       if (tb[CTA_TIMEOUT_GRE_UNREPLIED]) {
+               timeouts[GRE_CT_UNREPLIED] =
+                       ntohl(nla_get_be32(tb[CTA_TIMEOUT_GRE_UNREPLIED])) * HZ;
+       }
+       if (tb[CTA_TIMEOUT_GRE_REPLIED]) {
+               timeouts[GRE_CT_REPLIED] =
+                       ntohl(nla_get_be32(tb[CTA_TIMEOUT_GRE_REPLIED])) * HZ;
+       }
+       return 0;
+}
+
+static int
+gre_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
+{
+       const unsigned int *timeouts = data;
+
+       NLA_PUT_BE32(skb, CTA_TIMEOUT_GRE_UNREPLIED,
+                       htonl(timeouts[GRE_CT_UNREPLIED] / HZ));
+       NLA_PUT_BE32(skb, CTA_TIMEOUT_GRE_REPLIED,
+                       htonl(timeouts[GRE_CT_REPLIED] / HZ));
+       return 0;
+
+nla_put_failure:
+       return -ENOSPC;
+}
+
+static const struct nla_policy
+gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = {
+       [CTA_TIMEOUT_GRE_UNREPLIED]     = { .type = NLA_U32 },
+       [CTA_TIMEOUT_GRE_REPLIED]       = { .type = NLA_U32 },
+};
+#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
+
 /* protocol helper struct */
 static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
        .l3proto         = AF_INET,
@@ -287,6 +347,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
        .invert_tuple    = gre_invert_tuple,
        .print_tuple     = gre_print_tuple,
        .print_conntrack = gre_print_conntrack,
+       .get_timeouts    = gre_get_timeouts,
        .packet          = gre_packet,
        .new             = gre_new,
        .destroy         = gre_destroy,
@@ -297,6 +358,15 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
        .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
        .nla_policy      = nf_ct_port_nla_policy,
 #endif
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
+       .ctnl_timeout    = {
+               .nlattr_to_obj  = gre_timeout_nlattr_to_obj,
+               .obj_to_nlattr  = gre_timeout_obj_to_nlattr,
+               .nlattr_max     = CTA_TIMEOUT_GRE_MAX,
+               .obj_size       = sizeof(unsigned int) * GRE_CT_MAX,
+               .nla_policy     = gre_timeout_nla_policy,
+       },
+#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 };
 
 static int proto_gre_net_init(struct net *net)