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

net: fib_rules: Add new attribute to set protocol

For ages iproute2 has used `struct rtmsg` as the ancillary header for
FIB rules and in the process set the protocol value to RTPROT_BOOT.
Until ca56209a66 ("net: Allow a rule to track originating protocol")
the kernel rules code ignored the protocol value sent from userspace
and always returned 0 in notifications. To avoid incompatibility with
existing iproute2, send the protocol as a new attribute.

Fixes: cac56209a66 ("net: Allow a rule to track originating protocol")
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Donald Sharp and committed by
David S. Miller
1b71af60 cc30c93f

+20 -8
+4 -1
drivers/net/vrf.c
··· 1145 1145 sz = NLMSG_ALIGN(sizeof(struct fib_rule_hdr)); 1146 1146 sz += nla_total_size(sizeof(u8)); /* FRA_L3MDEV */ 1147 1147 sz += nla_total_size(sizeof(u32)); /* FRA_PRIORITY */ 1148 + sz += nla_total_size(sizeof(u8)); /* FRA_PROTOCOL */ 1148 1149 1149 1150 return sz; 1150 1151 } ··· 1175 1174 memset(frh, 0, sizeof(*frh)); 1176 1175 frh->family = family; 1177 1176 frh->action = FR_ACT_TO_TBL; 1178 - frh->proto = RTPROT_KERNEL; 1177 + 1178 + if (nla_put_u8(skb, FRA_PROTOCOL, RTPROT_KERNEL)) 1179 + goto nla_put_failure; 1179 1180 1180 1181 if (nla_put_u8(skb, FRA_L3MDEV, 1)) 1181 1182 goto nla_put_failure;
+2 -1
include/net/fib_rules.h
··· 109 109 [FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \ 110 110 [FRA_GOTO] = { .type = NLA_U32 }, \ 111 111 [FRA_L3MDEV] = { .type = NLA_U8 }, \ 112 - [FRA_UID_RANGE] = { .len = sizeof(struct fib_rule_uid_range) } 112 + [FRA_UID_RANGE] = { .len = sizeof(struct fib_rule_uid_range) }, \ 113 + [FRA_PROTOCOL] = { .type = NLA_U8 } 113 114 114 115 static inline void fib_rule_get(struct fib_rule *rule) 115 116 {
+3 -2
include/uapi/linux/fib_rules.h
··· 23 23 __u8 tos; 24 24 25 25 __u8 table; 26 - __u8 proto; 27 - __u8 res1; /* reserved */ 26 + __u8 res1; /* reserved */ 27 + __u8 res2; /* reserved */ 28 28 __u8 action; 29 29 30 30 __u32 flags; ··· 58 58 FRA_PAD, 59 59 FRA_L3MDEV, /* iif or oif is l3mdev goto its table */ 60 60 FRA_UID_RANGE, /* UID range */ 61 + FRA_PROTOCOL, /* Originator of the rule */ 61 62 __FRA_MAX 62 63 }; 63 64
+11 -4
net/core/fib_rules.c
··· 466 466 } 467 467 refcount_set(&rule->refcnt, 1); 468 468 rule->fr_net = net; 469 - rule->proto = frh->proto; 470 469 471 470 rule->pref = tb[FRA_PRIORITY] ? nla_get_u32(tb[FRA_PRIORITY]) 472 471 : fib_default_rule_pref(ops); 472 + 473 + rule->proto = tb[FRA_PROTOCOL] ? 474 + nla_get_u8(tb[FRA_PROTOCOL]) : RTPROT_UNSPEC; 473 475 474 476 if (tb[FRA_IIFNAME]) { 475 477 struct net_device *dev; ··· 668 666 } 669 667 670 668 list_for_each_entry(rule, &ops->rules_list, list) { 671 - if (frh->proto && (frh->proto != rule->proto)) 669 + if (tb[FRA_PROTOCOL] && 670 + (rule->proto != nla_get_u8(tb[FRA_PROTOCOL]))) 672 671 continue; 673 672 674 673 if (frh->action && (frh->action != rule->action)) ··· 789 786 + nla_total_size(4) /* FRA_FWMARK */ 790 787 + nla_total_size(4) /* FRA_FWMASK */ 791 788 + nla_total_size_64bit(8) /* FRA_TUN_ID */ 792 - + nla_total_size(sizeof(struct fib_kuid_range)); 789 + + nla_total_size(sizeof(struct fib_kuid_range)) 790 + + nla_total_size(1); /* FRA_PROTOCOL */ 793 791 794 792 if (ops->nlmsg_payload) 795 793 payload += ops->nlmsg_payload(rule); ··· 817 813 if (nla_put_u32(skb, FRA_SUPPRESS_PREFIXLEN, rule->suppress_prefixlen)) 818 814 goto nla_put_failure; 819 815 frh->res1 = 0; 816 + frh->res2 = 0; 820 817 frh->action = rule->action; 821 818 frh->flags = rule->flags; 822 - frh->proto = rule->proto; 819 + 820 + if (nla_put_u8(skb, FRA_PROTOCOL, rule->proto)) 821 + goto nla_put_failure; 823 822 824 823 if (rule->action == FR_ACT_GOTO && 825 824 rcu_access_pointer(rule->ctarget) == NULL)