util/ip.lua
author Kim Alvefur <zash@zash.se>
Tue, 14 May 2024 17:07:47 +0200
changeset 13494 6f840763fc73
parent 13435 4698f1e36e02
permissions -rw-r--r--
net.server_epoll: Add support for systemd socket activation Allows creating listening sockets and accepting client connections before Prosody starts. This is unlike normal Prosody dynamic resource management, where ports may added and removed at any time, and the ports defined by the config. Weird things happen if these are closed (e.g. due to reload) so here we prevent closing and ensure sockets are reused when opened again.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
     1
-- Prosody IM
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
     2
-- Copyright (C) 2008-2011 Florian Zeitz
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
     3
--
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
     4
-- This project is MIT/X11 licensed. Please see the
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
     5
-- COPYING file in the source package for more information.
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
     6
--
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
     7
12979
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12936
diff changeset
     8
local net = require "prosody.util.net";
13435
4698f1e36e02 util.ip: Remove ip.bits and related code, switch to more efficient strbitop
Matthew Wild <mwild1@gmail.com>
parents: 12979
diff changeset
     9
local strbit = require "prosody.util.strbitop";
8433
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    10
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    11
local ip_methods = {};
8431
ca44e462322c util.ip: Reflow metatable
Kim Alvefur <zash@zash.se>
parents: 8385
diff changeset
    12
ca44e462322c util.ip: Reflow metatable
Kim Alvefur <zash@zash.se>
parents: 8385
diff changeset
    13
local ip_mt = {
ca44e462322c util.ip: Reflow metatable
Kim Alvefur <zash@zash.se>
parents: 8385
diff changeset
    14
	__index = function (ip, key)
8439
ab9ddfb03d4d util.ip: Cache return values of all methods in one place
Kim Alvefur <zash@zash.se>
parents: 8438
diff changeset
    15
		local method = ip_methods[key];
ab9ddfb03d4d util.ip: Cache return values of all methods in one place
Kim Alvefur <zash@zash.se>
parents: 8438
diff changeset
    16
		if not method then return nil; end
ab9ddfb03d4d util.ip: Cache return values of all methods in one place
Kim Alvefur <zash@zash.se>
parents: 8438
diff changeset
    17
		local ret = method(ip);
ab9ddfb03d4d util.ip: Cache return values of all methods in one place
Kim Alvefur <zash@zash.se>
parents: 8438
diff changeset
    18
		ip[key] = ret;
ab9ddfb03d4d util.ip: Cache return values of all methods in one place
Kim Alvefur <zash@zash.se>
parents: 8438
diff changeset
    19
		return ret;
8431
ca44e462322c util.ip: Reflow metatable
Kim Alvefur <zash@zash.se>
parents: 8385
diff changeset
    20
	end,
ca44e462322c util.ip: Reflow metatable
Kim Alvefur <zash@zash.se>
parents: 8385
diff changeset
    21
	__tostring = function (ip) return ip.addr; end,
ca44e462322c util.ip: Reflow metatable
Kim Alvefur <zash@zash.se>
parents: 8385
diff changeset
    22
};
10597
079b31c8dbf2 util.ip: Fix equality metamethod for Lua 5.3
Kim Alvefur <zash@zash.se>
parents: 9959
diff changeset
    23
ip_mt.__eq = function (ipA, ipB)
079b31c8dbf2 util.ip: Fix equality metamethod for Lua 5.3
Kim Alvefur <zash@zash.se>
parents: 9959
diff changeset
    24
	if getmetatable(ipA) ~= ip_mt or getmetatable(ipB) ~= ip_mt then
079b31c8dbf2 util.ip: Fix equality metamethod for Lua 5.3
Kim Alvefur <zash@zash.se>
parents: 9959
diff changeset
    25
		-- Lua 5.3+ calls this if both operands are tables, even if metatables differ
079b31c8dbf2 util.ip: Fix equality metamethod for Lua 5.3
Kim Alvefur <zash@zash.se>
parents: 9959
diff changeset
    26
		return false;
079b31c8dbf2 util.ip: Fix equality metamethod for Lua 5.3
Kim Alvefur <zash@zash.se>
parents: 9959
diff changeset
    27
	end
079b31c8dbf2 util.ip: Fix equality metamethod for Lua 5.3
Kim Alvefur <zash@zash.se>
parents: 9959
diff changeset
    28
	return ipA.packed == ipB.packed;
