1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/netdevice.h>
24#include <linux/netlink.h>
25#include <linux/inetdevice.h>
26#include <linux/init.h>
27#include <linux/list.h>
28#include <linux/rcupdate.h>
29#include <linux/export.h>
30#include <net/ip.h>
31#include <net/route.h>
32#include <net/tcp.h>
33#include <net/ip_fib.h>
34#include <net/fib_rules.h>
35
36struct fib4_rule {
37 struct fib_rule common;
38 u8 dst_len;
39 u8 src_len;
40 u8 tos;
41 __be32 src;
42 __be32 srcmask;
43 __be32 dst;
44 __be32 dstmask;
45#ifdef CONFIG_IP_ROUTE_CLASSID
46 u32 tclassid;
47#endif
48};
49
50static bool fib4_rule_matchall(const struct fib_rule *rule)
51{
52 struct fib4_rule *r = container_of(rule, struct fib4_rule, common);
53
54 if (r->dst_len || r->src_len || r->tos)
55 return false;
56 return fib_rule_matchall(rule);
57}
58
59bool fib4_rule_default(const struct fib_rule *rule)
60{
61 if (!fib4_rule_matchall(rule) || rule->action != FR_ACT_TO_TBL)
62 return false;
63 if (rule->table != RT_TABLE_LOCAL && rule->table != RT_TABLE_MAIN &&
64 rule->table != RT_TABLE_DEFAULT)
65 return false;
66 return true;
67}
68EXPORT_SYMBOL_GPL(fib4_rule_default);
69
70int fib4_rules_dump(struct net *net, struct notifier_block *nb)
71{
72 return fib_rules_dump(net, nb, AF_INET);
73}
74
75unsigned int fib4_rules_seq_read(struct net *net)
76{
77 return fib_rules_seq_read(net, AF_INET);
78}
79
80int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res)
81{
82 struct fib_lookup_arg arg = {
83 .result = res,
84 .flags = FIB_LOOKUP_NOREF,
85 };
86 int err;
87
88 err = fib_rules_lookup(net->ipv4.rules_ops, flowi4_to_flowi(flp), 0, &arg);
89#ifdef CONFIG_IP_ROUTE_CLASSID
90 if (arg.rule)
91 res->tclassid = ((struct fib4_rule *)arg.rule)->tclassid;
92 else
93 res->tclassid = 0;
94#endif
95
96 if (err == -ESRCH)
97 err = -ENETUNREACH;
98
99 return err;
100}
101EXPORT_SYMBOL_GPL(__fib_lookup);
102
103static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,
104 int flags, struct fib_lookup_arg *arg)
105{
106 int err = -EAGAIN;
107 struct fib_table *tbl;
108
109 switch (rule->action) {
110 case FR_ACT_TO_TBL:
111 break;
112
113 case FR_ACT_UNREACHABLE:
114 return -ENETUNREACH;
115
116 case FR_ACT_PROHIBIT:
117 return -EACCES;
118
119 case FR_ACT_BLACKHOLE:
120 default:
121 return -EINVAL;
122 }
123
124 rcu_read_lock();
125
126 tbl = fib_get_table(rule->fr_net, rule->table);
127 if (tbl)
128 err = fib_table_lookup(tbl, &flp->u.ip4,
129 (struct fib_result *)arg->result,
130 arg->flags);
131
132 rcu_read_unlock();
133 return err;
134}
135
136static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
137{
138
139
140
141 struct fib_result *result = (struct fib_result *) arg->result;
142 if (result->prefixlen <= rule->suppress_prefixlen) {
143 if (!(arg->flags & FIB_LOOKUP_NOREF))
144 fib_info_put(result->fi);
145 return true;
146 }
147 return false;
148}
149
150static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
151{
152 struct fib4_rule *r = (struct fib4_rule *) rule;
153 struct flowi4 *fl4 = &fl->u.ip4;
154 __be32 daddr = fl4->daddr;
155 __be32 saddr = fl4->saddr;
156
157 if (((saddr ^ r->src) & r->srcmask) ||
158 ((daddr ^ r->dst) & r->dstmask))
159 return 0;
160
161 if (r->tos && (r->tos != fl4->flowi4_tos))
162 return 0;
163
164 return 1;
165}
166
167static struct fib_table *fib_empty_table(struct net *net)
168{
169 u32 id;
170
171 for (id = 1; id <= RT_TABLE_MAX; id++)
172 if (fib_get_table(net, id) == NULL)
173 return fib_new_table(net, id);
174 return NULL;
175}
176
177static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
178 FRA_GENERIC_POLICY,
179 [FRA_FLOW] = { .type = NLA_U32 },
180};
181
182static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
183 struct fib_rule_hdr *frh,
184 struct nlattr **tb)
185{
186 struct net *net = sock_net(skb->sk);
187 int err = -EINVAL;
188 struct fib4_rule *rule4 = (struct fib4_rule *) rule;
189
190 if (frh->tos & ~IPTOS_TOS_MASK)
191 goto errout;
192
193
194 err = fib_unmerge(net);
195 if (err)
196 goto errout;
197
198 if (rule->table == RT_TABLE_UNSPEC) {
199 if (rule->action == FR_ACT_TO_TBL) {
200 struct fib_table *table;
201
202 table = fib_empty_table(net);
203 if (table == NULL) {
204 err = -ENOBUFS;
205 goto errout;
206 }
207
208 rule->table = table->tb_id;
209 }
210 }
211
212 if (frh->src_len)
213 rule4->src = nla_get_in_addr(tb[FRA_SRC]);
214
215 if (frh->dst_len)
216 rule4->dst = nla_get_in_addr(tb[FRA_DST]);
217
218#ifdef CONFIG_IP_ROUTE_CLASSID
219 if (tb[FRA_FLOW]) {
220 rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
221 if (rule4->tclassid)
222 net->ipv4.fib_num_tclassid_users++;
223 }
224#endif
225
226 rule4->src_len = frh->src_len;
227 rule4->srcmask = inet_make_mask(rule4->src_len);
228 rule4->dst_len = frh->dst_len;
229 rule4->dstmask = inet_make_mask(rule4->dst_len);
230 rule4->tos = frh->tos;
231
232 net->ipv4.fib_has_custom_rules = true;
233
234 err = 0;
235errout:
236 return err;
237}
238
239static int fib4_rule_delete(struct fib_rule *rule)
240{
241 struct net *net = rule->fr_net;
242 int err;
243
244
245 err = fib_unmerge(net);
246 if (err)
247 goto errout;
248
249#ifdef CONFIG_IP_ROUTE_CLASSID
250 if (((struct fib4_rule *)rule)->tclassid)
251 net->ipv4.fib_num_tclassid_users--;
252#endif
253 net->ipv4.fib_has_custom_rules = true;
254errout:
255 return err;
256}
257
258static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
259 struct nlattr **tb)
260{
261 struct fib4_rule *rule4 = (struct fib4_rule *) rule;
262
263 if (frh->src_len && (rule4->src_len != frh->src_len))
264 return 0;
265
266 if (frh->dst_len && (rule4->dst_len != frh->dst_len))
267 return 0;
268
269 if (frh->tos && (rule4->tos != frh->tos))
270 return 0;
271
272#ifdef CONFIG_IP_ROUTE_CLASSID
273 if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
274 return 0;
275#endif
276
277 if (frh->src_len && (rule4->src != nla_get_in_addr(tb[FRA_SRC])))
278 return 0;
279
280 if (frh->dst_len && (rule4->dst != nla_get_in_addr(tb[FRA_DST])))
281 return 0;
282
283 return 1;
284}
285
286static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
287 struct fib_rule_hdr *frh)
288{
289 struct fib4_rule *rule4 = (struct fib4_rule *) rule;
290
291 frh->dst_len = rule4->dst_len;
292 frh->src_len = rule4->src_len;
293 frh->tos = rule4->tos;
294
295 if ((rule4->dst_len &&
296 nla_put_in_addr(skb, FRA_DST, rule4->dst)) ||
297 (rule4->src_len &&
298 nla_put_in_addr(skb, FRA_SRC, rule4->src)))
299 goto nla_put_failure;
300#ifdef CONFIG_IP_ROUTE_CLASSID
301 if (rule4->tclassid &&
302 nla_put_u32(skb, FRA_FLOW, rule4->tclassid))
303 goto nla_put_failure;
304#endif
305 return 0;
306
307nla_put_failure:
308 return -ENOBUFS;
309}
310
311static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
312{
313 return nla_total_size(4)
314 + nla_total_size(4)
315 + nla_total_size(4);
316}
317
318static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
319{
320 rt_cache_flush(ops->fro_net);
321}
322
323static const struct fib_rules_ops __net_initconst fib4_rules_ops_template = {
324 .family = AF_INET,
325 .rule_size = sizeof(struct fib4_rule),
326 .addr_size = sizeof(u32),
327 .action = fib4_rule_action,
328 .suppress = fib4_rule_suppress,
329 .match = fib4_rule_match,
330 .configure = fib4_rule_configure,
331 .delete = fib4_rule_delete,
332 .compare = fib4_rule_compare,
333 .fill = fib4_rule_fill,
334 .nlmsg_payload = fib4_rule_nlmsg_payload,
335 .flush_cache = fib4_rule_flush_cache,
336 .nlgroup = RTNLGRP_IPV4_RULE,
337 .policy = fib4_rule_policy,
338 .owner = THIS_MODULE,
339};
340
341static int fib_default_rules_init(struct fib_rules_ops *ops)
342{
343 int err;
344
345 err = fib_default_rule_add(ops, 0, RT_TABLE_LOCAL, 0);
346 if (err < 0)
347 return err;
348 err = fib_default_rule_add(ops, 0x7FFE, RT_TABLE_MAIN, 0);
349 if (err < 0)
350 return err;
351 err = fib_default_rule_add(ops, 0x7FFF, RT_TABLE_DEFAULT, 0);
352 if (err < 0)
353 return err;
354 return 0;
355}
356
357int __net_init fib4_rules_init(struct net *net)
358{
359 int err;
360 struct fib_rules_ops *ops;
361
362 ops = fib_rules_register(&fib4_rules_ops_template, net);
363 if (IS_ERR(ops))
364 return PTR_ERR(ops);
365
366 err = fib_default_rules_init(ops);
367 if (err < 0)
368 goto fail;
369 net->ipv4.rules_ops = ops;
370 net->ipv4.fib_has_custom_rules = false;
371 return 0;
372
373fail:
374
375 fib_rules_unregister(ops);
376 return err;
377}
378
379void __net_exit fib4_rules_exit(struct net *net)
380{
381 fib_rules_unregister(net->ipv4.rules_ops);
382}
383