diff --git a/bin/lua/wipf/util/ip.lua b/bin/lua/wipf/util/ip.lua index db212f4c..6c605fec 100644 --- a/bin/lua/wipf/util/ip.lua +++ b/bin/lua/wipf/util/ip.lua @@ -23,7 +23,7 @@ do local to_ip if sep == '-' then -- e.g. "127.0.0.0-127.255.255.255" to_ip = sock.inet_pton(mask, true) - if not to_ip then + if not to_ip or from_ip > to_ip then return end elseif sep == '/' then -- e.g. "127.0.0.0/24" @@ -40,9 +40,51 @@ do return from_ip, to_ip end + -- sort and try to merge ranges + local function iprange_map_merge(map) + -- fill temporary "from" range + local tmp_from, tmp_count = {}, 0 + for from in pairs(map) do + tmp_count = tmp_count + 1 + tmp_from[tmp_count] = from + end + + table.sort(tmp_from) + + -- try to merge ranges + local prev_from, prev_to + for i = 1, tmp_count do + local from = tmp_from[i] + local to = map[from] + if prev_from and from <= prev_to then -- collides with previous? + if to > prev_to then + map[prev_from], prev_to = to, to + end + tmp_from[i] = nil + else + prev_from, prev_to = from, to + end + end + + -- fill "from" & "to" ranges + local iprange_from, iprange_to, count = {}, {}, 0 + for i = 1, tmp_count do + local from = tmp_from[i] + if from then + count = count + 1 + iprange_from[count] = from + iprange_to[count] = map[from] + end + end + + iprange_from.n, iprange_to.n = count, count + + return iprange_from, iprange_to + end + ip4range_to_numbers = function (text) - local iprange_from, iprange_to = {}, {} - local line_no, index = 0, 0 + local iprange_map = {} + local line_no = 0 for line in string.gmatch(text, "%s*([^\n]+)") do local from, to = parse_address_mask(line) @@ -50,16 +92,13 @@ do line_no = line_no + 1 if from then - index = index + 1 - iprange_from[index], iprange_to[index] = from, to + iprange_map[from] = to elseif string.find(line, "%S") then return nil, line_no end end - iprange_from.n, iprange_to.n = index, index - - return iprange_from, iprange_to + return iprange_map_merge(iprange_map) end end diff --git a/test/wipf_test.lua b/test/wipf_test.lua index 8c58af01..5da69e41 100644 --- a/test/wipf_test.lua +++ b/test/wipf_test.lua @@ -45,7 +45,16 @@ end print"-- IPv4 Conversions" do - local from, to = util_ip.ip4range_to_numbers[[ + local _, err_line + _, err_line = util_ip.ip4range_to_numbers[[172.16.0.0/33]] + assert(err_line == 1) + _, err_line = util_ip.ip4range_to_numbers[[172.16.0.255/-16]] + assert(err_line == 1) + _, err_line = util_ip.ip4range_to_numbers[[10.0.0.32 - 10.0.0.24]] + assert(err_line == 1) + + local from, to + from, to = util_ip.ip4range_to_numbers[[ 172.16.0.0/20 192.168.0.0 - 192.168.255.255 ]] @@ -55,11 +64,16 @@ do assert(from[2] == sock.inet_pton("192.168.0.0", true)) assert(to[2] == sock.inet_pton("192.168.255.255", true)) - local _, err_line - _, err_line = util_ip.ip4range_to_numbers[[172.16.0.0/33]] - assert(err_line == 1) - _, err_line = util_ip.ip4range_to_numbers[[172.16.0.255/-16]] - assert(err_line == 1) + -- merge ranges + from, to = util_ip.ip4range_to_numbers[[ + 10.0.0.0 - 10.0.0.255 + 10.0.0.64 - 10.0.0.128 + 10.0.0.128 - 10.0.2.0 + ]] + assert(from.n == 1 and to.n == 1) + assert(from[1] == sock.inet_pton("10.0.0.0", true)) + assert(to[1] == sock.inet_pton("10.0.2.0", true)) + print("OK") end