079b31c8dbf2 util.ip: Fix equality metamethod for Lua 5.3
Kim Alvefur <zash@zash.se>
parents: 9959
diff changeset
    29
end
8431
ca44e462322c util.ip: Reflow metatable
Kim Alvefur <zash@zash.se>
parents: 8385
diff changeset
    30
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    31
local function new_ip(ipStr, proto)
8433
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    32
	local zone;
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    33
	if (not proto or proto == "IPv6") and ipStr:find('%', 1, true) then
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    34
		ipStr, zone = ipStr:match("^(.-)%%(.*)");
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    35
	end
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    36
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    37
	local packed, err = net.pton(ipStr);
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    38
	if not packed then return packed, err end
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    39
	if proto == "IPv6" and #packed ~= 16 then
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    40
		return nil, "invalid-ipv6";
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    41
	elseif proto == "IPv4" and #packed ~= 4 then
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    42
		return nil, "invalid-ipv4";
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    43
	elseif not proto then
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    44
		if #packed == 16 then
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    45
			proto = "IPv6";
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    46
		elseif #packed == 4 then
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    47
			proto = "IPv4";
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    48
		else
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    49
			return nil, "unknown protocol";
7055
306aabf2d57d util.ip: Automatically determine protocol of IP address if none specified. Return error if invalid. [Backported from 0.10]
Matthew Wild <mwild1@gmail.com>
parents: 5597
diff changeset
    50
		end
8433
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    51
	elseif proto ~= "IPv6" and proto ~= "IPv4" then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    52
		return nil, "invalid protocol";
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    53
	end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    54
8433
a58d560aa8d5 util.ip: Parse IP address using inet_pton
Kim Alvefur <zash@zash.se>
parents: 8432
diff changeset
    55
	return setmetatable({ addr = ipStr, packed = packed, proto = proto, zone = zone }, ip_mt);
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    56
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    57
8436
ca7f8e60410a util.ip: Add a method returning a normalized IP address
Kim Alvefur <zash@zash.se>
parents: 8435
diff changeset
    58
function ip_methods:normal()
ca7f8e60410a util.ip: Add a method returning a normalized IP address
Kim Alvefur <zash@zash.se>
parents: 8435
diff changeset
    59
	return net.ntop(self.packed);
ca7f8e60410a util.ip: Add a method returning a normalized IP address
Kim Alvefur <zash@zash.se>
parents: 8435
diff changeset
    60
end
ca7f8e60410a util.ip: Add a method returning a normalized IP address
Kim Alvefur <zash@zash.se>
parents: 8435
diff changeset
    61
13435
4698f1e36e02 util.ip: Remove ip.bits and related code, switch to more efficient strbitop
Matthew Wild <mwild1@gmail.com>
parents: 12979
diff changeset
    62
-- Returns the longest packed representation, i.e. IPv4 will be mapped
4698f1e36e02 util.ip: Remove ip.bits and related code, switch to more efficient strbitop
Matthew Wild <mwild1@gmail.com>
parents: 12979
diff changeset
    63
function ip_methods.packed_full(ip)
8434
a5a03d40a20c util.ip: Make bit string function into a method
Kim Alvefur <zash@zash.se>
parents: 8433
diff changeset
    64
	if ip.proto == "IPv4" then
a5a03d40a20c util.ip: Make bit string function into a method
Kim Alvefur <zash@zash.se>
parents: 8433
diff changeset
    65
		ip = ip.toV4mapped;
a5a03d40a20c util.ip: Make bit string function into a method
Kim Alvefur <zash@zash.se>
parents: 8433
diff changeset
    66
	end
13435
4698f1e36e02 util.ip: Remove ip.bits and related code, switch to more efficient strbitop
Matthew Wild <mwild1@gmail.com>
parents: 12979
diff changeset
    67
	return ip.packed;
8434
a5a03d40a20c util.ip: Make bit string function into a method
Kim Alvefur <zash@zash.se>
parents: 8433
diff changeset
    68
