From d068a95304a57306b732f45a5105be0357886f7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Oto=20=C5=A0=C5=A5=C3=A1va?= <oto.stava@nic.cz>
Date: Wed, 10 Jul 2024 16:38:26 +0200
Subject: [PATCH] drop libknot <=3.2.x support

---
 .github/workflows/macOS.yaml                  |   2 +-
 .gitlab-ci.yml                                |  52 +-
 NEWS                                          |   3 +-
 daemon/io.c                                   |   8 +-
 daemon/lua/kres-gen-31.lua                    | 697 ------------------
 .../lua/{kres-gen-32.lua => kres-gen-33.lua}  |   1 +
 daemon/lua/meson.build                        |   6 +-
 daemon/zimport.c                              |   4 -
 lib/resolve.c                                 |   4 -
 lib/utils.c                                   |   4 -
 meson.build                                   |   2 +-
 scripts/enable-repo-cznic-labs.sh             |  30 +
 scripts/enable-repo.py                        | 132 ----
 13 files changed, 56 insertions(+), 889 deletions(-)
 delete mode 100644 daemon/lua/kres-gen-31.lua
 rename daemon/lua/{kres-gen-32.lua => kres-gen-33.lua} (99%)
 create mode 100755 scripts/enable-repo-cznic-labs.sh
 delete mode 100755 scripts/enable-repo.py

diff --git a/.github/workflows/macOS.yaml b/.github/workflows/macOS.yaml
index f7fe0907a..6f022d320 100644
--- a/.github/workflows/macOS.yaml
+++ b/.github/workflows/macOS.yaml
@@ -8,7 +8,7 @@ jobs:
     runs-on: macOS-latest
     strategy:
       matrix:
-        knot-version: ['3.2', '3.3']
+        knot-version: ['3.3']
 
     steps:
       - name: Checkout resolver code
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4c4b6e81b..75a6ccbd7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -10,7 +10,7 @@ variables:
   RESPDIFF_COUNT: 1
   RESPDIFF_FORCE: 0
   RESPERF_FORCE: 0
-  KNOT_VERSION: '3.1'
+  KNOT_VERSION: '3.3'
   LIBKRES_ABI: 9
   LIBKRES_NAME: libkres
   MESON_TEST: meson test -C build_ci* -t 4 --print-errorlogs
@@ -135,32 +135,18 @@ build-stable:
     - ninja -C build_ci_stable install >/dev/null
     - ${MESON_TEST} --suite unit --suite config --suite dnstap --no-suite snowflake
 
-build-deb11-knot31:
-  <<: *build
-  image: $IMAGE_PREFIX/debian11-knot_3_1:$IMAGE_TAG
-  script:
-    - meson build_ci_deb11_knot31 --prefix=$PREFIX -Dmalloc=disabled -Dwerror=true -Dextra_tests=enabled
-    - ninja -C build_ci_deb11_knot31
-    - ninja -C build_ci_deb11_knot31 install >/dev/null
-    - ${MESON_TEST} --suite unit --suite config --suite dnstap --no-suite snowflake
-
-build-deb11-knot32:
-  <<: *build
-  image: $IMAGE_PREFIX/debian11-knot_3_2:$IMAGE_TAG
-  script:
-    - meson build_ci_deb11_knot32 --prefix=$PREFIX -Dmalloc=disabled -Dwerror=true -Dextra_tests=enabled
-    - ninja -C build_ci_deb11_knot32
-    - ninja -C build_ci_deb11_knot32 install >/dev/null
-    - ${MESON_TEST} --suite unit --suite config --suite dnstap --no-suite snowflake
-
-build-deb12-knot32:
-  <<: *build
-  image: $IMAGE_PREFIX/debian12-knot_3_2:$IMAGE_TAG
-  script:
-    - meson build_ci_deb12_knot32 --prefix=$PREFIX -Dmalloc=disabled -Dwerror=true -Dextra_tests=enabled
-    - ninja -C build_ci_deb12_knot32
-    - ninja -C build_ci_deb12_knot32 install >/dev/null
-    - ${MESON_TEST} --suite unit --suite config --suite dnstap --no-suite snowflake
+# This is currently the same as stable - uncomment this once Knot 3.4 is
+# released and we are building against that, to keep sanity-checking the 3.3
+# support.
+#
+#build-deb12-knot33:
+#  <<: *build
+#  image: $IMAGE_PREFIX/debian12-knot_3_3:$IMAGE_TAG
+#  script:
+#    - meson build_ci_deb12_knot33 --prefix=$PREFIX -Dmalloc=disabled -Dwerror=true -Dextra_tests=enabled
+#    - ninja -C build_ci_deb12_knot33
+#    - ninja -C build_ci_deb12_knot33 install >/dev/null
+#    - ${MESON_TEST} --suite unit --suite config --suite dnstap --no-suite snowflake
 
 build-deb12-knot-master:
   <<: *build
@@ -309,12 +295,9 @@ lint:coverity:
     - ninja -C build_ci_lib daemon/kresd
     - ninja -C build_ci_lib kres-gen
     - git diff --quiet || (git diff; exit 1)
-kres-gen-31:
+kres-gen-33:
   <<: *kres-gen
-  image: $IMAGE_PREFIX/debian11-knot_3_1:$IMAGE_TAG
-kres-gen-32:
-  <<: *kres-gen
-  image: $IMAGE_PREFIX/debian12-knot_3_2:$IMAGE_TAG
+  image: $IMAGE_PREFIX/debian12-knot_3_3:$IMAGE_TAG
 
 root.hints:
   <<: *sanity
@@ -613,7 +596,7 @@ obs:odvr:
 
 .enable_repo_build: &enable_repo_build
   before_script:
-    - ./scripts/enable-repo.py build
+    - ./scripts/enable-repo-cznic-labs.sh knot-dns
 
 .pkg_test: &pkg_test
   stage: pkg
@@ -665,10 +648,12 @@ pkg:make-archive:
 
 pkg:debian-12:
   <<: *pkg_test_deb
+  <<: *enable_repo_build
   image: $CI_REGISTRY/packaging/apkg/full/debian-12
 
 pkg:debian-11:
   <<: *pkg_test_deb
+  <<: *enable_repo_build
   image: $CI_REGISTRY/packaging/apkg/full/debian-11
 
 pkg:ubuntu-24.04:
