util/ip.lua
changeset 13435 4698f1e36e02
parent 12979 d10957394a3c
equal deleted inserted replaced
13434:1a5e3cf037f6 13435:4698f1e36e02
     4 -- This project is MIT/X11 licensed. Please see the
     4 -- This project is MIT/X11 licensed. Please see the
     5 -- COPYING file in the source package for more information.
     5 -- COPYING file in the source package for more information.
     6 --
     6 --
     7 
     7 
     8 local net = require "prosody.util.net";
     8 local net = require "prosody.util.net";
     9 local hex = require "prosody.util.hex";
     9 local strbit = require "prosody.util.strbitop";
    10 
    10 
    11 local ip_methods = {};
    11 local ip_methods = {};
    12 
    12 
    13 local ip_mt = {
    13 local ip_mt = {
    14 	__index = function (ip, key)
    14 	__index = function (ip, key)
    25 		-- Lua 5.3+ calls this if both operands are tables, even if metatables differ
    25 		-- Lua 5.3+ calls this if both operands are tables, even if metatables differ
    26 		return false;
    26 		return false;
    27 	end
    27 	end
    28 	return ipA.packed == ipB.packed;
    28 	return ipA.packed == ipB.packed;
    29 end
    29 end
    30 
       
    31 local hex2bits = {
       
    32 	["0"] = "0000", ["1"] = "0001", ["2"] = "0010", ["3"] = "0011",
       
    33 	["4"] = "0100", ["5"] = "0101", ["6"] = "0110", ["7"] = "0111",
       
    34 	["8"] = "1000", ["9"] = "1001", ["A"] = "1010", ["B"] = "1011",
       
    35 	["C"] = "1100", ["D"] = "1101", ["E"] = "1110", ["F"] = "1111",
       
    36 };
       
    37 
    30 
    38 local function new_ip(ipStr, proto)
    31 local function new_ip(ipStr, proto)
    39 	local zone;
    32 	local zone;
    40 	if (not proto or proto == "IPv6") and ipStr:find('%', 1, true) then
    33 	if (not proto or proto == "IPv6") and ipStr:find('%', 1, true) then
    41 		ipStr, zone = ipStr:match("^(.-)%%(.*)");
    34 		ipStr, zone = ipStr:match("^(.-)%%(.*)");
    64 
    57 
    65 function ip_methods:normal()
    58 function ip_methods:normal()
    66 	return net.ntop(self.packed);
    59 	return net.ntop(self.packed);
    67 end
    60 end
    68 
    61 
    69 function ip_methods.bits(ip)
    62 -- Returns the longest packed representation, i.e. IPv4 will be mapped
    70 	return hex.encode(ip.packed):upper():gsub(".", hex2bits);
    63 function ip_methods.packed_full(ip)
    71 end
       
    72 
       
    73 function ip_methods.bits_full(ip)
       
    74 	if ip.proto == "IPv4" then
    64 	if ip.proto == "IPv4" then
    75 		ip = ip.toV4mapped;
    65 		ip = ip.toV4mapped;
    76 	end
    66 	end
    77 	return ip.bits;
    67 	return ip.packed;
    78 end
    68 end
    79 
    69 
    80 local match;
    70 local match;
    81 
    71 
    82 local function commonPrefixLength(ipA, ipB)
    72 local function commonPrefixLength(ipA, ipB)
    83 	ipA, ipB = ipA.bits_full, ipB.bits_full;
    73 	return strbit.common_prefix_bits(ipA.packed_full, ipB.packed_full);
    84 	for i = 1, 128 do
       
    85 		if ipA:sub(i,i) ~= ipB:sub(i,i) then
       
    86 			return i-1;
       
    87 		end
       
    88 	end
       
    89 	return 128;
       
    90 end
    74 end
    91 
    75 
    92 -- Instantiate once
    76 -- Instantiate once
    93 local loopback = new_ip("::1");
    77 local loopback = new_ip("::1");
    94 local loopback4 = new_ip("127.0.0.0");
    78 local loopback4 = new_ip("127.0.0.0");
   236 		elseif ipB.proto == "IPv4" then
   220 		elseif ipB.proto == "IPv4" then
   237 			ipB = ipB.toV4mapped;
   221 			ipB = ipB.toV4mapped;
   238 			bits = bits + (128 - 32);
   222 			bits = bits + (128 - 32);
   239 		end
   223 		end
   240 	end
   224 	end
   241 	return ipA.bits:sub(1, bits) == ipB.bits:sub(1, bits);
   225 	return strbit.common_prefix_bits(ipA.packed, ipB.packed) >= bits;
   242 end
   226 end
   243 
   227 
   244 local function is_ip(obj)
   228 local function is_ip(obj)
   245 	return getmetatable(obj) == ip_mt;
   229 	return getmetatable(obj) == ip_mt;
   246 end
   230 end