end
a5a03d40a20c util.ip: Make bit string function into a method
Kim Alvefur <zash@zash.se>
parents: 8433
diff changeset
    69
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    70
local match;
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    71
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    72
local function commonPrefixLength(ipA, ipB)
13435
4698f1e36e02 util.ip: Remove ip.bits and related code, switch to more efficient strbitop
Matthew Wild <mwild1@gmail.com>
parents: 12979
diff changeset
    73
	return strbit.common_prefix_bits(ipA.packed_full, ipB.packed_full);
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    74
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    75
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    76
-- Instantiate once
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    77
local loopback = new_ip("::1");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    78
local loopback4 = new_ip("127.0.0.0");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    79
local sixtofour = new_ip("2002::");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    80
local teredo = new_ip("2001::");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    81
local linklocal = new_ip("fe80::");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    82
local linklocal4 = new_ip("169.254.0.0");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    83
local uniquelocal = new_ip("fc00::");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    84
local sitelocal = new_ip("fec0::");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    85
local sixbone = new_ip("3ffe::");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    86
local defaultunicast = new_ip("::");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    87
local multicast = new_ip("ff00::");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    88
local ipv6mapped = new_ip("::ffff:0:0");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    89
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    90
local function v4scope(ip)
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    91
	if match(ip, loopback4, 8) then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    92
		return 0x2;
11653
aa119de5f6c7 util.ip: Fix netmask for link-local address range
Kim Alvefur <zash@zash.se>
parents: 9959
diff changeset
    93
	elseif match(ip, linklocal4, 16) then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    94
		return 0x2;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
    95
	else -- Global unicast
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    96
		return 0xE;
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    97
	end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    98
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
    99
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   100
local function v6scope(ip)
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   101
	if ip == loopback then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   102
		return 0x2;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   103
	elseif match(ip, linklocal, 10) then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   104
		return 0x2;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   105
	elseif match(ip, sitelocal, 10) then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   106
		return 0x5;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   107
	elseif match(ip, multicast, 10) then
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   108
		return ip.packed:byte(2) % 0x10;
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   109
	else -- Global unicast
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   110
		return 0xE;
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   111
	end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   112
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   113
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   114
local function label(ip)
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   115
	if ip == loopback then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   116
		return 0;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   117
	elseif match(ip, sixtofour, 16) then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   118
		return 2;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   119
	elseif match(ip, teredo, 32) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   120
		return 5;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   121
	elseif match(ip, uniquelocal, 7) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   122
		return 13;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   123
	elseif match(ip, sitelocal, 10) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   124
		return 11;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   125
	elseif match(ip, sixbone, 16) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   126
		return 12;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   127
	elseif match(ip, defaultunicast, 96) then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   128
		return 3;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   129
	elseif match(ip, ipv6mapped, 96) then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   130
		return 4;
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   131
	else
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   132
		return 1;
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   133
	end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   134
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   135
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   136
local function precedence(ip)
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   137
	if ip == loopback then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   138
		return 50;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   139
	elseif match(ip, sixtofour, 16) then
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   140
		return 30;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   141
	elseif match(ip, teredo, 32) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   142
		return 5;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   143
	elseif match(ip, uniquelocal, 7) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   144
		return 3;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   145
	elseif match(ip, sitelocal, 10) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   146
		return 1;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   147
	elseif match(ip, sixbone, 16) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   148
		return 1;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   149
	elseif match(ip, defaultunicast, 96) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   150
		return 1;
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   151
	elseif match(ip, ipv6mapped, 96) then
5552
40e7a6cf15ff util.rfc{3484,6724}: Update to RFC 6724
Florian Zeitz <florob@babelmonkeys.de>
parents: 4433
diff changeset
   152
		return 35;
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   153
	else
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   154
		return 40;
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   155
	end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   156
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   157
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   158
function ip_methods:toV4mapped()
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   159
	if self.proto ~= "IPv4" then return nil, "No IPv4 address" end
8437
ec8f37baffaa util.ip: Simplify creation of IPv6-mapped IPv4 addresses
Kim Alvefur <zash@zash.se>
parents: 8436
diff changeset
   160
	local value = new_ip("::ffff:" .. self.normal);
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   161
	return value;
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   162
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   163
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   164
function ip_methods:label()
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   165
	if self.proto == "IPv4" then
8472
52d48cea1f60 util.ip: Remove redundant caching of method output (supposed to be done in ab9ddfb03d4d but lost somehow)
Kim Alvefur <zash@zash.se>
parents: 8471
diff changeset
   166
		return label(self.toV4mapped);
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   167
	else
