diff options
Diffstat (limited to 'networking')
-rw-r--r-- | networking/libiproute/iprule.c | 73 |
1 files changed, 46 insertions, 27 deletions
diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c index 8f3f86286..1bb5e759e 100644 --- a/networking/libiproute/iprule.c +++ b/networking/libiproute/iprule.c @@ -17,25 +17,32 @@ #include <netinet/ip.h> #include <arpa/inet.h> +/* from <linux/fib_rules.h>: */ +#define FRA_SUPPRESS_IFGROUP 13 +#define FRA_SUPPRESS_PREFIXLEN 14 + #include "ip_common.h" /* #include "libbb.h" is inside */ #include "rt_names.h" #include "utils.h" -/* -static void usage(void) __attribute__((noreturn)); - -static void usage(void) -{ - fprintf(stderr, "Usage: ip rule [ list | add | del ] SELECTOR ACTION\n"); - fprintf(stderr, "SELECTOR := [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK ]\n"); - fprintf(stderr, " [ dev STRING ] [ pref NUMBER ]\n"); - fprintf(stderr, "ACTION := [ table TABLE_ID ] [ nat ADDRESS ]\n"); - fprintf(stderr, " [ prohibit | reject | unreachable ]\n"); - fprintf(stderr, " [ realms [SRCREALM/]DSTREALM ]\n"); - fprintf(stderr, "TABLE_ID := [ local | main | default | NUMBER ]\n"); - exit(-1); -} -*/ +/* If you add stuff here, update iprule_full_usage */ +static const char keywords[] ALIGN1 = + "from\0""to\0""preference\0""order\0""priority\0" + "tos\0""fwmark\0""realms\0""table\0""lookup\0" + "suppress_prefixlength\0""suppress_ifgroup\0" + "dev\0""iif\0""nat\0""map-to\0""type\0""help\0" + ; +#define keyword_preference (keywords + sizeof("from") + sizeof("to")) +#define keyword_fwmark (keyword_preference + sizeof("preference") + sizeof("order") + sizeof("priority") + sizeof("tos")) +#define keyword_realms (keyword_fwmark + sizeof("fwmark")) +#define keyword_suppress_prefixlength (keyword_realms + sizeof("realms") + sizeof("table") + sizeof("lookup")) +#define keyword_suppress_ifgroup (keyword_suppress_prefixlength + sizeof("suppress_prefixlength")) +enum { + ARG_from = 1, ARG_to, ARG_preference, ARG_order, ARG_priority, + ARG_tos, ARG_fwmark, ARG_realms, ARG_table, ARG_lookup, + ARG_suppress_prefixlength, ARG_suppress_ifgroup, + ARG_dev, ARG_iif, ARG_nat, ARG_map_to, ARG_type, ARG_help, +}; static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM, struct nlmsghdr *n, void *arg UNUSED_PARAM) @@ -119,6 +126,17 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM, else if (r->rtm_table) printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table)); + if (tb[FRA_SUPPRESS_PREFIXLEN]) { + int pl = *(uint32_t*)RTA_DATA(tb[FRA_SUPPRESS_PREFIXLEN]); + if (pl != -1) + printf("%s %d ", keyword_suppress_prefixlength, pl); + } + if (tb[FRA_SUPPRESS_IFGROUP]) { + int grp = *(uint32_t*)RTA_DATA(tb[FRA_SUPPRESS_IFGROUP]); + if (grp != -1) + printf("%s %d ", keyword_suppress_ifgroup, grp); + } + if (tb[RTA_FLOW]) { uint32_t to = *(uint32_t*)RTA_DATA(tb[RTA_FLOW]); uint32_t from = to>>16; @@ -174,15 +192,6 @@ static int iprule_list(char **argv) /* Return value becomes exitcode. It's okay to not return at all */ static int iprule_modify(int cmd, char **argv) { - static const char keywords[] ALIGN1 = - "from\0""to\0""preference\0""order\0""priority\0" - "tos\0""fwmark\0""realms\0""table\0""lookup\0""dev\0" - "iif\0""nat\0""map-to\0""type\0""help\0"; - enum { - ARG_from = 1, ARG_to, ARG_preference, ARG_order, ARG_priority, - ARG_tos, ARG_fwmark, ARG_realms, ARG_table, ARG_lookup, ARG_dev, - ARG_iif, ARG_nat, ARG_map_to, ARG_type, ARG_help - }; bool table_ok = 0; struct rtnl_handle rth; struct { @@ -232,7 +241,7 @@ static int iprule_modify(int cmd, char **argv) ) { uint32_t pref; NEXT_ARG(); - pref = get_u32(*argv, "preference"); + pref = get_u32(*argv, keyword_preference); addattr32(&req.n, sizeof(req), RTA_PRIORITY, pref); } else if (key == ARG_tos) { uint32_t tos; @@ -243,13 +252,13 @@ static int iprule_modify(int cmd, char **argv) } else if (key == ARG_fwmark) { uint32_t fwmark; NEXT_ARG(); - fwmark = get_u32(*argv, "fwmark"); + fwmark = get_u32(*argv, keyword_fwmark); addattr32(&req.n, sizeof(req), RTA_PROTOINFO, fwmark); } else if (key == ARG_realms) { uint32_t realm; NEXT_ARG(); if (get_rt_realms(&realm, *argv)) - invarg_1_to_2(*argv, "realms"); + invarg_1_to_2(*argv, keyword_realms); addattr32(&req.n, sizeof(req), RTA_FLOW, realm); } else if (key == ARG_table || key == ARG_lookup @@ -265,6 +274,16 @@ static int iprule_modify(int cmd, char **argv) addattr32(&req.n, sizeof(req), RTA_TABLE, tid); } table_ok = 1; + } else if (key == ARG_suppress_prefixlength) { + int prefix_length; + NEXT_ARG(); + prefix_length = get_u32(*argv, keyword_suppress_prefixlength); + addattr32(&req.n, sizeof(req), FRA_SUPPRESS_PREFIXLEN, prefix_length); + } else if (key == ARG_suppress_ifgroup) { + int grp; + NEXT_ARG(); + grp = get_u32(*argv, keyword_suppress_ifgroup); + addattr32(&req.n, sizeof(req), FRA_SUPPRESS_IFGROUP, grp); } else if (key == ARG_dev || key == ARG_iif ) { |