// 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]) {
      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.
