aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorJohn Thacker <johnthacker@gmail.com>2023-09-01 07:56:58 -0400
committerAndersBroman <a.broman58@gmail.com>2023-09-03 07:23:50 +0000
commit1acc3ae5adccd6a9da9d4bd8ccc048de36b3fe1b (patch)
treeb6cf4afc04aedca5697def135103f7518c14bb51 /ui
parentcc83f62a4d49006db43f0709d7493011776d4260 (diff)
Qt: Call EditResolvedName from the PacketList
Allow Edit Resolved Name to be called from the packet details, for fields that are IPv4 or IPv6 addresses. Add to the combobox of possible addresses to edit all (non hidden) IPv4 or IPv6 fields. Set the index of the combobox to the selected column (if it is an address, and the packet list has focus or was selected), or to the currently selected field (if selected from the packet details, and an IP address.) Check other types of address columns (such as network address and custom columns) to see if they match the unresolved string for an IP address. Don't both redissecting the packets if the network resolution is off, because it won't do anything. There's a use case for editing several names before turning on the preference to avoid processor intensive redissects. Fix #17284
Diffstat (limited to 'ui')
-rw-r--r--ui/logray/logray_main_window_slots.cpp6
-rw-r--r--ui/qt/address_editor_frame.cpp120
-rw-r--r--ui/qt/address_editor_frame.h5
-rw-r--r--ui/qt/proto_tree.cpp5
-rw-r--r--ui/qt/utils/field_information.cpp2
-rw-r--r--ui/qt/utils/field_information.h2
-rw-r--r--ui/qt/wireshark_main_window_slots.cpp6
7 files changed, 128 insertions, 18 deletions
diff --git a/ui/logray/logray_main_window_slots.cpp b/ui/logray/logray_main_window_slots.cpp
index 481fd3b298..47c4074a46 100644
--- a/ui/logray/logray_main_window_slots.cpp
+++ b/ui/logray/logray_main_window_slots.cpp
@@ -2431,8 +2431,10 @@ void LograyMainWindow::editResolvedName()
//int column = packet_list_->selectedColumn();
int column = -1;
- if (packet_list_->currentIndex().isValid()) {
- column = packet_list_->currentIndex().column();
+ if (packet_list_->contextMenuActive() || packet_list_->hasFocus()) {
+ if (packet_list_->currentIndex().isValid()) {
+ column = packet_list_->currentIndex().column();
+ }
}
main_ui_->addressEditorFrame->editAddresses(capture_file_, column);
diff --git a/ui/qt/address_editor_frame.cpp b/ui/qt/address_editor_frame.cpp
index 03bda8a65c..c428d19d5a 100644
--- a/ui/qt/address_editor_frame.cpp
+++ b/ui/qt/address_editor_frame.cpp
@@ -30,6 +30,7 @@
// To do:
// - Fill in currently resolved address.
+// - Allow editing other kinds of addresses.
AddressEditorFrame::AddressEditorFrame(QWidget *parent) :
AccordionFrame(parent),
@@ -50,6 +51,48 @@ AddressEditorFrame::~AddressEditorFrame()
delete ui;
}
+QString AddressEditorFrame::addressToString(const FieldInformation& finfo)
+{
+ address addr;
+ ws_in4_addr ipv4;
+ const ws_in6_addr* ipv6;
+
+ if (!finfo.isValid()) {
+ return QString();
+ }
+
+ switch (finfo.headerInfo().type) {
+
+ case FT_IPv4:
+ // FieldInformation.toString gives us the result of
+ // proto_item_fill_display_label, but that gives us
+ // the currently resolved version, if resolution is
+ // available and enabled. We want the unresolved string.
+ ipv4 = fvalue_get_uinteger(finfo.fieldInfo()->value);
+ set_address(&addr, AT_IPv4, 4, &ipv4);
+ return gchar_free_to_qstring(address_to_str(NULL, &addr));
+ case FT_IPv6:
+ ipv6 = fvalue_get_ipv6(finfo.fieldInfo()->value);
+ set_address(&addr, AT_IPv6, sizeof(ws_in6_addr), ipv6);
+ return gchar_free_to_qstring(address_to_str(NULL, &addr));
+ default:
+ return QString();
+ }
+}
+
+void AddressEditorFrame::addAddresses(const ProtoNode& node, QStringList& addresses)
+{
+ QString addrString = addressToString(FieldInformation(&node));
+ if (!addrString.isEmpty()) {
+ addresses << addrString;
+ }
+ ProtoNode::ChildIterator kids = node.children();
+ while (kids.element().isValid()) {
+ addAddresses(kids.element(), addresses);
+ kids.next();
+ }
+}
+
void AddressEditorFrame::editAddresses(CaptureFile &cf, int column)
{
cap_file_ = cf.capFile();
@@ -66,10 +109,16 @@ void AddressEditorFrame::editAddresses(CaptureFile &cf, int column)
epan_dissect_t edt;
QStringList addresses;
+ QString selectedString;
ui->addressComboBox->clear();
- epan_dissect_init(&edt, cap_file_->epan, FALSE, FALSE);
+ // Dissect the record with a visible tree and fill in the custom
+ // columns. We don't really need to have a visible tree (we should
+ // have one in cap_file_->edt->tree as we have a current frame), but
+ // this is only a single frame that's previously been dissected so
+ // the performance hit is slight anyway.
+ epan_dissect_init(&edt, cap_file_->epan, TRUE, TRUE);
col_custom_prime_edt(&edt, &cap_file_->cinfo);
epan_dissect_run(&edt, cap_file_->cd_t, &cap_file_->rec,
@@ -77,23 +126,33 @@ void AddressEditorFrame::editAddresses(CaptureFile &cf, int column)
cap_file_->current_frame, &cap_file_->cinfo);
epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
- /* First check selected column */
- if (isAddressColumn(&cap_file_->cinfo, column)) {
- addresses << cap_file_->cinfo.col_expr.col_expr_val[column];
- }
-
- for (int col = 0; col < cap_file_->cinfo.num_cols; col++) {
- /* Then check all columns except the selected */
- if ((col != column) && (isAddressColumn(&cap_file_->cinfo, col))) {
- addresses << cap_file_->cinfo.col_expr.col_expr_val[col];
+ addAddresses(ProtoNode(edt.tree), addresses);
+
+ if (column >= 0) {
+ // Check selected column
+ if (isAddressColumn(&cap_file_->cinfo, column)) {
+ // This always gets the unresolved value.
+ // XXX: For multifield custom columns, we don't have a good
+ // function to return each string separately before joining
+ // them. Since we know that IP addresses don't include commas,
+ // we could split on commas here, and check each field value
+ // to find the first one that is an IP address in our list.
+ selectedString = cap_file_->cinfo.col_expr.col_expr_val[column];
}
+ } else if (cap_file_->finfo_selected) {
+ selectedString = addressToString(FieldInformation(cap_file_->finfo_selected));
}
epan_dissect_cleanup(&edt);
displayPreviousUserDefinedHostname();
+ addresses.removeDuplicates();
ui->addressComboBox->addItems(addresses);
+ int index = ui->addressComboBox->findText(selectedString);
+ if (index != -1) {
+ ui->addressComboBox->setCurrentIndex(index);
+ }
ui->nameLineEdit->setFocus();
updateWidgets();
}
@@ -124,6 +183,14 @@ void AddressEditorFrame::keyPressEvent(QKeyEvent *event)
void AddressEditorFrame::displayPreviousUserDefinedHostname()
{
QString addr = ui->addressComboBox->currentText();
+ // XXX: If there's a resolved name that wasn't manually entered,
+ // we should probably display that too. Possibly even if network
+ // name resolution is off globally, as get_edited_resolved_name() does.
+ // It's possible to have such names from DNS lookups if the global is
+ // turned on then turned back off, from NRBs, or from DNS packets.
+ // There's no clean API call to always get the resolved name, but
+ // we could access the hash tables directly the way that
+ // models/resolved_addresses_models.cpp does.
resolved_name_t* previous_entry = get_edited_resolved_name(addr.toUtf8().constData());
if (previous_entry)
{
@@ -176,7 +243,19 @@ void AddressEditorFrame::on_buttonBox_accepted()
return;
}
on_buttonBox_rejected();
- emit redissectPackets();
+ // There's no point in redissecting packets if the network resolution
+ // global is off. There is a use case for editing several names before
+ // turning on the preference to avoid a lot of expensive redissects.
+ // (Statistics->Resolved Addresses still displays them even when
+ // resolution is disabled, so the user can check what has been input.)
+ //
+ // XXX: Can entering a new name but having nothing happen because
+ // network name resolution is off be confusing to the user? The GTK
+ // dialog had a simple checkbox, the "Name Resolution Preferences..."
+ // is a little more complicated but hopefully obvious enough.
+ if (gbl_resolv_flags.network_name) {
+ emit redissectPackets();
+ }
}
void AddressEditorFrame::on_buttonBox_rejected()
@@ -192,12 +271,29 @@ bool AddressEditorFrame::isAddressColumn(epan_column_info *cinfo, int column)
if (((cinfo->columns[column].col_fmt == COL_DEF_SRC) ||
(cinfo->columns[column].col_fmt == COL_RES_SRC) ||
+ (cinfo->columns[column].col_fmt == COL_UNRES_SRC) ||
(cinfo->columns[column].col_fmt == COL_DEF_DST) ||
- (cinfo->columns[column].col_fmt == COL_RES_DST)) &&
+ (cinfo->columns[column].col_fmt == COL_RES_DST) ||
+ (cinfo->columns[column].col_fmt == COL_UNRES_DST) ||
+ (cinfo->columns[column].col_fmt == COL_DEF_NET_SRC) ||
+ (cinfo->columns[column].col_fmt == COL_RES_NET_SRC) ||
+ (cinfo->columns[column].col_fmt == COL_UNRES_NET_SRC) ||
+ (cinfo->columns[column].col_fmt == COL_DEF_NET_DST) ||
+ (cinfo->columns[column].col_fmt == COL_RES_NET_DST) ||
+ (cinfo->columns[column].col_fmt == COL_UNRES_NET_DST)) &&
strlen(cinfo->col_expr.col_expr_val[column]))
{
return true;
}
+ if ((cinfo->columns[column].col_fmt == COL_CUSTOM) &&
+ cinfo->columns[column].col_custom_fields) {
+ // We could cycle through all the col_custom_fields_ids and
+ // see if proto_registrar_get_ftype() says that any of them
+ // are FT_IPv4 or FT_IPv6, but let's just check the string
+ // against all the addresses we found from the tree.
+ return true;
+ }
+
return false;
}
diff --git a/ui/qt/address_editor_frame.h b/ui/qt/address_editor_frame.h
index 300e4dd5d6..a4981e350b 100644
--- a/ui/qt/address_editor_frame.h
+++ b/ui/qt/address_editor_frame.h
@@ -14,6 +14,9 @@
#include "capture_file.h"
+#include <ui/qt/utils/field_information.h>
+#include <ui/qt/utils/proto_node.h>
+
namespace Ui {
class AddressEditorFrame;
}
@@ -52,6 +55,8 @@ private:
Ui::AddressEditorFrame *ui;
capture_file *cap_file_;
+ static QString addressToString(const FieldInformation& finfo);
+ static void addAddresses(const ProtoNode& node, QStringList& addresses);
bool isAddressColumn(struct epan_column_info *cinfo, int column);
};
diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp
index 9d59d7acdb..33fb733b55 100644
--- a/ui/qt/proto_tree.cpp
+++ b/ui/qt/proto_tree.cpp
@@ -286,6 +286,11 @@ void ProtoTree::contextMenuEvent(QContextMenuEvent *event)
if (! buildForDialog)
{
+ if (finfo->headerInfo().type == FT_IPv4 || finfo->headerInfo().type == FT_IPv6) {
+ action = window()->findChild<QAction *>("actionViewEditResolvedName");
+ ctx_menu->addAction(action);
+ ctx_menu->addSeparator();
+ }
action = window()->findChild<QAction *>("actionAnalyzeApplyAsColumn");
ctx_menu->addAction(action);
ctx_menu->addSeparator();
diff --git a/ui/qt/utils/field_information.cpp b/ui/qt/utils/field_information.cpp
index 584975601b..395bde2fa8 100644
--- a/ui/qt/utils/field_information.cpp
+++ b/ui/qt/utils/field_information.cpp
@@ -18,7 +18,7 @@ FieldInformation::FieldInformation(field_info *fi, QObject * parent)
parent_fi_ = NULL;
}
-FieldInformation::FieldInformation(ProtoNode *node, QObject * parent)
+FieldInformation::FieldInformation(const ProtoNode *node, QObject * parent)
:QObject(parent)
{
fi_ = NULL;
diff --git a/ui/qt/utils/field_information.h b/ui/qt/utils/field_information.h
index 56e211e315..b0001b716c 100644
--- a/ui/qt/utils/field_information.h
+++ b/ui/qt/utils/field_information.h
@@ -44,7 +44,7 @@ public:
};
explicit FieldInformation(field_info * fi, QObject * parent = Q_NULLPTR);
- explicit FieldInformation(ProtoNode * node, QObject * parent = Q_NULLPTR);
+ explicit FieldInformation(const ProtoNode * node, QObject * parent = Q_NULLPTR);
bool isValid() const;
bool isLink() const ;
diff --git a/ui/qt/wireshark_main_window_slots.cpp b/ui/qt/wireshark_main_window_slots.cpp
index 207a4d4d76..d19c9bf019 100644
--- a/ui/qt/wireshark_main_window_slots.cpp
+++ b/ui/qt/wireshark_main_window_slots.cpp
@@ -2677,8 +2677,10 @@ void WiresharkMainWindow::editResolvedName()
//int column = packet_list_->selectedColumn();
int column = -1;
- if (packet_list_->currentIndex().isValid()) {
- column = packet_list_->currentIndex().column();
+ if (packet_list_->contextMenuActive() || packet_list_->hasFocus()) {
+ if (packet_list_->currentIndex().isValid()) {
+ column = packet_list_->currentIndex().column();
+ }
}
main_ui_->addressEditorFrame->editAddresses(capture_file_, column);