#include "config.h"

#include "ethernet_interface.hpp"

#include "config_parser.hpp"
#include "network_manager.hpp"
#include "util.hpp"

#include <arpa/inet.h>
#include <fmt/compile.h>
#include <fmt/format.h>
#include <linux/ethtool.h>
#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <net/if.h>

#include <algorithm>
#include <filesystem>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus/match.hpp>
#include <stdplus/fd/create.hpp>
#include <stdplus/raw.hpp>
#include <stdplus/zstring.hpp>
#include <string>
#include <unordered_map>
#include <variant>
#include <xyz/openbmc_project/Common/error.hpp>

namespace phosphor
{
namespace network
{

using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
using Argument = xyz::openbmc_project::Common::InvalidArgument;
using std::literals::string_view_literals::operator""sv;
constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";

constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";

constexpr auto METHOD_GET = "Get";

static stdplus::Fd& getIFSock()
{
    using namespace stdplus::fd;
    static auto fd =
        socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
    return fd;
}

struct LinkInfo
{
    bool autoneg;
    uint16_t speed;
};

static LinkInfo getLinkInfo(stdplus::zstring_view ifname)
{
    LinkInfo ret;
    try
    {
        ethtool_cmd edata = {};
        edata.cmd = ETHTOOL_GSET;

        ifreq ifr = {};
        const auto copied = std::min<std::size_t>(ifname.size(), IFNAMSIZ - 1);
        std::copy_n(ifname.begin(), copied, ifr.ifr_name);
        ifr.ifr_data = reinterpret_cast<char*>(&edata);

        getIFSock().ioctl(SIOCETHTOOL, &ifr);

        ret.speed = edata.speed;
        ret.autoneg = edata.autoneg;
    }
    catch (const std::system_error& e)
    {
        if (e.code() == std::errc::operation_not_supported)
        {
            auto msg = fmt::format("ETHTOOL not supported on {}", ifname);
            log<level::NOTICE>(msg.c_str(),
                               entry("INTERFACE=%s", ifname.c_str()));
        }
        else
        {
            auto msg =
                fmt::format("ETHTOOL failed on {}: {}", ifname, e.what());
            log<level::ERR>(msg.c_str(), entry("INTERFACE=%s", ifname.c_str()));
        }
    }
    return ret;
}

EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus,
                                     stdplus::zstring_view objPath,
                                     const config::Parser& config,
                                     Manager& parent, bool emitSignal,
                                     std::optional<bool> enabled) :
    Ifaces(bus, objPath.c_str(),
           emitSignal ? Ifaces::action::defer_emit
                      : Ifaces::action::emit_no_signals),
    bus(bus), manager(parent), objPath(objPath.c_str())
{
    auto intfName = std::string(objPath.substr(objPath.rfind('/') + 1));
    std::replace(intfName.begin(), intfName.end(), '_', '.');
    interfaceName(intfName);
    auto dhcpVal = getDHCPValue(config);
    EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
    EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
    EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
    EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
    const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
    const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
    std::string defaultGateway;
    std::string defaultGateway6;

    for (const auto& gateway : gatewayList)
    {
        if (gateway.first == intfName)
        {
            defaultGateway = gateway.second;
            break;
        }
    }

    for (const auto& gateway6 : gateway6List)
    {
        if (gateway6.first == intfName)
        {
            defaultGateway6 = gateway6.second;
            break;
        }
    }

    EthernetInterfaceIntf::defaultGateway(defaultGateway);
    EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
    // Don't get the mac address from the system as the mac address
    // would be same as parent interface.
    if (intfName.find(".") == std::string::npos)
    {
        try
        {
            MacAddressIntf::macAddress(getMACAddress(intfName));
        }
        catch (const std::exception& e)
        {
            auto msg =
                fmt::format("Failed to get MAC for {}: {}", intfName, e.what());
            log<level::ERR>(msg.c_str(),
                            entry("INTERFACE=%s", intfName.c_str()));
        }
    }
    EthernetInterfaceIntf::ntpServers(
        config.map.getValueStrings("Network", "NTP"));

    EthernetInterfaceIntf::linkUp(linkUp());
    EthernetInterfaceIntf::mtu(mtu());

    auto info = getLinkInfo(intfName);
    EthernetInterfaceIntf::autoNeg(info.autoneg);
    EthernetInterfaceIntf::speed(info.speed);

    // Emit deferred signal.
    if (emitSignal)
    {
        this->emit_object_added();
    }
}

static IP::Protocol getProtocol(const InAddrAny& addr)
{
    if (std::holds_alternative<in_addr>(addr))
    {
        return IP::Protocol::IPv4;
    }
    else if (std::holds_alternative<in6_addr>(addr))
    {
        return IP::Protocol::IPv6;
    }

    throw std::runtime_error("Invalid addr type");
}

bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
{
    switch (family)
    {
        case IP::Protocol::IPv6:
            return dhcp6();
        case IP::Protocol::IPv4:
            return dhcp4();
    }
    throw std::logic_error("Unreachable");
}

bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
{
    return (
#ifdef LINK_LOCAL_AUTOCONFIGURATION
        (origin == IP::AddressOrigin::Static)
#else
        (origin == IP::AddressOrigin::Static ||
         origin == IP::AddressOrigin::LinkLocal)
#endif

    );
}

void EthernetInterface::createIPAddressObjects()
{
    addrs.clear();

    AddressFilter filter;
    filter.interface = ifIndex();
    auto currentAddrs = getCurrentAddresses(filter);
    for (const auto& addr : currentAddrs)
    {
        if (addr.flags & IFA_F_DEPRECATED)
        {
            continue;
        }
        auto address = toString(addr.address);
        IP::Protocol addressType = getProtocol(addr.address);
        IP::AddressOrigin origin = IP::AddressOrigin::Static;
        if (dhcpIsEnabled(addressType))
        {
            origin = IP::AddressOrigin::DHCP;
        }
#ifdef LINK_LOCAL_AUTOCONFIGURATION
        if (addr.scope == RT_SCOPE_LINK)
        {
            origin = IP::AddressOrigin::LinkLocal;
        }
#endif

        auto ipAddressObjectPath =
            generateObjectPath(addressType, address, addr.prefix, origin);

        this->addrs.insert_or_assign(
            address, std::make_unique<IPAddress>(bus, ipAddressObjectPath,
                                                 *this, addressType, address,
                                                 origin, addr.prefix));
    }
}

void EthernetInterface::createStaticNeighborObjects()
{
    staticNeighbors.clear();

    NeighborFilter filter;
    filter.interface = ifIndex();
    filter.state = NUD_PERMANENT;
    auto neighbors = getCurrentNeighbors(filter);
    for (const auto& neighbor : neighbors)
    {
        if (!neighbor.mac)
        {
            continue;
        }
        auto ip = toString(neighbor.address);
        auto mac = mac_address::toString(*neighbor.mac);
        auto objectPath = generateStaticNeighborObjectPath(ip, mac);
        staticNeighbors.emplace(
            ip, std::make_unique<Neighbor>(bus, objectPath, *this, ip, mac,
                                           Neighbor::State::Permanent));
    }
}

unsigned EthernetInterface::ifIndex() const
{
    unsigned idx = if_nametoindex(interfaceName().c_str());
    if (idx == 0)
    {
        throw std::system_error(errno, std::generic_category(),
                                "if_nametoindex");
    }
    return idx;
}

ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
                                 uint8_t prefixLength, std::string)
{
    if (dhcpIsEnabled(protType))
    {
        log<level::INFO>("DHCP enabled on the interface, disabling"),
            entry("INTERFACE=%s", interfaceName().c_str());
        switch (protType)
        {
            case IP::Protocol::IPv4:
                dhcp4(false);
                break;
            case IP::Protocol::IPv6:
                dhcp6(false);
                break;
        }
        // Delete the IP address object and that reloads the networkd
        // to allow the same IP address to be set as Static IP
        deleteObject(ipaddress);
    }

    IP::AddressOrigin origin = IP::AddressOrigin::Static;

    int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;

    if (!isValidIP(addressFamily, ipaddress))
    {
        log<level::ERR>("Not a valid IP address"),
            entry("ADDRESS=%s", ipaddress.c_str());
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
                              Argument::ARGUMENT_VALUE(ipaddress.c_str()));
    }

    if (!isValidPrefix(addressFamily, prefixLength))
    {
        log<level::ERR>("PrefixLength is not correct "),
            entry("PREFIXLENGTH=%" PRIu8, prefixLength);
        elog<InvalidArgument>(
            Argument::ARGUMENT_NAME("prefixLength"),
            Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
    }

    auto objectPath =
        generateObjectPath(protType, ipaddress, prefixLength, origin);
    this->addrs.insert_or_assign(
        ipaddress,
        std::make_unique<IPAddress>(bus, objectPath, *this, protType, ipaddress,
                                    origin, prefixLength));

    writeConfigurationFile();
    manager.reloadConfigs();

    return objectPath;
}

