/*
    ettercap -- gtk interface packet factory

    Copyright (C) 2001  ALoR <alor@users.sourceforge.net>, NaGA <crwm@freemail.it>
    GTK+ 2.0 interface by daten <daten@dnetc.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.

    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, Boston, MA 02111-1307, USA.
*/

#include <ec_main.h>

#include <ec_gtk.h>
#include <ec_inet_forge.h>
#include <ec_inet.h>
#include <ec_inet_structures.h>
#include <ec_filterdrop.h>

/* if FORM is defined, ec_interface_form provides trim_buffer */
/* otherwise, a copy of trim_buffer will be provided by ec_gtk */
#ifdef HAVE_FORM
extern void trim_buffer(char *buffer, char trim);
#endif


// protos...

int Ginterface_Factory_Run(void);
int Ginterface_Factory_ETH(u_char *buf);
int Ginterface_Factory_IP(u_char *buf, short *proto);
int Ginterface_Factory_TCP(u_char *buf);
int Ginterface_Factory_UDP(u_char *buf);
int Ginterface_Factory_RAW(u_char *buf);

// global variables

extern GtkWidget *window;
extern int gConn_Pointer;


//---------------------------


int Ginterface_Factory_ETH(u_char *buf)
{
   GtkWidget *popup, *table;
   GtkWidget *source_entry, *dest_entry;
   GtkWidget *label;
   int finished = 0;
   short len = -1;

   DEBUG_MSG("Ginterface_Factory_ETH");

   popup = gtk_dialog_new_with_buttons ("Ethernet Header", GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT,
                                 "Set Filter", GTK_RESPONSE_YES, "Cancel", GTK_RESPONSE_NO, NULL);
   gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_CENTER);

   table = gtk_table_new (4, 2, TRUE);
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(popup)->vbox), table);

   label = gtk_label_new_with_mnemonic ("_Source MAC: ");
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
   gtk_widget_show(label);

   source_entry = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (source_entry), 17);
   gtk_entry_set_max_length(GTK_ENTRY (source_entry), 17);
   gtk_table_attach_defaults (GTK_TABLE (table), source_entry, 1, 2, 1, 2);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (source_entry));
   gtk_widget_show(source_entry);

   label = gtk_label_new_with_mnemonic ("_Dest   MAC: ");
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
   gtk_widget_show(label);

   dest_entry = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (dest_entry), 17);
   gtk_entry_set_max_length(GTK_ENTRY (dest_entry), 17);
   gtk_table_attach_defaults (GTK_TABLE (table), dest_entry, 1, 2, 2, 3);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (dest_entry));
   gtk_widget_show(dest_entry);

   label = gtk_label_new ("Type : IP (0x0800)");
   gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 2, 3, 4);
   gtk_widget_show(label);

   gtk_widget_show(table);

   if (!Conn_Between_Hosts)
   {
      gtk_entry_set_text( GTK_ENTRY (source_entry), Host_Source.mac);
      gtk_entry_set_text( GTK_ENTRY (dest_entry), Host_Dest.mac);
   }
   else
   {
      gtk_entry_set_text( GTK_ENTRY (source_entry), Conn_Between_Hosts[gConn_Pointer].source_mac);
      gtk_entry_set_text( GTK_ENTRY (dest_entry), Conn_Between_Hosts[gConn_Pointer].dest_mac);
   }

   finished = gtk_dialog_run (GTK_DIALOG (popup));

   if (finished == -8)  /* GTK_RESPONSE_YES is -8, that means they clicked "set filter" */
   {
      ETH_header *eth;

      eth = (ETH_header *) buf;

      if (Inet_GetMACfromString((char *)gtk_entry_get_text(GTK_ENTRY(source_entry)), eth->source_mac) == -1)
      {
         Ginterface_PopUp("Bad MAC parsing !! sould be in the form [01:02:03:04:05:06] !!");
         gtk_widget_destroy (popup);
         return -1;
      }

      if (Inet_GetMACfromString((char *)gtk_entry_get_text(GTK_ENTRY(dest_entry)), eth->dest_mac) == -1)
      {
         Ginterface_PopUp("Bad MAC parsing !! sould be in the form [01:02:03:04:05:06] !!");
         gtk_widget_destroy (popup);
         return -1;
      }

      DEBUG_MSG("Ginterface_Factory_ETH -- [%s]", gtk_entry_get_text(GTK_ENTRY(source_entry)));
      DEBUG_MSG("Ginterface_Factory_ETH -- [%s]", gtk_entry_get_text(GTK_ENTRY(dest_entry)));

      eth->type = htons(ETH_P_IP);
      len = ETH_HEADER;
   }

   gtk_widget_destroy (popup);
   return len;
}


