blob: afc9a089dddae5fb7773ede94dde3f17eb5fed4d [file] [log] [blame]
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -07001// Copyright (c) 2013 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#ifndef SHILL_NETLINK_MESSAGE_H_
6#define SHILL_NETLINK_MESSAGE_H_
7
8#include <map>
9#include <string>
10
11#include <base/bind.h>
12
13#include <gtest/gtest.h> // for FRIEND_TEST.
14
15#include "shill/byte_string.h"
16
17struct nlmsghdr;
18
19namespace shill {
20
21// Netlink messages are sent over netlink sockets to talk between user-space
22// programs (like shill) and kernel modules (like the cfg80211 module). Each
23// kernel module that talks netlink potentially adds its own family header to
24// the nlmsghdr (the top-level netlink message header) and, potentially, uses a
25// different payload format. The NetlinkMessage class represents that which
26// is common between the different types of netlink message.
27//
28// The common portions of Netlink Messages start with a |nlmsghdr|. Those
29// messages look something like the following (the functions, macros, and
30// datatypes described are provided by libnl -- see also
31// http://www.infradead.org/~tgr/libnl/doc/core.html):
32//
33// |<--------------nlmsg_total_size()----------->|
34// | |<------nlmsg_datalen()-------------->|
35// | | |
36// -----+-----+-+-----------------------------------+-+----
37// ... | | | netlink payload | |
38// | | +------------+-+--------------------+ |
39// | nl | | | | | | nl
40// | msg |p| (optional) |p| |p| msg ...
41// | hdr |a| family |a| family payload |a| hdr
42// | |d| header |d| |d|
43// | | | | | | |
44// -----+-----+-+------------+-+--------------------+-+----
45// ^
46// |
47// +-- nlmsg_data()
48//
49// All NetlinkMessages sent to the kernel need a valid message type (which is
50// found in the nlmsghdr structure) and all NetlinkMessages received from the
51// kernel have a valid message type. Some message types (NLMSG_NOOP,
52// NLMSG_ERROR, and GENL_ID_CTRL, for example) are allocated statically; for
53// those, the |message_type_| is assigned directly.
54//
55// Other message types ("nl80211", for example), are assigned by the kernel
56// dynamically. To get the message type, pass a closure to assign the
Wade Guthriebb9fca22013-04-10 17:21:42 -070057// message_type along with the sting to NetlinkManager::GetFamily:
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070058//
Wade Guthriebb9fca22013-04-10 17:21:42 -070059// nl80211_type = netlink_manager->GetFamily(Nl80211Message::kMessageType);
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070060//
61// Do all of this before you start to create NetlinkMessages so that
62// NetlinkMessage can be instantiated with a valid |message_type_|.
63
64class NetlinkMessage {
65 public:
66 static const uint32_t kBroadcastSequenceNumber;
67 static const uint16_t kIllegalMessageType;
68
69 explicit NetlinkMessage(uint16_t message_type) :
70 flags_(0), message_type_(message_type),
71 sequence_number_(kBroadcastSequenceNumber) {}
72 virtual ~NetlinkMessage() {}
73
74 // Returns a string of bytes representing the message (with it headers) and
75 // any necessary padding. These bytes are appropriately formatted to be
76 // written to a netlink socket.
77 virtual ByteString Encode(uint32_t sequence_number) = 0;
78
79 // Initializes the |NetlinkMessage| from a complete and legal message
80 // (potentially received from the kernel via a netlink socket).
81 virtual bool InitFromNlmsg(const nlmsghdr *msg);
82
83 uint16_t message_type() const { return message_type_; }
84 void AddFlag(uint16_t new_flag) { flags_ |= new_flag; }
85 uint16_t flags() const { return flags_; }
86 uint32_t sequence_number() const { return sequence_number_; }
Wade Guthrie0b1ebf12013-04-12 09:53:33 -070087 // Logs the message. Allows a different log level (presumably more
88 // stringent) for the body of the message than the header.
89 virtual void Print(int header_log_level, int detail_log_level) const = 0;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070090
91 // Logs the message's raw bytes (with minimal interpretation).
92 static void PrintBytes(int log_level, const unsigned char *buf,
93 size_t num_bytes);
94
95 protected:
Wade Guthriebb9fca22013-04-10 17:21:42 -070096 friend class NetlinkManagerTest;
97 FRIEND_TEST(NetlinkManagerTest, NL80211_CMD_NOTIFY_CQM);
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -070098
99 // Returns a string of bytes representing an |nlmsghdr|, filled-in, and its
100 // padding.
101 virtual ByteString EncodeHeader(uint32_t sequence_number);
102 // Reads the |nlmsghdr| and removes it from |input|.
103 virtual bool InitAndStripHeader(ByteString *input);
104
105 uint16_t flags_;
106 uint16_t message_type_;
107 uint32_t sequence_number_;
108
109 private:
110 DISALLOW_COPY_AND_ASSIGN(NetlinkMessage);
111};
112
113
114// The Error and Ack messages are received from the kernel and are combined,
115// here, because they look so much alike (the only difference is that the
116// error code is 0 for the Ack messages). Error messages are received from
117// the kernel in response to a sent message when there's a problem (such as
118// a malformed message or a busy kernel module). Ack messages are received
119// from the kernel when a sent message has the NLM_F_ACK flag set, indicating
120// that an Ack is requested.
121class ErrorAckMessage : public NetlinkMessage {
122 public:
123 static const uint16_t kMessageType;
124
125 ErrorAckMessage() : NetlinkMessage(kMessageType), error_(0) {}
Wade Guthrie5a4e2ef2013-04-30 12:51:39 -0700126 explicit ErrorAckMessage(uint32_t err)
127 : NetlinkMessage(kMessageType), error_(err) {}
Wade Guthrie7347bf22013-04-30 11:21:51 -0700128 static uint16_t GetMessageType() { return kMessageType; }
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700129 virtual bool InitFromNlmsg(const nlmsghdr *const_msg);
130 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700131 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700132 std::string ToString() const;
133 uint32_t error() const { return -error_; }
134
135 private:
136 uint32_t error_;
137
138 DISALLOW_COPY_AND_ASSIGN(ErrorAckMessage);
139};
140
141
142class NoopMessage : public NetlinkMessage {
143 public:
144 static const uint16_t kMessageType;
145
146 NoopMessage() : NetlinkMessage(kMessageType) {}
Wade Guthrie7347bf22013-04-30 11:21:51 -0700147 static uint16_t GetMessageType() { return kMessageType; }
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700148 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700149 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700150 std::string ToString() const { return "<NOOP>"; }
151
152 private:
153 DISALLOW_COPY_AND_ASSIGN(NoopMessage);
154};
155
156
157class DoneMessage : public NetlinkMessage {
158 public:
159 static const uint16_t kMessageType;
160
161 DoneMessage() : NetlinkMessage(kMessageType) {}
Wade Guthrie7347bf22013-04-30 11:21:51 -0700162 static uint16_t GetMessageType() { return kMessageType; }
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700163 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700164 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700165 std::string ToString() const { return "<DONE with multipart message>"; }
166
167 private:
168 DISALLOW_COPY_AND_ASSIGN(DoneMessage);
169};
170
171
172class OverrunMessage : public NetlinkMessage {
173 public:
174 static const uint16_t kMessageType;
175
176 OverrunMessage() : NetlinkMessage(kMessageType) {}
Wade Guthrie7347bf22013-04-30 11:21:51 -0700177 static uint16_t GetMessageType() { return kMessageType; }
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700178 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700179 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700180 std::string ToString() const { return "<OVERRUN - data lost>"; }
181
182 private:
183 DISALLOW_COPY_AND_ASSIGN(OverrunMessage);
184};
185
186
187class UnknownMessage : public NetlinkMessage {
188 public:
189 UnknownMessage(uint16_t message_type, ByteString message_body) :
190 NetlinkMessage(message_type), message_body_(message_body) {}
191 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700192 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700193
194 private:
195 ByteString message_body_;
196
197 DISALLOW_COPY_AND_ASSIGN(UnknownMessage);
198};
199
200
201//
202// Factory class.
203//
204
205class NetlinkMessageFactory {
206 public:
207 typedef base::Callback<NetlinkMessage *(const nlmsghdr *msg)> FactoryMethod;
208
209 NetlinkMessageFactory() {}
210
211 // Adds a message factory for a specific message_type. Intended to be used
212 // at initialization.
213 bool AddFactoryMethod(uint16_t message_type, FactoryMethod factory);
214
215 // Ownership of the message is passed to the caller and, as such, he should
216 // delete it.
217 NetlinkMessage *CreateMessage(const nlmsghdr *msg) const;
218
219 private:
220 std::map<uint16_t, FactoryMethod> factories_;
221
222 DISALLOW_COPY_AND_ASSIGN(NetlinkMessageFactory);
223};
224
225} // namespace shill
226
227#endif // SHILL_NETLINK_MESSAGE_H_