diff options
-rw-r--r-- | doc/bird.sgml | 8 | ||||
-rw-r--r-- | filter/config.Y | 5 | ||||
-rw-r--r-- | filter/f-inst.c | 68 | ||||
-rw-r--r-- | filter/f-inst.h | 1 | ||||
-rw-r--r-- | filter/filter.c | 3 | ||||
-rw-r--r-- | lib/flowspec.c | 28 | ||||
-rw-r--r-- | lib/flowspec.h | 3 |
7 files changed, 104 insertions, 12 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index aeea613f..2363fb52 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1295,7 +1295,9 @@ in the foot). prefix. The literals are written as <cf><m/ipaddress//<m/pxlen/ from <m/ipaddress//<m/pxlen/</cf>, where the first part is the destination prefix and the second art is the source prefix. They support the same - operators as IP prefixes, but just for the destination part. + operators as IP prefixes, but just for the destination part. They also + support <cf/.src/ and <cf/.dst/ operators to get respective parts of the + address as separate <cf/NET_IP6/ values. <cf/NET_VPN4/ and <cf/NET_VPN6/ prefixes hold an IP prefix with VPN Route Distinguisher (<rfc id="4364">). They support the same special @@ -1309,7 +1311,9 @@ in the foot). and <cf/.asn/ which extracts the ASN. <cf/NET_FLOW4/ and <cf/NET_FLOW6/ hold an IP prefix together with a - flowspec rule. Filters currently don't support flowspec parsing. + flowspec rule. Filters currently do not support much flowspec parsing, + only <cf/.src/ and <cf/.dst/ operators to get source and destination + parts of the flowspec as separate <cf/NET_IP4/ / <cf/NET_IP6/ values. <cf/NET_MPLS/ holds a single MPLS label and its handling is currently not implemented. diff --git a/filter/config.Y b/filter/config.Y index 340053ba..c8b868af 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -433,7 +433,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, TRUE, FALSE, RT, RO, UNKNOWN, GENERIC, FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, PREFERENCE, - ROA_CHECK, ASN, SRC, + ROA_CHECK, ASN, SRC, DST, IS_V4, IS_V6, LEN, MAXLEN, DEFINED, @@ -940,7 +940,8 @@ term: | term '.' LEN { $$ = f_new_inst(FI_LENGTH, $1); } | term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN, $1); } | term '.' ASN { $$ = f_new_inst(FI_ROA_ASN, $1); } - | term '.' SRC { $$ = f_new_inst(FI_SADR_SRC, $1); } + | term '.' SRC { $$ = f_new_inst(FI_NET_SRC, $1); } + | term '.' DST { $$ = f_new_inst(FI_NET_DST, $1); } | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, $1, $5); } | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST, $1); } | term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST, $1); } diff --git a/filter/f-inst.c b/filter/f-inst.c index 3bd0249c..e3e0d76d 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -771,18 +771,76 @@ } } - INST(FI_SADR_SRC, 1, 1) { /* Get SADR src prefix */ + INST(FI_NET_SRC, 1, 1) { /* Get src prefix */ ARG(1, T_NET); - if (!net_is_sadr(v1.val.net)) - runtime( "SADR expected" ); - net_addr_ip6_sadr *net = (void *) v1.val.net; + net_addr_union *net = (void *) v1.val.net; net_addr *src = falloc(sizeof(net_addr_ip6)); - net_fill_ip6(src, net->src_prefix, net->src_pxlen); + const byte *part; + + switch(v1.val.net->type) { + case NET_FLOW4: + part = flow4_get_part(&net->flow4, FLOW_TYPE_SRC_PREFIX); + if (part) + net_fill_ip4(src, flow_read_ip4_part(part), flow_read_pxlen(part)); + else + net_fill_ip4(src, IP4_NONE, 0); + break; + + case NET_FLOW6: + part = flow6_get_part(&net->flow6, FLOW_TYPE_SRC_PREFIX); + if (part) + net_fill_ip6(src, flow_read_ip6_part(part), flow_read_pxlen(part)); + else + net_fill_ip6(src, IP6_NONE, 0); + break; + + case NET_IP6_SADR: + net_fill_ip6(src, net->ip6_sadr.src_prefix, net->ip6_sadr.src_pxlen); + break; + + default: + runtime( "Flow or SADR expected" ); + } RESULT(T_NET, net, src); } + INST(FI_NET_DST, 1, 1) { /* Get dst prefix */ + ARG(1, T_NET); + + net_addr_union *net = (void *) v1.val.net; + net_addr *dst = falloc(sizeof(net_addr_ip6)); + const byte *part; + + switch(v1.val.net->type) { + case NET_FLOW4: + part = flow4_get_part(&net->flow4, FLOW_TYPE_DST_PREFIX); + if (part) + net_fill_ip4(dst, flow_read_ip4_part(part), flow_read_pxlen(part)); + else + net_fill_ip4(dst, IP4_NONE, 0); + break; + + case NET_FLOW6: + part = flow6_get_part(&net->flow6, FLOW_TYPE_DST_PREFIX); + if (part) + net_fill_ip6(dst, flow_read_ip6_part(part), flow_read_pxlen(part)); + else + net_fill_ip6(dst, IP6_NONE, 0); + break; + + case NET_IP6_SADR: + net_fill_ip6(dst, net->ip6_sadr.dst_prefix, net->ip6_sadr.dst_pxlen); + break; + + default: + runtime( "Flow or SADR expected" ); + } + + RESULT(T_NET, net, dst); + } + INST(FI_ROA_MAXLEN, 1, 1) { /* Get ROA max prefix length */ ARG(1, T_NET); if (!net_is_roa(v1.val.net)) diff --git a/filter/f-inst.h b/filter/f-inst.h index 8be8443b..bfa163fc 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -17,6 +17,7 @@ #include "conf/conf.h" #include "filter/filter.h" #include "filter/data.h" +#include "lib/flowspec.h" /* Flags for instructions */ enum f_instruction_flags { diff --git a/filter/filter.c b/filter/filter.c index ad9588b2..e505d570 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -32,8 +32,9 @@ #include "lib/socket.h" #include "lib/string.h" #include "lib/unaligned.h" -#include "lib/net.h" #include "lib/ip.h" +#include "lib/net.h" +#include "lib/flowspec.h" #include "nest/route.h" #include "nest/protocol.h" #include "nest/iface.h" diff --git a/lib/flowspec.c b/lib/flowspec.c index e9290b88..ef19aa96 100644 --- a/lib/flowspec.c +++ b/lib/flowspec.c @@ -243,12 +243,37 @@ flow6_next_part(const byte *pos, const byte *end) return flow_next_part(pos, end, 1); } +static const byte * +flow_get_part(const byte *data, uint dlen, uint type, int ipv6) +{ + const byte *part; + + for (part = flow_first_part(data); + part && (part[0] <= type); + part = flow_next_part(part, data+dlen, ipv6)) + if (part[0] == type) + return part; + + return NULL; +} + +const byte * +flow4_get_part(const net_addr_flow4 *f, uint type) +{ + return flow_get_part(f->data, f->length - sizeof(net_addr_flow4), type, 0); +} + +const byte * +flow6_get_part(const net_addr_flow6 *f, uint type) +{ + return flow_get_part(f->data, f->length - sizeof(net_addr_flow6), type, 1); +} + /* * Flowspec accessors */ - static inline ip4_addr flow_read_ip4(const byte *px, uint pxlen) { @@ -282,7 +307,6 @@ flow_read_ip6_part(const byte *part) } - /* * Flowspec validation */ diff --git a/lib/flowspec.h b/lib/flowspec.h index d486cda0..9bafc52e 100644 --- a/lib/flowspec.h +++ b/lib/flowspec.h @@ -83,6 +83,8 @@ const byte *flow4_first_part(const net_addr_flow4 *f); const byte *flow6_first_part(const net_addr_flow6 *f); const byte *flow4_next_part(const byte *pos, const byte *end); const byte *flow6_next_part(const byte *pos, const byte *end); +const byte *flow4_get_part(const net_addr_flow4 *f, uint type); +const byte *flow6_get_part(const net_addr_flow6 *f, uint type); /* @@ -91,6 +93,7 @@ const byte *flow6_next_part(const byte *pos, const byte *end); ip4_addr flow_read_ip4_part(const byte *part); ip6_addr flow_read_ip6_part(const byte *part); +static inline int flow_read_pxlen(const byte *part) { return part[1]; } /* |