• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
nfqnl_ct_get(struct sk_buff * entskb,size_t * size,enum ip_conntrack_info * ctinfo)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 *
nfqnl_ct_parse(const struct sk_buff * skb,const struct nlattr * attr,enum ip_conntrack_info * ctinfo)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 
nfqnl_ct_put(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo)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 
nfqnl_ct_seq_adjust(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,int diff)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_nat_hook *nfq_nat_ct;
91 
92 	nfq_nat_ct = rcu_dereference(nfq_ct_nat_hook);
93 	if (nfq_nat_ct == NULL)
94 		return;
95 
96 	if ((ct->status & IPS_NAT_MASK) && diff)
97 		nfq_nat_ct->seq_adjust(skb, ct, ctinfo, diff);
98 }
99