equal
deleted
inserted
replaced
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 |