ObjectPath EthernetInterface::neighbor(std::string ipAddress,
                                       std::string macAddress)
{
    if (!isValidIP(ipAddress))
    {
        log<level::ERR>("Not a valid IP address",
                        entry("ADDRESS=%s", ipAddress.c_str()));
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
                              Argument::ARGUMENT_VALUE(ipAddress.c_str()));
    }
    if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
    {
        log<level::ERR>("Not a valid MAC address",
                        entry("MACADDRESS=%s", ipAddress.c_str()));
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
                              Argument::ARGUMENT_VALUE(macAddress.c_str()));
    }

    auto objectPath = generateStaticNeighborObjectPath(ipAddress, macAddress);
    staticNeighbors.emplace(
        ipAddress,
        std::make_unique<Neighbor>(bus, objectPath, *this, ipAddress,
                                   macAddress, Neighbor::State::Permanent));

    writeConfigurationFile();
    manager.reloadConfigs();

    return objectPath;
}

/** @brief get the mac address of the interface.
 *  @return macaddress on success
 */

std::string
    EthernetInterface::getMACAddress(stdplus::const_zstring interfaceName) const
{
    std::string activeMACAddr = MacAddressIntf::macAddress();

    ifreq ifr = {};
    std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
    try
    {
        getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
                        entry("ERROR=%s", e.what()));
        elog<InternalFailure>();
    }
    return mac_address::toString(
        stdplus::raw::refFrom<ether_addr>(ifr.ifr_hwaddr.sa_data));
}

