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

#include "shill/netlink_message.h"

#include <limits.h>
#include <netlink/msg.h>
#include <netlink/netlink.h>

#include <map>
#include <string>

#include <base/format_macros.h>
#include <base/stl_util.h>
#include <base/stringprintf.h>

#include "shill/logging.h"

using base::StringAppendF;
using base::StringPrintf;
using std::map;
using std::min;
using std::string;

namespace shill {

const uint32_t NetlinkMessage::kBroadcastSequenceNumber = 0;
const uint16_t NetlinkMessage::kIllegalMessageType = UINT16_MAX;

// NetlinkMessage

ByteString NetlinkMessage::EncodeHeader(uint32_t sequence_number) {
  ByteString result;
  if (message_type_ == kIllegalMessageType) {
    LOG(ERROR) << "Message type not set";
    return result;
  }
  sequence_number_ = sequence_number;
  if (sequence_number_ == kBroadcastSequenceNumber) {
    LOG(ERROR) << "Couldn't get a legal sequence number";
    return result;
  }

  // Build netlink header.
  nlmsghdr header;
  size_t nlmsghdr_with_pad = NLMSG_ALIGN(sizeof(header));
  header.nlmsg_len = nlmsghdr_with_pad;
  header.nlmsg_type = message_type_;
  header.nlmsg_flags = NLM_F_REQUEST | flags_;
  header.nlmsg_seq = sequence_number_;
  header.nlmsg_pid = getpid();

  // Netlink header + pad.
  result.Append(ByteString(reinterpret_cast<unsigned char *>(&header),
                           sizeof(header)));
  result.Resize(nlmsghdr_with_pad);  // Zero-fill pad space (if any).
  return result;
}

bool NetlinkMessage::InitAndStripHeader(ByteString *input) {
  if (!input) {
    LOG(ERROR) << "NULL input";
    return false;
  }
  if (input->GetLength() < sizeof(nlmsghdr)) {
    LOG(ERROR) << "Insufficient input to extract nlmsghdr";
    return false;
  }

  // Read the nlmsghdr.
  nlmsghdr *header = reinterpret_cast<nlmsghdr *>(input->GetData());
  message_type_ = header->nlmsg_type;
  flags_ = header->nlmsg_flags;
  sequence_number_ = header->nlmsg_seq;

  // Strip the nlmsghdr.
  input->RemovePrefix(NLMSG_ALIGN(sizeof(struct nlmsghdr)));
  return true;
}

bool NetlinkMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
  if (!const_msg) {
    LOG(ERROR) << "Null |const_msg| parameter";
    return false;
  }
  ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
                     const_msg->nlmsg_len);
  if (!InitAndStripHeader(&message)) {
    return false;
  }
  return true;
}

// static
void NetlinkMessage::PrintBytes(int log_level, const unsigned char *buf,
                                size_t num_bytes) {
  SLOG(WiFi, log_level) << "Netlink Message -- Examining Bytes";
  if (!buf) {
    SLOG(WiFi, log_level) << "<NULL Buffer>";
    return;
  }

  if (num_bytes >= sizeof(nlmsghdr)) {
      const nlmsghdr *header = reinterpret_cast<const nlmsghdr *>(buf);
      SLOG(WiFi, log_level) << StringPrintf(
          "len:          %02x %02x %02x %02x = %u bytes",
          buf[0], buf[1], buf[2], buf[3], header->nlmsg_len);

      SLOG(WiFi, log_level) << StringPrintf(
          "type | flags: %02x %02x %02x %02x - type:%u flags:%s%s%s%s%s",
          buf[4], buf[5], buf[6], buf[7], header->nlmsg_type,
          ((header->nlmsg_flags & NLM_F_REQUEST) ? " REQUEST" : ""),
          ((header->nlmsg_flags & NLM_F_MULTI) ? " MULTI" : ""),
          ((header->nlmsg_flags & NLM_F_ACK) ? " ACK" : ""),
          ((header->nlmsg_flags & NLM_F_ECHO) ? " ECHO" : ""),
          ((header->nlmsg_flags & NLM_F_DUMP_INTR) ? " BAD-SEQ" : ""));

      SLOG(WiFi, log_level) << StringPrintf(
          "sequence:     %02x %02x %02x %02x = %u",
          buf[8], buf[9], buf[10], buf[11], header->nlmsg_seq);
      SLOG(WiFi, log_level) << StringPrintf(
          "pid:          %02x %02x %02x %02x = %u",
          buf[12], buf[13], buf[14], buf[15], header->nlmsg_pid);
      buf += sizeof(nlmsghdr);
      num_bytes -= sizeof(nlmsghdr);
  } else {
    SLOG(WiFi, log_level) << "Not enough bytes (" << num_bytes
                          << ") for a complete nlmsghdr (requires "
                          << sizeof(nlmsghdr) << ").";
  }

  while (num_bytes) {
    string output;
    size_t bytes_this_row = min(num_bytes, static_cast<size_t>(32));
    for (size_t i = 0; i < bytes_this_row; ++i) {
      StringAppendF(&output, " %02x", *buf++);
    }
    SLOG(WiFi, log_level) << output;
    num_bytes -= bytes_this_row;
  }
}

// ErrorAckMessage.

const uint16_t ErrorAckMessage::kMessageType = NLMSG_ERROR;

