File: IPv6.lua

package info (click to toggle)
lua-lpeg-patterns 0.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 220 kB
  • sloc: makefile: 6
file content (144 lines) | stat: -rw-r--r-- 4,126 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
-- 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;
}