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) | |
download | busybox-w32-eecd6f7a6c44af48f1c70d383ac87e3200dc1233.tar.gz busybox-w32-eecd6f7a6c44af48f1c70d383ac87e3200dc1233.tar.bz2 busybox-w32-eecd6f7a6c44af48f1c70d383ac87e3200dc1233.zip |
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 @@ | |||
252 | //usage:#define iprule_trivial_usage | 252 | //usage:#define iprule_trivial_usage |
253 | //usage: "[list] | add|del SELECTOR ACTION" | 253 | //usage: "[list] | add|del SELECTOR ACTION" |
254 | //usage:#define iprule_full_usage "\n\n" | 254 | //usage:#define iprule_full_usage "\n\n" |
255 | //usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n" | 255 | //usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK[/MASK]]\n" |
256 | //usage: " [dev IFACE] [pref NUMBER]\n" | 256 | //usage: " [dev IFACE] [pref NUMBER]\n" |
257 | //usage: " ACTION := [table TABLE_ID] [nat ADDR]\n" | 257 | //usage: " ACTION := [table TABLE_ID] [nat ADDR]\n" |
258 | //usage: " [prohibit|reject|unreachable]\n" | 258 | //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 @@ | |||
17 | #include <arpa/inet.h> | 17 | #include <arpa/inet.h> |
18 | 18 | ||
19 | /* from <linux/fib_rules.h>: */ | 19 | /* from <linux/fib_rules.h>: */ |
20 | #define FRA_SUPPRESS_IFGROUP 13 | 20 | #define FRA_FWMARK 10 |
21 | #define FRA_SUPPRESS_PREFIXLEN 14 | 21 | #define FRA_SUPPRESS_IFGROUP 13 |
22 | #define FRA_SUPPRESS_PREFIXLEN 14 | ||
23 | #define FRA_FWMASK 16 | ||
22 | 24 | ||
23 | #include "ip_common.h" /* #include "libbb.h" is inside */ | 25 | #include "ip_common.h" /* #include "libbb.h" is inside */ |
24 | #include "rt_names.h" | 26 | #include "rt_names.h" |
@@ -117,8 +119,18 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM, | |||
117 | if (r->rtm_tos) { | 119 | if (r->rtm_tos) { |
118 | printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos)); | 120 | printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos)); |
119 | } | 121 | } |
120 | if (tb[RTA_PROTOINFO]) { | 122 | |
121 | printf("fwmark %#x ", *(uint32_t*)RTA_DATA(tb[RTA_PROTOINFO])); | 123 | if (tb[FRA_FWMARK] || tb[FRA_FWMASK]) { |
124 | uint32_t mark = 0, mask = 0; | ||
125 | |||
126 | if (tb[FRA_FWMARK]) | ||
127 | mark = *(uint32_t*)RTA_DATA(tb[FRA_FWMARK]); | ||
128 | if (tb[FRA_FWMASK] | ||
129 | && (mask = *(uint32_t*)RTA_DATA(tb[FRA_FWMASK])) != 0xFFFFFFFF | ||
130 | ) | ||
131 | printf("fwmark %#x/%#x ", mark, mask); | ||
132 | else | ||
133 | printf("fwmark %#x ", mark); | ||
122 | } | 134 | } |
123 | 135 | ||
124 | if (tb[RTA_IIF]) { | 136 | if (tb[RTA_IIF]) { |
@@ -257,10 +269,18 @@ static int iprule_modify(int cmd, char **argv) | |||
257 | invarg_1_to_2(*argv, "TOS"); | 269 | invarg_1_to_2(*argv, "TOS"); |
258 | req.r.rtm_tos = tos; | 270 | req.r.rtm_tos = tos; |
259 | } else if (key == ARG_fwmark) { | 271 | } else if (key == ARG_fwmark) { |
260 | uint32_t fwmark; | 272 | char *slash; |
273 | uint32_t fwmark, fwmask; | ||
261 | NEXT_ARG(); | 274 | NEXT_ARG(); |
275 | slash = strchr(*argv, '/'); | ||
276 | if (slash) | ||
277 | *slash = '\0'; | ||
262 | fwmark = get_u32(*argv, keyword_fwmark); | 278 | fwmark = get_u32(*argv, keyword_fwmark); |
263 | addattr32(&req.n, sizeof(req), RTA_PROTOINFO, fwmark); | 279 | addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark); |
280 | if (slash) { | ||
281 | fwmask = get_u32(slash + 1, "fwmask"); | ||
282 | addattr32(&req.n, sizeof(req), FRA_FWMASK, fwmask); | ||
283 | } | ||
264 | } else if (key == ARG_realms) { | 284 | } else if (key == ARG_realms) { |
265 | uint32_t realm; | 285 | uint32_t realm; |
266 | NEXT_ARG(); | 286 | NEXT_ARG(); |