1 /* firewall_rules_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "firewall_rules_dialog.h"
13 #include <ui_firewall_rules_dialog.h>
15 #include "epan/packet_info.h"
16 #include "epan/to_str.h"
18 #include "ui/all_files_wildcard.h"
19 #include "ui/firewall_rules.h"
20 #include "ui/help_url.h"
22 #include "wsutil/file_util.h"
23 #include "wsutil/utf8_entities.h"
25 #include "main_application.h"
26 #include "ui/qt/widgets/wireshark_file_dialog.h"
29 #include <QMessageBox>
30 #include <QPushButton>
31 #include <QTextCursor>
33 // XXX As described in bug 2482, some of the generated rules don't
34 // make sense. We could generate rules for every conceivable use case,
35 // but that would add complexity. We could also add controls to let
36 // users fine-tune rule output, but that would also add complexity.
38 FirewallRulesDialog::FirewallRulesDialog(QWidget
&parent
, CaptureFile
&cf
) :
39 WiresharkDialog(parent
, cf
),
40 ui(new Ui::FirewallRulesDialog
),
45 setWindowSubtitle(tr("Firewall ACL Rules"));
47 ui
->buttonBox
->button(QDialogButtonBox::Apply
)->setText(tr("Copy"));
49 file_name_
= cf
.fileName(); // XXX Add extension?
50 packet_num_
= cf
.packetInfo()->num
;
52 packet_info
*pinfo
= cf
.packetInfo();
53 copy_address(&dl_src_
, &(pinfo
->dl_src
));
54 copy_address(&dl_dst_
, &(pinfo
->dl_dst
));
55 copy_address(&net_src_
, &(pinfo
->net_src
));
56 copy_address(&net_dst_
, &(pinfo
->net_dst
));
57 ptype_
= pinfo
->ptype
;
58 src_port_
= pinfo
->srcport
;
59 dst_port_
= pinfo
->destport
;
62 for (size_t prod
= 0; prod
< firewall_product_count(); prod
++) {
63 QString prod_name
= firewall_product_name(prod
);
65 // Default to Netfilter since it's likely the most popular.
66 if (prod_name
.contains("Netfilter")) nf_item
= ui
->productComboBox
->count();
67 ui
->productComboBox
->addItem(prod_name
);
69 ui
->productComboBox
->setCurrentIndex(nf_item
);
71 ui
->buttonBox
->button(QDialogButtonBox::Close
)->setDefault(true);
74 FirewallRulesDialog::~FirewallRulesDialog()
79 void FirewallRulesDialog::updateWidgets()
81 WiresharkDialog::updateWidgets();
83 QString comment_pfx
= firewall_product_comment_prefix(prod_
);
84 QString rule_hint
= firewall_product_rule_hint(prod_
);
87 rule_line
= QStringLiteral("%1 %2 rules for %3, packet %4.")
89 .arg(firewall_product_name(prod_
))
93 if (!rule_hint
.isEmpty()) rule_line
+= " " + rule_hint
;
95 ui
->textBrowser
->clear();
96 ui
->textBrowser
->append(rule_line
);
98 syntax_func v4_func
= firewall_product_ipv4_func(prod_
);
99 syntax_func port_func
= firewall_product_port_func(prod_
);
100 syntax_func v4_port_func
= firewall_product_ipv4_port_func(prod_
);
101 syntax_func mac_func
= firewall_product_mac_func(prod_
);
103 if (v4_func
&& net_src_
.type
== AT_IPv4
) {
104 addRule(tr("IPv4 source address."), v4_func
, &net_src_
, src_port_
);
105 addRule(tr("IPv4 destination address."), v4_func
, &net_dst_
, dst_port_
);
108 if (port_func
&& (ptype_
== PT_TCP
|| ptype_
== PT_UDP
)) {
109 addRule(tr("Source port."), port_func
, &net_src_
, src_port_
);
110 addRule(tr("Destination port."), port_func
, &net_dst_
, dst_port_
);
113 if (v4_port_func
&& net_src_
.type
== AT_IPv4
&&
114 (ptype_
== PT_TCP
|| ptype_
== PT_UDP
)) {
115 addRule(tr("IPv4 source address and port."), v4_port_func
, &net_src_
, src_port_
);
116 addRule(tr("IPv4 destination address and port."), v4_port_func
, &net_dst_
, dst_port_
);
119 if (mac_func
&& dl_src_
.type
== AT_ETHER
) {
120 addRule(tr("MAC source address."), mac_func
, &dl_src_
, src_port_
);
121 addRule(tr("MAC destination address."), mac_func
, &dl_dst_
, dst_port_
);
124 ui
->textBrowser
->moveCursor(QTextCursor::Start
);
126 ui
->inboundCheckBox
->setEnabled(firewall_product_does_inbound(prod_
));
129 #define ADDR_BUF_LEN 200
130 void FirewallRulesDialog::addRule(QString description
, syntax_func rule_func
, address
*addr
, uint32_t port
)
132 if (!rule_func
) return;
134 char addr_buf
[ADDR_BUF_LEN
];
135 QString comment_pfx
= firewall_product_comment_prefix(prod_
);
136 GString
*rule_str
= g_string_new("");
137 bool inbound
= ui
->inboundCheckBox
->isChecked();
138 bool deny
= ui
->denyCheckBox
->isChecked();
140 address_to_str_buf(addr
, addr_buf
, ADDR_BUF_LEN
);
141 rule_func(rule_str
, addr_buf
, port
, ptype_
, inbound
, deny
);
142 ui
->textBrowser
->append(QString());
144 QString comment_line
= QStringLiteral("%1 %2").arg(comment_pfx
, description
);
145 ui
->textBrowser
->append(comment_line
);
146 ui
->textBrowser
->append(rule_str
->str
);
148 g_string_free(rule_str
, TRUE
);
152 void FirewallRulesDialog::on_productComboBox_currentIndexChanged(int new_idx
)
154 prod_
= (size_t) new_idx
;
158 void FirewallRulesDialog::on_inboundCheckBox_toggled(bool)
163 void FirewallRulesDialog::on_denyCheckBox_toggled(bool)
168 void FirewallRulesDialog::on_buttonBox_clicked(QAbstractButton
*button
)
170 if (button
== ui
->buttonBox
->button(QDialogButtonBox::Save
)) {
171 QString save_title
= QStringLiteral("Save %1 rules as%2")
172 .arg(firewall_product_name(prod_
), UTF8_HORIZONTAL_ELLIPSIS
);
173 QByteArray file_name
= WiresharkFileDialog::getSaveFileName(this,
175 mainApp
->openDialogInitialDir().canonicalPath(),
176 tr("Text file (*.txt);;All Files (" ALL_FILES_WILDCARD
")")
178 if (file_name
.length() > 0) {
179 QFile
save_file(file_name
);
180 QByteArray rule_text
= ui
->textBrowser
->toPlainText().toUtf8();
182 save_file
.open(QIODevice::WriteOnly
);
183 save_file
.write(rule_text
);
186 if (save_file
.error() != QFile::NoError
) {
187 QMessageBox::warning(this, tr("Warning"), tr("Unable to save %1").arg(save_file
.fileName()));
191 /* Save the directory name for future file dialogs. */
192 mainApp
->setLastOpenDirFromFilename(file_name
);
194 } else if (button
== ui
->buttonBox
->button(QDialogButtonBox::Apply
)) {
195 if (ui
->textBrowser
->textCursor().hasSelection()) {
196 ui
->textBrowser
->copy();
198 mainApp
->clipboard()->setText(ui
->textBrowser
->toPlainText());
203 void FirewallRulesDialog::on_buttonBox_helpRequested()
205 mainApp
->helpTopicAction(HELP_FIREWALL_DIALOG
);