void EthernetInterface::deleteObject(std::string_view ipaddress)
{
    auto it = addrs.find(ipaddress);
    if (it == addrs.end())
    {
        log<level::ERR>("DeleteObject:Unable to find the object.");
        return;
    }
    this->addrs.erase(it);

    writeConfigurationFile();
    manager.reloadConfigs();
}

void EthernetInterface::deleteStaticNeighborObject(std::string_view ipAddress)
{
    auto it = staticNeighbors.find(ipAddress);
    if (it == staticNeighbors.end())
    {
        log<level::ERR>(
            "DeleteStaticNeighborObject:Unable to find the object.");
        return;
    }
    staticNeighbors.erase(it);

    writeConfigurationFile();
    manager.reloadConfigs();
}

void EthernetInterface::deleteVLANFromSystem(stdplus::zstring_view interface)
{
    const auto& confDir = manager.getConfDir();
    auto networkFile = config::pathForIntfConf(confDir, interface);
    auto deviceFile = config::pathForIntfDev(confDir, interface);

    // delete the vlan network file
    std::error_code ec;
    std::filesystem::remove(networkFile, ec);
    std::filesystem::remove(deviceFile, ec);

    // TODO  systemd doesn't delete the virtual network interface
    // even after deleting all the related configuartion.
    // https://github.com/systemd/systemd/issues/6600
    try
    {
        deleteInterface(interface);
    }
    catch (const InternalFailure& e)
    {
        commit<InternalFailure>();
    }
}

