Mercurial > prosody-hg
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 |
| parents | ec8f37baffaa |
| children | 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); |