int Ginterface_Factory_IP(u_char *buf, short *proto)
{
   GtkWidget *popup, *ltable;
   GtkWidget *entry[6]; /* 0 Source IP, 1 dest ip, 2 ident, 3 ttl, 4 protocol, 5 checksum */
   GtkWidget *label;
   int finished = 0;
   short len = -1;

   DEBUG_MSG("Ginterface_Factory_IP");

   popup = gtk_dialog_new_with_buttons ("IP Header", GTK_WINDOW (window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                 "Set Filter", GTK_RESPONSE_YES, "Cancel", GTK_RESPONSE_NO, NULL);
   gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_CENTER);

   ltable = gtk_table_new (7, 3, TRUE);
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(popup)->vbox), ltable);

   label = gtk_label_new_with_mnemonic ("_Source IP: ");
   gtk_table_attach_defaults (GTK_TABLE (ltable), label, 0, 1, 0, 1);
   gtk_widget_show(label);

   entry[0] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[0]), 17);
   gtk_entry_set_max_length(GTK_ENTRY (entry[0]), 17);
   gtk_table_attach_defaults (GTK_TABLE (ltable), entry[0], 1, 3, 0, 1);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[0]));
   gtk_widget_show(entry[0]);

   label = gtk_label_new_with_mnemonic ("_Dest   IP: ");
   gtk_table_attach_defaults (GTK_TABLE (ltable), label, 0, 1, 1, 2);
   gtk_widget_show(label);

   entry[1] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[1]), 17);
   gtk_entry_set_max_length(GTK_ENTRY (entry[0]), 17);
   gtk_table_attach_defaults (GTK_TABLE (ltable), entry[1], 1, 3, 1, 2);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[1]));
   gtk_widget_show(entry[1]);

   label = gtk_label_new_with_mnemonic ("_Ident    : 0x");
   gtk_table_attach_defaults (GTK_TABLE (ltable), label, 0, 1, 2, 3);
   gtk_widget_show(label);

   entry[2] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[2]), 4);
   gtk_entry_set_max_length(GTK_ENTRY (entry[2]), 4);
   gtk_table_attach_defaults (GTK_TABLE (ltable), entry[2], 1, 2, 2, 3);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[2]));
   gtk_widget_show(entry[2]);

   label = gtk_label_new_with_mnemonic ("_TTL      : ");
   gtk_table_attach_defaults (GTK_TABLE (ltable), label, 0, 1, 3, 4);
   gtk_widget_show(label);  

   entry[3] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[3]), 2);
   gtk_entry_set_max_length (GTK_ENTRY (entry[3]), 2);
   gtk_entry_set_text( GTK_ENTRY(entry[3]), "80");
   gtk_table_attach_defaults (GTK_TABLE (ltable), entry[3], 1, 2, 3, 4);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[3]));
   gtk_widget_show(entry[3]);

   label = gtk_label_new_with_mnemonic ("_Protocol : ");
   gtk_table_attach_defaults (GTK_TABLE (ltable), label, 0, 1, 4, 5);
   gtk_widget_show(label);

   entry[4] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[4]), 2);
   gtk_entry_set_max_length (GTK_ENTRY (entry[4]), 2);
   gtk_table_attach_defaults (GTK_TABLE (ltable), entry[4], 1, 2, 4, 5);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[4]));
   gtk_widget_show(entry[4]);

   label = gtk_label_new_with_mnemonic ("_CheckSum : ");
   gtk_table_attach_defaults (GTK_TABLE (ltable), label, 0, 1, 5, 6);
   gtk_widget_show(label);

   entry[5] = gtk_entry_new ();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[5]), 4);
   gtk_entry_set_max_length (GTK_ENTRY (entry[5]), 4);
   gtk_table_attach_defaults (GTK_TABLE (ltable), entry[5], 1, 2, 5, 6);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[5]));
   gtk_widget_show(entry[5]);

   label = gtk_label_new ("(tcp = 06  udp = 11)");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (ltable), label, 2, 3, 4, 5);
   gtk_widget_show(label);

   label = gtk_label_new ("(leave blank for auto)");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach_defaults (GTK_TABLE (ltable), label, 2, 3, 5, 6);
   gtk_widget_show(label);

   gtk_widget_show(ltable);

   if (!Conn_Between_Hosts)
   {
      gtk_entry_set_text (GTK_ENTRY (entry[0]), Host_Source.ip);
      gtk_entry_set_text (GTK_ENTRY (entry[1]), Host_Dest.ip);
      gtk_entry_set_text (GTK_ENTRY (entry[4]), "06");
   }
   else
   {
      gtk_entry_set_text (GTK_ENTRY (entry[0]), Conn_Between_Hosts[gConn_Pointer].source_ip);
      gtk_entry_set_text (GTK_ENTRY (entry[1]), Conn_Between_Hosts[gConn_Pointer].dest_ip);

      if (Conn_Between_Hosts[gConn_Pointer].proto == 'T')
         gtk_entry_set_text (GTK_ENTRY (entry[4]), "06");
      else
         gtk_entry_set_text (GTK_ENTRY (entry[4]), "11");
   }

   finished = gtk_dialog_run (GTK_DIALOG (popup));

   if (finished == -8)
   {
      IP_header *ip;

      ip = (IP_header *) buf;

      ip->h_len          = 5;
      ip->version        = 4;
      ip->tos            = 0;
      ip->t_len          = htons(IP_HEADER);    // to be calculated after payload len
      ip->ident          = htons(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[2])), NULL, 16));
      ip->frag_and_flags = htons(0x4000);       // don't fragment
      ip->ttl            = strtoul(gtk_entry_get_text(GTK_ENTRY (entry[3])), NULL, 16);
      ip->proto          = strtoul(gtk_entry_get_text(GTK_ENTRY (entry[4])), NULL, 16);
      ip->checksum       = 0;                   // to be calculated after header completion
      ip->source_ip      = inet_addr(gtk_entry_get_text(GTK_ENTRY (entry[0])));
      ip->dest_ip        = inet_addr(gtk_entry_get_text(GTK_ENTRY (entry[1])));

      DEBUG_MSG("Ginterface_Factory_IP -- [%s]", int_ntoa(ip->source_ip));
      DEBUG_MSG("Ginterface_Factory_IP -- [%s]", int_ntoa(ip->dest_ip));

      if (strtoul(gtk_entry_get_text(GTK_ENTRY (entry[5])), NULL, 16))
         ip->checksum    = htons(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[5])), NULL, 16));

      *proto = ip->proto;
      len = IP_HEADER;
   }

   gtk_widget_destroy (popup);
   return len;
}


