215 lines
No EOL
9 KiB
Lua
215 lines
No EOL
9 KiB
Lua
-- This code uses some functions from
|
|
-- https://github.com/libmoon/libmoon/blob/master/lua/utils.lua
|
|
|
|
local _M = {}
|
|
local bit = require 'plugins.crowdsec.bitop'
|
|
local bor, band, rshift, lshift, bswap = bit.bor, bit.band, bit.rshift, bit.lshift, bit.bswap
|
|
|
|
--- Byte swap for 16 bit integers
|
|
--- @param n 16 bit integer
|
|
--- @return Byte swapped integer
|
|
function bswap16(n)
|
|
return bor(rshift(n, 8), lshift(band(n, 0xFF), 8))
|
|
end
|
|
|
|
hton16 = bswap16
|
|
ntoh16 = hton16
|
|
|
|
_G.bswap = bswap -- export bit.bswap to global namespace to be consistent with bswap16
|
|
hton = bswap
|
|
ntoh = hton
|
|
|
|
local ffi = require "ffi"
|
|
|
|
local ipv4_netmasks = {
|
|
4294967295, 4294967294, 4294967292, 4294967288, 4294967280, 4294967264, 4294967232, 4294967168, 4294967040, 4294966784,
|
|
4294966272, 4294965248, 4294963200, 4294959104, 4294950912, 4294934528, 4294901760, 4294836224, 4294705152, 4294443008,
|
|
4293918720, 4292870144, 4290772992, 4286578688, 4278190080, 4261412864, 4227858432, 4160749568, 4026531840, 3758096384, 3221225472, 2147483648, 0
|
|
}
|
|
|
|
local ipv6_netmasks = {
|
|
{4294967295,4294967295,4294967295,4294967295}, {4294967295,4294967295,4294967295,4294967294}, {4294967295,4294967295,4294967295,4294967292},
|
|
{4294967295,4294967295,4294967295,4294967288}, {4294967295,4294967295,4294967295,4294967280}, {4294967295,4294967295,4294967295,4294967264},
|
|
{4294967295,4294967295,4294967295,4294967232}, {4294967295,4294967295,4294967295,4294967168}, {4294967295,4294967295,4294967295,4294967040},
|
|
{4294967295,4294967295,4294967295,4294966784}, {4294967295,4294967295,4294967295,4294966272}, {4294967295,4294967295,4294967295,4294965248},
|
|
{4294967295,4294967295,4294967295,4294963200}, {4294967295,4294967295,4294967295,4294959104}, {4294967295,4294967295,4294967295,4294950912},
|
|
{4294967295,4294967295,4294967295,4294934528}, {4294967295,4294967295,4294967295,4294901760}, {4294967295,4294967295,4294967295,4294836224},
|
|
{4294967295,4294967295,4294967295,4294705152}, {4294967295,4294967295,4294967295,4294443008}, {4294967295,4294967295,4294967295,4293918720},
|
|
{4294967295,4294967295,4294967295,4292870144}, {4294967295,4294967295,4294967295,4290772992}, {4294967295,4294967295,4294967295,4286578688},
|
|
{4294967295,4294967295,4294967295,4278190080}, {4294967295,4294967295,4294967295,4261412864}, {4294967295,4294967295,4294967295,4227858432},
|
|
{4294967295,4294967295,4294967295,4160749568}, {4294967295,4294967295,4294967295,4026531840}, {4294967295,4294967295,4294967295,3758096384},
|
|
{4294967295,4294967295,4294967295,3221225472}, {4294967295,4294967295,4294967295,2147483648}, {4294967295,4294967295,4294967295,0},
|
|
{4294967295,4294967295,4294967294,0}, {4294967295,4294967295,4294967292,0}, {4294967295,4294967295,4294967288,0},
|
|
{4294967295,4294967295,4294967280,0}, {4294967295,4294967295,4294967264,0}, {4294967295,4294967295,4294967232,0},
|
|
{4294967295,4294967295,4294967168,0}, {4294967295,4294967295,4294967040,0}, {4294967295,4294967295,4294966784,0},
|
|
{4294967295,4294967295,4294966272,0}, {4294967295,4294967295,4294965248,0}, {4294967295,4294967295,4294963200,0},
|
|
{4294967295,4294967295,4294959104,0}, {4294967295,4294967295,4294950912,0}, {4294967295,4294967295,4294934528,0},
|
|
{4294967295,4294967295,4294901760,0}, {4294967295,4294967295,4294836224,0}, {4294967295,4294967295,4294705152,0},
|
|
{4294967295,4294967295,4294443008,0}, {4294967295,4294967295,4293918720,0}, {4294967295,4294967295,4292870144,0},
|
|
{4294967295,4294967295,4290772992,0}, {4294967295,4294967295,4286578688,0}, {4294967295,4294967295,4278190080,0},
|
|
{4294967295,4294967295,4261412864,0}, {4294967295,4294967295,4227858432,0}, {4294967295,4294967295,4160749568,0},
|
|
{4294967295,4294967295,4026531840,0}, {4294967295,4294967295,3758096384,0}, {4294967295,4294967295,3221225472,0},
|
|
{4294967295,4294967295,2147483648,0},
|
|
{4294967295,4294967295,0,0}, {4294967295,4294967294,0,0}, {4294967295,4294967292,0,0}, {4294967295,4294967288,0,0},
|
|
{4294967295,4294967280,0,0}, {4294967295,4294967264,0,0}, {4294967295,4294967232,0,0}, {4294967295,4294967168,0,0},
|
|
{4294967295,4294967040,0,0}, {4294967295,4294966784,0,0}, {4294967295,4294966272,0,0}, {4294967295,4294965248,0,0},
|
|
{4294967295,4294963200,0,0}, {4294967295,4294959104,0,0}, {4294967295,4294950912,0,0}, {4294967295,4294934528,0,0},
|
|
{4294967295,4294901760,0,0}, {4294967295,4294836224,0,0}, {4294967295,4294705152,0,0}, {4294967295,4294443008,0,0},
|
|
{4294967295,4293918720,0,0}, {4294967295,4292870144,0,0}, {4294967295,4290772992,0,0}, {4294967295,4286578688,0,0},
|
|
{4294967295,4278190080,0,0}, {4294967295,4261412864,0,0}, {4294967295,4227858432,0,0}, {4294967295,4160749568,0,0},
|
|
{4294967295,4026531840,0,0}, {4294967295,3758096384,0,0}, {4294967295,3221225472,0,0}, {4294967295,2147483648,0,0},
|
|
{4294967295,0,0,0},{4294967294,0,0,0},{4294967292,0,0,0}, {4294967288,0,0,0}, {4294967280,0,0,0},{4294967264,0,0,0},
|
|
{4294967232,0,0,0},{4294967168,0,0,0},{4294967040,0,0,0}, {4294966784,0,0,0},{4294966272,0,0,0},{4294965248,0,0,0},
|
|
{4294963200,0,0,0},{4294959104,0,0,0},{4294950912,0,0,0}, {4294934528,0,0,0},{4294901760,0,0,0},{4294836224,0,0,0},
|
|
{4294705152,0,0,0},{4294443008,0,0,0},{4293918720,0,0,0}, {4292870144,0,0,0},{4290772992,0,0,0},{4286578688,0,0,0},
|
|
{4278190080,0,0,0},{4261412864,0,0,0},{4227858432,0,0,0}, {4160749568,0,0,0},{4026531840,0,0,0},{3758096384,0,0,0},
|
|
{3221225472,0,0,0},{2147483648,0,0,0},{0,0,0,0}
|
|
}
|
|
|
|
local netmasks_by_key_type = {}
|
|
netmasks_by_key_type["ipv4"] = ipv4_netmasks
|
|
netmasks_by_key_type["ipv6"] = ipv6_netmasks
|
|
|
|
_M.netmasks_by_key_type = netmasks_by_key_type
|
|
|
|
function _M.ipToInt( str )
|
|
local num = 0
|
|
if str and type(str)=="string" then
|
|
local o1,o2,o3,o4 = str:match("(%d+)%.(%d+)%.(%d+)%.(%d+)" )
|
|
num = 2^24*o1 + 2^16*o2 + 2^8*o3 + o4
|
|
end
|
|
return num
|
|
end
|
|
|
|
function _M.concatIPv6(ip)
|
|
if type(ip) == "table" and table.getn(ip) == 4 then
|
|
return ip[1]*2^96 + ip[2]*2^64 + ip[3]*2^32 + ip[4]
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function _M.ipv6_band(ip, netmask)
|
|
local res_table = {}
|
|
local nb = 1
|
|
for item in ip.gmatch(ip, "([^:]+)") do
|
|
table.insert(res_table, bit.band(tonumber(item), netmask[nb]))
|
|
nb = nb + 1
|
|
end
|
|
return table.concat(res_table, ":")
|
|
end
|
|
|
|
function _M.ipv4_band(ip, netmask)
|
|
return bit.band(ip, netmask)
|
|
end
|
|
|
|
function _M.splitRange(range)
|
|
if range and type(range) == "string" then
|
|
local ip_address, cidr = range:match("^([^/]+)/(%d+)")
|
|
return ip_address, tonumber(cidr)
|
|
end
|
|
return nil, nil
|
|
end
|
|
|
|
function _M.cidrToInt(cidr, ip_version)
|
|
if cidr and type(cidr) ~= "number" and ip_version and type(ip_version) ~= "string" then
|
|
return nil
|
|
end
|
|
if ip_version == "ipv4" then
|
|
return tostring(ipv4_netmasks[32-cidr+1])
|
|
end
|
|
if ip_version == "ipv6" then
|
|
return table.concat(ipv6_netmasks[128-cidr+1], ":")
|
|
end
|
|
end
|
|
|
|
--- Parse a string to an IP address
|
|
--- @return address ip address in ip4_address or ip6_address format or nil if invalid address
|
|
--- @return boolean true if IPv4 address, false otherwise
|
|
function _M.parseIPAddress(ip)
|
|
ip = tostring(ip)
|
|
local address = parseIP4Address(ip)
|
|
if address == nil then
|
|
return parseIP6Address(ip), false
|
|
end
|
|
return address, true
|
|
end
|
|
|
|
--- Parse a string to an IPv4 address
|
|
--- @param ip address in string format
|
|
--- @return address in uint32 format or nil if invalid address
|
|
function parseIP4Address(ip)
|
|
ip = tostring(ip)
|
|
local bytes = {string.match(ip, '(%d+)%.(%d+)%.(%d+)%.(%d+)')}
|
|
if bytes == nil then
|
|
return
|
|
end
|
|
for i = 1, 4 do
|
|
if bytes[i] == nil then
|
|
return
|
|
end
|
|
bytes[i] = tonumber(bytes[i])
|
|
if bytes[i] < 0 or bytes[i] > 255 then
|
|
return
|
|
end
|
|
end
|
|
|
|
-- build a uint32
|
|
ip = bytes[1]
|
|
for i = 2, 4 do
|
|
ip = bor(lshift(ip, 8), bytes[i])
|
|
end
|
|
return ip
|
|
end
|
|
|
|
ffi.cdef[[
|
|
union ip6_address {
|
|
uint8_t uint8[16];
|
|
uint32_t uint32[4];
|
|
uint64_t uint64[2];
|
|
};
|
|
]]
|
|
|
|
ffi.cdef[[
|
|
int inet_pton(int af, const char *src, void *dst);
|
|
]]
|
|
|
|
--- Parse a string to an IPv6 address
|
|
--- @param ip address in string format
|
|
--- @return address in ip6_address format or nil if invalid address
|
|
function parseIP6Address(ip)
|
|
ip = tostring(ip)
|
|
local LINUX_AF_INET6 = 10 --preprocessor constant of Linux
|
|
local tmp_addr = ffi.new("union ip6_address")
|
|
local res = ffi.C.inet_pton(LINUX_AF_INET6, ip, tmp_addr)
|
|
if res == 0 then
|
|
return nil
|
|
end
|
|
|
|
local addr = ffi.new("union ip6_address")
|
|
addr.uint32[0] = bswap(tmp_addr.uint32[3])
|
|
addr.uint32[1] = bswap(tmp_addr.uint32[2])
|
|
addr.uint32[2] = bswap(tmp_addr.uint32[1])
|
|
addr.uint32[3] = bswap(tmp_addr.uint32[0])
|
|
|
|
return addr
|
|
end
|
|
|
|
--- Merge tables.
|
|
--- @param args Arbitrary amount of tables to get merged.
|
|
function mergeTables(...)
|
|
local table = {}
|
|
if select("#", ...) > 0 then
|
|
table = select(1, ...)
|
|
for i = 2, select("#", ...) do
|
|
for k,v in pairs(select(i, ...)) do
|
|
table[k] = v
|
|
end
|
|
end
|
|
end
|
|
return table
|
|
end
|
|
|
|
local band = bit.band
|
|
local sar = bit.arshift
|
|
|
|
return _M |