OLD | NEW |
| (Empty) |
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 ~AddressTrackerLinux() override; | |
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 // Returns the name for the interface with interface index |interface_index|. | |
69 // |buf| should be a pointer to an array of size IFNAMSIZ. The returned | |
70 // pointer will point to |buf|. This function acts like if_indextoname which | |
71 // cannot be used as net/if.h cannot be mixed with linux/if.h. We'll stick | |
72 // with exclusively talking to the kernel and not the C library. | |
73 static char* GetInterfaceName(int interface_index, char* buf); | |
74 | |
75 private: | |
76 friend class AddressTrackerLinuxTest; | |
77 | |
78 // In tracking mode, holds |lock| while alive. In non-tracking mode, | |
79 // enforces single-threaded access. | |
80 class AddressTrackerAutoLock { | |
81 public: | |
82 AddressTrackerAutoLock(const AddressTrackerLinux& tracker, | |
83 base::Lock& lock); | |
84 ~AddressTrackerAutoLock(); | |
85 | |
86 private: | |
87 const AddressTrackerLinux& tracker_; | |
88 base::Lock& lock_; | |
89 DISALLOW_COPY_AND_ASSIGN(AddressTrackerAutoLock); | |
90 }; | |
91 | |
92 // A function that returns the name of an interface given the interface index | |
93 // in |interface_index|. |ifname| should be a buffer of size IFNAMSIZ. The | |
94 // function should return a pointer to |ifname|. | |
95 typedef char* (*GetInterfaceNameFunction)(int interface_index, char* ifname); | |
96 | |
97 // Sets |*address_changed| to indicate whether |address_map_| changed and | |
98 // sets |*link_changed| to indicate if |online_links_| changed and sets | |
99 // |*tunnel_changed| to indicate if |online_links_| changed with regards to a | |
100 // tunnel interface while reading messages from |netlink_fd_|. | |
101 void ReadMessages(bool* address_changed, | |
102 bool* link_changed, | |
103 bool* tunnel_changed); | |
104 | |
105 // Sets |*address_changed| to true if |address_map_| changed, sets | |
106 // |*link_changed| to true if |online_links_| changed, sets |*tunnel_changed| | |
107 // to true if |online_links_| changed with regards to a tunnel interface while | |
108 // reading the message from |buffer|. | |
109 void HandleMessage(char* buffer, | |
110 size_t length, | |
111 bool* address_changed, | |
112 bool* link_changed, | |
113 bool* tunnel_changed); | |
114 | |
115 // Call when some part of initialization failed; forces online and unblocks. | |
116 void AbortAndForceOnline(); | |
117 | |
118 // MessageLoopForIO::Watcher: | |
119 void OnFileCanReadWithoutBlocking(int fd) override; | |
120 void OnFileCanWriteWithoutBlocking(int /* fd */) override; | |
121 | |
122 // Close |netlink_fd_| | |
123 void CloseSocket(); | |
124 | |
125 // Does |interface_index| refer to a tunnel interface? | |
126 bool IsTunnelInterface(int interface_index) const; | |
127 | |
128 // Updates current_connection_type_ based on the network list. | |
129 void UpdateCurrentConnectionType(); | |
130 | |
131 // Gets the name of an interface given the interface index |interface_index|. | |
132 // May return empty string if it fails but should not return NULL. This is | |
133 // overridden by tests. | |
134 GetInterfaceNameFunction get_interface_name_; | |
135 | |
136 base::Closure address_callback_; | |
137 base::Closure link_callback_; | |
138 base::Closure tunnel_callback_; | |
139 | |
140 int netlink_fd_; | |
141 base::MessageLoopForIO::FileDescriptorWatcher watcher_; | |
142 | |
143 mutable base::Lock address_map_lock_; | |
144 AddressMap address_map_; | |
145 | |
146 // Set of interface indices for links that are currently online. | |
147 mutable base::Lock online_links_lock_; | |
148 base::hash_set<int> online_links_; | |
149 | |
150 base::Lock connection_type_lock_; | |
151 bool connection_type_initialized_; | |
152 base::ConditionVariable connection_type_initialized_cv_; | |
153 NetworkChangeNotifier::ConnectionType current_connection_type_; | |
154 bool tracking_; | |
155 | |
156 // Used to verify single-threaded access in non-tracking mode. | |
157 base::ThreadChecker thread_checker_; | |
158 }; | |
159 | |
160 } // namespace internal | |
161 } // namespace net | |
162 | |
163 #endif // NET_BASE_ADDRESS_TRACKER_LINUX_H_ | |
OLD | NEW |