@@ -677,6 +662,7 @@ pkg:ubuntu-24.04:
 
 pkg:ubuntu-22.04:
   <<: *pkg_test_deb
+  <<: *enable_repo_build
   image: $CI_REGISTRY/packaging/apkg/full/ubuntu-22.04
 
 pkg:ubuntu-20.04:
diff --git a/NEWS b/NEWS
index fabf7b756..28c6a1c9a 100644
--- a/NEWS
+++ b/NEWS
@@ -34,8 +34,7 @@ Incompatible changes
   the default behaviour as well. See the `relevant documentation section
   <https://www.knot-resolver.cz/documentation/latest/config-cache-predict.html>`_
   for more.
-- libknot 3.0.x support is dropped (!1558)
-  Upstream last maintained 3.0.x in spring 2022.
+- libknot <=3.2.x support is dropped (!1565)
 
 Bugfixes
 --------
diff --git a/daemon/io.c b/daemon/io.c
index 7f91fa97b..cf3727875 100644
--- a/daemon/io.c
+++ b/daemon/io.c
@@ -823,16 +823,10 @@ int io_listen_xdp(uv_loop_t *loop, struct endpoint *ep, const char *ifname)
 
 	// This call is a libknot version hell, unfortunately.
 	int ret = knot_xdp_init(&xhd->socket, ifname, ep->nic_queue,
-		#if KNOT_VERSION_HEX < 0x030200
-			ep->port ? ep->port : (KNOT_XDP_LISTEN_PORT_PASS | 0),
-			KNOT_XDP_LOAD_BPF_MAYBE
-		#else
 			KNOT_XDP_FILTER_UDP | (ep->port ? 0 : KNOT_XDP_FILTER_PASS),
 			ep->port, 0/*quic_port*/,
 			KNOT_XDP_LOAD_BPF_MAYBE,
-			NULL/*xdp_config*/
-		#endif
-		);
+			NULL/*xdp_config*/);
 
 	if (!ret) xdp_warn_mode(ifname);
 
