netlink/netlink-message.h
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu, 05 May 2011 09:28:21 +0200
changeset 66 2fe1f3e576c9
parent 63 model/netlink-message.h@e89dca438df6
permissions -rw-r--r--
make it somewhat build sanely

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2008 Liu Jian
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Liu Jian <liujatp@gmail.com>
 *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
 */

#ifndef NETLINK_MESSAGE_H
#define NETLINK_MESSAGE_H

#include "ns3/header.h"
#include "ns3/address.h"
#include "netlink-message-route.h"
#include "netlink-attribute.h"


namespace ns3 {
  class NetlinkPayload;
  class GeneralMessage;
  class InterfaceAddressMessage;
  class InterfaceInfoMessage;
  class RouteMessage;
  class MultipartNetlinkMessage;

/**
* \brief The Netlink message structure for an netlink packet
* 
There are three levels to a Netlink message: The general Netlink
message header, the IP service specific template, and the IP service
specific data.

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                   Netlink message header                      |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                  IP Service Template                          |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                  IP Service specific data in TLVs             |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/

  enum NetlinkMessageFlag
  {
    NETLINK_MSG_F_REQUEST = 1,  // It is request message.
    NETLINK_MSG_F_MULTI = 2,    // Multipart message, terminated by NETLINK_MSG_DONE
    NETLINK_MSG_F_ACK = 4,      // Reply with ack, with zero or error code
    NETLINK_MSG_F_ECHO = 8,     // Echo this request 

    /* Modifiers to Get request */
    NETLINK_MSG_F_ROOT = 0x100,        // specify tree root
    NETLINK_MSG_F_MATCH = 0x200,       // return all matching
    NETLINK_MSG_F_ATOMIC = 0x400,      // atomic Get =
    NETLINK_MSG_F_DUMP = (NETLINK_MSG_F_ROOT|NETLINK_MSG_F_MATCH),

    /* Modifiers to NEW request */
    NETLINK_MSG_F_REPLACE = 0x100, // Override existing = 
    NETLINK_MSG_F_EXCL = 0x200,   // Do not touch, if it exists
    NETLINK_MSG_F_CREATE = 0x400,  // Create, if it does not exist
    NETLINK_MSG_F_APPEND = 0x800,  // Add to end of list = 
  };

  enum NetlinkMessageType
  {
    NETLINK_MSG_NOOP = 0x1,          // Nothing.
    NETLINK_MSG_ERROR = 0x2,         // Error
    NETLINK_MSG_DONE = 0x3,          // End of a dump
    NETLINK_MSG_OVERRUN = 0x4,       // Data lost
    NETLINK_MSG_MIN_TYPE = 0x10,     // < 0x10: reserved control messages
  };

#define NETLINK_MSG_ALIGNTO 4
#define NETLINK_MSG_ALIGN(X)    (((X)+NETLINK_MSG_ALIGNTO-1) & ~(NETLINK_MSG_ALIGNTO-1) )

class NetlinkMessageHeader : public ObjectBase
{
public:
  NetlinkMessageHeader ();
  NetlinkMessageHeader (uint16_t type, uint16_t flags, uint32_t seq, uint32_t pid);

  static TypeId GetTypeId (void);
  virtual TypeId GetInstanceTypeId (void) const;
  void Print (std::ostream &os) const;
  uint32_t GetSerializedSize (void) const;
  void Serialize (Buffer::Iterator& start) const;
  uint32_t Deserialize (Buffer::Iterator& start);

  void SetMsgLen (uint32_t v);
  void SetMsgFlags (uint16_t v);
  void SetMsgType (uint16_t v);
  void SetMsgSeq (uint32_t v);
  void SetMsgPid (uint32_t v);
  uint32_t GetMsgLen (void) const;
  uint16_t GetMsgFlags (void) const;
  uint16_t GetMsgType (void) const;
  uint32_t GetMsgSeq (void) const;
  uint32_t GetMsgPid (void) const;

  static uint32_t GetHeaderSize ();
  uint32_t GetPayloadSize (void) const;

private:
  static const uint32_t NETLINK_MSG_HEADER_SIZE = 16; /* size of the nlmsghdr field*/
  uint32_t m_nlmsgLen;	/* Length of message including header */
  uint16_t m_nlmsgType;	/* Message content */
  uint16_t m_nlmsgFlags;	/* Additional flags */
  uint32_t m_nlmsgSeq;	/* Sequence number */
  uint32_t m_nlmsgPid;	/* Sending process PID */
};

