dinfo->switch_level
[metze/wireshark/wip.git] / capture_opts.c
index 13eb70c3b3fb1f21b30d378c04f2b8584e51e7e8..40df74d7dc37e0ebbc6f870d8c6ec2bfc378f63e 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #ifdef HAVE_LIBPCAP
 
 #include <string.h>
@@ -29,6 +33,7 @@
 #include <ui/exit_codes.h>
 #include <wsutil/file_util.h>
 #include <wsutil/ws_pipe.h>
+#include <wsutil/ws_assert.h>
 
 #include "capture/capture_ifinfo.h"
 #include "capture/capture-pcap-util.h"
@@ -58,8 +63,11 @@ capture_opts_init(capture_options *capture_opts)
     capture_opts->default_options.extcap          = NULL;
     capture_opts->default_options.extcap_fifo     = NULL;
     capture_opts->default_options.extcap_args     = NULL;
-    capture_opts->default_options.extcap_pipedata = NULL;
     capture_opts->default_options.extcap_pid      = WS_INVALID_PID;
+    capture_opts->default_options.extcap_pipedata = NULL;
+    capture_opts->default_options.extcap_stderr   = NULL;
+    capture_opts->default_options.extcap_stdout_watch = 0;
+    capture_opts->default_options.extcap_stderr_watch = 0;
 #ifdef _WIN32
     capture_opts->default_options.extcap_pipe_h   = INVALID_HANDLE_VALUE;
     capture_opts->default_options.extcap_control_in_h  = INVALID_HANDLE_VALUE;
@@ -100,6 +108,7 @@ capture_opts_init(capture_options *capture_opts)
     capture_opts->has_file_duration               = FALSE;
     capture_opts->file_duration                   = 60.0;             /* 1 min */
     capture_opts->has_file_interval               = FALSE;
+    capture_opts->has_nametimenum                 = FALSE;
     capture_opts->file_interval                   = 60;               /* 1 min */
     capture_opts->has_file_packets                = FALSE;
     capture_opts->file_packets                    = 0;
@@ -110,17 +119,23 @@ capture_opts_init(capture_options *capture_opts)
     capture_opts->autostop_files                  = 1;
     capture_opts->has_autostop_packets            = FALSE;
     capture_opts->autostop_packets                = 0;
+    capture_opts->has_autostop_written_packets    = FALSE;
+    capture_opts->autostop_written_packets        = 0;
     capture_opts->has_autostop_filesize           = FALSE;
     capture_opts->autostop_filesize               = 1000;             /* 1 MB */
     capture_opts->has_autostop_duration           = FALSE;
     capture_opts->autostop_duration               = 60.0;             /* 1 min */
-    capture_opts->capture_comment                 = NULL;
 
     capture_opts->output_to_pipe                  = FALSE;
     capture_opts->capture_child                   = FALSE;
+    capture_opts->stop_after_extcaps              = FALSE;
+    capture_opts->wait_for_extcap_cbs             = FALSE;
     capture_opts->print_file_names                = FALSE;
     capture_opts->print_name_to                   = NULL;
+    capture_opts->temp_dir                        = NULL;
     capture_opts->compress_type                   = NULL;
+    capture_opts->closed_msg                      = NULL;
+    capture_opts->extcap_terminate_id             = 0;
 }
 
 void
@@ -146,6 +161,16 @@ capture_opts_cleanup(capture_options *capture_opts)
         capture_opts->all_ifaces = NULL;
     }
     g_free(capture_opts->save_file);
+    g_free(capture_opts->temp_dir);
+
+    if (capture_opts->closed_msg) {
+        g_free(capture_opts->closed_msg);
+        capture_opts->closed_msg = NULL;
+    }
+    if (capture_opts->extcap_terminate_id > 0) {
+        g_source_remove(capture_opts->extcap_terminate_id);
+        capture_opts->extcap_terminate_id = 0;
+    }
 }
 
 /* log content of capture_opts */
