// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SHILL_RTNL_MESSAGE_H_
#define SHILL_RTNL_MESSAGE_H_

#include <unordered_map>
#include <vector>

#include <base/basictypes.h>
#include <base/stl_util.h>

#include "shill/byte_string.h"
#include "shill/ip_address.h"

struct rtattr;

namespace shill {

struct RTNLHeader;

class RTNLMessage {
 public:
  enum Type {
    kTypeUnknown,
    kTypeLink,
    kTypeAddress,
    kTypeRoute,
    kTypeRdnss,
    kTypeDnssl
  };

  enum Mode {
    kModeUnknown,
    kModeGet,
    kModeAdd,
    kModeDelete,
    kModeQuery
  };

  struct LinkStatus {
    LinkStatus()
        : type(0),
          flags(0),
          change(0) {}
    LinkStatus(unsigned int in_type,
               unsigned int in_flags,
               unsigned int in_change)
        : type(in_type),
          flags(in_flags),
          change(in_change) {}
    unsigned int type;
    unsigned int flags;
    unsigned int change;
  };

  struct AddressStatus {
    AddressStatus()
        : prefix_len(0),
          flags(0),
          scope(0) {}
    AddressStatus(unsigned char prefix_len_in,
                  unsigned char flags_in,
                  unsigned char scope_in)
        : prefix_len(prefix_len_in),
          flags(flags_in),
          scope(scope_in) {}
    unsigned char prefix_len;
    unsigned char flags;
    unsigned char scope;
  };

  struct RouteStatus {
    RouteStatus()
        : dst_prefix(0),
          src_prefix(0),
          table(0),
          protocol(0),
          scope(0),
          type(0),
          flags(0) {}
    RouteStatus(unsigned char dst_prefix_in,
                unsigned char src_prefix_in,
                unsigned char table_in,
                unsigned char protocol_in,
                unsigned char scope_in,
                unsigned char type_in,
                unsigned char flags_in)
        : dst_prefix(dst_prefix_in),
          src_prefix(src_prefix_in),
          table(table_in),
          protocol(protocol_in),
          scope(scope_in),
          type(type_in),
          flags(flags_in) {}
    unsigned char dst_prefix;
    unsigned char src_prefix;
    unsigned char table;
    unsigned char protocol;
    unsigned char scope;
    unsigned char type;
    unsigned char flags;
  };

  struct RdnssOption {
    RdnssOption()
        : lifetime(0) {}
    RdnssOption(uint32_t lifetime_in,
                std::vector<IPAddress> addresses_in)
        : lifetime(lifetime_in),
          addresses(addresses_in) {}
    uint32_t lifetime;
    std::vector<IPAddress> addresses;
  };

  // Empty constructor
  RTNLMessage();
  // Build an RTNL message from arguments
  RTNLMessage(Type type,
              Mode mode,
              unsigned int flags,
              uint32_t seq,
              uint32_t pid,
              int interface_index,
              IPAddress::Family family);

  // Parse an RTNL message.  Returns true on success.
  bool Decode(const ByteString &data);
  // Encode an RTNL message.  Returns empty ByteString on failure.
  ByteString Encode() const;
  // Reset all fields.
  void Reset();

  // Getters and setters
  Type type() const { return type_; }
  Mode mode() const { return mode_; }
  uint16_t flags() const { return flags_; }
  uint32_t seq() const { return seq_; }
  void set_seq(uint32_t seq) { seq_ = seq; }
  uint32_t pid() const { return pid_; }
  uint32_t interface_index() const { return interface_index_; }
  IPAddress::Family family() const { return family_; }

  const LinkStatus &link_status() const { return link_status_; }
  void set_link_status(const LinkStatus &link_status) {
    link_status_ = link_status;
  }
  const AddressStatus &address_status() const { return address_status_; }
  void set_address_status(const AddressStatus &address_status) {
    address_status_ = address_status;
  }
  const RouteStatus &route_status() const { return route_status_; }
  void set_route_status(const RouteStatus &route_status) {
    route_status_ = route_status;
  }
  const RdnssOption &rdnss_option() const { return rdnss_option_; }
  void set_rdnss_option(const RdnssOption &rdnss_option) {
    rdnss_option_ = rdnss_option;
  }
  // GLint hates "unsigned short", and I don't blame it, but that's the
  // type that's used in the system headers.  Use uint16_t instead and hope
  // that the conversion never ends up truncating on some strange platform.
  bool HasAttribute(uint16_t attr) const {
    return ContainsKey(attributes_, attr);
  }
  const ByteString GetAttribute(uint16_t attr) const {
    return HasAttribute(attr) ?
        attributes_.find(attr)->second : ByteString(0);
  }
  void SetAttribute(uint16_t attr, const ByteString &val) {
    attributes_[attr] = val;
  }

 private:
  bool DecodeInternal(const ByteString &msg);
  bool DecodeLink(const RTNLHeader *hdr,
                  Mode mode,
                  rtattr **attr_data,
                  int *attr_length);
  bool DecodeAddress(const RTNLHeader *hdr,
                      Mode mode,
                      rtattr **attr_data,
                      int *attr_length);
  bool DecodeRoute(const RTNLHeader *hdr,
                    Mode mode,
                    rtattr **attr_data,
                    int *attr_length);
  bool DecodeNdUserOption(const RTNLHeader *hdr,
                       Mode mode,
                       rtattr **attr_data,
                       int *attr_length);
  bool ParseRdnssOption(const uint8_t *data,
                        int length,
                        uint32_t lifetime);
  bool EncodeLink(RTNLHeader *hdr) const;
  bool EncodeAddress(RTNLHeader *hdr) const;
  bool EncodeRoute(RTNLHeader *hdr) const;

  Type type_;
  Mode mode_;
  uint16_t flags_;
  uint32_t seq_;
  uint32_t pid_;
  unsigned int interface_index_;
  IPAddress::Family family_;
  LinkStatus link_status_;
  AddressStatus address_status_;
  RouteStatus route_status_;
  RdnssOption rdnss_option_;
  std::unordered_map<uint16_t, ByteString> attributes_;

  DISALLOW_COPY_AND_ASSIGN(RTNLMessage);
};

}  // namespace shill

#endif  // SHILL_RTNL_MESSAGE_H_
