diff --git a/.gitignore b/.gitignore index 4e888447..afcd3145 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ tags *.orig *~ \#*# +.vscode/ 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/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 fa5bf30a..b316ef7a 100644 --- a/route.c +++ b/route.c @@ -439,14 +439,17 @@ 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; - 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) { @@ -455,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 @@ -490,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; @@ -516,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; @@ -550,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; @@ -580,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;