From Jim Young:

The ability to continue processing additional files if and when 
wtap_open_offline() should fail.  A new -C option reverts to capinfos' 
original behavior which is to cancel any further file processing at 
first file open failure.

Change the behavior of how the default display of all infos is initiated.
This gets rid of a special post getopt() argument count test.

Add new table output format (with related options). This feature allows 
outputting the various infos into a tab delimited text file, or to a comma 
separated variables file (*.csv) instead of the original "long" format.

svn path=/trunk/; revision=30956
daniel/osmux
Jaap Keuter 2009-11-13 21:43:57 +00:00
parent eeb2d89d92
commit 25470e5663
2 changed files with 577 additions and 53 deletions

View File

@ -24,6 +24,29 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* 2009-09-19: jyoung
*
* New capinfos features
*
* Continue processing additional files after
* a wiretap open failure. The new -C option
* reverts to capinfos' original behavior which
* is to cancels any further file processing at
* first file open failure.
*
* Change the behavior of how the default display
* of all infos is initiated. This gets rid of a
* special post getopt() argument count test.
*
* Add new table output format (with related options)
* This feature allows outputting the various infos
* into a tab delimited text file, or to a comma
* separated variables file (*.csv) instead of the
* original "long" format.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -57,20 +80,54 @@
#include "wsgetopt.h"
#endif
static gboolean cap_file_type = FALSE; /* Do not report capture type */
static gboolean cap_file_encap = FALSE; /* Do not report encapsulation */
static gboolean cap_packet_count = FALSE; /* Do not produce packet count */
static gboolean cap_file_size = FALSE; /* Do not report file size */
static gboolean cap_data_size = FALSE; /* Do not report packet byte size */
static gboolean cap_duration = FALSE; /* Do not report capture duration */
static gboolean cap_start_time = FALSE;
static gboolean cap_end_time = FALSE;
/*
* By default capinfos now continues processing
* the next filename if and when wiretap detects
* a problem opening a file.
* Use the '-C' option to revert back to original
* capinfos behavior which is to abort any
* additional file processing at first open file
* failure.
*/
static gboolean cap_data_rate_byte = FALSE;
static gboolean cap_data_rate_bit = FALSE;
static gboolean cap_packet_size = FALSE;
static gboolean cap_packet_rate = FALSE;
static gboolean continue_after_wtap_open_offline_failure = TRUE;
/*
* table report variables
*/
static gboolean long_report = TRUE; /* By default generate long report */
static gchar table_report_header = TRUE; /* Generate column header by default */
static gchar field_separator = '\t'; /* Use TAB as field separator by default */
static gchar quote_char = '\0'; /* Do NOT quote fields by default */
/*
* capinfos has the ability to report on a number of
* various characteristics ("infos") for each input file.
*
* By default reporting of all info fields is enabled.
*
* Optionally the reporting of any specific info field
* or combination of info fields can be enabled with
* individual options.
*/
static gboolean report_all_infos = TRUE; /* Report all infos */
static gboolean cap_file_type = TRUE; /* Report capture type */
static gboolean cap_file_encap = TRUE; /* Report encapsulation */
static gboolean cap_packet_count = TRUE; /* Report packet count */
static gboolean cap_file_size = TRUE; /* Report file size */
static gboolean cap_data_size = TRUE; /* Report packet byte size */
static gboolean cap_duration = TRUE; /* Report capture duration */
static gboolean cap_start_time = TRUE; /* Report capture start time */
static gboolean cap_end_time = TRUE; /* Report capture end time */
static gboolean cap_data_rate_byte = TRUE; /* Report data rate bytes/sec */
static gboolean cap_data_rate_bit = TRUE; /* Report data rate bites/sec */
static gboolean cap_packet_size = TRUE; /* Report average packet size */
static gboolean cap_packet_rate = TRUE; /* Report average packet rate */
typedef struct _capture_info {
const char *filename;
@ -92,6 +149,69 @@ typedef struct _capture_info {
double data_rate; /* in bytes */
} capture_info;
static void
enable_all_infos(void)
{
report_all_infos = TRUE;
cap_file_type = TRUE;
cap_file_encap = TRUE;
cap_packet_count = TRUE;
cap_file_size = TRUE;
cap_data_size = TRUE;
cap_duration = TRUE;
cap_start_time = TRUE;
cap_end_time = TRUE;
cap_data_rate_byte = TRUE;
cap_data_rate_bit = TRUE;
cap_packet_size = TRUE;
cap_packet_rate = TRUE;
}
static void
disable_all_infos(void)
{
report_all_infos = FALSE;
cap_file_type = FALSE;
cap_file_encap = FALSE;
cap_packet_count = FALSE;
cap_file_size = FALSE;
cap_data_size = FALSE;
cap_duration = FALSE;
cap_start_time = FALSE;
cap_end_time = FALSE;
cap_data_rate_byte = FALSE;
cap_data_rate_bit = FALSE;
cap_packet_size = FALSE;
cap_packet_rate = FALSE;
}
/*
* ctime_no_lf()
*
* This function simply truncates the string returned
* from the ctime() function to remove the trailing
* '\n' character.
*
* The ctime() function returns a string formatted as:
* "Www Mmm dd hh:mm:ss yyyy\n"
* The unwanted '\n' is the 24th character.
*/
static gchar *
ctime_no_lf(const time_t* timer)
{
gchar *time_string;
time_string = ctime(timer);
time_string[24] = '\0';
return(time_string);
}
static double
secs_nsecs(const struct wtap_nstime * nstime)
{
@ -106,7 +226,7 @@ static void print_value(gchar *text_p1, gint width, gchar *text_p2, double value
}
static void
print_stats(capture_info *cf_info)
print_stats(const gchar *filename, capture_info *cf_info)
{
const gchar *file_type_string, *file_encap_string;
time_t start_time_t;
@ -118,6 +238,7 @@ print_stats(capture_info *cf_info)
start_time_t = (time_t)cf_info->start_time;
stop_time_t = (time_t)cf_info->stop_time;
if (filename) printf ("File name: %s\n", filename);
if (cap_file_type) printf ("File type: %s\n", file_type_string);
if (cap_file_encap) printf ("File encapsulation: %s\n", file_encap_string);
if (cap_packet_count) printf ("Number of packets: %u\n", cf_info->packet_count);
@ -132,6 +253,156 @@ print_stats(capture_info *cf_info)
if (cap_packet_rate) print_value("Average packet rate: ", 2, " packets/sec", cf_info->packet_rate);
}
static void
putsep(void)
{
if (field_separator) putchar(field_separator);
}
static void
putquote(void)
{
if (quote_char) putchar(quote_char);
}
static void
print_stats_table_header_label(gchar *label)
{
putsep();
putquote();
printf("%s", label);
putquote();
}
static void
print_stats_table_header(void)
{
putquote();
printf("File name");
putquote();
if (cap_file_type) print_stats_table_header_label("File type");
if (cap_file_encap) print_stats_table_header_label("File encapsulation");
if (cap_packet_count) print_stats_table_header_label("Number of packets");
if (cap_file_size) print_stats_table_header_label("File size (bytes)");
if (cap_data_size) print_stats_table_header_label("Data size (bytes)");
if (cap_duration) print_stats_table_header_label("Capture duration (seconds)");
if (cap_start_time) print_stats_table_header_label("Start time");
if (cap_end_time) print_stats_table_header_label("End time");
if (cap_data_rate_byte) print_stats_table_header_label("Data byte rate (bytes/sec)");
if (cap_data_rate_bit) print_stats_table_header_label("Data bit rate (bits/sec)");
if (cap_packet_size) print_stats_table_header_label("Average packet size (bytes)");
if (cap_packet_rate) print_stats_table_header_label("Average packet rate (packets/sec)");
printf("\n");
}
static void
print_stats_table(const gchar *filename, capture_info *cf_info)
{
const gchar *file_type_string, *file_encap_string;
time_t start_time_t;
time_t stop_time_t;
/* Build printable strings for various stats */
file_type_string = wtap_file_type_string(cf_info->file_type);
file_encap_string = wtap_encap_string(cf_info->file_encap);
start_time_t = (time_t)cf_info->start_time;
stop_time_t = (time_t)cf_info->stop_time;
if (filename) {
putquote();
printf("%s", filename);
putquote();
}
if (cap_file_type) {
putsep();
putquote();
printf("%s", file_type_string);
putquote();
}
if (cap_file_encap) {
putsep();
putquote();
printf("%s", file_encap_string);
putquote();
}
if (cap_packet_count) {
putsep();
putquote();
printf("%u", cf_info->packet_count);
putquote();
}
if (cap_file_size) {
putsep();
putquote();
printf("%" G_GINT64_MODIFIER "d", cf_info->filesize);
putquote();
}
if (cap_data_size) {
putsep();
putquote();
printf("%" G_GINT64_MODIFIER "u", cf_info->packet_bytes);
putquote();
}
if (cap_duration) {
putsep();
putquote();
printf("%f", cf_info->duration);
putquote();
}
if (cap_start_time) {
putsep();
putquote();
printf("%s", (cf_info->packet_count>0) ? ctime_no_lf (&start_time_t) : "n/a");
putquote();
}
if (cap_end_time) {
putsep();
putquote();
printf("%s", (cf_info->packet_count>0) ? ctime_no_lf (&stop_time_t) : "n/a");
putquote();
}
if (cap_data_rate_byte) {
putsep();
putquote();
printf("%.2f", cf_info->data_rate);
putquote();
}
if (cap_data_rate_bit) {
putsep();
putquote();
printf("%.2f", cf_info->data_rate*8);
putquote();
}
if (cap_packet_size) {
putsep();
putquote();
printf("%.2f", cf_info->packet_size);
putquote();
}
if (cap_packet_rate) {
putsep();
putquote();
printf("%.2f", cf_info->packet_rate);
putquote();
}
printf("\n");
}
static int
process_cap_file(wtap *wth, const char *filename)
{
@ -222,8 +493,11 @@ process_cap_file(wtap *wth, const char *filename)
cf_info.packet_size = (double)bytes / packet; /* Avg packet size */
}
printf("File name: %s\n", filename);
print_stats(&cf_info);
if(long_report) {
print_stats(filename, &cf_info);
} else {
print_stats_table(filename, &cf_info);
}
return 0;
}
@ -246,35 +520,57 @@ usage(gboolean is_error)
" (" SVNVERSION " from " SVNPATH ")"
#endif
"\n", VERSION);
fprintf(output, "Prints information about capture files.\n");
fprintf(output, "Prints various information (infos) about capture files.\n");
fprintf(output, "See http://www.wireshark.org for more information.\n");
fprintf(output, "\n");
fprintf(output, "Usage: capinfos [options] <infile> ...\n");
fprintf(output, "\n");
fprintf(output, "General:\n");
fprintf(output, "General infos:\n");
fprintf(output, " -t display the capture file type\n");
fprintf(output, " -E display the capture file encapsulation\n");
fprintf(output, "\n");
fprintf(output, "Size:\n");
fprintf(output, "Size infos:\n");
fprintf(output, " -c display the number of packets\n");
fprintf(output, " -s display the size of the file (in bytes)\n");
fprintf(output, " -d display the total length of all packets (in bytes)\n");
fprintf(output, "\n");
fprintf(output, "Time:\n");
fprintf(output, "Time infos:\n");
fprintf(output, " -u display the capture duration (in seconds)\n");
fprintf(output, " -a display the capture start time\n");
fprintf(output, " -e display the capture end time\n");
fprintf(output, "\n");
fprintf(output, "Statistic:\n");
fprintf(output, "Statistic infos:\n");
fprintf(output, " -y display average data rate (in bytes/sec)\n");
fprintf(output, " -i display average data rate (in bits/sec)\n");
fprintf(output, " -z display average packet size (in bytes)\n");
fprintf(output, " -x display average packet rate (in packets/sec)\n");
fprintf(output, "\n");
fprintf(output, "Output format:\n");
fprintf(output, " -L generate long report (default)\n");
fprintf(output, " -T generate table report\n");
fprintf(output, "\n");
fprintf(output, "Table report options:\n");
fprintf(output, " -R generate header record (default)\n");
fprintf(output, " -r do not generate header record\n");
fprintf(output, "\n");
fprintf(output, " -B separate infos with TAB character (default)\n");
fprintf(output, " -m separate infos with comma (,) character\n");
fprintf(output, " -b separate infos with SPACE character\n");
fprintf(output, "\n");
fprintf(output, " -N do not quote infos (default)\n");
fprintf(output, " -q quote infos with single quotes (')\n");
fprintf(output, " -Q quote infos with double quotes (\")\n");
fprintf(output, "\n");
fprintf(output, "Miscellaneous:\n");
fprintf(output, " -h display this help and exit\n");
fprintf(output, " -C cancel processing if file open fails (default is to continue)\n");
fprintf(output, " -A generate all infos (default)\n");
fprintf(output, "\n");
fprintf(output, "If no options are given the default is to display all infos\n");
fprintf(output, "Options are processed from left to right order with later options superceeding\n");
fprintf(output, "or adding to earlier options.\n");
fprintf(output, "\n");
fprintf(output, "If no options are given the default is to display all infos in long report\n");
fprintf(output, "output format.\n");
}
#ifdef HAVE_PLUGINS
@ -322,58 +618,118 @@ main(int argc, char *argv[])
/* Process the options */
while ((opt = getopt(argc, argv, "tEcsduaeyizvhx")) !=-1) {
while ((opt = getopt(argc, argv, "tEcsduaeyizvhxCALTRrNqQBmb")) !=-1) {
switch (opt) {
case 't':
if (report_all_infos) disable_all_infos();
cap_file_type = TRUE;
break;
case 'E':
if (report_all_infos) disable_all_infos();
cap_file_encap = TRUE;
break;
case 'c':
if (report_all_infos) disable_all_infos();
cap_packet_count = TRUE;
break;
case 's':
if (report_all_infos) disable_all_infos();
cap_file_size = TRUE;
break;
case 'd':
if (report_all_infos) disable_all_infos();
cap_data_size = TRUE;
break;
case 'u':
if (report_all_infos) disable_all_infos();
cap_duration = TRUE;
break;
case 'a':
if (report_all_infos) disable_all_infos();
cap_start_time = TRUE;
break;
case 'e':
if (report_all_infos) disable_all_infos();
cap_end_time = TRUE;
break;
case 'y':
if (report_all_infos) disable_all_infos();
cap_data_rate_byte = TRUE;
break;
case 'i':
if (report_all_infos) disable_all_infos();
cap_data_rate_bit = TRUE;
break;
case 'z':
if (report_all_infos) disable_all_infos();
cap_packet_size = TRUE;
break;
case 'x':
if (report_all_infos) disable_all_infos();
cap_packet_rate = TRUE;
break;
case 'C':
continue_after_wtap_open_offline_failure = FALSE;
break;
case 'A':
enable_all_infos();
break;
case 'L':
long_report = TRUE;
break;
case 'T':
long_report = FALSE;
break;
case 'R':
table_report_header = TRUE;
break;
case 'r':
table_report_header = FALSE;
break;
case 'N':
quote_char = '\0';
break;
case 'q':
quote_char = '\'';
break;
case 'Q':
quote_char = '"';
break;
case 'B':
field_separator = '\t';
break;
case 'm':
field_separator = ',';
break;
case 'b':
field_separator = ' ';
break;
case 'h':
usage(FALSE);
exit(1);
@ -386,29 +742,15 @@ main(int argc, char *argv[])
}
}
if (optind < 2) {
/* If no arguments were given, by default display all statistics */
cap_file_type = TRUE;
cap_file_encap = TRUE;
cap_packet_count = TRUE;
cap_file_size = TRUE;
cap_data_size = TRUE;
cap_duration = TRUE;
cap_start_time = TRUE;
cap_end_time = TRUE;
cap_data_rate_byte = TRUE;
cap_data_rate_bit = TRUE;
cap_packet_size = TRUE;
cap_packet_rate = TRUE;
}
if ((argc - optind) < 1) {
usage(TRUE);
exit(1);
}
if(!long_report && table_report_header) {
print_stats_table_header();
}
for (opt = optind; opt < argc; opt++) {
wth = wtap_open_offline(argv[opt], &err, &err_info, FALSE);
@ -425,16 +767,19 @@ main(int argc, char *argv[])
g_free(err_info);
break;
}
exit(1);
if(!continue_after_wtap_open_offline_failure)
exit(1);
}
if (opt > optind)
printf("\n");
status = process_cap_file(wth, argv[opt]);
if(wth) {
if ((opt > optind) && (long_report))
printf("\n");
status = process_cap_file(wth, argv[opt]);
wtap_close(wth);
if (status)
exit(status);
wtap_close(wth);
if (status)
exit(status);
}
}
return 0;
}

