Software /
code /
prosody
Comparison
util/ip.lua @ 8435:47195f035d2f
util.ip: Instantiate various addresses used for comparisons once
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 01 Dec 2017 02:23:57 +0100 |
parent | 8434:ec8f37baffaa |
child | 8436:ab9ddfb03d4d |
comparison
equal
deleted
inserted
replaced
8434:ec8f37baffaa | 8435:47195f035d2f |
---|---|
65 ip = ip.toV4mapped; | 65 ip = ip.toV4mapped; |
66 end | 66 end |
67 return ip.bits; | 67 return ip.bits; |
68 end | 68 end |
69 | 69 |
70 local match; | |
71 | |
70 local function commonPrefixLength(ipA, ipB) | 72 local function commonPrefixLength(ipA, ipB) |
71 ipA, ipB = ipA.bits_full, ipB.bits_full; | 73 ipA, ipB = ipA.bits_full, ipB.bits_full; |
72 for i = 1, 128 do | 74 for i = 1, 128 do |
73 if ipA:sub(i,i) ~= ipB:sub(i,i) then | 75 if ipA:sub(i,i) ~= ipB:sub(i,i) then |
74 return i-1; | 76 return i-1; |
75 end | 77 end |
76 end | 78 end |
77 return 128; | 79 return 128; |
78 end | 80 end |
79 | 81 |
82 -- Instantiate once | |
83 local loopback = new_ip("::1"); | |
84 local loopback4 = new_ip("127.0.0.0"); | |
85 local sixtofour = new_ip("2002::"); | |
86 local teredo = new_ip("2001::"); | |
87 local linklocal = new_ip("fe80::"); | |
88 local linklocal4 = new_ip("169.254.0.0"); | |
89 local uniquelocal = new_ip("fc00::"); | |
90 local sitelocal = new_ip("fec0::"); | |
91 local sixbone = new_ip("3ffe::"); | |
92 local defaultunicast = new_ip("::"); | |
93 local multicast = new_ip("ff00::"); | |
94 local ipv6mapped = new_ip("::ffff:0:0"); | |
95 | |
80 local function v4scope(ip) | 96 local function v4scope(ip) |
81 local fields = {}; | 97 if match(ip, loopback4, 8) then |
82 ip:gsub("([^.]*).?", function (c) fields[#fields + 1] = tonumber(c) end); | 98 return 0x2; |
83 -- Loopback: | 99 elseif match(ip, linklocal4) then |
84 if fields[1] == 127 then | 100 return 0x2; |
85 return 0x2; | 101 else -- Global unicast |
86 -- Link-local unicast: | |
87 elseif fields[1] == 169 and fields[2] == 254 then | |
88 return 0x2; | |
89 -- Global unicast: | |
90 else | |
91 return 0xE; | 102 return 0xE; |
92 end | 103 end |
93 end | 104 end |
94 | 105 |
95 local function v6scope(ip) | 106 local function v6scope(ip) |
96 -- Loopback: | 107 if ip == loopback then |
97 if ip:match("^[0:]*1$") then | 108 return 0x2; |
98 return 0x2; | 109 elseif match(ip, linklocal, 10) then |
99 -- Link-local unicast: | 110 return 0x2; |
100 elseif ip:match("^[Ff][Ee][89ABab]") then | 111 elseif match(ip, sitelocal, 10) then |
101 return 0x2; | |
102 -- Site-local unicast: | |
103 elseif ip:match("^[Ff][Ee][CcDdEeFf]") then | |
104 return 0x5; | 112 return 0x5; |
105 -- Multicast: | 113 elseif match(ip, multicast, 10) then |
106 elseif ip:match("^[Ff][Ff]") then | 114 return ip.packed:byte(2) % 0x10; |
107 return tonumber("0x"..ip:sub(4,4)); | 115 else -- Global unicast |
108 -- Global unicast: | |
109 else | |
110 return 0xE; | 116 return 0xE; |
111 end | 117 end |
112 end | 118 end |
113 | 119 |
114 local function label(ip) | 120 local function label(ip) |
115 if commonPrefixLength(ip, new_ip("::1", "IPv6")) == 128 then | 121 if ip == loopback then |
116 return 0; | 122 return 0; |
117 elseif commonPrefixLength(ip, new_ip("2002::", "IPv6")) >= 16 then | 123 elseif match(ip, sixtofour, 16) then |
118 return 2; | 124 return 2; |
119 elseif commonPrefixLength(ip, new_ip("2001::", "IPv6")) >= 32 then | 125 elseif match(ip, teredo, 32) then |
120 return 5; | 126 return 5; |
121 elseif commonPrefixLength(ip, new_ip("fc00::", "IPv6")) >= 7 then | 127 elseif match(ip, uniquelocal, 7) then |
122 return 13; | 128 return 13; |
123 elseif commonPrefixLength(ip, new_ip("fec0::", "IPv6")) >= 10 then | 129 elseif match(ip, sitelocal, 10) then |
124 return 11; | 130 return 11; |
125 elseif commonPrefixLength(ip, new_ip("3ffe::", "IPv6")) >= 16 then | 131 elseif match(ip, sixbone, 16) then |
126 return 12; | 132 return 12; |
127 elseif commonPrefixLength(ip, new_ip("::", "IPv6")) >= 96 then | 133 elseif match(ip, defaultunicast, 96) then |
128 return 3; | 134 return 3; |
129 elseif commonPrefixLength(ip, new_ip("::ffff:0:0", "IPv6")) >= 96 then | 135 elseif match(ip, ipv6mapped, 96) then |
130 return 4; | 136 return 4; |
131 else | 137 else |
132 return 1; | 138 return 1; |
133 end | 139 end |
134 end | 140 end |
135 | 141 |
136 local function precedence(ip) | 142 local function precedence(ip) |
137 if commonPrefixLength(ip, new_ip("::1", "IPv6")) == 128 then | 143 if ip == loopback then |
138 return 50; | 144 return 50; |
139 elseif commonPrefixLength(ip, new_ip("2002::", "IPv6")) >= 16 then | 145 elseif match(ip, sixtofour, 16) then |
140 return 30; | 146 return 30; |
141 elseif commonPrefixLength(ip, new_ip("2001::", "IPv6")) >= 32 then | 147 elseif match(ip, teredo, 32) then |
142 return 5; | 148 return 5; |
143 elseif commonPrefixLength(ip, new_ip("fc00::", "IPv6")) >= 7 then | 149 elseif match(ip, uniquelocal, 7) then |
144 return 3; | 150 return 3; |
145 elseif commonPrefixLength(ip, new_ip("fec0::", "IPv6")) >= 10 then | 151 elseif match(ip, sitelocal, 10) then |
146 return 1; | 152 return 1; |
147 elseif commonPrefixLength(ip, new_ip("3ffe::", "IPv6")) >= 16 then | 153 elseif match(ip, sixbone, 16) then |
148 return 1; | 154 return 1; |
149 elseif commonPrefixLength(ip, new_ip("::", "IPv6")) >= 96 then | 155 elseif match(ip, defaultunicast, 96) then |
150 return 1; | 156 return 1; |
151 elseif commonPrefixLength(ip, new_ip("::ffff:0:0", "IPv6")) >= 96 then | 157 elseif match(ip, ipv6mapped, 96) then |
152 return 35; | 158 return 35; |
153 else | 159 else |
154 return 40; | 160 return 40; |
155 end | 161 end |
156 end | 162 end |
184 end | 190 end |
185 | 191 |
186 function ip_methods:scope() | 192 function ip_methods:scope() |
187 local value; | 193 local value; |
188 if self.proto == "IPv4" then | 194 if self.proto == "IPv4" then |
189 value = v4scope(self.addr); | 195 value = v4scope(self); |
190 else | 196 else |
191 value = v6scope(self.addr); | 197 value = v6scope(self); |
192 end | 198 end |
193 self.scope = value; | 199 self.scope = value; |
194 return value; | 200 return value; |
195 end | 201 end |
202 | |
203 local rfc1918_8 = new_ip("10.0.0.0"); | |
204 local rfc1918_12 = new_ip("172.16.0.0"); | |
205 local rfc1918_16 = new_ip("192.168.0.0"); | |
196 | 206 |
197 function ip_methods:private() | 207 function ip_methods:private() |
198 local private = self.scope ~= 0xE; | 208 local private = self.scope ~= 0xE; |
199 if not private and self.proto == "IPv4" then | 209 if not private and self.proto == "IPv4" then |
200 local ip = self.addr; | 210 private = match(self, rfc1918_8, 8) or match(self, rfc1918_12, 12) or match(self, rfc1918_16); |
201 local fields = {}; | |
202 ip:gsub("([^.]*).?", function (c) fields[#fields + 1] = tonumber(c) end); | |
203 if fields[1] == 127 or fields[1] == 10 or (fields[1] == 192 and fields[2] == 168) | |
204 or (fields[1] == 172 and (fields[2] >= 16 or fields[2] <= 32)) then | |
205 private = true; | |
206 end | |
207 end | 211 end |
208 self.private = private; | 212 self.private = private; |
209 return private; | 213 return private; |
210 end | 214 end |
211 | 215 |
217 cidr = cidr:sub(1, ip_len-1); | 221 cidr = cidr:sub(1, ip_len-1); |
218 end | 222 end |
219 return new_ip(cidr), bits; | 223 return new_ip(cidr), bits; |
220 end | 224 end |
221 | 225 |
222 local function match(ipA, ipB, bits) | 226 function match(ipA, ipB, bits) |
223 local common_bits = commonPrefixLength(ipA, ipB); | 227 local common_bits = commonPrefixLength(ipA, ipB); |
224 if bits and ipB.proto == "IPv4" then | 228 if bits and ipB.proto == "IPv4" then |
225 common_bits = common_bits - 96; -- v6 mapped addresses always share these bits | 229 common_bits = common_bits - 96; -- v6 mapped addresses always share these bits |
226 end | 230 end |
227 return common_bits >= (bits or 128); | 231 return common_bits >= (bits or 128); |