// Copyright 2018 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/net/attribute_list.h"

#include <ctype.h>
#include <linux/nl80211.h>

#include <iomanip>
#include <memory>
#include <string>

#include <base/logging.h>
#include <base/stl_util.h>

#include "shill/logging.h"
#include "shill/net/netlink_attribute.h"
#include "shill/net/netlink_message.h"

using std::string;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kRTNL;
static std::string ObjectID(const AttributeList* obj) {
  return "(attribute_list)";
}
}  // namespace Logging

AttributeList::AttributeList() = default;

AttributeList::~AttributeList() = default;

bool AttributeList::CreateAttribute(int id,
                                    AttributeList::NewFromIdMethod factory) {
  if (base::Contains(attributes_, id)) {
    SLOG(this, 7) << "Trying to re-add attribute " << id << ", not overwriting";
    return true;
  }
  attributes_[id] = factory.Run(id);
  return true;
}

bool AttributeList::CreateControlAttribute(int id) {
  return CreateAttribute(
      id, base::Bind(&NetlinkAttribute::NewControlAttributeFromId));
}

bool AttributeList::CreateNl80211Attribute(
    int id, NetlinkMessage::MessageContext context) {
  return CreateAttribute(
      id, base::Bind(&NetlinkAttribute::NewNl80211AttributeFromId, context));
}

bool AttributeList::CreateAndInitAttribute(
    const AttributeList::NewFromIdMethod& factory,
    int id,
    const ByteString& value) {
  if (!CreateAttribute(id, factory)) {
    return false;
  }
  return InitAttributeFromValue(id, value);
}

bool AttributeList::InitAttributeFromValue(int id, const ByteString& value) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->InitFromValue(value);
}

void AttributeList::Print(int log_level, int indent) const {
  for (const auto& id_attribute_pair : attributes_) {
    id_attribute_pair.second->Print(log_level, indent);
  }
}

// static
bool AttributeList::IterateAttributes(
    const ByteString& payload,
    size_t offset,
    const AttributeList::AttributeMethod& method) {
  // Nothing to iterate over.
  if (payload.IsEmpty())
    return true;

  const unsigned char* ptr = payload.GetConstData() + NLA_ALIGN(offset);
  const unsigned char* end = payload.GetConstData() + payload.GetLength();
  while (ptr + sizeof(nlattr) <= end) {
    const nlattr* attribute = reinterpret_cast<const nlattr*>(ptr);
    if (attribute->nla_len < sizeof(*attribute) ||
        ptr + attribute->nla_len > end) {
      LOG(ERROR) << "Malformed nla attribute indicates length "
                 << attribute->nla_len << ".  " << (end - ptr - NLA_HDRLEN)
                 << " bytes remain in buffer.  "
                 << "Error occurred at offset "
                 << (ptr - payload.GetConstData()) << ".";
      return false;
    }
    ByteString value;
    if (attribute->nla_len > NLA_HDRLEN) {
      value = ByteString(ptr + NLA_HDRLEN, attribute->nla_len - NLA_HDRLEN);
    }
    if (!method.Run(attribute->nla_type, value)) {
      return false;
    }
    ptr += NLA_ALIGN(attribute->nla_len);
  }
  if (ptr < end) {
    LOG(INFO) << "Decode left " << (end - ptr) << " unparsed bytes.";
  }
  return true;
}

bool AttributeList::Decode(const ByteString& payload,
                           size_t offset,
                           const AttributeList::NewFromIdMethod& factory) {
  return IterateAttributes(payload, offset,
                           base::Bind(&AttributeList::CreateAndInitAttribute,
                                      base::Unretained(this), factory));
}

ByteString AttributeList::Encode() const {
  ByteString result;
  for (const auto& id_attribute_pair : attributes_) {
    result.Append(id_attribute_pair.second->Encode());
  }
  return result;
}

// U8 Attribute.

bool AttributeList::GetU8AttributeValue(int id, uint8_t* value) const {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->GetU8Value(value);
}

bool AttributeList::CreateU8Attribute(int id, const char* id_string) {
  if (base::Contains(attributes_, id)) {
    LOG(ERROR) << "Trying to re-add attribute: " << id;
    return false;
  }
  attributes_[id] = std::make_unique<NetlinkU8Attribute>(id, id_string);
  return true;
}

bool AttributeList::SetU8AttributeValue(int id, uint8_t value) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->SetU8Value(value);
}

// U16 Attribute.

bool AttributeList::GetU16AttributeValue(int id, uint16_t* value) const {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->GetU16Value(value);
}

bool AttributeList::CreateU16Attribute(int id, const char* id_string) {
  if (base::Contains(attributes_, id)) {
    LOG(ERROR) << "Trying to re-add attribute: " << id;
    return false;
  }
  attributes_[id] = std::make_unique<NetlinkU16Attribute>(id, id_string);
  return true;
}

