/*
 * Copyright 2012 Daniel Drown
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * getaddr.c - get a locally configured address
 */
#include <net/if.h>
#include <netinet/in.h>
#include <string.h>
#include <strings.h>

#include <linux/if_addr.h>
#include <linux/rtnetlink.h>
#include <netlink/handlers.h>
#include <netlink/msg.h>

#include "getaddr.h"
#include "logging.h"
#include "netlink_msg.h"

// shared state between getinterface_ip and getaddr_cb
struct target {
  int family;
  unsigned int ifindex;
  union anyip ip;
  int foundip;
};

/* function: getaddr_cb
 * callback for getinterface_ip
 *   msg  - netlink message
 *   data - (struct target) info for which address we're looking for
 */
static int getaddr_cb(struct nl_msg *msg, void *data) {
  struct ifaddrmsg *ifa_p;
  struct rtattr *rta_p;
  int rta_len;
  struct target *targ_p = (struct target *)data;

  ifa_p = (struct ifaddrmsg *)nlmsg_data(nlmsg_hdr(msg));
  rta_p = (struct rtattr *)IFA_RTA(ifa_p);

  if (ifa_p->ifa_index != targ_p->ifindex) return NL_OK;

  if (ifa_p->ifa_scope != RT_SCOPE_UNIVERSE) return NL_OK;

  rta_len = RTM_PAYLOAD(nlmsg_hdr(msg));
  for (; RTA_OK(rta_p, rta_len); rta_p = RTA_NEXT(rta_p, rta_len)) {
    switch (rta_p->rta_type) {
      case IFA_ADDRESS:
        if ((targ_p->family == AF_INET6) && !(ifa_p->ifa_flags & IFA_F_SECONDARY)) {
          memcpy(&targ_p->ip.ip6, RTA_DATA(rta_p), rta_p->rta_len - sizeof(struct rtattr));
          targ_p->foundip = 1;
          return NL_OK;
        }
        break;
      case IFA_LOCAL:
        if (targ_p->family == AF_INET) {
          memcpy(&targ_p->ip.ip4, RTA_DATA(rta_p), rta_p->rta_len - sizeof(struct rtattr));
          targ_p->foundip = 1;
          return NL_OK;
        }
        break;
    }
  }

  return NL_OK;
}

/* function: error_handler
 * error callback for getinterface_ip
 *   nla  - source of the error message
 *   err  - netlink message
 *   arg  - (struct target) info for which address we're looking for
 */
static int error_handler(__attribute__((unused)) struct sockaddr_nl *nla,
                         __attribute__((unused)) struct nlmsgerr *err,
                         __attribute__((unused)) void *arg) {
  return NL_OK;
}

/* function: getinterface_ip
 * finds the first global non-privacy IP of the given family for the given interface, or returns
 * NULL.  caller frees pointer
 *   interface - interface to look for
 *   family    - family
 */
union anyip *getinterface_ip(const char *interface, int family) {
  struct ifaddrmsg ifa;
  struct nl_cb *callbacks = NULL;
  struct target targ;
  union anyip *retval = NULL;

  targ.family  = family;
  targ.foundip = 0;
  targ.ifindex = if_nametoindex(interface);
  if (targ.ifindex == 0) {
    return NULL;  // interface not found
  }

  memset(&ifa, 0, sizeof(ifa));
  ifa.ifa_family = targ.family;

  callbacks = nl_cb_alloc(NL_CB_DEFAULT);
  if (!callbacks) {
    goto cleanup;
  }
  nl_cb_set(callbacks, NL_CB_VALID, NL_CB_CUSTOM, getaddr_cb, &targ);
  nl_cb_err(callbacks, NL_CB_CUSTOM, error_handler, &targ);

  // sends message and waits for a response
  send_ifaddrmsg(RTM_GETADDR, NLM_F_REQUEST | NLM_F_ROOT, &ifa, callbacks);

  if (targ.foundip) {
    retval = malloc(sizeof(union anyip));
    if (!retval) {
      logmsg(ANDROID_LOG_FATAL, "getinterface_ip/out of memory");
      goto cleanup;
    }
    memcpy(retval, &targ.ip, sizeof(union anyip));
  }

cleanup:
  if (callbacks) nl_cb_put(callbacks);

  return retval;
}
