From f585166c566c26cdff6cc35fff3c736786a3b456 Mon Sep 17 00:00:00 2001 From: Gaspare Iengo Date: Sun, 3 Mar 2024 20:37:57 +0000 Subject: [PATCH 1/6] Added Visual Studio Code directory to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4e888447..afcd3145 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ tags *.orig *~ \#*# +.vscode/ From 893834d48a07a5a5479dbd2db8f43d0b8a1a275f Mon Sep 17 00:00:00 2001 From: Gaspare Iengo Date: Sun, 3 Mar 2024 21:03:16 +0000 Subject: [PATCH 2/6] Added router id to install filter The router id allows to assign origin-based pref-src. A use case is, when installing default routes originated by two edge routers with different subnets, and the client has 2 ips matching the separate subnets install ip 0.0.0.0/0 eq 0 id 00:02:00:00:00:00:1d:01 pref-src 66.199.5.163 install ip 0.0.0.0/0 eq 0 id 00:02:00:00:00:00:1d:00 pref-src 12.144.66.186 --- configuration.c | 5 +++-- configuration.h | 3 ++- route.c | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/configuration.c b/configuration.c index 045d3043..297bbb0f 100644 --- a/configuration.c +++ b/configuration.c @@ -1503,13 +1503,14 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen, } int -install_filter(const unsigned char *prefix, unsigned short plen, +install_filter(const unsigned char *id, + const unsigned char *prefix, unsigned short plen, const unsigned char *src_prefix, unsigned short src_plen, unsigned int ifindex, struct filter_result *result) { int res; - res = do_filter(install_filters, NULL, prefix, plen, + res = do_filter(install_filters, id, prefix, plen, src_prefix, src_plen, NULL, ifindex, 0, result); if(res < 0) res = INFINITY; diff --git a/configuration.h b/configuration.h index 95ce16cc..4e10fa00 100644 --- a/configuration.h +++ b/configuration.h @@ -84,7 +84,8 @@ int redistribute_filter(const unsigned char *prefix, unsigned short plen, const unsigned char *src_prefix, unsigned short src_plen, unsigned int ifindex, int proto, struct filter_result *result); -int install_filter(const unsigned char *prefix, unsigned short plen, +int install_filter(const unsigned char *id, + const unsigned char *prefix, unsigned short plen, const unsigned char *src_prefix, unsigned short src_plen, unsigned int ifindex, struct filter_result *result); int finalise_config(void); diff --git a/route.c b/route.c index fa5bf30a..cf2dcedf 100644 --- a/route.c +++ b/route.c @@ -446,7 +446,8 @@ change_route(int operation, const struct babel_route *route, int metric, unsigned int ifindex = route->neigh->ifp->ifindex; int m, table; - m = install_filter(route->src->prefix, route->src->plen, + m = install_filter(route->src->id, + route->src->prefix, route->src->plen, route->src->src_prefix, route->src->src_plen, ifindex, &filter_result); if(m >= INFINITY && operation == ROUTE_ADD) { From 9a08f36165a4a3b0c745323fbaabc70ef49a122e Mon Sep 17 00:00:00 2001 From: Gaspare Iengo Date: Sun, 3 Mar 2024 21:21:37 +0000 Subject: [PATCH 3/6] 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 --- kernel.h | 3 ++- kernel_netlink.c | 9 +++++---- kernel_socket.c | 9 +++++---- route.c | 26 ++++++++++++++++++++------ 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/kernel.h b/kernel.h index 94bcb4fb..56060d1a 100644 --- a/kernel.h +++ b/kernel.h @@ -85,7 +85,8 @@ int kernel_route(int operation, int table, const unsigned char *pref_src, const unsigned char *gate, int ifindex, unsigned int metric, const unsigned char *newgate, int newifindex, - unsigned int newmetric, int newtable); + unsigned int newmetric, int newtable, + const unsigned char *newpref_src); int kernel_dump(int operation, struct kernel_filter *filter); int kernel_callback(struct kernel_filter *filter); int if_eui64(char *ifname, int ifindex, unsigned char *eui); diff --git a/kernel_netlink.c b/kernel_netlink.c index 6ee991d8..5de9cc04 100644 --- a/kernel_netlink.c +++ b/kernel_netlink.c @@ -959,7 +959,8 @@ kernel_route(int operation, int table, const unsigned char *pref_src, const unsigned char *gate, int ifindex, unsigned int metric, const unsigned char *newgate, int newifindex, - unsigned int newmetric, int newtable) + unsigned int newmetric, int newtable, + const unsigned char *newpref_src) { union { char raw[1024]; struct nlmsghdr nh; } buf; struct rtmsg *rtm; @@ -1011,11 +1012,11 @@ kernel_route(int operation, int table, kernel_route(ROUTE_FLUSH, table, dest, plen, src, src_plen, pref_src, gate, ifindex, metric, - NULL, 0, 0, 0); + NULL, 0, 0, 0, NULL); rc = kernel_route(ROUTE_ADD, newtable, dest, plen, - src, src_plen, pref_src, + src, src_plen, newpref_src, newgate, newifindex, newmetric, - NULL, 0, 0, 0); + NULL, 0, 0, 0, NULL); if(rc < 0) { if(errno == EEXIST) rc = 1; diff --git a/kernel_socket.c b/kernel_socket.c index 9ffa2f53..f96e6b5c 100644 --- a/kernel_socket.c +++ b/kernel_socket.c @@ -407,7 +407,8 @@ kernel_route(int operation, int table, const unsigned char *pref_src, const unsigned char *gate, int ifindex, unsigned int metric, const unsigned char *newgate, int newifindex, - unsigned int newmetric, int newtable) + unsigned int newmetric, int newtable, + const unsigned char *newpref_src) { struct { struct rt_msghdr m_rtm; @@ -423,7 +424,7 @@ kernel_route(int operation, int table, /* Source-specific routes & preferred source IPs * are not implemented yet for BSD. */ - if((!is_default(src, src_plen)) || pref_src) { + if((!is_default(src, src_plen)) || pref_src || newpref_src) { errno = ENOSYS; return -1; } @@ -454,11 +455,11 @@ kernel_route(int operation, int table, kernel_route(ROUTE_FLUSH, table, dest, plen, src, src_plen, NULL, gate, ifindex, metric, - NULL, 0, 0, 0); + NULL, 0, 0, 0, NULL); return kernel_route(ROUTE_ADD, table, dest, plen, src, src_plen, NULL, newgate, newifindex, newmetric, - NULL, 0, 0, 0); + NULL, 0, 0, 0, NULL); } diff --git a/route.c b/route.c index cf2dcedf..b316ef7a 100644 --- a/route.c +++ b/route.c @@ -439,10 +439,12 @@ move_installed_route(struct babel_route *route, int i) static int change_route(int operation, const struct babel_route *route, int metric, const unsigned char *new_next_hop, - int new_ifindex, int new_metric) + int new_ifindex, int new_metric, + const struct source *newsrc) { struct filter_result filter_result; unsigned char *pref_src = NULL; + unsigned char *newpref_src = NULL; unsigned int ifindex = route->neigh->ifp->ifindex; int m, table; @@ -456,13 +458,24 @@ change_route(int operation, const struct babel_route *route, int metric, } pref_src = filter_result.pref_src; + newpref_src = pref_src; table = filter_result.table ? filter_result.table : export_table; + if(newsrc) { + m = install_filter(newsrc->id, + newsrc->prefix, newsrc->plen, + newsrc->src_prefix, newsrc->src_plen, + new_ifindex, &filter_result); + if(m < INFINITY && filter_result.pref_src) + newpref_src = filter_result.pref_src; + } + return kernel_route(operation, table, route->src->prefix, route->src->plen, route->src->src_prefix, route->src->src_plen, pref_src, route->nexthop, ifindex, metric, new_next_hop, new_ifindex, new_metric, - operation == ROUTE_MODIFY ? table : 0); + operation == ROUTE_MODIFY ? table : 0, + newpref_src); } void @@ -491,7 +504,7 @@ install_route(struct babel_route *route) format_prefix(route->src->prefix, route->src->plen), format_prefix(route->src->src_prefix, route->src->src_plen)); rc = change_route(ROUTE_ADD, route, metric_to_kernel(route_metric(route)), - NULL, 0, 0); + NULL, 0, 0, NULL); if(rc < 0 && errno != EEXIST) { perror("kernel_route(ADD)"); return; @@ -517,7 +530,7 @@ uninstall_route(struct babel_route *route) format_prefix(route->src->prefix, route->src->plen), format_prefix(route->src->src_prefix, route->src->src_plen)); rc = change_route(ROUTE_FLUSH, route, metric_to_kernel(route_metric(route)), - NULL, 0, 0); + NULL, 0, 0, NULL); if(rc < 0) { perror("kernel_route(FLUSH)"); return; @@ -551,7 +564,8 @@ switch_routes(struct babel_route *old, struct babel_route *new) format_prefix(old->src->src_prefix, old->src->src_plen)); rc = change_route(ROUTE_MODIFY, old, metric_to_kernel(route_metric(old)), new->nexthop, new->neigh->ifp->ifindex, - metric_to_kernel(route_metric(new))); + metric_to_kernel(route_metric(new)), + new->src); if(rc < 0) { perror("kernel_route(MODIFY)"); return; @@ -581,7 +595,7 @@ change_route_metric(struct babel_route *route, format_prefix(route->src->src_prefix, route->src->src_plen), old_metric, new_metric); rc = change_route(ROUTE_MODIFY, route, old_metric, route->nexthop, - route->neigh->ifp->ifindex, new_metric); + route->neigh->ifp->ifindex, new_metric, NULL); if(rc < 0) { perror("kernel_route(MODIFY metric)"); return; From 7a90164be59e3c57f2364c32de584b85c571bda4 Mon Sep 17 00:00:00 2001 From: Gaspare Iengo Date: Mon, 4 Mar 2024 12:40:48 +0000 Subject: [PATCH 4/6] Added metric update for redistribute filter It allows to change the metric of an existing redistribute filter using the live config --- configuration.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/configuration.c b/configuration.c index 297bbb0f..bfc9e484 100644 --- a/configuration.c +++ b/configuration.c @@ -64,6 +64,8 @@ static int config_finalised = 0; /* get_next_char callback */ typedef int (*gnc_t)(void*); +static int update_filter(struct filter *f, struct filter *newf); + static int skip_whitespace(int c, gnc_t gnc, void *closure) { @@ -1177,12 +1179,19 @@ parse_config_line(int c, gnc_t gnc, void *closure, add_filter(filter, FILTER_TYPE_OUTPUT); } else if(strcmp(token, "redistribute") == 0) { struct filter *filter; - if(config_finalised) - goto fail; c = parse_filter(c, gnc, closure, &filter); if(c < -1) goto fail; - add_filter(filter, FILTER_TYPE_REDISTRIBUTE); + if(config_finalised) { + if(!action_return) + goto fail; + c = update_filter(redistribute_filters, filter); + free_filter(filter); + if(c < -1) + goto fail; + } else { + add_filter(filter, FILTER_TYPE_REDISTRIBUTE); + } } else if(strcmp(token, "install") == 0) { struct filter *filter; if(config_finalised) @@ -1460,6 +1469,23 @@ do_filter(struct filter *f, const unsigned char *id, return -1; } +static int +update_filter(struct filter *f, struct filter *newf) +{ + while(f) { + if(filter_match(f, newf->id, newf->prefix, newf->plen, newf->src_prefix, newf->src_plen, + newf->neigh, newf->ifindex, newf->proto)) { + f->action.add_metric = newf->action.add_metric; + // f->action.table = newf->action.table; + // memcpy(f->action.pref_src, newf->action.pref_src, 16); + return -1; + } + f = f->next; + } + + return 0; +} + int input_filter(const unsigned char *id, const unsigned char *prefix, unsigned short plen, From 9a709e04c3d4b44e8ff74c7771509c8a2517c9ff Mon Sep 17 00:00:00 2001 From: Gaspare Iengo Date: Mon, 4 Mar 2024 12:43:03 +0000 Subject: [PATCH 5/6] Added check_infinity to check_xroutes Allows to send an update of a redistribute metric changed to INFINITY It adds a command check_xroutes that does not ignore the INFINITY metric of kernel routes --- babeld.c | 4 ++-- configuration.c | 5 +++++ configuration.h | 1 + local.c | 6 ++++++ xroute.c | 6 ++++-- xroute.h | 2 +- 6 files changed, 19 insertions(+), 5 deletions(-) diff --git a/babeld.c b/babeld.c index b0b7f55d..46b5a6b4 100644 --- a/babeld.c +++ b/babeld.c @@ -514,7 +514,7 @@ main(int argc, char **argv) check_interfaces(); - rc = check_xroutes(0, 0); + rc = check_xroutes(0, 0, 0); if(rc < 0) fprintf(stderr, "Warning: couldn't check exported routes.\n"); @@ -684,7 +684,7 @@ main(int argc, char **argv) if(kernel_addr_changed || (kernel_check_interval > 0 && now.tv_sec >= kernel_dump_time)) { - rc = check_xroutes(1, !kernel_addr_changed); + rc = check_xroutes(1, !kernel_addr_changed, 0); if(rc < 0) fprintf(stderr, "Warning: couldn't check exported routes.\n"); kernel_addr_changed = 0; diff --git a/configuration.c b/configuration.c index bfc9e484..e5fc6f70 100644 --- a/configuration.c +++ b/configuration.c @@ -1265,6 +1265,11 @@ parse_config_line(int c, gnc_t gnc, void *closure, goto fail; add_key(key->id, key->type, key->len, key->value); free(key); + } else if(strcmp(token, "check_xroutes") == 0) { + c = skip_eol(c, gnc, closure); + if(c < -1 || !action_return) + goto fail; + *action_return = CONFIG_ACTION_CHECK_XROUTES; } else { c = parse_option(c, gnc, closure, token); if(c < -1) diff --git a/configuration.h b/configuration.h index 4e10fa00..f99a2e63 100644 --- a/configuration.h +++ b/configuration.h @@ -28,6 +28,7 @@ THE SOFTWARE. #define CONFIG_ACTION_MONITOR 3 #define CONFIG_ACTION_UNMONITOR 4 #define CONFIG_ACTION_NO 5 +#define CONFIG_ACTION_CHECK_XROUTES 6 #define AUTH_TYPE_NONE 0 #define AUTH_TYPE_SHA256 1 diff --git a/local.c b/local.c index d4103c44..facdc143 100644 --- a/local.c +++ b/local.c @@ -366,6 +366,12 @@ local_read(struct local_socket *s) snprintf(reply, sizeof(reply), "no%s%s\n", message ? " " : "", message ? message : ""); break; + case CONFIG_ACTION_CHECK_XROUTES: + rc = check_xroutes(1, 0, 1); + if(rc < 0) { + snprintf(reply, sizeof(reply), "Warning: couldn't check exported routes.\n"); + } + break; default: snprintf(reply, sizeof(reply), "bad\n"); } diff --git a/xroute.c b/xroute.c index fb881ea3..03cbe582 100644 --- a/xroute.c +++ b/xroute.c @@ -434,7 +434,7 @@ kernel_route_notify(int add, struct kernel_route *kroute, void *closure) int -check_xroutes(int send_updates, int warn) +check_xroutes(int send_updates, int warn, int check_infinity) { int i, j, change = 0, rc; struct kernel_route *routes; @@ -481,6 +481,8 @@ check_xroutes(int send_updates, int warn) memcpy(routes[i].src_prefix, filter_result.src_prefix, 16); routes[i].src_plen = filter_result.src_plen; } + debugf("Route %s metric %d\n", + format_prefix(routes[i].prefix, routes[i].plen), routes[i].metric); } qsort(routes, numroutes, sizeof(struct kernel_route), kernel_route_compare); @@ -488,7 +490,7 @@ check_xroutes(int send_updates, int warn) j = 0; while(i < numroutes || j < numxroutes) { /* Ignore routes filtered out. */ - if(i < numroutes && routes[i].metric >= INFINITY) { + if(!check_infinity && i < numroutes && routes[i].metric >= INFINITY) { i++; continue; } diff --git a/xroute.h b/xroute.h index 812da58e..95dab6c4 100644 --- a/xroute.h +++ b/xroute.h @@ -45,4 +45,4 @@ void xroute_stream_done(struct xroute_stream *stream); int kernel_addresses(int ifindex, int ll, struct kernel_route *routes, int maxroutes); void kernel_route_notify(int add, struct kernel_route *route, void *closure); -int check_xroutes(int send_updates, int warn); +int check_xroutes(int send_updates, int warn, int check_infinity); From 983ac2e7837be6a08c6fa3cef407908f9f69babe Mon Sep 17 00:00:00 2001 From: Gaspare Iengo Date: Tue, 30 Jul 2024 12:45:02 +0000 Subject: [PATCH 6/6] Added error message for update_filter --- configuration.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configuration.c b/configuration.c index e5fc6f70..2033a408 100644 --- a/configuration.c +++ b/configuration.c @@ -1187,6 +1187,13 @@ parse_config_line(int c, gnc_t gnc, void *closure, goto fail; c = update_filter(redistribute_filters, filter); free_filter(filter); + if (c == 0) { + if(action_return) + *action_return = CONFIG_ACTION_NO; + if(message_return) { + *message_return = "Couldn't find the redistribute filter to update"; + } + } if(c < -1) goto fail; } else {