]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
yp: add new type for mixed integer with options
authorDaniel Salzman <daniel.salzman@nic.cz>
Thu, 20 Nov 2025 13:43:09 +0000 (14:43 +0100)
committerLibor Peltan <libor.peltan@nic.cz>
Mon, 24 Nov 2025 09:43:25 +0000 (10:43 +0100)
distro/pkg/deb/libknot16.symbols
src/knot/conf/base.c
src/knot/conf/conf.c
src/knot/nameserver/query_module.c
src/libknot/yparser/ypschema.h
src/libknot/yparser/yptrafo.c
src/libknot/yparser/yptrafo.h
tests/libknot/test_ypschema.c
tests/libknot/test_yptrafo.c

index 0e02587b7eb0bb045b57cce13a7b17947ec26542..cd0f9f5162e5f08365b846f52277166c2159047c 100644 (file)
@@ -376,6 +376,8 @@ libknot.so.16 libknot16 #MINVER#
  yp_int_to_txt@Base 3.5.0
  yp_item_to_bin@Base 3.5.0
  yp_item_to_txt@Base 3.5.0
+ yp_optint_to_bin@Base 3.5.2
+ yp_optint_to_txt@Base 3.5.2
  yp_option_to_bin@Base 3.5.0
  yp_option_to_txt@Base 3.5.0
  yp_parse@Base 3.5.0
index b3f0fe0b76a755f639ebb38c526f4bf9ed31e9dd..23fa1433bab6fdd635af24b286c22874051d55eb 100644 (file)
@@ -1171,6 +1171,9 @@ static void export_type(jsonw_t *w, const yp_item_t *item)
                        jsonw_str(w, "type", "string");
                );
                break;
+       case YP_TOPTINT:
+               // TODO
+               break;
        default:
                assert(0);
                break;
index 38250616b07dfacdef67a95df501acbc92b91773..fe20b000263b043a71404934ba000de2c0ad6915 100644 (file)
@@ -605,8 +605,10 @@ int64_t conf_int_alt(
 {
        assert(val != NULL && val->item != NULL);
        assert(val->item->type == YP_TINT ||
+              val->item->type == YP_TOPTINT ||
               (val->item->type == YP_TREF &&
-               val->item->var.r.ref->var.g.id->type == YP_TINT));
+               (val->item->var.r.ref->var.g.id->type == YP_TINT ||
+                val->item->var.r.ref->var.g.id->type == YP_TOPTINT)));
 
        if (val->code == KNOT_EOK) {
                conf_val(val);
index 0872e2523d6c4d8961a6f8d11856785ed0c5bda7..8d7c4af2debc03809e80a77a2a5a94cbb34aa94d 100644 (file)
@@ -473,6 +473,9 @@ static void set_val(yp_type_t type, knotd_conf_val_t *item, conf_val_t *val)
        case YP_TDATA:
                item->data = conf_data(val, &item->data_len);
                break;
+       case YP_TOPTINT:
+               item->integer = conf_int(val);
+               break;
        default:
                return;
        }
index 6e2b9f70c9aeb535a133b6e79168b7577eb43c8c..3be4eb0483563962e3fcdb55cc9f8b54d2aee44a 100644 (file)
@@ -52,6 +52,7 @@ struct wire_ctx;
 #define YP_VDATA       .var.d
 #define YP_VREF                .var.r
 #define YP_VGRP                .var.g
+#define YP_VOPTINT     .var.i
 
 /*! Schema item name is a char string with a leading byte (string length). */
 typedef char yp_name_t;
@@ -71,6 +72,7 @@ typedef enum {
        YP_TDATA,     /*!< Customized data. */
        YP_TREF,      /*!< Reference to another item. */
        YP_TGRP,      /*!< Group of sub-items. */
+       YP_TOPTINT,   /*!< Option from the list or integer. */
 } yp_type_t;
 
 /*! Schema item flags. */
