/*
* 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 <config.h>
#endif
#include <gtk/gtk.h>
#include <limits.h> /* UINT_MAX */
#include <math.h> /* pow */
#include <stdio.h>
#include <string.h> /* 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);
}
syntax highlighted by Code2HTML, v. 0.9.1