/* route-map for interface.
 * Copyright (C) 1999 Kunihiro Ishiguro
 *
 * This file is part of GNU Zebra.
 *
 * GNU Zebra is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * GNU Zebra is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNU Zebra; see the file COPYING.  If not, write to the Free
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.  
 */

#include <zebra.h>

#include "hash.h"
#include "command.h"
#include "memory.h"
#include "if.h"
#include "if_rmap.h"

struct hash *ifrmaphash;

/* Hook functions. */
static void (*if_rmap_add_hook) (struct if_rmap *) = NULL;
static void (*if_rmap_delete_hook) (struct if_rmap *) = NULL;

static struct if_rmap *
if_rmap_new (void)
{
  struct if_rmap *new;

  new = XCALLOC (MTYPE_IF_RMAP, sizeof (struct if_rmap));

  return new;
}

static void
if_rmap_free (struct if_rmap *if_rmap)
{
  if (if_rmap->ifname)
    XFREE (MTYPE_IF_RMAP_NAME, if_rmap->ifname);

  if (if_rmap->routemap[IF_RMAP_IN])
    XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
  if (if_rmap->routemap[IF_RMAP_OUT])
    XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);

  XFREE (MTYPE_IF_RMAP, if_rmap);
}

struct if_rmap *
if_rmap_lookup (const char *ifname)
{
  struct if_rmap key;
  struct if_rmap *if_rmap;

  /* temporary copy */
  key.ifname = (char *)ifname;

  if_rmap = hash_lookup (ifrmaphash, &key);
  
  return if_rmap;
}

void
if_rmap_hook_add (void (*func) (struct if_rmap *))
{
  if_rmap_add_hook = func;
}

void
if_rmap_hook_delete (void (*func) (struct if_rmap *))
{
  if_rmap_delete_hook = func;
}

static void *
if_rmap_hash_alloc (void *arg)
{
  struct if_rmap *ifarg = arg;
  struct if_rmap *if_rmap;

  if_rmap = if_rmap_new ();
  if_rmap->ifname = XSTRDUP (MTYPE_IF_RMAP_NAME, ifarg->ifname);

  return if_rmap;
}

static struct if_rmap *
if_rmap_get (const char *ifname)
{
  struct if_rmap key;

  /* temporary copy */
  key.ifname = (char *)ifname;

  return (struct if_rmap *) hash_get (ifrmaphash, &key, if_rmap_hash_alloc);
}

static unsigned int
if_rmap_hash_make (void *data)
{
  struct if_rmap *if_rmap = data;
  unsigned int i, key;

  key = 0;
  for (i = 0; i < strlen (if_rmap->ifname); i++)
    key += if_rmap->ifname[i];

  return key;
}

static int
if_rmap_hash_cmp (void *arg1, void* arg2)
{
  struct if_rmap *if_rmap1 = arg1;
  struct if_rmap *if_rmap2 = arg2;
  if (strcmp (if_rmap1->ifname, if_rmap2->ifname) == 0)
    return 1;
  return 0;
}

static struct if_rmap *
if_rmap_set (const char *ifname, enum if_rmap_type type, 
             const char *routemap_name)
{
  struct if_rmap *if_rmap;

  if_rmap = if_rmap_get (ifname);

  if (type == IF_RMAP_IN)
    {
      if (if_rmap->routemap[IF_RMAP_IN])
	XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
      if_rmap->routemap[IF_RMAP_IN] 
        = XSTRDUP (MTYPE_IF_RMAP_NAME, routemap_name);
    }
  if (type == IF_RMAP_OUT)
    {
      if (if_rmap->routemap[IF_RMAP_OUT])
	XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
      if_rmap->routemap[IF_RMAP_OUT] 
        = XSTRDUP (MTYPE_IF_RMAP_NAME, routemap_name);
    }

  if (if_rmap_add_hook)
    (*if_rmap_add_hook) (if_rmap);
  
  return if_rmap;
}

