diff --git a/daemon/lua/kres-gen-29.lua b/daemon/lua/kres-gen-29.lua
index ded494651e3a5f5526c7c820c280f5e8630dcca2..b1a09f9aaf797f0e55e6dc7c823e9cc3e6550176 100644
--- a/daemon/lua/kres-gen-29.lua
+++ b/daemon/lua/kres-gen-29.lua
@@ -308,7 +308,7 @@ struct kr_server_selection {
 	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_ZIMPORT, LOG_GRP_ZSCANNER, 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_REQDBG};
+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_ZIMPORT, LOG_GRP_ZSCANNER, 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_REQDBG};
 
 kr_layer_t kr_layer_t_static;
 _Bool kr_dbg_assertion_abort;
diff --git a/daemon/lua/kres-gen-31.lua b/daemon/lua/kres-gen-31.lua
index dc7334728cce7a53f3d7baa8e576d622d6ee2a43..8fe3ac8c32ab7c9d9c88f4594914f0ddd763c799 100644
--- a/daemon/lua/kres-gen-31.lua
+++ b/daemon/lua/kres-gen-31.lua
@@ -308,7 +308,7 @@ struct kr_server_selection {
 	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_ZIMPORT, LOG_GRP_ZSCANNER, 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_REQDBG};
+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_ZIMPORT, LOG_GRP_ZSCANNER, 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_REQDBG};
 
 kr_layer_t kr_layer_t_static;
 _Bool kr_dbg_assertion_abort;
diff --git a/lib/log.c b/lib/log.c
index 175b54b8e2bd7449832c83d5fb94b9c33175d7c9..1f44637fe0278c953cd18b3c61371a7213216db5 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -78,6 +78,7 @@ const log_group_names_t log_group_names[] = {
 	GRP_NAME_ITEM(LOG_GRP_CONTROL),
 	GRP_NAME_ITEM(LOG_GRP_MODULE),
 	GRP_NAME_ITEM(LOG_GRP_DEVEL),
+	GRP_NAME_ITEM(LOG_GRP_RENUMBER),
 	GRP_NAME_ITEM(LOG_GRP_REQDBG),
 	{ NULL, LOG_GRP_UNKNOWN },
 };
diff --git a/lib/log.h b/lib/log.h
index 8b7d11cc2a40964eb9285474df0be06aa769fa1b..a2879469b63eea83fa746cc4aa146e2bb15d4448 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -78,6 +78,7 @@ enum kr_log_group {
 	LOG_GRP_CONTROL,
 	LOG_GRP_MODULE,
 	LOG_GRP_DEVEL,
+	LOG_GRP_RENUMBER,
 	/* ^^ Add new log groups above ^^. */
 	LOG_GRP_REQDBG, /* Must be first non-displayed entry in enum! */
 };
@@ -130,6 +131,7 @@ enum kr_log_group {
 #define LOG_GRP_CONTROL_TAG		"contrl"	/**< ``contrl``: TTY control sockets*/
 #define LOG_GRP_MODULE_TAG		"module"	/**< ``module``: suitable for user-defined modules */
 #define LOG_GRP_DEVEL_TAG		"devel"		/**< ``devel``: for development purposes */
+#define LOG_GRP_RENUMBER_TAG		"renum"		/**< ``renum``: operation related to renumber */
 #define LOG_GRP_REQDBG_TAG		"reqdbg"	/**< ``reqdbg``: debug logs enabled by policy actions */
 ///@}
 
diff --git a/modules/policy/policy.lua b/modules/policy/policy.lua
index 7cd8ff926a2cf289d28246004292400195a96b62..e8d7e9b96a2c17e217854cebb97aaca03d273047 100644
--- a/modules/policy/policy.lua
+++ b/modules/policy/policy.lua
@@ -187,7 +187,13 @@ function policy.REROUTE(tbl, names)
 	local ren = require('kres_modules.renumber')
 	local prefixes = {}
 	for from, to in pairs(tbl) do
-		table.insert(prefixes, names and ren.name(from, to) or ren.prefix(from, to))
+		local prefix = names and ren.name(from, to) or ren.prefix(from, to)
+		local bitlen = prefix[2]
+		if bitlen ~= nil and bitlen % 8 ~= 0 then
+			log_warn(ffi.C.LOG_GRP_POLICY,
+				'REROUTE: network mask - only /8, /16, /24 etc. are supported (entire octets are rewritten)')
+		end
+		table.insert(prefixes, prefix)
 	end
 	-- Return rule closure
 	return ren.rule(prefixes)
diff --git a/modules/renumber/README.rst b/modules/renumber/README.rst
index ea26eafcb91c83b8c47ee3c482021092eb9d9157..b3cfc23e7db83c65776c17bd3588fabdb0168e00 100644
--- a/modules/renumber/README.rst
+++ b/modules/renumber/README.rst
@@ -10,7 +10,13 @@ e.g. you can redirect malicious addresses to a blackhole, or use private address
 in local zones, that will be remapped to real addresses by the resolver.
 
 
-.. warning:: While requests are still validated using DNSSEC, the signatures are stripped from final answer. The reason is that the address synthesis breaks signatures. You can see whether an answer was valid or not based on the AD flag.
+.. warning:: While requests are still validated using DNSSEC, the signatures
+   are stripped from final answer. The reason is that the address synthesis
+   breaks signatures. You can see whether an answer was valid or not based on
+   the AD flag.
+
+.. warning:: The module is currently limited to rewriting complete octets of
+   the IP addresses, i.e. only /8, /16, /24 etc. network masks are supported.
 
 Example configuration
 ---------------------
diff --git a/modules/renumber/renumber.lua b/modules/renumber/renumber.lua
index 425bc0546428f04f71f347bce87a91556157633f..ccd320f632d358b58c0e769f0b3762953c2d80ff 100644
--- a/modules/renumber/renumber.lua
+++ b/modules/renumber/renumber.lua
@@ -25,7 +25,12 @@ end
 
 -- Add subnet prefix rewrite rule
 local function add_prefix(subnet, addr)
-	table.insert(prefixes_global, matchprefix(subnet, addr))
+	local prefix = matchprefix(subnet, addr)
+	local bitlen = prefix[2]
+	if bitlen ~= nil and bitlen % 8 ~= 0 then
+		log_warn(ffi.C.LOG_GRP_RENUMBER, 'network mask: only /8, /16, /24 etc. are supported (entire octets are rewritten)')
+	end
+	table.insert(prefixes_global, prefix)
 end
 
 -- Match IP against given subnet or record owner