1 /* firewall_rules_dlg.c
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License
5 * as published by the Free Software Foundation; either version 2
6 * of the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * Generate firewall ACL rules based on packet addresses and ports.
20 * For directional rules, an outside interface is assumed.
22 * There may be better ways to present the information, e.g. all rules
23 * in one huge text window, or some sort of tree view.
27 * To add a new product, add syntax functions modify the products[] array.
29 * To add a new syntax function, add its prototype above the products[]
30 * array, and add the function below with all the others.
33 /* Copied from ssl-dlg.c */
49 #include <epan/packet.h>
50 #include <epan/addr_resolv.h>
51 #include <epan/epan_dissect.h>
52 #include <wsutil/filesystem.h>
53 #include <epan/dissectors/packet-ipv6.h>
55 #include <ui/alert_box.h>
56 #include <ui/last_open_dir.h>
58 #include <wsutil/file_util.h>
60 #include "ui/gtk/main.h"
61 #include "ui/gtk/dlg_utils.h"
62 #include "ui/gtk/file_dlg.h"
63 #include "ui/gtk/help_dlg.h"
64 #include "ui/gtk/gui_utils.h"
65 #include "ui/gtk/old-gtk-compat.h"
66 #include "ui/gtk/firewall_dlg.h"
68 #define MAX_RULE_LEN 200
85 /* Copied from packet_info struct */
86 typedef struct _rule_info_t {
96 GtkWidget *filter_combo_box;
98 GtkWidget *inbound_cb;
101 rule_type_t rule_type;
104 /* Syntax function prototypes */
105 typedef void (*syntax_func)(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
107 static void sf_dummy(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
109 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
110 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
112 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
113 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
114 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
115 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
116 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
117 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
118 /* XXX - Can you addresses-only filters using WFW/netsh? */
120 static void sf_ios_ext_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
121 static void sf_ipfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
122 static void sf_ipfw_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
123 static void sf_netfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
124 static void sf_pf_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
125 static void sf_netsh_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
127 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
128 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
129 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
130 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
131 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
132 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
134 typedef struct _fw_product_t {
136 const gchar *comment_pfx;
137 syntax_func mac_func;
138 syntax_func ipv4_func;
139 syntax_func port_func;
140 syntax_func ipv4_port_func;
141 gboolean does_inbound;
144 static fw_product products[] = {
145 { "Cisco IOS (standard)", "!", NULL, sf_ios_std_ipv4, NULL, NULL, FALSE },
146 { "Cisco IOS (extended)", "!",
147 NULL, sf_ios_ext_ipv4, sf_ios_ext_port, sf_ios_ext_ipv4_port, TRUE },
148 { "IP Filter (ipfilter)", "#",
149 NULL, sf_ipfilter_ipv4, sf_ipfilter_port, sf_ipfilter_ipv4_port, TRUE },
150 { "IPFirewall (ipfw)", "#",
151 sf_ipfw_mac, sf_ipfw_ipv4, sf_ipfw_port, sf_ipfw_ipv4_port, TRUE },
152 { "Netfilter (iptables)", "#",
153 sf_netfilter_mac, sf_netfilter_ipv4, sf_netfilter_port,
154 sf_netfilter_ipv4_port, TRUE },
155 { "Packet Filter (pf)", "#",
156 NULL, sf_pf_ipv4, sf_pf_port, sf_pf_ipv4_port, TRUE },
157 { "Windows Firewall (netsh)", "#",
158 NULL, NULL, sf_netsh_port, sf_netsh_ipv4_port, FALSE }
160 #define NUM_PRODS (sizeof(products) / sizeof(fw_product))
163 static void select_product(GtkWidget * win, gpointer data);
164 static void select_filter(GtkWidget * win, gpointer data);
165 static void toggle_inbound(GtkToggleButton *t, gpointer data);
166 static void toggle_deny(GtkToggleButton *t, gpointer data);
167 static void set_rule_text(rule_info_t *rule_info);
168 static void firewall_destroy_cb(GtkWidget * win, gpointer data);
169 static void firewall_copy_cmd_cb(GtkWidget * w, gpointer data);
170 static void firewall_save_as_cmd_cb(GtkWidget * w, gpointer data);
172 #define WS_RULE_INFO_KEY "rule_info_key"
175 /* List of "rule_info_t" structures for all rule windows. */
176 static GList *rule_infos;
178 /* Remove a "rule_info_t" structure from the list. */
180 forget_rule_info(rule_info_t *rule_info)
182 rule_infos = g_list_remove(rule_infos, rule_info);
187 firewall_rule_cb(GtkWidget *w _U_, gpointer data _U_)
189 GtkWidget *rule_w, *vbox, *txt_scrollw, *text;
190 GtkWidget *label, *product_combo_box;
191 GtkWidget *hbox, *button_hbox, *button;
192 rule_info_t *rule_info;
193 packet_info *pinfo = &cfile.edt->pi;
196 rule_info = g_new0(rule_info_t, 1);
197 COPY_ADDRESS(&(rule_info->dl_src), &(pinfo->dl_src));
198 COPY_ADDRESS(&(rule_info->dl_dst), &(pinfo->dl_dst));
199 COPY_ADDRESS(&(rule_info->net_src), &(pinfo->net_src));
200 COPY_ADDRESS(&(rule_info->net_dst), &(pinfo->net_dst));
201 rule_info->ptype = pinfo->ptype;
202 rule_info->srcport = pinfo->srcport;
203 rule_info->destport = pinfo->destport;
204 rule_info->inbound = TRUE;
205 rule_info->deny = TRUE;
206 rule_info->product = 0;
208 rule_w = dlg_window_new("Firewall ACL Rules");
210 gtk_widget_set_name(rule_w, "Firewall ACL rule window");
211 gtk_container_set_border_width(GTK_CONTAINER(rule_w), 6);
213 /* setup the container */
214 vbox = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
215 gtk_container_add(GTK_CONTAINER(rule_w), vbox);
217 /* rule type selectors hbox */
218 hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1, FALSE);
219 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
221 /* product selector */
222 label = gtk_label_new("Product");
223 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
225 product_combo_box = gtk_combo_box_text_new();
226 for (i = 0; i < NUM_PRODS; i++) {
227 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(product_combo_box), products[i].name);
229 g_object_set_data(G_OBJECT(product_combo_box), WS_RULE_INFO_KEY, rule_info);
230 g_signal_connect(product_combo_box, "changed", G_CALLBACK(select_product), NULL);
231 gtk_box_pack_start(GTK_BOX(hbox), product_combo_box, FALSE, FALSE, 5);
234 label = gtk_label_new("Filter");
235 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
237 rule_info->filter_combo_box = ws_combo_box_new_text_and_pointer();
238 g_object_set_data(G_OBJECT(rule_info->filter_combo_box), WS_RULE_INFO_KEY, rule_info); \
239 g_signal_connect(rule_info->filter_combo_box, "changed", G_CALLBACK(select_filter), NULL);
240 gtk_box_pack_start(GTK_BOX(hbox), rule_info->filter_combo_box, FALSE, FALSE, 5);
242 /* inbound selector */
243 rule_info->inbound_cb = gtk_check_button_new_with_label("Inbound");
244 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->inbound_cb),
246 gtk_box_pack_start(GTK_BOX(hbox), rule_info->inbound_cb, FALSE, FALSE, 10);
247 g_signal_connect(rule_info->inbound_cb, "toggled", G_CALLBACK(toggle_inbound), rule_info);
250 rule_info->deny_cb = gtk_check_button_new_with_label("Deny");
251 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->deny_cb),
253 gtk_box_pack_start(GTK_BOX(hbox), rule_info->deny_cb, FALSE, FALSE, 10);
254 g_signal_connect(rule_info->deny_cb, "toggled", G_CALLBACK(toggle_deny), rule_info);
256 /* create a scrolled window for the text */
257 txt_scrollw = scrolled_window_new(NULL, NULL);
258 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scrollw),
260 gtk_box_pack_start(GTK_BOX(vbox), txt_scrollw, TRUE, TRUE, 0);
262 /* create a text box */
263 text = gtk_text_view_new();
264 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
265 gtk_container_add(GTK_CONTAINER(txt_scrollw), text);
266 rule_info->text = text;
269 button_hbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_COPY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
270 gtk_box_pack_start(GTK_BOX(vbox), button_hbox, FALSE, FALSE, 0);
272 /* Create Copy Button */
273 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_COPY);
274 g_signal_connect(button, "clicked", G_CALLBACK(firewall_copy_cmd_cb), rule_info);
275 gtk_widget_set_tooltip_text(button, "Copy rule to clipboard");
277 /* Create Save Button */
278 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_SAVE);
279 g_signal_connect(button, "clicked", G_CALLBACK(firewall_save_as_cmd_cb), rule_info);
280 gtk_widget_set_tooltip_text(button, "Save the rule as currently displayed");
282 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_CANCEL);
283 gtk_widget_set_tooltip_text(button, "Cancel the dialog");
284 window_set_cancel_button(rule_w, button, window_cancel_button_cb);
286 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_HELP);
287 g_signal_connect(button, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_FIREWALL_DIALOG);
289 /* Tuck away the rule_info object into the window */
290 g_object_set_data(G_OBJECT(rule_w), WS_RULE_INFO_KEY, rule_info);
292 g_signal_connect(rule_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
293 g_signal_connect(rule_w, "destroy", G_CALLBACK(firewall_destroy_cb), NULL);
295 /* Make sure this widget gets destroyed if we quit the main loop,
296 so that if we exit, we clean up any temporary files we have
297 for "Follow SSL Stream" windows.
298 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
300 gtk_quit_add_destroy(gtk_main_level(), GTK_OBJECT(rule_w));
304 gtk_combo_box_set_active(GTK_COMBO_BOX(product_combo_box), 0); /* invokes select_product callback */
305 gtk_widget_show_all(rule_w);
306 window_present(rule_w);
309 /* Set the current product. */
310 #define ADD_TO_FILTER_MENU(rt) \
311 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(rule_info->filter_combo_box), name, GUINT_TO_POINTER(rt)); \
312 if (rule_type == RT_NONE) { \
316 #define NAME_TCP_UDP (rule_info->ptype == PT_TCP ? "TCP" : "UDP")
319 select_product(GtkWidget *w, gpointer data _U_)
321 guint prod = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
322 rule_info_t *rule_info;
323 gchar name[MAX_RULE_LEN], addr_str[MAX_RULE_LEN];
325 rule_type_t rule_type = RT_NONE;
326 gboolean sensitive = FALSE;
328 rule_info =(rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
330 if (prod >= NUM_PRODS || !rule_info)
333 rule_info->product = prod;
335 /* Clear the list store (ie: the como_box list items) */
336 ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(rule_info->filter_combo_box));
338 /* Fill in valid combo_box list items (in the list store). */
339 if (products[prod].mac_func && rule_info->dl_src.type == AT_ETHER) {
340 addr = &(rule_info->dl_src);
341 address_to_str_buf(addr, name, MAX_RULE_LEN);
342 ADD_TO_FILTER_MENU(RT_MAC_SRC);
344 addr = &(rule_info->dl_dst);
345 address_to_str_buf(addr, name, MAX_RULE_LEN);
346 ADD_TO_FILTER_MENU(RT_MAC_DST);
349 if (products[prod].ipv4_func && rule_info->net_src.type == AT_IPv4) {
350 addr = &(rule_info->net_src);
351 address_to_str_buf(addr, name, MAX_RULE_LEN);
352 ADD_TO_FILTER_MENU(RT_IPv4_SRC);
354 addr = &(rule_info->net_dst);
355 address_to_str_buf(addr, name, MAX_RULE_LEN);
356 ADD_TO_FILTER_MENU(RT_IPv4_DST);
359 if (products[prod].port_func && (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
360 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
362 ADD_TO_FILTER_MENU(RT_PORT_SRC);
363 if (rule_info->srcport != rule_info->destport) {
364 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
365 rule_info->destport);
366 ADD_TO_FILTER_MENU(RT_PORT_DST);
370 if (products[prod].ipv4_port_func && rule_info->net_src.type == AT_IPv4 &&
371 (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
372 addr = &(rule_info->net_src);
373 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
374 g_snprintf(name, MAX_RULE_LEN, "%s + %s port %u", addr_str,
375 NAME_TCP_UDP, rule_info->srcport);
376 ADD_TO_FILTER_MENU(RT_IPv4_PORT_SRC);
378 addr = &(rule_info->net_dst);
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->destport);
382 ADD_TO_FILTER_MENU(RT_IPv4_PORT_DST);
385 if (rule_type != RT_NONE) {
386 gtk_combo_box_set_active(GTK_COMBO_BOX(rule_info->filter_combo_box), 0); /* invokes select_filter callback */
389 select_filter(rule_info->filter_combo_box, NULL); /* Call if RT_NONE [with nothing selected] */
392 gtk_widget_set_sensitive(rule_info->filter_combo_box, sensitive);
393 gtk_widget_set_sensitive(rule_info->inbound_cb, products[prod].does_inbound && sensitive);
394 gtk_widget_set_sensitive(rule_info->deny_cb, sensitive);
397 /* Set the rule text based upon the current product and current filter. */
399 select_filter(GtkWidget *w, gpointer data _U_)
401 rule_type_t cur_type;
402 rule_info_t *rule_info;
405 rule_info = (rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
410 if (ws_combo_box_get_active_pointer(GTK_COMBO_BOX(w), &ptr))
411 cur_type = (rule_type_t)GPOINTER_TO_UINT(ptr);
413 cur_type = RT_NONE; /* If nothing selected (eg: nothing in filter list) */
415 if (cur_type >= NUM_RULE_TYPES)
418 rule_info->rule_type = cur_type;
420 set_rule_text(rule_info);
423 /* Set inbound/outbound */
425 toggle_inbound(GtkToggleButton *t, gpointer data)
427 rule_info_t *rule_info = (rule_info_t *) data;
429 rule_info->inbound = gtk_toggle_button_get_active(t);
431 set_rule_text(rule_info);
434 /* Set deny/allow. */
436 toggle_deny(GtkToggleButton *t, gpointer data)
438 rule_info_t *rule_info = (rule_info_t *) data;
440 rule_info->deny = gtk_toggle_button_get_active(t);
442 set_rule_text(rule_info);
445 /* Set the rule text */
446 #define DL_ADDR (rt == RT_MAC_SRC ? &(rule_info->dl_src) : &(rule_info->dl_dst))
447 #define NET_ADDR (rt == RT_IPv4_SRC ? &(rule_info->net_src) : &(rule_info->net_dst))
448 #define NET_PORT (rt == RT_PORT_SRC ? rule_info->srcport : rule_info->destport)
450 set_rule_text(rule_info_t *rule_info) {
451 GString *rtxt = g_string_new("");
452 gchar addr_str[MAX_RULE_LEN];
453 rule_type_t rt = rule_info->rule_type;
454 guint prod = rule_info->product;
455 address *addr = NULL;
457 syntax_func rt_func = NULL;
459 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
461 if (prod < NUM_PRODS) {
462 g_string_printf(rtxt, "%s %s\n", products[prod].comment_pfx, products[prod].name);
465 g_string_append_printf(rtxt, "%s Not supported", products[prod].comment_pfx);
471 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
472 rt_func = products[prod].mac_func;
477 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
478 rt_func = products[prod].ipv4_func;
483 rt_func = products[prod].port_func;
485 case RT_IPv4_PORT_SRC:
486 case RT_IPv4_PORT_DST:
488 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
490 rt_func = products[prod].ipv4_port_func;
498 rt_func(rtxt, addr_str, port, rule_info->ptype, rule_info->inbound, rule_info->deny);
500 g_string_append_printf(rtxt, "ERROR: Unable to create rule");
503 gtk_text_buffer_set_text(buf, rtxt->str, (gint) rtxt->len);
505 g_string_free(rtxt, TRUE);
509 /* Rule text functions */
511 static void sf_dummy(GString *rtxt _U_, gchar *addr _U_, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny _U_) {
515 #define IPFW_DENY (deny ? "deny" : "allow")
516 #define IPFW_IN (inbound ? "in" : "out")
517 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
518 g_string_append_printf(rtxt, "add %s MAC %s any %s",
519 IPFW_DENY, addr, IPFW_IN);
522 #define NF_DROP (deny ? "DROP" : "ACCEPT")
523 #define NF_INPUT (inbound ? "INPUT" : "OUTPUT")
524 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
525 g_string_append_printf(rtxt, "iptables -A %s --mac-source %s -j %s",
526 NF_INPUT, addr, NF_DROP);
530 #define IOS_DENY (deny ? "deny" : "permit")
531 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny) {
532 g_string_append_printf(rtxt, "access-list NUMBER %s host %s", IOS_DENY, addr);
535 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
537 g_string_append_printf(rtxt, "access-list NUMBER %s ip host %s any", IOS_DENY, addr);
539 g_string_append_printf(rtxt, "access-list NUMBER %s ip any host %s", IOS_DENY, addr);
542 #define IPFILTER_DENY (deny ? "block" : "pass")
543 #define IPFILTER_IN (inbound ? "in" : "out")
544 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
545 g_string_append_printf(rtxt, "%s %s on le0 from %s to any",
546 IPFILTER_DENY, IPFILTER_IN, addr);
549 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
550 g_string_append_printf(rtxt, "add %s ip from %s to any %s",
551 IPFW_DENY, addr, IPFW_IN);
554 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
555 g_string_append_printf(rtxt, "iptables -A %s -i eth0 -d %s/32 -j %s",
556 NF_INPUT, addr, NF_DROP);
559 #define PF_DENY (deny ? "block" : "pass")
560 #define PF_IN (inbound ? "in" : "out")
561 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
562 g_string_append_printf(rtxt, "%s %s quick on $ext_if from %s to any",
563 PF_DENY, PF_IN, addr);
567 #define RT_TCP_UDP (ptype == PT_TCP ? "tcp" : "udp")
568 static void sf_ios_ext_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
569 g_string_append_printf(rtxt, "access-list NUMBER %s %s any any eq %u",
570 IOS_DENY, RT_TCP_UDP, port);
573 static void sf_ipfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype _U_, gboolean inbound, gboolean deny) {
574 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to any port = %u",
575 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, port);
578 static void sf_ipfw_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
579 g_string_append_printf(rtxt, "add %s %s from any to any %u %s",
580 IPFW_DENY, RT_TCP_UDP, port, IPFW_IN);
583 static void sf_netfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
584 g_string_append_printf(rtxt, "iptables -A %s -p %s --destination-port %u -j %s",
585 NF_INPUT, RT_TCP_UDP, port, NF_DROP);
588 static void sf_pf_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
589 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from any to any port %u",
590 PF_DENY, PF_IN, RT_TCP_UDP, port);
593 #define NETSH_DENY (deny ? "DISABLE" : "ENABLE")
594 static void sf_netsh_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
595 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s",
596 RT_TCP_UDP, port, NETSH_DENY);
600 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
602 g_string_append_printf(rtxt, "access-list NUMBER %s %s host %s any eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
604 g_string_append_printf(rtxt, "access-list NUMBER %s %s any host %s eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
607 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
609 g_string_append_printf(rtxt, "%s %s on le0 proto %s from %s to any port = %u",
610 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
612 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to %s port = %u",
613 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
616 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
617 g_string_append_printf(rtxt, "add %s %s from %s to any %u %s",
618 IPFW_DENY, RT_TCP_UDP, addr, port, IPFW_IN);
621 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
622 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from %s to any port %u",
623 PF_DENY, PF_IN, RT_TCP_UDP, addr, port);
626 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
627 g_string_append_printf(rtxt, "iptables -A %s -p %s -d %s/32 --destination-port %u -j %s",
628 NF_INPUT, RT_TCP_UDP, addr, port, NF_DROP);
631 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
632 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s %s",
633 RT_TCP_UDP, port, NETSH_DENY, addr);
636 /* The destroy call back has the responsibility of
637 * unlinking the temporary file
638 * and freeing the filter_out_filter */
640 firewall_destroy_cb(GtkWidget *w, gpointer data _U_)
642 rule_info_t *rule_info;
644 rule_info = (rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
646 forget_rule_info(rule_info);
649 gtk_widget_destroy(w);
653 firewall_copy_cmd_cb(GtkWidget *w _U_, gpointer data)
655 rule_info_t *rule_info = (rule_info_t *)data;
657 GtkTextIter start, end;
660 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
661 gtk_text_buffer_get_start_iter(buf, &start);
662 gtk_text_buffer_get_end_iter(buf, &end);
663 gtk_text_buffer_select_range(buf, &start, &end);
664 gtk_text_buffer_copy_clipboard(buf, gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
668 firewall_save_as_ok_cb(char *to_name, rule_info_t *rule_info)
673 GtkTextIter start, end;
676 fh = ws_fopen(to_name, "w");
678 open_failure_alert_box(to_name, errno, TRUE);
683 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
684 gtk_text_buffer_get_start_iter(buf, &start);
685 gtk_text_buffer_get_end_iter(buf, &end);
686 rule = gtk_text_buffer_get_text(buf, &start, &end, FALSE);
695 gtk_firewall_save_as_file(GtkWidget *caller)
700 new_win = file_selection_new("Wireshark: Save Firewall ACL Rule",
702 FILE_SELECTION_SAVE);
704 pathname = file_selection_run(new_win);
705 if (pathname == NULL) {
706 /* User cancelled or closed the dialog. */
710 /* We've crosed the Rubicon; get rid of the dialog box. */
711 window_destroy(new_win);
717 firewall_save_as_cmd_cb(GtkWidget *w, gpointer data)
719 GtkWidget *caller = gtk_widget_get_toplevel(w);
720 rule_info_t *rule_info = (rule_info_t *)data;
724 * Loop until the user either selects a file or gives up.
727 pathname = gtk_firewall_save_as_file(caller);
728 if (pathname == NULL) {
732 if (firewall_save_as_ok_cb(pathname, rule_info)) {
737 /* Dump failed; let the user select another file or give up. */