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 "net/base/net_util.h" 24 #include "net/base/network_change_notifier.h" 25 26 namespace net { 27 namespace internal { 28 29 // Keeps track of network interface addresses using rtnetlink. Used by 30 // NetworkChangeNotifier to provide signals to registered IPAddressObservers. 31 class NET_EXPORT_PRIVATE AddressTrackerLinux : 32 public base::MessageLoopForIO::Watcher { 33 public: 34 typedef std::map<IPAddressNumber, struct ifaddrmsg> AddressMap; 35 36 // Will run |address_callback| when the AddressMap changes, |link_callback| 37 // when the list of online links changes, and |tunnel_callback| when the list 38 // of online tunnels changes. 39 AddressTrackerLinux(const base::Closure& address_callback, 40 const base::Closure& link_callback, 41 const base::Closure& tunnel_callback); 42 virtual ~AddressTrackerLinux(); 43 44 // Starts watching system configuration for changes. The current thread must 45 // have a MessageLoopForIO. 46 void Init(); 47 48 AddressMap GetAddressMap() const; 49 50 // Implementation of NetworkChangeNotifierLinux::GetCurrentConnectionType(). 51 // Safe to call from any thread, but will block until Init() has completed. 52 NetworkChangeNotifier::ConnectionType GetCurrentConnectionType(); 53 54 private: 55 friend class AddressTrackerLinuxTest; 56 57 // A function that returns the name of an interface given the interface index 58 // in |interface_index|. 59 typedef const char* (*GetInterfaceNameFunction)(int interface_index); 60 61 // Sets |*address_changed| to indicate whether |address_map_| changed and 62 // sets |*link_changed| to indicate if |online_links_| changed and sets 63 // |*tunnel_changed| to indicate if |online_links_| changed with regards to a 64 // tunnel interface while reading messages from |netlink_fd_|. 65 void ReadMessages(bool* address_changed, 66 bool* link_changed, 67 bool* tunnel_changed); 68 69 // Sets |*address_changed| to true if |address_map_| changed, sets 70 // |*link_changed| to true if |online_links_| changed, sets |*tunnel_changed| 71 // to true if |online_links_| changed with regards to a tunnel interface while 72 // reading the message from |buffer|. 73 void HandleMessage(char* buffer, 74 size_t length, 75 bool* address_changed, 76 bool* link_changed, 77 bool* tunnel_changed); 78 79 // Call when some part of initialization failed; forces online and unblocks. 80 void AbortAndForceOnline(); 81 82 // MessageLoopForIO::Watcher: 83 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; 84 virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE; 85 86 // Close |netlink_fd_| 87 void CloseSocket(); 88 89 // Does |msg| refer to a tunnel interface? 90 bool IsTunnelInterface(const struct ifinfomsg* msg) const; 91 92 // Gets the name of an interface given the interface index |interface_index|. 93 // May return empty string if it fails but should not return NULL. This is 94 // overridden by tests. 95 GetInterfaceNameFunction get_interface_name_; 96 97 base::Closure address_callback_; 98 base::Closure link_callback_; 99 base::Closure tunnel_callback_; 100 101 int netlink_fd_; 102 base::MessageLoopForIO::FileDescriptorWatcher watcher_; 103 104 mutable base::Lock address_map_lock_; 105 AddressMap address_map_; 106 107 // Set of interface indices for links that are currently online. 108 base::hash_set<int> online_links_; 109 110 base::Lock is_offline_lock_; 111 bool is_offline_; 112 bool is_offline_initialized_; 113 base::ConditionVariable is_offline_initialized_cv_; 114 }; 115 116 } // namespace internal 117 } // namespace net 118 119 #endif // NET_BASE_ADDRESS_TRACKER_LINUX_H_ 120