/* * Copyright (c) 2001 Fenris, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * File: callbacks.c * * Purpose: This file contains the definitions for use of events in the * gui portion of the realtime network monitor. * */ #ifdef HAVE_CONFIG_H # include #endif #include #include /* UINT_MAX */ #include /* pow */ #include #include /* strncat */ #include "bool.h" #include "callbacks.h" #include "display.h" #include "network.h" #include "globals.h" #include "interface.h" #include "support.h" #include "tree.h" #include "cache_list.h" #define MARGIN 10 #define RADIUS 7 #define VSPACE 40 static GdkPixmap *pixmap = NULL; static Display *display = NULL; enum bool src_chk = false; enum bool dst_chk = false; static char filter_buf[255] = "Displaying all traffic."; static char src_ports_buf[255]; static char dst_ports_buf[255]; static char src_addr_buf[255]; static char dst_addr_buf[255]; static char status_text[1276]; void draw(GtkWidget* widget) { static GdkFont * font = NULL; static int fontx; static GdkGC * gc = NULL; static GdkColormap * cmap = NULL; GdkColor color; Tree_Node * src_tree = NULL; Tree_Node * dst_tree = NULL; Dsp_Node * node; Dsp_Obj * dobj; int ldot = widget->allocation.width / 3; int rdot = ldot * 2; int y; unsigned char src[MAX_HOSTNAME_LEN]; unsigned char dst[MAX_HOSTNAME_LEN]; if (widget == NULL) { return; } /* Initialize the static variables, if necessary. */ if ((font == NULL) || (gc == NULL) || (cmap == NULL) || (display == NULL)) { font = gdk_font_load("lucidasans-10"); fontx = gdk_string_height(font, "!") / 2 + 1; gc = gdk_gc_new(widget->window); cmap = gdk_colormap_get_system(); if ((display = malloc(sizeof(Display))) == NULL) die("malloc"); display->min_rate = 0; display->max_rate = 1000; init_dsp(display); } if (pixmap != NULL) { gdk_pixmap_unref(pixmap); } if (widget->window == NULL) { return; } pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); if (pixmap == NULL) { return; } gdk_draw_rectangle(pixmap, widget->style->white_gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); clear_dsp(display); populate_dsp(display, net); y = VSPACE; node = display->src_list->head; while (node != NULL) { if ((dobj = node->obj) == NULL) { break; } set_root(&src_tree, dobj->src, y); strncpy(src, dobj->src_name, MAX_HOSTNAME_LEN); gdk_draw_string(pixmap, font, widget->style->black_gc, ldot - MARGIN - gdk_string_width(font, src), y + fontx, src); color.red = dobj->color.red; color.green = dobj->color.green; color.blue = dobj->color.blue; gdk_colormap_alloc_color(cmap, &color, TRUE, TRUE); gdk_gc_set_foreground(gc, &color); gdk_draw_arc(pixmap, gc, TRUE, ldot - (RADIUS / 2), y - (RADIUS / 2), RADIUS, RADIUS, 0, 360 * 64); node = node->next; y += VSPACE; } y = VSPACE; node = display->dst_list->head; while (node != NULL) { if ((dobj = node->obj) == NULL) { break; } set_root(&dst_tree, dobj->dst, y); strncpy(dst, dobj->dst_name, MAX_HOSTNAME_LEN); gdk_draw_string(pixmap, font, widget->style->black_gc, rdot + MARGIN + 1, y + fontx, dst); color.red = dobj->color.red; color.green = dobj->color.green; color.blue = dobj->color.blue; gdk_colormap_alloc_color(cmap, &color, TRUE, TRUE); gdk_gc_set_foreground(gc, &color); gdk_draw_arc(pixmap, gc, TRUE, rdot - (RADIUS / 2), y - (RADIUS / 2), RADIUS, RADIUS, 0, 360 * 64); node = node->next; y += VSPACE; } node = display->pair_list->head; while (node != NULL) { if ((dobj = node->obj) == NULL) { break; } color.red = dobj->color.red; color.green = dobj->color.green; color.blue = dobj->color.blue; gdk_colormap_alloc_color(cmap, &color, TRUE, TRUE); gdk_gc_set_foreground(gc, &color); gdk_draw_line(pixmap, gc, ldot, get_node(&src_tree, dobj->src), rdot, get_node(&dst_tree, dobj->dst)); node = node->next; } clean_tree(&src_tree); clean_tree(&dst_tree); gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], pixmap, 0, 0, 0, 0, widget->allocation.width, widget->allocation.height); return; } gint draw_timer(gpointer data) { draw(GTK_WIDGET(data)); gtk_timeout_add(3000, draw_timer, data); return FALSE; } gboolean event_configure(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { draw(widget); return FALSE; } gboolean event_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE; } void event_destroy(GtkObject *object, gpointer data) { gtk_main_quit(); return; } void on_file_exit_activate (GtkMenuItem *menuitem, gpointer user_data) { gtk_main_quit(); } void on_f_arp_all_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = arp_m; opts->net_submenu.arp = arp_all; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf, "Displaying all ARP traffic."); set_status_bar_text(); } void on_f_ip_all_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = ip_all; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf, "Displaying all IP traffic."); set_status_bar_text(); } void on_f_ip_icmp_all_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = icmp_m; opts->net_submenu.ip_submenu.icmp = icmp_all; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf, "Displaying all ICMP traffic."); set_status_bar_text(); } void on_f_ip_igmp_all_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = igmp_m; opts->net_submenu.ip_submenu.igmp = igmp_all; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf, "Displaying all IGMP traffic."); set_status_bar_text(); } void on_f_ip_tcp_all_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = tcp_m; opts->net_submenu.ip_submenu.tcp = tcp_all; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf, "Displaying all TCP traffic."); set_status_bar_text(); } void on_f_ip_udp_all_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = udp_m; opts->net_submenu.ip_submenu.udp = udp_all; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf , "Displaying all UDP traffic."); set_status_bar_text(); } void on_f_ip_icmp_request_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = icmp_m; opts->net_submenu.ip_submenu.icmp = icmp_rqst; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf , "Displaying ICMP requests."); set_status_bar_text(); } void on_f_ip_icmp_reply_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = icmp_m; opts->net_submenu.ip_submenu.icmp = icmp_rply; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf , "Displaying ICMP replies."); set_status_bar_text(); } void on_f_ip_icmp_pair_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = icmp_m; opts->net_submenu.ip_submenu.icmp = icmp_pair; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf , "Displaying ICMP request/reply pairs."); set_status_bar_text(); } void on_f_ip_tcp_http_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = tcp_m; opts->net_submenu.ip_submenu.tcp = tcp_http; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf , "Displaying TCP traffic on port 80 (http)."); set_status_bar_text(); } void on_f_ip_tcp_ftp_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = tcp_m; opts->net_submenu.ip_submenu.tcp = tcp_ftp; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf , "Displaying TCP traffic on port 21 (ftp)."); set_status_bar_text(); } void on_f_ip_tcp_ssh_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = tcp_m; opts->net_submenu.ip_submenu.tcp = tcp_ssh; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf , "Displaying TCP traffic on port 22 (ssh)."); set_status_bar_text(); } void on_f_ip_port_activate (GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *ports_dialog = user_data; gtk_widget_show(ports_dialog); pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = ip_port; pthread_mutex_unlock(filter_mutex); } void on_f_ip_tcp_port_activate (GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *ports_dialog = user_data; gtk_widget_show(ports_dialog); pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = tcp_m; opts->net_submenu.ip_submenu.tcp = tcp_port; pthread_mutex_unlock(filter_mutex); } void on_f_ip_udp_port_activate (GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *ports_dialog = user_data; gtk_widget_show(ports_dialog); pthread_mutex_lock(filter_mutex); opts->menu = ip_m; opts->net_submenu.ip = udp_m; opts->net_submenu.ip_submenu.udp = udp_port; pthread_mutex_unlock(filter_mutex); } void on_file_options_activate (GtkMenuItem *menuitem, gpointer user_data) { struct Options_Dialog_Context *context = user_data; char buf[64]; unsigned int min; unsigned int max; int i = 0; pthread_mutex_lock(filter_mutex); min = display->min_rate; max = display->max_rate; pthread_mutex_unlock(filter_mutex); gtk_spin_button_set_value(context->buf_size, net->timeout); while (min > 0 && min % 1000 == 0 && i < 3) { min /= 1000; i++; } snprintf(buf, 64, "%u", min); gtk_entry_set_text(context->min, buf); gtk_option_menu_set_history(context->min_option, i); i = 0; while (max > 0 && max % 1000 == 0 && i < 3) { max /= 1000; i++; } snprintf(buf, 64, "%u", max); gtk_entry_set_text(context->max, buf); gtk_option_menu_set_history(context->max_option, i); gtk_widget_show(context->dialog); return; } void on_file_clear_dns_activate (GtkMenuItem *menuitem, gpointer user_data) { empty_cache_list(&dnscache); return; } void on_option_ok_clicked (GtkButton *button, gpointer user_data) { struct Options_Dialog_Context * context = user_data; unsigned long min; unsigned long max; unsigned long val; int exp; char buf[16]; val = atoi(gtk_entry_get_text(context->min)); exp = g_list_index(GTK_MENU_SHELL(context->min_menu)->children, gtk_menu_get_active(context->min_menu)); min = val * pow(1000, exp); snprintf(buf, 15, "%d %sbps", val, (exp == 1 ? "K" : (exp == 2 ? "M" : (exp == 3 ? "G" : "")))); gtk_label_set_text(context->min_label, buf); val = atoi(gtk_entry_get_text(context->max)); exp = g_list_index(GTK_MENU_SHELL(context->max_menu)->children, gtk_menu_get_active(context->max_menu)); max = val * pow(1000, exp); snprintf(buf, 15, "%d %sbps", val, (exp == 1 ? "K" : (exp == 2 ? "M" : (exp == 3 ? "G" : "")))); gtk_label_set_text(context->max_label, buf); pthread_mutex_lock(net_mutex); net->timeout = gtk_spin_button_get_value_as_int(context->buf_size); display->min_rate = (min > UINT_MAX) ? UINT_MAX : min; display->max_rate = (max > UINT_MAX) ? UINT_MAX : max; pthread_mutex_unlock(net_mutex); gtk_widget_hide(context->dialog); return; } void on_options_cancel_clicked (GtkButton *button, gpointer user_data) { GtkWidget * options_dialog = user_data; gtk_widget_hide(options_dialog); return; } void on_f_all_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_mutex_lock(filter_mutex); opts->menu = all; pthread_mutex_unlock(filter_mutex); strcpy(filter_buf, "Displaying all traffic."); set_status_bar_text(); } void on_by_address_activate (GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *ip_filter_dialog = user_data; gtk_widget_show(ip_filter_dialog); } void on_filter_ok_clicked (GtkButton *button, gpointer user_data) { struct IP_Filter_Dialog_Context * context = user_data; char * src_1; char * src_2; char * src_3; char * src_4; char * dst_1; char * dst_2; char * dst_3; char * dst_4; char * src_mask; char * dst_mask; int temp; int src_addr, dst_addr; int src_cidr, dst_cidr; // moved from ports dialog enum bool range = false; char text[256]; char num[16]; int last; int i; char * src_port_entry; char * dst_port_entry; char * c; // test buffers /* right here, grab both check boxes, and all eight text boxes */ if (gtk_toggle_button_get_active((GtkToggleButton*) context->src_chk) != false) { src_1 = gtk_entry_get_text(context->src_entry_1); src_2 = gtk_entry_get_text(context->src_entry_2); src_3 = gtk_entry_get_text(context->src_entry_3); src_4 = gtk_entry_get_text(context->src_entry_4); src_mask = gtk_entry_get_text(context->src_cidr); /* do the atoi thing before filter lock */ src_addr = 0; temp = atoi(src_1); src_addr += temp; src_addr = src_addr << 8; temp = atoi(src_2); src_addr += temp; src_addr = src_addr << 8; temp = atoi(src_3); src_addr += temp; src_addr = src_addr << 8; temp = atoi(src_4); src_addr += temp; src_cidr = atoi(src_mask); pthread_mutex_lock(filter_mutex); opts->net_submenu.filter_on_src_addr = true; opts->net_submenu.src_addr = src_addr; opts->net_submenu.src_cidr = src_cidr; snprintf(src_addr_buf,255,"\nSource address %s.%s.%s.%s/%s", src_1, src_2, src_3, src_4, src_mask); pthread_mutex_unlock(filter_mutex); } else { pthread_mutex_lock(filter_mutex); opts->net_submenu.filter_on_src_addr = false; pthread_mutex_unlock(filter_mutex); } if (gtk_toggle_button_get_active((GtkToggleButton*) context->dst_chk) != false) { dst_1 = gtk_entry_get_text(context->dst_entry_1); dst_2 = gtk_entry_get_text(context->dst_entry_2); dst_3 = gtk_entry_get_text(context->dst_entry_3); dst_4 = gtk_entry_get_text(context->dst_entry_4); dst_mask = gtk_entry_get_text(context->dst_cidr); temp = atoi(dst_1); dst_addr += temp; dst_addr = dst_addr << 8; temp = atoi(dst_2); dst_addr += temp; dst_addr = dst_addr << 8; temp = atoi(dst_3); dst_addr += temp; dst_addr = dst_addr << 8; temp = atoi(dst_4); dst_addr += temp; dst_cidr = atoi(dst_mask); pthread_mutex_lock(filter_mutex); opts->net_submenu.filter_on_dst_addr = true; opts->net_submenu.dst_addr = dst_addr; opts->net_submenu.dst_cidr = dst_cidr; snprintf(dst_addr_buf,255,"\nDestination address %s.%s.%s.%s/%s", dst_1, dst_2, dst_3, dst_4, dst_mask); pthread_mutex_unlock(filter_mutex); } else { pthread_mutex_lock(filter_mutex); opts->net_submenu.filter_on_dst_addr = false; pthread_mutex_unlock(filter_mutex); } /* XXX insert ports dialog changes here.... */ if (gtk_toggle_button_get_active((GtkToggleButton*) context->src_port_chk) != false) { src_port_entry = gtk_entry_get_text(context->src_port_entry); pthread_mutex_lock(filter_mutex); opts->net_submenu.filter_on_src_ports = true; for (i = 1; i <= NUM_OF_PORTS; ++i) { opts->net_submenu.src_ports[i] = false; } c = src_port_entry; while (*c != '\0') { if (IS_DIGIT(*c)) { i = 0; do { num[i++] = *(c++); } while (IS_DIGIT(*c) && i < (sizeof(num) / sizeof(num[0]) - 1)); num[i] = '\0'; if (range) { for (i = last + 1; i <= atoi(num) && i <= NUM_OF_PORTS; ++i) { opts->net_submenu.src_ports[i] = true; } range = false; } else { last = atoi(num); if (last <= NUM_OF_PORTS) { opts->net_submenu.src_ports[last] = true; } } } if (*c == '-') { range = true; } ++c; } pthread_mutex_unlock(filter_mutex); } else opts->net_submenu.filter_on_src_ports = false; if (gtk_toggle_button_get_active((GtkToggleButton*) context->dst_port_chk) != false) { dst_port_entry = gtk_entry_get_text(context->dst_port_entry); pthread_mutex_lock(filter_mutex); opts->net_submenu.filter_on_dst_ports = true; for (i = 1; i <= NUM_OF_PORTS; ++i) { opts->net_submenu.dst_ports[i] = false; } c = dst_port_entry; while (*c != '\0') { if (IS_DIGIT(*c)) { i = 0; do { num[i++] = *(c++); } while (IS_DIGIT(*c) && i < (sizeof(num) / sizeof(num[0]) - 1)); num[i] = '\0'; if (range) { for (i = last + 1; i <= atoi(num) && i <= NUM_OF_PORTS; ++i) { opts->net_submenu.dst_ports[i] = true; } range = false; } else { last = atoi(num); if (last <= NUM_OF_PORTS) { opts->net_submenu.dst_ports[last] = true; } } } if (*c == '-') { range = true; } ++c; } pthread_mutex_unlock(filter_mutex); } else opts->net_submenu.filter_on_dst_ports = false; strncpy(dst_ports_buf, dst_port_entry, 255); pthread_mutex_lock(filter_mutex); snprintf(src_ports_buf, 255, "\nShowing source ports %s", src_port_entry); snprintf(dst_ports_buf, 255, "\nShowing destination ports %s", dst_port_entry); pthread_mutex_unlock(filter_mutex); gtk_widget_hide(context->dialog); set_status_bar_text(); } void on_filter_cancel_clicked (GtkButton *button, gpointer user_data) { GtkWidget * ip_filter_dialog = user_data; gtk_widget_hide(ip_filter_dialog); } void set_status_bar_text() { strncpy(status_text, filter_buf, 255); pthread_mutex_lock(filter_mutex); if (opts->net_submenu.filter_on_src_addr == true) { strncat(status_text, src_addr_buf, 255); } if (opts->net_submenu.filter_on_dst_addr == true) { strncat(status_text, dst_addr_buf, 255); } if (opts->net_submenu.filter_on_src_ports == true) { strncat(status_text, src_ports_buf, 255); } if (opts->net_submenu.filter_on_dst_ports == true) { strncat(status_text, dst_ports_buf, 255); } pthread_mutex_unlock(filter_mutex); gtk_label_set_text(statusbar, status_text); }