You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
4.0 KiB
Lua
145 lines
4.0 KiB
Lua
-- IPv6
|
|
|
|
local unpack = table.unpack or unpack -- luacheck: ignore 113 143
|
|
|
|
local lpeg = require "lpeg"
|
|
local P = lpeg.P
|
|
local V = lpeg.V
|
|
local Cc = lpeg.Cc
|
|
local Cg = lpeg.Cg
|
|
|
|
local util = require "lpeg_patterns.util"
|
|
|
|
local core = require "lpeg_patterns.core"
|
|
local HEXDIG = core.HEXDIG
|
|
|
|
local IPv4address = require "lpeg_patterns.IPv4".IPv4address
|
|
|
|
local IPv6_methods = {}
|
|
local IPv6_mt = {
|
|
__name = "lpeg_patterns.IPv6";
|
|
__index = IPv6_methods;
|
|
}
|
|
|
|
local function new_IPv6(o1, o2, o3, o4, o5, o6, o7, o8, zoneid)
|
|
return setmetatable({
|
|
o1, o2, o3, o4, o5, o6, o7, o8,
|
|
zoneid = zoneid;
|
|
}, IPv6_mt)
|
|
end
|
|
|
|
function IPv6_methods:unpack()
|
|
return self[1], self[2], self[3], self[4], self[5], self[6], self[7], self[8], self.zoneid
|
|
end
|
|
|
|
function IPv6_methods:binary()
|
|
local t = {}
|
|
for i=1, 8 do
|
|
local lo = self[i] % 256
|
|
t[i*2-1] = (self[i] - lo) / 256
|
|
t[i*2] = lo
|
|
end
|
|
-- TODO: append zoneid.
|
|
-- In a struct sockaddr_in6 it is the numeric index of the scope, so need to lookup?
|
|
return string.char(unpack(t, 1, 16))
|
|
end
|
|
|
|
function IPv6_methods:setzoneid(zoneid)
|
|
self.zoneid = zoneid
|
|
end
|
|
|
|
function IPv6_mt:__tostring()
|
|
local fmt_str
|
|
if self.zoneid then
|
|
fmt_str = "%x:%x:%x:%x:%x:%x:%x:%x%%%s"
|
|
else
|
|
fmt_str = "%x:%x:%x:%x:%x:%x:%x:%x"
|
|
end
|
|
return string.format(fmt_str, self:unpack())
|
|
end
|
|
|
|
-- RFC 3986 Section 3.2.2
|
|
-- This is written as a grammar to reduce memory usage
|
|
local raw_IPv6address = Cg(P{
|
|
h16 = HEXDIG * HEXDIG^-3 / util.read_hex;
|
|
h16c = V"h16" * P":";
|
|
ls32 = ( V"h16c" * V"h16" ) + IPv4address / function ( ipv4 )
|
|
local o1, o2, o3, o4 = ipv4:unpack()
|
|
return o1*2^8 + o2 , o3*2^8 + o4
|
|
end;
|
|
|
|
mh16c_1 = V"h16c";
|
|
mh16c_2 = V"h16c" * V"h16c";
|
|
mh16c_3 = V"h16c" * V"h16c" * V"h16c";
|
|
mh16c_4 = V"h16c" * V"h16c" * V"h16c" * V"h16c";
|
|
mh16c_5 = V"h16c" * V"h16c" * V"h16c" * V"h16c" * V"h16c";
|
|
mh16c_6 = V"h16c" * V"h16c" * V"h16c" * V"h16c" * V"h16c" * V"h16c";
|
|
|
|
mcc_1 = P"::" * Cc(0);
|
|
mcc_2 = P"::" * Cc(0, 0);
|
|
mcc_3 = P"::" * Cc(0, 0, 0);
|
|
mcc_4 = P"::" * Cc(0, 0, 0, 0);
|
|
mcc_5 = P"::" * Cc(0, 0, 0, 0, 0);
|
|
mcc_6 = P"::" * Cc(0, 0, 0, 0, 0, 0);
|
|
mcc_7 = P"::" * Cc(0, 0, 0, 0, 0, 0, 0);
|
|
mcc_8 = P"::" * Cc(0, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
mh16_1 = V"h16";
|
|
mh16_2 = V"mh16c_1" * V"h16";
|
|
mh16_3 = V"mh16c_2" * V"h16";
|
|
mh16_4 = V"mh16c_3" * V"h16";
|
|
mh16_5 = V"mh16c_4" * V"h16";
|
|
mh16_6 = V"mh16c_5" * V"h16";
|
|
mh16_7 = V"mh16c_6" * V"h16";
|
|
|
|
V"mh16c_6" * V"ls32"
|
|
+ V"mcc_1" * V"mh16c_5" * V"ls32"
|
|
+ V"mcc_2" * V"mh16c_4" * V"ls32"
|
|
+ V"h16" * V"mcc_1" * V"mh16c_4" * V"ls32"
|
|
+ V"mcc_3" * V"mh16c_3" * V"ls32"
|
|
+ V"h16" * V"mcc_2" * V"mh16c_3" * V"ls32"
|
|
+ V"mh16_2" * V"mcc_1" * V"mh16c_3" * V"ls32"
|
|
+ V"mcc_4" * V"mh16c_2" * V"ls32"
|
|
+ V"h16" * V"mcc_3" * V"mh16c_2" * V"ls32"
|
|
+ V"mh16_2" * V"mcc_2" * V"mh16c_2" * V"ls32"
|
|
+ V"mh16_3" * V"mcc_1" * V"mh16c_2" * V"ls32"
|
|
+ V"mcc_5" * V"h16c" * V"ls32"
|
|
+ V"h16" * V"mcc_4" * V"h16c" * V"ls32"
|
|
+ V"mh16_2" * V"mcc_3" * V"h16c" * V"ls32"
|
|
+ V"mh16_3" * V"mcc_2" * V"h16c" * V"ls32"
|
|
+ V"mh16_4" * V"mcc_1" * V"h16c" * V"ls32"
|
|
+ V"mcc_6" * V"ls32"
|
|
+ V"h16" * V"mcc_5" * V"ls32"
|
|
+ V"mh16_2" * V"mcc_4" * V"ls32"
|
|
+ V"mh16_3" * V"mcc_3" * V"ls32"
|
|
+ V"mh16_4" * V"mcc_2" * V"ls32"
|
|
+ V"mh16_5" * V"mcc_1" * V"ls32"
|
|
+ V"mcc_7" * V"h16"
|
|
+ V"h16" * V"mcc_6" * V"h16"
|
|
+ V"mh16_2" * V"mcc_5" * V"h16"
|
|
+ V"mh16_3" * V"mcc_4" * V"h16"
|
|
+ V"mh16_4" * V"mcc_3" * V"h16"
|
|
+ V"mh16_5" * V"mcc_2" * V"h16"
|
|
+ V"mh16_6" * V"mcc_1" * V"h16"
|
|
+ V"mcc_8"
|
|
+ V"mh16_1" * V"mcc_7"
|
|
+ V"mh16_2" * V"mcc_6"
|
|
+ V"mh16_3" * V"mcc_5"
|
|
+ V"mh16_4" * V"mcc_4"
|
|
+ V"mh16_5" * V"mcc_3"
|
|
+ V"mh16_6" * V"mcc_2"
|
|
+ V"mh16_7" * V"mcc_1"
|
|
})
|
|
|
|
local IPv6address = raw_IPv6address / new_IPv6
|
|
|
|
local ZoneID = P(1)^1 -- ZoneIDs can be any character
|
|
local IPv6addrz = raw_IPv6address * (P"%" * ZoneID)^-1 / new_IPv6
|
|
|
|
return {
|
|
IPv6_methods = IPv6_methods;
|
|
IPv6_mt = IPv6_mt;
|
|
IPv6address = IPv6address;
|
|
IPv6addrz = IPv6addrz;
|
|
}
|