xref: /kernel/linux/linux-5.10/net/ipv4/fib_rules.c (revision 8c2ecf20)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * INET		An implementation of the TCP/IP protocol suite for the LINUX
4 *		operating system.  INET is implemented using the  BSD Socket
5 *		interface as the means of communication with the user level.
6 *
7 *		IPv4 Forwarding Information Base: policy rules.
8 *
9 * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 *		Thomas Graf <tgraf@suug.ch>
11 *
12 * Fixes:
13 *		Rani Assaf	:	local_rule cannot be deleted
14 *		Marc Boucher	:	routing by fwmark
15 */
16
17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/netdevice.h>
20#include <linux/netlink.h>
21#include <linux/inetdevice.h>
22#include <linux/init.h>
23#include <linux/list.h>
24#include <linux/rcupdate.h>
25#include <linux/export.h>
26#include <net/ip.h>
27#include <net/route.h>
28#include <net/tcp.h>
29#include <net/ip_fib.h>
30#include <net/nexthop.h>
31#include <net/fib_rules.h>
32#include <linux/indirect_call_wrapper.h>
33
34struct fib4_rule {
35	struct fib_rule		common;
36	u8			dst_len;
37	u8			src_len;
38	u8			tos;
39	__be32			src;
40	__be32			srcmask;
41	__be32			dst;
42	__be32			dstmask;
43#ifdef CONFIG_IP_ROUTE_CLASSID
44	u32			tclassid;
45#endif
46};
47
48static bool fib4_rule_matchall(const struct fib_rule *rule)
49{
50	struct fib4_rule *r = container_of(rule, struct fib4_rule, common);
51
52	if (r->dst_len || r->src_len || r->tos)
53		return false;
54	return fib_rule_matchall(rule);
55}
56
57bool fib4_rule_default(const struct fib_rule *rule)
58{
59	if (!fib4_rule_matchall(rule) || rule->action != FR_ACT_TO_TBL ||
60	    rule->l3mdev)
61		return false;
62	if (rule->table != RT_TABLE_LOCAL && rule->table != RT_TABLE_MAIN &&
63	    rule->table != RT_TABLE_DEFAULT)
64		return false;
65	return true;
66}
67EXPORT_SYMBOL_GPL(fib4_rule_default);
68
69int fib4_rules_dump(struct net *net, struct notifier_block *nb,
70		    struct netlink_ext_ack *extack)
71{
72	return fib_rules_dump(net, nb, AF_INET, extack);
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,
81		 struct fib_result *res, unsigned int flags)
82{
83	struct fib_lookup_arg arg = {
84		.result = res,
85		.flags = flags,
86	};
87	int err;
88
89	/* update flow if oif or iif point to device enslaved to l3mdev */
90	l3mdev_update_flow(net, flowi4_to_flowi(flp));
91
92	err = fib_rules_lookup(net->ipv4.rules_ops, flowi4_to_flowi(flp), 0, &arg);
93#ifdef CONFIG_IP_ROUTE_CLASSID
94	if (arg.rule)
95		res->tclassid = ((struct fib4_rule *)arg.rule)->tclassid;
96	else
97		res->tclassid = 0;
98#endif
99
100	if (err == -ESRCH)
101		err = -ENETUNREACH;
102
103	return err;
104}
105EXPORT_SYMBOL_GPL(__fib_lookup);
106
107INDIRECT_CALLABLE_SCOPE int fib4_rule_action(struct fib_rule *rule,
108					     struct flowi *flp, int flags,
109					     struct fib_lookup_arg *arg)
110{
111	int err = -EAGAIN;
112	struct fib_table *tbl;
113	u32 tb_id;
114
115	switch (rule->action) {
116	case FR_ACT_TO_TBL:
117		break;
118
119	case FR_ACT_UNREACHABLE:
120		return -ENETUNREACH;
121
122	case FR_ACT_PROHIBIT:
123		return -EACCES;
124
125	case FR_ACT_BLACKHOLE:
126	default:
127		return -EINVAL;
128	}
129
130	rcu_read_lock();
131
132	tb_id = fib_rule_get_table(rule, arg);
133	tbl = fib_get_table(rule->fr_net, tb_id);
134	if (tbl)
135		err = fib_table_lookup(tbl, &flp->u.ip4,
136				       (struct fib_result *)arg->result,
137				       arg->flags);
138
139	rcu_read_unlock();
140	return err;
141}
142
143INDIRECT_CALLABLE_SCOPE bool fib4_rule_suppress(struct fib_rule *rule,
144						int flags,
145						struct fib_lookup_arg *arg)
146{
147	struct fib_result *result = (struct fib_result *) arg->result;
148	struct net_device *dev = NULL;
149
150	if (result->fi) {
151		struct fib_nh_common *nhc = fib_info_nhc(result->fi, 0);
152
153		dev = nhc->nhc_dev;
154	}
155
156	/* do not accept result if the route does
157	 * not meet the required prefix length
158	 */
159	if (result->prefixlen <= rule->suppress_prefixlen)
160		goto suppress_route;
161
162	/* do not accept result if the route uses a device
163	 * belonging to a forbidden interface group
164	 */
165	if (rule->suppress_ifgroup != -1 && dev && dev->group == rule->suppress_ifgroup)
166		goto suppress_route;
167
168	return false;
169
170suppress_route:
171	if (!(arg->flags & FIB_LOOKUP_NOREF))
172		fib_info_put(result->fi);
173	return true;
174}
175
176INDIRECT_CALLABLE_SCOPE int fib4_rule_match(struct fib_rule *rule,
177					    struct flowi *fl, int flags)
178{
179	struct fib4_rule *r = (struct fib4_rule *) rule;
180	struct flowi4 *fl4 = &fl->u.ip4;
181	__be32 daddr = fl4->daddr;
182	__be32 saddr = fl4->saddr;
183
184	if (((saddr ^ r->src) & r->srcmask) ||
185	    ((daddr ^ r->dst) & r->dstmask))
186		return 0;
187
188	if (r->tos && (r->tos != fl4->flowi4_tos))
189		return 0;
190
191	if (rule->ip_proto && (rule->ip_proto != fl4->flowi4_proto))
192		return 0;
193
194	if (fib_rule_port_range_set(&rule->sport_range) &&
195	    !fib_rule_port_inrange(&rule->sport_range, fl4->fl4_sport))
196		return 0;
197
198	if (fib_rule_port_range_set(&rule->dport_range) &&
199	    !fib_rule_port_inrange(&rule->dport_range, fl4->fl4_dport))
200		return 0;
201
202	return 1;
203}
204
205static struct fib_table *fib_empty_table(struct net *net)
206{
207	u32 id = 1;
208
209	while (1) {
210		if (!fib_get_table(net, id))
211			return fib_new_table(net, id);
212
213		if (id++ == RT_TABLE_MAX)
214			break;
215	}
216	return NULL;
217}
218
219static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
220	FRA_GENERIC_POLICY,
221	[FRA_FLOW]	= { .type = NLA_U32 },
222};
223
224static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
225			       struct fib_rule_hdr *frh,
226			       struct nlattr **tb,
227			       struct netlink_ext_ack *extack)
228{
229	struct net *net = sock_net(skb->sk);
230	int err = -EINVAL;
231	struct fib4_rule *rule4 = (struct fib4_rule *) rule;
232
233	if (frh->tos & ~IPTOS_TOS_MASK) {
234		NL_SET_ERR_MSG(extack, "Invalid tos");
235		goto errout;
236	}
237
238	/* split local/main if they are not already split */
239	err = fib_unmerge(net);
240	if (err)
241		goto errout;
242
243	if (rule->table == RT_TABLE_UNSPEC && !rule->l3mdev) {
244		if (rule->action == FR_ACT_TO_TBL) {
245			struct fib_table *table;
246
247			table = fib_empty_table(net);
248			if (!table) {
249				err = -ENOBUFS;
250				goto errout;
251			}
252
253			rule->table = table->tb_id;
254		}
255	}
256
257	if (frh->src_len)
258		rule4->src = nla_get_in_addr(tb[FRA_SRC]);
259
260	if (frh->dst_len)
261		rule4->dst = nla_get_in_addr(tb[FRA_DST]);
262
263#ifdef CONFIG_IP_ROUTE_CLASSID
264	if (tb[FRA_FLOW]) {
265		rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
266		if (rule4->tclassid)
267			atomic_inc(&net->ipv4.fib_num_tclassid_users);
268	}
269#endif
270
271	if (fib_rule_requires_fldissect(rule))
272		net->ipv4.fib_rules_require_fldissect++;
273
274	rule4->src_len = frh->src_len;
275	rule4->srcmask = inet_make_mask(rule4->src_len);
276	rule4->dst_len = frh->dst_len;
277	rule4->dstmask = inet_make_mask(rule4->dst_len);
278	rule4->tos = frh->tos;
279
280	net->ipv4.fib_has_custom_rules = true;
281
282	err = 0;
283errout:
284	return err;
285}
286
287static int fib4_rule_delete(struct fib_rule *rule)
288{
289	struct net *net = rule->fr_net;
290	int err;
291
292	/* split local/main if they are not already split */
293	err = fib_unmerge(net);
294	if (err)
295		goto errout;
296
297#ifdef CONFIG_IP_ROUTE_CLASSID
298	if (((struct fib4_rule *)rule)->tclassid)
299		atomic_dec(&net->ipv4.fib_num_tclassid_users);
300#endif
301	net->ipv4.fib_has_custom_rules = true;
302
303	if (net->ipv4.fib_rules_require_fldissect &&
304	    fib_rule_requires_fldissect(rule))
305		net->ipv4.fib_rules_require_fldissect--;
306errout:
307	return err;
308}
309
310static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
311			     struct nlattr **tb)
312{
313	struct fib4_rule *rule4 = (struct fib4_rule *) rule;
314
315	if (frh->src_len && (rule4->src_len != frh->src_len))
316		return 0;
317
318	if (frh->dst_len && (rule4->dst_len != frh->dst_len))
319		return 0;
320
321	if (frh->tos && (rule4->tos != frh->tos))
322		return 0;
323
324#ifdef CONFIG_IP_ROUTE_CLASSID
325	if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
326		return 0;
327#endif
328
329	if (frh->src_len && (rule4->src != nla_get_in_addr(tb[FRA_SRC])))
330		return 0;
331
332	if (frh->dst_len && (rule4->dst != nla_get_in_addr(tb[FRA_DST])))
333		return 0;
334
335	return 1;
336}
337
338static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
339			  struct fib_rule_hdr *frh)
340{
341	struct fib4_rule *rule4 = (struct fib4_rule *) rule;
342
343	frh->dst_len = rule4->dst_len;
344	frh->src_len = rule4->src_len;
345	frh->tos = rule4->tos;
346
347	if ((rule4->dst_len &&
348	     nla_put_in_addr(skb, FRA_DST, rule4->dst)) ||
349	    (rule4->src_len &&
350	     nla_put_in_addr(skb, FRA_SRC, rule4->src)))
351		goto nla_put_failure;
352#ifdef CONFIG_IP_ROUTE_CLASSID
353	if (rule4->tclassid &&
354	    nla_put_u32(skb, FRA_FLOW, rule4->tclassid))
355		goto nla_put_failure;
356#endif
357	return 0;
358
359nla_put_failure:
360	return -ENOBUFS;
361}
362
363static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
364{
365	return nla_total_size(4) /* dst */
366	       + nla_total_size(4) /* src */
367	       + nla_total_size(4); /* flow */
368}
369
370static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
371{
372	rt_cache_flush(ops->fro_net);
373}
374
375static const struct fib_rules_ops __net_initconst fib4_rules_ops_template = {
376	.family		= AF_INET,
377	.rule_size	= sizeof(struct fib4_rule),
378	.addr_size	= sizeof(u32),
379	.action		= fib4_rule_action,
380	.suppress	= fib4_rule_suppress,
381	.match		= fib4_rule_match,
382	.configure	= fib4_rule_configure,
383	.delete		= fib4_rule_delete,
384	.compare	= fib4_rule_compare,
385	.fill		= fib4_rule_fill,
386	.nlmsg_payload	= fib4_rule_nlmsg_payload,
387	.flush_cache	= fib4_rule_flush_cache,
388	.nlgroup	= RTNLGRP_IPV4_RULE,
389	.policy		= fib4_rule_policy,
390	.owner		= THIS_MODULE,
391};
392
393static int fib_default_rules_init(struct fib_rules_ops *ops)
394{
395	int err;
396
397	err = fib_default_rule_add(ops, 0, RT_TABLE_LOCAL, 0);
398	if (err < 0)
399		return err;
400	err = fib_default_rule_add(ops, 0x7FFE, RT_TABLE_MAIN, 0);
401	if (err < 0)
402		return err;
403	err = fib_default_rule_add(ops, 0x7FFF, RT_TABLE_DEFAULT, 0);
404	if (err < 0)
405		return err;
406	return 0;
407}
408
409int __net_init fib4_rules_init(struct net *net)
410{
411	int err;
412	struct fib_rules_ops *ops;
413
414	ops = fib_rules_register(&fib4_rules_ops_template, net);
415	if (IS_ERR(ops))
416		return PTR_ERR(ops);
417
418	err = fib_default_rules_init(ops);
419	if (err < 0)
420		goto fail;
421	net->ipv4.rules_ops = ops;
422	net->ipv4.fib_has_custom_rules = false;
423	net->ipv4.fib_rules_require_fldissect = 0;
424	return 0;
425
426fail:
427	/* also cleans all rules already added */
428	fib_rules_unregister(ops);
429	return err;
430}
431
432void __net_exit fib4_rules_exit(struct net *net)
433{
434	fib_rules_unregister(net->ipv4.rules_ops);
435}
436