kernel: refresh 3.12 patches on -rc7 release
[openwrt/svn-archive/archive.git] / target / linux / generic / patches-3.12 / 670-ipv6-allow-rejecting-with-source-address-failed-policy.patch
1 --- a/include/net/netns/ipv6.h
2 +++ b/include/net/netns/ipv6.h
3 @@ -55,6 +55,7 @@ struct netns_ipv6 {
4 unsigned long ip6_rt_last_gc;
5 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
6 struct rt6_info *ip6_prohibit_entry;
7 + struct rt6_info *ip6_failed_policy_entry;
8 struct rt6_info *ip6_blk_hole_entry;
9 struct fib6_table *fib6_local_tbl;
10 struct fib_rules_ops *fib6_rules_ops;
11 --- a/include/uapi/linux/fib_rules.h
12 +++ b/include/uapi/linux/fib_rules.h
13 @@ -64,6 +64,10 @@ enum {
14 FR_ACT_BLACKHOLE, /* Drop without notification */
15 FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */
16 FR_ACT_PROHIBIT, /* Drop with EACCES */
17 + FR_ACT_RES9,
18 + FR_ACT_RES10,
19 + FR_ACT_RES11,
20 + FR_ACT_FAILED_POLICY, /* Drop with EPERM */
21 __FR_ACT_MAX,
22 };
23
24 --- a/include/uapi/linux/rtnetlink.h
25 +++ b/include/uapi/linux/rtnetlink.h
26 @@ -203,6 +203,7 @@ enum {
27 RTN_THROW, /* Not in this table */
28 RTN_NAT, /* Translate this address */
29 RTN_XRESOLVE, /* Use external resolver */
30 + RTN_FAILED_POLICY, /* Failed ingress/egress policy */
31 __RTN_MAX
32 };
33
34 --- a/net/ipv4/fib_rules.c
35 +++ b/net/ipv4/fib_rules.c
36 @@ -84,6 +84,10 @@ static int fib4_rule_action(struct fib_r
37 err = -EACCES;
38 goto errout;
39
40 + case FR_ACT_FAILED_POLICY:
41 + err = -EPERM;
42 + goto errout;
43 +
44 case FR_ACT_BLACKHOLE:
45 default:
46 err = -EINVAL;
47 --- a/net/ipv4/fib_semantics.c
48 +++ b/net/ipv4/fib_semantics.c
49 @@ -138,6 +138,10 @@ const struct fib_prop fib_props[RTN_MAX
50 .error = -EINVAL,
51 .scope = RT_SCOPE_NOWHERE,
52 },
53 + [RTN_FAILED_POLICY] = {
54 + .error = -EPERM,
55 + .scope = RT_SCOPE_UNIVERSE,
56 + },
57 };
58
59 static void rt_fibinfo_free(struct rtable __rcu **rtp)
60 --- a/net/ipv4/fib_trie.c
61 +++ b/net/ipv4/fib_trie.c
62 @@ -2331,6 +2331,7 @@ static const char *const rtn_type_names[
63 [RTN_THROW] = "THROW",
64 [RTN_NAT] = "NAT",
65 [RTN_XRESOLVE] = "XRESOLVE",
66 + [RTN_FAILED_POLICY] = "FAILED_POLICY",
67 };
68
69 static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
70 --- a/net/ipv4/ipmr.c
71 +++ b/net/ipv4/ipmr.c
72 @@ -181,6 +181,7 @@ static int ipmr_rule_action(struct fib_r
73 case FR_ACT_UNREACHABLE:
74 return -ENETUNREACH;
75 case FR_ACT_PROHIBIT:
76 + case FR_ACT_FAILED_POLICY:
77 return -EACCES;
78 case FR_ACT_BLACKHOLE:
79 default:
80 --- a/net/ipv6/fib6_rules.c
81 +++ b/net/ipv6/fib6_rules.c
82 @@ -73,6 +73,9 @@ static int fib6_rule_action(struct fib_r
83 err = -EACCES;
84 rt = net->ipv6.ip6_prohibit_entry;
85 goto discard_pkt;
86 + case FR_ACT_FAILED_POLICY:
87 + rt = net->ipv6.ip6_failed_policy_entry;
88 + goto discard_pkt;
89 }
90
91 table = fib6_get_table(net, rule->table);
92 --- a/net/ipv6/ip6mr.c
93 +++ b/net/ipv6/ip6mr.c
94 @@ -166,6 +166,8 @@ static int ip6mr_rule_action(struct fib_
95 return -ENETUNREACH;
96 case FR_ACT_PROHIBIT:
97 return -EACCES;
98 + case FR_ACT_FAILED_POLICY:
99 + return -EPERM;
100 case FR_ACT_BLACKHOLE:
101 default:
102 return -EINVAL;
103 --- a/net/ipv6/route.c
104 +++ b/net/ipv6/route.c
105 @@ -252,6 +252,24 @@ static const struct rt6_info ip6_prohibi
106 .rt6i_ref = ATOMIC_INIT(1),
107 };
108
109 +static int ip6_pkt_failed_policy(struct sk_buff *skb);
110 +static int ip6_pkt_failed_policy_out(struct sk_buff *skb);
111 +
112 +static const struct rt6_info ip6_failed_policy_entry_template = {
113 + .dst = {
114 + .__refcnt = ATOMIC_INIT(1),
115 + .__use = 1,
116 + .obsolete = DST_OBSOLETE_FORCE_CHK,
117 + .error = -EPERM,
118 + .input = ip6_pkt_failed_policy,
119 + .output = ip6_pkt_failed_policy_out,
120 + },
121 + .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
122 + .rt6i_protocol = RTPROT_KERNEL,
123 + .rt6i_metric = ~(u32) 0,
124 + .rt6i_ref = ATOMIC_INIT(1),
125 +};
126 +
127 static const struct rt6_info ip6_blk_hole_entry_template = {
128 .dst = {
129 .__refcnt = ATOMIC_INIT(1),
130 @@ -1577,6 +1595,9 @@ int ip6_route_add(struct fib6_config *cf
131 case RTN_THROW:
132 rt->dst.error = -EAGAIN;
133 break;
134 + case RTN_FAILED_POLICY:
135 + rt->dst.error = -EPERM;
136 + break;
137 default:
138 rt->dst.error = -ENETUNREACH;
139 break;
140 @@ -2156,6 +2177,17 @@ static int ip6_pkt_prohibit_out(struct s
141 return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
142 }
143
144 +static int ip6_pkt_failed_policy(struct sk_buff *skb)
145 +{
146 + return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_INNOROUTES);
147 +}
148 +
149 +static int ip6_pkt_failed_policy_out(struct sk_buff *skb)
150 +{
151 + skb->dev = skb_dst(skb)->dev;
152 + return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_OUTNOROUTES);
153 +}
154 +
155 #endif
156
157 /*
158 @@ -2362,7 +2394,8 @@ static int rtm_to_fib6_config(struct sk_
159 if (rtm->rtm_type == RTN_UNREACHABLE ||
160 rtm->rtm_type == RTN_BLACKHOLE ||
161 rtm->rtm_type == RTN_PROHIBIT ||
162 - rtm->rtm_type == RTN_THROW)
163 + rtm->rtm_type == RTN_THROW ||
164 + rtm->rtm_type == RTN_FAILED_POLICY)
165 cfg->fc_flags |= RTF_REJECT;
166
167 if (rtm->rtm_type == RTN_LOCAL)
168 @@ -2564,6 +2597,9 @@ static int rt6_fill_node(struct net *net
169 case -EACCES:
170 rtm->rtm_type = RTN_PROHIBIT;
171 break;
172 + case -EPERM:
173 + rtm->rtm_type = RTN_FAILED_POLICY;
174 + break;
175 case -EAGAIN:
176 rtm->rtm_type = RTN_THROW;
177 break;
178 @@ -2814,6 +2850,8 @@ static int ip6_route_dev_notify(struct n
179 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
180 net->ipv6.ip6_prohibit_entry->dst.dev = dev;
181 net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
182 + net->ipv6.ip6_failed_policy_entry->dst.dev = dev;
183 + net->ipv6.ip6_failed_policy_entry->rt6i_idev = in6_dev_get(dev);
184 net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
185 net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
186 #endif
187 @@ -3074,6 +3112,17 @@ static int __net_init ip6_route_net_init
188 net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
189 dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
190 ip6_template_metrics, true);
191 +
192 + net->ipv6.ip6_failed_policy_entry =
193 + kmemdup(&ip6_failed_policy_entry_template,
194 + sizeof(*net->ipv6.ip6_failed_policy_entry), GFP_KERNEL);
195 + if (!net->ipv6.ip6_failed_policy_entry)
196 + goto out_ip6_blk_hole_entry;
197 + net->ipv6.ip6_failed_policy_entry->dst.path =
198 + (struct dst_entry *)net->ipv6.ip6_failed_policy_entry;
199 + net->ipv6.ip6_failed_policy_entry->dst.ops = &net->ipv6.ip6_dst_ops;
200 + dst_init_metrics(&net->ipv6.ip6_failed_policy_entry->dst,
201 + ip6_template_metrics, true);
202 #endif
203
204 net->ipv6.sysctl.flush_delay = 0;
205 @@ -3092,6 +3141,8 @@ out:
206 return ret;
207
208 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
209 +out_ip6_blk_hole_entry:
210 + kfree(net->ipv6.ip6_blk_hole_entry);
211 out_ip6_prohibit_entry:
212 kfree(net->ipv6.ip6_prohibit_entry);
213 out_ip6_null_entry:
214 @@ -3109,6 +3160,7 @@ static void __net_exit ip6_route_net_exi
215 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
216 kfree(net->ipv6.ip6_prohibit_entry);
217 kfree(net->ipv6.ip6_blk_hole_entry);
218 + kfree(net->ipv6.ip6_failed_policy_entry);
219 #endif
220 dst_entries_destroy(&net->ipv6.ip6_dst_ops);
221 }
222 @@ -3205,6 +3257,9 @@ int __init ip6_route_init(void)
223 init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
224 init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
225 init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
226 + init_net.ipv6.ip6_failed_policy_entry->dst.dev = init_net.loopback_dev;
227 + init_net.ipv6.ip6_failed_policy_entry->rt6i_idev =
228 + in6_dev_get(init_net.loopback_dev);
229 #endif
230 ret = fib6_init();
231 if (ret)