Commit 79c1a379 authored by Matthieu Boutier's avatar Matthieu Boutier Committed by Juliusz Chroboczek

Add filter to match source addresses.

Add 3 new options to configuration and manpages:
src-ip, src-eq, src-le and src-ge.
parent 46dd09f4
...@@ -411,6 +411,23 @@ This entry only applies to routes with a prefix length less or equal to ...@@ -411,6 +411,23 @@ This entry only applies to routes with a prefix length less or equal to
This entry only applies to routes with a prefix length greater or equal to This entry only applies to routes with a prefix length greater or equal to
.BR plen . .BR plen .
.TP .TP
.BI src-ip " prefix"
This entry only applies to routes with a source prefix in the given prefix.
.TP
.BI src-eq " plen"
This entry only applies to routes with a source prefix length equal to
.BR plen .
.TP
.BI src-le " plen"
This entry only applies to routes with a source prefix length less or
equal to
.BR plen .
.TP
.BI src-ge " plen"
This entry only applies to routes with a source prefix length greater
or equal to
.BR plen .
.TP
.BI neigh " address" .BI neigh " address"
This entry only applies to routes learned from a neighbour with This entry only applies to routes learned from a neighbour with
link-local address link-local address
......
...@@ -283,6 +283,7 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return) ...@@ -283,6 +283,7 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return)
if(filter == NULL) if(filter == NULL)
goto error; goto error;
filter->plen_le = 128; filter->plen_le = 128;
filter->src_plen_le = 128;
while(1) { while(1) {
c = skip_whitespace(c, gnc, closure); c = skip_whitespace(c, gnc, closure);
...@@ -295,10 +296,25 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return) ...@@ -295,10 +296,25 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return)
goto error; goto error;
if(strcmp(token, "ip") == 0) { if(strcmp(token, "ip") == 0) {
c = getnet(c, &filter->prefix, &filter->plen, &filter->af, int af;
c = getnet(c, &filter->prefix, &filter->plen, &af,
gnc, closure); gnc, closure);
if(c < -1) if(c < -1)
goto error; goto error;
if(filter->af == AF_UNSPEC)
filter->af = af;
else if(filter->af != af)
goto error;
} else if(strcmp(token, "src-ip") == 0) {
int af;
c = getnet(c, &filter->src_prefix, &filter->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;
} else if(strcmp(token, "eq") == 0) { } else if(strcmp(token, "eq") == 0) {
int p; int p;
c = getint(c, &p, gnc, closure); c = getint(c, &p, gnc, closure);
...@@ -318,6 +334,25 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return) ...@@ -318,6 +334,25 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return)
if(c < -1) if(c < -1)
goto error; goto error;
filter->plen_ge = MAX(filter->plen_ge, p); filter->plen_ge = MAX(filter->plen_ge, p);
} else if(strcmp(token, "src-eq") == 0) {
int p;
c = getint(c, &p, gnc, closure);
if(c < -1)
goto error;
filter->src_plen_ge = MAX(filter->src_plen_ge, p);
filter->src_plen_le = MIN(filter->src_plen_le, p);
} else if(strcmp(token, "src-le") == 0) {
int p;
c = getint(c, &p, gnc, closure);
if(c < -1)
goto error;
filter->src_plen_le = MIN(filter->src_plen_le, p);
} else if(strcmp(token, "src-ge") == 0) {
int p;
c = getint(c, &p, gnc, closure);
if(c < -1)
goto error;
filter->src_plen_ge = MAX(filter->src_plen_ge, p);
} else if(strcmp(token, "neigh") == 0) { } else if(strcmp(token, "neigh") == 0) {
unsigned char *neigh = NULL; unsigned char *neigh = NULL;
c = getip(c, &neigh, NULL, gnc, closure); c = getip(c, &neigh, NULL, gnc, closure);
...@@ -362,7 +397,8 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return) ...@@ -362,7 +397,8 @@ parse_filter(int c, gnc_t gnc, void *closure, struct filter **filter_return)
free(token); free(token);
} }
if(filter->af == 0) { if(filter->af == 0) {
if(filter->plen_le < 128 || filter->plen_ge > 0) if(filter->plen_le < 128 || filter->plen_ge > 0 ||
filter->src_plen_le < 128 || filter->src_plen_ge > 0)
filter->af = AF_INET6; filter->af = AF_INET6;
} else if(filter->af == AF_INET) { } else if(filter->af == AF_INET) {
filter->plen_le += 96; filter->plen_le += 96;
...@@ -885,6 +921,7 @@ renumber_filters() ...@@ -885,6 +921,7 @@ renumber_filters()
static int static int
filter_match(struct filter *f, const unsigned char *id, filter_match(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 *neigh, unsigned int ifindex, int proto) const unsigned char *neigh, unsigned int ifindex, int proto)
{ {
if(f->af) { if(f->af) {
...@@ -902,6 +939,11 @@ filter_match(struct filter *f, const unsigned char *id, ...@@ -902,6 +939,11 @@ filter_match(struct filter *f, const unsigned char *id,
if(!prefix || plen < f->plen || !in_prefix(prefix, f->prefix, f->plen)) if(!prefix || plen < f->plen || !in_prefix(prefix, f->prefix, f->plen))
return 0; return 0;
} }
if(f->src_prefix) {
if(!src_prefix || src_plen < f->src_plen ||
!in_prefix(src_prefix, f->src_prefix, f->src_plen))
return 0;
}
if(f->plen_ge > 0 || f->plen_le < 128) { if(f->plen_ge > 0 || f->plen_le < 128) {
if(!prefix) if(!prefix)
return 0; return 0;
...@@ -910,6 +952,14 @@ filter_match(struct filter *f, const unsigned char *id, ...@@ -910,6 +952,14 @@ filter_match(struct filter *f, const unsigned char *id,
if(plen < f->plen_ge) if(plen < f->plen_ge)
return 0; return 0;
} }
if(f->src_plen_ge > 0 || f->src_plen_le < 128) {
if(!src_prefix)
return 0;
if(src_plen > f->src_plen_le)
return 0;
if(src_plen < f->src_plen_ge)
return 0;
}
if(f->neigh) { if(f->neigh) {
if(!neigh || memcmp(f->neigh, neigh, 16) != 0) if(!neigh || memcmp(f->neigh, neigh, 16) != 0)
return 0; return 0;
...@@ -937,10 +987,12 @@ filter_match(struct filter *f, const unsigned char *id, ...@@ -937,10 +987,12 @@ filter_match(struct filter *f, const unsigned char *id,
static int 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 *neigh, unsigned int ifindex, int proto) const unsigned char *neigh, unsigned int ifindex, int proto)
{ {
while(f) { while(f) {
if(filter_match(f, id, prefix, plen, neigh, ifindex, proto)) if(filter_match(f, id, prefix, plen, src_prefix, src_plen,
neigh, ifindex, proto))
return f->add_metric; return f->add_metric;
f = f->next; f = f->next;
} }
...@@ -954,7 +1006,8 @@ input_filter(const unsigned char *id, ...@@ -954,7 +1006,8 @@ input_filter(const unsigned char *id,
const unsigned char *neigh, unsigned int ifindex) const unsigned char *neigh, unsigned int ifindex)
{ {
int res; int res;
res = do_filter(input_filters, id, prefix, plen, neigh, ifindex, 0); res = do_filter(input_filters, id, prefix, plen,
src_prefix, src_plen, neigh, ifindex, 0);
if(res < 0) if(res < 0)
res = 0; res = 0;
return res; return res;
...@@ -967,7 +1020,8 @@ output_filter(const unsigned char *id, ...@@ -967,7 +1020,8 @@ output_filter(const unsigned char *id,
unsigned int ifindex) unsigned int ifindex)
{ {
int res; int res;
res = do_filter(output_filters, id, prefix, plen, NULL, ifindex, 0); res = do_filter(output_filters, id, prefix, plen,
src_prefix, src_plen, NULL, ifindex, 0);
if(res < 0) if(res < 0)
res = 0; res = 0;
return res; return res;
...@@ -979,8 +1033,8 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen, ...@@ -979,8 +1033,8 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen,
unsigned int ifindex, int proto) unsigned int ifindex, int proto)
{ {
int res; int res;
res = do_filter(redistribute_filters, NULL, prefix, plen, NULL, res = do_filter(redistribute_filters, NULL, prefix, plen,
ifindex, proto); src_prefix, src_plen, NULL, ifindex, proto);
if(res < 0) if(res < 0)
res = INFINITY; res = INFINITY;
return res; return res;
...@@ -995,6 +1049,7 @@ finalise_config() ...@@ -995,6 +1049,7 @@ finalise_config()
filter->proto = RTPROT_BABEL_LOCAL; filter->proto = RTPROT_BABEL_LOCAL;
filter->plen_le = 128; filter->plen_le = 128;
filter->src_plen_le = 128;
add_filter(filter, &redistribute_filters); add_filter(filter, &redistribute_filters);
while(interface_confs) { while(interface_confs) {
......
...@@ -28,6 +28,9 @@ struct filter { ...@@ -28,6 +28,9 @@ struct filter {
unsigned char *prefix; unsigned char *prefix;
unsigned char plen; unsigned char plen;
unsigned char plen_ge, plen_le; unsigned char plen_ge, plen_le;
unsigned char *src_prefix;
unsigned char src_plen;
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; unsigned int add_metric;
......
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