/**
* \brief The struct nlmsgerr
*/
class NetlinkMessageError : public NetlinkPayload
{
public:
  NetlinkMessageError ();
  virtual ~NetlinkMessageError();

  static TypeId GetTypeId (void);
  virtual TypeId GetInstanceTypeId (void) const;
  virtual void Serialize (Buffer::Iterator& start) const;
  virtual uint32_t Deserialize (Buffer::Iterator& start);
  virtual void Print (std::ostream &os) const;
  virtual uint32_t GetSerializedSize (void) const;

  void SetError (int32_t v);
  int32_t GetError (void) const;
  void SetMsg(NetlinkMessageHeader v);
  NetlinkMessageHeader GetMsg (void) const;

private:
  static const int NETLINK_MSG_ERROR_SIZE = 20; /* size of the nlmsgerror field*/
  int32_t m_error;
  NetlinkMessageHeader m_msg;        
};


class NetlinkMessage : public ObjectBase
{
public:
  NetlinkMessage ();

  static TypeId GetTypeId (void);
  TypeId GetInstanceTypeId (void) const;
  void Print (std::ostream &os) const;
  uint32_t GetSerializedSize (void) const;
  void Serialize (Buffer::Iterator& start) const;
  uint32_t Deserialize (Buffer::Iterator& start);

  operator MultipartNetlinkMessage (void) const;

  uint32_t GetTotalSize (void) const;  //length of netlink message including padding
  uint32_t GetMsgSize (void) const;    //length of netlink message not including padding
  uint32_t GetPayloadSize (void) const; //length of message payload
  uint16_t GetMsgType (void) const;
  uint8_t GetFamily(void) const;

  void SetHeader (NetlinkMessageHeader hdr);
  NetlinkMessageHeader GetHeader (void) const;

  //before set message body, should set header first
  void SetErrorMessage (NetlinkMessageError errmsg);
  void SetGeneralMessage (GeneralMessage genmsg);
  void SetInterfaceInfoMessage (InterfaceInfoMessage v);
  void SetInterfaceAddressMessage (InterfaceAddressMessage v);
  void SetRouteMessage (RouteMessage v);
  NetlinkMessageError GetErrorMessage (void) const;
  GeneralMessage GetGeneralMessage (void) const;
  InterfaceInfoMessage GetInterfaceInfoMessage (void) const;
  InterfaceAddressMessage GetInterfaceAddressMessage (void) const;
  RouteMessage GetRouteMessage (void) const;

  /**
  * \returns true if type was control type, false otherwise.
  */
  static bool IsMessageNetlinkControl (uint16_t type);
  /**
  * \returns true if type was netlink route, false otherwise.
  */
  static bool IsMessageNetlinkRoute (uint16_t type);
  static bool IsMessageAddress (uint16_t type);
  static bool IsMessageInterface (uint16_t type);
  static bool IsMessageRoute (uint16_t type);
  /**
  * \returns true if type was GETxxx , false otherwise.
  */
  static bool IsMessageTypeGet (uint16_t type);
  /**
  * \returns true if flag has ack , false otherwise.
  */
  static bool IsMessageFlagsAck (uint16_t flags);
  /**
  * \returns true if flag has request , false otherwise.
  */
  static bool IsMessageFlagsRequest (uint16_t flags);
  /**
  * \returns true if flag has dump , false otherwise.
  */
  static bool IsMessageFlagsDump (uint16_t flags);

private:
  NetlinkMessageHeader m_hdr;

  //only one type of messages below exists in real world application
  NetlinkMessageError m_errorMessage;  
  GeneralMessage m_genmsg;
  InterfaceInfoMessage m_interfaceTemplate;
  InterfaceAddressMessage m_addressTemplate;
  RouteMessage m_routeTemplate;
};

class MultipartNetlinkMessage : public Header
{
public:
  MultipartNetlinkMessage ();

  static TypeId GetTypeId (void);
  virtual TypeId GetInstanceTypeId (void) const;
  virtual void Print (std::ostream &os) const;
  virtual uint32_t GetSerializedSize (void) const;
  virtual void Serialize (Buffer::Iterator start) const;
  virtual uint32_t Deserialize (Buffer::Iterator start);

  void AppendMessage (NetlinkMessage nlmsg);
  void Clear();
  uint32_t GetNMessages (void) const;
  NetlinkMessage GetMessage (uint32_t index) const;

private:
  std::vector<NetlinkMessage> m_netlinkMessages;
};

}; // namespace ns3

#endif /* NETLINK_MESSAGE_H */