8472
52d48cea1f60 util.ip: Remove redundant caching of method output (supposed to be done in ab9ddfb03d4d but lost somehow)
Kim Alvefur <zash@zash.se>
parents: 8471
diff changeset
   168
		return label(self);
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   169
	end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   170
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   171
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   172
function ip_methods:precedence()
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   173
	if self.proto == "IPv4" then
8472
52d48cea1f60 util.ip: Remove redundant caching of method output (supposed to be done in ab9ddfb03d4d but lost somehow)
Kim Alvefur <zash@zash.se>
parents: 8471
diff changeset
   174
		return precedence(self.toV4mapped);
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   175
	else
8472
52d48cea1f60 util.ip: Remove redundant caching of method output (supposed to be done in ab9ddfb03d4d but lost somehow)
Kim Alvefur <zash@zash.se>
parents: 8471
diff changeset
   176
		return precedence(self);
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   177
	end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   178
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   179
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   180
function ip_methods:scope()
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   181
	if self.proto == "IPv4" then
8472
52d48cea1f60 util.ip: Remove redundant caching of method output (supposed to be done in ab9ddfb03d4d but lost somehow)
Kim Alvefur <zash@zash.se>
parents: 8471
diff changeset
   182
		return v4scope(self);
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   183
	else
8472
52d48cea1f60 util.ip: Remove redundant caching of method output (supposed to be done in ab9ddfb03d4d but lost somehow)
Kim Alvefur <zash@zash.se>
parents: 8471
diff changeset
   184
		return v6scope(self);
4422
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   185
	end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   186
end
b1e49cc314cb util.ip: New module containing IP related functions
Florian Zeitz <florob@babelmonkeys.de>
parents:
diff changeset
   187
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   188
local rfc1918_8 = new_ip("10.0.0.0");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   189
local rfc1918_12 = new_ip("172.16.0.0");
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   190
local rfc1918_16 = new_ip("192.168.0.0");
8442
293dbb08427b util.ip: Add CGNAT network range reserved in RFC 6598
Kim Alvefur <zash@zash.se>
parents: 8441
diff changeset
   191
local rfc6598 = new_ip("100.64.0.0");
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   192
5588
8c1a3243d16f util.ip: Add 'private' method/property to determine whether an IP address is generally expected to be internet-routeable (YMMV)
Matthew Wild <mwild1@gmail.com>
parents: 5587
diff changeset
   193
function ip_methods:private()
8c1a3243d16f util.ip: Add 'private' method/property to determine whether an IP address is generally expected to be internet-routeable (YMMV)
Matthew Wild <mwild1@gmail.com>
parents: 5587
diff changeset
   194
	local private = self.scope ~= 0xE;
8c1a3243d16f util.ip: Add 'private' method/property to determine whether an IP address is generally expected to be internet-routeable (YMMV)
Matthew Wild <mwild1@gmail.com>
parents: 5587
diff changeset
   195
	if not private and self.proto == "IPv4" then
