/*
 * Copyright (c) 2017 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 <vnet/ip/ip.h>
#include <vnet/fib/fib_table.h>

u8
ip_is_zero (ip46_address_t * ip46_address, u8 is_ip4)
{
  if (is_ip4)
    return (ip46_address->ip4.as_u32 == 0);
  else
    return (ip46_address->as_u64[0] == 0 && ip46_address->as_u64[1] == 0);
}

u8
ip_is_local_host (ip46_address_t * ip46_address, u8 is_ip4)
{
  if (is_ip4)
    return (ip46_address->ip4.as_u8[0] == 127);
  else
    return (ip46_address->as_u64[0] == 0 &&
	    clib_net_to_host_u64 (ip46_address->as_u64[1]) == 1);
}

u8
ip4_is_local_host (ip4_address_t * ip4_address)
{
  return (ip4_address->as_u8[0] == 127);
}

u8
ip6_is_local_host (ip6_address_t * ip6_address)
{
  return (ip6_address->as_u64[0] == 0 &&
	  clib_net_to_host_u64 (ip6_address->as_u64[1]) == 1);
}

/**
 * Checks that an ip is local to the requested fib
 */
u8
ip_is_local (u32 fib_index, ip46_address_t * ip46_address, u8 is_ip4)
{
  fib_node_index_t fei;
  fib_entry_flag_t flags;
  fib_prefix_t prefix;

  /* Check if requester is local */
  if (is_ip4)
    {
      prefix.fp_len = 32;
      prefix.fp_proto = FIB_PROTOCOL_IP4;
    }
  else
    {
      prefix.fp_len = 128;
      prefix.fp_proto = FIB_PROTOCOL_IP6;
    }

  clib_memcpy_fast (&prefix.fp_addr, ip46_address, sizeof (ip46_address_t));
  fei = fib_table_lookup (fib_index, &prefix);
  flags = fib_entry_get_flags (fei);

  return (flags & FIB_ENTRY_FLAG_LOCAL);
}

void
ip_copy (ip46_address_t * dst, ip46_address_t * src, u8 is_ip4)
{
  if (is_ip4)
    dst->ip4.as_u32 = src->ip4.as_u32;
  else
    clib_memcpy_fast (&dst->ip6, &src->ip6, sizeof (ip6_address_t));
}

void
ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
{
  if (is_ip4)
    dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
  else
    clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
		      sizeof (ip6_address_t));
}

u8
ip_interface_has_address (u32 sw_if_index, ip46_address_t * ip, u8 is_ip4)
{
  ip_interface_address_t *ia = 0;

  if (is_ip4)
    {
      ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
      ip4_address_t *ip4;
      /* *INDENT-OFF* */
      foreach_ip_interface_address (lm4, ia, sw_if_index, 1 /* unnumbered */ ,
      ({
        ip4 = ip_interface_address_get_address (lm4, ia);
        if (ip4_address_compare (ip4, &ip->ip4) == 0)
          return 1;
      }));
      /* *INDENT-ON* */
    }
  else
    {
      ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
      ip6_address_t *ip6;
      /* *INDENT-OFF* */
      foreach_ip_interface_address (lm6, ia, sw_if_index, 1 /* unnumbered */ ,
      ({
        ip6 = ip_interface_address_get_address (lm6, ia);
        if (ip6_address_compare (ip6, &ip->ip6) == 0)
          return 1;
      }));
      /* *INDENT-ON* */
    }
  return 0;
}

void *
ip_interface_get_first_ip (u32 sw_if_index, u8 is_ip4)
{
  ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
  ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
  ip_interface_address_t *ia = 0;

  if (is_ip4)
    {
      /* *INDENT-OFF* */
      foreach_ip_interface_address (lm4, ia, sw_if_index, 1 /* unnumbered */ ,
      ({
        return ip_interface_address_get_address (lm4, ia);
      }));
      /* *INDENT-ON* */
    }
  else
    {
      /* *INDENT-OFF* */
      foreach_ip_interface_address (lm6, ia, sw_if_index, 1 /* unnumbered */ ,
      ({
        ip6_address_t *rv;
        rv = ip_interface_address_get_address (lm6, ia);
        /* Trying to use a link-local ip6 src address is a fool's errand */
        if (!ip6_address_is_link_local_unicast (rv))
          return rv;
      }));
      /* *INDENT-ON* */
    }

  return 0;
}

void
ip4_address_normalize (ip4_address_t * ip4, u8 preflen)
{
  ASSERT (preflen <= 32);
  if (preflen == 0)
    ip4->data_u32 = 0;
  else
    ip4->data_u32 &= clib_net_to_host_u32 (0xffffffff << (32 - preflen));
}

