diff --git a/capture_opts.h b/capture_opts.h index 704242f0f0..f9bdf89eb6 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -125,6 +125,7 @@ typedef struct interface_tag { remote_options remote_opts; #endif guint32 last_packets; + guint32 packet_diff; if_info_t if_info; gboolean selected; gboolean hidden; diff --git a/capture_ui_utils.c b/capture_ui_utils.c index d184ab1c77..ccd94b3549 100644 --- a/capture_ui_utils.c +++ b/capture_ui_utils.c @@ -101,7 +101,7 @@ capture_dev_user_descr_find(const gchar *if_name) gint capture_dev_user_linktype_find(const gchar *if_name) { - gchar *p, *next; + gchar *p, *next, *tmpname; long linktype; if ((prefs.capture_devices_linktypes == NULL) || @@ -109,13 +109,13 @@ capture_dev_user_linktype_find(const gchar *if_name) /* There are no link-layer header types */ return -1; } - - if ((p = strstr(prefs.capture_devices_linktypes, if_name)) == NULL) { + tmpname = g_strdup_printf(",%s(", if_name); + if ((p = strstr(prefs.capture_devices_linktypes, tmpname)) == NULL) { /* There are, but there isn't one for this interface. */ return -1; } - p += strlen(if_name) + 1; + p += strlen(if_name) + 2; linktype = strtol(p, &next, 10); if (next == p || *next != ')' || linktype < 0) { /* Syntax error */ @@ -133,7 +133,7 @@ capture_dev_user_linktype_find(const gchar *if_name) gint capture_dev_user_buffersize_find(const gchar *if_name) { - gchar *p, *next; + gchar *p, *next, *tmpname; gint buffersize; if ((prefs.capture_devices_buffersize == NULL) || @@ -141,13 +141,13 @@ capture_dev_user_buffersize_find(const gchar *if_name) /* There are no buffersizes defined */ return -1; } - - if ((p = strstr(prefs.capture_devices_buffersize, if_name)) == NULL) { + tmpname = g_strdup_printf(",%s(", if_name); + if ((p = strstr(prefs.capture_devices_buffersize, tmpname)) == NULL) { /* There are, but there isn't one for this interface. */ return -1; } - p += strlen(if_name) + 1; + p += strlen(if_name) + 2; buffersize = (gint)strtol(p, &next, 10); if (next == p || *next != ')' || buffersize < 0) { /* Syntax error */ @@ -165,7 +165,7 @@ capture_dev_user_buffersize_find(const gchar *if_name) gint capture_dev_user_snaplen_find(const gchar *if_name) { - gchar *p, *next; + gchar *p, *next, *tmpname; gint snaplen; if ((prefs.capture_devices_snaplen == NULL) || @@ -173,13 +173,13 @@ capture_dev_user_snaplen_find(const gchar *if_name) /* There is no snap length defined */ return -1; } - - if ((p = strstr(prefs.capture_devices_snaplen, if_name)) == NULL) { + tmpname = g_strdup_printf(",%s:", if_name); + if ((p = strstr(prefs.capture_devices_snaplen, tmpname)) == NULL) { /* There are, but there isn't one for this interface. */ return -1; } - p += strlen(if_name) + 3; + p += strlen(if_name) + 4; snaplen = (gint)strtol(p, &next, 10); if (next == p || *next != ')' || snaplen < 0) { /* Syntax error */ @@ -196,7 +196,7 @@ capture_dev_user_snaplen_find(const gchar *if_name) gboolean capture_dev_user_hassnap_find(const gchar *if_name) { - gchar *p, *next; + gchar *p, *next, *tmpname; gboolean hassnap; if ((prefs.capture_devices_snaplen == NULL) || @@ -204,13 +204,13 @@ capture_dev_user_hassnap_find(const gchar *if_name) /* There is no snap length defined */ return -1; } - - if ((p = strstr(prefs.capture_devices_snaplen, if_name)) == NULL) { + tmpname = g_strdup_printf(",%s:", if_name); + if ((p = strstr(prefs.capture_devices_snaplen, tmpname)) == NULL) { /* There are, but there isn't one for this interface. */ return -1; } - p += strlen(if_name) + 1; + p += strlen(if_name) + 2; hassnap = (gboolean)strtol(p, &next, 10); if (next == p || *next != '(') { /* Syntax error */ @@ -223,7 +223,7 @@ capture_dev_user_hassnap_find(const gchar *if_name) gboolean capture_dev_user_pmode_find(const gchar *if_name) { - gchar *p, *next; + gchar *p, *next, *tmpname; gboolean pmode; if ((prefs.capture_devices_pmode == NULL) || @@ -231,13 +231,13 @@ capture_dev_user_pmode_find(const gchar *if_name) /* There is no promiscuous mode defined */ return -1; } - - if ((p = strstr(prefs.capture_devices_pmode, if_name)) == NULL) { + tmpname = g_strdup_printf(",%s(", if_name); + if ((p = strstr(prefs.capture_devices_pmode, tmpname)) == NULL) { /* There are, but there isn't one for this interface. */ return -1; } - p += strlen(if_name) + 1; + p += strlen(if_name) + 2; pmode = (gboolean)strtol(p, &next, 10); if (next == p || *next != ')') { /* Syntax error */ @@ -246,6 +246,32 @@ capture_dev_user_pmode_find(const gchar *if_name) return (gboolean)pmode; } +gchar* +capture_dev_user_cfilter_find(const gchar *if_name) +{ + gchar *p, q[MAX_VAL_LEN], *tmpname; + int i = 0; + + if ((prefs.capture_devices_filter == NULL) || + (*prefs.capture_devices_filter == '\0')) { + /* There is no capture filter defined */ + return NULL; + } + tmpname = g_strdup_printf(",%s(", if_name); + if ((p = strstr(prefs.capture_devices_filter, tmpname)) == NULL) { + /* There are, but there isn't one for this interface. */ + return NULL; + } + + p += strlen(if_name) + 2; + while (p[i+1] != ',' && p[i+1] != '\0') { + q[i] = p[i]; + i++; + } + q[i] = '\0'; + return g_strdup(q); +} + /* * Return as descriptive a name for an interface as we can get. * If the user has specified a comment, use that. Otherwise, diff --git a/capture_ui_utils.h b/capture_ui_utils.h index a09db8d7ea..fd2a4e4b1e 100644 --- a/capture_ui_utils.h +++ b/capture_ui_utils.h @@ -66,6 +66,12 @@ gboolean capture_dev_user_hassnap_find(const gchar *if_name); */ gboolean capture_dev_user_pmode_find(const gchar *if_name); +/** + * Find user-specified capture filter that matches interface + * name, if any. + */ +gchar* capture_dev_user_cfilter_find(const gchar *if_name); + /** Return as descriptive a name for an interface as we can get. * If the user has specified a comment, use that. Otherwise, * if capture_interface_list() supplies a description, use that, diff --git a/epan/prefs.c b/epan/prefs.c index 6bfe314dd4..0cc1ff92d4 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -2431,6 +2431,10 @@ prefs_register_modules(void) prefs_register_bool_preference(capture_module, "prom_mode", "Capture in promiscuous mode", "Capture in promiscuous mode?", &prefs.capture_prom_mode); + prefs_register_string_preference(capture_module, "devices_filter", "Interface capture filter", + "Interface capture filter (Ex: en0(tcp),en1(udp),...)", + (const char **)&prefs.capture_devices_filter); + prefs_register_bool_preference(capture_module, "pcap_ng", "Capture in Pcap-NG format", "Capture in Pcap-NG format?", &prefs.capture_pcap_ng); diff --git a/epan/prefs.h b/epan/prefs.h index f757bbc818..12093ecd43 100644 --- a/epan/prefs.h +++ b/epan/prefs.h @@ -193,6 +193,7 @@ typedef struct _e_prefs { #endif gchar *capture_devices_snaplen; gchar *capture_devices_pmode; + gchar *capture_devices_filter; gboolean capture_prom_mode; gboolean capture_pcap_ng; gboolean capture_real_time; diff --git a/image/status.qrc b/image/status.qrc index 3b1a653fd2..5d9fb3db4e 100644 --- a/image/status.qrc +++ b/image/status.qrc @@ -5,5 +5,6 @@ expert_none.png expert_note.png expert_warn.png + expert_ok.png diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 8f3702f7cd..5b4e51e2bd 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -37,6 +37,7 @@ set(WIRESHARK_QT_HEADERS color_dialog.h color_utils.h column_preferences_frame.h + compiled_filter_output.h decode_as_dialog.h display_filter_combo.h display_filter_edit.h @@ -117,6 +118,7 @@ set(WIRESHARK_QT_SRC color_utils.cpp capture_preferences_frame.cpp column_preferences_frame.cpp + compiled_filter_output.cpp decode_as_dialog.cpp display_filter_combo.cpp display_filter_edit.cpp @@ -197,6 +199,7 @@ set(WIRESHARK_QT_UI capture_preferences_frame.ui capture_interfaces_dialog.ui column_preferences_frame.ui + compiled_filter_output.ui decode_as_dialog.ui export_object_dialog.ui export_pdu_dialog.ui diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index 71175e8b92..24d346ac55 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -133,6 +133,8 @@ capture_preferences_frame.cpp capture_preferences_frame.h: ui_capture_preference column_preferences_frame.cpp column_preferences_frame.h: ui_column_preferences_frame.h +compiled_filter_output.cpp compiled_filter_output.h: ui_compiled_filter_output.h + decode_as_dialog.cpp decode_as_dialog.h: ui_decode_as_dialog.h export_object_dialog.cpp export_object_dialog.h: ui_export_object_dialog.h diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index 7dac9f025d..bce1c96575 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -33,6 +33,7 @@ NODIST_GENERATED_HEADER_FILES = \ ui_capture_interfaces_dialog.h \ ui_capture_preferences_frame.h \ ui_column_preferences_frame.h \ + ui_compiled_filter_output.h \ ui_decode_as_dialog.h \ ui_export_object_dialog.h \ ui_export_pdu_dialog.h \ @@ -121,6 +122,7 @@ MOC_HDRS = \ color_utils.h \ capture_preferences_frame.h \ column_preferences_frame.h \ + compiled_filter_output.h \ decode_as_dialog.h \ display_filter_combo.h \ display_filter_edit.h \ @@ -189,6 +191,7 @@ UI_FILES = \ capture_interfaces_dialog.ui \ capture_preferences_frame.ui \ column_preferences_frame.ui \ + compiled_filter_output.ui \ decode_as_dialog.ui \ export_object_dialog.ui \ export_pdu_dialog.ui \ @@ -293,6 +296,7 @@ WIRESHARK_QT_SRC = \ color_utils.cpp \ capture_preferences_frame.cpp \ column_preferences_frame.cpp \ + compiled_filter_output.cpp \ decode_as_dialog.cpp \ display_filter_combo.cpp \ display_filter_edit.cpp \ diff --git a/ui/qt/QtShark.pro b/ui/qt/QtShark.pro index 5566eb9596..50d1da8a28 100644 --- a/ui/qt/QtShark.pro +++ b/ui/qt/QtShark.pro @@ -223,6 +223,7 @@ FORMS += \ capture_preferences_frame.ui \ capture_interfaces_dialog.ui \ column_preferences_frame.ui \ + compiled_filter_output.ui \ decode_as_dialog.ui \ export_object_dialog.ui \ export_pdu_dialog.ui \ @@ -268,6 +269,7 @@ HEADERS += $$HEADERS_WS_C \ capture_interfaces_dialog.h \ capture_preferences_frame.h \ column_preferences_frame.h \ + compiled_filter_output.h \ decode_as_dialog.h \ elided_label.h \ export_dissection_dialog.h \ @@ -582,6 +584,7 @@ SOURCES += \ color_dialog.cpp \ color_utils.cpp \ column_preferences_frame.cpp \ + compiled_filter_output.cpp \ decode_as_dialog.cpp \ display_filter_combo.cpp \ display_filter_edit.cpp \ diff --git a/ui/qt/capture_interfaces_dialog.cpp b/ui/qt/capture_interfaces_dialog.cpp index effdf1a311..173faf1269 100644 --- a/ui/qt/capture_interfaces_dialog.cpp +++ b/ui/qt/capture_interfaces_dialog.cpp @@ -24,13 +24,16 @@ #include #include "capture_interfaces_dialog.h" +#include "capture_filter_combo.h" #include "ui_capture_interfaces_dialog.h" +#include "compiled_filter_output.h" #include "wireshark_application.h" #ifdef HAVE_LIBPCAP #include +#include #include "capture_ui_utils.h" #include "ui/capture_globals.h" @@ -38,6 +41,7 @@ #include "ui/ui_util.h" #include "ui/utf8_entities.h" +#include "ui/preference_utils.h" #include #include @@ -59,14 +63,51 @@ CaptureInterfacesDialog::CaptureInterfacesDialog(QWidget *parent) : // XXX - Enable / disable as needed start_bt_ = ui->buttonBox->addButton(tr("Start"), QDialogButtonBox::YesRole); - connect(start_bt_, SIGNAL(clicked()), this, SLOT(on_bStart_clicked())); - stop_bt_ = ui->buttonBox->addButton(tr("Stop"), QDialogButtonBox::NoRole); - stop_bt_->setEnabled(false); - connect(stop_bt_, SIGNAL(clicked()), this, SLOT(on_bStop_clicked())); + start_bt_->setEnabled((global_capture_opts.num_selected > 0)? true: false); + connect(start_bt_, SIGNAL(clicked(bool)), this, SLOT(start_button_clicked())); - //connect(ui->tbInterfaces,SIGNAL(itemPressed(QTableWidgetItem *)),this,SLOT(tableItemPressed(QTableWidgetItem *))); connect(ui->tbInterfaces,SIGNAL(itemClicked(QTableWidgetItem *)),this,SLOT(tableItemClicked(QTableWidgetItem *))); + connect(ui->tbInterfaces, SIGNAL(itemSelectionChanged()), this, SLOT(tableSelected())); + connect(ui->allFilterComboBox, SIGNAL(captureFilterSyntaxChanged(bool)), this, SLOT(allFilterChanged())); + connect(this, SIGNAL(interfacesChanged()), ui->allFilterComboBox, SIGNAL(interfacesChanged())); +} + +void CaptureInterfacesDialog::allFilterChanged() +{ + QList selected = ui->tbInterfaces->selectedItems(); + for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) + { + QTableWidgetItem *it = ui->tbInterfaces->item(row, FILTER); + if (selected.contains(it)) { + QString str = ui->allFilterComboBox->currentText(); + it->setText(str); + } + } +} + +void CaptureInterfacesDialog::tableSelected() +{ + interface_t device; + + if (!ui->tbInterfaces->selectedItems().size()) { + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + device.selected = false; + device.locked = true; + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); + } + global_capture_opts.num_selected = 0; + start_bt_->setEnabled(false); + emit setSelectedInterfaces(); + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + device.locked = false; + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); + } + } } void CaptureInterfacesDialog::tableItemClicked(QTableWidgetItem * item) @@ -74,28 +115,39 @@ void CaptureInterfacesDialog::tableItemClicked(QTableWidgetItem * item) Q_UNUSED(item) interface_t device; + guint i; global_capture_opts.num_selected = 0; + QString filter = ui->allFilterComboBox->currentText(); + QList selected = ui->tbInterfaces->selectedItems(); for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) { - bool checked = (ui->tbInterfaces->item(row, 0)->checkState() == Qt::Checked) ? true : false; - QString interface_name = ui->tbInterfaces->item(row, 1)->text(); + QTableWidgetItem *it = ui->tbInterfaces->item(row, INTERFACE); + QString interface_name = it->text(); - device = g_array_index(global_capture_opts.all_ifaces, interface_t, row); - - if (checked == true) - { - device.selected = TRUE; + for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (interface_name.compare(device.display_name)) { + continue; + } else { + break; + } + } + if (selected.contains(it)) { + device.selected = true; global_capture_opts.num_selected++; - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, row); - g_array_insert_val(global_capture_opts.all_ifaces, row, device); + } else { + device.selected = false; } - else - { - device.selected = FALSE; - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, row); - g_array_insert_val(global_capture_opts.all_ifaces, row, device); + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); + + start_bt_->setEnabled((global_capture_opts.num_selected > 0)? true: false); + + if (filter.compare(QString(""))) { + emit interfacesChanged(); } + emit setSelectedInterfaces(); } } @@ -111,7 +163,17 @@ void CaptureInterfacesDialog::SetTab(int index) void CaptureInterfacesDialog::on_capturePromModeCheckBox_toggled(bool checked) { + interface_t device; prefs.capture_prom_mode = checked; + for (int row = 0; row < ui->tbInterfaces->rowCount(); row++){ + device = g_array_index(global_capture_opts.all_ifaces, interface_t, deviceMap[row]); + QString device_name = ui->tbInterfaces->item(row, INTERFACE)->text(); + device.pmode = checked; + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, deviceMap[row]); + g_array_insert_val(global_capture_opts.all_ifaces, deviceMap[row], device); + QTableWidgetItem *it = ui->tbInterfaces->item(row, PMODE); + it->setText(checked? tr("enabled"):tr("disabled")); + } } void CaptureInterfacesDialog::on_gbStopCaptureAuto_toggled(bool checked) @@ -155,25 +217,20 @@ void CaptureInterfacesDialog::on_cbResolveTransportNames_toggled(bool checked) gbl_resolv_flags.transport_name = checked; } -void CaptureInterfacesDialog::on_bStart_clicked() +void CaptureInterfacesDialog::start_button_clicked() { qDebug("Starting capture"); - emit startCapture(); + saveOptionsToPreferences(); + emit setFilterValid(true); accept(); } -void CaptureInterfacesDialog::on_bStop_clicked() -{ - qDebug("Stop capture"); - - emit stopCapture(); -} - // Not sure why we have to do this manually. void CaptureInterfacesDialog::on_buttonBox_rejected() { + saveOptionsToPreferences(); reject(); } @@ -205,27 +262,17 @@ void CaptureInterfacesDialog::UpdateInterfaces() ui->tbInterfaces->setRowCount(0); - GList *if_list; - int err; - gchar *err_str = NULL; GList *list; char *snaplen_string, *linkname; - //guint i; link_row *linkr = NULL; - //interface_t device; #if defined(_WIN32) || defined(HAVE_PCAP_CREATE) gint buffer; #endif gint snaplen; gboolean hassnap, pmode; - if_list = capture_interface_list(&err, &err_str,main_window_update); - if_list = g_list_sort(if_list, if_list_comparator_alph); - - // XXX Do we need to check for this? capture_interface_list returns an error if the length is 0. - if (g_list_length(if_list) > 0) { + if (global_capture_opts.all_ifaces->len > 0) { interface_t device; - //setDisabled(false); for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { QList *points; @@ -236,22 +283,20 @@ void CaptureInterfacesDialog::UpdateInterfaces() if (device.hidden) { continue; } - + deviceMap[ui->tbInterfaces->rowCount()] = i; QString output; ui->tbInterfaces->setRowCount(ui->tbInterfaces->rowCount() + 1); - QTableWidgetItem *cbSelected = new QTableWidgetItem(); - cbSelected->setCheckState(device.selected ? Qt::Checked : Qt::Unchecked); - ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, CAPTURE, cbSelected); - // traffic lines ui->tbInterfaces->setItemDelegateForColumn(TRAFFIC, new SparkLineDelegate()); points = new QList(); QTableWidgetItem *ti = new QTableWidgetItem(); + ti->setFlags(Qt::NoItemFlags); ti->setData(Qt::UserRole, qVariantFromValue(points)); ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, TRAFFIC, ti); + ui->tbInterfaces->setItemDelegateForColumn(INTERFACE, &combobox_item_delegate_); output = QString(device.display_name); ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, INTERFACE, new QTableWidgetItem(output)); @@ -300,38 +345,61 @@ void CaptureInterfacesDialog::UpdateInterfaces() } #endif + combobox_item_delegate_.setTable(ui->tbInterfaces); + ui->tbInterfaces->setColumnWidth(LINK, 100); + ui->tbInterfaces->setItemDelegateForColumn(LINK, &combobox_item_delegate_); output = QString(linkname); ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, LINK, new QTableWidgetItem(output)); - output = QString(device.pmode ? "true" : "false"); + ui->tbInterfaces->setItemDelegateForColumn(PMODE, &combobox_item_delegate_); + output = QString(device.pmode ? tr("enabled") : tr("disabled")); ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, PMODE, new QTableWidgetItem(output)); + ui->tbInterfaces->setItemDelegateForColumn(SNAPLEN, &combobox_item_delegate_); output = QString(snaplen_string); ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, SNAPLEN, new QTableWidgetItem(output)); - +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + ui->tbInterfaces->setItemDelegateForColumn(BUFFER, &combobox_item_delegate_); output = QString().sprintf("%d", device.buffer); ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, BUFFER, new QTableWidgetItem(output)); - -#if defined (HAVE_PCAP_CREATE) - output = QString(device.monitor_mode_enabled ? "true" : "false"); - ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, MONITOR, new QTableWidgetItem(output)); #else - ui->tbInterfaces->setColumnHidden(BUFFER+1, true); + ui->tbInterfaces->setColumnHidden(SNAPLEN+1, true); #endif +#if defined (HAVE_PCAP_CREATE) + ui->tbInterfaces->setItemDelegateForColumn(MONITOR, &combobox_item_delegate_); + output = QString(device.monitor_mode_supported? (device.monitor_mode_enabled ? tr("enabled") : tr("disabled")) : tr("n/a")); + ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, MONITOR, new QTableWidgetItem(output)); +#elif defined (_WIN32) + ui->tbInterfaces->setColumnHidden(BUFFER+1, true); +#else + ui->tbInterfaces->setColumnHidden(SNAPLEN+2, true); +#endif + ui->tbInterfaces->setItemDelegateForColumn(FILTER, &combobox_item_delegate_); + gchar* prefFilter = capture_dev_user_cfilter_find(device.name); + if (prefFilter) { + device.cfilter = g_strdup(prefFilter); + } + output = QString(device.cfilter); + ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, FILTER, new QTableWidgetItem(output)); if (strstr(prefs.capture_device, device.name) != NULL) { device.selected = TRUE; global_capture_opts.num_selected++; - global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); - g_array_insert_val(global_capture_opts.all_ifaces, i, device); } if (device.selected) { - ui->tbInterfaces->item(ui->tbInterfaces->rowCount()-1, 0)->setSelected(true); + for (int j = 0; j < NUM_COLUMNS; j++) { + if (ui->tbInterfaces->isColumnHidden(j)) + continue; + else + ui->tbInterfaces->item(ui->tbInterfaces->rowCount()-1, j)->setSelected(true); + } } + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); } } - free_interface_list(if_list); resizeEvent(NULL); + start_bt_->setEnabled((global_capture_opts.num_selected > 0)? true: false); if (!stat_timer_) { updateStatistics(); @@ -343,76 +411,419 @@ void CaptureInterfacesDialog::UpdateInterfaces() void CaptureInterfacesDialog::updateStatistics(void) { - //guint diff; QList *points = NULL; + interface_t device; + for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) { + points = new QList(); - if (!stat_cache_) { - // Start gathering statistics using dumpcap - // We crash (on OS X at least) if we try to do this from ::showEvent. - stat_cache_ = capture_stat_start(&global_capture_opts); + for (guint if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, if_idx); + QString device_name = ui->tbInterfaces->item(row, INTERFACE)->text(); + if (device_name.compare(device.display_name) || device.hidden || device.type == IF_PIPE) { + continue; + } + points = ui->tbInterfaces->item(row, TRAFFIC)->data(Qt::UserRole).value *>(); + points->append(device.packet_diff); + QTableWidgetItem *ti = new QTableWidgetItem(); + ti = ui->tbInterfaces->item(row, TRAFFIC); + ti->setData(Qt::UserRole, qVariantFromValue(points)); + ui->tbInterfaces->viewport()->update(); + } } - if (!stat_cache_) return; - +} +void CaptureInterfacesDialog::on_compileBPF_clicked() +{ + QString filter = ui->allFilterComboBox->currentText(); + if (!filter.compare(QString(""))) { + QMessageBox::warning(this, tr("Error"), + tr("Set a filter string to compile.")); + return; + } + QList selected = ui->tbInterfaces->selectedItems(); + if (selected.length() == 0) { + QMessageBox::warning(this, tr("Error"), + tr("No interfaces selected.")); + return; + } + QStringList *interfaces = new QStringList(); for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) { - //bool checked = (ui->tbInterfaces->item(row, 0)->checkState() == Qt::Checked) ? true : false; + QTableWidgetItem *it = ui->tbInterfaces->item(row, INTERFACE); + if (selected.contains(it)) { + QString str = it->text(); + interfaces->append(it->text()); + } + } - //points = new QList(); + CompiledFilterOutput *cfo = new CompiledFilterOutput(this, interfaces, filter); -// for (if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) { -// device = g_array_index(global_capture_opts.all_ifaces, interface_t, if_idx); -// QString device_name = ui->tbInterfaces->item(row, INTERFACE)->text(); -// if (device_name.compare(device.name) || device.hidden || device.type == IF_PIPE) -// continue; + cfo->show(); +} - //diff = 0; -// if (capture_stats(stat_cache_, device.name, &stats)) { -// if ((int)(stats.ps_recv - device.last_packets) >= 0) { -// diff = stats.ps_recv - device.last_packets; -// } -// device.last_packets = stats.ps_recv; -// } +void CaptureInterfacesDialog::saveOptionsToPreferences() +{ + interface_t device; + gchar *new_prefs, *tmp_prefs; - points = ui->tbInterfaces->item(row, TRAFFIC)->data(Qt::UserRole).value *>(); - emit getPoints(row, points); - //ui->tbInterfaces->item + for (int col = LINK; col <= FILTER; col++){ + if (ui->tbInterfaces->isColumnHidden(col)) { + continue; + } + /* All entries are separated by comma. There is also one before the first interface to be able to identify + word boundaries. As 'lo' is part of 'nflog' an exact match is necessary. */ + switch (col) { + case LINK: + new_prefs = (gchar *)g_malloc0(MAX_VAL_LEN); - //ui->tbInterfaces->setItemDelegateForColumn(TRAFFIC, new SparkLineDelegate()); - //points = new QList(); - //QTableWidgetItem *ti = new QTableWidgetItem(); - //ti->setData(Qt::UserRole, qVariantFromValue(points)); + for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, deviceMap[row]); + if (device.active_dlt == -1) { + continue; + } + g_strlcat(new_prefs, ",", MAX_VAL_LEN); + tmp_prefs = g_strdup_printf("%s(%d)", device.name, device.active_dlt); + g_strlcat(new_prefs, tmp_prefs, MAX_VAL_LEN); + g_free(tmp_prefs); + } + g_free(prefs.capture_devices_linktypes); + prefs.capture_devices_linktypes = new_prefs; + break; +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + case BUFFER: + new_prefs = (gchar *)g_malloc0(MAX_VAL_LEN); - QTableWidgetItem *ti = ui->tbInterfaces->item(ui->tbInterfaces->rowCount()-1, TRAFFIC); - ti->setData(Qt::UserRole, qVariantFromValue(points)); - //ui->tbInterfaces->setItem(ui->tbInterfaces->rowCount()-1, TRAFFIC, ti); + for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, deviceMap[row]); + if (device.buffer == -1) { + continue; + } + g_strlcat(new_prefs, ",", MAX_VAL_LEN); + tmp_prefs = g_strdup_printf("%s(%d)", device.name, device.buffer); + g_strlcat(new_prefs, tmp_prefs, MAX_VAL_LEN); + g_free(tmp_prefs); + } + g_free(prefs.capture_devices_buffersize); + prefs.capture_devices_buffersize = new_prefs; + break; +#endif + case SNAPLEN: + new_prefs = (gchar *)g_malloc0(MAX_VAL_LEN); - //points->append(diff); - ui->tbInterfaces->viewport()->update(); -// global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, if_idx); -// g_array_insert_val(global_capture_opts.all_ifaces, if_idx, device); + for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, deviceMap[row]); + g_strlcat(new_prefs, ",", MAX_VAL_LEN); + tmp_prefs = g_strdup_printf("%s:%d(%d)", device.name, device.has_snaplen, (device.has_snaplen?device.snaplen:WTAP_MAX_PACKET_SIZE)); + g_strlcat(new_prefs, tmp_prefs, MAX_VAL_LEN); + g_free(tmp_prefs); + } + g_free(prefs.capture_devices_snaplen); + prefs.capture_devices_snaplen = new_prefs; + break; + case PMODE: + new_prefs = (gchar *)g_malloc0(MAX_VAL_LEN); + for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, deviceMap[row]); + if (device.pmode == -1) { + continue; + } + g_strlcat(new_prefs, ",", MAX_VAL_LEN); + tmp_prefs = g_strdup_printf("%s(%d)", device.name, device.pmode); + g_strlcat(new_prefs, tmp_prefs, MAX_VAL_LEN); + g_free(tmp_prefs); + } + g_free(prefs.capture_devices_pmode); + prefs.capture_devices_pmode = new_prefs; + break; +#ifdef HAVE_PCAP_CREATE + case MONITOR: + new_prefs = (gchar *)g_malloc0(MAX_VAL_LEN); + + for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, deviceMap[row]); + if (!device.monitor_mode_supported || (device.monitor_mode_supported && !device.monitor_mode_enabled)) { + continue; + } + g_strlcat(new_prefs, ",", MAX_VAL_LEN); + tmp_prefs = g_strdup_printf("%s", device.name); + g_strlcat(new_prefs, tmp_prefs, MAX_VAL_LEN); + g_free(tmp_prefs); + } + g_free(prefs.capture_devices_monitor_mode); + prefs.capture_devices_monitor_mode = new_prefs; + break; +#endif + case FILTER: + new_prefs = (gchar *)g_malloc0(MAX_VAL_LEN); + + for (int row = 0; row < ui->tbInterfaces->rowCount(); row++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, deviceMap[row]); + if (!device.cfilter) { + continue; + } + g_strlcat(new_prefs, ",", MAX_VAL_LEN); + tmp_prefs = g_strdup_printf("%s(%s)", device.name, device.cfilter); + g_strlcat(new_prefs, tmp_prefs, MAX_VAL_LEN); + g_free(tmp_prefs); + } + g_free(prefs.capture_devices_filter); + prefs.capture_devices_filter = new_prefs; + break; + } + } + if (!prefs.gui_use_pref_save) { + prefs_main_write(); } } -/* -void CaptureInterfacesDialog::on_tbInterfaces_hideEvent(QHideEvent *evt) + +#include + +TbInterfacesDelegate::TbInterfacesDelegate(QObject *parent) + : QStyledItemDelegate(parent) { - Q_UNUSED(evt); - if (stat_timer_) stat_timer_->stop(); - if (stat_cache_) { - capture_stat_stop(stat_cache_); - stat_cache_ = NULL; - } } -void CaptureInterfacesDialog::on_tbInterfaces_showEvent(QShowEvent *evt) + +TbInterfacesDelegate::~TbInterfacesDelegate() { - Q_UNUSED(evt); - if (stat_timer_) stat_timer_->start(stat_update_interval_); } -*/ + + +QWidget* TbInterfacesDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const +{ + Q_UNUSED(option); + QWidget *w = NULL; +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + gint buffer = DEFAULT_CAPTURE_BUFFER_SIZE; +#endif + guint snap = WTAP_MAX_PACKET_SIZE; + + if (index.column() > 1) { + interface_t device; + QTableWidgetItem *it = table->item(index.row(), INTERFACE); + QString interface_name = it->text(); + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + buffer = device.buffer; +#endif + snap = device.snaplen; + if (interface_name.compare(device.display_name) || device.hidden || device.type == IF_PIPE) { + continue; + } else { + break; + } + } + switch (index.column()) { + case INTERFACE: + break; + case LINK: + { + GList *list; + link_row *temp; + QComboBox *cb = new QComboBox(parent); + for (list=device.links; list!=NULL; list=g_list_next(list)) { + temp = (link_row*)(list->data); + cb->addItem(QString("%1").arg(temp->name)); + } + connect(cb, SIGNAL(currentIndexChanged(QString)), this, SLOT(link_changed(QString))); + w = (QWidget*) cb; + break; + } + case PMODE: + { + // Create the combobox and populate it + QComboBox *cb = new QComboBox(parent); + cb->addItem(QString(tr("enabled"))); + cb->addItem(QString(tr("disabled"))); + connect(cb, SIGNAL(currentIndexChanged(QString)), this, SLOT(pmode_changed(QString))); + w = (QWidget*) cb; + break; + } +#if defined (HAVE_PCAP_CREATE) + case MONITOR: + { + if (index.data().toString().compare(QString("n/a"))) { + QComboBox *cb = new QComboBox(parent); + cb->addItem(QString(tr("enabled"))); + cb->addItem(QString(tr("disabled"))); + connect(cb, SIGNAL(currentIndexChanged(QString)), this, SLOT(monitor_changed(QString))); + w = (QWidget*) cb; + } + break; + } +#endif + case SNAPLEN: + { + QSpinBox *sb = new QSpinBox(parent); + sb->setRange(1, 65535); + sb->setValue(snap); + sb->setWrapping(true); + connect(sb, SIGNAL(valueChanged(int)), this, SLOT(snaplen_changed(int))); + w = (QWidget*) sb; + break; + } +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + case BUFFER: + { + QSpinBox *sb = new QSpinBox(parent); + sb->setRange(1, 65535); + sb->setValue(buffer); + sb->setWrapping(true); + connect(sb, SIGNAL(valueChanged(int)), this, SLOT(buffer_changed(int))); + w = (QWidget*) sb; + break; + } +#endif + case FILTER: + { + CaptureFilterCombo *cf = new CaptureFilterCombo(parent); + w = (QWidget*) cf; + } + } + } + return w; +} + +bool TbInterfacesDelegate::eventFilter(QObject *object, QEvent *event) +{ + QComboBox * comboBox = dynamic_cast(object); + if (comboBox) { + if (event->type() == QEvent::MouseButtonRelease) { + comboBox->showPopup(); + return true; + } + } else { + return QStyledItemDelegate::eventFilter( object, event ); + } + return false; +} + +void TbInterfacesDelegate::pmode_changed(QString index) +{ + interface_t device; + guint i; + QTableWidgetItem *it = table->item(table->currentRow(), INTERFACE); + QString interface_name = it->text(); + for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (interface_name.compare(device.display_name) || device.hidden || device.type == IF_PIPE) { + continue; + } else { + break; + } + } + if (!index.compare(QString(tr("enabled")))) { + device.pmode = true; + } else { + device.pmode = false; + } + + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); +} + +#if defined (HAVE_PCAP_CREATE) +void TbInterfacesDelegate::monitor_changed(QString index) +{ + interface_t device; + guint i; + QTableWidgetItem *it = table->item(table->currentRow(), INTERFACE); + QString interface_name = it->text(); + for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (interface_name.compare(device.display_name) || device.hidden || device.type == IF_PIPE) { + continue; + } else { + break; + } + } + if (!index.compare(QString(tr("enabled")))) { + device.monitor_mode_enabled = true; + } else { + device.monitor_mode_enabled = false; + } + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); +} +#endif + +void TbInterfacesDelegate::link_changed(QString index) +{ + GList *list; + link_row *temp; + interface_t device; + guint i; + + QTableWidgetItem *it = table->item(table->currentRow(), INTERFACE); + QString interface_name = it->text(); + for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (interface_name.compare(device.display_name) || device.hidden || device.type == IF_PIPE) { + continue; + } else { + break; + } + } + for (list = device.links; list != NULL; list = g_list_next(list)) { + temp = (link_row*) (list->data); + if (!index.compare(temp->name)) { + device.active_dlt = temp->dlt; + } + } + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); +} + +void TbInterfacesDelegate::snaplen_changed(int value) +{ + interface_t device; + guint i; + QTableWidgetItem *it = table->item(table->currentRow(), INTERFACE); + QString interface_name = it->text(); + for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (interface_name.compare(device.display_name) || device.hidden || device.type == IF_PIPE) { + continue; + } else { + break; + } + } + if (value != WTAP_MAX_PACKET_SIZE) { + device.has_snaplen = true; + device.snaplen = value; + } else { + device.has_snaplen = false; + device.snaplen = WTAP_MAX_PACKET_SIZE; + } + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); +} + +void TbInterfacesDelegate::buffer_changed(int value) +{ +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + interface_t device; + guint i; + QTableWidgetItem *it = table->item(table->currentRow(), INTERFACE); + QString interface_name = it->text(); + for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (interface_name.compare(device.display_name) || device.hidden || device.type == IF_PIPE) { + continue; + } else { + break; + } + } + device.buffer = value; + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); +#endif +} + #endif /* HAVE_LIBPCAP */ /* diff --git a/ui/qt/capture_interfaces_dialog.h b/ui/qt/capture_interfaces_dialog.h index 0adb046166..32f5b71604 100644 --- a/ui/qt/capture_interfaces_dialog.h +++ b/ui/qt/capture_interfaces_dialog.h @@ -41,18 +41,13 @@ typedef struct if_stat_cache_s if_stat_cache_t; */ enum { - CAPTURE = 0, - INTERFACE, + INTERFACE = 0, TRAFFIC, LINK, PMODE, SNAPLEN, -#if defined(HAVE_PCAP_CREATE) BUFFER, MONITOR, -#elif defined(_WIN32) && !defined(HAVE_PCAP_CREATE) - BUFFER, -#endif FILTER, NUM_COLUMNS }; @@ -62,6 +57,32 @@ namespace Ui { class CaptureInterfacesDialog; } +#include + +class TbInterfacesDelegate : public QStyledItemDelegate +{ + Q_OBJECT +private: + QTableWidget* table; + +public: + TbInterfacesDelegate(QObject *parent = 0); + ~TbInterfacesDelegate(); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; + void setTable(QTableWidget* tb) { table = tb; }; + bool eventFilter(QObject *object, QEvent *event); + +private slots: + void pmode_changed(QString index); +#if defined (HAVE_PCAP_CREATE) + void monitor_changed(QString index); +#endif + void link_changed(QString index); + void snaplen_changed(int value); + void buffer_changed(int value); +}; + class CaptureInterfacesDialog : public QDialog { Q_OBJECT @@ -72,7 +93,6 @@ public: void SetTab(int index); void UpdateInterfaces(); - //void updateStatistics(void); private slots: void on_capturePromModeCheckBox_toggled(bool checked); @@ -82,21 +102,24 @@ private slots: void on_gbNewFileAuto_toggled(bool checked); void on_cbExtraCaptureInfo_toggled(bool checked); void on_cbResolveMacAddresses_toggled(bool checked); + void on_compileBPF_clicked(); void on_cbResolveNetworkNames_toggled(bool checked); void on_cbResolveTransportNames_toggled(bool checked); - void on_bStart_clicked(); - void on_bStop_clicked(); + void start_button_clicked(); void on_buttonBox_rejected(); void on_buttonBox_helpRequested(); void tableItemClicked(QTableWidgetItem * item); + void tableSelected(); void updateStatistics(void); - //void on_tbInterfaces_hideEvent(QHideEvent *evt); - //void on_tbInterfaces_showEvent(QShowEvent *evt); + void allFilterChanged(); signals: void startCapture(); void stopCapture(); void getPoints(int row, PointList *pts); + void setSelectedInterfaces(); + void setFilterValid(bool valid); + void interfacesChanged(); private: Ui::CaptureInterfacesDialog *ui; @@ -106,6 +129,10 @@ private: QPushButton *stop_bt_; if_stat_cache_t *stat_cache_; QTimer *stat_timer_; + TbInterfacesDelegate combobox_item_delegate_; + QMap deviceMap; + + void saveOptionsToPreferences(); }; #endif /* HAVE_LIBPCAP */ diff --git a/ui/qt/capture_interfaces_dialog.ui b/ui/qt/capture_interfaces_dialog.ui index df3e77b8e9..96d48893a2 100644 --- a/ui/qt/capture_interfaces_dialog.ui +++ b/ui/qt/capture_interfaces_dialog.ui @@ -27,7 +27,7 @@ - QAbstractItemView::NoEditTriggers + QAbstractItemView::DoubleClicked true @@ -45,13 +45,8 @@ 0 - 9 + 8 - - - Capture - - Interface @@ -104,35 +99,46 @@ <html><head/><body><p>You probably want to enable this. Usually a network card will only capture the traffic sent to its own network address. If you want to capture all traffic that the network card can &quot;see&quot;, mark this option. See the FAQ for some more details of capturing packets from a switched network.</p></body></html> - Capture packets in promiscuous mode + Capture packets in promiscuous mode on all interfaces - - - <html><head/><body><p>Show the capture summary dialog while capturing.</p></body></html> + + + Qt::Horizontal - - Show the capture summary dialog while capturing + + + 13 + 3 + - + + + + + + + + Capture Filter for selected Interfaces: + + + + + + + + 0 + 0 + + + + + - - - - Qt::Horizontal - - - - 40 - 48 - - - - @@ -141,22 +147,16 @@ false - Add pipe... + Manage Interfaces... - - - Qt::Vertical + + + Compile BPFs - - - 20 - 18 - - - + @@ -629,6 +629,13 @@ + + + CaptureFilterCombo + QComboBox +
capture_filter_combo.h
+
+
diff --git a/ui/qt/compiled_filter_output.cpp b/ui/qt/compiled_filter_output.cpp new file mode 100644 index 0000000000..63265cd450 --- /dev/null +++ b/ui/qt/compiled_filter_output.cpp @@ -0,0 +1,115 @@ +/* compiled_filter_output.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include "ui_compiled_filter_output.h" +#include "compiled_filter_output.h" + +#include "capture_opts.h" +#include "wtap.h" +#include +#include "ui/capture_globals.h" + +CompiledFilterOutput::CompiledFilterOutput(QWidget *parent, QStringList *intList, QString &compile_filter) : + QDialog(parent), + intList_(intList), + compile_filter_(compile_filter), + ui(new Ui::CompiledFilterOutput) +{ + ui->setupUi(this); + + interface_list_ = ui->interfaceList; +#if GLIB_CHECK_VERSION(2,31,0) + pcap_compile_mtx = g_new(GMutex,1); + g_mutex_init(pcap_compile_mtx); +#else + pcap_compile_mtx = g_mutex_new(); +#endif + compileFilter(); + connect(interface_list_, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(compile_clicked(QListWidgetItem*, QListWidgetItem*))); +} + +CompiledFilterOutput::~CompiledFilterOutput() +{ + delete ui; +} + + +void CompiledFilterOutput::compileFilter() +{ + struct bpf_program fcode; + + foreach (QString interfaces, *intList_) { + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + + if (interfaces.compare(device.display_name)) { + continue; + } else { + pcap_t *pd = pcap_open_dead(device.active_dlt, WTAP_MAX_PACKET_SIZE); + g_mutex_lock(pcap_compile_mtx); + if (pcap_compile(pd, &fcode, compile_filter_.toUtf8().constData(), 1, 0) < 0) { + compile_results.insert(interfaces, QString("%1").arg(g_strdup(pcap_geterr(pd)))); + g_mutex_unlock(pcap_compile_mtx); + ui->interfaceList->addItem(new QListWidgetItem(QIcon(":expert/expert_error.png"),interfaces)); + } else { + GString *bpf_code_dump = g_string_new(""); + struct bpf_insn *insn = fcode.bf_insns; + int ii, n = fcode.bf_len; + gchar *bpf_code_str; + for (ii = 0; ii < n; ++insn, ++ii) { + g_string_append(bpf_code_dump, bpf_image(insn, ii)); + g_string_append(bpf_code_dump, "\n"); + } + bpf_code_str = g_string_free(bpf_code_dump, FALSE); + g_mutex_unlock(pcap_compile_mtx); + compile_results.insert(interfaces, QString("%1").arg(g_strdup(bpf_code_str))); + ui->interfaceList->addItem(new QListWidgetItem(QIcon(":expert/expert_ok.png"),interfaces)); + } + break; + } + } + } +} + + +void CompiledFilterOutput::compile_clicked(QListWidgetItem *current, QListWidgetItem *previous) +{ + Q_UNUSED(previous); + + QString interface = current->text(); + QHash::const_iterator iter = compile_results.find(interface); + ui->filterList->clear(); + ui->filterList->setText(iter.value()); +} + +// +// Editor modelines - http://www.wireshark.org/tools/modelines.html +// +// Local variables: +// c-basic-offset: 4 +// tab-width: 4 +// indent-tabs-mode: nil +// End: +// +// vi: set shiftwidth=4 tabstop=4 expandtab: +// :indentSize=4:tabSize=4:noTabs=true: +// diff --git a/ui/qt/compiled_filter_output.h b/ui/qt/compiled_filter_output.h new file mode 100644 index 0000000000..3da688d3f7 --- /dev/null +++ b/ui/qt/compiled_filter_output.h @@ -0,0 +1,72 @@ +/* compiled_filter_output.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef COMPILEDFILTEROUTPUT_H +#define COMPILEDFILTEROUTPUT_H + +#include "config.h" +#include +#include +#include +#include + +#include + +namespace Ui { +class CompiledFilterOutput; +} + +class CompiledFilterOutput : public QDialog +{ + Q_OBJECT + +private: + QStringList *intList_; + QString &compile_filter_; + Ui::CompiledFilterOutput *ui; + GMutex *pcap_compile_mtx; + QHash compile_results; + QListWidget *interface_list_; + void compileFilter(); + +public: + explicit CompiledFilterOutput(QWidget *parent = 0, QStringList *intList = new QStringList(), QString &filter = *new QString()); + + ~CompiledFilterOutput(); + +private slots: + void compile_clicked(QListWidgetItem* current, QListWidgetItem* previous); +}; + +#endif // COMPILEDFILTEROUTPUT_H + +// +// Editor modelines - http://www.wireshark.org/tools/modelines.html +// +// Local variables: +// c-basic-offset: 4 +// tab-width: 4 +// indent-tabs-mode: nil +// End: +// +// vi: set shiftwidth=4 tabstop=4 expandtab: +// :indentSize=4:tabSize=4:noTabs=true: +// diff --git a/ui/qt/compiled_filter_output.ui b/ui/qt/compiled_filter_output.ui new file mode 100644 index 0000000000..9a3b057f4a --- /dev/null +++ b/ui/qt/compiled_filter_output.ui @@ -0,0 +1,94 @@ + + + CompiledFilterOutput + + + + 0 + 0 + 654 + 380 + + + + Compiled Filter Output + + + + + 10 + 340 + 631 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + true + + + + + + 10 + 20 + 241 + 311 + + + + QAbstractItemView::NoEditTriggers + + + + + + 260 + 20 + 381 + 311 + + + + + + + + buttonBox + accepted() + CompiledFilterOutput + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CompiledFilterOutput + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/ui/qt/interface_tree.cpp b/ui/qt/interface_tree.cpp index ca0daae526..20fcd6c791 100644 --- a/ui/qt/interface_tree.cpp +++ b/ui/qt/interface_tree.cpp @@ -254,6 +254,7 @@ void InterfaceTree::updateStatistics(void) { if (capture_stats(stat_cache_, device.name, &stats)) { if ((int)(stats.ps_recv - device.last_packets) >= 0) { diff = stats.ps_recv - device.last_packets; + device.packet_diff = diff; } device.last_packets = stats.ps_recv; } @@ -306,6 +307,30 @@ void InterfaceTree::updateSelectedInterfaces() #endif // HAVE_LIBPCAP } +void InterfaceTree::setSelectedInterfaces() +{ +#ifdef HAVE_LIBPCAP + interface_t device; + QTreeWidgetItemIterator iter(this); + + while (*iter) { + QString device_name = (*iter)->data(0, Qt::UserRole).value(); + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (device_name.compare(QString().fromUtf8(device.name)) == 0) { + (*iter)->setSelected(device.selected); + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); + break; + } + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); + } + iter++; + } +#endif // HAVE_LIBPCAP +} + /* * Editor modelines * diff --git a/ui/qt/interface_tree.h b/ui/qt/interface_tree.h index a6c883d3b5..6a63590221 100644 --- a/ui/qt/interface_tree.h +++ b/ui/qt/interface_tree.h @@ -64,6 +64,7 @@ public slots: // change_interface_selection_for_all //void getPoints(int row, QList *pts); void getPoints(int row, PointList *pts); + void setSelectedInterfaces(); private slots: void getInterfaceList(); diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index e862f01d99..9a4adce43e 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -299,6 +299,8 @@ MainWindow::MainWindow(QWidget *parent) : connect(&capture_interfaces_dialog_, SIGNAL(getPoints(int,PointList*)), this->main_welcome_->getInterfaceTree(), SLOT(getPoints(int,PointList*))); + connect(&capture_interfaces_dialog_, SIGNAL(setSelectedInterfaces()), + this->main_welcome_->getInterfaceTree(), SLOT(setSelectedInterfaces())); #endif main_ui_->mainStack->setCurrentWidget(main_welcome_); @@ -1392,7 +1394,7 @@ void MainWindow::setMenusForFollowStream() main_ui_->actionAnalyzeFollowSSLStream->setEnabled(false); proto_get_frame_protocols(cap_file_->edt->pi.layers, NULL, &is_tcp, &is_udp, NULL, NULL); - + if (is_tcp) { main_ui_->actionAnalyzeFollowTCPStream->setEnabled(true); diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 87b3ac5a2d..9534d6b2f5 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -205,6 +205,8 @@ private slots: void redissectPackets(); void recreatePacketList(); + void startInterfaceCapture(bool valid); + void setFeaturesEnabled(bool enabled = true); void addDisplayFilterButton(QString df_text); diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index e9d8166743..69f5d61f1a 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -1101,6 +1101,12 @@ void MainWindow::captureFilterSyntaxChanged(bool valid) interfaceSelectionChanged(); } +void MainWindow::startInterfaceCapture(bool valid) +{ + capture_filter_valid_ = valid; + startCapture(); +} + void MainWindow::redissectPackets() { if (cap_file_) @@ -2320,6 +2326,7 @@ void MainWindow::on_actionSummary_triggered() #ifdef HAVE_LIBPCAP void MainWindow::on_actionCaptureInterfaces_triggered() { + connect(&capture_interfaces_dialog_, SIGNAL(setFilterValid(bool)), this, SLOT(startInterfaceCapture(bool))); capture_interfaces_dialog_.SetTab(0); capture_interfaces_dialog_.UpdateInterfaces();