2016-10-01 06:54:57 +00:00
|
|
|
/* interface_tree_model.cpp
|
|
|
|
* Model for the interface data for display in the interface frame
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-04-30 07:47:58 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2016-10-01 06:54:57 +00:00
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2017-07-25 14:47:16 +00:00
|
|
|
#include <ui/qt/models/interface_tree_model.h>
|
2016-10-01 06:54:57 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
#include "ui/capture.h"
|
2021-03-24 22:09:19 +00:00
|
|
|
#include "capture/capture-pcap-util.h"
|
2016-10-01 06:54:57 +00:00
|
|
|
#include "capture_opts.h"
|
|
|
|
#include "ui/capture_ui_utils.h"
|
|
|
|
#include "ui/capture_globals.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "wsutil/filesystem.h"
|
|
|
|
|
2017-07-25 14:15:18 +00:00
|
|
|
#include <ui/qt/utils/qt_ui_utils.h>
|
|
|
|
#include <ui/qt/utils/stock_icon.h>
|
2016-10-01 06:54:57 +00:00
|
|
|
#include "wireshark_application.h"
|
|
|
|
|
|
|
|
/* Needed for the meta type declaration of QList<int>* */
|
2017-07-25 14:47:16 +00:00
|
|
|
#include <ui/qt/models/sparkline_delegate.h>
|
2016-10-01 06:54:57 +00:00
|
|
|
|
|
|
|
#include "extcap.h"
|
|
|
|
|
2016-11-07 04:54:59 +00:00
|
|
|
const QString InterfaceTreeModel::DefaultNumericValue = QObject::tr("default");
|
2016-10-25 09:26:26 +00:00
|
|
|
|
2016-10-01 06:54:57 +00:00
|
|
|
/**
|
|
|
|
* This is the data model for interface trees. It implies, that the index within
|
|
|
|
* global_capture_opts.all_ifaces is identical to the row. This is always the case, even
|
|
|
|
* when interfaces are hidden by the proxy model. But for this to work, every access
|
|
|
|
* to the index from within the view, has to be filtered through the proxy model.
|
|
|
|
*/
|
|
|
|
InterfaceTreeModel::InterfaceTreeModel(QObject *parent) :
|
|
|
|
QAbstractTableModel(parent)
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
,stat_cache_(NULL)
|
|
|
|
#endif
|
|
|
|
{
|
2018-12-23 20:46:25 +00:00
|
|
|
connect(wsApp, &WiresharkApplication::appInitialized, this, &InterfaceTreeModel::interfaceListChanged);
|
|
|
|
connect(wsApp, &WiresharkApplication::localInterfaceListChanged, this, &InterfaceTreeModel::interfaceListChanged);
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
InterfaceTreeModel::~InterfaceTreeModel(void)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
if (stat_cache_) {
|
|
|
|
capture_stat_stop(stat_cache_);
|
|
|
|
stat_cache_ = NULL;
|
|
|
|
}
|
|
|
|
#endif // HAVE_LIBPCAP
|
|
|
|
}
|
|
|
|
|
2016-10-03 14:31:36 +00:00
|
|
|
QString InterfaceTreeModel::interfaceError()
|
|
|
|
{
|
Fix reporting of interface-list-fetching errors.
If the attempt to fetch the list of local interfaces failed, the model
will be empty, so "model is empty" doesn't imply "no interfaces found".
First, check whether there was an error, and report the error string;
otherwise, if the list is empty, report "No interfaces found." (and fix
the capitalization while we're at it) and, otherwise, return an empty
string.
Also, if pcap support wasn't configured in at compile time, skip all
that, and just return a string indicating that.
Change-Id: I498226888272e1bdede2355cc902f8a74b0cce72
Reviewed-on: https://code.wireshark.org/review/36446
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2020-03-16 06:23:43 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
//
|
|
|
|
// First, see if there was an error fetching the interfaces.
|
|
|
|
// If so, report it.
|
|
|
|
//
|
|
|
|
if (global_capture_opts.ifaces_err != 0)
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
Fix reporting of interface-list-fetching errors.
If the attempt to fetch the list of local interfaces failed, the model
will be empty, so "model is empty" doesn't imply "no interfaces found".
First, check whether there was an error, and report the error string;
otherwise, if the list is empty, report "No interfaces found." (and fix
the capitalization while we're at it) and, otherwise, return an empty
string.
Also, if pcap support wasn't configured in at compile time, skip all
that, and just return a string indicating that.
Change-Id: I498226888272e1bdede2355cc902f8a74b0cce72
Reviewed-on: https://code.wireshark.org/review/36446
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2020-03-16 06:23:43 +00:00
|
|
|
return tr(global_capture_opts.ifaces_err_info);
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
Fix reporting of interface-list-fetching errors.
If the attempt to fetch the list of local interfaces failed, the model
will be empty, so "model is empty" doesn't imply "no interfaces found".
First, check whether there was an error, and report the error string;
otherwise, if the list is empty, report "No interfaces found." (and fix
the capitalization while we're at it) and, otherwise, return an empty
string.
Also, if pcap support wasn't configured in at compile time, skip all
that, and just return a string indicating that.
Change-Id: I498226888272e1bdede2355cc902f8a74b0cce72
Reviewed-on: https://code.wireshark.org/review/36446
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2020-03-16 06:23:43 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Otherwise, if there are no rows, there were no interfaces
|
|
|
|
// found.
|
|
|
|
//
|
|
|
|
if (rowCount() == 0)
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
Fix reporting of interface-list-fetching errors.
If the attempt to fetch the list of local interfaces failed, the model
will be empty, so "model is empty" doesn't imply "no interfaces found".
First, check whether there was an error, and report the error string;
otherwise, if the list is empty, report "No interfaces found." (and fix
the capitalization while we're at it) and, otherwise, return an empty
string.
Also, if pcap support wasn't configured in at compile time, skip all
that, and just return a string indicating that.
Change-Id: I498226888272e1bdede2355cc902f8a74b0cce72
Reviewed-on: https://code.wireshark.org/review/36446
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2020-03-16 06:23:43 +00:00
|
|
|
return tr("No interfaces found.");
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
|
|
|
|
Fix reporting of interface-list-fetching errors.
If the attempt to fetch the list of local interfaces failed, the model
will be empty, so "model is empty" doesn't imply "no interfaces found".
First, check whether there was an error, and report the error string;
otherwise, if the list is empty, report "No interfaces found." (and fix
the capitalization while we're at it) and, otherwise, return an empty
string.
Also, if pcap support wasn't configured in at compile time, skip all
that, and just return a string indicating that.
Change-Id: I498226888272e1bdede2355cc902f8a74b0cce72
Reviewed-on: https://code.wireshark.org/review/36446
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2020-03-16 06:23:43 +00:00
|
|
|
//
|
|
|
|
// No error. Return an empty string.
|
|
|
|
//
|
|
|
|
return "";
|
|
|
|
#else
|
|
|
|
//
|
|
|
|
// We were built without pcap support, so we have no notion of
|
|
|
|
// local interfaces.
|
|
|
|
//
|
|
|
|
return tr("This version of Wireshark was built without packet capture support.");
|
|
|
|
#endif
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
|
|
|
|
2019-11-17 19:02:20 +00:00
|
|
|
int InterfaceTreeModel::rowCount(const QModelIndex &) const
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
2016-10-02 14:47:04 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2016-10-01 06:54:57 +00:00
|
|
|
return (global_capture_opts.all_ifaces ? global_capture_opts.all_ifaces->len : 0);
|
2016-10-02 14:47:04 +00:00
|
|
|
#else
|
|
|
|
/* Currently no interfaces available for libpcap-less builds */
|
|
|
|
return 0;
|
|
|
|
#endif
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
|
|
|
|
2019-11-17 19:02:20 +00:00
|
|
|
int InterfaceTreeModel::columnCount(const QModelIndex &) const
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
|
|
|
/* IFTREE_COL_MAX is not being displayed, it is the definition for the maximum numbers of columns */
|
|
|
|
return ((int) IFTREE_COL_MAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant InterfaceTreeModel::data(const QModelIndex &index, int role) const
|
|
|
|
{
|
2016-10-02 14:47:04 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2016-10-01 06:54:57 +00:00
|
|
|
bool interfacesLoaded = true;
|
2019-11-17 19:02:20 +00:00
|
|
|
if (! global_capture_opts.all_ifaces || global_capture_opts.all_ifaces->len == 0)
|
2016-10-01 06:54:57 +00:00
|
|
|
interfacesLoaded = false;
|
|
|
|
|
2019-11-17 19:02:20 +00:00
|
|
|
if (!index.isValid())
|
2016-10-01 06:54:57 +00:00
|
|
|
return QVariant();
|
|
|
|
|
|
|
|
int row = index.row();
|
2016-10-17 13:01:24 +00:00
|
|
|
InterfaceTreeColumns col = (InterfaceTreeColumns) index.column();
|
2016-10-01 06:54:57 +00:00
|
|
|
|
2019-11-17 19:02:20 +00:00
|
|
|
if (interfacesLoaded)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, row);
|
2016-10-17 13:01:24 +00:00
|
|
|
|
|
|
|
/* Data for display in cell */
|
2019-11-17 19:02:20 +00:00
|
|
|
if (role == Qt::DisplayRole)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
|
|
|
/* Only the name is being displayed */
|
2019-11-17 19:02:20 +00:00
|
|
|
if (col == IFTREE_COL_NAME)
|
2018-08-12 01:55:01 +00:00
|
|
|
{
|
|
|
|
return QString(device->name);
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_DESCRIPTION)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
2018-08-12 00:45:19 +00:00
|
|
|
return QString(device->friendly_name);
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_DISPLAY_NAME)
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
2018-08-12 01:55:01 +00:00
|
|
|
return QString(device->display_name);
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_PIPE_PATH)
|
2016-10-25 12:27:56 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
return QString(device->if_info.name);
|
2016-10-25 12:27:56 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_CAPTURE_FILTER)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (device->cfilter && strlen(device->cfilter) > 0)
|
2017-08-24 14:16:34 +00:00
|
|
|
return html_escape(QString(device->cfilter));
|
2016-10-25 09:26:26 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_EXTCAP_PATH)
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
return QString(device->if_info.extcap);
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_SNAPLEN)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
return device->has_snaplen ? QString::number(device->snaplen) : DefaultNumericValue;
|
2016-10-25 09:26:26 +00:00
|
|
|
}
|
|
|
|
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_BUFFERLEN)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
return QString::number(device->buffer);
|
2016-10-25 09:26:26 +00:00
|
|
|
}
|
|
|
|
#endif
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_TYPE)
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
return QVariant::fromValue((int)device->if_info.type);
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_COMMENT)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
QString comment = gchar_free_to_qstring(capture_dev_user_descr_find(device->name));
|
2019-11-17 19:02:20 +00:00
|
|
|
if (comment.length() > 0)
|
2016-10-17 13:01:24 +00:00
|
|
|
return comment;
|
|
|
|
else
|
2017-08-24 14:16:34 +00:00
|
|
|
return QString(device->if_info.vendor_description);
|
2016-10-17 13:01:24 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_DLT)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
2018-06-10 02:42:32 +00:00
|
|
|
// XXX - this is duplicated in
|
|
|
|
// InterfaceTreeWidgetItem::updateInterfaceColumns;
|
|
|
|
// it should be done in common code somewhere.
|
|
|
|
QString linkname;
|
|
|
|
if (device->active_dlt == -1)
|
|
|
|
linkname = "Unknown";
|
|
|
|
else {
|
|
|
|
linkname = QObject::tr("DLT %1").arg(device->active_dlt);
|
2019-08-14 08:18:51 +00:00
|
|
|
for (GList *list = device->links; list != Q_NULLPTR; list = gxx_list_next(list)) {
|
|
|
|
link_row *linkr = gxx_list_data(link_row *, list);
|
2018-06-10 02:42:32 +00:00
|
|
|
if (linkr->dlt == device->active_dlt) {
|
|
|
|
linkname = linkr->name;
|
|
|
|
break;
|
|
|
|
}
|
2016-10-25 09:26:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return linkname;
|
|
|
|
}
|
2016-10-17 13:01:24 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Return empty string for every other DisplayRole */
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (role == Qt::CheckStateRole)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (col == IFTREE_COL_HIDDEN)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
|
|
|
/* Hidden is a de-selection, therefore inverted logic here */
|
2017-08-24 14:16:34 +00:00
|
|
|
return device->hidden ? Qt::Unchecked : Qt::Checked;
|
2016-10-17 13:01:24 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_PROMISCUOUSMODE)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
return device->pmode ? Qt::Checked : Qt::Unchecked;
|
2016-10-25 09:26:26 +00:00
|
|
|
}
|
|
|
|
#ifdef HAVE_PCAP_CREATE
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_MONITOR_MODE)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
return device->monitor_mode_enabled ? Qt::Checked : Qt::Unchecked;
|
2016-10-25 09:26:26 +00:00
|
|
|
}
|
|
|
|
#endif
|
2016-10-17 13:01:24 +00:00
|
|
|
}
|
|
|
|
/* Used by SparkLineDelegate for loading the data for the statistics line */
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (role == Qt::UserRole)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (col == IFTREE_COL_STATS)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (points.contains(device->name))
|
2018-01-15 07:53:55 +00:00
|
|
|
return QVariant::fromValue(points[device->name]);
|
2016-10-17 13:01:24 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (col == IFTREE_COL_HIDDEN)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
return QVariant::fromValue((bool)device->hidden);
|
2016-10-17 13:01:24 +00:00
|
|
|
}
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
2016-10-17 13:01:24 +00:00
|
|
|
/* Displays the configuration icon for extcap interfaces */
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (role == Qt::DecorationRole)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (col == IFTREE_COL_EXTCAP)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (device->if_info.type == IF_EXTCAP)
|
2016-10-17 13:01:24 +00:00
|
|
|
return QIcon(StockIcon("x-capture-options"));
|
|
|
|
}
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (role == Qt::TextAlignmentRole)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (col == IFTREE_COL_EXTCAP)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
|
|
|
return Qt::AlignRight;
|
|
|
|
}
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
2016-10-17 13:01:24 +00:00
|
|
|
/* Displays the tooltip for each row */
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (role == Qt::ToolTipRole)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
|
|
|
return toolTipForInterface(row);
|
|
|
|
}
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
2016-10-17 05:32:00 +00:00
|
|
|
#else
|
2017-04-25 20:51:53 +00:00
|
|
|
Q_UNUSED(index)
|
|
|
|
Q_UNUSED(role)
|
2016-10-17 05:32:00 +00:00
|
|
|
#endif
|
2016-10-01 06:54:57 +00:00
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
2016-10-17 13:01:24 +00:00
|
|
|
QVariant InterfaceTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (orientation == Qt::Horizontal)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (role == Qt::DisplayRole)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (section == IFTREE_COL_HIDDEN)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
|
|
|
return tr("Show");
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_NAME)
|
2018-08-12 01:55:01 +00:00
|
|
|
{
|
|
|
|
return tr("Interface Name");
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_DESCRIPTION)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
|
|
|
return tr("Friendly Name");
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_DISPLAY_NAME)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
2018-08-12 01:55:01 +00:00
|
|
|
return tr("Friendly Name");
|
2016-10-17 13:01:24 +00:00
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_PIPE_PATH)
|
2016-10-25 12:27:56 +00:00
|
|
|
{
|
|
|
|
return tr("Local Pipe Path");
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_COMMENT)
|
2016-10-17 13:01:24 +00:00
|
|
|
{
|
|
|
|
return tr("Comment");
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_DLT)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
|
|
|
return tr("Link-Layer Header");
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_PROMISCUOUSMODE)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
|
|
|
return tr("Promiscuous");
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_SNAPLEN)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
|
|
|
return tr("Snaplen (B)");
|
|
|
|
}
|
|
|
|
#ifdef CAN_SET_CAPTURE_BUFFER_SIZE
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_BUFFERLEN)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
|
|
|
return tr("Buffer (MB)");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_PCAP_CREATE
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_MONITOR_MODE)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
|
|
|
return tr("Monitor Mode");
|
|
|
|
}
|
|
|
|
#endif
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (section == IFTREE_COL_CAPTURE_FILTER)
|
2016-10-25 09:26:26 +00:00
|
|
|
{
|
|
|
|
return tr("Capture Filter");
|
|
|
|
}
|
2016-10-17 13:01:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
2016-10-06 15:04:45 +00:00
|
|
|
QVariant InterfaceTreeModel::getColumnContent(int idx, int col, int role)
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
2016-10-06 15:04:45 +00:00
|
|
|
return InterfaceTreeModel::data(index(idx, col), role);
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
|
|
|
|
2016-12-27 09:14:32 +00:00
|
|
|
#ifdef HAVE_PCAP_REMOTE
|
|
|
|
bool InterfaceTreeModel::isRemote(int idx)
|
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
|
2019-11-17 19:02:20 +00:00
|
|
|
if (device->remote_opts.src_type == CAPTURE_IFREMOTE)
|
2016-12-27 09:14:32 +00:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-10-01 06:54:57 +00:00
|
|
|
/**
|
|
|
|
* The interface list has changed. global_capture_opts.all_ifaces may have been reloaded
|
|
|
|
* or changed with current data. beginResetModel() and endResetModel() will signalize the
|
|
|
|
* proxy model and the view, that the data has changed and the view has to reload
|
|
|
|
*/
|
|
|
|
void InterfaceTreeModel::interfaceListChanged()
|
|
|
|
{
|
|
|
|
emit beginResetModel();
|
|
|
|
|
|
|
|
points.clear();
|
|
|
|
|
|
|
|
emit endResetModel();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Displays the tooltip code for the given device index.
|
|
|
|
*/
|
|
|
|
QVariant InterfaceTreeModel::toolTipForInterface(int idx) const
|
|
|
|
{
|
2016-10-02 14:47:04 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2019-11-17 19:02:20 +00:00
|
|
|
if (! global_capture_opts.all_ifaces || global_capture_opts.all_ifaces->len <= (guint) idx)
|
2016-10-01 06:54:57 +00:00
|
|
|
return QVariant();
|
|
|
|
|
2017-08-24 14:16:34 +00:00
|
|
|
interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
|
2016-10-01 06:54:57 +00:00
|
|
|
|
|
|
|
QString tt_str = "<p>";
|
2019-11-17 19:02:20 +00:00
|
|
|
if (device->no_addresses > 0)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
|
|
|
tt_str += QString("%1: %2")
|
2017-08-24 14:16:34 +00:00
|
|
|
.arg(device->no_addresses > 1 ? tr("Addresses") : tr("Address"))
|
|
|
|
.arg(html_escape(device->addresses))
|
2016-10-01 06:54:57 +00:00
|
|
|
.replace('\n', ", ");
|
|
|
|
}
|
2019-11-17 19:02:20 +00:00
|
|
|
else if (device->if_info.type == IF_EXTCAP)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
tt_str = QString(tr("Extcap interface: %1")).arg(get_basename(device->if_info.extcap));
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tt_str = tr("No addresses");
|
|
|
|
}
|
|
|
|
tt_str += "<br/>";
|
|
|
|
|
2017-08-24 14:16:34 +00:00
|
|
|
QString cfilter = device->cfilter;
|
2019-11-17 19:02:20 +00:00
|
|
|
if (cfilter.isEmpty())
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
|
|
|
tt_str += tr("No capture filter");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tt_str += QString("%1: %2")
|
|
|
|
.arg(tr("Capture filter"))
|
|
|
|
.arg(html_escape(cfilter));
|
|
|
|
}
|
|
|
|
tt_str += "</p>";
|
|
|
|
|
|
|
|
return tt_str;
|
2016-10-02 14:47:04 +00:00
|
|
|
#else
|
2017-04-25 20:51:53 +00:00
|
|
|
Q_UNUSED(idx)
|
2016-10-02 14:47:04 +00:00
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
#endif
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
void InterfaceTreeModel::stopStatistic()
|
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (stat_cache_)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
|
|
|
capture_stat_stop(stat_cache_);
|
|
|
|
stat_cache_ = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void InterfaceTreeModel::updateStatistic(unsigned int idx)
|
|
|
|
{
|
2016-10-02 14:47:04 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2019-11-17 19:02:20 +00:00
|
|
|
if (! global_capture_opts.all_ifaces || global_capture_opts.all_ifaces->len <= (guint) idx)
|
2016-10-01 06:54:57 +00:00
|
|
|
return;
|
|
|
|
|
2017-08-24 14:16:34 +00:00
|
|
|
interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
|
2016-10-01 06:54:57 +00:00
|
|
|
|
2019-11-17 19:02:20 +00:00
|
|
|
if (device->if_info.type == IF_PIPE)
|
2016-10-01 06:54:57 +00:00
|
|
|
return;
|
|
|
|
|
2019-11-17 19:02:20 +00:00
|
|
|
if (!stat_cache_)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
|
|
|
// Start gathering statistics using dumpcap
|
2017-04-05 19:15:27 +00:00
|
|
|
// We crash (on macOS at least) if we try to do this from ::showEvent.
|
2016-10-01 06:54:57 +00:00
|
|
|
stat_cache_ = capture_stat_start(&global_capture_opts);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct pcap_stat stats;
|
2018-12-13 17:42:23 +00:00
|
|
|
unsigned diff = 0;
|
2016-10-01 06:54:57 +00:00
|
|
|
|
2019-11-17 19:02:20 +00:00
|
|
|
if (capture_stats(stat_cache_, device->name, &stats))
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if ((int)(stats.ps_recv - device->last_packets) >= 0)
|
2016-10-01 06:54:57 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
diff = stats.ps_recv - device->last_packets;
|
|
|
|
device->packet_diff = diff;
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
2017-08-24 14:16:34 +00:00
|
|
|
device->last_packets = stats.ps_recv;
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
|
|
|
|
2017-08-24 14:16:34 +00:00
|
|
|
points[device->name].append(diff);
|
2016-10-01 06:54:57 +00:00
|
|
|
emit dataChanged(index(idx, IFTREE_COL_STATS), index(idx, IFTREE_COL_STATS));
|
2016-10-02 14:47:04 +00:00
|
|
|
#else
|
2017-04-25 20:51:53 +00:00
|
|
|
Q_UNUSED(idx)
|
2016-10-02 14:47:04 +00:00
|
|
|
#endif
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void InterfaceTreeModel::getPoints(int idx, PointList *pts)
|
|
|
|
{
|
2016-10-02 14:47:04 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2019-11-17 19:02:20 +00:00
|
|
|
if (! global_capture_opts.all_ifaces || global_capture_opts.all_ifaces->len <= (guint) idx)
|
2016-10-01 06:54:57 +00:00
|
|
|
return;
|
|
|
|
|
2017-08-24 14:16:34 +00:00
|
|
|
interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
|
2019-11-17 19:02:20 +00:00
|
|
|
if (points.contains(device->name))
|
2017-08-24 14:16:34 +00:00
|
|
|
pts->append(points[device->name]);
|
2016-10-02 14:47:04 +00:00
|
|
|
#else
|
2017-04-25 20:51:53 +00:00
|
|
|
Q_UNUSED(idx)
|
|
|
|
Q_UNUSED(pts)
|
2016-10-02 14:47:04 +00:00
|
|
|
#endif
|
2016-10-01 06:54:57 +00:00
|
|
|
}
|
2016-10-03 14:31:36 +00:00
|
|
|
|
|
|
|
QItemSelection InterfaceTreeModel::selectedDevices()
|
|
|
|
{
|
|
|
|
QItemSelection mySelection;
|
2016-10-03 17:57:44 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2019-11-17 19:02:20 +00:00
|
|
|
for (int idx = 0; idx < rowCount(); idx++)
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
|
2016-10-03 14:31:36 +00:00
|
|
|
|
2019-11-17 19:02:20 +00:00
|
|
|
if (device->selected)
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
|
|
|
QModelIndex selectIndex = index(idx, 0);
|
|
|
|
mySelection.merge(
|
2019-11-17 19:02:20 +00:00
|
|
|
QItemSelection(selectIndex, index(selectIndex.row(), columnCount() - 1)),
|
2016-10-03 14:31:36 +00:00
|
|
|
QItemSelectionModel::SelectCurrent
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2016-10-03 17:57:44 +00:00
|
|
|
#endif
|
2016-10-03 14:31:36 +00:00
|
|
|
return mySelection;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool InterfaceTreeModel::updateSelectedDevices(QItemSelection sourceSelection)
|
|
|
|
{
|
|
|
|
bool selectionHasChanged = false;
|
2016-10-03 17:57:44 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2016-10-03 14:31:36 +00:00
|
|
|
QList<int> selectedIndices;
|
|
|
|
|
2016-10-18 20:28:28 +00:00
|
|
|
QItemSelection::const_iterator it = sourceSelection.constBegin();
|
2019-11-17 19:02:20 +00:00
|
|
|
while (it != sourceSelection.constEnd())
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
2016-10-18 20:28:28 +00:00
|
|
|
QModelIndexList indeces = ((QItemSelectionRange) (*it)).indexes();
|
|
|
|
|
|
|
|
QModelIndexList::const_iterator cit = indeces.constBegin();
|
2019-11-17 19:02:20 +00:00
|
|
|
while (cit != indeces.constEnd())
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
2016-10-18 20:28:28 +00:00
|
|
|
QModelIndex index = (QModelIndex) (*cit);
|
2019-11-17 19:02:20 +00:00
|
|
|
if (! selectedIndices.contains(index.row()))
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
|
|
|
selectedIndices.append(index.row());
|
|
|
|
}
|
2016-10-18 20:28:28 +00:00
|
|
|
++cit;
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
2016-10-18 20:28:28 +00:00
|
|
|
++it;
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
global_capture_opts.num_selected = 0;
|
|
|
|
|
2019-11-17 19:02:20 +00:00
|
|
|
for (unsigned int idx = 0; idx < global_capture_opts.all_ifaces->len; idx++)
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
2017-08-24 14:16:34 +00:00
|
|
|
interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, idx);
|
2019-11-17 19:02:20 +00:00
|
|
|
if (selectedIndices.contains(idx))
|
2016-10-03 14:31:36 +00:00
|
|
|
{
|
2019-11-17 19:02:20 +00:00
|
|
|
if (! device->selected)
|
2017-08-28 08:38:31 +00:00
|
|
|
selectionHasChanged = true;
|
|
|
|
device->selected = TRUE;
|
|
|
|
global_capture_opts.num_selected++;
|
|
|
|
} else {
|
2019-11-17 19:02:20 +00:00
|
|
|
if (device->selected)
|
2017-08-28 08:38:31 +00:00
|
|
|
selectionHasChanged = true;
|
|
|
|
device->selected = FALSE;
|
2016-10-03 14:31:36 +00:00
|
|
|
}
|
|
|
|
}
|
2016-10-03 17:57:44 +00:00
|
|
|
#else
|
2017-04-25 20:51:53 +00:00
|
|
|
Q_UNUSED(sourceSelection)
|
2016-10-03 17:57:44 +00:00
|
|
|
#endif
|
2016-10-03 14:31:36 +00:00
|
|
|
return selectionHasChanged;
|
|
|
|
}
|