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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 */
56 #include <epan/prefs.h>
57 #include <epan/packet.h>
58 #include <epan/addr_resolv.h>
59 #include <epan/charsets.h>
60 #include <epan/epan_dissect.h>
61 #include <epan/filesystem.h>
62 #include <epan/ipproto.h>
63 #include <epan/dissectors/packet-ipv6.h>
65 #include <../globals.h>
66 #include <../alert_box.h>
67 #include <../simple_dialog.h>
69 #include <wsutil/file_util.h>
72 #include <gtk/dlg_utils.h>
73 #include <gtk/file_dlg.h>
74 #include <gtk/help_dlg.h>
76 #include <gtk/gui_utils.h>
77 #include <gtk/font_utils.h>
78 #include "gtk/firewall_dlg.h"
80 #define MAX_RULE_LEN 200
97 /* Copied from packet_info struct */
98 typedef struct _rule_info_t {
108 GtkWidget *filter_om;
110 GtkWidget *inbound_cb;
111 GtkWidget *firewall_save_as_w;
114 rule_type_t rule_type;
117 /* Syntax function prototypes */
118 typedef void (*syntax_func)(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
120 static void sf_dummy(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
122 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
123 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
125 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
126 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
127 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
128 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
129 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
130 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
131 /* XXX - Can you addresses-only filters using WFW/netsh? */
133 static void sf_ios_ext_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
134 static void sf_ipfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
135 static void sf_ipfw_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
136 static void sf_netfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
137 static void sf_pf_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
138 static void sf_netsh_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
140 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
141 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
142 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
143 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
144 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
145 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
147 typedef struct _fw_product_t {
150 syntax_func mac_func;
151 syntax_func ipv4_func;
152 syntax_func port_func;
153 syntax_func ipv4_port_func;
154 gboolean does_inbound;
157 fw_product products[] = {
158 { "Cisco IOS (standard)", "!", NULL, sf_ios_std_ipv4, NULL, NULL, FALSE },
159 { "Cisco IOS (extended)", "!",
160 NULL, sf_ios_ext_ipv4, sf_ios_ext_port, sf_ios_ext_ipv4_port, TRUE },
161 { "IP Filter (ipfilter)", "#",
162 NULL, sf_ipfilter_ipv4, sf_ipfilter_port, sf_ipfilter_ipv4_port, TRUE },
163 { "IPFirewall (ipfw)", "#",
164 sf_ipfw_mac, sf_ipfw_ipv4, sf_ipfw_port, sf_ipfw_ipv4_port, TRUE },
165 { "Netfilter (iptables)", "#",
166 sf_netfilter_mac, sf_netfilter_ipv4, sf_netfilter_port,
167 sf_netfilter_ipv4_port, TRUE },
168 { "Packet Filter (pf)", "#",
169 NULL, sf_pf_ipv4, sf_pf_port, sf_pf_ipv4_port, TRUE },
170 { "Windows Firewall (netsh)", "#",
171 NULL, NULL, sf_netsh_port, sf_netsh_ipv4_port, FALSE }
173 #define NUM_PRODS (sizeof(products) / sizeof(fw_product))
176 static void select_product(GtkWidget * win, gpointer data);
177 static void select_filter(GtkWidget * win, gpointer data);
178 static void toggle_inbound(GtkToggleButton *t, gpointer data);
179 static void toggle_deny(GtkToggleButton *t, gpointer data);
180 static void set_rule_text(rule_info_t *rule_info);
181 static void firewall_destroy_cb(GtkWidget * win, gpointer data);
182 static void firewall_copy_cmd_cb(GtkWidget * w, gpointer data);
183 static void firewall_save_as_cmd_cb(GtkWidget * w, gpointer data);
184 static void firewall_save_as_ok_cb(GtkWidget * w, gpointer fs);
185 static void firewall_save_as_destroy_cb(GtkWidget * win, gpointer user_data);
187 #define WS_RULE_INFO_KEY "rule_info_key"
189 /* List of "rule_info_t" structures for all rule windows. */
190 static GList *rule_infos;
192 /* Remove a "rule_info_t" structure from the list. */
194 forget_rule_info(rule_info_t *rule_info)
196 rule_infos = g_list_remove(rule_infos, rule_info);
200 firewall_rule_cb(GtkWidget *w _U_, gpointer data _U_)
202 GtkWidget *rule_w, *vbox, *txt_scrollw, *text;
203 GtkWidget *label, *product_om, *menu, *menu_item;
204 GtkWidget *hbox, *button_hbox, *button;
205 GtkTooltips *tooltips;
206 rule_info_t *rule_info;
207 packet_info *pinfo = &cfile.edt->pi;
210 rule_info = g_new0(rule_info_t, 1);
211 COPY_ADDRESS(&(rule_info->dl_src), &(pinfo->dl_src));
212 COPY_ADDRESS(&(rule_info->dl_dst), &(pinfo->dl_dst));
213 COPY_ADDRESS(&(rule_info->net_src), &(pinfo->net_src));
214 COPY_ADDRESS(&(rule_info->net_dst), &(pinfo->net_dst));
215 rule_info->ptype = pinfo->ptype;
216 rule_info->srcport = pinfo->srcport;
217 rule_info->destport = pinfo->destport;
218 rule_info->inbound = TRUE;
219 rule_info->deny = TRUE;
220 rule_info->product = 0;
222 rule_w = dlg_window_new("Firewall ACL Rules");
224 gtk_widget_set_name(rule_w, "Firewall ACL rule window");
225 gtk_container_border_width(GTK_CONTAINER(rule_w), 6);
227 /* setup the container */
228 tooltips = gtk_tooltips_new ();
230 vbox = gtk_vbox_new(FALSE, 6);
231 gtk_container_add(GTK_CONTAINER(rule_w), vbox);
233 /* rule type selectors hbox */
234 hbox = gtk_hbox_new(FALSE, 1);
235 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
237 /* product selector */
238 label = gtk_label_new("Product");
239 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
241 product_om = gtk_option_menu_new();
242 menu = gtk_menu_new();
243 for (i = 0; i < NUM_PRODS; i++) {
244 menu_item = gtk_menu_item_new_with_label(products[i].name);
245 g_signal_connect(menu_item, "activate", G_CALLBACK(select_product), GUINT_TO_POINTER(i));
246 g_object_set_data(G_OBJECT(menu_item), WS_RULE_INFO_KEY, rule_info);
247 gtk_menu_append(GTK_MENU(menu), menu_item);
249 gtk_menu_item_select(GTK_MENU_ITEM(menu_item)); */
251 gtk_option_menu_set_menu(GTK_OPTION_MENU(product_om), menu);
252 gtk_box_pack_start(GTK_BOX(hbox), product_om, FALSE, FALSE, 5);
255 label = gtk_label_new("Filter");
256 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
258 rule_info->filter_om = gtk_option_menu_new();
259 gtk_box_pack_start(GTK_BOX(hbox), rule_info->filter_om, FALSE, FALSE, 5);
261 /* inbound selector */
262 rule_info->inbound_cb = gtk_check_button_new_with_label("Inbound");
263 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->inbound_cb),
265 gtk_box_pack_start(GTK_BOX(hbox), rule_info->inbound_cb, FALSE, FALSE, 10);
266 g_signal_connect(rule_info->inbound_cb, "toggled", G_CALLBACK(toggle_inbound), rule_info);
269 rule_info->deny_cb = gtk_check_button_new_with_label("Deny");
270 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->deny_cb),
272 gtk_box_pack_start(GTK_BOX(hbox), rule_info->deny_cb, FALSE, FALSE, 10);
273 g_signal_connect(rule_info->deny_cb, "toggled", G_CALLBACK(toggle_deny), rule_info);
275 /* create a scrolled window for the text */
276 txt_scrollw = scrolled_window_new(NULL, NULL);
277 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scrollw),
279 gtk_box_pack_start(GTK_BOX(vbox), txt_scrollw, TRUE, TRUE, 0);
281 /* create a text box */
282 text = gtk_text_view_new();
283 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
284 gtk_container_add(GTK_CONTAINER(txt_scrollw), text);
285 rule_info->text = text;
288 if(topic_available(HELP_FIREWALL_DIALOG)) {
289 button_hbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_COPY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
291 button_hbox = dlg_button_row_new(GTK_STOCK_COPY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
293 gtk_box_pack_start(GTK_BOX(vbox), button_hbox, FALSE, FALSE, 0);
295 /* Create Copy Button */
296 button = g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_COPY);
297 g_signal_connect(button, "clicked", G_CALLBACK(firewall_copy_cmd_cb), rule_info);
298 gtk_tooltips_set_tip (tooltips, button, "Copy rule to clipboard ", NULL);
300 /* Create Save Button */
301 button = g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_SAVE);
302 g_signal_connect(button, "clicked", G_CALLBACK(firewall_save_as_cmd_cb), rule_info);
303 gtk_tooltips_set_tip (tooltips, button, "Save the rule as currently displayed ", NULL);
305 button = g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_CANCEL);
306 gtk_tooltips_set_tip (tooltips, button, "Cancel the dialog", NULL);
307 window_set_cancel_button(rule_w, button, window_cancel_button_cb);
309 if(topic_available(HELP_FIND_DIALOG)) {
310 button = g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_HELP);
311 g_signal_connect(button, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_FIREWALL_DIALOG);
314 /* Tuck away the rule_info object into the window */
315 g_object_set_data(G_OBJECT(rule_w), WS_RULE_INFO_KEY, rule_info);
317 g_signal_connect(rule_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
318 g_signal_connect(rule_w, "destroy", G_CALLBACK(firewall_destroy_cb), NULL);
320 /* Make sure this widget gets destroyed if we quit the main loop,
321 so that if we exit, we clean up any temporary files we have
322 for "Follow SSL Stream" windows. */
323 gtk_quit_add_destroy(gtk_main_level(), GTK_OBJECT(rule_w));
325 gtk_widget_show_all(rule_w);
326 window_present(rule_w);
327 gtk_option_menu_set_history(GTK_OPTION_MENU(product_om), 0);
328 select_product(rule_w, GUINT_TO_POINTER(0));
331 /* Set the current product. */
332 #define ADD_TO_FILTER_MENU(rt) \
333 menu_item = gtk_menu_item_new_with_label(name); \
334 g_signal_connect(menu_item, "activate", G_CALLBACK(select_filter), \
335 GUINT_TO_POINTER(rt)); \
336 g_object_set_data(G_OBJECT(menu_item), WS_RULE_INFO_KEY, rule_info); \
337 gtk_menu_append(GTK_MENU(menu), menu_item); \
340 first_mi = menu_item; \
344 #define NAME_TCP_UDP (rule_info->ptype == PT_TCP ? "TCP" : "UDP")
346 select_product(GtkWidget *w, gpointer data)
348 guint prod = GPOINTER_TO_UINT(data);
349 rule_info_t *rule_info;
350 gchar name[MAX_RULE_LEN], addr_str[MAX_RULE_LEN];
352 GtkWidget *menu, *menu_item, *first_mi = NULL;
353 rule_type_t rule_type = RT_NONE;
354 gboolean rt_set = FALSE, sensitive = FALSE;
356 rule_info = g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
358 if (prod >= NUM_PRODS || !rule_info)
361 rule_info->product = prod;
364 gtk_option_menu_remove_menu(GTK_OPTION_MENU(rule_info->filter_om));
365 menu = gtk_menu_new();
366 gtk_option_menu_set_menu(GTK_OPTION_MENU(rule_info->filter_om), menu);
368 /* Fill in valid menu items. */
369 if (products[prod].mac_func && rule_info->dl_src.type == AT_ETHER) {
370 addr = &(rule_info->dl_src);
371 address_to_str_buf(addr, name, MAX_RULE_LEN);
372 ADD_TO_FILTER_MENU(RT_MAC_SRC);
374 addr = &(rule_info->dl_dst);
375 address_to_str_buf(addr, name, MAX_RULE_LEN);
376 ADD_TO_FILTER_MENU(RT_MAC_DST);
379 if (products[prod].ipv4_func && rule_info->net_src.type == AT_IPv4) {
380 addr = &(rule_info->net_src);
381 address_to_str_buf(addr, name, MAX_RULE_LEN);
382 ADD_TO_FILTER_MENU(RT_IPv4_SRC);
384 addr = &(rule_info->net_dst);
385 address_to_str_buf(addr, name, MAX_RULE_LEN);
386 ADD_TO_FILTER_MENU(RT_IPv4_DST);
389 if (products[prod].port_func && (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
390 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
392 ADD_TO_FILTER_MENU(RT_PORT_SRC);
393 if (rule_info->srcport != rule_info->destport) {
394 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
395 rule_info->destport);
396 ADD_TO_FILTER_MENU(RT_PORT_DST);
400 if (products[prod].ipv4_port_func && rule_info->net_src.type == AT_IPv4 &&
401 (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
402 addr = &(rule_info->net_src);
403 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
404 g_snprintf(name, MAX_RULE_LEN, "%s + %s port %u", addr_str,
405 NAME_TCP_UDP, rule_info->srcport);
406 ADD_TO_FILTER_MENU(RT_IPv4_PORT_SRC);
408 addr = &(rule_info->net_dst);
409 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
410 g_snprintf(name, MAX_RULE_LEN, "%s + %s port %u", addr_str,
411 NAME_TCP_UDP, rule_info->destport);
412 ADD_TO_FILTER_MENU(RT_IPv4_PORT_DST);
416 if (rule_type != RT_NONE) {
417 gtk_widget_show_all(rule_info->filter_om);
418 gtk_option_menu_set_history(GTK_OPTION_MENU(rule_info->filter_om), 0);
421 gtk_widget_set_sensitive(rule_info->filter_om, sensitive);
422 gtk_widget_set_sensitive(rule_info->inbound_cb,
423 products[prod].does_inbound && sensitive);
424 gtk_widget_set_sensitive(rule_info->deny_cb, sensitive);
426 select_filter(w, GUINT_TO_POINTER(rule_type));
429 /* Set the current product. */
431 select_filter(GtkWidget *w, gpointer data)
433 rule_type_t cur_type = GPOINTER_TO_UINT(data);
434 rule_info_t *rule_info;
436 rule_info = g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
438 if (cur_type >= NUM_RULE_TYPES || !rule_info)
441 rule_info->rule_type = cur_type;
443 set_rule_text(rule_info);
446 /* Set inbound/outbound */
448 toggle_inbound(GtkToggleButton *t, gpointer data)
450 rule_info_t *rule_info = (rule_info_t *) data;
452 rule_info->inbound = gtk_toggle_button_get_active(t);
454 set_rule_text(rule_info);
457 /* Set deny/allow. */
459 toggle_deny(GtkToggleButton *t, gpointer data)
461 rule_info_t *rule_info = (rule_info_t *) data;
463 rule_info->deny = gtk_toggle_button_get_active(t);
465 set_rule_text(rule_info);
468 /* Set the rule text */
469 #define DL_ADDR (rt == RT_MAC_SRC ? &(rule_info->dl_src) : &(rule_info->dl_dst))
470 #define NET_ADDR (rt == RT_IPv4_SRC ? &(rule_info->net_src) : &(rule_info->net_dst))
471 #define NET_PORT (rt == RT_PORT_SRC ? rule_info->srcport : rule_info->destport)
473 set_rule_text(rule_info_t *rule_info) {
474 GString *rtxt = g_string_new("");
475 gchar addr_str[MAX_RULE_LEN];
476 rule_type_t rt = rule_info->rule_type;
477 guint prod = rule_info->product;
478 address *addr = NULL;
480 syntax_func rt_func = NULL;
482 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
484 if (prod < NUM_PRODS) {
485 g_string_printf(rtxt, "%s %s\n", products[prod].comment_pfx, products[prod].name);
488 g_string_append_printf(rtxt, "%s Not supported", products[prod].comment_pfx);
494 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
495 rt_func = products[prod].mac_func;
500 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
501 rt_func = products[prod].ipv4_func;
506 rt_func = products[prod].port_func;
508 case RT_IPv4_PORT_SRC:
509 case RT_IPv4_PORT_DST:
511 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
513 rt_func = products[prod].ipv4_port_func;
521 rt_func(rtxt, addr_str, port, rule_info->ptype, rule_info->inbound, rule_info->deny);
523 g_string_append_printf(rtxt, "ERROR: Unable to create rule");
526 gtk_text_buffer_set_text(buf, rtxt->str, rtxt->len);
528 g_string_free(rtxt, TRUE);
532 /* Rule text functions */
534 static void sf_dummy(GString *rtxt _U_, gchar *addr _U_, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny _U_) {
538 #define IPFW_DENY (deny ? "deny" : "allow")
539 #define IPFW_IN (inbound ? "in" : "out")
540 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
541 g_string_append_printf(rtxt, "add %s MAC %s any %s",
542 IPFW_DENY, addr, IPFW_IN);
545 #define NF_DROP (deny ? "DROP" : "ACCEPT")
546 #define NF_INPUT (inbound ? "INPUT" : "OUTPUT")
547 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
548 g_string_append_printf(rtxt, "iptables -A %s --mac-source %s -j %s",
549 NF_INPUT, addr, NF_DROP);
553 #define IOS_DENY (deny ? "deny" : "permit")
554 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny) {
555 g_string_append_printf(rtxt, "access-list NUMBER %s host %s", IOS_DENY, addr);
558 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
560 g_string_append_printf(rtxt, "access-list NUMBER %s ip host %s any", IOS_DENY, addr);
562 g_string_append_printf(rtxt, "access-list NUMBER %s ip any host %s", IOS_DENY, addr);
565 #define IPFILTER_DENY (deny ? "block" : "pass")
566 #define IPFILTER_IN (inbound ? "in" : "out")
567 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
568 g_string_append_printf(rtxt, "%s %s on le0 from %s to any",
569 IPFILTER_DENY, IPFILTER_IN, addr);
572 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
573 g_string_append_printf(rtxt, "add %s ip from %s to any %s",
574 IPFW_DENY, addr, IPFW_IN);
577 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
578 g_string_append_printf(rtxt, "iptables -A %s -i eth0 -d %s/32 -j %s",
579 NF_INPUT, addr, NF_DROP);
582 #define PF_DENY (deny ? "block" : "pass")
583 #define PF_IN (inbound ? "in" : "out")
584 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
585 g_string_append_printf(rtxt, "%s %s quick on $ext_if from %s to any",
586 PF_DENY, PF_IN, addr);
590 #define RT_TCP_UDP (ptype == PT_TCP ? "tcp" : "udp")
591 static void sf_ios_ext_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
592 g_string_append_printf(rtxt, "access-list NUMBER %s %s any any eq %u",
593 IOS_DENY, RT_TCP_UDP, port);
596 static void sf_ipfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype _U_, gboolean inbound, gboolean deny) {
597 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to any port = %u",
598 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, port);
601 static void sf_ipfw_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
602 g_string_append_printf(rtxt, "add %s %s from any to any %u %s",
603 IPFW_DENY, RT_TCP_UDP, port, IPFW_IN);
606 static void sf_netfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
607 g_string_append_printf(rtxt, "iptables -A %s -p %s --destination-port %u -j %s",
608 NF_INPUT, RT_TCP_UDP, port, NF_DROP);
611 static void sf_pf_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
612 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from any to any port %u",
613 PF_DENY, PF_IN, RT_TCP_UDP, port);
616 #define NETSH_DENY (deny ? "DISABLE" : "ENABLE")
617 static void sf_netsh_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
618 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s",
619 RT_TCP_UDP, port, NETSH_DENY);
623 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
625 g_string_append_printf(rtxt, "access-list NUMBER %s %s host %s any eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
627 g_string_append_printf(rtxt, "access-list NUMBER %s %s any host %s eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
630 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
632 g_string_append_printf(rtxt, "%s %s on le0 proto %s from %s to any port = %u",
633 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
635 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to %s port = %u",
636 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
639 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
640 g_string_append_printf(rtxt, "add %s %s from %s to any %u %s",
641 IPFW_DENY, RT_TCP_UDP, addr, port, IPFW_IN);
644 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
645 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from %s to any port %u",
646 PF_DENY, PF_IN, RT_TCP_UDP, addr, port);
649 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
650 g_string_append_printf(rtxt, "iptables -A %s -p %s -d %s/32 --destination-port %u -j %s",
651 NF_INPUT, RT_TCP_UDP, addr, port, NF_DROP);
654 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
655 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s %s",
656 RT_TCP_UDP, port, NETSH_DENY, addr);
659 /* The destroy call back has the responsibility of
660 * unlinking the temporary file
661 * and freeing the filter_out_filter */
663 firewall_destroy_cb(GtkWidget *w, gpointer data _U_)
665 rule_info_t *rule_info;
667 rule_info = g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
668 forget_rule_info(rule_info);
674 firewall_copy_cmd_cb(GtkWidget *w _U_, gpointer data)
676 rule_info_t *rule_info = data;
678 GtkTextIter start, end;
681 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
682 gtk_text_buffer_get_start_iter(buf, &start);
683 gtk_text_buffer_get_end_iter(buf, &end);
684 gtk_text_buffer_move_mark_by_name(buf, "insert", &start);
685 gtk_text_buffer_move_mark_by_name(buf, "selection_bound", &end);
686 gtk_text_buffer_copy_clipboard(buf, gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
690 * Keep a static pointer to the current "Save SSL Follow Stream As" window, if
691 * any, so that if somebody tries to do "Save"
692 * while there's already a "Save SSL Follow Stream" window up, we just pop
693 * up the existing one, rather than creating a new one.
696 firewall_save_as_cmd_cb(GtkWidget *w _U_, gpointer data)
699 rule_info_t *rule_info = data;
701 if (rule_info->firewall_save_as_w != NULL) {
702 /* There's already a dialog box; reactivate it. */
703 reactivate_window(rule_info->firewall_save_as_w);
707 new_win = file_selection_new("Wireshark: Save Firewall ACL Rule",
708 FILE_SELECTION_SAVE);
709 rule_info->firewall_save_as_w = new_win;
711 /* Tuck away the rule_info object into the window */
712 g_object_set_data(G_OBJECT(new_win), WS_RULE_INFO_KEY, rule_info);
714 g_signal_connect(new_win, "destroy", G_CALLBACK(firewall_save_as_destroy_cb), rule_info);
716 if (gtk_dialog_run(GTK_DIALOG(new_win)) == GTK_RESPONSE_ACCEPT)
718 firewall_save_as_ok_cb(new_win, new_win);
720 window_destroy(new_win);
726 firewall_save_as_ok_cb(GtkWidget * w _U_, gpointer fs)
728 gchar *to_name, *rule;
729 rule_info_t *rule_info;
733 GtkTextIter start, end;
736 to_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
738 /* Perhaps the user specified a directory instead of a file.
739 Check whether they did. */
740 if (test_for_directory(to_name) == EISDIR) {
741 /* It's a directory - set the file selection box to display that
742 directory, and leave the selection box displayed. */
743 set_last_open_dir(to_name);
745 file_selection_set_current_folder(fs, get_last_open_dir());
749 rule_info = g_object_get_data(G_OBJECT(fs), WS_RULE_INFO_KEY);
750 fh = ws_fopen(to_name, "w");
752 open_failure_alert_box(to_name, errno, TRUE);
757 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
758 gtk_text_buffer_get_start_iter(buf, &start);
759 gtk_text_buffer_get_end_iter(buf, &end);
760 rule = gtk_text_buffer_get_text(buf, &start, &end, FALSE);
765 gtk_widget_hide(GTK_WIDGET(fs));
766 window_destroy(GTK_WIDGET(fs));
768 /* Save the directory name for future file dialogs. */
769 dirname = get_dirname(to_name); /* Overwrites to_name */
770 set_last_open_dir(dirname);
775 firewall_save_as_destroy_cb(GtkWidget * win _U_, gpointer data)
777 rule_info_t *rule_info = data;
779 /* Note that we no longer have a dialog box. */
780 rule_info->firewall_save_as_w = NULL;