forked from osmocom/wireshark
move capture_opts related things (init, command line, ...) from capture.c to a new file capture_opts.c and let both ethereal and tethereal use it.
svn path=/trunk/; revision=13474
This commit is contained in:
parent
a25fd8d7ca
commit
d643a55488
|
@ -152,6 +152,7 @@ ethereal_SOURCES = \
|
|||
$(ETHEREAL_COMMON_SRC) \
|
||||
alert_box.c \
|
||||
capture.c \
|
||||
capture_opts.c \
|
||||
capture_sync.c \
|
||||
capture_loop.c \
|
||||
color_filters.c \
|
||||
|
@ -186,6 +187,7 @@ ethereal_INCLUDES = \
|
|||
tethereal_SOURCES = \
|
||||
$(ETHEREAL_COMMON_SRC) \
|
||||
$(TETHEREAL_TAP_SRC) \
|
||||
capture_opts.c \
|
||||
tethereal-tap-register.c \
|
||||
tethereal.c
|
||||
|
||||
|
|
272
capture.c
272
capture.c
|
@ -76,278 +76,6 @@ static gboolean normal_do_capture(capture_options *capture_opts, gboolean is_tem
|
|||
static void stop_capture_signal_handler(int signo);
|
||||
|
||||
|
||||
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
|
||||
capture_opts->has_snaplen = FALSE;
|
||||
capture_opts->snaplen = MIN_PACKET_SIZE;
|
||||
capture_opts->promisc_mode = TRUE;
|
||||
capture_opts->linktype = -1; /* the default linktype */
|
||||
capture_opts->capture_child = FALSE;
|
||||
capture_opts->save_file = NULL;
|
||||
capture_opts->save_file_fd = -1;
|
||||
capture_opts->sync_mode = TRUE;
|
||||
capture_opts->show_info = TRUE;
|
||||
capture_opts->quit_after_cap = FALSE;
|
||||
|
||||
capture_opts->multi_files_on = FALSE;
|
||||
capture_opts->has_file_duration = FALSE;
|
||||
capture_opts->file_duration = 60; /* 1 min */
|
||||
capture_opts->has_ring_num_files = TRUE;
|
||||
capture_opts->ring_num_files = 2;
|
||||
|
||||
capture_opts->has_autostop_files = FALSE;
|
||||
capture_opts->autostop_files = 1;
|
||||
capture_opts->has_autostop_packets = FALSE;
|
||||
capture_opts->autostop_packets = 1;
|
||||
capture_opts->has_autostop_filesize = FALSE;
|
||||
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 if (strcmp(autostoparg,"files") == 0) {
|
||||
capture_opts->multi_files_on = TRUE;
|
||||
capture_opts->has_autostop_files = TRUE;
|
||||
capture_opts->autostop_files = get_positive_int(p,"autostop files");
|
||||
} 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)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int i;
|
||||
#endif
|
||||
|
||||
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
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
/* capture_opts.c
|
||||
* Routines for capture options setting
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@ethereal.com>
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
|
||||
#ifdef HAVE_IO_H
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include <pcap.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <epan/packet.h>
|
||||
|
||||
#include "capture.h"
|
||||
#include "ringbuffer.h"
|
||||
|
||||
|
||||
void
|
||||
capture_opts_init(capture_options *capture_opts, void *cfile)
|
||||
{
|
||||
capture_opts->cf = cfile;
|
||||
capture_opts->cfilter = g_strdup(""); /* No capture filter string specified */
|
||||
capture_opts->iface = NULL; /* Default is "pick the first interface" */
|
||||
#ifdef _WIN32
|
||||
capture_opts->buffer_size = 1; /* 1 MB */
|
||||
#endif
|
||||
capture_opts->has_snaplen = FALSE;
|
||||
capture_opts->snaplen = WTAP_MAX_PACKET_SIZE; /* snapshot length - default is
|
||||
infinite, in effect */
|
||||
capture_opts->promisc_mode = TRUE; /* promiscuous mode is the default */
|
||||
capture_opts->linktype = -1; /* the default linktype */
|
||||
capture_opts->capture_child = FALSE;
|
||||
capture_opts->save_file = NULL;
|
||||
capture_opts->save_file_fd = -1;
|
||||
capture_opts->sync_mode = TRUE;
|
||||
capture_opts->show_info = TRUE;
|
||||
capture_opts->quit_after_cap = FALSE;
|
||||
|
||||
capture_opts->multi_files_on = FALSE;
|
||||
capture_opts->has_file_duration = FALSE;
|
||||
capture_opts->file_duration = 60; /* 1 min */
|
||||
capture_opts->has_ring_num_files = FALSE;
|
||||
capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES;
|
||||
|
||||
capture_opts->has_autostop_files = FALSE;
|
||||
capture_opts->autostop_files = 1;
|
||||
capture_opts->has_autostop_packets = FALSE;
|
||||
capture_opts->autostop_packets = 1;
|
||||
capture_opts->has_autostop_filesize = FALSE;
|
||||
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 if (strcmp(autostoparg,"files") == 0) {
|
||||
capture_opts->multi_files_on = TRUE;
|
||||
capture_opts->has_autostop_files = TRUE;
|
||||
capture_opts->autostop_files = get_positive_int(p,"autostop files");
|
||||
} 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)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int i;
|
||||
#endif
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBPCAP */
|
|
@ -1620,6 +1620,9 @@ main(int argc, char *argv[])
|
|||
by preference settings and then again by the command line parameters. */
|
||||
capture_opts_init(capture_opts, &cfile);
|
||||
|
||||
capture_opts->snaplen = MIN_PACKET_SIZE;
|
||||
capture_opts->has_ring_num_files = TRUE;
|
||||
|
||||
command_name = get_basename(ethereal_path);
|
||||
/* Set "capture_child" to indicate whether this is going to be a child
|
||||
process for a "-S" capture. */
|
||||
|
|
274
tethereal.c
274
tethereal.c
|
@ -103,11 +103,12 @@
|
|||
#ifdef HAVE_LIBPCAP
|
||||
#include <wiretap/wtap-capture.h>
|
||||
#include <wiretap/libpcap.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "capture-wpcap.h"
|
||||
#endif
|
||||
#include "capture.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This is the template for the decode as option; it is shared between the
|
||||
|
@ -168,22 +169,23 @@ typedef struct _loop_data {
|
|||
static loop_data ld;
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
#if 0
|
||||
typedef struct {
|
||||
gchar *cfilter; /* Capture filter string */
|
||||
gchar *iface; /* the network interface to capture from */
|
||||
int snaplen; /* Maximum captured packet length */
|
||||
int promisc_mode; /* Capture in promiscuous mode */
|
||||
int autostop_count; /* Maximum packet count */
|
||||
int autostop_packets; /* Maximum packet count */
|
||||
gboolean has_autostop_duration; /* TRUE if maximum capture duration
|
||||
is specified */
|
||||
gint32 autostop_duration; /* Maximum capture duration */
|
||||
gboolean has_autostop_filesize; /* TRUE if maximum capture file size
|
||||
is specified */
|
||||
gint32 autostop_filesize; /* Maximum capture file size */
|
||||
gboolean ringbuffer_on; /* TRUE if ring buffer in use */
|
||||
guint32 ringbuffer_num_files; /* Number of ring buffer files */
|
||||
gboolean has_ring_duration; /* TRUE if ring duration specified */
|
||||
gint32 ringbuffer_duration; /* Switch file after n seconds */
|
||||
gboolean multi_files_on; /* TRUE if ring buffer in use */
|
||||
guint32 ring_num_files; /* Number of ring buffer files */
|
||||
gboolean has_file_duration; /* TRUE if ring duration specified */
|
||||
gint32 file_duration; /* Switch file after n seconds */
|
||||
int linktype; /* Data link type to use, or -1 for
|
||||
"use default" */
|
||||
} capture_options;
|
||||
|
@ -208,6 +210,8 @@ static capture_options capture_opts = {
|
|||
0, /* specified time is off by default */
|
||||
-1 /* Default to not change link type */
|
||||
};
|
||||
#endif /* 0 */
|
||||
static capture_options capture_opts;
|
||||
|
||||
static gboolean list_link_layer_types;
|
||||
|
||||
|
@ -306,145 +310,6 @@ print_usage(gboolean print_ver)
|
|||
fprintf(output, "\tdefault is libpcap\n");
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
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, "tethereal: The specified %s \"%s\" isn't a decimal number\n",
|
||||
name, string);
|
||||
exit(1);
|
||||
}
|
||||
if (number < 0) {
|
||||
fprintf(stderr, "tethereal: The specified %s is a negative number\n",
|
||||
name);
|
||||
exit(1);
|
||||
}
|
||||
if (number > INT_MAX) {
|
||||
fprintf(stderr, "tethereal: The specified %s is too large (greater than %d)\n",
|
||||
name, 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, "tethereal: 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(const char *autostoparg)
|
||||
{
|
||||
guchar *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(*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(const char *arg)
|
||||
{
|
||||
guchar *p = NULL, *colonp;
|
||||
|
||||
colonp = strchr(arg, ':');
|
||||
|
||||
if (colonp != NULL) {
|
||||
p = colonp;
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
capture_opts.ringbuffer_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(*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_ring_duration = TRUE;
|
||||
capture_opts.ringbuffer_duration = get_positive_int(p,
|
||||
"ring buffer duration");
|
||||
|
||||
*colonp = ':'; /* put the colon back */
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* structure to keep track of what tap listeners have been registered.
|
||||
*/
|
||||
typedef struct _ethereal_tap_list {
|
||||
|
@ -847,6 +712,7 @@ main(int argc, char *argv[])
|
|||
int out_file_type = WTAP_FILE_PCAP;
|
||||
gchar *cf_name = NULL, *rfilter = NULL;
|
||||
#ifdef HAVE_LIBPCAP
|
||||
gboolean start_capture = FALSE;
|
||||
gchar *if_text;
|
||||
GList *lt_list, *lt_entry;
|
||||
data_link_info_t *data_link_info;
|
||||
|
@ -861,8 +727,7 @@ main(int argc, char *argv[])
|
|||
gboolean got_tap = FALSE;
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
/* XXX - better use capture_opts_init instead */
|
||||
capture_opts.cfilter = g_strdup("");
|
||||
capture_opts_init(&capture_opts, NULL /* cfile */);
|
||||
#endif
|
||||
|
||||
set_timestamp_setting(TS_RELATIVE);
|
||||
|
@ -974,32 +839,14 @@ main(int argc, char *argv[])
|
|||
while ((opt = getopt(argc, argv, "a:b:c:d:Df:F:hi:lLnN:o:pqr:R:s:St:T:vw:Vxy:z:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'a': /* autostop criteria */
|
||||
#ifdef HAVE_LIBPCAP
|
||||
if (set_autostop_criterion(optarg) == FALSE) {
|
||||
fprintf(stderr, "tethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
capture_option_specified = TRUE;
|
||||
arg_error = TRUE;
|
||||
#endif
|
||||
break;
|
||||
case 'b': /* Ringbuffer option */
|
||||
#ifdef HAVE_LIBPCAP
|
||||
capture_opts.ringbuffer_on = TRUE;
|
||||
if (get_ring_arguments(optarg) == FALSE) {
|
||||
fprintf(stderr, "tethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
capture_option_specified = TRUE;
|
||||
arg_error = TRUE;
|
||||
#endif
|
||||
break;
|
||||
case 'c': /* Capture xxx packets */
|
||||
case 'f': /* capture filter */
|
||||
case 'p': /* Don't capture in promiscuous mode */
|
||||
case 's': /* Set the snapshot (capture) length */
|
||||
case 'y': /* Set the pcap data link type */
|
||||
#ifdef HAVE_LIBPCAP
|
||||
capture_opts.autostop_count =
|
||||
get_positive_int(optarg, "packet count");
|
||||
capture_opt_add(&capture_opts, opt, optarg, &start_capture);
|
||||
#else
|
||||
capture_option_specified = TRUE;
|
||||
arg_error = TRUE;
|
||||
|
@ -1042,17 +889,6 @@ main(int argc, char *argv[])
|
|||
#else
|
||||
capture_option_specified = TRUE;
|
||||
arg_error = TRUE;
|
||||
#endif
|
||||
break;
|
||||
case 'f':
|
||||
#ifdef HAVE_LIBPCAP
|
||||
capture_filter_specified = TRUE;
|
||||
if (capture_opts.cfilter)
|
||||
g_free(capture_opts.cfilter);
|
||||
capture_opts.cfilter = g_strdup(optarg);
|
||||
#else
|
||||
capture_option_specified = TRUE;
|
||||
arg_error = TRUE;
|
||||
#endif
|
||||
break;
|
||||
case 'F':
|
||||
|
@ -1178,14 +1014,6 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case 'p': /* Don't capture in promiscuous mode */
|
||||
#ifdef HAVE_LIBPCAP
|
||||
capture_opts.promisc_mode = FALSE;
|
||||
#else
|
||||
capture_option_specified = TRUE;
|
||||
arg_error = TRUE;
|
||||
#endif
|
||||
break;
|
||||
case 'q': /* Quiet */
|
||||
quiet = TRUE;
|
||||
break;
|
||||
|
@ -1195,14 +1023,6 @@ main(int argc, char *argv[])
|
|||
case 'R': /* Read file filter */
|
||||
rfilter = optarg;
|
||||
break;
|
||||
case 's': /* Set the snapshot (capture) length */
|
||||
#ifdef HAVE_LIBPCAP
|
||||
capture_opts.snaplen = get_positive_int(optarg, "snapshot length");
|
||||
#else
|
||||
capture_option_specified = TRUE;
|
||||
arg_error = TRUE;
|
||||
#endif
|
||||
break;
|
||||
case 'S': /* show packets in real time */
|
||||
print_packet_info = TRUE;
|
||||
break;
|
||||
|
@ -1260,24 +1080,6 @@ main(int argc, char *argv[])
|
|||
case 'x': /* Print packet data in hex (and ASCII) */
|
||||
print_hex = TRUE;
|
||||
break;
|
||||
case 'y': /* Set the pcap data link type */
|
||||
#ifdef HAVE_LIBPCAP
|
||||
#ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
|
||||
capture_opts.linktype = pcap_datalink_name_to_val(optarg);
|
||||
if (capture_opts.linktype == -1) {
|
||||
fprintf(stderr, "tethereal: 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 */
|
||||
#else
|
||||
capture_option_specified = TRUE;
|
||||
arg_error = TRUE;
|
||||
#endif
|
||||
break;
|
||||
case 'z':
|
||||
for(tli=tap_list;tli;tli=tli->next){
|
||||
if(!strncmp(tli->cmd,optarg,strlen(tli->cmd))){
|
||||
|
@ -1417,7 +1219,7 @@ main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
/* No - did they specify a ring buffer option? */
|
||||
if (capture_opts.ringbuffer_on) {
|
||||
if (capture_opts.multi_files_on) {
|
||||
fprintf(stderr, "tethereal: Ring buffer requested, but a capture isn't being done.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -1430,7 +1232,7 @@ main(int argc, char *argv[])
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (capture_opts.ringbuffer_on) {
|
||||
if (capture_opts.multi_files_on) {
|
||||
/* Ring buffer works only under certain conditions:
|
||||
a) ring buffer does not work if you're not saving the capture to
|
||||
a file;
|
||||
|
@ -1520,12 +1322,12 @@ main(int argc, char *argv[])
|
|||
else if (capture_opts.snaplen < MIN_PACKET_SIZE)
|
||||
capture_opts.snaplen = MIN_PACKET_SIZE;
|
||||
|
||||
/* Check the value range of the ringbuffer_num_files parameter */
|
||||
if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
|
||||
capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
|
||||
/* Check the value range of the ring_num_files parameter */
|
||||
if (capture_opts.ring_num_files > RINGBUFFER_MAX_NUM_FILES)
|
||||
capture_opts.ring_num_files = RINGBUFFER_MAX_NUM_FILES;
|
||||
#if RINGBUFFER_MIN_NUM_FILES > 0
|
||||
else if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
|
||||
capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
|
||||
else if (capture_opts.ring_num_files < RINGBUFFER_MIN_NUM_FILES)
|
||||
capture_opts.ring_num_files = RINGBUFFER_MIN_NUM_FILES;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -1694,7 +1496,7 @@ main(int argc, char *argv[])
|
|||
|
||||
capture(save_file, out_file_type);
|
||||
|
||||
if (capture_opts.ringbuffer_on) {
|
||||
if (capture_opts.multi_files_on) {
|
||||
ringbuf_free();
|
||||
}
|
||||
#else
|
||||
|
@ -1909,9 +1711,9 @@ capture(char *save_file, int out_file_type)
|
|||
goto error;
|
||||
}
|
||||
ld.save_file = save_file;
|
||||
if (capture_opts.ringbuffer_on) {
|
||||
if (capture_opts.multi_files_on) {
|
||||
save_file_fd = ringbuf_init(save_file,
|
||||
capture_opts.ringbuffer_num_files);
|
||||
capture_opts.ring_num_files);
|
||||
if (save_file_fd != -1) {
|
||||
ld.pdh = ringbuf_init_wtap_dump_fdopen(out_file_type, ld.linktype,
|
||||
file_snaplen, &err);
|
||||
|
@ -1972,9 +1774,9 @@ capture(char *save_file, int out_file_type)
|
|||
cnd_stop_timeout = cnd_new((const char*)CND_CLASS_TIMEOUT,
|
||||
(gint32)capture_opts.autostop_duration);
|
||||
|
||||
if (capture_opts.ringbuffer_on && capture_opts.has_ring_duration)
|
||||
if (capture_opts.multi_files_on && capture_opts.has_file_duration)
|
||||
cnd_ring_timeout = cnd_new(CND_CLASS_TIMEOUT,
|
||||
capture_opts.ringbuffer_duration);
|
||||
capture_opts.file_duration);
|
||||
|
||||
if (!setjmp(ld.stopenv)) {
|
||||
ld.go = TRUE;
|
||||
|
@ -2025,15 +1827,15 @@ capture(char *save_file, int out_file_type)
|
|||
reading the FIFO sees the packets immediately and doesn't get
|
||||
any partial packet, forcing it to block in the middle of reading
|
||||
that packet. */
|
||||
if (capture_opts.autostop_count == 0)
|
||||
if (capture_opts.autostop_packets == 0)
|
||||
pcap_cnt = -1;
|
||||
else {
|
||||
if (ld.packet_count >= capture_opts.autostop_count) {
|
||||
if (ld.packet_count >= capture_opts.autostop_packets) {
|
||||
/* XXX do we need this test here? */
|
||||
/* It appears there's nothing more to capture. */
|
||||
break;
|
||||
}
|
||||
pcap_cnt = capture_opts.autostop_count - ld.packet_count;
|
||||
pcap_cnt = capture_opts.autostop_packets - ld.packet_count;
|
||||
}
|
||||
} else {
|
||||
/* We need to check the capture file size or the timeout after
|
||||
|
@ -2055,8 +1857,8 @@ capture(char *save_file, int out_file_type)
|
|||
/* The specified capture time has elapsed; stop the capture. */
|
||||
ld.go = FALSE;
|
||||
} else if (inpkts > 0) {
|
||||
if (capture_opts.autostop_count != 0 &&
|
||||
ld.packet_count >= capture_opts.autostop_count) {
|
||||
if (capture_opts.autostop_packets != 0 &&
|
||||
ld.packet_count >= capture_opts.autostop_packets) {
|
||||
/* The specified number of packets have been captured and have
|
||||
passed both any capture filter in effect and any read filter
|
||||
in effect. */
|
||||
|
@ -2066,7 +1868,7 @@ capture(char *save_file, int out_file_type)
|
|||
(guint32)wtap_get_bytes_dumped(ld.pdh))) {
|
||||
/* We're saving the capture to a file, and the capture file reached
|
||||
its maximum size. */
|
||||
if (capture_opts.ringbuffer_on) {
|
||||
if (capture_opts.multi_files_on) {
|
||||
/* Switch to the next ringbuffer file */
|
||||
if (ringbuf_switch_file(&ld.pdh, &save_file, &save_file_fd, &loop_err)) {
|
||||
/* File switch succeeded: reset the condition */
|
||||
|
@ -2135,7 +1937,7 @@ capture(char *save_file, int out_file_type)
|
|||
|
||||
if (save_file != NULL) {
|
||||
/* We're saving to a file or files; close all files. */
|
||||
if (capture_opts.ringbuffer_on) {
|
||||
if (capture_opts.multi_files_on) {
|
||||
dump_ok = ringbuf_wtap_dump_close(&save_file, &err);
|
||||
} else {
|
||||
dump_ok = wtap_dump_close(ld.pdh, &err);
|
||||
|
@ -2172,7 +1974,7 @@ capture(char *save_file, int out_file_type)
|
|||
return TRUE;
|
||||
|
||||
error:
|
||||
if (capture_opts.ringbuffer_on) {
|
||||
if (capture_opts.multi_files_on) {
|
||||
ringbuf_error_cleanup();
|
||||
}
|
||||
g_free(save_file);
|
||||
|
|
Loading…
Reference in New Issue