// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#if defined(ANDROID) && __ANDROID_API__ < 24

#include "bin/ifaddrs.h"

#include <errno.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>

#include "bin/fdutils.h"
#include "platform/signal_blocker.h"

namespace dart {
namespace bin {

const int kMaxReadSize = 2048;

static bool SetIfName(struct ifaddrs* ifaddr, int interface) {
  char buf[IFNAMSIZ] = {0};
  char* name = if_indextoname(interface, buf);
  if (name == nullptr) {
    return false;
  }
  ifaddr->ifa_name = new char[strlen(name) + 1];
  strncpy(ifaddr->ifa_name, name, strlen(name) + 1);
  return true;
}

static void SetFlags(struct ifaddrs* ifaddr, int flag) {
  ifaddr->ifa_flags = flag;
}

static void SetAddresses(struct ifaddrs* ifaddr,
                         int family,
                         int index,
                         void* data,
                         size_t len) {
  if (family == AF_INET6) {
    sockaddr_in6* socketaddr = new sockaddr_in6;
    socketaddr->sin6_family = AF_INET6;
    socketaddr->sin6_scope_id = index;
    memmove(&socketaddr->sin6_addr, data, len);
    ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(socketaddr);
    return;
  }
  ASSERT(family == AF_INET);
  sockaddr_in* socketaddr = new sockaddr_in;
  socketaddr->sin_family = AF_INET;
  memmove(&socketaddr->sin_addr, data, len);
  ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(socketaddr);
}

static void SetNetmask(struct ifaddrs* ifaddr, int family) {
  if (family == AF_INET6) {
    sockaddr_in6* mask = new sockaddr_in6;
    mask->sin6_family = AF_INET6;
    memset(&mask->sin6_addr, 0, sizeof(mask->sin6_addr));
    ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
    return;
  }
  ASSERT(family == AF_INET);
  sockaddr_in* mask = new sockaddr_in;
  mask->sin_family = AF_INET;
  memset(&mask->sin_addr, 0, sizeof(mask->sin_addr));
  ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
}

static bool SetIfAddrsFromAddrMsg(struct ifaddrs* ifaddr,
                                  ifaddrmsg* msg,
                                  void* bytes,
                                  size_t len,
                                  nlmsghdr* header) {
  SetAddresses(ifaddr, msg->ifa_family, msg->ifa_index, bytes, len);
  SetNetmask(ifaddr, msg->ifa_family);
  SetFlags(ifaddr, msg->ifa_flags);
  return SetIfName(ifaddr, msg->ifa_index);
}

static bool SetIfAddrsFromInfoMsg(struct ifaddrs* ifaddr,
                                  ifinfomsg* ifi,
                                  void* bytes,
                                  size_t len,
                                  nlmsghdr* header) {
  SetAddresses(ifaddr, ifi->ifi_family, ifi->ifi_index, bytes, len);
  SetNetmask(ifaddr, ifi->ifi_family);
  SetFlags(ifaddr, ifi->ifi_flags);
  return SetIfName(ifaddr, ifi->ifi_index);
}

static int SendRequest() {
  int file_descriptor =
      NO_RETRY_EXPECTED(socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE));
  if (file_descriptor < 0) {
    return -1;
  }
  nlmsghdr header;
  memset(&header, 0, sizeof(header));
  header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
  header.nlmsg_type = RTM_GETADDR;
  header.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg));
  ssize_t num =
      TEMP_FAILURE_RETRY(send(file_descriptor, &header, header.nlmsg_len, 0));
  if (static_cast<size_t>(num) != header.nlmsg_len) {
    FDUtils::SaveErrorAndClose(file_descriptor);
    return -1;
  }
  return file_descriptor;
}

static int FailAndExit(int fd, ifaddrs* head) {
  FDUtils::SaveErrorAndClose(fd);
  freeifaddrs(head);
  return -1;
}

int getifaddrs(struct ifaddrs** result) {
  int file_descriptor = SendRequest();
  if (file_descriptor < 0) {
    return -1;
  }
  struct ifaddrs* head = nullptr;
  struct ifaddrs* cur = nullptr;
  char buf[kMaxReadSize];
  ssize_t amount_read;
  while (true) {
    amount_read =
        TEMP_FAILURE_RETRY(recv(file_descriptor, &buf, kMaxReadSize, 0));
    if (amount_read <= 0) {
      break;
    }
    nlmsghdr* header = reinterpret_cast<nlmsghdr*>(&buf[0]);
    size_t header_size = static_cast<size_t>(amount_read);
    for (; NLMSG_OK(header, header_size);
         header = NLMSG_NEXT(header, header_size)) {
      switch (header->nlmsg_type) {
        case RTM_NEWADDR: {
          ifaddrmsg* address_msg =
              reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(header));
          ssize_t payload_len = IFA_PAYLOAD(header);
          for (rtattr* rta = IFA_RTA(address_msg); RTA_OK(rta, payload_len);
               rta = RTA_NEXT(rta, payload_len)) {
            if (rta->rta_type != IFA_ADDRESS) {
              continue;
            }
            int family = address_msg->ifa_family;
            if (family != AF_INET && family != AF_INET6) {
              continue;
            }
            ifaddrs* next = new ifaddrs;
            memset(next, 0, sizeof(*next));
            if (cur != nullptr) {
              cur->ifa_next = next;
            } else {
              head = next;
            }
            if (!SetIfAddrsFromAddrMsg(next, address_msg, RTA_DATA(rta),
                                       RTA_PAYLOAD(rta), header)) {
              return FailAndExit(file_descriptor, head);
            }
            cur = next;
          }
          break;
        }
        case RTM_NEWLINK: {
          ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(header));
          ssize_t payload_len = IFLA_PAYLOAD(header);
          for (rtattr* rta = IFLA_RTA(ifi); RTA_OK(rta, payload_len);
               rta = RTA_NEXT(rta, payload_len)) {
            if (rta->rta_type != IFA_ADDRESS) {
              continue;
            }
            int family = ifi->ifi_family;
            if (family != AF_INET && family != AF_INET6) {
              continue;
            }
            ifaddrs* next = new ifaddrs;
            memset(next, 0, sizeof(*next));
            if (cur != nullptr) {
              cur->ifa_next = next;
            } else {
              head = next;
            }
            if (!SetIfAddrsFromInfoMsg(next, ifi, RTA_DATA(rta),
                                       RTA_PAYLOAD(rta), header)) {
              return FailAndExit(file_descriptor, head);
            }
            cur = next;
          }
          break;
        }
        case NLMSG_DONE:
          *result = head;
          FDUtils::SaveErrorAndClose(file_descriptor);
          return 0;
        case NLMSG_ERROR:
          return FailAndExit(file_descriptor, head);
      }
    }
  }
  return FailAndExit(file_descriptor, head);
}

void freeifaddrs(struct ifaddrs* addrs) {
  int err = errno;
  struct ifaddrs* previous = nullptr;
  while (addrs != nullptr) {
    delete[] addrs->ifa_name;
    delete addrs->ifa_addr;
    delete addrs->ifa_netmask;
    previous = addrs;
    addrs = addrs->ifa_next;
    delete previous;
  }
  errno = err;
}

}  // namespace bin
}  // namespace dart

#endif  // defined(ANDROID) && __ANDROID_API__ < 24