int Ginterface_Factory_TCP(u_char *buf)
{
   GtkWidget *entry[10]; /* source port, dest port, sequence, ack, flags, sum, file */
   GtkWidget *popup, *textview, *table, *label, *scrolled;
   GtkTextBuffer *textbuf = NULL;
   int finished = 0;
   short len = -1;

   DEBUG_MSG("Ginterface_Factory_TCP");

   popup = gtk_dialog_new_with_buttons ("IP Header", GTK_WINDOW (window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                 "Set Filter", GTK_RESPONSE_YES, "Cancel", GTK_RESPONSE_NO, NULL);
   gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_CENTER);

   table = gtk_table_new(8, 4, FALSE);
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(popup)->vbox), table);

   label = gtk_label_new_with_mnemonic ("_Source port : ");
   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[0] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[0]), 5);
   gtk_entry_set_max_length (GTK_ENTRY (entry[0]), 5);
   gtk_table_attach (GTK_TABLE (table), entry[0], 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[0]));
   gtk_widget_show(entry[0]);

   label = gtk_label_new_with_mnemonic ("_Dest port   : ");
   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[1] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[1]), 5);
   gtk_entry_set_max_length (GTK_ENTRY (entry[1]), 5);
   gtk_table_attach (GTK_TABLE (table), entry[1], 3, 4, 0, 1, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[1]));
   gtk_widget_show(entry[1]);

   label = gtk_label_new_with_mnemonic ("Se_quence : 0x");
   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[2] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[2]), 8);
   gtk_entry_set_max_length (GTK_ENTRY (entry[2]), 8);
   gtk_table_attach (GTK_TABLE (table), entry[2], 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[2]));
   gtk_widget_show(entry[2]);

   label = gtk_label_new_with_mnemonic ("_Acknowledge : 0x");
   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 1, 2, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[3] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[3]), 8);
   gtk_entry_set_max_length (GTK_ENTRY (entry[3]), 8);
   gtk_table_attach (GTK_TABLE (table), entry[3], 3, 4, 1, 2, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[3]));
   gtk_widget_show(entry[3]);

   label = gtk_label_new_with_mnemonic ("_Flags    : ");
   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[4] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[4]), 5);
   gtk_entry_set_max_length (GTK_ENTRY (entry[4]), 5);
   gtk_table_attach (GTK_TABLE (table), entry[4], 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[4]));
   gtk_widget_show(entry[4]);

   label = gtk_label_new ("(S/A/P/R/F)");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach (GTK_TABLE (table), label, 2, 4, 2, 3, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   label = gtk_label_new_with_mnemonic ("_CheckSum : 0x");
   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[5] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[5]), 4);
   gtk_entry_set_max_length (GTK_ENTRY (entry[5]), 4);
   gtk_table_attach (GTK_TABLE (table), entry[5], 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[5]));
   gtk_widget_show(entry[5]);

   label = gtk_label_new ("(leave blank for auto)");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach (GTK_TABLE (table), label, 2, 4, 3, 4, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   label = gtk_label_new_with_mnemonic ("_Payload: ");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach (GTK_TABLE (table), label, 0, 4, 4, 5, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   scrolled = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
   gtk_table_attach (GTK_TABLE (table), scrolled, 0, 4, 5, 6, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 10, 0);
   gtk_widget_show (scrolled);

   textview = gtk_text_view_new();
   textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
   gtk_container_add(GTK_CONTAINER (scrolled), textview);
   gtk_widget_show(textview);

   label = gtk_label_new_with_mnemonic ("Or _load Payload from file:");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach (GTK_TABLE (table), label, 0, 4, 6, 7, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[6] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[6]), 50);
   gtk_entry_set_max_length (GTK_ENTRY (entry[6]), 50);
   gtk_table_attach (GTK_TABLE (table), entry[6], 0, 4, 7, 8, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[6]));
   gtk_widget_show(entry[6]);

   gtk_entry_set_text(GTK_ENTRY (entry[4]), "PA");

   gtk_widget_show(table);

   if (!Conn_Between_Hosts)
   {
      char port[5];
      snprintf(port, sizeof(port), "%d", Host_Source.port);
      gtk_entry_set_text (GTK_ENTRY (entry[0]), port);
      snprintf(port, sizeof(port), "%d", Host_Dest.port);
      gtk_entry_set_text (GTK_ENTRY (entry[1]), port);

   }
   else
   {
      char tmp[10];
      snprintf(tmp, sizeof(tmp), "%d", Conn_Between_Hosts[gConn_Pointer].source_port);
      gtk_entry_set_text (GTK_ENTRY (entry[0]), tmp);
      snprintf(tmp, sizeof(tmp), "%d", Conn_Between_Hosts[gConn_Pointer].dest_port);
      gtk_entry_set_text (GTK_ENTRY (entry[1]), tmp);
      snprintf(tmp, sizeof(tmp), "%lx", Conn_Between_Hosts[gConn_Pointer].source_seq);
      gtk_entry_set_text (GTK_ENTRY (entry[2]), tmp);
      snprintf(tmp, sizeof(tmp), "%lx", Conn_Between_Hosts[gConn_Pointer].dest_seq);
      gtk_entry_set_text (GTK_ENTRY (entry[3]), tmp);
   }

   finished = gtk_dialog_run (GTK_DIALOG (popup));

   if (finished == -8)
   {
      TCP_header *tcp;
      IP_header *ip;
      u_char tmp[1500];
      u_char payload[8*50];
      int datalen, i;
      char flags = 0;

      ip = (IP_header *) (buf - IP_HEADER);     // we assume no IP Options !!
      tcp = (TCP_header *) buf;

      memset(tmp, 0, sizeof(tmp));
      memcpy(tmp, gtk_entry_get_text(GTK_ENTRY (entry[6])), 50);
      trim_buffer(tmp, ' ');
      if (strlen(tmp) != 0)   // load from file
      {
         FILE *fts;
         fts = fopen(tmp, "r");
         if (!fts)
         {
            Ginterface_PopUp("File not found !!");
            return len;
         }
         fseek(fts, 0, SEEK_END);

         DEBUG_MSG("Ginterface_Factory_TCP -- file opened [%s] size %d", tmp, ftell(fts));

         if (ftell(fts) + 40 > 1500)
         {
            Ginterface_PopUp("File too big (max 1460 bytes)");
            return len;
         }
         rewind(fts);
         fgets(tmp, 1460, fts);
         datalen = FilterDrop_strescape(payload, tmp);
      }
      else
      {
         GtkTextIter start, end;

         gtk_text_buffer_get_bounds(textbuf, &start, &end);
        
         memset(tmp, 0, sizeof(tmp));
         memcpy(tmp, gtk_text_buffer_get_text(textbuf, &start, &end, FALSE), 8*50);
         // snprintf(tmp, sizeof(tmp), "%s", gtk_text_buffer_get_text(textbuf, &start, &end, FALSE));
         trim_buffer(tmp, ' ');
         datalen = FilterDrop_strescape(payload, tmp);
      }

      memset(tmp, 0, 10);
      memcpy(tmp, gtk_entry_get_text(GTK_ENTRY (entry[4])), 5);
      for(i=0; i<=strlen(tmp); i++)
         switch(tmp[i])
         {
            case 'A':
            case 'a':
                     flags |= TH_ACK;
                     break;
            case 'P':
            case 'p':
                     flags |= TH_PSH;
                     break;
            case 'F':
            case 'f':
                     flags |= TH_FIN;
                     break;
            case 'S':
            case 's':
                     flags |= TH_SYN;
                     break;
            case 'R':
            case 'r':
                     flags |= TH_RST;
                     break;
         }


      tcp->source      = htons(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[0])), NULL, 10));
      tcp->dest        = htons(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[1])), NULL, 10));
      tcp->seq         = htonl(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[2])), NULL, 16));
      tcp->ack_seq     = htonl(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[3])), NULL, 16));
      tcp->flags       = flags;
      tcp->unused      = 0;
      tcp->doff        = 5;
      tcp->window      = htons(32120);
      tcp->checksum    = 0;
      tcp->urg_ptr     = 0;

      DEBUG_MSG("Ginterface_Factory_TCP -- [%d]", ntohs(tcp->source));
      DEBUG_MSG("Ginterface_Factory_TCP -- [%d]", ntohs(tcp->dest));

      ip->t_len        += htons(TCP_HEADER + datalen);
      if (!ip->checksum) ip->checksum = Inet_Forge_ChecksumIP( (u_short *)ip, sizeof(IP_header) );

      if (datalen)
         memcpy(buf + TCP_HEADER, payload, datalen);

      if (strtoul(gtk_entry_get_text(GTK_ENTRY (entry[5])), NULL, 16))
         tcp->checksum = htons(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[5])), NULL, 16));
      else
         tcp->checksum = Inet_Forge_Checksum( (u_short *)tcp, IPPROTO_TCP, TCP_HEADER+datalen, ip->source_ip, ip->dest_ip );

      len = TCP_HEADER + datalen;
   }

   gtk_widget_destroy (popup);
   return len;
}


