/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "common/libs/net/netlink_request.h"

#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <string.h>

#include <algorithm>
#include <string>
#include <vector>

#include "android-base/logging.h"

namespace cvd {
namespace {
uint32_t kRequestSequenceNumber = 0;
}  // namespace

uint32_t NetlinkRequest::SeqNo() const {
  return header_->nlmsg_seq;
}

void* NetlinkRequest::AppendRaw(const void* data, size_t length) {
  auto* output = static_cast<char*>(ReserveRaw(length));
  const auto* input = static_cast<const char*>(data);
  std::copy(input, input + length, output);
  return output;
}

void* NetlinkRequest::ReserveRaw(size_t length) {
  size_t original_size = request_.size();
  request_.resize(original_size + RTA_ALIGN(length), '\0');
  return reinterpret_cast<void*>(request_.data() + original_size);
}

nlattr* NetlinkRequest::AppendTag(
    uint16_t type, const void* data, uint16_t data_length) {
  nlattr* attr = Reserve<nlattr>();
  attr->nla_type = type;
  attr->nla_len = RTA_LENGTH(data_length);
  AppendRaw(data, data_length);
  return attr;
}

NetlinkRequest::NetlinkRequest(int32_t command, int32_t flags) {
  request_.reserve(512);
  header_ = Reserve<nlmsghdr>();
  flags |= NLM_F_ACK | NLM_F_REQUEST;
  header_->nlmsg_flags = flags;
  header_->nlmsg_type = command;
  header_->nlmsg_pid = getpid();
  header_->nlmsg_seq = kRequestSequenceNumber++;
}

NetlinkRequest::NetlinkRequest(NetlinkRequest&& other) {
  using std::swap;
  swap(lists_, other.lists_);
  swap(header_, other.header_);
  swap(request_, other.request_);
}

void NetlinkRequest::AddString(uint16_t type, const std::string& value) {
  AppendTag(type, value.c_str(), value.length() + 1);
}

void NetlinkRequest::AddIfInfo(int32_t if_index, bool operational) {
  ifinfomsg* if_info = Reserve<ifinfomsg>();
  if_info->ifi_family = AF_UNSPEC;
  if_info->ifi_index = if_index;
  if_info->ifi_flags = operational ? IFF_UP : 0;
  if_info->ifi_change = IFF_UP;
}

void NetlinkRequest::AddAddrInfo(int32_t if_index, int prefix_len) {
  ifaddrmsg* ad_info = Reserve<ifaddrmsg>();
  ad_info->ifa_family = AF_INET;
  ad_info->ifa_prefixlen = prefix_len;
  ad_info->ifa_flags = IFA_F_PERMANENT | IFA_F_SECONDARY;
  ad_info->ifa_scope = 0;
  ad_info->ifa_index = if_index;
}

void NetlinkRequest::PushList(uint16_t type) {
  int length = request_.size();
  nlattr* list = AppendTag(type, NULL, 0);
  lists_.push_back(std::make_pair(list, length));
}

void NetlinkRequest::PopList() {
  if (lists_.empty()) {
    LOG(ERROR) << "List pop with no lists left on stack.";
    return;
  }

  std::pair<nlattr*, int> list = lists_.back();
  lists_.pop_back();
  list.first->nla_len = request_.size() - list.second;
}

void* NetlinkRequest::RequestData() const {
  // Update request length before reporting raw data.
  header_->nlmsg_len = request_.size();
  return header_;
}

size_t NetlinkRequest::RequestLength() const {
  return request_.size();
}

}  // namespace cvd
