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 --- AUTHORS | 1 + client/Makefile.am | 26 + client/advancedwin.c | 59 + client/advancedwin.h | 10 + client/callbacks.c | 298 ++++ client/callbacks.h | 197 +++ client/connection.c | 292 ++++ client/connection.h | 41 + client/daemon.c | 198 +++ client/daemon.h | 13 + client/format.c | 216 +++ client/format.h | 34 + client/interface.c | 2173 +++++++++++++++++++++++++ client/interface.h | 9 + client/log.c | 71 + client/log.h | 12 + client/main.c | 55 + client/main.h | 7 + client/mainwin.c | 52 + client/mainwin.h | 12 + client/rule.c | 318 ++++ client/rule.h | 52 + client/ruleset.c | 534 ++++++ client/ruleset.h | 49 + client/rulewin.c | 249 +++ client/rulewin.h | 14 + client/support.c | 144 ++ client/support.h | 67 + client/test.fwx | 141 ++ configure.ac | 41 + daemon/Makefile.am | 34 + daemon/client.c | 292 ++++ daemon/client.h | 13 + daemon/common.h | 23 + daemon/icmp.c | 87 + daemon/icmp.h | 11 + daemon/ipqapi.c | 118 ++ daemon/ipqapi.h | 13 + daemon/main.c | 198 +++ daemon/main.h | 14 + daemon/packet.c | 101 ++ daemon/packet.h | 15 + fieryfilter.glade | 3962 +++++++++++++++++++++++++++++++++++++++++++++ fieryfilter.gladep | 9 + fieryfilter.init | 100 ++ fieryfilter.sh | 8 + helper/Makefile.am | 22 + helper/default.fwx | 42 + helper/install-firewall.c | 71 + helper/xml-iptables | 331 ++++ helper/xml-iptables-safe | 29 + 51 files changed, 10878 insertions(+) create mode 100644 AUTHORS create mode 100644 client/Makefile.am create mode 100644 client/advancedwin.c create mode 100644 client/advancedwin.h create mode 100644 client/callbacks.c create mode 100644 client/callbacks.h create mode 100644 client/connection.c create mode 100644 client/connection.h create mode 100644 client/daemon.c create mode 100644 client/daemon.h create mode 100644 client/format.c create mode 100644 client/format.h create mode 100644 client/interface.c create mode 100644 client/interface.h create mode 100644 client/log.c create mode 100644 client/log.h create mode 100644 client/main.c create mode 100644 client/main.h create mode 100644 client/mainwin.c create mode 100644 client/mainwin.h create mode 100644 client/rule.c create mode 100644 client/rule.h create mode 100644 client/ruleset.c create mode 100644 client/ruleset.h create mode 100644 client/rulewin.c create mode 100644 client/rulewin.h create mode 100644 client/support.c create mode 100644 client/support.h create mode 100644 client/test.fwx create mode 100644 configure.ac create mode 100644 daemon/Makefile.am create mode 100644 daemon/client.c create mode 100644 daemon/client.h create mode 100644 daemon/common.h create mode 100644 daemon/icmp.c create mode 100644 daemon/icmp.h create mode 100644 daemon/ipqapi.c create mode 100644 daemon/ipqapi.h create mode 100644 daemon/main.c create mode 100644 daemon/main.h create mode 100644 daemon/packet.c create mode 100644 daemon/packet.h create mode 100644 fieryfilter.glade create mode 100644 fieryfilter.gladep create mode 100755 fieryfilter.init create mode 100755 fieryfilter.sh create mode 100644 helper/Makefile.am create mode 100644 helper/default.fwx create mode 100644 helper/install-firewall.c create mode 100755 helper/xml-iptables create mode 100755 helper/xml-iptables-safe diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..79967c5 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Lennart Poettering diff --git a/client/Makefile.am b/client/Makefile.am new file mode 100644 index 0000000..8b6f709 --- /dev/null +++ b/client/Makefile.am @@ -0,0 +1,26 @@ +## Process this file with automake to produce Makefile.in + +INCLUDES = \ + -I/usr/include/libipq -Wall \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + @PACKAGE_CFLAGS@ + +bin_PROGRAMS = fieryfilter + +fieryfilter_SOURCES = \ + ruleset.c ruleset.h \ + main.c main.h \ + support.c support.h \ + interface.c interface.h \ + callbacks.c callbacks.h \ + connection.c connection.h \ + daemon.c daemon.h \ + mainwin.c mainwin.h \ + rulewin.c rulewin.h \ + log.c log.h \ + format.c format.h \ + rule.c rule.h \ + advancedwin.c advancedwin.h + +fieryfilter_LDADD = @PACKAGE_LIBS@ $(INTLLIBS) -lmcheck diff --git a/client/advancedwin.c b/client/advancedwin.c new file mode 100644 index 0000000..4cbac57 --- /dev/null +++ b/client/advancedwin.c @@ -0,0 +1,59 @@ +#include + +#include "advancedwin.h" +#include "interface.h" +#include "format.h" +#include "support.h" +#include "connection.h" +#include "ruleset.h" + +static gboolean ignore_apply = TRUE; + +static GtkWidget* get_window(void) { + static GtkWidget *aw = NULL; + + if (!aw) { + aw = create_advanced_window(); + fill_icmp_menu(GTK_OPTION_MENU(lookup_widget(aw, "icmp_option_menu")), TRUE, 0); + } + return aw; +} + + +void advancedwin_show(gboolean b) { + if (b) { + advancedwin_fill(); + gtk_widget_show_all(get_window()); + ignore_apply = FALSE; + } else { + ignore_apply = TRUE; + gtk_widget_hide(get_window()); + } +} + +void advancedwin_fill() { + GtkWidget *aw = get_window(); + + set_icmp_menu_entry(GTK_OPTION_MENU(lookup_widget(aw, "icmp_option_menu")), TRUE, ruleset.icmp_reject_code); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(aw, "tcp_rst_check_button")), ruleset.use_tcp_rst); +} + +void advancedwin_apply() { + GtkWidget *w, *aw; + GtkOptionMenu *om; + + if (ignore_apply) + return; + + aw = get_window(); + om = GTK_OPTION_MENU(lookup_widget(aw, "icmp_option_menu")); + + w = GTK_WIDGET(g_list_nth_data(gtk_container_get_children(GTK_CONTAINER(gtk_option_menu_get_menu(om))), + gtk_option_menu_get_history(om))); + ruleset.icmp_reject_code = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(w), "icmp_value")); + + ruleset.use_tcp_rst = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(aw, "tcp_rst_check_button"))); + + ruleset.modified = TRUE; + ruleset_update_ui(); +} diff --git a/client/advancedwin.h b/client/advancedwin.h new file mode 100644 index 0000000..c0c5f74 --- /dev/null +++ b/client/advancedwin.h @@ -0,0 +1,10 @@ +#ifndef fooadvancedwinhfoo +#define fooadvancedwinhfoo + +#include + +void advancedwin_show(gboolean b); +void advancedwin_fill(); +void advancedwin_apply(); + +#endif diff --git a/client/callbacks.c b/client/callbacks.c new file mode 100644 index 0000000..ac0cb4b --- /dev/null +++ b/client/callbacks.c @@ -0,0 +1,298 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#include "connection.h" +#include "mainwin.h" +#include "rulewin.h" +#include "log.h" +#include "rulewin.h" +#include "advancedwin.h" + +gboolean on_connection_window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) { + conn_verdict(VERDICT_DROP); + return TRUE; +} + + +void on_drop_button_clicked(GtkButton *button, gpointer user_data) { + conn_verdict(VERDICT_DROP); +} + + +void on_reject_button_clicked(GtkButton *button, gpointer user_data) { + conn_verdict(VERDICT_REJECT); +} + + +void on_accept_button_clicked(GtkButton *button, gpointer user_data) { + conn_verdict(VERDICT_ACCEPT); +} + +void on_quit_activate(GtkMenuItem *menuitem, gpointer user_data) { + gtk_main_quit(); +} + +void on_clear_log_activate(GtkMenuItem *menuitem, gpointer user_data) { + log_widget_clear(); +} + +void on_sticky_button_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + conn_set_sticky(); +} + +gboolean on_main_window_delete_event (GtkWidget *widget, GdkEvent *event, gpointer user_data) { + gtk_main_quit(); + return FALSE; +} + +void on_icmp_option_menu_changed(GtkOptionMenu *optionmenu, gpointer user_data) { + advancedwin_apply(); +} + +void on_direction_optionmenu_changed(GtkOptionMenu *optionmenu, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(optionmenu)); +} + +void on_match_direction_checkbutton_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(togglebutton)); +} + + +void on_match_interfaces_checkbutton_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(togglebutton)); +} + + +void on_protocol_optionmenu_changed(GtkOptionMenu *optionmenu, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(optionmenu)); +} + + +void on_port_spinbutton_value_changed(GtkSpinButton *spinbutton, gpointer user_data) { + GtkWidget *w = GTK_WIDGET(spinbutton); + struct servent *se; + guint16 port; + gchar *p; + static gchar txt[256]; + + port = (guint16) gtk_spin_button_get_value(GTK_SPIN_BUTTON(lookup_widget(w, "port_spinbutton"))); + + if ((se = getservbyport(htons(port), NULL))) + snprintf(p = txt, sizeof(txt), "%s", se->s_name); + else + p = "Unknown"; + + gtk_label_set_label(GTK_LABEL(lookup_widget(w, "type_label")), p); +} + + +void on_match_type_checkbutton_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(togglebutton)); +} + + +void on_src_netmask_checkbutton_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(togglebutton)); +} + +void on_dst_netmask_checkbutton_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(togglebutton)); +} + + +void on_src_netmask_spinbutton_value_changed(GtkSpinButton *spinbutton, gpointer user_data) { + rulewin_update_host_ranges(GTK_WIDGET(spinbutton)); +} + + +void on_src_ip_entry_changed(GtkEditable *editable, gpointer user_data) { + rulewin_update_host_ranges(GTK_WIDGET(editable)); +} + + +void on_match_source_checkbutton_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(togglebutton)); +} + + +void on_ok_button_clicked(GtkButton *button, gpointer user_data) { + GtkWidget *rw = GTK_WIDGET(button); + rulewin_ok(rw); + gtk_widget_destroy(rw); +} + + +void on_cancel_button_clicked(GtkButton *button, gpointer user_data) { + rulewin_cancel(GTK_WIDGET(button)); +} + + +void on_add_button_clicked(GtkButton *button, gpointer user_data) { + rulewin_show(NULL); +} + + +void on_desc_entry_changed(GtkEditable *editable, gpointer user_data) { + GtkWidget *rw = GTK_WIDGET(editable); + static gchar desc[256]; + const gchar *p; + // Yes, the user may insert <> charachters here, but is this tragic? + + p = gtk_entry_get_text(GTK_ENTRY(lookup_widget(rw, "desc_entry"))); + + if (!*p) + p = "New rule"; + + snprintf(desc, sizeof(desc), "%s", p); + gtk_label_set_label(GTK_LABEL(lookup_widget(rw, "desc_label")), desc); + rulewin_set_sensitive(GTK_WIDGET(editable)); +} + + +void on_bc_radiobutton_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(togglebutton)); +} + + + +void on_dst_netmask_spinbutton_value_changed(GtkSpinButton *spinbutton, gpointer user_data) { + rulewin_update_host_ranges(GTK_WIDGET(spinbutton)); +} + + +void on_dst_ip_entry_changed(GtkEditable *editable, gpointer user_data) { + rulewin_update_host_ranges(GTK_WIDGET(editable)); +} + + +void on_match_destination_checkbutton_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + rulewin_set_sensitive(GTK_WIDGET(togglebutton)); +} + + + +void on_properties_button_clicked(GtkButton *button, gpointer user_data) { + rule_t* rule; + + if ((rule = ruleset_get_current_rule())) + rulewin_show(rule); +} + + +void on_up_button_clicked(GtkButton *button, gpointer user_data) { + rule_t* rule; + + if ((rule = ruleset_get_current_rule())) + ruleset_move_rule(rule, -1); +} + + +void on_down_button_clicked(GtkButton *button, gpointer user_data) { + rule_t* rule; + + if ((rule = ruleset_get_current_rule())) + ruleset_move_rule(rule, +1); +} + + +void on_remove_button_clicked(GtkButton *button, gpointer user_data) { + rule_t* rule; + + if ((rule = ruleset_get_current_rule())) + ruleset_remove_rule(rule); +} + + +void on_clear_button_clicked(GtkButton *button, gpointer user_data) { + ruleset_clear(); +} + + +void on_ruleset_view_cursor_changed(GtkTreeView *treeview, gpointer user_data) { + ruleset_update_ui(); +} + + +gboolean on_rule_window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) { + rulewin_cancel(GTK_WIDGET(widget)); + return TRUE; +} + + +void on_commit_button_clicked(GtkButton *button, gpointer user_data) { + ruleset_commit(); +} + + +void +on_save_ruleset_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_open_ruleset_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void on_advanced_button_clicked(GtkButton *button, gpointer user_data){ + advancedwin_show(TRUE); +} + + +gboolean on_advanced_window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) { + advancedwin_show(FALSE); + return TRUE; +} + + +void on_tcp_rst_check_button_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + advancedwin_apply(); +} + + +void on_close_button_clicked(GtkButton *button, gpointer user_data) { + advancedwin_show(FALSE); +} + + +void on_ruleset_check_button_toggled(GtkToggleButton *togglebutton, gpointer user_data) { + ruleset.ignore_rules = !gtk_toggle_button_get_active(togglebutton); + ruleset.modified = TRUE; + ruleset_update_ui(); +} + + +void on_unmatch_optionmenu_changed(GtkOptionMenu *optionmenu, gpointer user_data) { + ruleset.unmatch_verdict = gtk_option_menu_get_history(optionmenu); + ruleset.modified = TRUE; + ruleset_update_ui(); +} + +void on_new_ruleset_activate(GtkMenuItem *menuitem, gpointer user_data) { + ruleset_new(NULL); +} + +void on_about_activate(GtkMenuItem *menuitem, gpointer user_data) { + +} + +void on_log_spinbutton_value_changed(GtkSpinButton *spinbutton, gpointer user_data) { + log_widget_cut(); +} + diff --git a/client/callbacks.h b/client/callbacks.h new file mode 100644 index 0000000..21b8f02 --- /dev/null +++ b/client/callbacks.h @@ -0,0 +1,197 @@ +#include + + +gboolean +on_connection_window_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void +on_drop_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_reject_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_accept_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_quit_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_clear_log_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_about_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_sticky_button_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +gboolean +on_main_window_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void +on_icmp_option_menu_changed (GtkOptionMenu *optionmenu, + gpointer user_data); + +void +on_direction_optionmenu_changed (GtkOptionMenu *optionmenu, + gpointer user_data); + +void +on_match_direction_checkbutton_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_match_interfaces_checkbutton_toggled + (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_protocol_optionmenu_changed (GtkOptionMenu *optionmenu, + gpointer user_data); + +void +on_port_spinbutton_value_changed (GtkSpinButton *spinbutton, + gpointer user_data); + +void +on_match_type_checkbutton_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_src_netmask_checkbutton_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_src_netmask_spinbutton_value_changed + (GtkSpinButton *spinbutton, + gpointer user_data); + +void +on_src_ip_entry_changed (GtkEditable *editable, + gpointer user_data); + +void +on_match_source_checkbutton_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_cancel_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_ok_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_add_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_desc_entry_changed (GtkEditable *editable, + gpointer user_data); + +void +on_bc_radiobutton_toggled (GtkToggleButton *togglebutton, + gpointer user_data); +void +on_dst_netmask_spinbutton_value_changed + (GtkSpinButton *spinbutton, + gpointer user_data); + +void +on_dst_ip_entry_changed (GtkEditable *editable, + gpointer user_data); + +void +on_match_destination_checkbutton_toggled + (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_dst_netmask_checkbutton_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_properties_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_up_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_down_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_remove_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_clear_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_ruleset_view_cursor_changed (GtkTreeView *treeview, + gpointer user_data); + +gboolean +on_rule_window_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void +on_commit_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_save_ruleset_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_open_ruleset_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_advanced_button_clicked (GtkButton *button, + gpointer user_data); + +gboolean +on_advanced_window_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void +on_tcp_rst_check_button_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_close_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_ruleset_check_button_toggled (GtkToggleButton *togglebutton, + gpointer user_data); + +void +on_unmatch_optionmenu_changed (GtkOptionMenu *optionmenu, + gpointer user_data); + +void +on_new_ruleset_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_log_spinbutton_value_changed (GtkSpinButton *spinbutton, + gpointer user_data); 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(); +} diff --git a/client/connection.h b/client/connection.h new file mode 100644 index 0000000..fe4fdf5 --- /dev/null +++ b/client/connection.h @@ -0,0 +1,41 @@ +#ifndef fooconnectionhfoo +#define fooconnectionhfoo + +#include +#include +#include +#include + +#include "../daemon/common.h" +#include "main.h" + +typedef struct conn_info { + unsigned long id; + conn_direction_t direction; + gchar device_in[IFNAMSIZ+1]; + gchar device_out[IFNAMSIZ+1]; + guint32 src_ip_address, dst_ip_address; + guint protocol; + guint16 port; + guint8 icmp_type; + long timestamp; + gboolean broadcast; + + gchar* from_string; + gchar* to_string; + gchar* type_string; + gchar* timestamp_string; + gchar* port_string; + + GtkTreeIter iter; +} conn_info_t; + +void conn_new(ipq_packet_msg_t *ci); +void conn_verdict(verdict_t v); +void conn_set_sticky(); + +extern guint total_conn_count; +extern guint queued_conn_count; +extern conn_info_t *conn_current; + +#endif diff --git a/client/daemon.c b/client/daemon.c new file mode 100644 index 0000000..fd69ef5 --- /dev/null +++ b/client/daemon.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include + +#include "daemon.h" +#include "../daemon/common.h" +#include "connection.h" + +int sock = -1; +GIOChannel *channel = NULL; +GSList *send_message_queue = NULL; + +static void dispatch(message_t *m) { + switch (m->code) { + case MSG_PACKET : + conn_new((ipq_packet_msg_t*) (m+1)); + break; + default: + break; + } + g_free(m); +} + +static gboolean recv_work() { + static guint8 temp[sizeof(message_t)]; + static message_t *m = NULL; + static guint index = 0; + + guint8 *p; + size_t l; + ssize_t r; + + if (index < sizeof(message_t)) { + p = temp + index; + l = sizeof(message_t); + } else { + p = ((guint8*) m) + index; + l = m->length+sizeof(message_t); + } + + if ((r = read(sock, p, l-index)) < 0) { + g_message("read() failed, exiting."); + gtk_main_quit(); + return FALSE; + } + + index += r; + + if (index == sizeof(message_t)) { + m = g_malloc(((message_t*) temp)->length + sizeof(message_t)); + memcpy(m, temp, sizeof(message_t)); + } + + if (index >= sizeof(message_t)) + if (index == sizeof(message_t) + m->length) { + dispatch(m); + m = NULL; + index = 0; + } + + return TRUE; +} + +static gboolean send_work() { + static message_t *m = NULL; + static int index = 0; + guint l, r; + guint8* p; + + if (!m) { + if (!send_message_queue) + return FALSE; + + m = (message_t*) send_message_queue->data; + send_message_queue = g_slist_remove(send_message_queue, m); + + index = 0; + } + + p = ((guint8*) m) + index; + l = m->length + sizeof(message_t); + + if ((r = write(sock, p, l - index)) < 0) { + g_message("write() failed, exiting"); + gtk_main_quit(); + return FALSE; + } + + index += r; + + + if (index >= l) { + g_free(m); + m = NULL; + index = 0; + } + + + return m || send_message_queue; +} + + +static gboolean callback(GIOChannel *source, GIOCondition condition, gpointer data) { + + if (condition & G_IO_HUP) { + gtk_main_quit(); + return FALSE; + } + + if (condition & G_IO_IN) + return recv_work(); + + if (condition & G_IO_OUT) + return send_work(); + + g_error("Huch?"); + return FALSE; +} + +static int enqueue_message(message_t *m) { + + send_message_queue = g_slist_append(send_message_queue, m); + + if (!send_message_queue->next) + g_io_add_watch(channel, G_IO_OUT, callback, NULL); + + return 0; +} + +static message_t* new_message(message_code_t code, guint8* p, guint s) { + message_t* m; + + if (!p) + s = 0; + + m = g_malloc(sizeof(message_t) + s); + + m->code = code; + m->pid = getpid(); + m->length = s; + + if (p) + memcpy(m+1, p, s); + + return m; +} + +static int unix_socket(gchar *p) { + struct sockaddr_un addr; + int sock; + + if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + perror("socket(PF_LOCAL, SOCK_STREAM, 0)"); + return -1; + } + + addr.sun_family = AF_LOCAL; + strncpy(addr.sun_path, p, sizeof(addr.sun_path)); + addr.sun_path[sizeof(addr.sun_path)-1] = 0; + + if (connect(sock, (struct sockaddr *) &addr, SUN_LEN(&addr)) < 0) { + perror("connect()"); + return -1; + } + + return sock; +} + +int daemon_init() { + + if ((sock = unix_socket(SOCKET_PATH)) < 0) + return -1; + + channel = g_io_channel_unix_new(sock); + g_io_add_watch(channel, G_IO_IN|G_IO_HUP, callback, NULL); + + return 0; +} + + +void daemon_done() { + if (sock >= 0) + close(sock); + + if (channel) + g_io_channel_unref(channel); +} + + +void daemon_verdict(unsigned long id, guint r) { + static guint8 buf[sizeof(unsigned long) + sizeof(guint32)]; + + *((unsigned long*) &buf[0]) = id; + *((guint32*) &buf[sizeof(unsigned long)]) = r; + + enqueue_message(new_message(MSG_VERDICT, buf, sizeof(buf))); +} diff --git a/client/daemon.h b/client/daemon.h new file mode 100644 index 0000000..cf8be3e --- /dev/null +++ b/client/daemon.h @@ -0,0 +1,13 @@ +#ifndef foodaemonhfoo +#define foodaemonhfoo + +#include +#include +#include + +int daemon_init(); +void daemon_done(); + +void daemon_verdict(unsigned long id, guint r); + +#endif diff --git a/client/format.c b/client/format.c new file mode 100644 index 0000000..6cc6057 --- /dev/null +++ b/client/format.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "format.h" + +icmp_entry_t icmp_type_table[] = { + { "Echo reply (PONG)", 0 }, + { "Destination unreachable", 3 }, + { "Source quench", 4 }, + { "Redirect", 5 }, + { "Echo request (PING)", 8 }, + { "Router advertisement", 9 }, + { "Timestamp request", 13 }, + { "Information request", 15 }, + { "Address mask reqeust", 17 }, + { "Traceroute", 30 }, + { "Domain name request", 37 }, + { NULL, 0 } + +}; + +icmp_entry_t icmp_code_table[] = { + { "Packet filtered", 13 }, + { "Network unreachable", 0 }, + { "Host unreachable", 1 }, + { "Protocol unreachable", 2 }, + { "Port unreachable", 3 }, + { "Network unknown", 6 }, + { "Host unknown", 7 }, + { "Network prohibited", 9 }, + { "Host prohibited", 10 }, + { NULL, 0 } +}; + +gchar* icmp_type_str(guint8 t) { + gint i; + for (i = 0; icmp_type_table[i].name; i++) + if (icmp_type_table[i].value == t) + return icmp_type_table[i].name; + + return NULL; +} + +gchar* icmp_code_str(guint8 c) { + gint i; + for (i = 0; icmp_code_table[i].name; i++) + if (icmp_code_table[i].value == c) + return icmp_code_table[i].name; + + return NULL; +} + +void fill_icmp_menu(GtkOptionMenu *om, gboolean w, guint8 def) { + guint i, r = 0; + GtkMenu *m; + icmp_entry_t *table = w ? icmp_code_table : icmp_type_table; + + m = GTK_MENU(gtk_menu_new()); + for (i = 0; table[i].name; i++) { + GtkMenuItem *mi = GTK_MENU_ITEM(gtk_menu_item_new_with_label(table[i].name)); + g_object_set_data(G_OBJECT(mi), "icmp_value", GUINT_TO_POINTER((guint) table[i].value)); + gtk_menu_shell_append(GTK_MENU_SHELL(m), GTK_WIDGET(mi)); + + if (table[i].value == def) + r = i; + } + + gtk_option_menu_set_menu(om, GTK_WIDGET(m)); + gtk_option_menu_set_history(om, r); +} + +void set_icmp_menu_entry(GtkOptionMenu *om, gboolean w, guint8 def) { + guint r = 0, i; + icmp_entry_t *table = w ? icmp_code_table : icmp_type_table; + + for (i = 0; table[i].name; i++) + if (table[i].value == def) { + r = i; + break; + } + + gtk_option_menu_set_history(om, r); +} + + +gchar* format_ip_address(guint32 a) { + static gchar txt[256]; + + snprintf(txt, sizeof(txt), "%u.%u.%u.%u", a & 0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF, a >> 24); + return txt; +} + + +gchar* format_hostname(guint32 a) { + static gchar txt[256]; + struct hostent *he; + + if ((he = gethostbyaddr(&a, 4, AF_INET))) { + g_strlcpy(txt, he->h_name, sizeof(txt)); + return txt; + } else + return format_ip_address(a); +} + +GList *fill_interface_list() { + GList *items = NULL; + int sock, n; + struct ifreq ifr[10]; + struct ifconf ifc; + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return NULL; + + ifc.ifc_req = ifr; + ifc.ifc_len = sizeof(ifr); + + if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) + goto finish; + + for (n = 0 ; n < ifc.ifc_len/sizeof(struct ifreq); n++) + if (strcmp(ifr[n].ifr_name, "lo") != 0) + items = g_list_prepend(items, g_strdup(ifr[n].ifr_name)); + +finish: + close(sock); + return items; +} + +void free_interface_list(GList *l) { + while (l) { + gchar *s = (gchar*) l->data; + l = g_list_remove(l, s); + g_free(s); + } +} + + +gboolean is_broadcast(guint32 ip) { + int sock, n; + struct ifreq ifr[10]; + struct ifconf ifc; + gboolean b = FALSE; + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return FALSE; + + ifc.ifc_req = ifr; + ifc.ifc_len = sizeof(ifr); + + if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { + b = FALSE; + goto finish; + } + + for (n = 0 ; n < ifc.ifc_len/sizeof(struct ifreq); n++) { + if (ioctl(sock, SIOCGIFBRDADDR, &ifc.ifc_req[n]) >= 0) { + if (ip == ((struct sockaddr_in*) &ifc.ifc_req[n].ifr_broadaddr)->sin_addr.s_addr) { + b = TRUE; + break; + } + } + } + +finish: + close(sock); + return b; +} + +gchar* format_host_range(const gchar *ip, gint bits) { + struct in_addr a; + guint32 i, f, t, m; + static char txt[256]; + + if (!inet_aton(ip, &a)) + return "Invalid IP Address"; + + if (bits > 32) bits = 32; + if (bits < 0) bits = 0; + + if (bits == 32) { + snprintf(txt, sizeof(txt), "Single host %s", ip); + return txt; + } else if (bits == 0) + return "Entire Internet"; + + i = a.s_addr; + + m = 0xFFFFFFFF << (32-bits); + + f = i & htonl(m); + t = i | htonl(~m); + + g_strlcpy(txt, inet_ntoa(*((struct in_addr*) &f)), sizeof(txt)); + g_strlcat(txt, " - ", sizeof(txt)); + g_strlcat(txt, inet_ntoa(*((struct in_addr*) &t)), sizeof(txt)); + + return txt; +} + +gchar* format_verdict(verdict_t v, verdict_format_t t) { + switch (v) { + case VERDICT_QUERY: return t == FORMAT_USER ? "Query User" : "query"; + case VERDICT_ACCEPT: return t == FORMAT_USER ? "Accept" : "accept"; + case VERDICT_REJECT: return t == FORMAT_USER ? "Reject" : "reject"; + case VERDICT_DROP: return t == FORMAT_USER ? "Drop" : "drop"; + } + + return "???"; +} diff --git a/client/format.h b/client/format.h new file mode 100644 index 0000000..a4453b3 --- /dev/null +++ b/client/format.h @@ -0,0 +1,34 @@ +#ifndef fooformathfoo +#define fooformathfoo + +#include +#include + +#include "main.h" + +typedef struct icmp_entry { + gchar *name; + guint8 value; +} icmp_entry_t; + +typedef enum verdict_format { + FORMAT_USER, + FORMAT_XML +} verdict_format_t; + +extern icmp_entry_t icmp_type_table[]; +extern icmp_entry_t icmp_code_table[]; + +gchar* icmp_type_str(guint8 t); +gchar* icmp_code_str(guint8 c); +void fill_icmp_menu(GtkOptionMenu *om, gboolean w, guint8 def); +void set_icmp_menu_entry(GtkOptionMenu *om, gboolean w, guint8 def); +gchar* format_hostname(guint32 a); +gchar* format_ip_address(guint32 a); +GList *fill_interface_list(); +void free_interface_list(GList *l); +gboolean is_broadcast(guint32 ip); +gchar* format_host_range(const gchar *ip, gint bits); +gchar* format_verdict(verdict_t v, verdict_format_t t); + +#endif diff --git a/client/interface.c b/client/interface.c new file mode 100644 index 0000000..dd764e1 --- /dev/null +++ b/client/interface.c @@ -0,0 +1,2173 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +GtkWidget* +create_connection_window (void) +{ + GtkWidget *connection_window; + GtkWidget *vbox2; + GtkWidget *title_eventbox; + GtkWidget *hbox27; + GtkWidget *title_image; + GtkWidget *title_label; + GtkWidget *hseparator11; + GtkWidget *hbox1; + GtkWidget *table2; + GtkWidget *interface_label; + GtkWidget *type_label; + GtkWidget *time_label; + GtkWidget *id_label; + GtkWidget *broadcast_label; + GtkWidget *to_eventbox; + GtkWidget *to_label; + GtkWidget *from_eventbox; + GtkWidget *from_label; + GtkWidget *_label2; + GtkWidget *_label3; + GtkWidget *_label4; + GtkWidget *_label5; + GtkWidget *label15; + GtkWidget *label16; + GtkWidget *label20; + GtkWidget *type_image; + GtkWidget *hseparator12; + GtkWidget *vbox23; + GtkWidget *queue_check_button; + GtkWidget *rule_check_button; + GtkWidget *hseparator13; + GtkWidget *hbuttonbox7; + GtkWidget *accept_button; + GtkWidget *alignment11; + GtkWidget *hbox12; + GtkWidget *image14; + GtkWidget *label29; + GtkWidget *reject_button; + GtkWidget *alignment13; + GtkWidget *hbox17; + GtkWidget *image24; + GtkWidget *label35; + GtkWidget *drop_button; + GtkWidget *alignment9; + GtkWidget *hbox10; + GtkWidget *image12; + GtkWidget *label27; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + connection_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (connection_window), _("FieryFilter Connection")); + gtk_window_set_position (GTK_WINDOW (connection_window), GTK_WIN_POS_CENTER); + gtk_window_set_resizable (GTK_WINDOW (connection_window), FALSE); + + vbox2 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (connection_window), vbox2); + + title_eventbox = gtk_event_box_new (); + gtk_widget_show (title_eventbox); + gtk_box_pack_start (GTK_BOX (vbox2), title_eventbox, FALSE, FALSE, 0); + + hbox27 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox27); + gtk_container_add (GTK_CONTAINER (title_eventbox), hbox27); + gtk_container_set_border_width (GTK_CONTAINER (hbox27), 5); + + title_image = gtk_image_new_from_stock ("gtk-go-forward", GTK_ICON_SIZE_DND); + gtk_widget_show (title_image); + gtk_box_pack_start (GTK_BOX (hbox27), title_image, FALSE, FALSE, 0); + + title_label = gtk_label_new (_("Outgoing Connection")); + gtk_widget_show (title_label); + gtk_box_pack_start (GTK_BOX (hbox27), title_label, FALSE, FALSE, 0); + gtk_label_set_use_markup (GTK_LABEL (title_label), TRUE); + gtk_label_set_justify (GTK_LABEL (title_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (title_label), 0, 0.5); + + hseparator11 = gtk_hseparator_new (); + gtk_widget_show (hseparator11); + gtk_box_pack_start (GTK_BOX (vbox2), hseparator11, FALSE, TRUE, 0); + + hbox1 = gtk_hbox_new (FALSE, 10); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbox1, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox1), 10); + + table2 = gtk_table_new (7, 2, FALSE); + gtk_widget_show (table2); + gtk_box_pack_start (GTK_BOX (hbox1), table2, TRUE, TRUE, 0); + gtk_table_set_row_spacings (GTK_TABLE (table2), 3); + gtk_table_set_col_spacings (GTK_TABLE (table2), 5); + + interface_label = gtk_label_new (_("eth0")); + gtk_widget_show (interface_label); + gtk_table_attach (GTK_TABLE (table2), interface_label, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + GTK_WIDGET_SET_FLAGS (interface_label, GTK_CAN_FOCUS); + gtk_label_set_justify (GTK_LABEL (interface_label), GTK_JUSTIFY_LEFT); + gtk_label_set_selectable (GTK_LABEL (interface_label), TRUE); + gtk_misc_set_alignment (GTK_MISC (interface_label), 0, 0.5); + + type_label = gtk_label_new (_("tcp-80-http")); + gtk_widget_show (type_label); + gtk_table_attach (GTK_TABLE (table2), type_label, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + GTK_WIDGET_SET_FLAGS (type_label, GTK_CAN_FOCUS); + gtk_label_set_justify (GTK_LABEL (type_label), GTK_JUSTIFY_LEFT); + gtk_label_set_selectable (GTK_LABEL (type_label), TRUE); + gtk_misc_set_alignment (GTK_MISC (type_label), 0, 0.5); + + time_label = gtk_label_new (_("label17")); + gtk_widget_show (time_label); + gtk_table_attach (GTK_TABLE (table2), time_label, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + GTK_WIDGET_SET_FLAGS (time_label, GTK_CAN_FOCUS); + gtk_label_set_justify (GTK_LABEL (time_label), GTK_JUSTIFY_LEFT); + gtk_label_set_selectable (GTK_LABEL (time_label), TRUE); + gtk_misc_set_alignment (GTK_MISC (time_label), 0, 0.5); + + id_label = gtk_label_new (_("label18")); + gtk_widget_show (id_label); + gtk_table_attach (GTK_TABLE (table2), id_label, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + GTK_WIDGET_SET_FLAGS (id_label, GTK_CAN_FOCUS); + gtk_label_set_justify (GTK_LABEL (id_label), GTK_JUSTIFY_LEFT); + gtk_label_set_selectable (GTK_LABEL (id_label), TRUE); + gtk_misc_set_alignment (GTK_MISC (id_label), 0, 0.5); + + broadcast_label = gtk_label_new (_("Yes")); + gtk_widget_show (broadcast_label); + gtk_table_attach (GTK_TABLE (table2), broadcast_label, 1, 2, 6, 7, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + gtk_label_set_justify (GTK_LABEL (broadcast_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (broadcast_label), 0, 0.5); + + to_eventbox = gtk_event_box_new (); + gtk_widget_show (to_eventbox); + gtk_table_attach (GTK_TABLE (table2), to_eventbox, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_tooltips_set_tip (tooltips, to_eventbox, _("addr"), NULL); + + to_label = gtk_label_new (_("www.heise.de")); + gtk_widget_show (to_label); + gtk_container_add (GTK_CONTAINER (to_eventbox), to_label); + GTK_WIDGET_SET_FLAGS (to_label, GTK_CAN_FOCUS); + gtk_label_set_justify (GTK_LABEL (to_label), GTK_JUSTIFY_LEFT); + gtk_label_set_selectable (GTK_LABEL (to_label), TRUE); + gtk_misc_set_alignment (GTK_MISC (to_label), 0, 0.5); + + from_eventbox = gtk_event_box_new (); + gtk_widget_show (from_eventbox); + gtk_table_attach (GTK_TABLE (table2), from_eventbox, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_tooltips_set_tip (tooltips, from_eventbox, _("addr"), NULL); + + from_label = gtk_label_new (_("localhost")); + gtk_widget_show (from_label); + gtk_container_add (GTK_CONTAINER (from_eventbox), from_label); + GTK_WIDGET_SET_FLAGS (from_label, GTK_CAN_FOCUS); + gtk_label_set_justify (GTK_LABEL (from_label), GTK_JUSTIFY_LEFT); + gtk_label_set_selectable (GTK_LABEL (from_label), TRUE); + gtk_misc_set_alignment (GTK_MISC (from_label), 0, 0.5); + + _label2 = gtk_label_new (_("Type:")); + gtk_widget_show (_label2); + gtk_table_attach (GTK_TABLE (table2), _label2, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (_label2), TRUE); + gtk_label_set_justify (GTK_LABEL (_label2), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (_label2), 1, 0.5); + + _label3 = gtk_label_new (_("Device:")); + gtk_widget_show (_label3); + gtk_table_attach (GTK_TABLE (table2), _label3, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (_label3), TRUE); + gtk_label_set_justify (GTK_LABEL (_label3), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (_label3), 1, 0.5); + + _label4 = gtk_label_new (_("From:")); + gtk_widget_show (_label4); + gtk_table_attach (GTK_TABLE (table2), _label4, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (_label4), TRUE); + gtk_label_set_justify (GTK_LABEL (_label4), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (_label4), 1, 0.5); + + _label5 = gtk_label_new (_("To:")); + gtk_widget_show (_label5); + gtk_table_attach (GTK_TABLE (table2), _label5, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (_label5), TRUE); + gtk_label_set_justify (GTK_LABEL (_label5), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (_label5), 1, 0.5); + + label15 = gtk_label_new (_("Time:")); + gtk_widget_show (label15); + gtk_table_attach (GTK_TABLE (table2), label15, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (label15), TRUE); + gtk_label_set_justify (GTK_LABEL (label15), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label15), 1, 0.5); + + label16 = gtk_label_new (_("ID#:")); + gtk_widget_show (label16); + gtk_table_attach (GTK_TABLE (table2), label16, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (label16), TRUE); + gtk_label_set_justify (GTK_LABEL (label16), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label16), 1, 0.5); + + label20 = gtk_label_new (_("Broadcast:")); + gtk_widget_show (label20); + gtk_table_attach (GTK_TABLE (table2), label20, 0, 1, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (label20), TRUE); + gtk_label_set_justify (GTK_LABEL (label20), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label20), 1, 0.5); + + type_image = gtk_image_new_from_stock ("gtk-missing-image", GTK_ICON_SIZE_DND); + gtk_widget_show (type_image); + gtk_box_pack_end (GTK_BOX (hbox1), type_image, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (type_image), 0.5, 0); + + hseparator12 = gtk_hseparator_new (); + gtk_widget_show (hseparator12); + gtk_box_pack_start (GTK_BOX (vbox2), hseparator12, FALSE, FALSE, 0); + + vbox23 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox23); + gtk_box_pack_start (GTK_BOX (vbox2), vbox23, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox23), 5); + + queue_check_button = gtk_check_button_new_with_mnemonic (_("Apply decision to all _queued connections")); + gtk_widget_show (queue_check_button); + gtk_box_pack_start (GTK_BOX (vbox23), queue_check_button, FALSE, FALSE, 0); + + rule_check_button = gtk_check_button_new_with_mnemonic (_("_Create a rule from this decision")); + gtk_widget_show (rule_check_button); + gtk_box_pack_start (GTK_BOX (vbox23), rule_check_button, FALSE, FALSE, 0); + + hseparator13 = gtk_hseparator_new (); + gtk_widget_show (hseparator13); + gtk_box_pack_start (GTK_BOX (vbox2), hseparator13, FALSE, FALSE, 0); + + hbuttonbox7 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox7); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox7, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox7), 5); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox7), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX (hbuttonbox7), 5); + + accept_button = gtk_button_new (); + gtk_widget_show (accept_button); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), accept_button); + GTK_WIDGET_SET_FLAGS (accept_button, GTK_CAN_DEFAULT); + + alignment11 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment11); + gtk_container_add (GTK_CONTAINER (accept_button), alignment11); + + hbox12 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox12); + gtk_container_add (GTK_CONTAINER (alignment11), hbox12); + + image14 = gtk_image_new_from_stock ("gtk-yes", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image14); + gtk_box_pack_start (GTK_BOX (hbox12), image14, FALSE, FALSE, 0); + + label29 = gtk_label_new_with_mnemonic (_("_Accept")); + gtk_widget_show (label29); + gtk_box_pack_start (GTK_BOX (hbox12), label29, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label29), GTK_JUSTIFY_LEFT); + + reject_button = gtk_button_new (); + gtk_widget_show (reject_button); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), reject_button); + GTK_WIDGET_SET_FLAGS (reject_button, GTK_CAN_DEFAULT); + + alignment13 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment13); + gtk_container_add (GTK_CONTAINER (reject_button), alignment13); + + hbox17 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox17); + gtk_container_add (GTK_CONTAINER (alignment13), hbox17); + + image24 = gtk_image_new_from_stock ("gtk-dialog-error", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image24); + gtk_box_pack_start (GTK_BOX (hbox17), image24, FALSE, FALSE, 0); + + label35 = gtk_label_new_with_mnemonic (_("_Reject")); + gtk_widget_show (label35); + gtk_box_pack_start (GTK_BOX (hbox17), label35, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label35), GTK_JUSTIFY_LEFT); + + drop_button = gtk_button_new (); + gtk_widget_show (drop_button); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), drop_button); + GTK_WIDGET_SET_FLAGS (drop_button, GTK_CAN_DEFAULT); + + alignment9 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment9); + gtk_container_add (GTK_CONTAINER (drop_button), alignment9); + + hbox10 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox10); + gtk_container_add (GTK_CONTAINER (alignment9), hbox10); + + image12 = gtk_image_new_from_stock ("gtk-delete", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image12); + gtk_box_pack_start (GTK_BOX (hbox10), image12, FALSE, FALSE, 0); + + label27 = gtk_label_new_with_mnemonic (_("_Drop")); + gtk_widget_show (label27); + gtk_box_pack_start (GTK_BOX (hbox10), label27, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label27), GTK_JUSTIFY_LEFT); + + g_signal_connect ((gpointer) connection_window, "delete_event", + G_CALLBACK (on_connection_window_delete_event), + NULL); + g_signal_connect ((gpointer) accept_button, "clicked", + G_CALLBACK (on_accept_button_clicked), + NULL); + g_signal_connect ((gpointer) reject_button, "clicked", + G_CALLBACK (on_reject_button_clicked), + NULL); + g_signal_connect ((gpointer) drop_button, "clicked", + G_CALLBACK (on_drop_button_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (connection_window, connection_window, "connection_window"); + GLADE_HOOKUP_OBJECT (connection_window, vbox2, "vbox2"); + GLADE_HOOKUP_OBJECT (connection_window, title_eventbox, "title_eventbox"); + GLADE_HOOKUP_OBJECT (connection_window, hbox27, "hbox27"); + GLADE_HOOKUP_OBJECT (connection_window, title_image, "title_image"); + GLADE_HOOKUP_OBJECT (connection_window, title_label, "title_label"); + GLADE_HOOKUP_OBJECT (connection_window, hseparator11, "hseparator11"); + GLADE_HOOKUP_OBJECT (connection_window, hbox1, "hbox1"); + GLADE_HOOKUP_OBJECT (connection_window, table2, "table2"); + GLADE_HOOKUP_OBJECT (connection_window, interface_label, "interface_label"); + GLADE_HOOKUP_OBJECT (connection_window, type_label, "type_label"); + GLADE_HOOKUP_OBJECT (connection_window, time_label, "time_label"); + GLADE_HOOKUP_OBJECT (connection_window, id_label, "id_label"); + GLADE_HOOKUP_OBJECT (connection_window, broadcast_label, "broadcast_label"); + GLADE_HOOKUP_OBJECT (connection_window, to_eventbox, "to_eventbox"); + GLADE_HOOKUP_OBJECT (connection_window, to_label, "to_label"); + GLADE_HOOKUP_OBJECT (connection_window, from_eventbox, "from_eventbox"); + GLADE_HOOKUP_OBJECT (connection_window, from_label, "from_label"); + GLADE_HOOKUP_OBJECT (connection_window, _label2, "_label2"); + GLADE_HOOKUP_OBJECT (connection_window, _label3, "_label3"); + GLADE_HOOKUP_OBJECT (connection_window, _label4, "_label4"); + GLADE_HOOKUP_OBJECT (connection_window, _label5, "_label5"); + GLADE_HOOKUP_OBJECT (connection_window, label15, "label15"); + GLADE_HOOKUP_OBJECT (connection_window, label16, "label16"); + GLADE_HOOKUP_OBJECT (connection_window, label20, "label20"); + GLADE_HOOKUP_OBJECT (connection_window, type_image, "type_image"); + GLADE_HOOKUP_OBJECT (connection_window, hseparator12, "hseparator12"); + GLADE_HOOKUP_OBJECT (connection_window, vbox23, "vbox23"); + GLADE_HOOKUP_OBJECT (connection_window, queue_check_button, "queue_check_button"); + GLADE_HOOKUP_OBJECT (connection_window, rule_check_button, "rule_check_button"); + GLADE_HOOKUP_OBJECT (connection_window, hseparator13, "hseparator13"); + GLADE_HOOKUP_OBJECT (connection_window, hbuttonbox7, "hbuttonbox7"); + GLADE_HOOKUP_OBJECT (connection_window, accept_button, "accept_button"); + GLADE_HOOKUP_OBJECT (connection_window, alignment11, "alignment11"); + GLADE_HOOKUP_OBJECT (connection_window, hbox12, "hbox12"); + GLADE_HOOKUP_OBJECT (connection_window, image14, "image14"); + GLADE_HOOKUP_OBJECT (connection_window, label29, "label29"); + GLADE_HOOKUP_OBJECT (connection_window, reject_button, "reject_button"); + GLADE_HOOKUP_OBJECT (connection_window, alignment13, "alignment13"); + GLADE_HOOKUP_OBJECT (connection_window, hbox17, "hbox17"); + GLADE_HOOKUP_OBJECT (connection_window, image24, "image24"); + GLADE_HOOKUP_OBJECT (connection_window, label35, "label35"); + GLADE_HOOKUP_OBJECT (connection_window, drop_button, "drop_button"); + GLADE_HOOKUP_OBJECT (connection_window, alignment9, "alignment9"); + GLADE_HOOKUP_OBJECT (connection_window, hbox10, "hbox10"); + GLADE_HOOKUP_OBJECT (connection_window, image12, "image12"); + GLADE_HOOKUP_OBJECT (connection_window, label27, "label27"); + GLADE_HOOKUP_OBJECT_NO_REF (connection_window, tooltips, "tooltips"); + + gtk_widget_grab_focus (accept_button); + gtk_widget_grab_default (accept_button); + return connection_window; +} + +GtkWidget* +create_main_window (void) +{ + GtkWidget *main_window; + GtkWidget *vbox5; + GtkWidget *menubar1; + GtkWidget *menuitem4; + GtkWidget *menuitem4_menu; + GtkWidget *new_ruleset1; + GtkWidget *image96; + GtkWidget *open_ruleset; + GtkWidget *image97; + GtkWidget *save_ruleset; + GtkWidget *image98; + GtkWidget *separatormenuitem1; + GtkWidget *quit; + GtkWidget *menuitem5; + GtkWidget *menuitem5_menu; + GtkWidget *clear_log; + GtkWidget *image99; + GtkWidget *menuitem7; + GtkWidget *menuitem7_menu; + GtkWidget *about; + GtkWidget *title_eventbox; + GtkWidget *hbox28; + GtkWidget *label76; + GtkWidget *version_label; + GtkWidget *hseparator7; + GtkWidget *notebook1; + GtkWidget *scrolledwindow2; + GtkWidget *log_view; + GtkWidget *label21; + GtkWidget *vbox6; + GtkWidget *frame1; + GtkWidget *vbox7; + GtkWidget *ruleset_check_button; + GtkWidget *hbox13; + GtkWidget *label30; + GtkWidget *unmatch_optionmenu; + GtkWidget *menu1; + GtkWidget *default_query; + GtkWidget *image114; + GtkWidget *default_accept; + GtkWidget *image115; + GtkWidget *default_reject; + GtkWidget *image116; + GtkWidget *default_drop; + GtkWidget *image117; + GtkWidget *label23; + GtkWidget *hbox21; + GtkWidget *vbox18; + GtkWidget *scrolledwindow3; + GtkWidget *ruleset_view; + GtkWidget *frame10; + GtkWidget *table7; + GtkWidget *label70; + GtkWidget *label64; + GtkWidget *label63; + GtkWidget *rule_verdict_label; + GtkWidget *rule_match_label; + GtkWidget *rule_name_label; + GtkWidget *rule_enabled_label; + GtkWidget *label82; + GtkWidget *label62; + GtkWidget *vbox19; + GtkWidget *properties_button; + GtkWidget *hseparator4; + GtkWidget *up_button; + GtkWidget *down_button; + GtkWidget *hseparator3; + GtkWidget *add_button; + GtkWidget *alignment6; + GtkWidget *hbox7; + GtkWidget *image9; + GtkWidget *label24; + GtkWidget *remove_button; + GtkWidget *alignment7; + GtkWidget *hbox8; + GtkWidget *image10; + GtkWidget *label25; + GtkWidget *clear_button; + GtkWidget *hseparator10; + GtkWidget *advanced_button; + GtkWidget *alignment16; + GtkWidget *hbox25; + GtkWidget *image59; + GtkWidget *label79; + GtkWidget *hseparator9; + GtkWidget *commit_button; + GtkWidget *alignment14; + GtkWidget *hbox23; + GtkWidget *image57; + GtkWidget *label77; + GtkWidget *label22; + GtkWidget *vbox8; + GtkWidget *frame2; + GtkWidget *vbox9; + GtkWidget *autoscroll_button; + GtkWidget *sticky_button; + GtkWidget *hbox22; + GtkWidget *label66; + GtkObject *log_spinbutton_adj; + GtkWidget *log_spinbutton; + GtkWidget *label36; + GtkWidget *label32; + GtkWidget *statusbar; + GtkAccelGroup *accel_group; + + accel_group = gtk_accel_group_new (); + + main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (main_window), _("FieryFilter")); + gtk_window_set_default_size (GTK_WINDOW (main_window), 620, 520); + + vbox5 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox5); + gtk_container_add (GTK_CONTAINER (main_window), vbox5); + + menubar1 = gtk_menu_bar_new (); + gtk_widget_show (menubar1); + gtk_box_pack_start (GTK_BOX (vbox5), menubar1, FALSE, FALSE, 0); + + menuitem4 = gtk_menu_item_new_with_mnemonic (_("_File")); + gtk_widget_show (menuitem4); + gtk_container_add (GTK_CONTAINER (menubar1), menuitem4); + + menuitem4_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem4), menuitem4_menu); + + new_ruleset1 = gtk_image_menu_item_new_with_mnemonic (_("_New ruleset")); + gtk_widget_show (new_ruleset1); + gtk_container_add (GTK_CONTAINER (menuitem4_menu), new_ruleset1); + + image96 = gtk_image_new_from_stock ("gtk-new", GTK_ICON_SIZE_MENU); + gtk_widget_show (image96); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (new_ruleset1), image96); + + open_ruleset = gtk_image_menu_item_new_with_mnemonic (_("_Open ruleset...")); + gtk_widget_show (open_ruleset); + gtk_container_add (GTK_CONTAINER (menuitem4_menu), open_ruleset); + + image97 = gtk_image_new_from_stock ("gtk-open", GTK_ICON_SIZE_MENU); + gtk_widget_show (image97); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (open_ruleset), image97); + + save_ruleset = gtk_image_menu_item_new_with_mnemonic (_("_Save ruleset as...")); + gtk_widget_show (save_ruleset); + gtk_container_add (GTK_CONTAINER (menuitem4_menu), save_ruleset); + + image98 = gtk_image_new_from_stock ("gtk-save-as", GTK_ICON_SIZE_MENU); + gtk_widget_show (image98); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (save_ruleset), image98); + + separatormenuitem1 = gtk_menu_item_new (); + gtk_widget_show (separatormenuitem1); + gtk_container_add (GTK_CONTAINER (menuitem4_menu), separatormenuitem1); + gtk_widget_set_sensitive (separatormenuitem1, FALSE); + + quit = gtk_image_menu_item_new_from_stock ("gtk-quit", accel_group); + gtk_widget_show (quit); + gtk_container_add (GTK_CONTAINER (menuitem4_menu), quit); + + menuitem5 = gtk_menu_item_new_with_mnemonic (_("_Edit")); + gtk_widget_show (menuitem5); + gtk_container_add (GTK_CONTAINER (menubar1), menuitem5); + + menuitem5_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem5), menuitem5_menu); + + clear_log = gtk_image_menu_item_new_with_mnemonic (_("_Clear Log")); + gtk_widget_show (clear_log); + gtk_container_add (GTK_CONTAINER (menuitem5_menu), clear_log); + + image99 = gtk_image_new_from_stock ("gtk-clear", GTK_ICON_SIZE_MENU); + gtk_widget_show (image99); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (clear_log), image99); + + menuitem7 = gtk_menu_item_new_with_mnemonic (_("_Help")); + gtk_widget_show (menuitem7); + gtk_container_add (GTK_CONTAINER (menubar1), menuitem7); + + menuitem7_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem7), menuitem7_menu); + + about = gtk_menu_item_new_with_mnemonic (_("_About")); + gtk_widget_show (about); + gtk_container_add (GTK_CONTAINER (menuitem7_menu), about); + + title_eventbox = gtk_event_box_new (); + gtk_widget_show (title_eventbox); + gtk_box_pack_start (GTK_BOX (vbox5), title_eventbox, FALSE, FALSE, 0); + + hbox28 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox28); + gtk_container_add (GTK_CONTAINER (title_eventbox), hbox28); + + label76 = gtk_label_new (_("FieryFilter Interactive Personal Firewall")); + gtk_widget_show (label76); + gtk_box_pack_start (GTK_BOX (hbox28), label76, TRUE, TRUE, 0); + gtk_label_set_use_markup (GTK_LABEL (label76), TRUE); + gtk_label_set_justify (GTK_LABEL (label76), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label76), 0, 0.5); + gtk_misc_set_padding (GTK_MISC (label76), 10, 5); + + version_label = gtk_label_new (_("Version 4711")); + gtk_widget_show (version_label); + gtk_box_pack_start (GTK_BOX (hbox28), version_label, FALSE, FALSE, 0); + gtk_label_set_use_markup (GTK_LABEL (version_label), TRUE); + gtk_label_set_justify (GTK_LABEL (version_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (version_label), 0.5, 1); + gtk_misc_set_padding (GTK_MISC (version_label), 10, 5); + + hseparator7 = gtk_hseparator_new (); + gtk_widget_show (hseparator7); + gtk_box_pack_start (GTK_BOX (vbox5), hseparator7, FALSE, TRUE, 0); + + notebook1 = gtk_notebook_new (); + gtk_widget_show (notebook1); + gtk_box_pack_start (GTK_BOX (vbox5), notebook1, TRUE, TRUE, 3); + + scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolledwindow2); + gtk_container_add (GTK_CONTAINER (notebook1), scrolledwindow2); + gtk_container_set_border_width (GTK_CONTAINER (scrolledwindow2), 5); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_SHADOW_IN); + + log_view = gtk_tree_view_new (); + gtk_widget_show (log_view); + gtk_container_add (GTK_CONTAINER (scrolledwindow2), log_view); + + label21 = gtk_label_new_with_mnemonic (_("Connection _Log")); + gtk_widget_show (label21); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 0), label21); + GTK_WIDGET_SET_FLAGS (label21, GTK_CAN_FOCUS); + gtk_label_set_use_markup (GTK_LABEL (label21), TRUE); + gtk_label_set_justify (GTK_LABEL (label21), GTK_JUSTIFY_LEFT); + + vbox6 = gtk_vbox_new (FALSE, 10); + gtk_widget_show (vbox6); + gtk_container_add (GTK_CONTAINER (notebook1), vbox6); + gtk_container_set_border_width (GTK_CONTAINER (vbox6), 5); + + frame1 = gtk_frame_new (NULL); + gtk_widget_show (frame1); + gtk_box_pack_start (GTK_BOX (vbox6), frame1, FALSE, TRUE, 0); + + vbox7 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox7); + gtk_container_add (GTK_CONTAINER (frame1), vbox7); + gtk_container_set_border_width (GTK_CONTAINER (vbox7), 5); + + ruleset_check_button = gtk_check_button_new_with_mnemonic (_("Respect r_uleset")); + gtk_widget_show (ruleset_check_button); + gtk_box_pack_start (GTK_BOX (vbox7), ruleset_check_button, FALSE, FALSE, 0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ruleset_check_button), TRUE); + + hbox13 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox13); + gtk_box_pack_start (GTK_BOX (vbox7), hbox13, FALSE, FALSE, 0); + + label30 = gtk_label_new_with_mnemonic (_("Un_matched connections:")); + gtk_widget_show (label30); + gtk_box_pack_start (GTK_BOX (hbox13), label30, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label30), GTK_JUSTIFY_LEFT); + + unmatch_optionmenu = gtk_option_menu_new (); + gtk_widget_show (unmatch_optionmenu); + gtk_box_pack_start (GTK_BOX (hbox13), unmatch_optionmenu, TRUE, TRUE, 0); + gtk_option_menu_set_history (GTK_OPTION_MENU (unmatch_optionmenu), 1); + + menu1 = gtk_menu_new (); + + default_query = gtk_image_menu_item_new_with_mnemonic (_("Query User")); + gtk_widget_show (default_query); + gtk_container_add (GTK_CONTAINER (menu1), default_query); + + image114 = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_MENU); + gtk_widget_show (image114); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (default_query), image114); + + default_accept = gtk_image_menu_item_new_with_mnemonic (_("Accept")); + gtk_widget_show (default_accept); + gtk_container_add (GTK_CONTAINER (menu1), default_accept); + + image115 = gtk_image_new_from_stock ("gtk-yes", GTK_ICON_SIZE_MENU); + gtk_widget_show (image115); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (default_accept), image115); + + default_reject = gtk_image_menu_item_new_with_mnemonic (_("Reject")); + gtk_widget_show (default_reject); + gtk_container_add (GTK_CONTAINER (menu1), default_reject); + + image116 = gtk_image_new_from_stock ("gtk-dialog-error", GTK_ICON_SIZE_MENU); + gtk_widget_show (image116); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (default_reject), image116); + + default_drop = gtk_image_menu_item_new_with_mnemonic (_("Drop")); + gtk_widget_show (default_drop); + gtk_container_add (GTK_CONTAINER (menu1), default_drop); + + image117 = gtk_image_new_from_stock ("gtk-delete", GTK_ICON_SIZE_MENU); + gtk_widget_show (image117); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (default_drop), image117); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (unmatch_optionmenu), menu1); + + label23 = gtk_label_new (_("Firewall mode")); + gtk_widget_show (label23); + gtk_frame_set_label_widget (GTK_FRAME (frame1), label23); + gtk_label_set_use_markup (GTK_LABEL (label23), TRUE); + gtk_label_set_justify (GTK_LABEL (label23), GTK_JUSTIFY_LEFT); + + hbox21 = gtk_hbox_new (FALSE, 10); + gtk_widget_show (hbox21); + gtk_box_pack_start (GTK_BOX (vbox6), hbox21, TRUE, TRUE, 0); + + vbox18 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox18); + gtk_box_pack_start (GTK_BOX (hbox21), vbox18, TRUE, TRUE, 0); + + scrolledwindow3 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolledwindow3); + gtk_box_pack_start (GTK_BOX (vbox18), scrolledwindow3, TRUE, TRUE, 0); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow3), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow3), GTK_SHADOW_IN); + + ruleset_view = gtk_tree_view_new (); + gtk_widget_show (ruleset_view); + gtk_container_add (GTK_CONTAINER (scrolledwindow3), ruleset_view); + + frame10 = gtk_frame_new (NULL); + gtk_widget_show (frame10); + gtk_box_pack_start (GTK_BOX (vbox18), frame10, FALSE, FALSE, 0); + + table7 = gtk_table_new (4, 2, FALSE); + gtk_widget_show (table7); + gtk_container_add (GTK_CONTAINER (frame10), table7); + gtk_container_set_border_width (GTK_CONTAINER (table7), 5); + gtk_table_set_row_spacings (GTK_TABLE (table7), 5); + gtk_table_set_col_spacings (GTK_TABLE (table7), 5); + + label70 = gtk_label_new (_("Verdict:")); + gtk_widget_show (label70); + gtk_table_attach (GTK_TABLE (table7), label70, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (label70), TRUE); + gtk_label_set_justify (GTK_LABEL (label70), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label70), 1, 0.5); + + label64 = gtk_label_new (_("Match:")); + gtk_widget_show (label64); + gtk_table_attach (GTK_TABLE (table7), label64, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (label64), TRUE); + gtk_label_set_justify (GTK_LABEL (label64), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label64), 1, 0.5); + + label63 = gtk_label_new (_("Description:")); + gtk_widget_show (label63); + gtk_table_attach (GTK_TABLE (table7), label63, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (label63), TRUE); + gtk_label_set_justify (GTK_LABEL (label63), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label63), 1, 0.5); + + rule_verdict_label = gtk_label_new (_("label69")); + gtk_widget_show (rule_verdict_label); + gtk_table_attach (GTK_TABLE (table7), rule_verdict_label, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (rule_verdict_label), TRUE); + gtk_label_set_justify (GTK_LABEL (rule_verdict_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (rule_verdict_label), 0, 0.5); + + rule_match_label = gtk_label_new (_("label68")); + gtk_widget_show (rule_match_label); + gtk_table_attach (GTK_TABLE (table7), rule_match_label, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (rule_match_label), TRUE); + gtk_label_set_justify (GTK_LABEL (rule_match_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (rule_match_label), 0, 0.5); + + rule_name_label = gtk_label_new (_("label67")); + gtk_widget_show (rule_name_label); + gtk_table_attach (GTK_TABLE (table7), rule_name_label, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (rule_name_label), TRUE); + gtk_label_set_justify (GTK_LABEL (rule_name_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (rule_name_label), 0, 0.5); + + rule_enabled_label = gtk_label_new (_("label80")); + gtk_widget_show (rule_enabled_label); + gtk_table_attach (GTK_TABLE (table7), rule_enabled_label, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (rule_enabled_label), TRUE); + gtk_label_set_justify (GTK_LABEL (rule_enabled_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (rule_enabled_label), 0, 0.5); + + label82 = gtk_label_new (_("Enabled:")); + gtk_widget_show (label82); + gtk_table_attach (GTK_TABLE (table7), label82, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (label82), TRUE); + gtk_label_set_justify (GTK_LABEL (label82), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label82), 1, 0.5); + + label62 = gtk_label_new (_("Rule")); + gtk_widget_show (label62); + gtk_frame_set_label_widget (GTK_FRAME (frame10), label62); + gtk_label_set_use_markup (GTK_LABEL (label62), TRUE); + gtk_label_set_justify (GTK_LABEL (label62), GTK_JUSTIFY_LEFT); + + vbox19 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox19); + gtk_box_pack_start (GTK_BOX (hbox21), vbox19, FALSE, FALSE, 0); + + properties_button = gtk_button_new_from_stock ("gtk-properties"); + gtk_widget_show (properties_button); + gtk_box_pack_start (GTK_BOX (vbox19), properties_button, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS (properties_button, GTK_CAN_DEFAULT); + + hseparator4 = gtk_hseparator_new (); + gtk_widget_show (hseparator4); + gtk_box_pack_start (GTK_BOX (vbox19), hseparator4, FALSE, TRUE, 5); + + up_button = gtk_button_new_from_stock ("gtk-go-up"); + gtk_widget_show (up_button); + gtk_box_pack_start (GTK_BOX (vbox19), up_button, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS (up_button, GTK_CAN_DEFAULT); + + down_button = gtk_button_new_from_stock ("gtk-go-down"); + gtk_widget_show (down_button); + gtk_box_pack_start (GTK_BOX (vbox19), down_button, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS (down_button, GTK_CAN_DEFAULT); + + hseparator3 = gtk_hseparator_new (); + gtk_widget_show (hseparator3); + gtk_box_pack_start (GTK_BOX (vbox19), hseparator3, FALSE, TRUE, 5); + + add_button = gtk_button_new (); + gtk_widget_show (add_button); + gtk_box_pack_start (GTK_BOX (vbox19), add_button, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS (add_button, GTK_CAN_DEFAULT); + + alignment6 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment6); + gtk_container_add (GTK_CONTAINER (add_button), alignment6); + + hbox7 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox7); + gtk_container_add (GTK_CONTAINER (alignment6), hbox7); + + image9 = gtk_image_new_from_stock ("gtk-add", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image9); + gtk_box_pack_start (GTK_BOX (hbox7), image9, FALSE, FALSE, 0); + + label24 = gtk_label_new_with_mnemonic (_("_Add new rule")); + gtk_widget_show (label24); + gtk_box_pack_start (GTK_BOX (hbox7), label24, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label24), GTK_JUSTIFY_LEFT); + + remove_button = gtk_button_new (); + gtk_widget_show (remove_button); + gtk_box_pack_start (GTK_BOX (vbox19), remove_button, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS (remove_button, GTK_CAN_DEFAULT); + + alignment7 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment7); + gtk_container_add (GTK_CONTAINER (remove_button), alignment7); + + hbox8 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox8); + gtk_container_add (GTK_CONTAINER (alignment7), hbox8); + + image10 = gtk_image_new_from_stock ("gtk-remove", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image10); + gtk_box_pack_start (GTK_BOX (hbox8), image10, FALSE, FALSE, 0); + + label25 = gtk_label_new_with_mnemonic (_("_Remove rule")); + gtk_widget_show (label25); + gtk_box_pack_start (GTK_BOX (hbox8), label25, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label25), GTK_JUSTIFY_LEFT); + + clear_button = gtk_button_new_from_stock ("gtk-clear"); + gtk_widget_show (clear_button); + gtk_box_pack_start (GTK_BOX (vbox19), clear_button, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS (clear_button, GTK_CAN_DEFAULT); + + hseparator10 = gtk_hseparator_new (); + gtk_widget_show (hseparator10); + gtk_box_pack_start (GTK_BOX (vbox19), hseparator10, FALSE, FALSE, 5); + + advanced_button = gtk_button_new (); + gtk_widget_show (advanced_button); + gtk_box_pack_start (GTK_BOX (vbox19), advanced_button, FALSE, FALSE, 0); + + alignment16 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment16); + gtk_container_add (GTK_CONTAINER (advanced_button), alignment16); + + hbox25 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox25); + gtk_container_add (GTK_CONTAINER (alignment16), hbox25); + + image59 = gtk_image_new_from_stock ("gtk-preferences", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image59); + gtk_box_pack_start (GTK_BOX (hbox25), image59, FALSE, FALSE, 0); + + label79 = gtk_label_new_with_mnemonic (_("_Advanced")); + gtk_widget_show (label79); + gtk_box_pack_start (GTK_BOX (hbox25), label79, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label79), GTK_JUSTIFY_LEFT); + + hseparator9 = gtk_hseparator_new (); + gtk_widget_show (hseparator9); + gtk_box_pack_start (GTK_BOX (vbox19), hseparator9, FALSE, FALSE, 5); + + commit_button = gtk_button_new (); + gtk_widget_show (commit_button); + gtk_box_pack_start (GTK_BOX (vbox19), commit_button, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS (commit_button, GTK_CAN_DEFAULT); + + alignment14 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment14); + gtk_container_add (GTK_CONTAINER (commit_button), alignment14); + + hbox23 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox23); + gtk_container_add (GTK_CONTAINER (alignment14), hbox23); + + image57 = gtk_image_new_from_stock ("gtk-execute", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image57); + gtk_box_pack_start (GTK_BOX (hbox23), image57, FALSE, FALSE, 0); + + label77 = gtk_label_new_with_mnemonic (_("Co_mmit")); + gtk_widget_show (label77); + gtk_box_pack_start (GTK_BOX (hbox23), label77, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label77), GTK_JUSTIFY_LEFT); + + label22 = gtk_label_new_with_mnemonic (_("Firewall _Rules")); + gtk_widget_show (label22); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 1), label22); + gtk_label_set_use_markup (GTK_LABEL (label22), TRUE); + gtk_label_set_justify (GTK_LABEL (label22), GTK_JUSTIFY_LEFT); + + vbox8 = gtk_vbox_new (FALSE, 10); + gtk_widget_show (vbox8); + gtk_container_add (GTK_CONTAINER (notebook1), vbox8); + gtk_container_set_border_width (GTK_CONTAINER (vbox8), 5); + + frame2 = gtk_frame_new (NULL); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox8), frame2, FALSE, FALSE, 0); + + vbox9 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox9); + gtk_container_add (GTK_CONTAINER (frame2), vbox9); + gtk_container_set_border_width (GTK_CONTAINER (vbox9), 5); + + autoscroll_button = gtk_check_button_new_with_mnemonic (_("_Automatic scrolling to newly added log entries")); + gtk_widget_show (autoscroll_button); + gtk_box_pack_start (GTK_BOX (vbox9), autoscroll_button, FALSE, FALSE, 0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (autoscroll_button), TRUE); + + sticky_button = gtk_check_button_new_with_mnemonic (_("Popup window is _sticky (visible on all desktops)")); + gtk_widget_show (sticky_button); + gtk_box_pack_start (GTK_BOX (vbox9), sticky_button, FALSE, FALSE, 0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sticky_button), TRUE); + + hbox22 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox22); + gtk_box_pack_start (GTK_BOX (vbox9), hbox22, TRUE, TRUE, 0); + + label66 = gtk_label_new (_("Maximum number of Log entries:")); + gtk_widget_show (label66); + gtk_box_pack_start (GTK_BOX (hbox22), label66, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label66), GTK_JUSTIFY_LEFT); + + log_spinbutton_adj = gtk_adjustment_new (100, 10, 999, 1, 10, 10); + log_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (log_spinbutton_adj), 1, 0); + gtk_widget_show (log_spinbutton); + gtk_box_pack_start (GTK_BOX (hbox22), log_spinbutton, FALSE, TRUE, 0); + + label36 = gtk_label_new (_("User Interface")); + gtk_widget_show (label36); + gtk_frame_set_label_widget (GTK_FRAME (frame2), label36); + gtk_label_set_use_markup (GTK_LABEL (label36), TRUE); + gtk_label_set_justify (GTK_LABEL (label36), GTK_JUSTIFY_LEFT); + + label32 = gtk_label_new_with_mnemonic (_("_Options")); + gtk_widget_show (label32); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 2), label32); + gtk_label_set_justify (GTK_LABEL (label32), GTK_JUSTIFY_LEFT); + + statusbar = gtk_statusbar_new (); + gtk_widget_show (statusbar); + gtk_box_pack_start (GTK_BOX (vbox5), statusbar, FALSE, FALSE, 0); + + g_signal_connect ((gpointer) main_window, "delete_event", + G_CALLBACK (on_main_window_delete_event), + NULL); + g_signal_connect ((gpointer) new_ruleset1, "activate", + G_CALLBACK (on_new_ruleset_activate), + NULL); + g_signal_connect ((gpointer) open_ruleset, "activate", + G_CALLBACK (on_open_ruleset_activate), + NULL); + g_signal_connect ((gpointer) save_ruleset, "activate", + G_CALLBACK (on_save_ruleset_activate), + NULL); + g_signal_connect ((gpointer) quit, "activate", + G_CALLBACK (on_quit_activate), + NULL); + g_signal_connect ((gpointer) clear_log, "activate", + G_CALLBACK (on_clear_log_activate), + NULL); + g_signal_connect ((gpointer) about, "activate", + G_CALLBACK (on_about_activate), + NULL); + g_signal_connect ((gpointer) ruleset_check_button, "toggled", + G_CALLBACK (on_ruleset_check_button_toggled), + NULL); + g_signal_connect ((gpointer) unmatch_optionmenu, "changed", + G_CALLBACK (on_unmatch_optionmenu_changed), + NULL); + g_signal_connect ((gpointer) ruleset_view, "cursor_changed", + G_CALLBACK (on_ruleset_view_cursor_changed), + NULL); + g_signal_connect ((gpointer) properties_button, "clicked", + G_CALLBACK (on_properties_button_clicked), + NULL); + g_signal_connect ((gpointer) up_button, "clicked", + G_CALLBACK (on_up_button_clicked), + NULL); + g_signal_connect ((gpointer) down_button, "clicked", + G_CALLBACK (on_down_button_clicked), + NULL); + g_signal_connect ((gpointer) add_button, "clicked", + G_CALLBACK (on_add_button_clicked), + NULL); + g_signal_connect ((gpointer) remove_button, "clicked", + G_CALLBACK (on_remove_button_clicked), + NULL); + g_signal_connect ((gpointer) clear_button, "clicked", + G_CALLBACK (on_clear_button_clicked), + NULL); + g_signal_connect ((gpointer) advanced_button, "clicked", + G_CALLBACK (on_advanced_button_clicked), + NULL); + g_signal_connect ((gpointer) commit_button, "clicked", + G_CALLBACK (on_commit_button_clicked), + NULL); + g_signal_connect ((gpointer) sticky_button, "toggled", + G_CALLBACK (on_sticky_button_toggled), + NULL); + g_signal_connect ((gpointer) log_spinbutton, "value_changed", + G_CALLBACK (on_log_spinbutton_value_changed), + NULL); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label30), unmatch_optionmenu); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (main_window, main_window, "main_window"); + GLADE_HOOKUP_OBJECT (main_window, vbox5, "vbox5"); + GLADE_HOOKUP_OBJECT (main_window, menubar1, "menubar1"); + GLADE_HOOKUP_OBJECT (main_window, menuitem4, "menuitem4"); + GLADE_HOOKUP_OBJECT (main_window, menuitem4_menu, "menuitem4_menu"); + GLADE_HOOKUP_OBJECT (main_window, new_ruleset1, "new_ruleset1"); + GLADE_HOOKUP_OBJECT (main_window, image96, "image96"); + GLADE_HOOKUP_OBJECT (main_window, open_ruleset, "open_ruleset"); + GLADE_HOOKUP_OBJECT (main_window, image97, "image97"); + GLADE_HOOKUP_OBJECT (main_window, save_ruleset, "save_ruleset"); + GLADE_HOOKUP_OBJECT (main_window, image98, "image98"); + GLADE_HOOKUP_OBJECT (main_window, separatormenuitem1, "separatormenuitem1"); + GLADE_HOOKUP_OBJECT (main_window, quit, "quit"); + GLADE_HOOKUP_OBJECT (main_window, menuitem5, "menuitem5"); + GLADE_HOOKUP_OBJECT (main_window, menuitem5_menu, "menuitem5_menu"); + GLADE_HOOKUP_OBJECT (main_window, clear_log, "clear_log"); + GLADE_HOOKUP_OBJECT (main_window, image99, "image99"); + GLADE_HOOKUP_OBJECT (main_window, menuitem7, "menuitem7"); + GLADE_HOOKUP_OBJECT (main_window, menuitem7_menu, "menuitem7_menu"); + GLADE_HOOKUP_OBJECT (main_window, about, "about"); + GLADE_HOOKUP_OBJECT (main_window, title_eventbox, "title_eventbox"); + GLADE_HOOKUP_OBJECT (main_window, hbox28, "hbox28"); + GLADE_HOOKUP_OBJECT (main_window, label76, "label76"); + GLADE_HOOKUP_OBJECT (main_window, version_label, "version_label"); + GLADE_HOOKUP_OBJECT (main_window, hseparator7, "hseparator7"); + GLADE_HOOKUP_OBJECT (main_window, notebook1, "notebook1"); + GLADE_HOOKUP_OBJECT (main_window, scrolledwindow2, "scrolledwindow2"); + GLADE_HOOKUP_OBJECT (main_window, log_view, "log_view"); + GLADE_HOOKUP_OBJECT (main_window, label21, "label21"); + GLADE_HOOKUP_OBJECT (main_window, vbox6, "vbox6"); + GLADE_HOOKUP_OBJECT (main_window, frame1, "frame1"); + GLADE_HOOKUP_OBJECT (main_window, vbox7, "vbox7"); + GLADE_HOOKUP_OBJECT (main_window, ruleset_check_button, "ruleset_check_button"); + GLADE_HOOKUP_OBJECT (main_window, hbox13, "hbox13"); + GLADE_HOOKUP_OBJECT (main_window, label30, "label30"); + GLADE_HOOKUP_OBJECT (main_window, unmatch_optionmenu, "unmatch_optionmenu"); + GLADE_HOOKUP_OBJECT (main_window, menu1, "menu1"); + GLADE_HOOKUP_OBJECT (main_window, default_query, "default_query"); + GLADE_HOOKUP_OBJECT (main_window, image114, "image114"); + GLADE_HOOKUP_OBJECT (main_window, default_accept, "default_accept"); + GLADE_HOOKUP_OBJECT (main_window, image115, "image115"); + GLADE_HOOKUP_OBJECT (main_window, default_reject, "default_reject"); + GLADE_HOOKUP_OBJECT (main_window, image116, "image116"); + GLADE_HOOKUP_OBJECT (main_window, default_drop, "default_drop"); + GLADE_HOOKUP_OBJECT (main_window, image117, "image117"); + GLADE_HOOKUP_OBJECT (main_window, label23, "label23"); + GLADE_HOOKUP_OBJECT (main_window, hbox21, "hbox21"); + GLADE_HOOKUP_OBJECT (main_window, vbox18, "vbox18"); + GLADE_HOOKUP_OBJECT (main_window, scrolledwindow3, "scrolledwindow3"); + GLADE_HOOKUP_OBJECT (main_window, ruleset_view, "ruleset_view"); + GLADE_HOOKUP_OBJECT (main_window, frame10, "frame10"); + GLADE_HOOKUP_OBJECT (main_window, table7, "table7"); + GLADE_HOOKUP_OBJECT (main_window, label70, "label70"); + GLADE_HOOKUP_OBJECT (main_window, label64, "label64"); + GLADE_HOOKUP_OBJECT (main_window, label63, "label63"); + GLADE_HOOKUP_OBJECT (main_window, rule_verdict_label, "rule_verdict_label"); + GLADE_HOOKUP_OBJECT (main_window, rule_match_label, "rule_match_label"); + GLADE_HOOKUP_OBJECT (main_window, rule_name_label, "rule_name_label"); + GLADE_HOOKUP_OBJECT (main_window, rule_enabled_label, "rule_enabled_label"); + GLADE_HOOKUP_OBJECT (main_window, label82, "label82"); + GLADE_HOOKUP_OBJECT (main_window, label62, "label62"); + GLADE_HOOKUP_OBJECT (main_window, vbox19, "vbox19"); + GLADE_HOOKUP_OBJECT (main_window, properties_button, "properties_button"); + GLADE_HOOKUP_OBJECT (main_window, hseparator4, "hseparator4"); + GLADE_HOOKUP_OBJECT (main_window, up_button, "up_button"); + GLADE_HOOKUP_OBJECT (main_window, down_button, "down_button"); + GLADE_HOOKUP_OBJECT (main_window, hseparator3, "hseparator3"); + GLADE_HOOKUP_OBJECT (main_window, add_button, "add_button"); + GLADE_HOOKUP_OBJECT (main_window, alignment6, "alignment6"); + GLADE_HOOKUP_OBJECT (main_window, hbox7, "hbox7"); + GLADE_HOOKUP_OBJECT (main_window, image9, "image9"); + GLADE_HOOKUP_OBJECT (main_window, label24, "label24"); + GLADE_HOOKUP_OBJECT (main_window, remove_button, "remove_button"); + GLADE_HOOKUP_OBJECT (main_window, alignment7, "alignment7"); + GLADE_HOOKUP_OBJECT (main_window, hbox8, "hbox8"); + GLADE_HOOKUP_OBJECT (main_window, image10, "image10"); + GLADE_HOOKUP_OBJECT (main_window, label25, "label25"); + GLADE_HOOKUP_OBJECT (main_window, clear_button, "clear_button"); + GLADE_HOOKUP_OBJECT (main_window, hseparator10, "hseparator10"); + GLADE_HOOKUP_OBJECT (main_window, advanced_button, "advanced_button"); + GLADE_HOOKUP_OBJECT (main_window, alignment16, "alignment16"); + GLADE_HOOKUP_OBJECT (main_window, hbox25, "hbox25"); + GLADE_HOOKUP_OBJECT (main_window, image59, "image59"); + GLADE_HOOKUP_OBJECT (main_window, label79, "label79"); + GLADE_HOOKUP_OBJECT (main_window, hseparator9, "hseparator9"); + GLADE_HOOKUP_OBJECT (main_window, commit_button, "commit_button"); + GLADE_HOOKUP_OBJECT (main_window, alignment14, "alignment14"); + GLADE_HOOKUP_OBJECT (main_window, hbox23, "hbox23"); + GLADE_HOOKUP_OBJECT (main_window, image57, "image57"); + GLADE_HOOKUP_OBJECT (main_window, label77, "label77"); + GLADE_HOOKUP_OBJECT (main_window, label22, "label22"); + GLADE_HOOKUP_OBJECT (main_window, vbox8, "vbox8"); + GLADE_HOOKUP_OBJECT (main_window, frame2, "frame2"); + GLADE_HOOKUP_OBJECT (main_window, vbox9, "vbox9"); + GLADE_HOOKUP_OBJECT (main_window, autoscroll_button, "autoscroll_button"); + GLADE_HOOKUP_OBJECT (main_window, sticky_button, "sticky_button"); + GLADE_HOOKUP_OBJECT (main_window, hbox22, "hbox22"); + GLADE_HOOKUP_OBJECT (main_window, label66, "label66"); + GLADE_HOOKUP_OBJECT (main_window, log_spinbutton, "log_spinbutton"); + GLADE_HOOKUP_OBJECT (main_window, label36, "label36"); + GLADE_HOOKUP_OBJECT (main_window, label32, "label32"); + GLADE_HOOKUP_OBJECT (main_window, statusbar, "statusbar"); + + gtk_widget_grab_default (commit_button); + gtk_window_add_accel_group (GTK_WINDOW (main_window), accel_group); + + return main_window; +} + +GtkWidget* +create_rule_window (void) +{ + GtkWidget *rule_window; + GtkWidget *vbox11; + GtkWidget *desc_eventbox; + GtkWidget *desc_label; + GtkWidget *hseparator2; + GtkWidget *notebook2; + GtkWidget *vbox12; + GtkWidget *label60; + GtkWidget *desc_entry; + GtkWidget *label72; + GtkWidget *rule_optionmenu; + GtkWidget *menu5; + GtkWidget *imagemenuitem1; + GtkWidget *image110; + GtkWidget *imagemenuitem2; + GtkWidget *image111; + GtkWidget *imagemenuitem3; + GtkWidget *image112; + GtkWidget *imagemenuitem4; + GtkWidget *image113; + GtkWidget *label56; + GtkWidget *vbox16; + GtkWidget *frame4; + GtkWidget *hbox18; + GtkWidget *direction_label; + GtkWidget *direction_optionmenu; + GtkWidget *menu4; + GtkWidget *incoming_menu_item; + GtkWidget *image37; + GtkWidget *outgoing_menu_item; + GtkWidget *image38; + GtkWidget *passing_menu_item; + GtkWidget *match_direction_checkbutton; + GtkWidget *frame5; + GtkWidget *table3; + GtkWidget *incoming_label; + GtkWidget *outgoing_label; + GtkWidget *outgoing_combo; + GtkWidget *combo_entry2; + GtkWidget *incoming_combo; + GtkWidget *combo_entry3; + GtkWidget *match_interfaces_checkbutton; + GtkWidget *label57; + GtkWidget *vbox17; + GtkWidget *frame6; + GtkWidget *table4; + GtkWidget *protocol_label; + GtkWidget *port_label; + GtkWidget *protocol_optionmenu; + GtkWidget *menu3; + GtkWidget *udp_menu_item; + GtkWidget *tcp_menu_item; + GtkWidget *icmp_menu_item; + GtkWidget *icmp_label; + GtkWidget *icmp_optionmenu; + GtkWidget *hbox19; + GtkObject *port_spinbutton_adj; + GtkWidget *port_spinbutton; + GtkWidget *type_label; + GtkWidget *match_type_checkbutton; + GtkWidget *label58; + GtkWidget *vbox13; + GtkWidget *frame7; + GtkWidget *table5; + GtkWidget *src_ip_label; + GtkWidget *src_ip_entry; + GtkWidget *src_host_range_value_label; + GtkObject *src_netmask_spinbutton_adj; + GtkWidget *src_netmask_spinbutton; + GtkWidget *src_netmask_label_bits; + GtkWidget *src_host_range_label; + GtkWidget *src_netmask_checkbutton; + GtkWidget *src_netmask_label; + GtkWidget *label74; + GtkWidget *match_source_checkbutton; + GtkWidget *frame8; + GtkWidget *table6; + GtkWidget *dst_ip_label; + GtkWidget *dst_ip_entry; + GtkWidget *dst_host_range_label; + GtkObject *dst_netmask_spinbutton_adj; + GtkWidget *dst_netmask_spinbutton; + GtkWidget *dst_netmask_label_bits; + GtkWidget *dst_host_range_value_label; + GtkWidget *dst_netmask_checkbutton; + GtkWidget *label75; + GtkWidget *dst_netmask_label; + GtkWidget *match_destination_checkbutton; + GtkWidget *frame9; + GtkWidget *vbox14; + GtkWidget *bc_dont_match_radiobutton; + GSList *bc_dont_match_radiobutton_group = NULL; + GtkWidget *bc_match_broadcast_radiobutton; + GtkWidget *bc_match_unicast_radiobutton; + GtkWidget *label41; + GtkWidget *label59; + GtkWidget *hbuttonbox3; + GtkWidget *ok_button; + GtkWidget *cancel_button; + + rule_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (rule_window), _("FieryFilter Rule")); + gtk_window_set_resizable (GTK_WINDOW (rule_window), FALSE); + + vbox11 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox11); + gtk_container_add (GTK_CONTAINER (rule_window), vbox11); + + desc_eventbox = gtk_event_box_new (); + gtk_widget_show (desc_eventbox); + gtk_box_pack_start (GTK_BOX (vbox11), desc_eventbox, FALSE, FALSE, 0); + + desc_label = gtk_label_new (_("desc_label")); + gtk_widget_show (desc_label); + gtk_container_add (GTK_CONTAINER (desc_eventbox), desc_label); + GTK_WIDGET_SET_FLAGS (desc_label, GTK_CAN_FOCUS); + gtk_label_set_use_markup (GTK_LABEL (desc_label), TRUE); + gtk_label_set_justify (GTK_LABEL (desc_label), GTK_JUSTIFY_LEFT); + gtk_label_set_selectable (GTK_LABEL (desc_label), TRUE); + gtk_misc_set_alignment (GTK_MISC (desc_label), 0, 0.5); + gtk_misc_set_padding (GTK_MISC (desc_label), 10, 10); + + hseparator2 = gtk_hseparator_new (); + gtk_widget_show (hseparator2); + gtk_box_pack_start (GTK_BOX (vbox11), hseparator2, FALSE, FALSE, 0); + + notebook2 = gtk_notebook_new (); + gtk_widget_show (notebook2); + gtk_box_pack_start (GTK_BOX (vbox11), notebook2, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (notebook2), 5); + + vbox12 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox12); + gtk_container_add (GTK_CONTAINER (notebook2), vbox12); + gtk_container_set_border_width (GTK_CONTAINER (vbox12), 5); + + label60 = gtk_label_new (_("Description:")); + gtk_widget_show (label60); + gtk_box_pack_start (GTK_BOX (vbox12), label60, FALSE, FALSE, 0); + gtk_label_set_use_markup (GTK_LABEL (label60), TRUE); + gtk_label_set_justify (GTK_LABEL (label60), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label60), 0, 0.5); + + desc_entry = gtk_entry_new (); + gtk_widget_show (desc_entry); + gtk_box_pack_start (GTK_BOX (vbox12), desc_entry, FALSE, FALSE, 0); + gtk_entry_set_max_length (GTK_ENTRY (desc_entry), 64); + gtk_entry_set_text (GTK_ENTRY (desc_entry), _("A new rule")); + + label72 = gtk_label_new (_("Action:")); + gtk_widget_show (label72); + gtk_box_pack_start (GTK_BOX (vbox12), label72, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label72), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label72), 0, 0.5); + + rule_optionmenu = gtk_option_menu_new (); + gtk_widget_show (rule_optionmenu); + gtk_box_pack_start (GTK_BOX (vbox12), rule_optionmenu, FALSE, FALSE, 0); + + menu5 = gtk_menu_new (); + + imagemenuitem1 = gtk_image_menu_item_new_with_mnemonic (_("Query User")); + gtk_widget_show (imagemenuitem1); + gtk_container_add (GTK_CONTAINER (menu5), imagemenuitem1); + + image110 = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_MENU); + gtk_widget_show (image110); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (imagemenuitem1), image110); + + imagemenuitem2 = gtk_image_menu_item_new_with_mnemonic (_("Accept")); + gtk_widget_show (imagemenuitem2); + gtk_container_add (GTK_CONTAINER (menu5), imagemenuitem2); + + image111 = gtk_image_new_from_stock ("gtk-yes", GTK_ICON_SIZE_MENU); + gtk_widget_show (image111); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (imagemenuitem2), image111); + + imagemenuitem3 = gtk_image_menu_item_new_with_mnemonic (_("Reject")); + gtk_widget_show (imagemenuitem3); + gtk_container_add (GTK_CONTAINER (menu5), imagemenuitem3); + + image112 = gtk_image_new_from_stock ("gtk-dialog-error", GTK_ICON_SIZE_MENU); + gtk_widget_show (image112); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (imagemenuitem3), image112); + + imagemenuitem4 = gtk_image_menu_item_new_with_mnemonic (_("Drop")); + gtk_widget_show (imagemenuitem4); + gtk_container_add (GTK_CONTAINER (menu5), imagemenuitem4); + + image113 = gtk_image_new_from_stock ("gtk-delete", GTK_ICON_SIZE_MENU); + gtk_widget_show (image113); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (imagemenuitem4), image113); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (rule_optionmenu), menu5); + + label56 = gtk_label_new (_("General")); + gtk_widget_show (label56); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 0), label56); + gtk_label_set_justify (GTK_LABEL (label56), GTK_JUSTIFY_LEFT); + + vbox16 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox16); + gtk_container_add (GTK_CONTAINER (notebook2), vbox16); + gtk_container_set_border_width (GTK_CONTAINER (vbox16), 5); + + frame4 = gtk_frame_new (NULL); + gtk_widget_show (frame4); + gtk_box_pack_start (GTK_BOX (vbox16), frame4, FALSE, FALSE, 0); + + hbox18 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox18); + gtk_container_add (GTK_CONTAINER (frame4), hbox18); + gtk_container_set_border_width (GTK_CONTAINER (hbox18), 5); + + direction_label = gtk_label_new (_("Direction:")); + gtk_widget_show (direction_label); + gtk_box_pack_start (GTK_BOX (hbox18), direction_label, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (direction_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (direction_label), 1, 0.5); + + direction_optionmenu = gtk_option_menu_new (); + gtk_widget_show (direction_optionmenu); + gtk_box_pack_start (GTK_BOX (hbox18), direction_optionmenu, TRUE, TRUE, 0); + + menu4 = gtk_menu_new (); + + incoming_menu_item = gtk_image_menu_item_new_with_mnemonic (_("Incoming")); + gtk_widget_show (incoming_menu_item); + gtk_container_add (GTK_CONTAINER (menu4), incoming_menu_item); + + image37 = gtk_image_new_from_stock ("gtk-go-forward", GTK_ICON_SIZE_MENU); + gtk_widget_show (image37); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (incoming_menu_item), image37); + + outgoing_menu_item = gtk_image_menu_item_new_with_mnemonic (_("Outgoing")); + gtk_widget_show (outgoing_menu_item); + gtk_container_add (GTK_CONTAINER (menu4), outgoing_menu_item); + + image38 = gtk_image_new_from_stock ("gtk-go-back", GTK_ICON_SIZE_MENU); + gtk_widget_show (image38); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (outgoing_menu_item), image38); + + passing_menu_item = gtk_menu_item_new_with_mnemonic (_("Passing")); + gtk_widget_show (passing_menu_item); + gtk_container_add (GTK_CONTAINER (menu4), passing_menu_item); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (direction_optionmenu), menu4); + + match_direction_checkbutton = gtk_check_button_new_with_mnemonic (_("Match _direction:")); + gtk_widget_show (match_direction_checkbutton); + gtk_frame_set_label_widget (GTK_FRAME (frame4), match_direction_checkbutton); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (match_direction_checkbutton), TRUE); + + frame5 = gtk_frame_new (NULL); + gtk_widget_show (frame5); + gtk_box_pack_start (GTK_BOX (vbox16), frame5, FALSE, FALSE, 0); + + table3 = gtk_table_new (2, 2, FALSE); + gtk_widget_show (table3); + gtk_container_add (GTK_CONTAINER (frame5), table3); + gtk_container_set_border_width (GTK_CONTAINER (table3), 5); + gtk_table_set_row_spacings (GTK_TABLE (table3), 5); + gtk_table_set_col_spacings (GTK_TABLE (table3), 5); + + incoming_label = gtk_label_new_with_mnemonic (_("In_coming:")); + gtk_widget_show (incoming_label); + gtk_table_attach (GTK_TABLE (table3), incoming_label, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (incoming_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (incoming_label), 1, 0.5); + + outgoing_label = gtk_label_new_with_mnemonic (_("_Outgoing:")); + gtk_widget_show (outgoing_label); + gtk_table_attach (GTK_TABLE (table3), outgoing_label, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (outgoing_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (outgoing_label), 1, 0.5); + + outgoing_combo = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (outgoing_combo)->popwin), + "GladeParentKey", outgoing_combo); + gtk_widget_show (outgoing_combo); + gtk_table_attach (GTK_TABLE (table3), outgoing_combo, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry2 = GTK_COMBO (outgoing_combo)->entry; + gtk_widget_show (combo_entry2); + + incoming_combo = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (incoming_combo)->popwin), + "GladeParentKey", incoming_combo); + gtk_widget_show (incoming_combo); + gtk_table_attach (GTK_TABLE (table3), incoming_combo, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry3 = GTK_COMBO (incoming_combo)->entry; + gtk_widget_show (combo_entry3); + + match_interfaces_checkbutton = gtk_check_button_new_with_mnemonic (_("Match _interfaces:")); + gtk_widget_show (match_interfaces_checkbutton); + gtk_frame_set_label_widget (GTK_FRAME (frame5), match_interfaces_checkbutton); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (match_interfaces_checkbutton), TRUE); + + label57 = gtk_label_new (_("Interface")); + gtk_widget_show (label57); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 1), label57); + gtk_label_set_justify (GTK_LABEL (label57), GTK_JUSTIFY_LEFT); + + vbox17 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox17); + gtk_container_add (GTK_CONTAINER (notebook2), vbox17); + gtk_container_set_border_width (GTK_CONTAINER (vbox17), 5); + + frame6 = gtk_frame_new (NULL); + gtk_widget_show (frame6); + gtk_box_pack_start (GTK_BOX (vbox17), frame6, FALSE, FALSE, 0); + + table4 = gtk_table_new (3, 2, FALSE); + gtk_widget_show (table4); + gtk_container_add (GTK_CONTAINER (frame6), table4); + gtk_container_set_border_width (GTK_CONTAINER (table4), 5); + gtk_table_set_row_spacings (GTK_TABLE (table4), 5); + gtk_table_set_col_spacings (GTK_TABLE (table4), 5); + + protocol_label = gtk_label_new_with_mnemonic (_("_Protocol:")); + gtk_widget_show (protocol_label); + gtk_table_attach (GTK_TABLE (table4), protocol_label, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (protocol_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (protocol_label), 1, 0.5); + + port_label = gtk_label_new_with_mnemonic (_("_Port number:")); + gtk_widget_show (port_label); + gtk_table_attach (GTK_TABLE (table4), port_label, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (port_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (port_label), 1, 0.5); + + protocol_optionmenu = gtk_option_menu_new (); + gtk_widget_show (protocol_optionmenu); + gtk_table_attach (GTK_TABLE (table4), protocol_optionmenu, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + menu3 = gtk_menu_new (); + + udp_menu_item = gtk_menu_item_new_with_mnemonic (_("UDP - User Datagram Protocol")); + gtk_widget_show (udp_menu_item); + gtk_container_add (GTK_CONTAINER (menu3), udp_menu_item); + + tcp_menu_item = gtk_menu_item_new_with_mnemonic (_("TCP - Transmission Control Protocol")); + gtk_widget_show (tcp_menu_item); + gtk_container_add (GTK_CONTAINER (menu3), tcp_menu_item); + + icmp_menu_item = gtk_menu_item_new_with_mnemonic (_("ICMP - Internet Control Message Protocol")); + gtk_widget_show (icmp_menu_item); + gtk_container_add (GTK_CONTAINER (menu3), icmp_menu_item); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (protocol_optionmenu), menu3); + + icmp_label = gtk_label_new_with_mnemonic (_("I_CMP-Type:")); + gtk_widget_show (icmp_label); + gtk_table_attach (GTK_TABLE (table4), icmp_label, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (icmp_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (icmp_label), 1, 0.5); + + icmp_optionmenu = gtk_option_menu_new (); + gtk_widget_show (icmp_optionmenu); + gtk_table_attach (GTK_TABLE (table4), icmp_optionmenu, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + hbox19 = gtk_hbox_new (TRUE, 5); + gtk_widget_show (hbox19); + gtk_table_attach (GTK_TABLE (table4), hbox19, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + port_spinbutton_adj = gtk_adjustment_new (65535, 1, 65535, 1, 100, 10); + port_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (port_spinbutton_adj), 5, 0); + gtk_widget_show (port_spinbutton); + gtk_box_pack_start (GTK_BOX (hbox19), port_spinbutton, TRUE, TRUE, 0); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (port_spinbutton), TRUE); + + type_label = gtk_label_new (_("www")); + gtk_widget_show (type_label); + gtk_box_pack_end (GTK_BOX (hbox19), type_label, FALSE, TRUE, 0); + gtk_label_set_use_markup (GTK_LABEL (type_label), TRUE); + gtk_label_set_justify (GTK_LABEL (type_label), GTK_JUSTIFY_LEFT); + + match_type_checkbutton = gtk_check_button_new_with_mnemonic (_("Match _type:")); + gtk_widget_show (match_type_checkbutton); + gtk_frame_set_label_widget (GTK_FRAME (frame6), match_type_checkbutton); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (match_type_checkbutton), TRUE); + + label58 = gtk_label_new (_("Type")); + gtk_widget_show (label58); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 2), label58); + gtk_label_set_justify (GTK_LABEL (label58), GTK_JUSTIFY_LEFT); + + vbox13 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox13); + gtk_container_add (GTK_CONTAINER (notebook2), vbox13); + gtk_container_set_border_width (GTK_CONTAINER (vbox13), 5); + + frame7 = gtk_frame_new (NULL); + gtk_widget_show (frame7); + gtk_box_pack_start (GTK_BOX (vbox13), frame7, FALSE, FALSE, 0); + + table5 = gtk_table_new (4, 3, FALSE); + gtk_widget_show (table5); + gtk_container_add (GTK_CONTAINER (frame7), table5); + gtk_container_set_border_width (GTK_CONTAINER (table5), 5); + gtk_table_set_row_spacings (GTK_TABLE (table5), 5); + gtk_table_set_col_spacings (GTK_TABLE (table5), 5); + + src_ip_label = gtk_label_new (_("IP-Address:")); + gtk_widget_show (src_ip_label); + gtk_table_attach (GTK_TABLE (table5), src_ip_label, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (src_ip_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (src_ip_label), 1, 0.5); + + src_ip_entry = gtk_entry_new (); + gtk_widget_show (src_ip_entry); + gtk_table_attach (GTK_TABLE (table5), src_ip_entry, 1, 3, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_entry_set_max_length (GTK_ENTRY (src_ip_entry), 15); + gtk_entry_set_text (GTK_ENTRY (src_ip_entry), _("192.168.0.1")); + + src_host_range_value_label = gtk_label_new (_("label48")); + gtk_widget_show (src_host_range_value_label); + gtk_table_attach (GTK_TABLE (table5), src_host_range_value_label, 1, 3, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_widget_set_sensitive (src_host_range_value_label, FALSE); + gtk_label_set_use_markup (GTK_LABEL (src_host_range_value_label), TRUE); + gtk_label_set_justify (GTK_LABEL (src_host_range_value_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (src_host_range_value_label), 0, 0.5); + + src_netmask_spinbutton_adj = gtk_adjustment_new (24, 0, 32, 1, 8, 10); + src_netmask_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (src_netmask_spinbutton_adj), 1, 0); + gtk_widget_show (src_netmask_spinbutton); + gtk_table_attach (GTK_TABLE (table5), src_netmask_spinbutton, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_widget_set_sensitive (src_netmask_spinbutton, FALSE); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (src_netmask_spinbutton), TRUE); + + src_netmask_label_bits = gtk_label_new (_("bits")); + gtk_widget_show (src_netmask_label_bits); + gtk_table_attach (GTK_TABLE (table5), src_netmask_label_bits, 2, 3, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_widget_set_sensitive (src_netmask_label_bits, FALSE); + gtk_label_set_justify (GTK_LABEL (src_netmask_label_bits), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (src_netmask_label_bits), 0, 0.5); + + src_host_range_label = gtk_label_new (_("Host range:")); + gtk_widget_show (src_host_range_label); + gtk_table_attach (GTK_TABLE (table5), src_host_range_label, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_widget_set_sensitive (src_host_range_label, FALSE); + gtk_label_set_justify (GTK_LABEL (src_host_range_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (src_host_range_label), 1, 0.5); + + src_netmask_checkbutton = gtk_check_button_new_with_mnemonic (_("Specify netmask")); + gtk_widget_show (src_netmask_checkbutton); + gtk_table_attach (GTK_TABLE (table5), src_netmask_checkbutton, 1, 3, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + src_netmask_label = gtk_label_new (_("Netmask:")); + gtk_widget_show (src_netmask_label); + gtk_table_attach (GTK_TABLE (table5), src_netmask_label, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (src_netmask_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (src_netmask_label), 1, 0.5); + + label74 = gtk_label_new (""); + gtk_widget_show (label74); + gtk_table_attach (GTK_TABLE (table5), label74, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (label74), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label74), 0, 0.5); + + match_source_checkbutton = gtk_check_button_new_with_mnemonic (_("Match source:")); + gtk_widget_show (match_source_checkbutton); + gtk_frame_set_label_widget (GTK_FRAME (frame7), match_source_checkbutton); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (match_source_checkbutton), TRUE); + + frame8 = gtk_frame_new (NULL); + gtk_widget_show (frame8); + gtk_box_pack_start (GTK_BOX (vbox13), frame8, FALSE, FALSE, 0); + + table6 = gtk_table_new (4, 3, FALSE); + gtk_widget_show (table6); + gtk_container_add (GTK_CONTAINER (frame8), table6); + gtk_container_set_border_width (GTK_CONTAINER (table6), 5); + gtk_table_set_row_spacings (GTK_TABLE (table6), 5); + gtk_table_set_col_spacings (GTK_TABLE (table6), 5); + + dst_ip_label = gtk_label_new (_("IP-Address:")); + gtk_widget_show (dst_ip_label); + gtk_table_attach (GTK_TABLE (table6), dst_ip_label, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dst_ip_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (dst_ip_label), 1, 0.5); + + dst_ip_entry = gtk_entry_new (); + gtk_widget_show (dst_ip_entry); + gtk_table_attach (GTK_TABLE (table6), dst_ip_entry, 1, 3, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_entry_set_max_length (GTK_ENTRY (dst_ip_entry), 15); + gtk_entry_set_text (GTK_ENTRY (dst_ip_entry), _("192.168.0.1")); + + dst_host_range_label = gtk_label_new (_("Host range:")); + gtk_widget_show (dst_host_range_label); + gtk_table_attach (GTK_TABLE (table6), dst_host_range_label, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dst_host_range_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (dst_host_range_label), 1, 0.5); + + dst_netmask_spinbutton_adj = gtk_adjustment_new (24, 0, 32, 1, 10, 10); + dst_netmask_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (dst_netmask_spinbutton_adj), 1, 0); + gtk_widget_show (dst_netmask_spinbutton); + gtk_table_attach (GTK_TABLE (table6), dst_netmask_spinbutton, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + dst_netmask_label_bits = gtk_label_new (_("bits")); + gtk_widget_show (dst_netmask_label_bits); + gtk_table_attach (GTK_TABLE (table6), dst_netmask_label_bits, 2, 3, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dst_netmask_label_bits), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (dst_netmask_label_bits), 0, 0.5); + + dst_host_range_value_label = gtk_label_new (_("label50")); + gtk_widget_show (dst_host_range_value_label); + gtk_table_attach (GTK_TABLE (table6), dst_host_range_value_label, 1, 3, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_use_markup (GTK_LABEL (dst_host_range_value_label), TRUE); + gtk_label_set_justify (GTK_LABEL (dst_host_range_value_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (dst_host_range_value_label), 0, 0.5); + + dst_netmask_checkbutton = gtk_check_button_new_with_mnemonic (_("Specify netmask")); + gtk_widget_show (dst_netmask_checkbutton); + gtk_table_attach (GTK_TABLE (table6), dst_netmask_checkbutton, 1, 3, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + label75 = gtk_label_new (""); + gtk_widget_show (label75); + gtk_table_attach (GTK_TABLE (table6), label75, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (label75), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label75), 0, 0.5); + + dst_netmask_label = gtk_label_new (_("Netmask:")); + gtk_widget_show (dst_netmask_label); + gtk_table_attach (GTK_TABLE (table6), dst_netmask_label, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (dst_netmask_label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (dst_netmask_label), 1, 0.5); + + match_destination_checkbutton = gtk_check_button_new_with_mnemonic (_("Match destination:")); + gtk_widget_show (match_destination_checkbutton); + gtk_frame_set_label_widget (GTK_FRAME (frame8), match_destination_checkbutton); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (match_destination_checkbutton), TRUE); + + frame9 = gtk_frame_new (NULL); + gtk_widget_show (frame9); + gtk_box_pack_start (GTK_BOX (vbox13), frame9, FALSE, FALSE, 0); + + vbox14 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox14); + gtk_container_add (GTK_CONTAINER (frame9), vbox14); + gtk_container_set_border_width (GTK_CONTAINER (vbox14), 5); + + bc_dont_match_radiobutton = gtk_radio_button_new_with_mnemonic (NULL, _("Don't match")); + gtk_widget_show (bc_dont_match_radiobutton); + gtk_box_pack_start (GTK_BOX (vbox14), bc_dont_match_radiobutton, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (bc_dont_match_radiobutton), bc_dont_match_radiobutton_group); + bc_dont_match_radiobutton_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (bc_dont_match_radiobutton)); + + bc_match_broadcast_radiobutton = gtk_radio_button_new_with_mnemonic (NULL, _("Match broadcast")); + gtk_widget_show (bc_match_broadcast_radiobutton); + gtk_box_pack_start (GTK_BOX (vbox14), bc_match_broadcast_radiobutton, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (bc_match_broadcast_radiobutton), bc_dont_match_radiobutton_group); + bc_dont_match_radiobutton_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (bc_match_broadcast_radiobutton)); + + bc_match_unicast_radiobutton = gtk_radio_button_new_with_mnemonic (NULL, _("Match unicast")); + gtk_widget_show (bc_match_unicast_radiobutton); + gtk_box_pack_start (GTK_BOX (vbox14), bc_match_unicast_radiobutton, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (bc_match_unicast_radiobutton), bc_dont_match_radiobutton_group); + bc_dont_match_radiobutton_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (bc_match_unicast_radiobutton)); + + label41 = gtk_label_new (_("Broadcast:")); + gtk_widget_show (label41); + gtk_frame_set_label_widget (GTK_FRAME (frame9), label41); + gtk_label_set_justify (GTK_LABEL (label41), GTK_JUSTIFY_LEFT); + + label59 = gtk_label_new (_("Addresses")); + gtk_widget_show (label59); + gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), 3), label59); + gtk_label_set_justify (GTK_LABEL (label59), GTK_JUSTIFY_LEFT); + + hbuttonbox3 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox11), hbuttonbox3, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox3), 5); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox3), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX (hbuttonbox3), 5); + + ok_button = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (ok_button); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), ok_button); + GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT); + + cancel_button = gtk_button_new_from_stock ("gtk-cancel"); + gtk_widget_show (cancel_button); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), cancel_button); + GTK_WIDGET_SET_FLAGS (cancel_button, GTK_CAN_DEFAULT); + + g_signal_connect_swapped ((gpointer) rule_window, "delete_event", + G_CALLBACK (on_rule_window_delete_event), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) desc_entry, "changed", + G_CALLBACK (on_desc_entry_changed), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) direction_optionmenu, "changed", + G_CALLBACK (on_direction_optionmenu_changed), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) match_direction_checkbutton, "toggled", + G_CALLBACK (on_match_direction_checkbutton_toggled), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) match_interfaces_checkbutton, "toggled", + G_CALLBACK (on_match_interfaces_checkbutton_toggled), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) protocol_optionmenu, "changed", + G_CALLBACK (on_protocol_optionmenu_changed), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) port_spinbutton, "value_changed", + G_CALLBACK (on_port_spinbutton_value_changed), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) match_type_checkbutton, "toggled", + G_CALLBACK (on_match_type_checkbutton_toggled), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) src_ip_entry, "changed", + G_CALLBACK (on_src_ip_entry_changed), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) src_netmask_spinbutton, "value_changed", + G_CALLBACK (on_src_netmask_spinbutton_value_changed), + GTK_OBJECT (rule_window)); + g_signal_connect ((gpointer) src_netmask_checkbutton, "toggled", + G_CALLBACK (on_src_netmask_checkbutton_toggled), + NULL); + g_signal_connect_swapped ((gpointer) match_source_checkbutton, "toggled", + G_CALLBACK (on_match_source_checkbutton_toggled), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) dst_ip_entry, "changed", + G_CALLBACK (on_dst_ip_entry_changed), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) dst_netmask_spinbutton, "value_changed", + G_CALLBACK (on_dst_netmask_spinbutton_value_changed), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) dst_netmask_checkbutton, "toggled", + G_CALLBACK (on_dst_netmask_checkbutton_toggled), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) match_destination_checkbutton, "toggled", + G_CALLBACK (on_match_destination_checkbutton_toggled), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) bc_dont_match_radiobutton, "toggled", + G_CALLBACK (on_bc_radiobutton_toggled), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) bc_match_broadcast_radiobutton, "toggled", + G_CALLBACK (on_bc_radiobutton_toggled), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) bc_match_unicast_radiobutton, "toggled", + G_CALLBACK (on_bc_radiobutton_toggled), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) ok_button, "clicked", + G_CALLBACK (on_ok_button_clicked), + GTK_OBJECT (rule_window)); + g_signal_connect_swapped ((gpointer) cancel_button, "clicked", + G_CALLBACK (on_cancel_button_clicked), + GTK_OBJECT (rule_window)); + + gtk_label_set_mnemonic_widget (GTK_LABEL (incoming_label), combo_entry3); + gtk_label_set_mnemonic_widget (GTK_LABEL (outgoing_label), combo_entry2); + gtk_label_set_mnemonic_widget (GTK_LABEL (protocol_label), protocol_optionmenu); + gtk_label_set_mnemonic_widget (GTK_LABEL (icmp_label), icmp_optionmenu); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (rule_window, rule_window, "rule_window"); + GLADE_HOOKUP_OBJECT (rule_window, vbox11, "vbox11"); + GLADE_HOOKUP_OBJECT (rule_window, desc_eventbox, "desc_eventbox"); + GLADE_HOOKUP_OBJECT (rule_window, desc_label, "desc_label"); + GLADE_HOOKUP_OBJECT (rule_window, hseparator2, "hseparator2"); + GLADE_HOOKUP_OBJECT (rule_window, notebook2, "notebook2"); + GLADE_HOOKUP_OBJECT (rule_window, vbox12, "vbox12"); + GLADE_HOOKUP_OBJECT (rule_window, label60, "label60"); + GLADE_HOOKUP_OBJECT (rule_window, desc_entry, "desc_entry"); + GLADE_HOOKUP_OBJECT (rule_window, label72, "label72"); + GLADE_HOOKUP_OBJECT (rule_window, rule_optionmenu, "rule_optionmenu"); + GLADE_HOOKUP_OBJECT (rule_window, menu5, "menu5"); + GLADE_HOOKUP_OBJECT (rule_window, imagemenuitem1, "imagemenuitem1"); + GLADE_HOOKUP_OBJECT (rule_window, image110, "image110"); + GLADE_HOOKUP_OBJECT (rule_window, imagemenuitem2, "imagemenuitem2"); + GLADE_HOOKUP_OBJECT (rule_window, image111, "image111"); + GLADE_HOOKUP_OBJECT (rule_window, imagemenuitem3, "imagemenuitem3"); + GLADE_HOOKUP_OBJECT (rule_window, image112, "image112"); + GLADE_HOOKUP_OBJECT (rule_window, imagemenuitem4, "imagemenuitem4"); + GLADE_HOOKUP_OBJECT (rule_window, image113, "image113"); + GLADE_HOOKUP_OBJECT (rule_window, label56, "label56"); + GLADE_HOOKUP_OBJECT (rule_window, vbox16, "vbox16"); + GLADE_HOOKUP_OBJECT (rule_window, frame4, "frame4"); + GLADE_HOOKUP_OBJECT (rule_window, hbox18, "hbox18"); + GLADE_HOOKUP_OBJECT (rule_window, direction_label, "direction_label"); + GLADE_HOOKUP_OBJECT (rule_window, direction_optionmenu, "direction_optionmenu"); + GLADE_HOOKUP_OBJECT (rule_window, menu4, "menu4"); + GLADE_HOOKUP_OBJECT (rule_window, incoming_menu_item, "incoming_menu_item"); + GLADE_HOOKUP_OBJECT (rule_window, image37, "image37"); + GLADE_HOOKUP_OBJECT (rule_window, outgoing_menu_item, "outgoing_menu_item"); + GLADE_HOOKUP_OBJECT (rule_window, image38, "image38"); + GLADE_HOOKUP_OBJECT (rule_window, passing_menu_item, "passing_menu_item"); + GLADE_HOOKUP_OBJECT (rule_window, match_direction_checkbutton, "match_direction_checkbutton"); + GLADE_HOOKUP_OBJECT (rule_window, frame5, "frame5"); + GLADE_HOOKUP_OBJECT (rule_window, table3, "table3"); + GLADE_HOOKUP_OBJECT (rule_window, incoming_label, "incoming_label"); + GLADE_HOOKUP_OBJECT (rule_window, outgoing_label, "outgoing_label"); + GLADE_HOOKUP_OBJECT (rule_window, outgoing_combo, "outgoing_combo"); + GLADE_HOOKUP_OBJECT (rule_window, combo_entry2, "combo_entry2"); + GLADE_HOOKUP_OBJECT (rule_window, incoming_combo, "incoming_combo"); + GLADE_HOOKUP_OBJECT (rule_window, combo_entry3, "combo_entry3"); + GLADE_HOOKUP_OBJECT (rule_window, match_interfaces_checkbutton, "match_interfaces_checkbutton"); + GLADE_HOOKUP_OBJECT (rule_window, label57, "label57"); + GLADE_HOOKUP_OBJECT (rule_window, vbox17, "vbox17"); + GLADE_HOOKUP_OBJECT (rule_window, frame6, "frame6"); + GLADE_HOOKUP_OBJECT (rule_window, table4, "table4"); + GLADE_HOOKUP_OBJECT (rule_window, protocol_label, "protocol_label"); + GLADE_HOOKUP_OBJECT (rule_window, port_label, "port_label"); + GLADE_HOOKUP_OBJECT (rule_window, protocol_optionmenu, "protocol_optionmenu"); + GLADE_HOOKUP_OBJECT (rule_window, menu3, "menu3"); + GLADE_HOOKUP_OBJECT (rule_window, udp_menu_item, "udp_menu_item"); + GLADE_HOOKUP_OBJECT (rule_window, tcp_menu_item, "tcp_menu_item"); + GLADE_HOOKUP_OBJECT (rule_window, icmp_menu_item, "icmp_menu_item"); + GLADE_HOOKUP_OBJECT (rule_window, icmp_label, "icmp_label"); + GLADE_HOOKUP_OBJECT (rule_window, icmp_optionmenu, "icmp_optionmenu"); + GLADE_HOOKUP_OBJECT (rule_window, hbox19, "hbox19"); + GLADE_HOOKUP_OBJECT (rule_window, port_spinbutton, "port_spinbutton"); + GLADE_HOOKUP_OBJECT (rule_window, type_label, "type_label"); + GLADE_HOOKUP_OBJECT (rule_window, match_type_checkbutton, "match_type_checkbutton"); + GLADE_HOOKUP_OBJECT (rule_window, label58, "label58"); + GLADE_HOOKUP_OBJECT (rule_window, vbox13, "vbox13"); + GLADE_HOOKUP_OBJECT (rule_window, frame7, "frame7"); + GLADE_HOOKUP_OBJECT (rule_window, table5, "table5"); + GLADE_HOOKUP_OBJECT (rule_window, src_ip_label, "src_ip_label"); + GLADE_HOOKUP_OBJECT (rule_window, src_ip_entry, "src_ip_entry"); + GLADE_HOOKUP_OBJECT (rule_window, src_host_range_value_label, "src_host_range_value_label"); + GLADE_HOOKUP_OBJECT (rule_window, src_netmask_spinbutton, "src_netmask_spinbutton"); + GLADE_HOOKUP_OBJECT (rule_window, src_netmask_label_bits, "src_netmask_label_bits"); + GLADE_HOOKUP_OBJECT (rule_window, src_host_range_label, "src_host_range_label"); + GLADE_HOOKUP_OBJECT (rule_window, src_netmask_checkbutton, "src_netmask_checkbutton"); + GLADE_HOOKUP_OBJECT (rule_window, src_netmask_label, "src_netmask_label"); + GLADE_HOOKUP_OBJECT (rule_window, label74, "label74"); + GLADE_HOOKUP_OBJECT (rule_window, match_source_checkbutton, "match_source_checkbutton"); + GLADE_HOOKUP_OBJECT (rule_window, frame8, "frame8"); + GLADE_HOOKUP_OBJECT (rule_window, table6, "table6"); + GLADE_HOOKUP_OBJECT (rule_window, dst_ip_label, "dst_ip_label"); + GLADE_HOOKUP_OBJECT (rule_window, dst_ip_entry, "dst_ip_entry"); + GLADE_HOOKUP_OBJECT (rule_window, dst_host_range_label, "dst_host_range_label"); + GLADE_HOOKUP_OBJECT (rule_window, dst_netmask_spinbutton, "dst_netmask_spinbutton"); + GLADE_HOOKUP_OBJECT (rule_window, dst_netmask_label_bits, "dst_netmask_label_bits"); + GLADE_HOOKUP_OBJECT (rule_window, dst_host_range_value_label, "dst_host_range_value_label"); + GLADE_HOOKUP_OBJECT (rule_window, dst_netmask_checkbutton, "dst_netmask_checkbutton"); + GLADE_HOOKUP_OBJECT (rule_window, label75, "label75"); + GLADE_HOOKUP_OBJECT (rule_window, dst_netmask_label, "dst_netmask_label"); + GLADE_HOOKUP_OBJECT (rule_window, match_destination_checkbutton, "match_destination_checkbutton"); + GLADE_HOOKUP_OBJECT (rule_window, frame9, "frame9"); + GLADE_HOOKUP_OBJECT (rule_window, vbox14, "vbox14"); + GLADE_HOOKUP_OBJECT (rule_window, bc_dont_match_radiobutton, "bc_dont_match_radiobutton"); + GLADE_HOOKUP_OBJECT (rule_window, bc_match_broadcast_radiobutton, "bc_match_broadcast_radiobutton"); + GLADE_HOOKUP_OBJECT (rule_window, bc_match_unicast_radiobutton, "bc_match_unicast_radiobutton"); + GLADE_HOOKUP_OBJECT (rule_window, label41, "label41"); + GLADE_HOOKUP_OBJECT (rule_window, label59, "label59"); + GLADE_HOOKUP_OBJECT (rule_window, hbuttonbox3, "hbuttonbox3"); + GLADE_HOOKUP_OBJECT (rule_window, ok_button, "ok_button"); + GLADE_HOOKUP_OBJECT (rule_window, cancel_button, "cancel_button"); + + gtk_widget_grab_focus (ok_button); + gtk_widget_grab_default (ok_button); + return rule_window; +} + +GtkWidget* +create_wait_window (void) +{ + GtkWidget *wait_window; + GtkWidget *hbox20; + GtkWidget *image39; + GtkWidget *label61; + + wait_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (wait_window), _("Firewall Update")); + gtk_window_set_position (GTK_WINDOW (wait_window), GTK_WIN_POS_CENTER); + gtk_window_set_modal (GTK_WINDOW (wait_window), TRUE); + gtk_window_set_resizable (GTK_WINDOW (wait_window), FALSE); + + hbox20 = gtk_hbox_new (FALSE, 10); + gtk_widget_show (hbox20); + gtk_container_add (GTK_CONTAINER (wait_window), hbox20); + gtk_container_set_border_width (GTK_CONTAINER (hbox20), 10); + + image39 = gtk_image_new_from_stock ("gtk-dialog-info", GTK_ICON_SIZE_DIALOG); + gtk_widget_show (image39); + gtk_box_pack_start (GTK_BOX (hbox20), image39, FALSE, FALSE, 0); + + label61 = gtk_label_new (_("Please be patient while the firewall is installed...\nThank you!")); + gtk_widget_show (label61); + gtk_box_pack_start (GTK_BOX (hbox20), label61, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (label61, GTK_CAN_FOCUS); + gtk_label_set_use_markup (GTK_LABEL (label61), TRUE); + gtk_label_set_selectable (GTK_LABEL (label61), TRUE); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (wait_window, wait_window, "wait_window"); + GLADE_HOOKUP_OBJECT (wait_window, hbox20, "hbox20"); + GLADE_HOOKUP_OBJECT (wait_window, image39, "image39"); + GLADE_HOOKUP_OBJECT (wait_window, label61, "label61"); + + return wait_window; +} + +GtkWidget* +create_advanced_window (void) +{ + GtkWidget *advanced_window; + GtkWidget *vbox20; + GtkWidget *frame3; + GtkWidget *vbox22; + GtkWidget *hbox16; + GtkWidget *label34; + GtkWidget *icmp_option_menu; + GtkWidget *menu2; + GtkWidget *tcp_rst_check_button; + GtkWidget *label37; + GtkWidget *hbuttonbox5; + GtkWidget *close_button; + + advanced_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (advanced_window), _("Advanced")); + gtk_window_set_resizable (GTK_WINDOW (advanced_window), FALSE); + + vbox20 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox20); + gtk_container_add (GTK_CONTAINER (advanced_window), vbox20); + gtk_container_set_border_width (GTK_CONTAINER (vbox20), 5); + + frame3 = gtk_frame_new (NULL); + gtk_widget_show (frame3); + gtk_box_pack_start (GTK_BOX (vbox20), frame3, FALSE, TRUE, 0); + + vbox22 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox22); + gtk_container_add (GTK_CONTAINER (frame3), vbox22); + gtk_container_set_border_width (GTK_CONTAINER (vbox22), 5); + + hbox16 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox16); + gtk_box_pack_start (GTK_BOX (vbox22), hbox16, TRUE, TRUE, 0); + + label34 = gtk_label_new_with_mnemonic (_("Reject with _ICMP-Code:")); + gtk_widget_show (label34); + gtk_box_pack_start (GTK_BOX (hbox16), label34, FALSE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (label34), GTK_JUSTIFY_LEFT); + + icmp_option_menu = gtk_option_menu_new (); + gtk_widget_show (icmp_option_menu); + gtk_box_pack_start (GTK_BOX (hbox16), icmp_option_menu, TRUE, TRUE, 0); + + menu2 = gtk_menu_new (); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (icmp_option_menu), menu2); + + tcp_rst_check_button = gtk_check_button_new_with_mnemonic (_("Reject TCP connections with RST-Flag")); + gtk_widget_show (tcp_rst_check_button); + gtk_box_pack_start (GTK_BOX (vbox22), tcp_rst_check_button, FALSE, FALSE, 0); + + label37 = gtk_label_new (_("Rejected connections")); + gtk_widget_show (label37); + gtk_frame_set_label_widget (GTK_FRAME (frame3), label37); + gtk_label_set_use_markup (GTK_LABEL (label37), TRUE); + gtk_label_set_justify (GTK_LABEL (label37), GTK_JUSTIFY_LEFT); + + hbuttonbox5 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox5); + gtk_box_pack_start (GTK_BOX (vbox20), hbuttonbox5, TRUE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox5), GTK_BUTTONBOX_END); + + close_button = gtk_button_new_from_stock ("gtk-close"); + gtk_widget_show (close_button); + gtk_container_add (GTK_CONTAINER (hbuttonbox5), close_button); + GTK_WIDGET_SET_FLAGS (close_button, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) advanced_window, "delete_event", + G_CALLBACK (on_advanced_window_delete_event), + NULL); + g_signal_connect ((gpointer) icmp_option_menu, "changed", + G_CALLBACK (on_icmp_option_menu_changed), + NULL); + g_signal_connect ((gpointer) tcp_rst_check_button, "toggled", + G_CALLBACK (on_tcp_rst_check_button_toggled), + NULL); + g_signal_connect ((gpointer) close_button, "clicked", + G_CALLBACK (on_close_button_clicked), + NULL); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label34), icmp_option_menu); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (advanced_window, advanced_window, "advanced_window"); + GLADE_HOOKUP_OBJECT (advanced_window, vbox20, "vbox20"); + GLADE_HOOKUP_OBJECT (advanced_window, frame3, "frame3"); + GLADE_HOOKUP_OBJECT (advanced_window, vbox22, "vbox22"); + GLADE_HOOKUP_OBJECT (advanced_window, hbox16, "hbox16"); + GLADE_HOOKUP_OBJECT (advanced_window, label34, "label34"); + GLADE_HOOKUP_OBJECT (advanced_window, icmp_option_menu, "icmp_option_menu"); + GLADE_HOOKUP_OBJECT (advanced_window, menu2, "menu2"); + GLADE_HOOKUP_OBJECT (advanced_window, tcp_rst_check_button, "tcp_rst_check_button"); + GLADE_HOOKUP_OBJECT (advanced_window, label37, "label37"); + GLADE_HOOKUP_OBJECT (advanced_window, hbuttonbox5, "hbuttonbox5"); + GLADE_HOOKUP_OBJECT (advanced_window, close_button, "close_button"); + + return advanced_window; +} + diff --git a/client/interface.h b/client/interface.h new file mode 100644 index 0000000..8acfac5 --- /dev/null +++ b/client/interface.h @@ -0,0 +1,9 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_connection_window (void); +GtkWidget* create_main_window (void); +GtkWidget* create_rule_window (void); +GtkWidget* create_wait_window (void); +GtkWidget* create_advanced_window (void); diff --git a/client/log.c b/client/log.c new file mode 100644 index 0000000..86b6e4a --- /dev/null +++ b/client/log.c @@ -0,0 +1,71 @@ +#include "mainwin.h" +#include "support.h" + +#include "log.h" + +static GtkListStore *log_list_store = NULL; +enum { COLUMN_TIME, COLUMN_TYPE, COLUMN_SOURCE, COLUMN_DESTINATION, COLUMN_DECISION, N_COLUMNS }; + +void log_widget_init() { + GtkTreeView *tv = GTK_TREE_VIEW(lookup_widget(get_main_window(), "log_view")); + + log_list_store = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + gtk_tree_view_set_model(tv, GTK_TREE_MODEL(log_list_store)); + + gtk_tree_view_append_column(tv, gtk_tree_view_column_new_with_attributes("Time", gtk_cell_renderer_text_new(), "text", COLUMN_TIME, NULL)); + gtk_tree_view_append_column(tv, gtk_tree_view_column_new_with_attributes("Type", gtk_cell_renderer_text_new(), "text", COLUMN_TYPE, NULL)); + gtk_tree_view_append_column(tv, gtk_tree_view_column_new_with_attributes("Source", gtk_cell_renderer_text_new(), "text", COLUMN_SOURCE, NULL)); + gtk_tree_view_append_column(tv, gtk_tree_view_column_new_with_attributes("Destination", gtk_cell_renderer_text_new(), "text", COLUMN_DESTINATION, NULL)); + gtk_tree_view_append_column(tv, gtk_tree_view_column_new_with_attributes("Decision", gtk_cell_renderer_text_new(), "text", COLUMN_DECISION, NULL)); +} + + +void log_widget_append(conn_info_t *ci) { + gtk_list_store_append(log_list_store, &ci->iter); + gtk_list_store_set(log_list_store, &ci->iter, + COLUMN_TIME, ci->timestamp_string, + COLUMN_TYPE, ci->type_string, + COLUMN_SOURCE, ci->from_string, + COLUMN_DESTINATION, ci->to_string, + COLUMN_DECISION, "outstanding...", + -1); + + log_widget_cut(); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(get_main_window(), "autoscroll_button")))) { + GtkTreeView *tv = GTK_TREE_VIEW(lookup_widget(get_main_window(), "log_view")); + GtkTreePath *path; + + path = gtk_tree_model_get_path(gtk_tree_view_get_model(tv), &ci->iter); + gtk_tree_view_set_cursor(tv, path, NULL, FALSE); + gtk_tree_view_scroll_to_cell(tv, path, NULL, TRUE, .5, 0); + gtk_tree_path_free(path); + } +} + +void log_widget_verdict(conn_info_t *ci, verdict_t v) { + gtk_list_store_set(log_list_store, &ci->iter, + COLUMN_DECISION, v == VERDICT_REJECT ? "REJECTED" : (v == VERDICT_DROP ? "DROPPPED" : "ACCEPTED"), + -1); +} + +void log_widget_clear() { + gtk_list_store_clear(log_list_store); +} + + +void log_widget_cut() { + gfloat m = gtk_spin_button_get_value(GTK_SPIN_BUTTON(lookup_widget(get_main_window(), "log_spinbutton"))); + + if (m < 10) + m = 10; + + while (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(log_list_store), NULL) > m) { + GtkTreeIter iter; + if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(log_list_store), &iter)) + return; + + gtk_list_store_remove(log_list_store, &iter); + } + +} diff --git a/client/log.h b/client/log.h new file mode 100644 index 0000000..3b34bcd --- /dev/null +++ b/client/log.h @@ -0,0 +1,12 @@ +#ifndef foologhfoo +#define foologhfoo + +#include "connection.h" + +void log_widget_init(); +void log_widget_append(conn_info_t *ci); +void log_widget_verdict(conn_info_t *ci, verdict_t v); +void log_widget_clear(); +void log_widget_cut(); + +#endif diff --git a/client/main.c b/client/main.c new file mode 100644 index 0000000..da8ce1a --- /dev/null +++ b/client/main.c @@ -0,0 +1,55 @@ +#include +#include + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "interface.h" +#include "support.h" +#include "connection.h" +#include "daemon.h" +#include "mainwin.h" +#include "ruleset.h" + +int main (int argc, char *argv[]) { + mtrace(); + +#ifdef ENABLE_NLS + bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); +#endif + + gtk_set_locale(); + gtk_init(&argc, &argv); + + add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); + + if (daemon_init() < 0) + goto finish; + + if (ruleset_init() < 0) + goto finish; + + if (ruleset_initial_load() < 0) + goto finish; + + if (ruleset_commit() < 0) + goto finish; + + mainwin_show(); + gtk_main (); + +finish: + ruleset_done(); + daemon_done(); + + //syscall(SYS_exit, 0); + + return 0; +} + + diff --git a/client/main.h b/client/main.h new file mode 100644 index 0000000..4b0e011 --- /dev/null +++ b/client/main.h @@ -0,0 +1,7 @@ +#ifndef foomainhfoo +#define foomainhfoo + +typedef enum verdict { VERDICT_QUERY, VERDICT_ACCEPT, VERDICT_REJECT, VERDICT_DROP } verdict_t; +typedef enum conn_direction { DIR_INCOMING, DIR_OUTGOING, DIR_PASSING } conn_direction_t; + +#endif diff --git a/client/mainwin.c b/client/mainwin.c new file mode 100644 index 0000000..e8189ef --- /dev/null +++ b/client/mainwin.c @@ -0,0 +1,52 @@ +#include +#include + +#include "mainwin.h" +#include "interface.h" +#include "support.h" +#include "connection.h" +#include "log.h" +#include "ruleset.h" +#include "format.h" +#include "advancedwin.h" + +GtkWidget* get_main_window(void) { + static GtkWidget *mw = NULL; + + if (!mw) { + GdkColor color; + mw = create_main_window(); + gdk_color_parse ("black", &color); + gtk_widget_modify_bg(lookup_widget(mw, "title_eventbox"), GTK_STATE_NORMAL, &color); + log_widget_init(); + ruleset_widget_init(); + + gtk_label_set_label(GTK_LABEL(lookup_widget(mw, "version_label")), "Version "VERSION""); + } + + return mw; +} + +void mainwin_show() { + gtk_widget_show_all(get_main_window()); +} + +void mainwin_update_status_bar() { + GtkStatusbar *s; + static guint ctx = (guint) -1; + static gchar txt[256]; + + s = GTK_STATUSBAR(lookup_widget(get_main_window(), "statusbar")); + + if (ctx == (guint) -1) + ctx = gtk_statusbar_get_context_id(s, "Recieved packets"); + else + gtk_statusbar_pop(s, ctx); + + if (queued_conn_count || conn_current) + snprintf(txt, sizeof(txt), "Recieved %u packets, %u oustanding", total_conn_count, queued_conn_count + (conn_current ? 1 : 0)); + else + snprintf(txt, sizeof(txt), "Recieved %u packets", total_conn_count); + + gtk_statusbar_push(s, ctx, txt); +} diff --git a/client/mainwin.h b/client/mainwin.h new file mode 100644 index 0000000..dc49fe8 --- /dev/null +++ b/client/mainwin.h @@ -0,0 +1,12 @@ +#ifndef foomainwinhfoo +#define foomainwinhfoo + +#include + +#include "connection.h" + +GtkWidget* get_main_window(void); +void mainwin_show(); +void mainwin_update_status_bar(); + +#endif diff --git a/client/rule.c b/client/rule.c new file mode 100644 index 0000000..60c7081 --- /dev/null +++ b/client/rule.c @@ -0,0 +1,318 @@ +#include +#include +#include +#include + +#include "rule.h" +#include "format.h" + +static int id = 0; + +rule_t* rule_new() { + rule_t* rule = g_new0(rule_t, 1); + + rule->enabled = TRUE; + rule->realized = FALSE; + rule->match = 0; + + rule->direction = DIR_OUTGOING; + rule->src_netmask_bits = 32; + rule->dst_netmask_bits = 32; + + rule->id = id++; + + //g_message("allocated rule %u", rule->id); + + return rule; +} + +void rule_free(rule_t *rule) { + //g_message("freed rule %u", rule->id); + + if (rule->being_edited) + g_message("WARNING! Rule being currently edited is freed!"); + g_free(rule); +} + +rule_t* rule_new_from_conn_info(conn_info_t *ci) { + rule_t *rule = rule_new(); + g_assert(ci); + + rule->enabled = TRUE; + rule->realized = FALSE; + rule->match = MATCH_DIRECTION | MATCH_TYPE; + + strncpy(rule->description, ci->type_string, sizeof(rule->description)); + strncpy(rule->device_in, ci->device_in, IFNAMSIZ); + strncpy(rule->device_out, ci->device_out, IFNAMSIZ); + + rule->protocol = ci->protocol; + rule->port = ci->port; + rule->icmp_type = ci->icmp_type; + rule->direction = ci->direction; + + rule->src_ip_address = ci->src_ip_address; + rule->dst_ip_address = ci->dst_ip_address; + + rule->src_netmask_bits = 32; + rule->dst_netmask_bits = 32; + + if (ci->broadcast) + rule->match |= MATCH_BROADCAST; + + if (ci->direction == DIR_INCOMING) + rule->match |= MATCH_SOURCE; + + if (ci->direction == DIR_OUTGOING) + rule->match |= MATCH_DESTINATION; + + if (ci->direction == DIR_PASSING) + rule->match |= MATCH_DESTINATION|MATCH_SOURCE; + + return rule; +} + +rule_t* rule_new_from_xml(xmlDocPtr doc, xmlNodePtr node) { + rule_t *rule = rule_new(); + xmlChar *text = NULL; + + rule->match = 0; + rule->enabled = TRUE; + rule->realized = TRUE; + + for (node = node->xmlChildrenNode; node; node = node->next) { + + if (node->type == XML_TEXT_NODE) + continue; + + if (node->type != XML_ELEMENT_NODE) + goto finish; + + text = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + + if (!xmlStrcmp(node->name, "description")) + g_strlcpy(rule->description, text, sizeof(rule->description)); + else if (!xmlStrcmp(node->name, "direction")) { + rule->match |= MATCH_DIRECTION; + + if (!xmlStrcmp(text, "incoming")) + rule->direction = DIR_INCOMING; + else if (!xmlStrcmp(text, "outgoing")) + rule->direction = DIR_OUTGOING; + else if (!xmlStrcmp(text, "passing")) + rule->direction = DIR_PASSING; + else + goto finish; + + } else if (!xmlStrcmp(node->name, "protocol")) { + rule->match |= MATCH_TYPE; + + if (!xmlStrcmp(text, "udp")) + rule->protocol = IPPROTO_UDP; + else if (!xmlStrcmp(text, "tcp")) + rule->protocol = IPPROTO_TCP; + else if (!xmlStrcmp(text, "tcp")) + rule->protocol = IPPROTO_ICMP; + else + goto finish; + + } else if (!xmlStrcmp(node->name, "destination-port")) { + rule->match |= MATCH_TYPE; + rule->port = atoi(text); + } else if (!xmlStrcmp(node->name, "icmp-type")) { + rule->match |= MATCH_TYPE; + rule->icmp_type = atoi(text); + } else if (!xmlStrcmp(node->name, "source")) { + rule->match |= MATCH_SOURCE; + if (!inet_aton(text, (struct in_addr*) &rule->src_ip_address)) + goto finish; + } else if (!xmlStrcmp(node->name, "destination")) { + rule->match |= MATCH_DESTINATION; + if (!inet_aton(text, (struct in_addr*) &rule->dst_ip_address)) + goto finish; + } else if (!xmlStrcmp(node->name, "input-device")) { + rule->match |= MATCH_INTERFACES; + g_strlcpy(rule->device_in, text, sizeof(rule->device_in)); + } else if (!xmlStrcmp(node->name, "output-device")) { + rule->match |= MATCH_INTERFACES; + g_strlcpy(rule->device_out, text, sizeof(rule->device_out)); + } else if (!xmlStrcmp(node->name, "source-netmask-bits")) { + rule->src_netmask_bits = atoi(text); + } else if (!xmlStrcmp(node->name, "destination-netmask-bits")) { + rule->dst_netmask_bits = atoi(text); + } else if (!xmlStrcmp(node->name, "broadcast")) { + rule->match |= MATCH_BROADCAST; + rule->match &= ~MATCH_UNICAST; + } else if (!xmlStrcmp(node->name, "unicast")) { + rule->match |= MATCH_UNICAST; + rule->match &= ~MATCH_BROADCAST; + } else if (!xmlStrcmp(node->name, "target")) { + + if (!xmlStrcmp(text, "drop")) + rule->verdict = VERDICT_DROP; + else if (!xmlStrcmp(text, "reject")) + rule->verdict = VERDICT_REJECT; + else if (!xmlStrcmp(text, "accept")) + rule->verdict = VERDICT_ACCEPT; + else if (!xmlStrcmp(text, "query") || !xmlStrcmp(text, "ask")) + rule->verdict = VERDICT_QUERY; + else + goto finish; + } else if (!xmlStrcmp(node->name, "disabled")) { + rule->enabled = FALSE; + } else + goto finish; + + if (text) + xmlFree(text); + text = NULL; + } + + return rule; + +finish: + if (text) + xmlFree(text); + + rule_free(rule); + return NULL; +} + + +gchar* rule_match_string(rule_t* rule) { + static char txt[256], txt2[256]; + guint l; + g_assert(rule); + + txt[0] = 0; + + if (rule->match & MATCH_DIRECTION) { + switch (rule->direction) { + case DIR_INCOMING: g_strlcat(txt, "incoming; ", sizeof(txt)); break; + case DIR_OUTGOING: g_strlcat(txt, "outgoing; ", sizeof(txt)); break; + case DIR_PASSING: g_strlcat(txt, "passing; ", sizeof(txt)); break; + } + + if (rule->match & MATCH_INTERFACES) { + if (rule->direction == DIR_INCOMING) + snprintf(txt2, sizeof(txt2), "device %s; ", rule->device_in); + else if (rule->direction == DIR_OUTGOING) + snprintf(txt2, sizeof(txt2), "device %s; ", rule->device_out); + else + snprintf(txt2, sizeof(txt2), "devices %s to %s; ", rule->device_in, rule->device_out); + + g_strlcat(txt, txt2, sizeof(txt)); + } + } + + if (rule->match & MATCH_TYPE) { + if (rule->protocol == IPPROTO_ICMP) + snprintf(txt2, sizeof(txt2), "protocol ICMP; type %s; ", icmp_type_str(rule->icmp_type)); + else + snprintf(txt2, sizeof(txt2), "protocol %s; port %u; ", rule->protocol == IPPROTO_TCP ? "TCP" : "UDP", rule->port); + + g_strlcat(txt, txt2, sizeof(txt)); + } + + if (rule->match & MATCH_SOURCE) { + if (rule->src_netmask_bits < 32) + snprintf(txt2, sizeof(txt2), "from %s/%i; ", format_ip_address(rule->src_ip_address), rule->src_netmask_bits); + else + snprintf(txt2, sizeof(txt2), "from %s; ", format_ip_address(rule->src_ip_address)); + + g_strlcat(txt, txt2, sizeof(txt)); + } + + if (rule->match & MATCH_DESTINATION) { + if (rule->dst_netmask_bits < 32) + snprintf(txt2, sizeof(txt2), "to %s/%i; ", format_ip_address(rule->dst_ip_address), rule->dst_netmask_bits); + else + snprintf(txt2, sizeof(txt2), "to %s; ", format_ip_address(rule->dst_ip_address)); + g_strlcat(txt, txt2, sizeof(txt)); + } + + if (rule->match & MATCH_BROADCAST) + g_strlcat(txt, "broadcast; ", sizeof(txt)); + + if (rule->match & MATCH_UNICAST) + g_strlcat(txt, "unicast; ", sizeof(txt)); + + + if ((l = strlen(txt)) > 2) { + txt[l-2] = 0; + return txt; + } else + return "all"; +} + +int rule_to_xml(rule_t*rule, xmlDocPtr doc, xmlNodePtr parent) { + static char txt[256]; + + xmlNodePtr node = NULL; + + if (!(node = xmlNewDocNode(doc, NULL, "rule", NULL))) + goto finish; + + snprintf(txt, sizeof(txt), "%u", rule->id); + xmlNewProp(node, "id", txt); + + xmlNewTextChild(node, NULL, "description", rule->description); + + if (!rule->enabled) + xmlNewTextChild(node, NULL, "disabled", NULL); + + xmlNewTextChild(node, NULL, "target", format_verdict(rule->verdict, FORMAT_XML)); + + if (rule->match & MATCH_DIRECTION) { + + xmlNewTextChild(node, NULL, "direction", rule->direction == DIR_INCOMING ? "incoming" : (rule->direction == DIR_OUTGOING ? "outgoing" : "passing")); + + if (rule->match & MATCH_INTERFACES) { + if ((rule->direction == DIR_INCOMING || rule->direction == DIR_PASSING) && rule->device_in[0]) + xmlNewTextChild(node, NULL, "input-device", rule->device_in); + else if ((rule->direction == DIR_OUTGOING || rule->direction == DIR_PASSING) && rule->device_out[0]) + xmlNewTextChild(node, NULL, "output-device", rule->device_out); + } + } + + if (rule->match & MATCH_TYPE) { + xmlNewTextChild(node, NULL, "protocol", rule->protocol == IPPROTO_UDP ? "udp" : (rule->protocol == IPPROTO_ICMP ? "icmp" : "tcp")); + + if (rule->protocol == IPPROTO_ICMP) { + snprintf(txt, sizeof(txt), "%u", rule->icmp_type); + xmlNewTextChild(node, NULL, "icmp-type", txt); + } else { + snprintf(txt, sizeof(txt), "%u", rule->port); + xmlNewTextChild(node, NULL, "destination-port", txt); + } + } + + if (rule->match & MATCH_SOURCE) { + xmlNewTextChild(node, NULL, "source", format_ip_address(rule->src_ip_address)); + if (rule->src_netmask_bits < 32) { + snprintf(txt, sizeof(txt), "%u", rule->src_netmask_bits); + xmlNewTextChild(node, NULL, "source-netmask-bits", txt); + } + } + + if (rule->match & MATCH_DESTINATION) { + xmlNewTextChild(node, NULL, "destination", format_ip_address(rule->dst_ip_address)); + if (rule->dst_netmask_bits < 32) { + snprintf(txt, sizeof(txt), "%u", rule->dst_netmask_bits); + xmlNewTextChild(node, NULL, "destination-netmask-bits", txt); + } + } else if (rule->match & MATCH_BROADCAST) + xmlNewTextChild(node, NULL, "broadcast", NULL); + else if (rule->match & MATCH_UNICAST) + xmlNewTextChild(node, NULL, "unicast", NULL); + + + xmlAddChild(parent, node); + return 0; + +finish: + if (node) + xmlFreeNode(node); + + return -1; +} diff --git a/client/rule.h b/client/rule.h new file mode 100644 index 0000000..bb50d12 --- /dev/null +++ b/client/rule.h @@ -0,0 +1,52 @@ +#ifndef foorulehfoo +#define foorulehfoo + +#include +#include +#include +#include + +#include "connection.h" +#include "main.h" + +typedef enum match { + MATCH_INTERFACES = 1, + MATCH_DIRECTION = 4, + MATCH_TYPE = 8, + MATCH_SOURCE = 16, + MATCH_DESTINATION = 32, + MATCH_BROADCAST = 64, + MATCH_UNICAST = 128 +} match_t; + +typedef struct rule { + gboolean realized; + gboolean enabled; + gboolean being_edited; + verdict_t verdict; + char description[64]; + guint32 id; + GtkTreeIter iter; + + match_t match; + char device_in[IFNAMSIZ+1]; + char device_out[IFNAMSIZ+1]; + conn_direction_t direction; + guint protocol; + guint port; + guint icmp_type; + guint32 src_ip_address; + guint src_netmask_bits; + guint32 dst_ip_address; + guint dst_netmask_bits; +} rule_t; + +rule_t* rule_new(); +rule_t* rule_new_from_conn_info(conn_info_t *ci); +rule_t* rule_new_from_xml(xmlDocPtr doc, xmlNodePtr node); +void rule_free(rule_t *rule); +gchar* rule_match_string(rule_t* rule); + +int rule_to_xml(rule_t*rule, xmlDocPtr doc, xmlNodePtr node); + +#endif diff --git a/client/ruleset.c b/client/ruleset.c new file mode 100644 index 0000000..5c1095a --- /dev/null +++ b/client/ruleset.c @@ -0,0 +1,534 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "ruleset.h" +#include "mainwin.h" +#include "support.h" +#include "format.h" +#include "interface.h" +#include "advancedwin.h" + +ruleset_t ruleset = { + modified : FALSE, + filename : NULL, + icmp_reject_code : 13, + use_tcp_rst : FALSE, + ignore_rules : FALSE, + unmatch_verdict : VERDICT_QUERY, + rules : NULL +}; + +static pid_t child_pid = (pid_t) -1; + +static GtkListStore *ruleset_list_store = NULL; +enum { COLUMN_ENABLED, COLUMN_DESCRIPTION, COLUMN_VERDICT, COLUMN_RULE, N_COLUMNS }; + +static int commit_pipe[2] = {-1, -1}; +volatile static gboolean commit_running = FALSE; +GtkWidget *commit_window = NULL; + +static void _free_list() { + while (ruleset.rules) { + rule_free(ruleset.rules->data); + ruleset.rules = g_list_remove(ruleset.rules, ruleset.rules->data); + } +} + +void _set_data(rule_t *rule) { + g_assert(ruleset_list_store && rule); + + gtk_list_store_set(ruleset_list_store, &rule->iter, + COLUMN_ENABLED, rule->enabled, + COLUMN_DESCRIPTION, rule->description, + COLUMN_VERDICT, format_verdict(rule->verdict, FORMAT_USER), + COLUMN_RULE, rule, + -1); +} + +void ruleset_reset() { + + g_free(ruleset.filename); + ruleset.filename = NULL; + + _free_list(); + + ruleset.modified = FALSE; + ruleset.icmp_reject_code = 13; + ruleset.use_tcp_rst = FALSE; + ruleset.ignore_rules = FALSE; + ruleset.unmatch_verdict = VERDICT_QUERY; + ruleset.rules = NULL; +} + +void ruleset_fill_ui() { + GList *l; + GtkWidget *mw = get_main_window(); + + g_assert(ruleset_list_store); + + gtk_list_store_clear(ruleset_list_store); + + for (l = ruleset.rules; l; l = l->next) { + rule_t *rule = (rule_t*) l->data; + gtk_list_store_append(ruleset_list_store, &rule->iter); + _set_data(rule); + rule->realized = TRUE; + } + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(mw, "ruleset_check_button")), !ruleset.ignore_rules); + gtk_option_menu_set_history(GTK_OPTION_MENU(lookup_widget(mw, "unmatch_optionmenu")), ruleset.unmatch_verdict); + + ruleset_update_ui(); +} + +int ruleset_load(gchar *fn) { + xmlDocPtr doc = NULL; + xmlNodePtr node; + + ruleset_reset(); + + if (!(doc = xmlParseFile(fn))) + goto finish; + + if (!(node = xmlDocGetRootElement(doc))) + goto finish; + + if (xmlStrcmp(node->name, "ruleset")) + goto finish; + + for (node = node->xmlChildrenNode; node; node = node->next) { + rule_t *rule; + + if (node->type == XML_TEXT_NODE) + continue; + + if (node->type != XML_ELEMENT_NODE) + goto finish; + + if (!xmlStrcmp(node->name, "use-tcp-rst")) { + ruleset.use_tcp_rst = TRUE; + continue; + } + + if (!xmlStrcmp(node->name, "ignore-rules")) { + ruleset.ignore_rules = TRUE; + continue; + } + + if (!xmlStrcmp(node->name, "unmatch-verdict")) { + xmlChar *text; + text = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + + if (!xmlStrcmp(text, "drop")) + ruleset.unmatch_verdict = VERDICT_DROP; + else if (!xmlStrcmp(text, "reject")) + ruleset.unmatch_verdict = VERDICT_REJECT; + else if (!xmlStrcmp(text, "accept")) + ruleset.unmatch_verdict = VERDICT_ACCEPT; + else if (!xmlStrcmp(text, "query") || !xmlStrcmp(text, "ask")) + ruleset.unmatch_verdict = VERDICT_QUERY; + else { + xmlFree(text); + goto finish; + } + + xmlFree(text); + continue; + } + + if (!xmlStrcmp(node->name, "icmp-reject-code")) { + xmlChar *text; + text = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + ruleset.icmp_reject_code = atoi(text); + xmlFree(text); + continue; + } + + if (xmlStrcmp(node->name, "rule")) + goto finish; + + if (!(rule = rule_new_from_xml(doc, node))) + goto finish; + + ruleset.rules = g_list_append(ruleset.rules, rule); + } + + xmlFreeDoc(doc); + + ruleset.filename = g_strdup(fn); + ruleset.modified = FALSE; + ruleset_fill_ui(); + + return 0; + +finish: + fprintf(stderr, "Broken XML file.\n"); + + if (doc) + xmlFreeDoc(doc); + + _free_list(); + + return -1; +} + +int ruleset_save(gchar *fn) { + GList *l; + xmlDocPtr doc = NULL; + xmlNodePtr node; + int r = -1; + char txt[256]; + + if (!fn) + fn = ruleset.filename; + + g_assert(fn); + + if (!(doc = xmlNewDoc("1.0"))) + goto finish; + + if (!(node = xmlNewNode(NULL, "ruleset"))) + goto finish; + + xmlDocSetRootElement(doc, node); + + if (ruleset.use_tcp_rst) + xmlNewTextChild(node, NULL, "use-tcp-rst", NULL); + + if (ruleset.ignore_rules) + xmlNewTextChild(node, NULL, "ignore-rules", NULL); + + xmlNewTextChild(node, NULL, "unmatch-verdict", format_verdict(ruleset.unmatch_verdict, FORMAT_XML)); + + snprintf(txt, sizeof(txt), "%u", ruleset.icmp_reject_code); + xmlNewTextChild(node, NULL, "icmp-reject-code", txt); + + for (l = ruleset.rules; l; l = l->next) { + if (rule_to_xml((rule_t*) l->data, doc, node) < 0) + goto finish; + } + + if (xmlSaveFormatFile(fn, doc, 1) < 0) + goto finish; + + xmlFreeDoc(doc); + + ruleset.modified = FALSE; + ruleset_update_ui(); + + return 0; + +finish: + fprintf(stderr, "Could not write XML file.\n"); + + if (doc) + xmlFreeDoc(doc); + + return r; +} + +rule_t* ruleset_get_current_rule() { + GtkTreePath *path; + GtkTreeIter iter; + GtkTreeView *tv = GTK_TREE_VIEW(lookup_widget(get_main_window(), "ruleset_view")); + rule_t *rule; + + gtk_tree_view_get_cursor(tv, &path, NULL); + + if (!path) + return NULL; + + gtk_tree_model_get_iter(GTK_TREE_MODEL(ruleset_list_store), &iter, path); + gtk_tree_model_get(GTK_TREE_MODEL(ruleset_list_store), &iter, COLUMN_RULE, &rule, -1); + + return rule; + +} + +int ruleset_install() { + char *argv[3]; + GError *e; + + g_assert(ruleset.filename); + + argv[0] = "install-firewall"; + argv[1] = ruleset.filename; + argv[2] = NULL; + + if (!g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH, NULL, NULL, &child_pid, NULL, NULL, NULL, &e)) { + fprintf(stderr, "Could not run install-firewall: %s\n", e->message); + g_error_free(e); + return -1; + } + + return 0; +} + +static void _sigchld(int sig) { + gchar c = 'X'; + write(commit_pipe[1], &c, 1); + signal(SIGCHLD, SIG_DFL); +} + + +static gboolean _commit_finish(GIOChannel *source, GIOCondition condition, gpointer data) { + gchar c; + read(commit_pipe[0], &c, 1); + gtk_widget_hide(commit_window); + commit_running = FALSE; + return TRUE; +} + +int ruleset_commit() { + g_assert(ruleset.filename); + + if (commit_running) + return 0; + + commit_running = TRUE; + + if (!commit_window) + commit_window = create_wait_window(); + + gtk_widget_show_all(commit_window); + + signal(SIGCHLD, _sigchld); + + if (ruleset.modified) + ruleset_save(ruleset.filename); + + return ruleset_install(); +} + +void ruleset_update_ui() { + GList *l; + rule_t *rule = ruleset_get_current_rule(); + + gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(get_main_window(), "properties_button")), rule && !rule->being_edited); + gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(get_main_window(), "remove_button")), rule ? TRUE : FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(get_main_window(), "clear_button")), ruleset.rules ? TRUE : FALSE); + + l = g_list_first(ruleset.rules); + gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(get_main_window(), "up_button")), !rule || !l || l->data == rule ? FALSE : TRUE); + l = g_list_last(ruleset.rules); + gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(get_main_window(), "down_button")), !rule || !l || l->data == rule ? FALSE : TRUE); + + + gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(get_main_window(), "commit_button")), ruleset.modified); + + if (rule) { + gtk_label_set_label(GTK_LABEL(lookup_widget(get_main_window(), "rule_enabled_label")), rule->enabled ? "Yes" : "No"); + gtk_label_set_label(GTK_LABEL(lookup_widget(get_main_window(), "rule_name_label")), rule->description); + gtk_label_set_label(GTK_LABEL(lookup_widget(get_main_window(), "rule_match_label")), rule_match_string(rule)); + gtk_label_set_label(GTK_LABEL(lookup_widget(get_main_window(), "rule_verdict_label")), format_verdict(rule->verdict, FORMAT_USER)); + } else { + gchar *p = "n/a"; + gtk_label_set_label(GTK_LABEL(lookup_widget(get_main_window(), "rule_enabled_label")), p); + gtk_label_set_label(GTK_LABEL(lookup_widget(get_main_window(), "rule_name_label")), p); + gtk_label_set_label(GTK_LABEL(lookup_widget(get_main_window(), "rule_match_label")), p); + gtk_label_set_label(GTK_LABEL(lookup_widget(get_main_window(), "rule_verdict_label")), p); + } + +} + +int ruleset_append_rule(rule_t *rule) { + g_assert(rule); + + if (g_list_find(ruleset.rules, rule)) + return -1; + + ruleset.rules = g_list_append(ruleset.rules, rule); + gtk_list_store_append(ruleset_list_store, &rule->iter); + _set_data(rule); + + rule->realized = TRUE; + + ruleset.modified = TRUE; + ruleset_update_ui(); + return 0; +} + +int ruleset_update_rule(rule_t *rule) { + g_assert(rule && rule->realized); + + _set_data(rule); + + ruleset.modified = TRUE; + ruleset_update_ui(); + return 0; +} + + +int ruleset_remove_rule(rule_t *rule) { + g_assert(rule); + + if (rule->being_edited) + return -1; + + if (!g_list_find(ruleset.rules, rule)) + return -1; + + gtk_list_store_remove(ruleset_list_store, &rule->iter); + ruleset.rules = g_list_remove(ruleset.rules, rule); + rule_free(rule); + + ruleset.modified = TRUE; + ruleset_update_ui(); + return 0; +} + + +int ruleset_move_rule(rule_t *rule, int i) { + GtkTreeIter *iter = NULL; + GList *a = NULL, *l; + + if (i == 0) + return -1; + + l = g_list_find(ruleset.rules, rule); + g_assert(l); + + + if (i > 0) { + if (!l->next) + return -1; + + iter = &(((rule_t*) l->next->data)->iter); + + a = l->next->next; + } + + if (i < 0) { + if (!l->prev) + return -1; + + iter = &(((rule_t*) l->prev->data)->iter); + + a = l->prev; + } + + ruleset.rules = g_list_remove(ruleset.rules, rule); + ruleset.rules = g_list_insert_before(ruleset.rules, a, rule); + + gtk_list_store_swap(ruleset_list_store, &rule->iter, iter); + + ruleset.modified = TRUE; + ruleset_update_ui(); + return 0; +} + +void ruleset_clear() { + _free_list(); + if (ruleset_list_store) + gtk_list_store_clear(ruleset_list_store); + ruleset_update_ui(); +} + +static void _ruleset_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer d) { + rule_t *rule; + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_string(path_str); + + gtk_tree_model_get_iter(GTK_TREE_MODEL(ruleset_list_store), &iter, path); + gtk_tree_model_get(GTK_TREE_MODEL(ruleset_list_store), &iter, COLUMN_RULE, &rule, -1); + + rule->enabled = !rule->enabled; + _set_data(rule); + + gtk_tree_path_free (path); + + ruleset.modified = TRUE; + ruleset_update_ui(); +} + +void ruleset_widget_init() { + GtkTreeView *tv = GTK_TREE_VIEW(lookup_widget(get_main_window(), "ruleset_view")); + GtkTreeViewColumn *c; + GtkCellRenderer *r; + + gtk_tree_view_set_model(tv, GTK_TREE_MODEL(ruleset_list_store)); + + r = gtk_cell_renderer_toggle_new(); + g_signal_connect(r, "toggled", G_CALLBACK(_ruleset_toggled), NULL); + + c = gtk_tree_view_column_new_with_attributes("", r, "active", COLUMN_ENABLED, NULL); + gtk_tree_view_append_column(tv, c); + + c = gtk_tree_view_column_new_with_attributes("Verdict", gtk_cell_renderer_text_new(), "text", COLUMN_VERDICT, NULL); + gtk_tree_view_column_set_resizable(c, TRUE); + gtk_tree_view_append_column(tv, c); + + c = gtk_tree_view_column_new_with_attributes("Description", gtk_cell_renderer_text_new(), "text", COLUMN_DESCRIPTION, NULL); + gtk_tree_view_column_set_resizable(c, TRUE); + gtk_tree_view_append_column(tv, c); + + ruleset_update_ui(); +} + + +int ruleset_init() { + GIOChannel *c; + if (pipe(commit_pipe) < 0) + return -1; + + if (!(c = g_io_channel_unix_new(commit_pipe[0]))) { + ruleset_done(); + return -1; + } + + g_io_add_watch(c, G_IO_IN, _commit_finish, NULL); + g_io_channel_unref(c); + + g_assert(!ruleset_list_store); + ruleset_list_store = gtk_list_store_new(N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + + return 0; +} + +void ruleset_done() { + g_free(ruleset.filename); + ruleset.filename = NULL; + + _free_list(); + + if (commit_pipe[0] >= 0) + close(commit_pipe[0]); + if (commit_pipe[1] >= 0) + close(commit_pipe[1]); + + commit_pipe[0] = commit_pipe[1] = -1; + + g_object_unref(ruleset_list_store); + +} + +int ruleset_new(gchar *fn) { + ruleset_reset(); + ruleset.filename = g_strdup(fn); + ruleset.modified = TRUE; + + ruleset_fill_ui(); + + return 0; +} + +int ruleset_initial_load() { + char fn[PATH_MAX]; + + snprintf(fn, sizeof(fn), "%s/.fieryfilter/", getenv("HOME")); + if (mkdir(fn, 0700) && errno != EEXIST) + return -1; + + snprintf(fn, sizeof(fn), "%s/.fieryfilter/default.fwx", getenv("HOME")); + if (ruleset_load(fn) < 0) + if (ruleset_new(fn) < 0) + return -1; + + return 0; +} + diff --git a/client/ruleset.h b/client/ruleset.h new file mode 100644 index 0000000..6ba2b67 --- /dev/null +++ b/client/ruleset.h @@ -0,0 +1,49 @@ +#ifndef foorulesethfoo +#define foorulesethfoo + +#include +#include + +#include "../daemon/common.h" +#include "main.h" +#include "connection.h" +#include "rule.h" + +typedef struct ruleset { + gboolean modified; + gchar *filename; + + guint icmp_reject_code; + gboolean use_tcp_rst; + gboolean ignore_rules; + verdict_t unmatch_verdict; + + GList *rules; +} ruleset_t; + +extern ruleset_t ruleset; + +int ruleset_new(gchar *fn); +int ruleset_load(gchar *fn); +int ruleset_save(gchar *fn); +int ruleset_initial_load(); +int ruleset_commit(); +int ruleset_append_rule(rule_t *rule); +int ruleset_update_rule(rule_t *rule); +int ruleset_remove_rule(rule_t *rule); +int ruleset_move_rule(rule_t *rule, int i); +void ruleset_clear(); + +void ruleset_widget_init(); +void ruleset_update_ui(); +void ruleset_show_rule_info(); +rule_t* ruleset_get_current_rule(); + +int ruleset_install(); + +int ruleset_init(); +void ruleset_done(); + + + +#endif diff --git a/client/rulewin.c b/client/rulewin.c new file mode 100644 index 0000000..ff3d9c4 --- /dev/null +++ b/client/rulewin.c @@ -0,0 +1,249 @@ +#include +#include +#include +#include + +#include "rulewin.h" +#include "interface.h" +#include "support.h" +#include "ruleset.h" +#include "format.h" + +void rulewin_fill(GtkWidget *rw, rule_t *r) { + GList *l; + GtkWidget *bc = NULL; + + if (r->description[0]) { + gtk_label_set_label(GTK_LABEL(lookup_widget(rw, "desc_label")), r->description); + gtk_entry_set_text(GTK_ENTRY(lookup_widget(rw, "desc_entry")), r->description); + } else { + gtk_label_set_label(GTK_LABEL(lookup_widget(rw, "desc_label")), "New rule"); + gtk_entry_set_text(GTK_ENTRY(lookup_widget(rw, "desc_entry")), ""); + } + + gtk_option_menu_set_history(GTK_OPTION_MENU(lookup_widget(rw, "rule_optionmenu")), r->verdict); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_direction_checkbutton")), r->match & MATCH_DIRECTION); + gtk_option_menu_set_history(GTK_OPTION_MENU(lookup_widget(rw, "direction_optionmenu")), r->direction); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_interfaces_checkbutton")), r->match & MATCH_INTERFACES); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(lookup_widget(rw, "incoming_combo"))->entry), r->device_in); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(lookup_widget(rw, "outgoing_combo"))->entry), r->device_out); + + l = fill_interface_list(); + gtk_combo_set_popdown_strings(GTK_COMBO(lookup_widget(rw, "incoming_combo")), l); + gtk_combo_set_popdown_strings(GTK_COMBO(lookup_widget(rw, "outgoing_combo")), l); + free_interface_list(l); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_type_checkbutton")), r->match & MATCH_TYPE); + + gtk_option_menu_set_history(GTK_OPTION_MENU(lookup_widget(rw, "protocol_optionmenu")), r->protocol == IPPROTO_UDP ? 0 : (r->protocol == IPPROTO_TCP ? 1 : 2)); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(lookup_widget(rw, "port_spinbutton")), r->port); + fill_icmp_menu(GTK_OPTION_MENU(lookup_widget(rw, "icmp_optionmenu")), FALSE, r->icmp_type); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_source_checkbutton")), r->match & MATCH_SOURCE); + gtk_entry_set_text(GTK_ENTRY(lookup_widget(rw, "src_ip_entry")), format_ip_address(r->src_ip_address)); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(lookup_widget(rw, "src_netmask_spinbutton")), r->src_netmask_bits); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "src_netmask_checkbutton")), r->src_netmask_bits < 32); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_destination_checkbutton")), r->match & MATCH_DESTINATION); + gtk_entry_set_text(GTK_ENTRY(lookup_widget(rw, "dst_ip_entry")), format_ip_address(r->dst_ip_address)); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(lookup_widget(rw, "dst_netmask_spinbutton")), r->dst_netmask_bits); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "dst_netmask_checkbutton")), r->dst_netmask_bits < 32); + + if (r->match & MATCH_BROADCAST) + bc = lookup_widget(rw, "bc_match_broadcast_radiobutton"); + else if (r->match & MATCH_UNICAST) + bc = lookup_widget(rw, "bc_match_unicast_radiobutton"); + else + bc = lookup_widget(rw, "bc_dont_match_radiobutton"); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bc), TRUE); +} + + +void rulewin_update_host_ranges(GtkWidget *rw) { + const gchar *ip; + gint bits; + + ip = gtk_entry_get_text(GTK_ENTRY(lookup_widget(rw, "src_ip_entry"))); + bits = (gint) gtk_spin_button_get_value(GTK_SPIN_BUTTON(lookup_widget(rw, "src_netmask_spinbutton"))); + gtk_label_set_label(GTK_LABEL(lookup_widget(rw, "src_host_range_value_label")), format_host_range(ip, bits)); + + ip = gtk_entry_get_text(GTK_ENTRY(lookup_widget(rw, "dst_ip_entry"))); + bits = (gint) gtk_spin_button_get_value(GTK_SPIN_BUTTON(lookup_widget(rw, "dst_netmask_spinbutton"))); + gtk_label_set_label(GTK_LABEL(lookup_widget(rw, "dst_host_range_value_label")), format_host_range(ip, bits)); +} + +void rulewin_set_sensitive(GtkWidget *rw) { + gboolean b; + guint i; + gtk_widget_set_sensitive(lookup_widget(rw, "ok_button"), *gtk_entry_get_text(GTK_ENTRY(lookup_widget(rw, "desc_entry"))) ? TRUE : FALSE); + + b = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_direction_checkbutton"))); + + gtk_widget_set_sensitive(lookup_widget(rw, "direction_label"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "direction_optionmenu"), b); + + gtk_widget_set_sensitive(lookup_widget(rw, "match_interfaces_checkbutton"), b); + b = b && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_interfaces_checkbutton"))); + i = gtk_option_menu_get_history(GTK_OPTION_MENU(lookup_widget(rw, "direction_optionmenu"))); + gtk_widget_set_sensitive(lookup_widget(rw, "incoming_label"), b && i != 1); + gtk_widget_set_sensitive(lookup_widget(rw, "incoming_combo"), b && i != 1); + gtk_widget_set_sensitive(lookup_widget(rw, "outgoing_label"), b && i != 0); + gtk_widget_set_sensitive(lookup_widget(rw, "outgoing_combo"), b && i != 0); + + + b = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_type_checkbutton"))); + gtk_widget_set_sensitive(lookup_widget(rw, "protocol_label"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "protocol_optionmenu"), b); + + i = gtk_option_menu_get_history(GTK_OPTION_MENU(lookup_widget(rw, "protocol_optionmenu"))); + + gtk_widget_set_sensitive(lookup_widget(rw, "port_label"), b && i != 2); + gtk_widget_set_sensitive(lookup_widget(rw, "port_spinbutton"), b && i != 2); + gtk_widget_set_sensitive(lookup_widget(rw, "type_label"), b && i != 2); + + gtk_widget_set_sensitive(lookup_widget(rw, "icmp_label"), b && i == 2); + gtk_widget_set_sensitive(lookup_widget(rw, "icmp_optionmenu"), b && i == 2); + + b = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_source_checkbutton"))); + gtk_widget_set_sensitive(lookup_widget(rw, "src_ip_label"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "src_ip_entry"), b); + + gtk_widget_set_sensitive(lookup_widget(rw, "src_netmask_checkbutton"), b); + b = b && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "src_netmask_checkbutton"))); + gtk_widget_set_sensitive(lookup_widget(rw, "src_netmask_spinbutton"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "src_netmask_label"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "src_netmask_label_bits"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "src_host_range_label"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "src_host_range_value_label"), b); + + b = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "bc_dont_match_radiobutton"))); + gtk_widget_set_sensitive(lookup_widget(rw, "match_destination_checkbutton"), b); + b = b && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_destination_checkbutton"))); + gtk_widget_set_sensitive(lookup_widget(rw, "dst_ip_label"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "dst_ip_entry"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "dst_netmask_checkbutton"), b); + + b = b && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "dst_netmask_checkbutton"))); + gtk_widget_set_sensitive(lookup_widget(rw, "dst_netmask_spinbutton"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "dst_netmask_label"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "dst_netmask_label_bits"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "dst_host_range_label"), b); + gtk_widget_set_sensitive(lookup_widget(rw, "dst_host_range_value_label"), b); +} + +int rulewin_show(rule_t *rule) { + GtkWidget *rw; + GdkColor color; + + if (!rule) + rule = rule_new(); + + if (rule->being_edited) + return -1; + + rule->being_edited = TRUE; + + rw = create_rule_window(); + g_object_set_data(G_OBJECT(rw), "rule", rule); + + gdk_color_parse ("black", &color); + gtk_widget_modify_bg(lookup_widget(rw, "desc_eventbox"), GTK_STATE_NORMAL, &color); + + rulewin_fill(rw, rule); + rulewin_set_sensitive(rw); + gtk_widget_show_all(rw); + + + ruleset_update_ui(); + + return 0; +} + +void rulewin_ok(GtkWidget *rw) { + rule_t *rule; + + rule = (rule_t*) g_object_get_data(G_OBJECT(rw), "rule"); + g_assert(rule); + + g_object_set_data(G_OBJECT(rw), "rule", NULL); + + rule->verdict = gtk_option_menu_get_history(GTK_OPTION_MENU(lookup_widget(rw, "rule_optionmenu"))); + strncpy(rule->description, gtk_entry_get_text(GTK_ENTRY(lookup_widget(rw, "desc_entry"))), sizeof(rule->description)); + + rule->match = 0; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_direction_checkbutton")))) + rule->match |= MATCH_DIRECTION; + + rule->direction = gtk_option_menu_get_history(GTK_OPTION_MENU(lookup_widget(rw, "direction_optionmenu"))); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_interfaces_checkbutton")))) + rule->match |= MATCH_INTERFACES; + + g_strlcpy(rule->device_in, gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(lookup_widget(rw, "incoming_combo"))->entry)), sizeof(rule->device_in)); + g_strlcpy(rule->device_out, gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(lookup_widget(rw, "outgoing_combo"))->entry)), sizeof(rule->device_out)); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_type_checkbutton")))) + rule->match |= MATCH_TYPE; + + switch (gtk_option_menu_get_history(GTK_OPTION_MENU(lookup_widget(rw, "protocol_optionmenu")))) { + case 0: rule->protocol = IPPROTO_UDP; break; + case 1: rule->protocol = IPPROTO_TCP; break; + default: rule->protocol = IPPROTO_UDP; + } + + rule->port = CLAMP(1, (guint16) gtk_spin_button_get_value(GTK_SPIN_BUTTON(lookup_widget(rw, "port_spinbutton"))), 0xFFFF); + + // ICMP fehlt + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_source_checkbutton")))) + rule->match |= MATCH_SOURCE; + + inet_aton(gtk_entry_get_text(GTK_ENTRY(lookup_widget(rw, "src_ip_entry"))), (struct in_addr*) &rule->src_ip_address); + rule->src_ip_address = rule->src_ip_address; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "src_netmask_checkbutton")))) + rule->src_netmask_bits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(lookup_widget(rw, "src_netmask_spinbutton"))); + else + rule->src_netmask_bits = 32; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "match_destination_checkbutton")))) + rule->match |= MATCH_DESTINATION; + + inet_aton(gtk_entry_get_text(GTK_ENTRY(lookup_widget(rw, "dst_ip_entry"))), (struct in_addr*) &rule->dst_ip_address); + rule->dst_ip_address = rule->dst_ip_address; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "dst_netmask_checkbutton")))) + rule->dst_netmask_bits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(lookup_widget(rw, "dst_netmask_spinbutton"))); + else + rule->dst_netmask_bits = 32; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "bc_match_broadcast_radiobutton")))) + rule->match |= MATCH_BROADCAST; + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(rw, "bc_match_unicast_radiobutton")))) + rule->match |= MATCH_UNICAST; + + rule->being_edited = FALSE; + + if (rule->realized) + ruleset_update_rule(rule); + else + ruleset_append_rule(rule); +} + +void rulewin_cancel(GtkWidget *rw) { + rule_t *rule; + + rule = (rule_t*) g_object_get_data(G_OBJECT(rw), "rule"); + rule->being_edited = FALSE; + + if (!rule->realized) + rule_free(rule); + + gtk_widget_destroy(rw); + + ruleset_update_ui(); +} diff --git a/client/rulewin.h b/client/rulewin.h new file mode 100644 index 0000000..698153f --- /dev/null +++ b/client/rulewin.h @@ -0,0 +1,14 @@ +#ifndef foorulewinhfoo +#define foorulewinhfoo + +#include + +#include "ruleset.h" + +int rulewin_show(rule_t *rule); +void rulewin_set_sensitive(GtkWidget *rw); +void rulewin_ok(GtkWidget *rw); +void rulewin_cancel(GtkWidget *rw); +void rulewin_update_host_ranges(GtkWidget *rw); + +#endif diff --git a/client/support.c b/client/support.c new file mode 100644 index 0000000..3f5998d --- /dev/null +++ b/client/support.c @@ -0,0 +1,144 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "support.h" + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to find pixmap files. */ +static gchar* +find_pixmap_file (const gchar *filename) +{ + GList *elem; + + /* We step through each of the pixmaps directory to find it. */ + elem = pixmaps_directories; + while (elem) + { + gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, + G_DIR_SEPARATOR_S, filename); + if (g_file_test (pathname, G_FILE_TEST_EXISTS)) + return pathname; + g_free (pathname); + elem = elem->next; + } + return NULL; +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *pathname = NULL; + GtkWidget *pixmap; + + if (!filename || !filename[0]) + return gtk_image_new (); + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return gtk_image_new (); + } + + pixmap = gtk_image_new_from_file (pathname); + g_free (pathname); + return pixmap; +} + +/* This is an internally used function to create pixmaps. */ +GdkPixbuf* +create_pixbuf (const gchar *filename) +{ + gchar *pathname = NULL; + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (!filename || !filename[0]) + return NULL; + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return NULL; + } + + pixbuf = gdk_pixbuf_new_from_file (pathname, &error); + if (!pixbuf) + { + fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", + pathname, error->message); + g_error_free (error); + } + g_free (pathname); + return pixbuf; +} + +/* This is used to set ATK action descriptions. */ +void +glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description) +{ + gint n_actions, i; + + n_actions = atk_action_get_n_actions (action); + for (i = 0; i < n_actions; i++) + { + if (!strcmp (atk_action_get_name (action, i), action_name)) + atk_action_set_description (action, i, description); + } +} + diff --git a/client/support.h b/client/support.h new file mode 100644 index 0000000..92201b9 --- /dev/null +++ b/client/support.h @@ -0,0 +1,67 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Standard gettext macros. + */ +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define N_(String) (String) +#endif + + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps used in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + +/* This is used to create the pixbufs used in the interface. */ +GdkPixbuf* create_pixbuf (const gchar *filename); + +/* This is used to set ATK action descriptions. */ +void glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description); + diff --git a/client/test.fwx b/client/test.fwx new file mode 100644 index 0000000..f5ac861 --- /dev/null +++ b/client/test.fwx @@ -0,0 +1,141 @@ + + + + SPOP3/Cocaine + accept + outgoing + tcp + 995 + 192.168.50.1 + + + POP3/hamburg.de + accept + outgoing + tcp + 110 + 62.181.130.2 + + + POP3/Hansenet + accept + outgoing + tcp + 110 + 213.191.73.2 + + + POP3/Strato + accept + outgoing + tcp + 110 + 192.67.198.2 + + + POP3/Strato + accept + outgoing + tcp + 110 + 192.67.198.79 + + + POP3/Strato + accept + outgoing + tcp + 110 + 192.67.198.62 + + + HTTP + accept + outgoing + tcp + 80 + + + DHCP + accept + outgoing + udp + 67 + 192.168.50.1 + + + CUPS Broadcast + accept + incoming + udp + 631 + 192.168.50.1 + + + + Samba Broadcast Port 138 (cocaine) + accept + incoming + udp + 138 + 192.168.50.1 + + + + Samba Broadcast Port 137 (cocaine) + accept + incoming + udp + 137 + 192.168.50.1 + + + + FTP - stud + accept + outgoing + tcp + 21 + 134.100.7.11 + + + NTP/PTB + accept + outgoing + udp + 123 + 192.53.103.104 + + + NTP/campari + accept + outgoing + udp + 123 + 192.168.100.1 + + + NTP + accept + outgoing + udp + 123 + 130.149.17.21 + + + NTP + accept + outgoing + udp + 123 + 131.188.3.222 + + + NTP + accept + outgoing + udp + 123 + 131.188.1.40 + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..ba32382 --- /dev/null +++ b/configure.ac @@ -0,0 +1,41 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.57) +AC_INIT(fieryfilter, 0.4) +AC_CONFIG_SRCDIR([daemon/main.c]) +AM_INIT_AUTOMAKE(fieryfilter, 0.4) +AM_MAINTAINER_MODE + +AM_CONFIG_HEADER(config.h) + +AC_ISC_POSIX +AC_PROG_CC +AM_PROG_CC_STDC + +AC_HEADER_STDC + +pkg_modules="glib-2.0 > 2.0 gtk+-2.0 >= 2.2.1 libxml-2.0 >= 2.0" +PKG_CHECK_MODULES(PACKAGE, [$pkg_modules]) +AC_SUBST(PACKAGE_CFLAGS) +AC_SUBST(PACKAGE_LIBS) + +GETTEXT_PACKAGE=fieryfilter +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE") + +dnl Add the languages which your application supports here. +ALL_LINGUAS="" +AM_GLIB_GNU_GETTEXT + +AC_CONFIG_SUBDIRS(daemon/libdaemon) + +AC_CONFIG_FILES([ +Makefile +client/Makefile +daemon/Makefile +helper/Makefile +po/Makefile.in +]) + +AC_OUTPUT diff --git a/daemon/Makefile.am b/daemon/Makefile.am new file mode 100644 index 0000000..66f66b2 --- /dev/null +++ b/daemon/Makefile.am @@ -0,0 +1,34 @@ +EXTRA_DIST = libdaemon + +CFLAGS+=-g -Wall -pipe + +INCLUDES = \ + -I/usr/include/libipq \ + -Ilibdaemon/src \ + @PACKAGE_CFLAGS@ + +sbin_PROGRAMS = fieryfilterd + +fieryfilterd_SOURCES = \ + icmp.h icmp.c \ + main.h main.c \ + ipqapi.c ipqapi.h \ + client.h client.c \ + packet.h packet.c \ + common.h + +fieryfilterd_LDADD = @PACKAGE_LIBS@ /usr/lib/libipq.a libdaemon/src/libdaemon.a + +dist-hook: + test -f libdaemon/Makefile && $(MAKE) -C libdaemon/ distclean || true + +copy: + rm -rf libdaemon/ + tar xzf ../../libdaemon/libdaemon-0.1.tar.gz && mv libdaemon-0.1 libdaemon + +libdaemon/src/libdaemon.a: + $(MAKE) -C libdaemon/ + +.PHONY: copy + + diff --git a/daemon/client.c b/daemon/client.c new file mode 100644 index 0000000..d4e6c3b --- /dev/null +++ b/daemon/client.c @@ -0,0 +1,292 @@ +#include +#include +#include +#include +#include + +#include + +#include "client.h" +#include "main.h" +#include "packet.h" +#include "ipqapi.h" + +#define MAX_QUEUE_LENGTH 10 +#define BUFSIZE (10*1024) + +static int unix_socket = -1, client_socket = -1; + +static GSList *send_queue = NULL; +static guint send_queue_length = 0; +static guint send_index = 0; + +static guint8 recv_buf[BUFSIZE]; +static guint recv_index = 0; + +int client_init() { + struct sockaddr_un addr; + mode_t save; + + save = umask(0007); + + if ((unix_socket = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + umask(save); + daemon_log(LOG_ERR, "socket(PF_LOCAL, SOCK_STREAM, 0): %s", strerror(errno)); + return -1; + } + + addr.sun_family = AF_LOCAL; + strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path)); + addr.sun_path[sizeof(addr.sun_path)-1] = 0; + + if (bind(unix_socket, (struct sockaddr *) &addr, SUN_LEN(&addr)) < 0) { + close(unix_socket); + umask(save); + daemon_log(LOG_ERR, "bind(): %s", strerror(errno)); + return (unix_socket = -1); + } + + umask(save); + + if (listen(unix_socket, 1) < 0) { + close(unix_socket); + daemon_log(LOG_ERR, "listen(): %s", strerror(errno)); + return (unix_socket = -1); + } + + FD_SET(unix_socket, &listen_rfds); + + return 0; +} + +void client_disconnect() { + if (client_socket < 0) + return; + + FD_CLR(client_socket, &listen_rfds); + close(client_socket); + client_socket = -1; + + while (send_queue) { + message_t *m = (message_t*) send_queue->data; + send_queue = g_slist_remove(send_queue, m); + g_free(m); + } + + send_queue_length = 0; + send_index = 0; + + recv_index = 0; + + daemon_log(LOG_INFO, "Client disconnected"); +} + + +void client_done() { + if (client_socket >= 0) + client_disconnect(); + + if (unix_socket >= 0) { + FD_CLR(unix_socket, &listen_rfds); + close(unix_socket); + unlink(SOCKET_PATH); + } + + unix_socket = -1; +} + + +int client_work_send() { + g_assert(client_socket >= 0); + + if (send_queue) { + size_t l; + ssize_t r; + message_t *m = (message_t*) send_queue->data; + + g_assert(m); + l = m->length + sizeof(message_t); + + if ((r = write(client_socket, ((guint8*) m) + send_index, l-send_index)) <= 0) { + daemon_log(LOG_ERR, "Write error on client socket (%s)", strerror(errno)); + return -1; + } + + send_index += r; + + if (send_index >= l) { + send_queue = g_slist_remove(send_queue, m); + send_queue_length--; + send_index = 0; + + g_free(m); + } + } + + if (!send_queue) + FD_CLR(client_socket, &listen_wfds); + else + FD_SET(client_socket, &listen_wfds); + + return 0; +} + +int client_dispatch(message_t*m) { + switch (m->code) { + + case MSG_SET_DEFAULT_VERDICT: + + if (m->length != sizeof(guint32)) { + daemon_log(LOG_WARNING, "Client sent MSG_SET_DEFAULT_VERDICT message with bogus size."); + return -1; + } + + default_verdict = *((guint*) (m+1)); + return 0; + + case MSG_VERDICT: { + ipq_packet_msg_t *ipqm; + unsigned long packet_id; + guint32 verdict; + + if (m->length != sizeof(unsigned long)+sizeof(guint32)) { + daemon_log(LOG_WARNING, "Client sent MSG_VERDICT message with bogus size."); + return -1; + } + + packet_id = *((unsigned long*) (m+1)); + verdict = *((guint32*) (((guint8*) (m+1)) + sizeof(unsigned long))); + + if (log_packets) + daemon_log(LOG_DEBUG, "[%lu] Recieved client verdict %u", packet_id, verdict); + + if ((ipqm = packet_find(packet_id))) { + if (ipqapi_verdict(ipqm, verdict) < 0) { + daemon_log(LOG_ERR, "Could not verdict."); + fail = TRUE; + } + + packet_release(packet_id); + + } else + daemon_log(LOG_WARNING, "Recieved verdict for unknown packet id, ignoring"); + + return 0; + } + + default: + daemon_log(LOG_WARNING, "Recieved bogus message from client."); + return -1; + } +} + +int client_work_recv() { + ssize_t r; + size_t l; + + + if (recv_index >= sizeof(message_t)) { + l = ((message_t*) recv_buf)->length + sizeof(message_t); + + if (l > BUFSIZE) { + daemon_log(LOG_WARNING, "Client message too large"); + return -1; + } + } else + l = sizeof(message_t); + + if ((r = read(client_socket, recv_buf + recv_index, l - recv_index)) <= 0) { + if (r < 0) + daemon_log(LOG_WARNING, "Read error on client socket (%s)", strerror(errno)); + return -1; + } + + recv_index += r; + + if (recv_index >= sizeof(message_t)) { + if (recv_index >= ((message_t*) recv_buf)->length + sizeof(message_t)) { + recv_index = 0; + + if (client_dispatch((message_t*) recv_buf)) + client_disconnect(); + } + } + return 0; +} + + +int client_work_accept() { + int fd; + + if ((fd = accept(unix_socket, NULL, NULL)) < 0) + return -1; + + if (client_socket >= 0) { + daemon_log(LOG_WARNING, "Client connecting while already in use, closing"); + close(fd); + return 0; + } + + client_socket = fd; + FD_SET(client_socket, &listen_rfds); + + daemon_log(LOG_INFO, "Client connected"); + + return 0; +} + +int client_work() { + int r = 0; + + if (FD_ISSET(unix_socket, &select_rfds)) + if ((r = client_work_accept()) < 0) + return r; + + if (client_socket >= 0 && FD_ISSET(client_socket, &select_rfds)) + if (client_work_recv() < 0) + client_disconnect(); + + if (client_socket >= 0 && FD_ISSET(client_socket, &select_wfds)) + if (client_work_send() < 0) + client_disconnect(); + + return 0; +} + +int client_send_enqueue(message_t *m) { + g_assert(client_socket >= 0); + + if (send_queue_length+1 > MAX_QUEUE_LENGTH) + return -1; + + send_queue = g_slist_append(send_queue, m); + FD_SET(client_socket, &listen_wfds); + + send_queue_length++; + return 0; +} + +int client_is_connected() { + return client_socket >= 0; +} + +message_t* message_new(message_code_t c, guint8* d, guint s) { + guchar *p; + message_t *m; + + if (!d) + s = 0; + + m = (message_t*) (p = g_new(guint8, sizeof(message_t) + s)); + + if (d) + memcpy(p + sizeof(message_t), d, s); + + m->code = c; + m->pid = getpid(); + m->length = s; + + return m; +} + + diff --git a/daemon/client.h b/daemon/client.h new file mode 100644 index 0000000..9e54fb9 --- /dev/null +++ b/daemon/client.h @@ -0,0 +1,13 @@ +#ifndef fooclienthfoo +#define fooclienthfoo + +#include "common.h" + +int client_init(); +void client_done(); +int client_work(); +int client_is_connected(); +int client_send_enqueue(message_t *m); +message_t* message_new(message_code_t c, guint8* d, guint s); + +#endif diff --git a/daemon/common.h b/daemon/common.h new file mode 100644 index 0000000..4a8e6b1 --- /dev/null +++ b/daemon/common.h @@ -0,0 +1,23 @@ +#ifndef foocommonhfoo +#define foocommonhfoo + +#include +#include +#include + +#define SOCKET_PATH "/tmp/fieryfilter" + +typedef enum message_code { + MSG_PACKET = 0, + MSG_VERDICT = 1, + MSG_SET_DEFAULT_VERDICT = 2 +} message_code_t; + +typedef struct message { + message_code_t code; + pid_t pid; + guint32 length; +} message_t; + + +#endif diff --git a/daemon/icmp.c b/daemon/icmp.c new file mode 100644 index 0000000..7252b7c --- /dev/null +++ b/daemon/icmp.c @@ -0,0 +1,87 @@ +#include +#include +#include + +#include +#include +#include + +#include "icmp.h" + +#define BUFSIZE (10*1024) + +static int icmp_socket = -1; + +guint16 ipsum(guint8 *p, guint l) { + guint32 sum = 0; + guint i; + + for (i = 0; i < l-1; i += 2) + sum += (p[i] << 8) + p[i+1]; + + if (i < l) + sum += p[i] << 8; + + sum = (sum & 0xFFFF) + (sum >> 16); + sum = (sum & 0xFFFF) + (sum >> 16); + + return ~sum; +} + + +int reply_icmp_error(ipq_packet_msg_t *m, int code) { + static guint8 buf[BUFSIZE]; + struct iphdr* ip = (struct iphdr*) m->payload; + struct icmphdr *icmp = (struct icmphdr*) buf; + guint l, tl; + struct sockaddr_in sa; + + icmp->type = 3; + icmp->code = code; + icmp->checksum = 0; + icmp->un.frag.__unused = 0; + icmp->un.frag.mtu = 0; + + l = ip->ihl*4 + 8; + memcpy(&buf[sizeof(struct icmphdr)], m->payload, l); + + tl = l + sizeof(struct icmphdr); + icmp->checksum = htons(ipsum((guint8*) icmp, tl)); + + sa.sin_family = AF_INET; + sa.sin_port = 0; + sa.sin_addr.s_addr = ip->saddr; + + + if (sendto(icmp_socket, icmp, tl, 0, (struct sockaddr*) &sa, sizeof(sa)) < 0) { + perror("sendto()"); + return -1; + } + + return 0; +} + +int icmp_init() { + int enable = 1; + + if ((icmp_socket = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { + perror("socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)"); + return -1; + + } + + if (setsockopt(icmp_socket, SOL_SOCKET, SO_BROADCAST, (char *)&enable, sizeof(enable)) < 0) { + perror("setsockopt(.., SOL_SOCKET, SO_BROADCAST)"); + return -1; + } + + return 0; +} + + +void icmp_done() { + if (icmp_socket >= 0) + close(icmp_socket); + + icmp_socket = -1; +} diff --git a/daemon/icmp.h b/daemon/icmp.h new file mode 100644 index 0000000..b2b62a9 --- /dev/null +++ b/daemon/icmp.h @@ -0,0 +1,11 @@ +#ifndef fooipsumhfoo +#define fooipsumhfoo + +#include +#include + +int reply_icmp_error(ipq_packet_msg_t *m, int code); +int icmp_init(); +void icmp_done(); + +#endif diff --git a/daemon/ipqapi.c b/daemon/ipqapi.c new file mode 100644 index 0000000..b0649bc --- /dev/null +++ b/daemon/ipqapi.c @@ -0,0 +1,118 @@ +#include +#include + +#include + +#include "icmp.h" +#include "ipqapi.h" +#include "main.h" +#include "client.h" +#include "packet.h" + +#define BUFSIZE (10*1024) + +static struct ipq_handle *ipq = NULL; + +int ipqapi_init() { + int status; + + if (!(ipq = ipq_create_handle(0, PF_INET))) { + daemon_log(LOG_ERR, "ipq_create_handle(): %s", ipq_errstr()); + return -1; + } + + if ((status = ipq_set_mode(ipq, IPQ_COPY_PACKET, BUFSIZE)) < 0) { + daemon_log(LOG_ERR, "ipq_set_mode(): %s", ipq_errstr()); + daemon_log(LOG_INFO, "Perhaps you should run 'modprobe ip_queue'?"); + ipq_destroy_handle(ipq); + ipq = NULL; + return -1; + } + + FD_SET(ipq->fd, &listen_rfds); + + return 0; +} + +void ipqapi_done() { + if (ipq) { + FD_CLR(ipq->fd, &listen_rfds); + ipq_destroy_handle(ipq); + } + + ipq = NULL; +} + +int ipqapi_work() { + int status; + static guint8 buf[BUFSIZE]; + + if (!FD_ISSET(ipq->fd, &select_rfds)) + return 0; + + if ((status = ipq_read(ipq, buf, BUFSIZE, 0)) < 0) { + daemon_log(LOG_ERR, "ipq_read(): %s", ipq_errstr()); + return -1; + } + + switch (ipq_message_type(buf)) { + case NLMSG_ERROR: + daemon_log(LOG_ERR, "Received error message: %s\n", strerror(ipq_get_msgerr(buf))); + return -1; + + case IPQM_PACKET: { + ipq_packet_msg_t *m = ipq_get_packet(buf); + + if (!m->timestamp_sec) + time(&m->timestamp_sec); + + if (log_packets) + daemon_log(LOG_DEBUG, "[%lu] Recieved packet, forwarding to client", m->packet_id); + + if (client_is_connected()) { + packet_new(m); + client_send_enqueue(message_new(MSG_PACKET, (guint8*) m, sizeof(ipq_packet_msg_t)+m->data_len)); + } else { + if (log_packets) + daemon_log(LOG_DEBUG, "[%lu] No clients listening, verdicting", m->packet_id); + + if (ipqapi_verdict(m, default_verdict) < 0) { + daemon_log(LOG_ERR, "Sending verdict failed."); + return -1; + } + } + + return 0; + } + + default: + daemon_log(LOG_WARNING, "Recieved invalid IPQ message."); + return -1; + } +} + +int ipqapi_verdict(ipq_packet_msg_t *m, guint32 resp) { + int nf = NF_DROP, icmp = 0; + + if (resp > 17) resp = 17; + + if (resp == 0) + nf = NF_DROP; + else if (resp == 1) + nf = NF_ACCEPT; + else { + nf = NF_DROP; + icmp = 1; + } + + if (ipq_set_verdict(ipq, m->packet_id, nf, 0, NULL) < 0) { + daemon_log(LOG_ERR, "ipq_set_verdict(): %s", ipq_errstr()); + return -1; + } + + + if (icmp) + return reply_icmp_error(m, resp-2); + + return 0; +} diff --git a/daemon/ipqapi.h b/daemon/ipqapi.h new file mode 100644 index 0000000..bac4d48 --- /dev/null +++ b/daemon/ipqapi.h @@ -0,0 +1,13 @@ +#ifndef fooipqapihfoo +#define fooipqapihfoo + +#include +#include +#include + +int ipqapi_verdict(ipq_packet_msg_t *m, guint32 resp); +int ipqapi_work(); +void ipqapi_done(); +int ipqapi_init(); + +#endif diff --git a/daemon/main.c b/daemon/main.c new file mode 100644 index 0000000..253bf35 --- /dev/null +++ b/daemon/main.c @@ -0,0 +1,198 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "common.h" +#include "main.h" +#include "ipqapi.h" +#include "client.h" +#include "icmp.h" +#include "packet.h" + +gboolean opt_fork = TRUE; +gboolean opt_syslog = TRUE; + +fd_set listen_wfds, listen_rfds, select_wfds, select_rfds; + +gboolean fail = FALSE; + +guint32 default_verdict = 15; // ICMP packet filtered +//guint32 default_verdict = 1; // Accept + +gboolean log_packets = FALSE; + +static gboolean _verdict_func(ipq_packet_msg_t*m) { + if (log_packets) + daemon_log(LOG_DEBUG, "[%lu] Still unanswered, verdicting", m->packet_id); + ipqapi_verdict(m, default_verdict); + return FALSE; +} + +int init() { + if (daemon_signal_init(SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGINT, SIGQUIT, SIGTERM, -1) < 0) + return -1; + + FD_ZERO(&listen_wfds); + FD_ZERO(&listen_rfds); + + if (ipqapi_init() < 0) + return -1; + + if (client_init() < 0 ) + return -1; + + if (icmp_init() < 0) + return -1; + + return 0; +} + +void done() { + ipqapi_done(); + client_done(); + icmp_done(); + packets_free(); + daemon_signal_done(); +} + +int loop() { + int r; + + daemon_log(LOG_INFO, "%s "VERSION" sucessfully initialized.", daemon_log_ident); + + while (!fail) { + int sig; + + select_rfds = listen_rfds; + select_wfds = listen_wfds; + + if (select(FD_SETSIZE, &select_rfds, &select_wfds, NULL, NULL) < 0 && errno != EINTR) { + daemon_log(LOG_ERR, "select: %s", strerror(errno)); + goto finish; + } + + if ((sig = daemon_signal_next()) >= 0) { + + switch (sig) { + case SIGINT: + case SIGQUIT: + case SIGTERM: + daemon_log(LOG_INFO, "Recieved signal <%s>, exiting cleanly", strsignal(sig)); + r = 0; + goto finish; + + case SIGHUP: + daemon_log(LOG_INFO, "Recieved signal <%s>, reporting status info:", strsignal(sig)); + daemon_log(LOG_INFO, "%u packets total, %u packets in queue", get_total_packets(), get_queued_packets()); + break; + + case SIGUSR1: + case SIGUSR2: + log_packets = sig == SIGUSR1; + daemon_log(LOG_INFO, "Recieved signal <%s>, %s packet logging", strsignal(sig), log_packets ? "enabling" : "disabling"); + break; + + case SIGPIPE: + break; + + default: + daemon_log(LOG_WARNING, "Recieved signal <%s>, ignoring.", strsignal(sig)); + } + + } else { + if (client_work() < 0) + goto finish; + + if (ipqapi_work() < 0) + goto finish; + } + + packet_foreach(client_is_connected(), _verdict_func); + } + + r = 0; + +finish: + + daemon_log(LOG_INFO, "%s exiting.", daemon_log_ident); + + return r; +} + + +int start() { + struct group *gr; + setuid(geteuid()); + + if (!(gr = getgrnam("fieryfilter"))) { + daemon_log(LOG_ERR, "Could not find group fieryfilter"); + return 1; + } + + if (setgid(gr->gr_gid) != 0) { + daemon_log(LOG_ERR, "setgid(): %s", strerror(errno)); + return 1; + } + + if (opt_fork) { + pid_t pid; + + daemon_retval_init(); + + if ((pid = daemon_fork()) < 0) + return 1; + else if (pid != 0) { + int r = daemon_retval_wait(10); + return r < 0 ? 1 : r; + } else { + daemon_log_use_syslog = opt_syslog; + + if (init() < 0) { + daemon_retval_send(1); + done(); + return 1; + } + + daemon_retval_send(0); + } + } else { + daemon_log_use_syslog = opt_syslog; + + if (init() < 0) { + done(); + return 1; + } + } + + + if (loop() < 0) { + done(); + return 1; + } + + done(); + return 0; + +} + +int main(int argc, char *argv[]) { + if ((daemon_log_ident = strrchr(argv[0], '/'))) + daemon_log_ident++; + else + daemon_log_ident = argv[0]; + + daemon_log_use_syslog = FALSE; + + return start(); +} diff --git a/daemon/main.h b/daemon/main.h new file mode 100644 index 0000000..b4c5e5b --- /dev/null +++ b/daemon/main.h @@ -0,0 +1,14 @@ +#ifndef foomainhfoo +#define foomainhfoo + +#include + +extern fd_set listen_wfds, listen_rfds, select_wfds, select_rfds; + +extern gboolean fail; + +extern guint32 default_verdict; + +extern gboolean log_packets; + +#endif diff --git a/daemon/packet.c b/daemon/packet.c new file mode 100644 index 0000000..c8722f8 --- /dev/null +++ b/daemon/packet.c @@ -0,0 +1,101 @@ +#include + +#include "packet.h" + +#define PACKET_TIMEOUT 30 + +typedef struct packet_wrapper { + time_t timestamp; + ipq_packet_msg_t m; +} packet_wrapper_t; + +static GSList *packets = NULL; +static guint n_packets = 0; +static guint total_packets = 0; + +guint get_queued_packets() { + return n_packets; +} + +guint get_total_packets() { + return total_packets; +} + +void packet_new(ipq_packet_msg_t *m) { + packet_wrapper_t *w = (packet_wrapper_t*) g_malloc(sizeof(packet_wrapper_t)+ m->data_len); + memcpy(&w->m, m, sizeof(ipq_packet_msg_t)+ m->data_len); + time(&w->timestamp); + + packets = g_slist_prepend(packets, w); + n_packets++; + total_packets++; +} + +static packet_wrapper_t* _find(unsigned long id) { + GSList *l; + + for (l = packets; l; l = l->next) { + packet_wrapper_t *w = (packet_wrapper_t*) l->data; + if (w->m.packet_id == id) + return w; + } + + return NULL; +} + +ipq_packet_msg_t* packet_find(unsigned long id) { + packet_wrapper_t* w; + + if ((w = _find(id))) + return &w->m; + + return NULL; +} + +void packet_release(unsigned long id) { + packet_wrapper_t *w; + + w = _find(id); + g_assert(w); + + packets = g_slist_remove(packets, w); + g_free(w); + n_packets--; +} + + +void packet_foreach(gboolean age, gboolean (*func)(ipq_packet_msg_t*)) { + GSList *l, *p; + + for (l = packets, p = NULL; l;) { + gboolean remove = FALSE; + packet_wrapper_t *w = (packet_wrapper_t*) l->data; + + if (!age || w->timestamp + PACKET_TIMEOUT < time(NULL)) + if (!func(&w->m)) + remove = TRUE; + + + + if (remove) { + if (p) + p->next = l->next; + else + packets = l->next; + + g_slist_free_1(l); + + l = p; + } else + l = l->next; + } +} + +void packets_free() { + while (packets) { + packet_wrapper_t *w; + w = (packet_wrapper_t*) packets->data; + packets = g_slist_remove(packets, w); + g_free(w); + } +} diff --git a/daemon/packet.h b/daemon/packet.h new file mode 100644 index 0000000..49fe042 --- /dev/null +++ b/daemon/packet.h @@ -0,0 +1,15 @@ +#ifndef foopackethfoo +#define foopackethfoo + +#include +#include + +void packet_new(ipq_packet_msg_t *m); +ipq_packet_msg_t* packet_find(unsigned long id); +void packet_release(unsigned long id); +void packet_foreach(gboolean age, gboolean (*func)(ipq_packet_msg_t*)); +void packets_free(); +guint get_queued_packets(); +guint get_total_packets(); + +#endif diff --git a/fieryfilter.glade b/fieryfilter.glade new file mode 100644 index 0000000..481689d --- /dev/null +++ b/fieryfilter.glade @@ -0,0 +1,3962 @@ + + + + + + + FieryFilter Connection + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + False + + + + + True + False + 0 + + + + True + + + + 5 + True + False + 5 + + + + True + gtk-go-forward + 5 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + <span size="xx-large" color="white"><b>Outgoing Connection</b></span> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + 0 + False + False + + + + + + True + + + 0 + False + True + + + + + + 10 + True + False + 10 + + + + True + 7 + 2 + False + 3 + 5 + + + + True + True + eth0 + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 1 + 2 + expand + + + + + + True + True + tcp-80-http + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 0 + 1 + expand + + + + + + True + True + label17 + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 4 + 5 + expand + + + + + + True + True + label18 + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 5 + 6 + expand + + + + + + True + Yes + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 6 + 7 + expand + + + + + + True + addr + + + + True + True + www.heise.de + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + + + 1 + 2 + 3 + 4 + fill + fill + + + + + + True + addr + + + + True + True + localhost + False + False + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 0 + 0 + + + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + True + <b>Type:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 0 + 1 + fill + expand + + + + + + True + <b>Device:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + expand + + + + + + True + <b>From:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 2 + 3 + fill + expand + + + + + + True + <b>To:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 3 + 4 + fill + expand + + + + + + True + <b>Time:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 4 + 5 + fill + expand + + + + + + True + <b>ID#:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 5 + 6 + fill + expand + + + + + + True + <b>Broadcast:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 6 + 7 + fill + expand + + + + + 0 + True + True + + + + + + True + gtk-missing-image + 5 + 0.5 + 0 + 0 + 0 + + + 0 + False + False + GTK_PACK_END + + + + + 0 + True + True + + + + + + True + + + 0 + False + False + + + + + + 5 + True + False + 0 + + + + True + True + Apply decision to all _queued connections + True + GTK_RELIEF_NORMAL + False + False + True + + + 0 + False + False + + + + + + True + True + _Create a rule from this decision + True + GTK_RELIEF_NORMAL + False + False + True + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + + + 0 + False + False + + + + + + 5 + True + GTK_BUTTONBOX_END + 5 + + + + True + True + True + True + True + GTK_RELIEF_NORMAL + + + + + True + 0.5 + 0.5 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-yes + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Accept + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + + + + True + True + True + GTK_RELIEF_NORMAL + + + + + True + 0.5 + 0.5 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-dialog-error + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Reject + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + + + + True + True + True + GTK_RELIEF_NORMAL + + + + + True + 0.5 + 0.5 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-delete + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Drop + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + + + 0 + False + False + + + + + + + + True + FieryFilter + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 620 + 520 + True + False + + + + + True + False + 0 + + + + True + + + + True + _File + True + + + + + + + True + _New ruleset + True + + + + + True + gtk-new + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Open ruleset... + True + + + + + True + gtk-open + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Save ruleset as... + True + + + + + True + gtk-save-as + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + gtk-quit + True + + + + + + + + + + + True + _Edit + True + + + + + + + True + _Clear Log + True + + + + + True + gtk-clear + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Help + True + + + + + + + True + _About + True + + + + + + + + + + 0 + False + False + + + + + + True + + + + True + False + 0 + + + + True + <b><span size="xx-large" color="white">FieryFilter Interactive Personal Firewall</span></b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 5 + + + 0 + True + True + + + + + + True + <span color="white"><i>Version 4711</i></span> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 1 + 10 + 5 + + + 0 + False + False + + + + + + + 0 + False + False + + + + + + True + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + 5 + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + + + + + False + True + + + + + + True + True + Connection _Log + True + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + 5 + True + False + 10 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + False + 5 + + + + True + True + Respect r_uleset + True + GTK_RELIEF_NORMAL + True + False + True + + + + 0 + False + False + + + + + + True + False + 5 + + + + True + Un_matched connections: + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + unmatch_optionmenu + + + 0 + False + False + + + + + + True + True + 1 + + + + + + + + True + Query User + True + + + + True + gtk-dialog-question + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Accept + True + + + + True + gtk-yes + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Reject + True + + + + True + gtk-dialog-error + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Drop + True + + + + True + gtk-delete + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + + + True + <b>Firewall mode</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 10 + + + + True + False + 5 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + 4 + 2 + False + 5 + 5 + + + + True + <b>Verdict:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + <b>Match:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + <b>Description:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + label69 + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 3 + 4 + + + + + + + True + label68 + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 2 + 3 + + + + + + + True + label67 + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 1 + 2 + + + + + + + True + label80 + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + <b>Enabled:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + + + True + <b>Rule</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + label_item + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + False + 5 + + + + True + True + True + gtk-properties + True + GTK_RELIEF_NORMAL + + + + 0 + False + False + + + + + + True + + + 5 + False + True + + + + + + True + True + True + gtk-go-up + True + GTK_RELIEF_NORMAL + + + + 0 + False + False + + + + + + True + True + True + gtk-go-down + True + GTK_RELIEF_NORMAL + + + + 0 + False + False + + + + + + True + + + 5 + False + True + + + + + + True + True + True + GTK_RELIEF_NORMAL + + + + + True + 0.5 + 0.5 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-add + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Add new rule + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + True + True + GTK_RELIEF_NORMAL + + + + + True + 0.5 + 0.5 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-remove + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Remove rule + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + True + True + gtk-clear + True + GTK_RELIEF_NORMAL + + + + 0 + False + False + + + + + + True + + + 5 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + + + + + True + 0.5 + 0.5 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-preferences + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Advanced + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + + + 5 + False + False + + + + + + True + True + True + True + GTK_RELIEF_NORMAL + + + + + True + 0.5 + 0.5 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-execute + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Co_mmit + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + False + + + + + 0 + True + True + + + + + False + True + + + + + + True + Firewall _Rules + True + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + 5 + True + False + 10 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + False + 5 + + + + True + True + _Automatic scrolling to newly added log entries + True + GTK_RELIEF_NORMAL + True + False + True + + + 0 + False + False + + + + + + True + True + Popup window is _sticky (visible on all desktops) + True + GTK_RELIEF_NORMAL + True + False + True + + + + 0 + False + False + + + + + + True + False + 5 + + + + True + Maximum number of Log entries: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 100 10 999 1 10 10 + + + + 0 + False + True + + + + + 0 + True + True + + + + + + + + True + <b>User Interface</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + label_item + + + + + 0 + False + False + + + + + False + True + + + + + + True + _Options + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + 3 + True + True + + + + + + True + True + + + 0 + False + False + + + + + + + + FieryFilter Rule + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + False + False + + + + + True + False + 0 + + + + True + + + + True + True + desc_label + False + True + GTK_JUSTIFY_LEFT + False + True + 0 + 0.5 + 10 + 10 + + + + + 0 + False + False + + + + + + True + + + 0 + False + False + + + + + + 5 + True + True + True + True + GTK_POS_TOP + False + False + + + + 5 + True + False + 5 + + + + True + Description: + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + True + True + 64 + A new rule + True + * + False + + + + 0 + False + False + + + + + + True + Action: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + 0 + + + + + + + True + Query User + True + + + + True + gtk-dialog-question + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Accept + True + + + + True + gtk-yes + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Reject + True + + + + True + gtk-dialog-error + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Drop + True + + + + True + gtk-delete + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + 0 + False + False + + + + + False + True + + + + + + True + General + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + 5 + True + False + 5 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + False + 5 + + + + True + Direction: + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + 0 + + + + + + + + True + Incoming + True + + + + True + gtk-go-forward + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Outgoing + True + + + + True + gtk-go-back + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Passing + True + + + + + + + 0 + True + True + + + + + + + + True + True + Match _direction: + True + GTK_RELIEF_NORMAL + True + False + True + + + + label_item + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + 2 + 2 + False + 5 + 5 + + + + True + In_coming: + True + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + combo-entry3 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + _Outgoing: + True + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + combo-entry2 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + False + False + False + True + False + + + + True + True + True + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + + 1 + 2 + 1 + 2 + + + + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + + 1 + 2 + 0 + 1 + + + + + + + + + True + True + Match _interfaces: + True + GTK_RELIEF_NORMAL + True + False + True + + + + label_item + + + + + 0 + False + False + + + + + False + True + + + + + + True + Interface + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + 5 + True + False + 5 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + 3 + 2 + False + 5 + 5 + + + + True + _Protocol: + True + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + protocol_optionmenu + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + _Port number: + True + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + 0 + + + + + + + + True + UDP - User Datagram Protocol + True + + + + + + True + TCP - Transmission Control Protocol + True + + + + + + True + ICMP - Internet Control Message Protocol + True + + + + + + + 1 + 2 + 0 + 1 + + + + + + + True + I_CMP-Type: + True + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + icmp_optionmenu + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + True + -1 + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + True + 5 + + + + True + True + 5 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 65535 1 65535 1 100 10 + + + + 0 + True + True + + + + + + True + www + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + True + GTK_PACK_END + + + + + 1 + 2 + 1 + 2 + fill + fill + + + + + + + + True + True + Match _type: + True + GTK_RELIEF_NORMAL + True + False + True + + + + label_item + + + + + 0 + False + False + + + + + False + True + + + + + + True + Type + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + + 5 + True + False + 5 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + 4 + 3 + False + 5 + 5 + + + + True + IP-Address: + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + True + True + 15 + 192.168.0.1 + True + * + False + + + + 1 + 3 + 0 + 1 + + + + + + + True + False + label48 + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 1 + 3 + 3 + 4 + fill + + + + + + + True + False + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 24 0 32 1 8 10 + + + + 1 + 2 + 2 + 3 + + + + + + + True + False + bits + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 2 + 3 + 2 + 3 + fill + + + + + + + True + False + Host range: + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + Specify netmask + True + GTK_RELIEF_NORMAL + False + False + True + + + + 1 + 3 + 1 + 2 + fill + + + + + + + True + Netmask: + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + + + True + True + Match source: + True + GTK_RELIEF_NORMAL + True + False + True + + + + label_item + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + 4 + 3 + False + 5 + 5 + + + + True + IP-Address: + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + True + True + 15 + 192.168.0.1 + True + * + False + + + + 1 + 3 + 0 + 1 + + + + + + + True + Host range: + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 24 0 32 1 10 10 + + + + 1 + 2 + 2 + 3 + + + + + + + True + bits + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 2 + 3 + 2 + 3 + fill + + + + + + + True + label50 + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 1 + 3 + 3 + 4 + fill + + + + + + + True + True + Specify netmask + True + GTK_RELIEF_NORMAL + False + False + True + + + + 1 + 3 + 1 + 2 + fill + + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + Netmask: + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + + + True + True + Match destination: + True + GTK_RELIEF_NORMAL + True + False + True + + + + label_item + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + False + 0 + + + + True + True + Don't match + True + GTK_RELIEF_NORMAL + False + False + True + + + + 0 + False + False + + + + + + True + True + Match broadcast + True + GTK_RELIEF_NORMAL + False + False + True + bc_dont_match_radiobutton + + + + 0 + False + False + + + + + + True + True + Match unicast + True + GTK_RELIEF_NORMAL + False + False + True + bc_dont_match_radiobutton + + + + 0 + False + False + + + + + + + + True + Broadcast: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + label_item + + + + + 0 + False + False + + + + + False + True + + + + + + True + Addresses + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + tab + + + + + 0 + True + True + + + + + + 5 + True + GTK_BUTTONBOX_END + 5 + + + + True + True + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + + + + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + + + + + + 0 + False + False + + + + + + + + True + Firewall Update + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + True + False + False + + + + 10 + True + False + 10 + + + + True + gtk-dialog-info + 6 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + Please be patient while the firewall is installed... +Thank you! + False + True + GTK_JUSTIFY_CENTER + False + True + 0.5 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + + + + True + Advanced + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + False + False + + + + + 5 + True + False + 5 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + False + 5 + + + + True + False + 5 + + + + True + Reject with _ICMP-Code: + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + icmp_option_menu + + + 0 + False + True + + + + + + True + True + -1 + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + True + Reject TCP connections with RST-Flag + True + GTK_RELIEF_NORMAL + False + False + True + + + + 0 + False + False + + + + + + + + True + <b>Rejected connections</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + GTK_BUTTONBOX_END + 0 + + + + True + True + True + gtk-close + True + GTK_RELIEF_NORMAL + + + + + + 0 + True + True + + + + + + + diff --git a/fieryfilter.gladep b/fieryfilter.gladep new file mode 100644 index 0000000..4e0a889 --- /dev/null +++ b/fieryfilter.gladep @@ -0,0 +1,9 @@ + + + + + FieryFilter + fieryfilter + client + FALSE + diff --git a/fieryfilter.init b/fieryfilter.init new file mode 100755 index 0000000..4aab0eb --- /dev/null +++ b/fieryfilter.init @@ -0,0 +1,100 @@ +#!/bin/bash + +reset() { + iptables -D INPUT -j ffsys_in + iptables -D OUTPUT -j ffsys_out + iptables -D FORWARD -j ffsys_for + + iptables -F ffsys_in + iptables -X ffsys_in + iptables -F ffsys_out + iptables -X ffsys_out + iptables -F ffsys_for + iptables -X ffsys_for + iptables -F ffsys + iptables -X ffsys +} + +create() { + iptables -N ffsys + iptables -A ffsys -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT + iptables -A ffsys -m state --state ESTABLISHED -j ACCEPT + iptables -A ffsys -m state --state RELATED -j ACCEPT + iptables -A ffsys -m state --state NEW -j RETURN + iptables -A ffsys -j DROP + + iptables -N ffsys_in + iptables -A ffsys_in -p icmp --icmp-type destination-unreachable -j ACCEPT + iptables -A ffsys_in -j ffsys + + iptables -N ffsys_out + iptables -A ffsys_out -p icmp --icmp-type destination-unreachable -j ACCEPT + iptables -A ffsys_out -j ffsys + + grep nameserver /etc/resolv.conf | sed s/nameserver// | { + while read ip ; do + iptables -A ffsys_out -p udp --dport 53 -d $ip -j ACCEPT + done + } + + iptables -N ffsys_for + iptables -A ffsys_for -j ffsys +} + +activate() { + iptables -A INPUT -j ffsys_in + iptables -A OUTPUT -j ffsys_out + iptables -A FORWARD -j ffsys_for +} + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/local/sbin/fieryfilterd +NAME=fieryfilterd +DESC="FieryFilter daemon" + +test -x $DAEMON || exit 0 + +case "$1" in + start) + echo -n "Starting $DESC: $NAME" + if pidof $DAEMON > /dev/null ; then + echo " - already running." + else + modprobe iptable_filter + modprobe ip_queue + modprobe ip_conntrack_ftp + + reset 2> /dev/null + create + activate + + rm -f /tmp/fieryfilter + + ( $DAEMON 2>&1 ) | logger -p daemon.info -t fieryfilterd & + disown + echo "." + fi + ;; + stop) + echo -n "Stopping $DESC: $NAME" + if pidof $DAEMON > /dev/null ; then + killall -INT fieryfilterd + reset 2> /dev/null + echo "." + else + echo " - not running." + fi + ;; + restart|force-reload) + $0 stop + sleep 2 + $1 start + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/fieryfilter.sh b/fieryfilter.sh new file mode 100755 index 0000000..49faa6f --- /dev/null +++ b/fieryfilter.sh @@ -0,0 +1,8 @@ +#!/bin/sh + + + + + + + diff --git a/helper/Makefile.am b/helper/Makefile.am new file mode 100644 index 0000000..4f324fa --- /dev/null +++ b/helper/Makefile.am @@ -0,0 +1,22 @@ +INCLUDES = \ + -I/usr/include/libipq -Wall \ + @PACKAGE_CFLAGS@ + +EXTRA_DIST = xml-iptables xml-iptables-safe + +bin_PROGRAMS = install-firewall + +bin_SCRIPTS = xml-iptables xml-iptables-safe + +install_firewall_SOURCES = \ + install-firewall.c + +install_firewall_LDADD = @PACKAGE_LIBS@ + +install-exec-hook: + chown root $(bindir)/install-firewall + chmod u+s $(bindir)/install-firewall + +setuid: install-firewall + chown root install-firewall + chmod u+s install-firewall diff --git a/helper/default.fwx b/helper/default.fwx new file mode 100644 index 0000000..d10329d --- /dev/null +++ b/helper/default.fwx @@ -0,0 +1,42 @@ + + + + + + Test + incoming + udp + 0815 + port-unreachable + 1.1.1.1 + 24 + 1.2.1.1 + eth0 + eth0 + + accept + + + + HTTP + incoming + tcp + 80 + eth0 + reject + + + + IPP + incoming + udp + 635 + eth0 + drop + + + + + + + diff --git a/helper/install-firewall.c b/helper/install-firewall.c new file mode 100644 index 0000000..c42edd7 --- /dev/null +++ b/helper/install-firewall.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + +#include + +int group_member(gid_t gid) { + int n; + gid_t *g; + if ((n = getgroups(0, NULL)) < 0) + return -1; + + g = g_new(gid_t, n); + if (getgroups(n, g) < 0) { + g_free(g); + return -1; + } + + for (; n >= 0; n--) + if (g[n] == gid) { + g_free(g); + return 1; + } + + g_free(g); + return 0; +} + +int main(int argc, char *argv[]) { + struct group *gr; + + if (!(gr = getgrnam("fieryfilter"))) { + g_message("Could not find group fieryfilter\n"); + return 1; + } + + if (group_member(gr->gr_gid) != 1) { + fprintf(stderr, "I am sorry, you are not a member of the group \"fieryfilter\", access denied.\n"); + return 1; + } + + if (geteuid() != 0) { + fprintf(stderr, "Binary %s not SETUID.\n", argv[0]); + return 1; + } + + if (setuid(geteuid()) != 0) { + fprintf(stderr, "Cannot make uid=euid: %s\n", strerror(errno)); + return 1; + } + + if (setgid(0) != 0) { + fprintf(stderr, "Cannot set uid=0: %s\n", strerror(errno)); + return 1; + } + + if (setgroups(0, NULL) != 0) { + fprintf(stderr, "setgroups(0, NULL): %s\n", strerror(errno)); + return 1; + } + + if (execvp("xml-iptables-safe", argv) < 0) { + fprintf(stderr, "Could not run xml-iptables-safe: %s\n", strerror(errno)); + return 1; + } + + return 0; +} diff --git a/helper/xml-iptables b/helper/xml-iptables new file mode 100755 index 0000000..9f2d941 --- /dev/null +++ b/helper/xml-iptables @@ -0,0 +1,331 @@ +#!/usr/bin/python + +import sys +import xml.dom.minidom +import xml.parsers.expat + +DIR_ANY = 0 +DIR_INCOMING = 1 +DIR_OUTGOING = 2 +DIR_PASSING = 3 + +PROTO_ANY = 0 +PROTO_TCP = 1 +PROTO_UDP = 2 +PROTO_ICMP = 3 + +TARGET_DROP = 0 +TARGET_ACCEPT = 1 +TARGET_REJECT = 2 +TARGET_QUEUE = 3 + +ruleCount = 0 +outputFile = sys.stdout +unmatchTarget = TARGET_QUEUE +useTcpRst = False +icmpRejectCode = 3 + +icmpTable = ["echo-reply", + "pong", + "destination-unreachable", + "network-unreachable", + "host-unreachable", + "protocol-unreachable", + "port-unreachable", + "fragmentation-needed", + "source-route-failed", + "network-unknown", + "host-unknown", + "network-prohibited", + "host-prohibited", + "TOS-network-unreachable", + "TOS-host-unreachable", + "communication-prohibited", + "host-precedence-violation", + "precedence-cutoff", + "source-quench", + "redirect", + "network-redirect", + "host-redirect", + "TOS-network-redirect", + "TOS-host-redirect", + "echo-request", + "ping", + "router-advertisement", + "router-solicitation", + "time-exceeded", + "ttl-exceeded", + "ttl-zero-during-transit", + "ttl-zero-during-reassembly", + "parameter-problem", + "ip-header-bad", + "required-option-missing", + "timestamp-request", + "timestamp-reply", + "address-mask-request", + "address-mask-reply"] + + +def icmpRejectCodeValid(c): + return c in [0, 1, 2, 3, 9, 10] + +def icmpRejectCodeToString(c): + if c == 0: + return "icmp-net-unreachable" + elif c == 1: + return "icmp-host-unreachable" + elif c == 2: + return "icmp-proto-unreachable" + elif c == 9: + return "icmp-net-prohibited" + elif c == 10: + return "icmp-host-prohibited" + + return "icmp-port-unreachable" + +def targetFromString(t): + if t == "accept": + return TARGET_ACCEPT + elif t == "reject": + return TARGET_REJECT + elif t in ("query", "ask"): + return TARGET_QUEUE + else: + return TARGET_DROP + +def targetToString(t): + if t == TARGET_ACCEPT: + return "ACCEPT" + elif t == TARGET_REJECT: + return "ffuser_reject" + elif t == TARGET_QUEUE: + return "QUEUE" + else: + return "DROP" + +def writeRule(rule): + outputFile.write("### Rule %s\n" % rule["description"]) + ipt = "" + + if rule.has_key("protocol"): + if rule["protocol"] == PROTO_TCP or rule["protocol"] == PROTO_UDP: + + if rule["protocol"] == PROTO_UDP: + ipt += " -p udp" + else: + ipt += " -p tcp" + + + if rule.has_key("destination-port"): + ipt += " --destination-port %i" % int(rule["destination-port"]) + + elif rule["protocol"] == PROTO_ICMP: + ipt += " -p icmp" + + if rule.has_key("icmp-type"): + if rule["icmp-type"] in icmpTable: + ipt += " --icmp-type %s" % rule["icmp-type"] + + + if rule.has_key("source"): + ipt += " -s %s" % rule["source"]; + + if rule.has_key("destination"): + ipt += " -d %s" % rule["destination"]; + elif rule.has_key("broadcast"): + ipt += " -m pkttype --pkt-type broadcast" + elif rule.has_key("unicast"): + ipt += " -m pkttype --pkt-type unicast" + + if rule["direction"] != DIR_ANY: + if rule["direction"] in (DIR_PASSING, DIR_INCOMING) and rule.has_key("input-device"): + ipt += " -i %s" % rule["input-device"] + elif rule["direction"] in (DIR_PASSING, DIR_OUTGOING) and rule.has_key("output-device"): + ipt += " -o %s" % rule["output-device"] + + + ipt += " -j " + targetToString(rule["target"]) + + if rule["direction"] in (DIR_ANY, DIR_INCOMING): + outputFile.write("iptables -A ffuser_in%s\n" % ipt) + if rule["direction"] in (DIR_ANY, DIR_OUTGOING): + outputFile.write("iptables -A ffuser_out%s\n" % ipt) + if rule["direction"] in (DIR_ANY, DIR_PASSING): + outputFile.write("iptables -A ffuser_for%s\n" % ipt) + +def getText(nodelist): + rc = "" + for node in nodelist: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc + +def handleRule(rule): + global ruleCount, outputFile + + ruleCount = ruleCount+1 + + try: + id = int(rule.attributes["id"].value) + except KeyError: + id = 0 + + if not id: + id = ruleCount + + r = {} + r["id"] = id + + enabledl = rule.getElementsByTagName("disabled") + if len(enabledl): + return + + descl = rule.getElementsByTagName("description") + if len(descl): + r["description"] = "%s (#%i)" % (getText(descl[0].childNodes).strip(), id) + else: + r["description"] = "#%i" % id + + r["direction"] = DIR_ANY + dir = rule.getElementsByTagName("direction") + if len(dir): + t = getText(dir[0].childNodes) + if t == "incoming": + r["direction"] = DIR_INCOMING + elif t == "outgoing": + r["direction"] = DIR_OUTGOING + elif t in ("forwarding", "passing"): + r["direction"] = DIR_PASSING + + proto = rule.getElementsByTagName("protocol") + if len(proto): + t = getText(proto[0].childNodes) + if t == "icmp": + r["protocol"] = PROTO_ICMP + elif t == "tcp": + r["protocol"] = PROTO_TCP + elif t == "udp": + r["protocol"] = PROTO_UDP + + r["icmp-type"] = "ping" + + r["target"] = TARGET_DROP + target = rule.getElementsByTagName("target") + if len(target): + r["target"] = targetFromString(getText(target[0].childNodes)) + + src = rule.getElementsByTagName("source") + if len(src): + r["source"] = getText(src[0].childNodes).strip() + + dst = rule.getElementsByTagName("destination") + if len(dst): + r["destination"] = getText(dst[0].childNodes).strip() + + dstp = rule.getElementsByTagName("destination-port") + if len(dstp): + try: + r["destination-port"] = int(getText(dstp[0].childNodes)) + except: + pass + + + idev = rule.getElementsByTagName("input-device") + if len(idev): + r["input-device"] = getText(idev[0].childNodes) + + odev = rule.getElementsByTagName("output-device") + if len(odev): + r["output-device"] = getText(odev[0].childNodes) + + bc = rule.getElementsByTagName("broadcast") + if len(bc): + r["broadcast"] = 1 + else: + uc = rule.getElementsByTagName("unicast") + if len(uc): + r["unicast"] = 1 + + writeRule(r) + + +def handleRuleset(ruleset): + global outputFile, useTcpRst, icmpRejectCode, unmatchVerdict + + outputFile.write("#!/bin/sh\n\n" + "### Try to deactivate chains\n" + "iptables -D ffsys_in -j ffuser_in &> /dev/null\n" + "iptables -D ffsys_out -j ffuser_out &> /dev/null\n" + "iptables -D ffsys_for -j ffuser_for &> /dev/null\n\n" + "set -e\n\n" + "### Create chains\n" + "iptables -F ffuser_in 2> /dev/null || iptables -N ffuser_in || exit 1\n" + "iptables -F ffuser_out 2> /dev/null || iptables -N ffuser_out || exit 2\n" + "iptables -F ffuser_for 2> /dev/null || iptables -N ffuser_for || exit 3\n\n" + "### Create reject chain\n" + "iptables -F ffuser_reject 2> /dev/null || iptables -N ffuser_reject || exit 4\n") + + + rs = ruleset.getElementsByTagName("ruleset")[0] + + utr = rs.getElementsByTagName("use-tcp-reject") + useTcpRst = len(utr) != 0; + + icr = rs.getElementsByTagName("icmp-reject-code") + if len(icr): + icmpRejectCode = int(getText(icr[0].childNodes)) + + if useTcpRst: + outputFile.write("iptables -A ffuser_reject -p tcp -j REJECT --reject-with=tcp-reset\n") + + if icmpRejectCodeValid(icmpRejectCode): + outputFile.write("iptables -A ffuser_reject -j REJECT --reject-with=%s\n" % icmpRejectCodeToString(icmpRejectCode)) + else: + outputFile.write("iptables -A ffuser_reject -j REJECT\n"); + + outputFile.write("\n"); + + ir = rs.getElementsByTagName("ignore-rules") + if not len(ir): + rules = rs.getElementsByTagName("rule") + for r in rules: + handleRule(r) + + uv = rs.getElementsByTagName("unmatch-verdict") + if len(uv): + unmatchTarget = targetFromString(getText(uv[0].childNodes)) + + + t = targetToString(unmatchTarget) + + outputFile.write("\n### Set unmatch target \n" + "iptables -A ffuser_in -j %s\n" + "iptables -A ffuser_out -j %s\n" + "iptables -A ffuser_for -j %s\n\n" + % (t, t, t)); + + + outputFile.write("### Now activate all rules\n" + "iptables -A ffsys_in -j ffuser_in\n" + "iptables -A ffsys_out -j ffuser_out\n" + "iptables -A ffsys_for -j ffuser_for\n\n" + "set +ex\n"); + +def main(): + if len(sys.argv) > 1: + f = open(sys.argv[1], "r") + else: + f = sys.stdin + + try: + dom = xml.dom.minidom.parse(f) + handleRuleset(dom) + except xml.parsers.expat.ExpatError, e: + sys.stderr.write("%s\n" % str(e)) + sys.exit(1) + + + +main() + + diff --git a/helper/xml-iptables-safe b/helper/xml-iptables-safe new file mode 100755 index 0000000..22e4804 --- /dev/null +++ b/helper/xml-iptables-safe @@ -0,0 +1,29 @@ +#!/bin/bash + +[ `id -u` = 0 ] || exit 1 + +export PATH=/sbin:/usr/local/sbin/:/usr/sbin:$PATH + +TEMP1=`tempfile` +TEMP2=`tempfile` +chmod 600 $TEMP1 $TEMP2 + +iptables-save > $TEMP1 +xml-iptables $1 > $TEMP2 +ret=$? + +if [ "$ret" = "0" ] ; then + . $TEMP2 + ret=$? +fi + +if [ "$ret" = "0" ] ; then + echo "Firewall installation succeeded." 2>&1 +else + echo "Firewall installation failed." 2>&1 + iptables-restore < $TEMP1 +fi + +rm -f $TEMP1 $TEMP2 + +exit $ret -- cgit