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 3 // found in the LICENSE file. 4 5 #ifndef NET_BASE_ADDRESS_TRACKER_LINUX_H_ 6 #define NET_BASE_ADDRESS_TRACKER_LINUX_H_ 7 8 #include <sys/socket.h> // Needed to include netlink. 9 // Mask superfluous definition of |struct net|. This is fixed in Linux 2.6.38. 10 #define net net_kernel 11 #include <linux/rtnetlink.h> 12 #undef net 13 14 #include <map> 15 16 #include "base/basictypes.h" 17 #include "base/callback.h" 18 #include "base/compiler_specific.h" 19 #include "base/containers/hash_tables.h" 20 #include "base/message_loop/message_loop.h" 21 #include "base/synchronization/condition_variable.h" 22 #include "base/synchronization/lock.h" 23 #include "base/threading/thread_checker.h" 24 #include "net/base/net_util.h" 25 #include "net/base/network_change_notifier.h" 26 27 namespace net { 28 namespace internal { 29 30 // Keeps track of network interface addresses using rtnetlink. Used by 31 // NetworkChangeNotifier to provide signals to registered IPAddressObservers. 32 class NET_EXPORT_PRIVATE AddressTrackerLinux : 33 public base::MessageLoopForIO::Watcher { 34 public: 35 typedef std::map<IPAddressNumber, struct ifaddrmsg> AddressMap; 36 37 // Non-tracking version constructor: it takes a snapshot of the 38 // current system configuration. Once Init() returns, the 39 // configuration is available through GetOnlineLinks() and 40 // GetAddressMap(). 41 AddressTrackerLinux(); 42 43 // Tracking version constructor: it will run |address_callback| when 44 // the AddressMap changes, |link_callback| when the list of online 45 // links changes, and |tunnel_callback| when the list of online 46 // tunnels changes. 47 AddressTrackerLinux(const base::Closure& address_callback, 48 const base::Closure& link_callback, 49 const base::Closure& tunnel_callback); 50 virtual ~AddressTrackerLinux(); 51 52 // In tracking mode, it starts watching the system configuration for 53 // changes. The current thread must have a MessageLoopForIO. In 54 // non-tracking mode, once Init() returns, a snapshot of the system 55 // configuration is available through GetOnlineLinks() and 56 // GetAddressMap(). 57 void Init(); 58 59 AddressMap GetAddressMap() const; 60 61 // Returns set of interface indicies for online interfaces. 62 base::hash_set<int> GetOnlineLinks() const; 63 64 // Implementation of NetworkChangeNotifierLinux::GetCurrentConnectionType(). 65 // Safe to call from any thread, but will block until Init() has completed. 66 NetworkChangeNotifier::ConnectionType GetCurrentConnectionType(); 67 68 private: 69 friend class AddressTrackerLinuxTest; 70 71 // In tracking mode, holds |lock| while alive. In non-tracking mode, 72 // enforces single-threaded access. 73 class AddressTrackerAutoLock { 74 public: 75 AddressTrackerAutoLock(const AddressTrackerLinux& tracker, 76 base::Lock& lock); 77 ~AddressTrackerAutoLock(); 78 79 private: 80 const AddressTrackerLinux& tracker_; 81 base::Lock& lock_; 82 DISALLOW_COPY_AND_ASSIGN(AddressTrackerAutoLock); 83 }; 84 85 // A function that returns the name of an interface given the interface index 86 // in |interface_index|. 87 typedef const char* (*GetInterfaceNameFunction)(int interface_index); 88 89 // Sets |*address_changed| to indicate whether |address_map_| changed and 90 // sets |*link_changed| to indicate if |online_links_| changed and sets 91 // |*tunnel_changed| to indicate if |online_links_| changed with regards to a 92 // tunnel interface while reading messages from |netlink_fd_|. 93 void ReadMessages(bool* address_changed, 94 bool* link_changed, 95 bool* tunnel_changed); 96 97 // Sets |*address_changed| to true if |address_map_| changed, sets 98 // |*link_changed| to true if |online_links_| changed, sets |*tunnel_changed| 99 // to true if |online_links_| changed with regards to a tunnel interface while 100 // reading the message from |buffer|. 101 void HandleMessage(char* buffer, 102 size_t length, 103 bool* address_changed, 104 bool* link_changed, 105 bool* tunnel_changed); 106 107 // Call when some part of initialization failed; forces online and unblocks. 108 void AbortAndForceOnline(); 109 110 // MessageLoopForIO::Watcher: 111 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; 112 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE; 113 114 // Close |netlink_fd_| 115 void CloseSocket(); 116 117 // Does |msg| refer to a tunnel interface? 118 bool IsTunnelInterface(const struct ifinfomsg* msg) const; 119 120 // Gets the name of an interface given the interface index |interface_index|. 121 // May return empty string if it fails but should not return NULL. This is 122 // overridden by tests. 123 GetInterfaceNameFunction get_interface_name_; 124 125 base::Closure address_callback_; 126 base::Closure link_callback_; 127 base::Closure tunnel_callback_; 128 129 int netlink_fd_; 130 base::MessageLoopForIO::FileDescriptorWatcher watcher_; 131 132 mutable base::Lock address_map_lock_; 133 AddressMap address_map_; 134 135 // Set of interface indices for links that are currently online. 136 mutable base::Lock online_links_lock_; 137 base::hash_set<int> online_links_; 138 139 base::Lock is_offline_lock_; 140 bool is_offline_; 141 bool is_offline_initialized_; 142 base::ConditionVariable is_offline_initialized_cv_; 143 bool tracking_; 144 145 // Used to verify single-threaded access in non-tracking mode. 146 base::ThreadChecker thread_checker_; 147 }; 148 149 } // namespace internal 150 } // namespace net 151 152 #endif // NET_BASE_ADDRESS_TRACKER_LINUX_H_ 153