Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 1 | // 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 Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 5 | // 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 Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 8 | // |
repo sync | bcaa694 | 2013-01-02 15:38:21 -0800 | [diff] [blame] | 9 | // [shill]--[nl80211 library, libnl_genl/libnl libraries] |
| 10 | // | |
| 11 | // (netlink socket) |
| 12 | // | |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 13 | // [cfg80211 kernel module] |
repo sync | bcaa694 | 2013-01-02 15:38:21 -0800 | [diff] [blame] | 14 | // | |
| 15 | // [mac80211 drivers] |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 16 | // |
| 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 Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 58 | |
| 59 | #ifndef SHILL_CONFIG80211_H_ |
| 60 | #define SHILL_CONFIG80211_H_ |
| 61 | |
Wade Guthrie | 5d3d6de | 2012-11-02 11:08:34 -0700 | [diff] [blame] | 62 | #include <gtest/gtest_prod.h> // for FRIEND_TEST |
| 63 | |
Wade Guthrie | b1ec860 | 2012-10-18 17:26:14 -0700 | [diff] [blame] | 64 | #include <list> |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 65 | #include <map> |
Wade Guthrie | d615361 | 2012-08-23 11:36:14 -0700 | [diff] [blame] | 66 | #include <set> |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 67 | #include <string> |
| 68 | |
| 69 | #include <base/basictypes.h> |
| 70 | #include <base/bind.h> |
| 71 | #include <base/lazy_instance.h> |
| 72 | |
Wade Guthrie | 89e6cb3 | 2013-03-07 08:03:45 -0800 | [diff] [blame^] | 73 | struct nlmsghdr; |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 74 | |
| 75 | namespace shill { |
| 76 | |
repo sync | bcaa694 | 2013-01-02 15:38:21 -0800 | [diff] [blame] | 77 | class Error; |
Wade Guthrie | 89e6cb3 | 2013-03-07 08:03:45 -0800 | [diff] [blame^] | 78 | class EventDispatcher; |
Liam McLoughlin | f4baef2 | 2012-08-01 19:08:25 -0700 | [diff] [blame] | 79 | struct InputData; |
Wade Guthrie | 89e6cb3 | 2013-03-07 08:03:45 -0800 | [diff] [blame^] | 80 | class IOHandler; |
Wade Guthrie | f48a195 | 2013-03-04 17:33:47 -0800 | [diff] [blame] | 81 | class NetlinkMessage; |
Wade Guthrie | 89e6cb3 | 2013-03-07 08:03:45 -0800 | [diff] [blame^] | 82 | class NetlinkSocket; |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 83 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 84 | // 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 Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 96 | class Config80211 { |
| 97 | public: |
Wade Guthrie | f48a195 | 2013-03-04 17:33:47 -0800 | [diff] [blame] | 98 | typedef base::Callback<void(const NetlinkMessage &)> NetlinkMessageHandler; |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 99 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 100 | // 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 Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 111 | }; |
| 112 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 113 | // 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 Guthrie | d615361 | 2012-08-23 11:36:14 -0700 | [diff] [blame] | 120 | // This represents whether the cfg80211/mac80211 are installed in the kernel. |
| 121 | enum WifiState { |
Wade Guthrie | d4977f2 | 2012-08-22 12:37:54 -0700 | [diff] [blame] | 122 | kWifiUp, |
| 123 | kWifiDown |
Wade Guthrie | d615361 | 2012-08-23 11:36:14 -0700 | [diff] [blame] | 124 | }; |
| 125 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 126 | // Config80211 is a singleton and this is the way to access it. |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 127 | static Config80211 *GetInstance(); |
| 128 | |
| 129 | // Performs non-trivial object initialization of the Config80211 singleton. |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 130 | bool Init(); |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 131 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 132 | // Passes the job of waiting for, and the subsequent reading from, the |
| 133 | // netlink socket to |dispatcher|. |
| 134 | void Start(EventDispatcher *dispatcher); |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 135 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 136 | // 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 Guthrie | c6c8196 | 2013-03-06 15:47:13 -0800 | [diff] [blame] | 149 | // 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 Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 153 | // Install a Config80211 NetlinkMessageHandler. The handler is a |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 154 | // 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 Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 159 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 160 | // Uninstall a NetlinkMessage Handler. |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 161 | bool RemoveBroadcastHandler(const NetlinkMessageHandler &message_handler); |
Wade Guthrie | b1ec860 | 2012-10-18 17:26:14 -0700 | [diff] [blame] | 162 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 163 | // Determines whether a handler is in the list of broadcast handlers. |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 164 | bool FindBroadcastHandler(const NetlinkMessageHandler &message_handler) const; |
Wade Guthrie | b1ec860 | 2012-10-18 17:26:14 -0700 | [diff] [blame] | 165 | |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 166 | // Uninstall all broadcast netlink message handlers. |
| 167 | void ClearBroadcastHandlers(); |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 168 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 169 | // 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 Guthrie | 5d53d49 | 2012-11-07 09:53:31 -0800 | [diff] [blame] | 171 | // TODO(wdg): Eventually, this should also include a timeout and a callback |
| 172 | // to call in case of timeout. |
Wade Guthrie | f48a195 | 2013-03-04 17:33:47 -0800 | [diff] [blame] | 173 | bool SendMessage(NetlinkMessage *message, const NetlinkMessageHandler |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 174 | &message_handler); |
Wade Guthrie | 5d53d49 | 2012-11-07 09:53:31 -0800 | [diff] [blame] | 175 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 176 | // Uninstall the handler for a specific netlink message. |
Wade Guthrie | f48a195 | 2013-03-04 17:33:47 -0800 | [diff] [blame] | 177 | bool RemoveMessageHandler(const NetlinkMessage &message); |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 178 | |
Wade Guthrie | d615361 | 2012-08-23 11:36:14 -0700 | [diff] [blame] | 179 | // Sign-up to receive and log multicast events of a specific type (once wifi |
| 180 | // is up). |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 181 | bool SubscribeToEvents(const std::string &family, const std::string &group); |
Wade Guthrie | d615361 | 2012-08-23 11:36:14 -0700 | [diff] [blame] | 182 | |
Wade Guthrie | bdcdaa7 | 2013-03-04 12:47:12 -0800 | [diff] [blame] | 183 | // Gets the next sequence number for a NetlinkMessage to be sent over |
| 184 | // Config80211's netlink socket. |
| 185 | uint32_t GetSequenceNumber(); |
| 186 | |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 187 | protected: |
| 188 | friend struct base::DefaultLazyInstanceTraits<Config80211>; |
| 189 | |
| 190 | explicit Config80211(); |
| 191 | |
| 192 | private: |
| 193 | friend class Config80211Test; |
Darin Petkov | d581838 | 2013-01-28 16:27:07 +0100 | [diff] [blame] | 194 | friend class ShillDaemonTest; |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 195 | FRIEND_TEST(Config80211Test, AddLinkTest); |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 196 | FRIEND_TEST(Config80211Test, BroadcastHandlerTest); |
| 197 | FRIEND_TEST(Config80211Test, MessageHandlerTest); |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 198 | typedef std::map<uint32_t, NetlinkMessageHandler> MessageHandlers; |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 199 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 200 | static const long kMaximumNewFamilyWaitSeconds; |
| 201 | static const long kMaximumNewFamilyWaitMicroSeconds; |
| 202 | |
| 203 | // Returns the file descriptor of socket used to read wifi data. |
Wade Guthrie | 89e6cb3 | 2013-03-07 08:03:45 -0800 | [diff] [blame^] | 204 | int file_descriptor() const; |
Wade Guthrie | d615361 | 2012-08-23 11:36:14 -0700 | [diff] [blame] | 205 | |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 206 | // EventDispatcher calls this when data is available on our socket. This |
repo sync | bcaa694 | 2013-01-02 15:38:21 -0800 | [diff] [blame] | 207 | // method passes each, individual, message in the input to |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 208 | // |OnNlMessageReceived|. Each part of a multipart message gets handled, |
| 209 | // individually, by this method. |
repo sync | bcaa694 | 2013-01-02 15:38:21 -0800 | [diff] [blame] | 210 | void OnRawNlMessageReceived(InputData *data); |
Wade Guthrie | b1ec860 | 2012-10-18 17:26:14 -0700 | [diff] [blame] | 211 | |
| 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 Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 215 | // Config80211 callbacks in |broadcast_handlers_|. |
repo sync | bcaa694 | 2013-01-02 15:38:21 -0800 | [diff] [blame] | 216 | void OnNlMessageReceived(nlmsghdr *msg); |
| 217 | |
| 218 | // Called by InputHandler on exceptional events. |
| 219 | void OnReadError(const Error &error); |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 220 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 221 | // 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 Petkov | d581838 | 2013-01-28 16:27:07 +0100 | [diff] [blame] | 223 | void Reset(bool full); |
Wade Guthrie | d615361 | 2012-08-23 11:36:14 -0700 | [diff] [blame] | 224 | |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 225 | // Handles a CTRL_CMD_NEWFAMILY message from the kernel. |
| 226 | void OnNewFamilyMessage(const NetlinkMessage &message); |
| 227 | |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 228 | // Config80211 Handlers, OnRawNlMessageReceived invokes each of these |
Wade Guthrie | b1ec860 | 2012-10-18 17:26:14 -0700 | [diff] [blame] | 229 | // User-supplied callback object when _it_ gets called to read libnl data. |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 230 | std::list<NetlinkMessageHandler> broadcast_handlers_; |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 231 | |
Wade Guthrie | 5d3d6de | 2012-11-02 11:08:34 -0700 | [diff] [blame] | 232 | // Message-specific callbacks, mapped by message ID. |
Wade Guthrie | 71cb0a7 | 2013-02-27 10:27:18 -0800 | [diff] [blame] | 233 | MessageHandlers message_handlers_; |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 234 | |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 235 | // Hooks needed to be called by shill's EventDispatcher. |
| 236 | EventDispatcher *dispatcher_; |
| 237 | base::WeakPtrFactory<Config80211> weak_ptr_factory_; |
repo sync | bcaa694 | 2013-01-02 15:38:21 -0800 | [diff] [blame] | 238 | base::Callback<void(InputData *)> dispatcher_callback_; |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 239 | scoped_ptr<IOHandler> dispatcher_handler_; |
| 240 | |
Wade Guthrie | cc53f23 | 2013-03-05 13:22:23 -0800 | [diff] [blame] | 241 | NetlinkSocket *sock_; |
Wade Guthrie | bee87c2 | 2013-03-06 11:00:46 -0800 | [diff] [blame] | 242 | std::map<const std::string, MessageType> message_types_; |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 243 | |
| 244 | DISALLOW_COPY_AND_ASSIGN(Config80211); |
| 245 | }; |
| 246 | |
Wade Guthrie | 0d43853 | 2012-05-18 14:18:50 -0700 | [diff] [blame] | 247 | } // namespace shill |
| 248 | |
| 249 | #endif // SHILL_CONFIG80211_H_ |