/***************************************************************************
                          icmp.c  -  ICMP stuff
                             -------------------
    begin                : Sat Feb 2 2002
    copyright            : (C) 2002 by Josiah Zayner
    email                : phric@legions.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "wand.h"

#ifdef _GTK_

/* globals for icmp*/
GtkWidget *itype_lbl, *icode_lbl, *itype, *isubs;
GtkWidget *fixed_pos2;

 /* ICMP subcodes DAMN thats alot */
void icmp_sub(GtkWidget *nook, GtkEntry *entry)
{
  GList *subs = NULL;
  const char *item;
  static int su = 0;
  item = gtk_entry_get_text(entry);

  if(strstr(item, "Destination Unreachable"))
  {
    if(su){ gtk_widget_hide(isubs); }
    su = 1;
    isubs = make_combo(fixed_pos2, isubs, 190, 10, 385, 290);
    subs = g_list_append(subs, (void *)"Network Unreachable");
    subs = g_list_append(subs, (void *)"Host Unreachable");
    subs = g_list_append(subs, (void *)"Bad Protocol");
    subs = g_list_append(subs, (void *)"Port Unreachable");
    subs = g_list_append(subs, (void *)"Need Fragmentation");
    subs = g_list_append(subs, (void *)"Source Route Failed");
    subs = g_list_append(subs, (void *)"Unknown Network");
    subs = g_list_append(subs, (void *)"Unknown Host");
    subs = g_list_append(subs, (void *)"Source Host Isolated");
    subs = g_list_append(subs, (void *)"Network Prohibited");
    subs = g_list_append(subs, (void *)"Host Prohibited");
    subs = g_list_append(subs, (void *)"Bad TOS For Network");
    subs = g_list_append(subs, (void *)"Bad TOS For Host");
    subs = g_list_append(subs, (void *)"Packet Filtered");
    subs = g_list_append(subs, (void *)"Host Precedence Violation");
    subs = g_list_append(subs, (void *)"Precedence Cutoff");
    gtk_combo_set_popdown_strings(GTK_COMBO(isubs), subs);
    g_list_free(subs);
    gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(isubs)->entry), FALSE);
  }

    else if(strstr(item, "Redirect"))
    {
      if(su){ gtk_widget_hide(isubs); }
      su = 1;
      isubs = make_combo(fixed_pos2, isubs, 190, 10, 385, 290);
      subs = g_list_append(subs, (void *)"Network Redirect");
      subs = g_list_append(subs, (void *)"Host Redirect");
      subs = g_list_append(subs, (void *)"Network TOS Redirect");
      subs = g_list_append(subs, (void *)"Host TOS Redirect");
      gtk_combo_set_popdown_strings(GTK_COMBO(isubs), subs);
      g_list_free(subs);
      gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(isubs)->entry), FALSE);
    }

      else if(strstr(item, "Time Exceeded"))
      {
        if(su){ gtk_widget_hide(isubs); }
        su = 1;
        isubs = make_combo(fixed_pos2, isubs, 190, 10, 385, 290);
        subs = g_list_append(subs, (void *)"In Transit");
        subs = g_list_append(subs, (void *)"IP Reassemmbly");
        gtk_combo_set_popdown_strings(GTK_COMBO(isubs), subs);
        g_list_free(subs);
        gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(isubs)->entry), FALSE);
      }

        else if(strstr(item, "Parameter Problem"))
        {
          if(su){ gtk_widget_hide(isubs); }
          su = 1;
          isubs = make_combo(fixed_pos2, isubs, 190, 10, 385, 290);
          subs = g_list_append(subs, (void *)"Required Option Absent");
          gtk_combo_set_popdown_strings(GTK_COMBO(isubs), subs);
          g_list_free(subs);
          gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(isubs)->entry), FALSE);

        }

          else if(su)
          { gtk_widget_hide(isubs); }
}

