blob: c50e447430b0178b6f517d940288413ae3b2cf74 [file] [log] [blame]
Wade Guthrie0d438532012-05-18 14:18:50 -07001// Copyright (c) 2012 The Chromium OS 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// This library provides an abstracted interface to the cfg80211 kernel module
6// and mac80211 drivers. These are accessed via a netlink socket using the
7// following software stack:
8//
repo syncbcaa6942013-01-02 15:38:21 -08009// [shill]--[nl80211 library, libnl_genl/libnl libraries]
10// |
11// (netlink socket)
12// |
Wade Guthrie0d438532012-05-18 14:18:50 -070013// [cfg80211 kernel module]
repo syncbcaa6942013-01-02 15:38:21 -080014// |
15// [mac80211 drivers]
Wade Guthrie0d438532012-05-18 14:18:50 -070016//
17// For the love of Pete, there are a lot of different types of callbacks,
18// here. I'll try to differentiate:
19//
20// Config80211 Callback -
21// This is a base::Callback object installed by the user and called by
22// Config80211 for each message it receives. More specifically, when the
23// user calls Config80211::SubscribeToEvents, Config80211 installs
Wade Guthrieb1ec8602012-10-18 17:26:14 -070024// OnRawNlMessageReceived as a netlink callback function (described below).
25// OnRawNlMessageReceived, in turn, parses the message from cfg80211 and
repo syncdc085c82012-12-28 08:54:41 -080026// calls Config80211::Callback with the resultant Nl80211Message.
Wade Guthrie0d438532012-05-18 14:18:50 -070027//
Wade Guthrie0d438532012-05-18 14:18:50 -070028// Dispatcher Callback -
29// This base::Callback is a private method of Config80211 created and
30// installed behind the scenes. This is not the callback you're looking
31// for; move along. This is called by shill's EventDispatcher when there's
32// data waiting for user space code on the netlink socket. This callback
33// then calls NetlinkSocket::GetMessages which calls nl_recvmsgs_default
34// which, in turn, calls the installed netlink callback function.
35
36#ifndef SHILL_CONFIG80211_H_
37#define SHILL_CONFIG80211_H_
38
Wade Guthrie5d3d6de2012-11-02 11:08:34 -070039#include <gtest/gtest_prod.h> // for FRIEND_TEST
40
Wade Guthrie0d438532012-05-18 14:18:50 -070041#include <iomanip>
Wade Guthrieb1ec8602012-10-18 17:26:14 -070042#include <list>
Wade Guthrie0d438532012-05-18 14:18:50 -070043#include <map>
Wade Guthried6153612012-08-23 11:36:14 -070044#include <set>
Wade Guthrie0d438532012-05-18 14:18:50 -070045#include <string>
46
47#include <base/basictypes.h>
48#include <base/bind.h>
49#include <base/lazy_instance.h>
50
51#include "shill/event_dispatcher.h"
52#include "shill/io_handler.h"
53#include "shill/nl80211_socket.h"
54
55namespace shill {
56
repo syncbcaa6942013-01-02 15:38:21 -080057class Error;
Liam McLoughlinf4baef22012-08-01 19:08:25 -070058struct InputData;
repo syncdc085c82012-12-28 08:54:41 -080059class Nl80211Message;
Wade Guthrie0d438532012-05-18 14:18:50 -070060
61// Provides a transport-independent ability to receive status from the wifi
62// configuration. In its current implementation, it uses the netlink socket
63// interface to interface with the wifi system.
64//
65// Config80211 is a singleton and, as such, coordinates access to libnl.
66class Config80211 {
67 public:
repo syncdc085c82012-12-28 08:54:41 -080068 typedef base::Callback<void(const Nl80211Message &)> Callback;
Wade Guthrie0d438532012-05-18 14:18:50 -070069
70 // The different kinds of events to which we can subscribe (and receive)
71 // from cfg80211.
72 enum EventType {
73 kEventTypeConfig,
74 kEventTypeScan,
75 kEventTypeRegulatory,
76 kEventTypeMlme,
77 kEventTypeCount
78 };
79
Wade Guthried6153612012-08-23 11:36:14 -070080 // This represents whether the cfg80211/mac80211 are installed in the kernel.
81 enum WifiState {
Wade Guthried4977f22012-08-22 12:37:54 -070082 kWifiUp,
83 kWifiDown
Wade Guthried6153612012-08-23 11:36:14 -070084 };
85
Wade Guthrie0d438532012-05-18 14:18:50 -070086 virtual ~Config80211();
87
88 // This is a singleton -- use Config80211::GetInstance()->Foo()
89 static Config80211 *GetInstance();
90
91 // Performs non-trivial object initialization of the Config80211 singleton.
92 bool Init(EventDispatcher *dispatcher);
93
94 // Returns the file descriptor of socket used to read wifi data.
95 int GetFd() const { return (sock_ ? sock_->GetFd() : -1); }
96
Wade Guthrieb1ec8602012-10-18 17:26:14 -070097 // Install a Config80211 Callback. The callback is a user-supplied object
98 // to be called by the system for user-bound messages that do not have a
99 // corresponding messaage-specific callback. |AddBroadcastCallback| should
100 // be called before |SubscribeToEvents| since the result of this call are
101 // used for that call.
102 bool AddBroadcastCallback(const Callback &callback);
Wade Guthrie0d438532012-05-18 14:18:50 -0700103
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700104 // Uninstall a Config80211 Callback.
105 bool RemoveBroadcastCallback(const Callback &callback);
106
107 // Determines whether a callback is in the list of broadcast callbacks.
108 bool FindBroadcastCallback(const Callback &callback) const;
109
110 // Uninstall all Config80211 broadcast Callbacks.
111 void ClearBroadcastCallbacks();
Wade Guthrie0d438532012-05-18 14:18:50 -0700112
Wade Guthrie5d53d492012-11-07 09:53:31 -0800113 // Sends a kernel-bound message using the Config80211 socket after
114 // installing a callback to handle it.
115 // TODO(wdg): Eventually, this should also include a timeout and a callback
116 // to call in case of timeout.
repo syncdc085c82012-12-28 08:54:41 -0800117 bool SendMessage(Nl80211Message *message, const Callback &callback);
Wade Guthrie5d53d492012-11-07 09:53:31 -0800118
Christopher Wiley393b93f2012-11-08 17:30:58 -0800119 // Uninstall a Config80211 Callback for a specific message.
repo syncdc085c82012-12-28 08:54:41 -0800120 bool RemoveMessageCallback(const Nl80211Message &message);
Wade Guthrie0d438532012-05-18 14:18:50 -0700121
122 // Return a string corresponding to the passed-in EventType.
123 static bool GetEventTypeString(EventType type, std::string *value);
124
Wade Guthried6153612012-08-23 11:36:14 -0700125 // Sign-up to receive and log multicast events of a specific type (once wifi
126 // is up).
Wade Guthrie0d438532012-05-18 14:18:50 -0700127 bool SubscribeToEvents(EventType type);
128
Wade Guthried6153612012-08-23 11:36:14 -0700129 // Indicate that the mac80211 driver is up and, ostensibly, accepting event
130 // subscription requests or down.
131 void SetWifiState(WifiState new_state);
132
Wade Guthrie0d438532012-05-18 14:18:50 -0700133 protected:
134 friend struct base::DefaultLazyInstanceTraits<Config80211>;
135
136 explicit Config80211();
137
138 private:
139 friend class Config80211Test;
Darin Petkovd5818382013-01-28 16:27:07 +0100140 friend class ShillDaemonTest;
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700141 FRIEND_TEST(Config80211Test, BroadcastCallbackTest);
142 FRIEND_TEST(Config80211Test, MessageCallbackTest);
Wade Guthried4977f22012-08-22 12:37:54 -0700143 typedef std::map<EventType, std::string> EventTypeStrings;
144 typedef std::set<EventType> SubscribedEvents;
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700145 typedef std::map<uint32_t, Callback> MessageCallbacks;
Wade Guthrie0d438532012-05-18 14:18:50 -0700146
Wade Guthried6153612012-08-23 11:36:14 -0700147 // Sign-up to receive and log multicast events of a specific type (assumes
148 // wifi is up).
149 bool ActuallySubscribeToEvents(EventType type);
150
Wade Guthrie0d438532012-05-18 14:18:50 -0700151 // EventDispatcher calls this when data is available on our socket. This
repo syncbcaa6942013-01-02 15:38:21 -0800152 // method passes each, individual, message in the input to
153 // |OnNlMessageReceived|.
154 void OnRawNlMessageReceived(InputData *data);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700155
156 // This method processes a message from |OnRawNlMessageReceived| by passing
157 // the message to either the Config80211 callback that matches the sequence
158 // number of the message or, if there isn't one, to all of the default
159 // Config80211 callbacks in |broadcast_callbacks_|.
repo syncbcaa6942013-01-02 15:38:21 -0800160 void OnNlMessageReceived(nlmsghdr *msg);
161
162 // Called by InputHandler on exceptional events.
163 void OnReadError(const Error &error);
Wade Guthrie0d438532012-05-18 14:18:50 -0700164
Darin Petkovd5818382013-01-28 16:27:07 +0100165 // Just for tests, this method turns off WiFi and clears the subscribed events
166 // list. If |full| is true, also clears state set by Init.
167 void Reset(bool full);
Wade Guthried6153612012-08-23 11:36:14 -0700168
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700169 // Config80211 Callbacks, OnRawNlMessageReceived invokes each of these
170 // User-supplied callback object when _it_ gets called to read libnl data.
171 std::list<Callback> broadcast_callbacks_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700172
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700173 // Message-specific callbacks, mapped by message ID.
174 MessageCallbacks message_callbacks_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700175
Wade Guthried6153612012-08-23 11:36:14 -0700176 static EventTypeStrings *event_types_;
177
178 WifiState wifi_state_;
179
Wade Guthried6153612012-08-23 11:36:14 -0700180 SubscribedEvents subscribed_events_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700181
182 // Hooks needed to be called by shill's EventDispatcher.
183 EventDispatcher *dispatcher_;
184 base::WeakPtrFactory<Config80211> weak_ptr_factory_;
repo syncbcaa6942013-01-02 15:38:21 -0800185 base::Callback<void(InputData *)> dispatcher_callback_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700186 scoped_ptr<IOHandler> dispatcher_handler_;
187
188 Nl80211Socket *sock_;
189
190 DISALLOW_COPY_AND_ASSIGN(Config80211);
191};
192
Wade Guthrie0d438532012-05-18 14:18:50 -0700193} // namespace shill
194
195#endif // SHILL_CONFIG80211_H_