1 /* firewall_rules_dlg.c
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Generate firewall ACL rules based on packet addresses and ports.
22 * For directional rules, an outside interface is assumed.
24 * There may be better ways to present the information, e.g. all rules
25 * in one huge text window, or some sort of tree view.
29 * To add a new product, add syntax functions modify the products[] array.
31 * To add a new syntax function, add its prototype above the products[]
32 * array, and add the function below with all the others.
35 /* Copied from ssl-dlg.c */
52 #include <epan/packet.h>
53 #include <epan/addr_resolv.h>
54 #include <epan/epan_dissect.h>
55 #include <epan/filesystem.h>
56 #include <epan/dissectors/packet-ipv6.h>
58 #include <ui/alert_box.h>
59 #include <ui/last_open_dir.h>
61 #include <wsutil/file_util.h>
63 #include "ui/gtk/main.h"
64 #include "ui/gtk/dlg_utils.h"
65 #include "ui/gtk/file_dlg.h"
66 #include "ui/gtk/help_dlg.h"
67 #include "ui/gtk/gui_utils.h"
68 #include "ui/gtk/old-gtk-compat.h"
69 #include "ui/gtk/firewall_dlg.h"
71 #define MAX_RULE_LEN 200
88 /* Copied from packet_info struct */
89 typedef struct _rule_info_t {
99 GtkWidget *filter_combo_box;
101 GtkWidget *inbound_cb;
102 GtkWidget *firewall_save_as_w;
105 rule_type_t rule_type;
108 /* Syntax function prototypes */
109 typedef void (*syntax_func)(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
111 static void sf_dummy(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
113 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
114 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
116 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
117 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
118 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
119 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
120 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
121 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
122 /* XXX - Can you addresses-only filters using WFW/netsh? */
124 static void sf_ios_ext_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
125 static void sf_ipfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
126 static void sf_ipfw_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
127 static void sf_netfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
128 static void sf_pf_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
129 static void sf_netsh_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
131 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
132 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
133 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
134 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
135 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
136 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
138 typedef struct _fw_product_t {
140 const gchar *comment_pfx;
141 syntax_func mac_func;
142 syntax_func ipv4_func;
143 syntax_func port_func;
144 syntax_func ipv4_port_func;
145 gboolean does_inbound;
148 static fw_product products[] = {
149 { "Cisco IOS (standard)", "!", NULL, sf_ios_std_ipv4, NULL, NULL, FALSE },
150 { "Cisco IOS (extended)", "!",
151 NULL, sf_ios_ext_ipv4, sf_ios_ext_port, sf_ios_ext_ipv4_port, TRUE },
152 { "IP Filter (ipfilter)", "#",
153 NULL, sf_ipfilter_ipv4, sf_ipfilter_port, sf_ipfilter_ipv4_port, TRUE },
154 { "IPFirewall (ipfw)", "#",
155 sf_ipfw_mac, sf_ipfw_ipv4, sf_ipfw_port, sf_ipfw_ipv4_port, TRUE },
156 { "Netfilter (iptables)", "#",
157 sf_netfilter_mac, sf_netfilter_ipv4, sf_netfilter_port,
158 sf_netfilter_ipv4_port, TRUE },
159 { "Packet Filter (pf)", "#",
160 NULL, sf_pf_ipv4, sf_pf_port, sf_pf_ipv4_port, TRUE },
161 { "Windows Firewall (netsh)", "#",
162 NULL, NULL, sf_netsh_port, sf_netsh_ipv4_port, FALSE }
164 #define NUM_PRODS (sizeof(products) / sizeof(fw_product))
167 static void select_product(GtkWidget * win, gpointer data);
168 static void select_filter(GtkWidget * win, gpointer data);
169 static void toggle_inbound(GtkToggleButton *t, gpointer data);
170 static void toggle_deny(GtkToggleButton *t, gpointer data);
171 static void set_rule_text(rule_info_t *rule_info);
172 static void firewall_destroy_cb(GtkWidget * win, gpointer data);
173 static void firewall_copy_cmd_cb(GtkWidget * w, gpointer data);
174 static void firewall_save_as_cmd_cb(GtkWidget * w, gpointer data);
175 static gboolean firewall_save_as_ok_cb(GtkWidget * w, gpointer fs);
176 static void firewall_save_as_destroy_cb(GtkWidget * win, gpointer user_data);
178 #define WS_RULE_INFO_KEY "rule_info_key"
181 /* List of "rule_info_t" structures for all rule windows. */
182 static GList *rule_infos;
184 /* Remove a "rule_info_t" structure from the list. */
186 forget_rule_info(rule_info_t *rule_info)
188 rule_infos = g_list_remove(rule_infos, rule_info);
193 firewall_rule_cb(GtkWidget *w _U_, gpointer data _U_)
195 GtkWidget *rule_w, *vbox, *txt_scrollw, *text;
196 GtkWidget *label, *product_combo_box;
197 GtkWidget *hbox, *button_hbox, *button;
198 rule_info_t *rule_info;
199 packet_info *pinfo = &cfile.edt->pi;
202 rule_info = g_new0(rule_info_t, 1);
203 COPY_ADDRESS(&(rule_info->dl_src), &(pinfo->dl_src));
204 COPY_ADDRESS(&(rule_info->dl_dst), &(pinfo->dl_dst));
205 COPY_ADDRESS(&(rule_info->net_src), &(pinfo->net_src));
206 COPY_ADDRESS(&(rule_info->net_dst), &(pinfo->net_dst));
207 rule_info->ptype = pinfo->ptype;
208 rule_info->srcport = pinfo->srcport;
209 rule_info->destport = pinfo->destport;
210 rule_info->inbound = TRUE;
211 rule_info->deny = TRUE;
212 rule_info->product = 0;
214 rule_w = dlg_window_new("Firewall ACL Rules");
216 gtk_widget_set_name(rule_w, "Firewall ACL rule window");
217 gtk_container_set_border_width(GTK_CONTAINER(rule_w), 6);
219 /* setup the container */
220 vbox = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
221 gtk_container_add(GTK_CONTAINER(rule_w), vbox);
223 /* rule type selectors hbox */
224 hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1, FALSE);
225 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
227 /* product selector */
228 label = gtk_label_new("Product");
229 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
231 product_combo_box = gtk_combo_box_text_new();
232 for (i = 0; i < NUM_PRODS; i++) {
233 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(product_combo_box), products[i].name);
235 g_object_set_data(G_OBJECT(product_combo_box), WS_RULE_INFO_KEY, rule_info);
236 g_signal_connect(product_combo_box, "changed", G_CALLBACK(select_product), NULL);
237 gtk_box_pack_start(GTK_BOX(hbox), product_combo_box, FALSE, FALSE, 5);
240 label = gtk_label_new("Filter");
241 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
243 rule_info->filter_combo_box = ws_combo_box_new_text_and_pointer();
244 g_object_set_data(G_OBJECT(rule_info->filter_combo_box), WS_RULE_INFO_KEY, rule_info); \
245 g_signal_connect(rule_info->filter_combo_box, "changed", G_CALLBACK(select_filter), NULL);
246 gtk_box_pack_start(GTK_BOX(hbox), rule_info->filter_combo_box, FALSE, FALSE, 5);
248 /* inbound selector */
249 rule_info->inbound_cb = gtk_check_button_new_with_label("Inbound");
250 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->inbound_cb),
252 gtk_box_pack_start(GTK_BOX(hbox), rule_info->inbound_cb, FALSE, FALSE, 10);
253 g_signal_connect(rule_info->inbound_cb, "toggled", G_CALLBACK(toggle_inbound), rule_info);
256 rule_info->deny_cb = gtk_check_button_new_with_label("Deny");
257 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->deny_cb),
259 gtk_box_pack_start(GTK_BOX(hbox), rule_info->deny_cb, FALSE, FALSE, 10);
260 g_signal_connect(rule_info->deny_cb, "toggled", G_CALLBACK(toggle_deny), rule_info);
262 /* create a scrolled window for the text */
263 txt_scrollw = scrolled_window_new(NULL, NULL);
264 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scrollw),
266 gtk_box_pack_start(GTK_BOX(vbox), txt_scrollw, TRUE, TRUE, 0);
268 /* create a text box */
269 text = gtk_text_view_new();
270 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
271 gtk_container_add(GTK_CONTAINER(txt_scrollw), text);
272 rule_info->text = text;
275 button_hbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_COPY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
276 gtk_box_pack_start(GTK_BOX(vbox), button_hbox, FALSE, FALSE, 0);
278 /* Create Copy Button */
279 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_COPY);
280 g_signal_connect(button, "clicked", G_CALLBACK(firewall_copy_cmd_cb), rule_info);
281 gtk_widget_set_tooltip_text(button, "Copy rule to clipboard");
283 /* Create Save Button */
284 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_SAVE);
285 g_signal_connect(button, "clicked", G_CALLBACK(firewall_save_as_cmd_cb), rule_info);
286 gtk_widget_set_tooltip_text(button, "Save the rule as currently displayed");
288 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_CANCEL);
289 gtk_widget_set_tooltip_text(button, "Cancel the dialog");
290 window_set_cancel_button(rule_w, button, window_cancel_button_cb);
292 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_HELP);
293 g_signal_connect(button, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_FIREWALL_DIALOG);
295 /* Tuck away the rule_info object into the window */
296 g_object_set_data(G_OBJECT(rule_w), WS_RULE_INFO_KEY, rule_info);
298 g_signal_connect(rule_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
299 g_signal_connect(rule_w, "destroy", G_CALLBACK(firewall_destroy_cb), NULL);
301 /* Make sure this widget gets destroyed if we quit the main loop,
302 so that if we exit, we clean up any temporary files we have
303 for "Follow SSL Stream" windows.
304 gtk_quit_add_destroy is deprecated and should not be used in newly-written code. This function is going to be removed in GTK+ 3.0
306 gtk_quit_add_destroy(gtk_main_level(), GTK_OBJECT(rule_w));
310 gtk_combo_box_set_active(GTK_COMBO_BOX(product_combo_box), 0); /* invokes select_product callback */
311 gtk_widget_show_all(rule_w);
312 window_present(rule_w);
315 /* Set the current product. */
316 #define ADD_TO_FILTER_MENU(rt) \
317 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(rule_info->filter_combo_box), name, GUINT_TO_POINTER(rt)); \
318 if (rule_type == RT_NONE) { \
322 #define NAME_TCP_UDP (rule_info->ptype == PT_TCP ? "TCP" : "UDP")
325 select_product(GtkWidget *w, gpointer data _U_)
327 guint prod = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
328 rule_info_t *rule_info;
329 gchar name[MAX_RULE_LEN], addr_str[MAX_RULE_LEN];
331 rule_type_t rule_type = RT_NONE;
332 gboolean sensitive = FALSE;
334 rule_info =(rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
336 if (prod >= NUM_PRODS || !rule_info)
339 rule_info->product = prod;
341 /* Clear the list store (ie: the como_box list items) */
342 ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(rule_info->filter_combo_box));
344 /* Fill in valid combo_box list items (in the list store). */
345 if (products[prod].mac_func && rule_info->dl_src.type == AT_ETHER) {
346 addr = &(rule_info->dl_src);
347 address_to_str_buf(addr, name, MAX_RULE_LEN);
348 ADD_TO_FILTER_MENU(RT_MAC_SRC);
350 addr = &(rule_info->dl_dst);
351 address_to_str_buf(addr, name, MAX_RULE_LEN);
352 ADD_TO_FILTER_MENU(RT_MAC_DST);
355 if (products[prod].ipv4_func && rule_info->net_src.type == AT_IPv4) {
356 addr = &(rule_info->net_src);
357 address_to_str_buf(addr, name, MAX_RULE_LEN);
358 ADD_TO_FILTER_MENU(RT_IPv4_SRC);
360 addr = &(rule_info->net_dst);
361 address_to_str_buf(addr, name, MAX_RULE_LEN);
362 ADD_TO_FILTER_MENU(RT_IPv4_DST);
365 if (products[prod].port_func && (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
366 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
368 ADD_TO_FILTER_MENU(RT_PORT_SRC);
369 if (rule_info->srcport != rule_info->destport) {
370 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
371 rule_info->destport);
372 ADD_TO_FILTER_MENU(RT_PORT_DST);
376 if (products[prod].ipv4_port_func && rule_info->net_src.type == AT_IPv4 &&
377 (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
378 addr = &(rule_info->net_src);
379 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
380 g_snprintf(name, MAX_RULE_LEN, "%s + %s port %u", addr_str,
381 NAME_TCP_UDP, rule_info->srcport);
382 ADD_TO_FILTER_MENU(RT_IPv4_PORT_SRC);
384 addr = &(rule_info->net_dst);
385 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
386 g_snprintf(name, MAX_RULE_LEN, "%s + %s port %u", addr_str,
387 NAME_TCP_UDP, rule_info->destport);
388 ADD_TO_FILTER_MENU(RT_IPv4_PORT_DST);
391 if (rule_type != RT_NONE) {
392 gtk_combo_box_set_active(GTK_COMBO_BOX(rule_info->filter_combo_box), 0); /* invokes select_filter callback */
395 select_filter(rule_info->filter_combo_box, NULL); /* Call if RT_NONE [with nothing selected] */
398 gtk_widget_set_sensitive(rule_info->filter_combo_box, sensitive);
399 gtk_widget_set_sensitive(rule_info->inbound_cb, products[prod].does_inbound && sensitive);
400 gtk_widget_set_sensitive(rule_info->deny_cb, sensitive);
403 /* Set the rule text based upon the current product and current filter. */
405 select_filter(GtkWidget *w, gpointer data _U_)
407 rule_type_t cur_type;
408 rule_info_t *rule_info;
411 rule_info = (rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
416 if (ws_combo_box_get_active_pointer(GTK_COMBO_BOX(w), &ptr))
417 cur_type = (rule_type_t)GPOINTER_TO_UINT(ptr);
419 cur_type = RT_NONE; /* If nothing selected (eg: nothing in filter list) */
421 if (cur_type >= NUM_RULE_TYPES)
424 rule_info->rule_type = cur_type;
426 set_rule_text(rule_info);
429 /* Set inbound/outbound */
431 toggle_inbound(GtkToggleButton *t, gpointer data)
433 rule_info_t *rule_info = (rule_info_t *) data;
435 rule_info->inbound = gtk_toggle_button_get_active(t);
437 set_rule_text(rule_info);
440 /* Set deny/allow. */
442 toggle_deny(GtkToggleButton *t, gpointer data)
444 rule_info_t *rule_info = (rule_info_t *) data;
446 rule_info->deny = gtk_toggle_button_get_active(t);
448 set_rule_text(rule_info);
451 /* Set the rule text */
452 #define DL_ADDR (rt == RT_MAC_SRC ? &(rule_info->dl_src) : &(rule_info->dl_dst))
453 #define NET_ADDR (rt == RT_IPv4_SRC ? &(rule_info->net_src) : &(rule_info->net_dst))
454 #define NET_PORT (rt == RT_PORT_SRC ? rule_info->srcport : rule_info->destport)
456 set_rule_text(rule_info_t *rule_info) {
457 GString *rtxt = g_string_new("");
458 gchar addr_str[MAX_RULE_LEN];
459 rule_type_t rt = rule_info->rule_type;
460 guint prod = rule_info->product;
461 address *addr = NULL;
463 syntax_func rt_func = NULL;
465 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
467 if (prod < NUM_PRODS) {
468 g_string_printf(rtxt, "%s %s\n", products[prod].comment_pfx, products[prod].name);
471 g_string_append_printf(rtxt, "%s Not supported", products[prod].comment_pfx);
477 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
478 rt_func = products[prod].mac_func;
483 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
484 rt_func = products[prod].ipv4_func;
489 rt_func = products[prod].port_func;
491 case RT_IPv4_PORT_SRC:
492 case RT_IPv4_PORT_DST:
494 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
496 rt_func = products[prod].ipv4_port_func;
504 rt_func(rtxt, addr_str, port, rule_info->ptype, rule_info->inbound, rule_info->deny);
506 g_string_append_printf(rtxt, "ERROR: Unable to create rule");
509 gtk_text_buffer_set_text(buf, rtxt->str, (gint) rtxt->len);
511 g_string_free(rtxt, TRUE);
515 /* Rule text functions */
517 static void sf_dummy(GString *rtxt _U_, gchar *addr _U_, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny _U_) {
521 #define IPFW_DENY (deny ? "deny" : "allow")
522 #define IPFW_IN (inbound ? "in" : "out")
523 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
524 g_string_append_printf(rtxt, "add %s MAC %s any %s",
525 IPFW_DENY, addr, IPFW_IN);
528 #define NF_DROP (deny ? "DROP" : "ACCEPT")
529 #define NF_INPUT (inbound ? "INPUT" : "OUTPUT")
530 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
531 g_string_append_printf(rtxt, "iptables -A %s --mac-source %s -j %s",
532 NF_INPUT, addr, NF_DROP);
536 #define IOS_DENY (deny ? "deny" : "permit")
537 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny) {
538 g_string_append_printf(rtxt, "access-list NUMBER %s host %s", IOS_DENY, addr);
541 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
543 g_string_append_printf(rtxt, "access-list NUMBER %s ip host %s any", IOS_DENY, addr);
545 g_string_append_printf(rtxt, "access-list NUMBER %s ip any host %s", IOS_DENY, addr);
548 #define IPFILTER_DENY (deny ? "block" : "pass")
549 #define IPFILTER_IN (inbound ? "in" : "out")
550 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
551 g_string_append_printf(rtxt, "%s %s on le0 from %s to any",
552 IPFILTER_DENY, IPFILTER_IN, addr);
555 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
556 g_string_append_printf(rtxt, "add %s ip from %s to any %s",
557 IPFW_DENY, addr, IPFW_IN);
560 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
561 g_string_append_printf(rtxt, "iptables -A %s -i eth0 -d %s/32 -j %s",
562 NF_INPUT, addr, NF_DROP);
565 #define PF_DENY (deny ? "block" : "pass")
566 #define PF_IN (inbound ? "in" : "out")
567 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
568 g_string_append_printf(rtxt, "%s %s quick on $ext_if from %s to any",
569 PF_DENY, PF_IN, addr);
573 #define RT_TCP_UDP (ptype == PT_TCP ? "tcp" : "udp")
574 static void sf_ios_ext_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
575 g_string_append_printf(rtxt, "access-list NUMBER %s %s any any eq %u",
576 IOS_DENY, RT_TCP_UDP, port);
579 static void sf_ipfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype _U_, gboolean inbound, gboolean deny) {
580 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to any port = %u",
581 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, port);
584 static void sf_ipfw_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
585 g_string_append_printf(rtxt, "add %s %s from any to any %u %s",
586 IPFW_DENY, RT_TCP_UDP, port, IPFW_IN);
589 static void sf_netfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
590 g_string_append_printf(rtxt, "iptables -A %s -p %s --destination-port %u -j %s",
591 NF_INPUT, RT_TCP_UDP, port, NF_DROP);
594 static void sf_pf_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
595 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from any to any port %u",
596 PF_DENY, PF_IN, RT_TCP_UDP, port);
599 #define NETSH_DENY (deny ? "DISABLE" : "ENABLE")
600 static void sf_netsh_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
601 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s",
602 RT_TCP_UDP, port, NETSH_DENY);
606 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
608 g_string_append_printf(rtxt, "access-list NUMBER %s %s host %s any eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
610 g_string_append_printf(rtxt, "access-list NUMBER %s %s any host %s eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
613 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
615 g_string_append_printf(rtxt, "%s %s on le0 proto %s from %s to any port = %u",
616 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
618 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to %s port = %u",
619 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
622 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
623 g_string_append_printf(rtxt, "add %s %s from %s to any %u %s",
624 IPFW_DENY, RT_TCP_UDP, addr, port, IPFW_IN);
627 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
628 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from %s to any port %u",
629 PF_DENY, PF_IN, RT_TCP_UDP, addr, port);
632 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
633 g_string_append_printf(rtxt, "iptables -A %s -p %s -d %s/32 --destination-port %u -j %s",
634 NF_INPUT, RT_TCP_UDP, addr, port, NF_DROP);
637 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
638 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s %s",
639 RT_TCP_UDP, port, NETSH_DENY, addr);
642 /* The destroy call back has the responsibility of
643 * unlinking the temporary file
644 * and freeing the filter_out_filter */
646 firewall_destroy_cb(GtkWidget *w, gpointer data _U_)
648 rule_info_t *rule_info;
650 rule_info = (rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
652 forget_rule_info(rule_info);
655 gtk_widget_destroy(w);
659 firewall_copy_cmd_cb(GtkWidget *w _U_, gpointer data)
661 rule_info_t *rule_info = (rule_info_t *)data;
663 GtkTextIter start, end;
666 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
667 gtk_text_buffer_get_start_iter(buf, &start);
668 gtk_text_buffer_get_end_iter(buf, &end);
669 gtk_text_buffer_select_range(buf, &start, &end);
670 gtk_text_buffer_copy_clipboard(buf, gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
674 * Keep a static pointer to the current "Save SSL Follow Stream As" window, if
675 * any, so that if somebody tries to do "Save"
676 * while there's already a "Save SSL Follow Stream" window up, we just pop
677 * up the existing one, rather than creating a new one.
680 firewall_save_as_cmd_cb(GtkWidget *w _U_, gpointer data)
682 GtkWidget *caller = gtk_widget_get_toplevel(w);
684 rule_info_t *rule_info = (rule_info_t *)data;
686 new_win = file_selection_new("Wireshark: Save Firewall ACL Rule",
688 FILE_SELECTION_SAVE);
689 rule_info->firewall_save_as_w = new_win;
691 /* Tuck away the rule_info object into the window */
692 g_object_set_data(G_OBJECT(new_win), WS_RULE_INFO_KEY, rule_info);
694 g_signal_connect(new_win, "destroy", G_CALLBACK(firewall_save_as_destroy_cb), rule_info);
697 if (gtk_dialog_run(GTK_DIALOG(new_win)) == GTK_RESPONSE_ACCEPT)
699 firewall_save_as_ok_cb(new_win, new_win);
701 window_destroy(new_win);
704 /* "Run" the GtkFileChooserDialog. */
705 /* Upon exit: If "Accept" run the OK callback. */
706 /* If the OK callback returns with a FALSE status, re-run the dialog.*/
707 /* If not accept (ie: cancel) destroy the window. */
708 /* XXX: If the OK callback pops up an alert box (eg: for an error) it *must* */
709 /* return with a TRUE status so that the dialog window will be destroyed. */
710 /* Trying to re-run the dialog after popping up an alert box will not work */
711 /* since the user will not be able to dismiss the alert box. */
712 /* The (somewhat unfriendly) effect: the user must re-invoke the */
713 /* GtkFileChooserDialog whenever the OK callback pops up an alert box. */
715 /* ToDo: use GtkFileChooserWidget in a dialog window instead of */
716 /* GtkFileChooserDialog. */
717 while (gtk_dialog_run(GTK_DIALOG(new_win)) == GTK_RESPONSE_ACCEPT) {
718 if (firewall_save_as_ok_cb(NULL, new_win)) {
719 break; /* we're done */
722 window_destroy(new_win);
728 firewall_save_as_ok_cb(GtkWidget * w _U_, gpointer fs)
730 gchar *to_name, *rule;
731 rule_info_t *rule_info;
735 GtkTextIter start, end;
738 to_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
740 /* Perhaps the user specified a directory instead of a file.
741 Check whether they did. */
742 if (test_for_directory(to_name) == EISDIR) {
743 /* It's a directory - set the file selection box to display that
744 directory, and leave the selection box displayed. */
745 set_last_open_dir(to_name);
747 file_selection_set_current_folder((GtkWidget *)fs, get_last_open_dir());
748 gtk_file_chooser_set_current_name((GtkFileChooser *)fs, "");
749 return FALSE; /* run the dialog again */
752 rule_info = (rule_info_t *)g_object_get_data(G_OBJECT(fs), WS_RULE_INFO_KEY);
753 fh = ws_fopen(to_name, "w");
755 open_failure_alert_box(to_name, errno, TRUE);
760 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
761 gtk_text_buffer_get_start_iter(buf, &start);
762 gtk_text_buffer_get_end_iter(buf, &end);
763 rule = gtk_text_buffer_get_text(buf, &start, &end, FALSE);
768 #if 0 /* handled by caller (for now) */
769 gtk_widget_hide(GTK_WIDGET(fs));
770 window_destroy(GTK_WIDGET(fs));
772 /* Save the directory name for future file dialogs. */
773 dirname = get_dirname(to_name); /* Overwrites to_name */
774 set_last_open_dir(dirname);
781 firewall_save_as_destroy_cb(GtkWidget * win _U_, gpointer data)
783 rule_info_t *rule_info = (rule_info_t *)data;
785 /* Note that we no longer have a dialog box. */
786 rule_info->firewall_save_as_w = NULL;