summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Zubkov <green@qrator.net>2023-08-24 04:30:42 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2023-08-24 04:33:33 +0200
commitfc3547880aafad726509f0514df2d5e0bb140728 (patch)
tree826c945354f71d509e298fdcb715f0624ccb6add
parenteddc0ffdab239c61cc0e064b6ebd33dfadcef3cd (diff)
Filter: Add bytestring type
- Rename BYTESTRING lexem to BYTETEXT, not to collide with 'bytestring' type name - Add bytestring type with id T_BYTESTRING (0x2c) - Add from_hex() filter function to create bytestring from hex string - Add filter test cases for bytestring type Minor changes by committer.
-rw-r--r--bird-gdb.py1
-rw-r--r--conf/cf-lex.l2
-rw-r--r--conf/confbase.Y2
-rw-r--r--filter/config.Y26
-rw-r--r--filter/data.c10
-rw-r--r--filter/data.h2
-rw-r--r--filter/f-inst.c15
-rw-r--r--filter/f-inst.h1
-rw-r--r--filter/test.conf30
-rw-r--r--nest/config.Y2
-rw-r--r--proto/radv/config.Y4
11 files changed, 81 insertions, 14 deletions
diff --git a/bird-gdb.py b/bird-gdb.py
index 3cf65a9c..262035dc 100644
--- a/bird-gdb.py
+++ b/bird-gdb.py
@@ -34,6 +34,7 @@ class BIRDFValPrinter(BIRDPrinter):
"T_IP": "ip",
"T_NET": "net",
"T_STRING": "s",
+ "T_BYTESTRING": "bs",
"T_PATH_MASK": "path_mask",
"T_PATH": "ad",
"T_CLIST": "ad",
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index 965e1e3f..e789e864 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -272,7 +272,7 @@ WHITE [ \t]
ASSERT(bs->length == len);
cf_lval.bs = bs;
- return BYTESTRING;
+ return BYTETEXT;
}
({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 3dd5fed7..da750d38 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -106,7 +106,7 @@ CF_DECLS
%token <i64> VPN_RD
%token <s> CF_SYM_KNOWN CF_SYM_UNDEFINED
%token <t> TEXT
-%token <bs> BYTESTRING
+%token <bs> BYTETEXT
%type <iface> ipa_scope
%type <i> expr bool pxlen4
diff --git a/filter/config.Y b/filter/config.Y
index a1e5e9f1..e2d133a9 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -301,7 +301,7 @@ CF_DECLS
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ACCEPT, REJECT, ERROR,
INT, BOOL, IP, TYPE, PREFIX, RD, PAIR, QUAD, EC, LC,
- SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
+ SET, STRING, BYTESTRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
IF, THEN, ELSE, CASE,
FOR, IN, DO,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
@@ -317,13 +317,14 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
MIN, MAX,
EMPTY,
FILTER, WHERE, EVAL, ATTRIBUTE,
+ FROM_HEX,
BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT)
%nonassoc THEN
%nonassoc ELSE
%type <xp> cmds_int cmd_prep
-%type <x> term cmd cmd_var cmds cmds_scoped constant constructor print_list var var_init var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
+%type <x> term term_bs cmd cmd_var cmds cmds_scoped constant constructor print_list var var_init var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
%type <fda> dynamic_attr
%type <fsa> static_attr
%type <f> filter where_filter
@@ -404,6 +405,7 @@ type:
| EC { $$ = T_EC; }
| LC { $$ = T_LC; }
| STRING { $$ = T_STRING; }
+ | BYTESTRING { $$ = T_BYTESTRING; }
| BGPMASK { $$ = T_PATH_MASK; }
| BGPPATH { $$ = T_PATH; }
| CLIST { $$ = T_CLIST; }
@@ -714,13 +716,14 @@ bgp_path_tail:
;
constant:
- NUM { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = $1, }); }
- | TRUE { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 1, }); }
- | FALSE { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 0, }); }
- | TEXT { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_STRING, .val.s = $1, }); }
- | fipa { $$ = f_new_inst(FI_CONSTANT, $1); }
- | VPN_RD { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.ec = $1, }); }
- | net_ { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_NET, .val.net = $1, }); }
+ NUM { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = $1, }); }
+ | TRUE { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 1, }); }
+ | FALSE { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 0, }); }
+ | TEXT { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_STRING, .val.s = $1, }); }
+ | BYTETEXT { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BYTESTRING, .val.bs = $1, }); }
+ | fipa { $$ = f_new_inst(FI_CONSTANT, $1); }
+ | VPN_RD { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.ec = $1, }); }
+ | net_ { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_NET, .val.net = $1, }); }
| '[' ']' { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_SET, .val.t = NULL, }); }
| '[' set_items ']' {
DBG( "We've got a set here..." );
@@ -868,9 +871,14 @@ term:
/* | term '.' LEN { $$->code = P('P','l'); } */
+ | term_bs
| function_call
;
+term_bs:
+ FROM_HEX '(' term ')' { $$ = f_new_inst(FI_FROM_HEX, $3); }
+ ;
+
break_command:
ACCEPT { $$ = F_ACCEPT; }
| REJECT { $$ = F_REJECT; }
diff --git a/filter/data.c b/filter/data.c
index 56d746fd..1d740b0d 100644
--- a/filter/data.c
+++ b/filter/data.c
@@ -46,6 +46,7 @@ static const char * const f_type_str[] = {
[T_IP] = "ip",
[T_NET] = "prefix",
[T_STRING] = "string",
+ [T_BYTESTRING] = "bytestring",
[T_PATH_MASK] = "bgpmask",
[T_PATH] = "bgppath",
[T_CLIST] = "clist",
@@ -223,6 +224,12 @@ val_compare(const struct f_val *v1, const struct f_val *v2)
}
static inline int
+bs_same(const struct bytestring *bs1, const struct bytestring *bs2)
+{
+ return (bs1->length == bs2->length) && !memcmp(bs1->data, bs2->data, bs1->length);
+}
+
+static inline int
pmi_same(const struct f_path_mask_item *mi1, const struct f_path_mask_item *mi2)
{
if (mi1->kind != mi2->kind)
@@ -286,6 +293,8 @@ val_same(const struct f_val *v1, const struct f_val *v2)
return 0;
switch (v1->type) {
+ case T_BYTESTRING:
+ return bs_same(v1->val.bs, v2->val.bs);
case T_PATH_MASK:
return pm_same(v1->val.path_mask, v2->val.path_mask);
case T_PATH_MASK_ITEM:
@@ -585,6 +594,7 @@ val_format(const struct f_val *v, buffer *buf)
case T_BOOL: buffer_puts(buf, v->val.i ? "TRUE" : "FALSE"); return;
case T_INT: buffer_print(buf, "%u", v->val.i); return;
case T_STRING: buffer_print(buf, "%s", v->val.s); return;
+ case T_BYTESTRING: bstrbintohex(v->val.bs->data, v->val.bs->length, buf2, 1000, ':'); buffer_print(buf, "%s", buf2); return;
case T_IP: buffer_print(buf, "%I", v->val.ip); return;
case T_NET: buffer_print(buf, "%N", v->val.net); return;
case T_PAIR: buffer_print(buf, "(%u,%u)", v->val.i >> 16, v->val.i & 0xffff); return;
diff --git a/filter/data.h b/filter/data.h
index b3767f7b..f44e08e1 100644
--- a/filter/data.h
+++ b/filter/data.h
@@ -58,6 +58,7 @@ enum f_type {
T_LCLIST = 0x29, /* Large community list */
T_RD = 0x2a, /* Route distinguisher for VPN addresses */
T_PATH_MASK_ITEM = 0x2b, /* Path mask item for path mask constructors */
+ T_BYTESTRING = 0x2c,
T_SET = 0x80,
T_PREFIX_SET = 0x81,
@@ -73,6 +74,7 @@ struct f_val {
ip_addr ip;
const net_addr *net;
const char *s;
+ const struct bytestring *bs;
const struct f_tree *t;
const struct f_trie *ti;
const struct adata *ad;
diff --git a/filter/f-inst.c b/filter/f-inst.c
index 33436853..8a2f474e 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -1555,6 +1555,21 @@
}
+ INST(FI_FROM_HEX, 1, 1) { /* Convert hex text to bytestring */
+ ARG(1, T_STRING);
+
+ int len = bstrhextobin(v1.val.s, NULL);
+ if (len < 0)
+ runtime("Invalid hex string");
+
+ struct bytestring *bs;
+ bs = falloc(sizeof(struct bytestring) + len);
+ bs->length = bstrhextobin(v1.val.s, bs->data);
+ ASSERT(bs->length == (size_t) len);
+
+ RESULT(T_BYTESTRING, bs, bs);
+ }
+
INST(FI_FORMAT, 1, 1) { /* Format */
ARG_ANY(1);
RESULT(T_STRING, s, val_format_str(fpool, &v1));
diff --git a/filter/f-inst.h b/filter/f-inst.h
index 72b080f8..3912df08 100644
--- a/filter/f-inst.h
+++ b/filter/f-inst.h
@@ -19,6 +19,7 @@
#include "filter/data.h"
#include "lib/buffer.h"
#include "lib/flowspec.h"
+#include "lib/string.h"
/* Flags for instructions */
enum f_instruction_flags {
diff --git a/filter/test.conf b/filter/test.conf
index e9e3af89..c014dadd 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -238,6 +238,36 @@ bt_test_suite(t_string, "Testing string matching");
/*
+ * Testing bytestings
+ * ------------------
+ */
+
+function t_bytestring()
+{
+ bytestring bs1 = hex:;
+ bytestring bs2 = hex:0112233445566778899aabbccddeeff0;
+
+ bt_assert(format(bs1) = "");
+ bt_assert(format(bs2) = "01:12:23:34:45:56:67:78:89:9a:ab:bc:cd:de:ef:f0");
+ bt_assert(hex:01:12:23:34:45:56:67:78:89:9a:ab:bc:cd:de:ef:f0 = bs2);
+ bt_assert(01:12:23:34:45:56:67:78:89:9a:ab:bc:cd:de:ef:f0 = bs2);
+ bt_assert(0112233445566778899aabbccddeeff0 = bs2);
+ bt_assert(hex:01234567 = hex:01:23:45:67);
+ bt_assert(hex:0123456789abcdef != bs2);
+ bt_assert(hex:0123456789abcdef != hex:0123);
+ bt_assert(format(hex:0123456789abcdef) = "01:23:45:67:89:ab:cd:ef");
+ bt_assert(from_hex(" ") = bs1);
+ bt_assert(from_hex("01:12:23:34:45:56:67:78:89:9a:ab:bc:cd:de:ef:f0") = bs2);
+ bt_assert(from_hex(format(bs2)) = bs2);
+ bt_assert(from_hex(" 0112:23-34455667 78-89 - 9a-ab bc:cd : de:eff0 ") = bs2);
+}
+
+bt_test_suite(t_bytestring, "Testing bytestrings");
+
+
+
+
+/*
* Testing pairs
* -------------
*/
diff --git a/nest/config.Y b/nest/config.Y
index c83c715b..9197f985 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -548,7 +548,7 @@ pass_key: PASSWORD | KEY;
password_item_begin:
pass_key text { init_password_list(); init_password($2, strlen($2), password_id++); }
- | pass_key BYTESTRING { init_password_list(); init_password($2->data, $2->length, password_id++); }
+ | pass_key BYTETEXT { init_password_list(); init_password($2->data, $2->length, password_id++); }
;
password_item_params:
diff --git a/proto/radv/config.Y b/proto/radv/config.Y
index eeafe6f4..9653cd7b 100644
--- a/proto/radv/config.Y
+++ b/proto/radv/config.Y
@@ -73,7 +73,7 @@ radv_proto_item:
| PREFIX radv_prefix { add_tail(&RADV_CFG->pref_list, NODE this_radv_prefix); }
| RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_CFG->rdnss_list, &radv_dns_list); }
| DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_CFG->dnssl_list, &radv_dns_list); }
- | CUSTOM OPTION TYPE expr VALUE BYTESTRING { radv_add_to_custom_list(&RADV_CFG->custom_list, $4, $6); }
+ | CUSTOM OPTION TYPE expr VALUE BYTETEXT { radv_add_to_custom_list(&RADV_CFG->custom_list, $4, $6); }
| TRIGGER net_ip6 { RADV_CFG->trigger = $2; }
| PROPAGATE ROUTES bool { RADV_CFG->propagate_routes = $3; }
;
@@ -138,7 +138,7 @@ radv_iface_item:
| PREFIX radv_prefix { add_tail(&RADV_IFACE->pref_list, NODE this_radv_prefix); }
| RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_IFACE->rdnss_list, &radv_dns_list); }
| DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_IFACE->dnssl_list, &radv_dns_list); }
- | CUSTOM OPTION TYPE expr VALUE BYTESTRING { radv_add_to_custom_list(&RADV_IFACE->custom_list, $4, $6); }
+ | CUSTOM OPTION TYPE expr VALUE BYTETEXT { radv_add_to_custom_list(&RADV_IFACE->custom_list, $4, $6); }
| RDNSS LOCAL bool { RADV_IFACE->rdnss_local = $3; }
| DNSSL LOCAL bool { RADV_IFACE->dnssl_local = $3; }
| CUSTOM OPTION LOCAL bool { RADV_IFACE->custom_local = $4; }