Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: net/base/net_util_mac.cc

Issue 734063004: Update from https://crrev.com/304418 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/net_util_mac.h ('k') | net/base/net_util_posix.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/net_util_mac.cc
diff --git a/net/base/net_util_mac.cc b/net/base/net_util_mac.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5dd46307789b37f7b17593970d643a88924e7809
--- /dev/null
+++ b/net/base/net_util_mac.cc
@@ -0,0 +1,246 @@
+// Copyright (c) 2014 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/base/net_util_mac.h"
+
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <set>
+#include <sys/types.h>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_tokenizer.h"
+#include "base/strings/string_util.h"
+#include "base/threading/thread_restrictions.h"
+#include "net/base/escape.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util_posix.h"
+#include "url/gurl.h"
+
+#if !defined(OS_IOS)
+#include <net/if_media.h>
+#include <netinet/in_var.h>
+#include <sys/ioctl.h>
+#endif // !OS_IOS
+
+namespace net {
+
+namespace {
+
+#if !defined(OS_IOS)
+
+// MacOSX implementation of IPAttributesGetterMac which calls ioctl on socket to
+// retrieve IP attributes.
+class IPAttributesGetterMacImpl : public internal::IPAttributesGetterMac {
+ public:
+ IPAttributesGetterMacImpl();
+ ~IPAttributesGetterMacImpl() override;
+ bool IsInitialized() const override;
+ bool GetIPAttributes(const char* ifname,
+ const sockaddr* sock_addr,
+ int* native_attributes) override;
+
+ private:
+ int ioctl_socket_;
+};
+
+IPAttributesGetterMacImpl::IPAttributesGetterMacImpl()
+ : ioctl_socket_(socket(AF_INET6, SOCK_DGRAM, 0)) {
+ DCHECK_GE(ioctl_socket_, 0);
+}
+
+bool IPAttributesGetterMacImpl::IsInitialized() const {
+ return ioctl_socket_ >= 0;
+}
+
+IPAttributesGetterMacImpl::~IPAttributesGetterMacImpl() {
+ if (ioctl_socket_ >= 0) {
+ close(ioctl_socket_);
+ }
+}
+
+bool IPAttributesGetterMacImpl::GetIPAttributes(const char* ifname,
+ const sockaddr* sock_addr,
+ int* native_attributes) {
+ struct in6_ifreq ifr = {};
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
+ memcpy(&ifr.ifr_ifru.ifru_addr, sock_addr, sock_addr->sa_len);
+ int rv = ioctl(ioctl_socket_, SIOCGIFAFLAG_IN6, &ifr);
+ if (rv >= 0) {
+ *native_attributes = ifr.ifr_ifru.ifru_flags;
+ }
+ return (rv >= 0);
+}
+
+// When returning true, the platform native IPv6 address attributes were
+// successfully converted to net IP address attributes. Otherwise, returning
+// false and the caller should drop the IP address which can't be used by the
+// application layer.
+bool TryConvertNativeToNetIPAttributes(int native_attributes,
+ int* net_attributes) {
+ // For MacOSX, we disallow addresses with attributes IN6_IFF_ANYCASE,
+ // IN6_IFF_DUPLICATED, IN6_IFF_TENTATIVE, and IN6_IFF_DETACHED as these are
+ // still progressing through duplicated address detection (DAD) or are not
+ // suitable to be used in an one-to-one communication and shouldn't be used
+ // by the application layer.
+ if (native_attributes & (IN6_IFF_ANYCAST | IN6_IFF_DUPLICATED |
+ IN6_IFF_TENTATIVE | IN6_IFF_DETACHED)) {
+ return false;
+ }
+
+ if (native_attributes & IN6_IFF_TEMPORARY) {
+ *net_attributes |= IP_ADDRESS_ATTRIBUTE_TEMPORARY;
+ }
+
+ if (native_attributes & IN6_IFF_DEPRECATED) {
+ *net_attributes |= IP_ADDRESS_ATTRIBUTE_DEPRECATED;
+ }
+
+ return true;
+}
+
+NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(
+ int addr_family,
+ const std::string& interface_name) {
+ NetworkChangeNotifier::ConnectionType type =
+ NetworkChangeNotifier::CONNECTION_UNKNOWN;
+
+ struct ifmediareq ifmr = {};
+ strncpy(ifmr.ifm_name, interface_name.c_str(), sizeof(ifmr.ifm_name) - 1);
+
+ int s = socket(addr_family, SOCK_DGRAM, 0);
+ if (s == -1) {
+ return type;
+ }
+
+ if (ioctl(s, SIOCGIFMEDIA, &ifmr) != -1) {
+ if (ifmr.ifm_current & IFM_IEEE80211) {
+ type = NetworkChangeNotifier::CONNECTION_WIFI;
+ } else if (ifmr.ifm_current & IFM_ETHER) {
+ type = NetworkChangeNotifier::CONNECTION_ETHERNET;
+ }
+ }
+ close(s);
+ return type;
+}
+
+#endif // !OS_IOS
+} // namespace
+
+namespace internal {
+
+bool GetNetworkListImpl(NetworkInterfaceList* networks,
+ int policy,
+ const ifaddrs* interfaces,
+ IPAttributesGetterMac* ip_attributes_getter) {
+ // Enumerate the addresses assigned to network interfaces which are up.
+ for (const ifaddrs* interface = interfaces; interface != NULL;
+ interface = interface->ifa_next) {
+ // Skip loopback interfaces, and ones which are down.
+ if (!(IFF_RUNNING & interface->ifa_flags))
+ continue;
+ if (IFF_LOOPBACK & interface->ifa_flags)
+ continue;
+ // Skip interfaces with no address configured.
+ struct sockaddr* addr = interface->ifa_addr;
+ if (!addr)
+ continue;
+
+ // Skip unspecified addresses (i.e. made of zeroes) and loopback addresses
+ // configured on non-loopback interfaces.
+ if (IsLoopbackOrUnspecifiedAddress(addr))
+ continue;
+
+ const std::string& name = interface->ifa_name;
+ // Filter out VMware interfaces, typically named vmnet1 and vmnet8.
+ if (ShouldIgnoreInterface(name, policy)) {
+ continue;
+ }
+
+ NetworkChangeNotifier::ConnectionType connection_type =
+ NetworkChangeNotifier::CONNECTION_UNKNOWN;
+
+ int ip_attributes = IP_ADDRESS_ATTRIBUTE_NONE;
+
+#if !defined(OS_IOS)
+ // Retrieve native ip attributes and convert to net version if a getter is
+ // given.
+ if (ip_attributes_getter && ip_attributes_getter->IsInitialized()) {
+ int native_attributes = 0;
+ if (addr->sa_family == AF_INET6 &&
+ ip_attributes_getter->GetIPAttributes(
+ interface->ifa_name, interface->ifa_addr, &native_attributes)) {
+ if (!TryConvertNativeToNetIPAttributes(native_attributes,
+ &ip_attributes)) {
+ continue;
+ }
+ }
+ }
+
+ connection_type = GetNetworkInterfaceType(addr->sa_family, name);
+#endif // !OS_IOS
+
+ IPEndPoint address;
+
+ int addr_size = 0;
+ if (addr->sa_family == AF_INET6) {
+ addr_size = sizeof(sockaddr_in6);
+ } else if (addr->sa_family == AF_INET) {
+ addr_size = sizeof(sockaddr_in);
+ }
+
+ if (address.FromSockAddr(addr, addr_size)) {
+ uint8 prefix_length = 0;
+ if (interface->ifa_netmask) {
+ // If not otherwise set, assume the same sa_family as ifa_addr.
+ if (interface->ifa_netmask->sa_family == 0) {
+ interface->ifa_netmask->sa_family = addr->sa_family;
+ }
+ IPEndPoint netmask;
+ if (netmask.FromSockAddr(interface->ifa_netmask, addr_size)) {
+ prefix_length = MaskPrefixLength(netmask.address());
+ }
+ }
+ networks->push_back(NetworkInterface(
+ name, name, if_nametoindex(name.c_str()), connection_type,
+ address.address(), prefix_length, ip_attributes));
+ }
+ }
+
+ return true;
+}
+
+} // namespace internal
+
+bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
+ if (networks == NULL)
+ return false;
+
+ // getifaddrs() may require IO operations.
+ base::ThreadRestrictions::AssertIOAllowed();
+
+ ifaddrs* interfaces;
+ if (getifaddrs(&interfaces) < 0) {
+ PLOG(ERROR) << "getifaddrs";
+ return false;
+ }
+
+ scoped_ptr<internal::IPAttributesGetterMac> ip_attributes_getter;
+
+#if !defined(OS_IOS)
+ ip_attributes_getter.reset(new IPAttributesGetterMacImpl());
+#endif
+
+ bool result = internal::GetNetworkListImpl(networks, policy, interfaces,
+ ip_attributes_getter.get());
+ freeifaddrs(interfaces);
+ return result;
+}
+
+} // namespace net
« no previous file with comments | « net/base/net_util_mac.h ('k') | net/base/net_util_posix.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698