]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Add support for src/dst accessors for Flowspec and SADR
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 9 Dec 2019 03:23:01 +0000 (04:23 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 9 Dec 2019 03:23:01 +0000 (04:23 +0100)
doc/bird.sgml
filter/config.Y
filter/f-inst.c
filter/f-inst.h
filter/filter.c
lib/flowspec.c
lib/flowspec.h

index aeea613fd4107a30eee51dcb26c38e4d111741d0..2363fb52d39ca4f0624d70899da324c25915a716 100644 (file)
@@ -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.
index 340053ba7b11108a22700c2c37a5d78f25696fba..c8b868af76457eb33392ec4e325b9baa0416d157 100644 (file)
@@ -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); }
index 3bd0249ca4d3d54fc305d5a99fe9a02064c19e55..e3e0d76d9dafa1fd02342540eb72a77902b10f24 100644 (file)
     }
   }
 
-  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))
index 8be8443b33433b433207ca081dab3ddfc40b9998..bfa163fcd261249016b775ef6ff744a69d7011fc 100644 (file)
@@ -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 {
index ad9588b2adfe3ed7d249ca56a5e0366ea78abe99..e505d570daf6e0898a7754ba9b8c42870d9e3dd8 100644 (file)
@@ -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"
index e9290b88972a7e0db376587540fd95fe01242fc2..ef19aa9626c394b3ca40960415c4fbc51b559e62 100644 (file)
@@ -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
  */
index d486cda020ba0c91c9ceb99d647ef9674b52e67a..9bafc52efb97331ca5ef91cfa9f5be78d26a8fdc 100644 (file)
@@ -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]; }
 
 
 /*