bool AttributeList::SetU16AttributeValue(int id, uint16_t value) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->SetU16Value(value);
}

// U32 Attribute.

bool AttributeList::GetU32AttributeValue(int id, uint32_t* value) const {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->GetU32Value(value);
}

bool AttributeList::CreateU32Attribute(int id, const char* id_string) {
  if (base::Contains(attributes_, id)) {
    LOG(ERROR) << "Trying to re-add attribute: " << id;
    return false;
  }
  attributes_[id] = std::make_unique<NetlinkU32Attribute>(id, id_string);
  return true;
}

bool AttributeList::SetU32AttributeValue(int id, uint32_t value) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->SetU32Value(value);
}

// U64 Attribute.

bool AttributeList::GetU64AttributeValue(int id, uint64_t* value) const {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->GetU64Value(value);
}

bool AttributeList::CreateU64Attribute(int id, const char* id_string) {
  if (base::Contains(attributes_, id)) {
    LOG(ERROR) << "Trying to re-add attribute: " << id;
    return false;
  }
  attributes_[id] = std::make_unique<NetlinkU64Attribute>(id, id_string);
  return true;
}

bool AttributeList::SetU64AttributeValue(int id, uint64_t value) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->SetU64Value(value);
}

// Flag Attribute.

bool AttributeList::GetFlagAttributeValue(int id, bool* value) const {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->GetFlagValue(value);
}

bool AttributeList::CreateFlagAttribute(int id, const char* id_string) {
  if (base::Contains(attributes_, id)) {
    LOG(ERROR) << "Trying to re-add attribute: " << id;
    return false;
  }
  attributes_[id] = std::make_unique<NetlinkFlagAttribute>(id, id_string);
  return true;
}

bool AttributeList::SetFlagAttributeValue(int id, bool value) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->SetFlagValue(value);
}

bool AttributeList::IsFlagAttributeTrue(int id) const {
  bool flag;
  if (!GetFlagAttributeValue(id, &flag)) {
    return false;
  }
  return flag;
}

// String Attribute.

bool AttributeList::GetStringAttributeValue(int id, string* value) const {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->GetStringValue(value);
}

bool AttributeList::CreateStringAttribute(int id, const char* id_string) {
  if (base::Contains(attributes_, id)) {
    LOG(ERROR) << "Trying to re-add attribute: " << id;
    return false;
  }
  attributes_[id] = std::make_unique<NetlinkStringAttribute>(id, id_string);
  return true;
}

bool AttributeList::CreateSsidAttribute(int id, const char* id_string) {
  if (base::Contains(attributes_, id)) {
    LOG(ERROR) << "Trying to re-add attribute: " << id;
    return false;
  }
  attributes_[id] = std::make_unique<NetlinkSsidAttribute>(id, id_string);
  return true;
}

bool AttributeList::SetStringAttributeValue(int id, const string& value) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->SetStringValue(value);
}

// Nested Attribute.

bool AttributeList::GetNestedAttributeList(int id, AttributeListRefPtr* value) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->GetNestedAttributeList(value);
}

bool AttributeList::ConstGetNestedAttributeList(
    int id, AttributeListConstRefPtr* value) const {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->ConstGetNestedAttributeList(value);
}

bool AttributeList::SetNestedAttributeHasAValue(int id) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->SetNestedHasAValue();
}

bool AttributeList::CreateNestedAttribute(int id, const char* id_string) {
  if (base::Contains(attributes_, id)) {
    LOG(ERROR) << "Trying to re-add attribute: " << id;
    return false;
  }
  attributes_[id] = std::make_unique<NetlinkNestedAttribute>(id, id_string);
  return true;
}

// Raw Attribute.

bool AttributeList::GetRawAttributeValue(int id, ByteString* output) const {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;

  ByteString raw_value;

  if (!attribute->GetRawValue(&raw_value))
    return false;

  if (output) {
    *output = raw_value;
  }
  return true;
}

bool AttributeList::SetRawAttributeValue(int id, ByteString value) {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;
  return attribute->SetRawValue(value);
}

bool AttributeList::CreateRawAttribute(int id, const char* id_string) {
  if (base::Contains(attributes_, id)) {
    LOG(ERROR) << "Trying to re-add attribute: " << id;
    return false;
  }
  attributes_[id] = std::make_unique<NetlinkRawAttribute>(id, id_string);
  return true;
}

bool AttributeList::GetAttributeAsString(int id, std::string* value) const {
  NetlinkAttribute* attribute = GetAttribute(id);
  if (!attribute)
    return false;

  return attribute->ToString(value);
}

NetlinkAttribute* AttributeList::GetAttribute(int id) const {
  AttributeMap::const_iterator i = attributes_.find(id);
  if (i == attributes_.end()) {
    return nullptr;
  }
  return i->second.get();
}

}  // namespace shill
