kernel: update 3.10 to 3.10.2
[openwrt.git] / target / linux / generic / patches-3.10 / 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/icmpv6.h
25 +++ b/include/uapi/linux/icmpv6.h
26 @@ -115,6 +115,7 @@ struct icmp6hdr {
27  #define ICMPV6_NOT_NEIGHBOUR           2
28  #define ICMPV6_ADDR_UNREACH            3
29  #define ICMPV6_PORT_UNREACH            4
30 +#define ICMPV6_FAILED_POLICY           5
31  
32  /*
33   *     Codes for Time Exceeded
34 --- a/include/uapi/linux/rtnetlink.h
35 +++ b/include/uapi/linux/rtnetlink.h
36 @@ -203,6 +203,7 @@ enum {
37         RTN_THROW,              /* Not in this table            */
38         RTN_NAT,                /* Translate this address       */
39         RTN_XRESOLVE,           /* Use external resolver        */
40 +       RTN_FAILED_POLICY,      /* Failed ingress/egress policy */
41         __RTN_MAX
42  };
43  
44 --- a/net/ipv4/fib_rules.c
45 +++ b/net/ipv4/fib_rules.c
46 @@ -84,6 +84,10 @@ static int fib4_rule_action(struct fib_r
47                 err = -EACCES;
48                 goto errout;
49  
50 +       case FR_ACT_FAILED_POLICY:
51 +               err = -EPERM;
52 +               goto errout;
53 +
54         case FR_ACT_BLACKHOLE:
55         default:
56                 err = -EINVAL;
57 --- a/net/ipv4/fib_semantics.c
58 +++ b/net/ipv4/fib_semantics.c
59 @@ -138,6 +138,10 @@ const struct fib_prop fib_props[RTN_MAX
60                 .error  = -EINVAL,
61                 .scope  = RT_SCOPE_NOWHERE,
62         },
63 +       [RTN_FAILED_POLICY] = {
64 +               .error  = -EPERM,
65 +               .scope  = RT_SCOPE_UNIVERSE,
66 +       },
67  };
68  
69  static void rt_fibinfo_free(struct rtable __rcu **rtp)
70 --- a/net/ipv4/fib_trie.c
71 +++ b/net/ipv4/fib_trie.c
72 @@ -2334,6 +2334,7 @@ static const char *const rtn_type_names[
73         [RTN_THROW] = "THROW",
74         [RTN_NAT] = "NAT",
75         [RTN_XRESOLVE] = "XRESOLVE",
76 +       [RTN_FAILED_POLICY] = "FAILED_POLICY",
77  };
78  
79  static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
80 --- a/net/ipv4/ipmr.c
81 +++ b/net/ipv4/ipmr.c
82 @@ -181,6 +181,7 @@ static int ipmr_rule_action(struct fib_r
83         case FR_ACT_UNREACHABLE:
84                 return -ENETUNREACH;
85         case FR_ACT_PROHIBIT:
86 +       case FR_ACT_FAILED_POLICY:
87                 return -EACCES;
88         case FR_ACT_BLACKHOLE:
89         default:
90 --- a/net/ipv6/fib6_rules.c
91 +++ b/net/ipv6/fib6_rules.c
92 @@ -69,6 +69,9 @@ static int fib6_rule_action(struct fib_r
93         case FR_ACT_PROHIBIT:
94                 rt = net->ipv6.ip6_prohibit_entry;
95                 goto discard_pkt;
96 +       case FR_ACT_FAILED_POLICY:
97 +               rt = net->ipv6.ip6_failed_policy_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 @@ -166,6 +166,8 @@ static int ip6mr_rule_action(struct fib_
105                 return -ENETUNREACH;
106         case FR_ACT_PROHIBIT:
107                 return -EACCES;
108 +       case FR_ACT_FAILED_POLICY:
109 +               return -EPERM;
110         case FR_ACT_BLACKHOLE:
111         default:
112                 return -EINVAL;
113 --- a/net/ipv6/route.c
114 +++ b/net/ipv6/route.c
115 @@ -245,6 +245,24 @@ static const struct rt6_info ip6_prohibi
116         .rt6i_ref       = ATOMIC_INIT(1),
117  };
118  
119 +static int ip6_pkt_failed_policy(struct sk_buff *skb);
120 +static int ip6_pkt_failed_policy_out(struct sk_buff *skb);
121 +
122 +static const struct rt6_info ip6_failed_policy_entry_template = {
123 +       .dst = {
124 +               .__refcnt       = ATOMIC_INIT(1),
125 +               .__use          = 1,
126 +               .obsolete       = DST_OBSOLETE_FORCE_CHK,
127 +               .error          = -EPERM,
128 +               .input          = ip6_pkt_failed_policy,
129 +               .output         = ip6_pkt_failed_policy_out,
130 +       },
131 +       .rt6i_flags     = (RTF_REJECT | RTF_NONEXTHOP),
132 +       .rt6i_protocol  = RTPROT_KERNEL,
133 +       .rt6i_metric    = ~(u32) 0,
134 +       .rt6i_ref       = ATOMIC_INIT(1),
135 +};
136 +
137  static const struct rt6_info ip6_blk_hole_entry_template = {
138         .dst = {
139                 .__refcnt       = ATOMIC_INIT(1),
140 @@ -1459,6 +1477,9 @@ int ip6_route_add(struct fib6_config *cf
141                 case RTN_THROW:
142                         rt->dst.error = -EAGAIN;
143                         break;
144 +               case RTN_FAILED_POLICY:
145 +                       rt->dst.error = -EPERM;
146 +                       break;
147                 default:
148                         rt->dst.error = -ENETUNREACH;
149                         break;
150 @@ -2035,6 +2056,17 @@ static int ip6_pkt_prohibit_out(struct s
151         return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
152  }
153  
154 +static int ip6_pkt_failed_policy(struct sk_buff *skb)
155 +{
156 +       return ip6_pkt_drop(skb, ICMPV6_FAILED_POLICY, IPSTATS_MIB_INNOROUTES);
157 +}
158 +
159 +static int ip6_pkt_failed_policy_out(struct sk_buff *skb)
160 +{
161 +       skb->dev = skb_dst(skb)->dev;
162 +       return ip6_pkt_drop(skb, ICMPV6_FAILED_POLICY, IPSTATS_MIB_OUTNOROUTES);
163 +}
164 +
165  #endif
166  
167  /*
168 @@ -2240,7 +2272,8 @@ static int rtm_to_fib6_config(struct sk_
169         if (rtm->rtm_type == RTN_UNREACHABLE ||
170             rtm->rtm_type == RTN_BLACKHOLE ||
171             rtm->rtm_type == RTN_PROHIBIT ||
172 -           rtm->rtm_type == RTN_THROW)
173 +           rtm->rtm_type == RTN_THROW ||
174 +           rtm->rtm_type == RTN_FAILED_POLICY)
175                 cfg->fc_flags |= RTF_REJECT;
176  
177         if (rtm->rtm_type == RTN_LOCAL)
178 @@ -2442,6 +2475,9 @@ static int rt6_fill_node(struct net *net
179                 case -EACCES:
180                         rtm->rtm_type = RTN_PROHIBIT;
181                         break;
182 +               case -EPERM:
183 +                       rtm->rtm_type = RTN_FAILED_POLICY;
184 +                       break;
185                 case -EAGAIN:
186                         rtm->rtm_type = RTN_THROW;
187                         break;
188 @@ -2692,6 +2728,8 @@ static int ip6_route_dev_notify(struct n
189  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
190                 net->ipv6.ip6_prohibit_entry->dst.dev = dev;
191                 net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
192 +               net->ipv6.ip6_failed_policy_entry->dst.dev = dev;
193 +               net->ipv6.ip6_failed_policy_entry->rt6i_idev = in6_dev_get(dev);
194                 net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
195                 net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
196  #endif
197 @@ -2952,6 +2990,17 @@ static int __net_init ip6_route_net_init
198         net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
199         dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
200                          ip6_template_metrics, true);
201 +
202 +       net->ipv6.ip6_failed_policy_entry =
203 +               kmemdup(&ip6_failed_policy_entry_template,
204 +                       sizeof(*net->ipv6.ip6_failed_policy_entry), GFP_KERNEL);
205 +       if (!net->ipv6.ip6_failed_policy_entry)
206 +               goto out_ip6_blk_hole_entry;
207 +       net->ipv6.ip6_failed_policy_entry->dst.path =
208 +               (struct dst_entry *)net->ipv6.ip6_failed_policy_entry;
209 +       net->ipv6.ip6_failed_policy_entry->dst.ops = &net->ipv6.ip6_dst_ops;
210 +       dst_init_metrics(&net->ipv6.ip6_failed_policy_entry->dst,
211 +                        ip6_template_metrics, true);
212  #endif
213  
214         net->ipv6.sysctl.flush_delay = 0;
215 @@ -2970,6 +3019,8 @@ out:
216         return ret;
217  
218  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
219 +out_ip6_blk_hole_entry:
220 +       kfree(net->ipv6.ip6_blk_hole_entry);
221  out_ip6_prohibit_entry:
222         kfree(net->ipv6.ip6_prohibit_entry);
223  out_ip6_null_entry:
224 @@ -2987,6 +3038,7 @@ static void __net_exit ip6_route_net_exi
225  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
226         kfree(net->ipv6.ip6_prohibit_entry);
227         kfree(net->ipv6.ip6_blk_hole_entry);
228 +       kfree(net->ipv6.ip6_failed_policy_entry);
229  #endif
230         dst_entries_destroy(&net->ipv6.ip6_dst_ops);
231  }
232 @@ -3083,6 +3135,9 @@ int __init ip6_route_init(void)
233         init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
234         init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
235         init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
236 +       init_net.ipv6.ip6_failed_policy_entry->dst.dev = init_net.loopback_dev;
237 +       init_net.ipv6.ip6_failed_policy_entry->rt6i_idev =
238 +               in6_dev_get(init_net.loopback_dev);
239    #endif
240         ret = fib6_init();
241         if (ret)