[git commit] ip rule: add support for fwmark/fwmask for policy routing

Denys Vlasenko vda.linux at googlemail.com
Sat Oct 3 20:08:39 UTC 2020


commit: https://git.busybox.net/busybox/commit/?id=eecd6f7a6c44af48f1c70d383ac87e3200dc1233
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/ip.c                |  2 +-
 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();


More information about the busybox-cvs mailing list