void EthernetInterface::deleteVLANObject(stdplus::zstring_view interface)
{
    auto it = vlanInterfaces.find(interface);
    if (it == vlanInterfaces.end())
    {
        log<level::ERR>("DeleteVLANObject:Unable to find the object",
                        entry("INTERFACE=%s", interface.c_str()));
        return;
    }

    deleteVLANFromSystem(interface);
    // delete the interface
    vlanInterfaces.erase(it);

    writeConfigurationFile();
    manager.reloadConfigs();
}

std::string EthernetInterface::generateObjectPath(
    IP::Protocol addressType, std::string_view ipAddress, uint8_t prefixLength,
    IP::AddressOrigin origin) const
{
    std::string_view type;
    switch (addressType)
    {
        case IP::Protocol::IPv4:
            type = "ipv4"sv;
            break;
        case IP::Protocol::IPv6:
            type = "ipv6"sv;
            break;
    }
    return fmt::format(
        FMT_COMPILE("{}/{}/{:08x}"), objPath, type,
        static_cast<uint32_t>(hash_multi(
            ipAddress, prefixLength,
            static_cast<std::underlying_type_t<IP::AddressOrigin>>(origin))));
}

std::string EthernetInterface::generateStaticNeighborObjectPath(
    std::string_view ipAddress, std::string_view macAddress) const
{
    return fmt::format(
        FMT_COMPILE("{}/static_neighbor/{:08x}"), objPath,
        static_cast<uint32_t>(hash_multi(ipAddress, macAddress)));
}

bool EthernetInterface::ipv6AcceptRA(bool value)
{
    if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
    {
        writeConfigurationFile();
        manager.reloadConfigs();
    }
    return value;
}

bool EthernetInterface::dhcp4(bool value)
{
    if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
    {
        writeConfigurationFile();
        manager.reloadConfigs();
    }
    return value;
}

bool EthernetInterface::dhcp6(bool value)
{
    if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
    {
        writeConfigurationFile();
        manager.reloadConfigs();
    }
    return value;
}

EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
{
    auto old4 = EthernetInterfaceIntf::dhcp4();
    auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
                                             value == DHCPConf::v4v6stateless ||
                                             value == DHCPConf::both);
    auto old6 = EthernetInterfaceIntf::dhcp6();
    auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
                                             value == DHCPConf::both);
    auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
    auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
        value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
        value == DHCPConf::v6 || value == DHCPConf::both);

    if (old4 != new4 || old6 != new6 || oldra != newra)
    {
        writeConfigurationFile();
        manager.reloadConfigs();
    }
    return value;
}

EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
{
    if (dhcp6())
    {
        return dhcp4() ? DHCPConf::both : DHCPConf::v6;
    }
    else if (dhcp4())
    {
        return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
    }
    return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
}

bool EthernetInterface::linkUp() const
{
    bool value = EthernetInterfaceIntf::linkUp();

    ifreq ifr = {};
    std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
    try
    {
        getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
        value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
                        entry("ERROR=%s", e.what()));
    }
    return value;
}

size_t EthernetInterface::mtu() const
{
    size_t value = EthernetInterfaceIntf::mtu();

    ifreq ifr = {};
    std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
    try
    {
        getIFSock().ioctl(SIOCGIFMTU, &ifr);
        value = ifr.ifr_mtu;
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("ioctl failed for SIOCGIFMTU:",
                        entry("ERROR=%s", e.what()));
    }
    return value;
}

