aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2014-09-29 16:27:11 -0700
committerGerald Combs <gerald@wireshark.org>2014-09-30 18:44:59 +0000
commitced39b6de863140eb0f793b04ca8a0c7c2a2c199 (patch)
tree6605d6a09b61c41a00ef2e1e59f56f5f4861ed97
parent5330875336fef3366b6b3c8f9696a289d39dbe29 (diff)
Qt: Start capture from the command line.
Fill in the capture-related mise en place so that -k and -i work. Get rid of global_capture_session in ui/qt and make it a member of MainWindow. Copy over privilege checking from GTK+. Move the global capture session struct to MainWindow. Change-Id: Iab5ec683860a40255a7e1d82e3872ced24fd55cb Reviewed-on: https://code.wireshark.org/review/4382 Reviewed-by: Gerald Combs <gerald@wireshark.org>
-rw-r--r--capchild/CMakeLists.txt1
-rw-r--r--ui/qt/main.cpp220
-rw-r--r--ui/qt/main_window.cpp1
-rw-r--r--ui/qt/main_window.h2
-rw-r--r--ui/qt/main_window_slots.cpp9
5 files changed, 205 insertions, 28 deletions
diff --git a/capchild/CMakeLists.txt b/capchild/CMakeLists.txt
index af4a1cbc58..8535144550 100644
--- a/capchild/CMakeLists.txt
+++ b/capchild/CMakeLists.txt
@@ -37,6 +37,7 @@ if (WERROR)
)
endif()
+file(GLOB CAPCHILD_HEADERS capture_session.h)
add_library(capchild STATIC
${CAPCHILD_SRC}
diff --git a/ui/qt/main.cpp b/ui/qt/main.cpp
index dce301c8f2..baf64bfa9f 100644
--- a/ui/qt/main.cpp
+++ b/ui/qt/main.cpp
@@ -113,13 +113,14 @@
#ifdef HAVE_LIBPCAP
# include "caputils/capture_ifinfo.h"
# include "ui/capture.h"
-# include <capchild/capture_sync.h>
+# include "capchild/capture_sync.h"
#endif
#ifdef _WIN32
# include "caputils/capture-wpcap.h"
# include "caputils/capture_wpcap_packet.h"
# include <tchar.h> /* Needed for Unicode */
+# include <wsutil/os_version_info.h>
# include <wsutil/unicode-utils.h>
# include <commctrl.h>
# include <shellapi.h>
@@ -132,22 +133,22 @@
//# include "airpcap_gui_utils.h"
#endif
-#include <epan/crypt/airpdcap_ws.h>
+#include "epan/crypt/airpdcap_ws.h"
-#include <QDebug>
#include <QDateTime>
+#include <QLibraryInfo>
+#include <QLocale>
+#include <QMessageBox>
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
#include <QTextCodec>
#endif
-#include <qtranslator.h>
-#include <qlocale.h>
-#include <qlibraryinfo.h>
+#include <QTranslator>
+
#include "conversation_dialog.h"
#include "endpoint_dialog.h"
#ifdef HAVE_LIBPCAP
capture_options global_capture_opts;
-capture_session global_capture_session;
#endif
capture_file cfile;
@@ -428,6 +429,44 @@ get_wireshark_runtime_info(GString *str)
}
}
+/* Check if there's something important to tell the user during startup.
+ * We want to do this *after* showing the main window so that any windows
+ * we pop up will be above the main window.
+ */
+static void
+check_and_warn_user_startup(const QString &cf_name)
+{
+#ifndef _WIN32
+ Q_UNUSED(cf_name)
+#endif
+ gchar *cur_user, *cur_group;
+
+ /* Tell the user not to run as root. */
+ if (running_with_special_privs() && recent.privs_warn_if_elevated) {
+ cur_user = get_cur_username();
+ cur_group = get_cur_groupname();
+ simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_elevated,
+ "Running as user \"%s\" and group \"%s\".\n"
+ "This could be dangerous.\n\n"
+ "If you're running Wireshark this way in order to perform live capture, "
+ "you may want to be aware that there is a better way documented at\n"
+ "http://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
+ g_free(cur_user);
+ g_free(cur_group);
+ }
+
+#ifdef _WIN32
+ /* Warn the user if npf.sys isn't loaded. */
+ if (!get_stdin_capture() && cf_name.isEmpty() && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_windows_major_version() >= 6) {
+ simple_message_box(ESD_TYPE_WARN, &recent.privs_warn_if_no_npf, "%s",
+ "The NPF driver isn't running. You may have trouble\n"
+ "capturing or listing interfaces.");
+ }
+#endif
+
+}
+
+
/* And now our feature presentation... [ fade to music ] */
int main(int argc, char *argv[])
{
@@ -447,7 +486,7 @@ int main(int argc, char *argv[])
#ifdef HAVE_LIBPCAP
int err;
gboolean start_capture = FALSE;
-// gboolean list_link_layer_types = FALSE;
+ gboolean list_link_layer_types = FALSE;
GList *if_list;
gchar *err_str;
int status;
@@ -461,6 +500,7 @@ int main(int argc, char *argv[])
#endif
e_prefs *prefs_p;
char badopt;
+ guint go_to_packet = 0;
cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
@@ -540,8 +580,8 @@ int main(int argc, char *argv[])
#endif /* _WIN32 */
QString locale;
- QString *cf_name = NULL;
- QString *display_filter = NULL;
+ QString cf_name;
+ QString display_filter;
int optind_initial;
unsigned int in_file_type = WTAP_TYPE_AUTO;
@@ -790,8 +830,6 @@ int main(int argc, char *argv[])
/* Set the initial values in the capture options. This might be overwritten
by preference settings and then again by the command line parameters. */
capture_opts_init(&global_capture_opts);
-
- capture_session_init(&global_capture_session, (void *)&cfile);
#endif
init_report_err(failure_alert_box, open_failure_alert_box,
@@ -931,7 +969,7 @@ int main(int argc, char *argv[])
/* Not supported yet */
break;
case 'g': /* Go to packet with the given packet number */
- /* Not supported yet */
+ go_to_packet = get_positive_int(optarg, "go to packet");
break;
case 'J': /* Jump to the first packet which matches the filter criteria */
/* Not supported yet */
@@ -940,7 +978,12 @@ int main(int argc, char *argv[])
/* Not supported yet */
break;
case 'L': /* Print list of link-layer types and exit */
- /* Not supported yet */
+#ifdef HAVE_LIBPCAP
+ list_link_layer_types = TRUE;
+#else
+ capture_option_specified = TRUE;
+ arg_error = TRUE;
+#endif
break;
case 'm': /* Fixed-width font for the display */
/* Not supported yet */
@@ -1000,7 +1043,7 @@ int main(int argc, char *argv[])
/* Path settings were already processed just ignore them this time*/
break;
case 'r':
- cf_name = new QString(optarg);
+ cf_name = optarg;
break;
case 'R': /* Read file filter */
/* Not supported yet */
@@ -1084,7 +1127,7 @@ int main(int argc, char *argv[])
argc -= optind;
argv += optind;
if (argc >= 1) {
- if (cf_name != NULL) {
+ if (!cf_name.isEmpty()) {
/*
* Input file name specified with "-r" *and* specified as a regular
* command-line argument.
@@ -1102,7 +1145,7 @@ int main(int argc, char *argv[])
* file - yes, you could have "-r" as the last part of the command,
* but that's a bit ugly.
*/
- cf_name = new QString(g_strdup(argv[0]));
+ cf_name = argv[0];
}
argc--;
@@ -1139,6 +1182,105 @@ int main(int argc, char *argv[])
#ifdef HAVE_LIBPCAP
fill_in_local_interfaces(main_window_update);
+ if (start_capture && list_link_layer_types) {
+ /* Specifying *both* is bogus. */
+ cmdarg_err("You can't specify both -L and a live capture.");
+ exit(1);
+ }
+
+ if (list_link_layer_types) {
+ /* We're supposed to list the link-layer types for an interface;
+ did the user also specify a capture file to be read? */
+ if (!cf_name.isEmpty()) {
+ /* Yes - that's bogus. */
+ cmdarg_err("You can't specify -L and a capture file to be read.");
+ exit(1);
+ }
+ /* No - did they specify a ring buffer option? */
+ if (global_capture_opts.multi_files_on) {
+ cmdarg_err("Ring buffer requested, but a capture isn't being done.");
+ exit(1);
+ }
+ } else {
+ /* We're supposed to do a live capture; did the user also specify
+ a capture file to be read? */
+ if (start_capture && !cf_name.isEmpty()) {
+ /* Yes - that's bogus. */
+ cmdarg_err("You can't specify both a live capture and a capture file to be read.");
+ exit(1);
+ }
+
+ /* No - was the ring buffer option specified and, if so, does it make
+ sense? */
+ if (global_capture_opts.multi_files_on) {
+ /* Ring buffer works only under certain conditions:
+ a) ring buffer does not work with temporary files;
+ b) real_time_mode and multi_files_on are mutually exclusive -
+ real_time_mode takes precedence;
+ c) it makes no sense to enable the ring buffer if the maximum
+ file size is set to "infinite". */
+ if (global_capture_opts.save_file == NULL) {
+ cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
+ global_capture_opts.multi_files_on = FALSE;
+ }
+ if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
+ cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
+ /* XXX - this must be redesigned as the conditions changed */
+ }
+ }
+ }
+
+ if (start_capture || list_link_layer_types) {
+ /* We're supposed to do a live capture or get a list of link-layer
+ types for a live capture device; if the user didn't specify an
+ interface to use, pick a default. */
+ status = capture_opts_default_iface_if_necessary(&global_capture_opts,
+ ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL);
+ if (status != 0) {
+ exit(status);
+ }
+ }
+
+ if (list_link_layer_types) {
+ /* Get the list of link-layer types for the capture devices. */
+ if_capabilities_t *caps;
+ guint i;
+ interface_t device;
+ for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
+
+ device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
+ if (device.selected) {
+#if defined(HAVE_PCAP_CREATE)
+ caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, &err_str, main_window_update);
+#else
+ caps = capture_get_if_capabilities(device.name, FALSE, &err_str,main_window_update);
+#endif
+ if (caps == NULL) {
+ cmdarg_err("%s", err_str);
+ g_free(err_str);
+ exit(2);
+ }
+ if (caps->data_link_types == NULL) {
+ cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
+ exit(2);
+ }
+#ifdef _WIN32
+ create_console();
+#endif /* _WIN32 */
+#if defined(HAVE_PCAP_CREATE)
+ capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
+#else
+ capture_opts_print_if_capabilities(caps, device.name, FALSE);
+#endif
+#ifdef _WIN32
+ destroy_console();
+#endif /* _WIN32 */
+ free_if_capabilities(caps);
+ }
+ }
+ exit(0);
+ }
+
capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
capture_opts_trim_ring_num_files(&global_capture_opts);
#endif /* HAVE_LIBPCAP */
@@ -1214,15 +1356,11 @@ int main(int argc, char *argv[])
g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
/* user could specify filename, or display filter, or both */
- if (cf_name != NULL || display_filter != NULL) {
- if (display_filter == NULL)
- display_filter = new QString();
- if (cf_name == NULL)
- cf_name = new QString();
+ if (!cf_name.isEmpty()) {
// XXX We need to call cf_open + start_requested_stats + cf_read
// similar to gtk/main.c:3110.
- main_w->openCaptureFile(*cf_name, *display_filter, in_file_type);
+ main_w->openCaptureFile(cf_name, display_filter, in_file_type);
/* Open stat windows; we do so after creating the main window,
to avoid Qt warnings, and after successfully opening the
@@ -1233,6 +1371,42 @@ int main(int argc, char *argv[])
filter. */
start_requested_stats();
}
+#ifdef HAVE_LIBPCAP
+ else {
+ if (start_capture) {
+ if (global_capture_opts.save_file != NULL) {
+ /* Save the directory name for future file dialogs. */
+ /* (get_dirname overwrites filename) */
+ gchar *s = get_dirname(g_strdup(global_capture_opts.save_file));
+ set_last_open_dir(s);
+ g_free(s);
+ }
+ /* "-k" was specified; start a capture. */
+// show_main_window(FALSE);
+ check_and_warn_user_startup(cf_name);
+
+ /* If no user interfaces were specified on the command line,
+ copy the list of selected interfaces to the set of interfaces
+ to use for this capture. */
+ if (global_capture_opts.ifaces->len == 0)
+ collect_ifaces(&global_capture_opts);
+ cfile.window = main_w;
+ if (capture_start(&global_capture_opts, main_w->captureSession(), main_window_update)) {
+ /* The capture started. Open stat windows; we do so after creating
+ the main window, to avoid GTK warnings, and after successfully
+ opening the capture file, so we know we have something to compute
+ stats on, and after registering all dissectors, so that MATE will
+ have registered its field array and we can have a tap filter with
+ one of MATE's late-registered fields as part of the filter. */
+ start_requested_stats();
+ }
+ }
+ /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
+ if (!start_capture && !global_capture_opts.default_options.cfilter) {
+ global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
+ }
+ }
+#endif /* HAVE_LIBPCAP */
g_main_loop_new(NULL, FALSE);
return wsApp->exec();
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 9ca45f6bf4..b8c6ceea2d 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -162,6 +162,7 @@ MainWindow::MainWindow(QWidget *parent) :
this, SLOT(openStatCommandDialog(QString,const char*,void*)));
}
gbl_cur_main_window_ = this;
+ capture_session_init(&cap_session_, (void *)&cfile);
main_ui_->setupUi(this);
setTitlebarForCaptureFile();
setMenusForCaptureFile();
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index b46ca24e43..68c206e646 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -76,6 +76,7 @@ public:
void setPipeInputHandler(gint source, gpointer user_data, int *child_process, pipe_input_cb_t input_cb);
QString getFilter();
+ capture_session *captureSession() { return &cap_session_; }
protected:
bool eventFilter(QObject *obj, QEvent *event);
@@ -106,6 +107,7 @@ private:
MainWelcome *main_welcome_;
DisplayFilterCombo *df_combo_box_;
capture_file *cap_file_;
+ capture_session cap_session_;
QFont mono_font_;
// XXX - packet_list_, proto_tree_, and byte_view_tab_ should
// probably be full-on values instead of pointers.
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index e0657e26f2..e1b47791f9 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -373,7 +373,6 @@ void MainWindow::filterAction(QString &action_filter, FilterAction::Action actio
void MainWindow::captureCapturePrepared(capture_session *cap_session) {
#ifdef HAVE_LIBPCAP
- qDebug() << "FIX captureCapturePrepared";
setTitlebarForCaptureInProgress();
setWindowIcon(wsApp->captureIcon());
@@ -625,18 +624,18 @@ void MainWindow::startCapture() {
// main_auto_scroll_live_changed(auto_scroll_live);
/* XXX - can this ever happen? */
- if (global_capture_session.state != CAPTURE_STOPPED)
+ if (cap_session_.state != CAPTURE_STOPPED)
return;
/* close the currently loaded capture file */
- cf_close((capture_file *) global_capture_session.cf);
+ cf_close((capture_file *) cap_session_.cf);
/* Copy the selected interfaces to the set of interfaces to use for
this capture. */
collect_ifaces(&global_capture_opts);
cfile.window = this;
- if (capture_start(&global_capture_opts, &global_capture_session, main_window_update)) {
+ if (capture_start(&global_capture_opts, &cap_session_, main_window_update)) {
/* The capture succeeded, which means the capture filter syntax is
valid; add this capture filter to the recent capture filter list. */
for (i = 0; i < global_capture_opts.ifaces->len; i++) {
@@ -730,7 +729,7 @@ void MainWindow::stopCapture() {
//#endif
#ifdef HAVE_LIBPCAP
- capture_stop(&global_capture_session);
+ capture_stop(&cap_session_);
#endif // HAVE_LIBPCAP
}