diff options
author | Rui Salvaterra <rsalvaterra@gmail.com> | 2020-07-31 10:10:36 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-10-03 22:08:39 +0200 |
commit | eecd6f7a6c44af48f1c70d383ac87e3200dc1233 (patch) | |
tree | b6a3a5993cd302c045bf4c24ae2b869852b9a2a0 | |
parent | 16e82c61d4db91e2e888600cdee7cf656ba4774c (diff) |
ip rule: add support for fwmark/fwmask for policy routing
This adds support for fwmark/fwmask in ip rule which is needed, for example, in
OpenWrt's mwan3. Masks are supported since Linux 2.6.19.
Fixes: https://bugs.busybox.net/show_bug.cgi?id=11621
Signed-off-by: Rui Salvaterra <rsalvaterra@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/ip.c | 2 | ||||
-rw-r--r-- | networking/libiproute/iprule.c | 32 |
2 files changed, 27 insertions, 7 deletions
diff --git a/networking/ip.c b/networking/ip.c index 7d3faf7f8..33bea5f49 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -252,7 +252,7 @@ //usage:#define iprule_trivial_usage //usage: "[list] | add|del SELECTOR ACTION" //usage:#define iprule_full_usage "\n\n" -//usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n" +//usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK[/MASK]]\n" //usage: " [dev IFACE] [pref NUMBER]\n" //usage: " ACTION := [table TABLE_ID] [nat ADDR]\n" //usage: " [prohibit|reject|unreachable]\n" diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c index 0ce0dfeef..50acfe4e7 100644 --- a/networking/libiproute/iprule.c +++ b/networking/libiproute/iprule.c @@ -17,8 +17,10 @@ #include <arpa/inet.h> /* from <linux/fib_rules.h>: */ -#define FRA_SUPPRESS_IFGROUP 13 -#define FRA_SUPPRESS_PREFIXLEN 14 +#define FRA_FWMARK 10 +#define FRA_SUPPRESS_IFGROUP 13 +#define FRA_SUPPRESS_PREFIXLEN 14 +#define FRA_FWMASK 16 #include "ip_common.h" /* #include "libbb.h" is inside */ #include "rt_names.h" @@ -117,8 +119,18 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM, if (r->rtm_tos) { printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos)); } - if (tb[RTA_PROTOINFO]) { - printf("fwmark %#x ", *(uint32_t*)RTA_DATA(tb[RTA_PROTOINFO])); + + if (tb[FRA_FWMARK] || tb[FRA_FWMASK]) { + uint32_t mark = 0, mask = 0; + + if (tb[FRA_FWMARK]) + mark = *(uint32_t*)RTA_DATA(tb[FRA_FWMARK]); + if (tb[FRA_FWMASK] + && (mask = *(uint32_t*)RTA_DATA(tb[FRA_FWMASK])) != 0xFFFFFFFF + ) + printf("fwmark %#x/%#x ", mark, mask); + else + printf("fwmark %#x ", mark); } if (tb[RTA_IIF]) { @@ -257,10 +269,18 @@ static int iprule_modify(int cmd, char **argv) invarg_1_to_2(*argv, "TOS"); req.r.rtm_tos = tos; } else if (key == ARG_fwmark) { - uint32_t fwmark; + char *slash; + uint32_t fwmark, fwmask; NEXT_ARG(); + slash = strchr(*argv, '/'); + if (slash) + *slash = '\0'; fwmark = get_u32(*argv, keyword_fwmark); - addattr32(&req.n, sizeof(req), RTA_PROTOINFO, fwmark); + addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark); + if (slash) { + fwmask = get_u32(slash + 1, "fwmask"); + addattr32(&req.n, sizeof(req), FRA_FWMASK, fwmask); + } } else if (key == ARG_realms) { uint32_t realm; NEXT_ARG(); |