@@ -169,7 +194,7 @@ capture_opts_log(const char *log_domain, enum ws_log_level log_level, capture_op
         ws_log(log_domain, log_level, "Promiscuous Mode[%02d]: %s", i, interface_opts->promisc_mode?"TRUE":"FALSE");
         ws_log(log_domain, log_level, "Extcap[%02d]          : %s", i, interface_opts->extcap ? interface_opts->extcap : "(unspecified)");
         ws_log(log_domain, log_level, "Extcap FIFO[%02d]     : %s", i, interface_opts->extcap_fifo ? interface_opts->extcap_fifo : "(unspecified)");
-        ws_log(log_domain, log_level, "Extcap PID[%02d]      : %d", i, interface_opts->extcap_pid);
+        ws_log(log_domain, log_level, "Extcap PID[%02d]      : %"PRIdMAX, i, (intmax_t)interface_opts->extcap_pid);
 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
         ws_log(log_domain, log_level, "Buffer size[%02d]     : %d (MB)", i, interface_opts->buffer_size);
 #endif
@@ -252,13 +277,16 @@ capture_opts_log(const char *log_domain, enum ws_log_level log_level, capture_op
     ws_log(log_domain, log_level, "FileDuration    (%u) : %.3f", capture_opts->has_file_duration, capture_opts->file_duration);
     ws_log(log_domain, log_level, "FileInterval    (%u) : %u", capture_opts->has_file_interval, capture_opts->file_interval);
     ws_log(log_domain, log_level, "FilePackets     (%u) : %u", capture_opts->has_file_packets, capture_opts->file_packets);
+    ws_log(log_domain, log_level, "FileNameType        : %s", (capture_opts->has_nametimenum) ? "prefix_time_num.suffix"  : "prefix_num_time.suffix");
     ws_log(log_domain, log_level, "RingNumFiles    (%u) : %u", capture_opts->has_ring_num_files, capture_opts->ring_num_files);
     ws_log(log_domain, log_level, "RingPrintFiles  (%u) : %s", capture_opts->print_file_names, (capture_opts->print_file_names ? capture_opts->print_name_to : ""));
 
     ws_log(log_domain, log_level, "AutostopFiles   (%u) : %u", capture_opts->has_autostop_files, capture_opts->autostop_files);
     ws_log(log_domain, log_level, "AutostopPackets (%u) : %u", capture_opts->has_autostop_packets, capture_opts->autostop_packets);
+    ws_log(log_domain, log_level, "AutostopWrittenPackets (%u) : %u", capture_opts->has_autostop_written_packets, capture_opts->autostop_written_packets);
     ws_log(log_domain, log_level, "AutostopFilesize(%u) : %u (KB)", capture_opts->has_autostop_filesize, capture_opts->autostop_filesize);
     ws_log(log_domain, log_level, "AutostopDuration(%u) : %.3f", capture_opts->has_autostop_duration, capture_opts->autostop_duration);
+    ws_log(log_domain, log_level, "Temporary Directory  : %s", capture_opts->temp_dir && capture_opts->temp_dir[0] ? capture_opts->temp_dir : g_get_tmp_dir());
 }
 
 /*
@@ -306,8 +334,8 @@ set_autostop_criterion(capture_options *capture_opts, const char *autostoparg)
         capture_opts->has_autostop_files = TRUE;
         capture_opts->autostop_files = get_positive_int(p,"autostop files");
     } else if (strcmp(autostoparg,"packets") == 0) {
-        capture_opts->has_autostop_packets = TRUE;
-        capture_opts->autostop_packets = get_positive_int(p,"packet count");
+        capture_opts->has_autostop_written_packets = TRUE;
+        capture_opts->autostop_written_packets = get_positive_int(p,"packet write count");
     } else {
         return FALSE;
     }
@@ -414,6 +442,9 @@ get_ring_arguments(capture_options *capture_opts, const char *arg)
     } else if (strcmp(arg,"interval") == 0) {
         capture_opts->has_file_interval = TRUE;
         capture_opts->file_interval = get_positive_int(p, "ring buffer interval");
+    } else if (strcmp(arg,"nametimenum") == 0) {
+        int val = get_positive_int(p, "file name: time before num");
+        capture_opts->has_nametimenum = (val > 1);
     } else if (strcmp(arg,"packets") == 0) {
         capture_opts->has_file_packets = TRUE;
         capture_opts->file_packets = get_positive_int(p, "ring buffer packet count");
@@ -539,7 +570,7 @@ capture_opts_generate_display_name(const char *friendly_name,
      * On UN*X, however, users are more used to interface names,
      * and may find it helpful to see them.
      */
-    return g_strdup_printf("%s: %s", friendly_name, name);
+    return ws_strdup_printf("%s: %s", friendly_name, name);
 }
 #endif
 
@@ -758,6 +789,9 @@ capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg_str
     interface_opts.extcap_args = NULL;
     interface_opts.extcap_pid = WS_INVALID_PID;
     interface_opts.extcap_pipedata = NULL;