int Ginterface_Factory_UDP(u_char *buf)
{
   GtkWidget *entry[4]; /* source port, dest port, checksum, file */
   GtkWidget *popup, *textview, *table, *label, *scrolled;
   GtkTextBuffer *textbuf = NULL; /* payload */
   int finished = 0;
   short len = -1;

   DEBUG_MSG("Ginterface_Factory_UDP");

   popup = gtk_dialog_new_with_buttons ("UDP Header", GTK_WINDOW (window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                 "Set Filter", GTK_RESPONSE_YES, "Cancel", GTK_RESPONSE_NO, NULL);
   gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_CENTER);

   table = gtk_table_new(8, 4, FALSE); 
   gtk_container_add (GTK_CONTAINER (GTK_DIALOG(popup)->vbox), table);
   
   label = gtk_label_new_with_mnemonic ("_Source port : ");
   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);
   
   entry[0] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[0]), 5);
   gtk_entry_set_max_length (GTK_ENTRY (entry[0]), 5);
   gtk_table_attach (GTK_TABLE (table), entry[0], 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[0]));
   gtk_widget_show(entry[0]);

   label = gtk_label_new_with_mnemonic ("_Dest port   : ");
   gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[1] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[1]), 5);
   gtk_entry_set_max_length (GTK_ENTRY (entry[1]), 5);
   gtk_table_attach (GTK_TABLE (table), entry[1], 3, 4, 0, 1, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[1]));
   gtk_widget_show(entry[1]);

   label = gtk_label_new_with_mnemonic ("_CheckSum : 0x");
   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[2] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[2]), 4);
   gtk_entry_set_max_length (GTK_ENTRY (entry[2]), 4);
   gtk_table_attach (GTK_TABLE (table), entry[2], 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[2]));
   gtk_widget_show(entry[2]);

   label = gtk_label_new ("(leave blank for auto)");
   gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
   gtk_table_attach (GTK_TABLE (table), label, 2, 4, 3, 4, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   label = gtk_label_new_with_mnemonic ("_Payload: ");
   gtk_table_attach (GTK_TABLE (table), label, 0, 4, 4, 5, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   scrolled = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
   gtk_table_attach (GTK_TABLE (table), scrolled, 0, 4, 5, 6, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 10, 0);
   gtk_widget_show (scrolled);

   textview = gtk_text_view_new();
   textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
   gtk_container_add(GTK_CONTAINER (scrolled), textview);
   gtk_widget_show(textview);

   label = gtk_label_new_with_mnemonic ("Or _load Payload from file:");
   gtk_table_attach (GTK_TABLE (table), label, 0, 4, 6, 7, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_widget_show(label);

   entry[3] = gtk_entry_new();
   gtk_entry_set_width_chars(GTK_ENTRY (entry[3]), 50);
   gtk_entry_set_max_length (GTK_ENTRY (entry[3]), 50);
   gtk_table_attach (GTK_TABLE (table), entry[3], 0, 4, 7, 8, GTK_FILL | GTK_EXPAND, 0, 10, 0);
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry[3]));
   gtk_widget_show(entry[3]);

   gtk_widget_show(table);

   if (!Conn_Between_Hosts)
   {
      char port[5];
      snprintf(port, sizeof(port), "%d", Host_Source.port);
      gtk_entry_set_text(GTK_ENTRY (entry[0]), port); 
      snprintf(port, sizeof(port), "%d", Host_Dest.port);
      gtk_entry_set_text(GTK_ENTRY (entry[1]), port);
   }
   else
   {
      char tmp[10];
      snprintf(tmp, sizeof(tmp), "%d", Conn_Between_Hosts[gConn_Pointer].source_port);
      gtk_entry_set_text(GTK_ENTRY (entry[0]), tmp);
      snprintf(tmp, sizeof(tmp), "%d", Conn_Between_Hosts[gConn_Pointer].dest_port);
      gtk_entry_set_text(GTK_ENTRY (entry[1]), tmp);
   }

   finished = gtk_dialog_run (GTK_DIALOG (popup));

   if (finished == -8)
   {
      UDP_header *udp;
      IP_header *ip;
      u_char tmp[8*50 + 5];
      u_char payload[8*50];
      int datalen;

      ip = (IP_header *) (buf - IP_HEADER);     // we assume no IP Options !!
      udp = (UDP_header *) buf;

      memset(tmp, 0, sizeof(tmp));
      memcpy(tmp, gtk_entry_get_text(GTK_ENTRY (entry[3])), 50);
      trim_buffer(tmp, ' ');
      if (strlen(tmp) != 0)   // load from file
      {
         FILE *fts;
         fts = fopen(tmp, "r");
         if (!fts)
         {
            Ginterface_PopUp("File not found !!");
            return len;
         }
         fseek(fts, 0, SEEK_END);

         DEBUG_MSG("Ginterface_Factory_UDP -- file opened [%s] size %d", tmp, ftell(fts));

         if (ftell(fts) + 40 > 1500)
         {
            Ginterface_PopUp("File too big (max 1460 bytes)");
            return len;
         }
         rewind(fts);
         fgets(tmp, 1460, fts);
         datalen = FilterDrop_strescape(payload, tmp);
      }
      else
      {
         GtkTextIter start, end;
         gtk_text_buffer_get_bounds(textbuf, &start, &end);

         memset(tmp, 0, sizeof(tmp));
         memcpy(tmp, gtk_text_buffer_get_text(textbuf, &start, &end, FALSE), 8*50);

         trim_buffer(tmp, ' ');
         datalen = FilterDrop_strescape(payload, tmp);
      }

      udp->source      = htons(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[0])), NULL, 10));
      udp->dest        = htons(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[1])), NULL, 10));
      udp->checksum    = 0;
      udp->len         = htons(datalen + UDP_HEADER);

      DEBUG_MSG("Ginterface_Factory_UDP -- [%d]", ntohs(udp->source));
      DEBUG_MSG("Ginterface_Factory_UDP -- [%d]", ntohs(udp->dest));

      ip->t_len        += htons(UDP_HEADER + datalen);
      if (!ip->checksum) ip->checksum = Inet_Forge_ChecksumIP( (u_short *)ip, sizeof(IP_header) );

      if (datalen)
         memcpy(buf + UDP_HEADER, payload, datalen);

      if (strtoul(gtk_entry_get_text(GTK_ENTRY (entry[2])), NULL, 16))
         udp->checksum = htons(strtoul(gtk_entry_get_text(GTK_ENTRY (entry[2])), NULL, 16));
      else
         udp->checksum = Inet_Forge_Checksum( (u_short *)udp, IPPROTO_UDP, UDP_HEADER+datalen, ip->source_ip, ip->dest_ip );

      len = UDP_HEADER + datalen;
   }

   gtk_widget_destroy (popup);
   return len;
}


