|
@@ -23,6 +23,12 @@
|
|
|
#include <net/netfilter/nf_conntrack_l3proto.h>
|
|
|
#include <net/netfilter/nf_conntrack_core.h>
|
|
|
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
|
|
|
+#include <net/netfilter/nf_nat_helper.h>
|
|
|
+
|
|
|
+int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
|
|
|
+ struct nf_conn *ct,
|
|
|
+ enum ip_conntrack_info ctinfo);
|
|
|
+EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook);
|
|
|
|
|
|
static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
|
|
|
struct nf_conntrack_tuple *tuple)
|
|
@@ -100,36 +106,42 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
|
|
|
const struct net_device *in,
|
|
|
const struct net_device *out,
|
|
|
int (*okfn)(struct sk_buff *))
|
|
|
-{
|
|
|
- /* We've seen it coming out the other side: confirm it */
|
|
|
- return nf_conntrack_confirm(skb);
|
|
|
-}
|
|
|
-
|
|
|
-static unsigned int ipv4_conntrack_help(unsigned int hooknum,
|
|
|
- struct sk_buff *skb,
|
|
|
- const struct net_device *in,
|
|
|
- const struct net_device *out,
|
|
|
- int (*okfn)(struct sk_buff *))
|
|
|
{
|
|
|
struct nf_conn *ct;
|
|
|
enum ip_conntrack_info ctinfo;
|
|
|
const struct nf_conn_help *help;
|
|
|
const struct nf_conntrack_helper *helper;
|
|
|
+ unsigned int ret;
|
|
|
|
|
|
/* This is where we call the helper: as the packet goes out. */
|
|
|
ct = nf_ct_get(skb, &ctinfo);
|
|
|
if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
|
|
|
- return NF_ACCEPT;
|
|
|
+ goto out;
|
|
|
|
|
|
help = nfct_help(ct);
|
|
|
if (!help)
|
|
|
- return NF_ACCEPT;
|
|
|
+ goto out;
|
|
|
+
|
|
|
/* rcu_read_lock()ed by nf_hook_slow */
|
|
|
helper = rcu_dereference(help->helper);
|
|
|
if (!helper)
|
|
|
- return NF_ACCEPT;
|
|
|
- return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
|
|
|
- ct, ctinfo);
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
|
|
|
+ ct, ctinfo);
|
|
|
+ if (ret != NF_ACCEPT)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
|
|
|
+ typeof(nf_nat_seq_adjust_hook) seq_adjust;
|
|
|
+
|
|
|
+ seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
|
|
|
+ if (!seq_adjust || !seq_adjust(skb, ct, ctinfo))
|
|
|
+ return NF_DROP;
|
|
|
+ }
|
|
|
+out:
|
|
|
+ /* We've seen it coming out the other side: confirm it */
|
|
|
+ return nf_conntrack_confirm(skb);
|
|
|
}
|
|
|
|
|
|
static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
|
|
@@ -210,20 +222,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
|
|
|
.hooknum = NF_INET_LOCAL_OUT,
|
|
|
.priority = NF_IP_PRI_CONNTRACK,
|
|
|
},
|
|
|
- {
|
|
|
- .hook = ipv4_conntrack_help,
|
|
|
- .owner = THIS_MODULE,
|
|
|
- .pf = PF_INET,
|
|
|
- .hooknum = NF_INET_POST_ROUTING,
|
|
|
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
|
|
|
- },
|
|
|
- {
|
|
|
- .hook = ipv4_conntrack_help,
|
|
|
- .owner = THIS_MODULE,
|
|
|
- .pf = PF_INET,
|
|
|
- .hooknum = NF_INET_LOCAL_IN,
|
|
|
- .priority = NF_IP_PRI_CONNTRACK_HELPER,
|
|
|
- },
|
|
|
{
|
|
|
.hook = ipv4_confirm,
|
|
|
.owner = THIS_MODULE,
|