Logo Search packages:      
Sourcecode: karpski version File versions  Download package

connects.c

/*

Connects.c
Brian Costello
This contains the routines used for keeping track of connections,
viewing the connections window and basically everything relating to
connections.

*/

#include <stdio.h>
#include <config.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <pthread.h>
#include <gtk/gtk.h>
#ifdef TM_IN_SYS_TIME
 #include <sys/time.h>
#else
 #include <time.h>
#endif

#include "proto.h"
#include "connects.h"
#include "karpski.h"
#include "gtk_misc.h"
#include "scrupdate.h"
#include "guidefs.h"

/* Globals */

GtkWidget *connectwindow;
GtkWidget *connectlist;
int connect_row;        /* The selected row in the connectlist */
int connect_col;
t_connect_rec *selected_cr = NULL;

t_connect_rec *updated_cl = NULL;
t_connect_rec *last_updated_cl=NULL;

int all_conns_selected=0;


/* External variables */

extern GtkWidget *label4;
extern GtkWidget *statswindow;
extern GtkWidget *main_clist;
extern t_arp_rec *selected_ar;
extern t_arp_rec *first_arp_rec;
extern t_karpski_stats karpski_stats;
extern pthread_mutex_t ArpRecMutex, ConnectMutex;


/* Defines */

#define NUM_CONNECTLIST_COLS 7

/* Functions */

int find_conn_rowno(struct in_addr src, int sport, struct in_addr dst, int dport, int prev)
{
   char *srcstr, *dststr, *sportstr, *dportstr;
   char saddr[32], daddr[32];
   int sportval, dportval;
   int row;
   int found = -1;
   
   if (!connectlist)
      return (-1);
   strcpy(saddr, (char *)inet_ntoa(src));
   strcpy(daddr, (char *)inet_ntoa(dst));
   for (row=prev+1; ((row<GTK_CLIST(connectlist)->rows) && (found<0)); row++)
   {
      gtk_clist_get_text(GTK_CLIST(connectlist), row, 1, &srcstr);
      gtk_clist_get_text(GTK_CLIST(connectlist), row, 2, &sportstr);
      gtk_clist_get_text(GTK_CLIST(connectlist), row, 3, &dststr);
      gtk_clist_get_text(GTK_CLIST(connectlist), row, 4, &dportstr);
        
      sportval = atoi(sportstr);
      dportval = atoi(dportstr);
      if ((sportval == sport) && (dportval == dport) && (!strcmp(saddr, srcstr)) && (!strcmp(daddr, dststr)))
         found = row;
      if ((sportval == dport) && (dportval == sport) && (!strcmp(saddr, dststr)) && (!strcmp(daddr, srcstr)))
         found = row;
   }
   return(found);
}


void update_connections(t_connect_rec *first_connect)
{
   t_connect_rec *t_rec;
   int rowno;
   
   if ((!first_connect) || (!connectlist))
      return;
      
   mutex_enter(ConnectMutex);
   for (t_rec = first_connect; t_rec; t_rec=t_rec->next)
   {
      if (t_rec->need_update)
      {
         rowno = find_conn_rowno(t_rec->src, t_rec->sport, t_rec->dst, t_rec->dport, -1);
         if (rowno<0)
         {
            printf("Can't find %s / %d ", inet_ntoa(t_rec->src), t_rec->sport);
            printf("to         %s / %d\n", inet_ntoa(t_rec->dst), t_rec->dport);
         }
         gtk_clist_set_text(GTK_CLIST(connectlist), rowno, 6, (t_rec->connect_stage == 5) ? "Closed" : "Open");
         if ((rowno = find_conn_rowno(t_rec->src, t_rec->sport, t_rec->dst, t_rec->dport, rowno))>-1)
         {
            gtk_clist_set_text(GTK_CLIST(connectlist), rowno, 0, (t_rec->watchwindow) ? "Yes" : "No");
            gtk_clist_set_text(GTK_CLIST(connectlist), rowno, 6, (t_rec->connect_stage == 5) ? "Closed" : "Open");
         }
         t_rec->need_update = 0;
      }
   }
   mutex_exit(ConnectMutex);
   
}