int Ginterface_Factory_RAW(u_char *buf)
{
   GtkWidget *entry; /* file */
   GtkWidget *popup, *textview, *label, *scrolled;
   GtkTextBuffer *textbuf = NULL; /* payload */
   int finished = 0;
   short len = -1;

   DEBUG_MSG("Ginterface_Factory_RAW");

   popup = gtk_dialog_new_with_buttons ("RAW data packet", GTK_WINDOW (window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                 "Set Filter", GTK_RESPONSE_YES, "Cancel", GTK_RESPONSE_NO, NULL);
   gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_CENTER);

   label = gtk_label_new_with_mnemonic ("_Payload : ");
   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(popup)->vbox), label, TRUE, FALSE, 0);
   gtk_widget_show(label);

   scrolled = gtk_scrolled_window_new(NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(popup)->vbox), scrolled, TRUE, TRUE, 0);
   gtk_widget_show (scrolled);

   textview = gtk_text_view_new();
   textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (textview));
   gtk_container_add(GTK_CONTAINER (scrolled), textview);
   gtk_widget_show(textview);
   
   label = gtk_label_new_with_mnemonic ("Or load Payload from _file: ");
   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(popup)->vbox), label, TRUE, FALSE, 0);
   gtk_widget_show(label);

   entry = gtk_entry_new();
   gtk_label_set_mnemonic_widget(GTK_LABEL (label), GTK_WIDGET (entry));
   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(popup)->vbox), entry, TRUE, FALSE, 0);
   gtk_widget_show(entry);

   finished = gtk_dialog_run(GTK_DIALOG(popup));

   if (finished == -8)
   {
      IP_header *ip;
      u_char tmp[14*50 + 5];
      u_char payload[14*50];
      int datalen;

      ip = (IP_header *) (buf - IP_HEADER);     // we assume no IP Options !!

      memset(tmp, 0, sizeof(tmp));
      memcpy(tmp, gtk_entry_get_text(GTK_ENTRY (entry)), 50);
      trim_buffer(tmp, ' ');
      if (strlen(tmp) != 0)   // load from file
      {
         FILE *fts;
         fts = fopen(tmp, "r");
         if (!fts)
         {
            Ginterface_PopUp("File not found !!");
            return len;
         }
         fseek(fts, 0, SEEK_END);

         DEBUG_MSG("Ginterface_Factory_RAW -- file opened [%s] size %d", tmp, ftell(fts));

         if (ftell(fts) + 40 > 1500)
         {
            Ginterface_PopUp("File too big (max 1460 bytes)");
            return len;
         }
         rewind(fts);
         fgets(tmp, 1460, fts);
         datalen = FilterDrop_strescape(payload, tmp);
      }
      else
      {
         GtkTextIter start, end;
         gtk_text_buffer_get_bounds(textbuf, &start, &end);

         memset(tmp, 0, sizeof(tmp));
         memcpy(tmp, gtk_text_buffer_get_text(textbuf, &start, &end, FALSE), 14*50);

         trim_buffer(tmp, ' ');
         datalen = FilterDrop_strescape(payload, tmp);
      }

      if (datalen)
         memcpy(buf, payload, datalen);

      ip->t_len += htons(datalen);
      if (!ip->checksum) ip->checksum = Inet_Forge_ChecksumIP( (u_short *)ip, sizeof(IP_header) );

      len = datalen;
   }

   gtk_widget_destroy (popup);
   return len;
}


