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 
25 namespace shill {
26 
27 class 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 
68 class SHILL_EXPORT GenericNetlinkMessage : public NetlinkMessage {
69  public:
GenericNetlinkMessage(uint16_t my_message_type,uint8_t command,const char * command_string)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) {}
~GenericNetlinkMessage()76   ~GenericNetlinkMessage() override {}
77 
78   ByteString Encode(uint32_t sequence_number) override;
79 
command()80   uint8_t command() const { return command_; }
command_string()81   const char* command_string() const { return command_string_; }
const_attributes()82   AttributeListConstRefPtr const_attributes() const { return attributes_; }
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 
105 class SHILL_EXPORT ControlNetlinkMessage : public GenericNetlinkMessage {
106  public:
107   static const uint16_t kMessageType;
ControlNetlinkMessage(uint8_t command,const char * command_string)108   ControlNetlinkMessage(uint8_t command, const char* command_string)
109       : GenericNetlinkMessage(kMessageType, command, command_string) {}
110 
GetMessageType()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 
122 class SHILL_EXPORT NewFamilyMessage : public ControlNetlinkMessage {
123  public:
124   static const uint8_t kCommand;
125   static const char kCommandString[];
126 
NewFamilyMessage()127   NewFamilyMessage() : ControlNetlinkMessage(kCommand, kCommandString) {}
128 
129  private:
130   DISALLOW_COPY_AND_ASSIGN(NewFamilyMessage);
131 };
132 
133 class 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 
144 class SHILL_EXPORT UnknownControlMessage : public ControlNetlinkMessage {
145  public:
UnknownControlMessage(uint8_t command)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