void display_connections(char *seladdr, t_connect_rec *first_connect, int free_after)
{
   char *texts[NUM_CONNECTLIST_COLS+1];
   char text[NUM_CONNECTLIST_COLS][128];
   char srcstr[32];
   char dststr[32];
   t_connect_rec *t_rec, *t_recnext=NULL;
   int i;

   if ((!connectwindow) || (!connectlist) || (!seladdr) || (!seladdr[0]))
      return;

   for (i=0; i<NUM_CONNECTLIST_COLS; i++)
   {
      texts[i] = text[i];
   }
   texts[NUM_CONNECTLIST_COLS] = NULL;

   mutex_enter(ConnectMutex);
   gtk_clist_freeze(GTK_CLIST(connectlist));

   for (t_rec = first_connect; t_rec; t_rec=t_recnext)
   {
      strcpy(srcstr, inet_ntoa(t_rec->src));
      strcpy(dststr, inet_ntoa(t_rec->dst));
      if ((all_conns_selected) || (!strcasecmp(seladdr, srcstr)) )
      {
         t_rec->need_update = 0;
         sprintf(texts[0], "%s", (t_rec->watchwindow) ? "Yes":"No");
         sprintf(texts[1], "%s", srcstr);
         sprintf(texts[2], "%d", t_rec->sport);
         sprintf(texts[3], "%s", dststr);
         sprintf(texts[4], "%d", t_rec->dport);
         sprintf(texts[5], "%s", t_rec->startstring);
         sprintf(texts[6], "%s", (t_rec->connect_stage == 5) ? "Closed" : "Open");
         gtk_clist_append(GTK_CLIST(connectlist), texts);
         t_recnext = t_rec->next;
      }
      if (free_after)
      {
         free(t_rec);
      }
   }
   
   gtk_clist_thaw(GTK_CLIST(connectlist));
   mutex_exit(ConnectMutex);
}

void draw_new_connections(t_arp_rec *selected_ar)
{
   if (updated_cl)
   {
      display_connections(selected_ar->machine_addr, updated_cl, 1);
      updated_cl = NULL;
      last_updated_cl = NULL;
   }
   else
      if (selected_ar)
         update_connections(selected_ar->first_connect);
}


void select_conlist(GtkWidget *widget, gint row, gint column, 
                    GdkEventButton *bevent)
{
   struct in_addr src, dst;
   u_short sport, dport;
   char *srcstr, *dststr, *sportstr, *dportstr, *seladdrstr;
   t_arp_rec *found_arp_rec;
   int ar_rowno;
   
   gtk_clist_get_text(GTK_CLIST(widget), row, 1, &srcstr);
   gtk_clist_get_text(GTK_CLIST(widget), row, 3, &dststr);
   gtk_clist_get_text(GTK_CLIST(widget), row, 2, &sportstr);
   gtk_clist_get_text(GTK_CLIST(widget), row, 4, &dportstr);
   if (column==3)
      seladdrstr = dststr;
   else
      seladdrstr = srcstr;
   
   src.s_addr = inet_addr(srcstr);
   dst.s_addr = inet_addr(dststr);
   sport = atoi(sportstr);
   dport = atoi(dportstr);
   
   connect_row = row;
   connect_col = column;
   if (all_conns_selected)
   {
      selected_cr = find_connection(first_arp_rec, NULL, src, sport, dst, dport, 0, &found_arp_rec, seladdrstr);
      ar_rowno = get_ar_rowno(found_arp_rec, GTK_CLIST(main_clist));
      gtk_clist_moveto(GTK_CLIST(main_clist), ar_rowno, -1, 0, 0);
      gtk_clist_select_row(GTK_CLIST(main_clist), ar_rowno, -1);
   }
   else
   {
      selected_cr = find_connection(selected_ar, NULL, src, sport, dst, dport, 1, NULL, NULL);
   }
   if (!selected_cr)
   {
      fprintf(stderr, "Can't find the connection!\n");
      /* This should never happen! */
   }
}
                       
