diff options
author | David S. Miller <davem@davemloft.net> | 2011-12-25 02:21:45 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-25 02:21:45 -0500 |
commit | c5e1fd8ccae09f574d6f978c90c2b968ee29030c (patch) | |
tree | e4485dc086ce76c4ff2ff551246255f5de0a250b /net/ipv6 | |
parent | 60b778ce519625102d3f72a2071ea72a05e990ce (diff) | |
parent | ceb98d03eac5704820f2ac1f370c9ff385e3a9f5 (diff) |
Merge branch 'nf-next' of git://1984.lsi.us.es/net-next
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 10 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_rpfilter.c | 133 | ||||
-rw-r--r-- | net/ipv6/route.c | 7 |
4 files changed, 151 insertions, 0 deletions
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index f792b34cbe9c..9a68fb5b9e77 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -125,6 +125,16 @@ config IP6_NF_MATCH_MH | |||
125 | 125 | ||
126 | To compile it as a module, choose M here. If unsure, say N. | 126 | To compile it as a module, choose M here. If unsure, say N. |
127 | 127 | ||
128 | config IP6_NF_MATCH_RPFILTER | ||
129 | tristate '"rpfilter" reverse path filter match support' | ||
130 | depends on NETFILTER_ADVANCED | ||
131 | ---help--- | ||
132 | This option allows you to match packets whose replies would | ||
133 | go out via the interface the packet came in. | ||
134 | |||
135 | To compile it as a module, choose M here. If unsure, say N. | ||
136 | The module will be called ip6t_rpfilter. | ||
137 | |||
128 | config IP6_NF_MATCH_RT | 138 | config IP6_NF_MATCH_RT |
129 | tristate '"rt" Routing header match support' | 139 | tristate '"rt" Routing header match support' |
130 | depends on NETFILTER_ADVANCED | 140 | depends on NETFILTER_ADVANCED |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index abfee91ce816..2eaed96db02c 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o | |||
27 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o | 27 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o |
28 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o | 28 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o |
29 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o | 29 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o |
30 | obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o | ||
30 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 31 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o |
31 | 32 | ||
32 | # targets | 33 | # targets |
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c new file mode 100644 index 000000000000..5d1d8b04d694 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_rpfilter.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Florian Westphal <fw@strlen.de> | ||
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 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | #include <linux/netdevice.h> | ||
12 | #include <linux/route.h> | ||
13 | #include <net/ip6_fib.h> | ||
14 | #include <net/ip6_route.h> | ||
15 | |||
16 | #include <linux/netfilter/xt_rpfilter.h> | ||
17 | #include <linux/netfilter/x_tables.h> | ||
18 | |||
19 | MODULE_LICENSE("GPL"); | ||
20 | MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); | ||
21 | MODULE_DESCRIPTION("Xtables: IPv6 reverse path filter match"); | ||
22 | |||
23 | static bool rpfilter_addr_unicast(const struct in6_addr *addr) | ||
24 | { | ||
25 | int addr_type = ipv6_addr_type(addr); | ||
26 | return addr_type & IPV6_ADDR_UNICAST; | ||
27 | } | ||
28 | |||
29 | static bool rpfilter_lookup_reverse6(const struct sk_buff *skb, | ||
30 | const struct net_device *dev, u8 flags) | ||
31 | { | ||
32 | struct rt6_info *rt; | ||
33 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
34 | bool ret = false; | ||
35 | struct flowi6 fl6 = { | ||
36 | .flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK, | ||
37 | .flowi6_proto = iph->nexthdr, | ||
38 | .daddr = iph->saddr, | ||
39 | }; | ||
40 | int lookup_flags; | ||
41 | |||
42 | if (rpfilter_addr_unicast(&iph->daddr)) { | ||
43 | memcpy(&fl6.saddr, &iph->daddr, sizeof(struct in6_addr)); | ||
44 | lookup_flags = RT6_LOOKUP_F_HAS_SADDR; | ||
45 | } else { | ||
46 | lookup_flags = 0; | ||
47 | } | ||
48 | |||
49 | fl6.flowi6_mark = flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0; | ||
50 | if ((flags & XT_RPFILTER_LOOSE) == 0) { | ||
51 | fl6.flowi6_oif = dev->ifindex; | ||
52 | lookup_flags |= RT6_LOOKUP_F_IFACE; | ||
53 | } | ||
54 | |||
55 | rt = (void *) ip6_route_lookup(dev_net(dev), &fl6, lookup_flags); | ||
56 | if (rt->dst.error) | ||
57 | goto out; | ||
58 | |||
59 | if (rt->rt6i_flags & (RTF_REJECT|RTF_ANYCAST)) | ||
60 | goto out; | ||
61 | |||
62 | if (rt->rt6i_flags & RTF_LOCAL) { | ||
63 | ret = flags & XT_RPFILTER_ACCEPT_LOCAL; | ||
64 | goto out; | ||
65 | } | ||
66 | |||
67 | if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE)) | ||
68 | ret = true; | ||
69 | out: | ||
70 | dst_release(&rt->dst); | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | ||
75 | { | ||
76 | const struct xt_rpfilter_info *info = par->matchinfo; | ||
77 | int saddrtype; | ||
78 | struct ipv6hdr *iph; | ||
79 | bool invert = info->flags & XT_RPFILTER_INVERT; | ||
80 | |||
81 | if (par->in->flags & IFF_LOOPBACK) | ||
82 | return true ^ invert; | ||
83 | |||
84 | iph = ipv6_hdr(skb); | ||
85 | saddrtype = ipv6_addr_type(&iph->saddr); | ||
86 | if (unlikely(saddrtype == IPV6_ADDR_ANY)) | ||
87 | return true ^ invert; /* not routable: forward path will drop it */ | ||
88 | |||
89 | return rpfilter_lookup_reverse6(skb, par->in, info->flags) ^ invert; | ||
90 | } | ||
91 | |||
92 | static int rpfilter_check(const struct xt_mtchk_param *par) | ||
93 | { | ||
94 | const struct xt_rpfilter_info *info = par->matchinfo; | ||
95 | unsigned int options = ~XT_RPFILTER_OPTION_MASK; | ||
96 | |||
97 | if (info->flags & options) { | ||
98 | pr_info("unknown options encountered"); | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | |||
102 | if (strcmp(par->table, "mangle") != 0 && | ||
103 | strcmp(par->table, "raw") != 0) { | ||
104 | pr_info("match only valid in the \'raw\' " | ||
105 | "or \'mangle\' tables, not \'%s\'.\n", par->table); | ||
106 | return -EINVAL; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static struct xt_match rpfilter_mt_reg __read_mostly = { | ||
113 | .name = "rpfilter", | ||
114 | .family = NFPROTO_IPV6, | ||
115 | .checkentry = rpfilter_check, | ||
116 | .match = rpfilter_mt, | ||
117 | .matchsize = sizeof(struct xt_rpfilter_info), | ||
118 | .hooks = (1 << NF_INET_PRE_ROUTING), | ||
119 | .me = THIS_MODULE | ||
120 | }; | ||
121 | |||
122 | static int __init rpfilter_mt_init(void) | ||
123 | { | ||
124 | return xt_register_match(&rpfilter_mt_reg); | ||
125 | } | ||
126 | |||
127 | static void __exit rpfilter_mt_exit(void) | ||
128 | { | ||
129 | xt_unregister_match(&rpfilter_mt_reg); | ||
130 | } | ||
131 | |||
132 | module_init(rpfilter_mt_init); | ||
133 | module_exit(rpfilter_mt_exit); | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ad438546d915..5855e9ede3cb 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -658,6 +658,13 @@ out: | |||
658 | 658 | ||
659 | } | 659 | } |
660 | 660 | ||
661 | struct dst_entry * ip6_route_lookup(struct net *net, struct flowi6 *fl6, | ||
662 | int flags) | ||
663 | { | ||
664 | return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup); | ||
665 | } | ||
666 | EXPORT_SYMBOL_GPL(ip6_route_lookup); | ||
667 | |||
661 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, | 668 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, |
662 | const struct in6_addr *saddr, int oif, int strict) | 669 | const struct in6_addr *saddr, int oif, int strict) |
663 | { | 670 | { |