Merge tag 'drm-misc-fixes-2018-11-21' of git://anongit.freedesktop.org/drm/drm-misc...
[sfrench/cifs-2.6.git] / net / netfilter / nf_conntrack_proto_generic.c
1 /* (C) 1999-2001 Paul `Rusty' Russell
2  * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8
9 #include <linux/types.h>
10 #include <linux/jiffies.h>
11 #include <linux/timer.h>
12 #include <linux/netfilter.h>
13 #include <net/netfilter/nf_conntrack_l4proto.h>
14 #include <net/netfilter/nf_conntrack_timeout.h>
15
16 static const unsigned int nf_ct_generic_timeout = 600*HZ;
17
18 static bool nf_generic_should_process(u8 proto)
19 {
20         switch (proto) {
21 #ifdef CONFIG_NF_CT_PROTO_GRE_MODULE
22         case IPPROTO_GRE:
23                 return false;
24 #endif
25         default:
26                 return true;
27         }
28 }
29
30 static bool generic_pkt_to_tuple(const struct sk_buff *skb,
31                                  unsigned int dataoff,
32                                  struct net *net, struct nf_conntrack_tuple *tuple)
33 {
34         tuple->src.u.all = 0;
35         tuple->dst.u.all = 0;
36
37         return true;
38 }
39
40 /* Returns verdict for packet, or -1 for invalid. */
41 static int generic_packet(struct nf_conn *ct,
42                           struct sk_buff *skb,
43                           unsigned int dataoff,
44                           enum ip_conntrack_info ctinfo,
45                           const struct nf_hook_state *state)
46 {
47         const unsigned int *timeout = nf_ct_timeout_lookup(ct);
48
49         if (!nf_generic_should_process(nf_ct_protonum(ct))) {
50                 pr_warn_once("conntrack: generic helper won't handle protocol %d. Please consider loading the specific helper module.\n",
51                              nf_ct_protonum(ct));
52                 return -NF_ACCEPT;
53         }
54
55         if (!timeout)
56                 timeout = &nf_generic_pernet(nf_ct_net(ct))->timeout;
57
58         nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
59         return NF_ACCEPT;
60 }
61
62 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
63
64 #include <linux/netfilter/nfnetlink.h>
65 #include <linux/netfilter/nfnetlink_cttimeout.h>
66
67 static int generic_timeout_nlattr_to_obj(struct nlattr *tb[],
68                                          struct net *net, void *data)
69 {
70         struct nf_generic_net *gn = nf_generic_pernet(net);
71         unsigned int *timeout = data;
72
73         if (!timeout)
74                 timeout = &gn->timeout;
75
76         if (tb[CTA_TIMEOUT_GENERIC_TIMEOUT])
77                 *timeout =
78                     ntohl(nla_get_be32(tb[CTA_TIMEOUT_GENERIC_TIMEOUT])) * HZ;
79         else {
80                 /* Set default generic timeout. */
81                 *timeout = gn->timeout;
82         }
83
84         return 0;
85 }
86
87 static int
88 generic_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
89 {
90         const unsigned int *timeout = data;
91
92         if (nla_put_be32(skb, CTA_TIMEOUT_GENERIC_TIMEOUT, htonl(*timeout / HZ)))
93                 goto nla_put_failure;
94
95         return 0;
96
97 nla_put_failure:
98         return -ENOSPC;
99 }
100
101 static const struct nla_policy
102 generic_timeout_nla_policy[CTA_TIMEOUT_GENERIC_MAX+1] = {
103         [CTA_TIMEOUT_GENERIC_TIMEOUT]   = { .type = NLA_U32 },
104 };
105 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
106
107 #ifdef CONFIG_SYSCTL
108 static struct ctl_table generic_sysctl_table[] = {
109         {
110                 .procname       = "nf_conntrack_generic_timeout",
111                 .maxlen         = sizeof(unsigned int),
112                 .mode           = 0644,
113                 .proc_handler   = proc_dointvec_jiffies,
114         },
115         { }
116 };
117 #endif /* CONFIG_SYSCTL */
118
119 static int generic_kmemdup_sysctl_table(struct nf_proto_net *pn,
120                                         struct nf_generic_net *gn)
121 {
122 #ifdef CONFIG_SYSCTL
123         pn->ctl_table = kmemdup(generic_sysctl_table,
124                                 sizeof(generic_sysctl_table),
125                                 GFP_KERNEL);
126         if (!pn->ctl_table)
127                 return -ENOMEM;
128
129         pn->ctl_table[0].data = &gn->timeout;
130 #endif
131         return 0;
132 }
133
134 static int generic_init_net(struct net *net)
135 {
136         struct nf_generic_net *gn = nf_generic_pernet(net);
137         struct nf_proto_net *pn = &gn->pn;
138
139         gn->timeout = nf_ct_generic_timeout;
140
141         return generic_kmemdup_sysctl_table(pn, gn);
142 }
143
144 static struct nf_proto_net *generic_get_net_proto(struct net *net)
145 {
146         return &net->ct.nf_ct_proto.generic.pn;
147 }
148
149 const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
150 {
151         .l4proto                = 255,
152         .pkt_to_tuple           = generic_pkt_to_tuple,
153         .packet                 = generic_packet,
154 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
155         .ctnl_timeout           = {
156                 .nlattr_to_obj  = generic_timeout_nlattr_to_obj,
157                 .obj_to_nlattr  = generic_timeout_obj_to_nlattr,
158                 .nlattr_max     = CTA_TIMEOUT_GENERIC_MAX,
159                 .obj_size       = sizeof(unsigned int),
160                 .nla_policy     = generic_timeout_nla_policy,
161         },
162 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
163         .init_net               = generic_init_net,
164         .get_net_proto          = generic_get_net_proto,
165 };