diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/Kconfig | 1 | ||||
-rw-r--r-- | net/netfilter/xt_addrtype.c | 98 |
2 files changed, 97 insertions, 2 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 32bff6d86cb2..c3f988aa1152 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -652,6 +652,7 @@ comment "Xtables matches" | |||
652 | config NETFILTER_XT_MATCH_ADDRTYPE | 652 | config NETFILTER_XT_MATCH_ADDRTYPE |
653 | tristate '"addrtype" address type match support' | 653 | tristate '"addrtype" address type match support' |
654 | depends on NETFILTER_ADVANCED | 654 | depends on NETFILTER_ADVANCED |
655 | depends on (IPV6 || IPV6=n) | ||
655 | ---help--- | 656 | ---help--- |
656 | This option allows you to match what routing thinks of an address, | 657 | This option allows you to match what routing thinks of an address, |
657 | eg. UNICAST, LOCAL, BROADCAST, ... | 658 | eg. UNICAST, LOCAL, BROADCAST, ... |
diff --git a/net/netfilter/xt_addrtype.c b/net/netfilter/xt_addrtype.c index e89c0b84583c..2220b85e9519 100644 --- a/net/netfilter/xt_addrtype.c +++ b/net/netfilter/xt_addrtype.c | |||
@@ -16,6 +16,12 @@ | |||
16 | #include <linux/ip.h> | 16 | #include <linux/ip.h> |
17 | #include <net/route.h> | 17 | #include <net/route.h> |
18 | 18 | ||
19 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | ||
20 | #include <net/ipv6.h> | ||
21 | #include <net/ip6_route.h> | ||
22 | #include <net/ip6_fib.h> | ||
23 | #endif | ||
24 | |||
19 | #include <linux/netfilter/xt_addrtype.h> | 25 | #include <linux/netfilter/xt_addrtype.h> |
20 | #include <linux/netfilter/x_tables.h> | 26 | #include <linux/netfilter/x_tables.h> |
21 | 27 | ||
@@ -23,6 +29,73 @@ MODULE_LICENSE("GPL"); | |||
23 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 29 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
24 | MODULE_DESCRIPTION("Xtables: address type match"); | 30 | MODULE_DESCRIPTION("Xtables: address type match"); |
25 | MODULE_ALIAS("ipt_addrtype"); | 31 | MODULE_ALIAS("ipt_addrtype"); |
32 | MODULE_ALIAS("ip6t_addrtype"); | ||
33 | |||
34 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | ||
35 | static u32 xt_addrtype_rt6_to_type(const struct rt6_info *rt) | ||
36 | { | ||
37 | u32 ret; | ||
38 | |||
39 | if (!rt) | ||
40 | return XT_ADDRTYPE_UNREACHABLE; | ||
41 | |||
42 | if (rt->rt6i_flags & RTF_REJECT) | ||
43 | ret = XT_ADDRTYPE_UNREACHABLE; | ||
44 | else | ||
45 | ret = 0; | ||
46 | |||
47 | if (rt->rt6i_flags & RTF_LOCAL) | ||
48 | ret |= XT_ADDRTYPE_LOCAL; | ||
49 | if (rt->rt6i_flags & RTF_ANYCAST) | ||
50 | ret |= XT_ADDRTYPE_ANYCAST; | ||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | static bool match_type6(struct net *net, const struct net_device *dev, | ||
55 | const struct in6_addr *addr, u16 mask) | ||
56 | { | ||
57 | int addr_type = ipv6_addr_type(addr); | ||
58 | |||
59 | if ((mask & XT_ADDRTYPE_MULTICAST) && | ||
60 | !(addr_type & IPV6_ADDR_MULTICAST)) | ||
61 | return false; | ||
62 | if ((mask & XT_ADDRTYPE_UNICAST) && !(addr_type & IPV6_ADDR_UNICAST)) | ||
63 | return false; | ||
64 | if ((mask & XT_ADDRTYPE_UNSPEC) && addr_type != IPV6_ADDR_ANY) | ||
65 | return false; | ||
66 | |||
67 | if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST | | ||
68 | XT_ADDRTYPE_UNREACHABLE) & mask) { | ||
69 | struct rt6_info *rt; | ||
70 | u32 type; | ||
71 | int ifindex = dev ? dev->ifindex : 0; | ||
72 | |||
73 | rt = rt6_lookup(net, addr, NULL, ifindex, !!dev); | ||
74 | |||
75 | type = xt_addrtype_rt6_to_type(rt); | ||
76 | |||
77 | dst_release(&rt->dst); | ||
78 | return !!(mask & type); | ||
79 | } | ||
80 | return true; | ||
81 | } | ||
82 | |||
83 | static bool | ||
84 | addrtype_mt6(struct net *net, const struct net_device *dev, | ||
85 | const struct sk_buff *skb, const struct xt_addrtype_info_v1 *info) | ||
86 | { | ||
87 | const struct ipv6hdr *iph = ipv6_hdr(skb); | ||
88 | bool ret = true; | ||
89 | |||
90 | if (info->source) | ||
91 | ret &= match_type6(net, dev, &iph->saddr, info->source) ^ | ||
92 | (info->flags & XT_ADDRTYPE_INVERT_SOURCE); | ||
93 | if (ret && info->dest) | ||
94 | ret &= match_type6(net, dev, &iph->daddr, info->dest) ^ | ||
95 | !!(info->flags & XT_ADDRTYPE_INVERT_DEST); | ||
96 | return ret; | ||
97 | } | ||
98 | #endif | ||
26 | 99 | ||
27 | static inline bool match_type(struct net *net, const struct net_device *dev, | 100 | static inline bool match_type(struct net *net, const struct net_device *dev, |
28 | __be32 addr, u_int16_t mask) | 101 | __be32 addr, u_int16_t mask) |
@@ -53,7 +126,7 @@ addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) | |||
53 | { | 126 | { |
54 | struct net *net = dev_net(par->in ? par->in : par->out); | 127 | struct net *net = dev_net(par->in ? par->in : par->out); |
55 | const struct xt_addrtype_info_v1 *info = par->matchinfo; | 128 | const struct xt_addrtype_info_v1 *info = par->matchinfo; |
56 | const struct iphdr *iph = ip_hdr(skb); | 129 | const struct iphdr *iph; |
57 | const struct net_device *dev = NULL; | 130 | const struct net_device *dev = NULL; |
58 | bool ret = true; | 131 | bool ret = true; |
59 | 132 | ||
@@ -62,6 +135,11 @@ addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) | |||
62 | else if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) | 135 | else if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) |
63 | dev = par->out; | 136 | dev = par->out; |
64 | 137 | ||
138 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | ||
139 | if (par->family == NFPROTO_IPV6) | ||
140 | return addrtype_mt6(net, dev, skb, info); | ||
141 | #endif | ||
142 | iph = ip_hdr(skb); | ||
65 | if (info->source) | 143 | if (info->source) |
66 | ret &= match_type(net, dev, iph->saddr, info->source) ^ | 144 | ret &= match_type(net, dev, iph->saddr, info->source) ^ |
67 | (info->flags & XT_ADDRTYPE_INVERT_SOURCE); | 145 | (info->flags & XT_ADDRTYPE_INVERT_SOURCE); |
@@ -98,6 +176,22 @@ static int addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par) | |||
98 | return -EINVAL; | 176 | return -EINVAL; |
99 | } | 177 | } |
100 | 178 | ||
179 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | ||
180 | if (par->family == NFPROTO_IPV6) { | ||
181 | if ((info->source | info->dest) & XT_ADDRTYPE_BLACKHOLE) { | ||
182 | pr_err("ipv6 BLACKHOLE matching not supported\n"); | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | if ((info->source | info->dest) >= XT_ADDRTYPE_PROHIBIT) { | ||
186 | pr_err("ipv6 PROHIBT (THROW, NAT ..) matching not supported\n"); | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | if ((info->source | info->dest) & XT_ADDRTYPE_BROADCAST) { | ||
190 | pr_err("ipv6 does not support BROADCAST matching\n"); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | } | ||
194 | #endif | ||
101 | return 0; | 195 | return 0; |
102 | } | 196 | } |
103 | 197 | ||
@@ -111,7 +205,7 @@ static struct xt_match addrtype_mt_reg[] __read_mostly = { | |||
111 | }, | 205 | }, |
112 | { | 206 | { |
113 | .name = "addrtype", | 207 | .name = "addrtype", |
114 | .family = NFPROTO_IPV4, | 208 | .family = NFPROTO_UNSPEC, |
115 | .revision = 1, | 209 | .revision = 1, |
116 | .match = addrtype_mt_v1, | 210 | .match = addrtype_mt_v1, |
117 | .checkentry = addrtype_mt_checkentry_v1, | 211 | .checkentry = addrtype_mt_checkentry_v1, |