From 63d51b566ea270b45b5b34b1feab37b8faa28232 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 9 May 2004 23:20:43 +0000 Subject: main fieryfilter work git-svn-id: file:///home/lennart/svn/public/fieryfilter/fieryfilter@31 79e6afc9-17da-0310-ae3c-b873bff394f4 --- client/connection.c | 292 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 client/connection.c (limited to 'client/connection.c') diff --git a/client/connection.c b/client/connection.c new file mode 100644 index 0000000..fb04e41 --- /dev/null +++ b/client/connection.c @@ -0,0 +1,292 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "connection.h" +#include "interface.h" +#include "support.h" +#include "daemon.h" +#include "mainwin.h" +#include "log.h" +#include "rulewin.h" +#include "ruleset.h" + +#include "format.h" + +GSList *queued_conn_list = NULL; +guint queued_conn_count = 0; + +conn_info_t *conn_current = NULL; + +guint total_conn_count = 0; + +static GtkWidget* get_window(void) { + static GtkWidget *cw = NULL; + + if (!cw) { + GdkColor color; + cw = create_connection_window(); + gdk_color_parse ("black", &color); + gtk_widget_modify_bg(lookup_widget(cw, "title_eventbox"), GTK_STATE_NORMAL, &color); + } + + return cw; +} + +void conn_fill_info(conn_info_t *c) { + struct protoent *pe = NULL; + struct servent *se = NULL; + static gchar txt[256]; + char *t; + + c->from_string = g_strdup(format_hostname(c->src_ip_address)); + c->to_string = g_strdup(format_hostname(c->dst_ip_address)); + + c->port_string = NULL; + + if (c->protocol == IPPROTO_ICMP) + snprintf(t = txt, sizeof(txt), "ICMP %s", icmp_type_str(c->icmp_type)); + else if (c->protocol == IPPROTO_TCP || c->protocol == IPPROTO_UDP) { + gchar *pp = c->protocol == IPPROTO_TCP ? "TCP" : "UDP"; + + if ((se = getservbyport(htons(c->port), NULL))) + snprintf(t = txt, sizeof(txt), "%s Port#%u (%s)", pp, c->port, c->port_string = g_strdup(se->s_name)); + else + snprintf(t = txt, sizeof(txt), "%s Port#%u", pp, c->port); + } else if ((pe = getprotobynumber(c->protocol))) + t = pe->p_name; + else + t = "Unknown"; + + c->type_string = g_strdup(t); + + strncpy(txt, ctime(&c->timestamp), sizeof(txt)); + if (txt[0]) // remove trailing \n + txt[strlen(txt)-1] = 0; + c->timestamp_string = g_strdup(txt); +} + +void conn_free(conn_info_t*c) { + g_free(c->from_string); + g_free(c->to_string); + g_free(c->type_string); + g_free(c->port_string); + g_free(c->timestamp_string); + g_free(c); +} + +void conn_set_sticky() { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(get_main_window(), "sticky_button")))) + gtk_window_stick(GTK_WINDOW(get_window())); + else + gtk_window_unstick(GTK_WINDOW(get_window())); +} + +void conn_show_info(conn_info_t *c) { + GtkWidget* window; + GtkTooltips *tooltips; + static gchar txt[256]; + static gchar fn[PATH_MAX]; + char *d; + GdkPixbuf *pixbuf; + + window = get_window(); + + snprintf(txt, sizeof(txt), "%s Connection", c->direction == DIR_INCOMING ? "Incoming" : (c->direction == DIR_OUTGOING ? "Outgoing" : "Passing")); + gtk_label_set_label(GTK_LABEL(lookup_widget(window, "title_label")), txt); + + gtk_image_set_from_stock(GTK_IMAGE(lookup_widget(window, "title_image")), c->direction == DIR_INCOMING ? GTK_STOCK_GO_FORWARD : (c->direction == DIR_OUTGOING ? GTK_STOCK_GO_BACK : GTK_STOCK_NEW), GTK_ICON_SIZE_DND); + + if (c->direction == DIR_INCOMING) + d = c->device_in; + else if (c->direction == DIR_OUTGOING) + d = c->device_out; + else + snprintf(d = txt, sizeof(txt), "%s => %s", c->device_in, c->device_out); + + gtk_label_set_label(GTK_LABEL(lookup_widget(window, "interface_label")), d); + gtk_label_set_label(GTK_LABEL(lookup_widget(window, "from_label")), c->from_string); + gtk_label_set_label(GTK_LABEL(lookup_widget(window, "to_label")), c->to_string); + gtk_label_set_label(GTK_LABEL(lookup_widget(window, "type_label")), c->type_string); + + tooltips = GTK_TOOLTIPS(lookup_widget(window, "tooltips")); + gtk_tooltips_set_tip(tooltips, lookup_widget(window, "from_eventbox"), format_ip_address(c->src_ip_address), NULL); + gtk_tooltips_set_tip(tooltips, lookup_widget(window, "to_eventbox"), format_ip_address(c->dst_ip_address), NULL); + gtk_tooltips_set_delay(tooltips, 0); + + snprintf(txt, sizeof(txt), "%lu", c->id); + gtk_label_set_label(GTK_LABEL(lookup_widget(window, "id_label")), txt); + + gtk_label_set_label(GTK_LABEL(lookup_widget(window, "time_label")), c->timestamp_string); + + gtk_widget_set_sensitive(lookup_widget(window, "reject_button"), !c->broadcast); + + gtk_label_set_label(GTK_LABEL(lookup_widget(window, "broadcast_label")), c->broadcast ? "Yes" : "No"); + + gtk_image_set_from_stock(GTK_IMAGE(lookup_widget(window, "type_image")), GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_DND); + if (c->port_string) { + snprintf(fn, sizeof(fn), "%s/pixmaps/%s.png", "..", c->port_string); + + if ((pixbuf = gdk_pixbuf_new_from_file(fn, NULL))) { + gtk_image_set_from_pixbuf(GTK_IMAGE(lookup_widget(window, "type_image")), pixbuf); + g_object_unref(pixbuf); + } + } + + gtk_widget_show_all(window); + conn_set_sticky(); + + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_window_present(GTK_WINDOW(window)); +} + + +void conn_show_count() { + static gchar txt[256]; + gchar *p; + + if (queued_conn_count) + snprintf(p = txt, sizeof(txt), "Connection (%i in queue)", queued_conn_count); + else + p = "Connection"; + + gtk_window_set_title(GTK_WINDOW(get_window()), p); +} + +void conn_pop() { + g_assert(!conn_current && queued_conn_list); + + conn_current = (conn_info_t*) queued_conn_list->data; + queued_conn_list = g_slist_remove(queued_conn_list, conn_current); + queued_conn_count--; + conn_show_count(); + conn_show_info(conn_current); +} + +static conn_info_t* ipq2ci(ipq_packet_msg_t* m) { + conn_info_t* ci = g_new0(conn_info_t, 1); + struct iphdr *ip = (struct iphdr*) m->payload; + + ci->id = m->packet_id; + ci->direction = (m->indev_name[0] && m->outdev_name[0]) ? DIR_PASSING : (m->indev_name[0] ? DIR_INCOMING : DIR_OUTGOING); + strncpy(ci->device_in, m->indev_name, IFNAMSIZ); ci->device_in[IFNAMSIZ] = 0; + strncpy(ci->device_out, m->outdev_name, IFNAMSIZ); ci->device_out[IFNAMSIZ] = 0; + + if (m->data_len < sizeof(struct iphdr)) { + g_message("Packet too small for complete IP header"); + g_free(ci); + return NULL; + } + + ci->src_ip_address = ip->saddr; + ci->dst_ip_address = ip->daddr; + ci->protocol = ip->protocol; + + ci->broadcast = is_broadcast(ci->dst_ip_address); + + ci->port = 0; + ci->icmp_type = 0; + + if (ci->protocol == IPPROTO_TCP || ci->protocol == IPPROTO_UDP) + ci->port = ntohs(*((guint16*) (m->payload + sizeof(struct iphdr) + 2))); + else if (ci->protocol == IPPROTO_ICMP) + ci->icmp_type = *((guint8*) (m->payload + sizeof(struct iphdr))); + + ci->timestamp = m->timestamp_sec; + + return ci; +} + +guint verdict2nr(verdict_t v) { + switch (v) { + case VERDICT_REJECT : return ruleset.icmp_reject_code+2; + case VERDICT_QUERY : + case VERDICT_DROP : return 0; + case VERDICT_ACCEPT : return 1; + } + + return 0; +} + +void conn_new(ipq_packet_msg_t *m) { + conn_info_t *ci; + + if ((ci = ipq2ci(m))) { + queued_conn_list = g_slist_append(queued_conn_list, ci); + queued_conn_count++; + total_conn_count++; + conn_fill_info(ci); + log_widget_append(ci); + + conn_show_count(); + + if (!conn_current) + conn_pop(); + + mainwin_update_status_bar(); + } +} + +void conn_verdict(verdict_t v) { + if (!conn_current) + return; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(get_window(), "queue_check_button")))) { + for (;;) { + verdict_t _v; + + if (v == VERDICT_REJECT && conn_current->broadcast) + _v = VERDICT_DROP; + else + _v = v; + + daemon_verdict(conn_current->id, verdict2nr(_v)); + log_widget_verdict(conn_current, _v); + conn_free(conn_current); + + if (!queued_conn_list) + break; + + conn_current = (conn_info_t*) queued_conn_list->data; + queued_conn_list = g_slist_remove(queued_conn_list, conn_current); + queued_conn_count--; + } + + + conn_current = NULL; + g_assert(queued_conn_count == 0); + + gtk_widget_hide(get_window()); + + } else { + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(get_window(), "rule_check_button")))) { + rule_t *rule; + + rule = rule_new_from_conn_info(conn_current); + rule->verdict = v; + rulewin_show(rule); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(get_window(), "rule_check_button")), FALSE); + } + + daemon_verdict(conn_current->id, verdict2nr(v)); + log_widget_verdict(conn_current, v); + conn_free(conn_current); + conn_current = NULL; + + if (!queued_conn_list) + gtk_widget_hide(get_window()); + else + conn_pop(); + } + + mainwin_update_status_bar(); +} -- cgit