Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / net / netfilter / nfnetlink_queue_ct.c
1 /*
2  * (C) 2012 by Pablo Neira Ayuso <pablo@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
10 #include <linux/skbuff.h>
11 #include <linux/netfilter.h>
12 #include <linux/netfilter/nfnetlink.h>
13 #include <linux/netfilter/nfnetlink_queue.h>
14 #include <net/netfilter/nf_conntrack.h>
15 #include <net/netfilter/nfnetlink_queue.h>
16
17 struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size,
18                              enum ip_conntrack_info *ctinfo)
19 {
20         struct nfq_ct_hook *nfq_ct;
21         struct nf_conn *ct;
22
23         /* rcu_read_lock()ed by __nf_queue already. */
24         nfq_ct = rcu_dereference(nfq_ct_hook);
25         if (nfq_ct == NULL)
26                 return NULL;
27
28         ct = nf_ct_get(entskb, ctinfo);
29         if (ct) {
30                 if (!nf_ct_is_untracked(ct))
31                         *size += nfq_ct->build_size(ct);
32                 else
33                         ct = NULL;
34         }
35         return ct;
36 }
37
38 struct nf_conn *
39 nfqnl_ct_parse(const struct sk_buff *skb, const struct nlattr *attr,
40                enum ip_conntrack_info *ctinfo)
41 {
42         struct nfq_ct_hook *nfq_ct;
43         struct nf_conn *ct;
44
45         /* rcu_read_lock()ed by __nf_queue already. */
46         nfq_ct = rcu_dereference(nfq_ct_hook);
47         if (nfq_ct == NULL)
48                 return NULL;
49
50         ct = nf_ct_get(skb, ctinfo);
51         if (ct && !nf_ct_is_untracked(ct))
52                 nfq_ct->parse(attr, ct);
53
54         return ct;
55 }
56
57 int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct,
58                  enum ip_conntrack_info ctinfo)
59 {
60         struct nfq_ct_hook *nfq_ct;
61         struct nlattr *nest_parms;
62         u_int32_t tmp;
63
64         nfq_ct = rcu_dereference(nfq_ct_hook);
65         if (nfq_ct == NULL)
66                 return 0;
67
68         nest_parms = nla_nest_start(skb, NFQA_CT | NLA_F_NESTED);
69         if (!nest_parms)
70                 goto nla_put_failure;
71
72         if (nfq_ct->build(skb, ct) < 0)
73                 goto nla_put_failure;
74
75         nla_nest_end(skb, nest_parms);
76
77         tmp = ctinfo;
78         if (nla_put_be32(skb, NFQA_CT_INFO, htonl(tmp)))
79                 goto nla_put_failure;
80
81         return 0;
82
83 nla_put_failure:
84         return -1;
85 }
86
87 void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
88                          enum ip_conntrack_info ctinfo, int diff)
89 {
90         struct nfq_ct_hook *nfq_ct;
91
92         nfq_ct = rcu_dereference(nfq_ct_hook);
93         if (nfq_ct == NULL)
94                 return;
95
96         if ((ct->status & IPS_NAT_MASK) && diff)
97                 nfq_ct->seq_adjust(skb, ct, ctinfo, diff);
98 }
99
100 int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr,
101                         u32 portid, u32 report)
102 {
103         struct nfq_ct_hook *nfq_ct;
104
105         if (nf_ct_is_untracked(ct))
106                 return 0;
107
108         nfq_ct = rcu_dereference(nfq_ct_hook);
109         if (nfq_ct == NULL)
110                 return -EOPNOTSUPP;
111
112         return nfq_ct->attach_expect(attr, ct, portid, report);
113 }