blob: a65ad6bb6aba06e409c95c0461ea3affc6efb750 [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//
Wade Guthriebb9fca22013-04-10 17:21:42 -070052// NetlinkManager *netlink_manager = NetlinkManager::GetInstance();
53// netlink_manager->SendMessage(&msg, Bind(&SomeClass::MyMessageHandler));
Wade Guthriebee87c22013-03-06 11:00:46 -080054//
Wade Guthriebb9fca22013-04-10 17:21:42 -070055// NetlinkManager will then save your handler and send your message. When a
Wade Guthriebee87c22013-03-06 11:00:46 -080056// response to your message arrives, it'll call your handler.
57//
Wade Guthrie0d438532012-05-18 14:18:50 -070058
Wade Guthriebb9fca22013-04-10 17:21:42 -070059#ifndef SHILL_NETLINK_MANAGER_H_
60#define SHILL_NETLINK_MANAGER_H_
Wade Guthrie0d438532012-05-18 14:18:50 -070061
Wade Guthrieb1ec8602012-10-18 17:26:14 -070062#include <list>
Wade Guthrie0d438532012-05-18 14:18:50 -070063#include <map>
Wade Guthried6153612012-08-23 11:36:14 -070064#include <set>
Wade Guthrie0d438532012-05-18 14:18:50 -070065#include <string>
66
67#include <base/basictypes.h>
68#include <base/bind.h>
69#include <base/lazy_instance.h>
Wade Guthrieb9c3feb2013-04-25 16:31:19 -070070#include <base/memory/scoped_ptr.h>
71#include <gtest/gtest_prod.h> // for FRIEND_TEST
Wade Guthrie0d438532012-05-18 14:18:50 -070072
Wade Guthrieb9c3feb2013-04-25 16:31:19 -070073#include "shill/io_handler.h"
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070074#include "shill/netlink_message.h"
Wade Guthrie12f113a2013-03-12 17:15:46 -070075
Wade Guthrie89e6cb32013-03-07 08:03:45 -080076struct nlmsghdr;
Wade Guthrie0d438532012-05-18 14:18:50 -070077
78namespace shill {
79
repo syncbcaa6942013-01-02 15:38:21 -080080class Error;
Wade Guthrie89e6cb32013-03-07 08:03:45 -080081class EventDispatcher;
Liam McLoughlinf4baef22012-08-01 19:08:25 -070082struct InputData;
Wade Guthrie89e6cb32013-03-07 08:03:45 -080083class NetlinkSocket;
Wade Guthrie0d438532012-05-18 14:18:50 -070084
Wade Guthriebb9fca22013-04-10 17:21:42 -070085// NetlinkManager is a singleton that coordinates sending netlink messages to,
Wade Guthriebee87c22013-03-06 11:00:46 -080086// and receiving netlink messages from, the kernel. The first use of this is
87// to communicate between user-space and the cfg80211 module that manages wifi
Wade Guthriebb9fca22013-04-10 17:21:42 -070088// drivers. Bring NetlinkManager up as follows:
89// NetlinkManager *netlink_manager_ = NetlinkManager::GetInstance();
Wade Guthriebee87c22013-03-06 11:00:46 -080090// EventDispatcher dispatcher_;
Wade Guthriebb9fca22013-04-10 17:21:42 -070091// netlink_manager_->Init(); // Initialize the socket.
Wade Guthriebee87c22013-03-06 11:00:46 -080092// // Get message types for all dynamic message types.
93// Nl80211Message::SetMessageType(
Wade Guthriebb9fca22013-04-10 17:21:42 -070094// netlink_manager_->GetFamily(Nl80211Message::kMessageTypeString,
Wade Guthriebee87c22013-03-06 11:00:46 -080095// Bind(&Nl80211Message::CreateMessage)));
Wade Guthriebb9fca22013-04-10 17:21:42 -070096// netlink_manager_->Start(&dispatcher_);
97class NetlinkManager {
Wade Guthrie0d438532012-05-18 14:18:50 -070098 public:
Wade Guthrief48a1952013-03-04 17:33:47 -080099 typedef base::Callback<void(const NetlinkMessage &)> NetlinkMessageHandler;
Wade Guthrie0d438532012-05-18 14:18:50 -0700100
Wade Guthriebee87c22013-03-06 11:00:46 -0800101 // Encapsulates all the different things we know about a specific message
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700102 // type like its name, and its id.
Wade Guthriebee87c22013-03-06 11:00:46 -0800103 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 Guthriebb9fca22013-04-10 17:21:42 -0700120 // NetlinkManager is a singleton and this is the way to access it.
121 static NetlinkManager *GetInstance();
Wade Guthrie0d438532012-05-18 14:18:50 -0700122
Wade Guthriebb9fca22013-04-10 17:21:42 -0700123 // Performs non-trivial object initialization of the NetlinkManager singleton.
Wade Guthriebee87c22013-03-06 11:00:46 -0800124 bool Init();
Wade Guthrie0d438532012-05-18 14:18:50 -0700125
Wade Guthriebee87c22013-03-06 11:00:46 -0800126 // Passes the job of waiting for, and the subsequent reading from, the
127 // netlink socket to |dispatcher|.
128 void Start(EventDispatcher *dispatcher);
Wade Guthrie0d438532012-05-18 14:18:50 -0700129
Wade Guthriebee87c22013-03-06 11:00:46 -0800130 // The following methods deal with the network family table. This table
131 // associates netlink family names with family_ids (also called message
132 // types). Note that some families have static ids assigned to them but
133 // others require the kernel to resolve a string describing the family into
134 // a dynamically-determined id.
135
136 // Returns the family_id (message type) associated with |family_name|,
137 // calling the kernel if needed. Returns
138 // |NetlinkMessage::kIllegalMessageType| if the message type could not be
139 // determined. May block so |GetFamily| should be called before entering the
140 // event loop.
Wade Guthrie12f113a2013-03-12 17:15:46 -0700141 uint16_t GetFamily(std::string family_name,
142 const NetlinkMessageFactory::FactoryMethod &message_factory);
Wade Guthriebee87c22013-03-06 11:00:46 -0800143
Wade Guthriec6c81962013-03-06 15:47:13 -0800144 // Retrieves a family id (message type) given the |name| string describing
145 // the message family.
146 uint16_t GetMessageType(std::string name) const;
147
Wade Guthriebb9fca22013-04-10 17:21:42 -0700148 // Install a NetlinkManager NetlinkMessageHandler. The handler is a
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800149 // user-supplied object to be called by the system for user-bound messages
150 // that do not have a corresponding messaage-specific callback.
151 // |AddBroadcastHandler| should be called before |SubscribeToEvents| since
152 // the result of this call are used for that call.
153 bool AddBroadcastHandler(const NetlinkMessageHandler &messge_handler);
Wade Guthrie0d438532012-05-18 14:18:50 -0700154
Wade Guthriebee87c22013-03-06 11:00:46 -0800155 // Uninstall a NetlinkMessage Handler.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800156 bool RemoveBroadcastHandler(const NetlinkMessageHandler &message_handler);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700157
Wade Guthriebee87c22013-03-06 11:00:46 -0800158 // Determines whether a handler is in the list of broadcast handlers.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800159 bool FindBroadcastHandler(const NetlinkMessageHandler &message_handler) const;
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700160
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800161 // Uninstall all broadcast netlink message handlers.
162 void ClearBroadcastHandlers();
Wade Guthrie0d438532012-05-18 14:18:50 -0700163
Wade Guthriebb9fca22013-04-10 17:21:42 -0700164 // Sends a netlink message to the kernel using the NetlinkManager socket after
Wade Guthriebee87c22013-03-06 11:00:46 -0800165 // installing a handler to deal with the kernel's response to the message.
Wade Guthrie5d53d492012-11-07 09:53:31 -0800166 // TODO(wdg): Eventually, this should also include a timeout and a callback
167 // to call in case of timeout.
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700168 virtual bool SendMessage(NetlinkMessage *message,
169 const NetlinkMessageHandler &message_handler);
Wade Guthrie5d53d492012-11-07 09:53:31 -0800170
Wade Guthriebee87c22013-03-06 11:00:46 -0800171 // Uninstall the handler for a specific netlink message.
Wade Guthrief48a1952013-03-04 17:33:47 -0800172 bool RemoveMessageHandler(const NetlinkMessage &message);
Wade Guthrie0d438532012-05-18 14:18:50 -0700173
Wade Guthried6153612012-08-23 11:36:14 -0700174 // Sign-up to receive and log multicast events of a specific type (once wifi
175 // is up).
Wade Guthriebee87c22013-03-06 11:00:46 -0800176 bool SubscribeToEvents(const std::string &family, const std::string &group);
Wade Guthried6153612012-08-23 11:36:14 -0700177
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800178 // Gets the next sequence number for a NetlinkMessage to be sent over
Wade Guthriebb9fca22013-04-10 17:21:42 -0700179 // NetlinkManager's netlink socket.
Wade Guthriebdcdaa72013-03-04 12:47:12 -0800180 uint32_t GetSequenceNumber();
181
Wade Guthrie0d438532012-05-18 14:18:50 -0700182 protected:
Wade Guthriebb9fca22013-04-10 17:21:42 -0700183 friend struct base::DefaultLazyInstanceTraits<NetlinkManager>;
Wade Guthrie0d438532012-05-18 14:18:50 -0700184
Wade Guthriebb9fca22013-04-10 17:21:42 -0700185 explicit NetlinkManager();
Wade Guthrie0d438532012-05-18 14:18:50 -0700186
187 private:
Wade Guthriebb9fca22013-04-10 17:21:42 -0700188 friend class NetlinkManagerTest;
Wade Guthrie12f113a2013-03-12 17:15:46 -0700189 friend class NetlinkMessageTest;
Darin Petkovd5818382013-01-28 16:27:07 +0100190 friend class ShillDaemonTest;
Wade Guthriebb9fca22013-04-10 17:21:42 -0700191 FRIEND_TEST(NetlinkManagerTest, AddLinkTest);
192 FRIEND_TEST(NetlinkManagerTest, BroadcastHandlerTest);
193 FRIEND_TEST(NetlinkManagerTest, MessageHandlerTest);
Wade Guthrie12f113a2013-03-12 17:15:46 -0700194 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_TRIGGER_SCAN);
195 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_NEW_SCAN_RESULTS);
196 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_NEW_STATION);
197 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_AUTHENTICATE);
198 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_ASSOCIATE);
199 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_CONNECT);
200 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_DEAUTHENTICATE);
201 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_DISCONNECT);
202 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_NOTIFY_CQM);
203 FRIEND_TEST(NetlinkMessageTest, Parse_NL80211_CMD_DISASSOCIATE);
204
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800205 typedef std::map<uint32_t, NetlinkMessageHandler> MessageHandlers;
Wade Guthrie0d438532012-05-18 14:18:50 -0700206
Wade Guthriebee87c22013-03-06 11:00:46 -0800207 static const long kMaximumNewFamilyWaitSeconds;
208 static const long kMaximumNewFamilyWaitMicroSeconds;
209
210 // Returns the file descriptor of socket used to read wifi data.
Wade Guthrie89e6cb32013-03-07 08:03:45 -0800211 int file_descriptor() const;
Wade Guthried6153612012-08-23 11:36:14 -0700212
Wade Guthrie0d438532012-05-18 14:18:50 -0700213 // EventDispatcher calls this when data is available on our socket. This
repo syncbcaa6942013-01-02 15:38:21 -0800214 // method passes each, individual, message in the input to
Wade Guthriebee87c22013-03-06 11:00:46 -0800215 // |OnNlMessageReceived|. Each part of a multipart message gets handled,
216 // individually, by this method.
repo syncbcaa6942013-01-02 15:38:21 -0800217 void OnRawNlMessageReceived(InputData *data);
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700218
219 // This method processes a message from |OnRawNlMessageReceived| by passing
Wade Guthriebb9fca22013-04-10 17:21:42 -0700220 // the message to either the NetlinkManager callback that matches the sequence
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700221 // number of the message or, if there isn't one, to all of the default
Wade Guthriebb9fca22013-04-10 17:21:42 -0700222 // NetlinkManager callbacks in |broadcast_handlers_|.
repo syncbcaa6942013-01-02 15:38:21 -0800223 void OnNlMessageReceived(nlmsghdr *msg);
224
225 // Called by InputHandler on exceptional events.
226 void OnReadError(const Error &error);
Wade Guthrie0d438532012-05-18 14:18:50 -0700227
Wade Guthriebee87c22013-03-06 11:00:46 -0800228 // Just for tests, this method turns off WiFi and clears the subscribed
229 // events list. If |full| is true, also clears state set by Init.
Darin Petkovd5818382013-01-28 16:27:07 +0100230 void Reset(bool full);
Wade Guthried6153612012-08-23 11:36:14 -0700231
Wade Guthriebee87c22013-03-06 11:00:46 -0800232 // Handles a CTRL_CMD_NEWFAMILY message from the kernel.
233 void OnNewFamilyMessage(const NetlinkMessage &message);
234
Wade Guthriebb9fca22013-04-10 17:21:42 -0700235 // NetlinkManager Handlers, OnRawNlMessageReceived invokes each of these
Wade Guthrieb1ec8602012-10-18 17:26:14 -0700236 // User-supplied callback object when _it_ gets called to read libnl data.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800237 std::list<NetlinkMessageHandler> broadcast_handlers_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700238
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700239 // Message-specific callbacks, mapped by message ID.
Wade Guthrie71cb0a72013-02-27 10:27:18 -0800240 MessageHandlers message_handlers_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700241
Wade Guthrie0d438532012-05-18 14:18:50 -0700242 // Hooks needed to be called by shill's EventDispatcher.
243 EventDispatcher *dispatcher_;
Wade Guthriebb9fca22013-04-10 17:21:42 -0700244 base::WeakPtrFactory<NetlinkManager> weak_ptr_factory_;
repo syncbcaa6942013-01-02 15:38:21 -0800245 base::Callback<void(InputData *)> dispatcher_callback_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700246 scoped_ptr<IOHandler> dispatcher_handler_;
247
Wade Guthriecc53f232013-03-05 13:22:23 -0800248 NetlinkSocket *sock_;
Wade Guthriebee87c22013-03-06 11:00:46 -0800249 std::map<const std::string, MessageType> message_types_;
Wade Guthrie12f113a2013-03-12 17:15:46 -0700250 NetlinkMessageFactory message_factory_;
Wade Guthrie0d438532012-05-18 14:18:50 -0700251
Wade Guthriebb9fca22013-04-10 17:21:42 -0700252 DISALLOW_COPY_AND_ASSIGN(NetlinkManager);
Wade Guthrie0d438532012-05-18 14:18:50 -0700253};
254
Wade Guthrie0d438532012-05-18 14:18:50 -0700255} // namespace shill
256
Wade Guthriebb9fca22013-04-10 17:21:42 -0700257#endif // SHILL_NETLINK_MANAGER_H_