/***************************************************************************
                          tcp.c  -  for tcp
                             -------------------
    begin                : Mon Oct 22 2001
    copyright            : (C) 2001 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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef _WAND_H
#include "wand.h"
#endif

#ifdef _GTK_

 /* globabls for tcp header(all text boxes) */
GtkWidget *src_te, *dst_te, *d_off_te, *seq_te, *ackseq_te;
GtkWidget *window_te, *urgp_te, *fixed_pos2;

/* all labels and check boxes */
GtkWidget *src_lbl, *dst_lbl, *d_off_lbl, *seq_lbl, *ackseq_lbl;
GtkWidget *flag_lbl, *window_lbl, *urgp_lbl, *none_check;
GtkWidget *syn_check, *ack_check, *psh_check, *rst_check, *fin_check, *urg_check;

GtkWidget *def_fields, *send_pack;

void tcp_spell(void)
{
  GtkWidget *tab2_lbl;

  tab2_lbl = def_fields = send_pack = NULL;

  tab2_lbl = gtk_label_new(" TCP ");
  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);

  src_lbl = make_label(fixed_pos2, src_lbl, "Source Port:", 40, 190);
  src_te = make_text(fixed_pos2, src_te, 50, 22, 120, 190);

  dst_lbl = make_label(fixed_pos2, dst_lbl, "Destination Port:", 190, 190);
  dst_te = make_text(fixed_pos2, dst_te, 50, 22, 290, 190);

  d_off_lbl = make_label(fixed_pos2, d_off_lbl, "Data Offset:", 360, 190);
  d_off_te = make_text(fixed_pos2, d_off_te, 30, 22, 440, 190);

  ackseq_lbl = make_label(fixed_pos2, ackseq_lbl, "ACK Sequence Number:", 290, 270);
  ackseq_te = make_text(fixed_pos2, ackseq_te, 80, 22, 440, 270);

  seq_lbl = make_label(fixed_pos2, seq_lbl, "Sequence Number:", 40, 270);
  seq_te = make_text(fixed_pos2, seq_te, 80, 22, 160, 270);

  syn_check = make_button(fixed_pos2, syn_check, "SYN", 0, 0, 100, 230,0);
  ack_check = make_button(fixed_pos2, ack_check, "ACK", 0, 0, 160, 230,0);
  psh_check = make_button(fixed_pos2, psh_check, "PSH", 0, 0, 220, 230,0);
  rst_check = make_button(fixed_pos2, rst_check, "RST", 0, 0, 280, 230,0);
  fin_check = make_button(fixed_pos2, fin_check, "FIN", 0, 0, 340, 230,0);
  urg_check = make_button(fixed_pos2, urg_check, "URG", 0, 0, 400, 230,0);
  none_check = make_button(fixed_pos2, none_check, "None", 0, 0, 460, 230,0);

  window_lbl = make_label(fixed_pos2, window_lbl, "Window Size:", 40, 310);
  window_te = make_text(fixed_pos2, window_te, 80, 22, 140, 310);

  urgp_lbl = make_label(fixed_pos2, urgp_lbl, "Urgent Pointer:", 340, 310);
  urgp_te = make_text(fixed_pos2, urgp_te, 80, 22, 440, 310);

  /* Our button to send packets*/
  send_pack = make_button(fixed_pos2,
                          send_pack,
                         "Send Packet",
                          90, 30,
                          40, 410,
			  1
                         );

  /* if we click on button send the packet*/
  gtk_signal_connect(GTK_OBJECT(send_pack),
                     "pressed",
                     GTK_SIGNAL_FUNC(send_packet),
                     NULL
                    );

  /* Our button to set defaults*/
  def_fields = make_button(fixed_pos2,
                           def_fields,
                           "Default Values",
                           90, 30,
                           480, 410,
                           1
                          );

  /* if we click on button to set the defaults*/
  gtk_signal_connect(GTK_OBJECT(def_fields),
                     "clicked",
                     GTK_SIGNAL_FUNC(tcp_defaults),
                     NULL
                    );


  tcp_defaults();
}

void tcp_defaults(void)
{

  char rando[10];
  char windo[6];
  char srco[6];

  /* so we can have a random sequence, source port , and window */
  srand(time(0));
  sprintf(rando, "%lu", 1+(unsigned long int) (1000000000.0 * rand()/(RAND_MAX+1.0)) );
  sprintf(windo, "%u", 1+(unsigned int) (4096.0 * rand()/(RAND_MAX+1.0)) );
  sprintf(srco, "%u", 1+(unsigned int) (6000.0 * rand()/(RAND_MAX+1.0)) );

  gtk_entry_set_text(GTK_ENTRY(src_te), srco);
  gtk_entry_set_text(GTK_ENTRY(dst_te), "23");
  gtk_entry_set_text(GTK_ENTRY(d_off_te), "5");
  gtk_entry_set_text(GTK_ENTRY(seq_te), rando);
  gtk_entry_set_text(GTK_ENTRY(ackseq_te), "0");
  gtk_entry_set_text(GTK_ENTRY(window_te), windo);
  gtk_entry_set_text(GTK_ENTRY(urgp_te), "0");


}

