// Copyright (c) 2019 The Chromium 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 "quic/qbone/platform/rtnetlink_message.h"

#include <utility>

namespace quic {

RtnetlinkMessage::RtnetlinkMessage(uint16_t type,
                                   uint16_t flags,
                                   uint32_t seq,
                                   uint32_t pid,
                                   const void* payload_header,
                                   size_t payload_header_length) {
  auto* buf = new uint8_t[NLMSG_SPACE(payload_header_length)];
  memset(buf, 0, NLMSG_SPACE(payload_header_length));

  auto* message_header = reinterpret_cast<struct nlmsghdr*>(buf);
  message_header->nlmsg_len = NLMSG_LENGTH(payload_header_length);
  message_header->nlmsg_type = type;
  message_header->nlmsg_flags = flags;
  message_header->nlmsg_seq = seq;
  message_header->nlmsg_pid = pid;

  if (payload_header != nullptr) {
    memcpy(NLMSG_DATA(message_header), payload_header, payload_header_length);
  }
  message_.push_back({buf, NLMSG_SPACE(payload_header_length)});
}

RtnetlinkMessage::~RtnetlinkMessage() {
  for (const auto& iov : message_) {
    delete[] reinterpret_cast<uint8_t*>(iov.iov_base);
  }
}

void RtnetlinkMessage::AppendAttribute(uint16_t type,
                                       const void* data,
                                       uint16_t data_length) {
  auto* buf = new uint8_t[RTA_SPACE(data_length)];
  memset(buf, 0, RTA_SPACE(data_length));

  auto* rta = reinterpret_cast<struct rtattr*>(buf);
  static_assert(sizeof(uint16_t) == sizeof(rta->rta_len),
                "struct rtattr uses unsigned short, it's no longer 16bits");
  static_assert(sizeof(uint16_t) == sizeof(rta->rta_type),
                "struct rtattr uses unsigned short, it's no longer 16bits");

  rta->rta_len = RTA_LENGTH(data_length);
  rta->rta_type = type;
  memcpy(RTA_DATA(rta), data, data_length);

  message_.push_back({buf, RTA_SPACE(data_length)});
  AdjustMessageLength(rta->rta_len);
}

std::unique_ptr<struct iovec[]> RtnetlinkMessage::BuildIoVec() const {
  auto message = std::make_unique<struct iovec[]>(message_.size());
  int idx = 0;
  for (const auto& vec : message_) {
    message[idx++] = vec;
  }
  return message;
}

size_t RtnetlinkMessage::IoVecSize() const {
  return message_.size();
}

void RtnetlinkMessage::AdjustMessageLength(size_t additional_data_length) {
  MessageHeader()->nlmsg_len =
      NLMSG_ALIGN(MessageHeader()->nlmsg_len) + additional_data_length;
}

struct nlmsghdr* RtnetlinkMessage::MessageHeader() {
  return reinterpret_cast<struct nlmsghdr*>(message_[0].iov_base);
}

LinkMessage LinkMessage::New(RtnetlinkMessage::Operation request_operation,
                             uint16_t flags,
                             uint32_t seq,
                             uint32_t pid,
                             const struct ifinfomsg* interface_info_header) {
  uint16_t request_type;
  switch (request_operation) {
    case RtnetlinkMessage::Operation::NEW:
      request_type = RTM_NEWLINK;
      break;
    case RtnetlinkMessage::Operation::DEL:
      request_type = RTM_DELLINK;
      break;
    case RtnetlinkMessage::Operation::GET:
      request_type = RTM_GETLINK;
      break;
  }
  bool is_get = request_type == RTM_GETLINK;

  if (is_get) {
    struct rtgenmsg g = {AF_UNSPEC};
    return LinkMessage(request_type, flags, seq, pid, &g, sizeof(g));
  }
  return LinkMessage(request_type, flags, seq, pid, interface_info_header,
                     sizeof(struct ifinfomsg));
}

AddressMessage AddressMessage::New(
    RtnetlinkMessage::Operation request_operation,
    uint16_t flags,
    uint32_t seq,
    uint32_t pid,
    const struct ifaddrmsg* interface_address_header) {
  uint16_t request_type;
  switch (request_operation) {
    case RtnetlinkMessage::Operation::NEW:
      request_type = RTM_NEWADDR;
      break;
    case RtnetlinkMessage::Operation::DEL:
      request_type = RTM_DELADDR;
      break;
    case RtnetlinkMessage::Operation::GET:
      request_type = RTM_GETADDR;
      break;
  }
  bool is_get = request_type == RTM_GETADDR;

  if (is_get) {
    struct rtgenmsg g = {AF_UNSPEC};
    return AddressMessage(request_type, flags, seq, pid, &g, sizeof(g));
  }
  return AddressMessage(request_type, flags, seq, pid, interface_address_header,
                        sizeof(struct ifaddrmsg));
}

RouteMessage RouteMessage::New(RtnetlinkMessage::Operation request_operation,
                               uint16_t flags,
                               uint32_t seq,
                               uint32_t pid,
                               const struct rtmsg* route_message_header) {
  uint16_t request_type;
  switch (request_operation) {
    case RtnetlinkMessage::Operation::NEW:
      request_type = RTM_NEWROUTE;
      break;
    case RtnetlinkMessage::Operation::DEL:
      request_type = RTM_DELROUTE;
      break;
    case RtnetlinkMessage::Operation::GET:
      request_type = RTM_GETROUTE;
      break;
  }
  return RouteMessage(request_type, flags, seq, pid, route_message_header,
                      sizeof(struct rtmsg));
}

RuleMessage RuleMessage::New(RtnetlinkMessage::Operation request_operation,
                             uint16_t flags,
                             uint32_t seq,
                             uint32_t pid,
                             const struct rtmsg* rule_message_header) {
  uint16_t request_type;
  switch (request_operation) {
    case RtnetlinkMessage::Operation::NEW:
      request_type = RTM_NEWRULE;
      break;
    case RtnetlinkMessage::Operation::DEL:
      request_type = RTM_DELRULE;
      break;
    case RtnetlinkMessage::Operation::GET:
      request_type = RTM_GETRULE;
      break;
  }
  return RuleMessage(request_type, flags, seq, pid, rule_message_header,
                     sizeof(rtmsg));
}
}  // namespace quic