@@ -121,6 +123,8 @@ typedef union {
                yp_style_t unit;
                /*! Alternative default value. */
                int64_t dflt_alt;
+               /*! List of options if OPTINT. */
+               struct knot_lookup const *opts;
        } i;
        /*! Boolean variables. */
        struct {
index 0550f7d96269b121e1763a633761692f3aae0be1..30321164f3759858870a21f2be00d67a411fb327 100644 (file)
@@ -724,14 +724,19 @@ int yp_addr_range_to_txt(
 _public_
 int yp_option_to_bin(
        YP_TXT_BIN_PARAMS,
-       const knot_lookup_t *opts)
+       const knot_lookup_t *opts,
+       bool extended)
 {
        YP_CHECK_PARAMS_BIN;
 
        while (opts->name != NULL) {
                if (YP_LEN == strlen(opts->name) &&
                    strncasecmp((char *)in->position, opts->name, YP_LEN) == 0) {
-                       wire_ctx_write_u8(out, opts->id);
+                       if (extended) {
+                               wire_ctx_write_u64(out, opts->id);
+                       } else {
+                               wire_ctx_write_u8(out, opts->id);
+                       }
                        wire_ctx_skip(in, YP_LEN);
                        YP_CHECK_RET;
                }
@@ -744,9 +749,10 @@ int yp_option_to_bin(
 _public_
 int yp_option_to_txt(
        YP_BIN_TXT_PARAMS,
-       const knot_lookup_t *opts)
+       const knot_lookup_t *opts,
+       bool extended)
 {
-       uint8_t id = wire_ctx_read_u8(in);
+       int64_t id = extended ? wire_ctx_read_u64(in) : wire_ctx_read_u8(in);
 
        while (opts->name != NULL) {
                if (id == opts->id) {
@@ -955,6 +961,41 @@ int yp_base64_to_txt(
        YP_CHECK_RET;
 }
 
+_public_
+int yp_optint_to_bin(
+       YP_TXT_BIN_PARAMS,
+       int64_t min,
+       int64_t max,
+       const knot_lookup_t *opts,
+       yp_style_t style)
+{
+       YP_CHECK_PARAMS_BIN;
+
+       const char first = *in->position;
+       if (is_digit(first) || first == '-') {
+               return yp_int_to_bin(in, out, stop, min, max, style);
+       } else {
+               return yp_option_to_bin(in, out, stop, opts, true);
+       }
+}
+
+_public_
+int yp_optint_to_txt(
+       YP_BIN_TXT_PARAMS,
+       const knot_lookup_t *opts,
+       yp_style_t style)
+{
+       YP_CHECK_PARAMS_TXT;
+
+       size_t offset = wire_ctx_offset(in);
+       if (yp_option_to_txt(in, out, opts, true) == KNOT_EOK) {
+               return KNOT_EOK;
+       } else {
+               wire_ctx_set_offset(in, offset);
+               return yp_int_to_txt(in, out, style);
+       }
+}
+
 _public_
 int yp_item_to_bin(
        const yp_item_t *item,
@@ -982,7 +1023,7 @@ int yp_item_to_bin(
                ret = yp_bool_to_bin(&in, &out, NULL);
                break;
        case YP_TOPT:
-               ret = yp_option_to_bin(&in, &out, NULL, item->var.o.opts);
+               ret = yp_option_to_bin(&in, &out, NULL, item->var.o.opts, false);
                break;
        case YP_TSTR:
                ret = yp_str_to_bin(&in, &out, NULL);
@@ -1012,6 +1053,11 @@ int yp_item_to_bin(
                                     out.position, &ref_len);
                wire_ctx_skip(&out, ref_len);
                break;
+       case YP_TOPTINT:
+               ret = yp_optint_to_bin(&in, &out, NULL, item->var.i.min,
+                                      item->var.i.max, item->var.i.opts,
+                                      item->var.i.unit);
+               break;
        default:
                ret = KNOT_EOK;
        }
@@ -1061,7 +1107,7 @@ int yp_item_to_txt(
                ret = yp_bool_to_txt(&in, &out);
                break;
        case YP_TOPT:
-               ret = yp_option_to_txt(&in, &out, item->var.o.opts);
+               ret = yp_option_to_txt(&in, &out, item->var.o.opts, false);
                break;
        case YP_TSTR:
                ret = yp_str_to_txt(&in, &out);
@@ -1092,6 +1138,9 @@ int yp_item_to_txt(
                                     &ref_len, style | YP_SNOQUOTE);
                wire_ctx_skip(&out, ref_len);
                break;
+       case YP_TOPTINT:
+               ret = yp_optint_to_txt(&in, &out, item->var.i.opts, item->var.i.unit & style);
+               break;
        default:
                ret = KNOT_EOK;
        }
index 1a448f67cb9513f3d35fbd241685e3f01f482d72..457f805cf353a76bc36a820687be53b49c67f3b9 100644 (file)
@@ -265,12 +265,14 @@ int yp_addr_range_to_txt(
 
 int yp_option_to_bin(
        YP_TXT_BIN_PARAMS,
-       const struct knot_lookup *opts
+       const struct knot_lookup *opts,
+       bool extended
 );
 
 int yp_option_to_txt(
        YP_BIN_TXT_PARAMS,
-       const struct knot_lookup *opts
+       const struct knot_lookup *opts,
+       bool extended
 );
 
 int yp_dname_to_bin(
@@ -297,4 +299,18 @@ int yp_base64_to_txt(
        YP_BIN_TXT_PARAMS
 );
 
+int yp_optint_to_bin(
+       YP_TXT_BIN_PARAMS,
+       int64_t min,
+       int64_t max,
+       const knot_lookup_t *opts,
+       yp_style_t style
+);
+
+int yp_optint_to_txt(
+       YP_BIN_TXT_PARAMS,
+       const knot_lookup_t *opts,
+       yp_style_t style
+);
+
 /*! @} */
index 6ba7ae0592a249af0a59fb59087eedd6ec26b408..b792824807b672fc89685cc2ad3ade7a87b402e0 100644 (file)
@@ -25,6 +25,7 @@
 #define C_REF          "\x09""reference"
 #define C_GRP          "\x05""group"
 #define C_MULTIGRP     "\x0B""multi-group"
+#define C_OPTINT       "\x06""optint"
 
 static const yp_item_t group[] = {
        { C_INT, YP_TINT, YP_VINT = { 0, 100, YP_NIL } },
@@ -43,7 +44,13 @@ static const knot_lookup_t opts[] = {
        { 1,   "one" },
        { 10,  "ten" },
        { 0, NULL }
-       };
+};
+
+static const knot_lookup_t optints[] = {
+       {  1000,  "opt1" },
+       { -2000,  "opt2" },
+       { 0, NULL }
+};
 
 static const yp_item_t static_schema[] = {
        { C_OPT,      YP_TOPT,   YP_VOPT = { opts } },
@@ -53,6 +60,7 @@ static const yp_item_t static_schema[] = {
        { C_MULTIGRP, YP_TGRP,   YP_VGRP = { multi_group }, YP_FMULTI },
        { C_REF,      YP_TREF,   YP_VREF = { C_MULTIGRP } },
        { C_DATA,     YP_TDATA,  YP_VNONE },
+       { C_OPTINT,   YP_TOPTINT,YP_VOPTINT = { -2, 1000, -10, YP_STIME, 0, optints } },
        { NULL }
 };
 
index 066db6d36d895119dd9149a105d14a4603800dd9..b8f91baae562c01a7901581300457cdefe61858e 100644 (file)
@@ -297,6 +297,27 @@ static void ref_test(const char *txt, bool val)
        ok(memcmp(txt, t, t_len) == 0, "compare");
 }
 
+static void optint_test(const char *txt, int64_t num, yp_style_t s,
+                        int64_t min, int64_t max, const knot_lookup_t *opts)
+{
+       int ret;
+       uint8_t b[64];
+       size_t b_len = sizeof(b);
+       char t[64];
+       size_t t_len = sizeof(t);
+       yp_item_t i = { NULL, YP_TOPTINT, YP_VOPTINT = { min, max, 0, s, 0, opts } };
+
+       diag("optint \"%s\":", txt);
+       ret = yp_item_to_bin(&i, txt, strlen(txt), b, &b_len);
+       is_int(KNOT_EOK, ret, "txt to bin");
+       ok(yp_int(b) == num, "compare");
+       ret = yp_item_to_txt(&i, b, b_len, t, &t_len, s | YP_SNOQUOTE);
+       is_int(KNOT_EOK, ret, "bin to txt");
+       ok(strlen(t) == t_len, "txt ret length");
+       ok(strlen(txt) == t_len, "txt length");
+       ok(memcmp(txt, t, t_len) == 0, "compare");
+}
+
 int main(int argc, char *argv[])
 {
        plan_lazy();
@@ -401,5 +422,21 @@ int main(int argc, char *argv[])
        /* Ref tests. */
        ref_test("on", true);
 
+       /* Optint tests. */
+       static const knot_lookup_t optints[] = {
+               { 0,         "opt1" },
+               { -1,        "opt2" },
+               { INT32_MIN, "opt3" },
+               { 0,         NULL }
+       };
+       int64_t optmin = -1000000, optmax = 10000;
+       optint_test("-1000000", -1000000, YP_SNONE, optmin, optmax, optints);
+       optint_test("-2", -2, YP_SNONE, optmin, optmax, optints);
+       optint_test("1", 1, YP_SNONE, optmin, optmax, optints);
+       optint_test("1h", 3600, YP_STIME, optmin, optmax, optints);
+       optint_test("opt1", 0, YP_STIME, optmin, optmax, optints);
+       optint_test("opt2", -1, YP_STIME, optmin, optmax, optints);
+       optint_test("opt3", INT32_MIN, YP_STIME, optmin, optmax, optints);
+
        return 0;
 }