aboutsummaryrefslogtreecommitdiffstats
path: root/capture.c
diff options
context:
space:
mode:
authorUlf Lamping <ulf.lamping@web.de>2005-02-06 21:20:35 +0000
committerUlf Lamping <ulf.lamping@web.de>2005-02-06 21:20:35 +0000
commit3a63719e389bd9fd1f27a1a467501c8d7fe3eb69 (patch)
tree0ed850112dc342fd11812f8dba14fa2cb1a08b33 /capture.c
parenta6694a746ff0ff2402e3989dfb3cf135122cf821 (diff)
another two steps towards privilege seperation:
move another two capture related fields (iface and cfilter) from cfile to capture_opts also move the handling of capture related command line options from main.c to capture.c, that way a future privilege seperated capture program can use the same code to parse it's command line than Ethereal. It might be even possible to share this parser code even with Tethereal, didn't took a closer look at this. svn path=/trunk/; revision=13320
Diffstat (limited to 'capture.c')
-rw-r--r--capture.c244
1 files changed, 238 insertions, 6 deletions
diff --git a/capture.c b/capture.c
index 229ddf84c0..38242fa2bb 100644
--- a/capture.c
+++ b/capture.c
@@ -83,6 +83,8 @@ void
capture_opts_init(capture_options *capture_opts, void *cfile)
{
capture_opts->cf = cfile;
+ capture_opts->cfilter = g_strdup("");
+ capture_opts->iface = NULL;
#ifdef _WIN32
capture_opts->buffer_size = 1; /* 1 MB */
#endif
@@ -111,23 +113,253 @@ capture_opts_init(capture_options *capture_opts, void *cfile)
capture_opts->autostop_filesize = 1024 * 1024; /* 1 MB */
capture_opts->has_autostop_duration = FALSE;
capture_opts->autostop_duration = 60; /* 1 min */
+
+}
+
+static int
+get_natural_int(const char *string, const char *name)
+{
+ long number;
+ char *p;
+
+ number = strtol(string, &p, 10);
+ if (p == string || *p != '\0') {
+ fprintf(stderr, "ethereal: The specified %s \"%s\" isn't a decimal number\n",
+ name, string);
+ exit(1);
+ }
+ if (number < 0) {
+ fprintf(stderr, "ethereal: The specified %s \"%s\" is a negative number\n",
+ name, string);
+ exit(1);
+ }
+ if (number > INT_MAX) {
+ fprintf(stderr, "ethereal: The specified %s \"%s\" is too large (greater than %d)\n",
+ name, string, INT_MAX);
+ exit(1);
+ }
+ return number;
+}
+
+
+static int
+get_positive_int(const char *string, const char *name)
+{
+ long number;
+
+ number = get_natural_int(string, name);
+
+ if (number == 0) {
+ fprintf(stderr, "ethereal: The specified %s is zero\n",
+ name);
+ exit(1);
+ }
+
+ return number;
}
+/*
+ * Given a string of the form "<autostop criterion>:<value>", as might appear
+ * as an argument to a "-a" option, parse it and set the criterion in
+ * question. Return an indication of whether it succeeded or failed
+ * in some fashion.
+ */
+static gboolean
+set_autostop_criterion(capture_options *capture_opts, const char *autostoparg)
+{
+ gchar *p, *colonp;
+
+ colonp = strchr(autostoparg, ':');
+ if (colonp == NULL)
+ return FALSE;
+
+ p = colonp;
+ *p++ = '\0';
+
+ /*
+ * Skip over any white space (there probably won't be any, but
+ * as we allow it in the preferences file, we might as well
+ * allow it here).
+ */
+ while (isspace((guchar)*p))
+ p++;
+ if (*p == '\0') {
+ /*
+ * Put the colon back, so if our caller uses, in an
+ * error message, the string they passed us, the message
+ * looks correct.
+ */
+ *colonp = ':';
+ return FALSE;
+ }
+ if (strcmp(autostoparg,"duration") == 0) {
+ capture_opts->has_autostop_duration = TRUE;
+ capture_opts->autostop_duration = get_positive_int(p,"autostop duration");
+ } else if (strcmp(autostoparg,"filesize") == 0) {
+ capture_opts->has_autostop_filesize = TRUE;
+ capture_opts->autostop_filesize = get_positive_int(p,"autostop filesize");
+ } else {
+ return FALSE;
+ }
+ *colonp = ':'; /* put the colon back */
+ return TRUE;
+}
+
+/*
+ * Given a string of the form "<ring buffer file>:<duration>", as might appear
+ * as an argument to a "-b" option, parse it and set the arguments in
+ * question. Return an indication of whether it succeeded or failed
+ * in some fashion.
+ */
+static gboolean
+get_ring_arguments(capture_options *capture_opts, const char *arg)
+{
+ gchar *p = NULL, *colonp;
+
+ colonp = strchr(arg, ':');
+
+ if (colonp != NULL) {
+ p = colonp;
+ *p++ = '\0';
+ }
+
+ capture_opts->ring_num_files =
+ get_natural_int(arg, "number of ring buffer files");
+
+ if (colonp == NULL)
+ return TRUE;
+
+ /*
+ * Skip over any white space (there probably won't be any, but
+ * as we allow it in the preferences file, we might as well
+ * allow it here).
+ */
+ while (isspace((guchar)*p))
+ p++;
+ if (*p == '\0') {
+ /*
+ * Put the colon back, so if our caller uses, in an
+ * error message, the string they passed us, the message
+ * looks correct.
+ */
+ *colonp = ':';
+ return FALSE;
+ }
+
+ capture_opts->has_file_duration = TRUE;
+ capture_opts->file_duration = get_positive_int(p,
+ "ring buffer duration");
+
+ *colonp = ':'; /* put the colon back */
+ return TRUE;
+}
+
+
+void
+capture_opt_add(capture_options *capture_opts, int opt, const char *optarg, gboolean *start_capture)
+{
+ int i;
+
+
+ switch(opt) {
+ case 'a': /* autostop criteria */
+ if (set_autostop_criterion(capture_opts, optarg) == FALSE) {
+ fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'b': /* Ringbuffer option */
+ capture_opts->multi_files_on = TRUE;
+ capture_opts->has_ring_num_files = TRUE;
+ if (get_ring_arguments(capture_opts, optarg) == FALSE) {
+ fprintf(stderr, "ethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'c': /* Capture xxx packets */
+ capture_opts->has_autostop_packets = TRUE;
+ capture_opts->autostop_packets = get_positive_int(optarg, "packet count");
+ break;
+ case 'f': /* capture filter */
+ if (capture_opts->cfilter)
+ g_free(capture_opts->cfilter);
+ capture_opts->cfilter = g_strdup(optarg);
+ break;
+ case 'H': /* Hide capture info dialog box */
+ capture_opts->show_info = FALSE;
+ break;
+ case 'i': /* Use interface xxx */
+ capture_opts->iface = g_strdup(optarg);
+ break;
+ case 'k': /* Start capture immediately */
+ *start_capture = TRUE;
+ break;
+ /*case 'l':*/ /* Automatic scrolling in live capture mode */
+ case 'p': /* Don't capture in promiscuous mode */
+ capture_opts->promisc_mode = FALSE;
+ break;
+ case 'Q': /* Quit after capture (just capture to file) */
+ capture_opts->quit_after_cap = TRUE;
+ *start_capture = TRUE; /*** -Q implies -k !! ***/
+ break;
+ case 's': /* Set the snapshot (capture) length */
+ capture_opts->has_snaplen = TRUE;
+ capture_opts->snaplen = get_positive_int(optarg, "snapshot length");
+ break;
+ case 'S': /* "Sync" mode: used for following file ala tail -f */
+ capture_opts->sync_mode = TRUE;
+ break;
+ case 'w': /* Write to capture file xxx */
+ capture_opts->save_file = g_strdup(optarg);
+ break;
+ case 'W': /* Write to capture file FD xxx */
+ capture_opts->save_file_fd = atoi(optarg);
+ break;
+ case 'y': /* Set the pcap data link type */
+#ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
+ capture_opts->linktype = pcap_datalink_name_to_val(optarg);
+ if (capture_opts->linktype == -1) {
+ fprintf(stderr, "ethereal: The specified data link type \"%s\" isn't valid\n",
+ optarg);
+ exit(1);
+ }
+#else /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
+ /* XXX - just treat it as a number */
+ capture_opts->linktype = get_natural_int(optarg, "data link type");
+#endif /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
+ break;
+#ifdef _WIN32
+ /* Hidden option supporting Sync mode */
+ case 'Z': /* Write to pipe FD XXX */
+ /* associate stdout with pipe */
+ i = atoi(optarg);
+ if (dup2(i, 1) < 0) {
+ fprintf(stderr, "Unable to dup pipe handle\n");
+ exit(1);
+ }
+ break;
+#endif /* _WIN32 */
+ default:
+ /* the caller is responsible to send us only the right opt's */
+ g_assert_not_reached();
+ }
+}
+
/* open the output file (temporary/specified name/ringbuffer) and close the old one */
/* Returns TRUE if the file opened successfully, FALSE otherwise. */
static gboolean
-capture_open_output(capture_options *capture_opts, const char *save_file, gboolean *is_tempfile) {
+capture_open_output(capture_options *capture_opts, gboolean *is_tempfile) {
char tmpname[128+1];
gchar *capfile_name;
- if (save_file != NULL) {
+ if (capture_opts->save_file != NULL) {
/* If the Sync option is set, we return to the caller while the capture
* is in progress. Therefore we need to take a copy of save_file in
* case the caller destroys it after we return.
*/
- capfile_name = g_strdup(save_file);
+ capfile_name = g_strdup(capture_opts->save_file);
if (capture_opts->multi_files_on) {
/* ringbuffer is enabled */
capture_opts->save_file_fd = ringbuf_init(capfile_name,
@@ -176,19 +408,19 @@ capture_open_output(capture_options *capture_opts, const char *save_file, gboole
to the file in question. */
/* Returns TRUE if the capture starts successfully, FALSE otherwise. */
gboolean
-do_capture(capture_options *capture_opts, const char *save_file)
+do_capture(capture_options *capture_opts)
{
gboolean is_tempfile;
gboolean ret;
gchar *title;
/* open the output file (temporary/specified name/ringbuffer) and close the old one */
- if(!capture_open_output(capture_opts, save_file, &is_tempfile)) {
+ if(!capture_open_output(capture_opts, &is_tempfile)) {
return FALSE;
}
title = g_strdup_printf("%s: Capturing - Ethereal",
- get_interface_descriptive_name(cf_get_iface(capture_opts->cf)));
+ get_interface_descriptive_name(capture_opts->iface));
if (capture_opts->sync_mode) {
/* sync mode: do the capture in a child process */
ret = sync_pipe_do_capture(capture_opts, is_tempfile);