1 /* 2 * net/core/fib_rules.c Generic Routing Rules 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation, version 2. 7 * 8 * Authors: Thomas Graf <tgraf@suug.ch> 9 */ 10 11 #include <linux/types.h> 12 #include <linux/kernel.h> 13 #include <linux/slab.h> 14 #include <linux/list.h> 15 #include <linux/module.h> 16 #include <net/net_namespace.h> 17 #include <net/sock.h> 18 #include <net/fib_rules.h> 19 20 int fib_default_rule_add(struct fib_rules_ops *ops, 21 u32 pref, u32 table, u32 flags) 22 { 23 struct fib_rule *r; 24 25 r = kzalloc(ops->rule_size, GFP_KERNEL); 26 if (r == NULL) 27 return -ENOMEM; 28 29 atomic_set(&r->refcnt, 1); 30 r->action = FR_ACT_TO_TBL; 31 r->pref = pref; 32 r->table = table; 33 r->flags = flags; 34 r->fr_net = hold_net(ops->fro_net); 35 36 r->suppress_prefixlen = -1; 37 r->suppress_ifgroup = -1; 38 39 /* The lock is not required here, the list in unreacheable 40 * at the moment this function is called */ 41 list_add_tail(&r->list, &ops->rules_list); 42 return 0; 43 } 44 EXPORT_SYMBOL(fib_default_rule_add); 45 46 u32 fib_default_rule_pref(struct fib_rules_ops *ops) 47 { 48 struct list_head *pos; 49 struct fib_rule *rule; 50 51 if (!list_empty(&ops->rules_list)) { 52 pos = ops->rules_list.next; 53 if (pos->next != &ops->rules_list) { 54 rule = list_entry(pos->next, struct fib_rule, list); 55 if (rule->pref) 56 return rule->pref - 1; 57 } 58 } 59 60 return 0; 61 } 62 EXPORT_SYMBOL(fib_default_rule_pref); 63 64 static void notify_rule_change(int event, struct fib_rule *rule, 65 struct fib_rules_ops *ops, struct nlmsghdr *nlh, 66 u32 pid); 67 68 static struct fib_rules_ops *lookup_rules_ops(struct net *net, int family) 69 { 70 struct fib_rules_ops *ops; 71 72 rcu_read_lock(); 73 list_for_each_entry_rcu(ops, &net->rules_ops, list) { 74 if (ops->family == family) { 75 if (!try_module_get(ops->owner)) 76 ops = NULL; 77 rcu_read_unlock(); 78 return ops; 79 } 80 } 81 rcu_read_unlock(); 82 83 return NULL; 84 } 85 86 static void rules_ops_put(struct fib_rules_ops *ops) 87 { 88 if (ops) 89 module_put(ops->owner); 90 } 91 92 static void flush_route_cache(struct fib_rules_ops *ops) 93 { 94 if (ops->flush_cache) 95 ops->flush_cache(ops); 96 } 97 98 static int __fib_rules_register(struct fib_rules_ops *ops) 99 { 100 int err = -EEXIST; 101 struct fib_rules_ops *o; 102 struct net *net; 103 104 net = ops->fro_net; 105 106 if (ops->rule_size < sizeof(struct fib_rule)) 107 return -EINVAL; 108 109 if (ops->match == NULL || ops->configure == NULL || 110 ops->compare == NULL || ops->fill == NULL || 111 ops->action == NULL) 112 return -EINVAL; 113 114 spin_lock(&net->rules_mod_lock); 115 list_for_each_entry(o, &net->rules_ops, list) 116 if (ops->family == o->family) 117 goto errout; 118 119 hold_net(net); 120 list_add_tail_rcu(&ops->list, &net->rules_ops); 121 err = 0; 122 errout: 123 spin_unlock(&net->rules_mod_lock); 124 125 return err; 126 } 127 128 struct fib_rules_ops * 129 fib_rules_register(const struct fib_rules_ops *tmpl, struct net *net) 130 { 131 struct fib_rules_ops *ops; 132 int err; 133 134 ops = kmemdup(tmpl, sizeof(*ops), GFP_KERNEL); 135 if (ops == NULL) 136 return ERR_PTR(-ENOMEM); 137 138 INIT_LIST_HEAD(&ops->rules_list); 139 ops->fro_net = net; 140 141 err = __fib_rules_register(ops); 142 if (err) { 143 kfree(ops); 144 ops = ERR_PTR(err); 145 } 146 147 return ops; 148 } 149 EXPORT_SYMBOL_GPL(fib_rules_register); 150 151 static void fib_rules_cleanup_ops(struct fib_rules_ops *ops) 152 { 153 struct fib_rule *rule, *tmp; 154 155 list_for_each_entry_safe(rule, tmp, &ops->rules_list, list) { 156 list_del_rcu(&rule->list); 157 if (ops->delete) 158 ops->delete(rule); 159 fib_rule_put(rule); 160 } 161 } 162 163 static void fib_rules_put_rcu(struct rcu_head *head) 164 { 165 struct fib_rules_ops *ops = container_of(head, struct fib_rules_ops, rcu); 166 struct net *net = ops->fro_net; 167 168 release_net(net); 169 kfree(ops); 170 } 171 172 void fib_rules_unregister(struct fib_rules_ops *ops) 173 { 174 struct net *net = ops->fro_net; 175 176 spin_lock(&net->rules_mod_lock); 177 list_del_rcu(&ops->list); 178 fib_rules_cleanup_ops(ops); 179 spin_unlock(&net->rules_mod_lock); 180 181 call_rcu(&ops->rcu, fib_rules_put_rcu); 182 } 183 EXPORT_SYMBOL_GPL(fib_rules_unregister); 184 185 static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops, 186 struct flowi *fl, int flags) 187 { 188 int ret = 0; 189 190 if (rule->iifindex && (rule->iifindex != fl->flowi_iif)) 191 goto out; 192 193 if (rule->oifindex && (rule->oifindex != fl->flowi_oif)) 194 goto out; 195 196 if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask) 197 goto out; 198 199 ret = ops->match(rule, fl, flags); 200 out: 201 return (rule->flags & FIB_RULE_INVERT) ? !ret : ret; 202 } 203 204 int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl, 205 int flags, struct fib_lookup_arg *arg) 206 { 207 struct fib_rule *rule; 208 int err; 209 210 rcu_read_lock(); 211 212 list_for_each_entry_rcu(rule, &ops->rules_list, list) { 213 jumped: 214 if (!fib_rule_match(rule, ops, fl, flags)) 215 continue; 216 217 if (rule->action == FR_ACT_GOTO) { 218 struct fib_rule *target; 219 220 target = rcu_dereference(rule->ctarget); 221 if (target == NULL) { 222 continue; 223 } else { 224 rule = target; 225 goto jumped; 226 } 227 } else if (rule->action == FR_ACT_NOP) 228 continue; 229 else 230 err = ops->action(rule, fl, flags, arg); 231 232 if (!err && ops->suppress && ops->suppress(rule, arg)) 233 continue; 234 235 if (err != -EAGAIN) { 236 if ((arg->flags & FIB_LOOKUP_NOREF) || 237 likely(atomic_inc_not_zero(&rule->refcnt))) { 238 arg->rule = rule; 239 goto out; 240 } 241 break; 242 } 243 } 244 245 err = -ESRCH; 246 out: 247 rcu_read_unlock(); 248 249 return err; 250 } 251 EXPORT_SYMBOL_GPL(fib_rules_lookup); 252 253 static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, 254 struct fib_rules_ops *ops) 255 { 256 int err = -EINVAL; 257 258 if (frh->src_len) 259 if (tb[FRA_SRC] == NULL || 260 frh->src_len > (ops->addr_size * 8) || 261 nla_len(tb[FRA_SRC]) != ops->addr_size) 262 goto errout; 263 264 if (frh->dst_len) 265 if (tb[FRA_DST] == NULL || 266 frh->dst_len > (ops->addr_size * 8) || 267 nla_len(tb[FRA_DST]) != ops->addr_size) 268 goto errout; 269 270 err = 0; 271 errout: 272 return err; 273 } 274 275 static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh) 276 { 277 struct net *net = sock_net(skb->sk); 278 struct fib_rule_hdr *frh = nlmsg_data(nlh); 279 struct fib_rules_ops *ops = NULL; 280 struct fib_rule *rule, *r, *last = NULL; 281 struct nlattr *tb[FRA_MAX+1]; 282 int err = -EINVAL, unresolved = 0; 283 284 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) 285 goto errout; 286 287 ops = lookup_rules_ops(net, frh->family); 288 if (ops == NULL) { 289 err = -EAFNOSUPPORT; 290 goto errout; 291 } 292 293 err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy); 294 if (err < 0) 295 goto errout; 296 297 err = validate_rulemsg(frh, tb, ops); 298 if (err < 0) 299 goto errout; 300 301 rule = kzalloc(ops->rule_size, GFP_KERNEL); 302 if (rule == NULL) { 303 err = -ENOMEM; 304 goto errout; 305 } 306 rule->fr_net = hold_net(net); 307 308 if (tb[FRA_PRIORITY]) 309 rule->pref = nla_get_u32(tb[FRA_PRIORITY]); 310 311 if (tb[FRA_IIFNAME]) { 312 struct net_device *dev; 313 314 rule->iifindex = -1; 315 nla_strlcpy(rule->iifname, tb[FRA_IIFNAME], IFNAMSIZ); 316 dev = __dev_get_by_name(net, rule->iifname); 317 if (dev) 318 rule->iifindex = dev->ifindex; 319 } 320 321 if (tb[FRA_OIFNAME]) { 322 struct net_device *dev; 323 324 rule->oifindex = -1; 325 nla_strlcpy(rule->oifname, tb[FRA_OIFNAME], IFNAMSIZ); 326 dev = __dev_get_by_name(net, rule->oifname); 327 if (dev) 328 rule->oifindex = dev->ifindex; 329 } 330 331 if (tb[FRA_FWMARK]) { 332 rule->mark = nla_get_u32(tb[FRA_FWMARK]); 333 if (rule->mark) 334 /* compatibility: if the mark value is non-zero all bits 335 * are compared unless a mask is explicitly specified. 336 */ 337 rule->mark_mask = 0xFFFFFFFF; 338 } 339 340 if (tb[FRA_FWMASK]) 341 rule->mark_mask = nla_get_u32(tb[FRA_FWMASK]); 342 343 rule->action = frh->action; 344 rule->flags = frh->flags; 345 rule->table = frh_get_table(frh, tb); 346 if (tb[FRA_SUPPRESS_PREFIXLEN]) 347 rule->suppress_prefixlen = nla_get_u32(tb[FRA_SUPPRESS_PREFIXLEN]); 348 else 349 rule->suppress_prefixlen = -1; 350 351 if (tb[FRA_SUPPRESS_IFGROUP]) 352 rule->suppress_ifgroup = nla_get_u32(tb[FRA_SUPPRESS_IFGROUP]); 353 else 354 rule->suppress_ifgroup = -1; 355 356 if (!tb[FRA_PRIORITY] && ops->default_pref) 357 rule->pref = ops->default_pref(ops); 358 359 err = -EINVAL; 360 if (tb[FRA_GOTO]) { 361 if (rule->action != FR_ACT_GOTO) 362 goto errout_free; 363 364 rule->target = nla_get_u32(tb[FRA_GOTO]); 365 /* Backward jumps are prohibited to avoid endless loops */ 366 if (rule->target <= rule->pref) 367 goto errout_free; 368 369 list_for_each_entry(r, &ops->rules_list, list) { 370 if (r->pref == rule->target) { 371 RCU_INIT_POINTER(rule->ctarget, r); 372 break; 373 } 374 } 375 376 if (rcu_dereference_protected(rule->ctarget, 1) == NULL) 377 unresolved = 1; 378 } else if (rule->action == FR_ACT_GOTO) 379 goto errout_free; 380 381 err = ops->configure(rule, skb, frh, tb); 382 if (err < 0) 383 goto errout_free; 384 385 list_for_each_entry(r, &ops->rules_list, list) { 386 if (r->pref > rule->pref) 387 break; 388 last = r; 389 } 390 391 fib_rule_get(rule); 392 393 if (last) 394 list_add_rcu(&rule->list, &last->list); 395 else 396 list_add_rcu(&rule->list, &ops->rules_list); 397 398 if (ops->unresolved_rules) { 399 /* 400 * There are unresolved goto rules in the list, check if 401 * any of them are pointing to this new rule. 402 */ 403 list_for_each_entry(r, &ops->rules_list, list) { 404 if (r->action == FR_ACT_GOTO && 405 r->target == rule->pref && 406 rtnl_dereference(r->ctarget) == NULL) { 407 rcu_assign_pointer(r->ctarget, rule); 408 if (--ops->unresolved_rules == 0) 409 break; 410 } 411 } 412 } 413 414 if (rule->action == FR_ACT_GOTO) 415 ops->nr_goto_rules++; 416 417 if (unresolved) 418 ops->unresolved_rules++; 419 420 notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).portid); 421 flush_route_cache(ops); 422 rules_ops_put(ops); 423 return 0; 424 425 errout_free: 426 release_net(rule->fr_net); 427 kfree(rule); 428 errout: 429 rules_ops_put(ops); 430 return err; 431 } 432 433 static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh) 434 { 435 struct net *net = sock_net(skb->sk); 436 struct fib_rule_hdr *frh = nlmsg_data(nlh); 437 struct fib_rules_ops *ops = NULL; 438 struct fib_rule *rule, *tmp; 439 struct nlattr *tb[FRA_MAX+1]; 440 int err = -EINVAL; 441 442 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) 443 goto errout; 444 445 ops = lookup_rules_ops(net, frh->family); 446 if (ops == NULL) { 447 err = -EAFNOSUPPORT; 448 goto errout; 449 } 450 451 err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy); 452 if (err < 0) 453 goto errout; 454 455 err = validate_rulemsg(frh, tb, ops); 456 if (err < 0) 457 goto errout; 458 459 list_for_each_entry(rule, &ops->rules_list, list) { 460 if (frh->action && (frh->action != rule->action)) 461 continue; 462 463 if (frh->table && (frh_get_table(frh, tb) != rule->table)) 464 continue; 465 466 if (tb[FRA_PRIORITY] && 467 (rule->pref != nla_get_u32(tb[FRA_PRIORITY]))) 468 continue; 469 470 if (tb[FRA_IIFNAME] && 471 nla_strcmp(tb[FRA_IIFNAME], rule->iifname)) 472 continue; 473 474 if (tb[FRA_OIFNAME] && 475 nla_strcmp(tb[FRA_OIFNAME], rule->oifname)) 476 continue; 477 478 if (tb[FRA_FWMARK] && 479 (rule->mark != nla_get_u32(tb[FRA_FWMARK]))) 480 continue; 481 482 if (tb[FRA_FWMASK] && 483 (rule->mark_mask != nla_get_u32(tb[FRA_FWMASK]))) 484 continue; 485 486 if (!ops->compare(rule, frh, tb)) 487 continue; 488 489 if (rule->flags & FIB_RULE_PERMANENT) { 490 err = -EPERM; 491 goto errout; 492 } 493 494 list_del_rcu(&rule->list); 495 496 if (rule->action == FR_ACT_GOTO) { 497 ops->nr_goto_rules--; 498 if (rtnl_dereference(rule->ctarget) == NULL) 499 ops->unresolved_rules--; 500 } 501 502 /* 503 * Check if this rule is a target to any of them. If so, 504 * disable them. As this operation is eventually very 505 * expensive, it is only performed if goto rules have 506 * actually been added. 507 */ 508 if (ops->nr_goto_rules > 0) { 509 list_for_each_entry(tmp, &ops->rules_list, list) { 510 if (rtnl_dereference(tmp->ctarget) == rule) { 511 RCU_INIT_POINTER(tmp->ctarget, NULL); 512 ops->unresolved_rules++; 513 } 514 } 515 } 516 517 notify_rule_change(RTM_DELRULE, rule, ops, nlh, 518 NETLINK_CB(skb).portid); 519 if (ops->delete) 520 ops->delete(rule); 521 fib_rule_put(rule); 522 flush_route_cache(ops); 523 rules_ops_put(ops); 524 return 0; 525 } 526 527 err = -ENOENT; 528 errout: 529 rules_ops_put(ops); 530 return err; 531 } 532 533 static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops, 534 struct fib_rule *rule) 535 { 536 size_t payload = NLMSG_ALIGN(sizeof(struct fib_rule_hdr)) 537 + nla_total_size(IFNAMSIZ) /* FRA_IIFNAME */ 538 + nla_total_size(IFNAMSIZ) /* FRA_OIFNAME */ 539 + nla_total_size(4) /* FRA_PRIORITY */ 540 + nla_total_size(4) /* FRA_TABLE */ 541 + nla_total_size(4) /* FRA_SUPPRESS_PREFIXLEN */ 542 + nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */ 543 + nla_total_size(4) /* FRA_FWMARK */ 544 + nla_total_size(4); /* FRA_FWMASK */ 545 546 if (ops->nlmsg_payload) 547 payload += ops->nlmsg_payload(rule); 548 549 return payload; 550 } 551 552 static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, 553 u32 pid, u32 seq, int type, int flags, 554 struct fib_rules_ops *ops) 555 { 556 struct nlmsghdr *nlh; 557 struct fib_rule_hdr *frh; 558 559 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags); 560 if (nlh == NULL) 561 return -EMSGSIZE; 562 563 frh = nlmsg_data(nlh); 564 frh->family = ops->family; 565 frh->table = rule->table; 566 if (nla_put_u32(skb, FRA_TABLE, rule->table)) 567 goto nla_put_failure; 568 if (nla_put_u32(skb, FRA_SUPPRESS_PREFIXLEN, rule->suppress_prefixlen)) 569 goto nla_put_failure; 570 frh->res1 = 0; 571 frh->res2 = 0; 572 frh->action = rule->action; 573 frh->flags = rule->flags; 574 575 if (rule->action == FR_ACT_GOTO && 576 rcu_access_pointer(rule->ctarget) == NULL) 577 frh->flags |= FIB_RULE_UNRESOLVED; 578 579 if (rule->iifname[0]) { 580 if (nla_put_string(skb, FRA_IIFNAME, rule->iifname)) 581 goto nla_put_failure; 582 if (rule->iifindex == -1) 583 frh->flags |= FIB_RULE_IIF_DETACHED; 584 } 585 586 if (rule->oifname[0]) { 587 if (nla_put_string(skb, FRA_OIFNAME, rule->oifname)) 588 goto nla_put_failure; 589 if (rule->oifindex == -1) 590 frh->flags |= FIB_RULE_OIF_DETACHED; 591 } 592 593 if ((rule->pref && 594 nla_put_u32(skb, FRA_PRIORITY, rule->pref)) || 595 (rule->mark && 596 nla_put_u32(skb, FRA_FWMARK, rule->mark)) || 597 ((rule->mark_mask || rule->mark) && 598 nla_put_u32(skb, FRA_FWMASK, rule->mark_mask)) || 599 (rule->target && 600 nla_put_u32(skb, FRA_GOTO, rule->target))) 601 goto nla_put_failure; 602 603 if (rule->suppress_ifgroup != -1) { 604 if (nla_put_u32(skb, FRA_SUPPRESS_IFGROUP, rule->suppress_ifgroup)) 605 goto nla_put_failure; 606 } 607 608 if (ops->fill(rule, skb, frh) < 0) 609 goto nla_put_failure; 610 611 return nlmsg_end(skb, nlh); 612 613 nla_put_failure: 614 nlmsg_cancel(skb, nlh); 615 return -EMSGSIZE; 616 } 617 618 static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, 619 struct fib_rules_ops *ops) 620 { 621 int idx = 0; 622 struct fib_rule *rule; 623 624 rcu_read_lock(); 625 list_for_each_entry_rcu(rule, &ops->rules_list, list) { 626 if (idx < cb->args[1]) 627 goto skip; 628 629 if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, 630 cb->nlh->nlmsg_seq, RTM_NEWRULE, 631 NLM_F_MULTI, ops) < 0) 632 break; 633 skip: 634 idx++; 635 } 636 rcu_read_unlock(); 637 cb->args[1] = idx; 638 rules_ops_put(ops); 639 640 return skb->len; 641 } 642 643 static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) 644 { 645 struct net *net = sock_net(skb->sk); 646 struct fib_rules_ops *ops; 647 int idx = 0, family; 648 649 family = rtnl_msg_family(cb->nlh); 650 if (family != AF_UNSPEC) { 651 /* Protocol specific dump request */ 652 ops = lookup_rules_ops(net, family); 653 if (ops == NULL) 654 return -EAFNOSUPPORT; 655 656 return dump_rules(skb, cb, ops); 657 } 658 659 rcu_read_lock(); 660 list_for_each_entry_rcu(ops, &net->rules_ops, list) { 661 if (idx < cb->args[0] || !try_module_get(ops->owner)) 662 goto skip; 663 664 if (dump_rules(skb, cb, ops) < 0) 665 break; 666 667 cb->args[1] = 0; 668 skip: 669 idx++; 670 } 671 rcu_read_unlock(); 672 cb->args[0] = idx; 673 674 return skb->len; 675 } 676 677 static void notify_rule_change(int event, struct fib_rule *rule, 678 struct fib_rules_ops *ops, struct nlmsghdr *nlh, 679 u32 pid) 680 { 681 struct net *net; 682 struct sk_buff *skb; 683 int err = -ENOBUFS; 684 685 net = ops->fro_net; 686 skb = nlmsg_new(fib_rule_nlmsg_size(ops, rule), GFP_KERNEL); 687 if (skb == NULL) 688 goto errout; 689 690 err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops); 691 if (err < 0) { 692 /* -EMSGSIZE implies BUG in fib_rule_nlmsg_size() */ 693 WARN_ON(err == -EMSGSIZE); 694 kfree_skb(skb); 695 goto errout; 696 } 697 698 rtnl_notify(skb, net, pid, ops->nlgroup, nlh, GFP_KERNEL); 699 return; 700 errout: 701 if (err < 0) 702 rtnl_set_sk_err(net, ops->nlgroup, err); 703 } 704 705 static void attach_rules(struct list_head *rules, struct net_device *dev) 706 { 707 struct fib_rule *rule; 708 709 list_for_each_entry(rule, rules, list) { 710 if (rule->iifindex == -1 && 711 strcmp(dev->name, rule->iifname) == 0) 712 rule->iifindex = dev->ifindex; 713 if (rule->oifindex == -1 && 714 strcmp(dev->name, rule->oifname) == 0) 715 rule->oifindex = dev->ifindex; 716 } 717 } 718 719 static void detach_rules(struct list_head *rules, struct net_device *dev) 720 { 721 struct fib_rule *rule; 722 723 list_for_each_entry(rule, rules, list) { 724 if (rule->iifindex == dev->ifindex) 725 rule->iifindex = -1; 726 if (rule->oifindex == dev->ifindex) 727 rule->oifindex = -1; 728 } 729 } 730 731 732 static int fib_rules_event(struct notifier_block *this, unsigned long event, 733 void *ptr) 734 { 735 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 736 struct net *net = dev_net(dev); 737 struct fib_rules_ops *ops; 738 739 ASSERT_RTNL(); 740 741 switch (event) { 742 case NETDEV_REGISTER: 743 list_for_each_entry(ops, &net->rules_ops, list) 744 attach_rules(&ops->rules_list, dev); 745 break; 746 747 case NETDEV_UNREGISTER: 748 list_for_each_entry(ops, &net->rules_ops, list) 749 detach_rules(&ops->rules_list, dev); 750 break; 751 } 752 753 return NOTIFY_DONE; 754 } 755 756 static struct notifier_block fib_rules_notifier = { 757 .notifier_call = fib_rules_event, 758 }; 759 760 static int __net_init fib_rules_net_init(struct net *net) 761 { 762 INIT_LIST_HEAD(&net->rules_ops); 763 spin_lock_init(&net->rules_mod_lock); 764 return 0; 765 } 766 767 static struct pernet_operations fib_rules_net_ops = { 768 .init = fib_rules_net_init, 769 }; 770 771 static int __init fib_rules_init(void) 772 { 773 int err; 774 rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL, NULL); 775 rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL, NULL); 776 rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule, NULL); 777 778 err = register_pernet_subsys(&fib_rules_net_ops); 779 if (err < 0) 780 goto fail; 781 782 err = register_netdevice_notifier(&fib_rules_notifier); 783 if (err < 0) 784 goto fail_unregister; 785 786 return 0; 787 788 fail_unregister: 789 unregister_pernet_subsys(&fib_rules_net_ops); 790 fail: 791 rtnl_unregister(PF_UNSPEC, RTM_NEWRULE); 792 rtnl_unregister(PF_UNSPEC, RTM_DELRULE); 793 rtnl_unregister(PF_UNSPEC, RTM_GETRULE); 794 return err; 795 } 796 797 subsys_initcall(fib_rules_init); 798