// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/dns/dns_util.h" #include #include #include #include "base/metrics/field_trial.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "build/build_config.h" #if defined(OS_POSIX) #include #if !defined(OS_NACL) #include #if !defined(OS_ANDROID) #include #endif // !defined(OS_ANDROID) #endif // !defined(OS_NACL) #endif // defined(OS_POSIX) #if defined(OS_ANDROID) #include "net/android/network_library.h" #endif namespace net { // Based on DJB's public domain code. bool DNSDomainFromDot(const base::StringPiece& dotted, std::string* out) { const char* buf = dotted.data(); unsigned n = dotted.size(); char label[63]; size_t labellen = 0; /* <= sizeof label */ char name[255]; size_t namelen = 0; /* <= sizeof name */ char ch; for (;;) { if (!n) break; ch = *buf++; --n; if (ch == '.') { // Don't allow empty labels per http://crbug.com/456391. if (!labellen) return false; if (namelen + labellen + 1 > sizeof name) return false; name[namelen++] = static_cast(labellen); memcpy(name + namelen, label, labellen); namelen += labellen; labellen = 0; continue; } if (labellen >= sizeof label) return false; label[labellen++] = ch; } // Allow empty label at end of name to disable suffix search. if (labellen) { if (namelen + labellen + 1 > sizeof name) return false; name[namelen++] = static_cast(labellen); memcpy(name + namelen, label, labellen); namelen += labellen; labellen = 0; } if (namelen + 1 > sizeof name) return false; if (namelen == 0) // Empty names e.g. "", "." are not valid. return false; name[namelen++] = 0; // This is the root label (of length 0). *out = std::string(name, namelen); return true; } std::string DNSDomainToString(const base::StringPiece& domain) { std::string ret; for (unsigned i = 0; i < domain.size() && domain[i]; i += domain[i] + 1) { #if CHAR_MIN < 0 if (domain[i] < 0) return std::string(); #endif if (domain[i] > 63) return std::string(); if (i) ret += "."; if (static_cast(domain[i]) + i + 1 > domain.size()) return std::string(); domain.substr(i + 1, domain[i]).AppendToString(&ret); } return ret; } bool HaveOnlyLoopbackAddresses() { #if defined(OS_ANDROID) return android::HaveOnlyLoopbackAddresses(); #elif defined(OS_NACL) NOTIMPLEMENTED(); return false; #elif defined(OS_POSIX) struct ifaddrs* interface_addr = NULL; int rv = getifaddrs(&interface_addr); if (rv != 0) { DVLOG(1) << "getifaddrs() failed with errno = " << errno; return false; } bool result = true; for (struct ifaddrs* interface = interface_addr; interface != NULL; interface = interface->ifa_next) { if (!(IFF_UP & interface->ifa_flags)) continue; if (IFF_LOOPBACK & interface->ifa_flags) continue; const struct sockaddr* addr = interface->ifa_addr; if (!addr) continue; if (addr->sa_family == AF_INET6) { // Safe cast since this is AF_INET6. const struct sockaddr_in6* addr_in6 = reinterpret_cast(addr); const struct in6_addr* sin6_addr = &addr_in6->sin6_addr; if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) continue; } if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET) continue; result = false; break; } freeifaddrs(interface_addr); return result; #elif defined(OS_WIN) // TODO(wtc): implement with the GetAdaptersAddresses function. NOTIMPLEMENTED(); return false; #else NOTIMPLEMENTED(); return false; #endif // defined(various platforms) } #if !defined(OS_NACL) namespace { bool GetTimeDeltaForConnectionTypeFromFieldTrial( const char* field_trial, NetworkChangeNotifier::ConnectionType type, base::TimeDelta* out) { std::string group = base::FieldTrialList::FindFullName(field_trial); if (group.empty()) return false; std::vector group_parts = base::SplitStringPiece( group, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); if (type < 0) return false; size_t type_size = static_cast(type); if (type_size >= group_parts.size()) return false; int64_t ms; if (!base::StringToInt64(group_parts[type_size], &ms)) return false; *out = base::TimeDelta::FromMilliseconds(ms); return true; } } // namespace base::TimeDelta GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault( const char* field_trial, base::TimeDelta default_delta, NetworkChangeNotifier::ConnectionType type) { base::TimeDelta out; if (!GetTimeDeltaForConnectionTypeFromFieldTrial(field_trial, type, &out)) out = default_delta; return out; } #endif // !defined(OS_NACL) } // namespace net