Commit 4df8ccad authored by Matthieu Boutier's avatar Matthieu Boutier

Set the source prefixes through filters.

Since it's a route attribute, it fits better there.
parent 79c1a379
...@@ -472,6 +472,10 @@ For an input or output filter, allow this route after increasing its metric by ...@@ -472,6 +472,10 @@ For an input or output filter, allow this route after increasing its metric by
.IR value . .IR value .
For a redistribute filter, redistribute this route with metric For a redistribute filter, redistribute this route with metric
.IR value . .IR value .
.TP
.BI src-prefix " prefix"
For a redistribute filter, set the source prefix of this route to
.IR prefix .
.PP .PP
If If
.I action .I action
...@@ -514,6 +518,12 @@ or, if you want to constrain the routes that you redistribute, ...@@ -514,6 +518,12 @@ or, if you want to constrain the routes that you redistribute,
\-C 'redistribute proto 11 ip ::/0 le 64 metric 256' \\ \-C 'redistribute proto 11 ip ::/0 le 64 metric 256' \\
\-C 'redistribute proto 11 ip 0.0.0.0/0 le 24 metric 256' \\ \-C 'redistribute proto 11 ip 0.0.0.0/0 le 24 metric 256' \\
wlan0 wlan0
.SS Source-sensitive routing
.PP
If your want to redistribute kernel routes as source-specific to the network,
with the 2001:DB8:0:1::/64 prefix:
.IP
redistribute src-prefix 2001:DB8:0:1::/64
.SH FILES .SH FILES
.TP .TP
.B /etc/babeld.conf .B /etc/babeld.conf
......
...@@ -381,16 +381,28 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return) ...@@ -381,16 +381,28 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return)
filter->ifname = interface; filter->ifname = interface;
filter->ifindex = if_nametoindex(interface); filter->ifindex = if_nametoindex(interface);
} else if(strcmp(token, "allow") == 0) { } else if(strcmp(token, "allow") == 0) {
filter->add_metric = 0; filter->action.add_metric = 0;
} else if(strcmp(token, "deny") == 0) { } else if(strcmp(token, "deny") == 0) {
filter->add_metric = INFINITY; filter->action.add_metric = INFINITY;
} else if(strcmp(token, "metric") == 0) { } else if(strcmp(token, "metric") == 0) {
int metric; int metric;
c = getint(c, &metric, gnc, closure); c = getint(c, &metric, gnc, closure);
if(c < -1) goto error; if(c < -1) goto error;
if(metric <= 0 || metric > INFINITY) if(metric <= 0 || metric > INFINITY)
goto error; goto error;
filter->add_metric = metric; filter->action.add_metric = metric;
} else if(strcmp(token, "src-prefix") == 0) {
int af;
c = getnet(c, &filter->action.src_prefix, &filter->action.src_plen,
&af, gnc, closure);
if(c < -1)
goto error;
if(filter->af == AF_UNSPEC)
filter->af = af;
else if(filter->af != af)
goto error;
if(af == AF_INET && filter->action.src_plen == 96)
memset(&filter->action.src_prefix, 0, 16);
} else { } else {
goto error; goto error;
} }
...@@ -988,12 +1000,18 @@ static int ...@@ -988,12 +1000,18 @@ static int
do_filter(struct filter *f, const unsigned char *id, do_filter(struct filter *f, const unsigned char *id,
const unsigned char *prefix, unsigned short plen, const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen, const unsigned char *src_prefix, unsigned short src_plen,
const unsigned char *neigh, unsigned int ifindex, int proto) const unsigned char *neigh, unsigned int ifindex, int proto,
struct filter_result *result)
{ {
if(result)
memset(result, 0, sizeof(struct filter_result));
while(f) { while(f) {
if(filter_match(f, id, prefix, plen, src_prefix, src_plen, if(filter_match(f, id, prefix, plen, src_prefix, src_plen,
neigh, ifindex, proto)) neigh, ifindex, proto)) {
return f->add_metric; if(result)
memcpy(result, &f->action, sizeof(struct filter_result));
return f->action.add_metric;
}
f = f->next; f = f->next;
} }
return -1; return -1;
...@@ -1003,11 +1021,12 @@ int ...@@ -1003,11 +1021,12 @@ int
input_filter(const unsigned char *id, input_filter(const unsigned char *id,
const unsigned char *prefix, unsigned short plen, const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen, const unsigned char *src_prefix, unsigned short src_plen,
const unsigned char *neigh, unsigned int ifindex) const unsigned char *neigh, unsigned int ifindex,
struct filter_result *result)
{ {
int res; int res;
res = do_filter(input_filters, id, prefix, plen, res = do_filter(input_filters, id, prefix, plen,
src_prefix, src_plen, neigh, ifindex, 0); src_prefix, src_plen, neigh, ifindex, 0, result);
if(res < 0) if(res < 0)
res = 0; res = 0;
return res; return res;
...@@ -1017,11 +1036,12 @@ int ...@@ -1017,11 +1036,12 @@ int
output_filter(const unsigned char *id, output_filter(const unsigned char *id,
const unsigned char *prefix, unsigned short plen, const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen, const unsigned char *src_prefix, unsigned short src_plen,
unsigned int ifindex) unsigned int ifindex,
struct filter_result *result)
{ {
int res; int res;
res = do_filter(output_filters, id, prefix, plen, res = do_filter(output_filters, id, prefix, plen,
src_prefix, src_plen, NULL, ifindex, 0); src_prefix, src_plen, NULL, ifindex, 0, result);
if(res < 0) if(res < 0)
res = 0; res = 0;
return res; return res;
...@@ -1030,11 +1050,12 @@ output_filter(const unsigned char *id, ...@@ -1030,11 +1050,12 @@ output_filter(const unsigned char *id,
int int
redistribute_filter(const unsigned char *prefix, unsigned short plen, redistribute_filter(const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen, const unsigned char *src_prefix, unsigned short src_plen,
unsigned int ifindex, int proto) unsigned int ifindex, int proto,
struct filter_result *result)
{ {
int res; int res;
res = do_filter(redistribute_filters, NULL, prefix, plen, res = do_filter(redistribute_filters, NULL, prefix, plen,
src_prefix, src_plen, NULL, ifindex, proto); src_prefix, src_plen, NULL, ifindex, proto, result);
if(res < 0) if(res < 0)
res = INFINITY; res = INFINITY;
return res; return res;
......
...@@ -20,6 +20,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ...@@ -20,6 +20,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
struct filter_result {
unsigned int add_metric; /* allow = 0, deny = INF, metric = <0..INF> */
unsigned char *src_prefix;
unsigned char src_plen;
};
struct filter { struct filter {
int af; int af;
char *ifname; char *ifname;
...@@ -33,7 +39,7 @@ struct filter { ...@@ -33,7 +39,7 @@ struct filter {
unsigned char src_plen_ge, src_plen_le; unsigned char src_plen_ge, src_plen_le;
unsigned char *neigh; unsigned char *neigh;
int proto; /* May be negative */ int proto; /* May be negative */
unsigned int add_metric; struct filter_result action;
struct filter *next; struct filter *next;
}; };
...@@ -46,12 +52,15 @@ void renumber_filters(void); ...@@ -46,12 +52,15 @@ void renumber_filters(void);
int input_filter(const unsigned char *id, int input_filter(const unsigned char *id,
const unsigned char *prefix, unsigned short plen, const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen, const unsigned char *src_prefix, unsigned short src_plen,
const unsigned char *neigh, unsigned int ifindex); const unsigned char *neigh, unsigned int ifindex,
struct filter_result *result);
int output_filter(const unsigned char *id, int output_filter(const unsigned char *id,
const unsigned char *prefix, unsigned short plen, const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen, const unsigned char *src_prefix, unsigned short src_plen,
unsigned int ifindex); unsigned int ifindex,
struct filter_result *result);
int redistribute_filter(const unsigned char *prefix, unsigned short plen, int redistribute_filter(const unsigned char *prefix, unsigned short plen,
const unsigned char *src_prefix, unsigned short src_plen, const unsigned char *src_prefix, unsigned short src_plen,
unsigned int ifindex, int proto); unsigned int ifindex, int proto,
struct filter_result *result);
int finalise_config(void); int finalise_config(void);
...@@ -1093,7 +1093,7 @@ really_send_update(struct interface *ifp, ...@@ -1093,7 +1093,7 @@ really_send_update(struct interface *ifp,
return; return;
add_metric = output_filter(id, prefix, plen, src_prefix, add_metric = output_filter(id, prefix, plen, src_prefix,
src_plen, ifp->ifindex); src_plen, ifp->ifindex, NULL);
if(add_metric >= INFINITY) if(add_metric >= INFINITY)
return; return;
......
...@@ -101,10 +101,11 @@ record_resend(int kind, const unsigned char *prefix, unsigned char plen, ...@@ -101,10 +101,11 @@ record_resend(int kind, const unsigned char *prefix, unsigned char plen,
return 0; return 0;
if((kind == RESEND_REQUEST && if((kind == RESEND_REQUEST &&
input_filter(NULL, prefix, plen, NULL, 0, NULL, ifindex) >= input_filter(NULL, prefix, plen, NULL, 0, NULL, ifindex, NULL) >=
INFINITY) || INFINITY) ||
(kind == RESEND_UPDATE && (kind == RESEND_UPDATE &&
output_filter(NULL, prefix, plen, src_prefix, src_plen, ifindex) >= output_filter(NULL, prefix, plen, src_prefix, src_plen,
ifindex, NULL) >=
INFINITY)) INFINITY))
return 0; return 0;
......
...@@ -767,7 +767,7 @@ update_route_metric(struct babel_route *route) ...@@ -767,7 +767,7 @@ update_route_metric(struct babel_route *route)
route->src->src_prefix, route->src->src_prefix,
route->src->src_plen, route->src->src_plen,
neigh->address, neigh->address,
neigh->ifp->ifindex); neigh->ifp->ifindex, NULL);
change_route_metric(route, route->refmetric, change_route_metric(route, route->refmetric,
neighbour_cost(route->neigh), add_metric); neighbour_cost(route->neigh), add_metric);
if(route_metric(route) != oldmetric || if(route_metric(route) != oldmetric ||
...@@ -849,9 +849,9 @@ update_route(const unsigned char *id, ...@@ -849,9 +849,9 @@ update_route(const unsigned char *id,
return NULL; return NULL;
add_metric = input_filter(id, prefix, plen, add_metric = input_filter(id, prefix, plen, src_prefix, src_plen,
src_prefix, src_plen, neigh->address, neigh->ifp->ifindex,
neigh->address, neigh->ifp->ifindex); NULL);
if(add_metric >= INFINITY) if(add_metric >= INFINITY)
return NULL; return NULL;
......
...@@ -169,7 +169,8 @@ check_xroutes(int send_updates) ...@@ -169,7 +169,8 @@ check_xroutes(int send_updates)
{ {
int i, j, metric, export, change = 0, rc; int i, j, metric, export, change = 0, rc;
struct kernel_route *routes; struct kernel_route *routes;
int numroutes; struct filter_result filter_result = {0};
int numroutes, numaddresses;
static int maxroutes = 8; static int maxroutes = 8;
const int maxmaxroutes = 16 * 1024; const int maxmaxroutes = 16 * 1024;
...@@ -191,6 +192,8 @@ check_xroutes(int send_updates) ...@@ -191,6 +192,8 @@ check_xroutes(int send_updates)
if(numroutes >= maxroutes) if(numroutes >= maxroutes)
goto resize; goto resize;
numaddresses = numroutes;
rc = kernel_routes(routes + numroutes, maxroutes - numroutes); rc = kernel_routes(routes + numroutes, maxroutes - numroutes);
if(rc < 0) if(rc < 0)
fprintf(stderr, "Couldn't get kernel routes.\n"); fprintf(stderr, "Couldn't get kernel routes.\n");
...@@ -200,6 +203,21 @@ check_xroutes(int send_updates) ...@@ -200,6 +203,21 @@ check_xroutes(int send_updates)
if(numroutes >= maxroutes) if(numroutes >= maxroutes)
goto resize; goto resize;
/* Apply filter to kernel routes (e.g. change the source prefix). */
for(i = numaddresses; i < numroutes; i++) {
filter_result.src_prefix = NULL;
redistribute_filter(routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen,
routes[i].ifindex, routes[i].proto,
&filter_result);
if(filter_result.src_prefix) {
memcpy(routes[i].src_prefix, filter_result.src_prefix, 16);
routes[i].src_plen = filter_result.src_plen;
}
}
/* Check for any routes that need to be flushed */ /* Check for any routes that need to be flushed */
i = 0; i = 0;
...@@ -207,7 +225,8 @@ check_xroutes(int send_updates) ...@@ -207,7 +225,8 @@ check_xroutes(int send_updates)
export = 0; export = 0;
metric = redistribute_filter(xroutes[i].prefix, xroutes[i].plen, metric = redistribute_filter(xroutes[i].prefix, xroutes[i].plen,
xroutes[i].src_prefix, xroutes[i].src_plen, xroutes[i].src_prefix, xroutes[i].src_plen,
xroutes[i].ifindex, xroutes[i].proto); xroutes[i].ifindex, xroutes[i].proto,
NULL);
if(metric < INFINITY && metric == xroutes[i].metric) { if(metric < INFINITY && metric == xroutes[i].metric) {
for(j = 0; j < numroutes; j++) { for(j = 0; j < numroutes; j++) {
if(xroutes[i].plen == routes[j].plen && if(xroutes[i].plen == routes[j].plen &&
...@@ -249,7 +268,7 @@ check_xroutes(int send_updates) ...@@ -249,7 +268,7 @@ check_xroutes(int send_updates)
continue; continue;
metric = redistribute_filter(routes[i].prefix, routes[i].plen, metric = redistribute_filter(routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen, routes[i].src_prefix, routes[i].src_plen,
routes[i].ifindex, routes[i].proto); routes[i].ifindex, routes[i].proto, NULL);
if(metric < INFINITY) { if(metric < INFINITY) {
rc = add_xroute(routes[i].prefix, routes[i].plen, rc = add_xroute(routes[i].prefix, routes[i].plen,
routes[i].src_prefix, routes[i].src_plen, routes[i].src_prefix, routes[i].src_plen,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment