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 <donaldsharp72@gmail.com>
Signed-off-by: Vladislav Grishenko <themiron@yandex-team.ru>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <20210416120708.1532-1-themiron@yandex-team.ru>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg22130.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit c7f95891a4a0aabb64e7d4f3200525c1a2fcf433)
... | ... |
@@ -426,6 +426,7 @@ typedef struct { |
426 | 426 |
inet_address_t gw; |
427 | 427 |
char iface[IFNAMSIZ]; |
428 | 428 |
bool default_only; |
429 |
+ unsigned int table; |
|
429 | 430 |
} route_res_t; |
430 | 431 |
|
431 | 432 |
static int |
... | ... |
@@ -435,7 +436,8 @@ sitnl_route_save(struct nlmsghdr *n, void *arg) |
435 | 435 |
struct rtmsg *r = NLMSG_DATA(n); |
436 | 436 |
struct rtattr *rta = RTM_RTA(r); |
437 | 437 |
int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)); |
438 |
- unsigned int ifindex = 0; |
|
438 |
+ unsigned int table, ifindex = 0; |
|
439 |
+ void *gw = NULL; |
|
439 | 440 |
|
440 | 441 |
/* filter-out non-zero dst prefixes */ |
441 | 442 |
if (res->default_only && r->rtm_dst_len != 0) |
... | ... |
@@ -443,6 +445,9 @@ sitnl_route_save(struct nlmsghdr *n, void *arg) |
443 | 443 |
return 1; |
444 | 444 |
} |
445 | 445 |
|
446 |
+ /* route table, ignored with RTA_TABLE */ |
|
447 |
+ table = r->rtm_table; |
|
448 |
+ |
|
446 | 449 |
while (RTA_OK(rta, len)) |
447 | 450 |
{ |
448 | 451 |
switch (rta->rta_type) |
... | ... |
@@ -458,13 +463,24 @@ sitnl_route_save(struct nlmsghdr *n, void *arg) |
458 | 458 |
|
459 | 459 |
/* GW for the route */ |
460 | 460 |
case RTA_GATEWAY: |
461 |
- memcpy(&res->gw, RTA_DATA(rta), res->addr_size); |
|
461 |
+ gw = RTA_DATA(rta); |
|
462 |
+ break; |
|
463 |
+ |
|
464 |
+ /* route table */ |
|
465 |
+ case RTA_TABLE: |
|
466 |
+ table = *(unsigned int *)RTA_DATA(rta); |
|
462 | 467 |
break; |
463 | 468 |
} |
464 | 469 |
|
465 | 470 |
rta = RTA_NEXT(rta, len); |
466 | 471 |
} |
467 | 472 |
|
473 |
+ /* filter out any route not coming from the selected table */ |
|
474 |
+ if (res->table && res->table != table) |
|
475 |
+ { |
|
476 |
+ return 1; |
|
477 |
+ } |
|
478 |
+ |
|
468 | 479 |
if (!if_indextoname(ifindex, res->iface)) |
469 | 480 |
{ |
470 | 481 |
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) |
472 | 472 |
return -1; |
473 | 473 |
} |
474 | 474 |
|
475 |
+ if (gw) |
|
476 |
+ { |
|
477 |
+ memcpy(&res->gw, gw, res->addr_size); |
|
478 |
+ } |
|
479 |
+ |
|
475 | 480 |
return 0; |
476 | 481 |
} |
477 | 482 |
|
... | ... |
@@ -507,6 +528,7 @@ sitnl_route_best_gw(sa_family_t af_family, const inet_address_t *dst, |
507 | 507 |
{ |
508 | 508 |
req.n.nlmsg_flags |= NLM_F_DUMP; |
509 | 509 |
res.default_only = true; |
510 |
+ res.table = RT_TABLE_MAIN; |
|
510 | 511 |
} |
511 | 512 |
else |
512 | 513 |
{ |