int Ginterface_Factory_Run(void)
{

   u_char *buf;
   u_char *forged_pck;
   int ret = 0;
   int MTU, sock;
   short proto;

#ifdef DEBUG
   #ifdef HAVE_FORM
      DEBUG_MSG("Ginterface_Factory_Run");
   #else
      DEBUG_MSG("Ginterface_Factory_Run -- NO FORM");
   #endif
#endif

   sock = Inet_OpenRawSock(Options.netiface);

   Inet_GetIfaceInfo(Options.netiface, &MTU, NULL, NULL, NULL);

   buf = forged_pck = Inet_Forge_packet( MTU );

   if ( (ret = Ginterface_Factory_ETH( forged_pck )) > 0) forged_pck += ret;
   else goto cancelled;

   if ( (ret = Ginterface_Factory_IP( forged_pck, &proto )) > 0) forged_pck += ret;
   else goto cancelled;

   if (proto == IPPROTO_TCP)
   {
      if ( (ret = Ginterface_Factory_TCP( forged_pck )) > 0) forged_pck += ret;
      else goto cancelled;
   }
   else if (proto == IPPROTO_UDP)
   {
      if ( (ret = Ginterface_Factory_UDP( forged_pck )) > 0) forged_pck += ret;
      else goto cancelled;
   }
   else
   {
      if ( (ret = Ginterface_Factory_RAW( forged_pck )) >= 0) forged_pck += ret;
      else goto cancelled;
   }

   Inet_SendRawPacket(sock, buf, forged_pck-buf);

   DEBUG_MSG("Ginterface_Factory_Run -- %d byte(s) sent", forged_pck-buf);

   // Ginterface_Redraw();
   Ginterface_PopUp("%d byte(s) forged and sent on the wire", forged_pck-buf);

cancelled:
   DEBUG_MSG("Ginterface_Factory_Run -- freeing buffer");

   Inet_Forge_packet_destroy( buf );
   Inet_CloseRawSock(sock);

   return 0;
}

/* EOF */
// vim:ts=3:expandtab
