hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/ipv6/fib6_rules.c
....@@ -1,12 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * net/ipv6/fib6_rules.c IPv6 Routing Policy Rules
34 *
45 * Copyright (C)2003-2006 Helsinki University of Technology
56 * Copyright (C)2003-2006 USAGI/WIDE Project
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License as
9
- * published by the Free Software Foundation, version 2.
107 *
118 * Authors
129 * Thomas Graf <tgraf@suug.ch>
....@@ -16,6 +13,7 @@
1613 #include <linux/netdevice.h>
1714 #include <linux/notifier.h>
1815 #include <linux/export.h>
16
+#include <linux/indirect_call_wrapper.h>
1917
2018 #include <net/fib_rules.h>
2119 #include <net/ipv6.h>
....@@ -50,9 +48,10 @@
5048 }
5149 EXPORT_SYMBOL_GPL(fib6_rule_default);
5250
53
-int fib6_rules_dump(struct net *net, struct notifier_block *nb)
51
+int fib6_rules_dump(struct net *net, struct notifier_block *nb,
52
+ struct netlink_ext_ack *extack)
5453 {
55
- return fib_rules_dump(net, nb, AF_INET6);
54
+ return fib_rules_dump(net, nb, AF_INET6, extack);
5655 }
5756
5857 unsigned int fib6_rules_seq_read(struct net *net)
....@@ -61,16 +60,16 @@
6160 }
6261
6362 /* called with rcu lock held; no reference taken on fib6_info */
64
-struct fib6_info *fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
65
- int flags)
63
+int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
64
+ struct fib6_result *res, int flags)
6665 {
67
- struct fib6_info *f6i;
6866 int err;
6967
7068 if (net->ipv6.fib6_has_custom_rules) {
7169 struct fib_lookup_arg arg = {
7270 .lookup_ptr = fib6_table_lookup,
7371 .lookup_data = &oif,
72
+ .result = res,
7473 .flags = FIB_LOOKUP_NOREF,
7574 };
7675
....@@ -78,19 +77,15 @@
7877
7978 err = fib_rules_lookup(net->ipv6.fib6_rules_ops,
8079 flowi6_to_flowi(fl6), flags, &arg);
81
- if (err)
82
- return ERR_PTR(err);
83
-
84
- f6i = arg.result ? : net->ipv6.fib6_null_entry;
8580 } else {
86
- f6i = fib6_table_lookup(net, net->ipv6.fib6_local_tbl,
87
- oif, fl6, flags);
88
- if (!f6i || f6i == net->ipv6.fib6_null_entry)
89
- f6i = fib6_table_lookup(net, net->ipv6.fib6_main_tbl,
90
- oif, fl6, flags);
81
+ err = fib6_table_lookup(net, net->ipv6.fib6_local_tbl, oif,
82
+ fl6, res, flags);
83
+ if (err || res->f6i == net->ipv6.fib6_null_entry)
84
+ err = fib6_table_lookup(net, net->ipv6.fib6_main_tbl,
85
+ oif, fl6, res, flags);
9186 }
9287
93
- return f6i;
88
+ return err;
9489 }
9590
9691 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
....@@ -98,9 +93,11 @@
9893 int flags, pol_lookup_t lookup)
9994 {
10095 if (net->ipv6.fib6_has_custom_rules) {
96
+ struct fib6_result res = {};
10197 struct fib_lookup_arg arg = {
10298 .lookup_ptr = lookup,
10399 .lookup_data = skb,
100
+ .result = &res,
104101 .flags = FIB_LOOKUP_NOREF,
105102 };
106103
....@@ -110,22 +107,25 @@
110107 fib_rules_lookup(net->ipv6.fib6_rules_ops,
111108 flowi6_to_flowi(fl6), flags, &arg);
112109
113
- if (arg.result)
114
- return arg.result;
110
+ if (res.rt6)
111
+ return &res.rt6->dst;
115112 } else {
116113 struct rt6_info *rt;
117114
118
- rt = lookup(net, net->ipv6.fib6_local_tbl, fl6, skb, flags);
115
+ rt = pol_lookup_func(lookup,
116
+ net, net->ipv6.fib6_local_tbl, fl6, skb, flags);
119117 if (rt != net->ipv6.ip6_null_entry && rt->dst.error != -EAGAIN)
120118 return &rt->dst;
121
- ip6_rt_put(rt);
122
- rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, skb, flags);
119
+ ip6_rt_put_flags(rt, flags);
120
+ rt = pol_lookup_func(lookup,
121
+ net, net->ipv6.fib6_main_tbl, fl6, skb, flags);
123122 if (rt->dst.error != -EAGAIN)
124123 return &rt->dst;
125
- ip6_rt_put(rt);
124
+ ip6_rt_put_flags(rt, flags);
126125 }
127126
128
- dst_hold(&net->ipv6.ip6_null_entry->dst);
127
+ if (!(flags & RT6_LOOKUP_F_DST_NOREF))
128
+ dst_hold(&net->ipv6.ip6_null_entry->dst);
129129 return &net->ipv6.ip6_null_entry->dst;
130130 }
131131
....@@ -157,11 +157,11 @@
157157 static int fib6_rule_action_alt(struct fib_rule *rule, struct flowi *flp,
158158 int flags, struct fib_lookup_arg *arg)
159159 {
160
+ struct fib6_result *res = arg->result;
160161 struct flowi6 *flp6 = &flp->u.ip6;
161162 struct net *net = rule->fr_net;
162163 struct fib6_table *table;
163
- struct fib6_info *f6i;
164
- int err = -EAGAIN, *oif;
164
+ int err, *oif;
165165 u32 tb_id;
166166
167167 switch (rule->action) {
....@@ -182,14 +182,12 @@
182182 return -EAGAIN;
183183
184184 oif = (int *)arg->lookup_data;
185
- f6i = fib6_table_lookup(net, table, *oif, flp6, flags);
186
- if (f6i != net->ipv6.fib6_null_entry) {
185
+ err = fib6_table_lookup(net, table, *oif, flp6, res, flags);
186
+ if (!err && res->f6i != net->ipv6.fib6_null_entry)
187187 err = fib6_rule_saddr(net, rule, flags, flp6,
188
- fib6_info_nh_dev(f6i));
189
-
190
- if (likely(!err))
191
- arg->result = f6i;
192
- }
188
+ res->nh->fib_nh_dev);
189
+ else
190
+ err = -EAGAIN;
193191
194192 return err;
195193 }
....@@ -197,6 +195,7 @@
197195 static int __fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
198196 int flags, struct fib_lookup_arg *arg)
199197 {
198
+ struct fib6_result *res = arg->result;
200199 struct flowi6 *flp6 = &flp->u.ip6;
201200 struct rt6_info *rt = NULL;
202201 struct fib6_table *table;
....@@ -230,7 +229,8 @@
230229 goto out;
231230 }
232231
233
- rt = lookup(net, table, flp6, arg->lookup_data, flags);
232
+ rt = pol_lookup_func(lookup,
233
+ net, table, flp6, arg->lookup_data, flags);
234234 if (rt != net->ipv6.ip6_null_entry) {
235235 err = fib6_rule_saddr(net, rule, flags, flp6,
236236 ip6_dst_idev(&rt->dst)->dev);
....@@ -243,20 +243,22 @@
243243 goto out;
244244 }
245245 again:
246
- ip6_rt_put(rt);
246
+ ip6_rt_put_flags(rt, flags);
247247 err = -EAGAIN;
248248 rt = NULL;
249249 goto out;
250250
251251 discard_pkt:
252
- dst_hold(&rt->dst);
252
+ if (!(flags & RT6_LOOKUP_F_DST_NOREF))
253
+ dst_hold(&rt->dst);
253254 out:
254
- arg->result = rt;
255
+ res->rt6 = rt;
255256 return err;
256257 }
257258
258
-static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
259
- int flags, struct fib_lookup_arg *arg)
259
+INDIRECT_CALLABLE_SCOPE int fib6_rule_action(struct fib_rule *rule,
260
+ struct flowi *flp, int flags,
261
+ struct fib_lookup_arg *arg)
260262 {
261263 if (arg->lookup_ptr == fib6_table_lookup)
262264 return fib6_rule_action_alt(rule, flp, flags, arg);
....@@ -264,10 +266,16 @@
264266 return __fib6_rule_action(rule, flp, flags, arg);
265267 }
266268
267
-static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
269
+INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule,
270
+ int flags,
271
+ struct fib_lookup_arg *arg)
268272 {
269
- struct rt6_info *rt = (struct rt6_info *) arg->result;
273
+ struct fib6_result *res = arg->result;
274
+ struct rt6_info *rt = res->rt6;
270275 struct net_device *dev = NULL;
276
+
277
+ if (!rt)
278
+ return false;
271279
272280 if (rt->rt6i_idev)
273281 dev = rt->rt6i_idev->dev;
....@@ -287,11 +295,12 @@
287295 return false;
288296
289297 suppress_route:
290
- ip6_rt_put(rt);
298
+ ip6_rt_put_flags(rt, flags);
291299 return true;
292300 }
293301
294
-static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
302
+INDIRECT_CALLABLE_SCOPE int fib6_rule_match(struct fib_rule *rule,
303
+ struct flowi *fl, int flags)
295304 {
296305 struct fib6_rule *r = (struct fib6_rule *) rule;
297306 struct flowi6 *fl6 = &fl->u.ip6;