diff options
author | Patrick McHardy <kaber@trash.net> | 2012-08-26 13:14:14 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-08-29 21:00:18 -0400 |
commit | b3f644fc8232ca761da0b5c5ccb6f30b423c4302 (patch) | |
tree | 6141514d1bb2046c90f66e93234c3494e658e04c | |
parent | 58a317f1061c894d2344c0b6a18ab4a64b69b815 (diff) |
netfilter: ip6tables: add MASQUERADE target
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/net/addrconf.h | 2 | ||||
-rw-r--r-- | include/net/netfilter/nf_nat.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_MASQUERADE.c | 3 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 12 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_MASQUERADE.c | 135 |
7 files changed, 155 insertions, 4 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 089a09d001d1..9e63e76b20e7 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h | |||
@@ -78,7 +78,7 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, | |||
78 | int strict); | 78 | int strict); |
79 | 79 | ||
80 | extern int ipv6_dev_get_saddr(struct net *net, | 80 | extern int ipv6_dev_get_saddr(struct net *net, |
81 | struct net_device *dev, | 81 | const struct net_device *dev, |
82 | const struct in6_addr *daddr, | 82 | const struct in6_addr *daddr, |
83 | unsigned int srcprefs, | 83 | unsigned int srcprefs, |
84 | struct in6_addr *saddr); | 84 | struct in6_addr *saddr); |
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 1752f1339054..bd8eea720f2e 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h | |||
@@ -43,7 +43,9 @@ struct nf_conn_nat { | |||
43 | struct nf_conn *ct; | 43 | struct nf_conn *ct; |
44 | union nf_conntrack_nat_help help; | 44 | union nf_conntrack_nat_help help; |
45 | #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ | 45 | #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ |
46 | defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) | 46 | defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) || \ |
47 | defined(CONFIG_IP6_NF_TARGET_MASQUERADE) || \ | ||
48 | defined(CONFIG_IP6_NF_TARGET_MASQUERADE_MODULE) | ||
47 | int masq_index; | 49 | int masq_index; |
48 | #endif | 50 | #endif |
49 | }; | 51 | }; |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 1c3aa28b51ae..5d5d4d1be9c2 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -99,7 +99,8 @@ device_cmp(struct nf_conn *i, void *ifindex) | |||
99 | 99 | ||
100 | if (!nat) | 100 | if (!nat) |
101 | return 0; | 101 | return 0; |
102 | 102 | if (nf_ct_l3num(i) != NFPROTO_IPV4) | |
103 | return 0; | ||
103 | return nat->masq_index == (int)(long)ifindex; | 104 | return nat->masq_index == (int)(long)ifindex; |
104 | } | 105 | } |
105 | 106 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e581009cb09e..19d4bffda9d7 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1093,7 +1093,7 @@ out: | |||
1093 | return ret; | 1093 | return ret; |
1094 | } | 1094 | } |
1095 | 1095 | ||
1096 | int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | 1096 | int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, |
1097 | const struct in6_addr *daddr, unsigned int prefs, | 1097 | const struct in6_addr *daddr, unsigned int prefs, |
1098 | struct in6_addr *saddr) | 1098 | struct in6_addr *saddr) |
1099 | { | 1099 | { |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index b27e0ad4b738..54a5032ea3df 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -144,6 +144,18 @@ config IP6_NF_TARGET_HL | |||
144 | (e.g. when running oldconfig). It selects | 144 | (e.g. when running oldconfig). It selects |
145 | CONFIG_NETFILTER_XT_TARGET_HL. | 145 | CONFIG_NETFILTER_XT_TARGET_HL. |
146 | 146 | ||
147 | config IP6_NF_TARGET_MASQUERADE | ||
148 | tristate "MASQUERADE target support" | ||
149 | depends on NF_NAT_IPV6 | ||
150 | help | ||
151 | Masquerading is a special case of NAT: all outgoing connections are | ||
152 | changed to seem to come from a particular interface's address, and | ||
153 | if the interface goes down, those connections are lost. This is | ||
154 | only useful for dialup accounts with dynamic IP address (ie. your IP | ||
155 | address will be different on next dialup). | ||
156 | |||
157 | To compile it as a module, choose M here. If unsure, say N. | ||
158 | |||
147 | config IP6_NF_FILTER | 159 | config IP6_NF_FILTER |
148 | tristate "Packet filtering" | 160 | tristate "Packet filtering" |
149 | default m if NETFILTER_ADVANCED=n | 161 | default m if NETFILTER_ADVANCED=n |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 76779376da4c..068bad199587 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -34,4 +34,5 @@ obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o | |||
34 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 34 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o |
35 | 35 | ||
36 | # targets | 36 | # targets |
37 | obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o | ||
37 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o | 38 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o |
diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c new file mode 100644 index 000000000000..60e9053bab05 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
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 | * Based on Rusty Russell's IPv6 MASQUERADE target. Development of IPv6 | ||
9 | * NAT funded by Astaro. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/netdevice.h> | ||
15 | #include <linux/ipv6.h> | ||
16 | #include <linux/netfilter.h> | ||
17 | #include <linux/netfilter_ipv6.h> | ||
18 | #include <linux/netfilter/x_tables.h> | ||
19 | #include <net/netfilter/nf_nat.h> | ||
20 | #include <net/addrconf.h> | ||
21 | #include <net/ipv6.h> | ||
22 | |||
23 | static unsigned int | ||
24 | masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
25 | { | ||
26 | const struct nf_nat_range *range = par->targinfo; | ||
27 | enum ip_conntrack_info ctinfo; | ||
28 | struct in6_addr src; | ||
29 | struct nf_conn *ct; | ||
30 | struct nf_nat_range newrange; | ||
31 | |||
32 | ct = nf_ct_get(skb, &ctinfo); | ||
33 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || | ||
34 | ctinfo == IP_CT_RELATED_REPLY)); | ||
35 | |||
36 | if (ipv6_dev_get_saddr(dev_net(par->out), par->out, | ||
37 | &ipv6_hdr(skb)->daddr, 0, &src) < 0) | ||
38 | return NF_DROP; | ||
39 | |||
40 | nfct_nat(ct)->masq_index = par->out->ifindex; | ||
41 | |||
42 | newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; | ||
43 | newrange.min_addr.in6 = src; | ||
44 | newrange.max_addr.in6 = src; | ||
45 | newrange.min_proto = range->min_proto; | ||
46 | newrange.max_proto = range->max_proto; | ||
47 | |||
48 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); | ||
49 | } | ||
50 | |||
51 | static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par) | ||
52 | { | ||
53 | const struct nf_nat_range *range = par->targinfo; | ||
54 | |||
55 | if (range->flags & NF_NAT_RANGE_MAP_IPS) | ||
56 | return -EINVAL; | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int device_cmp(struct nf_conn *ct, void *ifindex) | ||
61 | { | ||
62 | const struct nf_conn_nat *nat = nfct_nat(ct); | ||
63 | |||
64 | if (!nat) | ||
65 | return 0; | ||
66 | if (nf_ct_l3num(ct) != NFPROTO_IPV6) | ||
67 | return 0; | ||
68 | return nat->masq_index == (int)(long)ifindex; | ||
69 | } | ||
70 | |||
71 | static int masq_device_event(struct notifier_block *this, | ||
72 | unsigned long event, void *ptr) | ||
73 | { | ||
74 | const struct net_device *dev = ptr; | ||
75 | struct net *net = dev_net(dev); | ||
76 | |||
77 | if (event == NETDEV_DOWN) | ||
78 | nf_ct_iterate_cleanup(net, device_cmp, | ||
79 | (void *)(long)dev->ifindex); | ||
80 | |||
81 | return NOTIFY_DONE; | ||
82 | } | ||
83 | |||
84 | static struct notifier_block masq_dev_notifier = { | ||
85 | .notifier_call = masq_device_event, | ||
86 | }; | ||
87 | |||
88 | static int masq_inet_event(struct notifier_block *this, | ||
89 | unsigned long event, void *ptr) | ||
90 | { | ||
91 | struct inet6_ifaddr *ifa = ptr; | ||
92 | |||
93 | return masq_device_event(this, event, ifa->idev->dev); | ||
94 | } | ||
95 | |||
96 | static struct notifier_block masq_inet_notifier = { | ||
97 | .notifier_call = masq_inet_event, | ||
98 | }; | ||
99 | |||
100 | static struct xt_target masquerade_tg6_reg __read_mostly = { | ||
101 | .name = "MASQUERADE", | ||
102 | .family = NFPROTO_IPV6, | ||
103 | .checkentry = masquerade_tg6_checkentry, | ||
104 | .target = masquerade_tg6, | ||
105 | .targetsize = sizeof(struct nf_nat_range), | ||
106 | .table = "nat", | ||
107 | .hooks = 1 << NF_INET_POST_ROUTING, | ||
108 | .me = THIS_MODULE, | ||
109 | }; | ||
110 | |||
111 | static int __init masquerade_tg6_init(void) | ||
112 | { | ||
113 | int err; | ||
114 | |||
115 | err = xt_register_target(&masquerade_tg6_reg); | ||
116 | if (err == 0) { | ||
117 | register_netdevice_notifier(&masq_dev_notifier); | ||
118 | register_inet6addr_notifier(&masq_inet_notifier); | ||
119 | } | ||
120 | |||
121 | return err; | ||
122 | } | ||
123 | static void __exit masquerade_tg6_exit(void) | ||
124 | { | ||
125 | unregister_inet6addr_notifier(&masq_inet_notifier); | ||
126 | unregister_netdevice_notifier(&masq_dev_notifier); | ||
127 | xt_unregister_target(&masquerade_tg6_reg); | ||
128 | } | ||
129 | |||
130 | module_init(masquerade_tg6_init); | ||
131 | module_exit(masquerade_tg6_exit); | ||
132 | |||
133 | MODULE_LICENSE("GPL"); | ||
134 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
135 | MODULE_DESCRIPTION("Xtables: automatic address SNAT"); | ||