size_t EthernetInterface::mtu(size_t value)
{
    if (value == EthernetInterfaceIntf::mtu())
    {
        return value;
    }
    else if (value == 0)
    {
        return EthernetInterfaceIntf::mtu();
    }

    ifreq ifr = {};
    std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
    ifr.ifr_mtu = value;

    try
    {
        getIFSock().ioctl(SIOCSIFMTU, &ifr);
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("ioctl failed for SIOCSIFMTU:",
                        entry("ERROR=%s", strerror(errno)));
        return EthernetInterfaceIntf::mtu();
    }

    EthernetInterfaceIntf::mtu(value);
    return value;
}

bool EthernetInterface::queryNicEnabled() const
{
    constexpr auto svc = "org.freedesktop.network1";
    constexpr auto intf = "org.freedesktop.network1.Link";
    constexpr auto prop = "AdministrativeState";
    char* rpath;
    sd_bus_path_encode("/org/freedesktop/network1/link",
                       std::to_string(ifIndex()).c_str(), &rpath);
    std::string path(rpath);
    free(rpath);

    // Store / Parser for the AdministrativeState return value
    std::optional<bool> ret;
    auto cb = [&](std::string_view state) {
        if (state != "initialized")
        {
            ret = state != "unmanaged";
        }
    };

    // Build a matcher before making the property call to ensure we
    // can eventually get the value.
    sdbusplus::bus::match_t match(
        bus,
        fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
                    "'PropertiesChanged',arg0='{}',",
                    svc, path, PROPERTY_INTERFACE, intf)
            .c_str(),
        [&](sdbusplus::message_t& m) {
            std::string intf;
            std::unordered_map<std::string, std::variant<std::string>> values;
            try
            {
                m.read(intf, values);
                auto it = values.find(prop);
                // Ignore properties that aren't AdministrativeState
                if (it != values.end())
                {
                    cb(std::get<std::string>(it->second));
                }
            }
            catch (const std::exception& e)
            {
                log<level::ERR>(
                    fmt::format(
                        "AdministrativeState match parsing failed on {}: {}",
                        interfaceName(), e.what())
                        .c_str(),
                    entry("INTERFACE=%s", interfaceName().c_str()),
                    entry("ERROR=%s", e.what()));
            }
        });

    // Actively call for the value in case the interface is already configured
    auto method =
        bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
    method.append(intf, prop);
    try
    {
        auto reply = bus.call(method);
        std::variant<std::string> state;
        reply.read(state);
        cb(std::get<std::string>(state));
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            fmt::format("Failed to get AdministrativeState on {}: {}",
                        interfaceName(), e.what())
                .c_str(),
            entry("INTERFACE=%s", interfaceName().c_str()),
            entry("ERROR=%s", e.what()));
    }

    // The interface is not yet configured by systemd-networkd, wait until it
    // signals us a valid state.
    while (!ret)
    {
        bus.wait();
        bus.process_discard();
    }

    return *ret;
}

static void setNICAdminState(stdplus::const_zstring intf, bool up)
{
    ifreq ifr = {};
    std::strncpy(ifr.ifr_name, intf.data(), IF_NAMESIZE - 1);
    getIFSock().ioctl(SIOCGIFFLAGS, &ifr);

    ifr.ifr_flags &= ~IFF_UP;
    ifr.ifr_flags |= up ? IFF_UP : 0;
    getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
}

bool EthernetInterface::nicEnabled(bool value)
{
    if (value == EthernetInterfaceIntf::nicEnabled())
    {
        return value;
    }

    EthernetInterfaceIntf::nicEnabled(value);
    writeConfigurationFile();
    if (!value)
    {
        // We only need to bring down the interface, networkd will always bring
        // up managed interfaces
        manager.addReloadPreHook(
            [ifname = interfaceName()]() { setNICAdminState(ifname, false); });
    }
    manager.reloadConfigs();

    return value;
}

