aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docbook/wsug_src/wsug_work.adoc1
-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
8 files changed, 129 insertions, 18 deletions
diff --git a/docbook/wsug_src/wsug_work.adoc b/docbook/wsug_src/wsug_work.adoc
index aac9f1a4fe..deff08bd92 100644
--- a/docbook/wsug_src/wsug_work.adoc
+++ b/docbook/wsug_src/wsug_work.adoc
@@ -244,6 +244,7 @@ description of each item.
|menu:Collapse Subtrees[]|menu:View[]| Collapse the currently selected subtree.
|menu:Expand All[]|menu:View[]| Expand all subtrees in all packets in the capture.
|menu:Collapse All[]|menu:View[]| Wireshark keeps a list of all the protocol subtrees that are expanded, and uses it to ensure that the correct subtrees are expanded when you display a packet. This menu item collapses the tree view of all packets in the capture list.
+|menu:Edit Resolved Name[]|menu:View[]| Allows you to enter a name to resolve for the selected address.
|menu:Apply as Column[]|| Use the selected protocol item to create a new column in the packet list.
|menu:Apply as Filter[]|menu:Analyze[]|
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);