bool ErrorAckMessage::InitFromNlmsg(const nlmsghdr *const_msg) {
  if (!const_msg) {
    LOG(ERROR) << "Null |const_msg| parameter";
    return false;
  }
  ByteString message(reinterpret_cast<const unsigned char *>(const_msg),
                     const_msg->nlmsg_len);
  if (!InitAndStripHeader(&message)) {
    return false;
  }

  // Get the error code from the payload.
  error_ = *(reinterpret_cast<const uint32_t *>(message.GetConstData()));
  return true;
}

ByteString ErrorAckMessage::Encode(uint32_t sequence_number) {
  LOG(ERROR) << "We're not supposed to send errors or Acks to the kernel";
  return ByteString();
}

string ErrorAckMessage::ToString() const {
  string output;
  if (error()) {
    StringAppendF(&output, "NETLINK_ERROR 0x%" PRIx32 ": %s",
                  -error_, strerror(-error_));
  } else {
    StringAppendF(&output, "ACK");
  }
  return output;
}

void ErrorAckMessage::Print(int header_log_level,
                            int /*detail_log_level*/) const {
  SLOG(WiFi, header_log_level) << ToString();
}

// NoopMessage.

const uint16_t NoopMessage::kMessageType = NLMSG_NOOP;

ByteString NoopMessage::Encode(uint32_t sequence_number) {
  LOG(ERROR) << "We're not supposed to send NOOP to the kernel";
  return ByteString();
}

void NoopMessage::Print(int header_log_level, int /*detail_log_level*/) const {
  SLOG(WiFi, header_log_level) << ToString();
}

// DoneMessage.

const uint16_t DoneMessage::kMessageType = NLMSG_DONE;

ByteString DoneMessage::Encode(uint32_t sequence_number) {
  return EncodeHeader(sequence_number);
}

void DoneMessage::Print(int header_log_level, int /*detail_log_level*/) const {
  SLOG(WiFi, header_log_level) << ToString();
}

// OverrunMessage.

const uint16_t OverrunMessage::kMessageType = NLMSG_OVERRUN;

ByteString OverrunMessage::Encode(uint32_t sequence_number) {
  LOG(ERROR) << "We're not supposed to send Overruns to the kernel";
  return ByteString();
}

void OverrunMessage::Print(int header_log_level,
                           int /*detail_log_level*/) const {
  SLOG(WiFi, header_log_level) << ToString();
}

// UnknownMessage.

ByteString UnknownMessage::Encode(uint32_t sequence_number) {
  LOG(ERROR) << "We're not supposed to send UNKNOWN messages to the kernel";
  return ByteString();
}

void UnknownMessage::Print(int header_log_level,
                           int /*detail_log_level*/) const {
  int total_bytes = message_body_.GetLength();
  const uint8_t *const_data = message_body_.GetConstData();

  string output = StringPrintf("%d bytes:", total_bytes);
  for (int i = 0; i < total_bytes; ++i) {
    StringAppendF(&output, " 0x%02x", const_data[i]);
  }
  SLOG(WiFi, header_log_level) << output;
}

//
// Factory class.
//

bool NetlinkMessageFactory::AddFactoryMethod(uint16_t message_type,
                                             FactoryMethod factory) {
  if (ContainsKey(factories_, message_type)) {
    LOG(WARNING) << "Message type " << message_type << " already exists.";
    return false;
  }
  if (message_type == NetlinkMessage::kIllegalMessageType) {
    LOG(ERROR) << "Not installing factory for illegal message type.";
    return false;
  }
  factories_[message_type] = factory;
  return true;
}

NetlinkMessage *NetlinkMessageFactory::CreateMessage(
    const nlmsghdr *const_msg) const {
  if (!const_msg) {
    LOG(ERROR) << "NULL |const_msg| parameter";
    return NULL;
  }

  scoped_ptr<NetlinkMessage> message;

  if (const_msg->nlmsg_type == NoopMessage::kMessageType) {
    message.reset(new NoopMessage());
  } else if (const_msg->nlmsg_type == DoneMessage::kMessageType) {
    message.reset(new DoneMessage());
  } else if (const_msg->nlmsg_type == OverrunMessage::kMessageType) {
    message.reset(new OverrunMessage());
  } else if (const_msg->nlmsg_type == ErrorAckMessage::kMessageType) {
    message.reset(new ErrorAckMessage());
  } else if (ContainsKey(factories_, const_msg->nlmsg_type)) {
    map<uint16_t, FactoryMethod>::const_iterator factory;
    factory = factories_.find(const_msg->nlmsg_type);
    message.reset(factory->second.Run(const_msg));
  }

  // If no factory exists for this message _or_ if a factory exists but it
  // failed, there'll be no message.  Handle either of those cases, by
  // creating an |UnknownMessage|.
  if (!message) {
    // Casting away constness since, while nlmsg_data doesn't change its
    // parameter, it also doesn't declare its paramenter as const.
    nlmsghdr *msg = const_cast<nlmsghdr *>(const_msg);
    ByteString payload(reinterpret_cast<char *>(nlmsg_data(msg)),
                       nlmsg_datalen(msg));
    message.reset(new UnknownMessage(msg->nlmsg_type, payload));
  }

  if (!message->InitFromNlmsg(const_msg)) {
    LOG(ERROR) << "Message did not initialize properly";
    return NULL;
  }

  return message.release();
}

}  // namespace shill.