/* for agthering TCP packet header info */
struct packmack *tcp_gather(char *tcp_pack, char *data, struct in_addr sourcery, struct in_addr destined)
{
  struct tcphdr *tcp_magic = clalloc(S_TCP);
  struct nmrhdr *nmr_magic = clalloc(sizeof(struct nmrhdr));
  struct packmack *tcps = clalloc(sizeof(struct packmack));

  int d_len = strlen(data);



  nmr_magic->saddr = sourcery;
  nmr_magic->daddr = destined;
  nmr_magic->none = 0;
  nmr_magic->protocol = 6;
  nmr_magic->length = htons(S_TCP + d_len);
   /* put the psuedo header in the pack which will be overwritten */
  memcpy(tcp_pack, nmr_magic, sizeof(struct nmrhdr));

  tcp_magic->th_sport= htons(atoi(gtk_entry_get_text(GTK_ENTRY(src_te))));
  tcp_magic->th_dport = htons(atoi(gtk_entry_get_text(GTK_ENTRY(dst_te))));
  tcp_magic->th_off = atoi(gtk_entry_get_text(GTK_ENTRY(d_off_te)));

  /*  tcp_magic->th_x2 = atoi(gtk_entry_get_text(GTK_ENTRY(rsv2_te))); */

  tcp_magic->th_seq = htonl(strtol(gtk_entry_get_text(GTK_ENTRY(seq_te)), NULL, 0));
  tcp_magic->th_ack = htonl(strtol(gtk_entry_get_text(GTK_ENTRY(ackseq_te)), NULL, 0));

  /* WFWGH - What flags we got here? */
  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(urg_check)))
  { tcp_magic->th_flags += TH_URG; }

  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(syn_check)))
  { tcp_magic->th_flags += TH_SYN; }

  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ack_check)))
  { tcp_magic->th_flags += TH_ACK; }

  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(psh_check)))
  { tcp_magic->th_flags += TH_PUSH; }

  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rst_check)))
  { tcp_magic->th_flags += TH_RST; }

  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fin_check)))
  { tcp_magic->th_flags += TH_FIN; }

  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(none_check)))
  { tcp_magic->th_flags = 0; }


  tcp_magic->th_win = htons(atoi(gtk_entry_get_text(GTK_ENTRY(window_te))));
  tcp_magic->th_urp = atoi(gtk_entry_get_text(GTK_ENTRY(urgp_te)));

  tcps->d_port = tcp_magic->th_dport;

   /* putting our tcp header in the packet */
  memcpy((tcp_pack + sizeof(struct nmrhdr)), tcp_magic, S_TCP);
  /* add data */
  if(d_len)
    memcpy(tcp_pack + sizeof(struct nmrhdr) + S_TCP, data, d_len);

  /* calculate checksum for the psuedo no miss routed packet header and tcp header */
  tcp_magic->th_sum = in_cksum((u_short *)tcp_pack, S_TCP + sizeof(struct nmrhdr) + d_len);

  free(nmr_magic);
  memcpy(tcp_pack + S_IP, tcp_magic, S_TCP);

  if(d_len)
    memcpy(tcp_pack + S_TCPIP, data, d_len);



  free(tcp_magic);
  tcps->packsz = S_TCPIP + d_len;

  return tcps;
}

/* clear all tcp widgets off the board ! */
void clear_tcp(void)
{
  gtk_widget_hide(src_lbl);
  gtk_widget_hide(src_te);
  gtk_widget_hide(dst_lbl);
  gtk_widget_hide(dst_te);
  gtk_widget_hide(d_off_lbl);
  gtk_widget_hide(d_off_te);
  gtk_widget_hide(seq_lbl);
  gtk_widget_hide(seq_te);
  gtk_widget_hide(ackseq_lbl);
  gtk_widget_hide(ackseq_te);
  gtk_widget_hide(window_lbl);
  gtk_widget_hide(window_te);
  gtk_widget_hide(urgp_lbl);
  gtk_widget_hide(urgp_te);
  gtk_widget_hide(syn_check);
  gtk_widget_hide(ack_check);
  gtk_widget_hide(psh_check);
  gtk_widget_hide(fin_check);
  gtk_widget_hide(urg_check);
  gtk_widget_hide(rst_check);
  gtk_widget_hide(none_check);
  gtk_widget_hide(fixed_pos2);


}