diff --git a/daemon/lua/kres-gen-31.lua b/daemon/lua/kres-gen-31.lua
deleted file mode 100644
index 7b7274f37..000000000
--- a/daemon/lua/kres-gen-31.lua
+++ /dev/null
@@ -1,697 +0,0 @@
--- SPDX-License-Identifier: GPL-3.0-or-later
-
-local ffi = require('ffi')
---[[ This file is generated by ./kres-gen.sh ]] ffi.cdef[[
-
-typedef @time_t@ time_t;
-typedef @time_t@ __time_t;
-typedef @time_t@ __suseconds_t;
-struct timeval {
-	__time_t tv_sec;
-	__suseconds_t tv_usec;
-};
-
-typedef struct knot_dump_style knot_dump_style_t;
-extern const knot_dump_style_t KR_DUMP_STYLE_DEFAULT;
-struct kr_cdb_api {};
-struct lru {};
-typedef enum {KNOT_ANSWER, KNOT_AUTHORITY, KNOT_ADDITIONAL} knot_section_t;
-typedef struct {
-	uint16_t pos;
-	uint16_t flags;
-	uint16_t compress_ptr[16];
-} knot_rrinfo_t;
-typedef unsigned char knot_dname_t;
-typedef struct {
-	uint16_t len;
-	uint8_t data[];
-} knot_rdata_t;
-typedef struct {
-	uint16_t count;
-	uint32_t size;
-	knot_rdata_t *rdata;
-} knot_rdataset_t;
-typedef struct knot_db_val {
-	void *data;
-	size_t len;
-} knot_db_val_t;
-
-typedef struct knot_mm {
-	void *ctx, *alloc, *free;
-} knot_mm_t;
-
-typedef void *(*map_alloc_f)(void *, size_t);
-typedef void (*map_free_f)(void *baton, void *ptr);
-typedef void (*trace_log_f) (const struct kr_request *, const char *);
-typedef void (*trace_callback_f)(struct kr_request *);
-typedef uint8_t * (*alloc_wire_f)(struct kr_request *req, uint16_t *maxlen);
-typedef bool (*addr_info_f)(struct sockaddr*);
-typedef void (*zi_callback)(int state, void *param);
-typedef struct {
-	knot_dname_t *_owner;
-	uint32_t _ttl;
-	uint16_t type;
-	uint16_t rclass;
-	knot_rdataset_t rrs;
-	void *additional;
-} knot_rrset_t;
-
-struct kr_module;
-typedef char *(kr_prop_cb)(void *, struct kr_module *, const char *);
-typedef unsigned char knot_dname_storage_t[255];
-typedef struct knot_pkt knot_pkt_t;
-typedef struct {
-	uint8_t *ptr[18];
-} knot_edns_options_t;
-typedef struct {
-	knot_pkt_t *pkt;
-	uint16_t pos;
-	uint16_t count;
-} knot_pktsection_t;
-typedef struct knot_compr {
-	uint8_t *wire;
-	knot_rrinfo_t *rrinfo;
-	struct {
-		uint16_t pos;
-		uint8_t labels;
-	} suffix;
-} knot_compr_t;
-struct knot_pkt {
-	uint8_t *wire;
-	size_t size;
-	size_t max_size;
-	size_t parsed;
-	uint16_t reserved;
-	uint16_t qname_size;
-	uint16_t rrset_count;
-	uint16_t flags;
-	knot_rrset_t *opt_rr;
-	knot_rrset_t *tsig_rr;
-	knot_edns_options_t *edns_opts;
-	struct {
-		uint8_t *pos;
-		size_t len;
-	} tsig_wire;
-	knot_section_t current;
-	knot_pktsection_t sections[3];
-	size_t rrset_allocd;
-	knot_rrinfo_t *rr_info;
-	knot_rrset_t *rr;
-	knot_mm_t mm;
-	knot_compr_t compr;
-};
-typedef struct trie trie_t;
-struct kr_qflags {
-	_Bool NO_MINIMIZE : 1;
-	_Bool NO_IPV6 : 1;
-	_Bool NO_IPV4 : 1;
-	_Bool TCP : 1;
-	_Bool NO_ANSWER : 1;
-	_Bool RESOLVED : 1;
-	_Bool AWAIT_IPV4 : 1;
-	_Bool AWAIT_IPV6 : 1;
-	_Bool AWAIT_CUT : 1;
-	_Bool NO_EDNS : 1;
-	_Bool CACHED : 1;
-	_Bool NO_CACHE : 1;
-	_Bool EXPIRING : 1;
-	_Bool ALLOW_LOCAL : 1;
-	_Bool DNSSEC_WANT : 1;
-	_Bool DNSSEC_BOGUS : 1;
-	_Bool DNSSEC_INSECURE : 1;
-	_Bool DNSSEC_CD : 1;
-	_Bool STUB : 1;
-	_Bool ALWAYS_CUT : 1;
-	_Bool DNSSEC_WEXPAND : 1;
-	_Bool PERMISSIVE : 1;
-	_Bool STRICT : 1;
-	_Bool BADCOOKIE_AGAIN : 1;
-	_Bool CNAME : 1;
-	_Bool REORDER_RR : 1;
-	_Bool TRACE : 1;
-	_Bool NO_0X20 : 1;
-	_Bool DNSSEC_NODS : 1;
-	_Bool DNSSEC_OPTOUT : 1;
-	_Bool NONAUTH : 1;
-	_Bool FORWARD : 1;
-	_Bool DNS64_MARK : 1;
-	_Bool CACHE_TRIED : 1;
-	_Bool NO_NS_FOUND : 1;
-	_Bool PKT_IS_SANE : 1;
-	_Bool DNS64_DISABLE : 1;
-	_Bool PASSTHRU_LEGACY : 1;
-};
-typedef struct ranked_rr_array_entry {
-	uint32_t qry_uid;
-	uint8_t rank;
-	uint8_t revalidation_cnt;
-	_Bool cached : 1;
-	_Bool yielded : 1;
-	_Bool to_wire : 1;
-	_Bool expiring : 1;
-	_Bool in_progress : 1;
-	_Bool dont_cache : 1;
-	knot_rrset_t *rr;
-} ranked_rr_array_entry_t;
-typedef struct {
-	ranked_rr_array_entry_t **at;
-	size_t len;
-	size_t cap;
-} ranked_rr_array_t;
-typedef struct kr_http_header_array_entry {
-	char *name;
-	char *value;
-} kr_http_header_array_entry_t;
-typedef struct {
-	kr_http_header_array_entry_t *at;
-	size_t len;
-	size_t cap;
-} kr_http_header_array_t;
-typedef struct {
-	union kr_sockaddr *at;
-	size_t len;
-	size_t cap;
-} kr_sockaddr_array_t;
-struct kr_zonecut {
-	knot_dname_t *name;
-	knot_rrset_t *key;
-	knot_rrset_t *trust_anchor;
-	struct kr_zonecut *parent;
-	trie_t *nsset;
-	knot_mm_t *pool;
-	_Bool avoid_resolving;
-};
-typedef struct {
-	struct kr_query **at;
-	size_t len;
-	size_t cap;
-} kr_qarray_t;
-struct kr_rplan {
-	kr_qarray_t pending;
-	kr_qarray_t resolved;
-	struct kr_query *initial;
-	struct kr_request *request;
-	knot_mm_t *pool;
-	uint32_t next_uid;
-};
-struct kr_request_qsource_flags {
-	_Bool tcp : 1;
-	_Bool tls : 1;
-	_Bool http : 1;
-	_Bool xdp : 1;
-};
-typedef unsigned long kr_rule_tags_t;
-struct kr_rule_zonefile_config {
-	const char *filename;
-	const char *input_str;
-	size_t input_len;
-	_Bool is_rpz;
-	_Bool nodata;
-	kr_rule_tags_t tags;
-	const char *origin;
-	uint32_t ttl;
-};
-struct kr_rule_fwd_flags {
-	_Bool is_auth : 1;
-	_Bool is_tcp : 1;
-	_Bool is_nods : 1;
-};
-typedef struct kr_rule_fwd_flags kr_rule_fwd_flags_t;
-struct kr_extended_error {
-	int32_t info_code;
-	const char *extra_text;
-};
-struct kr_request {
-	struct kr_context *ctx;
-	knot_pkt_t *answer;
-	struct kr_query *current_query;
-	struct {
-		const struct sockaddr *addr;
-		const struct sockaddr *comm_addr;
-		const struct sockaddr *dst_addr;
-		const knot_pkt_t *packet;
-		struct kr_request_qsource_flags flags;
-		struct kr_request_qsource_flags comm_flags;
-		size_t size;
-		int32_t stream_id;
-		kr_http_header_array_t headers;
-	} qsource;
-	struct {
-		unsigned int rtt;
-		const struct kr_transport *transport;
-	} upstream;
-	struct kr_qflags options;
-	int state;
-	ranked_rr_array_t answ_selected;
-	ranked_rr_array_t auth_selected;
-	ranked_rr_array_t add_selected;
-	_Bool answ_validated;
-	_Bool auth_validated;
-	uint8_t rank;
-	struct kr_rplan rplan;
-	trace_log_f trace_log;
-	trace_callback_f trace_finish;
-	int vars_ref;
-	knot_mm_t pool;
-	unsigned int uid;
-	struct {
-		addr_info_f is_tls_capable;
-		addr_info_f is_tcp_connected;
-		addr_info_f is_tcp_waiting;
-		kr_sockaddr_array_t forwarding_targets;
-	} selection_context;
-	unsigned int count_no_nsaddr;
-	unsigned int count_fail_row;
-	alloc_wire_f alloc_wire_cb;
-	kr_rule_tags_t rule_tags;
-	struct kr_extended_error extended_error;
-};
-enum kr_rank {KR_RANK_INITIAL, KR_RANK_OMIT, KR_RANK_TRY, KR_RANK_INDET = 4, KR_RANK_BOGUS, KR_RANK_MISMATCH, KR_RANK_MISSING, KR_RANK_INSECURE, KR_RANK_AUTH = 16, KR_RANK_SECURE = 32};
-typedef struct kr_cdb * kr_cdb_pt;
-struct kr_cdb_stats {
-	uint64_t open;
-	uint64_t close;
-	uint64_t count;
-	uint64_t count_entries;
-	uint64_t clear;
-	uint64_t commit;
-	uint64_t read;
-	uint64_t read_miss;
-	uint64_t write;
-	uint64_t remove;
-	uint64_t remove_miss;
-	uint64_t match;
-	uint64_t match_miss;
-	uint64_t read_leq;
-	uint64_t read_leq_miss;
-	uint64_t read_less;
-	double usage_percent;
-};
-typedef struct uv_timer_s uv_timer_t;
-struct kr_cache {
-	kr_cdb_pt db;
-	const struct kr_cdb_api *api;
-	struct kr_cdb_stats stats;
-	uint32_t ttl_min;
-	uint32_t ttl_max;
-	struct timeval checkpoint_walltime;
-	uint64_t checkpoint_monotime;
-	uv_timer_t *health_timer;
-};
-typedef struct kr_layer {
-	int state;
-	struct kr_request *req;
-	const struct kr_layer_api *api;
-	knot_pkt_t *pkt;
-	struct sockaddr *dst;
-	_Bool is_stream;
-} kr_layer_t;
-typedef struct kr_layer_api {
-	int (*begin)(kr_layer_t *);
-	int (*reset)(kr_layer_t *);
-	int (*finish)(kr_layer_t *);
-	int (*consume)(kr_layer_t *, knot_pkt_t *);
-	int (*produce)(kr_layer_t *, knot_pkt_t *);
-	int (*checkout)(kr_layer_t *, knot_pkt_t *, struct sockaddr *, int);
-	int (*answer_finalize)(kr_layer_t *);
-	void *data;
-	int cb_slots[];
-} kr_layer_api_t;
-struct kr_prop {
-	kr_prop_cb *cb;
-	const char *name;
-	const char *info;
-};
-struct kr_module {
-	char *name;
-	int (*init)(struct kr_module *);
-	int (*deinit)(struct kr_module *);
-	int (*config)(struct kr_module *, const char *);
-	const kr_layer_api_t *layer;
-	const struct kr_prop *props;
-	void *lib;
-	void *data;
-};
-struct kr_server_selection {
-	_Bool initialized;
-	void (*choose_transport)(struct kr_query *, struct kr_transport **);
-	void (*update_rtt)(struct kr_query *, const struct kr_transport *, unsigned int);
-	void (*error)(struct kr_query *, const struct kr_transport *, enum kr_selection_error);
-	struct local_state *local_state;
-};
-typedef int kr_log_level_t;
-enum kr_log_group {LOG_GRP_UNKNOWN = -1, LOG_GRP_SYSTEM = 1, LOG_GRP_CACHE, LOG_GRP_IO, LOG_GRP_NETWORK, LOG_GRP_TA, LOG_GRP_TLS, LOG_GRP_GNUTLS, LOG_GRP_TLSCLIENT, LOG_GRP_XDP, LOG_GRP_DOH, LOG_GRP_DNSSEC, LOG_GRP_HINT, LOG_GRP_PLAN, LOG_GRP_ITERATOR, LOG_GRP_VALIDATOR, LOG_GRP_RESOLVER, LOG_GRP_SELECTION, LOG_GRP_ZCUT, LOG_GRP_COOKIES, LOG_GRP_STATISTICS, LOG_GRP_REBIND, LOG_GRP_WORKER, LOG_GRP_POLICY, LOG_GRP_TASENTINEL, LOG_GRP_TASIGNALING, LOG_GRP_TAUPDATE, LOG_GRP_DAF, LOG_GRP_DETECTTIMEJUMP, LOG_GRP_DETECTTIMESKEW, LOG_GRP_GRAPHITE, LOG_GRP_PREFILL, LOG_GRP_PRIMING, LOG_GRP_SRVSTALE, LOG_GRP_WATCHDOG, LOG_GRP_NSID, LOG_GRP_DNSTAP, LOG_GRP_TESTS, LOG_GRP_DOTAUTH, LOG_GRP_HTTP, LOG_GRP_CONTROL, LOG_GRP_MODULE, LOG_GRP_DEVEL, LOG_GRP_RENUMBER, LOG_GRP_EDE, LOG_GRP_RULES, LOG_GRP_PROTOLAYER, LOG_GRP_REQDBG};
-struct kr_query_data_src {
-	_Bool initialized;
-	_Bool all_set;
-	uint8_t rule_depth;
-	kr_rule_fwd_flags_t flags;
-	knot_db_val_t targets_ptr;
-};
-enum kr_rule_sub_t {KR_RULE_SUB_EMPTY = 1, KR_RULE_SUB_NXDOMAIN, KR_RULE_SUB_NODATA, KR_RULE_SUB_REDIRECT};
-enum kr_proto {KR_PROTO_INTERNAL, KR_PROTO_UDP53, KR_PROTO_TCP53, KR_PROTO_DOT, KR_PROTO_DOH, KR_PROTO_DOQ, KR_PROTO_COUNT};
-typedef unsigned char kr_proto_set;
-kr_layer_t kr_layer_t_static;
-_Bool kr_dbg_assertion_abort;
-int kr_dbg_assertion_fork;
-const uint32_t KR_RULE_TTL_DEFAULT;
-
-typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
-				const struct kr_query *qry);
-
-void kr_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner,
-			uint16_t type, uint16_t rclass, uint32_t ttl);
-struct kr_query {
-	struct kr_query *parent;
-	knot_dname_t *sname;
-	uint16_t stype;
-	uint16_t sclass;
-	uint16_t id;
-	uint16_t reorder;
-	struct kr_qflags flags;
-	struct kr_qflags forward_flags;
-	uint32_t secret;
-	uint32_t uid;
-	int32_t vld_limit_crypto_remains;
-	uint32_t vld_limit_uid;
-	uint64_t creation_time_mono;
-	uint64_t timestamp_mono;
-	struct timeval timestamp;
-	struct kr_zonecut zone_cut;
-	struct kr_layer_pickle *deferred;
-	struct kr_query_data_src data_src;
-	int8_t cname_depth;
-	struct kr_query *cname_parent;
-	struct kr_request *request;
-	kr_stale_cb stale_cb;
-	struct kr_server_selection server_selection;
-};
-struct kr_context {
-	struct kr_qflags options;
-	knot_rrset_t *downstream_opt_rr;
-	knot_rrset_t *upstream_opt_rr;
-	trie_t *trust_anchors;
-	trie_t *negative_anchors;
-	int32_t vld_limit_crypto;
-	struct kr_zonecut root_hints;
-	struct kr_cache cache;
-	unsigned int cache_rtt_tout_retry_interval;
-	char _stub[];
-};
-struct kr_transport {
-	knot_dname_t *ns_name;
-	/* beware: hidden stub, to avoid hardcoding sockaddr lengths */
-};
-const char *knot_strerror(int);
-knot_dname_t *knot_dname_copy(const knot_dname_t *, knot_mm_t *);
-knot_dname_t *knot_dname_from_str(uint8_t *, const char *, size_t);
-int knot_dname_in_bailiwick(const knot_dname_t *, const knot_dname_t *);
-_Bool knot_dname_is_equal(const knot_dname_t *, const knot_dname_t *);
-size_t knot_dname_labels(const uint8_t *, const uint8_t *);
-size_t knot_dname_size(const knot_dname_t *);
-void knot_dname_to_lower(knot_dname_t *);
-char *knot_dname_to_str(char *, const knot_dname_t *, size_t);
-knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *, uint16_t);
-int knot_rdataset_merge(knot_rdataset_t *, const knot_rdataset_t *, knot_mm_t *);
-int knot_rrset_add_rdata(knot_rrset_t *, const uint8_t *, uint16_t, knot_mm_t *);
-void knot_rrset_free(knot_rrset_t *, knot_mm_t *);
-int knot_rrset_txt_dump(const knot_rrset_t *, char **, size_t *, const knot_dump_style_t *);
-int knot_rrset_txt_dump_data(const knot_rrset_t *, const size_t, char *, const size_t, const knot_dump_style_t *);
-size_t knot_rrset_size(const knot_rrset_t *);
-int knot_pkt_begin(knot_pkt_t *, knot_section_t);
-int knot_pkt_put_question(knot_pkt_t *, const knot_dname_t *, uint16_t, uint16_t);
-int knot_pkt_put_rotate(knot_pkt_t *, uint16_t, const knot_rrset_t *, uint16_t, uint16_t);
-knot_pkt_t *knot_pkt_new(void *, uint16_t, knot_mm_t *);
-void knot_pkt_free(knot_pkt_t *);
-int knot_pkt_parse(knot_pkt_t *, unsigned int);
-knot_rrset_t *kr_request_ensure_edns(struct kr_request *);
-knot_pkt_t *kr_request_ensure_answer(struct kr_request *);
-int kr_request_set_extended_error(struct kr_request *, int, const char *);
-struct kr_rplan *kr_resolve_plan(struct kr_request *);
-knot_mm_t *kr_resolve_pool(struct kr_request *);
-struct kr_query *kr_rplan_push(struct kr_rplan *, struct kr_query *, const knot_dname_t *, uint16_t, uint16_t);
-int kr_rplan_pop(struct kr_rplan *, struct kr_query *);
-struct kr_query *kr_rplan_resolved(struct kr_rplan *);
-struct kr_query *kr_rplan_last(struct kr_rplan *);
-int kr_forward_add_target(struct kr_request *, const struct sockaddr *);
-_Bool kr_log_is_debug_fun(enum kr_log_group, const struct kr_request *);
-void kr_log_req1(const struct kr_request * const, uint32_t, const unsigned int, enum kr_log_group, const char *, const char *, ...);
-void kr_log_q1(const struct kr_query * const, enum kr_log_group, const char *, const char *, ...);
-const char *kr_log_grp2name(enum kr_log_group);
-void kr_log_fmt(enum kr_log_group, kr_log_level_t, const char *, const char *, const char *, const char *, ...);
-int kr_make_query(struct kr_query *, knot_pkt_t *);
-void kr_pkt_make_auth_header(knot_pkt_t *);
-int kr_pkt_put(knot_pkt_t *, const knot_dname_t *, uint32_t, uint16_t, uint16_t, const uint8_t *, uint16_t);
-int kr_pkt_recycle(knot_pkt_t *);
-int kr_pkt_clear_payload(knot_pkt_t *);
-_Bool kr_pkt_has_wire(const knot_pkt_t *);
-_Bool kr_pkt_has_dnssec(const knot_pkt_t *);
-uint16_t kr_pkt_qclass(const knot_pkt_t *);
-uint16_t kr_pkt_qtype(const knot_pkt_t *);
-char *kr_pkt_text(const knot_pkt_t *);
-void kr_rnd_buffered(void *, unsigned int);
-uint32_t kr_rrsig_sig_inception(const knot_rdata_t *);
-uint32_t kr_rrsig_sig_expiration(const knot_rdata_t *);
-uint16_t kr_rrsig_type_covered(const knot_rdata_t *);
-const char *kr_inaddr(const struct sockaddr *);
-int kr_inaddr_family(const struct sockaddr *);
-int kr_inaddr_len(const struct sockaddr *);
-int kr_inaddr_str(const struct sockaddr *, char *, size_t *);
-int kr_sockaddr_cmp(const struct sockaddr *, const struct sockaddr *);
-int kr_sockaddr_len(const struct sockaddr *);
-uint16_t kr_inaddr_port(const struct sockaddr *);
-int kr_straddr_family(const char *);
-int kr_straddr_subnet(void *, const char *);
-int kr_bitcmp(const char *, const char *, int);
-int kr_family_len(int);
-struct sockaddr *kr_straddr_socket(const char *, int, knot_mm_t *);
-int kr_straddr_split(const char *, char * restrict, uint16_t *);
-_Bool kr_rank_test(uint8_t, uint8_t);
-int kr_ranked_rrarray_add(ranked_rr_array_t *, const knot_rrset_t *, uint8_t, _Bool, uint32_t, knot_mm_t *);
-int kr_ranked_rrarray_finalize(ranked_rr_array_t *, uint32_t, knot_mm_t *);
-void kr_qflags_set(struct kr_qflags *, struct kr_qflags);
-void kr_qflags_clear(struct kr_qflags *, struct kr_qflags);
-int kr_zonecut_add(struct kr_zonecut *, const knot_dname_t *, const void *, int);
-_Bool kr_zonecut_is_empty(struct kr_zonecut *);
-void kr_zonecut_set(struct kr_zonecut *, const knot_dname_t *);
-uint64_t kr_now(void);
-const char *kr_strptime_diff(const char *, const char *, const char *, double *);
-time_t kr_file_mtime(const char *);
-long long kr_fssize(const char *);
-const char *kr_dirent_name(const struct dirent *);
-void lru_free_items_impl(struct lru *);
-struct lru *lru_create_impl(unsigned int, unsigned int, knot_mm_t *, knot_mm_t *);
-void *lru_get_impl(struct lru *, const char *, unsigned int, unsigned int, _Bool, _Bool *);
-void *mm_realloc(knot_mm_t *, void *, size_t, size_t);
-knot_rrset_t *kr_ta_get(trie_t *, const knot_dname_t *);
-int kr_ta_add(trie_t *, const knot_dname_t *, uint16_t, uint32_t, const uint8_t *, uint16_t);
-int kr_ta_del(trie_t *, const knot_dname_t *);
-void kr_ta_clear(trie_t *);
-_Bool kr_dnssec_key_sep_flag(const uint8_t *);
-_Bool kr_dnssec_key_revoked(const uint8_t *);
-int kr_dnssec_key_tag(uint16_t, const uint8_t *, size_t);
-int kr_dnssec_key_match(const uint8_t *, size_t, const uint8_t *, size_t);
-int kr_cache_closest_apex(struct kr_cache *, const knot_dname_t *, _Bool, knot_dname_t **);
-int kr_cache_insert_rr(struct kr_cache *, const knot_rrset_t *, const knot_rrset_t *, uint8_t, uint32_t, _Bool);
-int kr_cache_remove(struct kr_cache *, const knot_dname_t *, uint16_t);
-int kr_cache_remove_subtree(struct kr_cache *, const knot_dname_t *, _Bool, int);
-int kr_cache_commit(struct kr_cache *);
-uint32_t packet_ttl(const knot_pkt_t *);
-int kr_rules_init(const char *, size_t, _Bool);
-int kr_rules_commit(_Bool);
-int kr_rules_reset(void);
-int kr_view_insert_action(const char *, const char *, kr_proto_set, const char *);
-int kr_view_select_action(const struct kr_request *, knot_db_val_t *);
-int kr_rule_tag_add(const char *, kr_rule_tags_t *);
-int kr_rule_local_subtree(const knot_dname_t *, enum kr_rule_sub_t, uint32_t, kr_rule_tags_t);
-int kr_rule_zonefile(const struct kr_rule_zonefile_config *);
-int kr_rule_forward(const knot_dname_t *, kr_rule_fwd_flags_t, const struct sockaddr **);
-int kr_rule_local_address(const char *, const char *, _Bool, uint32_t, kr_rule_tags_t);
-int kr_rule_local_hosts(const char *, _Bool, uint32_t, kr_rule_tags_t);
-typedef struct {
-	int sock_type;
-	_Bool tls;
-	_Bool http;
-	_Bool xdp;
-	_Bool freebind;
-	const char *kind;
-} endpoint_flags_t;
-typedef struct {
-	char **at;
-	size_t len;
-	size_t cap;
-} addr_array_t;
-typedef struct {
-	int fd;
-	endpoint_flags_t flags;
-} flagged_fd_t;
-typedef struct {
-	flagged_fd_t *at;
-	size_t len;
-	size_t cap;
-} flagged_fd_array_t;
-typedef struct {
-	const char **at;
-	size_t len;
-	size_t cap;
-} config_array_t;
-struct args {
-	addr_array_t addrs;
-	addr_array_t addrs_tls;
-	flagged_fd_array_t fds;
-	int control_fd;
-	int forks;
-	config_array_t config;
-	const char *rundir;
-	_Bool interactive;
-	_Bool quiet;
-	_Bool tty_binary_output;
-};
-typedef struct {
-	const char *zone_file;
-	const char *origin;
-	uint32_t ttl;
-	enum {ZI_STAMP_NOW, ZI_STAMP_MTIM} time_src;
-	_Bool downgrade;
-	_Bool zonemd;
-	const knot_rrset_t *ds;
-	zi_callback cb;
-	void *cb_param;
-} zi_config_t;
-struct args *the_args;
-struct endpoint {
-	void *handle;
-	int fd;
-	int family;
-	uint16_t port;
-	int16_t nic_queue;
-	_Bool engaged;
-	endpoint_flags_t flags;
-};
-struct request_ctx {
-	struct kr_request req;
-	struct qr_task *task;
-	/* beware: hidden stub, to avoid hardcoding sockaddr lengths */
-};
-struct qr_task {
-	struct request_ctx *ctx;
-	/* beware: hidden stub, to avoid qr_tasklist_t */
-};
-int worker_resolve_exec(struct qr_task *, knot_pkt_t *);
-knot_pkt_t *worker_resolve_mk_pkt(const char *, uint16_t, uint16_t, const struct kr_qflags *);
-struct qr_task *worker_resolve_start(knot_pkt_t *, struct kr_qflags);
-int zi_zone_import(const zi_config_t);
-struct engine {
-	char _stub[];
-};
-struct worker_ctx {
-	char _stub[];
-};
-struct kr_context *the_resolver;
-struct worker_ctx *the_worker;
-struct engine *the_engine;
-typedef struct {
-	uint8_t *params_position;
-	uint8_t *mandatory_position;
-	uint8_t *param_position;
-	int32_t last_key;
-} zs_svcb_t;
-typedef struct {
-	uint8_t bitmap[32];
-	uint8_t length;
-} zs_win_t;
-typedef struct {
-	uint8_t excl_flag;
-	uint16_t addr_family;
-	uint8_t prefix_length;
-} zs_apl_t;
-typedef struct {
-	uint32_t d1;
-	uint32_t d2;
-	uint32_t m1;
-	uint32_t m2;
-	uint32_t s1;
-	uint32_t s2;
-	uint32_t alt;
-	uint64_t siz;
-	uint64_t hp;
-	uint64_t vp;
-	int8_t lat_sign;
-	int8_t long_sign;
-	int8_t alt_sign;
-} zs_loc_t;
-typedef enum {ZS_STATE_NONE, ZS_STATE_DATA, ZS_STATE_ERROR, ZS_STATE_INCLUDE, ZS_STATE_EOF, ZS_STATE_STOP} zs_state_t;
-typedef struct zs_scanner zs_scanner_t;
-typedef struct zs_scanner {
-	int cs;
-	int top;
-	int stack[16];
-	_Bool multiline;
-	uint64_t number64;
-	uint64_t number64_tmp;
-	uint32_t decimals;
-	uint32_t decimal_counter;
-	uint32_t item_length;
-	uint32_t item_length_position;
-	uint8_t *item_length_location;
-	uint8_t *item_length2_location;
-	uint32_t buffer_length;
-	uint8_t buffer[65535];
-	char include_filename[65535];
-	char *path;
-	zs_win_t windows[256];
-	int16_t last_window;
-	zs_apl_t apl;
-	zs_loc_t loc;
-	zs_svcb_t svcb;
-	uint8_t addr[16];
-	_Bool long_string;
-	_Bool comma_list;
-	uint8_t *dname;
-	uint32_t *dname_length;
-	uint32_t dname_tmp_length;
-	uint32_t r_data_tail;
-	uint32_t zone_origin_length;
-	uint8_t zone_origin[318];
-	uint16_t default_class;
-	uint32_t default_ttl;
-	zs_state_t state;
-	struct {
-		_Bool automatic;
-		void (*record)(zs_scanner_t *);
-		void (*error)(zs_scanner_t *);
-		void (*comment)(zs_scanner_t *);
-		void *data;
-	} process;
-	struct {
-		const char *start;
-		const char *current;
-		const char *end;
-		_Bool eof;
-		_Bool mmaped;
-	} input;
-	struct {
-		char *name;
-		int descriptor;
-	} file;
-	struct {
-		int code;
-		uint64_t counter;
-		_Bool fatal;
-	} error;
-	uint64_t line_counter;
-	uint32_t r_owner_length;
-	uint8_t r_owner[318];
-	uint16_t r_class;
-	uint32_t r_ttl;
-	uint16_t r_type;
-	uint32_t r_data_length;
-	uint8_t r_data[65535];
-} zs_scanner_t;
-void zs_deinit(zs_scanner_t *);
-int zs_init(zs_scanner_t *, const char *, const uint16_t, const uint32_t);
-int zs_parse_record(zs_scanner_t *);
-int zs_set_input_file(zs_scanner_t *, const char *);
-int zs_set_input_string(zs_scanner_t *, const char *, size_t);
-const char *zs_strerror(const int);
-]]
diff --git a/daemon/lua/kres-gen-32.lua b/daemon/lua/kres-gen-33.lua
similarity index 99%
rename from daemon/lua/kres-gen-32.lua
rename to daemon/lua/kres-gen-33.lua
index c3bd0d9ce..77e69f2c5 100644
--- a/daemon/lua/kres-gen-32.lua
+++ b/daemon/lua/kres-gen-33.lua
@@ -648,6 +648,7 @@ typedef struct zs_scanner {
 	uint8_t addr[16];
 	_Bool long_string;
 	_Bool comma_list;
+	_Bool pending_backslash;
 	uint8_t *dname;
 	uint32_t *dname_length;
 	uint32_t dname_tmp_length;
diff --git a/daemon/lua/meson.build b/daemon/lua/meson.build
index 22a5b3612..267bb56da 100644
--- a/daemon/lua/meson.build
+++ b/daemon/lua/meson.build
@@ -39,10 +39,8 @@ distro_preconfig = configure_file(
 )
 
 # Unfortunately the different ABI implies different contents of 'kres-gen.lua'.
-if libknot.version().version_compare('>= 3.2')
-  kres_gen_fname = 'kres-gen-32.lua'
-elif libknot.version().version_compare('>= 3.1')
-  kres_gen_fname = 'kres-gen-31.lua'
+if libknot.version().version_compare('>= 3.3')
+  kres_gen_fname = 'kres-gen-33.lua'
 endif
 
 # Exact types around time_t aren't easy to detect, but at least we need the same size.
diff --git a/daemon/zimport.c b/daemon/zimport.c
index 61a46a894..2f546354b 100644
--- a/daemon/zimport.c
+++ b/daemon/zimport.c
@@ -33,10 +33,6 @@
 #include <libzscanner/scanner.h>
 
 #include <libdnssec/digest.h>
-#if KNOT_VERSION_HEX < 0x030200
-	#define KNOT_ZONEMD_ALGORITHM_SHA384 KNOT_ZONEMD_ALORITHM_SHA384
-	#define KNOT_ZONEMD_ALGORITHM_SHA512 KNOT_ZONEMD_ALORITHM_SHA512
-#endif
 
 #include "daemon/worker.h"
 #include "lib/dnssec/ta.h"
diff --git a/lib/resolve.c b/lib/resolve.c
index ec00b2155..4730f105c 100644
--- a/lib/resolve.c
+++ b/lib/resolve.c
@@ -246,11 +246,7 @@ static int pkt_padding(knot_pkt_t *packet, int32_t padding)
 	if (padding == -1) { /* use the default padding policy from libknot */
 		const size_t block_size = knot_wire_get_qr(packet->wire)
 					? KNOT_EDNS_ALIGNMENT_RESPONSE_DEFAULT
-				#if KNOT_VERSION_HEX < 0x030200
-					: KNOT_EDNS_ALIGNMENT_QUERY_DEFALT;
-				#else
 					: KNOT_EDNS_ALIGNMENT_QUERY_DEFAULT;
-				#endif
 		pad_bytes = knot_edns_alignment_size(packet->size, knot_rrset_size(opt_rr),
 							block_size);
 	}
diff --git a/lib/utils.c b/lib/utils.c
index 2a0635e02..d04f5467b 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1198,11 +1198,7 @@ char *kr_pkt_text(const knot_pkt_t *pkt)
 
 const knot_dump_style_t KR_DUMP_STYLE_DEFAULT = { /* almost all = false, */
 	.show_ttl = true,
-#if KNOT_VERSION_HEX >= 0x030200
 	.human_timestamp = true,
-#else
-	.human_tmstamp = true,
-#endif
 };
 
 char *kr_rrset_text(const knot_rrset_t *rr)
diff --git a/meson.build b/meson.build
index a2a56a33e..4e2b6f7b5 100644
--- a/meson.build
+++ b/meson.build
@@ -18,7 +18,7 @@ endif
 
 
 message('--- required dependencies ---')
-knot_version = '>=3.1'
+knot_version = '>=3.3'
 libknot = dependency('libknot', version: knot_version)
 libdnssec = dependency('libdnssec', version: knot_version)
 libzscanner = dependency('libzscanner', version: knot_version)
diff --git a/scripts/enable-repo-cznic-labs.sh b/scripts/enable-repo-cznic-labs.sh
new file mode 100755
index 000000000..cbc64c685
--- /dev/null
+++ b/scripts/enable-repo-cznic-labs.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# enable CZ.NIC Labs Debian/Ubuntu repos - see https://pkg.labs.nic.cz/doc/
+set -e
+
+REPO=$1
+if [ -z "${REPO}" ]; then
+    echo "usage: $0 REPOSITORY"
+    echo -e "\nPlease see: https://pkg.labs.nic.cz/doc/"
+    exit 1
+fi
+if [ "$(whoami)" != "root" ]; then
+    echo "ERROR: this script must be run as ROOT"
+    echo -e "\nTry running with sudo:\n\n    sudo $0\n"
+    exit 2
+fi
+
+# update apt metadata and install requirements
+apt-get update
+apt-get install -y apt-transport-https ca-certificates lsb-release wget
+
+DISTRO=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
+CODENAME=$(lsb_release -sc)
+
+echo "Enabling $REPO repo on $DISTRO $CODENAME..."
+# get repo signing key
+wget -O /usr/share/keyrings/cznic-labs-pkg.gpg https://pkg.labs.nic.cz/gpg
+# create repo entry
+echo "deb [signed-by=/usr/share/keyrings/cznic-labs-pkg.gpg] https://pkg.labs.nic.cz/$REPO $CODENAME main" > /etc/apt/sources.list.d/cznic-labs-$REPO.list
+# update apt metadata from the new repo
+apt-get update
diff --git a/scripts/enable-repo.py b/scripts/enable-repo.py
deleted file mode 100755
index 2b9319ebc..000000000
--- a/scripts/enable-repo.py
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/usr/bin/python3
-"""
-Enable Knot Resolver upstream repo on current system.
-
-Requires python3-distro.
-
-Run this as ROOT.
-"""
-
-import argparse
-import distro as distro_
-from pathlib import Path
-from subprocess import run, PIPE
-import sys
-
-
-REPO_CHOICES = ['latest', 'testing', 'build']
-
-
-def detect_distro():
-    return '%s-%s' % (distro_.id(), distro_.version())
-
-
-def parse_distro(distro):
-    id_, _, ver_ = distro.rpartition('-')
-    return id_, ver_
-
-
-def distro2obs(distro):
-    distro_id, distro_ver = parse_distro(distro)
-    if not str(distro_ver):
-        return None
-    if distro_id == 'debian':
-        return 'Debian_%s' % distro_ver
-    if distro_id == 'ubuntu':
-        return 'xUbuntu_%s' % distro_ver
-    if distro_id == 'opensuse-leap':
-        return 'openSUSE_Leap_%s' % distro_ver
-    return None
-
-
-def show_info():
-    print("distro ID: %s" % detect_distro())
-    print("distro name: %s %s" % (distro_.name(), distro_.version(pretty=True)))
-
-
-def enable_deb_repo(repo_id, distro):
-    obs_distro = distro2obs(distro)
-    if not obs_distro:
-        return fail('unsupported Debian-based distro: %s' % distro)
-
-    requires = ['python3-requests', 'gnupg']
-    print("installing required packages: %s" % ' '.join(requires))
-    p = run(['apt', 'install', '-y'] + requires)
-    import requests
-
-    sources_p = Path('/etc/apt/sources.list.d/%s.list' % repo_id)
-    sources_txt = 'deb http://download.opensuse.org/repositories/home:/CZ-NIC:/%s/%s/ /' % (repo_id, obs_distro)
-    key_url = 'https://download.opensuse.org/repositories/home:CZ-NIC:%s/%s/Release.key' % (repo_id, obs_distro)
-    print("writing sources list: %s" % sources_p)
-    with sources_p.open('wt') as f:
-        f.write(sources_txt + '\n')
-        print(sources_txt)
-    print("fetching key: %s" % key_url)
-    r = requests.get(key_url)
-    if not r.ok:
-        return fail('failed to fetch repo key: %s' % key_url)
-    key_txt = r.content.decode('utf-8')
-    print("adding key using `apt-key add`")
-    p = run(['apt-key', 'add', '-'], input=key_txt, encoding='utf-8')
-    if p.returncode != 0:
-        print('apt-key add failed :(')
-    run(['apt', 'update'])
-    print("%s repo added" % repo_id)
-
-
-def enable_suse_repo(repo_id, distro):
-    obs_distro = distro2obs(distro)
-    if not obs_distro:
-        return fail('unsupported SUSE distro: %s' % distro)
-
-    repo_url = 'https://download.opensuse.org/repositories/home:CZ-NIC:{repo}/{distro}/home:CZ-NIC:{repo}.repo'.format(
-        repo=repo_id, distro=obs_distro)
-    print("adding OBS repo: %s" % repo_url)
-    run(['zypper', 'addrepo', repo_url])
-    run(['zypper', '--no-gpg-checks', 'refresh'])
-
-
-def enable_repo(repo_id, distro):
-    distro_id, distro_ver = parse_distro(distro)
-    print("enable %s repo on %s" % (repo_id, distro))
-
-    if distro_id in ['debian', 'ubuntu']:
-        enable_deb_repo(repo_id, distro)
-    elif distro_id == 'opensuse-leap':
-        enable_suse_repo(repo_id, distro)
-    elif distro_id == 'arch':
-        print("no external repo needed on %s" % distro_id)
-    else:
-        fail("unsupported distro: %s" % distro_id)
-
-
-def fail(msg):
-    print(msg)
-    sys.exit(1)
-
-
-def main():
-    parser = argparse.ArgumentParser(
-            description="Enable Knot Resolver repo on this system")
-    parser.add_argument('repo', choices=REPO_CHOICES, nargs='?', default=REPO_CHOICES[0],
-            help="repo to enable")
-    parser.add_argument('-d', '--distro', type=str,
-            help="override target distro (DISTRO-VERSION format)")
-    parser.add_argument('-i', '--info', action='store_true',
-            help="show distro information and exit")
-
-    args = parser.parse_args()
-    if args.info:
-        show_info()
-        return
-
-    distro = args.distro
-    if not distro:
-        distro = detect_distro()
-
-    repo = 'knot-resolver-%s' % args.repo
-    enable_repo(repo, distro)
-
-
-if __name__ == '__main__':
-    main()
-- 
GitLab