Commit f9af77fc authored by Daniel Salzman's avatar Daniel Salzman

conf: initial commit for lmdb based configuration

parent 528b2232
......@@ -176,14 +176,14 @@ src/knot/common/ref.c
src/knot/common/ref.h
src/knot/common/time.h
src/knot/common/trim.h
src/knot/conf/cf-lex.l
src/knot/conf/cf-parse.y
src/knot/conf/conf.c
src/knot/conf/conf.h
src/knot/conf/extra.c
src/knot/conf/extra.h
src/knot/conf/includes.c
src/knot/conf/includes.h
src/knot/conf/confdb.c
src/knot/conf/confdb.h
src/knot/conf/scheme.c
src/knot/conf/scheme.h
src/knot/conf/tools.c
src/knot/conf/tools.h
src/knot/ctl/estimator.c
src/knot/ctl/estimator.h
src/knot/ctl/knotc_main.c
......@@ -462,7 +462,6 @@ tests/acl.c
tests/base32hex.c
tests/base64.c
tests/changeset.c
tests/conf.c
tests/descriptor.c
tests/dname.c
tests/dthreads.c
......@@ -486,7 +485,6 @@ tests/requestor.c
tests/rrl.c
tests/rrset.c
tests/rrset_wire.c
tests/sample_conf.h
tests/server.c
tests/utils.c
tests/wire.c
......
......@@ -194,6 +194,14 @@ knotd_SOURCES = \
# static: server shared
libknotd_la_SOURCES = \
knot/conf/conf.c \
knot/conf/conf.h \
knot/conf/confdb.c \
knot/conf/confdb.h \
knot/conf/scheme.c \
knot/conf/scheme.h \
knot/conf/tools.c \
knot/conf/tools.h \
knot/ctl/estimator.c \
knot/ctl/estimator.h \
knot/ctl/process.c \
......
This diff is collapsed.
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* Server configuration and API.
*
* \addtogroup config
*
* @{
*/
#pragma once
#include <stdlib.h>
#include <sys/socket.h>
#include "knot/conf/scheme.h"
#include "libknot/internal/lists.h"
#include "libknot/internal/namedb/namedb.h"
#include "libknot/rrtype/tsig.h"
#include "libknot/yparser/ypscheme.h"
#define CONF_XFERS 10
#define CONF_DEFAULT_ID ((uint8_t *)"\x08""default\0")
#define CONF_DEFAULT_FILE (CONFIG_DIR "/knot.conf")
//#define CONF_DEFAULT_DBDIR (STORAGE_DIR "/confdb")
typedef struct {
const struct namedb_api *api;
yp_item_t *scheme;
mm_ctx_t *mm;
namedb_t *db;
// Read-only transaction for config access.
namedb_txn_t read_txn;
// For automatic NSID or CH ident.
char *hostname;
// For reload if started with config file.
char *filename;
// Temporary database path.
char *tmp_dir;
} conf_t;
typedef struct {
struct sockaddr_storage addr;
struct sockaddr_storage via;
knot_tsig_key_t key;
} conf_remote_t;
typedef struct {
const yp_item_t *item;
const uint8_t *blob;
size_t blob_len;
// Public items.
const uint8_t *data;
size_t len;
int code; // Return code.
} conf_val_t;
typedef struct {
const yp_item_t *item;
namedb_iter_t *iter;
uint8_t key0_code;
// Public items.
int code; // Return code.
} conf_iter_t;
extern conf_t *s_conf;
static inline conf_t* conf(void) {
return s_conf;
}
int conf_new(
conf_t **conf,
const yp_item_t *scheme,
const char *db_dir
);
int conf_clone(
conf_t **conf
);
int conf_post_open(
conf_t *conf
);
void conf_update(
conf_t *conf
);
void conf_free(
conf_t *conf,
bool is_clone
);
int conf_parse(
conf_t *conf,
namedb_txn_t *txn,
const char *input,
bool is_file,
size_t *incl_depth
);
int conf_import(
conf_t *conf,
const char *input,
bool is_file
);
int conf_export(
conf_t *conf,
const char *file_name,
yp_style_t style
);
/*****************/
conf_val_t conf_get(
conf_t *conf,
const yp_name_t *key0_name,
const yp_name_t *key1_name
);
conf_val_t conf_id_get(
conf_t *conf,
const yp_name_t *key0_name,
const yp_name_t *key1_name,
conf_val_t *id
);
conf_val_t conf_zone_get(
conf_t *conf,
const yp_name_t *key1_name,
const knot_dname_t *dname
);
conf_val_t conf_default_get(
conf_t *conf,
const yp_name_t *key1_name
);
size_t conf_id_count(
conf_t *conf,
const yp_name_t *key0_name
);
conf_iter_t conf_iter(
conf_t *conf,
const yp_name_t *key0_name
);
void conf_iter_next(
conf_t *conf,
conf_iter_t *iter
);
conf_val_t conf_iter_id(
conf_t *conf,
conf_iter_t *iter
);
void conf_iter_finish(
conf_t *conf,
conf_iter_t *iter
);
size_t conf_val_count(
conf_val_t *val
);
void conf_val_next(
conf_val_t *val
);
int64_t conf_int(
conf_val_t *val
);
bool conf_bool(
conf_val_t *val
);
unsigned conf_opt(
conf_val_t *val
);
const char* conf_str(
conf_val_t *val
);
char* conf_abs_path(
conf_val_t *val,
const char *base_dir
);
const knot_dname_t* conf_dname(
conf_val_t *val
);
struct sockaddr_storage conf_addr(
conf_val_t *val,
const char *sock_base_dir
);
struct sockaddr_storage conf_net(
conf_val_t *val,
unsigned *prefix_length
);
void conf_data(
conf_val_t *val
);
char* conf_zonefile(
conf_t *conf,
const knot_dname_t *zone
);
char* conf_journalfile(
conf_t *conf,
const knot_dname_t *zone
);
size_t conf_udp_threads(
conf_t *conf
);
size_t conf_tcp_threads(
conf_t *conf
);
int conf_bg_threads(
conf_t *conf
);
void conf_user(
conf_t *conf,
int *uid,
int *gid
);
conf_remote_t conf_remote(
conf_t *conf,
conf_val_t *id
);
This diff is collapsed.
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* Configuration database interface.
*
* \addtogroup config
*
* @{
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "knot/conf/conf.h"
#include "libknot/internal/namedb/namedb.h"
#include "libknot/yparser/ypscheme.h"
/*! Current version of the configuration database structure. */
#define CONF_DB_VERSION 1
/*! Minimum length of a database key ([category_id, item_id]. */
#define CONF_MIN_KEY_LEN (2 * sizeof(uint8_t))
/*! Maximum length of a database key ([category_id, item_id, identifier]. */
#define CONF_MAX_KEY_LEN (CONF_MIN_KEY_LEN + YP_MAX_ID_LEN)
/*! Maximum size of database data. */
#define CONF_MAX_DATA_LEN 65536
enum knot_conf_code {
CONF_CODE_KEY0_ROOT = 0,
CONF_CODE_KEY1_ITEMS = 0,
CONF_CODE_KEY1_ID = 1,
CONF_CODE_KEY1_FIRST = 2,
CONF_CODE_KEY1_LAST = 200,
CONF_CODE_KEY1_VERSION = 255
};
int conf_db_init(
conf_t *conf,
namedb_txn_t *txn
);
int conf_db_set(
conf_t *conf,
namedb_txn_t *txn,
yp_check_ctx_t *in
);
int conf_db_get(
conf_t *conf,
namedb_txn_t *txn,
const yp_name_t *key0,
const yp_name_t *key1,
const uint8_t *id,
size_t id_len,
conf_val_t *out
);
void conf_db_val(
conf_val_t *val
);
void conf_db_val_next(
conf_val_t *val
);
int conf_db_iter_begin(
conf_t *conf,
namedb_txn_t *txn,
const yp_name_t *key0,
conf_iter_t *iter
);
int conf_db_iter_next(
conf_t *conf,
conf_iter_t *iter
);
int conf_db_iter_id(
conf_t *conf,
conf_iter_t *iter,
uint8_t **data,
size_t *data_len
);
void conf_db_iter_finish(
conf_t *conf,
conf_iter_t *iter
);
int conf_db_code(
conf_t *conf,
namedb_txn_t *txn,
uint8_t section_code,
const yp_name_t *name,
bool read_only,
uint8_t *db_code
);
int conf_db_raw_dump(
conf_t *conf,
const char *file_name
);
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include "knot/conf/scheme.h"
#include "knot/conf/tools.h"
#include "knot/common/log.h"
#include "knot/ctl/remote.h"
#include "knot/server/rrl.h"
#include "knot/updates/acl.h"
#include "libknot/rrtype/opt.h"
#include "dnssec/lib/dnssec/tsig.h"
static const lookup_table_t key_algs[] = {
{ DNSSEC_TSIG_HMAC_MD5, "hmac-md5" },
{ DNSSEC_TSIG_HMAC_SHA1, "hmac-sha1" },
{ DNSSEC_TSIG_HMAC_SHA224, "hmac-sha224" },
{ DNSSEC_TSIG_HMAC_SHA256, "hmac-sha256" },
{ DNSSEC_TSIG_HMAC_SHA384, "hmac-sha384" },
{ DNSSEC_TSIG_HMAC_SHA512, "hmac-sha512" },
{ 0, NULL }
};
static const lookup_table_t acl_actions[] = {
{ ACL_ACTION_DENY, "deny" },
{ ACL_ACTION_XFER, "xfer" },
{ ACL_ACTION_NOTF, "notify" },
{ ACL_ACTION_DDNS, "update" },
{ ACL_ACTION_CNTL, "control" },
{ 0, NULL }
};
static const lookup_table_t serial_policies[] = {
{ SERIAL_POLICY_INCREMENT, "increment" },
{ SERIAL_POLICY_UNIXTIME, "unixtime" },
{ 0, NULL }
};
static const lookup_table_t log_severities[] = {
{ LOG_UPTO(LOG_CRIT), "critical" },
{ LOG_UPTO(LOG_ERR), "error" },
{ LOG_UPTO(LOG_WARNING), "warning" },
{ LOG_UPTO(LOG_NOTICE), "notice" },
{ LOG_UPTO(LOG_INFO), "info" },
{ LOG_UPTO(LOG_DEBUG), "debug" },
{ 0, NULL }
};
static const yp_item_t desc_server[] = {
{ C_IDENT, YP_TSTR, YP_VNONE },
{ C_VERSION, YP_TSTR, YP_VNONE },
{ C_NSID, YP_TDATA, YP_VDATA = { 0, NULL, hex_text_to_bin,
hex_text_to_txt } },
{ C_RUNDIR, YP_TSTR, YP_VSTR = { RUN_DIR } },
{ C_USER, YP_TSTR, YP_VNONE },
{ C_PIDFILE, YP_TSTR, YP_VSTR = { "knot.pid" } },
{ C_WORKERS, YP_TINT, YP_VINT = { 1, 255, YP_NIL } },
{ C_BG_WORKERS, YP_TINT, YP_VINT = { 1, 255, YP_NIL } },
{ C_ASYNC_START, YP_TBOOL, YP_VNONE },
{ C_MAX_CONN_IDLE, YP_TINT, YP_VINT = { 0, INT32_MAX, 20, YP_STIME } },
{ C_MAX_CONN_HANDSHAKE, YP_TINT, YP_VINT = { 0, INT32_MAX, 5, YP_STIME } },
{ C_MAX_CONN_REPLY, YP_TINT, YP_VINT = { 0, INT32_MAX, 10, YP_STIME } },
{ C_MAX_TCP_CLIENTS, YP_TINT, YP_VINT = { 0, INT32_MAX, 100 } },
{ C_MAX_UDP_PAYLOAD, YP_TINT, YP_VINT = { KNOT_EDNS_MIN_UDP_PAYLOAD,
KNOT_EDNS_MAX_UDP_PAYLOAD,
4096, YP_SSIZE } },
{ C_TRANSFERS, YP_TINT, YP_VINT = { 1, INT32_MAX, 10 } },
{ C_RATE_LIMIT, YP_TINT, YP_VINT = { 0, INT32_MAX, 0 } },
{ C_RATE_LIMIT_SLIP, YP_TINT, YP_VINT = { 1, RRL_SLIP_MAX, 1 } },
{ C_RATE_LIMIT_SIZE, YP_TINT, YP_VINT = { 1, INT32_MAX, 393241 } },
{ C_LISTEN, YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
static const yp_item_t desc_key[] = {
{ C_ID, YP_TDNAME, YP_VNONE },
{ C_ALG, YP_TOPT, YP_VOPT = { key_algs, DNSSEC_TSIG_UNKNOWN } },
{ C_SECRET, YP_TB64, YP_VNONE },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
static const yp_item_t desc_acl[] = {
{ C_ID, YP_TSTR, YP_VNONE },
{ C_ADDR, YP_TNET, YP_VNONE },
{ C_KEY, YP_TREF, YP_VREF = { C_KEY }, YP_FNONE, { check_ref } },
{ C_ACTION, YP_TOPT, YP_VOPT = { acl_actions, ACL_ACTION_DENY }, YP_FMULTI },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
static const yp_item_t desc_control[] = {
{ C_LISTEN, YP_TADDR, YP_VADDR = { REMOTE_PORT, REMOTE_SOCKET } },
{ C_ACL, YP_TREF, YP_VREF = { C_ACL }, YP_FMULTI, { check_ref } },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
static const yp_item_t desc_remote[] = {
{ C_ID, YP_TSTR, YP_VNONE },
{ C_ADDR, YP_TADDR, YP_VADDR = { 53 } },
{ C_VIA, YP_TADDR, YP_VNONE },
{ C_KEY, YP_TREF, YP_VREF = { C_KEY }, YP_FNONE, { check_ref } },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
#define ZONE_ITEMS \
{ C_STORAGE, YP_TSTR, YP_VSTR = { STORAGE_DIR } }, \
{ C_MASTER, YP_TREF, YP_VREF = { C_RMT }, YP_FMULTI, { check_ref } }, \
{ C_NOTIFY, YP_TREF, YP_VREF = { C_RMT }, YP_FMULTI, { check_ref } }, \
{ C_ACL, YP_TREF, YP_VREF = { C_ACL }, YP_FMULTI, { check_ref } }, \
{ C_SEM_CHECKS, YP_TBOOL, YP_VNONE }, \
{ C_DISABLE_ANY, YP_TBOOL, YP_VNONE }, \
{ C_NOTIFY_TIMEOUT, YP_TINT, YP_VINT = { 1, INT32_MAX, 60, YP_STIME } }, \
{ C_NOTIFY_RETRIES, YP_TINT, YP_VINT = { 1, INT32_MAX, 5 } }, \
{ C_ZONEFILE_SYNC, YP_TINT, YP_VINT = { 0, INT32_MAX, 0, YP_STIME } }, \
{ C_IXFR_DIFF, YP_TBOOL, YP_VNONE }, \
{ C_IXFR_FSLIMIT, YP_TINT, YP_VINT = { 0, INT64_MAX, INT64_MAX, YP_SSIZE } }, \
{ C_DNSSEC_ENABLE, YP_TBOOL, YP_VNONE }, \
{ C_DNSSEC_KEYDIR, YP_TSTR, YP_VSTR = { "keys" } }, \
{ C_SIG_LIFETIME, YP_TINT, YP_VINT = { 3 * 3600, INT32_MAX, 30 * 24 * 3600, YP_STIME } }, \
{ C_SERIAL_POLICY, YP_TOPT, YP_VOPT = { serial_policies, SERIAL_POLICY_INCREMENT } }, \
{ C_COMMENT, YP_TSTR, YP_VNONE },
static const yp_item_t desc_template[] = {
{ C_ID, YP_TSTR, YP_VNONE },
ZONE_ITEMS
{ NULL }
};
static const yp_item_t desc_zone[] = {
{ C_DOMAIN, YP_TDNAME, YP_VNONE },
{ C_FILE, YP_TSTR, YP_VNONE },
{ C_TPL, YP_TREF, YP_VREF = { C_TPL }, YP_FNONE, { check_ref } },
ZONE_ITEMS
{ NULL }
};
static const yp_item_t desc_log[] = {
{ C_TO, YP_TSTR, YP_VNONE },
{ C_SERVER, YP_TOPT, YP_VOPT = { log_severities, 0 } },
{ C_ZONE, YP_TOPT, YP_VOPT = { log_severities, 0 } },
{ C_ANY, YP_TOPT, YP_VOPT = { log_severities, 0 } },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
const yp_item_t conf_scheme[] = {
{ C_SRV, YP_TGRP, YP_VGRP = { desc_server } },
{ C_KEY, YP_TGRP, YP_VGRP = { desc_key }, YP_FMULTI },
{ C_ACL, YP_TGRP, YP_VGRP = { desc_acl }, YP_FMULTI },
{ C_CTL, YP_TGRP, YP_VGRP = { desc_control } },
{ C_RMT, YP_TGRP, YP_VGRP = { desc_remote }, YP_FMULTI },
{ C_TPL, YP_TGRP, YP_VGRP = { desc_template }, YP_FMULTI },
{ C_ZONE, YP_TGRP, YP_VGRP = { desc_zone }, YP_FMULTI },
{ C_LOG, YP_TGRP, YP_VGRP = { desc_log }, YP_FMULTI },
{ C_INCL, YP_TSTR, YP_VNONE, YP_FNONE, { NULL, include_file } },
{ NULL }
};
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* Server configuration scheme.
*
* \addtogroup config
*
* @{
*/
#pragma once
#include "libknot/yparser/ypscheme.h"
#define C_ACL "\x03""acl"
#define C_ACTION "\x06""action"
#define C_ADDR "\x07""address"
#define C_ALG "\x09""algorithm"
#define C_ANY "\x03""any"
#define C_ASYNC_START "\x12""asynchronous-start"
#define C_BG_WORKERS "\x12""background-workers"
#define C_COMMENT "\x07""comment"
#define C_CTL "\x07""control"
#define C_DISABLE_ANY "\x0B""disable-any"
#define C_DOMAIN "\x06""domain"
#define C_DNSSEC_ENABLE "\x0D""dnssec-enable"
#define C_DNSSEC_KEYDIR "\x0D""dnssec-keydir"
#define C_FILE "\x04""file"
#define C_IDENT "\x08""identity"
#define C_ID "\x02""id"
#define C_INCL "\x07""include"
#define C_IXFR_DIFF "\x15""ixfr-from-differences"
#define C_IXFR_FSLIMIT "\x0C""ixfr-fslimit"
#define C_KEY "\x03""key"
#define C_LOG "\x03""log"
#define C_LISTEN "\x06""listen"
#define C_MASTER "\x06""master"
#define C_MAX_CONN_HANDSHAKE "\x12""max-conn-handshake"
#define C_MAX_CONN_IDLE "\x0D""max-conn-idle"
#define C_MAX_CONN_REPLY "\x0E""max-conn-reply"
#define C_MAX_TCP_CLIENTS "\x0F""max-tcp-clients"
#define C_MAX_UDP_PAYLOAD "\x0F""max-udp-payload"
#define C_MODULE "\x06""module"
#define C_NOTIFY "\x06""notify"
#define C_NOTIFY_RETRIES "\x0E""notify-retries"
#define C_NOTIFY_TIMEOUT "\x0E""notify-timeout"
#define C_NSID "\x04""nsid"
#define C_PIDFILE "\x07""pidfile"
#define C_RATE_LIMIT "\x0A""rate-limit"
#define C_RATE_LIMIT_SIZE "\x0F""rate-limit-size"
#define C_RATE_LIMIT_SLIP "\x0F""rate-limit-slip"
#define C_RMT "\x06""remote"
#define C_RUNDIR "\x06""rundir"
#define C_SECRET "\x06""secret"
#define C_SEM_CHECKS "\x0F""semantic-checks"
#define C_SERIAL_POLICY "\x0D""serial-policy"
#define C_SERVER "\x06""server"
#define C_SIG_LIFETIME "\x12""signature-lifetime"
#define C_STORAGE "\x07""storage"
#define C_SRV "\x06""server"
#define C_TO "\x02""to"
#define C_TPL "\x08""template"
#define C_TRANSFERS "\x09""transfers"
#define C_USER "\x04""user"
#define C_VERSION "\x07""version"
#define C_VIA "\x03""via"
#define C_WORKERS "\x07""workers"
#define C_ZONE "\x04""zone"
#define C_ZONEFILE_SYNC "\x0D""zonefile-sync"
enum {
SERIAL_POLICY_INCREMENT = 1,
SERIAL_POLICY_UNIXTIME = 2
};
extern const yp_item_t conf_scheme[];
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <dirent.h>
#include <inttypes.h>
#include <libgen.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "knot/conf/tools.h"
#include "knot/conf/conf.h"
#include "knot/conf/confdb.h"
#include "knot/conf/scheme.h"
#include "libknot/errcode.h"
#include "libknot/yparser/yptrafo.h"
static int hex_to_num(char hex) {
if (hex >= '0' && hex <= '9') return hex - '0';
if (hex >= 'a' && hex <= 'f') return hex - 'a' + 10;
if (hex >= 'A' && hex <= 'F') return hex - 'A' + 10;
return -1;
}
int hex_text_to_bin(
char const *txt,
size_t txt_len,
uint8_t *bin,
size_t *bin_len)
{
// Check for hex notation (leading "0x").
if (txt_len >= 2 && txt[0] == '0' && txt[1] == 'x') {
txt += 2;
txt_len -= 2;
if (txt_len % 2 != 0) {
return KNOT_EINVAL;