aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/xt_addrtype.h17
-rw-r--r--net/netfilter/Kconfig1
-rw-r--r--net/netfilter/xt_addrtype.c98
3 files changed, 114 insertions, 2 deletions
diff --git a/include/linux/netfilter/xt_addrtype.h b/include/linux/netfilter/xt_addrtype.h
index b492fc84f737..b156baa9d55e 100644
--- a/include/linux/netfilter/xt_addrtype.h
+++ b/include/linux/netfilter/xt_addrtype.h
@@ -10,6 +10,23 @@ enum {
10 XT_ADDRTYPE_LIMIT_IFACE_OUT = 0x0008, 10 XT_ADDRTYPE_LIMIT_IFACE_OUT = 0x0008,
11}; 11};
12 12
13
14/* rtn_type enum values from rtnetlink.h, but shifted */
15enum {
16 XT_ADDRTYPE_UNSPEC = 1 << 0,
17 XT_ADDRTYPE_UNICAST = 1 << 1, /* 1 << RTN_UNICAST */
18 XT_ADDRTYPE_LOCAL = 1 << 2, /* 1 << RTN_LOCAL, etc */
19 XT_ADDRTYPE_BROADCAST = 1 << 3,
20 XT_ADDRTYPE_ANYCAST = 1 << 4,
21 XT_ADDRTYPE_MULTICAST = 1 << 5,
22 XT_ADDRTYPE_BLACKHOLE = 1 << 6,
23 XT_ADDRTYPE_UNREACHABLE = 1 << 7,
24 XT_ADDRTYPE_PROHIBIT = 1 << 8,
25 XT_ADDRTYPE_THROW = 1 << 9,
26 XT_ADDRTYPE_NAT = 1 << 10,
27 XT_ADDRTYPE_XRESOLVE = 1 << 11,
28};
29
13struct xt_addrtype_info_v1 { 30struct xt_addrtype_info_v1 {
14 __u16 source; /* source-type mask */ 31 __u16 source; /* source-type mask */
15 __u16 dest; /* dest-type mask */ 32 __u16 dest; /* dest-type mask */
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"
652config NETFILTER_XT_MATCH_ADDRTYPE 652config 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");
23MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 29MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
24MODULE_DESCRIPTION("Xtables: address type match"); 30MODULE_DESCRIPTION("Xtables: address type match");
25MODULE_ALIAS("ipt_addrtype"); 31MODULE_ALIAS("ipt_addrtype");
32MODULE_ALIAS("ip6t_addrtype");
33
34#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
35static 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
54static 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
83static bool
84addrtype_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
27static inline bool match_type(struct net *net, const struct net_device *dev, 100static 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,