Skip to content

Commit 9a08f36

Browse files
Fix pref-src on route change
When two similar routes with pref-src were switched, the pref-src was not updated to the new one. With this fix, switch_routes passes the new->src to change_route, which is used to reapply the install_filter and retrieve the newpref_src from the filter_result. kernel_route for netlink has been updated to support the newpref_src on ROUTE_MODIFY
1 parent 893834d commit 9a08f36

4 files changed

Lines changed: 32 additions & 15 deletions

File tree

kernel.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ int kernel_route(int operation, int table,
8585
const unsigned char *pref_src,
8686
const unsigned char *gate, int ifindex, unsigned int metric,
8787
const unsigned char *newgate, int newifindex,
88-
unsigned int newmetric, int newtable);
88+
unsigned int newmetric, int newtable,
89+
const unsigned char *newpref_src);
8990
int kernel_dump(int operation, struct kernel_filter *filter);
9091
int kernel_callback(struct kernel_filter *filter);
9192
int if_eui64(char *ifname, int ifindex, unsigned char *eui);

kernel_netlink.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,8 @@ kernel_route(int operation, int table,
959959
const unsigned char *pref_src,
960960
const unsigned char *gate, int ifindex, unsigned int metric,
961961
const unsigned char *newgate, int newifindex,
962-
unsigned int newmetric, int newtable)
962+
unsigned int newmetric, int newtable,
963+
const unsigned char *newpref_src)
963964
{
964965
union { char raw[1024]; struct nlmsghdr nh; } buf;
965966
struct rtmsg *rtm;
@@ -1011,11 +1012,11 @@ kernel_route(int operation, int table,
10111012
kernel_route(ROUTE_FLUSH, table, dest, plen,
10121013
src, src_plen, pref_src,
10131014
gate, ifindex, metric,
1014-
NULL, 0, 0, 0);
1015+
NULL, 0, 0, 0, NULL);
10151016
rc = kernel_route(ROUTE_ADD, newtable, dest, plen,
1016-
src, src_plen, pref_src,
1017+
src, src_plen, newpref_src,
10171018
newgate, newifindex, newmetric,
1018-
NULL, 0, 0, 0);
1019+
NULL, 0, 0, 0, NULL);
10191020
if(rc < 0) {
10201021
if(errno == EEXIST)
10211022
rc = 1;

kernel_socket.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,8 @@ kernel_route(int operation, int table,
407407
const unsigned char *pref_src,
408408
const unsigned char *gate, int ifindex, unsigned int metric,
409409
const unsigned char *newgate, int newifindex,
410-
unsigned int newmetric, int newtable)
410+
unsigned int newmetric, int newtable,
411+
const unsigned char *newpref_src)
411412
{
412413
struct {
413414
struct rt_msghdr m_rtm;
@@ -423,7 +424,7 @@ kernel_route(int operation, int table,
423424

424425
/* Source-specific routes & preferred source IPs
425426
* are not implemented yet for BSD. */
426-
if((!is_default(src, src_plen)) || pref_src) {
427+
if((!is_default(src, src_plen)) || pref_src || newpref_src) {
427428
errno = ENOSYS;
428429
return -1;
429430
}
@@ -454,11 +455,11 @@ kernel_route(int operation, int table,
454455
kernel_route(ROUTE_FLUSH, table, dest, plen,
455456
src, src_plen, NULL,
456457
gate, ifindex, metric,
457-
NULL, 0, 0, 0);
458+
NULL, 0, 0, 0, NULL);
458459
return kernel_route(ROUTE_ADD, table, dest, plen,
459460
src, src_plen, NULL,
460461
newgate, newifindex, newmetric,
461-
NULL, 0, 0, 0);
462+
NULL, 0, 0, 0, NULL);
462463

463464
}
464465

route.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -439,10 +439,12 @@ move_installed_route(struct babel_route *route, int i)
439439
static int
440440
change_route(int operation, const struct babel_route *route, int metric,
441441
const unsigned char *new_next_hop,
442-
int new_ifindex, int new_metric)
442+
int new_ifindex, int new_metric,
443+
const struct source *newsrc)
443444
{
444445
struct filter_result filter_result;
445446
unsigned char *pref_src = NULL;
447+
unsigned char *newpref_src = NULL;
446448
unsigned int ifindex = route->neigh->ifp->ifindex;
447449
int m, table;
448450

@@ -456,13 +458,24 @@ change_route(int operation, const struct babel_route *route, int metric,
456458
}
457459

458460
pref_src = filter_result.pref_src;
461+
newpref_src = pref_src;
459462
table = filter_result.table ? filter_result.table : export_table;
460463

464+
if(newsrc) {
465+
m = install_filter(newsrc->id,
466+
newsrc->prefix, newsrc->plen,
467+
newsrc->src_prefix, newsrc->src_plen,
468+
new_ifindex, &filter_result);
469+
if(m < INFINITY && filter_result.pref_src)
470+
newpref_src = filter_result.pref_src;
471+
}
472+
461473
return kernel_route(operation, table, route->src->prefix, route->src->plen,
462474
route->src->src_prefix, route->src->src_plen, pref_src,
463475
route->nexthop, ifindex,
464476
metric, new_next_hop, new_ifindex, new_metric,
465-
operation == ROUTE_MODIFY ? table : 0);
477+
operation == ROUTE_MODIFY ? table : 0,
478+
newpref_src);
466479
}
467480

468481
void
@@ -491,7 +504,7 @@ install_route(struct babel_route *route)
491504
format_prefix(route->src->prefix, route->src->plen),
492505
format_prefix(route->src->src_prefix, route->src->src_plen));
493506
rc = change_route(ROUTE_ADD, route, metric_to_kernel(route_metric(route)),
494-
NULL, 0, 0);
507+
NULL, 0, 0, NULL);
495508
if(rc < 0 && errno != EEXIST) {
496509
perror("kernel_route(ADD)");
497510
return;
@@ -517,7 +530,7 @@ uninstall_route(struct babel_route *route)
517530
format_prefix(route->src->prefix, route->src->plen),
518531
format_prefix(route->src->src_prefix, route->src->src_plen));
519532
rc = change_route(ROUTE_FLUSH, route, metric_to_kernel(route_metric(route)),
520-
NULL, 0, 0);
533+
NULL, 0, 0, NULL);
521534
if(rc < 0) {
522535
perror("kernel_route(FLUSH)");
523536
return;
@@ -551,7 +564,8 @@ switch_routes(struct babel_route *old, struct babel_route *new)
551564
format_prefix(old->src->src_prefix, old->src->src_plen));
552565
rc = change_route(ROUTE_MODIFY, old, metric_to_kernel(route_metric(old)),
553566
new->nexthop, new->neigh->ifp->ifindex,
554-
metric_to_kernel(route_metric(new)));
567+
metric_to_kernel(route_metric(new)),
568+
new->src);
555569
if(rc < 0) {
556570
perror("kernel_route(MODIFY)");
557571
return;
@@ -581,7 +595,7 @@ change_route_metric(struct babel_route *route,
581595
format_prefix(route->src->src_prefix, route->src->src_plen),
582596
old_metric, new_metric);
583597
rc = change_route(ROUTE_MODIFY, route, old_metric, route->nexthop,
584-
route->neigh->ifp->ifindex, new_metric);
598+
route->neigh->ifp->ifindex, new_metric, NULL);
585599
if(rc < 0) {
586600
perror("kernel_route(MODIFY metric)");
587601
return;

0 commit comments

Comments
 (0)