Commit 4df8ccad by Matthieu Boutier

Set the source prefixes through filters.

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