blob: 3815bb7683f556a4c555bee5b3fd5e0a9a797f1f [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 Guthrie0ae4b8e2013-04-10 16:49:15 -0700128 virtual bool InitFromNlmsg(const nlmsghdr *const_msg);
129 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700130 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700131 std::string ToString() const;
132 uint32_t error() const { return -error_; }
133
134 private:
135 uint32_t error_;
136
137 DISALLOW_COPY_AND_ASSIGN(ErrorAckMessage);
138};
139
140
141class NoopMessage : public NetlinkMessage {
142 public:
143 static const uint16_t kMessageType;
144
145 NoopMessage() : NetlinkMessage(kMessageType) {}
146 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700147 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700148 std::string ToString() const { return "<NOOP>"; }
149
150 private:
151 DISALLOW_COPY_AND_ASSIGN(NoopMessage);
152};
153
154
155class DoneMessage : public NetlinkMessage {
156 public:
157 static const uint16_t kMessageType;
158
159 DoneMessage() : NetlinkMessage(kMessageType) {}
160 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700161 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700162 std::string ToString() const { return "<DONE with multipart message>"; }
163
164 private:
165 DISALLOW_COPY_AND_ASSIGN(DoneMessage);
166};
167
168
169class OverrunMessage : public NetlinkMessage {
170 public:
171 static const uint16_t kMessageType;
172
173 OverrunMessage() : NetlinkMessage(kMessageType) {}
174 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700175 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700176 std::string ToString() const { return "<OVERRUN - data lost>"; }
177
178 private:
179 DISALLOW_COPY_AND_ASSIGN(OverrunMessage);
180};
181
182
183class UnknownMessage : public NetlinkMessage {
184 public:
185 UnknownMessage(uint16_t message_type, ByteString message_body) :
186 NetlinkMessage(message_type), message_body_(message_body) {}
187 virtual ByteString Encode(uint32_t sequence_number);
Wade Guthrie0b1ebf12013-04-12 09:53:33 -0700188 virtual void Print(int header_log_level, int detail_log_level) const;
Wade Guthrie0ae4b8e2013-04-10 16:49:15 -0700189
190 private:
191 ByteString message_body_;
192
193 DISALLOW_COPY_AND_ASSIGN(UnknownMessage);
194};
195
196
197//
198// Factory class.
199//
200
201class NetlinkMessageFactory {
202 public:
203 typedef base::Callback<NetlinkMessage *(const nlmsghdr *msg)> FactoryMethod;
204
205 NetlinkMessageFactory() {}
206
207 // Adds a message factory for a specific message_type. Intended to be used
208 // at initialization.
209 bool AddFactoryMethod(uint16_t message_type, FactoryMethod factory);
210
211 // Ownership of the message is passed to the caller and, as such, he should
212 // delete it.
213 NetlinkMessage *CreateMessage(const nlmsghdr *msg) const;
214
215 private:
216 std::map<uint16_t, FactoryMethod> factories_;
217
218 DISALLOW_COPY_AND_ASSIGN(NetlinkMessageFactory);
219};
220
221} // namespace shill
222
223#endif // SHILL_NETLINK_MESSAGE_H_