ServerList EthernetInterface::staticNameServers(ServerList value)
{
    for (const auto& nameserverip : value)
    {
        if (!isValidIP(nameserverip))
        {
            log<level::ERR>("Not a valid IP address"),
                entry("ADDRESS=%s", nameserverip.c_str());
            elog<InvalidArgument>(
                Argument::ARGUMENT_NAME("StaticNameserver"),
                Argument::ARGUMENT_VALUE(nameserverip.c_str()));
        }
    }
    try
    {
        EthernetInterfaceIntf::staticNameServers(value);

        writeConfigurationFile();
        manager.reloadConfigs();
    }
    catch (const InternalFailure& e)
    {
        log<level::ERR>("Exception processing DNS entries");
    }
    return EthernetInterfaceIntf::staticNameServers();
}

void EthernetInterface::loadNTPServers(const config::Parser& config)
{
    EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
    EthernetInterfaceIntf::staticNTPServers(
        config.map.getValueStrings("Network", "NTP"));
}

void EthernetInterface::loadNameServers(const config::Parser& config)
{
    EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
    EthernetInterfaceIntf::staticNameServers(
        config.map.getValueStrings("Network", "DNS"));
}

ServerList EthernetInterface::getNTPServerFromTimeSyncd()
{
    ServerList servers; // Variable to capture the NTP Server IPs
    auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
                                      PROPERTY_INTERFACE, METHOD_GET);

    method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");

    try
    {
        auto reply = bus.call(method);
        std::variant<ServerList> response;
        reply.read(response);
        servers = std::get<ServerList>(response);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        log<level::ERR>(
            "Failed to get NTP server information from Systemd-Timesyncd");
    }

    return servers;
}

ServerList EthernetInterface::getNameServerFromResolvd()
{
    ServerList servers;
    std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());

    /*
      The DNS property under org.freedesktop.resolve1.Link interface contains
      an array containing all DNS servers currently used by resolved. It
      contains similar information as the DNS server data written to
      /run/systemd/resolve/resolv.conf.

      Each structure in the array consists of a numeric network interface index,
      an address family, and a byte array containing the DNS server address
      (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
      The array contains DNS servers configured system-wide, including those
      possibly read from a foreign /etc/resolv.conf or the DNS= setting in
      /etc/systemd/resolved.conf, as well as per-interface DNS server
      information either retrieved from systemd-networkd or configured by
      external software via SetLinkDNS().
    */

    using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
    std::variant<type> name; // Variable to capture the DNS property
    auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
                                      PROPERTY_INTERFACE, METHOD_GET);

    method.append(RESOLVED_INTERFACE, "DNS");

    try
    {
        auto reply = bus.call(method);
        reply.read(name);
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
    }
    auto tupleVector = std::get_if<type>(&name);
    for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
    {
        int addressFamily = std::get<0>(*i);
        std::vector<uint8_t>& ipaddress = std::get<1>(*i);

        switch (addressFamily)
        {
            case AF_INET:
                if (ipaddress.size() == sizeof(struct in_addr))
                {
                    servers.push_back(toString(
                        *reinterpret_cast<struct in_addr*>(ipaddress.data())));
                }
                else
                {
                    log<level::ERR>(
                        "Invalid data recived from Systemd-Resolved");
                }
                break;

            case AF_INET6:
                if (ipaddress.size() == sizeof(struct in6_addr))
                {
                    servers.push_back(toString(
                        *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
                }
                else
                {
                    log<level::ERR>(
                        "Invalid data recived from Systemd-Resolved");
                }
                break;

            default:
                log<level::ERR>(
                    "Unsupported address family in DNS from Systemd-Resolved");
                break;
        }
    }
    return servers;
}

std::string EthernetInterface::vlanIntfName(VlanId id) const
{
    return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
}

std::string EthernetInterface::vlanObjPath(VlanId id) const
{
    return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
}

void EthernetInterface::loadVLAN(VlanId id)
{
    auto vlanInterfaceName = vlanIntfName(id);
    auto path = vlanObjPath(id);

    config::Parser config(
        config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));

    auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
        bus, path.c_str(), config, EthernetInterfaceIntf::nicEnabled(), id,
        *this, manager);

    // Fetch the ip address from the system
    // and create the dbus object.
    vlanIntf->createIPAddressObjects();
    vlanIntf->createStaticNeighborObjects();
    vlanIntf->loadNameServers(config);
    vlanIntf->loadNTPServers(config);

    this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
                                 std::move(vlanIntf));
}

