Modify 'ip rule' command to notice when the kernel passes to us the originating protocol.
Add code to allow the `ip rule flush protocol XXX` command to be accepted and properly handled. Modify the documentation to reflect these code changes. Signed-off-by: Donald Sharp <sha...@cumulusnetworks.com> --- ip/iprule.c | 36 +++++++++++++++++++++++++++++------- man/man8/ip-rule.8 | 18 +++++++++++++++++- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/ip/iprule.c b/ip/iprule.c index 94356bf8..17df9e9b 100644 --- a/ip/iprule.c +++ b/ip/iprule.c @@ -47,6 +47,7 @@ static void usage(void) " [ iif STRING ] [ oif STRING ] [ pref NUMBER ] [ l3mdev ]\n" " [ uidrange NUMBER-NUMBER ]\n" "ACTION := [ table TABLE_ID ]\n" + " [ protocol PROTO ]\n" " [ nat ADDRESS ]\n" " [ realms [SRCREALM/]DSTREALM ]\n" " [ goto NUMBER ]\n" @@ -71,6 +72,8 @@ static struct struct fib_rule_uid_range range; inet_prefix src; inet_prefix dst; + int protocol; + int protocolmask; } filter; static inline int frh_get_table(struct fib_rule_hdr *frh, struct rtattr **tb) @@ -338,6 +341,16 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) rtnl_rtntype_n2a(frh->action, b1, sizeof(b1))); + if (tb[FRA_PROTOCOL]) { + __u8 protocol = rta_getattr_u8(tb[FRA_PROTOCOL]); + + if ((protocol && protocol != RTPROT_KERNEL) || + show_details > 0) { + fprintf(fp, " proto %s ", + rtnl_rtprot_n2a(protocol, b1, sizeof(b1))); + } + } + fprintf(fp, "\n"); fflush(fp); return 0; @@ -391,6 +404,10 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, parse_rtattr(tb, FRA_MAX, RTM_RTA(frh), len); + if (tb[FRA_PROTOCOL] && + (filter.protocol^rta_getattr_u8(tb[FRA_PROTOCOL]))&filter.protocolmask) + return 0; + if (tb[FRA_PRIORITY]) { n->nlmsg_type = RTM_DELRULE; n->nlmsg_flags = NLM_F_REQUEST; @@ -415,12 +432,6 @@ static int iprule_list_flush_or_save(int argc, char **argv, int action) if (af == AF_UNSPEC) af = AF_INET; - if (action != IPRULE_LIST && argc > 0) { - fprintf(stderr, "\"ip rule %s\" does not take any arguments.\n", - action == IPRULE_SAVE ? "save" : "flush"); - return -1; - } - switch (action) { case IPRULE_SAVE: if (save_rule_prep()) @@ -508,7 +519,18 @@ static int iprule_list_flush_or_save(int argc, char **argv, int action) NEXT_ARG(); if (get_prefix(&filter.src, *argv, af)) invarg("from value is invalid\n", *argv); - } else { + } else if (matches(*argv, "protocol") == 0) { + __u32 prot; + NEXT_ARG(); + filter.protocolmask = -1; + if (rtnl_rtprot_a2n(&prot, *argv)) { + if (strcmp(*argv, "all") != 0) + invarg("invalid \"protocol\"\n", *argv); + prot = 0; + filter.protocolmask = 0; + } + filter.protocol = prot; + } else{ if (matches(*argv, "dst") == 0 || matches(*argv, "to") == 0) { NEXT_ARG(); diff --git a/man/man8/ip-rule.8 b/man/man8/ip-rule.8 index a5c47981..f4070542 100644 --- a/man/man8/ip-rule.8 +++ b/man/man8/ip-rule.8 @@ -50,6 +50,8 @@ ip-rule \- routing policy database management .IR ACTION " := [ " .B table .IR TABLE_ID " ] [ " +.B protocol +.IR PROTO " ] [ " .B nat .IR ADDRESS " ] [ " .B realms @@ -240,6 +242,10 @@ The options preference and order are synonyms with priority. the routing table identifier to lookup if the rule selector matches. It is also possible to use lookup instead of table. +.TP +.BI protocol " PROTO" +the protocol who installed the rule in question. + .TP .BI suppress_prefixlength " NUMBER" reject routing decisions that have a prefix length of NUMBER or less. @@ -275,7 +281,11 @@ updates, it flushes the routing cache with .RE .TP .B ip rule flush - also dumps all the deleted rules. -This command has no arguments. +.RS +.TP +.BI protocol " PROTO" +Select the originating protocol. +.RE .TP .B ip rule show - list rules This command has no arguments. @@ -283,6 +293,12 @@ The options list or lst are synonyms with show. .TP .B ip rule save +.RS +.TP +.BI protocl " PROTO" +Select the originating protocol. +.RE +.TP save rules table information to stdout .RS This command behaves like -- 2.14.3