OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From 1b5aaa4b16f6e6471ab1c07b38068197a1b4c395 Mon Sep 17 00:00:00 2001 |
2 | From: Jonas Gorski <jogo@openwrt.org> |
||
3 | Date: Fri, 24 May 2013 14:40:54 +0200 |
||
4 | Subject: [PATCH 1/2] ipv6: allow rejecting with "source address failed policy" |
||
5 | |||
6 | RFC6204 L-14 requires rejecting traffic from invalid addresses with |
||
7 | ICMPv6 Destination Unreachable, Code 5 (Source address failed ingress/ |
||
8 | egress policy) on the LAN side, so add an appropriate rule for that. |
||
9 | |||
10 | Signed-off-by: Jonas Gorski <jogo@openwrt.org> |
||
11 | --- |
||
12 | include/net/netns/ipv6.h | 1 + |
||
13 | include/uapi/linux/fib_rules.h | 4 +++ |
||
14 | include/uapi/linux/rtnetlink.h | 1 + |
||
15 | net/ipv4/fib_semantics.c | 4 +++ |
||
16 | net/ipv4/fib_trie.c | 1 + |
||
17 | net/ipv4/ipmr.c | 1 + |
||
18 | net/ipv6/fib6_rules.c | 4 +++ |
||
19 | net/ipv6/ip6mr.c | 2 ++ |
||
20 | net/ipv6/route.c | 58 +++++++++++++++++++++++++++++++++++++++++- |
||
21 | 9 files changed, 75 insertions(+), 1 deletion(-) |
||
22 | |||
23 | --- a/include/net/netns/ipv6.h |
||
24 | +++ b/include/net/netns/ipv6.h |
||
25 | @@ -59,6 +59,7 @@ struct netns_ipv6 { |
||
26 | unsigned long ip6_rt_last_gc; |
||
27 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
||
28 | struct rt6_info *ip6_prohibit_entry; |
||
29 | + struct rt6_info *ip6_policy_failed_entry; |
||
30 | struct rt6_info *ip6_blk_hole_entry; |
||
31 | struct fib6_table *fib6_local_tbl; |
||
32 | struct fib_rules_ops *fib6_rules_ops; |
||
33 | --- a/include/uapi/linux/fib_rules.h |
||
34 | +++ b/include/uapi/linux/fib_rules.h |
||
35 | @@ -64,6 +64,10 @@ enum { |
||
36 | FR_ACT_BLACKHOLE, /* Drop without notification */ |
||
37 | FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ |
||
38 | FR_ACT_PROHIBIT, /* Drop with EACCES */ |
||
39 | + FR_ACT_RES9, |
||
40 | + FR_ACT_RES10, |
||
41 | + FR_ACT_RES11, |
||
42 | + FR_ACT_POLICY_FAILED, /* Drop with EACCES */ |
||
43 | __FR_ACT_MAX, |
||
44 | }; |
||
45 | |||
46 | --- a/include/uapi/linux/rtnetlink.h |
||
47 | +++ b/include/uapi/linux/rtnetlink.h |
||
48 | @@ -203,6 +203,7 @@ enum { |
||
49 | RTN_THROW, /* Not in this table */ |
||
50 | RTN_NAT, /* Translate this address */ |
||
51 | RTN_XRESOLVE, /* Use external resolver */ |
||
52 | + RTN_POLICY_FAILED, /* Failed ingress/egress policy */ |
||
53 | __RTN_MAX |
||
54 | }; |
||
55 | |||
56 | --- a/net/ipv4/fib_semantics.c |
||
57 | +++ b/net/ipv4/fib_semantics.c |
||
58 | @@ -138,6 +138,10 @@ const struct fib_prop fib_props[RTN_MAX |
||
59 | .error = -EINVAL, |
||
60 | .scope = RT_SCOPE_NOWHERE, |
||
61 | }, |
||
62 | + [RTN_POLICY_FAILED] = { |
||
63 | + .error = -EACCES, |
||
64 | + .scope = RT_SCOPE_UNIVERSE, |
||
65 | + }, |
||
66 | }; |
||
67 | |||
68 | static void rt_fibinfo_free(struct rtable __rcu **rtp) |
||
69 | --- a/net/ipv4/fib_trie.c |
||
70 | +++ b/net/ipv4/fib_trie.c |
||
71 | @@ -2236,6 +2236,7 @@ static const char *const rtn_type_names[ |
||
72 | [RTN_THROW] = "THROW", |
||
73 | [RTN_NAT] = "NAT", |
||
74 | [RTN_XRESOLVE] = "XRESOLVE", |
||
75 | + [RTN_POLICY_FAILED] = "POLICY_FAILED", |
||
76 | }; |
||
77 | |||
78 | static inline const char *rtn_type(char *buf, size_t len, unsigned int t) |
||
79 | --- a/net/ipv4/ipmr.c |
||
80 | +++ b/net/ipv4/ipmr.c |
||
81 | @@ -184,6 +184,7 @@ static int ipmr_rule_action(struct fib_r |
||
82 | case FR_ACT_UNREACHABLE: |
||
83 | return -ENETUNREACH; |
||
84 | case FR_ACT_PROHIBIT: |
||
85 | + case FR_ACT_POLICY_FAILED: |
||
86 | return -EACCES; |
||
87 | case FR_ACT_BLACKHOLE: |
||
88 | default: |
||
89 | --- a/net/ipv6/fib6_rules.c |
||
90 | +++ b/net/ipv6/fib6_rules.c |
||
91 | @@ -73,6 +73,10 @@ static int fib6_rule_action(struct fib_r |
||
92 | err = -EACCES; |
||
93 | rt = net->ipv6.ip6_prohibit_entry; |
||
94 | goto discard_pkt; |
||
95 | + case FR_ACT_POLICY_FAILED: |
||
96 | + err = -EACCES; |
||
97 | + rt = net->ipv6.ip6_policy_failed_entry; |
||
98 | + goto discard_pkt; |
||
99 | } |
||
100 | |||
101 | table = fib6_get_table(net, rule->table); |
||
102 | --- a/net/ipv6/ip6mr.c |
||
103 | +++ b/net/ipv6/ip6mr.c |
||
104 | @@ -169,6 +169,8 @@ static int ip6mr_rule_action(struct fib_ |
||
105 | return -ENETUNREACH; |
||
106 | case FR_ACT_PROHIBIT: |
||
107 | return -EACCES; |
||
108 | + case FR_ACT_POLICY_FAILED: |
||
109 | + return -EACCES; |
||
110 | case FR_ACT_BLACKHOLE: |
||
111 | default: |
||
112 | return -EINVAL; |
||
113 | --- a/net/ipv6/route.c |
||
114 | +++ b/net/ipv6/route.c |
||
115 | @@ -87,6 +87,8 @@ static int ip6_pkt_discard(struct sk_bu |
||
116 | static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb); |
||
117 | static int ip6_pkt_prohibit(struct sk_buff *skb); |
||
118 | static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb); |
||
119 | +static int ip6_pkt_policy_failed(struct sk_buff *skb); |
||
120 | +static int ip6_pkt_policy_failed_out(struct sock *sk, struct sk_buff *skb); |
||
121 | static void ip6_link_failure(struct sk_buff *skb); |
||
122 | static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, |
||
123 | struct sk_buff *skb, u32 mtu); |
||
124 | @@ -283,6 +285,21 @@ static const struct rt6_info ip6_prohibi |
||
125 | .rt6i_ref = ATOMIC_INIT(1), |
||
126 | }; |
||
127 | |||
128 | +static const struct rt6_info ip6_policy_failed_entry_template = { |
||
129 | + .dst = { |
||
130 | + .__refcnt = ATOMIC_INIT(1), |
||
131 | + .__use = 1, |
||
132 | + .obsolete = DST_OBSOLETE_FORCE_CHK, |
||
133 | + .error = -EACCES, |
||
134 | + .input = ip6_pkt_policy_failed, |
||
135 | + .output = ip6_pkt_policy_failed_out, |
||
136 | + }, |
||
137 | + .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
||
138 | + .rt6i_protocol = RTPROT_KERNEL, |
||
139 | + .rt6i_metric = ~(u32) 0, |
||
140 | + .rt6i_ref = ATOMIC_INIT(1), |
||
141 | +}; |
||
142 | + |
||
143 | static const struct rt6_info ip6_blk_hole_entry_template = { |
||
144 | .dst = { |
||
145 | .__refcnt = ATOMIC_INIT(1), |
||
146 | @@ -1579,6 +1596,11 @@ int ip6_route_add(struct fib6_config *cf |
||
147 | rt->dst.output = ip6_pkt_prohibit_out; |
||
148 | rt->dst.input = ip6_pkt_prohibit; |
||
149 | break; |
||
150 | + case RTN_POLICY_FAILED: |
||
151 | + rt->dst.error = -EACCES; |
||
152 | + rt->dst.output = ip6_pkt_policy_failed_out; |
||
153 | + rt->dst.input = ip6_pkt_policy_failed; |
||
154 | + break; |
||
155 | case RTN_THROW: |
||
156 | default: |
||
157 | rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN |
||
158 | @@ -2142,6 +2164,17 @@ static int ip6_pkt_prohibit_out(struct s |
||
159 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); |
||
160 | } |
||
161 | |||
162 | +static int ip6_pkt_policy_failed(struct sk_buff *skb) |
||
163 | +{ |
||
164 | + return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_INNOROUTES); |
||
165 | +} |
||
166 | + |
||
167 | +static int ip6_pkt_policy_failed_out(struct sock *sk, struct sk_buff *skb) |
||
168 | +{ |
||
169 | + skb->dev = skb_dst(skb)->dev; |
||
170 | + return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_OUTNOROUTES); |
||
171 | +} |
||
172 | + |
||
173 | /* |
||
174 | * Allocate a dst for local (unicast / anycast) address. |
||
175 | */ |
||
176 | @@ -2368,7 +2401,8 @@ static int rtm_to_fib6_config(struct sk_ |
||
177 | if (rtm->rtm_type == RTN_UNREACHABLE || |
||
178 | rtm->rtm_type == RTN_BLACKHOLE || |
||
179 | rtm->rtm_type == RTN_PROHIBIT || |
||
180 | - rtm->rtm_type == RTN_THROW) |
||
181 | + rtm->rtm_type == RTN_THROW || |
||
182 | + rtm->rtm_type == RTN_POLICY_FAILED) |
||
183 | cfg->fc_flags |= RTF_REJECT; |
||
184 | |||
185 | if (rtm->rtm_type == RTN_LOCAL) |
||
186 | @@ -2570,6 +2604,9 @@ static int rt6_fill_node(struct net *net |
||
187 | case -EACCES: |
||
188 | rtm->rtm_type = RTN_PROHIBIT; |
||
189 | break; |
||
190 | + case -EPERM: |
||
191 | + rtm->rtm_type = RTN_POLICY_FAILED; |
||
192 | + break; |
||
193 | case -EAGAIN: |
||
194 | rtm->rtm_type = RTN_THROW; |
||
195 | break; |
||
196 | @@ -2828,6 +2865,8 @@ static int ip6_route_dev_notify(struct n |
||
197 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
||
198 | net->ipv6.ip6_prohibit_entry->dst.dev = dev; |
||
199 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); |
||
200 | + net->ipv6.ip6_policy_failed_entry->dst.dev = dev; |
||
201 | + net->ipv6.ip6_policy_failed_entry->rt6i_idev = in6_dev_get(dev); |
||
202 | net->ipv6.ip6_blk_hole_entry->dst.dev = dev; |
||
203 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); |
||
204 | #endif |
||
205 | @@ -3054,6 +3093,17 @@ static int __net_init ip6_route_net_init |
||
206 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
||
207 | dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, |
||
208 | ip6_template_metrics, true); |
||
209 | + |
||
210 | + net->ipv6.ip6_policy_failed_entry = |
||
211 | + kmemdup(&ip6_policy_failed_entry_template, |
||
212 | + sizeof(*net->ipv6.ip6_policy_failed_entry), GFP_KERNEL); |
||
213 | + if (!net->ipv6.ip6_policy_failed_entry) |
||
214 | + goto out_ip6_blk_hole_entry; |
||
215 | + net->ipv6.ip6_policy_failed_entry->dst.path = |
||
216 | + (struct dst_entry *)net->ipv6.ip6_policy_failed_entry; |
||
217 | + net->ipv6.ip6_policy_failed_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
||
218 | + dst_init_metrics(&net->ipv6.ip6_policy_failed_entry->dst, |
||
219 | + ip6_template_metrics, true); |
||
220 | #endif |
||
221 | |||
222 | net->ipv6.sysctl.flush_delay = 0; |
||
223 | @@ -3072,6 +3122,8 @@ out: |
||
224 | return ret; |
||
225 | |||
226 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
||
227 | +out_ip6_blk_hole_entry: |
||
228 | + kfree(net->ipv6.ip6_blk_hole_entry); |
||
229 | out_ip6_prohibit_entry: |
||
230 | kfree(net->ipv6.ip6_prohibit_entry); |
||
231 | out_ip6_null_entry: |
||
232 | @@ -3089,6 +3141,7 @@ static void __net_exit ip6_route_net_exi |
||
233 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
||
234 | kfree(net->ipv6.ip6_prohibit_entry); |
||
235 | kfree(net->ipv6.ip6_blk_hole_entry); |
||
236 | + kfree(net->ipv6.ip6_policy_failed_entry); |
||
237 | #endif |
||
238 | dst_entries_destroy(&net->ipv6.ip6_dst_ops); |
||
239 | } |
||
240 | @@ -3162,6 +3215,9 @@ void __init ip6_route_init_special_entri |
||
241 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
||
242 | init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; |
||
243 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
||
244 | + init_net.ipv6.ip6_policy_failed_entry->dst.dev = init_net.loopback_dev; |
||
245 | + init_net.ipv6.ip6_policy_failed_entry->rt6i_idev = |
||
246 | + in6_dev_get(init_net.loopback_dev); |
||
247 | #endif |
||
248 | } |
||
249 |