/*
 * Copyright (c) 2021 Cisco and/or its affiliates.
 * 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.
 */

#include "ip_sas.h"
#include <vppinfra/types.h>
#include <vnet/ip/ip_interface.h>
#include <vnet/fib/fib_table.h>
#include <vnet/ip/ip6_link.h>
#include <vppinfra/byte_order.h>

/*
 * This file implement source address selection for VPP applications
 * (e.g. ping, DNS, ICMP)
 * It does not yet implement full fledged RFC6724 SAS.
 * SAS assumes every IP enabled interface has an address. The algorithm will
 * not go and hunt for a suitable IP address on other interfaces than the
 * output interface or the specified preferred sw_if_index.
 * That means that an interface with just an IPv6 link-local address must also
 * be configured with an unnumbered configuration pointing to a numbered
 * interface.
 */

static int
ip6_sas_commonlen (const ip6_address_t *a1, const ip6_address_t *a2)
{
  u64 fa = clib_net_to_host_u64 (a1->as_u64[0]) ^
	   clib_net_to_host_u64 (a2->as_u64[0]);
  if (fa == 0)
    {
      u64 la = clib_net_to_host_u64 (a1->as_u64[1]) ^
	       clib_net_to_host_u64 (a2->as_u64[1]);
      if (la == 0)
	return 128;
      return 64 + __builtin_clzll (la);
    }
  else
    {
      return __builtin_clzll (fa);
    }
}

static int
ip4_sas_commonlen (const ip4_address_t *a1, const ip4_address_t *a2)
{
  if (!a1 || !a2)
    return 0;
  u64 a =
    clib_net_to_host_u32 (a1->as_u32) ^ clib_net_to_host_u32 (a2->as_u32);
  if (a == 0)
    return 32;
  return __builtin_clz (a);
}

/*
 * walk all addresses on an interface:
 *  - prefer a source matching the scope of the destination address.
 *  - last resort pick the source address with the longest
 *    common prefix with destination
 * NOTE: This should at some point implement RFC6724.
 */
bool
ip6_sas_by_sw_if_index (u32 sw_if_index, const ip6_address_t *dst,
			ip6_address_t *src)
{
  ip_interface_address_t *ia = 0;
  ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
  ip6_address_t *tmp, *bestsrc = 0;
  int bestlen = 0, l;

  if (ip6_address_is_link_local_unicast (dst) ||
      dst->as_u32[0] == clib_host_to_net_u32 (0xff020000))
    {
      const ip6_address_t *ll = ip6_get_link_local_address (sw_if_index);
      if (NULL == ll)
	{
	  return false;
	}
      ip6_address_copy (src, ll);
      return true;
    }

  foreach_ip_interface_address (
    lm6, ia, sw_if_index, 1, ({
      if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE)
	continue;
      tmp = ip_interface_address_get_address (lm6, ia);
      l = ip6_sas_commonlen (tmp, dst);
      if (l > bestlen || bestsrc == 0)
	{
	  bestsrc = tmp;
	  bestlen = l;
	}
    }));
  if (bestsrc)
    {
      ip6_address_copy (src, bestsrc);
      return true;
    }
  return false;
}

/*
 * walk all addresses on an interface and pick the source address with the
 * longest common prefix with destination.
 */
bool
ip4_sas_by_sw_if_index (u32 sw_if_index, const ip4_address_t *dst,
			ip4_address_t *src)
{
  ip_interface_address_t *ia = 0;
  ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
  ip4_address_t *tmp, *bestsrc = 0;
  int bestlen = 0, l;

  foreach_ip_interface_address (
    lm4, ia, sw_if_index, 1, ({
      if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE)
	continue;
      tmp = ip_interface_address_get_address (lm4, ia);
      l = ip4_sas_commonlen (tmp, dst);
      if (l > bestlen || bestsrc == 0)
	{
	  bestsrc = tmp;
	  bestlen = l;
	}
    }));
  if (bestsrc)
    {
      src->as_u32 = bestsrc->as_u32;
      return true;
    }
  return false;
}

/*
 * table_id must be set. Default = 0.
 * sw_if_index is the interface to pick SA from otherwise ~0 will pick from
 * outbound interface.
 *
 * NOTE: What to do if multiple output interfaces?
 *
 */
bool
ip6_sas (u32 table_id, u32 sw_if_index, const ip6_address_t *dst,
	 ip6_address_t *src)
{
  fib_prefix_t prefix;
  u32 if_index = sw_if_index;

  /* If sw_if_index is not specified use the output interface. */
  if (sw_if_index == ~0)
    {
      clib_memcpy (&prefix.fp_addr.ip6, dst, sizeof (*dst));
      prefix.fp_proto = FIB_PROTOCOL_IP6;
      prefix.fp_len = 128;

      u32 fib_index = fib_table_find (prefix.fp_proto, table_id);
      if (fib_index == (u32) ~0)
	return false;

      fib_node_index_t fei = fib_table_lookup (fib_index, &prefix);
      if (fei == FIB_NODE_INDEX_INVALID)
	return false;

      u32 output_sw_if_index = fib_entry_get_resolving_interface (fei);
      if (output_sw_if_index == ~0)
	return false;
      if_index = output_sw_if_index;
    }
  return ip6_sas_by_sw_if_index (if_index, dst, src);
}

/*
 * table_id must be set. Default = 0.
 * sw_if_index is the interface to pick SA from otherwise ~0 will pick from
 * outbound interface.
 *
 * NOTE: What to do if multiple output interfaces?
 *
 */
bool
ip4_sas (u32 table_id, u32 sw_if_index, const ip4_address_t *dst,
	 ip4_address_t *src)
{
  fib_prefix_t prefix;
  u32 if_index = sw_if_index;

  /* If sw_if_index is not specified use the output interface. */
  if (sw_if_index == ~0)
    {
      clib_memcpy (&prefix.fp_addr.ip4, dst, sizeof (*dst));
      prefix.fp_proto = FIB_PROTOCOL_IP4;
      prefix.fp_len = 32;

      u32 fib_index = fib_table_find (prefix.fp_proto, table_id);
      if (fib_index == (u32) ~0)
	return false;

      fib_node_index_t fei = fib_table_lookup (fib_index, &prefix);
      if (fei == FIB_NODE_INDEX_INVALID)
	return false;

      u32 output_sw_if_index = fib_entry_get_resolving_interface (fei);
      if (output_sw_if_index == ~0)
	return false;
      if_index = output_sw_if_index;
    }
  return ip4_sas_by_sw_if_index (if_index, dst, src);
}
