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

Rui Salvaterra rsalvaterra at gmail.com
Wed Sep 23 19:41:20 UTC 2020


Ping^2

On Fri, 31 Jul 2020 at 10:11, Rui Salvaterra <rsalvaterra at gmail.com> wrote:
>
> 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>
> ---
>  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
>


More information about the busybox mailing list