t_connect_rec *find_connection(t_arp_rec *first_ar, t_connect_rec **last_connect, struct in_addr src, int sport, struct in_addr dst, int dport, int justone, t_arp_rec **found_arp_rec, char *seladdrstr)
{
   t_connect_rec *t_rec, *fnd_rec;
   t_arp_rec *t_ar;
   int row;
   
   fnd_rec = NULL;

   if (last_connect)   
      *last_connect = NULL;
      
   if (found_arp_rec)
      (*found_arp_rec) = NULL;
      
   mutex_enter(ArpRecMutex);

   for (t_ar = first_ar ; ((t_ar) && (!fnd_rec)); t_ar=t_ar->next)
   {
      row = 0;
      if (((seladdrstr) && (!strcmp(seladdrstr, t_ar->machine_addr))) || (!seladdrstr))
      {
         for (t_rec = t_ar->first_connect; ((t_rec) && (!fnd_rec)); t_rec=t_rec->next)
         {
            if (
                  (t_rec->src.s_addr == src.s_addr) &&
                  (t_rec->sport == sport) &&
                  (t_rec->dst.s_addr == dst.s_addr) &&
                  (t_rec->dport == dport)
                  
               )
               fnd_rec = t_rec;

            if (
                  (t_rec->src.s_addr == dst.s_addr) &&
                  (t_rec->sport == dport) &&
                  (t_rec->dst.s_addr == src.s_addr) &&
                  (t_rec->dport == sport)
               )
               fnd_rec = t_rec;
            if ((!fnd_rec) && (last_connect))
            {
               (*last_connect) = t_rec;
               row++;
            }
         }
      }
      if ((fnd_rec) && (found_arp_rec))
         (*found_arp_rec) = t_ar;
      if (justone)
         break;
   }
   mutex_exit(ArpRecMutex);
   return(fnd_rec);
}

