/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014,  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-interface.hpp"
#include "core/logger.hpp"

#include <cerrno>
#include <cstring>
#include <type_traits>
#include <unordered_map>

#include <arpa/inet.h>   // for inet_ntop()
#include <netinet/in.h>  // for struct sockaddr_in{,6}
#include <ifaddrs.h>     // for getifaddrs()

#if defined(__linux__)
#include <net/if_arp.h>        // for ARPHRD_* constants
#include <netpacket/packet.h>  // for struct sockaddr_ll
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <net/if_dl.h>         // for struct sockaddr_dl
#include <net/if_types.h>      // for IFT_* constants
#endif

NFD_LOG_INIT("NetworkInterfaceInfo");

namespace nfd {

static_assert(std::is_standard_layout<NetworkInterfaceInfo>::value,
              "NetworkInterfaceInfo must be a standard layout type");
#ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE
static_assert(std::is_default_constructible<NetworkInterfaceInfo>::value,
              "NetworkInterfaceInfo must provide a default constructor");
#endif

std::vector<NetworkInterfaceInfo>
listNetworkInterfaces()
{
  using namespace boost::asio::ip;
  using std::strerror;

  std::unordered_map<std::string, NetworkInterfaceInfo> ifmap;
  ifaddrs* ifa_list = nullptr;

  if (::getifaddrs(&ifa_list) < 0)
    throw std::runtime_error(std::string("getifaddrs() failed: ") + strerror(errno));

  for (ifaddrs* ifa = ifa_list; ifa != nullptr; ifa = ifa->ifa_next) {
    std::string ifname(ifa->ifa_name);
    NetworkInterfaceInfo& netif = ifmap[ifname];
    netif.name = ifa->ifa_name;
    netif.flags = ifa->ifa_flags;

    if (ifa->ifa_addr == nullptr)
      continue;

    switch (ifa->ifa_addr->sa_family) {

    case AF_INET: {
      const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_addr);
      char address[INET_ADDRSTRLEN];
      if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address))) {
        netif.ipv4Addresses.push_back(address_v4::from_string(address));
        NFD_LOG_TRACE(ifname << ": added IPv4 address " << address);
      }
      else
        NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET) failed: " << strerror(errno));
      break;
    }

    case AF_INET6: {
      const sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr);
      char address[INET6_ADDRSTRLEN];
      if (::inet_ntop(AF_INET6, &sin6->sin6_addr, address, sizeof(address))) {
        netif.ipv6Addresses.push_back(address_v6::from_string(address));
        NFD_LOG_TRACE(ifname << ": added IPv6 address " << address);
      }
      else
        NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET6) failed: " << strerror(errno));
      break;
    }

#if defined(__linux__)
    case AF_PACKET: {
      const sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
      netif.index = sll->sll_ifindex;
      if (sll->sll_hatype == ARPHRD_ETHER && sll->sll_halen == ethernet::ADDR_LEN) {
        netif.etherAddress = ethernet::Address(sll->sll_addr);
        NFD_LOG_TRACE(ifname << ": added Ethernet address " << netif.etherAddress);
      }
      else if (sll->sll_hatype != ARPHRD_LOOPBACK) {
        NFD_LOG_DEBUG(ifname << ": ignoring link-layer address for unhandled hardware type "
                      << sll->sll_hatype);
      }
      break;
    }

#elif defined(__APPLE__) || defined(__FreeBSD__)
    case AF_LINK: {
      const sockaddr_dl* sdl = reinterpret_cast<sockaddr_dl*>(ifa->ifa_addr);
      netif.index = sdl->sdl_index;
      if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ethernet::ADDR_LEN) {
        netif.etherAddress = ethernet::Address(reinterpret_cast<uint8_t*>(LLADDR(sdl)));
        NFD_LOG_TRACE(ifname << ": added Ethernet address " << netif.etherAddress);
      }
      else if (sdl->sdl_type != IFT_LOOP) {
        NFD_LOG_DEBUG(ifname << ": ignoring link-layer address for unhandled interface type "
                      << sdl->sdl_type);
      }
      break;
    }
#endif
    }

    if (netif.isBroadcastCapable() && ifa->ifa_broadaddr != nullptr) {
      const sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ifa->ifa_broadaddr);
      char address[INET_ADDRSTRLEN];
      if (::inet_ntop(AF_INET, &sin->sin_addr, address, sizeof(address))) {
        netif.broadcastAddress = address_v4::from_string(address);
        NFD_LOG_TRACE(ifname << ": added IPv4 broadcast address " << address);
      }
      else
        NFD_LOG_WARN(ifname << ": inet_ntop(AF_INET) for broadaddr failed: " << strerror(errno));
    }
  }

  ::freeifaddrs(ifa_list);

  std::vector<NetworkInterfaceInfo> v;
  v.reserve(ifmap.size());
  for (auto&& element : ifmap) {
    v.push_back(element.second);
  }

  return v;
}

} // namespace nfd
