// // Copyright (C) 2013 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef SHILL_NET_GENERIC_NETLINK_MESSAGE_H_ #define SHILL_NET_GENERIC_NETLINK_MESSAGE_H_ #include "shill/net/attribute_list.h" #include "shill/net/byte_string.h" #include "shill/net/netlink_message.h" #include "shill/net/shill_export.h" namespace shill { class NetlinkPacket; // Objects of the |GenericNetlinkMessage| type represent messages that contain // a |genlmsghdr| after a |nlmsghdr|. These messages seem to all contain a // payload that consists of a list of structured attributes (it's possible that // some messages might have a genlmsghdr and a different kind of payload but I // haven't seen one, yet). The genlmsghdr contains a command id that, when // combined with the family_id (from the nlmsghdr), describes the ultimate use // for the netlink message. // // An attribute contains a header and a chunk of data. The header contains an // id which is an enumerated value that describes the use of the attribute's // data (the datatype of the attribute's data is implied by the attribute id) // and the length of the header+data in bytes. The attribute id is, // confusingly, called the type (or nla_type -- this is _not_ the data type of // the attribute). Each family defines the meaning of the nla_types in the // context of messages in that family (for example, the nla_type with the // value 3 will always mean the same thing for attributes in the same family). // EXCEPTION: Some attributes are nested (that is, they contain a list of other // attributes rather than a single value). Each nested attribute defines the // meaning of the nla_types in the context of attributes that are nested under // this attribute (for example, the nla_type with the value 3 will have a // different meaning when nested under another attribute -- that meaning is // defined by the attribute under which it is nested). Fun. // // The GenericNetlink messages look like this: // // -----+-----+-+-------------------------------------------------+-+-- // ... | | | message payload | | // | | +------+-+----------------------------------------+ | // | nl | | | | attributes | | // | msg |p| genl |p+-----------+-+---------+-+--------+-----+p| ... // | hdr |a| msg |a| struct |p| attrib |p| struct | ... |a| // | |d| hdr |d| nlattr |a| payload |a| nlattr | |d| // | | | | | |d| |d| | | | // -----+-----+-+------+-+-----------+-+---------+-+--------+-----+-+-- // | ^ | | // |<-NLA_HDRLEN->| | | // |<-----hdr.nla_len----->| | // |<NLA_ALIGN(hdr.nla_len)->| class SHILL_EXPORT GenericNetlinkMessage : public NetlinkMessage { public: GenericNetlinkMessage(uint16_t my_message_type, uint8_t command, const char* command_string) : NetlinkMessage(my_message_type), attributes_(new AttributeList), command_(command), command_string_(command_string) {} ~GenericNetlinkMessage() override {} ByteString Encode(uint32_t sequence_number) override; uint8_t command() const { return command_; } const char* command_string() const { return command_string_; } AttributeListConstRefPtr const_attributes() const { return attributes_; } AttributeListRefPtr attributes() { return attributes_; } void Print(int header_log_level, int detail_log_level) const override; protected: // Returns a string of bytes representing _both_ an |nlmsghdr| and a // |genlmsghdr|, filled-in, and its padding. ByteString EncodeHeader(uint32_t sequence_number) override; // Reads the |nlmsghdr| and |genlmsghdr| headers and consumes the latter // from the payload of |packet|. bool InitAndStripHeader(NetlinkPacket* packet) override; AttributeListRefPtr attributes_; const uint8_t command_; const char* command_string_; private: DISALLOW_COPY_AND_ASSIGN(GenericNetlinkMessage); }; // Control Messages class SHILL_EXPORT ControlNetlinkMessage : public GenericNetlinkMessage { public: static const uint16_t kMessageType; ControlNetlinkMessage(uint8_t command, const char* command_string) : GenericNetlinkMessage(kMessageType, command, command_string) {} static uint16_t GetMessageType() { return kMessageType; } bool InitFromPacket(NetlinkPacket* packet, MessageContext context); // Message factory for all types of Control netlink message. static NetlinkMessage* CreateMessage(const NetlinkPacket& packet); private: DISALLOW_COPY_AND_ASSIGN(ControlNetlinkMessage); }; class SHILL_EXPORT NewFamilyMessage : public ControlNetlinkMessage { public: static const uint8_t kCommand; static const char kCommandString[]; NewFamilyMessage() : ControlNetlinkMessage(kCommand, kCommandString) {} private: DISALLOW_COPY_AND_ASSIGN(NewFamilyMessage); }; class SHILL_EXPORT GetFamilyMessage : public ControlNetlinkMessage { public: static const uint8_t kCommand; static const char kCommandString[]; GetFamilyMessage(); private: DISALLOW_COPY_AND_ASSIGN(GetFamilyMessage); }; class SHILL_EXPORT UnknownControlMessage : public ControlNetlinkMessage { public: explicit UnknownControlMessage(uint8_t command) : ControlNetlinkMessage(command, "<UNKNOWN CONTROL MESSAGE>"), command_(command) {} private: uint8_t command_; DISALLOW_COPY_AND_ASSIGN(UnknownControlMessage); }; } // namespace shill #endif // SHILL_NET_GENERIC_NETLINK_MESSAGE_H_