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:
Guy Harris 2004-05-31 07:52:27 +00:00
parent d6d7816485
commit 8a429808e7
1 changed files with 371 additions and 374 deletions

View File

@ -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