aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/bird.sgml8
-rw-r--r--filter/config.Y5
-rw-r--r--filter/f-inst.c68
-rw-r--r--filter/f-inst.h1
-rw-r--r--filter/filter.c3
-rw-r--r--lib/flowspec.c28
-rw-r--r--lib/flowspec.h3
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]; }
/*