Hi,

On 16/04/2021 14:07, Vladislav Grishenko wrote:
> Current default gateway selection for zero destination address just
> dumps and parses all the routing tables. If any of non-main table
> with default route comes first, wrong default gateway can be picked.
> Since adding/removing routes currently handles only main table,
> let's stick to RT_TABLE_MAIN while selecting default route too.
> 
> v2: keep gateway address unchanged on lookup error
> v3: reduce ammout of gateway address copying
> 
> Reported-by: Donald Sharp <donaldshar...@gmail.com>
> Signed-off-by: Vladislav Grishenko <themi...@yandex-team.ru>
> ---
>  src/openvpn/networking_sitnl.c | 26 ++++++++++++++++++++++++--
>  1 file changed, 24 insertions(+), 2 deletions(-)
> 
> diff --git a/src/openvpn/networking_sitnl.c b/src/openvpn/networking_sitnl.c
> index 2bc70a50..ea1621ed 100644
> --- a/src/openvpn/networking_sitnl.c
> +++ b/src/openvpn/networking_sitnl.c
> @@ -426,6 +426,7 @@ typedef struct {
>      inet_address_t gw;
>      char iface[IFNAMSIZ];
>      bool default_only;
> +    unsigned int table;
>  } route_res_t;
>  
>  static int
> @@ -435,7 +436,8 @@ sitnl_route_save(struct nlmsghdr *n, void *arg)
>      struct rtmsg *r = NLMSG_DATA(n);
>      struct rtattr *rta = RTM_RTA(r);
>      int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r));
> -    unsigned int ifindex = 0;
> +    unsigned int table, ifindex = 0;
> +    void *gw = NULL;
>  
>      /* filter-out non-zero dst prefixes */
>      if (res->default_only && r->rtm_dst_len != 0)
> @@ -443,6 +445,9 @@ sitnl_route_save(struct nlmsghdr *n, void *arg)
>          return 1;
>      }
>  
> +    /* route table, ignored with RTA_TABLE */
> +    table = r->rtm_table;
> +
>      while (RTA_OK(rta, len))
>      {
>          switch (rta->rta_type)
> @@ -458,13 +463,24 @@ sitnl_route_save(struct nlmsghdr *n, void *arg)
>  
>              /* GW for the route */
>              case RTA_GATEWAY:
> -                memcpy(&res->gw, RTA_DATA(rta), res->addr_size);
> +                gw = RTA_DATA(rta);
> +                break;
> +
> +            /* route table */
> +            case RTA_TABLE:
> +                table = *(unsigned int *)RTA_DATA(rta);
>                  break;
>          }
>  
>          rta = RTA_NEXT(rta, len);
>      }
>  
> +    /* filter out any route not coming from the selected table */
> +    if (res->table && res->table != table)

Today I was wondering if 0 could be a meaningful table ID, since this
code uses 0 as "no table was selected for filtering" (thus creating a
false negative).

After checking rtnetlink.h, I could see that 0 is indeed the UNSPEC
value (RT_TABLE_UNSPEC=0), therefore your patch is correct.

However, to prevent the next casual reader from asking the same
question, wouldn't it make sense to change this comparison with:

if (res->table != RT_TABLE_UNSPEC && res->table != table)


> +    {
> +        return 1;
> +    }
> +
>      if (!if_indextoname(ifindex, res->iface))
>      {
>          msg(M_WARN | M_ERRNO, "%s: rtnl: can't get ifname for index %d",
> @@ -472,6 +488,11 @@ sitnl_route_save(struct nlmsghdr *n, void *arg)
>          return -1;
>      }
>  
> +    if (gw)
> +    {
> +        memcpy(&res->gw, gw, res->addr_size);
> +    }
> +
>      return 0;
>  }
>  
> @@ -507,6 +528,7 @@ sitnl_route_best_gw(sa_family_t af_family, const 
> inet_address_t *dst,
>              {
>                  req.n.nlmsg_flags |= NLM_F_DUMP;
>                  res.default_only = true;
> +                res.table = RT_TABLE_MAIN;

Another question: why restricting the research to the MAIN table only
for IPv4 and only when searching a default route?

Like you said in the commit message: OpenVPN only operates on the MAIN
routing table for the time being, therefore, shouldn't we just set
"res.table = RT_TABLE_MAIN" by default *all the time* for now?

Otherwise we are fixing this problem only for the ipv4/default search,
but the function remains "buggy" for the other cases.


>              }
>              else
>              {
> 


Regards,

-- 
Antonio Quartulli


_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to