/*
 * $Id: host.c,v 1.1 1999/03/31 02:10:05 jms Exp $
 * GXSNMP -- An snmp management application
 * Copyright (C) 1998 Gregory McLean
 *
 * This program 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 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc.,  59 Temple Place - Suite 330, Cambridge, MA 02139, USA.
 *
 * Host specific routines.
 */
#ifdef HAVE_CONFIG_H
#include <config.h>     /* -- Autoconf groked stuff */
#endif
#include "main.h"

#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <netdb.h>

#include "snmp_host.h"
#include "net_map.h"

extern gxsnmp  *app_info;

GHashTable    *host_hash = NULL;

struct hostent 
*lookuphost (char *hostname)
{
  static struct hostent       hent;
  static struct hostent       *hp;
  static char                 address[sizeof(u_long)];
  static char                 *addresses[] = { address, (char *) NULL};
  u_long                      hostaddr;

  /* 
   * Check and see if we got a host name or an ip address 
   */
  if (isdigit(*hostname)) 
    {
      /* Ip address, build our own hostent */
      hent.h_name     = hostname;
      hent.h_aliases  = (char **)NULL;
      hent.h_addrtype = AF_INET;
      hent.h_length   = sizeof(struct in_addr);
      hostaddr        = inet_addr (hostname);
      bcopy (&hostaddr, address, sizeof(u_long));
      hent.h_addr_list= addresses;
      return &hent;
    } else
      {
	hp = gethostbyname(hostname);
	if (hp)
	  return hp;
	else
	  return NULL;
      }
}

/*
 * Private internal functions 
 */
static void
check_host_hash_table (void)
{
  if (!host_hash)
      host_hash = g_hash_table_new (g_str_hash, g_str_equal);
}

/*
 * Function    : hl_add_host
 * Description : This function will add a host to the internal host table
 *               of all known hosts. Memory allocation/freeing is the 
 *               responsibility of the calling function.
 * Arguments   : entry   --- The hosts entry structure pointer of the host
 *                           to add to the list.
 * Returns     : The hosts entry pointer to the newly added host, or NULL on
 *               failure.
 */

hosts *
hl_add_host (hosts *entry)
{

  hosts         *last = NULL;
  char          buff[120];
  app_event     event;
/*  queue_entry   qentry;*/
  struct hostent *hp;

  g_return_val_if_fail (entry != NULL, (hosts *)NULL);

  check_host_hash_table ();
  last = g_hash_table_lookup (host_hash, entry->hl_snmp.name);
  if (!last)
    {
      g_hash_table_insert (host_hash, g_strdup(entry->hl_snmp.name), entry);
      hp = lookuphost (entry->hl_snmp.name);
      /*
       * This is the only way I could get this to work??
       */
      if (hp)
	{
	  struct in_addr bleh;
	  memcpy (&bleh, hp->h_addr_list[0], hp->h_length);
	  memcpy (&entry->hl_addr, &bleh, sizeof (struct in_addr));
	}
      /* 
       * init more bits of the structure...
       */
      entry->hl_monitor         = NULL;
      entry->listwidget         = NULL;
      entry->hl_if              = NULL;
      entry->hl_queue_last_time = 0;
      entry->hl_poll_interval   = 120;     /* Change to a config value */
      sprintf (buff, "Host \"%s\" has been added to the list.", 
	       entry->hl_snmp.name);
      event.category     = GX_EVENT_INFO;
      event.sub_category = GX_INFO_NONE;
      event.timestamp    = time (NULL);
      event.description  = g_strdup (buff);
      add_event (&event);
/*      qentry.id             = get_next_queue_id ();
      qentry.queue_callback = test_callback;
      qentry.data           = entry;
      add_queue_item (&qentry); */
/*      map_update_stat ("Host \"%s\" has been added to the list.", 
		       entry->hl_snmp.name); */
      return entry;
    }
 
  sprintf (buff, "Host \"%s\" was not added to the list.", 
	   entry->hl_snmp.name);
/*  map_update_stat (buff); */
  return (hosts *)NULL;
}

void
hl_del_host (hosts *entry)
{
  hosts     *del;
  char      buff[80];

  del  = (hosts *)g_hash_table_lookup (host_hash, entry->hl_snmp.name);
  if (del)
    {
#ifdef MEM_DEBUG
      DMC ();
#endif
      if (del->listwidget != NULL)
	  gtk_container_remove (GTK_CONTAINER (app_info->hlist_pane->list),
				entry->listwidget);
      if (app_info->brows_panel != NULL)
	browser_remove_host (del->hl_snmp.name);
      g_hash_table_remove (host_hash, entry->hl_snmp.name);
/*      sprintf (buff, "Host \"%s\" was deleted from the list.", 
	       entry->hl_snmp.name);
      map_update_stat (buff); */
    }
}

GHashTable *
get_host_hash ()
{
  return host_hash;
}