void switchconnect_routine(int all)
{

   GtkWidget *separator;
   GtkWidget *box1, *box2, *button;
   t_arp_rec *t_ar;
   
   static char *titles[NUM_CONNECTLIST_COLS] =
   {
      "Watch", 
      "Src",
      "Src port",
      "Dst",
      "Dst port",
      "Opened",
      "Status"
   };
   
   if (!selected_ar)
   {
      gtk_clist_select_row(GTK_CLIST(main_clist), 0, 0);
      if (!selected_ar)
         return;
   }
   
   if (!connectwindow)
   {
      connectwindow= gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_widget_set_name(connectwindow, "Connections");
      gtk_widget_set_usize(connectwindow, CONNECT_WIDTH, CONNECT_HEIGHT);
      
      gtk_widget_set_uposition(connectwindow, 800, 300);

      gtk_window_set_policy (GTK_WINDOW(connectwindow), TRUE, TRUE, FALSE);
         
      gtk_signal_connect (GTK_OBJECT (connectwindow), "destroy",
                          GTK_SIGNAL_FUNC(gtk_widget_destroyed), &connectwindow);
      if (all)                    
         gtk_window_set_title (GTK_WINDOW (connectwindow), "All Connections");
      else
         gtk_window_set_title (GTK_WINDOW (connectwindow), "Connections");
      gtk_container_border_width (GTK_CONTAINER (connectwindow), 0);
      box1 = gtk_vbox_new (FALSE, 0);
      gtk_container_add (GTK_CONTAINER (connectwindow), box1);
      gtk_widget_show (box1);
      box2 = gtk_vbox_new (FALSE, 10);
      gtk_container_border_width (GTK_CONTAINER (box2), 10);
      gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
      gtk_widget_show (box2);
      
      connectlist = gtk_clist_new_with_titles(7, titles);

      gtk_clist_set_row_height(GTK_CLIST(connectlist), 20); 
      
      gtk_clist_set_column_width(GTK_CLIST(connectlist), 0, 45);
      gtk_clist_set_column_width(GTK_CLIST(connectlist), 1, 100); 
      gtk_clist_set_column_width(GTK_CLIST(connectlist), 2, 60); 
      gtk_clist_set_column_width(GTK_CLIST(connectlist), 3, 100); 
      gtk_clist_set_column_width(GTK_CLIST(connectlist), 4, 60); 
      gtk_clist_set_column_width(GTK_CLIST(connectlist), 5, 80); 
      gtk_clist_set_column_width(GTK_CLIST(connectlist), 6, 80); 

      gtk_clist_set_selection_mode(GTK_CLIST(connectlist), GTK_SELECTION_BROWSE);
      gtk_clist_set_policy(GTK_CLIST(connectlist), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

      gtk_container_border_width(GTK_CONTAINER(connectlist), 5);
      gtk_box_pack_start(GTK_BOX(box2), connectlist, TRUE, TRUE, 0);
      gtk_widget_show(connectlist);

      separator = gtk_hseparator_new ();
      gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
      gtk_widget_show (separator);
      box2 = gtk_hbox_new (FALSE, 10);
      gtk_container_border_width (GTK_CONTAINER (box2), 10);
      gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
      gtk_widget_show (box2);

      button = gtk_button_new_with_label ("Watch");
      gtk_signal_connect( GTK_OBJECT(connectlist), "select_row", (GtkSignalFunc) select_conlist, NULL); 
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                              (GtkSignalFunc) switch_watch,
                              NULL);
      gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
      gtk_widget_show (button);
      button = gtk_button_new_with_label ("close");
      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                                GTK_SIGNAL_FUNC(gtk_widget_destroy),
                                GTK_OBJECT (connectwindow));
      gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
      gtk_widget_show (button);
      connect_row = -1;
   }
   if (!GTK_WIDGET_VISIBLE(connectwindow))
   {
      gtk_widget_show(connectwindow);
      if (all)
      {
         all_conns_selected = 1;
         gtk_clist_clear(GTK_CLIST(connectlist));
         
         mutex_enter(ArpRecMutex);
         
         for (t_ar=first_arp_rec; t_ar; t_ar=t_ar->next)
            if (t_ar->first_connect)
               display_connections(t_ar->machine_addr, t_ar->first_connect, 0);
            
         mutex_exit(ArpRecMutex);
      }
      else
      {
         all_conns_selected = 0;
         gtk_clist_clear(GTK_CLIST(connectlist));
         display_connections(selected_ar->machine_addr, selected_ar->first_connect, 0);
      }
   }
   else
   {
      if (all != all_conns_selected)
      {
         if (all)
         {
            gtk_window_set_title (GTK_WINDOW (connectwindow), "All Connections");
            all_conns_selected = 1;
            gtk_clist_clear(GTK_CLIST(connectlist));
            
            mutex_enter(ArpRecMutex);
            for (t_ar=first_arp_rec; t_ar; t_ar=t_ar->next)
               if (t_ar->first_connect)
                  display_connections(t_ar->machine_name, t_ar->first_connect, 0);
            mutex_exit(ArpRecMutex);
         }
         else
         {
            gtk_window_set_title (GTK_WINDOW (connectwindow), "Connections");
            all_conns_selected = 0;
            gtk_clist_clear(GTK_CLIST(connectlist));
            display_connections(selected_ar->machine_name, selected_ar->first_connect, 0);
         }
      }
      else
      {
         clear_copylist();
         gtk_widget_destroy(connectwindow);
         all_conns_selected = 0;
      }
   }
      
   return;
}

void clear_copylist()
{
   t_connect_rec *t_rec, *t_recnext;
   
   if (!updated_cl)
   {
      last_updated_cl = NULL;
      return;
   }
   
   mutex_enter(ConnectMutex);

   for (t_rec = updated_cl; t_rec; t_rec=t_recnext)
   {
      t_recnext = t_rec->next;
      free(t_rec);
   }
   updated_cl = NULL;
   last_updated_cl = NULL;
   
   mutex_exit(ConnectMutex);
}

void switchconnect()
{
   switchconnect_routine(0);
}

void switchallconnect()
{
   switchconnect_routine(1);
}

