OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/net_util.h" | 5 #include "net/base/port_util.h" |
6 | 6 |
7 #include <errno.h> | |
8 #include <string.h> | |
9 | |
10 #include <algorithm> | |
11 #include <iterator> | 7 #include <iterator> |
mmenke
2015/07/16 15:07:57
Do we ever explicitly include iterator? Worth not
eroman
2015/07/21 01:04:04
Removed.
(I had pruned the headers manually, and
| |
12 #include <limits> | |
13 #include <set> | 8 #include <set> |
14 | 9 |
15 #include "build/build_config.h" | |
16 | |
17 #if defined(OS_WIN) | |
18 #include <windows.h> | |
19 #include <iphlpapi.h> | |
20 #include <winsock2.h> | |
21 #include <ws2bth.h> | |
22 #pragma comment(lib, "iphlpapi.lib") | |
23 #elif defined(OS_POSIX) | |
24 #include <fcntl.h> | |
25 #include <netdb.h> | |
26 #include <netinet/in.h> | |
27 #include <unistd.h> | |
28 #if !defined(OS_NACL) | |
29 #include <net/if.h> | |
30 #if !defined(OS_ANDROID) | |
31 #include <ifaddrs.h> | |
32 #endif // !defined(OS_NACL) | |
33 #endif // !defined(OS_ANDROID) | |
34 #endif // defined(OS_POSIX) | |
35 | |
36 #include "base/basictypes.h" | |
37 #include "base/json/string_escape.h" | |
38 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
39 #include "base/logging.h" | 11 #include "base/logging.h" |
40 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
41 #include "base/strings/string_piece.h" | |
42 #include "base/strings/string_split.h" | |
43 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
44 #include "base/strings/stringprintf.h" | |
45 #include "base/strings/utf_string_conversions.h" | |
46 #include "base/sys_byteorder.h" | |
47 #include "base/values.h" | |
48 #include "net/base/address_list.h" | |
49 #include "net/base/dns_util.h" | |
50 #include "net/base/ip_address_number.h" | |
51 #include "net/base/net_module.h" | |
52 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | |
53 #include "net/grit/net_resources.h" | |
54 #include "net/http/http_content_disposition.h" | |
55 #include "url/gurl.h" | |
56 #include "url/third_party/mozilla/url_parse.h" | |
57 #include "url/url_canon.h" | |
58 #include "url/url_canon_ip.h" | |
59 #include "url/url_constants.h" | 14 #include "url/url_constants.h" |
60 | 15 |
61 #if defined(OS_ANDROID) | |
62 #include "net/android/network_library.h" | |
63 #endif | |
64 #if defined(OS_WIN) | |
65 #include "net/base/winsock_init.h" | |
66 #endif | |
67 | |
68 namespace net { | 16 namespace net { |
69 | 17 |
70 namespace { | 18 namespace { |
71 | 19 |
72 // The general list of blocked ports. Will be blocked unless a specific | 20 // The general list of blocked ports. Will be blocked unless a specific |
73 // protocol overrides it. (Ex: ftp can use ports 20 and 21) | 21 // protocol overrides it. (Ex: ftp can use ports 20 and 21) |
74 static const int kRestrictedPorts[] = { | 22 static const int kRestrictedPorts[] = { |
mmenke
2015/07/16 15:07:57
Optional: Could remove this static and the next w
eroman
2015/07/21 01:04:04
Done.
| |
75 1, // tcpmux | 23 1, // tcpmux |
76 7, // echo | 24 7, // echo |
77 9, // discard | 25 9, // discard |
78 11, // systat | 26 11, // systat |
79 13, // daytime | 27 13, // daytime |
80 15, // netstat | 28 15, // netstat |
81 17, // qotd | 29 17, // qotd |
82 19, // chargen | 30 19, // chargen |
83 20, // ftp data | 31 20, // ftp data |
84 21, // ftp access | 32 21, // ftp access |
85 22, // ssh | 33 22, // ssh |
86 23, // telnet | 34 23, // telnet |
87 25, // smtp | 35 25, // smtp |
88 37, // time | 36 37, // time |
89 42, // name | 37 42, // name |
90 43, // nicname | 38 43, // nicname |
91 53, // domain | 39 53, // domain |
92 77, // priv-rjs | 40 77, // priv-rjs |
93 79, // finger | 41 79, // finger |
94 87, // ttylink | 42 87, // ttylink |
95 95, // supdup | 43 95, // supdup |
96 101, // hostriame | 44 101, // hostriame |
97 102, // iso-tsap | 45 102, // iso-tsap |
98 103, // gppitnp | 46 103, // gppitnp |
99 104, // acr-nema | 47 104, // acr-nema |
100 109, // pop2 | 48 109, // pop2 |
101 110, // pop3 | 49 110, // pop3 |
102 111, // sunrpc | 50 111, // sunrpc |
103 113, // auth | 51 113, // auth |
104 115, // sftp | 52 115, // sftp |
105 117, // uucp-path | 53 117, // uucp-path |
106 119, // nntp | 54 119, // nntp |
107 123, // NTP | 55 123, // NTP |
108 135, // loc-srv /epmap | 56 135, // loc-srv /epmap |
109 139, // netbios | 57 139, // netbios |
110 143, // imap2 | 58 143, // imap2 |
111 179, // BGP | 59 179, // BGP |
112 389, // ldap | 60 389, // ldap |
113 465, // smtp+ssl | 61 465, // smtp+ssl |
114 512, // print / exec | 62 512, // print / exec |
115 513, // login | 63 513, // login |
116 514, // shell | 64 514, // shell |
117 515, // printer | 65 515, // printer |
118 526, // tempo | 66 526, // tempo |
119 530, // courier | 67 530, // courier |
120 531, // chat | 68 531, // chat |
121 532, // netnews | 69 532, // netnews |
122 540, // uucp | 70 540, // uucp |
123 556, // remotefs | 71 556, // remotefs |
124 563, // nntp+ssl | 72 563, // nntp+ssl |
125 587, // stmp? | 73 587, // stmp? |
126 601, // ?? | 74 601, // ?? |
127 636, // ldap+ssl | 75 636, // ldap+ssl |
128 993, // ldap+ssl | 76 993, // ldap+ssl |
129 995, // pop3+ssl | 77 995, // pop3+ssl |
130 2049, // nfs | 78 2049, // nfs |
131 3659, // apple-sasl / PasswordServer | 79 3659, // apple-sasl / PasswordServer |
132 4045, // lockd | 80 4045, // lockd |
133 6000, // X11 | 81 6000, // X11 |
134 6665, // Alternate IRC [Apple addition] | 82 6665, // Alternate IRC [Apple addition] |
135 6666, // Alternate IRC [Apple addition] | 83 6666, // Alternate IRC [Apple addition] |
136 6667, // Standard IRC [Apple addition] | 84 6667, // Standard IRC [Apple addition] |
137 6668, // Alternate IRC [Apple addition] | 85 6668, // Alternate IRC [Apple addition] |
138 6669, // Alternate IRC [Apple addition] | 86 6669, // Alternate IRC [Apple addition] |
139 0xFFFF, // Used to block all invalid port numbers (see | 87 0xFFFF, // Used to block all invalid port numbers (see |
140 // third_party/WebKit/Source/platform/weborigin/KURL.cpp, | 88 // third_party/WebKit/Source/platform/weborigin/KURL.cpp, |
141 // KURL::port()) | 89 // KURL::port()) |
142 }; | 90 }; |
143 | 91 |
144 // FTP overrides the following restricted ports. | 92 // FTP overrides the following restricted ports. |
145 static const int kAllowedFtpPorts[] = { | 93 static const int kAllowedFtpPorts[] = { |
146 21, // ftp data | 94 21, // ftp data |
147 22, // ssh | 95 22, // ssh |
148 }; | 96 }; |
149 | 97 |
150 std::string NormalizeHostname(const std::string& host) { | |
151 std::string result = base::StringToLowerASCII(host); | |
152 if (!result.empty() && *result.rbegin() == '.') | |
153 result.resize(result.size() - 1); | |
154 return result; | |
155 } | |
156 | |
157 bool IsNormalizedLocalhostTLD(const std::string& host) { | |
158 return base::EndsWith(host, ".localhost", true); | |
159 } | |
160 | |
161 // |host| should be normalized. | |
162 bool IsLocalHostname(const std::string& host) { | |
163 return host == "localhost" || host == "localhost.localdomain" || | |
164 IsNormalizedLocalhostTLD(host); | |
165 } | |
166 | |
167 // |host| should be normalized. | |
168 bool IsLocal6Hostname(const std::string& host) { | |
169 return host == "localhost6" || host == "localhost6.localdomain6"; | |
170 } | |
171 | |
172 } // namespace | 98 } // namespace |
173 | 99 |
174 static base::LazyInstance<std::multiset<int> >::Leaky | 100 static base::LazyInstance<std::multiset<int>>::Leaky |
175 g_explicitly_allowed_ports = LAZY_INSTANCE_INITIALIZER; | 101 g_explicitly_allowed_ports = LAZY_INSTANCE_INITIALIZER; |
mmenke
2015/07/16 15:07:57
Optional: Know it was like this before...maybe mo
eroman
2015/07/21 01:04:04
Done.
| |
176 | 102 |
177 std::string CanonicalizeHost(const std::string& host, | |
178 url::CanonHostInfo* host_info) { | |
179 // Try to canonicalize the host. | |
180 const url::Component raw_host_component(0, static_cast<int>(host.length())); | |
181 std::string canon_host; | |
182 url::StdStringCanonOutput canon_host_output(&canon_host); | |
183 url::CanonicalizeHostVerbose(host.c_str(), raw_host_component, | |
184 &canon_host_output, host_info); | |
185 | |
186 if (host_info->out_host.is_nonempty() && | |
187 host_info->family != url::CanonHostInfo::BROKEN) { | |
188 // Success! Assert that there's no extra garbage. | |
189 canon_host_output.Complete(); | |
190 DCHECK_EQ(host_info->out_host.len, static_cast<int>(canon_host.length())); | |
191 } else { | |
192 // Empty host, or canonicalization failed. We'll return empty. | |
193 canon_host.clear(); | |
194 } | |
195 | |
196 return canon_host; | |
197 } | |
198 | |
199 std::string GetDirectoryListingHeader(const base::string16& title) { | |
200 static const base::StringPiece header( | |
201 NetModule::GetResource(IDR_DIR_HEADER_HTML)); | |
202 // This can be null in unit tests. | |
203 DLOG_IF(WARNING, header.empty()) << | |
204 "Missing resource: directory listing header"; | |
205 | |
206 std::string result; | |
207 if (!header.empty()) | |
208 result.assign(header.data(), header.size()); | |
209 | |
210 result.append("<script>start("); | |
211 base::EscapeJSONString(title, true, &result); | |
212 result.append(");</script>\n"); | |
213 | |
214 return result; | |
215 } | |
216 | |
217 inline bool IsHostCharAlphanumeric(char c) { | |
218 // We can just check lowercase because uppercase characters have already been | |
219 // normalized. | |
220 return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')); | |
221 } | |
222 | |
223 bool IsCanonicalizedHostCompliant(const std::string& host) { | |
224 if (host.empty()) | |
225 return false; | |
226 | |
227 bool in_component = false; | |
228 bool most_recent_component_started_alphanumeric = false; | |
229 | |
230 for (std::string::const_iterator i(host.begin()); i != host.end(); ++i) { | |
231 const char c = *i; | |
232 if (!in_component) { | |
233 most_recent_component_started_alphanumeric = IsHostCharAlphanumeric(c); | |
234 if (!most_recent_component_started_alphanumeric && (c != '-') && | |
235 (c != '_')) { | |
236 return false; | |
237 } | |
238 in_component = true; | |
239 } else if (c == '.') { | |
240 in_component = false; | |
241 } else if (!IsHostCharAlphanumeric(c) && (c != '-') && (c != '_')) { | |
242 return false; | |
243 } | |
244 } | |
245 | |
246 return most_recent_component_started_alphanumeric; | |
247 } | |
248 | |
249 base::string16 StripWWW(const base::string16& text) { | |
250 const base::string16 www(base::ASCIIToUTF16("www.")); | |
251 return base::StartsWith(text, www, base::CompareCase::SENSITIVE) | |
252 ? text.substr(www.length()) : text; | |
253 } | |
254 | |
255 base::string16 StripWWWFromHost(const GURL& url) { | |
256 DCHECK(url.is_valid()); | |
257 return StripWWW(base::ASCIIToUTF16(url.host())); | |
258 } | |
259 | |
260 bool IsPortValid(int port) { | 103 bool IsPortValid(int port) { |
261 return port >= 0 && port <= std::numeric_limits<uint16_t>::max(); | 104 return port >= 0 && port <= std::numeric_limits<uint16_t>::max(); |
262 } | 105 } |
263 | 106 |
264 bool IsWellKnownPort(int port) { | 107 bool IsWellKnownPort(int port) { |
265 return port >= 0 && port < 1024; | 108 return port >= 0 && port < 1024; |
266 } | 109 } |
267 | 110 |
268 bool IsPortAllowedForScheme(int port, const std::string& url_scheme) { | 111 bool IsPortAllowedForScheme(int port, const std::string& url_scheme) { |
269 // Reject invalid ports. | 112 // Reject invalid ports. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 | 177 |
335 ScopedPortException::~ScopedPortException() { | 178 ScopedPortException::~ScopedPortException() { |
336 std::multiset<int>::iterator it = | 179 std::multiset<int>::iterator it = |
337 g_explicitly_allowed_ports.Get().find(port_); | 180 g_explicitly_allowed_ports.Get().find(port_); |
338 if (it != g_explicitly_allowed_ports.Get().end()) | 181 if (it != g_explicitly_allowed_ports.Get().end()) |
339 g_explicitly_allowed_ports.Get().erase(it); | 182 g_explicitly_allowed_ports.Get().erase(it); |
340 else | 183 else |
341 NOTREACHED(); | 184 NOTREACHED(); |
342 } | 185 } |
343 | 186 |
344 int SetNonBlocking(int fd) { | |
345 #if defined(OS_WIN) | |
346 unsigned long no_block = 1; | |
347 return ioctlsocket(fd, FIONBIO, &no_block); | |
348 #elif defined(OS_POSIX) | |
349 int flags = fcntl(fd, F_GETFL, 0); | |
350 if (-1 == flags) | |
351 return flags; | |
352 return fcntl(fd, F_SETFL, flags | O_NONBLOCK); | |
353 #endif | |
354 } | |
355 | |
356 bool ParseHostAndPort(std::string::const_iterator host_and_port_begin, | |
357 std::string::const_iterator host_and_port_end, | |
358 std::string* host, | |
359 int* port) { | |
360 if (host_and_port_begin >= host_and_port_end) | |
361 return false; | |
362 | |
363 // When using url, we use char*. | |
364 const char* auth_begin = &(*host_and_port_begin); | |
365 int auth_len = host_and_port_end - host_and_port_begin; | |
366 | |
367 url::Component auth_component(0, auth_len); | |
368 url::Component username_component; | |
369 url::Component password_component; | |
370 url::Component hostname_component; | |
371 url::Component port_component; | |
372 | |
373 url::ParseAuthority(auth_begin, auth_component, &username_component, | |
374 &password_component, &hostname_component, &port_component); | |
375 | |
376 // There shouldn't be a username/password. | |
377 if (username_component.is_valid() || password_component.is_valid()) | |
378 return false; | |
379 | |
380 if (!hostname_component.is_nonempty()) | |
381 return false; // Failed parsing. | |
382 | |
383 int parsed_port_number = -1; | |
384 if (port_component.is_nonempty()) { | |
385 parsed_port_number = url::ParsePort(auth_begin, port_component); | |
386 | |
387 // If parsing failed, port_number will be either PORT_INVALID or | |
388 // PORT_UNSPECIFIED, both of which are negative. | |
389 if (parsed_port_number < 0) | |
390 return false; // Failed parsing the port number. | |
391 } | |
392 | |
393 if (port_component.len == 0) | |
394 return false; // Reject inputs like "foo:" | |
395 | |
396 unsigned char tmp_ipv6_addr[16]; | |
397 | |
398 // If the hostname starts with a bracket, it is either an IPv6 literal or | |
399 // invalid. If it is an IPv6 literal then strip the brackets. | |
400 if (hostname_component.len > 0 && | |
401 auth_begin[hostname_component.begin] == '[') { | |
402 if (auth_begin[hostname_component.end() - 1] == ']' && | |
403 url::IPv6AddressToNumber( | |
404 auth_begin, hostname_component, tmp_ipv6_addr)) { | |
405 // Strip the brackets. | |
406 hostname_component.begin++; | |
407 hostname_component.len -= 2; | |
408 } else { | |
409 return false; | |
410 } | |
411 } | |
412 | |
413 // Pass results back to caller. | |
414 host->assign(auth_begin + hostname_component.begin, hostname_component.len); | |
415 *port = parsed_port_number; | |
416 | |
417 return true; // Success. | |
418 } | |
419 | |
420 bool ParseHostAndPort(const std::string& host_and_port, | |
421 std::string* host, | |
422 int* port) { | |
423 return ParseHostAndPort( | |
424 host_and_port.begin(), host_and_port.end(), host, port); | |
425 } | |
426 | |
427 std::string GetHostAndPort(const GURL& url) { | |
428 // For IPv6 literals, GURL::host() already includes the brackets so it is | |
429 // safe to just append a colon. | |
430 return base::StringPrintf("%s:%d", url.host().c_str(), | |
431 url.EffectiveIntPort()); | |
432 } | |
433 | |
434 std::string GetHostAndOptionalPort(const GURL& url) { | |
435 // For IPv6 literals, GURL::host() already includes the brackets | |
436 // so it is safe to just append a colon. | |
437 if (url.has_port()) | |
438 return base::StringPrintf("%s:%s", url.host().c_str(), url.port().c_str()); | |
439 return url.host(); | |
440 } | |
441 | |
442 bool IsHostnameNonUnique(const std::string& hostname) { | |
443 // CanonicalizeHost requires surrounding brackets to parse an IPv6 address. | |
444 const std::string host_or_ip = hostname.find(':') != std::string::npos ? | |
445 "[" + hostname + "]" : hostname; | |
446 url::CanonHostInfo host_info; | |
447 std::string canonical_name = CanonicalizeHost(host_or_ip, &host_info); | |
448 | |
449 // If canonicalization fails, then the input is truly malformed. However, | |
450 // to avoid mis-reporting bad inputs as "non-unique", treat them as unique. | |
451 if (canonical_name.empty()) | |
452 return false; | |
453 | |
454 // If |hostname| is an IP address, check to see if it's in an IANA-reserved | |
455 // range. | |
456 if (host_info.IsIPAddress()) { | |
457 IPAddressNumber host_addr; | |
458 if (!ParseIPLiteralToNumber(hostname.substr(host_info.out_host.begin, | |
459 host_info.out_host.len), | |
460 &host_addr)) { | |
461 return false; | |
462 } | |
463 switch (host_info.family) { | |
464 case url::CanonHostInfo::IPV4: | |
465 case url::CanonHostInfo::IPV6: | |
466 return IsIPAddressReserved(host_addr); | |
467 case url::CanonHostInfo::NEUTRAL: | |
468 case url::CanonHostInfo::BROKEN: | |
469 return false; | |
470 } | |
471 } | |
472 | |
473 // Check for a registry controlled portion of |hostname|, ignoring private | |
474 // registries, as they already chain to ICANN-administered registries, | |
475 // and explicitly ignoring unknown registries. | |
476 // | |
477 // Note: This means that as new gTLDs are introduced on the Internet, they | |
478 // will be treated as non-unique until the registry controlled domain list | |
479 // is updated. However, because gTLDs are expected to provide significant | |
480 // advance notice to deprecate older versions of this code, this an | |
481 // acceptable tradeoff. | |
482 return 0 == registry_controlled_domains::GetRegistryLength( | |
483 canonical_name, | |
484 registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, | |
485 registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); | |
486 } | |
487 | |
488 SockaddrStorage::SockaddrStorage(const SockaddrStorage& other) | |
489 : addr_len(other.addr_len), | |
490 addr(reinterpret_cast<struct sockaddr*>(&addr_storage)) { | |
491 memcpy(addr, other.addr, addr_len); | |
492 } | |
493 | |
494 void SockaddrStorage::operator=(const SockaddrStorage& other) { | |
495 addr_len = other.addr_len; | |
496 // addr is already set to &this->addr_storage by default ctor. | |
497 memcpy(addr, other.addr, addr_len); | |
498 } | |
499 | |
500 // Extracts the address and port portions of a sockaddr. | |
501 bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr, | |
502 socklen_t sock_addr_len, | |
503 const uint8_t** address, | |
504 size_t* address_len, | |
505 uint16_t* port) { | |
506 if (sock_addr->sa_family == AF_INET) { | |
507 if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in))) | |
508 return false; | |
509 const struct sockaddr_in* addr = | |
510 reinterpret_cast<const struct sockaddr_in*>(sock_addr); | |
511 *address = reinterpret_cast<const uint8_t*>(&addr->sin_addr); | |
512 *address_len = kIPv4AddressSize; | |
513 if (port) | |
514 *port = base::NetToHost16(addr->sin_port); | |
515 return true; | |
516 } | |
517 | |
518 if (sock_addr->sa_family == AF_INET6) { | |
519 if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in6))) | |
520 return false; | |
521 const struct sockaddr_in6* addr = | |
522 reinterpret_cast<const struct sockaddr_in6*>(sock_addr); | |
523 *address = reinterpret_cast<const uint8_t*>(&addr->sin6_addr); | |
524 *address_len = kIPv6AddressSize; | |
525 if (port) | |
526 *port = base::NetToHost16(addr->sin6_port); | |
527 return true; | |
528 } | |
529 | |
530 #if defined(OS_WIN) | |
531 if (sock_addr->sa_family == AF_BTH) { | |
532 if (sock_addr_len < static_cast<socklen_t>(sizeof(SOCKADDR_BTH))) | |
533 return false; | |
534 const SOCKADDR_BTH* addr = | |
535 reinterpret_cast<const SOCKADDR_BTH*>(sock_addr); | |
536 *address = reinterpret_cast<const uint8_t*>(&addr->btAddr); | |
537 *address_len = kBluetoothAddressSize; | |
538 if (port) | |
539 *port = static_cast<uint16_t>(addr->port); | |
540 return true; | |
541 } | |
542 #endif | |
543 | |
544 return false; // Unrecognized |sa_family|. | |
545 } | |
546 | |
547 std::string NetAddressToString(const struct sockaddr* sa, | |
548 socklen_t sock_addr_len) { | |
549 const uint8_t* address; | |
550 size_t address_len; | |
551 if (!GetIPAddressFromSockAddr(sa, sock_addr_len, &address, | |
552 &address_len, NULL)) { | |
553 NOTREACHED(); | |
554 return std::string(); | |
555 } | |
556 return IPAddressToString(address, address_len); | |
557 } | |
558 | |
559 std::string NetAddressToStringWithPort(const struct sockaddr* sa, | |
560 socklen_t sock_addr_len) { | |
561 const uint8_t* address; | |
562 size_t address_len; | |
563 uint16_t port; | |
564 if (!GetIPAddressFromSockAddr(sa, sock_addr_len, &address, | |
565 &address_len, &port)) { | |
566 NOTREACHED(); | |
567 return std::string(); | |
568 } | |
569 return IPAddressToStringWithPort(address, address_len, port); | |
570 } | |
571 | |
572 std::string GetHostName() { | |
573 #if defined(OS_NACL) | |
574 NOTIMPLEMENTED(); | |
575 return std::string(); | |
576 #else // defined(OS_NACL) | |
577 #if defined(OS_WIN) | |
578 EnsureWinsockInit(); | |
579 #endif | |
580 | |
581 // Host names are limited to 255 bytes. | |
582 char buffer[256]; | |
583 int result = gethostname(buffer, sizeof(buffer)); | |
584 if (result != 0) { | |
585 DVLOG(1) << "gethostname() failed with " << result; | |
586 buffer[0] = '\0'; | |
587 } | |
588 return std::string(buffer); | |
589 #endif // !defined(OS_NACL) | |
590 } | |
591 | |
592 void GetIdentityFromURL(const GURL& url, | |
593 base::string16* username, | |
594 base::string16* password) { | |
595 UnescapeRule::Type flags = | |
596 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS; | |
597 *username = UnescapeAndDecodeUTF8URLComponent(url.username(), flags); | |
598 *password = UnescapeAndDecodeUTF8URLComponent(url.password(), flags); | |
599 } | |
600 | |
601 std::string GetHostOrSpecFromURL(const GURL& url) { | |
602 return url.has_host() ? TrimEndingDot(url.host()) : url.spec(); | |
603 } | |
604 | |
605 bool CanStripTrailingSlash(const GURL& url) { | |
606 // Omit the path only for standard, non-file URLs with nothing but "/" after | |
607 // the hostname. | |
608 return url.IsStandard() && !url.SchemeIsFile() && | |
609 !url.SchemeIsFileSystem() && !url.has_query() && !url.has_ref() | |
610 && url.path() == "/"; | |
611 } | |
612 | |
613 GURL SimplifyUrlForRequest(const GURL& url) { | |
614 DCHECK(url.is_valid()); | |
615 GURL::Replacements replacements; | |
616 replacements.ClearUsername(); | |
617 replacements.ClearPassword(); | |
618 replacements.ClearRef(); | |
619 return url.ReplaceComponents(replacements); | |
620 } | |
621 | |
622 bool HaveOnlyLoopbackAddresses() { | |
623 #if defined(OS_ANDROID) | |
624 return android::HaveOnlyLoopbackAddresses(); | |
625 #elif defined(OS_NACL) | |
626 NOTIMPLEMENTED(); | |
627 return false; | |
628 #elif defined(OS_POSIX) | |
629 struct ifaddrs* interface_addr = NULL; | |
630 int rv = getifaddrs(&interface_addr); | |
631 if (rv != 0) { | |
632 DVLOG(1) << "getifaddrs() failed with errno = " << errno; | |
633 return false; | |
634 } | |
635 | |
636 bool result = true; | |
637 for (struct ifaddrs* interface = interface_addr; | |
638 interface != NULL; | |
639 interface = interface->ifa_next) { | |
640 if (!(IFF_UP & interface->ifa_flags)) | |
641 continue; | |
642 if (IFF_LOOPBACK & interface->ifa_flags) | |
643 continue; | |
644 const struct sockaddr* addr = interface->ifa_addr; | |
645 if (!addr) | |
646 continue; | |
647 if (addr->sa_family == AF_INET6) { | |
648 // Safe cast since this is AF_INET6. | |
649 const struct sockaddr_in6* addr_in6 = | |
650 reinterpret_cast<const struct sockaddr_in6*>(addr); | |
651 const struct in6_addr* sin6_addr = &addr_in6->sin6_addr; | |
652 if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) | |
653 continue; | |
654 } | |
655 if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET) | |
656 continue; | |
657 | |
658 result = false; | |
659 break; | |
660 } | |
661 freeifaddrs(interface_addr); | |
662 return result; | |
663 #elif defined(OS_WIN) | |
664 // TODO(wtc): implement with the GetAdaptersAddresses function. | |
665 NOTIMPLEMENTED(); | |
666 return false; | |
667 #else | |
668 NOTIMPLEMENTED(); | |
669 return false; | |
670 #endif // defined(various platforms) | |
671 } | |
672 | |
673 AddressFamily GetAddressFamily(const IPAddressNumber& address) { | |
674 switch (address.size()) { | |
675 case kIPv4AddressSize: | |
676 return ADDRESS_FAMILY_IPV4; | |
677 case kIPv6AddressSize: | |
678 return ADDRESS_FAMILY_IPV6; | |
679 default: | |
680 return ADDRESS_FAMILY_UNSPECIFIED; | |
681 } | |
682 } | |
683 | |
684 int ConvertAddressFamily(AddressFamily address_family) { | |
685 switch (address_family) { | |
686 case ADDRESS_FAMILY_UNSPECIFIED: | |
687 return AF_UNSPEC; | |
688 case ADDRESS_FAMILY_IPV4: | |
689 return AF_INET; | |
690 case ADDRESS_FAMILY_IPV6: | |
691 return AF_INET6; | |
692 } | |
693 NOTREACHED(); | |
694 return AF_UNSPEC; | |
695 } | |
696 | |
697 const uint16_t* GetPortFieldFromSockaddr(const struct sockaddr* address, | |
698 socklen_t address_len) { | |
699 if (address->sa_family == AF_INET) { | |
700 DCHECK_LE(sizeof(sockaddr_in), static_cast<size_t>(address_len)); | |
701 const struct sockaddr_in* sockaddr = | |
702 reinterpret_cast<const struct sockaddr_in*>(address); | |
703 return &sockaddr->sin_port; | |
704 } else if (address->sa_family == AF_INET6) { | |
705 DCHECK_LE(sizeof(sockaddr_in6), static_cast<size_t>(address_len)); | |
706 const struct sockaddr_in6* sockaddr = | |
707 reinterpret_cast<const struct sockaddr_in6*>(address); | |
708 return &sockaddr->sin6_port; | |
709 } else { | |
710 NOTREACHED(); | |
711 return NULL; | |
712 } | |
713 } | |
714 | |
715 int GetPortFromSockaddr(const struct sockaddr* address, socklen_t address_len) { | |
716 const uint16_t* port_field = GetPortFieldFromSockaddr(address, address_len); | |
717 if (!port_field) | |
718 return -1; | |
719 return base::NetToHost16(*port_field); | |
720 } | |
721 | |
722 bool ResolveLocalHostname(const std::string& host, | |
723 uint16_t port, | |
724 AddressList* address_list) { | |
725 static const unsigned char kLocalhostIPv4[] = {127, 0, 0, 1}; | |
726 static const unsigned char kLocalhostIPv6[] = { | |
727 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; | |
728 | |
729 std::string normalized_host = NormalizeHostname(host); | |
730 | |
731 address_list->clear(); | |
732 | |
733 bool is_local6 = IsLocal6Hostname(normalized_host); | |
734 if (!is_local6 && !IsLocalHostname(normalized_host)) | |
735 return false; | |
736 | |
737 address_list->push_back( | |
738 IPEndPoint(IPAddressNumber(kLocalhostIPv6, | |
739 kLocalhostIPv6 + arraysize(kLocalhostIPv6)), | |
740 port)); | |
741 if (!is_local6) { | |
742 address_list->push_back( | |
743 IPEndPoint(IPAddressNumber(kLocalhostIPv4, | |
744 kLocalhostIPv4 + arraysize(kLocalhostIPv4)), | |
745 port)); | |
746 } | |
747 | |
748 return true; | |
749 } | |
750 | |
751 bool IsLocalhost(const std::string& host) { | |
752 std::string normalized_host = NormalizeHostname(host); | |
753 if (IsLocalHostname(normalized_host) || IsLocal6Hostname(normalized_host)) | |
754 return true; | |
755 | |
756 IPAddressNumber ip_number; | |
757 if (ParseIPLiteralToNumber(host, &ip_number)) { | |
758 size_t size = ip_number.size(); | |
759 switch (size) { | |
760 case kIPv4AddressSize: { | |
761 IPAddressNumber localhost_prefix; | |
762 localhost_prefix.push_back(127); | |
763 for (int i = 0; i < 3; ++i) { | |
764 localhost_prefix.push_back(0); | |
765 } | |
766 return IPNumberMatchesPrefix(ip_number, localhost_prefix, 8); | |
767 } | |
768 | |
769 case kIPv6AddressSize: { | |
770 struct in6_addr sin6_addr; | |
771 memcpy(&sin6_addr, &ip_number[0], kIPv6AddressSize); | |
772 return !!IN6_IS_ADDR_LOOPBACK(&sin6_addr); | |
773 } | |
774 | |
775 default: | |
776 NOTREACHED(); | |
777 } | |
778 } | |
779 | |
780 return false; | |
781 } | |
782 | |
783 bool IsLocalhostTLD(const std::string& host) { | |
784 return IsNormalizedLocalhostTLD(NormalizeHostname(host)); | |
785 } | |
786 | |
787 bool HasGoogleHost(const GURL& url) { | |
788 static const char* kGoogleHostSuffixes[] = { | |
789 ".google.com", | |
790 ".youtube.com", | |
791 ".gmail.com", | |
792 ".doubleclick.net", | |
793 ".gstatic.com", | |
794 ".googlevideo.com", | |
795 ".googleusercontent.com", | |
796 ".googlesyndication.com", | |
797 ".google-analytics.com", | |
798 ".googleadservices.com", | |
799 ".googleapis.com", | |
800 ".ytimg.com", | |
801 }; | |
802 const std::string& host = url.host(); | |
803 for (const char* suffix : kGoogleHostSuffixes) { | |
804 if (base::EndsWith(host, suffix, false)) | |
805 return true; | |
806 } | |
807 return false; | |
808 } | |
809 | |
810 } // namespace net | 187 } // namespace net |
OLD | NEW |