// Copyright (c) 2013 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/generic_netlink_message.h"

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

#include <base/bind.h>
#include <base/strings/stringprintf.h>

#include "shill/logging.h"
#include "shill/netlink_attribute.h"

using base::Bind;
using base::StringPrintf;

namespace shill {

ByteString GenericNetlinkMessage::EncodeHeader(uint32_t sequence_number) {
  // Build nlmsghdr.
  ByteString result(NetlinkMessage::EncodeHeader(sequence_number));
  if (result.GetLength() == 0) {
    LOG(ERROR) << "Couldn't encode message header.";
    return result;
  }

  // Build and append the genl message header.
  genlmsghdr genl_header;
  genl_header.cmd = command();
  genl_header.version = 1;
  genl_header.reserved = 0;

  ByteString genl_header_string(
      reinterpret_cast<unsigned char *>(&genl_header), sizeof(genl_header));
  size_t genlmsghdr_with_pad = NLMSG_ALIGN(sizeof(genl_header));
  genl_header_string.Resize(genlmsghdr_with_pad);  // Zero-fill.

  nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
  pheader->nlmsg_len += genlmsghdr_with_pad;
  result.Append(genl_header_string);
  return result;
}

ByteString GenericNetlinkMessage::Encode(uint32_t sequence_number) {
  ByteString result(EncodeHeader(sequence_number));
  if (result.GetLength() == 0) {
    LOG(ERROR) << "Couldn't encode message header.";
    return result;
  }

  // Build and append attributes (padding is included by
  // AttributeList::Encode).
  ByteString attribute_string = attributes_->Encode();

  // Need to re-calculate |header| since |Append|, above, moves the data.
  nlmsghdr *pheader = reinterpret_cast<nlmsghdr *>(result.GetData());
  pheader->nlmsg_len += attribute_string.GetLength();
  result.Append(attribute_string);

  return result;
}

bool GenericNetlinkMessage::InitAndStripHeader(ByteString *input) {
  if (!input) {
    LOG(ERROR) << "NULL input";
    return false;
  }
  if (!NetlinkMessage::InitAndStripHeader(input)) {
    return false;
  }

  // Read the genlmsghdr.
  genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(input->GetData());
  if (command_ != gnlh->cmd) {
    LOG(WARNING) << "This object thinks it's a " << command_
                 << " but the message thinks it's a " << gnlh->cmd;
  }

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

void GenericNetlinkMessage::Print(int header_log_level,
                                  int detail_log_level) const {
  SLOG(WiFi, header_log_level) << StringPrintf("Message %s (%d)",
                                               command_string(),
                                               command());
  attributes_->Print(detail_log_level, 1);
}

// Control Message

const uint16_t ControlNetlinkMessage::kMessageType = GENL_ID_CTRL;

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

  if (!InitAndStripHeader(&message)) {
    return false;
  }

  // Attributes.
  // Parse the attributes from the nl message payload into the 'tb' array.
  nlattr *tb[CTRL_ATTR_MAX + 1];
  nla_parse(tb, CTRL_ATTR_MAX,
            reinterpret_cast<nlattr *>(message.GetData()), message.GetLength(),
            NULL);

  for (int i = 0; i < CTRL_ATTR_MAX + 1; ++i) {
    if (tb[i]) {
      attributes_->CreateAndInitAttribute(
          i, tb[i], Bind(&NetlinkAttribute::NewControlAttributeFromId));
    }
  }
  return true;
}

// Specific Control types.

const uint8_t NewFamilyMessage::kCommand = CTRL_CMD_NEWFAMILY;
const char NewFamilyMessage::kCommandString[] = "CTRL_CMD_NEWFAMILY";

const uint8_t GetFamilyMessage::kCommand = CTRL_CMD_GETFAMILY;
const char GetFamilyMessage::kCommandString[] = "CTRL_CMD_GETFAMILY";

GetFamilyMessage::GetFamilyMessage()
    : ControlNetlinkMessage(kCommand, kCommandString) {
  attributes()->CreateStringAttribute(CTRL_ATTR_FAMILY_NAME,
                                      "CTRL_ATTR_FAMILY_NAME");
}

// static
NetlinkMessage *ControlNetlinkMessage::CreateMessage(
    const nlmsghdr *const_msg) {
  if (!const_msg) {
    LOG(ERROR) << "NULL |const_msg| parameter";
    return NULL;
  }
  // 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);
  void *payload = nlmsg_data(msg);
  genlmsghdr *gnlh = reinterpret_cast<genlmsghdr *>(payload);

  switch (gnlh->cmd) {
    case NewFamilyMessage::kCommand:
      return new NewFamilyMessage();
    case GetFamilyMessage::kCommand:
      return new GetFamilyMessage();
    default:
      LOG(WARNING) << "Unknown/unhandled netlink control message " << gnlh->cmd;
      return new UnknownControlMessage(gnlh->cmd);
      break;
  }
  return NULL;
}

}  // namespace shill.
