/***************************************************************************
                          udp.c  -  UDP stuff and whatnot
                             -------------------
    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.                                   *
 *                                                                         *
 ***************************************************************************/


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

#ifdef _GTK_

/* globals for udp */
GtkWidget *ulen_te, *ulen_lbl, *utype_lbl, *utype, *dnsid_lbl, *dnsid_te, *dnsop_lbl, *dnsop;
GtkWidget *dnsr_check, *aa_check, *trun_check, *recur_check, *recura_check;
GtkWidget *dnsrc_lbl, *dnsrc, *fixed_pos2;
GtkWidget *src_lbl, *dst_lbl, *dst_te, *src_te;
/* also add DHCP for UDP */
/* DNS widgets */
void show_utypes(GtkEntry *entry)
{
  const char *uitem;
  GList *dnsops = NULL;
  GList *dnsrcs = NULL;
  static int ifdns = 0;

  uitem = gtk_entry_get_text(entry);

  if(strstr(uitem, "DNS"))
  {
    ifdns = 1;

    dnsid_lbl = make_label(fixed_pos, dnsid_lbl, "ID:", 40, 370);
    dnsid_te = make_text(fixed_pos, dnsid_te, 50, 22, 60, 370);

    /* ops codes */
    dnsop_lbl = make_label(fixed_pos, dnsop_lbl, "Opcode:", 130, 370);

    dnsop = make_combo(fixed_pos2, dnsop, 120, 12, 180, 370);
    dnsops = g_list_append(dnsops, (void *)"Query");
    dnsops = g_list_append(dnsops, (void *)"Inverse Query");
    dnsops = g_list_append(dnsops, (void *)"Status");
    dnsops = g_list_append(dnsops, (void *)"Notify of SOA change");

    gtk_combo_set_popdown_strings(GTK_COMBO(dnsop), dnsops);
    g_list_free(dnsops);
    gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(dnsop)->entry), FALSE);

    dnsr_check = make_button(fixed_pos, dnsr_check, "Response Flag", 0, 0, 40, 400,0);
    aa_check = make_button(fixed_pos, aa_check, "Authoritive Answer", 0, 0, 140, 400,0);
    trun_check = make_button(fixed_pos, trun_check, "Truncated Message", 0, 0, 260, 400,0);
    recur_check = make_button(fixed_pos, recur_check, "Recursion Desired", 0, 0, 380, 400,0);
    recura_check = make_button(fixed_pos, recura_check, "Recursion Available", 0, 0, 40, 430,0);

    dnsrc_lbl = make_label(fixed_pos, dnsrc_lbl, "Response Code:", 310, 370);

    dnsrc = make_combo(fixed_pos2, dnsrc, 120, 12, 400, 370);
    dnsrcs = g_list_append(dnsrcs, (void *)"No Error");
    dnsrcs = g_list_append(dnsrcs, (void *)"Format Error");
    dnsrcs = g_list_append(dnsrcs, (void *)"Server Failure");
    dnsrcs = g_list_append(dnsrcs, (void *)"Non Existent Domain");
    dnsrcs = g_list_append(dnsrcs, (void *)"Not Implemented");
    dnsrcs = g_list_append(dnsrcs, (void *)"Query Refused");

    gtk_combo_set_popdown_strings(GTK_COMBO(dnsrc), dnsrcs);
    g_list_free(dnsrcs);
    gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(dnsrc)->entry), FALSE);

  }

    else if(strstr(uitem, "None"))
    {
      if(ifdns)
      { clear_dns(); }
    }


      else if(strstr(uitem, "DHCP"))
      {
        if(ifdns)
        { clear_dns(); }
      }

}

/* display UDP widgets */
void udp_spell(void)
{

 GList *utypes = NULL;
 GtkWidget *tab2_lbl = NULL;

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

 ulen_lbl = make_label(fixed_pos2, ulen_te, "Length:", 360, 190);
 ulen_te = make_text(fixed_pos2, ulen_te, 30, 22, 410, 190);

 utype_lbl = make_label(fixed_pos2, utype_lbl, "Packet Type:", 200, 230);
 utype = make_combo(fixed_pos2, utype, 60, 10, 290, 230);
 utypes = g_list_append(utypes, (void *)"None");
 /*
 utypes = g_list_append(utypes, (void *)"DNS");
 utypes = g_list_append(utypes, (void *)"DHCP");
 */
 gtk_combo_set_popdown_strings(GTK_COMBO(utype), utypes);
 g_list_free(utypes);
 gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(utype)->entry), FALSE);


 gtk_signal_connect(GTK_OBJECT(GTK_COMBO(utype)->entry),
                    "changed",
                    GTK_SIGNAL_FUNC(show_utypes),
                    GTK_ENTRY(GTK_COMBO(utype)->entry)
                   );

 udp_defaults();
}

/* enter in default values */
void udp_defaults(void)
{
  char usrco[6];
  char udleng[5];

  sprintf(udleng, "%d", S_UDP);

  /* random seed */
  srand(time(0));
  /* random source port 0-6000 */
  sprintf(usrco, "%u", 1+(unsigned int) (6000.0*rand()/(RAND_MAX+1.0)) );
  gtk_entry_set_text(GTK_ENTRY(src_te), usrco);
  gtk_entry_set_text(GTK_ENTRY(dst_te), "53");
  gtk_entry_set_text(GTK_ENTRY(ulen_te), udleng);

}


