Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: fib_rules: add extack support

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Roopa Prabhu and committed by
David S. Miller
b16fb418 f9d4b0c1

+63 -22
+2 -1
include/net/fib_rules.h
··· 75 75 int (*configure)(struct fib_rule *, 76 76 struct sk_buff *, 77 77 struct fib_rule_hdr *, 78 - struct nlattr **); 78 + struct nlattr **, 79 + struct netlink_ext_ack *); 79 80 int (*delete)(struct fib_rule *); 80 81 int (*compare)(struct fib_rule *, 81 82 struct fib_rule_hdr *,
+42 -13
net/core/fib_rules.c
··· 469 469 if (frh->src_len) 470 470 if (!tb[FRA_SRC] || 471 471 frh->src_len > (ops->addr_size * 8) || 472 - nla_len(tb[FRA_SRC]) != ops->addr_size) 472 + nla_len(tb[FRA_SRC]) != ops->addr_size) { 473 + NL_SET_ERR_MSG(extack, "Invalid source address"); 473 474 goto errout; 475 + } 474 476 475 477 if (frh->dst_len) 476 478 if (!tb[FRA_DST] || 477 479 frh->dst_len > (ops->addr_size * 8) || 478 - nla_len(tb[FRA_DST]) != ops->addr_size) 480 + nla_len(tb[FRA_DST]) != ops->addr_size) { 481 + NL_SET_ERR_MSG(extack, "Invalid dst address"); 479 482 goto errout; 483 + } 480 484 481 485 nlrule = kzalloc(ops->rule_size, GFP_KERNEL); 482 486 if (!nlrule) { ··· 541 537 nlrule->l3mdev = nla_get_u8(tb[FRA_L3MDEV]); 542 538 if (nlrule->l3mdev != 1) 543 539 #endif 540 + NL_SET_ERR_MSG(extack, "Invalid l3mdev"); 544 541 goto errout_free; 545 542 } 546 543 ··· 559 554 nlrule->suppress_ifgroup = -1; 560 555 561 556 if (tb[FRA_GOTO]) { 562 - if (nlrule->action != FR_ACT_GOTO) 557 + if (nlrule->action != FR_ACT_GOTO) { 558 + NL_SET_ERR_MSG(extack, "Unexpected goto"); 563 559 goto errout_free; 560 + } 564 561 565 562 nlrule->target = nla_get_u32(tb[FRA_GOTO]); 566 563 /* Backward jumps are prohibited to avoid endless loops */ 567 - if (nlrule->target <= nlrule->pref) 564 + if (nlrule->target <= nlrule->pref) { 565 + NL_SET_ERR_MSG(extack, "Backward goto not supported"); 568 566 goto errout_free; 567 + } 569 568 } else if (nlrule->action == FR_ACT_GOTO) { 569 + NL_SET_ERR_MSG(extack, "Missing goto target for action goto"); 570 570 goto errout_free; 571 571 } 572 572 573 - if (nlrule->l3mdev && nlrule->table) 573 + if (nlrule->l3mdev && nlrule->table) { 574 + NL_SET_ERR_MSG(extack, "l3mdev and table are mutually exclusive"); 574 575 goto errout_free; 576 + } 575 577 576 578 if (tb[FRA_UID_RANGE]) { 577 579 if (current_user_ns() != net->user_ns) { 578 580 err = -EPERM; 581 + NL_SET_ERR_MSG(extack, "No permission to set uid"); 579 582 goto errout_free; 580 583 } 581 584 582 585 nlrule->uid_range = nla_get_kuid_range(tb); 583 586 584 587 if (!uid_range_set(&nlrule->uid_range) || 585 - !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) 588 + !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) { 589 + NL_SET_ERR_MSG(extack, "Invalid uid range"); 586 590 goto errout_free; 591 + } 587 592 } else { 588 593 nlrule->uid_range = fib_kuid_range_unset; 589 594 } ··· 604 589 if (tb[FRA_SPORT_RANGE]) { 605 590 err = nla_get_port_range(tb[FRA_SPORT_RANGE], 606 591 &nlrule->sport_range); 607 - if (err) 592 + if (err) { 593 + NL_SET_ERR_MSG(extack, "Invalid sport range"); 608 594 goto errout_free; 595 + } 609 596 } 610 597 611 598 if (tb[FRA_DPORT_RANGE]) { 612 599 err = nla_get_port_range(tb[FRA_DPORT_RANGE], 613 600 &nlrule->dport_range); 614 - if (err) 601 + if (err) { 602 + NL_SET_ERR_MSG(extack, "Invalid dport range"); 615 603 goto errout_free; 604 + } 616 605 } 617 606 618 607 *rule = nlrule; ··· 640 621 int err = -EINVAL, unresolved = 0; 641 622 bool user_priority = false; 642 623 643 - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) 624 + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) { 625 + NL_SET_ERR_MSG(extack, "Invalid msg length"); 644 626 goto errout; 627 + } 645 628 646 629 ops = lookup_rules_ops(net, frh->family); 647 630 if (!ops) { 648 631 err = -EAFNOSUPPORT; 632 + NL_SET_ERR_MSG(extack, "Rule family not supported"); 649 633 goto errout; 650 634 } 651 635 652 636 err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); 653 - if (err < 0) 637 + if (err < 0) { 638 + NL_SET_ERR_MSG(extack, "Error parsing msg"); 654 639 goto errout; 640 + } 655 641 656 642 err = fib_nl2rule(skb, nlh, extack, ops, tb, &rule, &user_priority); 657 643 if (err) ··· 668 644 goto errout_free; 669 645 } 670 646 671 - err = ops->configure(rule, skb, frh, tb); 647 + err = ops->configure(rule, skb, frh, tb, extack); 672 648 if (err < 0) 673 649 goto errout_free; 674 650 ··· 747 723 int err = -EINVAL; 748 724 bool user_priority = false; 749 725 750 - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) 726 + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) { 727 + NL_SET_ERR_MSG(extack, "Invalid msg length"); 751 728 goto errout; 729 + } 752 730 753 731 ops = lookup_rules_ops(net, frh->family); 754 732 if (ops == NULL) { 755 733 err = -EAFNOSUPPORT; 734 + NL_SET_ERR_MSG(extack, "Rule family not supported"); 756 735 goto errout; 757 736 } 758 737 759 738 err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); 760 - if (err < 0) 739 + if (err < 0) { 740 + NL_SET_ERR_MSG(extack, "Error parsing msg"); 761 741 goto errout; 742 + } 762 743 763 744 err = fib_nl2rule(skb, nlh, extack, ops, tb, &nlrule, &user_priority); 764 745 if (err)
+5 -2
net/decnet/dn_rules.c
··· 121 121 122 122 static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 123 123 struct fib_rule_hdr *frh, 124 - struct nlattr **tb) 124 + struct nlattr **tb, 125 + struct netlink_ext_ack *extack) 125 126 { 126 127 int err = -EINVAL; 127 128 struct dn_fib_rule *r = (struct dn_fib_rule *)rule; 128 129 129 - if (frh->tos) 130 + if (frh->tos) { 131 + NL_SET_ERR_MSG(extack, "Invalid tos value"); 130 132 goto errout; 133 + } 131 134 132 135 if (rule->table == RT_TABLE_UNSPEC) { 133 136 if (rule->action == FR_ACT_TO_TBL) {
+5 -2
net/ipv4/fib_rules.c
··· 213 213 214 214 static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 215 215 struct fib_rule_hdr *frh, 216 - struct nlattr **tb) 216 + struct nlattr **tb, 217 + struct netlink_ext_ack *extack) 217 218 { 218 219 struct net *net = sock_net(skb->sk); 219 220 int err = -EINVAL; 220 221 struct fib4_rule *rule4 = (struct fib4_rule *) rule; 221 222 222 - if (frh->tos & ~IPTOS_TOS_MASK) 223 + if (frh->tos & ~IPTOS_TOS_MASK) { 224 + NL_SET_ERR_MSG(extack, "Invalid tos"); 223 225 goto errout; 226 + } 224 227 225 228 /* split local/main if they are not already split */ 226 229 err = fib_unmerge(net);
+2 -1
net/ipv4/ipmr.c
··· 201 201 }; 202 202 203 203 static int ipmr_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 204 - struct fib_rule_hdr *frh, struct nlattr **tb) 204 + struct fib_rule_hdr *frh, struct nlattr **tb, 205 + struct netlink_ext_ack *extack) 205 206 { 206 207 return 0; 207 208 }
+5 -2
net/ipv6/fib6_rules.c
··· 245 245 246 246 static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 247 247 struct fib_rule_hdr *frh, 248 - struct nlattr **tb) 248 + struct nlattr **tb, 249 + struct netlink_ext_ack *extack) 249 250 { 250 251 int err = -EINVAL; 251 252 struct net *net = sock_net(skb->sk); 252 253 struct fib6_rule *rule6 = (struct fib6_rule *) rule; 253 254 254 255 if (rule->action == FR_ACT_TO_TBL && !rule->l3mdev) { 255 - if (rule->table == RT6_TABLE_UNSPEC) 256 + if (rule->table == RT6_TABLE_UNSPEC) { 257 + NL_SET_ERR_MSG(extack, "Invalid table"); 256 258 goto errout; 259 + } 257 260 258 261 if (fib6_new_table(net, rule->table) == NULL) { 259 262 err = -ENOBUFS;
+2 -1
net/ipv6/ip6mr.c
··· 180 180 }; 181 181 182 182 static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 183 - struct fib_rule_hdr *frh, struct nlattr **tb) 183 + struct fib_rule_hdr *frh, struct nlattr **tb, 184 + struct netlink_ext_ack *extack) 184 185 { 185 186 return 0; 186 187 }