/* displaying widgets for ICMP packet */
void icmp_spell(void)
{
  GList *itypes = NULL;
  GtkWidget *tab2_lbl = NULL;

  tab2_lbl = gtk_label_new(" ICMP ");
  fixed_pos2 = gtk_fixed_new();
  gtk_notebook_insert_page(GTK_NOTEBOOK(tab),
                           fixed_pos2,
                           tab2_lbl,
			   1);
  gtk_widget_show(fixed_pos2);
  gtk_widget_show(tab2_lbl);


  itype_lbl = icode_lbl = NULL;

  itype_lbl = make_label(fixed_pos2, itype_lbl, "ICMP Type:", 25, 290);
  itype = make_combo(fixed_pos2, itype, 170, 10, 102, 290);
  itypes = g_list_append(itypes, (void *)"Echo Reply");
  itypes = g_list_append(itypes, (void *)"Destination Unreachable");
  itypes = g_list_append(itypes, (void *)"Source Quench");
  itypes = g_list_append(itypes, (void *)"Redirect");
  itypes = g_list_append(itypes, (void *)"Echo Request");
  itypes = g_list_append(itypes, (void *)"Router Advertisement");
  itypes = g_list_append(itypes, (void *)"Router Solicitation");
  itypes = g_list_append(itypes, (void *)"Time Exceeded");
  itypes = g_list_append(itypes, (void *)"Parameter Problems");
  itypes = g_list_append(itypes, (void *)"Timestamp Request");
  itypes = g_list_append(itypes, (void *)"Timestamp Reply");
  itypes = g_list_append(itypes, (void *)"Information Request");
  itypes = g_list_append(itypes, (void *)"Information Reply");
  itypes = g_list_append(itypes, (void *)"Address Mask Request");
  itypes = g_list_append(itypes, (void *)"Address Mask Reply");

  gtk_combo_set_popdown_strings(GTK_COMBO(itype), itypes);
  g_list_free(itypes);
  gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(itype)->entry), FALSE);

  gtk_signal_connect(GTK_OBJECT(GTK_COMBO(itype)->entry),
                     "changed",
                     GTK_SIGNAL_FUNC(icmp_sub),
                     GTK_ENTRY(GTK_COMBO(itype)->entry)
                    );

  icode_lbl = make_label(fixed_pos2, icode_lbl, "ICMP Sub-Code:", 285, 290);

}


void icmp_defaults(void){}

/* clear ICMP widgets */
void clear_icmp(void)
{
  gtk_widget_hide(itype_lbl);
  gtk_widget_hide(itype);
  gtk_widget_hide(icode_lbl);
  gtk_widget_hide(fixed_pos2);

  if(isubs)
  { gtk_widget_hide(isubs); }
}

/* gather ICMP packet + data info */
struct packmack *icmp_gather(char *icmp_pack, char *data)
{
  struct icmp *icmp_magic = clalloc(S_ICMP);
  struct packmack *icmps = clalloc(sizeof(struct packmack ));
  int d_len = strlen(data);

  icmp_magic->icmp_type = geticmptypebyname(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(itype)->entry)));

  if(isubs == NULL)
  { icmp_magic->icmp_code = 0; }

  else
  { icmp_magic->icmp_code = geticmpsubbyname(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(isubs)->entry))); }

  memcpy(icmp_pack, icmp_magic, S_ICMP);
  if(d_len)
    memcpy(icmp_pack + S_ICMP, data, d_len);
  icmp_magic->icmp_cksum = in_cksum((u_short *)icmp_pack, S_ICMP + d_len);
  memcpy(icmp_pack + S_IP, icmp_magic, S_ICMP);
  if(d_len)
    memcpy(icmp_pack + S_IP + S_ICMP, data, d_len);
  free(icmp_magic);
  icmps->packsz = S_IP + S_ICMP + d_len;
  icmps->d_port = 0;
  return icmps;
}


