2014-09-09 20:42:58 +00:00
|
|
|
/* capture_file.cpp
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* 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 "capture_file.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @file Capture file class
|
|
|
|
*
|
|
|
|
* Wraps the capture_file struct, cfile global, and callbacks.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "globals.h"
|
|
|
|
capture_file cfile;
|
|
|
|
|
|
|
|
#include "file.h"
|
|
|
|
#include "log.h"
|
|
|
|
|
2016-03-18 17:34:41 +00:00
|
|
|
#include "epan/epan_dissect.h"
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
#include "ui/capture.h"
|
|
|
|
|
2014-12-21 21:23:02 +00:00
|
|
|
#include <QFileInfo>
|
2015-07-29 17:36:46 +00:00
|
|
|
#include <QTimer>
|
2014-12-21 21:23:02 +00:00
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
// To do:
|
|
|
|
// - Add getters and (if needed) setters:
|
|
|
|
// - Full filename
|
2015-02-20 14:30:23 +00:00
|
|
|
// - Capture state (stopped, prepared, running).
|
2015-05-15 20:36:04 +00:00
|
|
|
// - Call common_create_progress_dlg. This would let us manage the stop
|
|
|
|
// flag here as well as emit progress signals.
|
2014-09-09 20:42:58 +00:00
|
|
|
|
2014-12-21 21:23:02 +00:00
|
|
|
QString CaptureFile::no_capture_file_ = QObject::tr("[no capture file]");
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
CaptureFile::CaptureFile(QObject *parent, capture_file *cap_file) :
|
|
|
|
QObject(parent),
|
2014-12-21 21:23:02 +00:00
|
|
|
cap_file_(cap_file),
|
2015-05-22 21:01:31 +00:00
|
|
|
file_name_(no_capture_file_),
|
2014-12-22 23:51:36 +00:00
|
|
|
file_state_(QString())
|
2014-09-09 20:42:58 +00:00
|
|
|
{
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
capture_callback_add(captureCallback, (gpointer) this);
|
|
|
|
#endif
|
|
|
|
cf_callback_add(captureFileCallback, (gpointer) this);
|
|
|
|
}
|
|
|
|
|
|
|
|
CaptureFile::~CaptureFile()
|
|
|
|
{
|
|
|
|
cf_callback_remove(captureFileCallback, this);
|
|
|
|
}
|
|
|
|
|
2014-12-21 21:23:02 +00:00
|
|
|
bool CaptureFile::isValid() const
|
|
|
|
{
|
|
|
|
if (cap_file_ && cap_file_->state != FILE_CLOSED) { // XXX FILE_READ_IN_PROGRESS as well?
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-02-22 22:56:38 +00:00
|
|
|
int CaptureFile::currentRow()
|
|
|
|
{
|
|
|
|
if (isValid())
|
|
|
|
return cap_file_->current_row;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-05-22 22:33:38 +00:00
|
|
|
const QString CaptureFile::fileName()
|
|
|
|
{
|
|
|
|
if (isValid()) {
|
|
|
|
QFileInfo cfi(QString::fromUtf8(cap_file_->filename));
|
|
|
|
file_name_ = cfi.baseName();
|
|
|
|
}
|
2015-09-25 09:05:45 +00:00
|
|
|
|
2015-05-22 22:33:38 +00:00
|
|
|
return file_name_;
|
|
|
|
}
|
|
|
|
|
2016-03-18 17:34:41 +00:00
|
|
|
struct _packet_info *CaptureFile::packetInfo()
|
|
|
|
{
|
|
|
|
if (capFile() && capFile()->edt) {
|
|
|
|
return &(capFile()->edt->pi);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-09-01 20:51:13 +00:00
|
|
|
int CaptureFile::timestampPrecision()
|
|
|
|
{
|
2017-12-08 03:31:43 +00:00
|
|
|
if (capFile() && capFile()->provider.wth) {
|
|
|
|
return wtap_file_tsprec(capFile()->provider.wth);
|
2016-09-01 20:51:13 +00:00
|
|
|
}
|
|
|
|
return WTAP_TSPREC_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2014-12-21 21:23:02 +00:00
|
|
|
void CaptureFile::retapPackets()
|
|
|
|
{
|
|
|
|
if (cap_file_) {
|
|
|
|
cf_retap_packets(cap_file_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-29 17:36:46 +00:00
|
|
|
void CaptureFile::delayedRetapPackets()
|
|
|
|
{
|
|
|
|
QTimer::singleShot(0, this, SLOT(retapPackets()));
|
|
|
|
}
|
|
|
|
|
2015-07-03 20:52:49 +00:00
|
|
|
void CaptureFile::reload()
|
|
|
|
{
|
|
|
|
if (cap_file_ && cap_file_->state == FILE_READ_DONE) {
|
|
|
|
cf_reload(cap_file_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-19 23:56:44 +00:00
|
|
|
void CaptureFile::stopLoading()
|
2015-05-15 20:36:04 +00:00
|
|
|
{
|
2015-06-19 23:56:44 +00:00
|
|
|
setCaptureStopFlag(true);
|
2015-05-15 20:36:04 +00:00
|
|
|
}
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
capture_file *CaptureFile::globalCapFile()
|
|
|
|
{
|
|
|
|
return &cfile;
|
|
|
|
}
|
|
|
|
|
|
|
|
gpointer CaptureFile::window()
|
|
|
|
{
|
|
|
|
if (cap_file_) return cap_file_->window;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-06-19 23:56:44 +00:00
|
|
|
void CaptureFile::setCaptureStopFlag(bool stop_flag)
|
|
|
|
{
|
|
|
|
if (cap_file_) cap_file_->stop_flag = stop_flag;
|
|
|
|
}
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
void CaptureFile::captureFileCallback(gint event, gpointer data, gpointer user_data)
|
|
|
|
{
|
|
|
|
CaptureFile *capture_file = static_cast<CaptureFile *>(user_data);
|
|
|
|
if (!capture_file) return;
|
|
|
|
|
|
|
|
capture_file->captureFileEvent(event, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
void CaptureFile::captureCallback(gint event, capture_session *cap_session, gpointer user_data)
|
|
|
|
{
|
|
|
|
CaptureFile *capture_file = static_cast<CaptureFile *>(user_data);
|
|
|
|
if (!capture_file) return;
|
|
|
|
|
|
|
|
capture_file->captureEvent(event, cap_session);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void CaptureFile::captureFileEvent(int event, gpointer data)
|
|
|
|
{
|
|
|
|
switch(event) {
|
|
|
|
case(cf_cb_file_opened):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Opened");
|
|
|
|
cap_file_ = (capture_file *) data;
|
2015-05-22 22:33:38 +00:00
|
|
|
fileName();
|
2014-09-09 20:42:58 +00:00
|
|
|
emit captureFileOpened();
|
|
|
|
break;
|
|
|
|
case(cf_cb_file_closing):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
|
2014-12-22 23:51:36 +00:00
|
|
|
file_state_ = tr(" [closing]");
|
2014-09-09 20:42:58 +00:00
|
|
|
emit captureFileClosing();
|
|
|
|
break;
|
|
|
|
case(cf_cb_file_closed):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
|
2014-12-22 23:51:36 +00:00
|
|
|
file_state_ = tr(" [closed]");
|
2014-09-09 20:42:58 +00:00
|
|
|
emit captureFileClosed();
|
|
|
|
cap_file_ = NULL;
|
2015-05-22 21:01:31 +00:00
|
|
|
file_name_ = no_capture_file_;
|
2014-12-22 23:51:36 +00:00
|
|
|
file_state_ = QString();
|
2014-09-09 20:42:58 +00:00
|
|
|
break;
|
|
|
|
case(cf_cb_file_read_started):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
|
|
|
|
emit captureFileReadStarted();
|
|
|
|
break;
|
|
|
|
case(cf_cb_file_read_finished):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
|
|
|
|
emit captureFileReadFinished();
|
|
|
|
break;
|
|
|
|
case(cf_cb_file_reload_started):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload started");
|
2015-05-22 22:33:38 +00:00
|
|
|
emit captureFileReloadStarted();
|
2014-09-09 20:42:58 +00:00
|
|
|
break;
|
|
|
|
case(cf_cb_file_reload_finished):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
|
2015-05-22 22:33:38 +00:00
|
|
|
emit captureFileReloadFinished();
|
|
|
|
break;
|
|
|
|
case(cf_cb_file_rescan_started):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Rescan started");
|
|
|
|
emit captureFileRescanStarted();
|
|
|
|
break;
|
|
|
|
case(cf_cb_file_rescan_finished):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Rescan finished");
|
|
|
|
emit captureFileRescanFinished();
|
|
|
|
break;
|
2015-08-24 19:30:56 +00:00
|
|
|
case(cf_cb_file_retap_started):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Retap started");
|
|
|
|
emit captureFileRetapStarted();
|
|
|
|
break;
|
|
|
|
case(cf_cb_file_retap_finished):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Retap finished");
|
2015-12-06 21:29:53 +00:00
|
|
|
/* Flush any pending tapped packet before emitting captureFileRetapFinished() */
|
|
|
|
emit captureFileFlushTapsData();
|
2015-08-24 19:30:56 +00:00
|
|
|
emit captureFileRetapFinished();
|
|
|
|
break;
|
2017-01-21 00:05:56 +00:00
|
|
|
case(cf_cb_file_merge_started):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Merge started");
|
|
|
|
emit captureFileMergeStarted();
|
|
|
|
break;
|
|
|
|
case(cf_cb_file_merge_finished):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Merge finished");
|
|
|
|
emit captureFileMergeFinished();
|
|
|
|
break;
|
2015-05-22 22:33:38 +00:00
|
|
|
|
|
|
|
case(cf_cb_file_fast_save_finished):
|
2016-06-27 16:02:51 +00:00
|
|
|
// gtk/main.c calls main_cf_cb_file_rescan_finished. Should we do
|
|
|
|
// the equivalent?
|
2014-09-09 20:42:58 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case(cf_cb_packet_selected):
|
|
|
|
case(cf_cb_packet_unselected):
|
|
|
|
case(cf_cb_field_unselected):
|
2016-06-27 16:02:51 +00:00
|
|
|
// GTK+ only. Handled in Qt via signals and slots.
|
2014-09-09 20:42:58 +00:00
|
|
|
break;
|
|
|
|
|
2015-05-22 22:33:38 +00:00
|
|
|
case(cf_cb_file_save_started):
|
|
|
|
{
|
|
|
|
const QString file_path = (const char *) data;
|
|
|
|
captureFileSaveStarted(file_path);
|
|
|
|
break;
|
|
|
|
}
|
2015-02-21 01:03:48 +00:00
|
|
|
case(cf_cb_file_save_finished):
|
2015-05-22 22:33:38 +00:00
|
|
|
emit captureFileSaveFinished();
|
|
|
|
break;
|
2015-02-21 01:03:48 +00:00
|
|
|
case(cf_cb_file_save_failed):
|
2015-05-22 22:33:38 +00:00
|
|
|
emit captureFileSaveFailed();
|
|
|
|
break;
|
|
|
|
case(cf_cb_file_save_stopped):
|
|
|
|
emit captureFileSaveStopped();
|
2015-02-21 01:03:48 +00:00
|
|
|
break;
|
2015-05-22 22:33:38 +00:00
|
|
|
|
2015-09-11 00:31:19 +00:00
|
|
|
case cf_cb_file_export_specified_packets_started:
|
|
|
|
case cf_cb_file_export_specified_packets_finished:
|
|
|
|
case cf_cb_file_export_specified_packets_failed:
|
|
|
|
case cf_cb_file_export_specified_packets_stopped:
|
2016-06-27 16:02:51 +00:00
|
|
|
// GTK+ only.
|
2015-09-11 00:31:19 +00:00
|
|
|
break;
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
default:
|
|
|
|
g_warning("CaptureFile::captureFileCallback: event %u unknown", event);
|
2016-06-27 16:02:51 +00:00
|
|
|
g_assert_not_reached();
|
2014-09-09 20:42:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CaptureFile::captureEvent(int event, capture_session *cap_session)
|
|
|
|
{
|
|
|
|
#ifndef HAVE_LIBPCAP
|
|
|
|
Q_UNUSED(event)
|
|
|
|
Q_UNUSED(cap_session)
|
|
|
|
#else
|
|
|
|
switch(event) {
|
|
|
|
case(capture_cb_capture_prepared):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
|
|
|
|
emit captureCapturePrepared(cap_session);
|
|
|
|
cap_file_ = cap_session->cf;
|
|
|
|
break;
|
|
|
|
case(capture_cb_capture_update_started):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
|
|
|
|
emit captureCaptureUpdateStarted(cap_session);
|
|
|
|
break;
|
|
|
|
case(capture_cb_capture_update_continue):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");
|
|
|
|
emit captureCaptureUpdateContinue(cap_session);
|
|
|
|
break;
|
|
|
|
case(capture_cb_capture_update_finished):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
|
|
|
|
emit captureCaptureUpdateFinished(cap_session);
|
|
|
|
break;
|
|
|
|
case(capture_cb_capture_fixed_started):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
|
|
|
|
emit captureCaptureFixedStarted(cap_session);
|
|
|
|
break;
|
|
|
|
case(capture_cb_capture_fixed_continue):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
|
2015-04-06 21:56:17 +00:00
|
|
|
emit captureCaptureFixedContinue(cap_session);
|
2014-09-09 20:42:58 +00:00
|
|
|
break;
|
|
|
|
case(capture_cb_capture_fixed_finished):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
|
|
|
|
emit captureCaptureFixedFinished(cap_session);
|
|
|
|
break;
|
|
|
|
case(capture_cb_capture_stopping):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
|
|
|
|
/* Beware: this state won't be called, if the capture child
|
|
|
|
* closes the capturing on it's own! */
|
|
|
|
emit captureCaptureStopping(cap_session);
|
|
|
|
break;
|
|
|
|
case(capture_cb_capture_failed):
|
|
|
|
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture failed");
|
|
|
|
emit captureCaptureFailed(cap_session);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_warning("main_capture_callback: event %u unknown", event);
|
|
|
|
}
|
|
|
|
#endif // HAVE_LIBPCAP
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Editor modelines
|
|
|
|
*
|
|
|
|
* Local Variables:
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
|
|
*/
|