|
@@ -55,6 +55,44 @@
|
|
: ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \
|
|
: ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \
|
|
: "*ERROR*")))
|
|
: "*ERROR*")))
|
|
|
|
|
|
|
|
+#ifdef CONFIG_XFRM
|
|
|
|
+static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
|
|
|
|
+{
|
|
|
|
+ struct ip_conntrack *ct;
|
|
|
|
+ struct ip_conntrack_tuple *t;
|
|
|
|
+ enum ip_conntrack_info ctinfo;
|
|
|
|
+ enum ip_conntrack_dir dir;
|
|
|
|
+ unsigned long statusbit;
|
|
|
|
+
|
|
|
|
+ ct = ip_conntrack_get(skb, &ctinfo);
|
|
|
|
+ if (ct == NULL)
|
|
|
|
+ return;
|
|
|
|
+ dir = CTINFO2DIR(ctinfo);
|
|
|
|
+ t = &ct->tuplehash[dir].tuple;
|
|
|
|
+
|
|
|
|
+ if (dir == IP_CT_DIR_ORIGINAL)
|
|
|
|
+ statusbit = IPS_DST_NAT;
|
|
|
|
+ else
|
|
|
|
+ statusbit = IPS_SRC_NAT;
|
|
|
|
+
|
|
|
|
+ if (ct->status & statusbit) {
|
|
|
|
+ fl->fl4_dst = t->dst.ip;
|
|
|
|
+ if (t->dst.protonum == IPPROTO_TCP ||
|
|
|
|
+ t->dst.protonum == IPPROTO_UDP)
|
|
|
|
+ fl->fl_ip_dport = t->dst.u.tcp.port;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ statusbit ^= IPS_NAT_MASK;
|
|
|
|
+
|
|
|
|
+ if (ct->status & statusbit) {
|
|
|
|
+ fl->fl4_src = t->src.ip;
|
|
|
|
+ if (t->dst.protonum == IPPROTO_TCP ||
|
|
|
|
+ t->dst.protonum == IPPROTO_UDP)
|
|
|
|
+ fl->fl_ip_sport = t->src.u.tcp.port;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
static unsigned int
|
|
static unsigned int
|
|
ip_nat_fn(unsigned int hooknum,
|
|
ip_nat_fn(unsigned int hooknum,
|
|
struct sk_buff **pskb,
|
|
struct sk_buff **pskb,
|
|
@@ -330,10 +368,14 @@ static int init_or_cleanup(int init)
|
|
|
|
|
|
if (!init) goto cleanup;
|
|
if (!init) goto cleanup;
|
|
|
|
|
|
|
|
+#ifdef CONFIG_XFRM
|
|
|
|
+ BUG_ON(ip_nat_decode_session != NULL);
|
|
|
|
+ ip_nat_decode_session = nat_decode_session;
|
|
|
|
+#endif
|
|
ret = ip_nat_rule_init();
|
|
ret = ip_nat_rule_init();
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
printk("ip_nat_init: can't setup rules.\n");
|
|
printk("ip_nat_init: can't setup rules.\n");
|
|
- goto cleanup_nothing;
|
|
|
|
|
|
+ goto cleanup_decode_session;
|
|
}
|
|
}
|
|
ret = nf_register_hook(&ip_nat_in_ops);
|
|
ret = nf_register_hook(&ip_nat_in_ops);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
@@ -381,7 +423,11 @@ static int init_or_cleanup(int init)
|
|
nf_unregister_hook(&ip_nat_in_ops);
|
|
nf_unregister_hook(&ip_nat_in_ops);
|
|
cleanup_rule_init:
|
|
cleanup_rule_init:
|
|
ip_nat_rule_cleanup();
|
|
ip_nat_rule_cleanup();
|
|
- cleanup_nothing:
|
|
|
|
|
|
+ cleanup_decode_session:
|
|
|
|
+#ifdef CONFIG_XFRM
|
|
|
|
+ ip_nat_decode_session = NULL;
|
|
|
|
+ synchronize_net();
|
|
|
|
+#endif
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|