/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2023,  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>

#include <boost/lexical_cast.hpp>

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"));
  }
}

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
