]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
renumber: allow renumbering a subnet to a single IP
authorKonstantin Amelichev <kostya.amelichev@gmail.com>
Sat, 28 May 2022 11:30:32 +0000 (15:30 +0400)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 30 May 2022 10:03:49 +0000 (12:03 +0200)
https://github.com/CZ-NIC/knot-resolver/pull/77
originally but changed by vcunat quite a bit.

modules/renumber/renumber.lua

index 4272fbd1f0d464cf336b853c1acf8ee772098819..caa47779c260ba1d39130fe5391586e950c92e6a 100644 (file)
@@ -3,25 +3,41 @@
 local ffi = require('ffi')
 local prefixes_global = {}
 
+-- get address from config: either subnet prefix or fixed endpoint
+local function extract_address(target)
+       local idx = string.find(target, "!", 1, true)
+       if idx == nil then
+               return target, false
+       end
+       if idx ~= #target then
+               error("[renumber] \"!\" symbol in target is only accepted at the end of address")
+       end
+       return string.sub(target, 1, idx - 1), true
+end
+
 -- Create subnet prefix rule
 local function matchprefix(subnet, addr)
+       local is_exact
+       addr, is_exact = extract_address(addr)
        local target = kres.str2ip(addr)
        if target == nil then error('[renumber] invalid address: '..addr) end
        local addrtype = string.find(addr, ':', 1, true) and kres.type.AAAA or kres.type.A
        local subnet_cd = ffi.new('char[16]')
        local bitlen = ffi.C.kr_straddr_subnet(subnet_cd, subnet)
        if bitlen < 0 then error('[renumber] invalid subnet: '..subnet) end
-       return {subnet_cd, bitlen, target, addrtype}
+       return {subnet_cd, bitlen, target, addrtype, is_exact}
 end
 
 -- Create name match rule
 local function matchname(name, addr)
+       local is_exact
+       addr, is_exact = extract_address(addr) -- though matchname() always leads to replacing whole address
        local target = kres.str2ip(addr)
        if target == nil then error('[renumber] invalid address: '..addr) end
        local owner = todname(name)
        if not name then error('[renumber] invalid name: '..name) end
        local addrtype = string.find(addr, ':', 1, true) and kres.type.AAAA or kres.type.A
-       return {owner, nil, target, addrtype}
+       return {owner, nil, target, addrtype, is_exact}
 end
 
 -- Add subnet prefix rewrite rule
@@ -50,7 +66,12 @@ local function renumber_record(tbl, rr)
                -- If provided, compare record owner to prefix name
                if match_subnet(prefix[1], prefix[2], prefix[4], rr) then
                        -- Replace part or whole address
-                       local to_copy = prefix[2] or (#prefix[3] * 8)
+                       local to_copy
+                       if prefix[2] and not prefix[5] then
+                               to_copy = prefix[2]
+                       else
+                               to_copy = #prefix[3] * 8
+                       end
                        local chunks = to_copy / 8
                        local rdlen = #rr.rdata
                        if rdlen < chunks then return rr end -- Address length mismatch