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
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.
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,
| 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); }
}
}
- 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))
#include "conf/conf.h"
#include "filter/filter.h"
#include "filter/data.h"
+#include "lib/flowspec.h"
/* Flags for instructions */
enum f_instruction_flags {
#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"
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)
{
}
-
/*
* Flowspec validation
*/
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);
/*
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]; }
/*