+    interface_opts.extcap_stderr = NULL;
+    interface_opts.extcap_stdout_watch = 0;
+    interface_opts.extcap_stderr_watch = 0;
 #ifdef _WIN32
     interface_opts.extcap_pipe_h = INVALID_HANDLE_VALUE;
     interface_opts.extcap_control_in_h = INVALID_HANDLE_VALUE;
@@ -796,15 +830,9 @@ int
 capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_str_p)
 {
     int status, snaplen;
+    ws_statb64 fstat;
 
     switch(opt) {
-    case LONGOPT_NUM_CAP_COMMENT:  /* capture comment */
-        if (capture_opts->capture_comment) {
-            cmdarg_err("--capture-comment can be set only once per file");
-            return 1;
-        }
-        capture_opts->capture_comment = g_strdup(optarg_str_p);
-        break;
     case 'a':        /* autostop criteria */
         if (set_autostop_criterion(capture_opts, optarg_str_p) == FALSE) {
             cmdarg_err("Invalid or unknown -a flag \"%s\"", optarg_str_p);
@@ -988,16 +1016,49 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_
         if (strcmp(optarg_str_p, "none") == 0) {
             ;
         } else if (strcmp(optarg_str_p, "gzip") == 0) {
+#ifdef HAVE_ZLIB
             ;
+#else
+            cmdarg_err("'gzip' compression is not supported");
+            return 1;
+#endif
         } else {
+#ifdef HAVE_ZLIB
             cmdarg_err("parameter of --compress-type can be 'none' or 'gzip'");
+#else
+            cmdarg_err("parameter of --compress-type can only be 'none'");
+#endif
             return 1;
         }
         capture_opts->compress_type = g_strdup(optarg_str_p);
         break;
+    case LONGOPT_CAPTURE_TMPDIR:  /* capture temporary directory */
+        if (capture_opts->temp_dir) {
+            cmdarg_err("--temp-dir can be set only once");
+            return 1;
+        }
+        if (ws_stat64(optarg_str_p, &fstat) < 0) {
+            cmdarg_err("Can't set temporary directory %s: %s",
+                    optarg_str_p, g_strerror(errno));
+            return 1;
+        }
+        if (!S_ISDIR(fstat.st_mode)) {
+            cmdarg_err("Can't set temporary directory %s: not a directory",
+                    optarg_str_p);
+            return 1;
+        }
+#ifdef S_IRWXU
+        if ((fstat.st_mode & S_IRWXU) != S_IRWXU) {
+            cmdarg_err("Can't set temporary directory %s: not a writable directory",
+                    optarg_str_p);
+            return 1;
+        }
+#endif /* S_IRWXU */
+        capture_opts->temp_dir = g_strdup(optarg_str_p);
+        break;
     default:
         /* the caller is responsible to send us only the right opt's */
-        g_assert_not_reached();
+        ws_assert_not_reached();
     }
 
     return 0;
@@ -1230,8 +1291,10 @@ capture_opts_del_iface(capture_options *capture_opts, guint if_index)
     if (interface_opts->extcap_args)
         g_hash_table_unref(interface_opts->extcap_args);
     if (interface_opts->extcap_pid != WS_INVALID_PID)
-        ws_pipe_close((ws_pipe_t *) interface_opts->extcap_pipedata);
+        ws_warning("Extcap still running during interface delete");
     g_free(interface_opts->extcap_pipedata);
+    if (interface_opts->extcap_stderr)
+        g_string_free(interface_opts->extcap_stderr, TRUE);
     g_free(interface_opts->extcap_control_in);
     g_free(interface_opts->extcap_control_out);
 #ifdef HAVE_PCAP_REMOTE
@@ -1265,7 +1328,7 @@ collect_ifaces(capture_options *capture_opts)
     /* Now fill the list up again. */
     for (i = 0; i < capture_opts->all_ifaces->len; i++) {
         device = &g_array_index(capture_opts->all_ifaces, interface_t, i);
-        if (!device->hidden && device->selected) {
+        if (device->selected) {
             interface_opts.name = g_strdup(device->name);
             interface_opts.descr = g_strdup(device->friendly_name);
             interface_opts.ifname = NULL;
@@ -1286,6 +1349,7 @@ collect_ifaces(capture_options *capture_opts)
             if (interface_opts.extcap_args)
                 g_hash_table_ref(interface_opts.extcap_args);
             interface_opts.extcap_pipedata = NULL;
+            interface_opts.extcap_stderr = NULL;
 #ifdef _WIN32
             interface_opts.extcap_pipe_h = INVALID_HANDLE_VALUE;
             interface_opts.extcap_control_in_h = INVALID_HANDLE_VALUE;