1//
2// Copyright (C) 2013 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#ifndef SHILL_NET_GENERIC_NETLINK_MESSAGE_H_
18#define SHILL_NET_GENERIC_NETLINK_MESSAGE_H_
19
20#include "shill/net/attribute_list.h"
21#include "shill/net/byte_string.h"
22#include "shill/net/netlink_message.h"
23#include "shill/net/shill_export.h"
24
25namespace shill {
26
27class NetlinkPacket;
28
29// Objects of the |GenericNetlinkMessage| type represent messages that contain
30// a |genlmsghdr| after a |nlmsghdr|.  These messages seem to all contain a
31// payload that consists of a list of structured attributes (it's possible that
32// some messages might have a genlmsghdr and a different kind of payload but I
33// haven't seen one, yet).  The genlmsghdr contains a command id that, when
34// combined with the family_id (from the nlmsghdr), describes the ultimate use
35// for the netlink message.
36//
37// An attribute contains a header and a chunk of data. The header contains an
38// id which is an enumerated value that describes the use of the attribute's
39// data (the datatype of the attribute's data is implied by the attribute id)
40// and the length of the header+data in bytes.  The attribute id is,
41// confusingly, called the type (or nla_type -- this is _not_ the data type of
42// the attribute).  Each family defines the meaning of the nla_types in the
43// context of messages in that family (for example, the nla_type with the
44// value 3 will always mean the same thing for attributes in the same family).
45// EXCEPTION: Some attributes are nested (that is, they contain a list of other
46// attributes rather than a single value).  Each nested attribute defines the
47// meaning of the nla_types in the context of attributes that are nested under
48// this attribute (for example, the nla_type with the value 3 will have a
49// different meaning when nested under another attribute -- that meaning is
50// defined by the attribute under which it is nested).  Fun.
51//
52// The GenericNetlink messages look like this:
53//
54// -----+-----+-+-------------------------------------------------+-+--
55//  ... |     | |              message payload                    | |
56//      |     | +------+-+----------------------------------------+ |
57//      | nl  | |      | |                attributes              | |
58//      | msg |p| genl |p+-----------+-+---------+-+--------+-----+p| ...
59//      | hdr |a| msg  |a|  struct   |p| attrib  |p| struct | ... |a|
60//      |     |d| hdr  |d|  nlattr   |a| payload |a| nlattr |     |d|
61//      |     | |      | |           |d|         |d|        |     | |
62// -----+-----+-+------+-+-----------+-+---------+-+--------+-----+-+--
63//                       |              ^        | |
64//                       |<-NLA_HDRLEN->|        | |
65//                       |<-----hdr.nla_len----->| |
66//                       |<NLA_ALIGN(hdr.nla_len)->|
67
68class SHILL_EXPORT GenericNetlinkMessage : public NetlinkMessage {
69 public:
70  GenericNetlinkMessage(uint16_t my_message_type, uint8_t command,
71                        const char* command_string)
72      : NetlinkMessage(my_message_type),
73        attributes_(new AttributeList),
74        command_(command),
75        command_string_(command_string) {}
76  ~GenericNetlinkMessage() override {}
77
78  ByteString Encode(uint32_t sequence_number) override;
79
80  uint8_t command() const { return command_; }
81  const char* command_string() const { return command_string_; }
82  AttributeListConstRefPtr const_attributes() const { return attributes_; }
83  AttributeListRefPtr attributes() { return attributes_; }
84
85  void Print(int header_log_level, int detail_log_level) const override;
86
87 protected:
88  // Returns a string of bytes representing _both_ an |nlmsghdr| and a
89  // |genlmsghdr|, filled-in, and its padding.
90  ByteString EncodeHeader(uint32_t sequence_number) override;
91  // Reads the |nlmsghdr| and |genlmsghdr| headers and consumes the latter
92  // from the payload of |packet|.
93  bool InitAndStripHeader(NetlinkPacket* packet) override;
94
95  AttributeListRefPtr attributes_;
96  const uint8_t command_;
97  const char* command_string_;
98
99 private:
100  DISALLOW_COPY_AND_ASSIGN(GenericNetlinkMessage);
101};
102
103// Control Messages
104
105class SHILL_EXPORT ControlNetlinkMessage : public GenericNetlinkMessage {
106 public:
107  static const uint16_t kMessageType;
108  ControlNetlinkMessage(uint8_t command, const char* command_string)
109      : GenericNetlinkMessage(kMessageType, command, command_string) {}
110
111  static uint16_t GetMessageType() { return kMessageType; }
112
113  bool InitFromPacket(NetlinkPacket* packet, MessageContext context);
114
115  // Message factory for all types of Control netlink message.
116  static NetlinkMessage* CreateMessage(const NetlinkPacket& packet);
117
118 private:
119  DISALLOW_COPY_AND_ASSIGN(ControlNetlinkMessage);
120};
121
122class SHILL_EXPORT NewFamilyMessage : public ControlNetlinkMessage {
123 public:
124  static const uint8_t kCommand;
125  static const char kCommandString[];
126
127  NewFamilyMessage() : ControlNetlinkMessage(kCommand, kCommandString) {}
128
129 private:
130  DISALLOW_COPY_AND_ASSIGN(NewFamilyMessage);
131};
132
133class SHILL_EXPORT GetFamilyMessage : public ControlNetlinkMessage {
134 public:
135  static const uint8_t kCommand;
136  static const char kCommandString[];
137
138  GetFamilyMessage();
139
140 private:
141  DISALLOW_COPY_AND_ASSIGN(GetFamilyMessage);
142};
143
144class SHILL_EXPORT UnknownControlMessage : public ControlNetlinkMessage {
145 public:
146  explicit UnknownControlMessage(uint8_t command)
147      : ControlNetlinkMessage(command, "<UNKNOWN CONTROL MESSAGE>"),
148        command_(command) {}
149
150 private:
151  uint8_t command_;
152  DISALLOW_COPY_AND_ASSIGN(UnknownControlMessage);
153};
154
155}  // namespace shill
156
157#endif  // SHILL_NET_GENERIC_NETLINK_MESSAGE_H_
158