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