OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #if defined(WEBRTC_POSIX) | |
12 #include <sys/types.h> | |
13 #include <sys/socket.h> | |
14 #include <netinet/in.h> | |
15 #ifdef OPENBSD | |
16 #include <netinet/in_systm.h> | |
17 #endif | |
18 #ifndef __native_client__ | |
19 #include <netinet/ip.h> | |
20 #endif | |
21 #include <arpa/inet.h> | |
22 #include <netdb.h> | |
23 #include <unistd.h> | |
24 #endif | |
25 | |
26 #include <stdio.h> | |
27 | |
28 #include "webrtc/base/ipaddress.h" | |
29 #include "webrtc/base/byteorder.h" | |
30 #include "webrtc/base/checks.h" | |
31 #include "webrtc/base/logging.h" | |
32 #include "webrtc/base/nethelpers.h" | |
33 #include "webrtc/base/stringutils.h" | |
34 #include "webrtc/base/win32.h" | |
35 | |
36 namespace rtc { | |
37 | |
38 // Prefixes used for categorizing IPv6 addresses. | |
39 static const in6_addr kV4MappedPrefix = {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
40 0xFF, 0xFF, 0}}}; | |
41 static const in6_addr k6To4Prefix = {{{0x20, 0x02, 0}}}; | |
42 static const in6_addr kTeredoPrefix = {{{0x20, 0x01, 0x00, 0x00}}}; | |
43 static const in6_addr kV4CompatibilityPrefix = {{{0}}}; | |
44 static const in6_addr k6BonePrefix = {{{0x3f, 0xfe, 0}}}; | |
45 | |
46 static bool IsPrivateV4(uint32_t ip); | |
47 static in_addr ExtractMappedAddress(const in6_addr& addr); | |
48 | |
49 uint32_t IPAddress::v4AddressAsHostOrderInteger() const { | |
50 if (family_ == AF_INET) { | |
51 return NetworkToHost32(u_.ip4.s_addr); | |
52 } else { | |
53 return 0; | |
54 } | |
55 } | |
56 | |
57 bool IPAddress::IsNil() const { | |
58 return IPIsUnspec(*this); | |
59 } | |
60 | |
61 size_t IPAddress::Size() const { | |
62 switch (family_) { | |
63 case AF_INET: | |
64 return sizeof(in_addr); | |
65 case AF_INET6: | |
66 return sizeof(in6_addr); | |
67 } | |
68 return 0; | |
69 } | |
70 | |
71 | |
72 bool IPAddress::operator==(const IPAddress &other) const { | |
73 if (family_ != other.family_) { | |
74 return false; | |
75 } | |
76 if (family_ == AF_INET) { | |
77 return memcmp(&u_.ip4, &other.u_.ip4, sizeof(u_.ip4)) == 0; | |
78 } | |
79 if (family_ == AF_INET6) { | |
80 return memcmp(&u_.ip6, &other.u_.ip6, sizeof(u_.ip6)) == 0; | |
81 } | |
82 return family_ == AF_UNSPEC; | |
83 } | |
84 | |
85 bool IPAddress::operator!=(const IPAddress &other) const { | |
86 return !((*this) == other); | |
87 } | |
88 | |
89 bool IPAddress::operator >(const IPAddress &other) const { | |
90 return (*this) != other && !((*this) < other); | |
91 } | |
92 | |
93 bool IPAddress::operator <(const IPAddress &other) const { | |
94 // IPv4 is 'less than' IPv6 | |
95 if (family_ != other.family_) { | |
96 if (family_ == AF_UNSPEC) { | |
97 return true; | |
98 } | |
99 if (family_ == AF_INET && other.family_ == AF_INET6) { | |
100 return true; | |
101 } | |
102 return false; | |
103 } | |
104 // Comparing addresses of the same family. | |
105 switch (family_) { | |
106 case AF_INET: { | |
107 return NetworkToHost32(u_.ip4.s_addr) < | |
108 NetworkToHost32(other.u_.ip4.s_addr); | |
109 } | |
110 case AF_INET6: { | |
111 return memcmp(&u_.ip6.s6_addr, &other.u_.ip6.s6_addr, 16) < 0; | |
112 } | |
113 } | |
114 // Catches AF_UNSPEC and invalid addresses. | |
115 return false; | |
116 } | |
117 | |
118 std::ostream& operator<<(std::ostream& os, const IPAddress& ip) { | |
119 os << ip.ToString(); | |
120 return os; | |
121 } | |
122 | |
123 in6_addr IPAddress::ipv6_address() const { | |
124 return u_.ip6; | |
125 } | |
126 | |
127 in_addr IPAddress::ipv4_address() const { | |
128 return u_.ip4; | |
129 } | |
130 | |
131 std::string IPAddress::ToString() const { | |
132 if (family_ != AF_INET && family_ != AF_INET6) { | |
133 return std::string(); | |
134 } | |
135 char buf[INET6_ADDRSTRLEN] = {0}; | |
136 const void* src = &u_.ip4; | |
137 if (family_ == AF_INET6) { | |
138 src = &u_.ip6; | |
139 } | |
140 if (!rtc::inet_ntop(family_, src, buf, sizeof(buf))) { | |
141 return std::string(); | |
142 } | |
143 return std::string(buf); | |
144 } | |
145 | |
146 std::string IPAddress::ToSensitiveString() const { | |
147 #if !defined(NDEBUG) | |
148 // Return non-stripped in debug. | |
149 return ToString(); | |
150 #else | |
151 switch (family_) { | |
152 case AF_INET: { | |
153 std::string address = ToString(); | |
154 size_t find_pos = address.rfind('.'); | |
155 if (find_pos == std::string::npos) | |
156 return std::string(); | |
157 address.resize(find_pos); | |
158 address += ".x"; | |
159 return address; | |
160 } | |
161 case AF_INET6: { | |
162 std::string result; | |
163 result.resize(INET6_ADDRSTRLEN); | |
164 in6_addr addr = ipv6_address(); | |
165 size_t len = | |
166 rtc::sprintfn(&(result[0]), result.size(), "%x:%x:%x:x:x:x:x:x", | |
167 (addr.s6_addr[0] << 8) + addr.s6_addr[1], | |
168 (addr.s6_addr[2] << 8) + addr.s6_addr[3], | |
169 (addr.s6_addr[4] << 8) + addr.s6_addr[5]); | |
170 result.resize(len); | |
171 return result; | |
172 } | |
173 } | |
174 return std::string(); | |
175 #endif | |
176 } | |
177 | |
178 IPAddress IPAddress::Normalized() const { | |
179 if (family_ != AF_INET6) { | |
180 return *this; | |
181 } | |
182 if (!IPIsV4Mapped(*this)) { | |
183 return *this; | |
184 } | |
185 in_addr addr = ExtractMappedAddress(u_.ip6); | |
186 return IPAddress(addr); | |
187 } | |
188 | |
189 IPAddress IPAddress::AsIPv6Address() const { | |
190 if (family_ != AF_INET) { | |
191 return *this; | |
192 } | |
193 in6_addr v6addr = kV4MappedPrefix; | |
194 ::memcpy(&v6addr.s6_addr[12], &u_.ip4.s_addr, sizeof(u_.ip4.s_addr)); | |
195 return IPAddress(v6addr); | |
196 } | |
197 | |
198 bool InterfaceAddress::operator==(const InterfaceAddress &other) const { | |
199 return ipv6_flags_ == other.ipv6_flags() && | |
200 static_cast<const IPAddress&>(*this) == other; | |
201 } | |
202 | |
203 bool InterfaceAddress::operator!=(const InterfaceAddress &other) const { | |
204 return !((*this) == other); | |
205 } | |
206 | |
207 const InterfaceAddress& InterfaceAddress::operator=( | |
208 const InterfaceAddress& other) { | |
209 ipv6_flags_ = other.ipv6_flags_; | |
210 static_cast<IPAddress&>(*this) = other; | |
211 return *this; | |
212 } | |
213 | |
214 std::ostream& operator<<(std::ostream& os, const InterfaceAddress& ip) { | |
215 os << static_cast<const IPAddress&>(ip); | |
216 | |
217 if (ip.family() == AF_INET6) | |
218 os << "|flags:0x" << std::hex << ip.ipv6_flags(); | |
219 | |
220 return os; | |
221 } | |
222 | |
223 bool IsPrivateV4(uint32_t ip_in_host_order) { | |
224 return ((ip_in_host_order >> 24) == 127) || | |
225 ((ip_in_host_order >> 24) == 10) || | |
226 ((ip_in_host_order >> 20) == ((172 << 4) | 1)) || | |
227 ((ip_in_host_order >> 16) == ((192 << 8) | 168)) || | |
228 ((ip_in_host_order >> 16) == ((169 << 8) | 254)); | |
229 } | |
230 | |
231 in_addr ExtractMappedAddress(const in6_addr& in6) { | |
232 in_addr ipv4; | |
233 ::memcpy(&ipv4.s_addr, &in6.s6_addr[12], sizeof(ipv4.s_addr)); | |
234 return ipv4; | |
235 } | |
236 | |
237 bool IPFromAddrInfo(struct addrinfo* info, IPAddress* out) { | |
238 if (!info || !info->ai_addr) { | |
239 return false; | |
240 } | |
241 if (info->ai_addr->sa_family == AF_INET) { | |
242 sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(info->ai_addr); | |
243 *out = IPAddress(addr->sin_addr); | |
244 return true; | |
245 } else if (info->ai_addr->sa_family == AF_INET6) { | |
246 sockaddr_in6* addr = reinterpret_cast<sockaddr_in6*>(info->ai_addr); | |
247 *out = IPAddress(addr->sin6_addr); | |
248 return true; | |
249 } | |
250 return false; | |
251 } | |
252 | |
253 bool IPFromString(const std::string& str, IPAddress* out) { | |
254 if (!out) { | |
255 return false; | |
256 } | |
257 in_addr addr; | |
258 if (rtc::inet_pton(AF_INET, str.c_str(), &addr) == 0) { | |
259 in6_addr addr6; | |
260 if (rtc::inet_pton(AF_INET6, str.c_str(), &addr6) == 0) { | |
261 *out = IPAddress(); | |
262 return false; | |
263 } | |
264 *out = IPAddress(addr6); | |
265 } else { | |
266 *out = IPAddress(addr); | |
267 } | |
268 return true; | |
269 } | |
270 | |
271 bool IPFromString(const std::string& str, int flags, | |
272 InterfaceAddress* out) { | |
273 IPAddress ip; | |
274 if (!IPFromString(str, &ip)) { | |
275 return false; | |
276 } | |
277 | |
278 *out = InterfaceAddress(ip, flags); | |
279 return true; | |
280 } | |
281 | |
282 bool IPIsAny(const IPAddress& ip) { | |
283 switch (ip.family()) { | |
284 case AF_INET: | |
285 return ip == IPAddress(INADDR_ANY); | |
286 case AF_INET6: | |
287 return ip == IPAddress(in6addr_any) || ip == IPAddress(kV4MappedPrefix); | |
288 case AF_UNSPEC: | |
289 return false; | |
290 } | |
291 return false; | |
292 } | |
293 | |
294 bool IPIsLoopback(const IPAddress& ip) { | |
295 switch (ip.family()) { | |
296 case AF_INET: { | |
297 return (ip.v4AddressAsHostOrderInteger() >> 24) == 127; | |
298 } | |
299 case AF_INET6: { | |
300 return ip == IPAddress(in6addr_loopback); | |
301 } | |
302 } | |
303 return false; | |
304 } | |
305 | |
306 bool IPIsPrivate(const IPAddress& ip) { | |
307 switch (ip.family()) { | |
308 case AF_INET: { | |
309 return IsPrivateV4(ip.v4AddressAsHostOrderInteger()); | |
310 } | |
311 case AF_INET6: { | |
312 return IPIsLinkLocal(ip) || IPIsLoopback(ip); | |
313 } | |
314 } | |
315 return false; | |
316 } | |
317 | |
318 bool IPIsUnspec(const IPAddress& ip) { | |
319 return ip.family() == AF_UNSPEC; | |
320 } | |
321 | |
322 size_t HashIP(const IPAddress& ip) { | |
323 switch (ip.family()) { | |
324 case AF_INET: { | |
325 return ip.ipv4_address().s_addr; | |
326 } | |
327 case AF_INET6: { | |
328 in6_addr v6addr = ip.ipv6_address(); | |
329 const uint32_t* v6_as_ints = | |
330 reinterpret_cast<const uint32_t*>(&v6addr.s6_addr); | |
331 return v6_as_ints[0] ^ v6_as_ints[1] ^ v6_as_ints[2] ^ v6_as_ints[3]; | |
332 } | |
333 } | |
334 return 0; | |
335 } | |
336 | |
337 IPAddress TruncateIP(const IPAddress& ip, int length) { | |
338 if (length < 0) { | |
339 return IPAddress(); | |
340 } | |
341 if (ip.family() == AF_INET) { | |
342 if (length > 31) { | |
343 return ip; | |
344 } | |
345 if (length == 0) { | |
346 return IPAddress(INADDR_ANY); | |
347 } | |
348 int mask = (0xFFFFFFFF << (32 - length)); | |
349 uint32_t host_order_ip = NetworkToHost32(ip.ipv4_address().s_addr); | |
350 in_addr masked; | |
351 masked.s_addr = HostToNetwork32(host_order_ip & mask); | |
352 return IPAddress(masked); | |
353 } else if (ip.family() == AF_INET6) { | |
354 if (length > 127) { | |
355 return ip; | |
356 } | |
357 if (length == 0) { | |
358 return IPAddress(in6addr_any); | |
359 } | |
360 in6_addr v6addr = ip.ipv6_address(); | |
361 int position = length / 32; | |
362 int inner_length = 32 - (length - (position * 32)); | |
363 // Note: 64bit mask constant needed to allow possible 32-bit left shift. | |
364 uint32_t inner_mask = 0xFFFFFFFFLL << inner_length; | |
365 uint32_t* v6_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr); | |
366 for (int i = 0; i < 4; ++i) { | |
367 if (i == position) { | |
368 uint32_t host_order_inner = NetworkToHost32(v6_as_ints[i]); | |
369 v6_as_ints[i] = HostToNetwork32(host_order_inner & inner_mask); | |
370 } else if (i > position) { | |
371 v6_as_ints[i] = 0; | |
372 } | |
373 } | |
374 return IPAddress(v6addr); | |
375 } | |
376 return IPAddress(); | |
377 } | |
378 | |
379 int CountIPMaskBits(IPAddress mask) { | |
380 uint32_t word_to_count = 0; | |
381 int bits = 0; | |
382 switch (mask.family()) { | |
383 case AF_INET: { | |
384 word_to_count = NetworkToHost32(mask.ipv4_address().s_addr); | |
385 break; | |
386 } | |
387 case AF_INET6: { | |
388 in6_addr v6addr = mask.ipv6_address(); | |
389 const uint32_t* v6_as_ints = | |
390 reinterpret_cast<const uint32_t*>(&v6addr.s6_addr); | |
391 int i = 0; | |
392 for (; i < 4; ++i) { | |
393 if (v6_as_ints[i] != 0xFFFFFFFF) { | |
394 break; | |
395 } | |
396 } | |
397 if (i < 4) { | |
398 word_to_count = NetworkToHost32(v6_as_ints[i]); | |
399 } | |
400 bits = (i * 32); | |
401 break; | |
402 } | |
403 default: { | |
404 return 0; | |
405 } | |
406 } | |
407 if (word_to_count == 0) { | |
408 return bits; | |
409 } | |
410 | |
411 // Public domain bit-twiddling hack from: | |
412 // http://graphics.stanford.edu/~seander/bithacks.html | |
413 // Counts the trailing 0s in the word. | |
414 unsigned int zeroes = 32; | |
415 // This could also be written word_to_count &= -word_to_count, but | |
416 // MSVC emits warning C4146 when negating an unsigned number. | |
417 word_to_count &= ~word_to_count + 1; // Isolate lowest set bit. | |
418 if (word_to_count) zeroes--; | |
419 if (word_to_count & 0x0000FFFF) zeroes -= 16; | |
420 if (word_to_count & 0x00FF00FF) zeroes -= 8; | |
421 if (word_to_count & 0x0F0F0F0F) zeroes -= 4; | |
422 if (word_to_count & 0x33333333) zeroes -= 2; | |
423 if (word_to_count & 0x55555555) zeroes -= 1; | |
424 | |
425 return bits + (32 - zeroes); | |
426 } | |
427 | |
428 bool IPIsHelper(const IPAddress& ip, const in6_addr& tomatch, int length) { | |
429 // Helper method for checking IP prefix matches (but only on whole byte | |
430 // lengths). Length is in bits. | |
431 in6_addr addr = ip.ipv6_address(); | |
432 return ::memcmp(&addr, &tomatch, (length >> 3)) == 0; | |
433 } | |
434 | |
435 bool IPIs6Bone(const IPAddress& ip) { | |
436 return IPIsHelper(ip, k6BonePrefix, 16); | |
437 } | |
438 | |
439 bool IPIs6To4(const IPAddress& ip) { | |
440 return IPIsHelper(ip, k6To4Prefix, 16); | |
441 } | |
442 | |
443 bool IPIsLinkLocal(const IPAddress& ip) { | |
444 // Can't use the helper because the prefix is 10 bits. | |
445 in6_addr addr = ip.ipv6_address(); | |
446 return addr.s6_addr[0] == 0xFE && addr.s6_addr[1] == 0x80; | |
447 } | |
448 | |
449 // According to http://www.ietf.org/rfc/rfc2373.txt, Appendix A, page 19. An | |
450 // address which contains MAC will have its 11th and 12th bytes as FF:FE as well | |
451 // as the U/L bit as 1. | |
452 bool IPIsMacBased(const IPAddress& ip) { | |
453 in6_addr addr = ip.ipv6_address(); | |
454 return ((addr.s6_addr[8] & 0x02) && addr.s6_addr[11] == 0xFF && | |
455 addr.s6_addr[12] == 0xFE); | |
456 } | |
457 | |
458 bool IPIsSiteLocal(const IPAddress& ip) { | |
459 // Can't use the helper because the prefix is 10 bits. | |
460 in6_addr addr = ip.ipv6_address(); | |
461 return addr.s6_addr[0] == 0xFE && (addr.s6_addr[1] & 0xC0) == 0xC0; | |
462 } | |
463 | |
464 bool IPIsULA(const IPAddress& ip) { | |
465 // Can't use the helper because the prefix is 7 bits. | |
466 in6_addr addr = ip.ipv6_address(); | |
467 return (addr.s6_addr[0] & 0xFE) == 0xFC; | |
468 } | |
469 | |
470 bool IPIsTeredo(const IPAddress& ip) { | |
471 return IPIsHelper(ip, kTeredoPrefix, 32); | |
472 } | |
473 | |
474 bool IPIsV4Compatibility(const IPAddress& ip) { | |
475 return IPIsHelper(ip, kV4CompatibilityPrefix, 96); | |
476 } | |
477 | |
478 bool IPIsV4Mapped(const IPAddress& ip) { | |
479 return IPIsHelper(ip, kV4MappedPrefix, 96); | |
480 } | |
481 | |
482 int IPAddressPrecedence(const IPAddress& ip) { | |
483 // Precedence values from RFC 3484-bis. Prefers native v4 over 6to4/Teredo. | |
484 if (ip.family() == AF_INET) { | |
485 return 30; | |
486 } else if (ip.family() == AF_INET6) { | |
487 if (IPIsLoopback(ip)) { | |
488 return 60; | |
489 } else if (IPIsULA(ip)) { | |
490 return 50; | |
491 } else if (IPIsV4Mapped(ip)) { | |
492 return 30; | |
493 } else if (IPIs6To4(ip)) { | |
494 return 20; | |
495 } else if (IPIsTeredo(ip)) { | |
496 return 10; | |
497 } else if (IPIsV4Compatibility(ip) || IPIsSiteLocal(ip) || IPIs6Bone(ip)) { | |
498 return 1; | |
499 } else { | |
500 // A 'normal' IPv6 address. | |
501 return 40; | |
502 } | |
503 } | |
504 return 0; | |
505 } | |
506 | |
507 IPAddress GetLoopbackIP(int family) { | |
508 if (family == AF_INET) { | |
509 return rtc::IPAddress(INADDR_LOOPBACK); | |
510 } | |
511 if (family == AF_INET6) { | |
512 return rtc::IPAddress(in6addr_loopback); | |
513 } | |
514 return rtc::IPAddress(); | |
515 } | |
516 | |
517 IPAddress GetAnyIP(int family) { | |
518 if (family == AF_INET) { | |
519 return rtc::IPAddress(INADDR_ANY); | |
520 } | |
521 if (family == AF_INET6) { | |
522 return rtc::IPAddress(in6addr_any); | |
523 } | |
524 return rtc::IPAddress(); | |
525 } | |
526 | |
527 } // namespace rtc | |
OLD | NEW |