9959
c74c89a96cbf util.ip: Add missing netmask for 192.168/16 range (fixes #1343)
Kim Alvefur <zash@zash.se>
parents: 8472
diff changeset
   196
		return match(self, rfc1918_8, 8) or match(self, rfc1918_12, 12) or match(self, rfc1918_16, 16) or match(self, rfc6598, 10);
5588
8c1a3243d16f util.ip: Add 'private' method/property to determine whether an IP address is generally expected to be internet-routeable (YMMV)
Matthew Wild <mwild1@gmail.com>
parents: 5587
diff changeset
   197
	end
8c1a3243d16f util.ip: Add 'private' method/property to determine whether an IP address is generally expected to be internet-routeable (YMMV)
Matthew Wild <mwild1@gmail.com>
parents: 5587
diff changeset
   198
	return private;
8c1a3243d16f util.ip: Add 'private' method/property to determine whether an IP address is generally expected to be internet-routeable (YMMV)
Matthew Wild <mwild1@gmail.com>
parents: 5587
diff changeset
   199
end
8c1a3243d16f util.ip: Add 'private' method/property to determine whether an IP address is generally expected to be internet-routeable (YMMV)
Matthew Wild <mwild1@gmail.com>
parents: 5587
diff changeset
   200
5603
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   201
local function parse_cidr(cidr)
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   202
	local bits;
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   203
	local ip_len = cidr:find("/", 1, true);
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   204
	if ip_len then
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   205
		bits = tonumber(cidr:sub(ip_len+1, -1));
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   206
		cidr = cidr:sub(1, ip_len-1);
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   207
	end
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   208
	return new_ip(cidr), bits;
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   209
end
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   210
8438
47195f035d2f util.ip: Instantiate various addresses used for comparisons once
Kim Alvefur <zash@zash.se>
parents: 8437
diff changeset
   211
function match(ipA, ipB, bits)
8441
499663bd0122 util.ip: Do exact match for longer bit counts than available
Kim Alvefur <zash@zash.se>
parents: 8440
diff changeset
   212
	if not bits or bits >= 128 or ipB.proto == "IPv4" and bits >= 32 then
8440
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   213
		return ipA == ipB;
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   214
	elseif bits < 1 then
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   215
		return true;
5603
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   216
	end
8440
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   217
	if ipA.proto ~= ipB.proto then
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   218
		if ipA.proto == "IPv4" then
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   219
			ipA = ipA.toV4mapped;
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   220
		elseif ipB.proto == "IPv4" then
8471
5bfe58539b6c util.ip: Convert the correct IP to IPv6-mapped for comparison (fixes traceback, possibly invalid result)
Kim Alvefur <zash@zash.se>
parents: 8444
diff changeset
   221
			ipB = ipB.toV4mapped;
8440
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   222
			bits = bits + (128 - 32);
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   223
		end
021129f7b0a3 util.ip: Do CIDR matching by comparing all bits at once instead of using O(n) function
Kim Alvefur <zash@zash.se>
parents: 8439
diff changeset
   224
	end
13435
4698f1e36e02 util.ip: Remove ip.bits and related code, switch to more efficient strbitop
Matthew Wild <mwild1@gmail.com>
parents: 12979
diff changeset
   225
	return strbit.common_prefix_bits(ipA.packed, ipB.packed) >= bits;
5603
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   226
end
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   227
12935
bbae3acc6694 util.ip: Add is_ip() helper method to detect if an object is an ip object
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   228
local function is_ip(obj)
bbae3acc6694 util.ip: Add is_ip() helper method to detect if an object is an ip object
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   229
	return getmetatable(obj) == ip_mt;
bbae3acc6694 util.ip: Add is_ip() helper method to detect if an object is an ip object
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   230
end
bbae3acc6694 util.ip: Add is_ip() helper method to detect if an object is an ip object
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   231
12936
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   232
local function truncate(ip, n_bits)
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   233
	if n_bits % 8 ~= 0 then
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   234
		return error("ip.truncate() only supports multiples of 8 bits");
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   235
	end
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   236
	local n_octets = n_bits / 8;
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   237
	if not is_ip(ip) then
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   238
		ip = new_ip(ip);
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   239
	end
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   240
	return new_ip(net.ntop(ip.packed:sub(1, n_octets)..("\0"):rep(#ip.packed-n_octets)))
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   241
end
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   242
8432
b3562a1b1caa util.ip: Reflow module export table
Kim Alvefur <zash@zash.se>
parents: 8431
diff changeset
   243
return {
b3562a1b1caa util.ip: Reflow module export table
Kim Alvefur <zash@zash.se>
parents: 8431
diff changeset
   244
	new_ip = new_ip,
5603
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   245
	commonPrefixLength = commonPrefixLength,
e07f4f02e4f9 util.ip: Add CIDR notation parsing and matching
Matthew Wild <mwild1@gmail.com>
parents: 5599
diff changeset
   246
	parse_cidr = parse_cidr,
8432
b3562a1b1caa util.ip: Reflow module export table
Kim Alvefur <zash@zash.se>
parents: 8431
diff changeset
   247
	match = match,
12935
bbae3acc6694 util.ip: Add is_ip() helper method to detect if an object is an ip object
Matthew Wild <mwild1@gmail.com>
parents: 12359
diff changeset
   248
	is_ip = is_ip;
12936
9bb044705ea1 util.ip: Add ip.truncate() to return a new IP with only the prefix of another
Matthew Wild <mwild1@gmail.com>
parents: 12935
diff changeset
   249
	truncate = truncate;
8432
b3562a1b1caa util.ip: Reflow module export table
Kim Alvefur <zash@zash.se>
parents: 8431
diff changeset
   250
};