ObjectPath EthernetInterface::createVLAN(VlanId id)
{
    auto vlanInterfaceName = vlanIntfName(id);
    if (this->vlanInterfaces.find(vlanInterfaceName) !=
        this->vlanInterfaces.end())
    {
        log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
        elog<InvalidArgument>(
            Argument::ARGUMENT_NAME("VLANId"),
            Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
    }

    auto path = vlanObjPath(id);

    // Pass the parents nicEnabled property, so that the child
    // VLAN interface can inherit.
    auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
        bus, path.c_str(), config::Parser(),
        EthernetInterfaceIntf::nicEnabled(), id, *this, manager);

    // write the device file for the vlan interface.
    vlanIntf->writeDeviceFile();

    this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));

    writeConfigurationFile();
    manager.reloadConfigs();

    return path;
}

ServerList EthernetInterface::staticNTPServers(ServerList value)
{
    try
    {
        EthernetInterfaceIntf::staticNTPServers(value);

        writeConfigurationFile();
        manager.reloadConfigs();
    }
    catch (InternalFailure& e)
    {
        log<level::ERR>("Exception processing NTP entries");
    }
    return EthernetInterfaceIntf::staticNTPServers();
}

ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
{
    elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
}
// Need to merge the below function with the code which writes the
// config file during factory reset.
// TODO openbmc/openbmc#1751

void EthernetInterface::writeConfigurationFile()
{
    for (const auto& intf : vlanInterfaces)
    {
        intf.second->writeConfigurationFile();
    }

    config::Parser config;
    config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
    {
        auto& link = config.map["Link"].emplace_back();
#ifdef PERSIST_MAC
        auto mac = MacAddressIntf::macAddress();
        if (!mac.empty())
        {
            link["MACAddress"].emplace_back(mac);
        }
#endif
        if (!EthernetInterfaceIntf::nicEnabled())
        {
            link["Unmanaged"].emplace_back("yes");
        }
    }
    {
        auto& network = config.map["Network"].emplace_back();
        auto& lla = network["LinkLocalAddressing"];
#ifdef LINK_LOCAL_AUTOCONFIGURATION
        lla.emplace_back("yes");
#else
        lla.emplace_back("no");
#endif
        network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
        network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
                                             : (dhcp6() ? "ipv6" : "false"));
        {
            auto& vlans = network["VLAN"];
            for (const auto& intf : vlanInterfaces)
            {
                vlans.emplace_back(
                    intf.second->EthernetInterface::interfaceName());
            }
        }
        {
            auto& ntps = network["NTP"];
            for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
            {
                ntps.emplace_back(ntp);
            }
        }
        {
            auto& dnss = network["DNS"];
            for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
            {
                dnss.emplace_back(dns);
            }
        }
        {
            auto& address = network["Address"];
            for (const auto& addr : getAddresses())
            {
                if (originIsManuallyAssigned(addr.second->origin()) &&
                    !dhcpIsEnabled(addr.second->type()))
                {
                    address.emplace_back(
                        fmt::format("{}/{}", addr.second->address(),
                                    addr.second->prefixLength()));
                }
            }
        }
        {
            auto& gateways = network["Gateway"];
            if (!dhcp4())
            {
                auto gateway = EthernetInterfaceIntf::defaultGateway();
                if (!gateway.empty())
                {
                    gateways.emplace_back(gateway);
                }
            }

            if (!dhcp6())
            {
                auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
                if (!gateway6.empty())
                {
                    gateways.emplace_back(gateway6);
                }
            }
        }
    }
    config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
        dhcp6() ? "true" : "false");
    {
        auto& neighbors = config.map["Neighbor"];
        for (const auto& sneighbor : staticNeighbors)
        {
            auto& neighbor = neighbors.emplace_back();
            neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
            neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
        }
    }
    {
        auto& dhcp = config.map["DHCP"].emplace_back();
        dhcp["ClientIdentifier"].emplace_back("mac");
        if (manager.getDHCPConf())
        {
            const auto& conf = *manager.getDHCPConf();
            auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
            dhcp["UseDNS"].emplace_back(dns_enabled);
            dhcp["UseDomains"].emplace_back(dns_enabled);
            dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
            dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
                                                                    : "false");
            dhcp["SendHostname"].emplace_back(
                conf.sendHostNameEnabled() ? "true" : "false");
        }
    }
    auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
    config.writeFile(path);
    auto msg = fmt::format("Wrote networkd file: {}", path.native());
    log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
}

