aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Salvaterra <rsalvaterra@gmail.com>2020-07-31 10:10:36 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-10-03 22:08:39 +0200
commiteecd6f7a6c44af48f1c70d383ac87e3200dc1233 (patch)
treeb6a3a5993cd302c045bf4c24ae2b869852b9a2a0
parent16e82c61d4db91e2e888600cdee7cf656ba4774c (diff)
downloadbusybox-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.c2
-rw-r--r--networking/libiproute/iprule.c32
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();