//
// 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_