blob: cb2e9fae5364767bc02d03737c9c6fffa7f93f29 [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
Wade Guthriebee87c22013-03-06 11:00:46 -08005// This software provides an abstracted interface to the netlink socket
6// interface. In its current implementation it is used, primarily, to
7// communicate with the cfg80211 kernel module and mac80211 drivers:
Wade Guthrie0d438532012-05-18 14:18:50 -07008//
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 Guthriebee87c22013-03-06 11:00:46 -080016//
17// In order to send a message and handle it's response, do the following:
18// - Create a handler (it'll want to verify that it's the kind of message you
19// want, cast it to the appropriate type, and get attributes from the cast
20// message):
21//
22// #include "nl80211_message.h"
23// class SomeClass {
24// static void MyMessageHandler(const NetlinkMessage &raw) {
25// if (raw.message_type() != ControlNetlinkMessage::kMessageType)
26// return;
27// const ControlNetlinkMessage *message =
28// reinterpret_cast<const ControlNetlinkMessage *>(&raw);
29// if (message.command() != NewFamilyMessage::kCommand)
30// return;
31// uint16_t my_attribute;
32// message->const_attributes()->GetU16AttributeValue(
33// CTRL_ATTR_FAMILY_ID, &my_attribute);
34// } // MyMessageHandler.
35// } // class SomeClass.
36//
37// - Instantiate a message:
38//
39// #include "nl80211_message.h"
40// GetFamilyMessage msg;
41//
42// - And add attributes:
43//
44// if (msg.attributes()->CreateStringAttribute(CTRL_ATTR_FAMILY_NAME,
45// "CTRL_ATTR_FAMILY_NAME")) {
46// msg.attributes()->SetStringAttributeValue(CTRL_ATTR_FAMILY_NAME,
47// "foo");
48// }
49//
50// - Then send the message, passing-in a closure to the handler you created:
51//
52// Config80211 *config80211 = Config80211::GetInstance();
53// config80211->SendMessage(&msg, Bind(&SomeClass::MyMessageHandler));
54//
55// Config80211 will then save your handler and send your message. When a
56// response to your message arrives, it'll call your handler.
57//
Wade Guthrie0d438532012-05-18 14:18:50 -070058
59#ifndef SHILL_CONFIG80211_H_
60#define SHILL_CONFIG80211_H_
61
Wade Guthrie5d3d6de2012-11-02 11:08:34 -070062#include <gtest/gtest_prod.h> // for FRIEND_TEST
63
Wade Guthrieb1ec8602012-10-18 17:26:14 -070064#include <list>
Wade Guthrie0d438532012-05-18 14:18:50 -070065#include <map>
Wade Guthried6153612012-08-23 11:36:14 -070066#include <set>
Wade Guthrie0d438532012-05-18 14:18:50 -070067#include <string>
68
69#include <base/basictypes.h>
70#include <base/bind.h>
71#include <base/lazy_instance.h>
72
Wade Guthrie89e6cb32013-03-07 08:03:45 -080073struct nlmsghdr;
Wade Guthrie0d438532012-05-18 14:18:50 -070074
75namespace shill {
76
repo syncbcaa6942013-01-02 15:38:21 -080077class Error;
Wade Guthrie89e6cb32013-03-07 08:03:45 -080078class EventDispatcher;
Liam McLoughlinf4baef22012-08-01 19:08:25 -070079struct InputData;
Wade Guthrie89e6cb32013-03-07 08:03:45 -080080class IOHandler;
Wade Guthrief48a1952013-03-04 17:33:47 -080081class NetlinkMessage;
Wade Guthrie89e6cb32013-03-07 08:03:45 -080082class NetlinkSocket;
Wade Guthrie0d438532012-05-18 14:18:50 -070083
Wade Guthriebee87c22013-03-06 11:00:46 -080084// Config80211 is a singleton that coordinates sending netlink messages to,
85// and receiving netlink messages from, the kernel. The first use of this is
86// to communicate between user-space and the cfg80211 module that manages wifi
87// drivers. Bring Config80211 up as follows:
88// Config80211 *config80211_ = Config80211::GetInstance();
89// EventDispatcher dispatcher_;
90// config80211_->Init(); // Initialize the socket.
91// // Get message types for all dynamic message types.
92// Nl80211Message::SetMessageType(
93// config80211_->GetFamily(Nl80211Message::kMessageTypeString,
94// Bind(&Nl80211Message::CreateMessage)));
95// config80211_->Start(&dispatcher_); // Leave event loop handling to others.
Wade Guthrie0d438532012-05-18 14:18:50 -070096class Config80211 {
97 public:
Wade Guthrief48a1952013-03-04 17:33:47 -080098 typedef base::Callback<void(const NetlinkMessage &)> NetlinkMessageHandler;
Wade Guthrie0d438532012-05-18 14:18:50 -070099
Wade Guthriebee87c22013-03-06 11:00:46 -0800100 // Encapsulates all the different things we know about a specific message
101 // type like its name, its id, and, eventually, a factory for creating
102 // messages of the designated type.
103 struct MessageType {
104 MessageType();
105
106 uint16_t family_id;
107
108 // Multicast groups supported by the family. The string and mapping to
109 // a group id are extracted from the CTRL_CMD_NEWFAMILY message.
110 std::map<std::string, uint32_t> groups;
Wade Guthrie0d438532012-05-18 14:18:50 -0700111 };
112
Wade Guthriebee87c22013-03-06 11:00:46 -0800113 // Various kinds of events to which we can subscribe (and receive) from
114 // cfg80211.
115 static const char kEventTypeConfig[];
116 static const char kEventTypeScan[];
117 static const char kEventTypeRegulatory[];
118 static const char kEventTypeMlme[];
119
Wade Guthried6153612012-08-23 11:36:14 -0700120 // This represents whether the cfg80211/mac80211 are installed in the kernel.
121 enum WifiState {
Wade Guthried4977f22012-08-22 12:37:54 -0700122 kWifiUp,
123 kWifiDown
Wade Guthried6153612012-08-23 11:36:14 -0700124 };
125
Wade Guthriebee87c22013-03-06 11:00:46 -0800126 // Config80211 is a singleton and this is the way to access it.
Wade Guthrie0d438532012-05-18 14:18:50 -0700127 static Config80211 *GetInstance();
128
129 // Performs non-trivial object initialization of the Config80211 singleton.
Wade Guthriebee87c22013-03-06 11:00:46 -0800130 bool Init();
Wade Guthrie0d438532012-05-18 14:18:50 -0700131
Wade Guthriebee87c22013-03-06 11:00:46 -0800132 // Passes the job of waiting for, and the subsequent reading from, the
133 // netlink socket to |dispatcher|.
134 void Start(EventDispatcher *dispatcher);
Wade Guthrie0d438532012-05-18 14:18:50 -0700135
Wade Guthriebee87c22013-03-06 11:00:46 -0800136 // The following methods deal with the network family table. This table
137 // associates netlink family names with family_ids (also called message
138 // types). Note that some families have static ids assigned to them but
139 // others require the kernel to resolve a string describing the family into
140 // a dynamically-determined id.
141
142 // Returns the family_id (message type) associated with |family_name|,
143 // calling the kernel if needed. Returns
144 // |NetlinkMessage::kIllegalMessageType| if the message type could not be
145 // determined. May block so |GetFamily| should be called before entering the
146 // event loop.
147 uint16_t GetFamily(std::string family_name);
148
Wade Guthriec6c81962013-03-06 15:47:13 -0800149 // Retrieves a family id (message type) given the |name| string describing
150 // the message family.
151 uint16_t GetMessageType(std::string name) const;
152
Wade Guthriebee87c22013-03-06 11:00:46 -0800153 // Install a Config80211 NetlinkMessageHandler. The handler is a
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800154 // user-supplied object to be called by the system for user-bound messages
155 // that do not have a corresponding messaage-specific callback.
156 // |AddBroadcastHandler| should be called before |SubscribeToEvents| since
157 // the result of this call are used for that call.
158 bool AddBroadcastHandler(const NetlinkMessageHandler &messge_handler);
Wade Guthrie0d438532012-05-18 14:18:50 -0700159
Wade Guthriebee87c22013-03-06 11:00:46 -0800160 // Uninstall a NetlinkMessage Handler.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800161 bool RemoveBroadcastHandler(const NetlinkMessageHandler &message_handler);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700162
Wade Guthriebee87c22013-03-06 11:00:46 -0800163 // Determines whether a handler is in the list of broadcast handlers.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800164 bool FindBroadcastHandler(const NetlinkMessageHandler &message_handler) const;
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700165
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800166 // Uninstall all broadcast netlink message handlers.
167 void ClearBroadcastHandlers();
Wade Guthrie0d438532012-05-18 14:18:50 -0700168
Wade Guthriebee87c22013-03-06 11:00:46 -0800169 // Sends a netlink message to the kernel using the Config80211 socket after
170 // installing a handler to deal with the kernel's response to the message.
Wade Guthrie5d53d492012-11-07 09:53:31 -0800171 // TODO(wdg): Eventually, this should also include a timeout and a callback
172 // to call in case of timeout.
Wade Guthrief48a1952013-03-04 17:33:47 -0800173 bool SendMessage(NetlinkMessage *message, const NetlinkMessageHandler
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800174 &message_handler);
Wade Guthrie5d53d492012-11-07 09:53:31 -0800175
Wade Guthriebee87c22013-03-06 11:00:46 -0800176 // Uninstall the handler for a specific netlink message.
Wade Guthrief48a1952013-03-04 17:33:47 -0800177 bool RemoveMessageHandler(const NetlinkMessage &message);
Wade Guthrie0d438532012-05-18 14:18:50 -0700178
Wade Guthried6153612012-08-23 11:36:14 -0700179 // Sign-up to receive and log multicast events of a specific type (once wifi
180 // is up).
Wade Guthriebee87c22013-03-06 11:00:46 -0800181 bool SubscribeToEvents(const std::string &family, const std::string &group);
Wade Guthried6153612012-08-23 11:36:14 -0700182
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800183 // Gets the next sequence number for a NetlinkMessage to be sent over
184 // Config80211's netlink socket.
185 uint32_t GetSequenceNumber();
186
Wade Guthrie0d438532012-05-18 14:18:50 -0700187 protected:
188 friend struct base::DefaultLazyInstanceTraits<Config80211>;
189
190 explicit Config80211();
191
192 private:
193 friend class Config80211Test;
Darin Petkovd5818382013-01-28 16:27:07 +0100194 friend class ShillDaemonTest;
Wade Guthriebee87c22013-03-06 11:00:46 -0800195 FRIEND_TEST(Config80211Test, AddLinkTest);
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800196 FRIEND_TEST(Config80211Test, BroadcastHandlerTest);
197 FRIEND_TEST(Config80211Test, MessageHandlerTest);
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800198 typedef std::map<uint32_t, NetlinkMessageHandler> MessageHandlers;
Wade Guthrie0d438532012-05-18 14:18:50 -0700199
Wade Guthriebee87c22013-03-06 11:00:46 -0800200 static const long kMaximumNewFamilyWaitSeconds;
201 static const long kMaximumNewFamilyWaitMicroSeconds;
202
203 // Returns the file descriptor of socket used to read wifi data.
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800204 int file_descriptor() const;
Wade Guthried6153612012-08-23 11:36:14 -0700205
Wade Guthrie0d438532012-05-18 14:18:50 -0700206 // EventDispatcher calls this when data is available on our socket. This
repo syncbcaa6942013-01-02 15:38:21 -0800207 // method passes each, individual, message in the input to
Wade Guthriebee87c22013-03-06 11:00:46 -0800208 // |OnNlMessageReceived|. Each part of a multipart message gets handled,
209 // individually, by this method.
repo syncbcaa6942013-01-02 15:38:21 -0800210 void OnRawNlMessageReceived(InputData *data);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700211
212 // This method processes a message from |OnRawNlMessageReceived| by passing
213 // the message to either the Config80211 callback that matches the sequence
214 // number of the message or, if there isn't one, to all of the default
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800215 // Config80211 callbacks in |broadcast_handlers_|.
repo syncbcaa6942013-01-02 15:38:21 -0800216 void OnNlMessageReceived(nlmsghdr *msg);
217
218 // Called by InputHandler on exceptional events.
219 void OnReadError(const Error &error);
Wade Guthrie0d438532012-05-18 14:18:50 -0700220
Wade Guthriebee87c22013-03-06 11:00:46 -0800221 // Just for tests, this method turns off WiFi and clears the subscribed
222 // events list. If |full| is true, also clears state set by Init.
Darin Petkovd5818382013-01-28 16:27:07 +0100223 void Reset(bool full);
Wade Guthried6153612012-08-23 11:36:14 -0700224
Wade Guthriebee87c22013-03-06 11:00:46 -0800225 // Handles a CTRL_CMD_NEWFAMILY message from the kernel.
226 void OnNewFamilyMessage(const NetlinkMessage &message);
227
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800228 // Config80211 Handlers, OnRawNlMessageReceived invokes each of these
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700229 // User-supplied callback object when _it_ gets called to read libnl data.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800230 std::list<NetlinkMessageHandler> broadcast_handlers_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700231
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700232 // Message-specific callbacks, mapped by message ID.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800233 MessageHandlers message_handlers_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700234
Wade Guthrie0d438532012-05-18 14:18:50 -0700235 // Hooks needed to be called by shill's EventDispatcher.
236 EventDispatcher *dispatcher_;
237 base::WeakPtrFactory<Config80211> weak_ptr_factory_;
repo syncbcaa6942013-01-02 15:38:21 -0800238 base::Callback<void(InputData *)> dispatcher_callback_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700239 scoped_ptr<IOHandler> dispatcher_handler_;
240
Wade Guthriecc53f232013-03-05 13:22:23 -0800241 NetlinkSocket *sock_;
Wade Guthriebee87c22013-03-06 11:00:46 -0800242 std::map<const std::string, MessageType> message_types_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700243
244 DISALLOW_COPY_AND_ASSIGN(Config80211);
245};
246
Wade Guthrie0d438532012-05-18 14:18:50 -0700247} // namespace shill
248
249#endif // SHILL_CONFIG80211_H_