// 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 "quiche/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