void clear_and_free_connections(t_connect_rec *first_connect)
{
   t_connect_rec *t_cr, *t_next;
   
   for (t_cr=first_connect; (t_cr); t_cr=t_next)
   {
      if (t_cr->watchwindow)
      {
         gtk_widget_destroy(t_cr->watchwindow);
         t_cr->watchwindow = NULL;
      }
      t_next = t_cr->next;
      free(t_cr);
   }
}

/***************** Collection thread routines **************************/

void add_new_rec(t_connect_rec *new_rec)
{
   t_connect_rec *copy_rec;
   
   if (!connectwindow)
      return;
      
   copy_rec = MALLOC(sizeof(t_connect_rec), "Copy connect rec - connects.c");
   bcopy(new_rec, copy_rec, sizeof(t_connect_rec));
   copy_rec->next = NULL;
   
   mutex_enter(ConnectMutex);
   if (last_updated_cl)
      last_updated_cl->next = copy_rec;
   else
      updated_cl = copy_rec;
      
   last_updated_cl = copy_rec;
   mutex_exit(ConnectMutex);
   return;
}



int add_connection(t_arp_rec *t_ar,struct in_addr src, int sport, struct in_addr dst, int dport, int our_clist_showing, packet_parse *packet_info, char *methodstr)
{
   char buf2[50];
   t_connect_rec *new_rec, *last_connect, *found_connect;
   char *dptr;                /* A pointer to the TCP payload */
   int dlen, hlen;
   int flag;
   time_t timeval;
   struct tm *tmval;

   if (all_conns_selected)
      our_clist_showing = 1;
   found_connect = find_connection(t_ar, &last_connect, src, sport, dst, dport, 1, NULL, NULL);

   if (found_connect)
   {
      hlen = packet_info->hlen;
      dlen = packet_info->dlen;
      dptr = packet_info->dptr;

      
      if ((flag = getaddonval(packet_info, "flags"))>-1)
      {
         if ((flag & TH_FIN) || ((flag & TH_ACK) && (flag & TH_RST) && (found_connect->connect_stage == 1)))
         {
/*            printf("Closed connection!\n"); */
            found_connect->need_update = 1;
            found_connect->connect_stage = 5;
         }
         else
            if (found_connect->connect_stage != 5)
               found_connect->connect_stage = 2;
      }
      else
         fprintf(stderr, "Error parsing addon value flags in packet\n");

      if ((dlen > 0) && (found_connect->watchwindow))
      {
         printpkt(&found_connect->watchtextbox, packet_info, methodstr);
      }
      return(0);
   }
   
   if ((flag = getaddonval(packet_info, "flags"))>-1)
   {
      if (flag & TH_FIN)
         return(0);           /* Don't accept new connections from FINs */
      
   }
   
   new_rec = MALLOC(sizeof(t_connect_rec), "New connect rec - connects.c");
   
   if (!new_rec)
   {
      perror("malloc");
      return(0);
   }

   karpski_stats.nconnections++;
   set_overall_update(4);

   bzero(new_rec, sizeof(new_rec));
   new_rec->src.s_addr = src.s_addr;
   new_rec->sport = sport;
   new_rec->dst.s_addr = dst.s_addr;
   new_rec->dport = dport;
   new_rec->watchwindow = NULL;
   new_rec->watchtextbox = NULL;
   new_rec->need_update=1;
   if (flag == TH_SYN)
      new_rec->connect_stage = 1;
   else
      new_rec->connect_stage = 2;
   
   timeval = time(NULL);
   tmval = localtime(&timeval);
   
   sprintf(buf2, "%02d:%02d:%02d", tmval->tm_hour, tmval->tm_min, tmval->tm_sec);
   strncpy(new_rec->startstring, buf2, 9);
   new_rec->next = NULL;
   
   add_new_rec(new_rec);

   mutex_enter(ArpRecMutex);
   
   if (last_connect)
      last_connect->next = new_rec;
   else
      t_ar->first_connect = new_rec;

   mutex_exit(ArpRecMutex);

   return(1);
}

Generated by  Doxygen 1.6.0   Back to index