void
ip6_address_normalize (ip6_address_t * ip6, u8 preflen)
{
  ASSERT (preflen <= 128);
  if (preflen == 0)
    {
      ip6->as_u64[0] = 0;
      ip6->as_u64[1] = 0;
    }
  else if (preflen <= 64)
    {
      ip6->as_u64[0] &=
	clib_host_to_net_u64 (0xffffffffffffffffL << (64 - preflen));
      ip6->as_u64[1] = 0;
    }
  else
    ip6->as_u64[1] &=
      clib_host_to_net_u64 (0xffffffffffffffffL << (128 - preflen));
}

void
ip4_preflen_to_mask (u8 pref_len, ip4_address_t * ip)
{
  if (pref_len == 0)
    ip->as_u32 = 0;
  else
    ip->as_u32 = clib_host_to_net_u32 (~((1 << (32 - pref_len)) - 1));
}

u32
ip4_mask_to_preflen (ip4_address_t * mask)
{
  if (mask->as_u32 == 0)
    return 0;
  return (32 - log2_first_set (clib_net_to_host_u32 (mask->as_u32)));
}

void
ip4_prefix_max_address_host_order (ip4_address_t * ip, u8 plen,
				   ip4_address_t * res)
{
  u32 not_mask;
  not_mask = (1 << (32 - plen)) - 1;
  res->as_u32 = clib_net_to_host_u32 (ip->as_u32) + not_mask;
}

void
ip6_preflen_to_mask (u8 pref_len, ip6_address_t * mask)
{
  if (pref_len == 0)
    {
      mask->as_u64[0] = 0;
      mask->as_u64[1] = 0;
    }
  else if (pref_len <= 64)
    {
      mask->as_u64[0] =
	clib_host_to_net_u64 (0xffffffffffffffffL << (64 - pref_len));
      mask->as_u64[1] = 0;
    }
  else
    {
      mask->as_u64[0] = 0xffffffffffffffffL;
      mask->as_u64[1] =
	clib_host_to_net_u64 (0xffffffffffffffffL << (128 - pref_len));
    }
}

void
ip6_prefix_max_address_host_order (ip6_address_t * ip, u8 plen,
				   ip6_address_t * res)
{
  u64 not_mask;
  if (plen == 0)
    {
      res->as_u64[0] = 0xffffffffffffffffL;
      res->as_u64[1] = 0xffffffffffffffffL;
    }
  else if (plen <= 64)
    {
      not_mask = ((u64) 1 << (64 - plen)) - 1;
      res->as_u64[0] = clib_net_to_host_u64 (ip->as_u64[0]) + not_mask;
      res->as_u64[1] = 0xffffffffffffffffL;
    }
  else
    {
      not_mask = ((u64) 1 << (128 - plen)) - 1;
      res->as_u64[1] = clib_net_to_host_u64 (ip->as_u64[1]) + not_mask;
    }
}

u32
ip6_mask_to_preflen (ip6_address_t * mask)
{
  u8 first1, first0;
  if (mask->as_u64[0] == 0 && mask->as_u64[1] == 0)
    return 0;
  first1 = log2_first_set (clib_net_to_host_u64 (mask->as_u64[1]));
  first0 = log2_first_set (clib_net_to_host_u64 (mask->as_u64[0]));

  if (first1 != 0)
    return 128 - first1;
  else
    return 64 - first0;
}

u8 *
format_ip_address_family (u8 * s, va_list * args)
{
  ip_address_family_t af = va_arg (*args, ip_address_family_t);

  switch (af)
    {
    case AF_IP4:
      return (format (s, "ip4"));
    case AF_IP6:
      return (format (s, "ip6"));
    }

  return (format (s, "unknown"));
}

u8 *
format_ip_dscp (u8 * s, va_list * va)
{
  ip_dscp_t dscp = va_arg (*va, u32);	// int promotion of u8

  switch (dscp)
    {
#define _(n,v)                                                  \
    case IP_DSCP_##v:                                           \
      return (format (s, "%s", #v));
      foreach_ip_dscp
#undef _
    }

  return (format (s, "unknown"));
}

u8 *
format_ip_ecn (u8 * s, va_list * va)
{
  ip_ecn_t ecn = va_arg (*va, u32);	// int promotion of u8

  switch (ecn)
    {
#define _(n,v)                                                  \
    case IP_ECN_##v:                                           \
      return (format (s, "%s", #v));
      foreach_ip_ecn
#undef _
    }

  return (format (s, "unknown"));
}

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