int geticmptypebyname(const char *type_name)
{
  int type = 0;

  if(strstr(type_name, "Echo Reply"))
  { type = ICMP_ECHOREPLY; }

  else if(strstr(type_name, "Destination Unreachable"))
  { type = ICMP_DEST_UNREACH; }

  else if(strstr(type_name, "Source Quench"))
  { type = ICMP_SOURCE_QUENCH; }

  else if(strstr(type_name, "Redirect"))
  { type = ICMP_REDIRECT; }

  else if(strstr(type_name, "Echo Request") && !strstr(type_name, "Echo Reply"))
  { type = ICMP_ECHO; }
  else if(strstr(type_name, "Router Advertisement"))
  { type = ICMP_ROUTERADVERT; }

  else if(strstr(type_name, "Router Solicitation"))
  { type = ICMP_ROUTERSOLICIT; }

  else if(strstr(type_name, "Time Exceeded"))
  { type = ICMP_TIMXCEED; }

  else if(strstr(type_name, "Parameter Problem"))
  { type = ICMP_PARAMPROB; }

  else if(strstr(type_name, "Timestamp Request"))
  { type = ICMP_TSTAMP; }

  else if(strstr(type_name, "Timestamp Reply"))
  { type = ICMP_TSTAMPREPLY; }

  else if(strstr(type_name, "Information Request"))
  { type = ICMP_IREQ; }

  else if(strstr(type_name, "Information Reply"))
  { type = ICMP_IREQREPLY; }

  else if(strstr(type_name, "Address Mask Request"))
  { type = ICMP_MASKREQ; }

  else if(strstr(type_name, "Address Mask Reply"))
  { type = ICMP_MASKREPLY; }



  return type;
}



int geticmpsubbyname(const char *sub_name)
{
  int sub = 0;

  if(strstr(sub_name, "Network Unreachable") || strstr(sub_name, "Network Redirect")
     || strstr(sub_name, "In Transit"))
  { sub = 0; }

  else if(strstr(sub_name, "Host Unreachable") || strstr(sub_name, "Host Redirect")
          || strstr(sub_name, "In Reass") || strstr(sub_name, "Required Option Absent"))
  { sub = 1; }

  else if(strstr(sub_name, "Protocol Unreachable") || strstr(sub_name, "Network TOS Redirect"))
  { sub = 2; }

  else if(strstr(sub_name, "Port Unreachable") || strstr(sub_name, "Host TOS Redirect"))
  { sub = 3; }

  else if(strstr(sub_name, "Need Fragmentation"))
  { sub = ICMP_UNREACH_NEEDFRAG; }

  else if(strstr(sub_name, "Source Route Failed"))
  { sub = ICMP_UNREACH_SRCFAIL; }

  else if(strstr(sub_name, "Network Unknown"))
  { sub = ICMP_UNREACH_NET_UNKNOWN; }

  else if(strstr(sub_name, "Host Unknown"))
  { sub = ICMP_UNREACH_HOST_UNKNOWN; }

  else if(strstr(sub_name, "Host Isolated"))
  { sub = ICMP_UNREACH_ISOLATED; }

  else if(strstr(sub_name, "Network Prohibited"))
  { sub = ICMP_UNREACH_NET_PROHIB; }

  else if(strstr(sub_name, "Host Prohibited"))
  { sub = ICMP_UNREACH_HOST_PROHIB; }

  else if(strstr(sub_name, "Bad TOS For Network"))
  { sub = ICMP_UNREACH_TOSNET; }

  else if(strstr(sub_name, "Bad TOS For Host"))
  { sub = ICMP_UNREACH_TOSHOST; }

  else if(strstr(sub_name, "Packet Filtered"))
  { sub = ICMP_UNREACH_FILTER_PROHIB; }

  else if(strstr(sub_name, "Host Precedence Violation"))
  { sub = ICMP_UNREACH_HOST_PRECEDENCE; }

  else if(strstr(sub_name, "Precedence Cutoff"))
  { sub = ICMP_UNREACH_PRECEDENCE_CUTOFF; }

  return sub;
}

#endif /* _GTK_ */




#ifdef _CON_

int get_icmp_arg(char *arg, char *next_arg, struct icmp *eyec)
{

  switch((int)arg[2])
  {
    /* should we error check our type and subcodes?
       this prevents experimenting or codes and types I missed..
    */
    case 't':
    eyec->icmp_type = atoi(next_arg);
    switch((int)eyec->icmp_type)
    {
       case 30:

       break;
    }
    break;

    case 's':
    eyec->icmp_code = atoi(next_arg);
    break;


    case 'i':
    eyec->icmp_ex.seqid.id = atoi(next_arg);
    break;

    default:
    fprintf(stderr, "Bad Option: %s, see usage -h\n", arg);
    exit(-1);
    break;
  }

  return 0;
}

#endif /* _CON_ */