View File

@ -17,19 +17,39 @@ S<[ B<-e> ]>
S<[ B<-y> ]>
S<[ B<-i> ]>
S<[ B<-z> ]>
S<[ B<-x> ]>
S<[ B<-L> ]>
S<[ B<-T> ]>
S<[ B<-R> ]>
S<[ B<-r> ]>
S<[ B<-B> ]>
S<[ B<-m> ]>
S<[ B<-b> ]>
S<[ B<-N> ]>
S<[ B<-q> ]>
S<[ B<-Q> ]>
S<[ B<-h> ]>
S<[ B<-C> ]>
S<[ B<-A> ]>
E<lt>I<infile>E<gt>
I<...>
=head1 DESCRIPTION
B<Capinfos> is a program that reads one or more capture files and
returns some or all available statistics of each E<lt>I<infile>E<gt>.
returns some or all available statistics (infos) of each E<lt>I<infile>E<gt>
in one of two types of output formats: long or table.
The user specifies which statistics to report by specifying flags
corresponding to the statistic. If no flags are specified, B<Capinfos>
will report all statistics available.
The long output is suitable for a human to read. The table output
is useful for generating a report that can be easily imported into
a spreadsheet or database.
The user specifies what type of output (long or table) and which
statistics to display by specifying flags (options) that corresponding
to the report type and desired infos. If no options are specified,
B<Capinfos> will report all statistics available in "long" format.
Options are processed from left to right order with later options
superceeding or adding to earlier options.
B<Capinfos> is able to detect and read the same capture files that are
supported by B<Wireshark>.
@ -54,7 +74,7 @@ Displays the per-file encapsulation of the capture file.
=item -c
Counts the number of packets in the capture file.
Displays the number of packets in the capture file.
=item -s
@ -109,12 +129,170 @@ displays the average packet size, in bytes
displays the average packet rate, in packets/sec
=item -L
Generate long report. Capinfos can generate two
different styles of reports. The "long" report is
the default style of output and is suitable for a
human to use.
=item -T
Generate a table report. A table report is a text file
that is suitable for importing into a spreadsheet or
database. Capinfos can build a tab delimited text file
(the default) or several variations on Comma-separated
values (CSV) files.
=item -R
Generate header record. This option is only useful
when generating a table style report (-T). A header
is generated by default. A header record (if generated)
is the first line of data reported and includes labels
for all the columns included within the table report.
=item -r
Do not generate header record. This option is only
useful when generating a table style report (-T).
If this option is specified then B<no> header record will be
generated within the table report.
=item -B
Separate the infos with ASCII TAB characters.
This option is only useful when generating a table
style report (-T). The various info values will be
separated (delimited) from one another with a single
ASCII TAB character. The TAB character is the default
delimiter when -T style report is enabled.
=item -m
Separate the infos with comma (,) characters. This option
is only useful when generating a table style report (-T).
The various info values will be separated (delimited)
from one another with a single comma "," character.
=item -b
Separate infos with ASCII SPACE (0x20) characters.
This option is only useful when generating a table
style report (-T). The various info values will be
separated (delimited) from one another with a single
ASCII SPACE character.
NOTE: Since some of the header labels as well as some
of the value fields contain SPACE characters. This
option is of limited value unless one of the quoting
options (-q or -Q) is also specified.
=item -N
Do not quote the infos. This option is only useful
when generating a table style report (-T). Excluding
any quoting characters around the various values and
using a TAB delimiter produces a very "clean" table
report that is easily parsed with CLI tools. By
default infos are B<NOT> quoted.
=item -q
Quote infos with single quotes ('). This option is
only useful when generating a table style report (-T).
When this option is enabled, each value will be
encapsulated within a pair of single quote (')
characters. This option (when used with the -m
option) is useful for generating one type of CSV
style file report.
=item -Q
Quote infos with double quotes ("). This option is
only useful when generating a table style report (-T).
When this option is enabled, each value will be
encapsulated within a pair of double quote (")
characters. This option (when used with the -m
option) is useful for generating the most common
type of CSV style file report.
=item -h
Prints the help listing and exits.
=item -C
Cancel processing any additional files if and
when capinfos should fail to open an input file.
By default capinfos will attempt to open each and
every file name argument.
Note: An error message will be written to stderr
whenever capinfos fails to open a file regardless
of whether the -C option is specified or not.
=item -A
Generate all infos. By default capinfos will display
all infos values for each input file, but enabling
any of the individual display infos options will
disable the generate all option.
=back
=head1 EXAMPLES
To see a description of the capinfos options use:
capinfos -h
To generate a long form report for the capture file
mycapture.pcap use:
capinfos mycapture.pcap
To generate a TAB delimited table form report for the capture
file mycapture.pcap use:
capinfos -T mycapture.pcap
To generate a CSV style table form report for the capture
file mycapture.pcap use:
capinfos -T -m -Q mycapture.pcap
or
capinfos -TmQ mycapture.pcap
To generate a TAB delimited table style report with just the
filenames, capture type, capture encapsulation type and packet
count for all the pcap files in the current directory use:
capinfos -T -t -E -c *.pcap
or
capinfos -TtEs *.pcap
Note: The ability to use of filename globbing characters are
a feature of *nix style command shells.
To generate a CSV delimited table style report of all infos
for all pcap files in the current directory and write it to
a text file called mycaptures.csv use:
capinfos -TmQ *.pcap >mycaptures.csv
The resulting mycaptures.csv file can be easily imported
into spreadsheet applications.
=head1 SEE ALSO
tcpdump(8), pcap(3), wireshark(1), mergecap(1), editcap(1), tshark(1),
@ -138,3 +316,4 @@ L<http://www.wireshark.org/docs/man-pages>.
Contributors
------------
Gerald Combs <gerald[AT]wireshark.org>
Jim Young <jyoung[AT]gsu.edu>