diff mbox series

[v2] busybox: fix fwmark and add fwmask support to ip rule

Message ID 20200804081429.1032-1-rsalvaterra@gmail.com
State New
Headers show
Series [v2] busybox: fix fwmark and add fwmask support to ip rule | expand

Commit Message

Rui Salvaterra Aug. 4, 2020, 8:14 a.m. UTC
BusyBox ip (rule) applet supports fwmark for policy routing (albeit through the
old and deprecated RTA_PROTOINFO message attribute), but fwmask is completely
unsupported. For this reason, mwan3 depends on ip(-tiny), which compiles to
over 280 kiB on MIPS32 (-mips16 -mtune=74kc -O2).

This pending [1] BusyBox patch modernises the fwmark implementation (using the
FRA_FWMARK attribute) and also implements fwmask (FRA_FWMASK) required by mwan3,
allowing it to drop its dependecy on ip.

Other potential candidates for dropping their ip dependency (relying only on
BusyBox ip) are shadowsocks-libev, strongswan and vpn-policy-routing.

[1] http://lists.busybox.net/pipermail/busybox/2020-July/088164.html

Signed-off-by: Rui Salvaterra <rsalvaterra@gmail.com>
---
 package/utils/busybox/Makefile                |  2 +-
 .../302-ip-rule-add-support-for-fwmask.patch  | 90 +++++++++++++++++++
 2 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 package/utils/busybox/patches/302-ip-rule-add-support-for-fwmask.patch

Comments

Paul Spooren Aug. 4, 2020, 9:09 a.m. UTC | #1
Hi Rui,

On 03.08.20 22:14, Rui Salvaterra wrote:
> BusyBox ip (rule) applet supports fwmark for policy routing (albeit through the
> old and deprecated RTA_PROTOINFO message attribute), but fwmask is completely
> unsupported. For this reason, mwan3 depends on ip(-tiny), which compiles to
> over 280 kiB on MIPS32 (-mips16 -mtune=74kc -O2).
>
> This pending [1] BusyBox patch modernises the fwmark implementation (using the
> FRA_FWMARK attribute) and also implements fwmask (FRA_FWMASK) required by mwan3,
> allowing it to drop its dependecy on ip.
>
> Other potential candidates for dropping their ip dependency (relying only on
> BusyBox ip) are shadowsocks-libev, strongswan and vpn-policy-routing.
>
> [1] http://lists.busybox.net/pipermail/busybox/2020-July/088164.html
>
> Signed-off-by: Rui Salvaterra <rsalvaterra@gmail.com>

Not run-time tested but seem to compile fine on multiple architectures!

Size increase is between 70-140B[1].

What do you think about the PROVIDES idea of Yousong?

[1]: https://gitlab.com/aparcar/openwrt/-/jobs/669753470

> ---
>   package/utils/busybox/Makefile                |  2 +-
>   .../302-ip-rule-add-support-for-fwmask.patch  | 90 +++++++++++++++++++
>   2 files changed, 91 insertions(+), 1 deletion(-)
>   create mode 100644 package/utils/busybox/patches/302-ip-rule-add-support-for-fwmask.patch
>
> diff --git a/package/utils/busybox/Makefile b/package/utils/busybox/Makefile
> index 01441d1e87..baf375eb13 100644
> --- a/package/utils/busybox/Makefile
> +++ b/package/utils/busybox/Makefile
> @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
>   
>   PKG_NAME:=busybox
>   PKG_VERSION:=1.31.1
> -PKG_RELEASE:=1
> +PKG_RELEASE:=2
>   PKG_FLAGS:=essential
>   
>   PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
> diff --git a/package/utils/busybox/patches/302-ip-rule-add-support-for-fwmask.patch b/package/utils/busybox/patches/302-ip-rule-add-support-for-fwmask.patch
> new file mode 100644
> index 0000000000..abdc309068
> --- /dev/null
> +++ b/package/utils/busybox/patches/302-ip-rule-add-support-for-fwmask.patch
> @@ -0,0 +1,90 @@
> +From f06ac1e49b4a5a57660c7b370a7ebd436981bd89 Mon Sep 17 00:00:00 2001
> +From: Rui Salvaterra <rsalvaterra@gmail.com>
> +Date: Fri, 31 Jul 2020 09:59:40 +0100
> +Subject: [PATCH] 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>
> +---
> + networking/ip.c                |  2 +-
> + networking/libiproute/iprule.c | 31 +++++++++++++++++++++++++------
> + 2 files changed, 26 insertions(+), 7 deletions(-)
> +
> +diff --git a/networking/ip.c b/networking/ip.c
> +index 034ee4fc8..bade93e62 100644
> +--- a/networking/ip.c
> ++++ b/networking/ip.c
> +@@ -257,7 +257,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..40a09a4ab 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,17 @@ 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();
> ++			if ((slash = strchr(*argv, '/')) != NULL)
> ++				*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();
> +--
> +2.28.0
> +
diff mbox series

Patch

diff --git a/package/utils/busybox/Makefile b/package/utils/busybox/Makefile
index 01441d1e87..baf375eb13 100644
--- a/package/utils/busybox/Makefile
+++ b/package/utils/busybox/Makefile
@@ -9,7 +9,7 @@  include $(TOPDIR)/rules.mk
 
 PKG_NAME:=busybox
 PKG_VERSION:=1.31.1
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 PKG_FLAGS:=essential
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
diff --git a/package/utils/busybox/patches/302-ip-rule-add-support-for-fwmask.patch b/package/utils/busybox/patches/302-ip-rule-add-support-for-fwmask.patch
new file mode 100644
index 0000000000..abdc309068
--- /dev/null
+++ b/package/utils/busybox/patches/302-ip-rule-add-support-for-fwmask.patch
@@ -0,0 +1,90 @@ 
+From f06ac1e49b4a5a57660c7b370a7ebd436981bd89 Mon Sep 17 00:00:00 2001
+From: Rui Salvaterra <rsalvaterra@gmail.com>
+Date: Fri, 31 Jul 2020 09:59:40 +0100
+Subject: [PATCH] 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>
+---
+ networking/ip.c                |  2 +-
+ networking/libiproute/iprule.c | 31 +++++++++++++++++++++++++------
+ 2 files changed, 26 insertions(+), 7 deletions(-)
+
+diff --git a/networking/ip.c b/networking/ip.c
+index 034ee4fc8..bade93e62 100644
+--- a/networking/ip.c
++++ b/networking/ip.c
+@@ -257,7 +257,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..40a09a4ab 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,17 @@ 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();
++			if ((slash = strchr(*argv, '/')) != NULL)
++				*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();
+-- 
+2.28.0
+