static int
if_rmap_unset (const char *ifname, enum if_rmap_type type, 
               const char *routemap_name)
{
  struct if_rmap *if_rmap;

  if_rmap = if_rmap_lookup (ifname);
  if (!if_rmap)
    return 0;

  if (type == IF_RMAP_IN)
    {
      if (!if_rmap->routemap[IF_RMAP_IN])
	return 0;
      if (strcmp (if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0)
	return 0;

      XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
      if_rmap->routemap[IF_RMAP_IN] = NULL;      
    }

  if (type == IF_RMAP_OUT)
    {
      if (!if_rmap->routemap[IF_RMAP_OUT])
	return 0;
      if (strcmp (if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0)
	return 0;

      XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
      if_rmap->routemap[IF_RMAP_OUT] = NULL;      
    }

  if (if_rmap_delete_hook)
    (*if_rmap_delete_hook) (if_rmap);

  if (if_rmap->routemap[IF_RMAP_IN] == NULL &&
      if_rmap->routemap[IF_RMAP_OUT] == NULL)
    {
      hash_release (ifrmaphash, if_rmap);
      if_rmap_free (if_rmap);
    }

  return 1;
}

DEFUN (if_rmap,
       if_rmap_cmd,
       "route-map RMAP_NAME (in|out) IFNAME",
       "Route map set\n"
       "Route map name\n"
       "Route map set for input filtering\n"
       "Route map set for output filtering\n"
       "Route map interface name\n")
{
  enum if_rmap_type type;
  struct if_rmap *if_rmap;

  if (strncmp (argv[1], "i", 1) == 0)
    type = IF_RMAP_IN;
  else if (strncmp (argv[1], "o", 1) == 0)
    type = IF_RMAP_OUT;
  else
    {
      vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE);
      return CMD_WARNING;
    }

  if_rmap = if_rmap_set (argv[2], type, argv[0]);

  return CMD_SUCCESS;
}      

ALIAS (if_rmap,
       if_ipv6_rmap_cmd,
       "route-map RMAP_NAME (in|out) IFNAME",
       "Route map set\n"
       "Route map name\n"
       "Route map set for input filtering\n"
       "Route map set for output filtering\n"
       "Route map interface name\n")

DEFUN (no_if_rmap,
       no_if_rmap_cmd,
       "no route-map ROUTEMAP_NAME (in|out) IFNAME",
       NO_STR
       "Route map unset\n"
       "Route map name\n"
       "Route map for input filtering\n"
       "Route map for output filtering\n"
       "Route map interface name\n")
{
  int ret;
  enum if_rmap_type type;

  if (strncmp (argv[1], "i", 1) == 0)
    type = IF_RMAP_IN;
  else if (strncmp (argv[1], "o", 1) == 0)
    type = IF_RMAP_OUT;
  else
    {
      vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE);
      return CMD_WARNING;
    }

  ret = if_rmap_unset (argv[2], type, argv[0]);
  if (! ret)
    {
      vty_out (vty, "route-map doesn't exist%s", VTY_NEWLINE);
      return CMD_WARNING;
    }
  return CMD_SUCCESS;
}      

ALIAS (no_if_rmap,
       no_if_ipv6_rmap_cmd,
       "no route-map ROUTEMAP_NAME (in|out) IFNAME",
       NO_STR
       "Route map unset\n"
       "Route map name\n"
       "Route map for input filtering\n"
       "Route map for output filtering\n"
       "Route map interface name\n")

/* Configuration write function. */
int
config_write_if_rmap (struct vty *vty)
{
  unsigned int i;
  struct hash_backet *mp;
  int write = 0;

  for (i = 0; i < ifrmaphash->size; i++)
    for (mp = ifrmaphash->index[i]; mp; mp = mp->next)
      {
	struct if_rmap *if_rmap;

	if_rmap = mp->data;

	if (if_rmap->routemap[IF_RMAP_IN])
	  {
	    vty_out (vty, " route-map %s in %s%s", 
		     if_rmap->routemap[IF_RMAP_IN],
		     if_rmap->ifname,
		     VTY_NEWLINE);
	    write++;
	  }

	if (if_rmap->routemap[IF_RMAP_OUT])
	  {
	    vty_out (vty, " route-map %s out %s%s", 
		     if_rmap->routemap[IF_RMAP_OUT],
		     if_rmap->ifname,
		     VTY_NEWLINE);
	    write++;
	  }
      }
  return write;
}

void
if_rmap_reset ()
{
  hash_clean (ifrmaphash, (void (*) (void *)) if_rmap_free);
}

void
if_rmap_init (int node)
{
  ifrmaphash = hash_create (if_rmap_hash_make, if_rmap_hash_cmp);
  if (node == RIPNG_NODE) {
    install_element (RIPNG_NODE, &if_ipv6_rmap_cmd);
    install_element (RIPNG_NODE, &no_if_ipv6_rmap_cmd);
  } else if (node == RIP_NODE) {
    install_element (RIP_NODE, &if_rmap_cmd);
    install_element (RIP_NODE, &no_if_rmap_cmd);
  }
}
