Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/core/fib_rules.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* net/core/fib_rules.c Generic Routing Rules
4
*
5
* Authors: Thomas Graf <[email protected]>
6
*/
7
8
#include <linux/types.h>
9
#include <linux/kernel.h>
10
#include <linux/slab.h>
11
#include <linux/list.h>
12
#include <linux/module.h>
13
#include <net/net_namespace.h>
14
#include <net/inet_dscp.h>
15
#include <net/sock.h>
16
#include <net/fib_rules.h>
17
#include <net/ip_tunnels.h>
18
#include <linux/indirect_call_wrapper.h>
19
20
#if defined(CONFIG_IPV6) && defined(CONFIG_IPV6_MULTIPLE_TABLES)
21
#ifdef CONFIG_IP_MULTIPLE_TABLES
22
#define INDIRECT_CALL_MT(f, f2, f1, ...) \
23
INDIRECT_CALL_INET(f, f2, f1, __VA_ARGS__)
24
#else
25
#define INDIRECT_CALL_MT(f, f2, f1, ...) INDIRECT_CALL_1(f, f2, __VA_ARGS__)
26
#endif
27
#elif defined(CONFIG_IP_MULTIPLE_TABLES)
28
#define INDIRECT_CALL_MT(f, f2, f1, ...) INDIRECT_CALL_1(f, f1, __VA_ARGS__)
29
#else
30
#define INDIRECT_CALL_MT(f, f2, f1, ...) f(__VA_ARGS__)
31
#endif
32
33
static const struct fib_kuid_range fib_kuid_range_unset = {
34
KUIDT_INIT(0),
35
KUIDT_INIT(~0),
36
};
37
38
bool fib_rule_matchall(const struct fib_rule *rule)
39
{
40
if (READ_ONCE(rule->iifindex) || READ_ONCE(rule->oifindex) ||
41
rule->mark || rule->tun_id || rule->flags)
42
return false;
43
if (rule->suppress_ifgroup != -1 || rule->suppress_prefixlen != -1)
44
return false;
45
if (!uid_eq(rule->uid_range.start, fib_kuid_range_unset.start) ||
46
!uid_eq(rule->uid_range.end, fib_kuid_range_unset.end))
47
return false;
48
if (fib_rule_port_range_set(&rule->sport_range))
49
return false;
50
if (fib_rule_port_range_set(&rule->dport_range))
51
return false;
52
return true;
53
}
54
EXPORT_SYMBOL_GPL(fib_rule_matchall);
55
56
int fib_default_rule_add(struct fib_rules_ops *ops,
57
u32 pref, u32 table)
58
{
59
struct fib_rule *r;
60
61
r = kzalloc(ops->rule_size, GFP_KERNEL_ACCOUNT);
62
if (r == NULL)
63
return -ENOMEM;
64
65
refcount_set(&r->refcnt, 1);
66
r->action = FR_ACT_TO_TBL;
67
r->pref = pref;
68
r->table = table;
69
r->proto = RTPROT_KERNEL;
70
r->fr_net = ops->fro_net;
71
r->uid_range = fib_kuid_range_unset;
72
73
r->suppress_prefixlen = -1;
74
r->suppress_ifgroup = -1;
75
76
/* The lock is not required here, the list in unreachable
77
* at the moment this function is called */
78
list_add_tail(&r->list, &ops->rules_list);
79
return 0;
80
}
81
EXPORT_SYMBOL(fib_default_rule_add);
82
83
static u32 fib_default_rule_pref(struct fib_rules_ops *ops)
84
{
85
struct list_head *pos;
86
struct fib_rule *rule;
87
88
if (!list_empty(&ops->rules_list)) {
89
pos = ops->rules_list.next;
90
if (pos->next != &ops->rules_list) {
91
rule = list_entry(pos->next, struct fib_rule, list);
92
if (rule->pref)
93
return rule->pref - 1;
94
}
95
}
96
97
return 0;
98
}
99
100
static void notify_rule_change(int event, struct fib_rule *rule,
101
struct fib_rules_ops *ops, struct nlmsghdr *nlh,
102
u32 pid);
103
104
static struct fib_rules_ops *lookup_rules_ops(const struct net *net,
105
int family)
106
{
107
struct fib_rules_ops *ops;
108
109
rcu_read_lock();
110
list_for_each_entry_rcu(ops, &net->rules_ops, list) {
111
if (ops->family == family) {
112
if (!try_module_get(ops->owner))
113
ops = NULL;
114
rcu_read_unlock();
115
return ops;
116
}
117
}
118
rcu_read_unlock();
119
120
return NULL;
121
}
122
123
static void rules_ops_put(struct fib_rules_ops *ops)
124
{
125
if (ops)
126
module_put(ops->owner);
127
}
128
129
static void flush_route_cache(struct fib_rules_ops *ops)
130
{
131
if (ops->flush_cache)
132
ops->flush_cache(ops);
133
}
134
135
static int __fib_rules_register(struct fib_rules_ops *ops)
136
{
137
int err = -EEXIST;
138
struct fib_rules_ops *o;
139
struct net *net;
140
141
net = ops->fro_net;
142
143
if (ops->rule_size < sizeof(struct fib_rule))
144
return -EINVAL;
145
146
if (ops->match == NULL || ops->configure == NULL ||
147
ops->compare == NULL || ops->fill == NULL ||
148
ops->action == NULL)
149
return -EINVAL;
150
151
spin_lock(&net->rules_mod_lock);
152
list_for_each_entry(o, &net->rules_ops, list)
153
if (ops->family == o->family)
154
goto errout;
155
156
list_add_tail_rcu(&ops->list, &net->rules_ops);
157
err = 0;
158
errout:
159
spin_unlock(&net->rules_mod_lock);
160
161
return err;
162
}
163
164
struct fib_rules_ops *
165
fib_rules_register(const struct fib_rules_ops *tmpl, struct net *net)
166
{
167
struct fib_rules_ops *ops;
168
int err;
169
170
ops = kmemdup(tmpl, sizeof(*ops), GFP_KERNEL);
171
if (ops == NULL)
172
return ERR_PTR(-ENOMEM);
173
174
INIT_LIST_HEAD(&ops->rules_list);
175
ops->fro_net = net;
176
177
err = __fib_rules_register(ops);
178
if (err) {
179
kfree(ops);
180
ops = ERR_PTR(err);
181
}
182
183
return ops;
184
}
185
EXPORT_SYMBOL_GPL(fib_rules_register);
186
187
static void fib_rules_cleanup_ops(struct fib_rules_ops *ops)
188
{
189
struct fib_rule *rule, *tmp;
190
191
list_for_each_entry_safe(rule, tmp, &ops->rules_list, list) {
192
list_del_rcu(&rule->list);
193
if (ops->delete)
194
ops->delete(rule);
195
fib_rule_put(rule);
196
}
197
}
198
199
void fib_rules_unregister(struct fib_rules_ops *ops)
200
{
201
struct net *net = ops->fro_net;
202
203
spin_lock(&net->rules_mod_lock);
204
list_del_rcu(&ops->list);
205
spin_unlock(&net->rules_mod_lock);
206
207
fib_rules_cleanup_ops(ops);
208
kfree_rcu(ops, rcu);
209
}
210
EXPORT_SYMBOL_GPL(fib_rules_unregister);
211
212
static int uid_range_set(struct fib_kuid_range *range)
213
{
214
return uid_valid(range->start) && uid_valid(range->end);
215
}
216
217
static struct fib_kuid_range nla_get_kuid_range(struct nlattr **tb)
218
{
219
struct fib_rule_uid_range *in;
220
struct fib_kuid_range out;
221
222
in = (struct fib_rule_uid_range *)nla_data(tb[FRA_UID_RANGE]);
223
224
out.start = make_kuid(current_user_ns(), in->start);
225
out.end = make_kuid(current_user_ns(), in->end);
226
227
return out;
228
}
229
230
static int nla_put_uid_range(struct sk_buff *skb, struct fib_kuid_range *range)
231
{
232
struct fib_rule_uid_range out = {
233
from_kuid_munged(current_user_ns(), range->start),
234
from_kuid_munged(current_user_ns(), range->end)
235
};
236
237
return nla_put(skb, FRA_UID_RANGE, sizeof(out), &out);
238
}
239
240
static int nla_get_port_range(struct nlattr *pattr,
241
struct fib_rule_port_range *port_range)
242
{
243
const struct fib_rule_port_range *pr = nla_data(pattr);
244
245
if (!fib_rule_port_range_valid(pr))
246
return -EINVAL;
247
248
port_range->start = pr->start;
249
port_range->end = pr->end;
250
251
return 0;
252
}
253
254
static int nla_put_port_range(struct sk_buff *skb, int attrtype,
255
struct fib_rule_port_range *range)
256
{
257
return nla_put(skb, attrtype, sizeof(*range), range);
258
}
259
260
static bool fib_rule_iif_match(const struct fib_rule *rule, int iifindex,
261
const struct flowi *fl)
262
{
263
u8 iif_is_l3_master = READ_ONCE(rule->iif_is_l3_master);
264
265
return iif_is_l3_master ? l3mdev_fib_rule_iif_match(fl, iifindex) :
266
fl->flowi_iif == iifindex;
267
}
268
269
static bool fib_rule_oif_match(const struct fib_rule *rule, int oifindex,
270
const struct flowi *fl)
271
{
272
u8 oif_is_l3_master = READ_ONCE(rule->oif_is_l3_master);
273
274
return oif_is_l3_master ? l3mdev_fib_rule_oif_match(fl, oifindex) :
275
fl->flowi_oif == oifindex;
276
}
277
278
static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
279
struct flowi *fl, int flags,
280
struct fib_lookup_arg *arg)
281
{
282
int iifindex, oifindex, ret = 0;
283
284
iifindex = READ_ONCE(rule->iifindex);
285
if (iifindex && !fib_rule_iif_match(rule, iifindex, fl))
286
goto out;
287
288
oifindex = READ_ONCE(rule->oifindex);
289
if (oifindex && !fib_rule_oif_match(rule, oifindex, fl))
290
goto out;
291
292
if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask)
293
goto out;
294
295
if (rule->tun_id && (rule->tun_id != fl->flowi_tun_key.tun_id))
296
goto out;
297
298
if (rule->l3mdev && !l3mdev_fib_rule_match(rule->fr_net, fl, arg))
299
goto out;
300
301
if (uid_lt(fl->flowi_uid, rule->uid_range.start) ||
302
uid_gt(fl->flowi_uid, rule->uid_range.end))
303
goto out;
304
305
ret = INDIRECT_CALL_MT(ops->match,
306
fib6_rule_match,
307
fib4_rule_match,
308
rule, fl, flags);
309
out:
310
return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
311
}
312
313
int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
314
int flags, struct fib_lookup_arg *arg)
315
{
316
struct fib_rule *rule;
317
int err;
318
319
rcu_read_lock();
320
321
list_for_each_entry_rcu(rule, &ops->rules_list, list) {
322
jumped:
323
if (!fib_rule_match(rule, ops, fl, flags, arg))
324
continue;
325
326
if (rule->action == FR_ACT_GOTO) {
327
struct fib_rule *target;
328
329
target = rcu_dereference(rule->ctarget);
330
if (target == NULL) {
331
continue;
332
} else {
333
rule = target;
334
goto jumped;
335
}
336
} else if (rule->action == FR_ACT_NOP)
337
continue;
338
else
339
err = INDIRECT_CALL_MT(ops->action,
340
fib6_rule_action,
341
fib4_rule_action,
342
rule, fl, flags, arg);
343
344
if (!err && ops->suppress && INDIRECT_CALL_MT(ops->suppress,
345
fib6_rule_suppress,
346
fib4_rule_suppress,
347
rule, flags, arg))
348
continue;
349
350
if (err != -EAGAIN) {
351
if ((arg->flags & FIB_LOOKUP_NOREF) ||
352
likely(refcount_inc_not_zero(&rule->refcnt))) {
353
arg->rule = rule;
354
goto out;
355
}
356
break;
357
}
358
}
359
360
err = -ESRCH;
361
out:
362
rcu_read_unlock();
363
364
return err;
365
}
366
EXPORT_SYMBOL_GPL(fib_rules_lookup);
367
368
static int call_fib_rule_notifier(struct notifier_block *nb,
369
enum fib_event_type event_type,
370
struct fib_rule *rule, int family,
371
struct netlink_ext_ack *extack)
372
{
373
struct fib_rule_notifier_info info = {
374
.info.family = family,
375
.info.extack = extack,
376
.rule = rule,
377
};
378
379
return call_fib_notifier(nb, event_type, &info.info);
380
}
381
382
static int call_fib_rule_notifiers(struct net *net,
383
enum fib_event_type event_type,
384
struct fib_rule *rule,
385
struct fib_rules_ops *ops,
386
struct netlink_ext_ack *extack)
387
{
388
struct fib_rule_notifier_info info = {
389
.info.family = ops->family,
390
.info.extack = extack,
391
.rule = rule,
392
};
393
394
ASSERT_RTNL_NET(net);
395
396
/* Paired with READ_ONCE() in fib_rules_seq() */
397
WRITE_ONCE(ops->fib_rules_seq, ops->fib_rules_seq + 1);
398
return call_fib_notifiers(net, event_type, &info.info);
399
}
400
401
/* Called with rcu_read_lock() */
402
int fib_rules_dump(struct net *net, struct notifier_block *nb, int family,
403
struct netlink_ext_ack *extack)
404
{
405
struct fib_rules_ops *ops;
406
struct fib_rule *rule;
407
int err = 0;
408
409
ops = lookup_rules_ops(net, family);
410
if (!ops)
411
return -EAFNOSUPPORT;
412
list_for_each_entry_rcu(rule, &ops->rules_list, list) {
413
err = call_fib_rule_notifier(nb, FIB_EVENT_RULE_ADD,
414
rule, family, extack);
415
if (err)
416
break;
417
}
418
rules_ops_put(ops);
419
420
return err;
421
}
422
EXPORT_SYMBOL_GPL(fib_rules_dump);
423
424
unsigned int fib_rules_seq_read(const struct net *net, int family)
425
{
426
unsigned int fib_rules_seq;
427
struct fib_rules_ops *ops;
428
429
ops = lookup_rules_ops(net, family);
430
if (!ops)
431
return 0;
432
/* Paired with WRITE_ONCE() in call_fib_rule_notifiers() */
433
fib_rules_seq = READ_ONCE(ops->fib_rules_seq);
434
rules_ops_put(ops);
435
436
return fib_rules_seq;
437
}
438
EXPORT_SYMBOL_GPL(fib_rules_seq_read);
439
440
static struct fib_rule *rule_find(struct fib_rules_ops *ops,
441
struct fib_rule_hdr *frh,
442
struct nlattr **tb,
443
struct fib_rule *rule,
444
bool user_priority)
445
{
446
struct fib_rule *r;
447
448
list_for_each_entry(r, &ops->rules_list, list) {
449
if (rule->action && r->action != rule->action)
450
continue;
451
452
if (rule->table && r->table != rule->table)
453
continue;
454
455
if (user_priority && r->pref != rule->pref)
456
continue;
457
458
if (rule->iifname[0] &&
459
memcmp(r->iifname, rule->iifname, IFNAMSIZ))
460
continue;
461
462
if (rule->oifname[0] &&
463
memcmp(r->oifname, rule->oifname, IFNAMSIZ))
464
continue;
465
466
if (rule->mark && r->mark != rule->mark)
467
continue;
468
469
if (rule->suppress_ifgroup != -1 &&
470
r->suppress_ifgroup != rule->suppress_ifgroup)
471
continue;
472
473
if (rule->suppress_prefixlen != -1 &&
474
r->suppress_prefixlen != rule->suppress_prefixlen)
475
continue;
476
477
if (rule->mark_mask && r->mark_mask != rule->mark_mask)
478
continue;
479
480
if (rule->tun_id && r->tun_id != rule->tun_id)
481
continue;
482
483
if (rule->l3mdev && r->l3mdev != rule->l3mdev)
484
continue;
485
486
if (uid_range_set(&rule->uid_range) &&
487
(!uid_eq(r->uid_range.start, rule->uid_range.start) ||
488
!uid_eq(r->uid_range.end, rule->uid_range.end)))
489
continue;
490
491
if (rule->ip_proto && r->ip_proto != rule->ip_proto)
492
continue;
493
494
if (rule->proto && r->proto != rule->proto)
495
continue;
496
497
if (fib_rule_port_range_set(&rule->sport_range) &&
498
!fib_rule_port_range_compare(&r->sport_range,
499
&rule->sport_range))
500
continue;
501
502
if (rule->sport_mask && r->sport_mask != rule->sport_mask)
503
continue;
504
505
if (fib_rule_port_range_set(&rule->dport_range) &&
506
!fib_rule_port_range_compare(&r->dport_range,
507
&rule->dport_range))
508
continue;
509
510
if (rule->dport_mask && r->dport_mask != rule->dport_mask)
511
continue;
512
513
if (!ops->compare(r, frh, tb))
514
continue;
515
return r;
516
}
517
518
return NULL;
519
}
520
521
#ifdef CONFIG_NET_L3_MASTER_DEV
522
static int fib_nl2rule_l3mdev(struct nlattr *nla, struct fib_rule *nlrule,
523
struct netlink_ext_ack *extack)
524
{
525
nlrule->l3mdev = nla_get_u8(nla);
526
if (nlrule->l3mdev != 1) {
527
NL_SET_ERR_MSG(extack, "Invalid l3mdev attribute");
528
return -1;
529
}
530
531
return 0;
532
}
533
#else
534
static int fib_nl2rule_l3mdev(struct nlattr *nla, struct fib_rule *nlrule,
535
struct netlink_ext_ack *extack)
536
{
537
NL_SET_ERR_MSG(extack, "l3mdev support is not enabled in kernel");
538
return -1;
539
}
540
#endif
541
542
static int fib_nl2rule_port_mask(const struct nlattr *mask_attr,
543
const struct fib_rule_port_range *range,
544
u16 *port_mask,
545
struct netlink_ext_ack *extack)
546
{
547
if (!fib_rule_port_range_valid(range)) {
548
NL_SET_ERR_MSG_ATTR(extack, mask_attr,
549
"Cannot specify port mask without port value");
550
return -EINVAL;
551
}
552
553
if (fib_rule_port_is_range(range)) {
554
NL_SET_ERR_MSG_ATTR(extack, mask_attr,
555
"Cannot specify port mask for port range");
556
return -EINVAL;
557
}
558
559
if (range->start & ~nla_get_u16(mask_attr)) {
560
NL_SET_ERR_MSG_ATTR(extack, mask_attr, "Invalid port mask");
561
return -EINVAL;
562
}
563
564
*port_mask = nla_get_u16(mask_attr);
565
566
return 0;
567
}
568
569
static int fib_nl2rule(struct net *net, struct nlmsghdr *nlh,
570
struct netlink_ext_ack *extack,
571
struct fib_rules_ops *ops,
572
struct nlattr *tb[],
573
struct fib_rule **rule,
574
bool *user_priority)
575
{
576
struct fib_rule_hdr *frh = nlmsg_data(nlh);
577
struct fib_rule *nlrule = NULL;
578
int err = -EINVAL;
579
580
if (frh->src_len)
581
if (!tb[FRA_SRC] ||
582
frh->src_len > (ops->addr_size * 8) ||
583
nla_len(tb[FRA_SRC]) != ops->addr_size) {
584
NL_SET_ERR_MSG(extack, "Invalid source address");
585
goto errout;
586
}
587
588
if (frh->dst_len)
589
if (!tb[FRA_DST] ||
590
frh->dst_len > (ops->addr_size * 8) ||
591
nla_len(tb[FRA_DST]) != ops->addr_size) {
592
NL_SET_ERR_MSG(extack, "Invalid dst address");
593
goto errout;
594
}
595
596
nlrule = kzalloc(ops->rule_size, GFP_KERNEL_ACCOUNT);
597
if (!nlrule) {
598
err = -ENOMEM;
599
goto errout;
600
}
601
refcount_set(&nlrule->refcnt, 1);
602
nlrule->fr_net = net;
603
604
if (tb[FRA_PRIORITY]) {
605
nlrule->pref = nla_get_u32(tb[FRA_PRIORITY]);
606
*user_priority = true;
607
}
608
609
nlrule->proto = nla_get_u8_default(tb[FRA_PROTOCOL], RTPROT_UNSPEC);
610
611
if (tb[FRA_IIFNAME]) {
612
nlrule->iifindex = -1;
613
nla_strscpy(nlrule->iifname, tb[FRA_IIFNAME], IFNAMSIZ);
614
}
615
616
if (tb[FRA_OIFNAME]) {
617
nlrule->oifindex = -1;
618
nla_strscpy(nlrule->oifname, tb[FRA_OIFNAME], IFNAMSIZ);
619
}
620
621
if (tb[FRA_FWMARK]) {
622
nlrule->mark = nla_get_u32(tb[FRA_FWMARK]);
623
if (nlrule->mark)
624
/* compatibility: if the mark value is non-zero all bits
625
* are compared unless a mask is explicitly specified.
626
*/
627
nlrule->mark_mask = 0xFFFFFFFF;
628
}
629
630
if (tb[FRA_FWMASK])
631
nlrule->mark_mask = nla_get_u32(tb[FRA_FWMASK]);
632
633
if (tb[FRA_TUN_ID])
634
nlrule->tun_id = nla_get_be64(tb[FRA_TUN_ID]);
635
636
if (tb[FRA_L3MDEV] &&
637
fib_nl2rule_l3mdev(tb[FRA_L3MDEV], nlrule, extack) < 0)
638
goto errout_free;
639
640
nlrule->action = frh->action;
641
nlrule->flags = frh->flags;
642
nlrule->table = frh_get_table(frh, tb);
643
if (tb[FRA_SUPPRESS_PREFIXLEN])
644
nlrule->suppress_prefixlen = nla_get_u32(tb[FRA_SUPPRESS_PREFIXLEN]);
645
else
646
nlrule->suppress_prefixlen = -1;
647
648
if (tb[FRA_SUPPRESS_IFGROUP])
649
nlrule->suppress_ifgroup = nla_get_u32(tb[FRA_SUPPRESS_IFGROUP]);
650
else
651
nlrule->suppress_ifgroup = -1;
652
653
if (tb[FRA_GOTO]) {
654
if (nlrule->action != FR_ACT_GOTO) {
655
NL_SET_ERR_MSG(extack, "Unexpected goto");
656
goto errout_free;
657
}
658
659
nlrule->target = nla_get_u32(tb[FRA_GOTO]);
660
} else if (nlrule->action == FR_ACT_GOTO) {
661
NL_SET_ERR_MSG(extack, "Missing goto target for action goto");
662
goto errout_free;
663
}
664
665
if (nlrule->l3mdev && nlrule->table) {
666
NL_SET_ERR_MSG(extack, "l3mdev and table are mutually exclusive");
667
goto errout_free;
668
}
669
670
if (tb[FRA_UID_RANGE]) {
671
if (current_user_ns() != net->user_ns) {
672
err = -EPERM;
673
NL_SET_ERR_MSG(extack, "No permission to set uid");
674
goto errout_free;
675
}
676
677
nlrule->uid_range = nla_get_kuid_range(tb);
678
679
if (!uid_range_set(&nlrule->uid_range) ||
680
!uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) {
681
NL_SET_ERR_MSG(extack, "Invalid uid range");
682
goto errout_free;
683
}
684
} else {
685
nlrule->uid_range = fib_kuid_range_unset;
686
}
687
688
if (tb[FRA_IP_PROTO])
689
nlrule->ip_proto = nla_get_u8(tb[FRA_IP_PROTO]);
690
691
if (tb[FRA_SPORT_RANGE]) {
692
err = nla_get_port_range(tb[FRA_SPORT_RANGE],
693
&nlrule->sport_range);
694
if (err) {
695
NL_SET_ERR_MSG(extack, "Invalid sport range");
696
goto errout_free;
697
}
698
if (!fib_rule_port_is_range(&nlrule->sport_range))
699
nlrule->sport_mask = U16_MAX;
700
}
701
702
if (tb[FRA_SPORT_MASK]) {
703
err = fib_nl2rule_port_mask(tb[FRA_SPORT_MASK],
704
&nlrule->sport_range,
705
&nlrule->sport_mask, extack);
706
if (err)
707
goto errout_free;
708
}
709
710
if (tb[FRA_DPORT_RANGE]) {
711
err = nla_get_port_range(tb[FRA_DPORT_RANGE],
712
&nlrule->dport_range);
713
if (err) {
714
NL_SET_ERR_MSG(extack, "Invalid dport range");
715
goto errout_free;
716
}
717
if (!fib_rule_port_is_range(&nlrule->dport_range))
718
nlrule->dport_mask = U16_MAX;
719
}
720
721
if (tb[FRA_DPORT_MASK]) {
722
err = fib_nl2rule_port_mask(tb[FRA_DPORT_MASK],
723
&nlrule->dport_range,
724
&nlrule->dport_mask, extack);
725
if (err)
726
goto errout_free;
727
}
728
729
*rule = nlrule;
730
731
return 0;
732
733
errout_free:
734
kfree(nlrule);
735
errout:
736
return err;
737
}
738
739
static int fib_nl2rule_rtnl(struct fib_rule *nlrule,
740
struct fib_rules_ops *ops,
741
struct nlattr *tb[],
742
struct netlink_ext_ack *extack)
743
{
744
if (!tb[FRA_PRIORITY])
745
nlrule->pref = fib_default_rule_pref(ops);
746
747
/* Backward jumps are prohibited to avoid endless loops */
748
if (tb[FRA_GOTO] && nlrule->target <= nlrule->pref) {
749
NL_SET_ERR_MSG(extack, "Backward goto not supported");
750
return -EINVAL;
751
}
752
753
if (tb[FRA_IIFNAME]) {
754
struct net_device *dev;
755
756
dev = __dev_get_by_name(nlrule->fr_net, nlrule->iifname);
757
if (dev) {
758
nlrule->iifindex = dev->ifindex;
759
nlrule->iif_is_l3_master = netif_is_l3_master(dev);
760
}
761
}
762
763
if (tb[FRA_OIFNAME]) {
764
struct net_device *dev;
765
766
dev = __dev_get_by_name(nlrule->fr_net, nlrule->oifname);
767
if (dev) {
768
nlrule->oifindex = dev->ifindex;
769
nlrule->oif_is_l3_master = netif_is_l3_master(dev);
770
}
771
}
772
773
return 0;
774
}
775
776
static int rule_exists(struct fib_rules_ops *ops, struct fib_rule_hdr *frh,
777
struct nlattr **tb, struct fib_rule *rule)
778
{
779
struct fib_rule *r;
780
781
list_for_each_entry(r, &ops->rules_list, list) {
782
if (r->action != rule->action)
783
continue;
784
785
if (r->table != rule->table)
786
continue;
787
788
if (r->pref != rule->pref)
789
continue;
790
791
if (memcmp(r->iifname, rule->iifname, IFNAMSIZ))
792
continue;
793
794
if (memcmp(r->oifname, rule->oifname, IFNAMSIZ))
795
continue;
796
797
if (r->mark != rule->mark)
798
continue;
799
800
if (r->suppress_ifgroup != rule->suppress_ifgroup)
801
continue;
802
803
if (r->suppress_prefixlen != rule->suppress_prefixlen)
804
continue;
805
806
if (r->mark_mask != rule->mark_mask)
807
continue;
808
809
if (r->tun_id != rule->tun_id)
810
continue;
811
812
if (r->l3mdev != rule->l3mdev)
813
continue;
814
815
if (!uid_eq(r->uid_range.start, rule->uid_range.start) ||
816
!uid_eq(r->uid_range.end, rule->uid_range.end))
817
continue;
818
819
if (r->ip_proto != rule->ip_proto)
820
continue;
821
822
if (r->proto != rule->proto)
823
continue;
824
825
if (!fib_rule_port_range_compare(&r->sport_range,
826
&rule->sport_range))
827
continue;
828
829
if (r->sport_mask != rule->sport_mask)
830
continue;
831
832
if (!fib_rule_port_range_compare(&r->dport_range,
833
&rule->dport_range))
834
continue;
835
836
if (r->dport_mask != rule->dport_mask)
837
continue;
838
839
if (!ops->compare(r, frh, tb))
840
continue;
841
return 1;
842
}
843
return 0;
844
}
845
846
static const struct nla_policy fib_rule_policy[FRA_MAX + 1] = {
847
[FRA_UNSPEC] = { .strict_start_type = FRA_DPORT_RANGE + 1 },
848
[FRA_IIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
849
[FRA_OIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
850
[FRA_PRIORITY] = { .type = NLA_U32 },
851
[FRA_FWMARK] = { .type = NLA_U32 },
852
[FRA_FLOW] = { .type = NLA_U32 },
853
[FRA_TUN_ID] = { .type = NLA_U64 },
854
[FRA_FWMASK] = { .type = NLA_U32 },
855
[FRA_TABLE] = { .type = NLA_U32 },
856
[FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 },
857
[FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 },
858
[FRA_GOTO] = { .type = NLA_U32 },
859
[FRA_L3MDEV] = { .type = NLA_U8 },
860
[FRA_UID_RANGE] = { .len = sizeof(struct fib_rule_uid_range) },
861
[FRA_PROTOCOL] = { .type = NLA_U8 },
862
[FRA_IP_PROTO] = { .type = NLA_U8 },
863
[FRA_SPORT_RANGE] = { .len = sizeof(struct fib_rule_port_range) },
864
[FRA_DPORT_RANGE] = { .len = sizeof(struct fib_rule_port_range) },
865
[FRA_DSCP] = NLA_POLICY_MAX(NLA_U8, INET_DSCP_MASK >> 2),
866
[FRA_FLOWLABEL] = { .type = NLA_BE32 },
867
[FRA_FLOWLABEL_MASK] = { .type = NLA_BE32 },
868
[FRA_SPORT_MASK] = { .type = NLA_U16 },
869
[FRA_DPORT_MASK] = { .type = NLA_U16 },
870
[FRA_DSCP_MASK] = NLA_POLICY_MASK(NLA_U8, INET_DSCP_MASK >> 2),
871
};
872
873
int fib_newrule(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh,
874
struct netlink_ext_ack *extack, bool rtnl_held)
875
{
876
struct fib_rule *rule = NULL, *r, *last = NULL;
877
int err = -EINVAL, unresolved = 0;
878
struct fib_rules_ops *ops = NULL;
879
struct nlattr *tb[FRA_MAX + 1];
880
bool user_priority = false;
881
struct fib_rule_hdr *frh;
882
883
frh = nlmsg_payload(nlh, sizeof(*frh));
884
if (!frh) {
885
NL_SET_ERR_MSG(extack, "Invalid msg length");
886
goto errout;
887
}
888
889
ops = lookup_rules_ops(net, frh->family);
890
if (!ops) {
891
err = -EAFNOSUPPORT;
892
NL_SET_ERR_MSG(extack, "Rule family not supported");
893
goto errout;
894
}
895
896
err = nlmsg_parse_deprecated(nlh, sizeof(*frh), tb, FRA_MAX,
897
fib_rule_policy, extack);
898
if (err < 0) {
899
NL_SET_ERR_MSG(extack, "Error parsing msg");
900
goto errout;
901
}
902
903
err = fib_nl2rule(net, nlh, extack, ops, tb, &rule, &user_priority);
904
if (err)
905
goto errout;
906
907
if (!rtnl_held)
908
rtnl_net_lock(net);
909
910
err = fib_nl2rule_rtnl(rule, ops, tb, extack);
911
if (err)
912
goto errout_free;
913
914
if ((nlh->nlmsg_flags & NLM_F_EXCL) &&
915
rule_exists(ops, frh, tb, rule)) {
916
err = -EEXIST;
917
goto errout_free;
918
}
919
920
err = ops->configure(rule, skb, frh, tb, extack);
921
if (err < 0)
922
goto errout_free;
923
924
err = call_fib_rule_notifiers(net, FIB_EVENT_RULE_ADD, rule, ops,
925
extack);
926
if (err < 0)
927
goto errout_free;
928
929
list_for_each_entry(r, &ops->rules_list, list) {
930
if (r->pref == rule->target) {
931
RCU_INIT_POINTER(rule->ctarget, r);
932
break;
933
}
934
}
935
936
if (rcu_dereference_protected(rule->ctarget, 1) == NULL)
937
unresolved = 1;
938
939
list_for_each_entry(r, &ops->rules_list, list) {
940
if (r->pref > rule->pref)
941
break;
942
last = r;
943
}
944
945
if (last)
946
list_add_rcu(&rule->list, &last->list);
947
else
948
list_add_rcu(&rule->list, &ops->rules_list);
949
950
if (ops->unresolved_rules) {
951
/*
952
* There are unresolved goto rules in the list, check if
953
* any of them are pointing to this new rule.
954
*/
955
list_for_each_entry(r, &ops->rules_list, list) {
956
if (r->action == FR_ACT_GOTO &&
957
r->target == rule->pref &&
958
rtnl_dereference(r->ctarget) == NULL) {
959
rcu_assign_pointer(r->ctarget, rule);
960
if (--ops->unresolved_rules == 0)
961
break;
962
}
963
}
964
}
965
966
if (rule->action == FR_ACT_GOTO)
967
ops->nr_goto_rules++;
968
969
if (unresolved)
970
ops->unresolved_rules++;
971
972
if (rule->tun_id)
973
ip_tunnel_need_metadata();
974
975
fib_rule_get(rule);
976
977
if (!rtnl_held)
978
rtnl_net_unlock(net);
979
980
notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).portid);
981
fib_rule_put(rule);
982
flush_route_cache(ops);
983
rules_ops_put(ops);
984
return 0;
985
986
errout_free:
987
if (!rtnl_held)
988
rtnl_net_unlock(net);
989
kfree(rule);
990
errout:
991
rules_ops_put(ops);
992
return err;
993
}
994
EXPORT_SYMBOL_GPL(fib_newrule);
995
996
static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
997
struct netlink_ext_ack *extack)
998
{
999
return fib_newrule(sock_net(skb->sk), skb, nlh, extack, false);
1000
}
1001
1002
int fib_delrule(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh,
1003
struct netlink_ext_ack *extack, bool rtnl_held)
1004
{
1005
struct fib_rule *rule = NULL, *nlrule = NULL;
1006
struct fib_rules_ops *ops = NULL;
1007
struct nlattr *tb[FRA_MAX+1];
1008
bool user_priority = false;
1009
struct fib_rule_hdr *frh;
1010
int err = -EINVAL;
1011
1012
frh = nlmsg_payload(nlh, sizeof(*frh));
1013
if (!frh) {
1014
NL_SET_ERR_MSG(extack, "Invalid msg length");
1015
goto errout;
1016
}
1017
1018
ops = lookup_rules_ops(net, frh->family);
1019
if (ops == NULL) {
1020
err = -EAFNOSUPPORT;
1021
NL_SET_ERR_MSG(extack, "Rule family not supported");
1022
goto errout;
1023
}
1024
1025
err = nlmsg_parse_deprecated(nlh, sizeof(*frh), tb, FRA_MAX,
1026
fib_rule_policy, extack);
1027
if (err < 0) {
1028
NL_SET_ERR_MSG(extack, "Error parsing msg");
1029
goto errout;
1030
}
1031
1032
err = fib_nl2rule(net, nlh, extack, ops, tb, &nlrule, &user_priority);
1033
if (err)
1034
goto errout;
1035
1036
if (!rtnl_held)
1037
rtnl_net_lock(net);
1038
1039
err = fib_nl2rule_rtnl(nlrule, ops, tb, extack);
1040
if (err)
1041
goto errout_free;
1042
1043
rule = rule_find(ops, frh, tb, nlrule, user_priority);
1044
if (!rule) {
1045
err = -ENOENT;
1046
goto errout_free;
1047
}
1048
1049
if (rule->flags & FIB_RULE_PERMANENT) {
1050
err = -EPERM;
1051
goto errout_free;
1052
}
1053
1054
if (ops->delete) {
1055
err = ops->delete(rule);
1056
if (err)
1057
goto errout_free;
1058
}
1059
1060
if (rule->tun_id)
1061
ip_tunnel_unneed_metadata();
1062
1063
list_del_rcu(&rule->list);
1064
1065
if (rule->action == FR_ACT_GOTO) {
1066
ops->nr_goto_rules--;
1067
if (rtnl_dereference(rule->ctarget) == NULL)
1068
ops->unresolved_rules--;
1069
}
1070
1071
/*
1072
* Check if this rule is a target to any of them. If so,
1073
* adjust to the next one with the same preference or
1074
* disable them. As this operation is eventually very
1075
* expensive, it is only performed if goto rules, except
1076
* current if it is goto rule, have actually been added.
1077
*/
1078
if (ops->nr_goto_rules > 0) {
1079
struct fib_rule *n, *r;
1080
1081
n = list_next_entry(rule, list);
1082
if (&n->list == &ops->rules_list || n->pref != rule->pref)
1083
n = NULL;
1084
list_for_each_entry(r, &ops->rules_list, list) {
1085
if (rtnl_dereference(r->ctarget) != rule)
1086
continue;
1087
rcu_assign_pointer(r->ctarget, n);
1088
if (!n)
1089
ops->unresolved_rules++;
1090
}
1091
}
1092
1093
call_fib_rule_notifiers(net, FIB_EVENT_RULE_DEL, rule, ops, NULL);
1094
1095
if (!rtnl_held)
1096
rtnl_net_unlock(net);
1097
1098
notify_rule_change(RTM_DELRULE, rule, ops, nlh, NETLINK_CB(skb).portid);
1099
fib_rule_put(rule);
1100
flush_route_cache(ops);
1101
rules_ops_put(ops);
1102
kfree(nlrule);
1103
return 0;
1104
1105
errout_free:
1106
if (!rtnl_held)
1107
rtnl_net_unlock(net);
1108
kfree(nlrule);
1109
errout:
1110
rules_ops_put(ops);
1111
return err;
1112
}
1113
EXPORT_SYMBOL_GPL(fib_delrule);
1114
1115
static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
1116
struct netlink_ext_ack *extack)
1117
{
1118
return fib_delrule(sock_net(skb->sk), skb, nlh, extack, false);
1119
}
1120
1121
static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
1122
struct fib_rule *rule)
1123
{
1124
size_t payload = NLMSG_ALIGN(sizeof(struct fib_rule_hdr))
1125
+ nla_total_size(IFNAMSIZ) /* FRA_IIFNAME */
1126
+ nla_total_size(IFNAMSIZ) /* FRA_OIFNAME */
1127
+ nla_total_size(4) /* FRA_PRIORITY */
1128
+ nla_total_size(4) /* FRA_TABLE */
1129
+ nla_total_size(4) /* FRA_SUPPRESS_PREFIXLEN */
1130
+ nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */
1131
+ nla_total_size(4) /* FRA_FWMARK */
1132
+ nla_total_size(4) /* FRA_FWMASK */
1133
+ nla_total_size_64bit(8) /* FRA_TUN_ID */
1134
+ nla_total_size(sizeof(struct fib_kuid_range))
1135
+ nla_total_size(1) /* FRA_PROTOCOL */
1136
+ nla_total_size(1) /* FRA_IP_PROTO */
1137
+ nla_total_size(sizeof(struct fib_rule_port_range)) /* FRA_SPORT_RANGE */
1138
+ nla_total_size(sizeof(struct fib_rule_port_range)) /* FRA_DPORT_RANGE */
1139
+ nla_total_size(2) /* FRA_SPORT_MASK */
1140
+ nla_total_size(2); /* FRA_DPORT_MASK */
1141
1142
if (ops->nlmsg_payload)
1143
payload += ops->nlmsg_payload(rule);
1144
1145
return payload;
1146
}
1147
1148
static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
1149
u32 pid, u32 seq, int type, int flags,
1150
struct fib_rules_ops *ops)
1151
{
1152
struct nlmsghdr *nlh;
1153
struct fib_rule_hdr *frh;
1154
1155
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
1156
if (nlh == NULL)
1157
return -EMSGSIZE;
1158
1159
frh = nlmsg_data(nlh);
1160
frh->family = ops->family;
1161
frh->table = rule->table < 256 ? rule->table : RT_TABLE_COMPAT;
1162
if (nla_put_u32(skb, FRA_TABLE, rule->table))
1163
goto nla_put_failure;
1164
if (nla_put_u32(skb, FRA_SUPPRESS_PREFIXLEN, rule->suppress_prefixlen))
1165
goto nla_put_failure;
1166
frh->res1 = 0;
1167
frh->res2 = 0;
1168
frh->action = rule->action;
1169
frh->flags = rule->flags;
1170
1171
if (nla_put_u8(skb, FRA_PROTOCOL, rule->proto))
1172
goto nla_put_failure;
1173
1174
if (rule->action == FR_ACT_GOTO &&
1175
rcu_access_pointer(rule->ctarget) == NULL)
1176
frh->flags |= FIB_RULE_UNRESOLVED;
1177
1178
if (rule->iifname[0]) {
1179
if (nla_put_string(skb, FRA_IIFNAME, rule->iifname))
1180
goto nla_put_failure;
1181
if (READ_ONCE(rule->iifindex) == -1)
1182
frh->flags |= FIB_RULE_IIF_DETACHED;
1183
}
1184
1185
if (rule->oifname[0]) {
1186
if (nla_put_string(skb, FRA_OIFNAME, rule->oifname))
1187
goto nla_put_failure;
1188
if (READ_ONCE(rule->oifindex) == -1)
1189
frh->flags |= FIB_RULE_OIF_DETACHED;
1190
}
1191
1192
if ((rule->pref &&
1193
nla_put_u32(skb, FRA_PRIORITY, rule->pref)) ||
1194
(rule->mark &&
1195
nla_put_u32(skb, FRA_FWMARK, rule->mark)) ||
1196
((rule->mark_mask || rule->mark) &&
1197
nla_put_u32(skb, FRA_FWMASK, rule->mark_mask)) ||
1198
(rule->target &&
1199
nla_put_u32(skb, FRA_GOTO, rule->target)) ||
1200
(rule->tun_id &&
1201
nla_put_be64(skb, FRA_TUN_ID, rule->tun_id, FRA_PAD)) ||
1202
(rule->l3mdev &&
1203
nla_put_u8(skb, FRA_L3MDEV, rule->l3mdev)) ||
1204
(uid_range_set(&rule->uid_range) &&
1205
nla_put_uid_range(skb, &rule->uid_range)) ||
1206
(fib_rule_port_range_set(&rule->sport_range) &&
1207
nla_put_port_range(skb, FRA_SPORT_RANGE, &rule->sport_range)) ||
1208
(rule->sport_mask && nla_put_u16(skb, FRA_SPORT_MASK,
1209
rule->sport_mask)) ||
1210
(fib_rule_port_range_set(&rule->dport_range) &&
1211
nla_put_port_range(skb, FRA_DPORT_RANGE, &rule->dport_range)) ||
1212
(rule->dport_mask && nla_put_u16(skb, FRA_DPORT_MASK,
1213
rule->dport_mask)) ||
1214
(rule->ip_proto && nla_put_u8(skb, FRA_IP_PROTO, rule->ip_proto)))
1215
goto nla_put_failure;
1216
1217
if (rule->suppress_ifgroup != -1) {
1218
if (nla_put_u32(skb, FRA_SUPPRESS_IFGROUP, rule->suppress_ifgroup))
1219
goto nla_put_failure;
1220
}
1221
1222
if (ops->fill(rule, skb, frh) < 0)
1223
goto nla_put_failure;
1224
1225
nlmsg_end(skb, nlh);
1226
return 0;
1227
1228
nla_put_failure:
1229
nlmsg_cancel(skb, nlh);
1230
return -EMSGSIZE;
1231
}
1232
1233
static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
1234
struct fib_rules_ops *ops)
1235
{
1236
int idx = 0;
1237
struct fib_rule *rule;
1238
int err = 0;
1239
1240
rcu_read_lock();
1241
list_for_each_entry_rcu(rule, &ops->rules_list, list) {
1242
if (idx < cb->args[1])
1243
goto skip;
1244
1245
err = fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid,
1246
cb->nlh->nlmsg_seq, RTM_NEWRULE,
1247
NLM_F_MULTI, ops);
1248
if (err)
1249
break;
1250
skip:
1251
idx++;
1252
}
1253
rcu_read_unlock();
1254
cb->args[1] = idx;
1255
rules_ops_put(ops);
1256
1257
return err;
1258
}
1259
1260
static int fib_valid_dumprule_req(const struct nlmsghdr *nlh,
1261
struct netlink_ext_ack *extack)
1262
{
1263
struct fib_rule_hdr *frh;
1264
1265
frh = nlmsg_payload(nlh, sizeof(*frh));
1266
if (!frh) {
1267
NL_SET_ERR_MSG(extack, "Invalid header for fib rule dump request");
1268
return -EINVAL;
1269
}
1270
1271
if (frh->dst_len || frh->src_len || frh->tos || frh->table ||
1272
frh->res1 || frh->res2 || frh->action || frh->flags) {
1273
NL_SET_ERR_MSG(extack,
1274
"Invalid values in header for fib rule dump request");
1275
return -EINVAL;
1276
}
1277
1278
if (nlmsg_attrlen(nlh, sizeof(*frh))) {
1279
NL_SET_ERR_MSG(extack, "Invalid data after header in fib rule dump request");
1280
return -EINVAL;
1281
}
1282
1283
return 0;
1284
}
1285
1286
static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
1287
{
1288
const struct nlmsghdr *nlh = cb->nlh;
1289
struct net *net = sock_net(skb->sk);
1290
struct fib_rules_ops *ops;
1291
int err, idx = 0, family;
1292
1293
if (cb->strict_check) {
1294
err = fib_valid_dumprule_req(nlh, cb->extack);
1295
1296
if (err < 0)
1297
return err;
1298
}
1299
1300
family = rtnl_msg_family(nlh);
1301
if (family != AF_UNSPEC) {
1302
/* Protocol specific dump request */
1303
ops = lookup_rules_ops(net, family);
1304
if (ops == NULL)
1305
return -EAFNOSUPPORT;
1306
1307
return dump_rules(skb, cb, ops);
1308
}
1309
1310
err = 0;
1311
rcu_read_lock();
1312
list_for_each_entry_rcu(ops, &net->rules_ops, list) {
1313
if (idx < cb->args[0] || !try_module_get(ops->owner))
1314
goto skip;
1315
1316
err = dump_rules(skb, cb, ops);
1317
if (err < 0)
1318
break;
1319
1320
cb->args[1] = 0;
1321
skip:
1322
idx++;
1323
}
1324
rcu_read_unlock();
1325
cb->args[0] = idx;
1326
1327
return err;
1328
}
1329
1330
static void notify_rule_change(int event, struct fib_rule *rule,
1331
struct fib_rules_ops *ops, struct nlmsghdr *nlh,
1332
u32 pid)
1333
{
1334
struct net *net;
1335
struct sk_buff *skb;
1336
int err = -ENOMEM;
1337
1338
net = ops->fro_net;
1339
skb = nlmsg_new(fib_rule_nlmsg_size(ops, rule), GFP_KERNEL);
1340
if (skb == NULL)
1341
goto errout;
1342
1343
err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
1344
if (err < 0) {
1345
/* -EMSGSIZE implies BUG in fib_rule_nlmsg_size() */
1346
WARN_ON(err == -EMSGSIZE);
1347
kfree_skb(skb);
1348
goto errout;
1349
}
1350
1351
rtnl_notify(skb, net, pid, ops->nlgroup, nlh, GFP_KERNEL);
1352
return;
1353
errout:
1354
rtnl_set_sk_err(net, ops->nlgroup, err);
1355
}
1356
1357
static void attach_rules(struct list_head *rules, struct net_device *dev)
1358
{
1359
struct fib_rule *rule;
1360
1361
list_for_each_entry(rule, rules, list) {
1362
if (rule->iifindex == -1 &&
1363
strcmp(dev->name, rule->iifname) == 0) {
1364
WRITE_ONCE(rule->iifindex, dev->ifindex);
1365
WRITE_ONCE(rule->iif_is_l3_master,
1366
netif_is_l3_master(dev));
1367
}
1368
if (rule->oifindex == -1 &&
1369
strcmp(dev->name, rule->oifname) == 0) {
1370
WRITE_ONCE(rule->oifindex, dev->ifindex);
1371
WRITE_ONCE(rule->oif_is_l3_master,
1372
netif_is_l3_master(dev));
1373
}
1374
}
1375
}
1376
1377
static void detach_rules(struct list_head *rules, struct net_device *dev)
1378
{
1379
struct fib_rule *rule;
1380
1381
list_for_each_entry(rule, rules, list) {
1382
if (rule->iifindex == dev->ifindex) {
1383
WRITE_ONCE(rule->iifindex, -1);
1384
WRITE_ONCE(rule->iif_is_l3_master, false);
1385
}
1386
if (rule->oifindex == dev->ifindex) {
1387
WRITE_ONCE(rule->oifindex, -1);
1388
WRITE_ONCE(rule->oif_is_l3_master, false);
1389
}
1390
}
1391
}
1392
1393
1394
static int fib_rules_event(struct notifier_block *this, unsigned long event,
1395
void *ptr)
1396
{
1397
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1398
struct net *net = dev_net(dev);
1399
struct fib_rules_ops *ops;
1400
1401
ASSERT_RTNL();
1402
1403
switch (event) {
1404
case NETDEV_REGISTER:
1405
list_for_each_entry(ops, &net->rules_ops, list)
1406
attach_rules(&ops->rules_list, dev);
1407
break;
1408
1409
case NETDEV_CHANGENAME:
1410
list_for_each_entry(ops, &net->rules_ops, list) {
1411
detach_rules(&ops->rules_list, dev);
1412
attach_rules(&ops->rules_list, dev);
1413
}
1414
break;
1415
1416
case NETDEV_UNREGISTER:
1417
list_for_each_entry(ops, &net->rules_ops, list)
1418
detach_rules(&ops->rules_list, dev);
1419
break;
1420
}
1421
1422
return NOTIFY_DONE;
1423
}
1424
1425
static struct notifier_block fib_rules_notifier = {
1426
.notifier_call = fib_rules_event,
1427
};
1428
1429
static int __net_init fib_rules_net_init(struct net *net)
1430
{
1431
INIT_LIST_HEAD(&net->rules_ops);
1432
spin_lock_init(&net->rules_mod_lock);
1433
return 0;
1434
}
1435
1436
static void __net_exit fib_rules_net_exit(struct net *net)
1437
{
1438
WARN_ON_ONCE(!list_empty(&net->rules_ops));
1439
}
1440
1441
static struct pernet_operations fib_rules_net_ops = {
1442
.init = fib_rules_net_init,
1443
.exit = fib_rules_net_exit,
1444
};
1445
1446
static const struct rtnl_msg_handler fib_rules_rtnl_msg_handlers[] __initconst = {
1447
{.msgtype = RTM_NEWRULE, .doit = fib_nl_newrule,
1448
.flags = RTNL_FLAG_DOIT_PERNET},
1449
{.msgtype = RTM_DELRULE, .doit = fib_nl_delrule,
1450
.flags = RTNL_FLAG_DOIT_PERNET},
1451
{.msgtype = RTM_GETRULE, .dumpit = fib_nl_dumprule,
1452
.flags = RTNL_FLAG_DUMP_UNLOCKED},
1453
};
1454
1455
static int __init fib_rules_init(void)
1456
{
1457
int err;
1458
1459
rtnl_register_many(fib_rules_rtnl_msg_handlers);
1460
1461
err = register_pernet_subsys(&fib_rules_net_ops);
1462
if (err < 0)
1463
goto fail;
1464
1465
err = register_netdevice_notifier(&fib_rules_notifier);
1466
if (err < 0)
1467
goto fail_unregister;
1468
1469
return 0;
1470
1471
fail_unregister:
1472
unregister_pernet_subsys(&fib_rules_net_ops);
1473
fail:
1474
rtnl_unregister_many(fib_rules_rtnl_msg_handlers);
1475
return err;
1476
}
1477
1478
subsys_initcall(fib_rules_init);
1479
1480