std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
{
#ifdef PERSIST_MAC
    ether_addr newMAC;
    try
    {
        newMAC = mac_address::fromString(value);
    }
    catch (const std::invalid_argument&)
    {
        log<level::ERR>("MACAddress is not valid.",
                        entry("MAC=%s", value.c_str()));
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
                              Argument::ARGUMENT_VALUE(value.c_str()));
    }
    if (!mac_address::isUnicast(newMAC))
    {
        log<level::ERR>("MACAddress is not valid.",
                        entry("MAC=%s", value.c_str()));
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
                              Argument::ARGUMENT_VALUE(value.c_str()));
    }

    auto interface = interfaceName();
    std::string validMAC = mac_address::toString(newMAC);

    // We don't need to update the system if the address is unchanged
    ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
    if (!stdplus::raw::equal(newMAC, oldMAC))
    {
        // Update everything that depends on the MAC value
        for (const auto& [name, intf] : vlanInterfaces)
        {
            intf->MacAddressIntf::macAddress(validMAC);
        }
        MacAddressIntf::macAddress(validMAC);

        writeConfigurationFile();
        manager.addReloadPreHook([interface]() {
            // The MAC and LLADDRs will only update if the NIC is already down
            setNICAdminState(interface, false);
        });
        manager.reloadConfigs();
    }

#ifdef HAVE_UBOOT_ENV
    // Ensure that the valid address is stored in the u-boot-env
    auto envVar = interfaceToUbootEthAddr(interface);
    if (envVar)
    {
        // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
        // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
        execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
                validMAC.c_str());
    }
#endif // HAVE_UBOOT_ENV

    return value;
#else
    elog<NotAllowed>(
        NotAllowedArgument::REASON("Writing MAC address is not allowed"));
#endif // PERSIST_MAC
}

void EthernetInterface::deleteAll()
{
    // clear all the ip on the interface
    addrs.clear();

    writeConfigurationFile();
    manager.reloadConfigs();
}

std::string EthernetInterface::defaultGateway(std::string gateway)
{
    auto gw = EthernetInterfaceIntf::defaultGateway();
    if (gw == gateway)
    {
        return gw;
    }

    if (!isValidIP(AF_INET, gateway) && !gateway.empty())
    {
        log<level::ERR>("Not a valid v4 Gateway",
                        entry("GATEWAY=%s", gateway.c_str()));
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
                              Argument::ARGUMENT_VALUE(gateway.c_str()));
    }
    gw = EthernetInterfaceIntf::defaultGateway(gateway);

    writeConfigurationFile();
    manager.reloadConfigs();

    return gw;
}

std::string EthernetInterface::defaultGateway6(std::string gateway)
{
    auto gw = EthernetInterfaceIntf::defaultGateway6();
    if (gw == gateway)
    {
        return gw;
    }

    if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
    {
        log<level::ERR>("Not a valid v6 Gateway",
                        entry("GATEWAY=%s", gateway.c_str()));
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
                              Argument::ARGUMENT_VALUE(gateway.c_str()));
    }
    gw = EthernetInterfaceIntf::defaultGateway6(gateway);

    writeConfigurationFile();
    manager.reloadConfigs();

    return gw;
}
} // namespace network
} // namespace phosphor
