// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define _POSIX_C_SOURCE 200809L

#define _GNU_SOURCE
#define _DARWIN_C_SOURCE

#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include "netprotocol.h"

static const char* hostname;
static struct sockaddr_in6 addr;
static bool found = false;
static char found_device_nodename[MAX_NODENAME_LENGTH];
static bool local_address = false;
static const char* appname;

static bool on_device(device_info_t* device, void* cookie) {
  if (hostname != NULL && strcmp(hostname, device->nodename)) {
    // Asking for a specific address and this isn't it.
    return true;
  }

  if (found && strcmp(found_device_nodename, device->nodename) != 0) {
    fprintf(stderr, "Multiple devices found, including %s and %s. Specify a hostname.\n",
            found_device_nodename, device->nodename);
    exit(1);
  }

  addr = device->inet6_addr;
  strncpy(found_device_nodename, device->nodename, MAX_NODENAME_LENGTH);
  found = true;
  return true;
}

static void usage(void) {
  fprintf(stderr, "usage: %s [options] [hostname]\n", appname);
  netboot_usage(false);
  fprintf(stderr, "    --local           Print local address that routes to remote.\n");
}

static struct option netaddr_opts[] = {
    {"local", no_argument, NULL, 'l'},
    {NULL, 0, NULL, 0},
};

static bool netaddr_opt_callback(int ch, int argc, char* const* argv) {
  switch (ch) {
    case 'l':
      local_address = true;
      break;
    default:
      return false;
  }
  return true;
}

int main(int argc, char** argv) {
  appname = argv[0];
  int index = netboot_handle_custom_getopt(argc, argv, netaddr_opts, netaddr_opt_callback);
  if (index < 0) {
    usage();
    return -1;
  }

  argv += index;
  argc -= index;

  if (argc > 1) {
    usage();
  }

  if (argc == 1) {
    hostname = argv[0];
    if (!*hostname || (*hostname == ':' && hostname[1] == '\0'))
      hostname = NULL;
  }

  if (netboot_discover(NB_SERVER_PORT, NULL, on_device, NULL) || !found) {
    fprintf(stderr, "Failed to discover %s\n", hostname ? hostname : "");
    return 1;
  }

  if (local_address) {
    // Bind an ephemeral UDP socket to the Fuchsia target address, then inspect
    // the local address it bound to (poor mans portable "lookup route").
    int s;
    if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
      fprintf(stderr, "error: cannot create socket: %s\n", strerror(errno));
      return -1;
    }
    if (connect(s, (const struct sockaddr*)&addr, sizeof(addr)) < 0) {
      fprintf(stderr, "error: cannot \"connect\" socket: %s\n", strerror(errno));
      return -1;
    }
    socklen_t addrlen = sizeof(addr);
    if (getsockname(s, (struct sockaddr*)&addr, &addrlen) < 0) {
      fprintf(stderr, "error: %s\n", strerror(errno));
      return -1;
    }
    shutdown(s, SHUT_RDWR);
  }

  // Get the string form of the address.
  char tmp[INET6_ADDRSTRLEN];
  const char* addr_s = inet_ntop(AF_INET6, &addr.sin6_addr, tmp, sizeof(tmp));
  if (addr_s == NULL) {
    fprintf(stderr, "error: %s\n", strerror(errno));
    return -1;
  }
  fprintf(stdout, "%s%%%d\n", addr_s, addr.sin6_scope_id);

  return 0;
}
