forked from osmocom/wireshark
Move the packet counting, dissecting, and filtering out of the "write
packet" and "print packet" callbacks into a common routine, so that we don't count packets twice if we're counting and dissecting. Print the packet count with ^T iff we're not updating a displayed packet count as packets arrive, regardless of whether we're printing packet information, saving packets to a file, or both (tcpdump prints it regardless of whether it's printing packet information or saving packets to a file). svn path=/trunk/; revision=11037
This commit is contained in:
parent
d6d7816485
commit
8a429808e7
745
tethereal.c
745
tethereal.c
|
@ -1,6 +1,6 @@
|
||||||
/* tethereal.c
|
/* tethereal.c
|
||||||
*
|
*
|
||||||
* $Id: tethereal.c,v 1.239 2004/05/09 10:03:39 guy Exp $
|
* $Id: tethereal.c,v 1.240 2004/05/31 07:52:27 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
@ -120,7 +120,7 @@ static guint32 firstsec, firstusec;
|
||||||
static guint32 prevsec, prevusec;
|
static guint32 prevsec, prevusec;
|
||||||
static GString *comp_info_str, *runtime_info_str;
|
static GString *comp_info_str, *runtime_info_str;
|
||||||
static gboolean quiet;
|
static gboolean quiet;
|
||||||
static gboolean decode;
|
static gboolean print_packet_info; /* TRUE if we're to print packet information */
|
||||||
static gboolean verbose;
|
static gboolean verbose;
|
||||||
static gboolean print_hex;
|
static gboolean print_hex;
|
||||||
static gboolean line_buffered;
|
static gboolean line_buffered;
|
||||||
|
@ -166,18 +166,16 @@ static void report_counts_siginfo(int);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
#endif /* HAVE_LIBPCAP */
|
#endif /* HAVE_LIBPCAP */
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
capture_file *cf;
|
|
||||||
wtap_dumper *pdh;
|
|
||||||
} cb_args_t;
|
|
||||||
|
|
||||||
static int load_cap_file(capture_file *, int);
|
static int load_cap_file(capture_file *, int);
|
||||||
static void wtap_dispatch_cb_write(guchar *, const struct wtap_pkthdr *, long,
|
static void process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
|
||||||
union wtap_pseudo_header *, const guchar *);
|
const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header,
|
||||||
|
const guchar *pd);
|
||||||
|
static void write_packet(capture_file *cf, wtap_dumper *pdh,
|
||||||
|
const struct wtap_pkthdr *phdr, union wtap_pseudo_header *pseudo_header,
|
||||||
|
const guchar *buf);
|
||||||
static void show_capture_file_io_error(const char *, int, gboolean);
|
static void show_capture_file_io_error(const char *, int, gboolean);
|
||||||
static void wtap_dispatch_cb_print(guchar *, const struct wtap_pkthdr *, long,
|
|
||||||
union wtap_pseudo_header *, const guchar *);
|
|
||||||
static void show_print_file_io_error(int err);
|
static void show_print_file_io_error(int err);
|
||||||
|
static void print_packet(capture_file *cf, epan_dissect_t *edt);
|
||||||
static char *cf_open_error_message(int err, gchar *err_info,
|
static char *cf_open_error_message(int err, gchar *err_info,
|
||||||
gboolean for_writing, int file_type);
|
gboolean for_writing, int file_type);
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
|
@ -1117,12 +1115,11 @@ main(int argc, char *argv[])
|
||||||
is probably actually better for "-V", as it does fewer
|
is probably actually better for "-V", as it does fewer
|
||||||
writes).
|
writes).
|
||||||
|
|
||||||
See the comment in "wtap_dispatch_cb_print()" for an
|
See the comment in "print_packet()" for an explanation of
|
||||||
explanation of why we do that, and why we don't just
|
why we do that, and why we don't just use "setvbuf()" to
|
||||||
use "setvbuf()" to make the standard output line-buffered
|
make the standard output line-buffered (short version: in
|
||||||
(short version: in Windows, "line-buffered" is the same
|
Windows, "line-buffered" is the same as "fully-buffered",
|
||||||
as "fully-buffered", and the output buffer is only flushed
|
and the output buffer is only flushed when it fills up). */
|
||||||
when it fills up). */
|
|
||||||
line_buffered = TRUE;
|
line_buffered = TRUE;
|
||||||
break;
|
break;
|
||||||
case 'L': /* Print list of link-layer types and exit */
|
case 'L': /* Print list of link-layer types and exit */
|
||||||
|
@ -1189,7 +1186,7 @@ main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 'S': /* show packets in real time */
|
case 'S': /* show packets in real time */
|
||||||
decode = TRUE;
|
print_packet_info = TRUE;
|
||||||
break;
|
break;
|
||||||
case 't': /* Time stamp type */
|
case 't': /* Time stamp type */
|
||||||
if (strcmp(optarg, "r") == 0)
|
if (strcmp(optarg, "r") == 0)
|
||||||
|
@ -1345,6 +1342,9 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
} else {
|
||||||
|
/* We're not writing to a file, so we should print packet information. */
|
||||||
|
print_packet_info = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_LIBPCAP
|
#ifndef HAVE_LIBPCAP
|
||||||
|
@ -1618,7 +1618,7 @@ main(int argc, char *argv[])
|
||||||
/* Do the low-level work of a capture.
|
/* Do the low-level work of a capture.
|
||||||
Returns TRUE if it succeeds, FALSE otherwise. */
|
Returns TRUE if it succeeds, FALSE otherwise. */
|
||||||
|
|
||||||
static condition *volatile cnd_ring_timeout = NULL; /* this must be visible in wtap_dispatch_cb_write */
|
static condition *volatile cnd_ring_timeout = NULL; /* this must be visible in write_packet */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
capture(int out_file_type)
|
capture(int out_file_type)
|
||||||
|
@ -2098,7 +2098,6 @@ capture_pcap_cb(guchar *user, const struct pcap_pkthdr *phdr,
|
||||||
struct wtap_pkthdr whdr;
|
struct wtap_pkthdr whdr;
|
||||||
union wtap_pseudo_header pseudo_header;
|
union wtap_pseudo_header pseudo_header;
|
||||||
loop_data *ld = (loop_data *) user;
|
loop_data *ld = (loop_data *) user;
|
||||||
cb_args_t args;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* Convert from libpcap to Wiretap format.
|
/* Convert from libpcap to Wiretap format.
|
||||||
|
@ -2106,30 +2105,32 @@ capture_pcap_cb(guchar *user, const struct pcap_pkthdr *phdr,
|
||||||
written an error message). */
|
written an error message). */
|
||||||
pd = wtap_process_pcap_packet(ld->linktype, phdr, pd, &pseudo_header,
|
pd = wtap_process_pcap_packet(ld->linktype, phdr, pd, &pseudo_header,
|
||||||
&whdr, &err);
|
&whdr, &err);
|
||||||
if (pd == NULL) {
|
if (pd == NULL)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
args.cf = &cfile;
|
#ifdef SIGINFO
|
||||||
args.pdh = ld->pdh;
|
/*
|
||||||
if (ld->pdh) {
|
* Prevent a SIGINFO handler from writing to stdout while we're
|
||||||
wtap_dispatch_cb_write((guchar *)&args, &whdr, 0, &pseudo_header, pd);
|
* doing so; instead, have it just set a flag telling us to print
|
||||||
/* Report packet capture count if not quiet */
|
* that information when we're done.
|
||||||
if (!quiet) {
|
*/
|
||||||
if (!decode) {
|
infodelay = TRUE;
|
||||||
if (ld->packet_count != 0) {
|
#endif /* SIGINFO */
|
||||||
fprintf(stderr, "\r%u ", ld->packet_count);
|
|
||||||
/* stderr could be line buffered */
|
process_packet(&cfile, ld->pdh, 0, &whdr, &pseudo_header, pd);
|
||||||
fflush(stderr);
|
|
||||||
}
|
#ifdef SIGINFO
|
||||||
} else {
|
/*
|
||||||
wtap_dispatch_cb_print((guchar *)&args, &whdr, 0,
|
* Allow SIGINFO handlers to write.
|
||||||
&pseudo_header, pd);
|
*/
|
||||||
}
|
infodelay = FALSE;
|
||||||
}
|
|
||||||
} else {
|
/*
|
||||||
wtap_dispatch_cb_print((guchar *)&args, &whdr, 0, &pseudo_header, pd);
|
* If a SIGINFO handler asked us to write out capture counts, do so.
|
||||||
}
|
*/
|
||||||
|
if (infoprint)
|
||||||
|
report_counts();
|
||||||
|
#endif /* SIGINFO */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -2183,10 +2184,9 @@ report_counts(void)
|
||||||
signal(SIGINFO, report_counts_siginfo);
|
signal(SIGINFO, report_counts_siginfo);
|
||||||
#endif /* SIGINFO */
|
#endif /* SIGINFO */
|
||||||
|
|
||||||
if (cfile.save_file != NULL && quiet) {
|
if (quiet || print_packet_info) {
|
||||||
/* Report the count only if we're capturing to a file (rather
|
/* Report the count only if we aren't printing a packet count
|
||||||
than printing captured packet information out) and aren't
|
as packets arrive. */
|
||||||
updating a count as packets arrive. */
|
|
||||||
fprintf(stderr, "%u packets captured\n", ld.packet_count);
|
fprintf(stderr, "%u packets captured\n", ld.packet_count);
|
||||||
}
|
}
|
||||||
#ifdef SIGINFO
|
#ifdef SIGINFO
|
||||||
|
@ -2219,8 +2219,7 @@ load_cap_file(capture_file *cf, int out_file_type)
|
||||||
wtap_dumper *pdh;
|
wtap_dumper *pdh;
|
||||||
int err;
|
int err;
|
||||||
gchar *err_info;
|
gchar *err_info;
|
||||||
int success;
|
long data_offset;
|
||||||
cb_args_t args;
|
|
||||||
|
|
||||||
linktype = wtap_file_encap(cf->wth);
|
linktype = wtap_file_encap(cf->wth);
|
||||||
if (cf->save_file != NULL) {
|
if (cf->save_file != NULL) {
|
||||||
|
@ -2271,10 +2270,6 @@ load_cap_file(capture_file *cf, int out_file_type)
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
args.cf = cf;
|
|
||||||
args.pdh = pdh;
|
|
||||||
success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (guchar *) &args,
|
|
||||||
&err, &err_info);
|
|
||||||
} else {
|
} else {
|
||||||
print_preamble(stdout, print_format, cf->filename);
|
print_preamble(stdout, print_format, cf->filename);
|
||||||
if (ferror(stdout)) {
|
if (ferror(stdout)) {
|
||||||
|
@ -2282,24 +2277,13 @@ load_cap_file(capture_file *cf, int out_file_type)
|
||||||
show_print_file_io_error(err);
|
show_print_file_io_error(err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
args.cf = cf;
|
pdh = NULL;
|
||||||
args.pdh = NULL;
|
|
||||||
success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (guchar *) &args,
|
|
||||||
&err, &err_info);
|
|
||||||
}
|
}
|
||||||
if (success) {
|
while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
|
||||||
if (cf->save_file != NULL) {
|
process_packet(cf, pdh, data_offset, wtap_phdr(cf->wth),
|
||||||
/* Now close the capture file. */
|
wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth));
|
||||||
if (!wtap_dump_close(args.pdh, &err))
|
}
|
||||||
show_capture_file_io_error(cfile.save_file, err, TRUE);
|
if (err != 0) {
|
||||||
} else {
|
|
||||||
print_finale(stdout, print_format);
|
|
||||||
if (ferror(stdout)) {
|
|
||||||
err = errno;
|
|
||||||
show_print_file_io_error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Print a message noting that the read failed somewhere along the line. */
|
/* Print a message noting that the read failed somewhere along the line. */
|
||||||
switch (err) {
|
switch (err) {
|
||||||
|
|
||||||
|
@ -2335,9 +2319,21 @@ load_cap_file(capture_file *cf, int out_file_type)
|
||||||
}
|
}
|
||||||
if (cf->save_file != NULL) {
|
if (cf->save_file != NULL) {
|
||||||
/* Now close the capture file. */
|
/* Now close the capture file. */
|
||||||
if (!wtap_dump_close(args.pdh, &err))
|
if (!wtap_dump_close(pdh, &err))
|
||||||
show_capture_file_io_error(cfile.save_file, err, TRUE);
|
show_capture_file_io_error(cfile.save_file, err, TRUE);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (cf->save_file != NULL) {
|
||||||
|
/* Now close the capture file. */
|
||||||
|
if (!wtap_dump_close(pdh, &err))
|
||||||
|
show_capture_file_io_error(cfile.save_file, err, TRUE);
|
||||||
|
} else {
|
||||||
|
print_finale(stdout, print_format);
|
||||||
|
if (ferror(stdout)) {
|
||||||
|
err = errno;
|
||||||
|
show_print_file_io_error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -2416,99 +2412,148 @@ clear_fdata(frame_data *fdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wtap_dispatch_cb_write(guchar *user, const struct wtap_pkthdr *phdr,
|
process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
|
||||||
long offset, union wtap_pseudo_header *pseudo_header, const guchar *buf)
|
const struct wtap_pkthdr *whdr,
|
||||||
|
union wtap_pseudo_header *pseudo_header, const guchar *pd)
|
||||||
{
|
{
|
||||||
cb_args_t *args = (cb_args_t *) user;
|
frame_data fdata;
|
||||||
capture_file *cf = args->cf;
|
gboolean create_proto_tree;
|
||||||
wtap_dumper *pdh = args->pdh;
|
|
||||||
frame_data fdata;
|
|
||||||
int err;
|
|
||||||
gboolean passed;
|
|
||||||
epan_dissect_t *edt;
|
epan_dissect_t *edt;
|
||||||
|
gboolean passed;
|
||||||
|
|
||||||
#ifdef HAVE_LIBPCAP
|
/* Count this packet. */
|
||||||
#ifdef SIGINFO
|
|
||||||
/*
|
|
||||||
* Prevent a SIGINFO handler from writing to stdout while we're
|
|
||||||
* doing so; instead, have it just set a flag telling us to print
|
|
||||||
* that information when we're done.
|
|
||||||
*/
|
|
||||||
infodelay = TRUE;
|
|
||||||
#endif /* SIGINFO */
|
|
||||||
#endif /* HAVE_LIBPCAP */
|
|
||||||
|
|
||||||
cf->count++;
|
cf->count++;
|
||||||
if (cf->rfcode) {
|
|
||||||
fill_in_fdata(&fdata, cf, phdr, offset);
|
/* If we're going to print packet information, or we're going to
|
||||||
edt = epan_dissect_new(TRUE, FALSE);
|
run a read filter, set up to do a dissection and do so. */
|
||||||
epan_dissect_prime_dfilter(edt, cf->rfcode);
|
if (print_packet_info || cf->rfcode) {
|
||||||
epan_dissect_run(edt, pseudo_header, buf, &fdata, NULL);
|
fill_in_fdata(&fdata, cf, whdr, offset);
|
||||||
passed = dfilter_apply_edt(cf->rfcode, edt);
|
|
||||||
} else {
|
if (print_packet_info) {
|
||||||
|
/* Grab any resolved addresses */
|
||||||
|
|
||||||
|
if (g_resolv_flags) {
|
||||||
|
host_name_lookup_process(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
passed = TRUE;
|
passed = TRUE;
|
||||||
|
if (cf->rfcode || verbose || num_tap_filters!=0)
|
||||||
|
create_proto_tree = TRUE;
|
||||||
|
else
|
||||||
|
create_proto_tree = FALSE;
|
||||||
|
/* The protocol tree will be "visible", i.e., printed, only if we're
|
||||||
|
printing packet details, which is true if we're printing stuff
|
||||||
|
("print_packet_info" is true) and we're in verbose mode ("verbose"
|
||||||
|
is true). */
|
||||||
|
edt = epan_dissect_new(create_proto_tree, print_packet_info && verbose);
|
||||||
|
|
||||||
|
/* If we're running a read filter, prime the epan_dissect_t with that
|
||||||
|
filter. */
|
||||||
|
if (cf->rfcode)
|
||||||
|
epan_dissect_prime_dfilter(edt, cf->rfcode);
|
||||||
|
|
||||||
|
tap_queue_init(edt);
|
||||||
|
|
||||||
|
/* We only need the columns if we're printing packet info but we're
|
||||||
|
*not* verbose; in verbose mode, we print the protocol tree, not
|
||||||
|
the protocol summary. */
|
||||||
|
epan_dissect_run(edt, pseudo_header, pd, &fdata,
|
||||||
|
(print_packet_info && !verbose) ? &cf->cinfo : NULL);
|
||||||
|
|
||||||
|
tap_push_tapped_queue(edt);
|
||||||
|
|
||||||
|
/* Run the read filter if we have one. */
|
||||||
|
if (cf->rfcode)
|
||||||
|
passed = dfilter_apply_edt(cf->rfcode, edt);
|
||||||
|
else
|
||||||
|
passed = TRUE;
|
||||||
|
} else {
|
||||||
|
/* We're not running a display filter and we're not printing any
|
||||||
|
packet information, so we don't need to do a dissection, and all
|
||||||
|
packets are processed. */
|
||||||
edt = NULL;
|
edt = NULL;
|
||||||
|
passed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passed) {
|
if (passed) {
|
||||||
/* The packet passed the read filter. */
|
/* Count this packet. */
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
int loop_err;
|
|
||||||
|
|
||||||
ld.packet_count++;
|
ld.packet_count++;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The current packet may have arrived after a very long silence,
|
/* Process this packet. */
|
||||||
* way past the time to switch files. In order not to have
|
if (pdh != NULL) {
|
||||||
* the first packet of a new series of events as the last
|
/* We're writing to a capture file; write this packet. */
|
||||||
* [or only] packet in the file, switch before writing!
|
write_packet(cf, pdh, whdr, pseudo_header, pd);
|
||||||
*/
|
/* Report packet capture count if not quiet */
|
||||||
if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
|
if (!quiet && !print_packet_info) {
|
||||||
/* time elasped for this ring file, switch to the next */
|
/* Don't print a packet count if we were asked not to with "-q"
|
||||||
if (ringbuf_switch_file(&cfile, &ld.pdh, &loop_err)) {
|
or if we're also printing packet info. */
|
||||||
/* File switch succeeded: reset the condition */
|
if (ld.packet_count != 0) {
|
||||||
cnd_reset(cnd_ring_timeout);
|
fprintf(stderr, "\r%u ", ld.packet_count);
|
||||||
} else {
|
/* stderr could be line buffered */
|
||||||
/* File switch failed: stop here */
|
fflush(stderr);
|
||||||
/* XXX - we should do something with "loop_err" */
|
}
|
||||||
ld.go = FALSE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
if (print_packet_info) {
|
||||||
if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
|
/* We're printing packet information; print the information for
|
||||||
#ifdef HAVE_LIBPCAP
|
this packet. */
|
||||||
if (ld.pch != NULL && !quiet) {
|
print_packet(cf, edt);
|
||||||
/* We're capturing packets, so (if -q not specified) we're printing
|
|
||||||
a count of packets captured; move to the line after the count. */
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
show_capture_file_io_error(cf->save_file, err, FALSE);
|
|
||||||
#ifdef HAVE_LIBPCAP
|
|
||||||
if (ld.pch != NULL)
|
|
||||||
pcap_close(ld.pch);
|
|
||||||
#endif
|
|
||||||
wtap_dump_close(pdh, &err);
|
|
||||||
exit(2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edt != NULL)
|
if (edt != NULL)
|
||||||
epan_dissect_free(edt);
|
epan_dissect_free(edt);
|
||||||
if (cf->rfcode)
|
|
||||||
|
if (print_packet_info || cf->rfcode)
|
||||||
clear_fdata(&fdata);
|
clear_fdata(&fdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_packet(capture_file *cf, wtap_dumper *pdh, const struct wtap_pkthdr *phdr,
|
||||||
|
union wtap_pseudo_header *pseudo_header, const guchar *buf)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
#ifdef HAVE_LIBPCAP
|
||||||
|
int loop_err;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBPCAP
|
#ifdef HAVE_LIBPCAP
|
||||||
#ifdef SIGINFO
|
/* The current packet may have arrived after a very long silence,
|
||||||
/*
|
* way past the time to switch files. In order not to have
|
||||||
* Allow SIGINFO handlers to write.
|
* the first packet of a new series of events as the last
|
||||||
|
* [or only] packet in the file, switch before writing!
|
||||||
*/
|
*/
|
||||||
infodelay = FALSE;
|
if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
|
||||||
|
/* time elapsed for this ring file, switch to the next */
|
||||||
/*
|
if (ringbuf_switch_file(&cfile, &ld.pdh, &loop_err)) {
|
||||||
* If a SIGINFO handler asked us to write out capture counts, do so.
|
/* File switch succeeded: reset the condition */
|
||||||
*/
|
cnd_reset(cnd_ring_timeout);
|
||||||
if (infoprint)
|
} else {
|
||||||
report_counts();
|
/* File switch failed: stop here */
|
||||||
#endif /* SIGINFO */
|
/* XXX - we should do something with "loop_err" */
|
||||||
#endif /* HAVE_LIBPCAP */
|
ld.go = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
|
||||||
|
#ifdef HAVE_LIBPCAP
|
||||||
|
if (ld.pch != NULL && !quiet) {
|
||||||
|
/* We're capturing packets, so (if -q not specified) we're printing
|
||||||
|
a count of packets captured; move to the line after the count. */
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
show_capture_file_io_error(cf->save_file, err, FALSE);
|
||||||
|
#ifdef HAVE_LIBPCAP
|
||||||
|
if (ld.pch != NULL)
|
||||||
|
pcap_close(ld.pch);
|
||||||
|
#endif
|
||||||
|
wtap_dump_close(pdh, &err);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2562,261 +2607,216 @@ show_capture_file_io_error(const char *fname, int err, gboolean is_close)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wtap_dispatch_cb_print(guchar *user, const struct wtap_pkthdr *phdr,
|
print_packet(capture_file *cf, epan_dissect_t *edt)
|
||||||
long offset, union wtap_pseudo_header *pseudo_header, const guchar *buf)
|
|
||||||
{
|
{
|
||||||
cb_args_t *args = (cb_args_t *) user;
|
|
||||||
capture_file *cf = args->cf;
|
|
||||||
frame_data fdata;
|
|
||||||
gboolean passed;
|
|
||||||
print_args_t print_args;
|
print_args_t print_args;
|
||||||
epan_dissect_t *edt;
|
|
||||||
gboolean create_proto_tree;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cf->count++;
|
print_args.to_file = TRUE;
|
||||||
|
print_args.format = print_format;
|
||||||
|
print_args.print_summary = !verbose;
|
||||||
|
print_args.print_hex = verbose && print_hex;
|
||||||
|
print_args.print_formfeed = FALSE;
|
||||||
|
print_args.print_dissections = verbose ? print_dissections_expanded : print_dissections_none;
|
||||||
|
|
||||||
fill_in_fdata(&fdata, cf, phdr, offset);
|
/* init the packet range */
|
||||||
|
packet_range_init(&print_args.range);
|
||||||
|
|
||||||
/* Grab any resolved addresses */
|
if (verbose) {
|
||||||
if (g_resolv_flags) {
|
/* Print the information in the protocol tree. */
|
||||||
host_name_lookup_process(NULL);
|
proto_tree_print(&print_args, edt, stdout);
|
||||||
}
|
if (!print_hex) {
|
||||||
|
/* "print_hex_data()" will put out a leading blank line, as well
|
||||||
|
as a trailing one; print one here, to separate the packets,
|
||||||
|
only if "print_hex_data()" won't be called. */
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Just fill in the columns. */
|
||||||
|
epan_dissect_fill_in_columns(edt);
|
||||||
|
|
||||||
passed = TRUE;
|
/* Now print them. */
|
||||||
if (cf->rfcode || verbose || num_tap_filters!=0)
|
for (i = 0; i < cf->cinfo.num_cols; i++) {
|
||||||
create_proto_tree = TRUE;
|
switch (cf->cinfo.col_fmt[i]) {
|
||||||
else
|
case COL_NUMBER:
|
||||||
create_proto_tree = FALSE;
|
/*
|
||||||
/* The protocol tree will be "visible", i.e., printed, only if we're
|
* Don't print this if we're doing a live capture from a network
|
||||||
not printing a summary.
|
* interface - if we're doing a live capture, you won't be
|
||||||
|
* able to look at the capture in the future (it's not being
|
||||||
|
* saved anywhere), so the frame numbers are unlikely to be
|
||||||
|
* useful.
|
||||||
|
*
|
||||||
|
* (XXX - it might be nice to be able to save and print at
|
||||||
|
* the same time, sort of like an "Update list of packets
|
||||||
|
* in real time" capture in Ethereal.)
|
||||||
|
*/
|
||||||
|
if (cf->iface != NULL)
|
||||||
|
continue;
|
||||||
|
printf("%3s", cf->cinfo.col_data[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
We only need the columns if we're *not* verbose; in verbose mode,
|
case COL_CLS_TIME:
|
||||||
we print the protocol tree, not the protocol summary. */
|
case COL_REL_TIME:
|
||||||
|
case COL_ABS_TIME:
|
||||||
|
case COL_ABS_DATE_TIME: /* XXX - wider */
|
||||||
|
printf("%10s", cf->cinfo.col_data[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
edt = epan_dissect_new(create_proto_tree, verbose);
|
case COL_DEF_SRC:
|
||||||
if (cf->rfcode) {
|
case COL_RES_SRC:
|
||||||
epan_dissect_prime_dfilter(edt, cf->rfcode);
|
case COL_UNRES_SRC:
|
||||||
}
|
case COL_DEF_DL_SRC:
|
||||||
|
case COL_RES_DL_SRC:
|
||||||
|
case COL_UNRES_DL_SRC:
|
||||||
|
case COL_DEF_NET_SRC:
|
||||||
|
case COL_RES_NET_SRC:
|
||||||
|
case COL_UNRES_NET_SRC:
|
||||||
|
printf("%12s", cf->cinfo.col_data[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
tap_queue_init(edt);
|
case COL_DEF_DST:
|
||||||
epan_dissect_run(edt, pseudo_header, buf, &fdata, verbose ? NULL : &cf->cinfo);
|
case COL_RES_DST:
|
||||||
tap_push_tapped_queue(edt);
|
case COL_UNRES_DST:
|
||||||
|
case COL_DEF_DL_DST:
|
||||||
|
case COL_RES_DL_DST:
|
||||||
|
case COL_UNRES_DL_DST:
|
||||||
|
case COL_DEF_NET_DST:
|
||||||
|
case COL_RES_NET_DST:
|
||||||
|
case COL_UNRES_NET_DST:
|
||||||
|
printf("%-12s", cf->cinfo.col_data[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
if (cf->rfcode) {
|
default:
|
||||||
passed = dfilter_apply_edt(cf->rfcode, edt);
|
printf("%s", cf->cinfo.col_data[i]);
|
||||||
}
|
break;
|
||||||
if (passed) {
|
|
||||||
/* The packet passed the read filter. */
|
|
||||||
#ifdef HAVE_LIBPCAP
|
|
||||||
ld.packet_count++;
|
|
||||||
#endif
|
|
||||||
print_args.to_file = TRUE;
|
|
||||||
print_args.format = print_format;
|
|
||||||
print_args.print_summary = !verbose;
|
|
||||||
print_args.print_hex = verbose && print_hex;
|
|
||||||
print_args.print_formfeed = FALSE;
|
|
||||||
print_args.print_dissections = verbose ? print_dissections_expanded : print_dissections_none;
|
|
||||||
|
|
||||||
/* init the packet range */
|
|
||||||
packet_range_init(&print_args.range);
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
/* Print the information in the protocol tree. */
|
|
||||||
proto_tree_print(&print_args, edt, stdout);
|
|
||||||
if (!print_hex) {
|
|
||||||
/* "print_hex_data()" will put out a leading blank line, as well
|
|
||||||
as a trailing one; print one here, to separate the packets,
|
|
||||||
only if "print_hex_data()" won't be called. */
|
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
} else {
|
if (i != cf->cinfo.num_cols - 1) {
|
||||||
/* Just fill in the columns. */
|
/*
|
||||||
epan_dissect_fill_in_columns(edt);
|
* This isn't the last column, so we need to print a
|
||||||
|
* separator between this column and the next.
|
||||||
|
*
|
||||||
|
* If we printed a network source and are printing a
|
||||||
|
* network destination of the same type next, separate
|
||||||
|
* them with "->"; if we printed a network destination
|
||||||
|
* and are printing a network source of the same type
|
||||||
|
* next, separate them with "<-"; otherwise separate them
|
||||||
|
* with a space.
|
||||||
|
*/
|
||||||
|
switch (cf->cinfo.col_fmt[i]) {
|
||||||
|
|
||||||
/* Now print them. */
|
case COL_DEF_SRC:
|
||||||
for (i = 0; i < cf->cinfo.num_cols; i++) {
|
case COL_RES_SRC:
|
||||||
switch (cf->cinfo.col_fmt[i]) {
|
case COL_UNRES_SRC:
|
||||||
case COL_NUMBER:
|
switch (cf->cinfo.col_fmt[i + 1]) {
|
||||||
/*
|
|
||||||
* Don't print this if we're doing a live capture from a network
|
|
||||||
* interface - if we're doing a live capture, you won't be
|
|
||||||
* able to look at the capture in the future (it's not being
|
|
||||||
* saved anywhere), so the frame numbers are unlikely to be
|
|
||||||
* useful.
|
|
||||||
*
|
|
||||||
* (XXX - it might be nice to be able to save and print at
|
|
||||||
* the same time, sort of like an "Update list of packets
|
|
||||||
* in real time" capture in Ethereal.)
|
|
||||||
*/
|
|
||||||
if (cf->iface != NULL)
|
|
||||||
continue;
|
|
||||||
printf("%3s", cf->cinfo.col_data[i]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COL_CLS_TIME:
|
|
||||||
case COL_REL_TIME:
|
|
||||||
case COL_ABS_TIME:
|
|
||||||
case COL_ABS_DATE_TIME: /* XXX - wider */
|
|
||||||
printf("%10s", cf->cinfo.col_data[i]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COL_DEF_SRC:
|
|
||||||
case COL_RES_SRC:
|
|
||||||
case COL_UNRES_SRC:
|
|
||||||
case COL_DEF_DL_SRC:
|
|
||||||
case COL_RES_DL_SRC:
|
|
||||||
case COL_UNRES_DL_SRC:
|
|
||||||
case COL_DEF_NET_SRC:
|
|
||||||
case COL_RES_NET_SRC:
|
|
||||||
case COL_UNRES_NET_SRC:
|
|
||||||
printf("%12s", cf->cinfo.col_data[i]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COL_DEF_DST:
|
|
||||||
case COL_RES_DST:
|
|
||||||
case COL_UNRES_DST:
|
|
||||||
case COL_DEF_DL_DST:
|
|
||||||
case COL_RES_DL_DST:
|
|
||||||
case COL_UNRES_DL_DST:
|
|
||||||
case COL_DEF_NET_DST:
|
|
||||||
case COL_RES_NET_DST:
|
|
||||||
case COL_UNRES_NET_DST:
|
|
||||||
printf("%-12s", cf->cinfo.col_data[i]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printf("%s", cf->cinfo.col_data[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i != cf->cinfo.num_cols - 1) {
|
|
||||||
/*
|
|
||||||
* This isn't the last column, so we need to print a
|
|
||||||
* separator between this column and the next.
|
|
||||||
*
|
|
||||||
* If we printed a network source and are printing a
|
|
||||||
* network destination of the same type next, separate
|
|
||||||
* them with "->"; if we printed a network destination
|
|
||||||
* and are printing a network source of the same type
|
|
||||||
* next, separate them with "<-"; otherwise separate them
|
|
||||||
* with a space.
|
|
||||||
*/
|
|
||||||
switch (cf->cinfo.col_fmt[i]) {
|
|
||||||
|
|
||||||
case COL_DEF_SRC:
|
|
||||||
case COL_RES_SRC:
|
|
||||||
case COL_UNRES_SRC:
|
|
||||||
switch (cf->cinfo.col_fmt[i + 1]) {
|
|
||||||
|
|
||||||
case COL_DEF_DST:
|
|
||||||
case COL_RES_DST:
|
|
||||||
case COL_UNRES_DST:
|
|
||||||
printf(" -> ");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
putchar(' ');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COL_DEF_DL_SRC:
|
|
||||||
case COL_RES_DL_SRC:
|
|
||||||
case COL_UNRES_DL_SRC:
|
|
||||||
switch (cf->cinfo.col_fmt[i + 1]) {
|
|
||||||
|
|
||||||
case COL_DEF_DL_DST:
|
|
||||||
case COL_RES_DL_DST:
|
|
||||||
case COL_UNRES_DL_DST:
|
|
||||||
printf(" -> ");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
putchar(' ');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COL_DEF_NET_SRC:
|
|
||||||
case COL_RES_NET_SRC:
|
|
||||||
case COL_UNRES_NET_SRC:
|
|
||||||
switch (cf->cinfo.col_fmt[i + 1]) {
|
|
||||||
|
|
||||||
case COL_DEF_NET_DST:
|
|
||||||
case COL_RES_NET_DST:
|
|
||||||
case COL_UNRES_NET_DST:
|
|
||||||
printf(" -> ");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
putchar(' ');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COL_DEF_DST:
|
case COL_DEF_DST:
|
||||||
case COL_RES_DST:
|
case COL_RES_DST:
|
||||||
case COL_UNRES_DST:
|
case COL_UNRES_DST:
|
||||||
switch (cf->cinfo.col_fmt[i + 1]) {
|
printf(" -> ");
|
||||||
|
|
||||||
case COL_DEF_SRC:
|
|
||||||
case COL_RES_SRC:
|
|
||||||
case COL_UNRES_SRC:
|
|
||||||
printf(" <- ");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
putchar(' ');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COL_DEF_DL_DST:
|
|
||||||
case COL_RES_DL_DST:
|
|
||||||
case COL_UNRES_DL_DST:
|
|
||||||
switch (cf->cinfo.col_fmt[i + 1]) {
|
|
||||||
|
|
||||||
case COL_DEF_DL_SRC:
|
|
||||||
case COL_RES_DL_SRC:
|
|
||||||
case COL_UNRES_DL_SRC:
|
|
||||||
printf(" <- ");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
putchar(' ');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case COL_DEF_NET_DST:
|
|
||||||
case COL_RES_NET_DST:
|
|
||||||
case COL_UNRES_NET_DST:
|
|
||||||
switch (cf->cinfo.col_fmt[i + 1]) {
|
|
||||||
|
|
||||||
case COL_DEF_NET_SRC:
|
|
||||||
case COL_RES_NET_SRC:
|
|
||||||
case COL_UNRES_NET_SRC:
|
|
||||||
printf(" <- ");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
putchar(' ');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COL_DEF_DL_SRC:
|
||||||
|
case COL_RES_DL_SRC:
|
||||||
|
case COL_UNRES_DL_SRC:
|
||||||
|
switch (cf->cinfo.col_fmt[i + 1]) {
|
||||||
|
|
||||||
|
case COL_DEF_DL_DST:
|
||||||
|
case COL_RES_DL_DST:
|
||||||
|
case COL_UNRES_DL_DST:
|
||||||
|
printf(" -> ");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
putchar(' ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COL_DEF_NET_SRC:
|
||||||
|
case COL_RES_NET_SRC:
|
||||||
|
case COL_UNRES_NET_SRC:
|
||||||
|
switch (cf->cinfo.col_fmt[i + 1]) {
|
||||||
|
|
||||||
|
case COL_DEF_NET_DST:
|
||||||
|
case COL_RES_NET_DST:
|
||||||
|
case COL_UNRES_NET_DST:
|
||||||
|
printf(" -> ");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
putchar(' ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COL_DEF_DST:
|
||||||
|
case COL_RES_DST:
|
||||||
|
case COL_UNRES_DST:
|
||||||
|
switch (cf->cinfo.col_fmt[i + 1]) {
|
||||||
|
|
||||||
|
case COL_DEF_SRC:
|
||||||
|
case COL_RES_SRC:
|
||||||
|
case COL_UNRES_SRC:
|
||||||
|
printf(" <- ");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
putchar(' ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COL_DEF_DL_DST:
|
||||||
|
case COL_RES_DL_DST:
|
||||||
|
case COL_UNRES_DL_DST:
|
||||||
|
switch (cf->cinfo.col_fmt[i + 1]) {
|
||||||
|
|
||||||
|
case COL_DEF_DL_SRC:
|
||||||
|
case COL_RES_DL_SRC:
|
||||||
|
case COL_UNRES_DL_SRC:
|
||||||
|
printf(" <- ");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
putchar(' ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COL_DEF_NET_DST:
|
||||||
|
case COL_RES_NET_DST:
|
||||||
|
case COL_UNRES_NET_DST:
|
||||||
|
switch (cf->cinfo.col_fmt[i + 1]) {
|
||||||
|
|
||||||
|
case COL_DEF_NET_SRC:
|
||||||
|
case COL_RES_NET_SRC:
|
||||||
|
case COL_UNRES_NET_SRC:
|
||||||
|
printf(" <- ");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
putchar(' ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
putchar(' ');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
putchar('\n');
|
|
||||||
}
|
|
||||||
if (print_hex) {
|
|
||||||
print_hex_data(stdout, print_args.format, edt);
|
|
||||||
putchar('\n');
|
|
||||||
}
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
if (print_hex) {
|
||||||
|
print_hex_data(stdout, print_args.format, edt);
|
||||||
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The ANSI C standard does not appear to *require* that a line-buffered
|
/* The ANSI C standard does not appear to *require* that a line-buffered
|
||||||
|
@ -2846,9 +2846,6 @@ wtap_dispatch_cb_print(guchar *user, const struct wtap_pkthdr *phdr,
|
||||||
show_print_file_io_error(errno);
|
show_print_file_io_error(errno);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
epan_dissect_free(edt);
|
|
||||||
|
|
||||||
clear_fdata(&fdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue