On Sat, Jun 24, 2023 at 3:16 PM Ondrej Zajicek <santi...@crfreenet.org> wrote: > > On Sat, Jun 24, 2023 at 02:20:03AM +0200, Alexander Zubkov wrote: > > > Yes, the original idea there was to add bytestring as a data type, make > > > hex() a regular (filter) function instead of special function-like > > > syntax, and add equivalent of 'expr' grammar term for other data types. > > > > > > > I see. I think I can look into preparing a patch for that too. > > But for such variant I would suggest using function names like > > "from_hex/base64" instead of "hex/base64", or something including > > bytestring reference: "bs_hex". Because the simple variants could be > > misleading when used not only in the limited set of scopes. > > they can be thought of converting to hex/base64 representation too. Or they > > could collide with "hex" function to convert from string to int, which > > someone would need to implement in the future. > > Yes, that is true. > > You can try it if you are brave enough to add new f_val type.
Take a look at the patch, please. Waiting for the critics and improvement suggestions. Some remarks: It was needed to add another function like f_eval_int(), so I decided to do some more generic approach and replaced all occurences of f_eval_int() with it. Bytestrings for password caused conflicts with strings on being presented as symbol names. Insted of adding something like "string_or_bytestring", I decided to allow bytestring term to be derived from strings too. I also used different approach from "expr", where it evaluates only complex expressions. I decided that handling constants and symbols via evalutation would be easier. So I have special case only for literals. There is separate "term_bs" term, so that it is possible to use "from_hex()" without outer brackets. Again, added a new file in lib dir for bytestrings. And I changed some struct bytestring pointers to const struct bytestring. > > > > > > I think this should be quite good too, the only problem with it > > > > is inability to mix "hex" symbol with hex("...") bytestrings. > > > > > > This is an issue with any keyword, so not a big thing. > > > > > > > Yes. By the way what do you think about the patch that allows using > > keywords and symbols together? Is it viable? > > Answered there. > > > -- > Elen sila lumenn' omentielvo > > Ondrej 'Santiago' Zajicek (email: santi...@crfreenet.org) > OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) > "To err is human -- to blame it on a computer is even more so."
commit 7cc6700c64e94019df1743de685c84dbca85b406 Author: Alexander Zubkov <gr...@qrator.net> Date: Mon Jun 26 02:38:54 2023 +0200 Conf: make bytestring a type 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 9025a84d..59b88bd5 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -256,37 +256,26 @@ WHITE [ \t] } ({XIGIT}{2}){16,}|{XIGIT}{2}(:{XIGIT}{2}){15,}|hex:({XIGIT}{2}(:?{XIGIT}{2})*)? { - char *s, *sb = yytext; - size_t len = 0, i; + char *sb = yytext; + size_t len = 0; struct bytestring *bytes; - byte *b; /* skip 'hex:' prefix */ if (sb[0] == 'h' && sb[1] == 'e' && sb[2] == 'x' && sb[3] == ':') sb += 4; - s = sb; - while (*s) { - len++; - s += 2; - if (*s == ':') - s++; - } + errno = 0; + len = bstrhextobin(sb, 0); + if (errno || len == (size_t)-1) + cf_error("Invalid hex string"); + bytes = cfg_allocz(sizeof(*bytes) + len); bytes->length = len; - b = &bytes->data[0]; - s = sb; - errno = 0; - for (i = 0; i < len; i++) { - *b = bstrtobyte16(s); - if (errno == ERANGE) - cf_error("Invalid hex string"); - b++; - s += 2; - if (*s == ':') - s++; - } + bstrhextobin(sb, bytes->data); + if (errno) + cf_error("Invalid hex string"); + cf_lval.bs = bytes; return BYTESTRING; } @@ -361,7 +350,6 @@ else: { quoted_buffer_init(); } -<QUOTED>\n cf_error("Unterminated string"); <QUOTED><<EOF>> cf_error("Unterminated string"); <QUOTED>["] { BEGIN(INITIAL); @@ -370,7 +358,7 @@ else: { return TEXT; } -<QUOTED>. BUFFER_PUSH(quoted_buffer) = yytext[0]; +<QUOTED>(.|\n) BUFFER_PUSH(quoted_buffer) = yytext[0]; <INITIAL,COMMENT><<EOF>> { if (check_eof()) return END; } diff --git a/conf/confbase.Y b/conf/confbase.Y index 3e8f5807..ebaa93b8 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -94,7 +94,7 @@ CF_DECLS struct channel_limit cl; struct timeformat *tf; mpls_label_stack *mls; - struct bytestring *bs; + const struct bytestring *bs; } %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT @@ -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 @@ -155,14 +158,14 @@ conf: definition ; definition: DEFINE symbol '=' term ';' { struct f_val *val = cfg_allocz(sizeof(struct f_val)); - if (f_eval(f_linearize($4, 1), cfg_mem, val) > F_RETURN) cf_error("Runtime error"); + f_eval_conf($4, val, T_VOID); cf_define_symbol($2, SYM_CONSTANT | val->type, val, val); } ; expr: NUM - | '(' term ')' { $$ = f_eval_int(f_linearize($2, 1)); } + | '(' term ')' { $$ = f_eval_val($2, T_INT, i); } | CF_SYM_KNOWN { if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected"); $$ = SYM_VAL($1).i; } @@ -395,6 +398,43 @@ opttext: | /* empty */ { $$ = NULL; } ; +bytestring: + BYTESTRING + | 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; + f_eval_conf($1, &val, 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/filter/config.Y b/filter/config.Y index a1e5e9f1..6718fb78 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -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 @@ -343,6 +344,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, CF_GRAMMAR +kw_sym: FROM_HEX ; + conf: filter_def ; filter_def: FILTER symbol { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); } @@ -357,7 +360,7 @@ filter_def: conf: filter_eval ; filter_eval: - EVAL term { f_eval_int(f_linearize($2, 1)); } + EVAL term { f_eval_val($2, T_INT, i); } ; conf: custom_attr ; @@ -404,6 +407,7 @@ type: | EC { $$ = T_EC; } | LC { $$ = T_LC; } | STRING { $$ = T_STRING; } + | BYTESTRING { $$ = T_BYTESTRING; } | BGPMASK { $$ = T_PATH_MASK; } | BGPPATH { $$ = T_PATH; } | CLIST { $$ = T_CLIST; } @@ -571,7 +575,7 @@ set_atom: | VPN_RD { $$.type = T_RD; $$.val.ec = $1; } | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } | '(' term ')' { - if (f_eval(f_linearize($2, 1), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error"); + f_eval_conf($2, &($$), T_VOID); if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type"); } | CF_SYM_KNOWN { @@ -583,13 +587,13 @@ set_atom: switch_atom: NUM { $$.type = T_INT; $$.val.i = $1; } - | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int(f_linearize($2, 1)); } + | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_val($2, T_INT, i); } | fipa { $$ = $1; } | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } ; cnum: - term { $$ = f_eval_int(f_linearize($1, 1)); } + term { $$ = f_eval_val($1, T_INT, i); } pair_item: '(' cnum ',' cnum ')' { $$ = f_new_pair_item($2, $2, $4, $4); } @@ -714,13 +718,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, }); } + | BYTESTRING { $$ = 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 +873,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..62573f4e 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", @@ -286,6 +287,8 @@ val_same(const struct f_val *v1, const struct f_val *v2) return 0; switch (v1->type) { + case T_BYTESTRING: + return v1->val.bs->length == v2->val.bs->length && !memcmp(v1->val.bs->data, v2->val.bs->data, v1->val.bs->length); case T_PATH_MASK: return pm_same(v1->val.path_mask, v2->val.path_mask); case T_PATH_MASK_ITEM: @@ -585,6 +588,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, 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..565aa2a9 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -1555,6 +1555,27 @@ } + INST(FI_FROM_HEX, 1, 1) { /* Convert hex text to bytestring */ + ARG(1, T_STRING); + + size_t len; + struct bytestring *bs; + + errno = 0; + len = bstrhextobin(v1.val.s, 0); + if (errno || len == (size_t)-1) + runtime("Invalid hex string"); + + bs = falloc(sizeof(*bs) + len); + bs->length = len; + + bstrhextobin(v1.val.s, bs->data); + if (errno) + runtime("Invalid hex string"); + + 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..185c01ac 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -13,12 +13,15 @@ #ifndef _BIRD_F_INST_H_ #define _BIRD_F_INST_H_ +#include <errno.h> + #include "nest/bird.h" #include "conf/conf.h" #include "filter/filter.h" #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/filter.c b/filter/filter.c index 20a380dc..2d19f438 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -373,30 +373,18 @@ f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres) } /* - * f_eval_int - get an integer value of a term + * f_eval_conf - evaluate a value of a term and check its type * Called internally from the config parser, uses its internal memory pool * for allocations. Do not call in other cases. */ -uint -f_eval_int(const struct f_line *expr) +void +f_eval_conf(const struct f_inst *inst, struct f_val *val, int type) { - /* Called independently in parse-time to eval expressions */ - filter_state = (struct filter_state) { - .stack = &filter_stack, - .pool = cfg_mem, - }; - - struct f_val val; - - LOG_BUFFER_INIT(filter_state.buf); - - if (interpret(&filter_state, expr, &val) > F_RETURN) + if (f_eval(f_linearize(inst, 1), cfg_mem, val) > F_RETURN) cf_error("Runtime error while evaluating expression; see log for details"); - if (val.type != T_INT) - cf_error("Integer expression expected"); - - return val.val.i; + if (type != T_VOID && val->type != type) + cf_error("Expression of type %s expected", f_type_name(type)); } /* diff --git a/filter/filter.h b/filter/filter.h index 26c1037b..6e54b4ad 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -43,6 +43,7 @@ static inline const char *filter_return_str(const enum filter_return fret) { struct f_val; /* The filter encapsulating structure to be pointed-to from outside */ +struct f_inst; struct f_line; struct filter { struct symbol *sym; @@ -53,9 +54,14 @@ struct rte; enum filter_return f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags); enum filter_return f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool); -uint f_eval_int(const struct f_line *expr); +void f_eval_conf(const struct f_inst *inst, struct f_val *val, int type); enum filter_return f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf); +#define f_eval_val(from_, type_, name_) ({ \ + struct f_val val; \ + f_eval_conf(from_, &val, type_); \ + val.val.name_; }) + const char *filter_name(const struct filter *filter); int filter_same(const struct filter *new, const struct filter *old); int f_same(const struct f_line *f1, const struct f_line *f2); diff --git a/filter/test.conf b/filter/test.conf index e9e3af89..819e15a1 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -237,6 +237,27 @@ bt_test_suite(t_string, "Testing string matching"); +/* + * Testing bytestings + * ------------------ + */ + +function t_bytestring() +{ + bytestring bs1 = hex:; + bytestring bs2 = hex:00112233445566778899aabbccddeeff; + + bt_assert(format(bs1) = "hex:"); + bt_assert(hex:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff = bs2); + bt_assert(00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff = bs2); + bt_assert(00112233445566778899aabbccddeeff = bs2); + bt_assert(format(hex:0123456789abcdef) = "hex:01:23:45:67:89:ab:cd:ef"); + bt_assert(from_hex(" ") = bs1); + bt_assert(from_hex(" 0011:2233-44556677 88-99 - aa-bb cc:dd : ee:ff ") = bs1); +} + +bt_test_suite(t_bytestring, "Testing bytestrings"); + /* * Testing pairs * ------------- diff --git a/lib/Makefile b/lib/Makefile index 812f721c..296152ff 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,4 +1,4 @@ -src := bitmap.c bitops.c blake2s.c blake2b.c checksum.c event.c flowspec.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c +src := bitmap.c bitops.c blake2s.c blake2b.c bytestring.c checksum.c event.c flowspec.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c obj := $(src-o-files) $(all-daemon) diff --git a/lib/bytestring.c b/lib/bytestring.c new file mode 100644 index 00000000..f25c9398 --- /dev/null +++ b/lib/bytestring.c @@ -0,0 +1,93 @@ +/* + * BIRD Library -- Work with binary sequences + * + * (c) 2023 TODO + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#include <ctype.h> +#include <errno.h> + +#include "nest/bird.h" +#include "lib/string.h" +#include "conf/conf.h" + +char +toxdigit(int b) +{ + if (b >= 0 && b <= 9) + return ('0' + b); + else if (b >= 10 && b < 16) + return ('a' + b - 10); + else + return 0; +} + +int +bstrhextobin(const char *s, byte *d) +{ + size_t len = 0; + + while (*s) { + if (!isalnum(s[0])) { + s++; + continue; + } + + if (!isalnum(s[1])) { + errno = ERANGE; + return -1; + } + + if (d) { + errno = 0; + *d = bstrtobyte16(s); + if (errno) + return -1; + d++; + } + + s += 2; + len++; + } + + return len; +} + +int +bstrbintohex(const struct bytestring *bs, byte *buf, uint size) +{ + if (size < 8) + return -1; + + size_t len = bs->length; + const byte *b = bs->data; + + byte *end = buf + size - 4; + + memcpy(buf, "hex", 3); + buf += 3; + + if (!len) { + strcpy(buf, ":"); + return 0; + } + + size_t i; + for (i = 0; i < len && buf + 3 <= end; ++i, buf += 3) { + byte x = b[i]; + buf[0] = ':'; + buf[1] = toxdigit(x >> 4); + buf[2] = toxdigit(x & 0xF); + } + + if (i < len) { + strcpy(buf, "..."); + return -1; + } + + *buf = 0; + + return 0; +} diff --git a/lib/string.h b/lib/string.h index 2829943d..62f03eb6 100644 --- a/lib/string.h +++ b/lib/string.h @@ -33,6 +33,10 @@ u64 bstrtoul10(const char *str, char **end); u64 bstrtoul16(const char *str, char **end); byte bstrtobyte16(const char *str); +struct bytestring; +int bstrhextobin(const char *s, byte *d); +int bstrbintohex(const struct bytestring *bs, byte *buf, uint size); + int patmatch(const byte *pat, const byte *str); static inline char *xbasename(const char *str) diff --git a/nest/config.Y b/nest/config.Y index c83c715b..49222442 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -167,7 +167,7 @@ rtrid: idval: NUM { $$ = $1; } - | '(' term ')' { $$ = f_eval_int(f_linearize($2, 1)); } + | '(' term ')' { $$ = f_eval_val($2, T_INT, i); } | IP4 { $$ = ip4_to_u32($1); } | CF_SYM_KNOWN { if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD)) @@ -547,8 +547,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 BYTESTRING { init_password_list(); init_password($2->data, $2->length, password_id++); } + pass_key bytestring { 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 5c213d50..3213403a 100644 --- a/proto/radv/config.Y +++ b/proto/radv/config.Y @@ -26,7 +26,7 @@ static list radv_dns_list; /* Used by radv_rdnss and radv_dnssl */ static u8 radv_mult_val; /* Used by radv_mult for second return value */ static inline void -radv_add_to_custom_list(list *l, int type, struct bytestring *payload) +radv_add_to_custom_list(list *l, int type, const struct bytestring *payload) { if (type < 0 || type > 255) cf_error("RA cusom type must be in range 0-255"); struct radv_custom_config *cf = cfg_allocz(sizeof(struct radv_custom_config)); @@ -71,7 +71,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); } - | OTHER TYPE expr BYTESTRING { radv_add_to_custom_list(&RADV_CFG->custom_list, $3, $4); } + | OTHER TYPE expr bytestring { radv_add_to_custom_list(&RADV_CFG->custom_list, $3, $4); } | TRIGGER net_ip6 { RADV_CFG->trigger = $2; } | PROPAGATE ROUTES bool { RADV_CFG->propagate_routes = $3; } ; @@ -136,7 +136,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); } - | OTHER TYPE expr BYTESTRING { radv_add_to_custom_list(&RADV_IFACE->custom_list, $3, $4); } + | OTHER TYPE expr bytestring { radv_add_to_custom_list(&RADV_IFACE->custom_list, $3, $4); } | RDNSS LOCAL bool { RADV_IFACE->rdnss_local = $3; } | DNSSL LOCAL bool { RADV_IFACE->dnssl_local = $3; } | OTHER LOCAL bool { RADV_IFACE->custom_local = $3; } diff --git a/proto/radv/radv.h b/proto/radv/radv.h index 8c716158..2baf0bad 100644 --- a/proto/radv/radv.h +++ b/proto/radv/radv.h @@ -129,7 +129,7 @@ struct radv_custom_config { node n; u8 type; /* Identifier of the type of option */ - struct bytestring *payload; /* Payload of the option */ + const struct bytestring *payload; /* Payload of the option */ }; /*