From fdb7c222bf234ab6cc9d1757642ac336fb39bbd8 Mon Sep 17 00:00:00 2001
From: Alexander Zubkov <green@qrator.net>
Date: Thu, 29 Jun 2023 13:51:01 +0200
Subject: [PATCH] Conf: use nonterminal bytestring instead of BYTETEXT

Nonterminal bytestring allows to provide expressions to be evaluated in places
where BYTETEXT is used now: passwords, radv custom option.
---
 conf/confbase.Y     | 40 ++++++++++++++++++++++++++++++++++++++++
 nest/config.Y       |  5 +----
 proto/radv/config.Y |  4 ++--
 3 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/conf/confbase.Y b/conf/confbase.Y
index e109ddf5..5006c185 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -117,9 +117,12 @@ CF_DECLS
 %type <mls> label_stack_start label_stack
 
 %type <t> text opttext
+%type <bs> bytestring
 %type <s> symbol
 %type <kw> kw_sym
 
+%type <x> bytestring_inst
+
 %nonassoc PREFIX_DUMMY
 %left AND OR
 %nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA PO PC
@@ -395,6 +398,43 @@ opttext:
  | /* empty */ { $$ = NULL; }
  ;
 
+bytestring:
+   BYTETEXT
+ | TEXT {
+     int len = strlen($1);
+     struct bytestring *bs = cfg_allocz(sizeof(*bs) + len);
+     $$ = bs;
+     bs->length = len;
+     memcpy(bs->data, $1, len);
+   }
+ | bytestring_inst {
+     struct f_val val = cf_eval($1, T_VOID);
+
+     switch (val.type) {
+       case T_BYTESTRING:
+	 $$ = val.val.bs;
+	 break;
+
+       case T_STRING:
+         int len = strlen(val.val.s);
+         struct bytestring *bs = cfg_allocz(sizeof(*bs) + len);
+         $$ = bs;
+         bs->length = len;
+         memcpy(bs->data, val.val.s, len);
+         break;
+
+       default:
+	 cf_error("Bytestring value is expected");
+     }
+   }
+ ;
+
+bytestring_inst:
+   symbol_value
+ | term_bs
+ | '(' term ')' { $$ = $2; }
+ ;
+
 
 CF_CODE
 
diff --git a/nest/config.Y b/nest/config.Y
index 610b1c01..2fdbb991 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -546,10 +546,7 @@ password_item:
 
 pass_key: PASSWORD | KEY;
 
-password_item_begin:
-    pass_key text { init_password_list(); init_password($2, strlen($2), password_id++); }
-  | pass_key BYTETEXT { init_password_list(); init_password($2->data, $2->length, password_id++); }
-;
+password_item_begin: pass_key bytestring { init_password_list(); init_password($2->data, $2->length, password_id++); };
 
 password_item_params:
    /* empty */ { }
diff --git a/proto/radv/config.Y b/proto/radv/config.Y
index 9653cd7b..9c5e1761 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 BYTETEXT { radv_add_to_custom_list(&RADV_CFG->custom_list, $4, $6); }
+ | CUSTOM OPTION TYPE expr VALUE bytestring { 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 BYTETEXT { radv_add_to_custom_list(&RADV_IFACE->custom_list, $4, $6); }
+ | CUSTOM OPTION TYPE expr VALUE bytestring { 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; }
-- 
2.41.0

