|
@@ -20,12 +20,13 @@
|
|
#include <linux/netfilter.h>
|
|
#include <linux/netfilter.h>
|
|
#include <linux/types.h>
|
|
#include <linux/types.h>
|
|
#include <linux/netfilter_ipv4.h>
|
|
#include <linux/netfilter_ipv4.h>
|
|
|
|
+#include <linux/netfilter_ipv6.h>
|
|
#include <linux/netfilter/x_tables.h>
|
|
#include <linux/netfilter/x_tables.h>
|
|
#include <net/addrconf.h>
|
|
#include <net/addrconf.h>
|
|
#include <net/checksum.h>
|
|
#include <net/checksum.h>
|
|
#include <net/protocol.h>
|
|
#include <net/protocol.h>
|
|
#include <net/netfilter/nf_nat.h>
|
|
#include <net/netfilter/nf_nat.h>
|
|
-#include <net/netfilter/ipv4/nf_nat_redirect.h>
|
|
|
|
|
|
+#include <net/netfilter/nf_nat_redirect.h>
|
|
|
|
|
|
unsigned int
|
|
unsigned int
|
|
nf_nat_redirect_ipv4(struct sk_buff *skb,
|
|
nf_nat_redirect_ipv4(struct sk_buff *skb,
|
|
@@ -78,5 +79,49 @@ nf_nat_redirect_ipv4(struct sk_buff *skb,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4);
|
|
EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4);
|
|
|
|
|
|
|
|
+static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
|
|
|
|
+
|
|
|
|
+unsigned int
|
|
|
|
+nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range,
|
|
|
|
+ unsigned int hooknum)
|
|
|
|
+{
|
|
|
|
+ struct nf_nat_range newrange;
|
|
|
|
+ struct in6_addr newdst;
|
|
|
|
+ enum ip_conntrack_info ctinfo;
|
|
|
|
+ struct nf_conn *ct;
|
|
|
|
+
|
|
|
|
+ ct = nf_ct_get(skb, &ctinfo);
|
|
|
|
+ if (hooknum == NF_INET_LOCAL_OUT) {
|
|
|
|
+ newdst = loopback_addr;
|
|
|
|
+ } else {
|
|
|
|
+ struct inet6_dev *idev;
|
|
|
|
+ struct inet6_ifaddr *ifa;
|
|
|
|
+ bool addr = false;
|
|
|
|
+
|
|
|
|
+ rcu_read_lock();
|
|
|
|
+ idev = __in6_dev_get(skb->dev);
|
|
|
|
+ if (idev != NULL) {
|
|
|
|
+ list_for_each_entry(ifa, &idev->addr_list, if_list) {
|
|
|
|
+ newdst = ifa->addr;
|
|
|
|
+ addr = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
+
|
|
|
|
+ if (!addr)
|
|
|
|
+ return NF_DROP;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
|
|
|
|
+ newrange.min_addr.in6 = newdst;
|
|
|
|
+ newrange.max_addr.in6 = newdst;
|
|
|
|
+ newrange.min_proto = range->min_proto;
|
|
|
|
+ newrange.max_proto = range->max_proto;
|
|
|
|
+
|
|
|
|
+ return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv6);
|
|
|
|
+
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
|
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|