add parameter dcerpc_info to PIDL_dissect_ipv?address()
[wireshark-wip.git] / ui / gtk / firewall_dlg.c
blobcfa83a0a2cd4aa32c85688ca463d175525e7088c
1 /* firewall_rules_dlg.c
3 * $Id$
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 */
37 #include "config.h"
39 #include <stdio.h>
40 #include <string.h>
42 #ifdef HAVE_FCNTL_H
43 #include <fcntl.h>
44 #endif
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
50 #include <gtk/gtk.h>
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
73 /* Rule types */
74 typedef enum {
75 RT_NONE,
76 RT_MAC_SRC,
77 RT_MAC_DST,
78 RT_IPv4_SRC,
79 RT_IPv4_DST,
80 RT_PORT_SRC,
81 RT_PORT_DST,
82 RT_IPv4_PORT_SRC,
83 RT_IPv4_PORT_DST,
84 NUM_RULE_TYPES
85 } rule_type_t;
88 /* Copied from packet_info struct */
89 typedef struct _rule_info_t {
90 gint product;
91 address dl_src;
92 address dl_dst;
93 address net_src;
94 address net_dst;
95 port_type ptype;
96 guint32 srcport;
97 guint32 destport;
98 GtkWidget *text;
99 GtkWidget *filter_combo_box;
100 GtkWidget *deny_cb;
101 GtkWidget *inbound_cb;
102 gboolean inbound;
103 gboolean deny;
104 rule_type_t rule_type;
105 } rule_info_t;
107 /* Syntax function prototypes */
108 typedef void (*syntax_func)(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
110 static void sf_dummy(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
112 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
113 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
115 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
116 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
117 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
118 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
119 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
120 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
121 /* XXX - Can you addresses-only filters using WFW/netsh? */
123 static void sf_ios_ext_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
124 static void sf_ipfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
125 static void sf_ipfw_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
126 static void sf_netfilter_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
127 static void sf_pf_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
128 static void sf_netsh_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
130 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
131 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
132 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
133 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
134 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
135 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny);
137 typedef struct _fw_product_t {
138 const gchar *name;
139 const gchar *comment_pfx;
140 syntax_func mac_func;
141 syntax_func ipv4_func;
142 syntax_func port_func;
143 syntax_func ipv4_port_func;
144 gboolean does_inbound;
145 } fw_product;
147 static fw_product products[] = {
148 { "Cisco IOS (standard)", "!", NULL, sf_ios_std_ipv4, NULL, NULL, FALSE },
149 { "Cisco IOS (extended)", "!",
150 NULL, sf_ios_ext_ipv4, sf_ios_ext_port, sf_ios_ext_ipv4_port, TRUE },
151 { "IP Filter (ipfilter)", "#",
152 NULL, sf_ipfilter_ipv4, sf_ipfilter_port, sf_ipfilter_ipv4_port, TRUE },
153 { "IPFirewall (ipfw)", "#",
154 sf_ipfw_mac, sf_ipfw_ipv4, sf_ipfw_port, sf_ipfw_ipv4_port, TRUE },
155 { "Netfilter (iptables)", "#",
156 sf_netfilter_mac, sf_netfilter_ipv4, sf_netfilter_port,
157 sf_netfilter_ipv4_port, TRUE },
158 { "Packet Filter (pf)", "#",
159 NULL, sf_pf_ipv4, sf_pf_port, sf_pf_ipv4_port, TRUE },
160 { "Windows Firewall (netsh)", "#",
161 NULL, NULL, sf_netsh_port, sf_netsh_ipv4_port, FALSE }
163 #define NUM_PRODS (sizeof(products) / sizeof(fw_product))
166 static void select_product(GtkWidget * win, gpointer data);
167 static void select_filter(GtkWidget * win, gpointer data);
168 static void toggle_inbound(GtkToggleButton *t, gpointer data);
169 static void toggle_deny(GtkToggleButton *t, gpointer data);
170 static void set_rule_text(rule_info_t *rule_info);
171 static void firewall_destroy_cb(GtkWidget * win, gpointer data);
172 static void firewall_copy_cmd_cb(GtkWidget * w, gpointer data);
173 static void firewall_save_as_cmd_cb(GtkWidget * w, gpointer data);
175 #define WS_RULE_INFO_KEY "rule_info_key"
177 #if 0
178 /* List of "rule_info_t" structures for all rule windows. */
179 static GList *rule_infos;
181 /* Remove a "rule_info_t" structure from the list. */
182 static void
183 forget_rule_info(rule_info_t *rule_info)
185 rule_infos = g_list_remove(rule_infos, rule_info);
187 #endif
189 void
190 firewall_rule_cb(GtkWidget *w _U_, gpointer data _U_)
192 GtkWidget *rule_w, *vbox, *txt_scrollw, *text;
193 GtkWidget *label, *product_combo_box;
194 GtkWidget *hbox, *button_hbox, *button;
195 rule_info_t *rule_info;
196 packet_info *pinfo = &cfile.edt->pi;
197 guint i;
199 rule_info = g_new0(rule_info_t, 1);
200 COPY_ADDRESS(&(rule_info->dl_src), &(pinfo->dl_src));
201 COPY_ADDRESS(&(rule_info->dl_dst), &(pinfo->dl_dst));
202 COPY_ADDRESS(&(rule_info->net_src), &(pinfo->net_src));
203 COPY_ADDRESS(&(rule_info->net_dst), &(pinfo->net_dst));
204 rule_info->ptype = pinfo->ptype;
205 rule_info->srcport = pinfo->srcport;
206 rule_info->destport = pinfo->destport;
207 rule_info->inbound = TRUE;
208 rule_info->deny = TRUE;
209 rule_info->product = 0;
211 rule_w = dlg_window_new("Firewall ACL Rules");
213 gtk_widget_set_name(rule_w, "Firewall ACL rule window");
214 gtk_container_set_border_width(GTK_CONTAINER(rule_w), 6);
216 /* setup the container */
217 vbox = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
218 gtk_container_add(GTK_CONTAINER(rule_w), vbox);
220 /* rule type selectors hbox */
221 hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1, FALSE);
222 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
224 /* product selector */
225 label = gtk_label_new("Product");
226 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
228 product_combo_box = gtk_combo_box_text_new();
229 for (i = 0; i < NUM_PRODS; i++) {
230 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(product_combo_box), products[i].name);
232 g_object_set_data(G_OBJECT(product_combo_box), WS_RULE_INFO_KEY, rule_info);
233 g_signal_connect(product_combo_box, "changed", G_CALLBACK(select_product), NULL);
234 gtk_box_pack_start(GTK_BOX(hbox), product_combo_box, FALSE, FALSE, 5);
236 /* type selector */
237 label = gtk_label_new("Filter");
238 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
240 rule_info->filter_combo_box = ws_combo_box_new_text_and_pointer();
241 g_object_set_data(G_OBJECT(rule_info->filter_combo_box), WS_RULE_INFO_KEY, rule_info); \
242 g_signal_connect(rule_info->filter_combo_box, "changed", G_CALLBACK(select_filter), NULL);
243 gtk_box_pack_start(GTK_BOX(hbox), rule_info->filter_combo_box, FALSE, FALSE, 5);
245 /* inbound selector */
246 rule_info->inbound_cb = gtk_check_button_new_with_label("Inbound");
247 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->inbound_cb),
248 rule_info->inbound);
249 gtk_box_pack_start(GTK_BOX(hbox), rule_info->inbound_cb, FALSE, FALSE, 10);
250 g_signal_connect(rule_info->inbound_cb, "toggled", G_CALLBACK(toggle_inbound), rule_info);
252 /* deny selector */
253 rule_info->deny_cb = gtk_check_button_new_with_label("Deny");
254 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rule_info->deny_cb),
255 rule_info->deny);
256 gtk_box_pack_start(GTK_BOX(hbox), rule_info->deny_cb, FALSE, FALSE, 10);
257 g_signal_connect(rule_info->deny_cb, "toggled", G_CALLBACK(toggle_deny), rule_info);
259 /* create a scrolled window for the text */
260 txt_scrollw = scrolled_window_new(NULL, NULL);
261 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scrollw),
262 GTK_SHADOW_IN);
263 gtk_box_pack_start(GTK_BOX(vbox), txt_scrollw, TRUE, TRUE, 0);
265 /* create a text box */
266 text = gtk_text_view_new();
267 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
268 gtk_container_add(GTK_CONTAINER(txt_scrollw), text);
269 rule_info->text = text;
271 /* Button row */
272 button_hbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_COPY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
273 gtk_box_pack_start(GTK_BOX(vbox), button_hbox, FALSE, FALSE, 0);
275 /* Create Copy Button */
276 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_COPY);
277 g_signal_connect(button, "clicked", G_CALLBACK(firewall_copy_cmd_cb), rule_info);
278 gtk_widget_set_tooltip_text(button, "Copy rule to clipboard");
280 /* Create Save Button */
281 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_SAVE);
282 g_signal_connect(button, "clicked", G_CALLBACK(firewall_save_as_cmd_cb), rule_info);
283 gtk_widget_set_tooltip_text(button, "Save the rule as currently displayed");
285 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_CANCEL);
286 gtk_widget_set_tooltip_text(button, "Cancel the dialog");
287 window_set_cancel_button(rule_w, button, window_cancel_button_cb);
289 button = (GtkWidget *)g_object_get_data(G_OBJECT(button_hbox), GTK_STOCK_HELP);
290 g_signal_connect(button, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_FIREWALL_DIALOG);
292 /* Tuck away the rule_info object into the window */
293 g_object_set_data(G_OBJECT(rule_w), WS_RULE_INFO_KEY, rule_info);
295 g_signal_connect(rule_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
296 g_signal_connect(rule_w, "destroy", G_CALLBACK(firewall_destroy_cb), NULL);
298 /* Make sure this widget gets destroyed if we quit the main loop,
299 so that if we exit, we clean up any temporary files we have
300 for "Follow SSL Stream" windows.
301 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
303 gtk_quit_add_destroy(gtk_main_level(), GTK_OBJECT(rule_w));
307 gtk_combo_box_set_active(GTK_COMBO_BOX(product_combo_box), 0); /* invokes select_product callback */
308 gtk_widget_show_all(rule_w);
309 window_present(rule_w);
312 /* Set the current product. */
313 #define ADD_TO_FILTER_MENU(rt) \
314 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(rule_info->filter_combo_box), name, GUINT_TO_POINTER(rt)); \
315 if (rule_type == RT_NONE) { \
316 rule_type = rt; \
319 #define NAME_TCP_UDP (rule_info->ptype == PT_TCP ? "TCP" : "UDP")
321 static void
322 select_product(GtkWidget *w, gpointer data _U_)
324 guint prod = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
325 rule_info_t *rule_info;
326 gchar name[MAX_RULE_LEN], addr_str[MAX_RULE_LEN];
327 address *addr;
328 rule_type_t rule_type = RT_NONE;
329 gboolean sensitive = FALSE;
331 rule_info =(rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
333 if (prod >= NUM_PRODS || !rule_info)
334 return;
336 rule_info->product = prod;
338 /* Clear the list store (ie: the como_box list items) */
339 ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(rule_info->filter_combo_box));
341 /* Fill in valid combo_box list items (in the list store). */
342 if (products[prod].mac_func && rule_info->dl_src.type == AT_ETHER) {
343 addr = &(rule_info->dl_src);
344 address_to_str_buf(addr, name, MAX_RULE_LEN);
345 ADD_TO_FILTER_MENU(RT_MAC_SRC);
347 addr = &(rule_info->dl_dst);
348 address_to_str_buf(addr, name, MAX_RULE_LEN);
349 ADD_TO_FILTER_MENU(RT_MAC_DST);
352 if (products[prod].ipv4_func && rule_info->net_src.type == AT_IPv4) {
353 addr = &(rule_info->net_src);
354 address_to_str_buf(addr, name, MAX_RULE_LEN);
355 ADD_TO_FILTER_MENU(RT_IPv4_SRC);
357 addr = &(rule_info->net_dst);
358 address_to_str_buf(addr, name, MAX_RULE_LEN);
359 ADD_TO_FILTER_MENU(RT_IPv4_DST);
362 if (products[prod].port_func && (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
363 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
364 rule_info->srcport);
365 ADD_TO_FILTER_MENU(RT_PORT_SRC);
366 if (rule_info->srcport != rule_info->destport) {
367 g_snprintf(name, MAX_RULE_LEN, "%s port %u", NAME_TCP_UDP,
368 rule_info->destport);
369 ADD_TO_FILTER_MENU(RT_PORT_DST);
373 if (products[prod].ipv4_port_func && rule_info->net_src.type == AT_IPv4 &&
374 (rule_info->ptype == PT_TCP || rule_info->ptype == PT_UDP)) {
375 addr = &(rule_info->net_src);
376 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
377 g_snprintf(name, MAX_RULE_LEN, "%s + %s port %u", addr_str,
378 NAME_TCP_UDP, rule_info->srcport);
379 ADD_TO_FILTER_MENU(RT_IPv4_PORT_SRC);
381 addr = &(rule_info->net_dst);
382 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
383 g_snprintf(name, MAX_RULE_LEN, "%s + %s port %u", addr_str,
384 NAME_TCP_UDP, rule_info->destport);
385 ADD_TO_FILTER_MENU(RT_IPv4_PORT_DST);
388 if (rule_type != RT_NONE) {
389 gtk_combo_box_set_active(GTK_COMBO_BOX(rule_info->filter_combo_box), 0); /* invokes select_filter callback */
390 sensitive = TRUE;
391 } else {
392 select_filter(rule_info->filter_combo_box, NULL); /* Call if RT_NONE [with nothing selected] */
395 gtk_widget_set_sensitive(rule_info->filter_combo_box, sensitive);
396 gtk_widget_set_sensitive(rule_info->inbound_cb, products[prod].does_inbound && sensitive);
397 gtk_widget_set_sensitive(rule_info->deny_cb, sensitive);
400 /* Set the rule text based upon the current product and current filter. */
401 static void
402 select_filter(GtkWidget *w, gpointer data _U_)
404 rule_type_t cur_type;
405 rule_info_t *rule_info;
406 gpointer ptr;
408 rule_info = (rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
409 if (!rule_info)
410 return;
413 if (ws_combo_box_get_active_pointer(GTK_COMBO_BOX(w), &ptr))
414 cur_type = (rule_type_t)GPOINTER_TO_UINT(ptr);
415 else
416 cur_type = RT_NONE; /* If nothing selected (eg: nothing in filter list) */
418 if (cur_type >= NUM_RULE_TYPES)
419 return;
421 rule_info->rule_type = cur_type;
423 set_rule_text(rule_info);
426 /* Set inbound/outbound */
427 static void
428 toggle_inbound(GtkToggleButton *t, gpointer data)
430 rule_info_t *rule_info = (rule_info_t *) data;
432 rule_info->inbound = gtk_toggle_button_get_active(t);
434 set_rule_text(rule_info);
437 /* Set deny/allow. */
438 static void
439 toggle_deny(GtkToggleButton *t, gpointer data)
441 rule_info_t *rule_info = (rule_info_t *) data;
443 rule_info->deny = gtk_toggle_button_get_active(t);
445 set_rule_text(rule_info);
448 /* Set the rule text */
449 #define DL_ADDR (rt == RT_MAC_SRC ? &(rule_info->dl_src) : &(rule_info->dl_dst))
450 #define NET_ADDR (rt == RT_IPv4_SRC ? &(rule_info->net_src) : &(rule_info->net_dst))
451 #define NET_PORT (rt == RT_PORT_SRC ? rule_info->srcport : rule_info->destport)
452 static void
453 set_rule_text(rule_info_t *rule_info) {
454 GString *rtxt = g_string_new("");
455 gchar addr_str[MAX_RULE_LEN];
456 rule_type_t rt = rule_info->rule_type;
457 guint prod = rule_info->product;
458 address *addr = NULL;
459 guint32 port = 0;
460 syntax_func rt_func = NULL;
462 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
464 if (prod < NUM_PRODS) {
465 g_string_printf(rtxt, "%s %s\n", products[prod].comment_pfx, products[prod].name);
466 switch(rt) {
467 case RT_NONE:
468 g_string_append_printf(rtxt, "%s Not supported", products[prod].comment_pfx);
469 rt_func = sf_dummy;
470 break;
471 case RT_MAC_SRC:
472 case RT_MAC_DST:
473 addr = DL_ADDR;
474 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
475 rt_func = products[prod].mac_func;
476 break;
477 case RT_IPv4_SRC:
478 case RT_IPv4_DST:
479 addr = NET_ADDR;
480 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
481 rt_func = products[prod].ipv4_func;
482 break;
483 case RT_PORT_SRC:
484 case RT_PORT_DST:
485 port = NET_PORT;
486 rt_func = products[prod].port_func;
487 break;
488 case RT_IPv4_PORT_SRC:
489 case RT_IPv4_PORT_DST:
490 addr = NET_ADDR;
491 address_to_str_buf(addr, addr_str, MAX_RULE_LEN);
492 port = NET_PORT;
493 rt_func = products[prod].ipv4_port_func;
494 break;
495 default:
496 break;
500 if (rt_func) {
501 rt_func(rtxt, addr_str, port, rule_info->ptype, rule_info->inbound, rule_info->deny);
502 } else {
503 g_string_append_printf(rtxt, "ERROR: Unable to create rule");
506 gtk_text_buffer_set_text(buf, rtxt->str, (gint) rtxt->len);
508 g_string_free(rtxt, TRUE);
512 /* Rule text functions */
513 /* Dummy */
514 static void sf_dummy(GString *rtxt _U_, gchar *addr _U_, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny _U_) {
517 /* MAC */
518 #define IPFW_DENY (deny ? "deny" : "allow")
519 #define IPFW_IN (inbound ? "in" : "out")
520 static void sf_ipfw_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
521 g_string_append_printf(rtxt, "add %s MAC %s any %s",
522 IPFW_DENY, addr, IPFW_IN);
525 #define NF_DROP (deny ? "DROP" : "ACCEPT")
526 #define NF_INPUT (inbound ? "INPUT" : "OUTPUT")
527 static void sf_netfilter_mac(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
528 g_string_append_printf(rtxt, "iptables -A %s --mac-source %s -j %s",
529 NF_INPUT, addr, NF_DROP);
532 /* IPv4 */
533 #define IOS_DENY (deny ? "deny" : "permit")
534 static void sf_ios_std_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound _U_, gboolean deny) {
535 g_string_append_printf(rtxt, "access-list NUMBER %s host %s", IOS_DENY, addr);
538 static void sf_ios_ext_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
539 if (inbound)
540 g_string_append_printf(rtxt, "access-list NUMBER %s ip host %s any", IOS_DENY, addr);
541 else
542 g_string_append_printf(rtxt, "access-list NUMBER %s ip any host %s", IOS_DENY, addr);
545 #define IPFILTER_DENY (deny ? "block" : "pass")
546 #define IPFILTER_IN (inbound ? "in" : "out")
547 static void sf_ipfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
548 g_string_append_printf(rtxt, "%s %s on le0 from %s to any",
549 IPFILTER_DENY, IPFILTER_IN, addr);
552 static void sf_ipfw_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
553 g_string_append_printf(rtxt, "add %s ip from %s to any %s",
554 IPFW_DENY, addr, IPFW_IN);
557 static void sf_netfilter_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
558 g_string_append_printf(rtxt, "iptables -A %s -i eth0 -d %s/32 -j %s",
559 NF_INPUT, addr, NF_DROP);
562 #define PF_DENY (deny ? "block" : "pass")
563 #define PF_IN (inbound ? "in" : "out")
564 static void sf_pf_ipv4(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
565 g_string_append_printf(rtxt, "%s %s quick on $ext_if from %s to any",
566 PF_DENY, PF_IN, addr);
569 /* Port */
570 #define RT_TCP_UDP (ptype == PT_TCP ? "tcp" : "udp")
571 static void sf_ios_ext_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
572 g_string_append_printf(rtxt, "access-list NUMBER %s %s any any eq %u",
573 IOS_DENY, RT_TCP_UDP, port);
576 static void sf_ipfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype _U_, gboolean inbound, gboolean deny) {
577 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to any port = %u",
578 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, port);
581 static void sf_ipfw_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
582 g_string_append_printf(rtxt, "add %s %s from any to any %u %s",
583 IPFW_DENY, RT_TCP_UDP, port, IPFW_IN);
586 static void sf_netfilter_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
587 g_string_append_printf(rtxt, "iptables -A %s -p %s --destination-port %u -j %s",
588 NF_INPUT, RT_TCP_UDP, port, NF_DROP);
591 static void sf_pf_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
592 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from any to any port %u",
593 PF_DENY, PF_IN, RT_TCP_UDP, port);
596 #define NETSH_DENY (deny ? "DISABLE" : "ENABLE")
597 static void sf_netsh_port(GString *rtxt, gchar *addr _U_, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
598 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s",
599 RT_TCP_UDP, port, NETSH_DENY);
602 /* IPv4 + port */
603 static void sf_ios_ext_ipv4_port(GString *rtxt, gchar *addr, guint32 port _U_, port_type ptype _U_, gboolean inbound, gboolean deny) {
604 if (inbound)
605 g_string_append_printf(rtxt, "access-list NUMBER %s %s host %s any eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
606 else
607 g_string_append_printf(rtxt, "access-list NUMBER %s %s any host %s eq %u", IOS_DENY, RT_TCP_UDP, addr, port);
610 static void sf_ipfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
611 if (inbound)
612 g_string_append_printf(rtxt, "%s %s on le0 proto %s from %s to any port = %u",
613 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
614 else
615 g_string_append_printf(rtxt, "%s %s on le0 proto %s from any to %s port = %u",
616 IPFILTER_DENY, IPFILTER_IN, RT_TCP_UDP, addr, port);
619 static void sf_ipfw_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
620 g_string_append_printf(rtxt, "add %s %s from %s to any %u %s",
621 IPFW_DENY, RT_TCP_UDP, addr, port, IPFW_IN);
624 static void sf_pf_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
625 g_string_append_printf(rtxt, "%s %s quick on $ext_if proto %s from %s to any port %u",
626 PF_DENY, PF_IN, RT_TCP_UDP, addr, port);
629 static void sf_netfilter_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny) {
630 g_string_append_printf(rtxt, "iptables -A %s -p %s -d %s/32 --destination-port %u -j %s",
631 NF_INPUT, RT_TCP_UDP, addr, port, NF_DROP);
634 static void sf_netsh_ipv4_port(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound _U_, gboolean deny) {
635 g_string_append_printf(rtxt, "add portopening %s %u Wireshark %s %s",
636 RT_TCP_UDP, port, NETSH_DENY, addr);
639 /* The destroy call back has the responsibility of
640 * unlinking the temporary file
641 * and freeing the filter_out_filter */
642 static void
643 firewall_destroy_cb(GtkWidget *w, gpointer data _U_)
645 rule_info_t *rule_info;
647 rule_info = (rule_info_t *)g_object_get_data(G_OBJECT(w), WS_RULE_INFO_KEY);
648 #if 0
649 forget_rule_info(rule_info);
650 #endif
651 g_free(rule_info);
652 gtk_widget_destroy(w);
655 static void
656 firewall_copy_cmd_cb(GtkWidget *w _U_, gpointer data)
658 rule_info_t *rule_info = (rule_info_t *)data;
660 GtkTextIter start, end;
661 GtkTextBuffer *buf;
663 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
664 gtk_text_buffer_get_start_iter(buf, &start);
665 gtk_text_buffer_get_end_iter(buf, &end);
666 gtk_text_buffer_select_range(buf, &start, &end);
667 gtk_text_buffer_copy_clipboard(buf, gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
670 static gboolean
671 firewall_save_as_ok_cb(char *to_name, rule_info_t *rule_info)
673 FILE *fh;
674 gchar *rule;
676 GtkTextIter start, end;
677 GtkTextBuffer *buf;
679 fh = ws_fopen(to_name, "w");
680 if (fh == NULL) {
681 open_failure_alert_box(to_name, errno, TRUE);
682 g_free(to_name);
683 return FALSE;
686 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(rule_info->text));
687 gtk_text_buffer_get_start_iter(buf, &start);
688 gtk_text_buffer_get_end_iter(buf, &end);
689 rule = gtk_text_buffer_get_text(buf, &start, &end, FALSE);
691 fputs(rule, fh);
692 fclose(fh);
694 return TRUE;
697 static char *
698 gtk_firewall_save_as_file(GtkWidget *caller)
700 GtkWidget *new_win;
701 char *pathname;
703 new_win = file_selection_new("Wireshark: Save Firewall ACL Rule",
704 GTK_WINDOW(caller),
705 FILE_SELECTION_SAVE);
707 pathname = file_selection_run(new_win);
708 if (pathname == NULL) {
709 /* User cancelled or closed the dialog. */
710 return NULL;
713 /* We've crosed the Rubicon; get rid of the dialog box. */
714 window_destroy(new_win);
716 return pathname;
719 static void
720 firewall_save_as_cmd_cb(GtkWidget *w, gpointer data)
722 GtkWidget *caller = gtk_widget_get_toplevel(w);
723 rule_info_t *rule_info = (rule_info_t *)data;
724 char *pathname;
727 * Loop until the user either selects a file or gives up.
729 for (;;) {
730 pathname = gtk_firewall_save_as_file(caller);
731 if (pathname == NULL) {
732 /* User gave up. */
733 break;
735 if (firewall_save_as_ok_cb(pathname, rule_info)) {
736 /* We succeeded. */
737 g_free(pathname);
738 break;
740 /* Dump failed; let the user select another file or give up. */
741 g_free(pathname);