/* for clearing our UDP widgets off */
void clear_udp(void)
{

  gtk_widget_hide(src_lbl);
  gtk_widget_hide(src_te);
  gtk_widget_hide(dst_lbl);
  gtk_widget_hide(dst_te);
  gtk_widget_hide(ulen_lbl);
  gtk_widget_hide(ulen_te);
  gtk_widget_hide(utype_lbl);
  gtk_widget_hide(utype);
  gtk_widget_hide(fixed_pos2);

  /* for DNS */
  if(strstr(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(utype)->entry)), "DNS"))
  { clear_dns(); }

}

/* for clearing DNS widgets off */
void clear_dns(void)
{
  gtk_widget_hide(dnsid_lbl);
  gtk_widget_hide(dnsid_te);
  gtk_widget_hide(dnsop_lbl);
  gtk_widget_hide(dnsop);
  gtk_widget_hide(dnsr_check);
  gtk_widget_hide(aa_check);
  gtk_widget_hide(trun_check);
  gtk_widget_hide(recur_check);
  gtk_widget_hide(recura_check);
  gtk_widget_hide(dnsrc_lbl);
  gtk_widget_hide(dnsrc);

}

/* this is where the packet is actually made, we grab the values
   from the text boxes, menus, etc. and put them into the packet
*/
struct packmack *udp_gather(char *udp_pack, char *data, struct in_addr scorch, struct in_addr desterdly)
{
  struct udphdr *udp_magic = clalloc(S_UDP);
  struct nmrhdr *nmr_magic = clalloc(S_NMR);
  struct packmack *udps = clalloc(sizeof(struct packmack));
  int d_len = strlen(data);

  /* for DNS */
  /*
  struct HEADER *dns_magic;
  char *op;

  if(strstr(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(utype)->entry)), "DNS"))
  {
    dns_magic = (struct HEADER *)(pack + S_IP + S_UDP);
    memset(dns_magic, '\0', sizeof(struct HEADER *));
    dns_magic->id = atoi(gtk_entry_get_text(GTK_ENTRY(dnsid_te)));

    op = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(dnsop)->entry));

    if(strstr(op, "Query") && !strstr(op, "Inverse"))
    { dns_magic->opcode = QUERY; }

    else if(strstr(op, "Inverse"))
    { dns_magic->opcode = IQUERY; }

    else if(strstr(op, "Status"))
    { dns_magic->opcode = STATUS; }

    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dnsr_check)))
    { dns_magic->qr = 1; }

    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(aa_check)))
    { dns_magic->aa = 1; }

    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(trun_check)))
    { dns_magic->tc = 1; }

    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(recur_check)))
    { dns_magic->rd = 1; }

    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(recura_check)))
    { dns_magic->ra = 1; }


  }
   */


  /* psuedo no miss routed header, create checksum packet */
  nmr_magic->saddr = scorch;
  nmr_magic->daddr = desterdly;
  nmr_magic->none = 0;
  nmr_magic->protocol = 17;
  nmr_magic->length = htons(S_UDP + d_len);
  memcpy(udp_pack, nmr_magic, S_NMR);

  /* UDP header + data */
  udp_magic->uh_sport = htons(atoi(gtk_entry_get_text(GTK_ENTRY(src_te))));
  udp_magic->uh_dport = htons(atoi(gtk_entry_get_text(GTK_ENTRY(dst_te))));
  udp_magic->uh_ulen = htons(atoi(gtk_entry_get_text(GTK_ENTRY(ulen_te))) + d_len);
  memcpy(udp_pack + S_NMR, udp_magic, S_UDP);
  if(d_len)
    memcpy(udp_pack + S_NMR + S_UDP, data, d_len);

  /* calculate checksum */
  udp_magic->uh_sum = in_cksum((u_short *)udp_pack, S_UDP + S_NMR + d_len);
  free(nmr_magic);
  /* make real packet */
  memcpy(udp_pack + S_IP, udp_magic, S_UDP);

  if(d_len)
    memcpy(udp_pack + S_IP + S_UDP, data, d_len);

  udps->d_port = udp_magic->uh_dport;
  free(udp_magic);
  udps->packsz = S_IP + S_UDP + d_len;

  return udps;
}

void make_udp_scroll(struct udphdr *udps, int howthick, void *gtkwid)
{
    char packetd[100];
    sprintf(packetd,"\nReceived UDP Packet: \n"
           "           Src Port: %d\tDst Port: %d\n"
           ,ntohs(udps->uh_sport)
           ,ntohs(udps->uh_dport)
          );
 gtk_text_insert(GTK_TEXT((GtkWidget *)gtkwid), NULL, NULL, NULL, packetd, -1);

}
#endif /* _GTK_ */

#ifdef _CON_

int get_udp_arg(char *arg,
                char *next_arg,
                struct udphdr *pdu
               )
{
  switch((int)arg[2])
  {
    case 's':
    if(0 <= atoi(next_arg) && atoi(next_arg) < 65536)
      pdu->uh_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)
      pdu->uh_dport = htons(atoi(next_arg));
    else
      prterr("Destination Port to large using default port\n");
    break;

    case 'l':
    pdu->uh_ulen = atoi(next_arg);
    break;

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

  return 0;
}

/* for printing a UDP packet */
void make_udp_scroll(struct udphdr *udps, int howthick, void *gtkwid)
{
    printf("\nReceived UDP Packet: \n"
           "           Src Port: %d\tDst Port: %d\n"
           ,ntohs(udps->uh_sport)
           ,ntohs(udps->uh_dport)
          );


}


#endif /* _CON_ */

