// 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/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]) {
      // TODO(wdg): When NetlinkMessages instantiate their own attributes,
      // this call should, instead, call |SetAttributeFromNlAttr|.
      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.
