Commit 89cf17b6 authored by Julien Muchembled's avatar Julien Muchembled

New pref-src & src-prefix actions in install filter

The purpose is to override *locally*:
- RTA_SRC ('from' option in ip-route)
- RTA_PREFSRC ('src' in ip-route)

For RTA_PREFSRC, there is a pull request that could replace this at
  https://github.com/jech/babeld/pull/18
But it looks better to do it our way.

TODO: documentation
parent b2b22806
...@@ -469,6 +469,15 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return) ...@@ -469,6 +469,15 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return)
if(table <= 0 || table > INFINITY) if(table <= 0 || table > INFINITY)
goto error; goto error;
filter->action.table = table; filter->action.table = table;
} else if(strcmp(token, "pref-src") == 0) {
int af;
c = getip(c, &filter->action.pref_src, &af, gnc, closure);
if(c < -1)
goto error;
if(filter->af == AF_UNSPEC)
filter->af = af;
else if(filter->af != af)
goto error;
} else { } else {
goto error; goto error;
} }
......
...@@ -34,6 +34,7 @@ struct filter_result { ...@@ -34,6 +34,7 @@ struct filter_result {
unsigned char *src_prefix; unsigned char *src_prefix;
unsigned char src_plen; unsigned char src_plen;
unsigned int table; unsigned int table;
unsigned char *pref_src;
}; };
struct filter { struct filter {
......
...@@ -36,6 +36,7 @@ THE SOFTWARE. ...@@ -36,6 +36,7 @@ THE SOFTWARE.
#include "neighbour.h" #include "neighbour.h"
#include "rule.h" #include "rule.h"
#include "disambiguation.h" #include "disambiguation.h"
#include "configuration.h"
struct zone { struct zone {
const unsigned char *dst_prefix; const unsigned char *dst_prefix;
...@@ -211,38 +212,57 @@ is_installed(struct zone *zone) ...@@ -211,38 +212,57 @@ is_installed(struct zone *zone)
zone->src_prefix, zone->src_plen) != NULL; zone->src_prefix, zone->src_plen) != NULL;
} }
static const unsigned char *install_zone(struct zone *zone)
{
struct filter_result filter_result;
if(INFINITY == install_filter(zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen,
&filter_result))
return NULL;
if(filter_result.src_prefix) {
zone->src_prefix = filter_result.src_prefix;
zone->src_plen = filter_result.src_plen;
}
return filter_result.pref_src;
}
static int static int
add_route(const struct zone *zone, const struct babel_route *route) add_route(struct zone *zone, const struct babel_route *route)
{ {
const unsigned char *pref_src = install_zone(zone);
int table = find_table(zone->dst_prefix, zone->dst_plen, int table = find_table(zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen); zone->src_prefix, zone->src_plen);
return kernel_route(ROUTE_ADD, table, zone->dst_prefix, zone->dst_plen, return kernel_route(ROUTE_ADD, table, zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen, zone->src_prefix, zone->src_plen, pref_src,
route->nexthop, route->nexthop,
route->neigh->ifp->ifindex, route->neigh->ifp->ifindex,
metric_to_kernel(route_metric(route)), NULL, 0, 0, 0); metric_to_kernel(route_metric(route)), NULL, 0, 0, 0);
} }
static int static int
del_route(const struct zone *zone, const struct babel_route *route) del_route(struct zone *zone, const struct babel_route *route)
{ {
const unsigned char *pref_src = install_zone(zone);
int table = find_table(zone->dst_prefix, zone->dst_plen, int table = find_table(zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen); zone->src_prefix, zone->src_plen);
return kernel_route(ROUTE_FLUSH, table, zone->dst_prefix, zone->dst_plen, return kernel_route(ROUTE_FLUSH, table, zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen, zone->src_prefix, zone->src_plen, pref_src,
route->nexthop, route->nexthop,
route->neigh->ifp->ifindex, route->neigh->ifp->ifindex,
metric_to_kernel(route_metric(route)), NULL, 0, 0, 0); metric_to_kernel(route_metric(route)), NULL, 0, 0, 0);
} }
static int static int
chg_route(const struct zone *zone, const struct babel_route *old, chg_route(struct zone *zone, const struct babel_route *old,
const struct babel_route *new) const struct babel_route *new)
{ {
const unsigned char *pref_src = install_zone(zone);
int table = find_table(zone->dst_prefix, zone->dst_plen, int table = find_table(zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen); zone->src_prefix, zone->src_plen);
return kernel_route(ROUTE_MODIFY, table, zone->dst_prefix, zone->dst_plen, return kernel_route(ROUTE_MODIFY, table, zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen, zone->src_prefix, zone->src_plen, pref_src,
old->nexthop, old->neigh->ifp->ifindex, old->nexthop, old->neigh->ifp->ifindex,
metric_to_kernel(route_metric(old)), metric_to_kernel(route_metric(old)),
new->nexthop, new->neigh->ifp->ifindex, new->nexthop, new->neigh->ifp->ifindex,
...@@ -250,13 +270,14 @@ chg_route(const struct zone *zone, const struct babel_route *old, ...@@ -250,13 +270,14 @@ chg_route(const struct zone *zone, const struct babel_route *old,
} }
static int static int
chg_route_metric(const struct zone *zone, const struct babel_route *route, chg_route_metric(struct zone *zone, const struct babel_route *route,
int old_metric, int new_metric) int old_metric, int new_metric)
{ {
const unsigned char *pref_src = install_zone(zone);
int table = find_table(zone->dst_prefix, zone->dst_plen, int table = find_table(zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen); zone->src_prefix, zone->src_plen);
return kernel_route(ROUTE_MODIFY, table, zone->dst_prefix, zone->dst_plen, return kernel_route(ROUTE_MODIFY, table, zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen, zone->src_prefix, zone->src_plen, pref_src,
route->nexthop, route->neigh->ifp->ifindex, route->nexthop, route->neigh->ifp->ifindex,
old_metric, old_metric,
route->nexthop, route->neigh->ifp->ifindex, route->nexthop, route->neigh->ifp->ifindex,
......
...@@ -94,6 +94,7 @@ int kernel_disambiguate(int v4); ...@@ -94,6 +94,7 @@ int kernel_disambiguate(int v4);
int kernel_route(int operation, int table, int kernel_route(int operation, int table,
const unsigned char *dest, unsigned short plen, const unsigned char *dest, unsigned short plen,
const unsigned char *src, unsigned short src_plen, const unsigned char *src, unsigned short src_plen,
const unsigned char *pref_src,
const unsigned char *gate, int ifindex, unsigned int metric, const unsigned char *gate, int ifindex, unsigned int metric,
const unsigned char *newgate, int newifindex, const unsigned char *newgate, int newifindex,
unsigned int newmetric, int newtable); unsigned int newmetric, int newtable);
......
...@@ -927,6 +927,7 @@ int ...@@ -927,6 +927,7 @@ int
kernel_route(int operation, int table, kernel_route(int operation, int table,
const unsigned char *dest, unsigned short plen, const unsigned char *dest, unsigned short plen,
const unsigned char *src, unsigned short src_plen, const unsigned char *src, unsigned short src_plen,
const unsigned char *pref_src,
const unsigned char *gate, int ifindex, unsigned int metric, const unsigned char *gate, int ifindex, unsigned int metric,
const unsigned char *newgate, int newifindex, const unsigned char *newgate, int newifindex,
unsigned int newmetric, int newtable) unsigned int newmetric, int newtable)
...@@ -980,11 +981,11 @@ kernel_route(int operation, int table, ...@@ -980,11 +981,11 @@ kernel_route(int operation, int table,
stick with the naive approach, and hope that the window is stick with the naive approach, and hope that the window is
small enough to be negligible. */ small enough to be negligible. */
kernel_route(ROUTE_FLUSH, table, dest, plen, kernel_route(ROUTE_FLUSH, table, dest, plen,
src, src_plen, src, src_plen, pref_src,
gate, ifindex, metric, gate, ifindex, metric,
NULL, 0, 0, 0); NULL, 0, 0, 0);
rc = kernel_route(ROUTE_ADD, newtable, dest, plen, rc = kernel_route(ROUTE_ADD, newtable, dest, plen,
src, src_plen, src, src_plen, pref_src,
newgate, newifindex, newmetric, newgate, newifindex, newmetric,
NULL, 0, 0, 0); NULL, 0, 0, 0);
if(rc < 0) { if(rc < 0) {
...@@ -1067,17 +1068,24 @@ kernel_route(int operation, int table, ...@@ -1067,17 +1068,24 @@ kernel_route(int operation, int table,
rta->rta_type = RTA_OIF; rta->rta_type = RTA_OIF;
*(int*)RTA_DATA(rta) = ifindex; *(int*)RTA_DATA(rta) = ifindex;
if(ipv4) { #define ADD_IPARG(type, addr) \
rta = RTA_NEXT(rta, len); do if(ipv4) { \
rta->rta_len = RTA_LENGTH(sizeof(struct in_addr)); rta = RTA_NEXT(rta, len); \
rta->rta_type = RTA_GATEWAY; rta->rta_len = RTA_LENGTH(sizeof(struct in_addr)); \
memcpy(RTA_DATA(rta), gate + 12, sizeof(struct in_addr)); rta->rta_type = type; \
} else { memcpy(RTA_DATA(rta), addr + 12, sizeof(struct in_addr)); \
rta = RTA_NEXT(rta, len); } else { \
rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); rta = RTA_NEXT(rta, len); \
rta->rta_type = RTA_GATEWAY; rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr)); \
memcpy(RTA_DATA(rta), gate, sizeof(struct in6_addr)); rta->rta_type = type; \
} memcpy(RTA_DATA(rta), addr, sizeof(struct in6_addr)); \
} while (0)
ADD_IPARG(RTA_GATEWAY, gate);
if(pref_src)
ADD_IPARG(RTA_PREFSRC, pref_src);
#undef ADD_IPARG
} else { } else {
*(int*)RTA_DATA(rta) = -1; *(int*)RTA_DATA(rta) = -1;
} }
......
...@@ -406,6 +406,7 @@ int ...@@ -406,6 +406,7 @@ int
kernel_route(int operation, int table, kernel_route(int operation, int table,
const unsigned char *dest, unsigned short plen, const unsigned char *dest, unsigned short plen,
const unsigned char *src, unsigned short src_plen, const unsigned char *src, unsigned short src_plen,
const unsigned char *pref_src,
const unsigned char *gate, int ifindex, unsigned int metric, const unsigned char *gate, int ifindex, unsigned int metric,
const unsigned char *newgate, int newifindex, const unsigned char *newgate, int newifindex,
unsigned int newmetric, int newtable) unsigned int newmetric, int newtable)
...@@ -422,8 +423,9 @@ kernel_route(int operation, int table, ...@@ -422,8 +423,9 @@ kernel_route(int operation, int table,
{{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01 }}}; 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01 }}};
/* Source-specific routes are not implemented yet for BSD. */ /* Source-specific routes & preferred source IPs
if(!is_default(src, src_plen)) { * are not implemented yet for BSD. */
if((!is_default(src, src_plen)) || pref_src) {
errno = ENOSYS; errno = ENOSYS;
return -1; return -1;
} }
......
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