void make_tcp_scroll(struct tcphdr *tcps, int howthick, void *gtkwid)
{
  char packetd[200];
  char *bloated = NULL;

  if(howthick == 1)
  {
    sprintf(packetd," TCP\t| Src Port: %d\t| Dst Port: %d\t| Flags: %s\n\n"
           ,ntohs(tcps->th_sport)
           ,ntohs(tcps->th_dport)
           ,(bloated = TCP_FLAGS(tcps->th_flags))
          );
    gtk_text_insert(GTK_TEXT((GtkWidget *)gtkwid), NULL, NULL, NULL, packetd, -1);
    free(bloated);

  }
  else if(howthick == 2)
  {
    sprintf(packetd,"TCP\t| Src Port: %d\t| Dst Port: %d\t| Flags: %s\t| Window: %d\t"
           "\n| Seq. Num: %u\t| ACK Seq.: %u\n\n"
           ,ntohs(tcps->th_sport)
           ,ntohs(tcps->th_dport)
           ,(bloated = TCP_FLAGS(tcps->th_flags))
           ,ntohs(tcps->th_win)
           ,ntohl(tcps->th_seq)
           ,ntohl(tcps->th_ack)
          );

    gtk_text_insert(GTK_TEXT((GtkWidget *)gtkwid), NULL, NULL, NULL, packetd, -1);
    free(bloated);
  }

}


#endif /* _GTK_ */

#ifdef _CON_


int get_tcp_arg(char *arg, char *next_arg, struct tcphdr *tcme)
{
  switch((int)arg[2])
  {

    case 's':
    if(0 <= atoi(next_arg) && atoi(next_arg) < 65536)
      tcme->th_sport = htons(atoi(next_arg));
    else
       prterr("Source Port to large using default port\n");
    break;

    case 'd':
    if(0 <= atoi(next_arg) && atoi(next_arg) < 65536)
      tcme->th_dport = htons(atoi(next_arg));
    else
      prterr("Destination Port to large using default port\n");
    break;

    case 'o':
    tcme->th_off = htons(atoi(next_arg));
    break;

    case 'q':
    tcme->th_seq = 0;
    tcme->th_seq = htonl(strtoul(next_arg,NULL,0));
    break;

    case 'a':
    tcme->th_ack = htonl(strtoul(next_arg,NULL,0));
    break;

    case 'f':
    tcme->th_flags = 0;
    if(strchr(next_arg, 'S'))
    { tcme->th_flags += TH_SYN; }
    if(strchr(next_arg, 'A'))
    { tcme->th_flags += TH_ACK; }
    if(strchr(next_arg, 'F'))
    { tcme->th_flags += TH_FIN; }
    if(strchr(next_arg, 'R'))
    { tcme->th_flags += TH_RST; }
    if(strchr(next_arg, 'U'))
    { tcme->th_flags += TH_URG; }
    if(strchr(next_arg, 'P'))
    { tcme->th_flags += TH_PUSH; }
    if(strchr(next_arg, 'N'))
    { tcme->th_flags = 0; }
    break;

    case 'w':
    if(0 <= atoi(next_arg) && atoi(next_arg) < 65536)
      tcme->th_win = htons(atoi(next_arg));
    else
      prterr("Windows size to big!\n");
    break;

    case 'u':
    tcme->th_urp = atoi(next_arg);
    break;

    default:
    break;
  }


  return 0;
}

/* for printing a TCP packet */
void make_tcp_scroll(struct tcphdr *tcps, int howthick, void *gtkwid)
{
  char *bloated = NULL;
  if(howthick == 1)
  {
    printf("\nReceived TCP Packet: \n"
           "           Src Port: %d\tDst Port: %d\n"
           "              Flags: %s\n\n"
           ,ntohs(tcps->th_sport)
           ,ntohs(tcps->th_dport)
           ,(bloated = TCP_FLAGS(tcps->th_flags))
          );
    free(bloated);

  }
  else if(howthick == 2)
  {
    printf("\nReceived TCP Packet: \n"
           "           Src Port: %d\t        Dst Port: %d\n"
           "              Flags: %s\t  Window: %d\n"
           "           Seq. Num: %u\t        ACK Seq.: %u\n\n"
           ,ntohs(tcps->th_sport)
           ,ntohs(tcps->th_dport)
           ,(bloated = TCP_FLAGS(tcps->th_flags))
           ,ntohs(tcps->th_win)
           ,ntohl(tcps->th_seq)
           ,ntohl(tcps->th_ack)
          );
    free(bloated);
  }

}


#endif /* _CON_ */