/*
 * interface stuff
 */
void
show_interface_list (hosts *entry)
{
  GSList    *item;
  inf_list  *interface;

  if (!entry->hl_if)
    g_print ("No interfaces known for this host.\n");
  else
    {
      item = entry->hl_if;
      while (item)
	{
	  interface = (inf_list *)item->data;
	  g_print ("Interface %s on node %s\n", inet_ntoa (interface->if_addr),
		   entry->hl_snmp.name);
	  item = g_slist_next (item);
	}
    }
}

static int      found            = FALSE;
static inf_list *which_interface = NULL;

static void
search_host (void *key, void *val, void *data)
{
  hosts           *host;
  struct in_addr  if_addr;
  inf_list        *interface;
  GSList          *item;

  host   = (hosts *)val;
  if (!host->hl_if)
    return;           /* empty list */
  if (found)
    return;
  if_addr.s_addr = ((struct in_addr *)data)->s_addr;
  item = host->hl_if;
  while (item)
    {
      interface = (inf_list *)item->data;
      if ( memcmp ((char *)&interface->if_addr.s_addr,(char *)&if_addr.s_addr,
		   sizeof (if_addr.s_addr)) == 0)
	{
	  found = TRUE;
	  which_interface = interface;
	  break;
	}
      item = g_slist_next (item);
    }
}
/*
 * Global functions provided by this module
 */
/*
 * Function    : find_interface_by_addr 
 * Description : This function will search through all hosts and interfaces
 *               looking for an interface by address. 
 * Arguments   : if_addr -- struct in_addr pointer of the interface in
 *                          in question.
 * Returns     : inf_list structure pointer of the located interface on 
 *               success.
 *               NULL pointer is returned on failure.
 */
inf_list *
find_interface_by_addr (struct in_addr *if_addr)
{
  found           = FALSE;
  which_interface = NULL;

  g_hash_table_foreach (host_hash, search_host, if_addr);
  if (found)
    return which_interface;
  else
    return NULL;
}
/*
 * Function    : add_interface
 * Description : This function will add a new interface to a host.
 * Arguments   : host      -- The hosts entry structure pointer for the host.
 *               interface -- The inf_list structure pointer of the interface
 *                            to add to this host.
 * Returns     : None for now.
 */
void
add_interface (hosts *host, inf_list *interface)
{
  inf_list   *cp;

  if (!host)
    return;
#ifdef MEM_DEBUG
  DMC ();
#endif
  cp = (inf_list *)g_malloc (sizeof (inf_list));
  if (cp)
    {
      memmove ((char *)cp, interface, sizeof (inf_list));
      cp->if_host = host;
      find_interface_by_addr (&cp->if_addr);
      host->hl_if = g_slist_append (host->hl_if, cp);
    }
  else
    {
      return;         /* TODO: set an error code and return */
    }
}

void 
remove_interface (hosts *host, inf_list *interface)
{
  /*TODO: Write me */
}

/*
 * Function    : get_current_host
 * Description : This function will retrive the current host for a given
 *               panel. Or a default if no host was set for the panel.
 * Arguments   : widget  -- A widget of the panel in question.
 * Returns     : The hosts entry structure pointer for the host.
 */
hosts *
get_current_host (GtkWidget *widget)
{
  return NULL;
}

/*
 * Function   : add_host_net_connection
 * Description: This function will add a new connection from a host to 
 *              a network. This can be the same network or multiple 
 *              networks. This is mainly used by the mapping functions.
 * Arguments  : host    -- The hosts structure pointer for the host.
 *              network -- The net_entry structure pointer for the
 *                         network to connect this host to.
 * Returns    : None for now.
 */
void
add_host_net_connection (hosts *host, net_entry *network, 
			 GnomeCanvasItem *item)
{
  g_return_if_fail (network !=NULL);
  g_return_if_fail (host != NULL);

}

/*
 * Function    : find_host_by_name
 * Description : This function will locate a host in the global list
 *               by its name. This is mainly used in the internal list
 *               handling stuff.
 * Arguments   : hostname -- The name of the host to locate.
 * Returns     : hosts entry structure pointer on success.
 *               NULL pointer on failure.
 */      
hosts *
find_host_by_name (const gchar *hostname)
{

  if (host_hash)	
     return (g_hash_table_lookup (host_hash, hostname));
  else
     return NULL;
}

/*
 * Function    : find_host_by_addr
 * Description : This function will locate a host by an address associated
 *               with it, on one of its interfaces, return the hosts entry
 *               structure pointer for said host.
 * Arguments   : addr -- The struct in_addr pointer of the address to find
 *                       on a host.
 * Returns     : hosts entry structure pointer on success.
 *               NULL pointer on failure.
 */
hosts *
find_host_by_addr (struct in_addr *addr)
{
  /*TODO: needs to be written */
  return NULL;
}
/* EOF */

