/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2022,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "network-predicate.hpp"
#include "common/config-file.hpp"
#include "core/network.hpp"

#include <fnmatch.h>

namespace nfd::face {

NetworkPredicateBase::NetworkPredicateBase()
{
  this->clear();
}

NetworkPredicateBase::~NetworkPredicateBase() = default;

void
NetworkPredicateBase::clear()
{
  m_whitelist = std::set<std::string>{"*"};
  m_blacklist.clear();
}

void
NetworkPredicateBase::parseList(std::set<std::string>& set,
                                const boost::property_tree::ptree& list,
                                const std::string& section)
{
  set.clear();

  for (const auto& item : list) {
    if (item.first == "*") {
      // insert wildcard
      set.insert(item.first);
    }
    else {
      if (!isRuleSupported(item.first)) {
        NDN_THROW(ConfigFile::Error("Unrecognized rule '" + item.first +
                                    "' in section '" + section + "'"));
      }

      auto value = item.second.get_value<std::string>();
      if (!isRuleValid(item.first, value)) {
        NDN_THROW(ConfigFile::Error("Malformed " + item.first + " '" + value +
                                    "' in section '" + section + "'"));
      }
      set.insert(value);
    }
  }
}

void
NetworkPredicateBase::parseList(std::set<std::string>& set,
                                std::initializer_list<std::pair<std::string, std::string>> list)
{
  set.clear();

  for (const auto& item : list) {
    if (item.first == "*") {
      // insert wildcard
      set.insert(item.first);
    }
    else {
      if (!isRuleSupported(item.first)) {
        NDN_THROW(std::runtime_error("Unrecognized rule '" + item.first + "'"));
      }

      if (!isRuleValid(item.first, item.second)) {
        NDN_THROW(std::runtime_error("Malformed " + item.first + " '" + item.second + "'"));
      }
      set.insert(item.second);
    }
  }
}

void
NetworkPredicateBase::parseWhitelist(const boost::property_tree::ptree& list)
{
  parseList(m_whitelist, list, "whitelist");
}

void
NetworkPredicateBase::parseBlacklist(const boost::property_tree::ptree& list)
{
  parseList(m_blacklist, list, "blacklist");
}

void
NetworkPredicateBase::assign(std::initializer_list<std::pair<std::string, std::string>> whitelist,
                             std::initializer_list<std::pair<std::string, std::string>> blacklist)
{
  parseList(m_whitelist, whitelist);
  parseList(m_blacklist, blacklist);
}

bool
NetworkInterfacePredicate::isRuleSupported(const std::string& key)
{
  return key == "ifname" || key == "ether" || key == "subnet";
}

bool
NetworkInterfacePredicate::isRuleValid(const std::string& key, const std::string& value)
{
  if (key == "ifname") {
    // very basic sanity check for interface names
    return !value.empty();
  }
  else if (key == "ether") {
    // validate ethernet address
    return !ndn::ethernet::Address::fromString(value).isNull();
  }
  else if (key == "subnet") {
    // example subnet: 10.0.0.0/8
    return Network::isValidCidr(value);
  }
  else {
    NDN_THROW(std::logic_error("Only supported rules are expected"));
  }
}

bool
IpAddressPredicate::isRuleSupported(const std::string& key)
{
  return key == "subnet";
}

bool
IpAddressPredicate::isRuleValid(const std::string& key, const std::string& value)
{
  if (key == "subnet") {
    // example subnet: 10.0.0.0/8
    return Network::isValidCidr(value);
  }
  else {
    NDN_THROW(std::logic_error("Only supported rules are expected"));
  }
}

bool
NetworkPredicateBase::operator==(const NetworkPredicateBase& other) const
{
  return this->m_whitelist == other.m_whitelist &&
         this->m_blacklist == other.m_blacklist;
}

static bool
doesMatchPattern(const std::string& ifname, const std::string& pattern)
{
  // use fnmatch(3) to provide unix glob-style matching for interface names
  // fnmatch returns 0 if there is a match
  return ::fnmatch(pattern.data(), ifname.data(), 0) == 0;
}

static bool
doesNetifMatchRule(const ndn::net::NetworkInterface& netif, const std::string& rule)
{
  // if '/' is in rule, this is a subnet, check if IP in subnet
  if (rule.find('/') != std::string::npos) {
    Network n = boost::lexical_cast<Network>(rule);
    for (const auto& addr : netif.getNetworkAddresses()) {
      if (n.doesContain(addr.getIp())) {
        return true;
      }
    }
  }

  return rule == "*" ||
         doesMatchPattern(netif.getName(), rule) ||
         netif.getEthernetAddress().toString() == rule;
}

bool
NetworkInterfacePredicate::operator()(const ndn::net::NetworkInterface& netif) const
{
  return std::any_of(m_whitelist.begin(), m_whitelist.end(),
                     [&netif] (const auto& rule) { return doesNetifMatchRule(netif, rule); }) &&
         std::none_of(m_blacklist.begin(), m_blacklist.end(),
                      [&netif] (const auto& rule) { return doesNetifMatchRule(netif, rule); });
}

static bool
doesAddressMatchRule(const boost::asio::ip::address& address, const std::string& rule)
{
  // if '/' is in rule, this is a subnet, check if IP in subnet
  if (rule.find('/') != std::string::npos) {
    Network n = boost::lexical_cast<Network>(rule);
    if (n.doesContain(address)) {
      return true;
    }
  }

  return rule == "*";
}

bool
IpAddressPredicate::operator()(const boost::asio::ip::address& address) const
{
  return std::any_of(m_whitelist.begin(), m_whitelist.end(),
                     [&address] (const auto& rule) { return doesAddressMatchRule(address, rule); }) &&
         std::none_of(m_blacklist.begin(), m_blacklist.end(),
                      [&address] (const auto& rule) { return doesAddressMatchRule(address, rule); });
}

} // namespace nfd::face
