Commit d42c1dbd authored by Killian Lufau's avatar Killian Lufau Committed by Juliusz Chroboczek

Add install filter parameter pref_src.

The purpose is to override *locally* RTA_PREFSRC ('src' in ip-route).
parent 90fc2cbf
...@@ -562,6 +562,12 @@ filter, specify the kernel routing table to use. For source-specific ...@@ -562,6 +562,12 @@ filter, specify the kernel routing table to use. For source-specific
routes, this only works reliably for IPv6, and only when routes, this only works reliably for IPv6, and only when
.B ipv6-subtrees .B ipv6-subtrees
is true. is true.
.TP
.BI pref-src " ip"
Specify the preferred source address to use with this route. Only useful
in an
.B install
filter.
.PP .PP
If If
.I action .I action
......
...@@ -471,6 +471,15 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return) ...@@ -471,6 +471,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;
} }
...@@ -1337,11 +1346,12 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen, ...@@ -1337,11 +1346,12 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen,
int int
install_filter(const unsigned char *prefix, unsigned short plen, install_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,
struct filter_result *result) struct filter_result *result)
{ {
int res; int res;
res = do_filter(install_filters, NULL, prefix, plen, res = do_filter(install_filters, NULL, prefix, plen,
src_prefix, src_plen, NULL, 0, 0, result); src_prefix, src_plen, NULL, ifindex, 0, result);
if(res < 0) if(res < 0)
res = INFINITY; res = INFINITY;
return res; return res;
......
...@@ -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 {
...@@ -75,5 +76,5 @@ int redistribute_filter(const unsigned char *prefix, unsigned short plen, ...@@ -75,5 +76,5 @@ int redistribute_filter(const unsigned char *prefix, unsigned short plen,
struct filter_result *result); struct filter_result *result);
int install_filter(const unsigned char *prefix, unsigned short plen, int install_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,
struct filter_result *result); unsigned int ifindex, struct filter_result *result);
int finalise_config(void); int finalise_config(void);
...@@ -221,17 +221,21 @@ change_route(int operation, const struct zone *zone, ...@@ -221,17 +221,21 @@ change_route(int operation, const struct zone *zone,
int new_ifindex, int new_metric) int new_ifindex, int new_metric)
{ {
struct filter_result filter_result; struct filter_result filter_result;
unsigned char *pref_src = NULL;
unsigned int ifindex = route->neigh->ifp->ifindex; unsigned int ifindex = route->neigh->ifp->ifindex;
install_filter(zone->dst_prefix, zone->dst_plen, int m = install_filter(zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen, &filter_result); zone->src_prefix, zone->src_plen,
ifindex, &filter_result);
if (m < INFINITY)
pref_src = filter_result.pref_src;
int table = filter_result.table ? filter_result.table : int table = filter_result.table ? filter_result.table :
find_table(zone->dst_prefix, zone->dst_plen, find_table(zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen); zone->src_prefix, zone->src_plen);
return kernel_route(operation, table, zone->dst_prefix, zone->dst_plen, return kernel_route(operation, table, zone->dst_prefix, zone->dst_plen,
zone->src_prefix, zone->src_plen, zone->src_prefix, zone->src_plen, pref_src,
route->nexthop, ifindex, route->nexthop, ifindex,
metric, new_next_hop, new_ifindex, new_metric, metric, new_next_hop, new_ifindex, new_metric,
operation == ROUTE_MODIFY ? table : 0); operation == ROUTE_MODIFY ? table : 0);
......
...@@ -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);
......
...@@ -944,6 +944,7 @@ int ...@@ -944,6 +944,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)
...@@ -997,11 +998,11 @@ kernel_route(int operation, int table, ...@@ -997,11 +998,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) {
...@@ -1084,17 +1085,24 @@ kernel_route(int operation, int table, ...@@ -1084,17 +1085,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;
} }
......
...@@ -408,6 +408,7 @@ int ...@@ -408,6 +408,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)
...@@ -424,8 +425,9 @@ kernel_route(int operation, int table, ...@@ -424,8 +425,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