From 70d432c35724b23cfb1f6d80773b520523a65f75 Mon Sep 17 00:00:00 2001 From: David Perry Date: Sun, 20 Feb 2022 19:39:37 +0000 Subject: [PATCH] Remove editor modelines and .editorconfig exceptions from root files --- .editorconfig | 48 - capinfos.c | 2824 ++++++++-------- captype.c | 229 +- cfile.c | 17 +- cfile.h | 169 +- dftest.c | 197 +- file.c | 7995 +++++++++++++++++++++++----------------------- file.h | 13 - frame_tvbuff.c | 387 ++- frame_tvbuff.h | 13 - mergecap.c | 615 ++-- randpkt.c | 339 +- ringbuffer.c | 726 +++-- ringbuffer.h | 13 - sharkd.c | 956 +++--- sharkd_daemon.c | 617 ++-- sharkd_session.c | 6447 +++++++++++++++++++------------------ tfshark.c | 3305 ++++++++++--------- tshark.c | 7274 +++++++++++++++++++++-------------------- 19 files changed, 15965 insertions(+), 16219 deletions(-) diff --git a/.editorconfig b/.editorconfig index fc0aed1765..b06b9e1ee2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -71,51 +71,3 @@ indent_size = 8 [*.{c,cpp,h}] indent_style = space indent_size = 4 - -[{capinfos,captype,mergecap,tfshark,tshark}.c] -indent_size = 2 - -[{dftest,randpkt,trigcap}.c] -indent_style = tab -indent_size = tab - -[capture_stop_conditions.[ch]] -indent_size = 2 - -[cfile.[ch]] -indent_size = 2 - -[conditions.[ch]] -indent_size = 2 - -[file.[ch]] -indent_size = 2 - -[frame_tvbuff.[ch]] -indent_style = tab -indent_size = tab - -[pcapio.[ch]] -indent_size = 8 - -[ringbuffer.[ch]] -indent_size = 2 - -[randpkt_core.[ch]] -indent_style = tab -indent_size = tab - -[sharkd.c] -indent_size = 2 - -[sharkd_daemon.c] -indent_style = tab -indent_size = tab - -[sharkd_session.c] -indent_style = tab -indent_size = tab - -[version_info.[ch]] -indent_style = tab -indent_size = tab diff --git a/capinfos.c b/capinfos.c index 06572c626b..684dc79132 100644 --- a/capinfos.c +++ b/capinfos.c @@ -38,7 +38,6 @@ * (Previously a success status was always * returned if the -C option was not used). * - */ @@ -170,47 +169,47 @@ static guint num_decryption_secrets; * Otherwise, we have no idea. */ typedef enum { - IN_ORDER, - NOT_IN_ORDER, - ORDER_UNKNOWN + IN_ORDER, + NOT_IN_ORDER, + ORDER_UNKNOWN } order_t; typedef struct _capture_info { - const char *filename; - guint16 file_type; - wtap_compression_type compression_type; - int file_encap; - int file_tsprec; - wtap *wth; - gint64 filesize; - guint64 packet_bytes; - gboolean times_known; - nstime_t start_time; - int start_time_tsprec; - nstime_t stop_time; - int stop_time_tsprec; - guint32 packet_count; - gboolean snap_set; /* If set in capture file header */ - guint32 snaplen; /* value from the capture file header */ - guint32 snaplen_min_inferred; /* If caplen < len for 1 or more rcds */ - guint32 snaplen_max_inferred; /* ... */ - gboolean drops_known; - guint32 drop_count; + const char *filename; + guint16 file_type; + wtap_compression_type compression_type; + int file_encap; + int file_tsprec; + wtap *wth; + gint64 filesize; + guint64 packet_bytes; + gboolean times_known; + nstime_t start_time; + int start_time_tsprec; + nstime_t stop_time; + int stop_time_tsprec; + guint32 packet_count; + gboolean snap_set; /* If set in capture file header */ + guint32 snaplen; /* value from the capture file header */ + guint32 snaplen_min_inferred; /* If caplen < len for 1 or more rcds */ + guint32 snaplen_max_inferred; /* ... */ + gboolean drops_known; + guint32 drop_count; - nstime_t duration; - int duration_tsprec; - double packet_rate; - double packet_size; - double data_rate; /* in bytes/s */ - gboolean know_order; - order_t order; + nstime_t duration; + int duration_tsprec; + double packet_rate; + double packet_size; + double data_rate; /* in bytes/s */ + gboolean know_order; + order_t order; - int *encap_counts; /* array of per_packet encap counts; array has one entry per wtap_encap type */ + int *encap_counts; /* array of per_packet encap counts; array has one entry per wtap_encap type */ - guint num_interfaces; /* number of IDBs, and thus size of interface_packet_counts array */ - GArray *interface_packet_counts; /* array of per_packet interface_id counts; one entry per file IDB */ - guint32 pkt_interface_id_unknown; /* counts if packet interface_id didn't match a known one */ - GArray *idb_info_strings; /* array of IDB info strings */ + guint num_interfaces; /* number of IDBs, and thus size of interface_packet_counts array */ + GArray *interface_packet_counts; /* array of per_packet interface_id counts; one entry per file IDB */ + guint32 pkt_interface_id_unknown; /* counts if packet interface_id didn't match a known one */ + GArray *idb_info_strings; /* array of IDB info strings */ } capture_info; static char *decimal_point; @@ -218,368 +217,369 @@ static char *decimal_point; static void enable_all_infos(void) { - report_all_infos = TRUE; + report_all_infos = TRUE; - cap_file_type = TRUE; - cap_file_encap = TRUE; - cap_snaplen = TRUE; - cap_packet_count = TRUE; - cap_file_size = TRUE; - cap_comment = TRUE; - cap_file_more_info = TRUE; - cap_file_idb = TRUE; - cap_file_nrb = TRUE; - cap_file_dsb = TRUE; + cap_file_type = TRUE; + cap_file_encap = TRUE; + cap_snaplen = TRUE; + cap_packet_count = TRUE; + cap_file_size = TRUE; + cap_comment = TRUE; + cap_file_more_info = TRUE; + cap_file_idb = TRUE; + cap_file_nrb = TRUE; + cap_file_dsb = TRUE; - cap_data_size = TRUE; - cap_duration = TRUE; - cap_start_time = TRUE; - cap_end_time = TRUE; - cap_order = TRUE; + cap_data_size = TRUE; + cap_duration = TRUE; + cap_start_time = TRUE; + cap_end_time = TRUE; + cap_order = TRUE; - cap_data_rate_byte = TRUE; - cap_data_rate_bit = TRUE; - cap_packet_size = TRUE; - cap_packet_rate = TRUE; + cap_data_rate_byte = TRUE; + cap_data_rate_bit = TRUE; + cap_packet_size = TRUE; + cap_packet_rate = TRUE; - cap_file_hashes = TRUE; + cap_file_hashes = TRUE; } static void disable_all_infos(void) { - report_all_infos = FALSE; + report_all_infos = FALSE; - cap_file_type = FALSE; - cap_file_encap = FALSE; - cap_snaplen = FALSE; - cap_packet_count = FALSE; - cap_file_size = FALSE; - cap_comment = FALSE; - cap_file_more_info = FALSE; - cap_file_idb = FALSE; - cap_file_nrb = FALSE; - cap_file_dsb = FALSE; + cap_file_type = FALSE; + cap_file_encap = FALSE; + cap_snaplen = FALSE; + cap_packet_count = FALSE; + cap_file_size = FALSE; + cap_comment = FALSE; + cap_file_more_info = FALSE; + cap_file_idb = FALSE; + cap_file_nrb = FALSE; + cap_file_dsb = FALSE; - cap_data_size = FALSE; - cap_duration = FALSE; - cap_start_time = FALSE; - cap_end_time = FALSE; - cap_order = FALSE; + cap_data_size = FALSE; + cap_duration = FALSE; + cap_start_time = FALSE; + cap_end_time = FALSE; + cap_order = FALSE; - cap_data_rate_byte = FALSE; - cap_data_rate_bit = FALSE; - cap_packet_size = FALSE; - cap_packet_rate = FALSE; + cap_data_rate_byte = FALSE; + cap_data_rate_bit = FALSE; + cap_packet_size = FALSE; + cap_packet_rate = FALSE; - cap_file_hashes = FALSE; + cap_file_hashes = FALSE; } static const gchar * order_string(order_t order) { - switch (order) { + switch (order) { - case IN_ORDER: - return "True"; + case IN_ORDER: + return "True"; - case NOT_IN_ORDER: - return "False"; + case NOT_IN_ORDER: + return "False"; - case ORDER_UNKNOWN: - return "Unknown"; + case ORDER_UNKNOWN: + return "Unknown"; - default: - return "???"; /* "cannot happen" (the next step is "Profit!") */ - } + default: + return "???"; /* "cannot happen" (the next step is "Profit!") */ + } } static gchar * absolute_time_string(nstime_t *timer, int tsprecision, capture_info *cf_info) { - /* - * https://web.archive.org/web/20120513133703/http://www.idrbt.ac.in/publications/workingpapers/Working%20Paper%20No.%209.pdf - * - * says: - * - * A 64-bit Unix time would be safe for the indefinite future, as - * this variable would not overflow until 2**63 or - * 9,223,372,036,854,775,808 (over nine quintillion) seconds - * after the beginning of the Unix epoch - corresponding to - * GMT 15:30:08, Sunday, 4th December, 292,277,026,596. - * - * So, if we're displaying the time as YYYY-MM-DD HH:MM:SS.SSSSSSSSS, - * we'll have the buffer be large enouth for a date of the format - * 292277026596-MM-DD HH:MM:SS.SSSSSSSSS, which is the biggest value - * you'll get with a 64-bit time_t and a nanosecond-resolution - * fraction-of-a-second. - * - * That's 12+1+2+1+2+1+2+1+2+2+2+1+9+1, including the terminating - * \0, or 39. - * - * If we're displaying the time as epoch time, and the time is - * unsigned, 2^64-1 is 18446744073709551615, so the buffer has - * to be big enough for 18446744073709551615.999999999. That's - * 20+1+9+1, including the terminating '\0', or 31. If it's - * signed, 2^63 is 9223372036854775808, so the buffer has to - * be big enough for -9223372036854775808.999999999, which is - * again 20+1+9+1, or 31. - * - * So we go with 39. - */ - static gchar time_string_buf[39]; - struct tm *ti_tm; + /* + * https://web.archive.org/web/20120513133703/http://www.idrbt.ac.in/publications/workingpapers/Working%20Paper%20No.%209.pdf + * + * says: + * + * A 64-bit Unix time would be safe for the indefinite future, as + * this variable would not overflow until 2**63 or + * 9,223,372,036,854,775,808 (over nine quintillion) seconds + * after the beginning of the Unix epoch - corresponding to + * GMT 15:30:08, Sunday, 4th December, 292,277,026,596. + * + * So, if we're displaying the time as YYYY-MM-DD HH:MM:SS.SSSSSSSSS, + * we'll have the buffer be large enouth for a date of the format + * 292277026596-MM-DD HH:MM:SS.SSSSSSSSS, which is the biggest value + * you'll get with a 64-bit time_t and a nanosecond-resolution + * fraction-of-a-second. + * + * That's 12+1+2+1+2+1+2+1+2+2+2+1+9+1, including the terminating + * \0, or 39. + * + * If we're displaying the time as epoch time, and the time is + * unsigned, 2^64-1 is 18446744073709551615, so the buffer has + * to be big enough for 18446744073709551615.999999999. That's + * 20+1+9+1, including the terminating '\0', or 31. If it's + * signed, 2^63 is 9223372036854775808, so the buffer has to + * be big enough for -9223372036854775808.999999999, which is + * again 20+1+9+1, or 31. + * + * So we go with 39. + */ + static gchar time_string_buf[39]; + struct tm *ti_tm; - if (cf_info->times_known && cf_info->packet_count > 0) { - if (time_as_secs) { - switch (tsprecision) { + if (cf_info->times_known && cf_info->packet_count > 0) { + if (time_as_secs) { + switch (tsprecision) { - case WTAP_TSPREC_SEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64, - (gint64)timer->secs); - break; + case WTAP_TSPREC_SEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64, + (gint64)timer->secs); + break; - case WTAP_TSPREC_DSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%01d", - (gint64)timer->secs, - decimal_point, - timer->nsecs / 100000000); - break; + case WTAP_TSPREC_DSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%01d", + (gint64)timer->secs, + decimal_point, + timer->nsecs / 100000000); + break; - case WTAP_TSPREC_CSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%02d", - (gint64)timer->secs, - decimal_point, - timer->nsecs / 10000000); - break; + case WTAP_TSPREC_CSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%02d", + (gint64)timer->secs, + decimal_point, + timer->nsecs / 10000000); + break; - case WTAP_TSPREC_MSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%03d", - (gint64)timer->secs, - decimal_point, - timer->nsecs / 1000000); - break; + case WTAP_TSPREC_MSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%03d", + (gint64)timer->secs, + decimal_point, + timer->nsecs / 1000000); + break; - case WTAP_TSPREC_USEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%06d", - (gint64)timer->secs, - decimal_point, - timer->nsecs / 1000); - break; + case WTAP_TSPREC_USEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%06d", + (gint64)timer->secs, + decimal_point, + timer->nsecs / 1000); + break; - case WTAP_TSPREC_NSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%09d", - (gint64)timer->secs, - decimal_point, - timer->nsecs); - break; + case WTAP_TSPREC_NSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%09d", + (gint64)timer->secs, + decimal_point, + timer->nsecs); + break; - default: - snprintf(time_string_buf, sizeof time_string_buf, - "Unknown precision %d", - tsprecision); - break; - } - return time_string_buf; - } else { - ti_tm = localtime(&timer->secs); - if (ti_tm == NULL) { - snprintf(time_string_buf, sizeof time_string_buf, "Not representable"); - return time_string_buf; - } - switch (tsprecision) { + default: + snprintf(time_string_buf, sizeof time_string_buf, + "Unknown precision %d", + tsprecision); + break; + } + return time_string_buf; + } else { + ti_tm = localtime(&timer->secs); + if (ti_tm == NULL) { + snprintf(time_string_buf, sizeof time_string_buf, "Not representable"); + return time_string_buf; + } + switch (tsprecision) { - case WTAP_TSPREC_SEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%04d-%02d-%02d %02d:%02d:%02d", - ti_tm->tm_year + 1900, - ti_tm->tm_mon + 1, - ti_tm->tm_mday, - ti_tm->tm_hour, - ti_tm->tm_min, - ti_tm->tm_sec); - break; + case WTAP_TSPREC_SEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%04d-%02d-%02d %02d:%02d:%02d", + ti_tm->tm_year + 1900, + ti_tm->tm_mon + 1, + ti_tm->tm_mday, + ti_tm->tm_hour, + ti_tm->tm_min, + ti_tm->tm_sec); + break; - case WTAP_TSPREC_DSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%04d-%02d-%02d %02d:%02d:%02d%s%01d", - ti_tm->tm_year + 1900, - ti_tm->tm_mon + 1, - ti_tm->tm_mday, - ti_tm->tm_hour, - ti_tm->tm_min, - ti_tm->tm_sec, - decimal_point, - timer->nsecs / 100000000); - break; + case WTAP_TSPREC_DSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%04d-%02d-%02d %02d:%02d:%02d%s%01d", + ti_tm->tm_year + 1900, + ti_tm->tm_mon + 1, + ti_tm->tm_mday, + ti_tm->tm_hour, + ti_tm->tm_min, + ti_tm->tm_sec, + decimal_point, + timer->nsecs / 100000000); + break; - case WTAP_TSPREC_CSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%04d-%02d-%02d %02d:%02d:%02d%s%02d", - ti_tm->tm_year + 1900, - ti_tm->tm_mon + 1, - ti_tm->tm_mday, - ti_tm->tm_hour, - ti_tm->tm_min, - ti_tm->tm_sec, - decimal_point, - timer->nsecs / 10000000); - break; + case WTAP_TSPREC_CSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%04d-%02d-%02d %02d:%02d:%02d%s%02d", + ti_tm->tm_year + 1900, + ti_tm->tm_mon + 1, + ti_tm->tm_mday, + ti_tm->tm_hour, + ti_tm->tm_min, + ti_tm->tm_sec, + decimal_point, + timer->nsecs / 10000000); + break; - case WTAP_TSPREC_MSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%04d-%02d-%02d %02d:%02d:%02d%s%03d", - ti_tm->tm_year + 1900, - ti_tm->tm_mon + 1, - ti_tm->tm_mday, - ti_tm->tm_hour, - ti_tm->tm_min, - ti_tm->tm_sec, - decimal_point, - timer->nsecs / 1000000); - break; + case WTAP_TSPREC_MSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%04d-%02d-%02d %02d:%02d:%02d%s%03d", + ti_tm->tm_year + 1900, + ti_tm->tm_mon + 1, + ti_tm->tm_mday, + ti_tm->tm_hour, + ti_tm->tm_min, + ti_tm->tm_sec, + decimal_point, + timer->nsecs / 1000000); + break; - case WTAP_TSPREC_USEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%04d-%02d-%02d %02d:%02d:%02d%s%06d", - ti_tm->tm_year + 1900, - ti_tm->tm_mon + 1, - ti_tm->tm_mday, - ti_tm->tm_hour, - ti_tm->tm_min, - ti_tm->tm_sec, - decimal_point, - timer->nsecs / 1000); - break; + case WTAP_TSPREC_USEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%04d-%02d-%02d %02d:%02d:%02d%s%06d", + ti_tm->tm_year + 1900, + ti_tm->tm_mon + 1, + ti_tm->tm_mday, + ti_tm->tm_hour, + ti_tm->tm_min, + ti_tm->tm_sec, + decimal_point, + timer->nsecs / 1000); + break; - case WTAP_TSPREC_NSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%04d-%02d-%02d %02d:%02d:%02d%s%09d", - ti_tm->tm_year + 1900, - ti_tm->tm_mon + 1, - ti_tm->tm_mday, - ti_tm->tm_hour, - ti_tm->tm_min, - ti_tm->tm_sec, - decimal_point, - timer->nsecs); - break; + case WTAP_TSPREC_NSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%04d-%02d-%02d %02d:%02d:%02d%s%09d", + ti_tm->tm_year + 1900, + ti_tm->tm_mon + 1, + ti_tm->tm_mday, + ti_tm->tm_hour, + ti_tm->tm_min, + ti_tm->tm_sec, + decimal_point, + timer->nsecs); + break; - default: - snprintf(time_string_buf, sizeof time_string_buf, - "Unknown precision %d", - tsprecision); - break; - } - return time_string_buf; + default: + snprintf(time_string_buf, sizeof time_string_buf, + "Unknown precision %d", + tsprecision); + break; + } + return time_string_buf; + } } - } - snprintf(time_string_buf, sizeof time_string_buf, "n/a"); - return time_string_buf; + snprintf(time_string_buf, sizeof time_string_buf, "n/a"); + return time_string_buf; } static gchar * relative_time_string(nstime_t *timer, int tsprecision, capture_info *cf_info, gboolean want_seconds) { - const gchar *second = want_seconds ? " second" : ""; - const gchar *plural = want_seconds ? "s" : ""; - /* - * If we're displaying the time as epoch time, and the time is - * unsigned, 2^64-1 is 18446744073709551615, so the buffer has - * to be big enough for "18446744073709551615.999999999 seconds". - * That's 20+1+9+1+7+1, including the terminating '\0', or 39. - * If it'ssigned, 2^63 is 9223372036854775808, so the buffer has to - * be big enough for "-9223372036854775808.999999999 seconds", - * which is again 20+1+9+1+7+1, or 39. - */ - static gchar time_string_buf[39]; + const gchar *second = want_seconds ? " second" : ""; + const gchar *plural = want_seconds ? "s" : ""; + /* + * If we're displaying the time as epoch time, and the time is + * unsigned, 2^64-1 is 18446744073709551615, so the buffer has + * to be big enough for "18446744073709551615.999999999 seconds". + * That's 20+1+9+1+7+1, including the terminating '\0', or 39. + * If it'ssigned, 2^63 is 9223372036854775808, so the buffer has to + * be big enough for "-9223372036854775808.999999999 seconds", + * which is again 20+1+9+1+7+1, or 39. + */ + static gchar time_string_buf[39]; - if (cf_info->times_known && cf_info->packet_count > 0) { - switch (tsprecision) { + if (cf_info->times_known && cf_info->packet_count > 0) { + switch (tsprecision) { - case WTAP_TSPREC_SEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%s", - (gint64)timer->secs, - second, - timer->secs == 1 ? "" : plural); - break; + case WTAP_TSPREC_SEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%s", + (gint64)timer->secs, + second, + timer->secs == 1 ? "" : plural); + break; - case WTAP_TSPREC_DSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%01d%s%s", - (gint64)timer->secs, - decimal_point, - timer->nsecs / 100000000, - second, - (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); - break; + case WTAP_TSPREC_DSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%01d%s%s", + (gint64)timer->secs, + decimal_point, + timer->nsecs / 100000000, + second, + (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); + break; - case WTAP_TSPREC_CSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%02d%s%s", - (gint64)timer->secs, - decimal_point, - timer->nsecs / 10000000, - second, - (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); - break; + case WTAP_TSPREC_CSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%02d%s%s", + (gint64)timer->secs, + decimal_point, + timer->nsecs / 10000000, + second, + (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); + break; - case WTAP_TSPREC_MSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%03d%s%s", - (gint64)timer->secs, - decimal_point, - timer->nsecs / 1000000, - second, - (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); - break; + case WTAP_TSPREC_MSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%03d%s%s", + (gint64)timer->secs, + decimal_point, + timer->nsecs / 1000000, + second, + (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); + break; - case WTAP_TSPREC_USEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%06d%s%s", - (gint64)timer->secs, - decimal_point, - timer->nsecs / 1000, - second, - (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); - break; + case WTAP_TSPREC_USEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%06d%s%s", + (gint64)timer->secs, + decimal_point, + timer->nsecs / 1000, + second, + (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); + break; - case WTAP_TSPREC_NSEC: - snprintf(time_string_buf, sizeof time_string_buf, - "%"PRId64"%s%09d%s%s", - (gint64)timer->secs, - decimal_point, - timer->nsecs, - second, - (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); - break; + case WTAP_TSPREC_NSEC: + snprintf(time_string_buf, sizeof time_string_buf, + "%"PRId64"%s%09d%s%s", + (gint64)timer->secs, + decimal_point, + timer->nsecs, + second, + (timer->secs == 1 && timer->nsecs == 0) ? "" : plural); + break; - default: - snprintf(time_string_buf, sizeof time_string_buf, - "Unknown precision %d", - tsprecision); - break; + default: + snprintf(time_string_buf, sizeof time_string_buf, + "Unknown precision %d", + tsprecision); + break; + } + return time_string_buf; } - return time_string_buf; - } - snprintf(time_string_buf, sizeof time_string_buf, "n/a"); - return time_string_buf; + snprintf(time_string_buf, sizeof time_string_buf, "n/a"); + return time_string_buf; } -static void print_value(const gchar *text_p1, gint width, const gchar *text_p2, double value) { - if (value > 0.0) - printf("%s%.*f%s\n", text_p1, width, value, text_p2); - else - printf("%sn/a\n", text_p1); +static void print_value(const gchar *text_p1, gint width, const gchar *text_p2, double value) +{ + if (value > 0.0) + printf("%s%.*f%s\n", text_p1, width, value, text_p2); + else + printf("%sn/a\n", text_p1); } /* multi-line comments would conflict with the formatting that capinfos uses @@ -587,961 +587,962 @@ static void print_value(const gchar *text_p1, gint width, const gchar *text_p2, static void string_replace_newlines(gchar *str) { - gchar *p; + gchar *p; - if (str) { - p = str; - while (*p != '\0') { - if (*p == '\n') - *p = ' '; - if (*p == '\r') - *p = ' '; - p++; + if (str) { + p = str; + while (*p != '\0') { + if (*p == '\n') + *p = ' '; + if (*p == '\r') + *p = ' '; + p++; + } } - } } static void show_option_string(const char *prefix, const char *option_str) { - char *str; + char *str; - if (option_str != NULL && option_str[0] != '\0') { - str = g_strdup(option_str); - string_replace_newlines(str); - printf("%s%s\n", prefix, str); - g_free(str); - } + if (option_str != NULL && option_str[0] != '\0') { + str = g_strdup(option_str); + string_replace_newlines(str); + printf("%s%s\n", prefix, str); + g_free(str); + } } static void print_stats(const gchar *filename, capture_info *cf_info) { - const gchar *file_type_string, *file_encap_string; - gchar *size_string; + const gchar *file_type_string, *file_encap_string; + gchar *size_string; - /* Build printable strings for various stats */ - if (machine_readable) { - file_type_string = wtap_file_type_subtype_name(cf_info->file_type); - file_encap_string = wtap_encap_name(cf_info->file_encap); - } - else { - file_type_string = wtap_file_type_subtype_description(cf_info->file_type); - file_encap_string = wtap_encap_description(cf_info->file_encap); - } - - if (filename) printf ("File name: %s\n", filename); - if (cap_file_type) { - const char *compression_type_description; - compression_type_description = wtap_compression_type_description(cf_info->compression_type); - if (compression_type_description == NULL) - printf ("File type: %s\n", - file_type_string); - else - printf ("File type: %s (%s)\n", - file_type_string, compression_type_description); - } - if (cap_file_encap) { - printf ("File encapsulation: %s\n", file_encap_string); - if (cf_info->file_encap == WTAP_ENCAP_PER_PACKET) { - int i; - printf ("Encapsulation in use by packets (# of pkts):\n"); - for (i=0; iencap_counts[i] > 0) - printf(" %s (%d)\n", - wtap_encap_description(i), cf_info->encap_counts[i]); - } - } - } - if (cap_file_more_info) { - printf ("File timestamp precision: %s (%d)\n", - wtap_tsprec_string(cf_info->file_tsprec), cf_info->file_tsprec); - } - - if (cap_snaplen && cf_info->snap_set) - printf ("Packet size limit: file hdr: %u bytes\n", cf_info->snaplen); - else if (cap_snaplen && !cf_info->snap_set) - printf ("Packet size limit: file hdr: (not set)\n"); - if (cf_info->snaplen_max_inferred > 0) { - if (cf_info->snaplen_min_inferred == cf_info->snaplen_max_inferred) - printf ("Packet size limit: inferred: %u bytes\n", cf_info->snaplen_min_inferred); - else - printf ("Packet size limit: inferred: %u bytes - %u bytes (range)\n", - cf_info->snaplen_min_inferred, cf_info->snaplen_max_inferred); - } - if (cap_packet_count) { - printf ("Number of packets: "); + /* Build printable strings for various stats */ if (machine_readable) { - printf ("%u\n", cf_info->packet_count); - } else { - size_string = format_size(cf_info->packet_count, FORMAT_SIZE_UNIT_NONE, 0); - printf ("%s\n", size_string); - g_free(size_string); + file_type_string = wtap_file_type_subtype_name(cf_info->file_type); + file_encap_string = wtap_encap_name(cf_info->file_encap); } - } - if (cap_file_size) { - printf ("File size: "); - if (machine_readable) { - printf ("%" PRId64 " bytes\n", cf_info->filesize); - } else { - size_string = format_size(cf_info->filesize, FORMAT_SIZE_UNIT_BYTES, 0); - printf ("%s\n", size_string); - g_free(size_string); + else { + file_type_string = wtap_file_type_subtype_description(cf_info->file_type); + file_encap_string = wtap_encap_description(cf_info->file_encap); } - } - if (cap_data_size) { - printf ("Data size: "); - if (machine_readable) { - printf ("%" PRIu64 " bytes\n", cf_info->packet_bytes); - } else { - size_string = format_size(cf_info->packet_bytes, FORMAT_SIZE_UNIT_BYTES, 0); - printf ("%s\n", size_string); - g_free(size_string); + + if (filename) printf ("File name: %s\n", filename); + if (cap_file_type) { + const char *compression_type_description; + compression_type_description = wtap_compression_type_description(cf_info->compression_type); + if (compression_type_description == NULL) + printf ("File type: %s\n", + file_type_string); + else + printf ("File type: %s (%s)\n", + file_type_string, compression_type_description); } - } - if (cf_info->times_known) { - if (cap_duration) /* XXX - shorten to hh:mm:ss */ - printf("Capture duration: %s\n", relative_time_string(&cf_info->duration, cf_info->duration_tsprec, cf_info, TRUE)); - if (cap_start_time) - printf("First packet time: %s\n", absolute_time_string(&cf_info->start_time, cf_info->start_time_tsprec, cf_info)); - if (cap_end_time) - printf("Last packet time: %s\n", absolute_time_string(&cf_info->stop_time, cf_info->stop_time_tsprec, cf_info)); - if (cap_data_rate_byte) { - printf("Data byte rate: "); - if (machine_readable) { - print_value("", 2, " bytes/sec", cf_info->data_rate); - } else { - size_string = format_size((int64_t)cf_info->data_rate, FORMAT_SIZE_UNIT_BYTES_S, 0); - printf ("%s\n", size_string); - g_free(size_string); - } - } - if (cap_data_rate_bit) { - printf("Data bit rate: "); - if (machine_readable) { - print_value("", 2, " bits/sec", cf_info->data_rate*8); - } else { - size_string = format_size((int64_t)(cf_info->data_rate*8), FORMAT_SIZE_UNIT_BITS_S, 0); - printf ("%s\n", size_string); - g_free(size_string); - } - } - } - if (cap_packet_size) printf("Average packet size: %.2f bytes\n", cf_info->packet_size); - if (cf_info->times_known) { - if (cap_packet_rate) { - printf("Average packet rate: "); - if (machine_readable) { - print_value("", 2, " packets/sec", cf_info->packet_rate); - } else { - size_string = format_size((int64_t)cf_info->packet_rate, FORMAT_SIZE_UNIT_PACKETS_S, 0); - printf ("%s\n", size_string); - g_free(size_string); - } - } - } - if (cap_file_hashes) { - printf ("SHA256: %s\n", file_sha256); - printf ("RIPEMD160: %s\n", file_rmd160); - printf ("SHA1: %s\n", file_sha1); - } - if (cap_order) printf ("Strict time order: %s\n", order_string(cf_info->order)); - - gboolean has_multiple_sections = (wtap_file_get_num_shbs(cf_info->wth) > 1); - - for (guint section_number = 0; - section_number < wtap_file_get_num_shbs(cf_info->wth); - section_number++) { - wtap_block_t shb; - - // If we have more than one section, add headers for each section. - if (has_multiple_sections) - printf("Section %u:\n\n", section_number); - - shb = wtap_file_get_shb(cf_info->wth, section_number); - if (shb != NULL) { - if (cap_file_more_info) { - char *str; - - if (wtap_block_get_string_option_value(shb, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS) - show_option_string("Capture hardware: ", str); - if (wtap_block_get_string_option_value(shb, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS) - show_option_string("Capture oper-sys: ", str); - if (wtap_block_get_string_option_value(shb, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS) - show_option_string("Capture application: ", str); - } - if (cap_comment) { - unsigned int i; - char *str; - - for (i = 0; wtap_block_get_nth_string_option_value(shb, OPT_COMMENT, i, &str) == WTAP_OPTTYPE_SUCCESS; i++) { - show_option_string("Capture comment: ", str); + if (cap_file_encap) { + printf ("File encapsulation: %s\n", file_encap_string); + if (cf_info->file_encap == WTAP_ENCAP_PER_PACKET) { + int i; + printf ("Encapsulation in use by packets (# of pkts):\n"); + for (i=0; iencap_counts[i] > 0) + printf(" %s (%d)\n", + wtap_encap_description(i), cf_info->encap_counts[i]); + } } - } + } + if (cap_file_more_info) { + printf ("File timestamp precision: %s (%d)\n", + wtap_tsprec_string(cf_info->file_tsprec), cf_info->file_tsprec); + } - if (cap_file_idb && cf_info->num_interfaces != 0) { - guint i; - ws_assert(cf_info->num_interfaces == cf_info->idb_info_strings->len); - printf ("Number of interfaces in file: %u\n", cf_info->num_interfaces); - for (i = 0; i < cf_info->idb_info_strings->len; i++) { - gchar *s = g_array_index(cf_info->idb_info_strings, gchar*, i); - guint32 packet_count = 0; - if (i < cf_info->interface_packet_counts->len) - packet_count = g_array_index(cf_info->interface_packet_counts, guint32, i); - printf ("Interface #%u info:\n", i); - printf ("%s", s); - printf (" Number of packets = %u\n", packet_count); + if (cap_snaplen && cf_info->snap_set) + printf ("Packet size limit: file hdr: %u bytes\n", cf_info->snaplen); + else if (cap_snaplen && !cf_info->snap_set) + printf ("Packet size limit: file hdr: (not set)\n"); + if (cf_info->snaplen_max_inferred > 0) { + if (cf_info->snaplen_min_inferred == cf_info->snaplen_max_inferred) + printf ("Packet size limit: inferred: %u bytes\n", cf_info->snaplen_min_inferred); + else + printf ("Packet size limit: inferred: %u bytes - %u bytes (range)\n", + cf_info->snaplen_min_inferred, cf_info->snaplen_max_inferred); + } + if (cap_packet_count) { + printf ("Number of packets: "); + if (machine_readable) { + printf ("%u\n", cf_info->packet_count); + } else { + size_string = format_size(cf_info->packet_count, FORMAT_SIZE_UNIT_NONE, 0); + printf ("%s\n", size_string); + g_free(size_string); } - } } + if (cap_file_size) { + printf ("File size: "); + if (machine_readable) { + printf ("%" PRId64 " bytes\n", cf_info->filesize); + } else { + size_string = format_size(cf_info->filesize, FORMAT_SIZE_UNIT_BYTES, 0); + printf ("%s\n", size_string); + g_free(size_string); + } + } + if (cap_data_size) { + printf ("Data size: "); + if (machine_readable) { + printf ("%" PRIu64 " bytes\n", cf_info->packet_bytes); + } else { + size_string = format_size(cf_info->packet_bytes, FORMAT_SIZE_UNIT_BYTES, 0); + printf ("%s\n", size_string); + g_free(size_string); + } + } + if (cf_info->times_known) { + if (cap_duration) /* XXX - shorten to hh:mm:ss */ + printf("Capture duration: %s\n", relative_time_string(&cf_info->duration, cf_info->duration_tsprec, cf_info, TRUE)); + if (cap_start_time) + printf("First packet time: %s\n", absolute_time_string(&cf_info->start_time, cf_info->start_time_tsprec, cf_info)); + if (cap_end_time) + printf("Last packet time: %s\n", absolute_time_string(&cf_info->stop_time, cf_info->stop_time_tsprec, cf_info)); + if (cap_data_rate_byte) { + printf("Data byte rate: "); + if (machine_readable) { + print_value("", 2, " bytes/sec", cf_info->data_rate); + } else { + size_string = format_size((int64_t)cf_info->data_rate, FORMAT_SIZE_UNIT_BYTES_S, 0); + printf ("%s\n", size_string); + g_free(size_string); + } + } + if (cap_data_rate_bit) { + printf("Data bit rate: "); + if (machine_readable) { + print_value("", 2, " bits/sec", cf_info->data_rate*8); + } else { + size_string = format_size((int64_t)(cf_info->data_rate*8), FORMAT_SIZE_UNIT_BITS_S, 0); + printf ("%s\n", size_string); + g_free(size_string); + } + } + } + if (cap_packet_size) printf("Average packet size: %.2f bytes\n", cf_info->packet_size); + if (cf_info->times_known) { + if (cap_packet_rate) { + printf("Average packet rate: "); + if (machine_readable) { + print_value("", 2, " packets/sec", cf_info->packet_rate); + } else { + size_string = format_size((int64_t)cf_info->packet_rate, FORMAT_SIZE_UNIT_PACKETS_S, 0); + printf ("%s\n", size_string); + g_free(size_string); + } + } + } + if (cap_file_hashes) { + printf ("SHA256: %s\n", file_sha256); + printf ("RIPEMD160: %s\n", file_rmd160); + printf ("SHA1: %s\n", file_sha1); + } + if (cap_order) printf ("Strict time order: %s\n", order_string(cf_info->order)); - if (cap_file_nrb) { - if (num_ipv4_addresses != 0) - printf ("Number of resolved IPv4 addresses in file: %u\n", num_ipv4_addresses); - if (num_ipv6_addresses != 0) - printf ("Number of resolved IPv6 addresses in file: %u\n", num_ipv6_addresses); + gboolean has_multiple_sections = (wtap_file_get_num_shbs(cf_info->wth) > 1); + + for (guint section_number = 0; + section_number < wtap_file_get_num_shbs(cf_info->wth); + section_number++) { + wtap_block_t shb; + + // If we have more than one section, add headers for each section. + if (has_multiple_sections) + printf("Section %u:\n\n", section_number); + + shb = wtap_file_get_shb(cf_info->wth, section_number); + if (shb != NULL) { + if (cap_file_more_info) { + char *str; + + if (wtap_block_get_string_option_value(shb, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS) + show_option_string("Capture hardware: ", str); + if (wtap_block_get_string_option_value(shb, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS) + show_option_string("Capture oper-sys: ", str); + if (wtap_block_get_string_option_value(shb, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS) + show_option_string("Capture application: ", str); + } + if (cap_comment) { + unsigned int i; + char *str; + + for (i = 0; wtap_block_get_nth_string_option_value(shb, OPT_COMMENT, i, &str) == WTAP_OPTTYPE_SUCCESS; i++) { + show_option_string("Capture comment: ", str); + } + } + + if (cap_file_idb && cf_info->num_interfaces != 0) { + guint i; + ws_assert(cf_info->num_interfaces == cf_info->idb_info_strings->len); + printf ("Number of interfaces in file: %u\n", cf_info->num_interfaces); + for (i = 0; i < cf_info->idb_info_strings->len; i++) { + gchar *s = g_array_index(cf_info->idb_info_strings, gchar*, i); + guint32 packet_count = 0; + if (i < cf_info->interface_packet_counts->len) + packet_count = g_array_index(cf_info->interface_packet_counts, guint32, i); + printf ("Interface #%u info:\n", i); + printf ("%s", s); + printf (" Number of packets = %u\n", packet_count); + } + } + } + + if (cap_file_nrb) { + if (num_ipv4_addresses != 0) + printf ("Number of resolved IPv4 addresses in file: %u\n", num_ipv4_addresses); + if (num_ipv6_addresses != 0) + printf ("Number of resolved IPv6 addresses in file: %u\n", num_ipv6_addresses); + } + if (cap_file_dsb) { + if (num_decryption_secrets != 0) + printf ("Number of decryption secrets in file: %u\n", num_decryption_secrets); + } } - if (cap_file_dsb) { - if (num_decryption_secrets != 0) - printf ("Number of decryption secrets in file: %u\n", num_decryption_secrets); - } - } } static void putsep(void) { - if (field_separator) putchar(field_separator); + if (field_separator) putchar(field_separator); } static void putquote(void) { - if (quote_char) putchar(quote_char); + if (quote_char) putchar(quote_char); } static void print_stats_table_header_label(const gchar *label) { - putsep(); - putquote(); - printf("%s", label); - putquote(); + putsep(); + putquote(); + printf("%s", label); + putquote(); } static void print_stats_table_header(void) { - putquote(); - printf("File name"); - putquote(); + 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_file_more_info) print_stats_table_header_label("File time precision"); - if (cap_snaplen) { - print_stats_table_header_label("Packet size limit"); - print_stats_table_header_label("Packet size limit min (inferred)"); - print_stats_table_header_label("Packet size limit max (inferred)"); - } - 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)"); - if (cap_file_hashes) { - print_stats_table_header_label("SHA256"); - print_stats_table_header_label("RIPEMD160"); - print_stats_table_header_label("SHA1"); - } - if (cap_order) print_stats_table_header_label("Strict time order"); - if (cap_file_more_info) { - print_stats_table_header_label("Capture hardware"); - print_stats_table_header_label("Capture oper-sys"); - print_stats_table_header_label("Capture application"); - } - if (cap_comment) print_stats_table_header_label("Capture comment"); + if (cap_file_type) print_stats_table_header_label("File type"); + if (cap_file_encap) print_stats_table_header_label("File encapsulation"); + if (cap_file_more_info) print_stats_table_header_label("File time precision"); + if (cap_snaplen) { + print_stats_table_header_label("Packet size limit"); + print_stats_table_header_label("Packet size limit min (inferred)"); + print_stats_table_header_label("Packet size limit max (inferred)"); + } + 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)"); + if (cap_file_hashes) { + print_stats_table_header_label("SHA256"); + print_stats_table_header_label("RIPEMD160"); + print_stats_table_header_label("SHA1"); + } + if (cap_order) print_stats_table_header_label("Strict time order"); + if (cap_file_more_info) { + print_stats_table_header_label("Capture hardware"); + print_stats_table_header_label("Capture oper-sys"); + print_stats_table_header_label("Capture application"); + } + if (cap_comment) print_stats_table_header_label("Capture comment"); - printf("\n"); + printf("\n"); } static void print_stats_table(const gchar *filename, capture_info *cf_info) { - const gchar *file_type_string, *file_encap_string; + const gchar *file_type_string, *file_encap_string; - /* Build printable strings for various stats */ - file_type_string = wtap_file_type_subtype_name(cf_info->file_type); - file_encap_string = wtap_encap_name(cf_info->file_encap); + /* Build printable strings for various stats */ + file_type_string = wtap_file_type_subtype_name(cf_info->file_type); + file_encap_string = wtap_encap_name(cf_info->file_encap); - if (filename) { - putquote(); - printf("%s", filename); - putquote(); - } - - if (cap_file_type) { - putsep(); - putquote(); - printf("%s", file_type_string); - putquote(); - } - - /* ToDo: If WTAP_ENCAP_PER_PACKET, show the list of encapsulations encountered; - * Output a line for each different encap with all fields repeated except - * the encapsulation field which has "Per Packet: ..." for each - * encapsulation type seen ? - */ - if (cap_file_encap) { - putsep(); - putquote(); - printf("%s", file_encap_string); - putquote(); - } - - if (cap_file_more_info) { - putsep(); - putquote(); - printf("%s", wtap_tsprec_string(cf_info->file_tsprec)); - putquote(); - } - - if (cap_snaplen) { - putsep(); - putquote(); - if (cf_info->snap_set) - printf("%u", cf_info->snaplen); - else - printf("(not set)"); - putquote(); - if (cf_info->snaplen_max_inferred > 0) { - putsep(); - putquote(); - printf("%u", cf_info->snaplen_min_inferred); - putquote(); - putsep(); - putquote(); - printf("%u", cf_info->snaplen_max_inferred); - putquote(); - } - else { - putsep(); - putquote(); - printf("n/a"); - putquote(); - putsep(); - putquote(); - printf("n/a"); - putquote(); - } - } - - if (cap_packet_count) { - putsep(); - putquote(); - printf("%u", cf_info->packet_count); - putquote(); - } - - if (cap_file_size) { - putsep(); - putquote(); - printf("%" PRId64, cf_info->filesize); - putquote(); - } - - if (cap_data_size) { - putsep(); - putquote(); - printf("%" PRIu64, cf_info->packet_bytes); - putquote(); - } - - if (cap_duration) { - putsep(); - putquote(); - printf("%s", relative_time_string(&cf_info->duration, cf_info->duration_tsprec, cf_info, FALSE)); - putquote(); - } - - if (cap_start_time) { - putsep(); - putquote(); - printf("%s", absolute_time_string(&cf_info->start_time, cf_info->start_time_tsprec, cf_info)); - putquote(); - } - - if (cap_end_time) { - putsep(); - putquote(); - printf("%s", absolute_time_string(&cf_info->stop_time, cf_info->stop_time_tsprec, cf_info)); - putquote(); - } - - if (cap_data_rate_byte) { - putsep(); - putquote(); - if (cf_info->times_known) - printf("%.2f", cf_info->data_rate); - else - printf("n/a"); - putquote(); - } - - if (cap_data_rate_bit) { - putsep(); - putquote(); - if (cf_info->times_known) - printf("%.2f", cf_info->data_rate*8); - else - printf("n/a"); - putquote(); - } - - if (cap_packet_size) { - putsep(); - putquote(); - printf("%.2f", cf_info->packet_size); - putquote(); - } - - if (cap_packet_rate) { - putsep(); - putquote(); - if (cf_info->times_known) - printf("%.2f", cf_info->packet_rate); - else - printf("n/a"); - putquote(); - } - - if (cap_file_hashes) { - putsep(); - putquote(); - printf("%s", file_sha256); - putquote(); - - putsep(); - putquote(); - printf("%s", file_rmd160); - putquote(); - - putsep(); - putquote(); - printf("%s", file_sha1); - putquote(); - } - - if (cap_order) { - putsep(); - putquote(); - printf("%s", order_string(cf_info->order)); - putquote(); - } - - for (guint section_number = 0; - section_number < wtap_file_get_num_shbs(cf_info->wth); - section_number++) { - wtap_block_t shb; - - shb = wtap_file_get_shb(cf_info->wth, section_number); - if (cap_file_more_info) { - char *str; - - putsep(); - putquote(); - if (wtap_block_get_string_option_value(shb, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS) { - printf("%s", str); - } - putquote(); - - putsep(); - putquote(); - if (wtap_block_get_string_option_value(shb, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS) { - printf("%s", str); - } - putquote(); - - putsep(); - putquote(); - if (wtap_block_get_string_option_value(shb, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS) { - printf("%s", str); - } - putquote(); + if (filename) { + putquote(); + printf("%s", filename); + putquote(); } - /* - * One might argue that the following is silly to put into a table format, - * but oh well note that there may be *more than one* of each of these types - * of options. To mitigate some of the potential silliness the if(cap_comment) - * block is moved AFTER the if(cap_file_more_info) block. This will make any - * comments the last item(s) in each row. We now have a new -K option to - * disable cap_comment to more easily manage the potential silliness. - * Potential silliness includes multiple comments (therefore resulting in - * more than one additional column and/or comments with embeded newlines - * and/or possible delimiters). + if (cap_file_type) { + putsep(); + putquote(); + printf("%s", file_type_string); + putquote(); + } + + /* ToDo: If WTAP_ENCAP_PER_PACKET, show the list of encapsulations encountered; + * Output a line for each different encap with all fields repeated except + * the encapsulation field which has "Per Packet: ..." for each + * encapsulation type seen ? */ - if (cap_comment) { - unsigned int i; - char *opt_comment; - gboolean have_cap = FALSE; - - for (i = 0; wtap_block_get_nth_string_option_value(shb, OPT_COMMENT, i, &opt_comment) == WTAP_OPTTYPE_SUCCESS; i++) { - have_cap = TRUE; + if (cap_file_encap) { putsep(); putquote(); - printf("%s", opt_comment); + printf("%s", file_encap_string); putquote(); - } - if(!have_cap) { - /* Maintain column alignment when we have no OPT_COMMENT */ - putsep(); - putquote(); - putquote(); - } } - } + if (cap_file_more_info) { + putsep(); + putquote(); + printf("%s", wtap_tsprec_string(cf_info->file_tsprec)); + putquote(); + } - printf("\n"); + if (cap_snaplen) { + putsep(); + putquote(); + if (cf_info->snap_set) + printf("%u", cf_info->snaplen); + else + printf("(not set)"); + putquote(); + if (cf_info->snaplen_max_inferred > 0) { + putsep(); + putquote(); + printf("%u", cf_info->snaplen_min_inferred); + putquote(); + putsep(); + putquote(); + printf("%u", cf_info->snaplen_max_inferred); + putquote(); + } + else { + putsep(); + putquote(); + printf("n/a"); + putquote(); + putsep(); + putquote(); + printf("n/a"); + putquote(); + } + } + + if (cap_packet_count) { + putsep(); + putquote(); + printf("%u", cf_info->packet_count); + putquote(); + } + + if (cap_file_size) { + putsep(); + putquote(); + printf("%" PRId64, cf_info->filesize); + putquote(); + } + + if (cap_data_size) { + putsep(); + putquote(); + printf("%" PRIu64, cf_info->packet_bytes); + putquote(); + } + + if (cap_duration) { + putsep(); + putquote(); + printf("%s", relative_time_string(&cf_info->duration, cf_info->duration_tsprec, cf_info, FALSE)); + putquote(); + } + + if (cap_start_time) { + putsep(); + putquote(); + printf("%s", absolute_time_string(&cf_info->start_time, cf_info->start_time_tsprec, cf_info)); + putquote(); + } + + if (cap_end_time) { + putsep(); + putquote(); + printf("%s", absolute_time_string(&cf_info->stop_time, cf_info->stop_time_tsprec, cf_info)); + putquote(); + } + + if (cap_data_rate_byte) { + putsep(); + putquote(); + if (cf_info->times_known) + printf("%.2f", cf_info->data_rate); + else + printf("n/a"); + putquote(); + } + + if (cap_data_rate_bit) { + putsep(); + putquote(); + if (cf_info->times_known) + printf("%.2f", cf_info->data_rate*8); + else + printf("n/a"); + putquote(); + } + + if (cap_packet_size) { + putsep(); + putquote(); + printf("%.2f", cf_info->packet_size); + putquote(); + } + + if (cap_packet_rate) { + putsep(); + putquote(); + if (cf_info->times_known) + printf("%.2f", cf_info->packet_rate); + else + printf("n/a"); + putquote(); + } + + if (cap_file_hashes) { + putsep(); + putquote(); + printf("%s", file_sha256); + putquote(); + + putsep(); + putquote(); + printf("%s", file_rmd160); + putquote(); + + putsep(); + putquote(); + printf("%s", file_sha1); + putquote(); + } + + if (cap_order) { + putsep(); + putquote(); + printf("%s", order_string(cf_info->order)); + putquote(); + } + + for (guint section_number = 0; + section_number < wtap_file_get_num_shbs(cf_info->wth); + section_number++) { + wtap_block_t shb; + + shb = wtap_file_get_shb(cf_info->wth, section_number); + if (cap_file_more_info) { + char *str; + + putsep(); + putquote(); + if (wtap_block_get_string_option_value(shb, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS) { + printf("%s", str); + } + putquote(); + + putsep(); + putquote(); + if (wtap_block_get_string_option_value(shb, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS) { + printf("%s", str); + } + putquote(); + + putsep(); + putquote(); + if (wtap_block_get_string_option_value(shb, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS) { + printf("%s", str); + } + putquote(); + } + + /* + * One might argue that the following is silly to put into a table format, + * but oh well note that there may be *more than one* of each of these types + * of options. To mitigate some of the potential silliness the if(cap_comment) + * block is moved AFTER the if(cap_file_more_info) block. This will make any + * comments the last item(s) in each row. We now have a new -K option to + * disable cap_comment to more easily manage the potential silliness. + * Potential silliness includes multiple comments (therefore resulting in + * more than one additional column and/or comments with embeded newlines + * and/or possible delimiters). + */ + if (cap_comment) { + unsigned int i; + char *opt_comment; + gboolean have_cap = FALSE; + + for (i = 0; wtap_block_get_nth_string_option_value(shb, OPT_COMMENT, i, &opt_comment) == WTAP_OPTTYPE_SUCCESS; i++) { + have_cap = TRUE; + putsep(); + putquote(); + printf("%s", opt_comment); + putquote(); + } + if(!have_cap) { + /* Maintain column alignment when we have no OPT_COMMENT */ + putsep(); + putquote(); + putquote(); + } + } + + } + + printf("\n"); } static void cleanup_capture_info(capture_info *cf_info) { - guint i; - ws_assert(cf_info != NULL); + guint i; + ws_assert(cf_info != NULL); - g_free(cf_info->encap_counts); - cf_info->encap_counts = NULL; + g_free(cf_info->encap_counts); + cf_info->encap_counts = NULL; - g_array_free(cf_info->interface_packet_counts, TRUE); - cf_info->interface_packet_counts = NULL; + g_array_free(cf_info->interface_packet_counts, TRUE); + cf_info->interface_packet_counts = NULL; - if (cf_info->idb_info_strings) { - for (i = 0; i < cf_info->idb_info_strings->len; i++) { - gchar *s = g_array_index(cf_info->idb_info_strings, gchar*, i); - g_free(s); + if (cf_info->idb_info_strings) { + for (i = 0; i < cf_info->idb_info_strings->len; i++) { + gchar *s = g_array_index(cf_info->idb_info_strings, gchar*, i); + g_free(s); + } + g_array_free(cf_info->idb_info_strings, TRUE); } - g_array_free(cf_info->idb_info_strings, TRUE); - } - cf_info->idb_info_strings = NULL; + cf_info->idb_info_strings = NULL; } static void count_ipv4_address(const guint addr _U_, const gchar *name _U_) { - num_ipv4_addresses++; + num_ipv4_addresses++; } static void count_ipv6_address(const void *addrp _U_, const gchar *name _U_) { - num_ipv6_addresses++; + num_ipv6_addresses++; } static void count_decryption_secret(guint32 secrets_type _U_, const void *secrets _U_, guint size _U_) { - /* XXX - count them based on the secrets type (which is an opaque code, - not a small integer)? */ - num_decryption_secrets++; + /* XXX - count them based on the secrets type (which is an opaque code, + not a small integer)? */ + num_decryption_secrets++; } static void -hash_to_str(const unsigned char *hash, size_t length, char *str) { - int i; +hash_to_str(const unsigned char *hash, size_t length, char *str) +{ + int i; - for (i = 0; i < (int) length; i++) { - snprintf(str+(i*2), 3, "%02x", hash[i]); - } + for (i = 0; i < (int) length; i++) { + snprintf(str+(i*2), 3, "%02x", hash[i]); + } } static void calculate_hashes(const char *filename) { - FILE *fh; - size_t hash_bytes; + FILE *fh; + size_t hash_bytes; - (void) g_strlcpy(file_sha256, "", HASH_STR_SIZE); - (void) g_strlcpy(file_rmd160, "", HASH_STR_SIZE); - (void) g_strlcpy(file_sha1, "", HASH_STR_SIZE); + (void) g_strlcpy(file_sha256, "", HASH_STR_SIZE); + (void) g_strlcpy(file_rmd160, "", HASH_STR_SIZE); + (void) g_strlcpy(file_sha1, "", HASH_STR_SIZE); - if (cap_file_hashes) { - fh = ws_fopen(filename, "rb"); - if (fh && hd) { - while((hash_bytes = fread(hash_buf, 1, HASH_BUF_SIZE, fh)) > 0) { - gcry_md_write(hd, hash_buf, hash_bytes); - } - gcry_md_final(hd); - hash_to_str(gcry_md_read(hd, GCRY_MD_SHA256), HASH_SIZE_SHA256, file_sha256); - hash_to_str(gcry_md_read(hd, GCRY_MD_RMD160), HASH_SIZE_RMD160, file_rmd160); - hash_to_str(gcry_md_read(hd, GCRY_MD_SHA1), HASH_SIZE_SHA1, file_sha1); + if (cap_file_hashes) { + fh = ws_fopen(filename, "rb"); + if (fh && hd) { + while((hash_bytes = fread(hash_buf, 1, HASH_BUF_SIZE, fh)) > 0) { + gcry_md_write(hd, hash_buf, hash_bytes); + } + gcry_md_final(hd); + hash_to_str(gcry_md_read(hd, GCRY_MD_SHA256), HASH_SIZE_SHA256, file_sha256); + hash_to_str(gcry_md_read(hd, GCRY_MD_RMD160), HASH_SIZE_RMD160, file_rmd160); + hash_to_str(gcry_md_read(hd, GCRY_MD_SHA1), HASH_SIZE_SHA1, file_sha1); + } + if (fh) fclose(fh); + if (hd) gcry_md_reset(hd); } - if (fh) fclose(fh); - if (hd) gcry_md_reset(hd); - } } static int process_cap_file(const char *filename, gboolean need_separator) { - int status = 0; - int err; - gchar *err_info; - gint64 size; - gint64 data_offset; + int status = 0; + int err; + gchar *err_info; + gint64 size; + gint64 data_offset; - guint32 packet = 0; - gint64 bytes = 0; - guint32 snaplen_min_inferred = 0xffffffff; - guint32 snaplen_max_inferred = 0; - wtap_rec rec; - Buffer buf; - capture_info cf_info; - gboolean have_times = TRUE; - nstime_t start_time; - int start_time_tsprec; - nstime_t stop_time; - int stop_time_tsprec; - nstime_t cur_time; - nstime_t prev_time; - gboolean know_order = FALSE; - order_t order = IN_ORDER; - guint i; - wtapng_iface_descriptions_t *idb_info; + guint32 packet = 0; + gint64 bytes = 0; + guint32 snaplen_min_inferred = 0xffffffff; + guint32 snaplen_max_inferred = 0; + wtap_rec rec; + Buffer buf; + capture_info cf_info; + gboolean have_times = TRUE; + nstime_t start_time; + int start_time_tsprec; + nstime_t stop_time; + int stop_time_tsprec; + nstime_t cur_time; + nstime_t prev_time; + gboolean know_order = FALSE; + order_t order = IN_ORDER; + guint i; + wtapng_iface_descriptions_t *idb_info; - cf_info.wth = wtap_open_offline(filename, WTAP_TYPE_AUTO, &err, &err_info, FALSE); - if (!cf_info.wth) { - cfile_open_failure_message(filename, err, err_info); - return 2; - } - - /* - * Calculate the checksums. Do this after wtap_open_offline, so we don't - * bother calculating them for files that are not known capture types - * where we wouldn't print them anyway. - */ - calculate_hashes(filename); - - if (need_separator && long_report) { - printf("\n"); - } - - nstime_set_zero(&start_time); - start_time_tsprec = WTAP_TSPREC_UNKNOWN; - nstime_set_zero(&stop_time); - stop_time_tsprec = WTAP_TSPREC_UNKNOWN; - nstime_set_zero(&cur_time); - nstime_set_zero(&prev_time); - - cf_info.encap_counts = g_new0(int,WTAP_NUM_ENCAP_TYPES); - - idb_info = wtap_file_get_idb_info(cf_info.wth); - - ws_assert(idb_info->interface_data != NULL); - - cf_info.num_interfaces = idb_info->interface_data->len; - cf_info.interface_packet_counts = g_array_sized_new(FALSE, TRUE, sizeof(guint32), cf_info.num_interfaces); - g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces); - cf_info.pkt_interface_id_unknown = 0; - - g_free(idb_info); - idb_info = NULL; - - /* Register callbacks for new name<->address maps from the file and - decryption secrets from the file. */ - wtap_set_cb_new_ipv4(cf_info.wth, count_ipv4_address); - wtap_set_cb_new_ipv6(cf_info.wth, count_ipv6_address); - wtap_set_cb_new_secrets(cf_info.wth, count_decryption_secret); - - /* Zero out the counters for the callbacks. */ - num_ipv4_addresses = 0; - num_ipv6_addresses = 0; - num_decryption_secrets = 0; - - /* Tally up data that we need to parse through the file to find */ - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - while (wtap_read(cf_info.wth, &rec, &buf, &err, &err_info, &data_offset)) { - if (rec.presence_flags & WTAP_HAS_TS) { - prev_time = cur_time; - cur_time = rec.ts; - if (packet == 0) { - start_time = rec.ts; - start_time_tsprec = rec.tsprec; - stop_time = rec.ts; - stop_time_tsprec = rec.tsprec; - prev_time = rec.ts; - } - if (nstime_cmp(&cur_time, &prev_time) < 0) { - order = NOT_IN_ORDER; - } - if (nstime_cmp(&cur_time, &start_time) < 0) { - start_time = cur_time; - start_time_tsprec = rec.tsprec; - } - if (nstime_cmp(&cur_time, &stop_time) > 0) { - stop_time = cur_time; - stop_time_tsprec = rec.tsprec; - } - } else { - have_times = FALSE; /* at least one packet has no time stamp */ - if (order != NOT_IN_ORDER) - order = ORDER_UNKNOWN; + cf_info.wth = wtap_open_offline(filename, WTAP_TYPE_AUTO, &err, &err_info, FALSE); + if (!cf_info.wth) { + cfile_open_failure_message(filename, err, err_info); + return 2; } - if (rec.rec_type == REC_TYPE_PACKET) { - bytes += rec.rec_header.packet_header.len; - packet++; + /* + * Calculate the checksums. Do this after wtap_open_offline, so we don't + * bother calculating them for files that are not known capture types + * where we wouldn't print them anyway. + */ + calculate_hashes(filename); - /* If caplen < len for a rcd, then presumably */ - /* 'Limit packet capture length' was done for this rcd. */ - /* Keep track as to the min/max actual snapshot lengths */ - /* seen for this file. */ - if (rec.rec_header.packet_header.caplen < rec.rec_header.packet_header.len) { - if (rec.rec_header.packet_header.caplen < snaplen_min_inferred) - snaplen_min_inferred = rec.rec_header.packet_header.caplen; - if (rec.rec_header.packet_header.caplen > snaplen_max_inferred) - snaplen_max_inferred = rec.rec_header.packet_header.caplen; - } - - if ((rec.rec_header.packet_header.pkt_encap > 0) && - (rec.rec_header.packet_header.pkt_encap < WTAP_NUM_ENCAP_TYPES)) { - cf_info.encap_counts[rec.rec_header.packet_header.pkt_encap] += 1; - } else { - fprintf(stderr, "capinfos: Unknown packet encapsulation %d in frame %u of file \"%s\"\n", - rec.rec_header.packet_header.pkt_encap, packet, filename); - } - - /* Packet interface_id info */ - if (rec.presence_flags & WTAP_HAS_INTERFACE_ID) { - /* cf_info.num_interfaces is size, not index, so it's one more than max index */ - if (rec.rec_header.packet_header.interface_id >= cf_info.num_interfaces) { - /* - * OK, re-fetch the number of interfaces, as there might have - * been an interface that was in the middle of packets, and - * grow the array to be big enough for the new number of - * interfaces. - */ - idb_info = wtap_file_get_idb_info(cf_info.wth); - - cf_info.num_interfaces = idb_info->interface_data->len; - g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces); - - g_free(idb_info); - idb_info = NULL; - } - if (rec.rec_header.packet_header.interface_id < cf_info.num_interfaces) { - g_array_index(cf_info.interface_packet_counts, guint32, - rec.rec_header.packet_header.interface_id) += 1; - } - else { - cf_info.pkt_interface_id_unknown += 1; - } - } - else { - /* it's for interface_id 0 */ - if (cf_info.num_interfaces != 0) { - g_array_index(cf_info.interface_packet_counts, guint32, 0) += 1; - } - else { - cf_info.pkt_interface_id_unknown += 1; - } - } + if (need_separator && long_report) { + printf("\n"); } - wtap_rec_reset(&rec); - } /* while */ - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); + nstime_set_zero(&start_time); + start_time_tsprec = WTAP_TSPREC_UNKNOWN; + nstime_set_zero(&stop_time); + stop_time_tsprec = WTAP_TSPREC_UNKNOWN; + nstime_set_zero(&cur_time); + nstime_set_zero(&prev_time); - /* - * Get IDB info strings. - * We do this at the end, so we can get information for all IDBs in - * the file, even those that come after packet records, and so that - * we get, for example, a count of the number of statistics entries - * for each interface as of the *end* of the file. - */ - idb_info = wtap_file_get_idb_info(cf_info.wth); + cf_info.encap_counts = g_new0(int,WTAP_NUM_ENCAP_TYPES); - cf_info.idb_info_strings = g_array_sized_new(FALSE, FALSE, sizeof(gchar*), cf_info.num_interfaces); - cf_info.num_interfaces = idb_info->interface_data->len; - for (i = 0; i < cf_info.num_interfaces; i++) { - const wtap_block_t if_descr = g_array_index(idb_info->interface_data, wtap_block_t, i); - gchar *s = wtap_get_debug_if_descr(if_descr, 21, "\n"); - g_array_append_val(cf_info.idb_info_strings, s); - } + idb_info = wtap_file_get_idb_info(cf_info.wth); - g_free(idb_info); - idb_info = NULL; + ws_assert(idb_info->interface_data != NULL); - if (err != 0) { - fprintf(stderr, - "capinfos: An error occurred after reading %u packets from \"%s\".\n", - packet, filename); - cfile_read_failure_message(filename, err, err_info); - if (err == WTAP_ERR_SHORT_READ) { - /* Don't give up completely with this one. */ - status = 1; + cf_info.num_interfaces = idb_info->interface_data->len; + cf_info.interface_packet_counts = g_array_sized_new(FALSE, TRUE, sizeof(guint32), cf_info.num_interfaces); + g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces); + cf_info.pkt_interface_id_unknown = 0; + + g_free(idb_info); + idb_info = NULL; + + /* Register callbacks for new name<->address maps from the file and + decryption secrets from the file. */ + wtap_set_cb_new_ipv4(cf_info.wth, count_ipv4_address); + wtap_set_cb_new_ipv6(cf_info.wth, count_ipv6_address); + wtap_set_cb_new_secrets(cf_info.wth, count_decryption_secret); + + /* Zero out the counters for the callbacks. */ + num_ipv4_addresses = 0; + num_ipv6_addresses = 0; + num_decryption_secrets = 0; + + /* Tally up data that we need to parse through the file to find */ + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + while (wtap_read(cf_info.wth, &rec, &buf, &err, &err_info, &data_offset)) { + if (rec.presence_flags & WTAP_HAS_TS) { + prev_time = cur_time; + cur_time = rec.ts; + if (packet == 0) { + start_time = rec.ts; + start_time_tsprec = rec.tsprec; + stop_time = rec.ts; + stop_time_tsprec = rec.tsprec; + prev_time = rec.ts; + } + if (nstime_cmp(&cur_time, &prev_time) < 0) { + order = NOT_IN_ORDER; + } + if (nstime_cmp(&cur_time, &start_time) < 0) { + start_time = cur_time; + start_time_tsprec = rec.tsprec; + } + if (nstime_cmp(&cur_time, &stop_time) > 0) { + stop_time = cur_time; + stop_time_tsprec = rec.tsprec; + } + } else { + have_times = FALSE; /* at least one packet has no time stamp */ + if (order != NOT_IN_ORDER) + order = ORDER_UNKNOWN; + } + + if (rec.rec_type == REC_TYPE_PACKET) { + bytes += rec.rec_header.packet_header.len; + packet++; + + /* If caplen < len for a rcd, then presumably */ + /* 'Limit packet capture length' was done for this rcd. */ + /* Keep track as to the min/max actual snapshot lengths */ + /* seen for this file. */ + if (rec.rec_header.packet_header.caplen < rec.rec_header.packet_header.len) { + if (rec.rec_header.packet_header.caplen < snaplen_min_inferred) + snaplen_min_inferred = rec.rec_header.packet_header.caplen; + if (rec.rec_header.packet_header.caplen > snaplen_max_inferred) + snaplen_max_inferred = rec.rec_header.packet_header.caplen; + } + + if ((rec.rec_header.packet_header.pkt_encap > 0) && + (rec.rec_header.packet_header.pkt_encap < WTAP_NUM_ENCAP_TYPES)) { + cf_info.encap_counts[rec.rec_header.packet_header.pkt_encap] += 1; + } else { + fprintf(stderr, "capinfos: Unknown packet encapsulation %d in frame %u of file \"%s\"\n", + rec.rec_header.packet_header.pkt_encap, packet, filename); + } + + /* Packet interface_id info */ + if (rec.presence_flags & WTAP_HAS_INTERFACE_ID) { + /* cf_info.num_interfaces is size, not index, so it's one more than max index */ + if (rec.rec_header.packet_header.interface_id >= cf_info.num_interfaces) { + /* + * OK, re-fetch the number of interfaces, as there might have + * been an interface that was in the middle of packets, and + * grow the array to be big enough for the new number of + * interfaces. + */ + idb_info = wtap_file_get_idb_info(cf_info.wth); + + cf_info.num_interfaces = idb_info->interface_data->len; + g_array_set_size(cf_info.interface_packet_counts, cf_info.num_interfaces); + + g_free(idb_info); + idb_info = NULL; + } + if (rec.rec_header.packet_header.interface_id < cf_info.num_interfaces) { + g_array_index(cf_info.interface_packet_counts, guint32, + rec.rec_header.packet_header.interface_id) += 1; + } + else { + cf_info.pkt_interface_id_unknown += 1; + } + } + else { + /* it's for interface_id 0 */ + if (cf_info.num_interfaces != 0) { + g_array_index(cf_info.interface_packet_counts, guint32, 0) += 1; + } + else { + cf_info.pkt_interface_id_unknown += 1; + } + } + } + + wtap_rec_reset(&rec); + } /* while */ + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + + /* + * Get IDB info strings. + * We do this at the end, so we can get information for all IDBs in + * the file, even those that come after packet records, and so that + * we get, for example, a count of the number of statistics entries + * for each interface as of the *end* of the file. + */ + idb_info = wtap_file_get_idb_info(cf_info.wth); + + cf_info.idb_info_strings = g_array_sized_new(FALSE, FALSE, sizeof(gchar*), cf_info.num_interfaces); + cf_info.num_interfaces = idb_info->interface_data->len; + for (i = 0; i < cf_info.num_interfaces; i++) { + const wtap_block_t if_descr = g_array_index(idb_info->interface_data, wtap_block_t, i); + gchar *s = wtap_get_debug_if_descr(if_descr, 21, "\n"); + g_array_append_val(cf_info.idb_info_strings, s); + } + + g_free(idb_info); + idb_info = NULL; + + if (err != 0) { fprintf(stderr, - " (will continue anyway, checksums might be incorrect)\n"); - } else { + "capinfos: An error occurred after reading %u packets from \"%s\".\n", + packet, filename); + cfile_read_failure_message(filename, err, err_info); + if (err == WTAP_ERR_SHORT_READ) { + /* Don't give up completely with this one. */ + status = 1; + fprintf(stderr, + " (will continue anyway, checksums might be incorrect)\n"); + } else { + cleanup_capture_info(&cf_info); + wtap_close(cf_info.wth); + return 2; + } + } + + /* File size */ + size = wtap_file_size(cf_info.wth, &err); + if (size == -1) { + fprintf(stderr, + "capinfos: Can't get size of \"%s\": %s.\n", + filename, g_strerror(err)); cleanup_capture_info(&cf_info); wtap_close(cf_info.wth); return 2; } - } - /* File size */ - size = wtap_file_size(cf_info.wth, &err); - if (size == -1) { - fprintf(stderr, - "capinfos: Can't get size of \"%s\": %s.\n", - filename, g_strerror(err)); + cf_info.filesize = size; + + /* File Type */ + cf_info.file_type = wtap_file_type_subtype(cf_info.wth); + cf_info.compression_type = wtap_get_compression_type(cf_info.wth); + + /* File Encapsulation */ + cf_info.file_encap = wtap_file_encap(cf_info.wth); + + cf_info.file_tsprec = wtap_file_tsprec(cf_info.wth); + + /* Packet size limit (snaplen) */ + cf_info.snaplen = wtap_snapshot_length(cf_info.wth); + if (cf_info.snaplen > 0) + cf_info.snap_set = TRUE; + else + cf_info.snap_set = FALSE; + + cf_info.snaplen_min_inferred = snaplen_min_inferred; + cf_info.snaplen_max_inferred = snaplen_max_inferred; + + /* # of packets */ + cf_info.packet_count = packet; + + /* File Times */ + cf_info.times_known = have_times; + cf_info.start_time = start_time; + cf_info.start_time_tsprec = start_time_tsprec; + cf_info.stop_time = stop_time; + cf_info.stop_time_tsprec = stop_time_tsprec; + nstime_delta(&cf_info.duration, &stop_time, &start_time); + /* Duration precision is the higher of the start and stop time precisions. */ + if (cf_info.stop_time_tsprec > cf_info.start_time_tsprec) + cf_info.duration_tsprec = cf_info.stop_time_tsprec; + else + cf_info.duration_tsprec = cf_info.start_time_tsprec; + cf_info.know_order = know_order; + cf_info.order = order; + + /* Number of packet bytes */ + cf_info.packet_bytes = bytes; + + cf_info.data_rate = 0.0; + cf_info.packet_rate = 0.0; + cf_info.packet_size = 0.0; + + if (packet > 0) { + double delta_time = nstime_to_sec(&stop_time) - nstime_to_sec(&start_time); + if (delta_time > 0.0) { + cf_info.data_rate = (double)bytes / delta_time; /* Data rate per second */ + cf_info.packet_rate = (double)packet / delta_time; /* packet rate per second */ + } + cf_info.packet_size = (double)bytes / packet; /* Avg packet size */ + } + + if (long_report) { + print_stats(filename, &cf_info); + } else { + print_stats_table(filename, &cf_info); + } + cleanup_capture_info(&cf_info); wtap_close(cf_info.wth); - return 2; - } - cf_info.filesize = size; - - /* File Type */ - cf_info.file_type = wtap_file_type_subtype(cf_info.wth); - cf_info.compression_type = wtap_get_compression_type(cf_info.wth); - - /* File Encapsulation */ - cf_info.file_encap = wtap_file_encap(cf_info.wth); - - cf_info.file_tsprec = wtap_file_tsprec(cf_info.wth); - - /* Packet size limit (snaplen) */ - cf_info.snaplen = wtap_snapshot_length(cf_info.wth); - if (cf_info.snaplen > 0) - cf_info.snap_set = TRUE; - else - cf_info.snap_set = FALSE; - - cf_info.snaplen_min_inferred = snaplen_min_inferred; - cf_info.snaplen_max_inferred = snaplen_max_inferred; - - /* # of packets */ - cf_info.packet_count = packet; - - /* File Times */ - cf_info.times_known = have_times; - cf_info.start_time = start_time; - cf_info.start_time_tsprec = start_time_tsprec; - cf_info.stop_time = stop_time; - cf_info.stop_time_tsprec = stop_time_tsprec; - nstime_delta(&cf_info.duration, &stop_time, &start_time); - /* Duration precision is the higher of the start and stop time precisions. */ - if (cf_info.stop_time_tsprec > cf_info.start_time_tsprec) - cf_info.duration_tsprec = cf_info.stop_time_tsprec; - else - cf_info.duration_tsprec = cf_info.start_time_tsprec; - cf_info.know_order = know_order; - cf_info.order = order; - - /* Number of packet bytes */ - cf_info.packet_bytes = bytes; - - cf_info.data_rate = 0.0; - cf_info.packet_rate = 0.0; - cf_info.packet_size = 0.0; - - if (packet > 0) { - double delta_time = nstime_to_sec(&stop_time) - nstime_to_sec(&start_time); - if (delta_time > 0.0) { - cf_info.data_rate = (double)bytes / delta_time; /* Data rate per second */ - cf_info.packet_rate = (double)packet / delta_time; /* packet rate per second */ - } - cf_info.packet_size = (double)bytes / packet; /* Avg packet size */ - } - - if (long_report) { - print_stats(filename, &cf_info); - } else { - print_stats_table(filename, &cf_info); - } - - cleanup_capture_info(&cf_info); - wtap_close(cf_info.wth); - - return status; + return status; } static void print_usage(FILE *output) { - fprintf(output, "\n"); - fprintf(output, "Usage: capinfos [options] ...\n"); - fprintf(output, "\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, " -I display the capture file interface information\n"); - fprintf(output, " -F display additional capture file information\n"); - fprintf(output, " -H display the SHA256, RIPEMD160, and SHA1 hashes of the file\n"); - fprintf(output, " -k display the capture comment\n"); - fprintf(output, "\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, " -l display the packet size limit (snapshot length)\n"); - fprintf(output, "\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, " -o display the capture file chronological status (True/False)\n"); - fprintf(output, " -S display start and end times as seconds\n"); - fprintf(output, "\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, "Metadata infos:\n"); - fprintf(output, " -n display number of resolved IPv4 and IPv6 addresses\n"); - fprintf(output, " -D display number of decryption secrets\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, " -M display machine-readable values in long reports\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, --help display this help and exit\n"); - fprintf(output, " -v, --version display version info 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, " -K disable displaying the capture comment\n"); - fprintf(output, "\n"); - fprintf(output, "Options are processed from left to right order with later options superseding\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"); + fprintf(output, "\n"); + fprintf(output, "Usage: capinfos [options] ...\n"); + fprintf(output, "\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, " -I display the capture file interface information\n"); + fprintf(output, " -F display additional capture file information\n"); + fprintf(output, " -H display the SHA256, RIPEMD160, and SHA1 hashes of the file\n"); + fprintf(output, " -k display the capture comment\n"); + fprintf(output, "\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, " -l display the packet size limit (snapshot length)\n"); + fprintf(output, "\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, " -o display the capture file chronological status (True/False)\n"); + fprintf(output, " -S display start and end times as seconds\n"); + fprintf(output, "\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, "Metadata infos:\n"); + fprintf(output, " -n display number of resolved IPv4 and IPv6 addresses\n"); + fprintf(output, " -D display number of decryption secrets\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, " -M display machine-readable values in long reports\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, --help display this help and exit\n"); + fprintf(output, " -v, --version display version info 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, " -K disable displaying the capture comment\n"); + fprintf(output, "\n"); + fprintf(output, "Options are processed from left to right order with later options superseding\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"); } /* @@ -1550,9 +1551,9 @@ print_usage(FILE *output) static void capinfos_cmdarg_err(const char *msg_format, va_list ap) { - fprintf(stderr, "capinfos: "); - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + fprintf(stderr, "capinfos: "); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } /* @@ -1561,328 +1562,315 @@ capinfos_cmdarg_err(const char *msg_format, va_list ap) static void capinfos_cmdarg_err_cont(const char *msg_format, va_list ap) { - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } int main(int argc, char *argv[]) { - char *init_progfile_dir_error; - static const struct report_message_routines capinfos_report_routines = { - failure_message, - failure_message, - open_failure_message, - read_failure_message, - write_failure_message, - cfile_open_failure_message, - cfile_dump_open_failure_message, - cfile_read_failure_message, - cfile_write_failure_message, - cfile_close_failure_message - }; - gboolean need_separator = FALSE; - int opt; - int overall_error_status = EXIT_SUCCESS; - static const struct ws_option long_options[] = { - {"help", ws_no_argument, NULL, 'h'}, - {"version", ws_no_argument, NULL, 'v'}, - {0, 0, 0, 0 } - }; + char *init_progfile_dir_error; + static const struct report_message_routines capinfos_report_routines = { + failure_message, + failure_message, + open_failure_message, + read_failure_message, + write_failure_message, + cfile_open_failure_message, + cfile_dump_open_failure_message, + cfile_read_failure_message, + cfile_write_failure_message, + cfile_close_failure_message + }; + gboolean need_separator = FALSE; + int opt; + int overall_error_status = EXIT_SUCCESS; + static const struct ws_option long_options[] = { + {"help", ws_no_argument, NULL, 'h'}, + {"version", ws_no_argument, NULL, 'v'}, + {0, 0, 0, 0 } + }; - int status = 0; + int status = 0; - /* - * Set the C-language locale to the native environment and set the - * code page to UTF-8 on Windows. - */ + /* + * Set the C-language locale to the native environment and set the + * code page to UTF-8 on Windows. + */ #ifdef _WIN32 - setlocale(LC_ALL, ".UTF-8"); + setlocale(LC_ALL, ".UTF-8"); #else - setlocale(LC_ALL, ""); + setlocale(LC_ALL, ""); #endif - cmdarg_err_init(capinfos_cmdarg_err, capinfos_cmdarg_err_cont); + cmdarg_err_init(capinfos_cmdarg_err, capinfos_cmdarg_err_cont); - /* Initialize log handler early so we can have proper logging during startup. */ - ws_log_init("capinfos", vcmdarg_err); + /* Initialize log handler early so we can have proper logging during startup. */ + ws_log_init("capinfos", vcmdarg_err); - /* Early logging command-line initialization. */ - ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION); + /* Early logging command-line initialization. */ + ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION); - /* Get the decimal point. */ - decimal_point = g_strdup(localeconv()->decimal_point); + /* Get the decimal point. */ + decimal_point = g_strdup(localeconv()->decimal_point); - /* Initialize the version information. */ - ws_init_version_info("Capinfos (Wireshark)", NULL, NULL, NULL); + /* Initialize the version information. */ + ws_init_version_info("Capinfos (Wireshark)", NULL, NULL, NULL); #ifdef _WIN32 - create_app_running_mutex(); + create_app_running_mutex(); #endif /* _WIN32 */ - /* - * Get credential information for later use. - */ - init_process_policies(); + /* + * Get credential information for later use. + */ + init_process_policies(); - /* - * Attempt to get the pathname of the directory containing the - * executable file. - */ - init_progfile_dir_error = init_progfile_dir(argv[0]); - if (init_progfile_dir_error != NULL) { - fprintf(stderr, - "capinfos: Can't get pathname of directory containing the capinfos program: %s.\n", - init_progfile_dir_error); - g_free(init_progfile_dir_error); - } + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + init_progfile_dir_error = init_progfile_dir(argv[0]); + if (init_progfile_dir_error != NULL) { + fprintf(stderr, + "capinfos: Can't get pathname of directory containing the capinfos program: %s.\n", + init_progfile_dir_error); + g_free(init_progfile_dir_error); + } - init_report_message("capinfos", &capinfos_report_routines); + init_report_message("capinfos", &capinfos_report_routines); - wtap_init(TRUE); + wtap_init(TRUE); - /* Process the options */ - while ((opt = ws_getopt_long(argc, argv, "abcdehiklmnoqrstuvxyzABCDEFHIKLMNQRST", long_options, NULL)) !=-1) { + /* Process the options */ + while ((opt = ws_getopt_long(argc, argv, "abcdehiklmnoqrstuvxyzABCDEFHIKLMNQRST", long_options, NULL)) !=-1) { - switch (opt) { + switch (opt) { - case 't': - if (report_all_infos) disable_all_infos(); - cap_file_type = TRUE; - break; + 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 'E': + if (report_all_infos) disable_all_infos(); + cap_file_encap = TRUE; + break; - case 'l': - if (report_all_infos) disable_all_infos(); - cap_snaplen = TRUE; - break; + case 'l': + if (report_all_infos) disable_all_infos(); + cap_snaplen = TRUE; + break; - case 'c': - if (report_all_infos) disable_all_infos(); - cap_packet_count = 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 '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 '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 '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 '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 'e': + if (report_all_infos) disable_all_infos(); + cap_end_time = TRUE; + break; - case 'S': - time_as_secs = TRUE; - break; + case 'S': + time_as_secs = TRUE; + break; - case 'y': - if (report_all_infos) disable_all_infos(); - cap_data_rate_byte = 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 '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 '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 'x': + if (report_all_infos) disable_all_infos(); + cap_packet_rate = TRUE; + break; - case 'H': - if (report_all_infos) disable_all_infos(); - cap_file_hashes = TRUE; - break; + case 'H': + if (report_all_infos) disable_all_infos(); + cap_file_hashes = TRUE; + break; - case 'o': - if (report_all_infos) disable_all_infos(); - cap_order = TRUE; - break; + case 'o': + if (report_all_infos) disable_all_infos(); + cap_order = TRUE; + break; - case 'k': - if (report_all_infos) disable_all_infos(); - cap_comment = TRUE; - break; + case 'k': + if (report_all_infos) disable_all_infos(); + cap_comment = TRUE; + break; - case 'K': - cap_comment = FALSE; - break; + case 'K': + cap_comment = FALSE; + break; - case 'F': - if (report_all_infos) disable_all_infos(); - cap_file_more_info = TRUE; - break; + case 'F': + if (report_all_infos) disable_all_infos(); + cap_file_more_info = TRUE; + break; - case 'I': - if (report_all_infos) disable_all_infos(); - cap_file_idb = TRUE; - break; + case 'I': + if (report_all_infos) disable_all_infos(); + cap_file_idb = TRUE; + break; - case 'n': - if (report_all_infos) disable_all_infos(); - cap_file_nrb = TRUE; - break; + case 'n': + if (report_all_infos) disable_all_infos(); + cap_file_nrb = TRUE; + break; - case 'D': - if (report_all_infos) disable_all_infos(); - cap_file_dsb = TRUE; - break; + case 'D': + if (report_all_infos) disable_all_infos(); + cap_file_dsb = TRUE; + break; - case 'C': - stop_after_failure = TRUE; - break; + case 'C': + stop_after_failure = TRUE; + break; - case 'A': - enable_all_infos(); - break; + case 'A': + enable_all_infos(); + break; - case 'L': - long_report = TRUE; - break; + case 'L': + long_report = TRUE; + break; - case 'T': - long_report = FALSE; - break; + case 'T': + long_report = FALSE; + break; - case 'M': - machine_readable = TRUE; - break; + case 'M': + machine_readable = TRUE; + break; - case 'R': - table_report_header = TRUE; - break; + case 'R': + table_report_header = TRUE; + break; - case 'r': - table_report_header = FALSE; - break; + case 'r': + table_report_header = FALSE; + break; - case 'N': - quote_char = '\0'; - break; + case 'N': + quote_char = '\0'; + break; - case 'q': - quote_char = '\''; - break; + case 'q': + quote_char = '\''; + break; - case 'Q': - quote_char = '"'; - break; + case 'Q': + quote_char = '"'; + break; - case 'B': - field_separator = '\t'; - break; + case 'B': + field_separator = '\t'; + break; - case 'm': - field_separator = ','; - break; + case 'm': + field_separator = ','; + break; - case 'b': - field_separator = ' '; - break; + case 'b': + field_separator = ' '; + break; - case 'h': - show_help_header("Print various information (infos) about capture files."); - print_usage(stdout); - goto exit; - break; + case 'h': + show_help_header("Print various information (infos) about capture files."); + print_usage(stdout); + goto exit; + break; - case 'v': - show_version(); - goto exit; - break; + case 'v': + show_version(); + goto exit; + break; - case '?': /* Bad flag - print usage message */ + case '?': /* Bad flag - print usage message */ + print_usage(stderr); + overall_error_status = INVALID_OPTION; + goto exit; + break; + } + } + + if ((argc - ws_optind) < 1) { print_usage(stderr); overall_error_status = INVALID_OPTION; goto exit; - break; } - } - if ((argc - ws_optind) < 1) { - print_usage(stderr); - overall_error_status = INVALID_OPTION; - goto exit; - } - - if (!long_report && table_report_header) { - print_stats_table_header(); - } - - if (cap_file_hashes) { - gcry_check_version(NULL); - gcry_md_open(&hd, GCRY_MD_SHA256, 0); - if (hd) { - gcry_md_enable(hd, GCRY_MD_RMD160); - gcry_md_enable(hd, GCRY_MD_SHA1); + if (!long_report && table_report_header) { + print_stats_table_header(); } - hash_buf = (char *)g_malloc(HASH_BUF_SIZE); - } - overall_error_status = 0; - - for (opt = ws_optind; opt < argc; opt++) { - - status = process_cap_file(argv[opt], need_separator); - if (status) { - /* Something failed. It's been reported; remember that processing - one file failed and, if -C was specified, stop. */ - overall_error_status = status; - if (stop_after_failure) - goto exit; + if (cap_file_hashes) { + gcry_check_version(NULL); + gcry_md_open(&hd, GCRY_MD_SHA256, 0); + if (hd) { + gcry_md_enable(hd, GCRY_MD_RMD160); + gcry_md_enable(hd, GCRY_MD_SHA1); + } + hash_buf = (char *)g_malloc(HASH_BUF_SIZE); } - if (status != 2) { - /* Either it succeeded or it got a "short read" but printed - information anyway. Note that we need a blank line before - the next file's information, to separate it from the - previous file. */ - need_separator = TRUE; + + overall_error_status = 0; + + for (opt = ws_optind; opt < argc; opt++) { + + status = process_cap_file(argv[opt], need_separator); + if (status) { + /* Something failed. It's been reported; remember that processing + one file failed and, if -C was specified, stop. */ + overall_error_status = status; + if (stop_after_failure) + goto exit; + } + if (status != 2) { + /* Either it succeeded or it got a "short read" but printed + information anyway. Note that we need a blank line before + the next file's information, to separate it from the + previous file. */ + need_separator = TRUE; + } } - } exit: - g_free(hash_buf); - gcry_md_close(hd); - wtap_cleanup(); - free_progdirs(); - return overall_error_status; + g_free(hash_buf); + gcry_md_close(hd); + wtap_cleanup(); + free_progdirs(); + return overall_error_status; } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/captype.c b/captype.c index 5820210184..fe541f5387 100644 --- a/captype.c +++ b/captype.c @@ -46,12 +46,12 @@ static void print_usage(FILE *output) { - fprintf(output, "\n"); - fprintf(output, "Usage: captype [options] ...\n"); - fprintf(output, "\n"); - fprintf(output, "Miscellaneous:\n"); - fprintf(output, " -h, --help display this help and exit\n"); - fprintf(output, " -v, --version display version info and exit\n"); + fprintf(output, "\n"); + fprintf(output, "Usage: captype [options] ...\n"); + fprintf(output, "\n"); + fprintf(output, "Miscellaneous:\n"); + fprintf(output, " -h, --help display this help and exit\n"); + fprintf(output, " -v, --version display version info and exit\n"); } /* @@ -60,9 +60,9 @@ print_usage(FILE *output) static void captype_cmdarg_err(const char *msg_format, va_list ap) { - fprintf(stderr, "captype: "); - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + fprintf(stderr, "captype: "); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } /* @@ -71,145 +71,132 @@ captype_cmdarg_err(const char *msg_format, va_list ap) static void captype_cmdarg_err_cont(const char *msg_format, va_list ap) { - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } int main(int argc, char *argv[]) { - char *init_progfile_dir_error; - static const struct report_message_routines captype_report_routines = { - failure_message, - failure_message, - open_failure_message, - read_failure_message, - write_failure_message, - cfile_open_failure_message, - cfile_dump_open_failure_message, - cfile_read_failure_message, - cfile_write_failure_message, - cfile_close_failure_message - }; - wtap *wth; - int err; - gchar *err_info; - int i; - int opt; - int overall_error_status; - static const struct ws_option long_options[] = { - {"help", ws_no_argument, NULL, 'h'}, - {"version", ws_no_argument, NULL, 'v'}, - {0, 0, 0, 0 } - }; + char *init_progfile_dir_error; + static const struct report_message_routines captype_report_routines = { + failure_message, + failure_message, + open_failure_message, + read_failure_message, + write_failure_message, + cfile_open_failure_message, + cfile_dump_open_failure_message, + cfile_read_failure_message, + cfile_write_failure_message, + cfile_close_failure_message + }; + wtap *wth; + int err; + gchar *err_info; + int i; + int opt; + int overall_error_status; + static const struct ws_option long_options[] = { + {"help", ws_no_argument, NULL, 'h'}, + {"version", ws_no_argument, NULL, 'v'}, + {0, 0, 0, 0 } + }; - /* - * Set the C-language locale to the native environment and set the - * code page to UTF-8 on Windows. - */ + /* + * Set the C-language locale to the native environment and set the + * code page to UTF-8 on Windows. + */ #ifdef _WIN32 - setlocale(LC_ALL, ".UTF-8"); + setlocale(LC_ALL, ".UTF-8"); #else - setlocale(LC_ALL, ""); + setlocale(LC_ALL, ""); #endif - cmdarg_err_init(captype_cmdarg_err, captype_cmdarg_err_cont); + cmdarg_err_init(captype_cmdarg_err, captype_cmdarg_err_cont); - /* Initialize log handler early so we can have proper logging during startup. */ - ws_log_init("captype", vcmdarg_err); + /* Initialize log handler early so we can have proper logging during startup. */ + ws_log_init("captype", vcmdarg_err); - /* Early logging command-line initialization. */ - ws_log_parse_args(&argc, argv, vcmdarg_err, 1); + /* Early logging command-line initialization. */ + ws_log_parse_args(&argc, argv, vcmdarg_err, 1); - /* Initialize the version information. */ - ws_init_version_info("Captype (Wireshark)", NULL, NULL, NULL); + /* Initialize the version information. */ + ws_init_version_info("Captype (Wireshark)", NULL, NULL, NULL); #ifdef _WIN32 - create_app_running_mutex(); + create_app_running_mutex(); #endif /* _WIN32 */ - /* - * Get credential information for later use. - */ - init_process_policies(); + /* + * Get credential information for later use. + */ + init_process_policies(); - /* - * Attempt to get the pathname of the directory containing the - * executable file. - */ - init_progfile_dir_error = init_progfile_dir(argv[0]); - if (init_progfile_dir_error != NULL) { - fprintf(stderr, - "captype: Can't get pathname of directory containing the captype program: %s.\n", - init_progfile_dir_error); - g_free(init_progfile_dir_error); - } + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + init_progfile_dir_error = init_progfile_dir(argv[0]); + if (init_progfile_dir_error != NULL) { + fprintf(stderr, + "captype: Can't get pathname of directory containing the captype program: %s.\n", + init_progfile_dir_error); + g_free(init_progfile_dir_error); + } - init_report_message("captype", &captype_report_routines); + init_report_message("captype", &captype_report_routines); - wtap_init(TRUE); + wtap_init(TRUE); - /* Process the options */ - while ((opt = ws_getopt_long(argc, argv, "hv", long_options, NULL)) !=-1) { + /* Process the options */ + while ((opt = ws_getopt_long(argc, argv, "hv", long_options, NULL)) !=-1) { - switch (opt) { + switch (opt) { - case 'h': - show_help_header("Print the file types of capture files."); - print_usage(stdout); - exit(0); - break; + case 'h': + show_help_header("Print the file types of capture files."); + print_usage(stdout); + exit(0); + break; - case 'v': - show_version(); - exit(0); - break; + case 'v': + show_version(); + exit(0); + break; - case '?': /* Bad flag - print usage message */ + case '?': /* Bad flag - print usage message */ + print_usage(stderr); + exit(1); + break; + } + } + + if (argc < 2) { print_usage(stderr); - exit(1); - break; - } - } - - if (argc < 2) { - print_usage(stderr); - return 1; - } - - overall_error_status = 0; - - for (i = 1; i < argc; i++) { - wth = wtap_open_offline(argv[i], WTAP_TYPE_AUTO, &err, &err_info, FALSE); - - if(wth) { - printf("%s: %s\n", argv[i], wtap_file_type_subtype_name(wtap_file_type_subtype(wth))); - wtap_close(wth); - } else { - if (err == WTAP_ERR_FILE_UNKNOWN_FORMAT) - printf("%s: unknown\n", argv[i]); - else { - cfile_open_failure_message(argv[i], err, err_info); - overall_error_status = 2; /* remember that an error has occurred */ - } + return 1; } - } + overall_error_status = 0; - wtap_cleanup(); - free_progdirs(); - return overall_error_status; + for (i = 1; i < argc; i++) { + wth = wtap_open_offline(argv[i], WTAP_TYPE_AUTO, &err, &err_info, FALSE); + + if(wth) { + printf("%s: %s\n", argv[i], wtap_file_type_subtype_name(wtap_file_type_subtype(wth))); + wtap_close(wth); + } else { + if (err == WTAP_ERR_FILE_UNKNOWN_FORMAT) + printf("%s: unknown\n", argv[i]); + else { + cfile_open_failure_message(argv[i], err, err_info); + overall_error_status = 2; /* remember that an error has occurred */ + } + } + + } + + wtap_cleanup(); + free_progdirs(); + return overall_error_status; } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/cfile.c b/cfile.c index ef4b28c58d..fbc2b98df6 100644 --- a/cfile.c +++ b/cfile.c @@ -20,19 +20,6 @@ void cap_file_init(capture_file *cf) { - /* Initialize the capture file struct */ - memset(cf, 0, sizeof(capture_file)); + /* Initialize the capture file struct */ + memset(cf, 0, sizeof(capture_file)); } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local Variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * ex: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/cfile.h b/cfile.h index e532ecc286..70b0ef915c 100644 --- a/cfile.h +++ b/cfile.h @@ -25,107 +25,107 @@ extern "C" { /* Current state of file. */ typedef enum { - FILE_CLOSED, /* No file open */ - FILE_READ_IN_PROGRESS, /* Reading a file we've opened */ - FILE_READ_ABORTED, /* Read aborted by user */ - FILE_READ_DONE /* Read completed */ + FILE_CLOSED, /* No file open */ + FILE_READ_IN_PROGRESS, /* Reading a file we've opened */ + FILE_READ_ABORTED, /* Read aborted by user */ + FILE_READ_DONE /* Read completed */ } file_state; /* Requested packets rescan action. */ typedef enum { - RESCAN_NONE = 0, /* No rescan requested */ - RESCAN_SCAN, /* Request rescan without full redissection. */ - RESCAN_REDISSECT /* Request full redissection. */ + RESCAN_NONE = 0, /* No rescan requested */ + RESCAN_SCAN, /* Request rescan without full redissection. */ + RESCAN_REDISSECT /* Request full redissection. */ } rescan_type; /* Character set for text search. */ typedef enum { - SCS_NARROW_AND_WIDE, - SCS_NARROW, - SCS_WIDE - /* add EBCDIC when it's implemented */ + SCS_NARROW_AND_WIDE, + SCS_NARROW, + SCS_WIDE + /* add EBCDIC when it's implemented */ } search_charset_t; typedef enum { - SD_FORWARD, - SD_BACKWARD + SD_FORWARD, + SD_BACKWARD } search_direction; /* * Packet provider for programs using a capture file. */ struct packet_provider_data { - wtap *wth; /* Wiretap session */ - const frame_data *ref; - frame_data *prev_dis; - frame_data *prev_cap; - frame_data_sequence *frames; /* Sequence of frames, if we're keeping that information */ - GTree *frames_modified_blocks; /* BST with modified blocks for frames (key = frame_data) */ + wtap *wth; /* Wiretap session */ + const frame_data *ref; + frame_data *prev_dis; + frame_data *prev_cap; + frame_data_sequence *frames; /* Sequence of frames, if we're keeping that information */ + GTree *frames_modified_blocks; /* BST with modified blocks for frames (key = frame_data) */ }; typedef struct _capture_file { - epan_t *epan; - file_state state; /* Current state of capture file */ - gchar *filename; /* Name of capture file */ - gchar *source; /* Temp file source, e.g. "Pipe from elsewhere" */ - gboolean is_tempfile; /* Is capture file a temporary file? */ - gboolean unsaved_changes; /* Does the capture file have changes that have not been saved? */ - gboolean stop_flag; /* Stop current processing (loading, searching, etc.) */ + epan_t *epan; + file_state state; /* Current state of capture file */ + gchar *filename; /* Name of capture file */ + gchar *source; /* Temp file source, e.g. "Pipe from elsewhere" */ + gboolean is_tempfile; /* Is capture file a temporary file? */ + gboolean unsaved_changes; /* Does the capture file have changes that have not been saved? */ + gboolean stop_flag; /* Stop current processing (loading, searching, etc.) */ - gint64 f_datalen; /* Size of capture file data (uncompressed) */ - guint16 cd_t; /* File type of capture file */ - unsigned int open_type; /* open_routine index+1 used, if selected, or WTAP_TYPE_AUTO */ - wtap_compression_type compression_type; /* Compression type of the file, or uncompressed */ - int lnk_t; /* File link-layer type; could be WTAP_ENCAP_PER_PACKET */ - GArray *linktypes; /* Array of packet link-layer types */ - guint32 count; /* Total number of frames */ - guint64 packet_comment_count; /* Number of comments in frames (could be >1 per frame... */ - guint32 displayed_count; /* Number of displayed frames */ - guint32 marked_count; /* Number of marked frames */ - guint32 ignored_count; /* Number of ignored frames */ - guint32 ref_time_count; /* Number of time referenced frames */ - gboolean drops_known; /* TRUE if we know how many packets were dropped */ - guint32 drops; /* Dropped packets */ - nstime_t elapsed_time; /* Elapsed time */ - int snap; /* Maximum captured packet length; 0 if unknown */ - dfilter_t *rfcode; /* Compiled read filter program */ - dfilter_t *dfcode; /* Compiled display filter program */ - gchar *dfilter; /* Display filter string */ - gboolean redissecting; /* TRUE if currently redissecting (cf_redissect_packets) */ - gboolean read_lock; /* TRUE if currently processing a file (cf_read) */ - rescan_type redissection_queued; /* Queued redissection type. */ - /* search */ - gchar *sfilter; /* Filter, hex value, or string being searched */ - gboolean hex; /* TRUE if "Hex value" search was last selected */ - gboolean string; /* TRUE if "String" search was last selected */ - gboolean summary_data; /* TRUE if "String" search in "Packet list" (Info column) was last selected */ - gboolean decode_data; /* TRUE if "String" search in "Packet details" was last selected */ - gboolean packet_data; /* TRUE if "String" search in "Packet data" was last selected */ - guint32 search_pos; /* Byte position of last byte found in a hex search */ - guint32 search_len; /* Length of bytes matching the search */ - gboolean case_type; /* TRUE if case-insensitive text search */ - GRegex *regex; /* Set if regular expression search */ - search_charset_t scs_type; /* Character set for text search */ - search_direction dir; /* Direction in which to do searches */ - gboolean search_in_progress; /* TRUE if user just clicked OK in the Find dialog or hit N/B */ - /* packet provider */ - struct packet_provider_data provider; - /* frames */ - guint32 first_displayed; /* Frame number of first frame displayed */ - guint32 last_displayed; /* Frame number of last frame displayed */ - /* Data for currently selected frame */ - column_info cinfo; /* Column formatting information */ - frame_data *current_frame; /* Frame data */ - gint current_row; /* Row number */ - epan_dissect_t *edt; /* Protocol dissection */ - field_info *finfo_selected; /* Field info */ - wtap_rec rec; /* Record header */ - Buffer buf; /* Record data */ + gint64 f_datalen; /* Size of capture file data (uncompressed) */ + guint16 cd_t; /* File type of capture file */ + unsigned int open_type; /* open_routine index+1 used, if selected, or WTAP_TYPE_AUTO */ + wtap_compression_type compression_type; /* Compression type of the file, or uncompressed */ + int lnk_t; /* File link-layer type; could be WTAP_ENCAP_PER_PACKET */ + GArray *linktypes; /* Array of packet link-layer types */ + guint32 count; /* Total number of frames */ + guint64 packet_comment_count; /* Number of comments in frames (could be >1 per frame... */ + guint32 displayed_count; /* Number of displayed frames */ + guint32 marked_count; /* Number of marked frames */ + guint32 ignored_count; /* Number of ignored frames */ + guint32 ref_time_count; /* Number of time referenced frames */ + gboolean drops_known; /* TRUE if we know how many packets were dropped */ + guint32 drops; /* Dropped packets */ + nstime_t elapsed_time; /* Elapsed time */ + int snap; /* Maximum captured packet length; 0 if unknown */ + dfilter_t *rfcode; /* Compiled read filter program */ + dfilter_t *dfcode; /* Compiled display filter program */ + gchar *dfilter; /* Display filter string */ + gboolean redissecting; /* TRUE if currently redissecting (cf_redissect_packets) */ + gboolean read_lock; /* TRUE if currently processing a file (cf_read) */ + rescan_type redissection_queued; /* Queued redissection type. */ + /* search */ + gchar *sfilter; /* Filter, hex value, or string being searched */ + gboolean hex; /* TRUE if "Hex value" search was last selected */ + gboolean string; /* TRUE if "String" search was last selected */ + gboolean summary_data; /* TRUE if "String" search in "Packet list" (Info column) was last selected */ + gboolean decode_data; /* TRUE if "String" search in "Packet details" was last selected */ + gboolean packet_data; /* TRUE if "String" search in "Packet data" was last selected */ + guint32 search_pos; /* Byte position of last byte found in a hex search */ + guint32 search_len; /* Length of bytes matching the search */ + gboolean case_type; /* TRUE if case-insensitive text search */ + GRegex *regex; /* Set if regular expression search */ + search_charset_t scs_type; /* Character set for text search */ + search_direction dir; /* Direction in which to do searches */ + gboolean search_in_progress; /* TRUE if user just clicked OK in the Find dialog or hit N/B */ + /* packet provider */ + struct packet_provider_data provider; + /* frames */ + guint32 first_displayed; /* Frame number of first frame displayed */ + guint32 last_displayed; /* Frame number of last frame displayed */ + /* Data for currently selected frame */ + column_info cinfo; /* Column formatting information */ + frame_data *current_frame; /* Frame data */ + gint current_row; /* Row number */ + epan_dissect_t *edt; /* Protocol dissection */ + field_info *finfo_selected; /* Field info */ + wtap_rec rec; /* Record header */ + Buffer buf; /* Record data */ - gpointer window; /* Top-level window associated with file */ - gulong computed_elapsed; /* Elapsed time to load the file (in msec). */ + gpointer window; /* Top-level window associated with file */ + gulong computed_elapsed; /* Elapsed time to load the file (in msec). */ - guint32 cum_bytes; + guint32 cum_bytes; } capture_file; extern void cap_file_init(capture_file *cf); @@ -140,16 +140,3 @@ void cap_file_provider_set_modified_block(struct packet_provider_data *prov, fra #endif /* __cplusplus */ #endif /* cfile.h */ - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local Variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/dftest.c b/dftest.c index 1c7ba933b5..b5cc14496a 100644 --- a/dftest.c +++ b/dftest.c @@ -43,115 +43,115 @@ static void dftest_cmdarg_err_cont(const char *fmt, va_list ap); int main(int argc, char **argv) { - char *init_progfile_dir_error; - static const struct report_message_routines dftest_report_routines = { - failure_message, - failure_message, - open_failure_message, - read_failure_message, - write_failure_message, - cfile_open_failure_message, - cfile_dump_open_failure_message, - cfile_read_failure_message, - cfile_write_failure_message, - cfile_close_failure_message - }; - char *text; - dfilter_t *df; - gchar *err_msg; + char *init_progfile_dir_error; + static const struct report_message_routines dftest_report_routines = { + failure_message, + failure_message, + open_failure_message, + read_failure_message, + write_failure_message, + cfile_open_failure_message, + cfile_dump_open_failure_message, + cfile_read_failure_message, + cfile_write_failure_message, + cfile_close_failure_message + }; + char *text; + dfilter_t *df; + gchar *err_msg; - cmdarg_err_init(dftest_cmdarg_err, dftest_cmdarg_err_cont); + cmdarg_err_init(dftest_cmdarg_err, dftest_cmdarg_err_cont); - /* Initialize log handler early so we can have proper logging during startup. */ - ws_log_init("dftest", vcmdarg_err); + /* Initialize log handler early so we can have proper logging during startup. */ + ws_log_init("dftest", vcmdarg_err); - /* Early logging command-line initialization. */ - ws_log_parse_args(&argc, argv, vcmdarg_err, 1); + /* Early logging command-line initialization. */ + ws_log_parse_args(&argc, argv, vcmdarg_err, 1); - /* - * Get credential information for later use. - */ - init_process_policies(); + /* + * Get credential information for later use. + */ + init_process_policies(); - /* - * Attempt to get the pathname of the directory containing the - * executable file. - */ - init_progfile_dir_error = init_progfile_dir(argv[0]); - if (init_progfile_dir_error != NULL) { - fprintf(stderr, "dftest: Can't get pathname of directory containing the dftest program: %s.\n", - init_progfile_dir_error); - g_free(init_progfile_dir_error); - } + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + init_progfile_dir_error = init_progfile_dir(argv[0]); + if (init_progfile_dir_error != NULL) { + fprintf(stderr, "dftest: Can't get pathname of directory containing the dftest program: %s.\n", + init_progfile_dir_error); + g_free(init_progfile_dir_error); + } - init_report_message("dftest", &dftest_report_routines); + init_report_message("dftest", &dftest_report_routines); - timestamp_set_type(TS_RELATIVE); - timestamp_set_seconds_type(TS_SECONDS_DEFAULT); + timestamp_set_type(TS_RELATIVE); + timestamp_set_seconds_type(TS_SECONDS_DEFAULT); - /* - * Libwiretap must be initialized before libwireshark is, so that - * dissection-time handlers for file-type-dependent blocks can - * register using the file type/subtype value for the file type. - */ - wtap_init(TRUE); + /* + * Libwiretap must be initialized before libwireshark is, so that + * dissection-time handlers for file-type-dependent blocks can + * register using the file type/subtype value for the file type. + */ + wtap_init(TRUE); - /* Register all dissectors; we must do this before checking for the - "-g" flag, as the "-g" flag dumps a list of fields registered - by the dissectors, and we must do it before we read the preferences, - in case any dissectors register preferences. */ - if (!epan_init(NULL, NULL, FALSE)) - return 2; + /* Register all dissectors; we must do this before checking for the + "-g" flag, as the "-g" flag dumps a list of fields registered + by the dissectors, and we must do it before we read the preferences, + in case any dissectors register preferences. */ + if (!epan_init(NULL, NULL, FALSE)) + return 2; - /* - * Set the C-language locale to the native environment and set the - * code page to UTF-8 on Windows. - */ + /* + * Set the C-language locale to the native environment and set the + * code page to UTF-8 on Windows. + */ #ifdef _WIN32 - setlocale(LC_ALL, ".UTF-8"); + setlocale(LC_ALL, ".UTF-8"); #else - setlocale(LC_ALL, ""); + setlocale(LC_ALL, ""); #endif - /* Load libwireshark settings from the current profile. */ - epan_load_settings(); + /* Load libwireshark settings from the current profile. */ + epan_load_settings(); - /* notify all registered modules that have had any of their preferences - changed either from one of the preferences file or from the command - line that its preferences have changed. */ - prefs_apply_all(); + /* notify all registered modules that have had any of their preferences + changed either from one of the preferences file or from the command + line that its preferences have changed. */ + prefs_apply_all(); - /* Check for filter on command line */ - if (argc <= 1) { - fprintf(stderr, "Usage: dftest \n"); - exit(1); - } + /* Check for filter on command line */ + if (argc <= 1) { + fprintf(stderr, "Usage: dftest \n"); + exit(1); + } - /* Get filter text */ - text = get_args_as_string(argc, argv, 1); + /* Get filter text */ + text = get_args_as_string(argc, argv, 1); - printf("Filter: %s\n", text); + printf("Filter: %s\n", text); - /* Compile it */ - if (!dfilter_compile(text, &df, &err_msg)) { - fprintf(stderr, "dftest: %s\n", err_msg); - g_free(err_msg); - epan_cleanup(); - g_free(text); - exit(2); - } + /* Compile it */ + if (!dfilter_compile(text, &df, &err_msg)) { + fprintf(stderr, "dftest: %s\n", err_msg); + g_free(err_msg); + epan_cleanup(); + g_free(text); + exit(2); + } - printf("\n"); + printf("\n"); - if (df == NULL) - printf("Filter is empty\n"); - else - dfilter_dump(df); + if (df == NULL) + printf("Filter is empty\n"); + else + dfilter_dump(df); - dfilter_free(df); - epan_cleanup(); - g_free(text); - exit(0); + dfilter_free(df); + epan_cleanup(); + g_free(text); + exit(0); } /* @@ -160,9 +160,9 @@ main(int argc, char **argv) static void dftest_cmdarg_err(const char *fmt, va_list ap) { - fprintf(stderr, "dftest: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + fprintf(stderr, "dftest: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); } /* @@ -171,19 +171,6 @@ dftest_cmdarg_err(const char *fmt, va_list ap) static void dftest_cmdarg_err_cont(const char *fmt, va_list ap) { - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 8 - * tab-width: 8 - * indent-tabs-mode: t - * End: - * - * vi: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: - */ diff --git a/file.c b/file.c index ea916c7743..23c5fef297 100644 --- a/file.c +++ b/file.c @@ -79,41 +79,41 @@ static gboolean read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect); typedef enum { - MR_NOTMATCHED, - MR_MATCHED, - MR_ERROR + MR_NOTMATCHED, + MR_MATCHED, + MR_ERROR } match_result; typedef match_result (*ws_match_function)(capture_file *, frame_data *, - wtap_rec *, Buffer *, void *); + wtap_rec *, Buffer *, void *); static match_result match_protocol_tree(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static void match_subtree_text(proto_node *node, gpointer data); static match_result match_summary_line(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_narrow_and_wide_case(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_narrow(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_narrow_case(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_wide(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_wide_case(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_binary(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_regex(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_dfilter(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_marked(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static match_result match_time_reference(capture_file *cf, frame_data *fdata, - wtap_rec *, Buffer *, void *criterion); + wtap_rec *, Buffer *, void *criterion); static gboolean find_packet(capture_file *cf, ws_match_function match_function, - void *criterion, search_direction dir); + void *criterion, search_direction dir); static void cf_rename_failure_alert_box(const char *filename, int err); @@ -137,7 +137,7 @@ static guint32 max_records = G_MAXUINT32; void cf_set_max_records(guint max_records_arg) { - max_records = max_records_arg; + max_records = max_records_arg; } /* @@ -146,8 +146,8 @@ cf_set_max_records(guint max_records_arg) * instance for the signals. */ typedef struct { - cf_callback_t cb_fct; - gpointer user_data; + cf_callback_t cb_fct; + gpointer user_data; } cf_callback_data_t; static GList *cf_callbacks = NULL; @@ -155,193 +155,193 @@ static GList *cf_callbacks = NULL; static void cf_callback_invoke(int event, gpointer data) { - cf_callback_data_t *cb; - GList *cb_item = cf_callbacks; + cf_callback_data_t *cb; + GList *cb_item = cf_callbacks; - /* there should be at least one interested */ - ws_assert(cb_item != NULL); + /* there should be at least one interested */ + ws_assert(cb_item != NULL); - while (cb_item != NULL) { - cb = (cf_callback_data_t *)cb_item->data; - cb->cb_fct(event, data, cb->user_data); - cb_item = g_list_next(cb_item); - } + while (cb_item != NULL) { + cb = (cf_callback_data_t *)cb_item->data; + cb->cb_fct(event, data, cb->user_data); + cb_item = g_list_next(cb_item); + } } - void cf_callback_add(cf_callback_t func, gpointer user_data) { - cf_callback_data_t *cb; + cf_callback_data_t *cb; - cb = g_new(cf_callback_data_t,1); - cb->cb_fct = func; - cb->user_data = user_data; + cb = g_new(cf_callback_data_t,1); + cb->cb_fct = func; + cb->user_data = user_data; - cf_callbacks = g_list_prepend(cf_callbacks, cb); + cf_callbacks = g_list_prepend(cf_callbacks, cb); } void cf_callback_remove(cf_callback_t func, gpointer user_data) { - cf_callback_data_t *cb; - GList *cb_item = cf_callbacks; + cf_callback_data_t *cb; + GList *cb_item = cf_callbacks; - while (cb_item != NULL) { - cb = (cf_callback_data_t *)cb_item->data; - if (cb->cb_fct == func && cb->user_data == user_data) { - cf_callbacks = g_list_remove(cf_callbacks, cb); - g_free(cb); - return; + while (cb_item != NULL) { + cb = (cf_callback_data_t *)cb_item->data; + if (cb->cb_fct == func && cb->user_data == user_data) { + cf_callbacks = g_list_remove(cf_callbacks, cb); + g_free(cb); + return; + } + cb_item = g_list_next(cb_item); } - cb_item = g_list_next(cb_item); - } - ws_assert_not_reached(); + ws_assert_not_reached(); } void cf_timestamp_auto_precision(capture_file *cf) { - int i; + int i; - /* don't try to get the file's precision if none is opened */ - if (cf->state == FILE_CLOSED) { - return; - } - - /* Set the column widths of those columns that show the time in - "command-line-specified" format. */ - for (i = 0; i < cf->cinfo.num_cols; i++) { - if (col_has_time_fmt(&cf->cinfo, i)) { - packet_list_resize_column(i); + /* don't try to get the file's precision if none is opened */ + if (cf->state == FILE_CLOSED) { + return; + } + + /* Set the column widths of those columns that show the time in + "command-line-specified" format. */ + for (i = 0; i < cf->cinfo.num_cols; i++) { + if (col_has_time_fmt(&cf->cinfo, i)) { + packet_list_resize_column(i); + } } - } } gulong cf_get_computed_elapsed(capture_file *cf) { - return cf->computed_elapsed; + return cf->computed_elapsed; } -static void compute_elapsed(capture_file *cf, gint64 start_time) +static void +compute_elapsed(capture_file *cf, gint64 start_time) { - gint64 delta_time = g_get_monotonic_time() - start_time; + gint64 delta_time = g_get_monotonic_time() - start_time; - cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */ + cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */ } static const nstime_t * ws_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num) { - if (prov->prev_dis && prov->prev_dis->num == frame_num) - return &prov->prev_dis->abs_ts; + if (prov->prev_dis && prov->prev_dis->num == frame_num) + return &prov->prev_dis->abs_ts; - if (prov->prev_cap && prov->prev_cap->num == frame_num) - return &prov->prev_cap->abs_ts; + if (prov->prev_cap && prov->prev_cap->num == frame_num) + return &prov->prev_cap->abs_ts; - if (prov->frames) { - frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); + if (prov->frames) { + frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); - return (fd) ? &fd->abs_ts : NULL; - } + return (fd) ? &fd->abs_ts : NULL; + } - return NULL; + return NULL; } static epan_t * ws_epan_new(capture_file *cf) { - static const struct packet_provider_funcs funcs = { - ws_get_frame_ts, - cap_file_provider_get_interface_name, - cap_file_provider_get_interface_description, - cap_file_provider_get_modified_block - }; + static const struct packet_provider_funcs funcs = { + ws_get_frame_ts, + cap_file_provider_get_interface_name, + cap_file_provider_get_interface_description, + cap_file_provider_get_modified_block + }; - return epan_new(&cf->provider, &funcs); + return epan_new(&cf->provider, &funcs); } cf_status_t cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err) { - wtap *wth; - gchar *err_info; + wtap *wth; + gchar *err_info; - wth = wtap_open_offline(fname, type, err, &err_info, TRUE); - if (wth == NULL) - goto fail; + wth = wtap_open_offline(fname, type, err, &err_info, TRUE); + if (wth == NULL) + goto fail; - /* The open succeeded. Close whatever capture file we had open, - and fill in the information for this file. */ - cf_close(cf); + /* The open succeeded. Close whatever capture file we had open, + and fill in the information for this file. */ + cf_close(cf); - /* Initialize the record metadata. */ - wtap_rec_init(&cf->rec); + /* Initialize the record metadata. */ + wtap_rec_init(&cf->rec); - /* XXX - we really want to initialize this after we've read all - the packets, so we know how much we'll ultimately need. */ - ws_buffer_init(&cf->buf, 1514); + /* XXX - we really want to initialize this after we've read all + the packets, so we know how much we'll ultimately need. */ + ws_buffer_init(&cf->buf, 1514); - /* We're about to start reading the file. */ - cf->state = FILE_READ_IN_PROGRESS; + /* We're about to start reading the file. */ + cf->state = FILE_READ_IN_PROGRESS; - cf->provider.wth = wth; - cf->f_datalen = 0; + cf->provider.wth = wth; + cf->f_datalen = 0; - /* Set the file name because we need it to set the follow stream filter. - XXX - is that still true? We need it for other reasons, though, - in any case. */ - cf->filename = g_strdup(fname); + /* Set the file name because we need it to set the follow stream filter. + XXX - is that still true? We need it for other reasons, though, + in any case. */ + cf->filename = g_strdup(fname); - /* Indicate whether it's a permanent or temporary file. */ - cf->is_tempfile = is_tempfile; + /* Indicate whether it's a permanent or temporary file. */ + cf->is_tempfile = is_tempfile; - /* No user changes yet. */ - cf->unsaved_changes = FALSE; + /* No user changes yet. */ + cf->unsaved_changes = FALSE; - cf->computed_elapsed = 0; + cf->computed_elapsed = 0; - cf->cd_t = wtap_file_type_subtype(cf->provider.wth); - cf->open_type = type; - cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1); - cf->count = 0; - cf->packet_comment_count = 0; - cf->displayed_count = 0; - cf->marked_count = 0; - cf->ignored_count = 0; - cf->ref_time_count = 0; - cf->drops_known = FALSE; - cf->drops = 0; - cf->snap = wtap_snapshot_length(cf->provider.wth); + cf->cd_t = wtap_file_type_subtype(cf->provider.wth); + cf->open_type = type; + cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1); + cf->count = 0; + cf->packet_comment_count = 0; + cf->displayed_count = 0; + cf->marked_count = 0; + cf->ignored_count = 0; + cf->ref_time_count = 0; + cf->drops_known = FALSE; + cf->drops = 0; + cf->snap = wtap_snapshot_length(cf->provider.wth); - /* Allocate a frame_data_sequence for the frames in this file */ - cf->provider.frames = new_frame_data_sequence(); + /* Allocate a frame_data_sequence for the frames in this file */ + cf->provider.frames = new_frame_data_sequence(); - nstime_set_zero(&cf->elapsed_time); - cf->provider.ref = NULL; - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; - cf->cum_bytes = 0; + nstime_set_zero(&cf->elapsed_time); + cf->provider.ref = NULL; + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; + cf->cum_bytes = 0; - /* Create new epan session for dissection. - * (The old one was freed in cf_close().) - */ - cf->epan = ws_epan_new(cf); + /* Create new epan session for dissection. + * (The old one was freed in cf_close().) + */ + cf->epan = ws_epan_new(cf); - packet_list_queue_draw(); - cf_callback_invoke(cf_cb_file_opened, cf); + packet_list_queue_draw(); + cf_callback_invoke(cf_cb_file_opened, cf); - wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name); - wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name); - wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); + wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name); + wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name); + wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); - return CF_OK; + return CF_OK; fail: - cfile_open_failure_alert_box(fname, *err, err_info); - return CF_ERROR; + cfile_open_failure_alert_box(fname, *err, err_info); + return CF_ERROR; } /* @@ -350,100 +350,100 @@ fail: static void cf_add_encapsulation_type(capture_file *cf, int encap) { - guint i; + guint i; - for (i = 0; i < cf->linktypes->len; i++) { - if (g_array_index(cf->linktypes, gint, i) == encap) - return; /* it's already there */ - } - /* It's not already there - add it. */ - g_array_append_val(cf->linktypes, encap); + for (i = 0; i < cf->linktypes->len; i++) { + if (g_array_index(cf->linktypes, gint, i) == encap) + return; /* it's already there */ + } + /* It's not already there - add it. */ + g_array_append_val(cf->linktypes, encap); } /* Reset everything to a pristine state */ void cf_close(capture_file *cf) { - cf->stop_flag = FALSE; - if (cf->state == FILE_CLOSED) - return; /* Nothing to do */ + cf->stop_flag = FALSE; + if (cf->state == FILE_CLOSED) + return; /* Nothing to do */ - /* Die if we're in the middle of reading a file. */ - ws_assert(cf->state != FILE_READ_IN_PROGRESS); - ws_assert(!cf->read_lock); + /* Die if we're in the middle of reading a file. */ + ws_assert(cf->state != FILE_READ_IN_PROGRESS); + ws_assert(!cf->read_lock); - cf_callback_invoke(cf_cb_file_closing, cf); + cf_callback_invoke(cf_cb_file_closing, cf); - /* close things, if not already closed before */ - color_filters_cleanup(); + /* close things, if not already closed before */ + color_filters_cleanup(); - if (cf->provider.wth) { - wtap_close(cf->provider.wth); - cf->provider.wth = NULL; - } - /* We have no file open... */ - if (cf->filename != NULL) { - /* If it's a temporary file, remove it. */ - if (cf->is_tempfile) - ws_unlink(cf->filename); - g_free(cf->filename); - cf->filename = NULL; - } - /* ...which means we have no changes to that file to save. */ - cf->unsaved_changes = FALSE; + if (cf->provider.wth) { + wtap_close(cf->provider.wth); + cf->provider.wth = NULL; + } + /* We have no file open... */ + if (cf->filename != NULL) { + /* If it's a temporary file, remove it. */ + if (cf->is_tempfile) + ws_unlink(cf->filename); + g_free(cf->filename); + cf->filename = NULL; + } + /* ...which means we have no changes to that file to save. */ + cf->unsaved_changes = FALSE; - /* no open_routine type */ - cf->open_type = WTAP_TYPE_AUTO; + /* no open_routine type */ + cf->open_type = WTAP_TYPE_AUTO; - /* Clean up the record metadata. */ - wtap_rec_cleanup(&cf->rec); + /* Clean up the record metadata. */ + wtap_rec_cleanup(&cf->rec); - /* Clear the packet list. */ - packet_list_freeze(); - packet_list_clear(); - packet_list_thaw(); + /* Clear the packet list. */ + packet_list_freeze(); + packet_list_clear(); + packet_list_thaw(); - /* Free up the packet buffer. */ - ws_buffer_free(&cf->buf); + /* Free up the packet buffer. */ + ws_buffer_free(&cf->buf); - dfilter_free(cf->rfcode); - cf->rfcode = NULL; - if (cf->provider.frames != NULL) { - free_frame_data_sequence(cf->provider.frames); - cf->provider.frames = NULL; - } - if (cf->provider.frames_modified_blocks) { - g_tree_destroy(cf->provider.frames_modified_blocks); - cf->provider.frames_modified_blocks = NULL; - } - cf_unselect_packet(cf); /* nothing to select */ - cf->first_displayed = 0; - cf->last_displayed = 0; + dfilter_free(cf->rfcode); + cf->rfcode = NULL; + if (cf->provider.frames != NULL) { + free_frame_data_sequence(cf->provider.frames); + cf->provider.frames = NULL; + } + if (cf->provider.frames_modified_blocks) { + g_tree_destroy(cf->provider.frames_modified_blocks); + cf->provider.frames_modified_blocks = NULL; + } + cf_unselect_packet(cf); /* nothing to select */ + cf->first_displayed = 0; + cf->last_displayed = 0; - /* No frames, no frame selected, no field in that frame selected. */ - cf->count = 0; - cf->current_frame = NULL; - cf->current_row = 0; - cf->finfo_selected = NULL; + /* No frames, no frame selected, no field in that frame selected. */ + cf->count = 0; + cf->current_frame = NULL; + cf->current_row = 0; + cf->finfo_selected = NULL; - /* No frame link-layer types, either. */ - if (cf->linktypes != NULL) { - g_array_free(cf->linktypes, TRUE); - cf->linktypes = NULL; - } + /* No frame link-layer types, either. */ + if (cf->linktypes != NULL) { + g_array_free(cf->linktypes, TRUE); + cf->linktypes = NULL; + } - cf->f_datalen = 0; - nstime_set_zero(&cf->elapsed_time); + cf->f_datalen = 0; + nstime_set_zero(&cf->elapsed_time); - reset_tap_listeners(); + reset_tap_listeners(); - epan_free(cf->epan); - cf->epan = NULL; + epan_free(cf->epan); + cf->epan = NULL; - /* We have no file open. */ - cf->state = FILE_CLOSED; + /* We have no file open. */ + cf->state = FILE_CLOSED; - cf_callback_invoke(cf_cb_file_closed, cf); + cf_callback_invoke(cf_cb_file_closed, cf); } /* @@ -453,797 +453,808 @@ cf_close(capture_file *cf) static inline gboolean progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos) { - double elapsed; + double elapsed; - if (progdlg) return FALSE; - elapsed = g_timer_elapsed(prog_timer, NULL); - if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */ - || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */ - return TRUE; - } - return FALSE; + if (progdlg) return FALSE; + elapsed = g_timer_elapsed(prog_timer, NULL); + if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */ + || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */ + return TRUE; + } + return FALSE; } static float calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size) { - float progbar_val; + float progbar_val; - progbar_val = (gfloat) file_pos / (gfloat) size; - if (progbar_val > 1.0) { + progbar_val = (gfloat) file_pos / (gfloat) size; + if (progbar_val > 1.0) { - /* The file probably grew while we were reading it. - * Update file size, and try again. - */ - size = wtap_file_size(cf->provider.wth, NULL); + /* The file probably grew while we were reading it. + * Update file size, and try again. + */ + size = wtap_file_size(cf->provider.wth, NULL); - if (size >= 0) - progbar_val = (gfloat) file_pos / (gfloat) size; + if (size >= 0) + progbar_val = (gfloat) file_pos / (gfloat) size; - /* If it's still > 1, either "wtap_file_size()" failed (in which - * case there's not much we can do about it), or the file - * *shrank* (in which case there's not much we can do about - * it); just clip the progress value at 1.0. - */ - if (progbar_val > 1.0f) - progbar_val = 1.0f; - } + /* If it's still > 1, either "wtap_file_size()" failed (in which + * case there's not much we can do about it), or the file + * *shrank* (in which case there's not much we can do about + * it); just clip the progress value at 1.0. + */ + if (progbar_val > 1.0f) + progbar_val = 1.0f; + } - snprintf(status_str, status_size, - "%" PRId64 "KB of %" PRId64 "KB", - file_pos / 1024, size / 1024); + snprintf(status_str, status_size, + "%" PRId64 "KB of %" PRId64 "KB", + file_pos / 1024, size / 1024); - return progbar_val; + return progbar_val; } cf_read_status_t cf_read(capture_file *cf, gboolean reloading) { - int err = 0; - gchar *err_info = NULL; - volatile gboolean too_many_records = FALSE; - gchar *name_ptr; - progdlg_t *volatile progbar = NULL; - GTimer *prog_timer = g_timer_new(); - gint64 size; - gint64 start_time; - epan_dissect_t edt; - wtap_rec rec; - Buffer buf; - dfilter_t *dfcode; - column_info *cinfo; - volatile gboolean create_proto_tree; - guint tap_flags; - gboolean compiled _U_; - volatile gboolean is_read_aborted = FALSE; + int err = 0; + gchar *err_info = NULL; + volatile gboolean too_many_records = FALSE; + gchar *name_ptr; + progdlg_t *volatile progbar = NULL; + GTimer *prog_timer = g_timer_new(); + gint64 size; + gint64 start_time; + epan_dissect_t edt; + wtap_rec rec; + Buffer buf; + dfilter_t *dfcode; + column_info *cinfo; + volatile gboolean create_proto_tree; + guint tap_flags; + gboolean compiled _U_; + volatile gboolean is_read_aborted = FALSE; - /* The update_progress_dlg call below might end up accepting a user request to - * trigger redissection/rescans which can modify/destroy the dissection - * context ("cf->epan"). That condition should be prevented by callers, but in - * case it occurs let's fail gracefully. - */ - if (cf->read_lock) { - ws_warning("Failing due to recursive cf_read(\"%s\", %d) call!", - cf->filename, reloading); - return CF_READ_ERROR; - } - cf->read_lock = TRUE; - - /* Compile the current display filter. - * We assume this will not fail since cf->dfilter is only set in - * cf_filter IFF the filter was valid. - */ - compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); - ws_assert(!cf->dfilter || (compiled && dfcode)); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * a postdissector wants field values or protocols on - * the first pass. - */ - create_proto_tree = - (dfcode != NULL || have_filtering_tap_listeners() || - (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); - - reset_tap_listeners(); - - name_ptr = g_filename_display_basename(cf->filename); - - if (reloading) - cf_callback_invoke(cf_cb_file_reload_started, cf); - else - cf_callback_invoke(cf_cb_file_read_started, cf); - - /* Record the file's compression type. - XXX - do we know this at open time? */ - cf->compression_type = wtap_get_compression_type(cf->provider.wth); - - /* The packet list window will be empty until the file is completly loaded */ - packet_list_freeze(); - - cf->stop_flag = FALSE; - start_time = g_get_monotonic_time(); - - epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); - - /* If any tap listeners require the columns, construct them. */ - cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - - /* Find the size of the file. */ - size = wtap_file_size(cf->provider.wth, NULL); - - g_timer_start(prog_timer); - - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - - TRY { - guint32 count = 0; - - gint64 file_pos; - gint64 data_offset; - - float progbar_val; - gchar status_str[100]; - - while ((wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, - &data_offset))) { - if (size >= 0) { - if (cf->count == max_records) { - /* - * Quit if we've already read the maximum number of - * records allowed. - */ - too_many_records = TRUE; - break; - } - count++; - file_pos = wtap_read_so_far(cf->provider.wth); - - /* Create the progress bar if necessary. */ - if (progress_is_slow(progbar, prog_timer, size, file_pos)) { - progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); - progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, TRUE, - &cf->stop_flag, progbar_val); - } - - /* - * Update the progress bar, but do it only after - * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg - * and packets_bar_update will likely trigger UI paint events, which - * might take a while depending on the platform and display. Reset - * our timer *after* painting. - */ - if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); - /* update the packet bar content on the first run or frequently on very large files */ - update_progress_dlg(progbar, progbar_val, status_str); - compute_elapsed(cf, start_time); - packets_bar_update(); - g_timer_start(prog_timer); - } - /* - * The previous GUI triggers should not have destroyed the running - * session. If that did happen, it could blow up when read_record tries - * to use the destroyed edt.session, so detect it right here. - */ - ws_assert(edt.session == cf->epan); - } - - if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to exit Wireshark. Break out of the - loop, and let the code below (which is called even if there - aren't any packets left to read) exit. */ - is_read_aborted = TRUE; - break; - } - if (cf->stop_flag) { - /* Well, the user decided to abort the read. He/She will be warned and - it might be enough for him/her to work with the already loaded - packets. - This is especially true for very large capture files, where you don't - want to wait loading the whole file (which may last minutes or even - hours even on fast machines) just to see that it was the wrong file. */ - break; - } - read_record(cf, &rec, &buf, dfcode, &edt, cinfo, data_offset); - wtap_rec_reset(&rec); - } - } - CATCH(OutOfMemoryError) { - simple_message_box(ESD_TYPE_ERROR, NULL, - "More information and workarounds can be found at\n" - WS_WIKI_URL("KnownBugs/OutOfMemory"), - "Sorry, but Wireshark has run out of memory and has to terminate now."); -#if 0 - /* Could we close the current capture and free up memory from that? */ -#else - /* we have to terminate, as we cannot recover from the memory error */ - exit(1); -#endif - } - ENDTRY; - - /* We're done reading sequentially through the file. */ - cf->state = FILE_READ_DONE; - - /* Destroy the progress bar if it was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); - - /* Free the display name */ - g_free(name_ptr); - - /* Cleanup and release all dfilter resources */ - dfilter_free(dfcode); - - epan_dissect_cleanup(&edt); - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - - /* Close the sequential I/O side, to free up memory it requires. */ - wtap_sequential_close(cf->provider.wth); - - /* Allow the protocol dissectors to free up memory that they - * don't need after the sequential run-through of the packets. */ - postseq_cleanup_all_protocols(); - - /* compute the time it took to load the file */ - compute_elapsed(cf, start_time); - - /* Set the file encapsulation type now; we don't know what it is until - we've looked at all the packets, as we don't know until then whether - there's more than one type (and thus whether it's - WTAP_ENCAP_PER_PACKET). */ - cf->lnk_t = wtap_file_encap(cf->provider.wth); - - cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed); - cf->current_row = 0; - - packet_list_thaw(); - if (reloading) - cf_callback_invoke(cf_cb_file_reload_finished, cf); - else - cf_callback_invoke(cf_cb_file_read_finished, cf); - - /* If we have any displayed packets to select, select the first of those - packets by making the first row the selected row. */ - if (cf->first_displayed != 0) { - packet_list_select_first_row(); - } - - /* It is safe again to execute redissections. */ - ws_assert(cf->read_lock); - cf->read_lock = FALSE; - - if (is_read_aborted) { - /* - * Well, the user decided to exit Wireshark while reading this *offline* - * capture file (Live captures are handled by something like - * cf_continue_tail). Clean up accordingly. + /* The update_progress_dlg call below might end up accepting a user request to + * trigger redissection/rescans which can modify/destroy the dissection + * context ("cf->epan"). That condition should be prevented by callers, but in + * case it occurs let's fail gracefully. */ - cf_close(cf); - cf->redissection_queued = RESCAN_NONE; - return CF_READ_ABORTED; - } + if (cf->read_lock) { + ws_warning("Failing due to recursive cf_read(\"%s\", %d) call!", + cf->filename, reloading); + return CF_READ_ERROR; + } + cf->read_lock = TRUE; - if (cf->redissection_queued != RESCAN_NONE) { - /* Redissection was queued up. Clear the request and perform it now. */ - gboolean redissect = cf->redissection_queued == RESCAN_REDISSECT; - rescan_packets(cf, NULL, NULL, redissect); - } + /* Compile the current display filter. + * We assume this will not fail since cf->dfilter is only set in + * cf_filter IFF the filter was valid. + */ + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); + ws_assert(!cf->dfilter || (compiled && dfcode)); - if (cf->stop_flag) { - simple_message_box(ESD_TYPE_WARN, NULL, - "The remaining packets in the file were discarded.\n" - "\n" - "As a lot of packets from the original file will be missing,\n" - "remember to be careful when saving the current content to a file.\n", - "File loading was cancelled."); - return CF_READ_ERROR; - } + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - if (err != 0) { - /* Put up a message box noting that the read failed somewhere along - the line. Don't throw out the stuff we managed to read, though, - if any. */ - cfile_read_failure_alert_box(NULL, err, err_info); - return CF_READ_ERROR; - } else if (too_many_records) { - simple_message_box(ESD_TYPE_WARN, NULL, - "The remaining packets in the file were discarded.\n" - "\n" - "As a lot of packets from the original file will be missing,\n" - "remember to be careful when saving the current content to a file.\n" - "\n" - "The command-line utility editcap can be used to split " - "the file into multiple smaller files", - "The file contains more records than the maximum " - "supported number of records, %u.", max_records); - return CF_READ_ERROR; - } else - return CF_READ_OK; + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * a postdissector wants field values or protocols on + * the first pass. + */ + create_proto_tree = + (dfcode != NULL || have_filtering_tap_listeners() || + (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); + + reset_tap_listeners(); + + name_ptr = g_filename_display_basename(cf->filename); + + if (reloading) + cf_callback_invoke(cf_cb_file_reload_started, cf); + else + cf_callback_invoke(cf_cb_file_read_started, cf); + + /* Record the file's compression type. + XXX - do we know this at open time? */ + cf->compression_type = wtap_get_compression_type(cf->provider.wth); + + /* The packet list window will be empty until the file is completly loaded */ + packet_list_freeze(); + + cf->stop_flag = FALSE; + start_time = g_get_monotonic_time(); + + epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + + /* If any tap listeners require the columns, construct them. */ + cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; + + /* Find the size of the file. */ + size = wtap_file_size(cf->provider.wth, NULL); + + g_timer_start(prog_timer); + + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + + TRY { + guint32 count = 0; + + gint64 file_pos; + gint64 data_offset; + + float progbar_val; + gchar status_str[100]; + + while ((wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, + &data_offset))) { + if (size >= 0) { + if (cf->count == max_records) { + /* + * Quit if we've already read the maximum number of + * records allowed. + */ + too_many_records = TRUE; + break; + } + count++; + file_pos = wtap_read_so_far(cf->provider.wth); + + /* Create the progress bar if necessary. */ + if (progress_is_slow(progbar, prog_timer, size, file_pos)) { + progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); + progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, TRUE, + &cf->stop_flag, progbar_val); + } + + /* + * Update the progress bar, but do it only after + * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg + * and packets_bar_update will likely trigger UI paint events, which + * might take a while depending on the platform and display. Reset + * our timer *after* painting. + */ + if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str)); + /* update the packet bar content on the first run or frequently on very large files */ + update_progress_dlg(progbar, progbar_val, status_str); + compute_elapsed(cf, start_time); + packets_bar_update(); + g_timer_start(prog_timer); + } + /* + * The previous GUI triggers should not have destroyed the running + * session. If that did happen, it could blow up when read_record tries + * to use the destroyed edt.session, so detect it right here. + */ + ws_assert(edt.session == cf->epan); + } + + if (cf->state == FILE_READ_ABORTED) { + /* Well, the user decided to exit Wireshark. Break out of the + loop, and let the code below (which is called even if there + aren't any packets left to read) exit. */ + is_read_aborted = TRUE; + break; + } + if (cf->stop_flag) { + /* Well, the user decided to abort the read. He/She will be warned and + it might be enough for him/her to work with the already loaded + packets. + This is especially true for very large capture files, where you don't + want to wait loading the whole file (which may last minutes or even + hours even on fast machines) just to see that it was the wrong file. */ + break; + } + read_record(cf, &rec, &buf, dfcode, &edt, cinfo, data_offset); + wtap_rec_reset(&rec); + } + } + CATCH(OutOfMemoryError) { + simple_message_box(ESD_TYPE_ERROR, NULL, + "More information and workarounds can be found at\n" + WS_WIKI_URL("KnownBugs/OutOfMemory"), + "Sorry, but Wireshark has run out of memory and has to terminate now."); +#if 0 + /* Could we close the current capture and free up memory from that? */ +#else + /* we have to terminate, as we cannot recover from the memory error */ + exit(1); +#endif + } + ENDTRY; + + /* We're done reading sequentially through the file. */ + cf->state = FILE_READ_DONE; + + /* Destroy the progress bar if it was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); + + /* Free the display name */ + g_free(name_ptr); + + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); + + epan_dissect_cleanup(&edt); + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + + /* Close the sequential I/O side, to free up memory it requires. */ + wtap_sequential_close(cf->provider.wth); + + /* Allow the protocol dissectors to free up memory that they + * don't need after the sequential run-through of the packets. */ + postseq_cleanup_all_protocols(); + + /* compute the time it took to load the file */ + compute_elapsed(cf, start_time); + + /* Set the file encapsulation type now; we don't know what it is until + we've looked at all the packets, as we don't know until then whether + there's more than one type (and thus whether it's + WTAP_ENCAP_PER_PACKET). */ + cf->lnk_t = wtap_file_encap(cf->provider.wth); + + cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed); + cf->current_row = 0; + + packet_list_thaw(); + if (reloading) + cf_callback_invoke(cf_cb_file_reload_finished, cf); + else + cf_callback_invoke(cf_cb_file_read_finished, cf); + + /* If we have any displayed packets to select, select the first of those + packets by making the first row the selected row. */ + if (cf->first_displayed != 0) { + packet_list_select_first_row(); + } + + /* It is safe again to execute redissections. */ + ws_assert(cf->read_lock); + cf->read_lock = FALSE; + + if (is_read_aborted) { + /* + * Well, the user decided to exit Wireshark while reading this *offline* + * capture file (Live captures are handled by something like + * cf_continue_tail). Clean up accordingly. + */ + cf_close(cf); + cf->redissection_queued = RESCAN_NONE; + return CF_READ_ABORTED; + } + + if (cf->redissection_queued != RESCAN_NONE) { + /* Redissection was queued up. Clear the request and perform it now. */ + gboolean redissect = cf->redissection_queued == RESCAN_REDISSECT; + rescan_packets(cf, NULL, NULL, redissect); + } + + if (cf->stop_flag) { + simple_message_box(ESD_TYPE_WARN, NULL, + "The remaining packets in the file were discarded.\n" + "\n" + "As a lot of packets from the original file will be missing,\n" + "remember to be careful when saving the current content to a file.\n", + "File loading was cancelled."); + return CF_READ_ERROR; + } + + if (err != 0) { + /* Put up a message box noting that the read failed somewhere along + the line. Don't throw out the stuff we managed to read, though, + if any. */ + cfile_read_failure_alert_box(NULL, err, err_info); + return CF_READ_ERROR; + } else if (too_many_records) { + simple_message_box(ESD_TYPE_WARN, NULL, + "The remaining packets in the file were discarded.\n" + "\n" + "As a lot of packets from the original file will be missing,\n" + "remember to be careful when saving the current content to a file.\n" + "\n" + "The command-line utility editcap can be used to split " + "the file into multiple smaller files", + "The file contains more records than the maximum " + "supported number of records, %u.", max_records); + return CF_READ_ERROR; + } else + return CF_READ_OK; } #ifdef HAVE_LIBPCAP cf_read_status_t cf_continue_tail(capture_file *cf, volatile int to_read, wtap_rec *rec, - Buffer *buf, int *err) + Buffer *buf, int *err) { - gchar *err_info; - volatile int newly_displayed_packets = 0; - dfilter_t *dfcode; - epan_dissect_t edt; - gboolean create_proto_tree; - guint tap_flags; - gboolean compiled _U_; + gchar *err_info; + volatile int newly_displayed_packets = 0; + dfilter_t *dfcode; + epan_dissect_t edt; + gboolean create_proto_tree; + guint tap_flags; + gboolean compiled _U_; - /* Compile the current display filter. - * We assume this will not fail since cf->dfilter is only set in - * cf_filter IFF the filter was valid. - */ - compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); - ws_assert(!cf->dfilter || (compiled && dfcode)); + /* Compile the current display filter. + * We assume this will not fail since cf->dfilter is only set in + * cf_filter IFF the filter was valid. + */ + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); + ws_assert(!cf->dfilter || (compiled && dfcode)); - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * a postdissector wants field values or protocols on - * the first pass. - */ - create_proto_tree = - (dfcode != NULL || have_filtering_tap_listeners() || - (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * a postdissector wants field values or protocols on + * the first pass. + */ + create_proto_tree = + (dfcode != NULL || have_filtering_tap_listeners() || + (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); - *err = 0; + *err = 0; - /* Don't freeze/thaw the list when doing live capture */ - /*packet_list_freeze();*/ + /* Don't freeze/thaw the list when doing live capture */ + /*packet_list_freeze();*/ - epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); - TRY { - gint64 data_offset = 0; - column_info *cinfo; + TRY { + gint64 data_offset = 0; + column_info *cinfo; - /* If any tap listeners require the columns, construct them. */ - cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; + /* If any tap listeners require the columns, construct them. */ + cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - while (to_read != 0) { - wtap_cleareof(cf->provider.wth); - if (!wtap_read(cf->provider.wth, rec, buf, err, &err_info, - &data_offset)) { - break; - } - if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to exit Wireshark. Break out of the - loop, and let the code below (which is called even if there - aren't any packets left to read) exit. */ - break; - } - if (read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset)) { - newly_displayed_packets++; - } - to_read--; + while (to_read != 0) { + wtap_cleareof(cf->provider.wth); + if (!wtap_read(cf->provider.wth, rec, buf, err, &err_info, + &data_offset)) { + break; + } + if (cf->state == FILE_READ_ABORTED) { + /* Well, the user decided to exit Wireshark. Break out of the + loop, and let the code below (which is called even if there + aren't any packets left to read) exit. */ + break; + } + if (read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset)) { + newly_displayed_packets++; + } + to_read--; + } + wtap_rec_reset(rec); } - wtap_rec_reset(rec); - } - CATCH(OutOfMemoryError) { - simple_message_box(ESD_TYPE_ERROR, NULL, - "More information and workarounds can be found at\n" - WS_WIKI_URL("KnownBugs/OutOfMemory"), - "Sorry, but Wireshark has run out of memory and has to terminate now."); + CATCH(OutOfMemoryError) { + simple_message_box(ESD_TYPE_ERROR, NULL, + "More information and workarounds can be found at\n" + WS_WIKI_URL("KnownBugs/OutOfMemory"), + "Sorry, but Wireshark has run out of memory and has to terminate now."); #if 0 - /* Could we close the current capture and free up memory from that? */ - return CF_READ_ABORTED; + /* Could we close the current capture and free up memory from that? */ + return CF_READ_ABORTED; #else - /* we have to terminate, as we cannot recover from the memory error */ - exit(1); + /* we have to terminate, as we cannot recover from the memory error */ + exit(1); #endif - } - ENDTRY; - - /* Update the file encapsulation; it might have changed based on the - packets we've read. */ - cf->lnk_t = wtap_file_encap(cf->provider.wth); - - /* Cleanup and release all dfilter resources */ - dfilter_free(dfcode); - - epan_dissect_cleanup(&edt); - - /* Don't freeze/thaw the list when doing live capture */ - /*packet_list_thaw();*/ - /* With the new packet list the first packet - * isn't automatically selected. - */ - if (!cf->current_frame && !packet_list_multi_select_active()) - packet_list_select_first_row(); - - /* moving to the end of the packet list - if the user requested so and - we have some new packets. */ - if (newly_displayed_packets && cf->count != 0) - packet_list_moveto_end(); - - if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED - so that our caller can kill off the capture child process; - this will cause an EOF on the pipe from the child, so - "cf_finish_tail()" will be called, and it will clean up - and exit. */ - return CF_READ_ABORTED; - } else if (*err != 0) { - /* We got an error reading the capture file. - XXX - pop up a dialog box instead? */ - if (err_info != NULL) { - ws_warning("Error \"%s\" while reading \"%s\" (\"%s\")", - wtap_strerror(*err), cf->filename, err_info); - g_free(err_info); - } else { - ws_warning("Error \"%s\" while reading \"%s\"", - wtap_strerror(*err), cf->filename); } - return CF_READ_ERROR; - } else - return CF_READ_OK; + ENDTRY; + + /* Update the file encapsulation; it might have changed based on the + packets we've read. */ + cf->lnk_t = wtap_file_encap(cf->provider.wth); + + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); + + epan_dissect_cleanup(&edt); + + /* Don't freeze/thaw the list when doing live capture */ + /*packet_list_thaw();*/ + /* With the new packet list the first packet + * isn't automatically selected. + */ + if (!cf->current_frame && !packet_list_multi_select_active()) + packet_list_select_first_row(); + + /* moving to the end of the packet list - if the user requested so and + we have some new packets. */ + if (newly_displayed_packets && cf->count != 0) + packet_list_moveto_end(); + + if (cf->state == FILE_READ_ABORTED) { + /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED + so that our caller can kill off the capture child process; + this will cause an EOF on the pipe from the child, so + "cf_finish_tail()" will be called, and it will clean up + and exit. */ + return CF_READ_ABORTED; + } else if (*err != 0) { + /* We got an error reading the capture file. + XXX - pop up a dialog box instead? */ + if (err_info != NULL) { + ws_warning("Error \"%s\" while reading \"%s\" (\"%s\")", + wtap_strerror(*err), cf->filename, err_info); + g_free(err_info); + } else { + ws_warning("Error \"%s\" while reading \"%s\"", + wtap_strerror(*err), cf->filename); + } + return CF_READ_ERROR; + } else + return CF_READ_OK; } void -cf_fake_continue_tail(capture_file *cf) { - cf->state = FILE_READ_DONE; +cf_fake_continue_tail(capture_file *cf) +{ + cf->state = FILE_READ_DONE; } cf_read_status_t cf_finish_tail(capture_file *cf, wtap_rec *rec, Buffer *buf, int *err) { - gchar *err_info; - gint64 data_offset; - dfilter_t *dfcode; - column_info *cinfo; - epan_dissect_t edt; - gboolean create_proto_tree; - guint tap_flags; - gboolean compiled _U_; + gchar *err_info; + gint64 data_offset; + dfilter_t *dfcode; + column_info *cinfo; + epan_dissect_t edt; + gboolean create_proto_tree; + guint tap_flags; + gboolean compiled _U_; - /* Compile the current display filter. - * We assume this will not fail since cf->dfilter is only set in - * cf_filter IFF the filter was valid. - */ - compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); - ws_assert(!cf->dfilter || (compiled && dfcode)); + /* Compile the current display filter. + * We assume this will not fail since cf->dfilter is only set in + * cf_filter IFF the filter was valid. + */ + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); + ws_assert(!cf->dfilter || (compiled && dfcode)); - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - /* If any tap listeners require the columns, construct them. */ - cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; + /* If any tap listeners require the columns, construct them. */ + cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * a postdissector wants field values or protocols on - * the first pass. - */ - create_proto_tree = - (dfcode != NULL || have_filtering_tap_listeners() || - (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * a postdissector wants field values or protocols on + * the first pass. + */ + create_proto_tree = + (dfcode != NULL || have_filtering_tap_listeners() || + (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids()); - if (cf->provider.wth == NULL) { - cf_close(cf); - return CF_READ_ERROR; - } + if (cf->provider.wth == NULL) { + cf_close(cf); + return CF_READ_ERROR; + } - /* Don't freeze/thaw the list when doing live capture */ - /*packet_list_freeze();*/ + /* Don't freeze/thaw the list when doing live capture */ + /*packet_list_freeze();*/ - epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + + while ((wtap_read(cf->provider.wth, rec, buf, err, &err_info, &data_offset))) { + if (cf->state == FILE_READ_ABORTED) { + /* Well, the user decided to abort the read. Break out of the + loop, and let the code below (which is called even if there + aren't any packets left to read) exit. */ + break; + } + read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset); + wtap_rec_reset(rec); + } + + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); + + epan_dissect_cleanup(&edt); + + /* Don't freeze/thaw the list when doing live capture */ + /*packet_list_thaw();*/ - while ((wtap_read(cf->provider.wth, rec, buf, err, &err_info, &data_offset))) { if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to abort the read. Break out of the - loop, and let the code below (which is called even if there - aren't any packets left to read) exit. */ - break; + /* Well, the user decided to abort the read. We're only called + when the child capture process closes the pipe to us (meaning + it's probably exited), so we can just close the capture + file; we return CF_READ_ABORTED so our caller can do whatever + is appropriate when that happens. */ + cf_close(cf); + return CF_READ_ABORTED; } - read_record(cf, rec, buf, dfcode, &edt, cinfo, data_offset); - wtap_rec_reset(rec); - } - /* Cleanup and release all dfilter resources */ - dfilter_free(dfcode); + /* We're done reading sequentially through the file. */ + cf->state = FILE_READ_DONE; - epan_dissect_cleanup(&edt); + /* We're done reading sequentially through the file; close the + sequential I/O side, to free up memory it requires. */ + wtap_sequential_close(cf->provider.wth); - /* Don't freeze/thaw the list when doing live capture */ - /*packet_list_thaw();*/ + /* Allow the protocol dissectors to free up memory that they + * don't need after the sequential run-through of the packets. */ + postseq_cleanup_all_protocols(); - if (cf->state == FILE_READ_ABORTED) { - /* Well, the user decided to abort the read. We're only called - when the child capture process closes the pipe to us (meaning - it's probably exited), so we can just close the capture - file; we return CF_READ_ABORTED so our caller can do whatever - is appropriate when that happens. */ - cf_close(cf); - return CF_READ_ABORTED; - } + /* Update the file encapsulation; it might have changed based on the + packets we've read. */ + cf->lnk_t = wtap_file_encap(cf->provider.wth); - /* We're done reading sequentially through the file. */ - cf->state = FILE_READ_DONE; + /* Update the details in the file-set dialog, as the capture file + * has likely grown since we first stat-ed it */ + fileset_update_file(cf->filename); - /* We're done reading sequentially through the file; close the - sequential I/O side, to free up memory it requires. */ - wtap_sequential_close(cf->provider.wth); - - /* Allow the protocol dissectors to free up memory that they - * don't need after the sequential run-through of the packets. */ - postseq_cleanup_all_protocols(); - - /* Update the file encapsulation; it might have changed based on the - packets we've read. */ - cf->lnk_t = wtap_file_encap(cf->provider.wth); - - /* Update the details in the file-set dialog, as the capture file - * has likely grown since we first stat-ed it */ - fileset_update_file(cf->filename); - - if (*err != 0) { - /* We got an error reading the capture file. - XXX - pop up a dialog box? */ - if (err_info != NULL) { - ws_warning("Error \"%s\" while reading \"%s\" (\"%s\")", - wtap_strerror(*err), cf->filename, err_info); - g_free(err_info); + if (*err != 0) { + /* We got an error reading the capture file. + XXX - pop up a dialog box? */ + if (err_info != NULL) { + ws_warning("Error \"%s\" while reading \"%s\" (\"%s\")", + wtap_strerror(*err), cf->filename, err_info); + g_free(err_info); + } else { + ws_warning("Error \"%s\" while reading \"%s\"", + wtap_strerror(*err), cf->filename); + } + return CF_READ_ERROR; } else { - ws_warning("Error \"%s\" while reading \"%s\"", - wtap_strerror(*err), cf->filename); + return CF_READ_OK; } - return CF_READ_ERROR; - } else { - return CF_READ_OK; - } } #endif /* HAVE_LIBPCAP */ gchar * cf_get_display_name(capture_file *cf) { - gchar *displayname; + gchar *displayname; - /* Return a name to use in displays */ - if (!cf->is_tempfile) { - /* Get the last component of the file name, and use that. */ - if (cf->filename) { - displayname = g_filename_display_basename(cf->filename); + /* Return a name to use in displays */ + if (!cf->is_tempfile) { + /* Get the last component of the file name, and use that. */ + if (cf->filename) { + displayname = g_filename_display_basename(cf->filename); + } else { + displayname=g_strdup("(No file)"); + } } else { - displayname=g_strdup("(No file)"); + /* The file we read is a temporary file from a live capture or + a merge operation; we don't mention its name, but, if it's + from a capture, give the source of the capture. */ + if (cf->source) { + displayname = g_strdup(cf->source); + } else { + displayname = g_strdup("(Untitled)"); + } } - } else { - /* The file we read is a temporary file from a live capture or - a merge operation; we don't mention its name, but, if it's - from a capture, give the source of the capture. */ - if (cf->source) { - displayname = g_strdup(cf->source); - } else { - displayname = g_strdup("(Untitled)"); - } - } - return displayname; + return displayname; } gchar * cf_get_basename(capture_file *cf) { - gchar *displayname; + gchar *displayname; - /* Return a name to use in the GUI for the basename for files to - which we save statistics */ - if (!cf->is_tempfile) { - /* Get the last component of the file name, and use that. */ - if (cf->filename) { - displayname = g_filename_display_basename(cf->filename); + /* Return a name to use in the GUI for the basename for files to + which we save statistics */ + if (!cf->is_tempfile) { + /* Get the last component of the file name, and use that. */ + if (cf->filename) { + displayname = g_filename_display_basename(cf->filename); - /* If the file name ends with any extension that corresponds - to a file type we support - including compressed versions - of those files - strip it off. */ - size_t displayname_len = strlen(displayname); - GSList *extensions = wtap_get_all_file_extensions_list(); - GSList *suffix; - for (suffix = extensions; suffix != NULL; suffix = g_slist_next(suffix)) { - /* Does the file name end with that extension? */ - const char *extension = (char *)suffix->data; - size_t extension_len = strlen(extension); - if (displayname_len > extension_len && - displayname[displayname_len - extension_len - 1] == '.' && - strcmp(&displayname[displayname_len - extension_len], extension) == 0) { - /* Yes. Strip the extension off, and return the result. */ - displayname[displayname_len - extension_len - 1] = '\0'; - break; + /* If the file name ends with any extension that corresponds + to a file type we support - including compressed versions + of those files - strip it off. */ + size_t displayname_len = strlen(displayname); + GSList *extensions = wtap_get_all_file_extensions_list(); + GSList *suffix; + for (suffix = extensions; suffix != NULL; suffix = g_slist_next(suffix)) { + /* Does the file name end with that extension? */ + const char *extension = (char *)suffix->data; + size_t extension_len = strlen(extension); + if (displayname_len > extension_len && + displayname[displayname_len - extension_len - 1] == '.' && + strcmp(&displayname[displayname_len - extension_len], extension) == 0) { + /* Yes. Strip the extension off, and return the result. */ + displayname[displayname_len - extension_len - 1] = '\0'; + break; + } + } + wtap_free_extensions_list(extensions); + } else { + displayname=g_strdup(""); } - } - wtap_free_extensions_list(extensions); } else { - displayname=g_strdup(""); + /* The file we read is a temporary file from a live capture or + a merge operation; we don't mention its name, but, if it's + from a capture, give the source of the capture. */ + if (cf->source) { + displayname = g_strdup(cf->source); + } else { + displayname = g_strdup(""); + } } - } else { - /* The file we read is a temporary file from a live capture or - a merge operation; we don't mention its name, but, if it's - from a capture, give the source of the capture. */ + return displayname; +} + +void +cf_set_tempfile_source(capture_file *cf, gchar *source) +{ if (cf->source) { - displayname = g_strdup(cf->source); - } else { - displayname = g_strdup(""); + g_free(cf->source); + } + + if (source) { + cf->source = g_strdup(source); + } else { + cf->source = g_strdup(""); } - } - return displayname; } -void cf_set_tempfile_source(capture_file *cf, gchar *source) { - if (cf->source) { - g_free(cf->source); - } +const gchar * +cf_get_tempfile_source(capture_file *cf) +{ + if (!cf->source) { + return ""; + } - if (source) { - cf->source = g_strdup(source); - } else { - cf->source = g_strdup(""); - } -} - -const gchar *cf_get_tempfile_source(capture_file *cf) { - if (!cf->source) { - return ""; - } - - return cf->source; + return cf->source; } /* XXX - use a macro instead? */ int cf_get_packet_count(capture_file *cf) { - return cf->count; + return cf->count; } /* XXX - use a macro instead? */ gboolean cf_is_tempfile(capture_file *cf) { - return cf->is_tempfile; + return cf->is_tempfile; } -void cf_set_tempfile(capture_file *cf, gboolean is_tempfile) +void +cf_set_tempfile(capture_file *cf, gboolean is_tempfile) { - cf->is_tempfile = is_tempfile; + cf->is_tempfile = is_tempfile; } /* XXX - use a macro instead? */ -void cf_set_drops_known(capture_file *cf, gboolean drops_known) +void +cf_set_drops_known(capture_file *cf, gboolean drops_known) { - cf->drops_known = drops_known; + cf->drops_known = drops_known; } /* XXX - use a macro instead? */ -void cf_set_drops(capture_file *cf, guint32 drops) +void +cf_set_drops(capture_file *cf, guint32 drops) { - cf->drops = drops; + cf->drops = drops; } /* XXX - use a macro instead? */ -gboolean cf_get_drops_known(capture_file *cf) +gboolean +cf_get_drops_known(capture_file *cf) { - return cf->drops_known; + return cf->drops_known; } /* XXX - use a macro instead? */ -guint32 cf_get_drops(capture_file *cf) +guint32 +cf_get_drops(capture_file *cf) { - return cf->drops; + return cf->drops; } -void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode) +void +cf_set_rfcode(capture_file *cf, dfilter_t *rfcode) { - cf->rfcode = rfcode; + cf->rfcode = rfcode; } static void add_packet_to_packet_list(frame_data *fdata, capture_file *cf, - epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo, - wtap_rec *rec, Buffer *buf, gboolean add_to_packet_list) + epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo, + wtap_rec *rec, Buffer *buf, gboolean add_to_packet_list) { - frame_data_set_before_dissect(fdata, &cf->elapsed_time, - &cf->provider.ref, cf->provider.prev_dis); - cf->provider.prev_cap = fdata; + frame_data_set_before_dissect(fdata, &cf->elapsed_time, + &cf->provider.ref, cf->provider.prev_dis); + cf->provider.prev_cap = fdata; - if (dfcode != NULL) { - epan_dissect_prime_with_dfilter(edt, dfcode); - } + if (dfcode != NULL) { + epan_dissect_prime_with_dfilter(edt, dfcode); + } #if 0 - /* Prepare coloring rules, this ensures that display filter rules containing - * frame.color_rule references are still processed. - * TODO: actually detect that situation or maybe apply other optimizations? */ - if (edt->tree && color_filters_used()) { - color_filters_prime_edt(edt); - fdata->need_colorize = 1; - } + /* Prepare coloring rules, this ensures that display filter rules containing + * frame.color_rule references are still processed. + * TODO: actually detect that situation or maybe apply other optimizations? */ + if (edt->tree && color_filters_used()) { + color_filters_prime_edt(edt); + fdata->need_colorize = 1; + } #endif - if (!fdata->visited) { - /* This is the first pass, so prime the epan_dissect_t with the - hfids postdissectors want on the first pass. */ - prime_epan_dissect_with_postdissector_wanted_hfids(edt); - } - - /* Dissect the frame. */ - epan_dissect_run_with_taps(edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, cinfo); - - /* If we don't have a display filter, set "passed_dfilter" to 1. */ - if (dfcode != NULL) { - fdata->passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0; - - if (fdata->passed_dfilter) { - /* This frame passed the display filter but it may depend on other - * (potentially not displayed) frames. Find those frames and mark them - * as depended upon. - */ - g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); + if (!fdata->visited) { + /* This is the first pass, so prime the epan_dissect_t with the + hfids postdissectors want on the first pass. */ + prime_epan_dissect_with_postdissector_wanted_hfids(edt); } - } else - fdata->passed_dfilter = 1; - if (fdata->passed_dfilter || fdata->ref_time) - cf->displayed_count++; + /* Dissect the frame. */ + epan_dissect_run_with_taps(edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, cinfo); - if (add_to_packet_list) { - /* We fill the needed columns from new_packet_list */ - packet_list_append(cinfo, fdata); - } + /* If we don't have a display filter, set "passed_dfilter" to 1. */ + if (dfcode != NULL) { + fdata->passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0; - if (fdata->passed_dfilter || fdata->ref_time) - { - frame_data_set_after_dissect(fdata, &cf->cum_bytes); - cf->provider.prev_dis = fdata; + if (fdata->passed_dfilter) { + /* This frame passed the display filter but it may depend on other + * (potentially not displayed) frames. Find those frames and mark them + * as depended upon. + */ + g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); + } + } else + fdata->passed_dfilter = 1; - /* If we haven't yet seen the first frame, this is it. */ - if (cf->first_displayed == 0) - cf->first_displayed = fdata->num; + if (fdata->passed_dfilter || fdata->ref_time) + cf->displayed_count++; - /* This is the last frame we've seen so far. */ - cf->last_displayed = fdata->num; - } + if (add_to_packet_list) { + /* We fill the needed columns from new_packet_list */ + packet_list_append(cinfo, fdata); + } - epan_dissect_reset(edt); + if (fdata->passed_dfilter || fdata->ref_time) + { + frame_data_set_after_dissect(fdata, &cf->cum_bytes); + cf->provider.prev_dis = fdata; + + /* If we haven't yet seen the first frame, this is it. */ + if (cf->first_displayed == 0) + cf->first_displayed = fdata->num; + + /* This is the last frame we've seen so far. */ + cf->last_displayed = fdata->num; + } + + epan_dissect_reset(edt); } /* @@ -1253,365 +1264,365 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, */ static gboolean read_record(capture_file *cf, wtap_rec *rec, Buffer *buf, dfilter_t *dfcode, - epan_dissect_t *edt, column_info *cinfo, gint64 offset) + epan_dissect_t *edt, column_info *cinfo, gint64 offset) { - frame_data fdlocal; - frame_data *fdata; - gboolean passed = TRUE; - gboolean added = FALSE; + frame_data fdlocal; + frame_data *fdata; + gboolean passed = TRUE; + gboolean added = FALSE; - /* Add this packet's link-layer encapsulation type to cf->linktypes, if - it's not already there. - XXX - yes, this is O(N), so if every packet had a different - link-layer encapsulation type, it'd be O(N^2) to read the file, but - there are probably going to be a small number of encapsulation types - in a file. */ - if (rec->rec_type == REC_TYPE_PACKET) { - cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap); - } - - /* The frame number of this packet, if we add it to the set of frames, - would be one more than the count of frames in the file so far. */ - frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes); - - if (cf->rfcode) { - epan_dissect_t rf_edt; - - epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE); - epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode); - epan_dissect_run(&rf_edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf), - &fdlocal, NULL); - passed = dfilter_apply_edt(cf->rfcode, &rf_edt); - epan_dissect_cleanup(&rf_edt); - } - - if (passed) { - added = TRUE; - - /* This does a shallow copy of fdlocal, which is good enough. */ - fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal); - - cf->count++; - if (rec->block != NULL) - cf->packet_comment_count += wtap_block_count_option(rec->block, OPT_COMMENT); - cf->f_datalen = offset + fdlocal.cap_len; - - /* When a redissection is in progress (or queued), do not process packets. - * This will be done once all (new) packets have been scanned. */ - if (!cf->redissecting && cf->redissection_queued == RESCAN_NONE) { - add_packet_to_packet_list(fdata, cf, edt, dfcode, cinfo, rec, buf, TRUE); + /* Add this packet's link-layer encapsulation type to cf->linktypes, if + it's not already there. + XXX - yes, this is O(N), so if every packet had a different + link-layer encapsulation type, it'd be O(N^2) to read the file, but + there are probably going to be a small number of encapsulation types + in a file. */ + if (rec->rec_type == REC_TYPE_PACKET) { + cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap); } - } - return added; + /* The frame number of this packet, if we add it to the set of frames, + would be one more than the count of frames in the file so far. */ + frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes); + + if (cf->rfcode) { + epan_dissect_t rf_edt; + + epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE); + epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode); + epan_dissect_run(&rf_edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf), + &fdlocal, NULL); + passed = dfilter_apply_edt(cf->rfcode, &rf_edt); + epan_dissect_cleanup(&rf_edt); + } + + if (passed) { + added = TRUE; + + /* This does a shallow copy of fdlocal, which is good enough. */ + fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal); + + cf->count++; + if (rec->block != NULL) + cf->packet_comment_count += wtap_block_count_option(rec->block, OPT_COMMENT); + cf->f_datalen = offset + fdlocal.cap_len; + + /* When a redissection is in progress (or queued), do not process packets. + * This will be done once all (new) packets have been scanned. */ + if (!cf->redissecting && cf->redissection_queued == RESCAN_NONE) { + add_packet_to_packet_list(fdata, cf, edt, dfcode, cinfo, rec, buf, TRUE); + } + } + + return added; } typedef struct _callback_data_t { - gpointer pd_window; - gint64 f_len; - progdlg_t *progbar; - GTimer *prog_timer; - gboolean stop_flag; + gpointer pd_window; + gint64 f_len; + progdlg_t *progbar; + GTimer *prog_timer; + gboolean stop_flag; } callback_data_t; static gboolean merge_callback(merge_event event, int num _U_, - const merge_in_file_t in_files[], const guint in_file_count, - void *data) + const merge_in_file_t in_files[], const guint in_file_count, + void *data) { - guint i; - callback_data_t *cb_data = (callback_data_t*) data; + guint i; + callback_data_t *cb_data = (callback_data_t*) data; - ws_assert(cb_data != NULL); + ws_assert(cb_data != NULL); - switch (event) { + switch (event) { - case MERGE_EVENT_INPUT_FILES_OPENED: - /* do nothing */ - break; + case MERGE_EVENT_INPUT_FILES_OPENED: + /* do nothing */ + break; - case MERGE_EVENT_FRAME_TYPE_SELECTED: - /* do nothing */ - break; + case MERGE_EVENT_FRAME_TYPE_SELECTED: + /* do nothing */ + break; - case MERGE_EVENT_READY_TO_MERGE: - /* Get the sum of the sizes of all the files. */ - for (i = 0; i < in_file_count; i++) - cb_data->f_len += in_files[i].size; - - cb_data->prog_timer = g_timer_new(); - g_timer_start(cb_data->prog_timer); - break; - - case MERGE_EVENT_RECORD_WAS_READ: - { - /* Create the progress bar if necessary. - We check on every iteration of the loop, so that it takes no - longer than the standard time to create it (otherwise, for a - large file, we might take considerably longer than that standard - time in order to get to the next progress bar step). */ - if (cb_data->progbar == NULL) { - cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, NULL, NULL, - FALSE, &cb_data->stop_flag, 0.0f); - } - - /* - * Update the progress bar, but do it only after - * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg - * and packets_bar_update will likely trigger UI paint events, which - * might take a while depending on the platform and display. Reset - * our timer *after* painting. - */ - if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - float progbar_val; - gint64 file_pos = 0; - /* Get the sum of the seek positions in all of the files. */ + case MERGE_EVENT_READY_TO_MERGE: + /* Get the sum of the sizes of all the files. */ for (i = 0; i < in_file_count; i++) - file_pos += wtap_read_so_far(in_files[i].wth); + cb_data->f_len += in_files[i].size; - progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len; - if (progbar_val > 1.0f) { - /* Some file probably grew while we were reading it. - That "shouldn't happen", so we'll just clip the progress - value at 1.0. */ - progbar_val = 1.0f; - } - - if (cb_data->progbar != NULL) { - gchar status_str[100]; - snprintf(status_str, sizeof(status_str), - "%" PRId64 "KB of %" PRId64 "KB", - file_pos / 1024, cb_data->f_len / 1024); - update_progress_dlg(cb_data->progbar, progbar_val, status_str); - } + cb_data->prog_timer = g_timer_new(); g_timer_start(cb_data->prog_timer); - } - } - break; + break; - case MERGE_EVENT_DONE: - /* We're done merging the files; destroy the progress bar if it was created. */ - if (cb_data->progbar != NULL) - destroy_progress_dlg(cb_data->progbar); - g_timer_destroy(cb_data->prog_timer); - break; - } + case MERGE_EVENT_RECORD_WAS_READ: + { + /* Create the progress bar if necessary. + We check on every iteration of the loop, so that it takes no + longer than the standard time to create it (otherwise, for a + large file, we might take considerably longer than that standard + time in order to get to the next progress bar step). */ + if (cb_data->progbar == NULL) { + cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, NULL, NULL, + FALSE, &cb_data->stop_flag, 0.0f); + } - return cb_data->stop_flag; + /* + * Update the progress bar, but do it only after + * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg + * and packets_bar_update will likely trigger UI paint events, which + * might take a while depending on the platform and display. Reset + * our timer *after* painting. + */ + if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + float progbar_val; + gint64 file_pos = 0; + /* Get the sum of the seek positions in all of the files. */ + for (i = 0; i < in_file_count; i++) + file_pos += wtap_read_so_far(in_files[i].wth); + + progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len; + if (progbar_val > 1.0f) { + /* Some file probably grew while we were reading it. + That "shouldn't happen", so we'll just clip the progress + value at 1.0. */ + progbar_val = 1.0f; + } + + if (cb_data->progbar != NULL) { + gchar status_str[100]; + snprintf(status_str, sizeof(status_str), + "%" PRId64 "KB of %" PRId64 "KB", + file_pos / 1024, cb_data->f_len / 1024); + update_progress_dlg(cb_data->progbar, progbar_val, status_str); + } + g_timer_start(cb_data->prog_timer); + } + } + break; + + case MERGE_EVENT_DONE: + /* We're done merging the files; destroy the progress bar if it was created. */ + if (cb_data->progbar != NULL) + destroy_progress_dlg(cb_data->progbar); + g_timer_destroy(cb_data->prog_timer); + break; + } + + return cb_data->stop_flag; } cf_status_t cf_merge_files_to_tempfile(gpointer pd_window, const char *temp_dir, char **out_filenamep, - int in_file_count, const char *const *in_filenames, - int file_type, gboolean do_append) + int in_file_count, const char *const *in_filenames, + int file_type, gboolean do_append) { - int err = 0; - gchar *err_info = NULL; - guint err_fileno; - guint32 err_framenum; - merge_result status; - merge_progress_callback_t cb; - callback_data_t *cb_data = g_new0(callback_data_t, 1); + int err = 0; + gchar *err_info = NULL; + guint err_fileno; + guint32 err_framenum; + merge_result status; + merge_progress_callback_t cb; + callback_data_t *cb_data = g_new0(callback_data_t, 1); - /* prepare our callback routine */ - cb_data->pd_window = pd_window; - cb.callback_func = merge_callback; - cb.data = cb_data; + /* prepare our callback routine */ + cb_data->pd_window = pd_window; + cb.callback_func = merge_callback; + cb.data = cb_data; - cf_callback_invoke(cf_cb_file_merge_started, NULL); + cf_callback_invoke(cf_cb_file_merge_started, NULL); - /* merge the files */ - status = merge_files_to_tempfile(temp_dir, out_filenamep, "wireshark", file_type, - in_filenames, - in_file_count, do_append, - IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */, - "Wireshark", &cb, &err, &err_info, - &err_fileno, &err_framenum); + /* merge the files */ + status = merge_files_to_tempfile(temp_dir, out_filenamep, "wireshark", file_type, + in_filenames, + in_file_count, do_append, + IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */, + "Wireshark", &cb, &err, &err_info, + &err_fileno, &err_framenum); - g_free(cb.data); + g_free(cb.data); - switch (status) { - case MERGE_OK: - break; + switch (status) { + case MERGE_OK: + break; - case MERGE_USER_ABORTED: - /* this isn't really an error, though we will return CF_ERROR later */ - break; + case MERGE_USER_ABORTED: + /* this isn't really an error, though we will return CF_ERROR later */ + break; - case MERGE_ERR_CANT_OPEN_INFILE: - cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info); - break; + case MERGE_ERR_CANT_OPEN_INFILE: + cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info); + break; - case MERGE_ERR_CANT_OPEN_OUTFILE: - cfile_dump_open_failure_alert_box(*out_filenamep, err, err_info, - file_type); - break; + case MERGE_ERR_CANT_OPEN_OUTFILE: + cfile_dump_open_failure_alert_box(*out_filenamep, err, err_info, + file_type); + break; - case MERGE_ERR_CANT_READ_INFILE: - cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info); - break; + case MERGE_ERR_CANT_READ_INFILE: + cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info); + break; - case MERGE_ERR_BAD_PHDR_INTERFACE_ID: - simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.", - err_framenum, in_filenames[err_fileno]); - break; + case MERGE_ERR_BAD_PHDR_INTERFACE_ID: + simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.", + err_framenum, in_filenames[err_fileno]); + break; - case MERGE_ERR_CANT_WRITE_OUTFILE: - cfile_write_failure_alert_box(in_filenames[err_fileno], - *out_filenamep, err, err_info, - err_framenum, file_type); - break; + case MERGE_ERR_CANT_WRITE_OUTFILE: + cfile_write_failure_alert_box(in_filenames[err_fileno], + *out_filenamep, err, err_info, + err_framenum, file_type); + break; - case MERGE_ERR_CANT_CLOSE_OUTFILE: - cfile_close_failure_alert_box(*out_filenamep, err, err_info); - break; + case MERGE_ERR_CANT_CLOSE_OUTFILE: + cfile_close_failure_alert_box(*out_filenamep, err, err_info); + break; - default: - simple_error_message_box("Unknown merge_files error %d", status); - break; - } + default: + simple_error_message_box("Unknown merge_files error %d", status); + break; + } - cf_callback_invoke(cf_cb_file_merge_finished, NULL); + cf_callback_invoke(cf_cb_file_merge_finished, NULL); - if (status != MERGE_OK) { - /* Callers aren't expected to treat an error or an explicit abort - differently - we put up error dialogs ourselves, so they don't - have to. */ - return CF_ERROR; - } else - return CF_OK; + if (status != MERGE_OK) { + /* Callers aren't expected to treat an error or an explicit abort + differently - we put up error dialogs ourselves, so they don't + have to. */ + return CF_ERROR; + } else + return CF_OK; } cf_status_t cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force) { - const char *filter_new = dftext ? dftext : ""; - const char *filter_old = cf->dfilter ? cf->dfilter : ""; - dfilter_t *dfcode; - gchar *err_msg; + const char *filter_new = dftext ? dftext : ""; + const char *filter_old = cf->dfilter ? cf->dfilter : ""; + dfilter_t *dfcode; + gchar *err_msg; + + /* if new filter equals old one, do nothing unless told to do so */ + if (!force && strcmp(filter_new, filter_old) == 0) { + return CF_OK; + } + + dfcode=NULL; + + if (dftext == NULL) { + /* The new filter is an empty filter (i.e., display all packets). + * so leave dfcode==NULL + */ + } else { + /* + * We have a filter; make a copy of it (as we'll be saving it), + * and try to compile it. + */ + dftext = g_strdup(dftext); + if (!dfilter_compile(dftext, &dfcode, &err_msg)) { + /* The attempt failed; report an error. */ + simple_message_box(ESD_TYPE_ERROR, NULL, + "See the help for a description of the display filter syntax.", + "\"%s\" isn't a valid display filter: %s", + dftext, err_msg); + g_free(err_msg); + g_free(dftext); + return CF_ERROR; + } + + /* Was it empty? */ + if (dfcode == NULL) { + /* Yes - free the filter text, and set it to null. */ + g_free(dftext); + dftext = NULL; + } + } + + /* We have a valid filter. Replace the current filter. */ + g_free(cf->dfilter); + cf->dfilter = dftext; + + + /* Now rescan the packet list, applying the new filter, but not + * throwing away information constructed on a previous pass. + * If a dissection is already in progress, queue it. + */ + if (cf->redissection_queued == RESCAN_NONE) { + if (cf->read_lock) { + cf->redissection_queued = RESCAN_SCAN; + } else if (cf->state != FILE_CLOSED) { + if (dftext == NULL) { + rescan_packets(cf, "Resetting", "filter", FALSE); + } else { + rescan_packets(cf, "Filtering", dftext, FALSE); + } + } + } + + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); - /* if new filter equals old one, do nothing unless told to do so */ - if (!force && strcmp(filter_new, filter_old) == 0) { return CF_OK; - } - - dfcode=NULL; - - if (dftext == NULL) { - /* The new filter is an empty filter (i.e., display all packets). - * so leave dfcode==NULL - */ - } else { - /* - * We have a filter; make a copy of it (as we'll be saving it), - * and try to compile it. - */ - dftext = g_strdup(dftext); - if (!dfilter_compile(dftext, &dfcode, &err_msg)) { - /* The attempt failed; report an error. */ - simple_message_box(ESD_TYPE_ERROR, NULL, - "See the help for a description of the display filter syntax.", - "\"%s\" isn't a valid display filter: %s", - dftext, err_msg); - g_free(err_msg); - g_free(dftext); - return CF_ERROR; - } - - /* Was it empty? */ - if (dfcode == NULL) { - /* Yes - free the filter text, and set it to null. */ - g_free(dftext); - dftext = NULL; - } - } - - /* We have a valid filter. Replace the current filter. */ - g_free(cf->dfilter); - cf->dfilter = dftext; - - - /* Now rescan the packet list, applying the new filter, but not - * throwing away information constructed on a previous pass. - * If a dissection is already in progress, queue it. - */ - if (cf->redissection_queued == RESCAN_NONE) { - if (cf->read_lock) { - cf->redissection_queued = RESCAN_SCAN; - } else if (cf->state != FILE_CLOSED) { - if (dftext == NULL) { - rescan_packets(cf, "Resetting", "filter", FALSE); - } else { - rescan_packets(cf, "Filtering", dftext, FALSE); - } - } - } - - /* Cleanup and release all dfilter resources */ - dfilter_free(dfcode); - - return CF_OK; } void cf_redissect_packets(capture_file *cf) { - if (cf->read_lock || cf->redissection_queued == RESCAN_SCAN) { - /* Dissection in progress, signal redissection rather than rescanning. That - * would destroy the current (in-progress) dissection in "cf_read" which - * will cause issues when "cf_read" tries to add packets to the list. - * If a previous rescan was requested, "upgrade" it to a full redissection. - */ - cf->redissection_queued = RESCAN_REDISSECT; - } - if (cf->redissection_queued != RESCAN_NONE) { - /* Redissection is (already) queued, wait for "cf_read" to finish. */ - return; - } + if (cf->read_lock || cf->redissection_queued == RESCAN_SCAN) { + /* Dissection in progress, signal redissection rather than rescanning. That + * would destroy the current (in-progress) dissection in "cf_read" which + * will cause issues when "cf_read" tries to add packets to the list. + * If a previous rescan was requested, "upgrade" it to a full redissection. + */ + cf->redissection_queued = RESCAN_REDISSECT; + } + if (cf->redissection_queued != RESCAN_NONE) { + /* Redissection is (already) queued, wait for "cf_read" to finish. */ + return; + } - if (cf->state != FILE_CLOSED) { - /* Restart dissection in case no cf_read is pending. */ - rescan_packets(cf, "Reprocessing", "all packets", TRUE); - } + if (cf->state != FILE_CLOSED) { + /* Restart dissection in case no cf_read is pending. */ + rescan_packets(cf, "Reprocessing", "all packets", TRUE); + } } gboolean cf_read_record(capture_file *cf, const frame_data *fdata, - wtap_rec *rec, Buffer *buf) + wtap_rec *rec, Buffer *buf) { - int err; - gchar *err_info; + int err; + gchar *err_info; - if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) { - cfile_read_failure_alert_box(cf->filename, err, err_info); - return FALSE; - } - return TRUE; + if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) { + cfile_read_failure_alert_box(cf->filename, err, err_info); + return FALSE; + } + return TRUE; } gboolean cf_read_record_no_alert(capture_file *cf, const frame_data *fdata, - wtap_rec *rec, Buffer *buf) + wtap_rec *rec, Buffer *buf) { - int err; - gchar *err_info; + int err; + gchar *err_info; - if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) { - g_free(err_info); - return FALSE; - } - return TRUE; + if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) { + g_free(err_info); + return FALSE; + } + return TRUE; } gboolean cf_read_current_record(capture_file *cf) { - return cf_read_record(cf, cf->current_frame, &cf->rec, &cf->buf); + return cf_read_record(cf, cf->current_frame, &cf->rec, &cf->buf); } /* Rescan the list of packets, reconstructing the CList. @@ -1629,390 +1640,390 @@ cf_read_current_record(capture_file *cf) static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect) { - /* Rescan packets new packet list */ - guint32 framenum; - frame_data *fdata; - wtap_rec rec; - Buffer buf; - progdlg_t *progbar = NULL; - GTimer *prog_timer = g_timer_new(); - int count; - frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame; - int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num; - gboolean selected_frame_seen; - float progbar_val; - gint64 start_time; - gchar status_str[100]; - epan_dissect_t edt; - dfilter_t *dfcode; - column_info *cinfo; - gboolean create_proto_tree; - guint tap_flags; - gboolean add_to_packet_list = FALSE; - gboolean compiled _U_; - guint32 frames_count; - gboolean queued_rescan_type = RESCAN_NONE; + /* Rescan packets new packet list */ + guint32 framenum; + frame_data *fdata; + wtap_rec rec; + Buffer buf; + progdlg_t *progbar = NULL; + GTimer *prog_timer = g_timer_new(); + int count; + frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame; + int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num; + gboolean selected_frame_seen; + float progbar_val; + gint64 start_time; + gchar status_str[100]; + epan_dissect_t edt; + dfilter_t *dfcode; + column_info *cinfo; + gboolean create_proto_tree; + guint tap_flags; + gboolean add_to_packet_list = FALSE; + gboolean compiled _U_; + guint32 frames_count; + gboolean queued_rescan_type = RESCAN_NONE; - /* Rescan in progress, clear pending actions. */ - cf->redissection_queued = RESCAN_NONE; - ws_assert(!cf->read_lock); - cf->read_lock = TRUE; + /* Rescan in progress, clear pending actions. */ + cf->redissection_queued = RESCAN_NONE; + ws_assert(!cf->read_lock); + cf->read_lock = TRUE; - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - /* Compile the current display filter. - * We assume this will not fail since cf->dfilter is only set in - * cf_filter IFF the filter was valid. - */ - compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); - ws_assert(!cf->dfilter || (compiled && dfcode)); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - /* If any tap listeners require the columns, construct them. */ - cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * we're redissecting and a postdissector wants field - * values or protocols on the first pass. - */ - create_proto_tree = - (dfcode != NULL || have_filtering_tap_listeners() || - (tap_flags & TL_REQUIRES_PROTO_TREE) || - (redissect && postdissectors_want_hfids())); - - reset_tap_listeners(); - /* Which frame, if any, is the currently selected frame? - XXX - should the selected frame or the focus frame be the "current" - frame, that frame being the one from which "Find Frame" searches - start? */ - selected_frame = cf->current_frame; - - /* Mark frame num as not found */ - selected_frame_num = -1; - - /* Freeze the packet list while we redo it, so we don't get any - screen updates while it happens. */ - packet_list_freeze(); - - if (redissect) { - /* We need to re-initialize all the state information that protocols - keep, because some preference that controls a dissector has changed, - which might cause the state information to be constructed differently - by that dissector. */ - - /* We might receive new packets while redissecting, and we don't - want to dissect those before their time. */ - cf->redissecting = TRUE; - - /* 'reset' dissection session */ - epan_free(cf->epan); - if (cf->edt && cf->edt->pi.fd) { - /* All pointers in "per frame proto data" for the currently selected - packet are allocated in wmem_file_scope() and deallocated in epan_free(). - Free them here to avoid unintended usage in packet_list_clear(). */ - frame_data_destroy(cf->edt->pi.fd); - } - cf->epan = ws_epan_new(cf); - cf->cinfo.epan = cf->epan; - - /* A new Lua tap listener may be registered in lua_prime_all_fields() - called via epan_new() / init_dissection() when reloading Lua plugins. */ - if (!create_proto_tree && have_filtering_tap_listeners()) { - create_proto_tree = TRUE; - } - - /* We need to redissect the packets so we have to discard our old - * packet list store. */ - packet_list_clear(); - add_to_packet_list = TRUE; - } - - /* We don't yet know which will be the first and last frames displayed. */ - cf->first_displayed = 0; - cf->last_displayed = 0; - - /* We currently don't display any packets */ - cf->displayed_count = 0; - - /* Iterate through the list of frames. Call a routine for each frame - to check whether it should be displayed and, if so, add it to - the display list. */ - cf->provider.ref = NULL; - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; - cf->cum_bytes = 0; - - cf_callback_invoke(cf_cb_file_rescan_started, cf); - - g_timer_start(prog_timer); - /* Count of packets at which we've looked. */ - count = 0; - /* Progress so far. */ - progbar_val = 0.0f; - - cf->stop_flag = FALSE; - start_time = g_get_monotonic_time(); - - /* no previous row yet */ - prev_frame_num = -1; - prev_frame = NULL; - - preceding_frame_num = -1; - preceding_frame = NULL; - following_frame_num = -1; - following_frame = NULL; - - selected_frame_seen = FALSE; - - frames_count = cf->count; - - epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); - - if (redissect) { - /* - * Decryption secrets are read while sequentially processing records and - * then passed to the dissector. During redissection, the previous secrets - * are lost (see epan_free above), but they are not read again from the - * file as only packet records are re-read. Therefore reset the wtap secrets - * callback such that wtap resupplies the secrets callback with previously - * read secrets. + /* Compile the current display filter. + * We assume this will not fail since cf->dfilter is only set in + * cf_filter IFF the filter was valid. */ - wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); - } + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); + ws_assert(!cf->dfilter || (compiled && dfcode)); - for (framenum = 1; framenum <= frames_count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - /* Create the progress bar if necessary. - We check on every iteration of the loop, so that it takes no - longer than the standard time to create it (otherwise, for a - large file, we might take considerably longer than that standard - time in order to get to the next progress bar step). */ - if (progbar == NULL) - progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE, - &cf->stop_flag, - progbar_val); + /* If any tap listeners require the columns, construct them. */ + cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; /* - * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL - * has elapsed. Calling update_progress_dlg and packets_bar_update will - * likely trigger UI paint events, which might take a while depending on - * the platform and display. Reset our timer *after* painting. + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * we're redissecting and a postdissector wants field + * values or protocols on the first pass. */ - if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - /* let's not divide by zero. I should never be started - * with count == 0, so let's assert that - */ - ws_assert(cf->count > 0); - progbar_val = (gfloat) count / frames_count; + create_proto_tree = + (dfcode != NULL || have_filtering_tap_listeners() || + (tap_flags & TL_REQUIRES_PROTO_TREE) || + (redissect && postdissectors_want_hfids())); - if (progbar != NULL) { - snprintf(status_str, sizeof(status_str), - "%4u of %u frames", count, frames_count); - update_progress_dlg(progbar, progbar_val, status_str); - } + reset_tap_listeners(); + /* Which frame, if any, is the currently selected frame? + XXX - should the selected frame or the focus frame be the "current" + frame, that frame being the one from which "Find Frame" searches + start? */ + selected_frame = cf->current_frame; - g_timer_start(prog_timer); - } + /* Mark frame num as not found */ + selected_frame_num = -1; - queued_rescan_type = cf->redissection_queued; - if (queued_rescan_type != RESCAN_NONE) { - /* A redissection was requested while an existing redissection was - * pending. */ - break; - } - - if (cf->stop_flag) { - /* Well, the user decided to abort the filtering. Just stop. - - XXX - go back to the previous filter? Users probably just - want not to wait for a filtering operation to finish; - unless we cancel by having no filter, reverting to the - previous filter will probably be even more expensive than - continuing the filtering, as it involves going back to the - beginning and filtering, and even with no filter we currently - have to re-generate the entire clist, which is also expensive. - - I'm not sure what Network Monitor does, but it doesn't appear - to give you an unfiltered display if you cancel. */ - break; - } - - count++; + /* Freeze the packet list while we redo it, so we don't get any + screen updates while it happens. */ + packet_list_freeze(); if (redissect) { - /* Since all state for the frame was destroyed, mark the frame - * as not visited, free the GSList referring to the state - * data (the per-frame data itself was freed by - * "init_dissection()"), and null out the GSList pointer. */ - frame_data_reset(fdata); - frames_count = cf->count; + /* We need to re-initialize all the state information that protocols + keep, because some preference that controls a dissector has changed, + which might cause the state information to be constructed differently + by that dissector. */ + + /* We might receive new packets while redissecting, and we don't + want to dissect those before their time. */ + cf->redissecting = TRUE; + + /* 'reset' dissection session */ + epan_free(cf->epan); + if (cf->edt && cf->edt->pi.fd) { + /* All pointers in "per frame proto data" for the currently selected + packet are allocated in wmem_file_scope() and deallocated in epan_free(). + Free them here to avoid unintended usage in packet_list_clear(). */ + frame_data_destroy(cf->edt->pi.fd); + } + cf->epan = ws_epan_new(cf); + cf->cinfo.epan = cf->epan; + + /* A new Lua tap listener may be registered in lua_prime_all_fields() + called via epan_new() / init_dissection() when reloading Lua plugins. */ + if (!create_proto_tree && have_filtering_tap_listeners()) { + create_proto_tree = TRUE; + } + + /* We need to redissect the packets so we have to discard our old + * packet list store. */ + packet_list_clear(); + add_to_packet_list = TRUE; } - /* Frame dependencies from the previous dissection/filtering are no longer valid. */ - fdata->dependent_of_displayed = 0; + /* We don't yet know which will be the first and last frames displayed. */ + cf->first_displayed = 0; + cf->last_displayed = 0; - if (!cf_read_record(cf, fdata, &rec, &buf)) - break; /* error reading the frame */ + /* We currently don't display any packets */ + cf->displayed_count = 0; - /* If the previous frame is displayed, and we haven't yet seen the - selected frame, remember that frame - it's the closest one we've - yet seen before the selected frame. */ - if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->passed_dfilter) { - preceding_frame_num = prev_frame_num; - preceding_frame = prev_frame; + /* Iterate through the list of frames. Call a routine for each frame + to check whether it should be displayed and, if so, add it to + the display list. */ + cf->provider.ref = NULL; + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; + cf->cum_bytes = 0; + + cf_callback_invoke(cf_cb_file_rescan_started, cf); + + g_timer_start(prog_timer); + /* Count of packets at which we've looked. */ + count = 0; + /* Progress so far. */ + progbar_val = 0.0f; + + cf->stop_flag = FALSE; + start_time = g_get_monotonic_time(); + + /* no previous row yet */ + prev_frame_num = -1; + prev_frame = NULL; + + preceding_frame_num = -1; + preceding_frame = NULL; + following_frame_num = -1; + following_frame = NULL; + + selected_frame_seen = FALSE; + + frames_count = cf->count; + + epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE); + + if (redissect) { + /* + * Decryption secrets are read while sequentially processing records and + * then passed to the dissector. During redissection, the previous secrets + * are lost (see epan_free above), but they are not read again from the + * file as only packet records are re-read. Therefore reset the wtap secrets + * callback such that wtap resupplies the secrets callback with previously + * read secrets. + */ + wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); } - add_packet_to_packet_list(fdata, cf, &edt, dfcode, - cinfo, &rec, &buf, - add_to_packet_list); + for (framenum = 1; framenum <= frames_count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); - /* If this frame is displayed, and this is the first frame we've - seen displayed after the selected frame, remember this frame - - it's the closest one we've yet seen at or after the selected - frame. */ - if (fdata->passed_dfilter && selected_frame_seen && following_frame_num == -1) { - following_frame_num = fdata->num; - following_frame = fdata; - } - if (fdata == selected_frame) { - selected_frame_seen = TRUE; - if (fdata->passed_dfilter) - selected_frame_num = fdata->num; + /* Create the progress bar if necessary. + We check on every iteration of the loop, so that it takes no + longer than the standard time to create it (otherwise, for a + large file, we might take considerably longer than that standard + time in order to get to the next progress bar step). */ + if (progbar == NULL) + progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE, + &cf->stop_flag, + progbar_val); + + /* + * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL + * has elapsed. Calling update_progress_dlg and packets_bar_update will + * likely trigger UI paint events, which might take a while depending on + * the platform and display. Reset our timer *after* painting. + */ + if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + /* let's not divide by zero. I should never be started + * with count == 0, so let's assert that + */ + ws_assert(cf->count > 0); + progbar_val = (gfloat) count / frames_count; + + if (progbar != NULL) { + snprintf(status_str, sizeof(status_str), + "%4u of %u frames", count, frames_count); + update_progress_dlg(progbar, progbar_val, status_str); + } + + g_timer_start(prog_timer); + } + + queued_rescan_type = cf->redissection_queued; + if (queued_rescan_type != RESCAN_NONE) { + /* A redissection was requested while an existing redissection was + * pending. */ + break; + } + + if (cf->stop_flag) { + /* Well, the user decided to abort the filtering. Just stop. + + XXX - go back to the previous filter? Users probably just + want not to wait for a filtering operation to finish; + unless we cancel by having no filter, reverting to the + previous filter will probably be even more expensive than + continuing the filtering, as it involves going back to the + beginning and filtering, and even with no filter we currently + have to re-generate the entire clist, which is also expensive. + + I'm not sure what Network Monitor does, but it doesn't appear + to give you an unfiltered display if you cancel. */ + break; + } + + count++; + + if (redissect) { + /* Since all state for the frame was destroyed, mark the frame + * as not visited, free the GSList referring to the state + * data (the per-frame data itself was freed by + * "init_dissection()"), and null out the GSList pointer. */ + frame_data_reset(fdata); + frames_count = cf->count; + } + + /* Frame dependencies from the previous dissection/filtering are no longer valid. */ + fdata->dependent_of_displayed = 0; + + if (!cf_read_record(cf, fdata, &rec, &buf)) + break; /* error reading the frame */ + + /* If the previous frame is displayed, and we haven't yet seen the + selected frame, remember that frame - it's the closest one we've + yet seen before the selected frame. */ + if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->passed_dfilter) { + preceding_frame_num = prev_frame_num; + preceding_frame = prev_frame; + } + + add_packet_to_packet_list(fdata, cf, &edt, dfcode, + cinfo, &rec, &buf, + add_to_packet_list); + + /* If this frame is displayed, and this is the first frame we've + seen displayed after the selected frame, remember this frame - + it's the closest one we've yet seen at or after the selected + frame. */ + if (fdata->passed_dfilter && selected_frame_seen && following_frame_num == -1) { + following_frame_num = fdata->num; + following_frame = fdata; + } + if (fdata == selected_frame) { + selected_frame_seen = TRUE; + if (fdata->passed_dfilter) + selected_frame_num = fdata->num; + } + + /* Remember this frame - it'll be the previous frame + on the next pass through the loop. */ + prev_frame_num = fdata->num; + prev_frame = fdata; + wtap_rec_reset(&rec); } - /* Remember this frame - it'll be the previous frame - on the next pass through the loop. */ - prev_frame_num = fdata->num; - prev_frame = fdata; - wtap_rec_reset(&rec); - } + epan_dissect_cleanup(&edt); + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); - epan_dissect_cleanup(&edt); - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); + /* We are done redissecting the packet list. */ + cf->redissecting = FALSE; - /* We are done redissecting the packet list. */ - cf->redissecting = FALSE; + if (redissect) { + frames_count = cf->count; + /* Clear out what remains of the visited flags and per-frame data + pointers. - if (redissect) { - frames_count = cf->count; - /* Clear out what remains of the visited flags and per-frame data - pointers. - - XXX - that may cause various forms of bogosity when dissecting - these frames, as they won't have been seen by this sequential - pass, but the only alternative I see is to keep scanning them - even though the user requested that the scan stop, and that - would leave the user stuck with an Wireshark grinding on - until it finishes. Should we just stick them with that? */ - for (; framenum <= frames_count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - frame_data_reset(fdata); + XXX - that may cause various forms of bogosity when dissecting + these frames, as they won't have been seen by this sequential + pass, but the only alternative I see is to keep scanning them + even though the user requested that the scan stop, and that + would leave the user stuck with an Wireshark grinding on + until it finishes. Should we just stick them with that? */ + for (; framenum <= frames_count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + frame_data_reset(fdata); + } } - } - /* We're done filtering the packets; destroy the progress bar if it - was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); + /* We're done filtering the packets; destroy the progress bar if it + was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); - /* Unfreeze the packet list. */ - if (!add_to_packet_list) - packet_list_recreate_visible_rows(); + /* Unfreeze the packet list. */ + if (!add_to_packet_list) + packet_list_recreate_visible_rows(); - /* Compute the time it took to filter the file */ - compute_elapsed(cf, start_time); + /* Compute the time it took to filter the file */ + compute_elapsed(cf, start_time); - packet_list_thaw(); + packet_list_thaw(); - cf_callback_invoke(cf_cb_file_rescan_finished, cf); + cf_callback_invoke(cf_cb_file_rescan_finished, cf); - if (selected_frame_num == -1) { - /* The selected frame didn't pass the filter. */ - if (selected_frame == NULL) { - /* That's because there *was* no selected frame. Make the first - displayed frame the current frame. */ - selected_frame_num = 0; + if (selected_frame_num == -1) { + /* The selected frame didn't pass the filter. */ + if (selected_frame == NULL) { + /* That's because there *was* no selected frame. Make the first + displayed frame the current frame. */ + selected_frame_num = 0; + } else { + /* Find the nearest displayed frame to the selected frame (whether + it's before or after that frame) and make that the current frame. + If the next and previous displayed frames are equidistant from the + selected frame, choose the next one. */ + ws_assert(following_frame == NULL || + following_frame->num >= selected_frame->num); + ws_assert(preceding_frame == NULL || + preceding_frame->num <= selected_frame->num); + if (following_frame == NULL) { + /* No frame after the selected frame passed the filter, so we + have to select the last displayed frame before the selected + frame. */ + selected_frame_num = preceding_frame_num; + selected_frame = preceding_frame; + } else if (preceding_frame == NULL) { + /* No frame before the selected frame passed the filter, so we + have to select the first displayed frame after the selected + frame. */ + selected_frame_num = following_frame_num; + selected_frame = following_frame; + } else { + /* Frames before and after the selected frame passed the filter, so + we'll select the previous frame */ + selected_frame_num = preceding_frame_num; + selected_frame = preceding_frame; + } + } + } + + if (selected_frame_num == -1) { + /* There are no frames displayed at all. */ + cf_unselect_packet(cf); } else { - /* Find the nearest displayed frame to the selected frame (whether - it's before or after that frame) and make that the current frame. - If the next and previous displayed frames are equidistant from the - selected frame, choose the next one. */ - ws_assert(following_frame == NULL || - following_frame->num >= selected_frame->num); - ws_assert(preceding_frame == NULL || - preceding_frame->num <= selected_frame->num); - if (following_frame == NULL) { - /* No frame after the selected frame passed the filter, so we - have to select the last displayed frame before the selected - frame. */ - selected_frame_num = preceding_frame_num; - selected_frame = preceding_frame; - } else if (preceding_frame == NULL) { - /* No frame before the selected frame passed the filter, so we - have to select the first displayed frame after the selected - frame. */ - selected_frame_num = following_frame_num; - selected_frame = following_frame; - } else { - /* Frames before and after the selected frame passed the filter, so - we'll select the previous frame */ - selected_frame_num = preceding_frame_num; - selected_frame = preceding_frame; - } + /* Either the frame that was selected passed the filter, or we've + found the nearest displayed frame to that frame. Select it, make + it the focus row, and make it visible. */ + /* Set to invalid to force update of packet list and packet details */ + cf->current_row = -1; + if (selected_frame_num == 0) { + packet_list_select_first_row(); + }else{ + if (!packet_list_select_row_from_data(selected_frame)) { + /* We didn't find a row corresponding to this frame. + This means that the frame isn't being displayed currently, + so we can't select it. */ + simple_message_box(ESD_TYPE_INFO, NULL, + "The capture file is probably not fully dissected.", + "End of capture exceeded."); + } + } } - } - if (selected_frame_num == -1) { - /* There are no frames displayed at all. */ - cf_unselect_packet(cf); - } else { - /* Either the frame that was selected passed the filter, or we've - found the nearest displayed frame to that frame. Select it, make - it the focus row, and make it visible. */ - /* Set to invalid to force update of packet list and packet details */ - cf->current_row = -1; - if (selected_frame_num == 0) { - packet_list_select_first_row(); - }else{ - if (!packet_list_select_row_from_data(selected_frame)) { - /* We didn't find a row corresponding to this frame. - This means that the frame isn't being displayed currently, - so we can't select it. */ - simple_message_box(ESD_TYPE_INFO, NULL, - "The capture file is probably not fully dissected.", - "End of capture exceeded."); - } + /* Cleanup and release all dfilter resources */ + dfilter_free(dfcode); + + /* It is safe again to execute redissections. */ + ws_assert(cf->read_lock); + cf->read_lock = FALSE; + + /* If another rescan (due to dfilter change) or redissection (due to profile + * change) was requested, the rescan above is aborted and restarted here. */ + if (queued_rescan_type != RESCAN_NONE) { + redissect = redissect || queued_rescan_type == RESCAN_REDISSECT; + rescan_packets(cf, "Reprocessing", "all packets", redissect); } - } - - /* Cleanup and release all dfilter resources */ - dfilter_free(dfcode); - - /* It is safe again to execute redissections. */ - ws_assert(cf->read_lock); - cf->read_lock = FALSE; - - /* If another rescan (due to dfilter change) or redissection (due to profile - * change) was requested, the rescan above is aborted and restarted here. */ - if (queued_rescan_type != RESCAN_NONE) { - redissect = redissect || queued_rescan_type == RESCAN_REDISSECT; - rescan_packets(cf, "Reprocessing", "all packets", redissect); - } } @@ -2024,1233 +2035,1233 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb void cf_reftime_packets(capture_file* cf) { - guint32 framenum; - frame_data *fdata; - nstime_t rel_ts; + guint32 framenum; + frame_data *fdata; + nstime_t rel_ts; - cf->provider.ref = NULL; - cf->provider.prev_dis = NULL; - cf->cum_bytes = 0; + cf->provider.ref = NULL; + cf->provider.prev_dis = NULL; + cf->cum_bytes = 0; - for (framenum = 1; framenum <= cf->count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); + for (framenum = 1; framenum <= cf->count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); - /* just add some value here until we know if it is being displayed or not */ - fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len; + /* just add some value here until we know if it is being displayed or not */ + fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len; - /* - *Timestamps - */ + /* + *Timestamps + */ - /* If we don't have the time stamp of the first packet in the - capture, it's because this is the first packet. Save the time - stamp of this packet as the time stamp of the first packet. */ - if (cf->provider.ref == NULL) - cf->provider.ref = fdata; - /* if this frames is marked as a reference time frame, reset - firstsec and firstusec to this frame */ - if (fdata->ref_time) - cf->provider.ref = fdata; + /* If we don't have the time stamp of the first packet in the + capture, it's because this is the first packet. Save the time + stamp of this packet as the time stamp of the first packet. */ + if (cf->provider.ref == NULL) + cf->provider.ref = fdata; + /* if this frames is marked as a reference time frame, reset + firstsec and firstusec to this frame */ + if (fdata->ref_time) + cf->provider.ref = fdata; - /* If we don't have the time stamp of the previous displayed packet, - it's because this is the first displayed packet. Save the time - stamp of this packet as the time stamp of the previous displayed - packet. */ - if (cf->provider.prev_dis == NULL) { - cf->provider.prev_dis = fdata; - } + /* If we don't have the time stamp of the previous displayed packet, + it's because this is the first displayed packet. Save the time + stamp of this packet as the time stamp of the previous displayed + packet. */ + if (cf->provider.prev_dis == NULL) { + cf->provider.prev_dis = fdata; + } - /* Get the time elapsed between the first packet and this packet. */ - fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0; - nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts); + /* Get the time elapsed between the first packet and this packet. */ + fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0; + nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts); - /* If it's greater than the current elapsed time, set the elapsed time - to it (we check for "greater than" so as not to be confused by - time moving backwards). */ - if ((gint32)cf->elapsed_time.secs < rel_ts.secs - || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) { - cf->elapsed_time = rel_ts; - } + /* If it's greater than the current elapsed time, set the elapsed time + to it (we check for "greater than" so as not to be confused by + time moving backwards). */ + if ((gint32)cf->elapsed_time.secs < rel_ts.secs + || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) { + cf->elapsed_time = rel_ts; + } - /* If this frame is displayed, get the time elapsed between the - previous displayed packet and this packet. */ - if ( fdata->passed_dfilter ) { - fdata->prev_dis_num = cf->provider.prev_dis->num; - cf->provider.prev_dis = fdata; - } + /* If this frame is displayed, get the time elapsed between the + previous displayed packet and this packet. */ + if ( fdata->passed_dfilter ) { + fdata->prev_dis_num = cf->provider.prev_dis->num; + cf->provider.prev_dis = fdata; + } - /* - * Byte counts - */ - if ( (fdata->passed_dfilter) || (fdata->ref_time) ) { - /* This frame either passed the display filter list or is marked as - a time reference frame. All time reference frames are displayed - even if they don't pass the display filter */ - if (fdata->ref_time) { - /* if this was a TIME REF frame we should reset the cum_bytes field */ - cf->cum_bytes = fdata->pkt_len; - fdata->cum_bytes = cf->cum_bytes; - } else { - /* increase cum_bytes with this packets length */ - cf->cum_bytes += fdata->pkt_len; + /* + * Byte counts + */ + if ( (fdata->passed_dfilter) || (fdata->ref_time) ) { + /* This frame either passed the display filter list or is marked as + a time reference frame. All time reference frames are displayed + even if they don't pass the display filter */ + if (fdata->ref_time) { + /* if this was a TIME REF frame we should reset the cum_bytes field */ + cf->cum_bytes = fdata->pkt_len; + fdata->cum_bytes = cf->cum_bytes; + } else { + /* increase cum_bytes with this packets length */ + cf->cum_bytes += fdata->pkt_len; + } } } - } } typedef enum { - PSP_FINISHED, - PSP_STOPPED, - PSP_FAILED + PSP_FINISHED, + PSP_STOPPED, + PSP_FAILED } psp_return_t; static psp_return_t process_specified_records(capture_file *cf, packet_range_t *range, - const char *string1, const char *string2, gboolean terminate_is_stop, - gboolean (*callback)(capture_file *, frame_data *, - wtap_rec *, Buffer *, void *), - void *callback_args, - gboolean show_progress_bar) + const char *string1, const char *string2, gboolean terminate_is_stop, + gboolean (*callback)(capture_file *, frame_data *, + wtap_rec *, Buffer *, void *), + void *callback_args, + gboolean show_progress_bar) { - guint32 framenum; - frame_data *fdata; - wtap_rec rec; - Buffer buf; - psp_return_t ret = PSP_FINISHED; + guint32 framenum; + frame_data *fdata; + wtap_rec rec; + Buffer buf; + psp_return_t ret = PSP_FINISHED; - progdlg_t *progbar = NULL; - GTimer *prog_timer = g_timer_new(); - int progbar_count; - float progbar_val; - gchar progbar_status_str[100]; - range_process_e process_this; + progdlg_t *progbar = NULL; + GTimer *prog_timer = g_timer_new(); + int progbar_count; + float progbar_val; + gchar progbar_status_str[100]; + range_process_e process_this; - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - g_timer_start(prog_timer); - /* Count of packets at which we've looked. */ - progbar_count = 0; - /* Progress so far. */ - progbar_val = 0.0f; + g_timer_start(prog_timer); + /* Count of packets at which we've looked. */ + progbar_count = 0; + /* Progress so far. */ + progbar_val = 0.0f; - if (cf->read_lock) { - ws_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename); - return PSP_FAILED; - } - cf->read_lock = TRUE; + if (cf->read_lock) { + ws_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename); + return PSP_FAILED; + } + cf->read_lock = TRUE; - cf->stop_flag = FALSE; + cf->stop_flag = FALSE; - if (range != NULL) - packet_range_process_init(range); + if (range != NULL) + packet_range_process_init(range); - /* Iterate through all the packets, printing the packets that - were selected by the current display filter. */ - for (framenum = 1; framenum <= cf->count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); + /* Iterate through all the packets, printing the packets that + were selected by the current display filter. */ + for (framenum = 1; framenum <= cf->count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); - /* Create the progress bar if necessary. - We check on every iteration of the loop, so that it takes no - longer than the standard time to create it (otherwise, for a - large file, we might take considerably longer than that standard - time in order to get to the next progress bar step). */ - if (show_progress_bar && progbar == NULL) - progbar = delayed_create_progress_dlg(cf->window, string1, string2, - terminate_is_stop, - &cf->stop_flag, - progbar_val); + /* Create the progress bar if necessary. + We check on every iteration of the loop, so that it takes no + longer than the standard time to create it (otherwise, for a + large file, we might take considerably longer than that standard + time in order to get to the next progress bar step). */ + if (show_progress_bar && progbar == NULL) + progbar = delayed_create_progress_dlg(cf->window, string1, string2, + terminate_is_stop, + &cf->stop_flag, + progbar_val); - /* - * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL - * has elapsed. Calling update_progress_dlg and packets_bar_update will - * likely trigger UI paint events, which might take a while depending on - * the platform and display. Reset our timer *after* painting. - */ - if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - /* let's not divide by zero. I should never be started - * with count == 0, so let's assert that - */ - ws_assert(cf->count > 0); - progbar_val = (gfloat) progbar_count / cf->count; + /* + * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL + * has elapsed. Calling update_progress_dlg and packets_bar_update will + * likely trigger UI paint events, which might take a while depending on + * the platform and display. Reset our timer *after* painting. + */ + if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + /* let's not divide by zero. I should never be started + * with count == 0, so let's assert that + */ + ws_assert(cf->count > 0); + progbar_val = (gfloat) progbar_count / cf->count; - snprintf(progbar_status_str, sizeof(progbar_status_str), - "%4u of %u packets", progbar_count, cf->count); - update_progress_dlg(progbar, progbar_val, progbar_status_str); + snprintf(progbar_status_str, sizeof(progbar_status_str), + "%4u of %u packets", progbar_count, cf->count); + update_progress_dlg(progbar, progbar_val, progbar_status_str); - g_timer_start(prog_timer); + g_timer_start(prog_timer); + } + + if (cf->stop_flag) { + /* Well, the user decided to abort the operation. Just stop, + and arrange to return PSP_STOPPED to our caller, so they know + it was stopped explicitly. */ + ret = PSP_STOPPED; + break; + } + + progbar_count++; + + if (range != NULL) { + /* do we have to process this packet? */ + process_this = packet_range_process_packet(range, fdata); + if (process_this == range_process_next) { + /* this packet uninteresting, continue with next one */ + continue; + } else if (process_this == range_processing_finished) { + /* all interesting packets processed, stop the loop */ + break; + } + } + + /* Get the packet */ + if (!cf_read_record(cf, fdata, &rec, &buf)) { + /* Attempt to get the packet failed. */ + ret = PSP_FAILED; + break; + } + /* Process the packet */ + if (!callback(cf, fdata, &rec, &buf, callback_args)) { + /* Callback failed. We assume it reported the error appropriately. */ + ret = PSP_FAILED; + break; + } + wtap_rec_reset(&rec); } - if (cf->stop_flag) { - /* Well, the user decided to abort the operation. Just stop, - and arrange to return PSP_STOPPED to our caller, so they know - it was stopped explicitly. */ - ret = PSP_STOPPED; - break; - } + /* We're done printing the packets; destroy the progress bar if + it was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); - progbar_count++; + ws_assert(cf->read_lock); + cf->read_lock = FALSE; - if (range != NULL) { - /* do we have to process this packet? */ - process_this = packet_range_process_packet(range, fdata); - if (process_this == range_process_next) { - /* this packet uninteresting, continue with next one */ - continue; - } else if (process_this == range_processing_finished) { - /* all interesting packets processed, stop the loop */ - break; - } - } + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); - /* Get the packet */ - if (!cf_read_record(cf, fdata, &rec, &buf)) { - /* Attempt to get the packet failed. */ - ret = PSP_FAILED; - break; - } - /* Process the packet */ - if (!callback(cf, fdata, &rec, &buf, callback_args)) { - /* Callback failed. We assume it reported the error appropriately. */ - ret = PSP_FAILED; - break; - } - wtap_rec_reset(&rec); - } - - /* We're done printing the packets; destroy the progress bar if - it was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); - - ws_assert(cf->read_lock); - cf->read_lock = FALSE; - - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - - return ret; + return ret; } typedef struct { - epan_dissect_t edt; - column_info *cinfo; + epan_dissect_t edt; + column_info *cinfo; } retap_callback_args_t; static gboolean retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf, - void *argsp) + void *argsp) { - retap_callback_args_t *args = (retap_callback_args_t *)argsp; + retap_callback_args_t *args = (retap_callback_args_t *)argsp; - epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, args->cinfo); - epan_dissect_reset(&args->edt); + epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, args->cinfo); + epan_dissect_reset(&args->edt); - return TRUE; + return TRUE; } cf_read_status_t cf_retap_packets(capture_file *cf) { - packet_range_t range; - retap_callback_args_t callback_args; - gboolean create_proto_tree; - guint tap_flags; - psp_return_t ret; + packet_range_t range; + retap_callback_args_t callback_args; + gboolean create_proto_tree; + guint tap_flags; + psp_return_t ret; - /* Presumably the user closed the capture file. */ - if (cf == NULL) { - return CF_READ_ABORTED; - } + /* Presumably the user closed the capture file. */ + if (cf == NULL) { + return CF_READ_ABORTED; + } - cf_callback_invoke(cf_cb_file_retap_started, cf); + cf_callback_invoke(cf_cb_file_retap_started, cf); - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - /* If any tap listeners require the columns, construct them. */ - callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; + /* If any tap listeners require the columns, construct them. */ + callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL; - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree. - */ - create_proto_tree = - (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE)); + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree. + */ + create_proto_tree = + (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE)); - /* Reset the tap listeners. */ - reset_tap_listeners(); + /* Reset the tap listeners. */ + reset_tap_listeners(); - epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE); + epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE); - /* Iterate through the list of packets, dissecting all packets and - re-running the taps. */ - packet_range_init(&range, cf); - packet_range_process_init(&range); + /* Iterate through the list of packets, dissecting all packets and + re-running the taps. */ + packet_range_init(&range, cf); + packet_range_process_init(&range); - ret = process_specified_records(cf, &range, "Recalculating statistics on", - "all packets", TRUE, retap_packet, - &callback_args, TRUE); + ret = process_specified_records(cf, &range, "Recalculating statistics on", + "all packets", TRUE, retap_packet, + &callback_args, TRUE); - packet_range_cleanup(&range); - epan_dissect_cleanup(&callback_args.edt); + packet_range_cleanup(&range); + epan_dissect_cleanup(&callback_args.edt); - cf_callback_invoke(cf_cb_file_retap_finished, cf); + cf_callback_invoke(cf_cb_file_retap_finished, cf); - switch (ret) { - case PSP_FINISHED: - /* Completed successfully. */ + switch (ret) { + case PSP_FINISHED: + /* Completed successfully. */ + return CF_READ_OK; + + case PSP_STOPPED: + /* Well, the user decided to abort the refiltering. + Return CF_READ_ABORTED so our caller knows they did that. */ + return CF_READ_ABORTED; + + case PSP_FAILED: + /* Error while retapping. */ + return CF_READ_ERROR; + } + + ws_assert_not_reached(); return CF_READ_OK; - - case PSP_STOPPED: - /* Well, the user decided to abort the refiltering. - Return CF_READ_ABORTED so our caller knows they did that. */ - return CF_READ_ABORTED; - - case PSP_FAILED: - /* Error while retapping. */ - return CF_READ_ERROR; - } - - ws_assert_not_reached(); - return CF_READ_OK; } typedef struct { - print_args_t *print_args; - gboolean print_header_line; - char *header_line_buf; - int header_line_buf_len; - gboolean print_formfeed; - gboolean print_separator; - char *line_buf; - int line_buf_len; - gint *col_widths; - int num_visible_cols; - gint *visible_cols; - epan_dissect_t edt; + print_args_t *print_args; + gboolean print_header_line; + char *header_line_buf; + int header_line_buf_len; + gboolean print_formfeed; + gboolean print_separator; + char *line_buf; + int line_buf_len; + gint *col_widths; + int num_visible_cols; + gint *visible_cols; + epan_dissect_t edt; } print_callback_args_t; static gboolean print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, Buffer *buf, - void *argsp) + void *argsp) { - print_callback_args_t *args = (print_callback_args_t *)argsp; - int i; - char *cp; - int line_len; - int column_len; - int cp_off; - char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */ - char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */ - col_item_t* col_item; + print_callback_args_t *args = (print_callback_args_t *)argsp; + int i; + char *cp; + int line_len; + int column_len; + int cp_off; + char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */ + char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */ + col_item_t* col_item; - /* Fill in the column information if we're printing the summary - information. */ - if (args->print_args->print_summary) { - col_custom_prime_edt(&args->edt, &cf->cinfo); - epan_dissect_run(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, &cf->cinfo); - epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); - } else - epan_dissect_run(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); - - if (args->print_formfeed) { - if (!new_page(args->print_args->stream)) - goto fail; - - /* - * Print another header line if we print a packet summary on the - * new page. - */ - if (args->print_args->print_col_headings) - args->print_header_line = TRUE; - } else { - if (args->print_separator) { - if (!print_line(args->print_args->stream, 0, "")) - goto fail; - } - } - - /* - * We generate bookmarks, if the output format supports them. - * The name is "__frameN__". - */ - snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num); - - if (args->print_args->print_summary) { - if (!args->print_args->print_col_headings) - args->print_header_line = FALSE; - if (args->print_header_line) { - if (!print_line(args->print_args->stream, 0, args->header_line_buf)) - goto fail; - args->print_header_line = FALSE; /* we might not need to print any more */ - } - cp = &args->line_buf[0]; - line_len = 0; - for (i = 0; i < args->num_visible_cols; i++) { - col_item = &cf->cinfo.columns[args->visible_cols[i]]; - /* Find the length of the string for this column. */ - column_len = (int) strlen(col_item->col_data); - if (args->col_widths[i] > column_len) - column_len = args->col_widths[i]; - - /* Make sure there's room in the line buffer for the column; if not, - double its length. */ - line_len += column_len + 1; /* "+1" for space */ - if (line_len > args->line_buf_len) { - cp_off = (int) (cp - args->line_buf); - args->line_buf_len = 2 * line_len; - args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1); - cp = args->line_buf + cp_off; - } - - /* Right-justify the packet number column. */ - if (col_item->col_fmt == COL_NUMBER) - snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data); - else - snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data); - cp += column_len; - if (i != args->num_visible_cols - 1) - *cp++ = ' '; - } - *cp = '\0'; - - /* - * Generate a bookmark, using the summary line as the title. - */ - if (!print_bookmark(args->print_args->stream, bookmark_name, - args->line_buf)) - goto fail; - - if (!print_line(args->print_args->stream, 0, args->line_buf)) - goto fail; - } else { - /* - * Generate a bookmark, using "Frame N" as the title, as we're not - * printing the summary line. - */ - snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num); - if (!print_bookmark(args->print_args->stream, bookmark_name, - bookmark_title)) - goto fail; - } /* if (print_summary) */ - - if (args->print_args->print_dissections != print_dissections_none) { + /* Fill in the column information if we're printing the summary + information. */ if (args->print_args->print_summary) { - /* Separate the summary line from the tree with a blank line. */ - if (!print_line(args->print_args->stream, 0, "")) - goto fail; + col_custom_prime_edt(&args->edt, &cf->cinfo); + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, &cf->cinfo); + epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); + } else + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); + + if (args->print_formfeed) { + if (!new_page(args->print_args->stream)) + goto fail; + + /* + * Print another header line if we print a packet summary on the + * new page. + */ + if (args->print_args->print_col_headings) + args->print_header_line = TRUE; + } else { + if (args->print_separator) { + if (!print_line(args->print_args->stream, 0, "")) + goto fail; + } } - /* Print the information in that tree. */ - if (!proto_tree_print(args->print_args->print_dissections, - args->print_args->print_hex, &args->edt, NULL, - args->print_args->stream)) - goto fail; + /* + * We generate bookmarks, if the output format supports them. + * The name is "__frameN__". + */ + snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num); - /* Print a blank line if we print anything after this (aka more than one packet). */ - args->print_separator = TRUE; + if (args->print_args->print_summary) { + if (!args->print_args->print_col_headings) + args->print_header_line = FALSE; + if (args->print_header_line) { + if (!print_line(args->print_args->stream, 0, args->header_line_buf)) + goto fail; + args->print_header_line = FALSE; /* we might not need to print any more */ + } + cp = &args->line_buf[0]; + line_len = 0; + for (i = 0; i < args->num_visible_cols; i++) { + col_item = &cf->cinfo.columns[args->visible_cols[i]]; + /* Find the length of the string for this column. */ + column_len = (int) strlen(col_item->col_data); + if (args->col_widths[i] > column_len) + column_len = args->col_widths[i]; - /* Print a header line if we print any more packet summaries */ - if (args->print_args->print_col_headings) - args->print_header_line = TRUE; - } + /* Make sure there's room in the line buffer for the column; if not, + double its length. */ + line_len += column_len + 1; /* "+1" for space */ + if (line_len > args->line_buf_len) { + cp_off = (int) (cp - args->line_buf); + args->line_buf_len = 2 * line_len; + args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1); + cp = args->line_buf + cp_off; + } - if (args->print_args->print_hex) { - if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) { - if (!print_line(args->print_args->stream, 0, "")) - goto fail; + /* Right-justify the packet number column. */ + if (col_item->col_fmt == COL_NUMBER) + snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data); + else + snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data); + cp += column_len; + if (i != args->num_visible_cols - 1) + *cp++ = ' '; + } + *cp = '\0'; + + /* + * Generate a bookmark, using the summary line as the title. + */ + if (!print_bookmark(args->print_args->stream, bookmark_name, + args->line_buf)) + goto fail; + + if (!print_line(args->print_args->stream, 0, args->line_buf)) + goto fail; + } else { + /* + * Generate a bookmark, using "Frame N" as the title, as we're not + * printing the summary line. + */ + snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num); + if (!print_bookmark(args->print_args->stream, bookmark_name, + bookmark_title)) + goto fail; + } /* if (print_summary) */ + + if (args->print_args->print_dissections != print_dissections_none) { + if (args->print_args->print_summary) { + /* Separate the summary line from the tree with a blank line. */ + if (!print_line(args->print_args->stream, 0, "")) + goto fail; + } + + /* Print the information in that tree. */ + if (!proto_tree_print(args->print_args->print_dissections, + args->print_args->print_hex, &args->edt, NULL, + args->print_args->stream)) + goto fail; + + /* Print a blank line if we print anything after this (aka more than one packet). */ + args->print_separator = TRUE; + + /* Print a header line if we print any more packet summaries */ + if (args->print_args->print_col_headings) + args->print_header_line = TRUE; } - /* Print the full packet data as hex. */ - if (!print_hex_data(args->print_args->stream, &args->edt, args->print_args->hexdump_options)) - goto fail; - /* Print a blank line if we print anything after this (aka more than one packet). */ - args->print_separator = TRUE; + if (args->print_args->print_hex) { + if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) { + if (!print_line(args->print_args->stream, 0, "")) + goto fail; + } + /* Print the full packet data as hex. */ + if (!print_hex_data(args->print_args->stream, &args->edt, args->print_args->hexdump_options)) + goto fail; - /* Print a header line if we print any more packet summaries */ - if (args->print_args->print_col_headings) - args->print_header_line = TRUE; - } /* if (args->print_args->print_dissections != print_dissections_none) */ + /* Print a blank line if we print anything after this (aka more than one packet). */ + args->print_separator = TRUE; - epan_dissect_reset(&args->edt); + /* Print a header line if we print any more packet summaries */ + if (args->print_args->print_col_headings) + args->print_header_line = TRUE; + } /* if (args->print_args->print_dissections != print_dissections_none) */ - /* do we want to have a formfeed between each packet from now on? */ - if (args->print_args->print_formfeed) { - args->print_formfeed = TRUE; - } + epan_dissect_reset(&args->edt); - return TRUE; + /* do we want to have a formfeed between each packet from now on? */ + if (args->print_args->print_formfeed) { + args->print_formfeed = TRUE; + } + + return TRUE; fail: - epan_dissect_reset(&args->edt); - return FALSE; + epan_dissect_reset(&args->edt); + return FALSE; } cf_print_status_t cf_print_packets(capture_file *cf, print_args_t *print_args, - gboolean show_progress_bar) + gboolean show_progress_bar) { - print_callback_args_t callback_args; - gint data_width; - char *cp; - int i, cp_off, column_len, line_len; - int num_visible_col = 0, last_visible_col = 0, visible_col_count; - psp_return_t ret; - GList *clp; - fmt_data *cfmt; - gboolean proto_tree_needed; + print_callback_args_t callback_args; + gint data_width; + char *cp; + int i, cp_off, column_len, line_len; + int num_visible_col = 0, last_visible_col = 0, visible_col_count; + psp_return_t ret; + GList *clp; + fmt_data *cfmt; + gboolean proto_tree_needed; - callback_args.print_args = print_args; - callback_args.print_header_line = print_args->print_col_headings; - callback_args.header_line_buf = NULL; - callback_args.header_line_buf_len = 256; - callback_args.print_formfeed = FALSE; - callback_args.print_separator = FALSE; - callback_args.line_buf = NULL; - callback_args.line_buf_len = 256; - callback_args.col_widths = NULL; - callback_args.num_visible_cols = 0; - callback_args.visible_cols = NULL; + callback_args.print_args = print_args; + callback_args.print_header_line = print_args->print_col_headings; + callback_args.header_line_buf = NULL; + callback_args.header_line_buf_len = 256; + callback_args.print_formfeed = FALSE; + callback_args.print_separator = FALSE; + callback_args.line_buf = NULL; + callback_args.line_buf_len = 256; + callback_args.col_widths = NULL; + callback_args.num_visible_cols = 0; + callback_args.visible_cols = NULL; - if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) { - destroy_print_stream(print_args->stream); - return CF_PRINT_WRITE_ERROR; - } + if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) { + destroy_print_stream(print_args->stream); + return CF_PRINT_WRITE_ERROR; + } - if (print_args->print_summary) { - /* We're printing packet summaries. Allocate the header line buffer - and get the column widths. */ - callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1); + if (print_args->print_summary) { + /* We're printing packet summaries. Allocate the header line buffer + and get the column widths. */ + callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1); - /* Find the number of visible columns and the last visible column */ - for (i = 0; i < prefs.num_cols; i++) { + /* Find the number of visible columns and the last visible column */ + for (i = 0; i < prefs.num_cols; i++) { - clp = g_list_nth(prefs.col_list, i); - if (clp == NULL) /* Sanity check, Invalid column requested */ - continue; + clp = g_list_nth(prefs.col_list, i); + if (clp == NULL) /* Sanity check, Invalid column requested */ + continue; - cfmt = (fmt_data *) clp->data; - if (cfmt->visible) { - num_visible_col++; - last_visible_col = i; + cfmt = (fmt_data *) clp->data; + if (cfmt->visible) { + num_visible_col++; + last_visible_col = i; + } } + + /* if num_visible_col is 0, we are done */ + if (num_visible_col == 0) { + g_free(callback_args.header_line_buf); + return CF_PRINT_OK; + } + + /* Find the widths for each of the columns - maximum of the + width of the title and the width of the data - and construct + a buffer with a line containing the column titles. */ + callback_args.num_visible_cols = num_visible_col; + callback_args.col_widths = g_new(gint, num_visible_col); + callback_args.visible_cols = g_new(gint, num_visible_col); + cp = &callback_args.header_line_buf[0]; + line_len = 0; + visible_col_count = 0; + for (i = 0; i < cf->cinfo.num_cols; i++) { + + clp = g_list_nth(prefs.col_list, i); + if (clp == NULL) /* Sanity check, Invalid column requested */ + continue; + + cfmt = (fmt_data *) clp->data; + if (cfmt->visible == FALSE) + continue; + + /* Save the order of visible columns */ + callback_args.visible_cols[visible_col_count] = i; + + /* Don't pad the last column. */ + if (i == last_visible_col) + callback_args.col_widths[visible_col_count] = 0; + else { + callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title); + data_width = get_column_char_width(get_column_format(i)); + if (data_width > callback_args.col_widths[visible_col_count]) + callback_args.col_widths[visible_col_count] = data_width; + } + + /* Find the length of the string for this column. */ + column_len = (int) strlen(cf->cinfo.columns[i].col_title); + if (callback_args.col_widths[visible_col_count] > column_len) + column_len = callback_args.col_widths[visible_col_count]; + + /* Make sure there's room in the line buffer for the column; if not, + double its length. */ + line_len += column_len + 1; /* "+1" for space */ + if (line_len > callback_args.header_line_buf_len) { + cp_off = (int) (cp - callback_args.header_line_buf); + callback_args.header_line_buf_len = 2 * line_len; + callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf, + callback_args.header_line_buf_len + 1); + cp = callback_args.header_line_buf + cp_off; + } + + /* Right-justify the packet number column. */ +/* if (cf->cinfo.col_fmt[i] == COL_NUMBER) + snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title); + else*/ + snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title); + cp += column_len; + if (i != cf->cinfo.num_cols - 1) + *cp++ = ' '; + + visible_col_count++; + } + *cp = '\0'; + + /* Now start out the main line buffer with the same length as the + header line buffer. */ + callback_args.line_buf_len = callback_args.header_line_buf_len; + callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1); + } /* if (print_summary) */ + + /* Create the protocol tree, and make it visible, if we're printing + the dissection or the hex data. + XXX - do we need it if we're just printing the hex data? */ + proto_tree_needed = + callback_args.print_args->print_dissections != print_dissections_none || + callback_args.print_args->print_hex || + have_custom_cols(&cf->cinfo) || have_field_extractors(); + epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); + + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Printing", + "selected packets", TRUE, print_packet, + &callback_args, show_progress_bar); + epan_dissect_cleanup(&callback_args.edt); + g_free(callback_args.header_line_buf); + g_free(callback_args.line_buf); + g_free(callback_args.col_widths); + g_free(callback_args.visible_cols); + + switch (ret) { + + case PSP_FINISHED: + /* Completed successfully. */ + break; + + case PSP_STOPPED: + /* Well, the user decided to abort the printing. + + XXX - note that what got generated before they did that + will get printed if we're piping to a print program; we'd + have to write to a file and then hand that to the print + program to make it actually not print anything. */ + break; + + case PSP_FAILED: + /* Error while printing. + + XXX - note that what got generated before they did that + will get printed if we're piping to a print program; we'd + have to write to a file and then hand that to the print + program to make it actually not print anything. */ + destroy_print_stream(print_args->stream); + return CF_PRINT_WRITE_ERROR; } - /* if num_visible_col is 0, we are done */ - if (num_visible_col == 0) { - g_free(callback_args.header_line_buf); - return CF_PRINT_OK; + if (!print_finale(print_args->stream)) { + destroy_print_stream(print_args->stream); + return CF_PRINT_WRITE_ERROR; } - /* Find the widths for each of the columns - maximum of the - width of the title and the width of the data - and construct - a buffer with a line containing the column titles. */ - callback_args.num_visible_cols = num_visible_col; - callback_args.col_widths = g_new(gint, num_visible_col); - callback_args.visible_cols = g_new(gint, num_visible_col); - cp = &callback_args.header_line_buf[0]; - line_len = 0; - visible_col_count = 0; - for (i = 0; i < cf->cinfo.num_cols; i++) { + if (!destroy_print_stream(print_args->stream)) + return CF_PRINT_WRITE_ERROR; - clp = g_list_nth(prefs.col_list, i); - if (clp == NULL) /* Sanity check, Invalid column requested */ - continue; - - cfmt = (fmt_data *) clp->data; - if (cfmt->visible == FALSE) - continue; - - /* Save the order of visible columns */ - callback_args.visible_cols[visible_col_count] = i; - - /* Don't pad the last column. */ - if (i == last_visible_col) - callback_args.col_widths[visible_col_count] = 0; - else { - callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title); - data_width = get_column_char_width(get_column_format(i)); - if (data_width > callback_args.col_widths[visible_col_count]) - callback_args.col_widths[visible_col_count] = data_width; - } - - /* Find the length of the string for this column. */ - column_len = (int) strlen(cf->cinfo.columns[i].col_title); - if (callback_args.col_widths[visible_col_count] > column_len) - column_len = callback_args.col_widths[visible_col_count]; - - /* Make sure there's room in the line buffer for the column; if not, - double its length. */ - line_len += column_len + 1; /* "+1" for space */ - if (line_len > callback_args.header_line_buf_len) { - cp_off = (int) (cp - callback_args.header_line_buf); - callback_args.header_line_buf_len = 2 * line_len; - callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf, - callback_args.header_line_buf_len + 1); - cp = callback_args.header_line_buf + cp_off; - } - - /* Right-justify the packet number column. */ -/* if (cf->cinfo.col_fmt[i] == COL_NUMBER) - snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title); - else*/ - snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title); - cp += column_len; - if (i != cf->cinfo.num_cols - 1) - *cp++ = ' '; - - visible_col_count++; - } - *cp = '\0'; - - /* Now start out the main line buffer with the same length as the - header line buffer. */ - callback_args.line_buf_len = callback_args.header_line_buf_len; - callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1); - } /* if (print_summary) */ - - /* Create the protocol tree, and make it visible, if we're printing - the dissection or the hex data. - XXX - do we need it if we're just printing the hex data? */ - proto_tree_needed = - callback_args.print_args->print_dissections != print_dissections_none || - callback_args.print_args->print_hex || - have_custom_cols(&cf->cinfo) || have_field_extractors(); - epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); - - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Printing", - "selected packets", TRUE, print_packet, - &callback_args, show_progress_bar); - epan_dissect_cleanup(&callback_args.edt); - g_free(callback_args.header_line_buf); - g_free(callback_args.line_buf); - g_free(callback_args.col_widths); - g_free(callback_args.visible_cols); - - switch (ret) { - - case PSP_FINISHED: - /* Completed successfully. */ - break; - - case PSP_STOPPED: - /* Well, the user decided to abort the printing. - - XXX - note that what got generated before they did that - will get printed if we're piping to a print program; we'd - have to write to a file and then hand that to the print - program to make it actually not print anything. */ - break; - - case PSP_FAILED: - /* Error while printing. - - XXX - note that what got generated before they did that - will get printed if we're piping to a print program; we'd - have to write to a file and then hand that to the print - program to make it actually not print anything. */ - destroy_print_stream(print_args->stream); - return CF_PRINT_WRITE_ERROR; - } - - if (!print_finale(print_args->stream)) { - destroy_print_stream(print_args->stream); - return CF_PRINT_WRITE_ERROR; - } - - if (!destroy_print_stream(print_args->stream)) - return CF_PRINT_WRITE_ERROR; - - return CF_PRINT_OK; + return CF_PRINT_OK; } typedef struct { - FILE *fh; - epan_dissect_t edt; - print_args_t *print_args; - json_dumper jdumper; + FILE *fh; + epan_dissect_t edt; + print_args_t *print_args; + json_dumper jdumper; } write_packet_callback_args_t; static gboolean write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; + write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; - /* Create the protocol tree, but don't fill in the column information. */ - epan_dissect_run(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); + /* Create the protocol tree, but don't fill in the column information. */ + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); - /* Write out the information in that tree. */ - write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE); + /* Write out the information in that tree. */ + write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE); - epan_dissect_reset(&args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_pdml_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - FILE *fh; - psp_return_t ret; + write_packet_callback_args_t callback_args; + FILE *fh; + psp_return_t ret; - fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + fh = ws_fopen(print_args->file, "w"); + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - write_pdml_preamble(fh, cf->filename); - if (ferror(fh)) { + write_pdml_preamble(fh, cf->filename); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + callback_args.fh = fh; + callback_args.print_args = print_args; + epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); + + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Writing PDML", + "selected packets", TRUE, + write_pdml_packet, &callback_args, TRUE); + + epan_dissect_cleanup(&callback_args.edt); + + switch (ret) { + + case PSP_FINISHED: + /* Completed successfully. */ + break; + + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; + + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + write_pdml_finale(fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + /* XXX - check for an error */ fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - callback_args.fh = fh; - callback_args.print_args = print_args; - epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); - - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Writing PDML", - "selected packets", TRUE, - write_pdml_packet, &callback_args, TRUE); - - epan_dissect_cleanup(&callback_args.edt); - - switch (ret) { - - case PSP_FINISHED: - /* Completed successfully. */ - break; - - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; - - case PSP_FAILED: - /* Error while printing. */ - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - write_pdml_finale(fh); - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - /* XXX - check for an error */ - fclose(fh); - - return CF_PRINT_OK; + return CF_PRINT_OK; } static gboolean write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; + write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; - /* Fill in the column information */ - col_custom_prime_edt(&args->edt, &cf->cinfo); - epan_dissect_run(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, &cf->cinfo); - epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); + /* Fill in the column information */ + col_custom_prime_edt(&args->edt, &cf->cinfo); + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, &cf->cinfo); + epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); - /* Write out the column information. */ - write_psml_columns(&args->edt, args->fh, FALSE); + /* Write out the column information. */ + write_psml_columns(&args->edt, args->fh, FALSE); - epan_dissect_reset(&args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_psml_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - FILE *fh; - psp_return_t ret; + write_packet_callback_args_t callback_args; + FILE *fh; + psp_return_t ret; - gboolean proto_tree_needed; + gboolean proto_tree_needed; - fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + fh = ws_fopen(print_args->file, "w"); + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - write_psml_preamble(&cf->cinfo, fh); - if (ferror(fh)) { + write_psml_preamble(&cf->cinfo, fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + callback_args.fh = fh; + callback_args.print_args = print_args; + + /* Fill in the column information, only create the protocol tree + if having custom columns or field extractors. */ + proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors(); + epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); + + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Writing PSML", + "selected packets", TRUE, + write_psml_packet, &callback_args, TRUE); + + epan_dissect_cleanup(&callback_args.edt); + + switch (ret) { + + case PSP_FINISHED: + /* Completed successfully. */ + break; + + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; + + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + write_psml_finale(fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + /* XXX - check for an error */ fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - callback_args.fh = fh; - callback_args.print_args = print_args; - - /* Fill in the column information, only create the protocol tree - if having custom columns or field extractors. */ - proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors(); - epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); - - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Writing PSML", - "selected packets", TRUE, - write_psml_packet, &callback_args, TRUE); - - epan_dissect_cleanup(&callback_args.edt); - - switch (ret) { - - case PSP_FINISHED: - /* Completed successfully. */ - break; - - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; - - case PSP_FAILED: - /* Error while printing. */ - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - write_psml_finale(fh); - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - /* XXX - check for an error */ - fclose(fh); - - return CF_PRINT_OK; + return CF_PRINT_OK; } static gboolean write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; + write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; - /* Fill in the column information */ - col_custom_prime_edt(&args->edt, &cf->cinfo); - epan_dissect_run(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, &cf->cinfo); - epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); + /* Fill in the column information */ + col_custom_prime_edt(&args->edt, &cf->cinfo); + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, &cf->cinfo); + epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE); - /* Write out the column information. */ - write_csv_columns(&args->edt, args->fh); + /* Write out the column information. */ + write_csv_columns(&args->edt, args->fh); - epan_dissect_reset(&args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_csv_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - gboolean proto_tree_needed; - FILE *fh; - psp_return_t ret; + write_packet_callback_args_t callback_args; + gboolean proto_tree_needed; + FILE *fh; + psp_return_t ret; - fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + fh = ws_fopen(print_args->file, "w"); + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - write_csv_column_titles(&cf->cinfo, fh); - if (ferror(fh)) { + write_csv_column_titles(&cf->cinfo, fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + callback_args.fh = fh; + callback_args.print_args = print_args; + + /* only create the protocol tree if having custom columns or field extractors. */ + proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors(); + epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); + + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Writing CSV", + "selected packets", TRUE, + write_csv_packet, &callback_args, TRUE); + + epan_dissect_cleanup(&callback_args.edt); + + switch (ret) { + + case PSP_FINISHED: + /* Completed successfully. */ + break; + + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; + + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + /* XXX - check for an error */ fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - callback_args.fh = fh; - callback_args.print_args = print_args; - - /* only create the protocol tree if having custom columns or field extractors. */ - proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors(); - epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed); - - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Writing CSV", - "selected packets", TRUE, - write_csv_packet, &callback_args, TRUE); - - epan_dissect_cleanup(&callback_args.edt); - - switch (ret) { - - case PSP_FINISHED: - /* Completed successfully. */ - break; - - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; - - case PSP_FAILED: - /* Error while printing. */ - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - /* XXX - check for an error */ - fclose(fh); - - return CF_PRINT_OK; + return CF_PRINT_OK; } static gboolean carrays_write_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; + write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; - epan_dissect_run(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); - write_carrays_hex_data(fdata->num, args->fh, &args->edt); - epan_dissect_reset(&args->edt); + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); + write_carrays_hex_data(fdata->num, args->fh, &args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_carrays_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - FILE *fh; - psp_return_t ret; + write_packet_callback_args_t callback_args; + FILE *fh; + psp_return_t ret; - fh = ws_fopen(print_args->file, "w"); + fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + callback_args.fh = fh; + callback_args.print_args = print_args; + epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); + + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, + "Writing C Arrays", + "selected packets", TRUE, + carrays_write_packet, &callback_args, TRUE); + + epan_dissect_cleanup(&callback_args.edt); + + switch (ret) { + case PSP_FINISHED: + /* Completed successfully. */ + break; + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } - if (ferror(fh)) { fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - callback_args.fh = fh; - callback_args.print_args = print_args; - epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); - - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, - "Writing C Arrays", - "selected packets", TRUE, - carrays_write_packet, &callback_args, TRUE); - - epan_dissect_cleanup(&callback_args.edt); - - switch (ret) { - case PSP_FINISHED: - /* Completed successfully. */ - break; - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; - case PSP_FAILED: - /* Error while printing. */ - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - fclose(fh); - return CF_PRINT_OK; + return CF_PRINT_OK; } static gboolean write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; + write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp; - /* Create the protocol tree, but don't fill in the column information. */ - epan_dissect_run(&args->edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); + /* Create the protocol tree, but don't fill in the column information. */ + epan_dissect_run(&args->edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); - /* Write out the information in that tree. */ - write_json_proto_tree(NULL, args->print_args->print_dissections, - args->print_args->print_hex, NULL, PF_NONE, - &args->edt, &cf->cinfo, proto_node_group_children_by_unique, - &args->jdumper); + /* Write out the information in that tree. */ + write_json_proto_tree(NULL, args->print_args->print_dissections, + args->print_args->print_hex, NULL, PF_NONE, + &args->edt, &cf->cinfo, proto_node_group_children_by_unique, + &args->jdumper); - epan_dissect_reset(&args->edt); + epan_dissect_reset(&args->edt); - return !ferror(args->fh); + return !ferror(args->fh); } cf_print_status_t cf_write_json_packets(capture_file *cf, print_args_t *print_args) { - write_packet_callback_args_t callback_args; - FILE *fh; - psp_return_t ret; + write_packet_callback_args_t callback_args; + FILE *fh; + psp_return_t ret; - fh = ws_fopen(print_args->file, "w"); - if (fh == NULL) - return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ + fh = ws_fopen(print_args->file, "w"); + if (fh == NULL) + return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */ - callback_args.jdumper = write_json_preamble(fh); - if (ferror(fh)) { + callback_args.jdumper = write_json_preamble(fh); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + callback_args.fh = fh; + callback_args.print_args = print_args; + epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); + + /* Iterate through the list of packets, printing the packets we were + told to print. */ + ret = process_specified_records(cf, &print_args->range, "Writing JSON", + "selected packets", TRUE, + write_json_packet, &callback_args, TRUE); + + epan_dissect_cleanup(&callback_args.edt); + + switch (ret) { + + case PSP_FINISHED: + /* Completed successfully. */ + break; + + case PSP_STOPPED: + /* Well, the user decided to abort the printing. */ + break; + + case PSP_FAILED: + /* Error while printing. */ + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + write_json_finale(&callback_args.jdumper); + if (ferror(fh)) { + fclose(fh); + return CF_PRINT_WRITE_ERROR; + } + + /* XXX - check for an error */ fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - callback_args.fh = fh; - callback_args.print_args = print_args; - epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE); - - /* Iterate through the list of packets, printing the packets we were - told to print. */ - ret = process_specified_records(cf, &print_args->range, "Writing JSON", - "selected packets", TRUE, - write_json_packet, &callback_args, TRUE); - - epan_dissect_cleanup(&callback_args.edt); - - switch (ret) { - - case PSP_FINISHED: - /* Completed successfully. */ - break; - - case PSP_STOPPED: - /* Well, the user decided to abort the printing. */ - break; - - case PSP_FAILED: - /* Error while printing. */ - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - write_json_finale(&callback_args.jdumper); - if (ferror(fh)) { - fclose(fh); - return CF_PRINT_WRITE_ERROR; - } - - /* XXX - check for an error */ - fclose(fh); - - return CF_PRINT_OK; + return CF_PRINT_OK; } gboolean cf_find_packet_protocol_tree(capture_file *cf, const char *string, - search_direction dir) + search_direction dir) { - match_data mdata; + match_data mdata; - mdata.string = string; - mdata.string_len = strlen(string); - return find_packet(cf, match_protocol_tree, &mdata, dir); + mdata.string = string; + mdata.string_len = strlen(string); + return find_packet(cf, match_protocol_tree, &mdata, dir); } gboolean cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata) { - mdata->frame_matched = FALSE; - mdata->string = convert_string_case(cf->sfilter, cf->case_type); - mdata->string_len = strlen(mdata->string); - mdata->cf = cf; - /* Iterate through all the nodes looking for matching text */ - proto_tree_children_foreach(tree, match_subtree_text, mdata); - return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; + mdata->frame_matched = FALSE; + mdata->string = convert_string_case(cf->sfilter, cf->case_type); + mdata->string_len = strlen(mdata->string); + mdata->cf = cf; + /* Iterate through all the nodes looking for matching text */ + proto_tree_children_foreach(tree, match_subtree_text, mdata); + return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; } static match_result match_protocol_tree(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - match_data *mdata = (match_data *)criterion; - epan_dissect_t edt; + match_data *mdata = (match_data *)criterion; + epan_dissect_t edt; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } - /* Construct the protocol tree, including the displayed text */ - epan_dissect_init(&edt, cf->epan, TRUE, TRUE); - /* We don't need the column information */ - epan_dissect_run(&edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); + /* Construct the protocol tree, including the displayed text */ + epan_dissect_init(&edt, cf->epan, TRUE, TRUE); + /* We don't need the column information */ + epan_dissect_run(&edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); - /* Iterate through all the nodes, seeing if they have text that matches. */ - mdata->cf = cf; - mdata->frame_matched = FALSE; - proto_tree_children_foreach(edt.tree, match_subtree_text, mdata); - epan_dissect_cleanup(&edt); - return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; + /* Iterate through all the nodes, seeing if they have text that matches. */ + mdata->cf = cf; + mdata->frame_matched = FALSE; + proto_tree_children_foreach(edt.tree, match_subtree_text, mdata); + epan_dissect_cleanup(&edt); + return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED; } static void match_subtree_text(proto_node *node, gpointer data) { - match_data *mdata = (match_data *) data; - const gchar *string = mdata->string; - size_t string_len = mdata->string_len; - capture_file *cf = mdata->cf; - field_info *fi = PNODE_FINFO(node); - gchar label_str[ITEM_LABEL_LENGTH]; - gchar *label_ptr; - size_t label_len; - guint32 i; - guint8 c_char; - size_t c_match = 0; + match_data *mdata = (match_data *) data; + const gchar *string = mdata->string; + size_t string_len = mdata->string_len; + capture_file *cf = mdata->cf; + field_info *fi = PNODE_FINFO(node); + gchar label_str[ITEM_LABEL_LENGTH]; + gchar *label_ptr; + size_t label_len; + guint32 i; + guint8 c_char; + size_t c_match = 0; - /* dissection with an invisible proto tree? */ - ws_assert(fi); + /* dissection with an invisible proto tree? */ + ws_assert(fi); - if (mdata->frame_matched) { - /* We already had a match; don't bother doing any more work. */ - return; - } - - /* Don't match invisible entries. */ - if (proto_item_is_hidden(node)) - return; - - /* was a free format label produced? */ - if (fi->rep) { - label_ptr = fi->rep->representation; - } else { - /* no, make a generic label */ - label_ptr = label_str; - proto_item_fill_label(fi, label_str); - } - - if (cf->regex) { - if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) { - mdata->frame_matched = TRUE; - mdata->finfo = fi; - return; + if (mdata->frame_matched) { + /* We already had a match; don't bother doing any more work. */ + return; } - } else { - /* Does that label match? */ - label_len = strlen(label_ptr); - for (i = 0; i < label_len; i++) { - c_char = label_ptr[i]; - if (cf->case_type) - c_char = g_ascii_toupper(c_char); - if (c_char == string[c_match]) { - c_match++; - if (c_match == string_len) { - /* No need to look further; we have a match */ - mdata->frame_matched = TRUE; - mdata->finfo = fi; - return; + + /* Don't match invisible entries. */ + if (proto_item_is_hidden(node)) + return; + + /* was a free format label produced? */ + if (fi->rep) { + label_ptr = fi->rep->representation; + } else { + /* no, make a generic label */ + label_ptr = label_str; + proto_item_fill_label(fi, label_str); + } + + if (cf->regex) { + if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) { + mdata->frame_matched = TRUE; + mdata->finfo = fi; + return; + } + } else { + /* Does that label match? */ + label_len = strlen(label_ptr); + for (i = 0; i < label_len; i++) { + c_char = label_ptr[i]; + if (cf->case_type) + c_char = g_ascii_toupper(c_char); + if (c_char == string[c_match]) { + c_match++; + if (c_match == string_len) { + /* No need to look further; we have a match */ + mdata->frame_matched = TRUE; + mdata->finfo = fi; + return; + } + } else + c_match = 0; } - } else - c_match = 0; } - } - /* Recurse into the subtree, if it exists */ - if (node->first_child != NULL) - proto_tree_children_foreach(node, match_subtree_text, mdata); + /* Recurse into the subtree, if it exists */ + if (node->first_child != NULL) + proto_tree_children_foreach(node, match_subtree_text, mdata); } gboolean cf_find_packet_summary_line(capture_file *cf, const char *string, - search_direction dir) + search_direction dir) { - match_data mdata; + match_data mdata; - mdata.string = string; - mdata.string_len = strlen(string); - return find_packet(cf, match_summary_line, &mdata, dir); + mdata.string = string; + mdata.string_len = strlen(string); + return find_packet(cf, match_summary_line, &mdata, dir); } static match_result match_summary_line(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - match_data *mdata = (match_data *)criterion; - const gchar *string = mdata->string; - size_t string_len = mdata->string_len; - epan_dissect_t edt; - const char *info_column; - size_t info_column_len; - match_result result = MR_NOTMATCHED; - gint colx; - guint32 i; - guint8 c_char; - size_t c_match = 0; + match_data *mdata = (match_data *)criterion; + const gchar *string = mdata->string; + size_t string_len = mdata->string_len; + epan_dissect_t edt; + const char *info_column; + size_t info_column_len; + match_result result = MR_NOTMATCHED; + gint colx; + guint32 i; + guint8 c_char; + size_t c_match = 0; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - /* Don't bother constructing the protocol tree */ - epan_dissect_init(&edt, cf->epan, FALSE, FALSE); - /* Get the column information */ - epan_dissect_run(&edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, &cf->cinfo); - - /* Find the Info column */ - for (colx = 0; colx < cf->cinfo.num_cols; colx++) { - if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) { - /* Found it. See if we match. */ - info_column = edt.pi.cinfo->columns[colx].col_data; - info_column_len = strlen(info_column); - if (cf->regex) { - if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) { - result = MR_MATCHED; - break; - } - } else { - for (i = 0; i < info_column_len; i++) { - c_char = info_column[i]; - if (cf->case_type) - c_char = g_ascii_toupper(c_char); - if (c_char == string[c_match]) { - c_match++; - if (c_match == string_len) { - result = MR_MATCHED; - break; - } - } else - c_match = 0; - } - } - break; + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; } - } - epan_dissect_cleanup(&edt); - return result; + + /* Don't bother constructing the protocol tree */ + epan_dissect_init(&edt, cf->epan, FALSE, FALSE); + /* Get the column information */ + epan_dissect_run(&edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, &cf->cinfo); + + /* Find the Info column */ + for (colx = 0; colx < cf->cinfo.num_cols; colx++) { + if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) { + /* Found it. See if we match. */ + info_column = edt.pi.cinfo->columns[colx].col_data; + info_column_len = strlen(info_column); + if (cf->regex) { + if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) { + result = MR_MATCHED; + break; + } + } else { + for (i = 0; i < info_column_len; i++) { + c_char = info_column[i]; + if (cf->case_type) + c_char = g_ascii_toupper(c_char); + if (c_char == string[c_match]) { + c_match++; + if (c_match == string_len) { + result = MR_MATCHED; + break; + } + } else + c_match = 0; + } + } + break; + } + } + epan_dissect_cleanup(&edt); + return result; } typedef struct { @@ -3277,478 +3288,478 @@ typedef struct { gboolean cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size, - search_direction dir) + search_direction dir) { - cbs_t info; - guint8 needles[3]; - ws_mempbrk_pattern pattern; + cbs_t info; + guint8 needles[3]; + ws_mempbrk_pattern pattern; - info.data = string; - info.data_len = string_size; + info.data = string; + info.data_len = string_size; - /* Regex, String or hex search? */ - if (cf->regex) { - /* Regular Expression search */ - return find_packet(cf, match_regex, NULL, dir); - } else if (cf->string) { - /* String search - what type of string? */ - if (cf->case_type) { - needles[0] = string[0]; - needles[1] = g_ascii_tolower(needles[0]); - needles[2] = '\0'; - ws_mempbrk_compile(&pattern, needles); - info.pattern = &pattern; - switch (cf->scs_type) { + /* Regex, String or hex search? */ + if (cf->regex) { + /* Regular Expression search */ + return find_packet(cf, match_regex, NULL, dir); + } else if (cf->string) { + /* String search - what type of string? */ + if (cf->case_type) { + needles[0] = string[0]; + needles[1] = g_ascii_tolower(needles[0]); + needles[2] = '\0'; + ws_mempbrk_compile(&pattern, needles); + info.pattern = &pattern; + switch (cf->scs_type) { - case SCS_NARROW_AND_WIDE: - return find_packet(cf, match_narrow_and_wide_case, &info, dir); + case SCS_NARROW_AND_WIDE: + return find_packet(cf, match_narrow_and_wide_case, &info, dir); - case SCS_NARROW: - return find_packet(cf, match_narrow_case, &info, dir); + case SCS_NARROW: + return find_packet(cf, match_narrow_case, &info, dir); - case SCS_WIDE: - return find_packet(cf, match_wide_case, &info, dir); + case SCS_WIDE: + return find_packet(cf, match_wide_case, &info, dir); - default: - ws_assert_not_reached(); - return FALSE; - } + default: + ws_assert_not_reached(); + return FALSE; + } - } else { - switch (cf->scs_type) { + } else { + switch (cf->scs_type) { - case SCS_NARROW_AND_WIDE: - return find_packet(cf, match_narrow_and_wide, &info, dir); + case SCS_NARROW_AND_WIDE: + return find_packet(cf, match_narrow_and_wide, &info, dir); - case SCS_NARROW: - return find_packet(cf, match_narrow, &info, dir); + case SCS_NARROW: + return find_packet(cf, match_narrow, &info, dir); - case SCS_WIDE: - return find_packet(cf, match_wide, &info, dir); + case SCS_WIDE: + return find_packet(cf, match_wide, &info, dir); - default: - ws_assert_not_reached(); - return FALSE; - } - } - } else - return find_packet(cf, match_binary, &info, dir); + default: + ws_assert_not_reached(); + return FALSE; + } + } + } else + return find_packet(cf, match_binary, &info, dir); } static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); - if (pd == NULL) break; - /* Try narrow match at this start location */ - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = pd[i]; - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; - } - } else { - break; - } + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; } - /* Now try wide match at the same start location. */ - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = pd[i]; - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); + if (pd == NULL) break; + /* Try narrow match at this start location */ + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = pd[i]; + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } + } + + /* Now try wide match at the same start location. */ + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = pd[i]; + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + i++; + if (pd + i >= buf_end || pd[i] != '\0') break; + } else { + break; + } } - i++; - if (pd + i >= buf_end || pd[i] != '\0') break; - } else { - break; - } } - } done: - return result; + return result; } /* Case insensitive match */ static match_result match_narrow_and_wide_case(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - ws_mempbrk_pattern *pattern = info->pattern; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + ws_mempbrk_pattern *pattern = info->pattern; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - ws_assert(pattern != NULL); - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); - if (pd == NULL) break; - /* Try narrow match at this start location */ - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = g_ascii_toupper(pd[i]); - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; - } - } else { - break; - } + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; } - /* Now try wide match at the same start location. */ - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = g_ascii_toupper(pd[i]); - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; + ws_assert(pattern != NULL); + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); + if (pd == NULL) break; + /* Try narrow match at this start location */ + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = g_ascii_toupper(pd[i]); + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } + } + + /* Now try wide match at the same start location. */ + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = g_ascii_toupper(pd[i]); + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + i++; + if (pd + i >= buf_end || pd[i] != '\0') break; + } else { + break; + } } - i++; - if (pd + i >= buf_end || pd[i] != '\0') break; - } else { - break; - } } - } done: - return result; + return result; } static match_result match_narrow(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = pd[i]; - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; - } - } else { - break; - } + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = pd[i]; + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } + } } - } done: - return result; + return result; } /* Case insensitive match */ static match_result match_narrow_case(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - ws_mempbrk_pattern *pattern = info->pattern; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + ws_mempbrk_pattern *pattern = info->pattern; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - ws_assert(pattern != NULL); - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = g_ascii_toupper(pd[i]); - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; - } - } else { - break; - } + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + ws_assert(pattern != NULL); + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = g_ascii_toupper(pd[i]); + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } + } } - } done: - return result; + return result; } static match_result match_wide(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = pd[i]; - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; - } - i++; - if (pd + i >= buf_end || pd[i] != '\0') break; - } else { - break; - } + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)memchr(pd, ascii_text[0], buf_end - pd); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = pd[i]; + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + i++; + if (pd + i >= buf_end || pd[i] != '\0') break; + } else { + break; + } + } } - } done: - return result; + return result; } /* Case insensitive match */ static match_result match_wide_case(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *ascii_text = info->data; - size_t textlen = info->data_len; - ws_mempbrk_pattern *pattern = info->pattern; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - guint8 c_char; - size_t c_match = 0; + cbs_t *info = (cbs_t *)criterion; + const guint8 *ascii_text = info->data; + size_t textlen = info->data_len; + ws_mempbrk_pattern *pattern = info->pattern; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + guint8 c_char; + size_t c_match = 0; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - ws_assert(pattern != NULL); - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - c_char = g_ascii_toupper(pd[i]); - if (c_char == ascii_text[c_match]) { - c_match++; - if (c_match == textlen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; - } - i++; - if (pd + i >= buf_end || pd[i] != '\0') break; - } else { - break; - } + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + ws_assert(pattern != NULL); + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)ws_mempbrk_exec(pd, buf_end - pd, pattern, &c_char); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + c_char = g_ascii_toupper(pd[i]); + if (c_char == ascii_text[c_match]) { + c_match++; + if (c_match == textlen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + i++; + if (pd + i >= buf_end || pd[i] != '\0') break; + } else { + break; + } + } } - } done: - return result; + return result; } static match_result match_binary(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - cbs_t *info = (cbs_t *)criterion; - const guint8 *binary_data = info->data; - size_t datalen = info->data_len; - match_result result; - guint32 buf_len; - guint8 *pd, *buf_start, *buf_end; - guint32 i; - size_t c_match = 0; + cbs_t *info = (cbs_t *)criterion; + const guint8 *binary_data = info->data; + size_t datalen = info->data_len; + match_result result; + guint32 buf_len; + guint8 *pd, *buf_start, *buf_end; + guint32 i; + size_t c_match = 0; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } - - result = MR_NOTMATCHED; - buf_len = fdata->cap_len; - buf_start = ws_buffer_start_ptr(buf); - buf_end = buf_start + buf_len; - /* Not clear if using memcmp() is faster. memmem() on systems that - * have it should be faster, though. - */ - for (pd = buf_start; pd < buf_end; pd++) { - pd = (guint8 *)memchr(pd, binary_data[0], buf_end - pd); - if (pd == NULL) break; - c_match = 0; - for (i = 0; pd + i < buf_end; i++) { - if (pd[i] == binary_data[c_match]) { - c_match++; - if (c_match == datalen) { - result = MR_MATCHED; - cf->search_pos = i + (guint32)(pd - buf_start); - /* Save the position of the last character - for highlighting the field. */ - cf->search_len = i + 1; - goto done; - } - } else { - break; - } + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } + + result = MR_NOTMATCHED; + buf_len = fdata->cap_len; + buf_start = ws_buffer_start_ptr(buf); + buf_end = buf_start + buf_len; + /* Not clear if using memcmp() is faster. memmem() on systems that + * have it should be faster, though. + */ + for (pd = buf_start; pd < buf_end; pd++) { + pd = (guint8 *)memchr(pd, binary_data[0], buf_end - pd); + if (pd == NULL) break; + c_match = 0; + for (i = 0; pd + i < buf_end; i++) { + if (pd[i] == binary_data[c_match]) { + c_match++; + if (c_match == datalen) { + result = MR_MATCHED; + cf->search_pos = i + (guint32)(pd - buf_start); + /* Save the position of the last character + for highlighting the field. */ + cf->search_len = i + 1; + goto done; + } + } else { + break; + } + } } - } done: - return result; + return result; } static match_result match_regex(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion _U_) + wtap_rec *rec, Buffer *buf, void *criterion _U_) { match_result result = MR_NOTMATCHED; GMatchInfo *match_info = NULL; @@ -3760,7 +3771,7 @@ match_regex(capture_file *cf, frame_data *fdata, } if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(buf), fdata->cap_len, - 0, (GRegexMatchFlags) 0, &match_info, NULL)) + 0, (GRegexMatchFlags) 0, &match_info, NULL)) { gint start_pos = 0, end_pos = 0; g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos); @@ -3773,296 +3784,296 @@ match_regex(capture_file *cf, frame_data *fdata, gboolean cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode, - search_direction dir) + search_direction dir) { - return find_packet(cf, match_dfilter, sfcode, dir); + return find_packet(cf, match_dfilter, sfcode, dir); } gboolean cf_find_packet_dfilter_string(capture_file *cf, const char *filter, - search_direction dir) + search_direction dir) { - dfilter_t *sfcode; - gboolean result; + dfilter_t *sfcode; + gboolean result; - if (!dfilter_compile(filter, &sfcode, NULL)) { - /* - * XXX - this shouldn't happen, as the filter string is machine - * generated - */ - return FALSE; - } - if (sfcode == NULL) { - /* - * XXX - this shouldn't happen, as the filter string is machine - * generated. - */ - return FALSE; - } - result = find_packet(cf, match_dfilter, sfcode, dir); - dfilter_free(sfcode); - return result; + if (!dfilter_compile(filter, &sfcode, NULL)) { + /* + * XXX - this shouldn't happen, as the filter string is machine + * generated + */ + return FALSE; + } + if (sfcode == NULL) { + /* + * XXX - this shouldn't happen, as the filter string is machine + * generated. + */ + return FALSE; + } + result = find_packet(cf, match_dfilter, sfcode, dir); + dfilter_free(sfcode); + return result; } static match_result match_dfilter(capture_file *cf, frame_data *fdata, - wtap_rec *rec, Buffer *buf, void *criterion) + wtap_rec *rec, Buffer *buf, void *criterion) { - dfilter_t *sfcode = (dfilter_t *)criterion; - epan_dissect_t edt; - match_result result; + dfilter_t *sfcode = (dfilter_t *)criterion; + epan_dissect_t edt; + match_result result; - /* Load the frame's data. */ - if (!cf_read_record(cf, fdata, rec, buf)) { - /* Attempt to get the packet failed. */ - return MR_ERROR; - } + /* Load the frame's data. */ + if (!cf_read_record(cf, fdata, rec, buf)) { + /* Attempt to get the packet failed. */ + return MR_ERROR; + } - epan_dissect_init(&edt, cf->epan, TRUE, FALSE); - epan_dissect_prime_with_dfilter(&edt, sfcode); - epan_dissect_run(&edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, NULL); - result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED; - epan_dissect_cleanup(&edt); - return result; + epan_dissect_init(&edt, cf->epan, TRUE, FALSE); + epan_dissect_prime_with_dfilter(&edt, sfcode); + epan_dissect_run(&edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, NULL); + result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED; + epan_dissect_cleanup(&edt); + return result; } gboolean cf_find_packet_marked(capture_file *cf, search_direction dir) { - return find_packet(cf, match_marked, NULL, dir); + return find_packet(cf, match_marked, NULL, dir); } static match_result match_marked(capture_file *cf _U_, frame_data *fdata, wtap_rec *rec _U_, - Buffer *buf _U_, void *criterion _U_) + Buffer *buf _U_, void *criterion _U_) { - return fdata->marked ? MR_MATCHED : MR_NOTMATCHED; + return fdata->marked ? MR_MATCHED : MR_NOTMATCHED; } gboolean cf_find_packet_time_reference(capture_file *cf, search_direction dir) { - return find_packet(cf, match_time_reference, NULL, dir); + return find_packet(cf, match_time_reference, NULL, dir); } static match_result match_time_reference(capture_file *cf _U_, frame_data *fdata, wtap_rec *rec _U_, - Buffer *buf _U_, void *criterion _U_) + Buffer *buf _U_, void *criterion _U_) { - return fdata->ref_time ? MR_MATCHED : MR_NOTMATCHED; + return fdata->ref_time ? MR_MATCHED : MR_NOTMATCHED; } static gboolean find_packet(capture_file *cf, ws_match_function match_function, - void *criterion, search_direction dir) + void *criterion, search_direction dir) { - frame_data *start_fd; - guint32 framenum; - guint32 prev_framenum; - frame_data *fdata; - wtap_rec rec; - Buffer buf; - frame_data *new_fd = NULL; - progdlg_t *progbar = NULL; - GTimer *prog_timer = g_timer_new(); - int count; - gboolean succeeded; - float progbar_val; - gchar status_str[100]; - match_result result; + frame_data *start_fd; + guint32 framenum; + guint32 prev_framenum; + frame_data *fdata; + wtap_rec rec; + Buffer buf; + frame_data *new_fd = NULL; + progdlg_t *progbar = NULL; + GTimer *prog_timer = g_timer_new(); + int count; + gboolean succeeded; + float progbar_val; + gchar status_str[100]; + match_result result; - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - start_fd = cf->current_frame; - if (start_fd != NULL) { - prev_framenum = start_fd->num; - } else { - prev_framenum = 0; /* No start packet selected. */ - } - - /* Iterate through the list of packets, starting at the packet we've - picked, calling a routine to run the filter on the packet, see if - it matches, and stop if so. */ - count = 0; - framenum = prev_framenum; - - g_timer_start(prog_timer); - /* Progress so far. */ - progbar_val = 0.0f; - - cf->stop_flag = FALSE; - - for (;;) { - /* Create the progress bar if necessary. - We check on every iteration of the loop, so that it takes no - longer than the standard time to create it (otherwise, for a - large file, we might take considerably longer than that standard - time in order to get to the next progress bar step). */ - if (progbar == NULL) - progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, - FALSE, &cf->stop_flag, progbar_val); - - /* - * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL - * has elapsed. Calling update_progress_dlg and packets_bar_update will - * likely trigger UI paint events, which might take a while depending on - * the platform and display. Reset our timer *after* painting. - */ - if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - /* let's not divide by zero. I should never be started - * with count == 0, so let's assert that - */ - ws_assert(cf->count > 0); - - progbar_val = (gfloat) count / cf->count; - - snprintf(status_str, sizeof(status_str), - "%4u of %u packets", count, cf->count); - update_progress_dlg(progbar, progbar_val, status_str); - - g_timer_start(prog_timer); - } - - if (cf->stop_flag) { - /* Well, the user decided to abort the search. Go back to the - frame where we started. */ - new_fd = start_fd; - break; - } - - /* Go past the current frame. */ - if (dir == SD_BACKWARD) { - /* Go on to the previous frame. */ - if (framenum <= 1) { - /* - * XXX - other apps have a bit more of a detailed message - * for this, and instead of offering "OK" and "Cancel", - * they offer things such as "Continue" and "Cancel"; - * we need an API for popping up alert boxes with - * {Verb} and "Cancel". - */ - - if (prefs.gui_find_wrap) { - statusbar_push_temporary_msg("Search reached the beginning. Continuing at end."); - framenum = cf->count; /* wrap around */ - } else { - statusbar_push_temporary_msg("Search reached the beginning."); - framenum = prev_framenum; /* stay on previous packet */ - } - } else - framenum--; + start_fd = cf->current_frame; + if (start_fd != NULL) { + prev_framenum = start_fd->num; } else { - /* Go on to the next frame. */ - if (framenum == cf->count) { - if (prefs.gui_find_wrap) { - statusbar_push_temporary_msg("Search reached the end. Continuing at beginning."); - framenum = 1; /* wrap around */ - } else { - statusbar_push_temporary_msg("Search reached the end."); - framenum = prev_framenum; /* stay on previous packet */ + prev_framenum = 0; /* No start packet selected. */ + } + + /* Iterate through the list of packets, starting at the packet we've + picked, calling a routine to run the filter on the packet, see if + it matches, and stop if so. */ + count = 0; + framenum = prev_framenum; + + g_timer_start(prog_timer); + /* Progress so far. */ + progbar_val = 0.0f; + + cf->stop_flag = FALSE; + + for (;;) { + /* Create the progress bar if necessary. + We check on every iteration of the loop, so that it takes no + longer than the standard time to create it (otherwise, for a + large file, we might take considerably longer than that standard + time in order to get to the next progress bar step). */ + if (progbar == NULL) + progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, + FALSE, &cf->stop_flag, progbar_val); + + /* + * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL + * has elapsed. Calling update_progress_dlg and packets_bar_update will + * likely trigger UI paint events, which might take a while depending on + * the platform and display. Reset our timer *after* painting. + */ + if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + /* let's not divide by zero. I should never be started + * with count == 0, so let's assert that + */ + ws_assert(cf->count > 0); + + progbar_val = (gfloat) count / cf->count; + + snprintf(status_str, sizeof(status_str), + "%4u of %u packets", count, cf->count); + update_progress_dlg(progbar, progbar_val, status_str); + + g_timer_start(prog_timer); + } + + if (cf->stop_flag) { + /* Well, the user decided to abort the search. Go back to the + frame where we started. */ + new_fd = start_fd; + break; + } + + /* Go past the current frame. */ + if (dir == SD_BACKWARD) { + /* Go on to the previous frame. */ + if (framenum <= 1) { + /* + * XXX - other apps have a bit more of a detailed message + * for this, and instead of offering "OK" and "Cancel", + * they offer things such as "Continue" and "Cancel"; + * we need an API for popping up alert boxes with + * {Verb} and "Cancel". + */ + + if (prefs.gui_find_wrap) { + statusbar_push_temporary_msg("Search reached the beginning. Continuing at end."); + framenum = cf->count; /* wrap around */ + } else { + statusbar_push_temporary_msg("Search reached the beginning."); + framenum = prev_framenum; /* stay on previous packet */ + } + } else + framenum--; + } else { + /* Go on to the next frame. */ + if (framenum == cf->count) { + if (prefs.gui_find_wrap) { + statusbar_push_temporary_msg("Search reached the end. Continuing at beginning."); + framenum = 1; /* wrap around */ + } else { + statusbar_push_temporary_msg("Search reached the end."); + framenum = prev_framenum; /* stay on previous packet */ + } + } else + framenum++; + } + + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + count++; + + /* Is this packet in the display? */ + if (fdata && fdata->passed_dfilter) { + /* Yes. Does it match the search criterion? */ + result = (*match_function)(cf, fdata, &rec, &buf, criterion); + if (result == MR_ERROR) { + /* Error; our caller has reported the error. Go back to the frame + where we started. */ + new_fd = start_fd; + break; + } else if (result == MR_MATCHED) { + /* Yes. Go to the new frame. */ + new_fd = fdata; + break; + } + wtap_rec_reset(&rec); + } + + if (fdata == start_fd) { + /* We're back to the frame we were on originally, and that frame + doesn't match the search filter. The search failed. */ + break; } - } else - framenum++; } - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - count++; + /* We're done scanning the packets; destroy the progress bar if it + was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); - /* Is this packet in the display? */ - if (fdata && fdata->passed_dfilter) { - /* Yes. Does it match the search criterion? */ - result = (*match_function)(cf, fdata, &rec, &buf, criterion); - if (result == MR_ERROR) { - /* Error; our caller has reported the error. Go back to the frame - where we started. */ - new_fd = start_fd; - break; - } else if (result == MR_MATCHED) { - /* Yes. Go to the new frame. */ - new_fd = fdata; - break; - } - wtap_rec_reset(&rec); - } + if (new_fd != NULL) { + /* We found a frame that's displayed and that matches. + Try to find and select the packet summary list row for that frame. */ + gboolean found_row; - if (fdata == start_fd) { - /* We're back to the frame we were on originally, and that frame - doesn't match the search filter. The search failed. */ - break; - } - } - - /* We're done scanning the packets; destroy the progress bar if it - was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); - - if (new_fd != NULL) { - /* We found a frame that's displayed and that matches. - Try to find and select the packet summary list row for that frame. */ - gboolean found_row; - - cf->search_in_progress = TRUE; - found_row = packet_list_select_row_from_data(new_fd); - cf->search_in_progress = FALSE; - cf->search_pos = 0; /* Reset the position */ - cf->search_len = 0; /* Reset length */ - if (!found_row) { - /* We didn't find a row corresponding to this frame. - This means that the frame isn't being displayed currently, - so we can't select it. */ - simple_message_box(ESD_TYPE_INFO, NULL, - "The capture file is probably not fully dissected.", - "End of capture exceeded."); - succeeded = FALSE; /* The search succeeded but we didn't find the row */ + cf->search_in_progress = TRUE; + found_row = packet_list_select_row_from_data(new_fd); + cf->search_in_progress = FALSE; + cf->search_pos = 0; /* Reset the position */ + cf->search_len = 0; /* Reset length */ + if (!found_row) { + /* We didn't find a row corresponding to this frame. + This means that the frame isn't being displayed currently, + so we can't select it. */ + simple_message_box(ESD_TYPE_INFO, NULL, + "The capture file is probably not fully dissected.", + "End of capture exceeded."); + succeeded = FALSE; /* The search succeeded but we didn't find the row */ + } else + succeeded = TRUE; /* The search succeeded and we found the row */ } else - succeeded = TRUE; /* The search succeeded and we found the row */ - } else - succeeded = FALSE; /* The search failed */ - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - return succeeded; + succeeded = FALSE; /* The search failed */ + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + return succeeded; } gboolean cf_goto_frame(capture_file *cf, guint fnumber) { - frame_data *fdata; + frame_data *fdata; - if (cf == NULL || cf->provider.frames == NULL) { - /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */ - statusbar_push_temporary_msg("There is no file loaded"); - return FALSE; /* we failed to go to that packet */ - } + if (cf == NULL || cf->provider.frames == NULL) { + /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */ + statusbar_push_temporary_msg("There is no file loaded"); + return FALSE; /* we failed to go to that packet */ + } - fdata = frame_data_sequence_find(cf->provider.frames, fnumber); + fdata = frame_data_sequence_find(cf->provider.frames, fnumber); - if (fdata == NULL) { - /* we didn't find a packet with that packet number */ - statusbar_push_temporary_msg("There is no packet number %u.", fnumber); - return FALSE; /* we failed to go to that packet */ - } - if (!fdata->passed_dfilter) { - /* that packet currently isn't displayed */ - /* XXX - add it to the set of displayed packets? */ - statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber); - return FALSE; /* we failed to go to that packet */ - } + if (fdata == NULL) { + /* we didn't find a packet with that packet number */ + statusbar_push_temporary_msg("There is no packet number %u.", fnumber); + return FALSE; /* we failed to go to that packet */ + } + if (!fdata->passed_dfilter) { + /* that packet currently isn't displayed */ + /* XXX - add it to the set of displayed packets? */ + statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber); + return FALSE; /* we failed to go to that packet */ + } - if (!packet_list_select_row_from_data(fdata)) { - /* We didn't find a row corresponding to this frame. - This means that the frame isn't being displayed currently, - so we can't select it. */ - simple_message_box(ESD_TYPE_INFO, NULL, - "The capture file is probably not fully dissected.", - "End of capture exceeded."); - return FALSE; - } - return TRUE; /* we got to that packet */ + if (!packet_list_select_row_from_data(fdata)) { + /* We didn't find a row corresponding to this frame. + This means that the frame isn't being displayed currently, + so we can't select it. */ + simple_message_box(ESD_TYPE_INFO, NULL, + "The capture file is probably not fully dissected.", + "End of capture exceeded."); + return FALSE; + } + return TRUE; /* we got to that packet */ } /* @@ -4071,99 +4082,99 @@ cf_goto_frame(capture_file *cf, guint fnumber) gboolean cf_goto_framenum(capture_file *cf) { - header_field_info *hfinfo; - guint32 framenum; + header_field_info *hfinfo; + guint32 framenum; - if (cf->finfo_selected) { - hfinfo = cf->finfo_selected->hfinfo; - ws_assert(hfinfo); - if (hfinfo->type == FT_FRAMENUM) { - framenum = fvalue_get_uinteger(&cf->finfo_selected->value); - if (framenum != 0) - return cf_goto_frame(cf, framenum); - } - } + if (cf->finfo_selected) { + hfinfo = cf->finfo_selected->hfinfo; + ws_assert(hfinfo); + if (hfinfo->type == FT_FRAMENUM) { + framenum = fvalue_get_uinteger(&cf->finfo_selected->value); + if (framenum != 0) + return cf_goto_frame(cf, framenum); + } + } - return FALSE; + return FALSE; } /* Select the packet on a given row. */ void cf_select_packet(capture_file *cf, int row) { - epan_dissect_t *old_edt; - frame_data *fdata; + epan_dissect_t *old_edt; + frame_data *fdata; - /* Get the frame data struct pointer for this frame */ - fdata = packet_list_get_row_data(row); + /* Get the frame data struct pointer for this frame */ + fdata = packet_list_get_row_data(row); - if (fdata == NULL) { - return; - } + if (fdata == NULL) { + return; + } - /* Get the data in that frame. */ - if (!cf_read_record(cf, fdata, &cf->rec, &cf->buf)) { - return; - } + /* Get the data in that frame. */ + if (!cf_read_record(cf, fdata, &cf->rec, &cf->buf)) { + return; + } - /* Record that this frame is the current frame. */ - cf->current_frame = fdata; - cf->current_row = row; + /* Record that this frame is the current frame. */ + cf->current_frame = fdata; + cf->current_row = row; - /* - * The change to defer freeing the current epan_dissect_t was in - * commit a2bb94c3b33d53f42534aceb7cc67aab1d1fb1f9; to quote - * that commit's comment: - * - * Clear GtkTreeStore before freeing edt - * - * When building current data for packet details treeview we store two - * things. - * - Generated string with item label - * - Pointer to node field_info structure - * - * After epan_dissect_{free, cleanup} pointer to field_info node is no - * longer valid so we should clear GtkTreeStore before freeing. - * - * XXX - we're no longer using GTK+; is there a way to ensure that - * *nothing* refers to any of the current frame information before - * we replace it? - */ - old_edt = cf->edt; - /* Create the logical protocol tree. */ - /* We don't need the columns here. */ - cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE); + /* + * The change to defer freeing the current epan_dissect_t was in + * commit a2bb94c3b33d53f42534aceb7cc67aab1d1fb1f9; to quote + * that commit's comment: + * + * Clear GtkTreeStore before freeing edt + * + * When building current data for packet details treeview we store two + * things. + * - Generated string with item label + * - Pointer to node field_info structure + * + * After epan_dissect_{free, cleanup} pointer to field_info node is no + * longer valid so we should clear GtkTreeStore before freeing. + * + * XXX - we're no longer using GTK+; is there a way to ensure that + * *nothing* refers to any of the current frame information before + * we replace it? + */ + old_edt = cf->edt; + /* Create the logical protocol tree. */ + /* We don't need the columns here. */ + cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE); - tap_build_interesting(cf->edt); - epan_dissect_run(cf->edt, cf->cd_t, &cf->rec, - frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf), - cf->current_frame, NULL); + tap_build_interesting(cf->edt); + epan_dissect_run(cf->edt, cf->cd_t, &cf->rec, + frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf), + cf->current_frame, NULL); - dfilter_macro_build_ftv_cache(cf->edt->tree); + dfilter_macro_build_ftv_cache(cf->edt->tree); - if (old_edt != NULL) - epan_dissect_free(old_edt); + if (old_edt != NULL) + epan_dissect_free(old_edt); } /* Unselect the selected packet, if any. */ void cf_unselect_packet(capture_file *cf) { - epan_dissect_t *old_edt = cf->edt; + epan_dissect_t *old_edt = cf->edt; - /* - * See the comment in cf_select_packet() about deferring the freeing - * of the old cf->edt. - */ - cf->edt = NULL; + /* + * See the comment in cf_select_packet() about deferring the freeing + * of the old cf->edt. + */ + cf->edt = NULL; - /* No packet is selected. */ - cf->current_frame = NULL; - cf->current_row = 0; + /* No packet is selected. */ + cf->current_frame = NULL; + cf->current_row = 0; - /* Destroy the epan_dissect_t for the unselected packet. */ - if (old_edt != NULL) - epan_dissect_free(old_edt); + /* Destroy the epan_dissect_t for the unselected packet. */ + if (old_edt != NULL) + epan_dissect_free(old_edt); } /* @@ -4172,11 +4183,11 @@ cf_unselect_packet(capture_file *cf) void cf_mark_frame(capture_file *cf, frame_data *frame) { - if (! frame->marked) { - frame->marked = TRUE; - if (cf->count > cf->marked_count) - cf->marked_count++; - } + if (! frame->marked) { + frame->marked = TRUE; + if (cf->count > cf->marked_count) + cf->marked_count++; + } } /* @@ -4185,11 +4196,11 @@ cf_mark_frame(capture_file *cf, frame_data *frame) void cf_unmark_frame(capture_file *cf, frame_data *frame) { - if (frame->marked) { - frame->marked = FALSE; - if (cf->marked_count > 0) - cf->marked_count--; - } + if (frame->marked) { + frame->marked = FALSE; + if (cf->marked_count > 0) + cf->marked_count--; + } } /* @@ -4198,11 +4209,11 @@ cf_unmark_frame(capture_file *cf, frame_data *frame) void cf_ignore_frame(capture_file *cf, frame_data *frame) { - if (! frame->ignored) { - frame->ignored = TRUE; - if (cf->count > cf->ignored_count) - cf->ignored_count++; - } + if (! frame->ignored) { + frame->ignored = TRUE; + if (cf->count > cf->ignored_count) + cf->ignored_count++; + } } /* @@ -4211,11 +4222,11 @@ cf_ignore_frame(capture_file *cf, frame_data *frame) void cf_unignore_frame(capture_file *cf, frame_data *frame) { - if (frame->ignored) { - frame->ignored = FALSE; - if (cf->ignored_count > 0) - cf->ignored_count--; - } + if (frame->ignored) { + frame->ignored = FALSE; + if (cf->ignored_count > 0) + cf->ignored_count--; + } } /* @@ -4224,30 +4235,30 @@ cf_unignore_frame(capture_file *cf, frame_data *frame) void cf_update_section_comment(capture_file *cf, gchar *comment) { - wtap_block_t shb_inf; - gchar *shb_comment; + wtap_block_t shb_inf; + gchar *shb_comment; - /* Get the first SHB. */ - /* XXX - support multiple SHBs */ - shb_inf = wtap_file_get_shb(cf->provider.wth, 0); + /* Get the first SHB. */ + /* XXX - support multiple SHBs */ + shb_inf = wtap_file_get_shb(cf->provider.wth, 0); - /* Get the first comment from the SHB. */ - /* XXX - support multiple comments */ - if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) { - /* There's no comment - add one. */ - wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment)); - } else { - /* See if the comment has changed or not */ - if (strcmp(shb_comment, comment) == 0) { - g_free(comment); - return; + /* Get the first comment from the SHB. */ + /* XXX - support multiple comments */ + if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) { + /* There's no comment - add one. */ + wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment)); + } else { + /* See if the comment has changed or not */ + if (strcmp(shb_comment, comment) == 0) { + g_free(comment); + return; + } + + /* The comment has changed, let's update it */ + wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment)); } - - /* The comment has changed, let's update it */ - wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment)); - } - /* Mark the file as having unsaved changes */ - cf->unsaved_changes = TRUE; + /* Mark the file as having unsaved changes */ + cf->unsaved_changes = TRUE; } /* @@ -4259,28 +4270,28 @@ cf_update_section_comment(capture_file *cf, gchar *comment) wtap_block_t cf_get_packet_block(capture_file *cf, const frame_data *fd) { - /* If this block has been modified, fetch the modified version */ - if (fd->has_modified_block) - return wtap_block_ref(cap_file_provider_get_modified_block(&cf->provider, fd)); - else { - wtap_rec rec; /* Record metadata */ - Buffer buf; /* Record data */ - wtap_block_t block; + /* If this block has been modified, fetch the modified version */ + if (fd->has_modified_block) + return wtap_block_ref(cap_file_provider_get_modified_block(&cf->provider, fd)); + else { + wtap_rec rec; /* Record metadata */ + Buffer buf; /* Record data */ + wtap_block_t block; - /* fetch record block */ - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); + /* fetch record block */ + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - if (!cf_read_record(cf, fd, &rec, &buf)) - { /* XXX, what we can do here? */ } + if (!cf_read_record(cf, fd, &rec, &buf)) + { /* XXX, what we can do here? */ } - /* rec.block is owned by the record, steal it before it is gone. */ - block = wtap_block_ref(rec.block); + /* rec.block is owned by the record, steal it before it is gone. */ + block = wtap_block_ref(rec.block); - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - return block; - } + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + return block; + } } /* @@ -4289,36 +4300,36 @@ cf_get_packet_block(capture_file *cf, const frame_data *fd) gboolean cf_set_modified_block(capture_file *cf, frame_data *fd, const wtap_block_t new_block) { - wtap_block_t pkt_block = cf_get_packet_block(cf, fd); + wtap_block_t pkt_block = cf_get_packet_block(cf, fd); - /* It's possible to further modify the modified block "in place" by doing - * a call to cf_get_packet_block() that returns an already created modified - * block, modifying that, and calling this function. - * If the caller did that, then the block pointers will be equal. - */ - if (pkt_block == new_block) { - /* No need to save anything here, the caller changes went right - * onto the block. - * Unfortunately we don't have a way to know how many comments were in the block - * before the caller modified it. + /* It's possible to further modify the modified block "in place" by doing + * a call to cf_get_packet_block() that returns an already created modified + * block, modifying that, and calling this function. + * If the caller did that, then the block pointers will be equal. */ - } - else { - if (pkt_block) - cf->packet_comment_count -= wtap_block_count_option(pkt_block, OPT_COMMENT); + if (pkt_block == new_block) { + /* No need to save anything here, the caller changes went right + * onto the block. + * Unfortunately we don't have a way to know how many comments were in the block + * before the caller modified it. + */ + } + else { + if (pkt_block) + cf->packet_comment_count -= wtap_block_count_option(pkt_block, OPT_COMMENT); - if (new_block) - cf->packet_comment_count += wtap_block_count_option(new_block, OPT_COMMENT); + if (new_block) + cf->packet_comment_count += wtap_block_count_option(new_block, OPT_COMMENT); - cap_file_provider_set_modified_block(&cf->provider, fd, new_block); + cap_file_provider_set_modified_block(&cf->provider, fd, new_block); - expert_update_comment_count(cf->packet_comment_count); - } + expert_update_comment_count(cf->packet_comment_count); + } - /* Either way, we have unsaved changes. */ - wtap_block_unref(pkt_block); - cf->unsaved_changes = TRUE; - return TRUE; + /* Either way, we have unsaved changes. */ + wtap_block_unref(pkt_block); + cf->unsaved_changes = TRUE; + return TRUE; } /* @@ -4327,32 +4338,32 @@ cf_set_modified_block(capture_file *cf, frame_data *fd, const wtap_block_t new_b guint32 cf_comment_types(capture_file *cf) { - guint32 comment_types = 0; + guint32 comment_types = 0; - /* - * Does this file have any sections with at least one comment? - */ - for (guint section_number = 0; - section_number < wtap_file_get_num_shbs(cf->provider.wth); - section_number++) { - wtap_block_t shb_inf; - char *shb_comment; + /* + * Does this file have any sections with at least one comment? + */ + for (guint section_number = 0; + section_number < wtap_file_get_num_shbs(cf->provider.wth); + section_number++) { + wtap_block_t shb_inf; + char *shb_comment; - shb_inf = wtap_file_get_shb(cf->provider.wth, section_number); + shb_inf = wtap_file_get_shb(cf->provider.wth, section_number); - /* Try to get the first comment from that SHB. */ - if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, - &shb_comment) == WTAP_OPTTYPE_SUCCESS) { - /* We succeeded, so this file has at least one section comment. */ - comment_types |= WTAP_COMMENT_PER_SECTION; + /* Try to get the first comment from that SHB. */ + if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, + &shb_comment) == WTAP_OPTTYPE_SUCCESS) { + /* We succeeded, so this file has at least one section comment. */ + comment_types |= WTAP_COMMENT_PER_SECTION; - /* We don't need to search any more. */ - break; + /* We don't need to search any more. */ + break; + } } - } - if (cf->packet_comment_count != 0) - comment_types |= WTAP_COMMENT_PER_PACKET; - return comment_types; + if (cf->packet_comment_count != 0) + comment_types |= WTAP_COMMENT_PER_PACKET; + return comment_types; } /* @@ -4361,22 +4372,22 @@ cf_comment_types(capture_file *cf) gboolean cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name) { - /* - * XXX - support multiple resolved address lists, and add to the one - * attached to this file? - */ - if (!add_ip_name_from_string(addr, name)) - return FALSE; + /* + * XXX - support multiple resolved address lists, and add to the one + * attached to this file? + */ + if (!add_ip_name_from_string(addr, name)) + return FALSE; - /* OK, we have unsaved changes. */ - cf->unsaved_changes = TRUE; - return TRUE; + /* OK, we have unsaved changes. */ + cf->unsaved_changes = TRUE; + return TRUE; } typedef struct { - wtap_dumper *pdh; - const char *fname; - int file_type; + wtap_dumper *pdh; + const char *fname; + int file_type; } save_callback_args_t; /* @@ -4388,35 +4399,35 @@ typedef struct { */ static gboolean save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec, - Buffer *buf, void *argsp) + Buffer *buf, void *argsp) { - save_callback_args_t *args = (save_callback_args_t *)argsp; - wtap_rec new_rec; - int err; - gchar *err_info; - wtap_block_t pkt_block; + save_callback_args_t *args = (save_callback_args_t *)argsp; + wtap_rec new_rec; + int err; + gchar *err_info; + wtap_block_t pkt_block; - /* Copy the record information from what was read in from the file. */ - new_rec = *rec; + /* Copy the record information from what was read in from the file. */ + new_rec = *rec; - /* Make changes based on anything that the user has done but that - hasn't been saved yet. */ - if (fdata->has_modified_block) - pkt_block = cap_file_provider_get_modified_block(&cf->provider, fdata); - else - pkt_block = rec->block; - new_rec.block = pkt_block; - new_rec.block_was_modified = fdata->has_modified_block ? TRUE : FALSE; - /* XXX - what if times have been shifted? */ + /* Make changes based on anything that the user has done but that + hasn't been saved yet. */ + if (fdata->has_modified_block) + pkt_block = cap_file_provider_get_modified_block(&cf->provider, fdata); + else + pkt_block = rec->block; + new_rec.block = pkt_block; + new_rec.block_was_modified = fdata->has_modified_block ? TRUE : FALSE; + /* XXX - what if times have been shifted? */ - /* and save the packet */ - if (!wtap_dump(args->pdh, &new_rec, ws_buffer_start_ptr(buf), &err, &err_info)) { - cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num, - args->file_type); - return FALSE; - } + /* and save the packet */ + if (!wtap_dump(args->pdh, &new_rec, ws_buffer_start_ptr(buf), &err, &err_info)) { + cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num, + args->file_type); + return FALSE; + } - return TRUE; + return TRUE; } /* @@ -4426,10 +4437,10 @@ save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec, gboolean cf_can_write_with_wiretap(capture_file *cf) { - /* We don't care whether we support the comments in this file or not; - if we can't, we'll offer the user the option of discarding the - comments. */ - return wtap_dump_can_write(cf->linktypes, 0); + /* We don't care whether we support the comments in this file or not; + if we can't, we'll offer the user the option of discarding the + comments. */ + return wtap_dump_can_write(cf->linktypes, 0); } /* @@ -4455,21 +4466,21 @@ cf_can_write_with_wiretap(capture_file *cf) gboolean cf_can_save(capture_file *cf) { - if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) { - /* Saved changes, and we can write it out with Wiretap. */ - return TRUE; - } + if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) { + /* Saved changes, and we can write it out with Wiretap. */ + return TRUE; + } - if (cf->is_tempfile && !cf->unsaved_changes) { - /* - * Temporary file with no unsaved changes, so we can just do a - * raw binary copy. - */ - return TRUE; - } + if (cf->is_tempfile && !cf->unsaved_changes) { + /* + * Temporary file with no unsaved changes, so we can just do a + * raw binary copy. + */ + return TRUE; + } - /* Nothing to save. */ - return FALSE; + /* Nothing to save. */ + return FALSE; } /* @@ -4494,21 +4505,21 @@ cf_can_save(capture_file *cf) gboolean cf_can_save_as(capture_file *cf) { - if (wtap_dump_can_write(cf->linktypes, 0)) { - /* We can write it out with Wiretap. */ - return TRUE; - } + if (wtap_dump_can_write(cf->linktypes, 0)) { + /* We can write it out with Wiretap. */ + return TRUE; + } - if (cf->is_tempfile && !cf->unsaved_changes) { - /* - * Temporary file with no unsaved changes, so we can just do a - * raw binary copy. - */ - return TRUE; - } + if (cf->is_tempfile && !cf->unsaved_changes) { + /* + * Temporary file with no unsaved changes, so we can just do a + * raw binary copy. + */ + return TRUE; + } - /* Nothing to save. */ - return FALSE; + /* Nothing to save. */ + return FALSE; } /* @@ -4517,11 +4528,11 @@ cf_can_save_as(capture_file *cf) gboolean cf_has_unsaved_data(capture_file *cf) { - /* - * If this is a temporary file, or a file with unsaved changes, it - * has unsaved data. - */ - return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes; + /* + * If this is a temporary file, or a file with unsaved changes, it + * has unsaved data. + */ + return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes; } /* @@ -4530,287 +4541,546 @@ cf_has_unsaved_data(capture_file *cf) static cf_read_status_t rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile) { - wtap_rec rec; - Buffer buf; - int err; - gchar *err_info; - gchar *name_ptr; - gint64 data_offset; - progdlg_t *progbar = NULL; - GTimer *prog_timer = g_timer_new(); - gint64 size; - float progbar_val; - gint64 start_time; - gchar status_str[100]; - guint32 framenum; - frame_data *fdata; - int count = 0; + wtap_rec rec; + Buffer buf; + int err; + gchar *err_info; + gchar *name_ptr; + gint64 data_offset; + progdlg_t *progbar = NULL; + GTimer *prog_timer = g_timer_new(); + gint64 size; + float progbar_val; + gint64 start_time; + gchar status_str[100]; + guint32 framenum; + frame_data *fdata; + int count = 0; - /* Close the old handle. */ - wtap_close(cf->provider.wth); + /* Close the old handle. */ + wtap_close(cf->provider.wth); - /* Open the new file. */ - /* XXX: this will go through all open_routines for a matching one. But right - now rescan_file() is only used when a file is being saved to a different - format than the original, and the user is not given a choice of which - reader to use (only which format to save it in), so doing this makes - sense for now. */ - cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); - if (cf->provider.wth == NULL) { - cfile_open_failure_alert_box(fname, err, err_info); - return CF_READ_ERROR; - } - - /* We're scanning a file whose contents should be the same as what - we had before, so we don't discard dissection state etc.. */ - cf->f_datalen = 0; - - /* Set the file name because we need it to set the follow stream filter. - XXX - is that still true? We need it for other reasons, though, - in any case. */ - cf->filename = g_strdup(fname); - - /* Indicate whether it's a permanent or temporary file. */ - cf->is_tempfile = is_tempfile; - - /* No user changes yet. */ - cf->unsaved_changes = FALSE; - - cf->cd_t = wtap_file_type_subtype(cf->provider.wth); - cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1); - - cf->snap = wtap_snapshot_length(cf->provider.wth); - - name_ptr = g_filename_display_basename(cf->filename); - - cf_callback_invoke(cf_cb_file_rescan_started, cf); - - /* Record the file's compression type. - XXX - do we know this at open time? */ - cf->compression_type = wtap_get_compression_type(cf->provider.wth); - - /* Find the size of the file. */ - size = wtap_file_size(cf->provider.wth, NULL); - - g_timer_start(prog_timer); - - cf->stop_flag = FALSE; - start_time = g_get_monotonic_time(); - - framenum = 0; - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - while ((wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, - &data_offset))) { - framenum++; - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - fdata->file_off = data_offset; - if (size >= 0) { - count++; - cf->f_datalen = wtap_read_so_far(cf->provider.wth); - - /* Create the progress bar if necessary. */ - if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) { - progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str)); - progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, - TRUE, &cf->stop_flag, progbar_val); - } - - /* - * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL - * has elapsed. Calling update_progress_dlg and packets_bar_update will - * likely trigger UI paint events, which might take a while depending on - * the platform and display. Reset our timer *after* painting. - */ - if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { - progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str)); - /* update the packet bar content on the first run or frequently on very large files */ - update_progress_dlg(progbar, progbar_val, status_str); - compute_elapsed(cf, start_time); - packets_bar_update(); - g_timer_start(prog_timer); - } + /* Open the new file. */ + /* XXX: this will go through all open_routines for a matching one. But right + now rescan_file() is only used when a file is being saved to a different + format than the original, and the user is not given a choice of which + reader to use (only which format to save it in), so doing this makes + sense for now. */ + cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); + if (cf->provider.wth == NULL) { + cfile_open_failure_alert_box(fname, err, err_info); + return CF_READ_ERROR; } + /* We're scanning a file whose contents should be the same as what + we had before, so we don't discard dissection state etc.. */ + cf->f_datalen = 0; + + /* Set the file name because we need it to set the follow stream filter. + XXX - is that still true? We need it for other reasons, though, + in any case. */ + cf->filename = g_strdup(fname); + + /* Indicate whether it's a permanent or temporary file. */ + cf->is_tempfile = is_tempfile; + + /* No user changes yet. */ + cf->unsaved_changes = FALSE; + + cf->cd_t = wtap_file_type_subtype(cf->provider.wth); + cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1); + + cf->snap = wtap_snapshot_length(cf->provider.wth); + + name_ptr = g_filename_display_basename(cf->filename); + + cf_callback_invoke(cf_cb_file_rescan_started, cf); + + /* Record the file's compression type. + XXX - do we know this at open time? */ + cf->compression_type = wtap_get_compression_type(cf->provider.wth); + + /* Find the size of the file. */ + size = wtap_file_size(cf->provider.wth, NULL); + + g_timer_start(prog_timer); + + cf->stop_flag = FALSE; + start_time = g_get_monotonic_time(); + + framenum = 0; + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + while ((wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, + &data_offset))) { + framenum++; + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + fdata->file_off = data_offset; + if (size >= 0) { + count++; + cf->f_datalen = wtap_read_so_far(cf->provider.wth); + + /* Create the progress bar if necessary. */ + if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) { + progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str)); + progbar = delayed_create_progress_dlg(cf->window, NULL, NULL, + TRUE, &cf->stop_flag, progbar_val); + } + + /* + * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL + * has elapsed. Calling update_progress_dlg and packets_bar_update will + * likely trigger UI paint events, which might take a while depending on + * the platform and display. Reset our timer *after* painting. + */ + if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) { + progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str)); + /* update the packet bar content on the first run or frequently on very large files */ + update_progress_dlg(progbar, progbar_val, status_str); + compute_elapsed(cf, start_time); + packets_bar_update(); + g_timer_start(prog_timer); + } + } + + if (cf->stop_flag) { + /* Well, the user decided to abort the rescan. Sadly, as this + isn't a reread, recovering is difficult, so we'll just + close the current capture. */ + break; + } + + /* Add this packet's link-layer encapsulation type to cf->linktypes, if + it's not already there. + XXX - yes, this is O(N), so if every packet had a different + link-layer encapsulation type, it'd be O(N^2) to read the file, but + there are probably going to be a small number of encapsulation types + in a file. */ + if (rec.rec_type == REC_TYPE_PACKET) { + cf_add_encapsulation_type(cf, rec.rec_header.packet_header.pkt_encap); + } + } + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + + /* Free the display name */ + g_free(name_ptr); + + /* We're done reading the file; destroy the progress bar if it was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + g_timer_destroy(prog_timer); + + /* We're done reading sequentially through the file. */ + cf->state = FILE_READ_DONE; + + /* Close the sequential I/O side, to free up memory it requires. */ + wtap_sequential_close(cf->provider.wth); + + /* compute the time it took to load the file */ + compute_elapsed(cf, start_time); + + /* Set the file encapsulation type now; we don't know what it is until + we've looked at all the packets, as we don't know until then whether + there's more than one type (and thus whether it's + WTAP_ENCAP_PER_PACKET). */ + cf->lnk_t = wtap_file_encap(cf->provider.wth); + + cf_callback_invoke(cf_cb_file_rescan_finished, cf); + if (cf->stop_flag) { - /* Well, the user decided to abort the rescan. Sadly, as this - isn't a reread, recovering is difficult, so we'll just - close the current capture. */ - break; + /* Our caller will give up at this point. */ + return CF_READ_ABORTED; } - /* Add this packet's link-layer encapsulation type to cf->linktypes, if - it's not already there. - XXX - yes, this is O(N), so if every packet had a different - link-layer encapsulation type, it'd be O(N^2) to read the file, but - there are probably going to be a small number of encapsulation types - in a file. */ - if (rec.rec_type == REC_TYPE_PACKET) { - cf_add_encapsulation_type(cf, rec.rec_header.packet_header.pkt_encap); - } - } - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - - /* Free the display name */ - g_free(name_ptr); - - /* We're done reading the file; destroy the progress bar if it was created. */ - if (progbar != NULL) - destroy_progress_dlg(progbar); - g_timer_destroy(prog_timer); - - /* We're done reading sequentially through the file. */ - cf->state = FILE_READ_DONE; - - /* Close the sequential I/O side, to free up memory it requires. */ - wtap_sequential_close(cf->provider.wth); - - /* compute the time it took to load the file */ - compute_elapsed(cf, start_time); - - /* Set the file encapsulation type now; we don't know what it is until - we've looked at all the packets, as we don't know until then whether - there's more than one type (and thus whether it's - WTAP_ENCAP_PER_PACKET). */ - cf->lnk_t = wtap_file_encap(cf->provider.wth); - - cf_callback_invoke(cf_cb_file_rescan_finished, cf); - - if (cf->stop_flag) { - /* Our caller will give up at this point. */ - return CF_READ_ABORTED; - } - - if (err != 0) { - /* Put up a message box noting that the read failed somewhere along - the line. Don't throw out the stuff we managed to read, though, - if any. */ - cfile_read_failure_alert_box(NULL, err, err_info); - return CF_READ_ERROR; - } else - return CF_READ_OK; + if (err != 0) { + /* Put up a message box noting that the read failed somewhere along + the line. Don't throw out the stuff we managed to read, though, + if any. */ + cfile_read_failure_alert_box(NULL, err, err_info); + return CF_READ_ERROR; + } else + return CF_READ_OK; } cf_write_status_t cf_save_records(capture_file *cf, const char *fname, guint save_format, - wtap_compression_type compression_type, - gboolean discard_comments, gboolean dont_reopen) + wtap_compression_type compression_type, + gboolean discard_comments, gboolean dont_reopen) { - gchar *err_info; - gchar *fname_new = NULL; - wtap_dumper *pdh; - frame_data *fdata; - addrinfo_lists_t *addr_lists; - guint framenum; - int err; + gchar *err_info; + gchar *fname_new = NULL; + wtap_dumper *pdh; + frame_data *fdata; + addrinfo_lists_t *addr_lists; + guint framenum; + int err; #ifdef _WIN32 - gchar *display_basename; + gchar *display_basename; #endif - enum { - SAVE_WITH_MOVE, - SAVE_WITH_COPY, - SAVE_WITH_WTAP - } how_to_save; - save_callback_args_t callback_args; - gboolean needs_reload = FALSE; + enum { + SAVE_WITH_MOVE, + SAVE_WITH_COPY, + SAVE_WITH_WTAP + } how_to_save; + save_callback_args_t callback_args; + gboolean needs_reload = FALSE; - /* XXX caller should avoid saving the file while a read is pending - * (e.g. by delaying the save action) */ - if (cf->read_lock) { - ws_warning("cf_save_records(\"%s\") while the file is being read, potential crash ahead", fname); - } + /* XXX caller should avoid saving the file while a read is pending + * (e.g. by delaying the save action) */ + if (cf->read_lock) { + ws_warning("cf_save_records(\"%s\") while the file is being read, potential crash ahead", fname); + } - cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname); + cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname); - addr_lists = get_addrinfo_list(); + addr_lists = get_addrinfo_list(); - if (save_format == cf->cd_t && compression_type == cf->compression_type - && !discard_comments && !cf->unsaved_changes - && (wtap_addrinfo_list_empty(addr_lists) || wtap_file_type_subtype_supports_block(save_format, WTAP_BLOCK_NAME_RESOLUTION) == BLOCK_NOT_SUPPORTED)) { - /* We're saving in the format it's already in, and we're not discarding - comments, and there are no changes we have in memory that aren't saved - to the file, and we have no name resolution information to write or - the file format we're saving in doesn't support writing name - resolution information, so we can just move or copy the raw data. */ + if (save_format == cf->cd_t && compression_type == cf->compression_type + && !discard_comments && !cf->unsaved_changes + && (wtap_addrinfo_list_empty(addr_lists) || wtap_file_type_subtype_supports_block(save_format, WTAP_BLOCK_NAME_RESOLUTION) == BLOCK_NOT_SUPPORTED)) { + /* We're saving in the format it's already in, and we're not discarding + comments, and there are no changes we have in memory that aren't saved + to the file, and we have no name resolution information to write or + the file format we're saving in doesn't support writing name + resolution information, so we can just move or copy the raw data. */ - if (cf->is_tempfile) { - /* The file being saved is a temporary file from a live - capture, so it doesn't need to stay around under that name; - first, try renaming the capture buffer file to the new name. - This acts as a "safe save", in that, if the file already - exists, the existing file will be removed only if the rename - succeeds. + if (cf->is_tempfile) { + /* The file being saved is a temporary file from a live + capture, so it doesn't need to stay around under that name; + first, try renaming the capture buffer file to the new name. + This acts as a "safe save", in that, if the file already + exists, the existing file will be removed only if the rename + succeeds. - Sadly, on Windows, as we have the current capture file - open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING - (to cause the rename to remove an existing target), as - done by ws_stdio_rename() (ws_rename() is #defined to - be ws_stdio_rename() on Windows) will fail. + Sadly, on Windows, as we have the current capture file + open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING + (to cause the rename to remove an existing target), as + done by ws_stdio_rename() (ws_rename() is #defined to + be ws_stdio_rename() on Windows) will fail. - According to the MSDN documentation for CreateFile(), if, - when we open a capture file, we were to directly do a CreateFile(), - opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then - convert it to a file descriptor with _open_osfhandle(), - that would allow the file to be renamed out from under us. + According to the MSDN documentation for CreateFile(), if, + when we open a capture file, we were to directly do a CreateFile(), + opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then + convert it to a file descriptor with _open_osfhandle(), + that would allow the file to be renamed out from under us. - However, that doesn't work in practice. Perhaps the problem - is that the process doing the rename is the process that - has the file open. */ + However, that doesn't work in practice. Perhaps the problem + is that the process doing the rename is the process that + has the file open. */ #ifndef _WIN32 - if (ws_rename(cf->filename, fname) == 0) { - /* That succeeded - there's no need to copy the source file. */ - how_to_save = SAVE_WITH_MOVE; - } else { - if (errno == EXDEV) { - /* They're on different file systems, so we have to copy the - file. */ - how_to_save = SAVE_WITH_COPY; - } else { - /* The rename failed, but not because they're on different - file systems - put up an error message. (Or should we - just punt and try to copy? The only reason why I'd - expect the rename to fail and the copy to succeed would - be if we didn't have permission to remove the file from - the temporary directory, and that might be fixable - but - is it worth requiring the user to go off and fix it?) */ - cf_rename_failure_alert_box(fname, errno); - goto fail; - } - } + if (ws_rename(cf->filename, fname) == 0) { + /* That succeeded - there's no need to copy the source file. */ + how_to_save = SAVE_WITH_MOVE; + } else { + if (errno == EXDEV) { + /* They're on different file systems, so we have to copy the + file. */ + how_to_save = SAVE_WITH_COPY; + } else { + /* The rename failed, but not because they're on different + file systems - put up an error message. (Or should we + just punt and try to copy? The only reason why I'd + expect the rename to fail and the copy to succeed would + be if we didn't have permission to remove the file from + the temporary directory, and that might be fixable - but + is it worth requiring the user to go off and fix it?) */ + cf_rename_failure_alert_box(fname, errno); + goto fail; + } + } #else - /* Windows - copy the file to its new location. */ - how_to_save = SAVE_WITH_COPY; + /* Windows - copy the file to its new location. */ + how_to_save = SAVE_WITH_COPY; #endif + } else { + /* It's a permanent file, so we should copy it, and not remove the + original. */ + how_to_save = SAVE_WITH_COPY; + } + + if (how_to_save == SAVE_WITH_COPY) { + /* Copy the file, if we haven't moved it. If we're overwriting + an existing file, we do it with a "safe save", by writing + to a new file and, if the write succeeds, renaming the + new file on top of the old file. */ + if (file_exists(fname)) { + fname_new = ws_strdup_printf("%s~", fname); + if (!copy_file_binary_mode(cf->filename, fname_new)) + goto fail; + } else { + if (!copy_file_binary_mode(cf->filename, fname)) + goto fail; + } + } } else { - /* It's a permanent file, so we should copy it, and not remove the - original. */ - how_to_save = SAVE_WITH_COPY; + /* Either we're saving in a different format or we're saving changes, + such as added, modified, or removed comments, that haven't yet + been written to the underlying file; we can't do that by copying + or moving the capture file, we have to do it by writing the packets + out in Wiretap. */ + + wtap_dump_params params; + int encap; + + /* XXX: what free's params.shb_hdr? */ + wtap_dump_params_init(¶ms, cf->provider.wth); + + /* Determine what file encapsulation type we should use. */ + encap = wtap_dump_file_encap_type(cf->linktypes); + params.encap = encap; + + /* Use the snaplen from cf (XXX - does wtap_dump_params_init handle that?) */ + params.snaplen = cf->snap; + + if (file_exists(fname)) { + /* We're overwriting an existing file; write out to a new file, + and, if that succeeds, rename the new file on top of the + old file. That makes this a "safe save", so that we don't + lose the old file if we have a problem writing out the new + file. (If the existing file is the current capture file, + we *HAVE* to do that, otherwise we're overwriting the file + from which we're reading the packets that we're writing!) */ + fname_new = ws_strdup_printf("%s~", fname); + pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms, + &err, &err_info); + } else { + pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, + &err, &err_info); + } + /* XXX idb_inf is documented to be used until wtap_dump_close. */ + g_free(params.idb_inf); + params.idb_inf = NULL; + + if (pdh == NULL) { + cfile_dump_open_failure_alert_box(fname, err, err_info, save_format); + goto fail; + } + + /* Add address resolution */ + wtap_dump_set_addrinfo_list(pdh, addr_lists); + + /* Iterate through the list of packets, processing all the packets. */ + callback_args.pdh = pdh; + callback_args.fname = fname; + callback_args.file_type = save_format; + switch (process_specified_records(cf, NULL, "Saving", "packets", + TRUE, save_record, &callback_args, TRUE)) { + + case PSP_FINISHED: + /* Completed successfully. */ + break; + + case PSP_STOPPED: + /* The user decided to abort the saving. + If we're writing to a temporary file, remove it. + XXX - should we do so even if we're not writing to a + temporary file? */ + wtap_dump_close(pdh, &err, &err_info); + if (fname_new != NULL) + ws_unlink(fname_new); + cf_callback_invoke(cf_cb_file_save_stopped, NULL); + return CF_WRITE_ABORTED; + + case PSP_FAILED: + /* Error while saving. + If we're writing to a temporary file, remove it. */ + if (fname_new != NULL) + ws_unlink(fname_new); + wtap_dump_close(pdh, &err, &err_info); + goto fail; + } + + needs_reload = wtap_dump_get_needs_reload(pdh); + + if (!wtap_dump_close(pdh, &err, &err_info)) { + cfile_close_failure_alert_box(fname, err, err_info); + goto fail; + } + + how_to_save = SAVE_WITH_WTAP; } - if (how_to_save == SAVE_WITH_COPY) { - /* Copy the file, if we haven't moved it. If we're overwriting - an existing file, we do it with a "safe save", by writing - to a new file and, if the write succeeds, renaming the - new file on top of the old file. */ - if (file_exists(fname)) { - fname_new = ws_strdup_printf("%s~", fname); - if (!copy_file_binary_mode(cf->filename, fname_new)) - goto fail; - } else { - if (!copy_file_binary_mode(cf->filename, fname)) - goto fail; - } + if (fname_new != NULL) { + /* We wrote out to fname_new, and should rename it on top of + fname. fname_new is now closed, so that should be possible even + on Windows. However, on Windows, we first need to close whatever + file descriptors we have open for fname. */ +#ifdef _WIN32 + wtap_fdclose(cf->provider.wth); +#endif + /* Now do the rename. */ + if (ws_rename(fname_new, fname) == -1) { + /* Well, the rename failed. */ + cf_rename_failure_alert_box(fname, errno); +#ifdef _WIN32 + /* Attempt to reopen the random file descriptor using the + current file's filename. (At this point, the sequential + file descriptor is closed.) */ + if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) { + /* Oh, well, we're screwed. */ + display_basename = g_filename_display_basename(cf->filename); + simple_error_message_box( + file_open_error_message(err, FALSE), display_basename); + g_free(display_basename); + } +#endif + goto fail; + } } - } else { - /* Either we're saving in a different format or we're saving changes, - such as added, modified, or removed comments, that haven't yet - been written to the underlying file; we can't do that by copying - or moving the capture file, we have to do it by writing the packets - out in Wiretap. */ - wtap_dump_params params; - int encap; + /* If this was a temporary file, and we didn't do the save by doing + a move, so the tempoary file is still around under its old name, + remove it. */ + if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) { + /* If this fails, there's not much we can do, so just ignore errors. */ + ws_unlink(cf->filename); + } + + cf_callback_invoke(cf_cb_file_save_finished, NULL); + cf->unsaved_changes = FALSE; + + if (!dont_reopen) { + switch (how_to_save) { + + case SAVE_WITH_MOVE: + /* We just moved the file, so the wtap structure refers to the + new file, and all the information other than the filename + and the "is temporary" status applies to the new file; just + update that. */ + g_free(cf->filename); + cf->filename = g_strdup(fname); + cf->is_tempfile = FALSE; + cf_callback_invoke(cf_cb_file_fast_save_finished, cf); + break; + + case SAVE_WITH_COPY: + /* We just copied the file, so all the information other than + the wtap structure, the filename, and the "is temporary" + status applies to the new file; just update that. */ + wtap_close(cf->provider.wth); + /* Although we're just "copying" and then opening the copy, it will + try all open_routine readers to open the copy, so we need to + reset the cfile's open_type. */ + cf->open_type = WTAP_TYPE_AUTO; + cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); + if (cf->provider.wth == NULL) { + cfile_open_failure_alert_box(fname, err, err_info); + cf_close(cf); + } else { + g_free(cf->filename); + cf->filename = g_strdup(fname); + cf->is_tempfile = FALSE; + } + cf_callback_invoke(cf_cb_file_fast_save_finished, cf); + break; + + case SAVE_WITH_WTAP: + /* Open and read the file we saved to. + + XXX - this is somewhat of a waste; we already have the + packets, all this gets us is updated file type information + (which we could just stuff into "cf"), and having the new + file be the one we have opened and from which we're reading + the data, and it means we have to spend time opening and + reading the file, which could be a significant amount of + time if the file is large. + + If the capture-file-writing code were to return the + seek offset of each packet it writes, we could save that + in the frame_data structure for the frame, and just open + the file without reading it again... + + ...as long as, for gzipped files, the process of writing + out the file *also* generates the information needed to + support fast random access to the compressed file. */ + /* rescan_file will cause us to try all open_routines, so + reset cfile's open_type */ + cf->open_type = WTAP_TYPE_AUTO; + /* There are cases when SAVE_WITH_WTAP can result in new packets + being written to the file, e.g ERF records + In that case, we need to reload the whole file */ + if(needs_reload) { + if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) { + if (cf_read(cf, TRUE) != CF_READ_OK) { + /* The rescan failed; just close the file. Either + a dialog was popped up for the failure, so the + user knows what happened, or they stopped the + rescan, in which case they know what happened. */ + /* XXX: This is inconsistent with normal open/reload behaviour. */ + cf_close(cf); + } + } + } + else { + if (rescan_file(cf, fname, FALSE) != CF_READ_OK) { + /* The rescan failed; just close the file. Either + a dialog was popped up for the failure, so the + user knows what happened, or they stopped the + rescan, in which case they know what happened. */ + cf_close(cf); + } + } + break; + } + + /* If we were told to discard the comments, do so. */ + if (discard_comments) { + /* Remove SHB comment, if any. */ + wtap_write_shb_comment(cf->provider.wth, NULL); + + /* remove all user comments */ + for (framenum = 1; framenum <= cf->count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + + // XXX: This also ignores non-comment options like verdict + fdata->has_modified_block = FALSE; + } + + if (cf->provider.frames_modified_blocks) { + g_tree_destroy(cf->provider.frames_modified_blocks); + cf->provider.frames_modified_blocks = NULL; + } + + cf->packet_comment_count = 0; + } + } + return CF_WRITE_OK; + +fail: + if (fname_new != NULL) { + /* We were trying to write to a temporary file; get rid of it if it + exists. (We don't care whether this fails, as, if it fails, + there's not much we can do about it. I guess if it failed for + a reason other than "it doesn't exist", we could report an + error, so the user knows there's a junk file that they might + want to clean up.) */ + ws_unlink(fname_new); + g_free(fname_new); + } + cf_callback_invoke(cf_cb_file_save_failed, NULL); + return CF_WRITE_ERROR; +} + +cf_write_status_t +cf_export_specified_packets(capture_file *cf, const char *fname, + packet_range_t *range, guint save_format, + wtap_compression_type compression_type) +{ + gchar *fname_new = NULL; + int err; + gchar *err_info; + wtap_dumper *pdh; + save_callback_args_t callback_args; + wtap_dump_params params; + int encap; + + packet_range_process_init(range); + + /* We're writing out specified packets from the specified capture + file to another file. Even if all captured packets are to be + written, don't special-case the operation - read each packet + and then write it out if it's one of the specified ones. */ /* XXX: what free's params.shb_hdr? */ wtap_dump_params_init(¶ms, cf->provider.wth); @@ -4823,362 +5093,103 @@ cf_save_records(capture_file *cf, const char *fname, guint save_format, params.snaplen = cf->snap; if (file_exists(fname)) { - /* We're overwriting an existing file; write out to a new file, - and, if that succeeds, rename the new file on top of the - old file. That makes this a "safe save", so that we don't - lose the old file if we have a problem writing out the new - file. (If the existing file is the current capture file, - we *HAVE* to do that, otherwise we're overwriting the file - from which we're reading the packets that we're writing!) */ - fname_new = ws_strdup_printf("%s~", fname); - pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms, - &err, &err_info); + /* We're overwriting an existing file; write out to a new file, + and, if that succeeds, rename the new file on top of the + old file. That makes this a "safe save", so that we don't + lose the old file if we have a problem writing out the new + file. (If the existing file is the current capture file, + we *HAVE* to do that, otherwise we're overwriting the file + from which we're reading the packets that we're writing!) */ + fname_new = ws_strdup_printf("%s~", fname); + pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms, + &err, &err_info); } else { - pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, - &err, &err_info); + pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, + &err, &err_info); } /* XXX idb_inf is documented to be used until wtap_dump_close. */ g_free(params.idb_inf); params.idb_inf = NULL; if (pdh == NULL) { - cfile_dump_open_failure_alert_box(fname, err, err_info, save_format); - goto fail; + cfile_dump_open_failure_alert_box(fname, err, err_info, save_format); + goto fail; } /* Add address resolution */ - wtap_dump_set_addrinfo_list(pdh, addr_lists); + wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list()); - /* Iterate through the list of packets, processing all the packets. */ + /* Iterate through the list of packets, processing the packets we were + told to process. + + XXX - we've already called "packet_range_process_init(range)", but + "process_specified_records()" will do it again. Fortunately, + that's harmless in this case, as we haven't done anything to + "range" since we initialized it. */ callback_args.pdh = pdh; callback_args.fname = fname; callback_args.file_type = save_format; - switch (process_specified_records(cf, NULL, "Saving", "packets", - TRUE, save_record, &callback_args, TRUE)) { + switch (process_specified_records(cf, range, "Writing", "specified records", + TRUE, save_record, &callback_args, TRUE)) { - case PSP_FINISHED: - /* Completed successfully. */ - break; + case PSP_FINISHED: + /* Completed successfully. */ + break; - case PSP_STOPPED: - /* The user decided to abort the saving. - If we're writing to a temporary file, remove it. - XXX - should we do so even if we're not writing to a - temporary file? */ - wtap_dump_close(pdh, &err, &err_info); - if (fname_new != NULL) - ws_unlink(fname_new); - cf_callback_invoke(cf_cb_file_save_stopped, NULL); - return CF_WRITE_ABORTED; + case PSP_STOPPED: + /* The user decided to abort the saving. + If we're writing to a temporary file, remove it. + XXX - should we do so even if we're not writing to a + temporary file? */ + wtap_dump_close(pdh, &err, &err_info); + if (fname_new != NULL) { + ws_unlink(fname_new); + g_free(fname_new); + } + return CF_WRITE_ABORTED; + break; - case PSP_FAILED: - /* Error while saving. - If we're writing to a temporary file, remove it. */ - if (fname_new != NULL) - ws_unlink(fname_new); - wtap_dump_close(pdh, &err, &err_info); - goto fail; + case PSP_FAILED: + /* Error while saving. */ + wtap_dump_close(pdh, &err, &err_info); + /* + * We don't report any error from closing; the error that caused + * process_specified_records() to fail has already been reported. + */ + goto fail; } - needs_reload = wtap_dump_get_needs_reload(pdh); - if (!wtap_dump_close(pdh, &err, &err_info)) { - cfile_close_failure_alert_box(fname, err, err_info); - goto fail; + cfile_close_failure_alert_box(fname, err, err_info); + goto fail; } - how_to_save = SAVE_WITH_WTAP; - } - - if (fname_new != NULL) { - /* We wrote out to fname_new, and should rename it on top of - fname. fname_new is now closed, so that should be possible even - on Windows. However, on Windows, we first need to close whatever - file descriptors we have open for fname. */ -#ifdef _WIN32 - wtap_fdclose(cf->provider.wth); -#endif - /* Now do the rename. */ - if (ws_rename(fname_new, fname) == -1) { - /* Well, the rename failed. */ - cf_rename_failure_alert_box(fname, errno); -#ifdef _WIN32 - /* Attempt to reopen the random file descriptor using the - current file's filename. (At this point, the sequential - file descriptor is closed.) */ - if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) { - /* Oh, well, we're screwed. */ - display_basename = g_filename_display_basename(cf->filename); - simple_error_message_box( - file_open_error_message(err, FALSE), display_basename); - g_free(display_basename); - } -#endif - goto fail; - } - } - - /* If this was a temporary file, and we didn't do the save by doing - a move, so the tempoary file is still around under its old name, - remove it. */ - if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) { - /* If this fails, there's not much we can do, so just ignore errors. */ - ws_unlink(cf->filename); - } - - cf_callback_invoke(cf_cb_file_save_finished, NULL); - cf->unsaved_changes = FALSE; - - if (!dont_reopen) { - switch (how_to_save) { - - case SAVE_WITH_MOVE: - /* We just moved the file, so the wtap structure refers to the - new file, and all the information other than the filename - and the "is temporary" status applies to the new file; just - update that. */ - g_free(cf->filename); - cf->filename = g_strdup(fname); - cf->is_tempfile = FALSE; - cf_callback_invoke(cf_cb_file_fast_save_finished, cf); - break; - - case SAVE_WITH_COPY: - /* We just copied the file, so all the information other than - the wtap structure, the filename, and the "is temporary" - status applies to the new file; just update that. */ - wtap_close(cf->provider.wth); - /* Although we're just "copying" and then opening the copy, it will - try all open_routine readers to open the copy, so we need to - reset the cfile's open_type. */ - cf->open_type = WTAP_TYPE_AUTO; - cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE); - if (cf->provider.wth == NULL) { - cfile_open_failure_alert_box(fname, err, err_info); - cf_close(cf); - } else { - g_free(cf->filename); - cf->filename = g_strdup(fname); - cf->is_tempfile = FALSE; - } - cf_callback_invoke(cf_cb_file_fast_save_finished, cf); - break; - - case SAVE_WITH_WTAP: - /* Open and read the file we saved to. - - XXX - this is somewhat of a waste; we already have the - packets, all this gets us is updated file type information - (which we could just stuff into "cf"), and having the new - file be the one we have opened and from which we're reading - the data, and it means we have to spend time opening and - reading the file, which could be a significant amount of - time if the file is large. - - If the capture-file-writing code were to return the - seek offset of each packet it writes, we could save that - in the frame_data structure for the frame, and just open - the file without reading it again... - - ...as long as, for gzipped files, the process of writing - out the file *also* generates the information needed to - support fast random access to the compressed file. */ - /* rescan_file will cause us to try all open_routines, so - reset cfile's open_type */ - cf->open_type = WTAP_TYPE_AUTO; - /* There are cases when SAVE_WITH_WTAP can result in new packets - being written to the file, e.g ERF records - In that case, we need to reload the whole file */ - if(needs_reload) { - if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) { - if (cf_read(cf, TRUE) != CF_READ_OK) { - /* The rescan failed; just close the file. Either - a dialog was popped up for the failure, so the - user knows what happened, or they stopped the - rescan, in which case they know what happened. */ - /* XXX: This is inconsistent with normal open/reload behaviour. */ - cf_close(cf); - } + if (fname_new != NULL) { + /* We wrote out to fname_new, and should rename it on top of + fname; fname is now closed, so that should be possible even + on Windows. Do the rename. */ + if (ws_rename(fname_new, fname) == -1) { + /* Well, the rename failed. */ + cf_rename_failure_alert_box(fname, errno); + goto fail; } - } - else { - if (rescan_file(cf, fname, FALSE) != CF_READ_OK) { - /* The rescan failed; just close the file. Either - a dialog was popped up for the failure, so the - user knows what happened, or they stopped the - rescan, in which case they know what happened. */ - cf_close(cf); - } - } - break; + g_free(fname_new); } - /* If we were told to discard the comments, do so. */ - if (discard_comments) { - /* Remove SHB comment, if any. */ - wtap_write_shb_comment(cf->provider.wth, NULL); - - /* remove all user comments */ - for (framenum = 1; framenum <= cf->count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - - // XXX: This also ignores non-comment options like verdict - fdata->has_modified_block = FALSE; - } - - if (cf->provider.frames_modified_blocks) { - g_tree_destroy(cf->provider.frames_modified_blocks); - cf->provider.frames_modified_blocks = NULL; - } - - cf->packet_comment_count = 0; - } - } - return CF_WRITE_OK; + return CF_WRITE_OK; fail: - if (fname_new != NULL) { - /* We were trying to write to a temporary file; get rid of it if it - exists. (We don't care whether this fails, as, if it fails, - there's not much we can do about it. I guess if it failed for - a reason other than "it doesn't exist", we could report an - error, so the user knows there's a junk file that they might - want to clean up.) */ - ws_unlink(fname_new); - g_free(fname_new); - } - cf_callback_invoke(cf_cb_file_save_failed, NULL); - return CF_WRITE_ERROR; -} - -cf_write_status_t -cf_export_specified_packets(capture_file *cf, const char *fname, - packet_range_t *range, guint save_format, - wtap_compression_type compression_type) -{ - gchar *fname_new = NULL; - int err; - gchar *err_info; - wtap_dumper *pdh; - save_callback_args_t callback_args; - wtap_dump_params params; - int encap; - - packet_range_process_init(range); - - /* We're writing out specified packets from the specified capture - file to another file. Even if all captured packets are to be - written, don't special-case the operation - read each packet - and then write it out if it's one of the specified ones. */ - - /* XXX: what free's params.shb_hdr? */ - wtap_dump_params_init(¶ms, cf->provider.wth); - - /* Determine what file encapsulation type we should use. */ - encap = wtap_dump_file_encap_type(cf->linktypes); - params.encap = encap; - - /* Use the snaplen from cf (XXX - does wtap_dump_params_init handle that?) */ - params.snaplen = cf->snap; - - if (file_exists(fname)) { - /* We're overwriting an existing file; write out to a new file, - and, if that succeeds, rename the new file on top of the - old file. That makes this a "safe save", so that we don't - lose the old file if we have a problem writing out the new - file. (If the existing file is the current capture file, - we *HAVE* to do that, otherwise we're overwriting the file - from which we're reading the packets that we're writing!) */ - fname_new = ws_strdup_printf("%s~", fname); - pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms, - &err, &err_info); - } else { - pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, - &err, &err_info); - } - /* XXX idb_inf is documented to be used until wtap_dump_close. */ - g_free(params.idb_inf); - params.idb_inf = NULL; - - if (pdh == NULL) { - cfile_dump_open_failure_alert_box(fname, err, err_info, save_format); - goto fail; - } - - /* Add address resolution */ - wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list()); - - /* Iterate through the list of packets, processing the packets we were - told to process. - - XXX - we've already called "packet_range_process_init(range)", but - "process_specified_records()" will do it again. Fortunately, - that's harmless in this case, as we haven't done anything to - "range" since we initialized it. */ - callback_args.pdh = pdh; - callback_args.fname = fname; - callback_args.file_type = save_format; - switch (process_specified_records(cf, range, "Writing", "specified records", - TRUE, save_record, &callback_args, TRUE)) { - - case PSP_FINISHED: - /* Completed successfully. */ - break; - - case PSP_STOPPED: - /* The user decided to abort the saving. - If we're writing to a temporary file, remove it. - XXX - should we do so even if we're not writing to a - temporary file? */ - wtap_dump_close(pdh, &err, &err_info); - if (fname_new != NULL) { + if (fname_new != NULL) { + /* We were trying to write to a temporary file; get rid of it if it + exists. (We don't care whether this fails, as, if it fails, + there's not much we can do about it. I guess if it failed for + a reason other than "it doesn't exist", we could report an + error, so the user knows there's a junk file that they might + want to clean up.) */ ws_unlink(fname_new); g_free(fname_new); - } - return CF_WRITE_ABORTED; - break; - - case PSP_FAILED: - /* Error while saving. */ - wtap_dump_close(pdh, &err, &err_info); - /* - * We don't report any error from closing; the error that caused - * process_specified_records() to fail has already been reported. - */ - goto fail; - } - - if (!wtap_dump_close(pdh, &err, &err_info)) { - cfile_close_failure_alert_box(fname, err, err_info); - goto fail; - } - - if (fname_new != NULL) { - /* We wrote out to fname_new, and should rename it on top of - fname; fname is now closed, so that should be possible even - on Windows. Do the rename. */ - if (ws_rename(fname_new, fname) == -1) { - /* Well, the rename failed. */ - cf_rename_failure_alert_box(fname, errno); - goto fail; } - g_free(fname_new); - } - - return CF_WRITE_OK; - -fail: - if (fname_new != NULL) { - /* We were trying to write to a temporary file; get rid of it if it - exists. (We don't care whether this fails, as, if it fails, - there's not much we can do about it. I guess if it failed for - a reason other than "it doesn't exist", we could report an - error, so the user knows there's a junk file that they might - want to clean up.) */ - ws_unlink(fname_new); - g_free(fname_new); - } - return CF_WRITE_ERROR; + return CF_WRITE_ERROR; } /* @@ -5189,102 +5200,90 @@ fail: static void cf_rename_failure_alert_box(const char *filename, int err) { - gchar *display_basename; + gchar *display_basename; - display_basename = g_filename_display_basename(filename); - switch (err) { + display_basename = g_filename_display_basename(filename); + switch (err) { - case ENOENT: - /* XXX - should check whether the source exists and, if not, - report it as the problem and, if so, report the destination - as the problem. */ - simple_error_message_box("The path to the file \"%s\" doesn't exist.", - display_basename); - break; + case ENOENT: + /* XXX - should check whether the source exists and, if not, + report it as the problem and, if so, report the destination + as the problem. */ + simple_error_message_box("The path to the file \"%s\" doesn't exist.", + display_basename); + break; - case EACCES: - /* XXX - if we're doing a rename after a safe save, we should - probably say something else. */ - simple_error_message_box("You don't have permission to move the capture file to \"%s\".", - display_basename); - break; + case EACCES: + /* XXX - if we're doing a rename after a safe save, we should + probably say something else. */ + simple_error_message_box("You don't have permission to move the capture file to \"%s\".", + display_basename); + break; - default: - /* XXX - this should probably mention both the source and destination - pathnames. */ - simple_error_message_box("The file \"%s\" could not be moved: %s.", - display_basename, wtap_strerror(err)); - break; - } - g_free(display_basename); + default: + /* XXX - this should probably mention both the source and destination + pathnames. */ + simple_error_message_box("The file \"%s\" could not be moved: %s.", + display_basename, wtap_strerror(err)); + break; + } + g_free(display_basename); } /* Reload the current capture file. */ cf_status_t -cf_reload(capture_file *cf) { - gchar *filename; - gboolean is_tempfile; - cf_status_t cf_status = CF_OK; - int err; +cf_reload(capture_file *cf) +{ + gchar *filename; + gboolean is_tempfile; + cf_status_t cf_status = CF_OK; + int err; - if (cf->read_lock) { - ws_warning("Failing cf_reload(\"%s\") since a read is in progress", cf->filename); - return CF_ERROR; - } - - /* If the file could be opened, "cf_open()" calls "cf_close()" - to get rid of state for the old capture file before filling in state - for the new capture file. "cf_close()" will remove the file if - it's a temporary file; we don't want that to happen (for one thing, - it'd prevent subsequent reopens from working). Remember whether it's - a temporary file, mark it as not being a temporary file, and then - reopen it as the type of file it was. - - Also, "cf_close()" will free "cf->filename", so we must make - a copy of it first. */ - filename = g_strdup(cf->filename); - is_tempfile = cf->is_tempfile; - cf->is_tempfile = FALSE; - if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) { - switch (cf_read(cf, TRUE)) { - - case CF_READ_OK: - case CF_READ_ERROR: - /* Just because we got an error, that doesn't mean we were unable - to read any of the file; we handle what we could get from the - file. */ - break; - - case CF_READ_ABORTED: - /* The user bailed out of re-reading the capture file; the - capture file has been closed. */ - break; + if (cf->read_lock) { + ws_warning("Failing cf_reload(\"%s\") since a read is in progress", cf->filename); + return CF_ERROR; } - } else { - /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile". - Instead, the file was left open, so we should restore "cf->is_tempfile" - ourselves. - XXX - change the menu? Presumably "cf_open()" will do that; - make sure it does! */ - cf->is_tempfile = is_tempfile; - cf_status = CF_ERROR; - } - /* "cf_open()" made a copy of the file name we handed it, so - we should free up our copy. */ - g_free(filename); - return cf_status; + /* If the file could be opened, "cf_open()" calls "cf_close()" + to get rid of state for the old capture file before filling in state + for the new capture file. "cf_close()" will remove the file if + it's a temporary file; we don't want that to happen (for one thing, + it'd prevent subsequent reopens from working). Remember whether it's + a temporary file, mark it as not being a temporary file, and then + reopen it as the type of file it was. + + Also, "cf_close()" will free "cf->filename", so we must make + a copy of it first. */ + filename = g_strdup(cf->filename); + is_tempfile = cf->is_tempfile; + cf->is_tempfile = FALSE; + if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) { + switch (cf_read(cf, TRUE)) { + + case CF_READ_OK: + case CF_READ_ERROR: + /* Just because we got an error, that doesn't mean we were unable + to read any of the file; we handle what we could get from the + file. */ + break; + + case CF_READ_ABORTED: + /* The user bailed out of re-reading the capture file; the + capture file has been closed. */ + break; + } + } else { + /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile". + Instead, the file was left open, so we should restore "cf->is_tempfile" + ourselves. + + XXX - change the menu? Presumably "cf_open()" will do that; + make sure it does! */ + cf->is_tempfile = is_tempfile; + cf_status = CF_ERROR; + } + /* "cf_open()" made a copy of the file name we handed it, so + we should free up our copy. */ + g_free(filename); + return cf_status; } - -/* - * Editor modelines - * - * Local Variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * ex: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/file.h b/file.h index 6117d66574..8dc935c8c4 100644 --- a/file.h +++ b/file.h @@ -735,16 +735,3 @@ gboolean cf_add_ip_name_from_string(capture_file *cf, const char *addr, const ch #endif /* __cplusplus */ #endif /* file.h */ - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 4 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=4 tabstop=8 expandtab: - * :indentSize=4:tabSize=8:noTabs=true: - */ diff --git a/frame_tvbuff.c b/frame_tvbuff.c index cb8426fbf1..1aec22c22d 100644 --- a/frame_tvbuff.c +++ b/frame_tvbuff.c @@ -21,36 +21,36 @@ #include "wiretap/wtap-int.h" /* for ->random_fh */ struct tvb_frame { - struct tvbuff tvb; + struct tvbuff tvb; - Buffer *buf; /* Packet data */ + Buffer *buf; /* Packet data */ - const struct packet_provider_data *prov; /* provider of packet information */ - gint64 file_off; /**< File offset */ + const struct packet_provider_data *prov; /* provider of packet information */ + gint64 file_off; /**< File offset */ - guint offset; + guint offset; }; static gboolean frame_read(struct tvb_frame *frame_tvb, wtap_rec *rec, Buffer *buf) { - int err; - gchar *err_info; - gboolean ok = TRUE; + int err; + gchar *err_info; + gboolean ok = TRUE; - /* XXX, what if phdr->caplen isn't equal to - * frame_tvb->tvb.length + frame_tvb->offset? - */ - if (!wtap_seek_read(frame_tvb->prov->wth, frame_tvb->file_off, rec, buf, &err, &err_info)) { - /* XXX - report error! */ - switch (err) { - case WTAP_ERR_BAD_FILE: - g_free(err_info); - ok = FALSE; - break; - } - } - return ok; + /* XXX, what if phdr->caplen isn't equal to + * frame_tvb->tvb.length + frame_tvb->offset? + */ + if (!wtap_seek_read(frame_tvb->prov->wth, frame_tvb->file_off, rec, buf, &err, &err_info)) { + /* XXX - report error! */ + switch (err) { + case WTAP_ERR_BAD_FILE: + g_free(err_info); + ok = FALSE; + break; + } + } + return ok; } static GPtrArray *buffer_cache = NULL; @@ -58,287 +58,274 @@ static GPtrArray *buffer_cache = NULL; static void frame_cache(struct tvb_frame *frame_tvb) { - wtap_rec rec; /* Record metadata */ + wtap_rec rec; /* Record metadata */ - wtap_rec_init(&rec); + wtap_rec_init(&rec); - if (frame_tvb->buf == NULL) { - if (G_UNLIKELY(!buffer_cache)) buffer_cache = g_ptr_array_sized_new(1024); + if (frame_tvb->buf == NULL) { + if (G_UNLIKELY(!buffer_cache)) buffer_cache = g_ptr_array_sized_new(1024); - if (buffer_cache->len > 0) { - frame_tvb->buf = (struct Buffer *) g_ptr_array_remove_index(buffer_cache, buffer_cache->len - 1); - } else { - frame_tvb->buf = g_new(struct Buffer, 1); - } + if (buffer_cache->len > 0) { + frame_tvb->buf = (struct Buffer *) g_ptr_array_remove_index(buffer_cache, buffer_cache->len - 1); + } else { + frame_tvb->buf = g_new(struct Buffer, 1); + } - ws_buffer_init(frame_tvb->buf, frame_tvb->tvb.length + frame_tvb->offset); + ws_buffer_init(frame_tvb->buf, frame_tvb->tvb.length + frame_tvb->offset); - if (!frame_read(frame_tvb, &rec, frame_tvb->buf)) - { /* TODO: THROW(???); */ } - } + if (!frame_read(frame_tvb, &rec, frame_tvb->buf)) + { /* TODO: THROW(???); */ } + } - frame_tvb->tvb.real_data = ws_buffer_start_ptr(frame_tvb->buf) + frame_tvb->offset; + frame_tvb->tvb.real_data = ws_buffer_start_ptr(frame_tvb->buf) + frame_tvb->offset; - wtap_rec_cleanup(&rec); + wtap_rec_cleanup(&rec); } static void frame_free(tvbuff_t *tvb) { - struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; + struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; - if (frame_tvb->buf) { - ws_buffer_free(frame_tvb->buf); - g_ptr_array_add(buffer_cache, frame_tvb->buf); - } + if (frame_tvb->buf) { + ws_buffer_free(frame_tvb->buf); + g_ptr_array_add(buffer_cache, frame_tvb->buf); + } } static const guint8 * frame_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length _U_) { - struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; + struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; - frame_cache(frame_tvb); + frame_cache(frame_tvb); - return tvb->real_data + abs_offset; + return tvb->real_data + abs_offset; } static void * frame_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length) { - struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; + struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; - frame_cache(frame_tvb); + frame_cache(frame_tvb); - return memcpy(target, tvb->real_data + abs_offset, abs_length); + return memcpy(target, tvb->real_data + abs_offset, abs_length); } static gint frame_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle) { - struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; - const guint8 *result; + struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; + const guint8 *result; - frame_cache(frame_tvb); + frame_cache(frame_tvb); - result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit); - if (result) - return (gint) (result - tvb->real_data); - else - return -1; + result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit); + if (result) + return (gint) (result - tvb->real_data); + else + return -1; } static gint frame_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle) { - struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; + struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; - frame_cache(frame_tvb); + frame_cache(frame_tvb); - return tvb_ws_mempbrk_pattern_guint8(tvb, abs_offset, limit, pattern, found_needle); + return tvb_ws_mempbrk_pattern_guint8(tvb, abs_offset, limit, pattern, found_needle); } static guint frame_offset(const tvbuff_t *tvb _U_, const guint counter) { - /* XXX: frame_tvb->offset */ - return counter; + /* XXX: frame_tvb->offset */ + return counter; } static tvbuff_t *frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length); static const struct tvb_ops tvb_frame_ops = { - sizeof(struct tvb_frame), /* size */ + sizeof(struct tvb_frame), /* size */ - frame_free, /* free */ - frame_offset, /* offset */ - frame_get_ptr, /* get_ptr */ - frame_memcpy, /* memcpy */ - frame_find_guint8, /* find_guint8 */ - frame_pbrk_guint8, /* pbrk_guint8 */ - frame_clone, /* clone */ + frame_free, /* free */ + frame_offset, /* offset */ + frame_get_ptr, /* get_ptr */ + frame_memcpy, /* memcpy */ + frame_find_guint8, /* find_guint8 */ + frame_pbrk_guint8, /* pbrk_guint8 */ + frame_clone, /* clone */ }; /* based on tvb_new_real_data() */ tvbuff_t * frame_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd, - const guint8 *buf) + const guint8 *buf) { - struct tvb_frame *frame_tvb; - tvbuff_t *tvb; + struct tvb_frame *frame_tvb; + tvbuff_t *tvb; - tvb = tvb_new(&tvb_frame_ops); + tvb = tvb_new(&tvb_frame_ops); - /* - * XXX - currently, the length arguments in - * tvbuff structure are signed, but the captured - * and reported length values are unsigned; this means - * that length values > 2^31 - 1 will appear as - * negative lengths - * - * Captured length values that large will already - * have been filtered out by the Wiretap modules - * (the file will be reported as corrupted), to - * avoid trying to allocate large chunks of data. - * - * Reported length values will not have been - * filtered out, and should not be filtered out, - * as those lengths are not necessarily invalid. - * - * For now, we clip the reported length at G_MAXINT - * - * (XXX, is this still a problem?) There was an exception when we call - * tvb_new_real_data() now there's no one - */ + /* + * XXX - currently, the length arguments in + * tvbuff structure are signed, but the captured + * and reported length values are unsigned; this means + * that length values > 2^31 - 1 will appear as + * negative lengths + * + * Captured length values that large will already + * have been filtered out by the Wiretap modules + * (the file will be reported as corrupted), to + * avoid trying to allocate large chunks of data. + * + * Reported length values will not have been + * filtered out, and should not be filtered out, + * as those lengths are not necessarily invalid. + * + * For now, we clip the reported length at G_MAXINT + * + * (XXX, is this still a problem?) There was an exception when we call + * tvb_new_real_data() now there's no one + */ - tvb->real_data = buf; - tvb->length = fd->cap_len; - tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len; - tvb->contained_length = tvb->reported_length; - tvb->initialized = TRUE; + tvb->real_data = buf; + tvb->length = fd->cap_len; + tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len; + tvb->contained_length = tvb->reported_length; + tvb->initialized = TRUE; - /* - * This is the top-level real tvbuff for this data source, - * so its data source tvbuff is itself. - */ - tvb->ds_tvb = tvb; + /* + * This is the top-level real tvbuff for this data source, + * so its data source tvbuff is itself. + */ + tvb->ds_tvb = tvb; - frame_tvb = (struct tvb_frame *) tvb; + frame_tvb = (struct tvb_frame *) tvb; - /* XXX, wtap_can_seek() */ - if (prov->wth && prov->wth->random_fh) { - frame_tvb->prov = prov; - frame_tvb->file_off = fd->file_off; - frame_tvb->offset = 0; - } else - frame_tvb->prov = NULL; + /* XXX, wtap_can_seek() */ + if (prov->wth && prov->wth->random_fh) { + frame_tvb->prov = prov; + frame_tvb->file_off = fd->file_off; + frame_tvb->offset = 0; + } else + frame_tvb->prov = NULL; - frame_tvb->buf = NULL; + frame_tvb->buf = NULL; - return tvb; + return tvb; } tvbuff_t * frame_tvbuff_new_buffer(const struct packet_provider_data *prov, - const frame_data *fd, Buffer *buf) + const frame_data *fd, Buffer *buf) { - return frame_tvbuff_new(prov, fd, ws_buffer_start_ptr(buf)); + return frame_tvbuff_new(prov, fd, ws_buffer_start_ptr(buf)); } static tvbuff_t * frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length) { - struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; + struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb; - tvbuff_t *cloned_tvb; - struct tvb_frame *cloned_frame_tvb; + tvbuff_t *cloned_tvb; + struct tvb_frame *cloned_frame_tvb; - /* file not seekable */ - if (!frame_tvb->prov) - return NULL; + /* file not seekable */ + if (!frame_tvb->prov) + return NULL; - abs_offset += frame_tvb->offset; + abs_offset += frame_tvb->offset; - cloned_tvb = tvb_new(&tvb_frame_ops); + cloned_tvb = tvb_new(&tvb_frame_ops); - /* data will be read when needed */ - cloned_tvb->real_data = NULL; - cloned_tvb->length = abs_length; - cloned_tvb->reported_length = abs_length; /* XXX? */ - cloned_tvb->contained_length = cloned_tvb->reported_length; - cloned_tvb->initialized = TRUE; + /* data will be read when needed */ + cloned_tvb->real_data = NULL; + cloned_tvb->length = abs_length; + cloned_tvb->reported_length = abs_length; /* XXX? */ + cloned_tvb->contained_length = cloned_tvb->reported_length; + cloned_tvb->initialized = TRUE; - /* - * This is the top-level real tvbuff for this data source, - * so its data source tvbuff is itself. - */ - cloned_tvb->ds_tvb = cloned_tvb; + /* + * This is the top-level real tvbuff for this data source, + * so its data source tvbuff is itself. + */ + cloned_tvb->ds_tvb = cloned_tvb; - cloned_frame_tvb = (struct tvb_frame *) cloned_tvb; - cloned_frame_tvb->prov = frame_tvb->prov; - cloned_frame_tvb->file_off = frame_tvb->file_off; - cloned_frame_tvb->offset = abs_offset; - cloned_frame_tvb->buf = NULL; + cloned_frame_tvb = (struct tvb_frame *) cloned_tvb; + cloned_frame_tvb->prov = frame_tvb->prov; + cloned_frame_tvb->file_off = frame_tvb->file_off; + cloned_frame_tvb->offset = abs_offset; + cloned_frame_tvb->buf = NULL; - return cloned_tvb; + return cloned_tvb; } /* based on tvb_new_real_data() */ tvbuff_t * file_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd, - const guint8 *buf) + const guint8 *buf) { - struct tvb_frame *frame_tvb; - tvbuff_t *tvb; + struct tvb_frame *frame_tvb; + tvbuff_t *tvb; - tvb = tvb_new(&tvb_frame_ops); + tvb = tvb_new(&tvb_frame_ops); - /* - * XXX - currently, the length arguments in - * tvbuff structure are signed, but the captured - * and reported length values are unsigned; this means - * that length values > 2^31 - 1 will appear as - * negative lengths - * - * Captured length values that large will already - * have been filtered out by the Wiretap modules - * (the file will be reported as corrupted), to - * avoid trying to allocate large chunks of data. - * - * Reported length values will not have been - * filtered out, and should not be filtered out, - * as those lengths are not necessarily invalid. - * - * For now, we clip the reported length at G_MAXINT - * - * (XXX, is this still a problem?) There was an exception when we call - * tvb_new_real_data() now there's no one - */ + /* + * XXX - currently, the length arguments in + * tvbuff structure are signed, but the captured + * and reported length values are unsigned; this means + * that length values > 2^31 - 1 will appear as + * negative lengths + * + * Captured length values that large will already + * have been filtered out by the Wiretap modules + * (the file will be reported as corrupted), to + * avoid trying to allocate large chunks of data. + * + * Reported length values will not have been + * filtered out, and should not be filtered out, + * as those lengths are not necessarily invalid. + * + * For now, we clip the reported length at G_MAXINT + * + * (XXX, is this still a problem?) There was an exception when we call + * tvb_new_real_data() now there's no one + */ - tvb->real_data = buf; - tvb->length = fd->cap_len; - tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len; - tvb->contained_length = tvb->reported_length; - tvb->initialized = TRUE; + tvb->real_data = buf; + tvb->length = fd->cap_len; + tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len; + tvb->contained_length = tvb->reported_length; + tvb->initialized = TRUE; - /* - * This is the top-level real tvbuff for this data source, - * so its data source tvbuff is itself. - */ - tvb->ds_tvb = tvb; + /* + * This is the top-level real tvbuff for this data source, + * so its data source tvbuff is itself. + */ + tvb->ds_tvb = tvb; - frame_tvb = (struct tvb_frame *) tvb; + frame_tvb = (struct tvb_frame *) tvb; - /* XXX, wtap_can_seek() */ - if (prov->wth && prov->wth->random_fh) { - frame_tvb->prov = prov; - frame_tvb->file_off = fd->file_off; - frame_tvb->offset = 0; - } else - frame_tvb->prov = NULL; + /* XXX, wtap_can_seek() */ + if (prov->wth && prov->wth->random_fh) { + frame_tvb->prov = prov; + frame_tvb->file_off = fd->file_off; + frame_tvb->offset = 0; + } else + frame_tvb->prov = NULL; - frame_tvb->buf = NULL; + frame_tvb->buf = NULL; - return tvb; + return tvb; } tvbuff_t * file_tvbuff_new_buffer(const struct packet_provider_data *prov, - const frame_data *fd, Buffer *buf) + const frame_data *fd, Buffer *buf) { - return frame_tvbuff_new(prov, fd, ws_buffer_start_ptr(buf)); + return frame_tvbuff_new(prov, fd, ws_buffer_start_ptr(buf)); } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 8 - * tab-width: 8 - * indent-tabs-mode: t - * End: - * - * vi: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: - */ diff --git a/frame_tvbuff.h b/frame_tvbuff.h index 612c100e4f..3f377c13d4 100644 --- a/frame_tvbuff.h +++ b/frame_tvbuff.h @@ -37,16 +37,3 @@ extern tvbuff_t *file_tvbuff_new_buffer(const struct packet_provider_data *prov, #endif /* __cplusplus */ #endif /* __FRAME_TVBUFF_H__ */ - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 8 - * tab-width: 8 - * indent-tabs-mode: t - * End: - * - * vi: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: - */ diff --git a/mergecap.c b/mergecap.c index 69147bd9c3..0a05469678 100644 --- a/mergecap.c +++ b/mergecap.c @@ -52,23 +52,23 @@ static void print_usage(FILE *output) { - fprintf(output, "\n"); - fprintf(output, "Usage: mergecap [options] -w |- [ ...]\n"); - fprintf(output, "\n"); - fprintf(output, "Output:\n"); - fprintf(output, " -a concatenate rather than merge files.\n"); - fprintf(output, " default is to merge based on frame timestamps.\n"); - fprintf(output, " -s truncate packets to bytes of data.\n"); - fprintf(output, " -w |- set the output filename to or '-' for stdout.\n"); - fprintf(output, " -F set the output file type; default is pcapng.\n"); - fprintf(output, " an empty \"-F\" option will list the file types.\n"); - fprintf(output, " -I set the merge mode for Interface Description Blocks; default is 'all'.\n"); - fprintf(output, " an empty \"-I\" option will list the merge modes.\n"); - fprintf(output, "\n"); - fprintf(output, "Miscellaneous:\n"); - fprintf(output, " -h display this help and exit.\n"); - fprintf(output, " -v verbose output.\n"); - fprintf(output, " -V print version information and exit.\n"); + fprintf(output, "\n"); + fprintf(output, "Usage: mergecap [options] -w |- [ ...]\n"); + fprintf(output, "\n"); + fprintf(output, "Output:\n"); + fprintf(output, " -a concatenate rather than merge files.\n"); + fprintf(output, " default is to merge based on frame timestamps.\n"); + fprintf(output, " -s truncate packets to bytes of data.\n"); + fprintf(output, " -w |- set the output filename to or '-' for stdout.\n"); + fprintf(output, " -F set the output file type; default is pcapng.\n"); + fprintf(output, " an empty \"-F\" option will list the file types.\n"); + fprintf(output, " -I set the merge mode for Interface Description Blocks; default is 'all'.\n"); + fprintf(output, " an empty \"-I\" option will list the merge modes.\n"); + fprintf(output, "\n"); + fprintf(output, "Miscellaneous:\n"); + fprintf(output, " -h display this help and exit.\n"); + fprintf(output, " -v verbose output.\n"); + fprintf(output, " -V print version information and exit.\n"); } /* @@ -77,9 +77,9 @@ print_usage(FILE *output) static void mergecap_cmdarg_err(const char *fmt, va_list ap) { - fprintf(stderr, "mergecap: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + fprintf(stderr, "mergecap: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); } /* @@ -88,352 +88,339 @@ mergecap_cmdarg_err(const char *fmt, va_list ap) static void mergecap_cmdarg_err_cont(const char *fmt, va_list ap) { - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); } static void list_capture_types(void) { - GArray *writable_type_subtypes; + GArray *writable_type_subtypes; - fprintf(stderr, "mergecap: The available capture file types for the \"-F\" flag are:\n"); - writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME); - for (guint i = 0; i < writable_type_subtypes->len; i++) { - int ft = g_array_index(writable_type_subtypes, int, i); - fprintf(stderr, " %s - %s\n", wtap_file_type_subtype_name(ft), - wtap_file_type_subtype_description(ft)); - } - g_array_free(writable_type_subtypes, TRUE); + fprintf(stderr, "mergecap: The available capture file types for the \"-F\" flag are:\n"); + writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME); + for (guint i = 0; i < writable_type_subtypes->len; i++) { + int ft = g_array_index(writable_type_subtypes, int, i); + fprintf(stderr, " %s - %s\n", wtap_file_type_subtype_name(ft), + wtap_file_type_subtype_description(ft)); + } + g_array_free(writable_type_subtypes, TRUE); } static void list_idb_merge_modes(void) { - int i; + int i; - fprintf(stderr, "mergecap: The available IDB merge modes for the \"-I\" flag are:\n"); - for (i = 0; i < IDB_MERGE_MODE_MAX; i++) { - fprintf(stderr, " %s\n", merge_idb_merge_mode_to_string(i)); - } + fprintf(stderr, "mergecap: The available IDB merge modes for the \"-I\" flag are:\n"); + for (i = 0; i < IDB_MERGE_MODE_MAX; i++) { + fprintf(stderr, " %s\n", merge_idb_merge_mode_to_string(i)); + } } static gboolean merge_callback(merge_event event, int num, - const merge_in_file_t in_files[], const guint in_file_count, - void *data _U_) + const merge_in_file_t in_files[], const guint in_file_count, + void *data _U_) { - guint i; + guint i; - switch (event) { + switch (event) { - case MERGE_EVENT_INPUT_FILES_OPENED: - for (i = 0; i < in_file_count; i++) { - fprintf(stderr, "mergecap: %s is type %s.\n", in_files[i].filename, - wtap_file_type_subtype_description(wtap_file_type_subtype(in_files[i].wth))); - } - break; - - case MERGE_EVENT_FRAME_TYPE_SELECTED: - /* for this event, num = frame_type */ - if (num == WTAP_ENCAP_PER_PACKET) { - /* - * Find out why we had to choose WTAP_ENCAP_PER_PACKET. - */ - int first_frame_type, this_frame_type; - - first_frame_type = wtap_file_encap(in_files[0].wth); - for (i = 1; i < in_file_count; i++) { - this_frame_type = wtap_file_encap(in_files[i].wth); - if (first_frame_type != this_frame_type) { - fprintf(stderr, "mergecap: multiple frame encapsulation types detected\n"); - fprintf(stderr, " defaulting to WTAP_ENCAP_PER_PACKET\n"); - fprintf(stderr, " %s had type %s (%s)\n", - in_files[0].filename, - wtap_encap_description(first_frame_type), - wtap_encap_name(first_frame_type)); - fprintf(stderr, " %s had type %s (%s)\n", - in_files[i].filename, - wtap_encap_description(this_frame_type), - wtap_encap_name(this_frame_type)); + case MERGE_EVENT_INPUT_FILES_OPENED: + for (i = 0; i < in_file_count; i++) { + fprintf(stderr, "mergecap: %s is type %s.\n", in_files[i].filename, + wtap_file_type_subtype_description(wtap_file_type_subtype(in_files[i].wth))); + } break; - } - } - } - fprintf(stderr, "mergecap: selected frame_type %s (%s)\n", - wtap_encap_description(num), - wtap_encap_name(num)); - break; - case MERGE_EVENT_READY_TO_MERGE: - fprintf(stderr, "mergecap: ready to merge records\n"); - break; + case MERGE_EVENT_FRAME_TYPE_SELECTED: + /* for this event, num = frame_type */ + if (num == WTAP_ENCAP_PER_PACKET) { + /* + * Find out why we had to choose WTAP_ENCAP_PER_PACKET. + */ + int first_frame_type, this_frame_type; - case MERGE_EVENT_RECORD_WAS_READ: - /* for this event, num = count */ - fprintf(stderr, "Record: %d\n", num); - break; + first_frame_type = wtap_file_encap(in_files[0].wth); + for (i = 1; i < in_file_count; i++) { + this_frame_type = wtap_file_encap(in_files[i].wth); + if (first_frame_type != this_frame_type) { + fprintf(stderr, "mergecap: multiple frame encapsulation types detected\n"); + fprintf(stderr, " defaulting to WTAP_ENCAP_PER_PACKET\n"); + fprintf(stderr, " %s had type %s (%s)\n", + in_files[0].filename, + wtap_encap_description(first_frame_type), + wtap_encap_name(first_frame_type)); + fprintf(stderr, " %s had type %s (%s)\n", + in_files[i].filename, + wtap_encap_description(this_frame_type), + wtap_encap_name(this_frame_type)); + break; + } + } + } + fprintf(stderr, "mergecap: selected frame_type %s (%s)\n", + wtap_encap_description(num), + wtap_encap_name(num)); + break; - case MERGE_EVENT_DONE: - fprintf(stderr, "mergecap: merging complete\n"); - break; - } + case MERGE_EVENT_READY_TO_MERGE: + fprintf(stderr, "mergecap: ready to merge records\n"); + break; - /* false = do not stop merging */ - return FALSE; + case MERGE_EVENT_RECORD_WAS_READ: + /* for this event, num = count */ + fprintf(stderr, "Record: %d\n", num); + break; + + case MERGE_EVENT_DONE: + fprintf(stderr, "mergecap: merging complete\n"); + break; + } + + /* false = do not stop merging */ + return FALSE; } int main(int argc, char *argv[]) { - char *init_progfile_dir_error; - static const struct report_message_routines mergecap_report_routines = { - failure_message, - failure_message, - open_failure_message, - read_failure_message, - write_failure_message, - cfile_open_failure_message, - cfile_dump_open_failure_message, - cfile_read_failure_message, - cfile_write_failure_message, - cfile_close_failure_message - }; - int opt; - static const struct ws_option long_options[] = { - {"help", ws_no_argument, NULL, 'h'}, - {"version", ws_no_argument, NULL, 'V'}, - {0, 0, 0, 0 } - }; - gboolean do_append = FALSE; - gboolean verbose = FALSE; - int in_file_count = 0; - guint32 snaplen = 0; - int file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; - int err = 0; - gchar *err_info = NULL; - int err_fileno; - guint32 err_framenum; - char *out_filename = NULL; - merge_result status = MERGE_OK; - idb_merge_mode mode = IDB_MERGE_MODE_MAX; - merge_progress_callback_t cb; + char *init_progfile_dir_error; + static const struct report_message_routines mergecap_report_routines = { + failure_message, + failure_message, + open_failure_message, + read_failure_message, + write_failure_message, + cfile_open_failure_message, + cfile_dump_open_failure_message, + cfile_read_failure_message, + cfile_write_failure_message, + cfile_close_failure_message + }; + int opt; + static const struct ws_option long_options[] = { + {"help", ws_no_argument, NULL, 'h'}, + {"version", ws_no_argument, NULL, 'V'}, + {0, 0, 0, 0 } + }; + gboolean do_append = FALSE; + gboolean verbose = FALSE; + int in_file_count = 0; + guint32 snaplen = 0; + int file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; + int err = 0; + gchar *err_info = NULL; + int err_fileno; + guint32 err_framenum; + char *out_filename = NULL; + merge_result status = MERGE_OK; + idb_merge_mode mode = IDB_MERGE_MODE_MAX; + merge_progress_callback_t cb; - cmdarg_err_init(mergecap_cmdarg_err, mergecap_cmdarg_err_cont); + cmdarg_err_init(mergecap_cmdarg_err, mergecap_cmdarg_err_cont); - /* Initialize log handler early so we can have proper logging during startup. */ - ws_log_init("mergecap", vcmdarg_err); + /* Initialize log handler early so we can have proper logging during startup. */ + ws_log_init("mergecap", vcmdarg_err); - /* Early logging command-line initialization. */ - ws_log_parse_args(&argc, argv, vcmdarg_err, 1); + /* Early logging command-line initialization. */ + ws_log_parse_args(&argc, argv, vcmdarg_err, 1); #ifdef _WIN32 - create_app_running_mutex(); + create_app_running_mutex(); #endif /* _WIN32 */ - /* Initialize the version information. */ - ws_init_version_info("Mergecap (Wireshark)", NULL, NULL, NULL); + /* Initialize the version information. */ + ws_init_version_info("Mergecap (Wireshark)", NULL, NULL, NULL); - /* - * Get credential information for later use. - */ - init_process_policies(); + /* + * Get credential information for later use. + */ + init_process_policies(); - /* - * Attempt to get the pathname of the directory containing the - * executable file. - */ - init_progfile_dir_error = init_progfile_dir(argv[0]); - if (init_progfile_dir_error != NULL) { - fprintf(stderr, - "mergecap: Can't get pathname of directory containing the mergecap program: %s.\n", - init_progfile_dir_error); - g_free(init_progfile_dir_error); - } - - init_report_message("mergecap", &mergecap_report_routines); - - wtap_init(TRUE); - - /* Process the options first */ - while ((opt = ws_getopt_long(argc, argv, "aF:hI:s:vVw:", long_options, NULL)) != -1) { - - switch (opt) { - case 'a': - do_append = !do_append; - break; - - case 'F': - file_type = wtap_name_to_file_type_subtype(ws_optarg); - if (file_type < 0) { - fprintf(stderr, "mergecap: \"%s\" isn't a valid capture file type\n", - ws_optarg); - list_capture_types(); - status = MERGE_ERR_INVALID_OPTION; - goto clean_exit; - } - break; - - case 'h': - show_help_header("Merge two or more capture files into one."); - print_usage(stdout); - goto clean_exit; - break; - - case 'I': - mode = merge_string_to_idb_merge_mode(ws_optarg); - if (mode == IDB_MERGE_MODE_MAX) { - fprintf(stderr, "mergecap: \"%s\" isn't a valid IDB merge mode\n", - ws_optarg); - list_idb_merge_modes(); - status = MERGE_ERR_INVALID_OPTION; - goto clean_exit; - } - break; - - case 's': - snaplen = get_nonzero_guint32(ws_optarg, "snapshot length"); - break; - - case 'v': - verbose = TRUE; - break; - - case 'V': - show_version(); - goto clean_exit; - break; - - case 'w': - out_filename = ws_optarg; - break; - - case '?': /* Bad options if GNU getopt */ - switch(ws_optopt) { - case'F': - list_capture_types(); - break; - case'I': - list_idb_merge_modes(); - break; - default: - print_usage(stderr); - } - status = MERGE_ERR_INVALID_OPTION; - goto clean_exit; - break; + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + init_progfile_dir_error = init_progfile_dir(argv[0]); + if (init_progfile_dir_error != NULL) { + fprintf(stderr, + "mergecap: Can't get pathname of directory containing the mergecap program: %s.\n", + init_progfile_dir_error); + g_free(init_progfile_dir_error); } - } - /* Default to pcapng when writing. */ - if (file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) - file_type = wtap_pcapng_file_type_subtype(); + init_report_message("mergecap", &mergecap_report_routines); - cb.callback_func = merge_callback; - cb.data = NULL; + wtap_init(TRUE); - /* check for proper args; at a minimum, must have an output - * filename and one input file - */ - in_file_count = argc - ws_optind; - if (!out_filename) { - fprintf(stderr, "mergecap: an output filename must be set with -w\n"); - fprintf(stderr, " run with -h for help\n"); - status = MERGE_ERR_INVALID_OPTION; - goto clean_exit; - } - if (in_file_count < 1) { - fprintf(stderr, "mergecap: No input files were specified\n"); - return 1; - } + /* Process the options first */ + while ((opt = ws_getopt_long(argc, argv, "aF:hI:s:vVw:", long_options, NULL)) != -1) { - /* - * Setting IDB merge mode must use a file format that supports - * (and thus requires) interface ID and information blocks. - */ - if (mode != IDB_MERGE_MODE_MAX && - wtap_file_type_subtype_supports_block(file_type, WTAP_BLOCK_IF_ID_AND_INFO) == BLOCK_NOT_SUPPORTED) { - fprintf(stderr, "The IDB merge mode can only be used with an output format that identifies interfaces\n"); - status = MERGE_ERR_INVALID_OPTION; - goto clean_exit; - } + switch (opt) { + case 'a': + do_append = !do_append; + break; - /* if they didn't set IDB merge mode, set it to our default */ - if (mode == IDB_MERGE_MODE_MAX) { - mode = IDB_MERGE_MODE_ALL_SAME; - } + case 'F': + file_type = wtap_name_to_file_type_subtype(ws_optarg); + if (file_type < 0) { + fprintf(stderr, "mergecap: \"%s\" isn't a valid capture file type\n", + ws_optarg); + list_capture_types(); + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; + } + break; - /* open the outfile */ - if (strcmp(out_filename, "-") == 0) { - /* merge the files to the standard output */ - status = merge_files_to_stdout(file_type, - (const char *const *) &argv[ws_optind], - in_file_count, do_append, mode, snaplen, - get_appname_and_version(), - verbose ? &cb : NULL, - &err, &err_info, &err_fileno, &err_framenum); - } else { - /* merge the files to the outfile */ - status = merge_files(out_filename, file_type, - (const char *const *) &argv[ws_optind], in_file_count, - do_append, mode, snaplen, get_appname_and_version(), - verbose ? &cb : NULL, - &err, &err_info, &err_fileno, &err_framenum); - } + case 'h': + show_help_header("Merge two or more capture files into one."); + print_usage(stdout); + goto clean_exit; + break; - switch (status) { - case MERGE_OK: - break; + case 'I': + mode = merge_string_to_idb_merge_mode(ws_optarg); + if (mode == IDB_MERGE_MODE_MAX) { + fprintf(stderr, "mergecap: \"%s\" isn't a valid IDB merge mode\n", + ws_optarg); + list_idb_merge_modes(); + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; + } + break; - case MERGE_USER_ABORTED: - /* we don't catch SIGINT/SIGTERM (yet?), so we couldn't have aborted */ - ws_assert_not_reached(); - break; + case 's': + snaplen = get_nonzero_guint32(ws_optarg, "snapshot length"); + break; - case MERGE_ERR_CANT_OPEN_INFILE: - cfile_open_failure_message(argv[ws_optind + err_fileno], err, err_info); - break; + case 'v': + verbose = TRUE; + break; - case MERGE_ERR_CANT_OPEN_OUTFILE: - cfile_dump_open_failure_message(out_filename, err, err_info, file_type); - break; + case 'V': + show_version(); + goto clean_exit; + break; - case MERGE_ERR_CANT_READ_INFILE: - cfile_read_failure_message(argv[ws_optind + err_fileno], err, err_info); - break; + case 'w': + out_filename = ws_optarg; + break; - case MERGE_ERR_BAD_PHDR_INTERFACE_ID: - cmdarg_err("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.", - err_framenum, argv[ws_optind + err_fileno]); - break; + case '?': /* Bad options if GNU getopt */ + switch(ws_optopt) { + case'F': + list_capture_types(); + break; + case'I': + list_idb_merge_modes(); + break; + default: + print_usage(stderr); + } + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; + break; + } + } - case MERGE_ERR_CANT_WRITE_OUTFILE: - cfile_write_failure_message(argv[ws_optind + err_fileno], out_filename, - err, err_info, err_framenum, file_type); - break; + /* Default to pcapng when writing. */ + if (file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) + file_type = wtap_pcapng_file_type_subtype(); - case MERGE_ERR_CANT_CLOSE_OUTFILE: - cfile_close_failure_message(out_filename, err, err_info); - break; + cb.callback_func = merge_callback; + cb.data = NULL; - default: - cmdarg_err("Unknown merge_files error %d", status); - break; - } + /* check for proper args; at a minimum, must have an output + * filename and one input file + */ + in_file_count = argc - ws_optind; + if (!out_filename) { + fprintf(stderr, "mergecap: an output filename must be set with -w\n"); + fprintf(stderr, " run with -h for help\n"); + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; + } + if (in_file_count < 1) { + fprintf(stderr, "mergecap: No input files were specified\n"); + return 1; + } + + /* + * Setting IDB merge mode must use a file format that supports + * (and thus requires) interface ID and information blocks. + */ + if (mode != IDB_MERGE_MODE_MAX && + wtap_file_type_subtype_supports_block(file_type, WTAP_BLOCK_IF_ID_AND_INFO) == BLOCK_NOT_SUPPORTED) { + fprintf(stderr, "The IDB merge mode can only be used with an output format that identifies interfaces\n"); + status = MERGE_ERR_INVALID_OPTION; + goto clean_exit; + } + + /* if they didn't set IDB merge mode, set it to our default */ + if (mode == IDB_MERGE_MODE_MAX) { + mode = IDB_MERGE_MODE_ALL_SAME; + } + + /* open the outfile */ + if (strcmp(out_filename, "-") == 0) { + /* merge the files to the standard output */ + status = merge_files_to_stdout(file_type, + (const char *const *) &argv[ws_optind], + in_file_count, do_append, mode, snaplen, + get_appname_and_version(), + verbose ? &cb : NULL, + &err, &err_info, &err_fileno, &err_framenum); + } else { + /* merge the files to the outfile */ + status = merge_files(out_filename, file_type, + (const char *const *) &argv[ws_optind], in_file_count, + do_append, mode, snaplen, get_appname_and_version(), + verbose ? &cb : NULL, + &err, &err_info, &err_fileno, &err_framenum); + } + + switch (status) { + case MERGE_OK: + break; + + case MERGE_USER_ABORTED: + /* we don't catch SIGINT/SIGTERM (yet?), so we couldn't have aborted */ + ws_assert_not_reached(); + break; + + case MERGE_ERR_CANT_OPEN_INFILE: + cfile_open_failure_message(argv[ws_optind + err_fileno], err, err_info); + break; + + case MERGE_ERR_CANT_OPEN_OUTFILE: + cfile_dump_open_failure_message(out_filename, err, err_info, file_type); + break; + + case MERGE_ERR_CANT_READ_INFILE: + cfile_read_failure_message(argv[ws_optind + err_fileno], err, err_info); + break; + + case MERGE_ERR_BAD_PHDR_INTERFACE_ID: + cmdarg_err("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.", + err_framenum, argv[ws_optind + err_fileno]); + break; + + case MERGE_ERR_CANT_WRITE_OUTFILE: + cfile_write_failure_message(argv[ws_optind + err_fileno], out_filename, + err, err_info, err_framenum, file_type); + break; + + case MERGE_ERR_CANT_CLOSE_OUTFILE: + cfile_close_failure_message(out_filename, err, err_info); + break; + + default: + cmdarg_err("Unknown merge_files error %d", status); + break; + } clean_exit: - wtap_cleanup(); - free_progdirs(); - return (status == MERGE_OK) ? 0 : 2; + wtap_cleanup(); + free_progdirs(); + return (status == MERGE_OK) ? 0 : 2; } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/randpkt.c b/randpkt.c index ec02aa800c..6ca5e10316 100644 --- a/randpkt.c +++ b/randpkt.c @@ -45,9 +45,9 @@ static void randpkt_cmdarg_err(const char *msg_format, va_list ap) { - fprintf(stderr, "randpkt: "); - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + fprintf(stderr, "randpkt: "); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } /* @@ -56,219 +56,206 @@ randpkt_cmdarg_err(const char *msg_format, va_list ap) static void randpkt_cmdarg_err_cont(const char *msg_format, va_list ap) { - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } /* Print usage statement and exit program */ static void usage(gboolean is_error) { - FILE *output; - char** abbrev_list; - char** longname_list; - unsigned i = 0; + FILE *output; + char** abbrev_list; + char** longname_list; + unsigned i = 0; - if (!is_error) { - output = stdout; - } - else { - output = stderr; - } + if (!is_error) { + output = stdout; + } + else { + output = stderr; + } - fprintf(output, "Usage: randpkt [-b maxbytes] [-c count] [-t type] [-r] filename\n"); - fprintf(output, "Default max bytes (per packet) is 5000\n"); - fprintf(output, "Default count is 1000.\n"); - fprintf(output, "-r: random packet type selection\n"); - fprintf(output, "\n"); - fprintf(output, "Types:\n"); + fprintf(output, "Usage: randpkt [-b maxbytes] [-c count] [-t type] [-r] filename\n"); + fprintf(output, "Default max bytes (per packet) is 5000\n"); + fprintf(output, "Default count is 1000.\n"); + fprintf(output, "-r: random packet type selection\n"); + fprintf(output, "\n"); + fprintf(output, "Types:\n"); - /* Get the examples list */ - randpkt_example_list(&abbrev_list, &longname_list); - while (abbrev_list[i] && longname_list[i]) { - fprintf(output, "\t%-16s%s\n", abbrev_list[i], longname_list[i]); - i++; - } + /* Get the examples list */ + randpkt_example_list(&abbrev_list, &longname_list); + while (abbrev_list[i] && longname_list[i]) { + fprintf(output, "\t%-16s%s\n", abbrev_list[i], longname_list[i]); + i++; + } - g_strfreev(abbrev_list); - g_strfreev(longname_list); + g_strfreev(abbrev_list); + g_strfreev(longname_list); - fprintf(output, "\nIf type is not specified, a random packet will be chosen\n\n"); + fprintf(output, "\nIf type is not specified, a random packet will be chosen\n\n"); } int main(int argc, char *argv[]) { - char *init_progfile_dir_error; - static const struct report_message_routines randpkt_report_routines = { - failure_message, - failure_message, - open_failure_message, - read_failure_message, - write_failure_message, - cfile_open_failure_message, - cfile_dump_open_failure_message, - cfile_read_failure_message, - cfile_write_failure_message, - cfile_close_failure_message - }; - int opt; - int produce_type = -1; - char *produce_filename = NULL; - int produce_max_bytes = 5000; - int produce_count = 1000; - randpkt_example *example; - guint8* type = NULL; - int allrandom = FALSE; - wtap_dumper *savedump; - int ret = EXIT_SUCCESS; - static const struct ws_option long_options[] = { - {"help", ws_no_argument, NULL, 'h'}, - {0, 0, 0, 0 } - }; + char *init_progfile_dir_error; + static const struct report_message_routines randpkt_report_routines = { + failure_message, + failure_message, + open_failure_message, + read_failure_message, + write_failure_message, + cfile_open_failure_message, + cfile_dump_open_failure_message, + cfile_read_failure_message, + cfile_write_failure_message, + cfile_close_failure_message + }; + int opt; + int produce_type = -1; + char *produce_filename = NULL; + int produce_max_bytes = 5000; + int produce_count = 1000; + randpkt_example *example; + guint8* type = NULL; + int allrandom = FALSE; + wtap_dumper *savedump; + int ret = EXIT_SUCCESS; + static const struct ws_option long_options[] = { + {"help", ws_no_argument, NULL, 'h'}, + {0, 0, 0, 0 } + }; - cmdarg_err_init(randpkt_cmdarg_err, randpkt_cmdarg_err_cont); + cmdarg_err_init(randpkt_cmdarg_err, randpkt_cmdarg_err_cont); - /* Initialize log handler early so we can have proper logging during startup. */ - ws_log_init("randpkt", vcmdarg_err); + /* Initialize log handler early so we can have proper logging during startup. */ + ws_log_init("randpkt", vcmdarg_err); - /* Early logging command-line initialization. */ - ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION); + /* Early logging command-line initialization. */ + ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION); - /* - * Get credential information for later use. - */ - init_process_policies(); + /* + * Get credential information for later use. + */ + init_process_policies(); - /* - * Attempt to get the pathname of the directory containing the - * executable file. - */ - init_progfile_dir_error = init_progfile_dir(argv[0]); - if (init_progfile_dir_error != NULL) { - fprintf(stderr, - "capinfos: Can't get pathname of directory containing the capinfos program: %s.\n", - init_progfile_dir_error); - g_free(init_progfile_dir_error); - } + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + init_progfile_dir_error = init_progfile_dir(argv[0]); + if (init_progfile_dir_error != NULL) { + fprintf(stderr, + "capinfos: Can't get pathname of directory containing the capinfos program: %s.\n", + init_progfile_dir_error); + g_free(init_progfile_dir_error); + } - init_report_message("randpkt", &randpkt_report_routines); + init_report_message("randpkt", &randpkt_report_routines); - wtap_init(TRUE); + wtap_init(TRUE); #ifdef _WIN32 - create_app_running_mutex(); + create_app_running_mutex(); #endif /* _WIN32 */ - while ((opt = ws_getopt_long(argc, argv, "b:c:ht:r", long_options, NULL)) != -1) { - switch (opt) { - case 'b': /* max bytes */ - produce_max_bytes = get_positive_int(ws_optarg, "max bytes"); - if (produce_max_bytes > 65536) { - cmdarg_err("max bytes is > 65536"); - ret = INVALID_OPTION; - goto clean_exit; - } - break; + while ((opt = ws_getopt_long(argc, argv, "b:c:ht:r", long_options, NULL)) != -1) { + switch (opt) { + case 'b': /* max bytes */ + produce_max_bytes = get_positive_int(ws_optarg, "max bytes"); + if (produce_max_bytes > 65536) { + cmdarg_err("max bytes is > 65536"); + ret = INVALID_OPTION; + goto clean_exit; + } + break; - case 'c': /* count */ - produce_count = get_positive_int(ws_optarg, "count"); - break; + case 'c': /* count */ + produce_count = get_positive_int(ws_optarg, "count"); + break; - case 't': /* type of packet to produce */ - type = g_strdup(ws_optarg); - break; + case 't': /* type of packet to produce */ + type = g_strdup(ws_optarg); + break; - case 'h': - usage(FALSE); - goto clean_exit; - break; + case 'h': + usage(FALSE); + goto clean_exit; + break; - case 'r': - allrandom = TRUE; - break; + case 'r': + allrandom = TRUE; + break; - default: - usage(TRUE); - ret = INVALID_OPTION; - goto clean_exit; - break; - } - } + default: + usage(TRUE); + ret = INVALID_OPTION; + goto clean_exit; + break; + } + } - /* any more command line parameters? */ - if (argc > ws_optind) { - produce_filename = argv[ws_optind]; - } else { - usage(TRUE); - ret = INVALID_OPTION; - goto clean_exit; - } + /* any more command line parameters? */ + if (argc > ws_optind) { + produce_filename = argv[ws_optind]; + } else { + usage(TRUE); + ret = INVALID_OPTION; + goto clean_exit; + } - if (!allrandom) { - produce_type = randpkt_parse_type(type); - g_free(type); + if (!allrandom) { + produce_type = randpkt_parse_type(type); + g_free(type); - example = randpkt_find_example(produce_type); - if (!example) { - ret = INVALID_OPTION; - goto clean_exit; - } + example = randpkt_find_example(produce_type); + if (!example) { + ret = INVALID_OPTION; + goto clean_exit; + } - ret = randpkt_example_init(example, produce_filename, produce_max_bytes); - if (ret != EXIT_SUCCESS) - goto clean_exit; - randpkt_loop(example, produce_count, 0); - } else { - if (type) { - fprintf(stderr, "Can't set type in random mode\n"); - ret = INVALID_TYPE; - goto clean_exit; - } + ret = randpkt_example_init(example, produce_filename, produce_max_bytes); + if (ret != EXIT_SUCCESS) + goto clean_exit; + randpkt_loop(example, produce_count, 0); + } else { + if (type) { + fprintf(stderr, "Can't set type in random mode\n"); + ret = INVALID_TYPE; + goto clean_exit; + } - produce_type = randpkt_parse_type(NULL); - example = randpkt_find_example(produce_type); - if (!example) { - ret = INVALID_OPTION; - goto clean_exit; - } - ret = randpkt_example_init(example, produce_filename, produce_max_bytes); - if (ret != EXIT_SUCCESS) - goto clean_exit; + produce_type = randpkt_parse_type(NULL); + example = randpkt_find_example(produce_type); + if (!example) { + ret = INVALID_OPTION; + goto clean_exit; + } + ret = randpkt_example_init(example, produce_filename, produce_max_bytes); + if (ret != EXIT_SUCCESS) + goto clean_exit; - while (produce_count-- > 0) { - randpkt_loop(example, 1, 0); - produce_type = randpkt_parse_type(NULL); + while (produce_count-- > 0) { + randpkt_loop(example, 1, 0); + produce_type = randpkt_parse_type(NULL); - savedump = example->dump; + savedump = example->dump; - example = randpkt_find_example(produce_type); - if (!example) { - ret = INVALID_OPTION; - goto clean_exit; - } - example->dump = savedump; - example->filename = produce_filename; - } - } - if (!randpkt_example_close(example)) { - ret = CLOSE_ERROR; - } + example = randpkt_find_example(produce_type); + if (!example) { + ret = INVALID_OPTION; + goto clean_exit; + } + example->dump = savedump; + example->filename = produce_filename; + } + } + if (!randpkt_example_close(example)) { + ret = CLOSE_ERROR; + } clean_exit: - wtap_cleanup(); - return ret; + wtap_cleanup(); + return ret; } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 8 - * tab-width: 8 - * indent-tabs-mode: t - * End: - * - * vi: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: - */ diff --git a/ringbuffer.c b/ringbuffer.c index ec99c6871b..ff2b42e2c0 100644 --- a/ringbuffer.c +++ b/ringbuffer.c @@ -60,30 +60,30 @@ /* Ringbuffer file structure */ typedef struct _rb_file { - gchar *name; + gchar *name; } rb_file; #define MAX_FILENAME_QUEUE 100 /** Ringbuffer data structure */ typedef struct _ringbuf_data { - rb_file *files; - guint num_files; /**< Number of ringbuffer files (1 to ...) */ - guint curr_file_num; /**< Number of the current file (ever increasing) */ - gchar *fprefix; /**< Filename prefix */ - gchar *fsuffix; /**< Filename suffix */ - gboolean nametimenum; /**< ...num_time... or ...time_num... */ - gboolean unlimited; /**< TRUE if unlimited number of files */ + rb_file *files; + guint num_files; /**< Number of ringbuffer files (1 to ...) */ + guint curr_file_num; /**< Number of the current file (ever increasing) */ + gchar *fprefix; /**< Filename prefix */ + gchar *fsuffix; /**< Filename suffix */ + gboolean nametimenum; /**< ...num_time... or ...time_num... */ + gboolean unlimited; /**< TRUE if unlimited number of files */ - int fd; /**< Current ringbuffer file descriptor */ - FILE *pdh; - char *io_buffer; /**< The IO buffer used to write to the file */ - gboolean group_read_access; /**< TRUE if files need to be opened with group read access */ - FILE *name_h; /**< write names of completed files to this handle */ - gchar *compress_type; /**< compress type */ + int fd; /**< Current ringbuffer file descriptor */ + FILE *pdh; + char *io_buffer; /**< The IO buffer used to write to the file */ + gboolean group_read_access; /**< TRUE if files need to be opened with group read access */ + FILE *name_h; /**< write names of completed files to this handle */ + gchar *compress_type; /**< compress type */ - GMutex mutex; /**< mutex for oldnames */ - gchar *oldnames[MAX_FILENAME_QUEUE]; /**< filename list of pending to be deleted */ + GMutex mutex; /**< mutex for oldnames */ + gchar *oldnames[MAX_FILENAME_QUEUE]; /**< filename list of pending to be deleted */ } ringbuf_data; static ringbuf_data rb_data; @@ -91,172 +91,177 @@ static ringbuf_data rb_data; /* * delete pending uncompressed pcap files. */ -static void CleanupOldCap(gchar* name) +static void +CleanupOldCap(gchar* name) { - ws_statb64 statb; - size_t i; + ws_statb64 statb; + size_t i; - g_mutex_lock(&rb_data.mutex); + g_mutex_lock(&rb_data.mutex); - /* Delete pending delete file */ - for (i = 0; i < sizeof(rb_data.oldnames) / sizeof(rb_data.oldnames[0]); i++) { - if (rb_data.oldnames[i] != NULL) { - ws_unlink(rb_data.oldnames[i]); - if (ws_stat64(rb_data.oldnames[i], &statb) != 0) { - g_free(rb_data.oldnames[i]); - rb_data.oldnames[i] = NULL; - } - } - } - - if (name) { - /* push the current file to pending list if it failed to delete */ - if (ws_stat64(name, &statb) == 0) { - for (i = 0; i < sizeof(rb_data.oldnames) / sizeof(rb_data.oldnames[0]); i++) { - if (rb_data.oldnames[i] == NULL) { - rb_data.oldnames[i] = g_strdup(name); - break; + /* Delete pending delete file */ + for (i = 0; i < sizeof(rb_data.oldnames) / sizeof(rb_data.oldnames[0]); i++) { + if (rb_data.oldnames[i] != NULL) { + ws_unlink(rb_data.oldnames[i]); + if (ws_stat64(rb_data.oldnames[i], &statb) != 0) { + g_free(rb_data.oldnames[i]); + rb_data.oldnames[i] = NULL; + } } - } } - } - g_mutex_unlock(&rb_data.mutex); + if (name) { + /* push the current file to pending list if it failed to delete */ + if (ws_stat64(name, &statb) == 0) { + for (i = 0; i < sizeof(rb_data.oldnames) / sizeof(rb_data.oldnames[0]); i++) { + if (rb_data.oldnames[i] == NULL) { + rb_data.oldnames[i] = g_strdup(name); + break; + } + } + } + } + + g_mutex_unlock(&rb_data.mutex); } #ifdef HAVE_ZLIB /* * compress capture file */ -static int ringbuf_exec_compress(gchar* name) +static int +ringbuf_exec_compress(gchar* name) { - guint8 *buffer = NULL; - gchar* outgz = NULL; - int fd = -1; - ssize_t nread; - gboolean delete_org_file = TRUE; - gzFile fi = NULL; + guint8 *buffer = NULL; + gchar* outgz = NULL; + int fd = -1; + ssize_t nread; + gboolean delete_org_file = TRUE; + gzFile fi = NULL; - fd = ws_open(name, O_RDONLY | O_BINARY, 0000); - if (fd < 0) { - return -1; - } + fd = ws_open(name, O_RDONLY | O_BINARY, 0000); + if (fd < 0) { + return -1; + } - outgz = ws_strdup_printf("%s.gz", name); - fi = gzopen(outgz, "wb"); - g_free(outgz); - if (fi == NULL) { - ws_close(fd); - return -1; - } + outgz = ws_strdup_printf("%s.gz", name); + fi = gzopen(outgz, "wb"); + g_free(outgz); + if (fi == NULL) { + ws_close(fd); + return -1; + } #define FS_READ_SIZE 65536 - buffer = (guint8*)g_malloc(FS_READ_SIZE); - if (buffer == NULL) { + buffer = (guint8*)g_malloc(FS_READ_SIZE); + if (buffer == NULL) { + ws_close(fd); + gzclose(fi); + return -1; + } + + while ((nread = ws_read(fd, buffer, FS_READ_SIZE)) > 0) { + int n = gzwrite(fi, buffer, (unsigned int)nread); + if (n <= 0) { + /* mark compression as failed */ + delete_org_file = FALSE; + break; + } + } + if (nread < 0) { + /* mark compression as failed */ + delete_org_file = FALSE; + } ws_close(fd); gzclose(fi); - return -1; - } + g_free(buffer); - while ((nread = ws_read(fd, buffer, FS_READ_SIZE)) > 0) { - int n = gzwrite(fi, buffer, (unsigned int)nread); - if (n <= 0) { - /* mark compression as failed */ - delete_org_file = FALSE; - break; + /* delete the original file only if compression succeeds */ + if (delete_org_file) { + ws_unlink(name); + CleanupOldCap(name); } - } - if (nread < 0) { - /* mark compression as failed */ - delete_org_file = FALSE; - } - ws_close(fd); - gzclose(fi); - g_free(buffer); - - /* delete the original file only if compression succeeds */ - if (delete_org_file) { - ws_unlink(name); - CleanupOldCap(name); - } - g_free(name); - return 0; + g_free(name); + return 0; } /* * thread to compress capture file */ -static void* exec_compress_thread(void* arg) +static void* +exec_compress_thread(void* arg) { - ringbuf_exec_compress((gchar*)arg); - return NULL; + ringbuf_exec_compress((gchar*)arg); + return NULL; } /* * start a thread to compress capture file */ -static int ringbuf_start_compress_file(rb_file* rfile) +static int +ringbuf_start_compress_file(rb_file* rfile) { - gchar* name = g_strdup(rfile->name); - g_thread_new("exec_compress", &exec_compress_thread, name); - return 0; + gchar* name = g_strdup(rfile->name); + g_thread_new("exec_compress", &exec_compress_thread, name); + return 0; } #endif /* * create the next filename and open a new binary file with that name */ -static int ringbuf_open_file(rb_file *rfile, int *err) +static int +ringbuf_open_file(rb_file *rfile, int *err) { - char filenum[5+1]; - char timestr[14+1]; - time_t current_time; - struct tm *tm; + char filenum[5+1]; + char timestr[14+1]; + time_t current_time; + struct tm *tm; - if (rfile->name != NULL) { - if (rb_data.unlimited == FALSE) { - /* remove old file (if any, so ignore error) */ - ws_unlink(rfile->name); - } + if (rfile->name != NULL) { + if (rb_data.unlimited == FALSE) { + /* remove old file (if any, so ignore error) */ + ws_unlink(rfile->name); + } #ifdef HAVE_ZLIB - else if (rb_data.compress_type != NULL && strcmp(rb_data.compress_type, "gzip") == 0) { - ringbuf_start_compress_file(rfile); - } + else if (rb_data.compress_type != NULL && strcmp(rb_data.compress_type, "gzip") == 0) { + ringbuf_start_compress_file(rfile); + } #endif - g_free(rfile->name); - } + g_free(rfile->name); + } #ifdef _WIN32 - _tzset(); + _tzset(); #endif - current_time = time(NULL); + current_time = time(NULL); - snprintf(filenum, sizeof(filenum), "%05u", (rb_data.curr_file_num + 1) % RINGBUFFER_MAX_NUM_FILES); - tm = localtime(¤t_time); - if (tm != NULL) - strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", tm); - else - (void) g_strlcpy(timestr, "196912312359", sizeof(timestr)); /* second before the Epoch */ - if (rb_data.nametimenum) { - rfile->name = g_strconcat(rb_data.fprefix, "_", timestr, "_", filenum, rb_data.fsuffix, NULL); - } else { - rfile->name = g_strconcat(rb_data.fprefix, "_", filenum, "_", timestr, rb_data.fsuffix, NULL); - } + snprintf(filenum, sizeof(filenum), "%05u", (rb_data.curr_file_num + 1) % RINGBUFFER_MAX_NUM_FILES); + tm = localtime(¤t_time); + if (tm != NULL) + strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", tm); + else + (void) g_strlcpy(timestr, "196912312359", sizeof(timestr)); /* second before the Epoch */ + if (rb_data.nametimenum) { + rfile->name = g_strconcat(rb_data.fprefix, "_", timestr, "_", filenum, rb_data.fsuffix, NULL); + } else { + rfile->name = g_strconcat(rb_data.fprefix, "_", filenum, "_", timestr, rb_data.fsuffix, NULL); + } - if (rfile->name == NULL) { - if (err != NULL) - *err = ENOMEM; - return -1; - } + if (rfile->name == NULL) { + if (err != NULL) + *err = ENOMEM; + return -1; + } - rb_data.fd = ws_open(rfile->name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, - rb_data.group_read_access ? 0640 : 0600); + rb_data.fd = ws_open(rfile->name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, + rb_data.group_read_access ? 0640 : 0600); - if (rb_data.fd == -1 && err != NULL) { - *err = errno; - } + if (rb_data.fd == -1 && err != NULL) { + *err = errno; + } - return rb_data.fd; + return rb_data.fd; } /* @@ -264,92 +269,92 @@ static int ringbuf_open_file(rb_file *rfile, int *err) */ int ringbuf_init(const char *capfile_name, guint num_files, gboolean group_read_access, - gchar *compress_type, gboolean has_nametimenum) + gchar *compress_type, gboolean has_nametimenum) { - unsigned int i; - char *pfx, *last_pathsep; - gchar *save_file; + unsigned int i; + char *pfx, *last_pathsep; + gchar *save_file; - rb_data.files = NULL; - rb_data.curr_file_num = 0; - rb_data.fprefix = NULL; - rb_data.fsuffix = NULL; - rb_data.nametimenum = has_nametimenum; - rb_data.unlimited = FALSE; - rb_data.fd = -1; - rb_data.pdh = NULL; - rb_data.io_buffer = NULL; - rb_data.group_read_access = group_read_access; - rb_data.name_h = NULL; - rb_data.compress_type = compress_type; - g_mutex_init(&rb_data.mutex); - - /* just to be sure ... */ - if (num_files <= RINGBUFFER_MAX_NUM_FILES) { - rb_data.num_files = num_files; - } else { - rb_data.num_files = RINGBUFFER_MAX_NUM_FILES; - } - - /* Check file name */ - if (capfile_name == NULL) { - /* ringbuffer does not work with temporary files! */ - return -1; - } - - /* set file name prefix/suffix */ - - save_file = g_strdup(capfile_name); - last_pathsep = strrchr(save_file, G_DIR_SEPARATOR); - pfx = strrchr(save_file,'.'); - if (pfx != NULL && (last_pathsep == NULL || pfx > last_pathsep)) { - /* The pathname has a "." in it, and it's in the last component - of the pathname (because there is either only one component, - i.e. last_pathsep is null as there are no path separators, - or the "." is after the path separator before the last - component. - - Treat it as a separator between the rest of the file name and - the file name suffix, and arrange that the names given to the - ring buffer files have the specified suffix, i.e. put the - changing part of the name *before* the suffix. */ - pfx[0] = '\0'; - rb_data.fprefix = g_strdup(save_file); - pfx[0] = '.'; /* restore capfile_name */ - rb_data.fsuffix = g_strdup(pfx); - } else { - /* Either there's no "." in the pathname, or it's in a directory - component, so the last component has no suffix. */ - rb_data.fprefix = g_strdup(save_file); + rb_data.files = NULL; + rb_data.curr_file_num = 0; + rb_data.fprefix = NULL; rb_data.fsuffix = NULL; - } - g_free(save_file); - save_file = NULL; + rb_data.nametimenum = has_nametimenum; + rb_data.unlimited = FALSE; + rb_data.fd = -1; + rb_data.pdh = NULL; + rb_data.io_buffer = NULL; + rb_data.group_read_access = group_read_access; + rb_data.name_h = NULL; + rb_data.compress_type = compress_type; + g_mutex_init(&rb_data.mutex); - /* allocate rb_file structures (only one if unlimited since there is no - need to save all file names in that case) */ + /* just to be sure ... */ + if (num_files <= RINGBUFFER_MAX_NUM_FILES) { + rb_data.num_files = num_files; + } else { + rb_data.num_files = RINGBUFFER_MAX_NUM_FILES; + } - if (num_files == RINGBUFFER_UNLIMITED_FILES) { - rb_data.unlimited = TRUE; - rb_data.num_files = 1; - } + /* Check file name */ + if (capfile_name == NULL) { + /* ringbuffer does not work with temporary files! */ + return -1; + } - rb_data.files = g_new(rb_file, rb_data.num_files); - if (rb_data.files == NULL) { - return -1; - } + /* set file name prefix/suffix */ - for (i=0; i < rb_data.num_files; i++) { - rb_data.files[i].name = NULL; - } + save_file = g_strdup(capfile_name); + last_pathsep = strrchr(save_file, G_DIR_SEPARATOR); + pfx = strrchr(save_file,'.'); + if (pfx != NULL && (last_pathsep == NULL || pfx > last_pathsep)) { + /* The pathname has a "." in it, and it's in the last component + of the pathname (because there is either only one component, + i.e. last_pathsep is null as there are no path separators, + or the "." is after the path separator before the last + component. - /* create the first file */ - if (ringbuf_open_file(&rb_data.files[0], NULL) == -1) { - ringbuf_error_cleanup(); - return -1; - } + Treat it as a separator between the rest of the file name and + the file name suffix, and arrange that the names given to the + ring buffer files have the specified suffix, i.e. put the + changing part of the name *before* the suffix. */ + pfx[0] = '\0'; + rb_data.fprefix = g_strdup(save_file); + pfx[0] = '.'; /* restore capfile_name */ + rb_data.fsuffix = g_strdup(pfx); + } else { + /* Either there's no "." in the pathname, or it's in a directory + component, so the last component has no suffix. */ + rb_data.fprefix = g_strdup(save_file); + rb_data.fsuffix = NULL; + } + g_free(save_file); + save_file = NULL; - return rb_data.fd; + /* allocate rb_file structures (only one if unlimited since there is no + need to save all file names in that case) */ + + if (num_files == RINGBUFFER_UNLIMITED_FILES) { + rb_data.unlimited = TRUE; + rb_data.num_files = 1; + } + + rb_data.files = g_new(rb_file, rb_data.num_files); + if (rb_data.files == NULL) { + return -1; + } + + for (i=0; i < rb_data.num_files; i++) { + rb_data.files[i].name = NULL; + } + + /* create the first file */ + if (ringbuf_open_file(&rb_data.files[0], NULL) == -1) { + ringbuf_error_cleanup(); + return -1; + } + + return rb_data.fd; } /* @@ -358,41 +363,43 @@ ringbuf_init(const char *capfile_name, guint num_files, gboolean group_read_acce gboolean ringbuf_set_print_name(gchar *name, int *err) { - if (rb_data.name_h != NULL) { - if (EOF == fclose(rb_data.name_h)) { - if (err != NULL) { - *err = errno; - } - return FALSE; + if (rb_data.name_h != NULL) { + if (EOF == fclose(rb_data.name_h)) { + if (err != NULL) { + *err = errno; + } + return FALSE; + } } - } - if (!strcmp(name, "-") || !strcmp(name, "stdout")) { - rb_data.name_h = stdout; - } else if (!strcmp(name, "stderr")) { - rb_data.name_h = stderr; - } else { - if (NULL == (rb_data.name_h = ws_fopen(name, "wt"))) { - if (err != NULL) { - *err = errno; - } - return FALSE; + if (!strcmp(name, "-") || !strcmp(name, "stdout")) { + rb_data.name_h = stdout; + } else if (!strcmp(name, "stderr")) { + rb_data.name_h = stderr; + } else { + if (NULL == (rb_data.name_h = ws_fopen(name, "wt"))) { + if (err != NULL) { + *err = errno; + } + return FALSE; + } } - } - return TRUE; + return TRUE; } /* * Whether the ringbuf filenames are ready. * (Whether ringbuf_init is called and ringbuf_free is not called.) */ -gboolean ringbuf_is_initialized(void) +gboolean +ringbuf_is_initialized(void) { - return rb_data.files != NULL; + return rb_data.files != NULL; } -const gchar *ringbuf_current_filename(void) +const gchar * +ringbuf_current_filename(void) { - return rb_data.files[rb_data.curr_file_num % rb_data.num_files].name; + return rb_data.files[rb_data.curr_file_num % rb_data.num_files].name; } /* @@ -401,28 +408,28 @@ const gchar *ringbuf_current_filename(void) FILE * ringbuf_init_libpcap_fdopen(int *err) { - rb_data.pdh = ws_fdopen(rb_data.fd, "wb"); - if (rb_data.pdh == NULL) { - if (err != NULL) { - *err = errno; - } - } else { - size_t buffsize = IO_BUF_SIZE; + rb_data.pdh = ws_fdopen(rb_data.fd, "wb"); + if (rb_data.pdh == NULL) { + if (err != NULL) { + *err = errno; + } + } else { + size_t buffsize = IO_BUF_SIZE; #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - ws_statb64 statb; + ws_statb64 statb; - if (ws_fstat64(rb_data.fd, &statb) == 0) { - if (statb.st_blksize > IO_BUF_SIZE) { - buffsize = statb.st_blksize; - } - } + if (ws_fstat64(rb_data.fd, &statb) == 0) { + if (statb.st_blksize > IO_BUF_SIZE) { + buffsize = statb.st_blksize; + } + } #endif - /* Increase the size of the IO buffer */ - rb_data.io_buffer = (char *)g_realloc(rb_data.io_buffer, buffsize); - setvbuf(rb_data.pdh, rb_data.io_buffer, _IOFBF, buffsize); - } + /* Increase the size of the IO buffer */ + rb_data.io_buffer = (char *)g_realloc(rb_data.io_buffer, buffsize); + setvbuf(rb_data.pdh, rb_data.io_buffer, _IOFBF, buffsize); + } - return rb_data.pdh; + return rb_data.pdh; } /* @@ -431,51 +438,51 @@ ringbuf_init_libpcap_fdopen(int *err) gboolean ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err) { - int next_file_index; - rb_file *next_rfile = NULL; + int next_file_index; + rb_file *next_rfile = NULL; - /* close current file */ + /* close current file */ - if (fclose(rb_data.pdh) == EOF) { - if (err != NULL) { - *err = errno; + if (fclose(rb_data.pdh) == EOF) { + if (err != NULL) { + *err = errno; + } + ws_close(rb_data.fd); /* XXX - the above should have closed this already */ + rb_data.pdh = NULL; /* it's still closed, we just got an error while closing */ + rb_data.fd = -1; + g_free(rb_data.io_buffer); + rb_data.io_buffer = NULL; + return FALSE; } - ws_close(rb_data.fd); /* XXX - the above should have closed this already */ - rb_data.pdh = NULL; /* it's still closed, we just got an error while closing */ - rb_data.fd = -1; - g_free(rb_data.io_buffer); - rb_data.io_buffer = NULL; - return FALSE; - } - rb_data.pdh = NULL; - rb_data.fd = -1; + rb_data.pdh = NULL; + rb_data.fd = -1; - if (rb_data.name_h != NULL) { - fprintf(rb_data.name_h, "%s\n", ringbuf_current_filename()); - fflush(rb_data.name_h); - } + if (rb_data.name_h != NULL) { + fprintf(rb_data.name_h, "%s\n", ringbuf_current_filename()); + fflush(rb_data.name_h); + } - /* get the next file number and open it */ + /* get the next file number and open it */ - rb_data.curr_file_num++ /* = next_file_num*/; - next_file_index = (rb_data.curr_file_num) % rb_data.num_files; - next_rfile = &rb_data.files[next_file_index]; + rb_data.curr_file_num++ /* = next_file_num*/; + next_file_index = (rb_data.curr_file_num) % rb_data.num_files; + next_rfile = &rb_data.files[next_file_index]; - if (ringbuf_open_file(next_rfile, err) == -1) { - return FALSE; - } + if (ringbuf_open_file(next_rfile, err) == -1) { + return FALSE; + } - if (ringbuf_init_libpcap_fdopen(err) == NULL) { - return FALSE; - } + if (ringbuf_init_libpcap_fdopen(err) == NULL) { + return FALSE; + } - /* switch to the new file */ - *save_file = next_rfile->name; - *save_file_fd = rb_data.fd; - (*pdh) = rb_data.pdh; + /* switch to the new file */ + *save_file = next_rfile->name; + *save_file_fd = rb_data.fd; + (*pdh) = rb_data.pdh; - return TRUE; + return TRUE; } /* @@ -484,36 +491,36 @@ ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err) gboolean ringbuf_libpcap_dump_close(gchar **save_file, int *err) { - gboolean ret_val = TRUE; + gboolean ret_val = TRUE; + + /* close current file, if it's open */ + if (rb_data.pdh != NULL) { + if (fclose(rb_data.pdh) == EOF) { + if (err != NULL) { + *err = errno; + } + ws_close(rb_data.fd); + ret_val = FALSE; + } + rb_data.pdh = NULL; + rb_data.fd = -1; + g_free(rb_data.io_buffer); + rb_data.io_buffer = NULL; - /* close current file, if it's open */ - if (rb_data.pdh != NULL) { - if (fclose(rb_data.pdh) == EOF) { - if (err != NULL) { - *err = errno; - } - ws_close(rb_data.fd); - ret_val = FALSE; } - rb_data.pdh = NULL; - rb_data.fd = -1; - g_free(rb_data.io_buffer); - rb_data.io_buffer = NULL; - } + if (rb_data.name_h != NULL) { + fprintf(rb_data.name_h, "%s\n", ringbuf_current_filename()); + fflush(rb_data.name_h); - if (rb_data.name_h != NULL) { - fprintf(rb_data.name_h, "%s\n", ringbuf_current_filename()); - fflush(rb_data.name_h); - - if (EOF == fclose(rb_data.name_h)) { - /* Can't really do much about this, can we? */ + if (EOF == fclose(rb_data.name_h)) { + /* Can't really do much about this, can we? */ + } } - } - /* set the save file name to the current file */ - *save_file = rb_data.files[rb_data.curr_file_num % rb_data.num_files].name; - return ret_val; + /* set the save file name to the current file */ + *save_file = rb_data.files[rb_data.curr_file_num % rb_data.num_files].name; + return ret_val; } /* @@ -522,28 +529,28 @@ ringbuf_libpcap_dump_close(gchar **save_file, int *err) void ringbuf_free(void) { - unsigned int i; + unsigned int i; - if (rb_data.files != NULL) { - for (i=0; i < rb_data.num_files; i++) { - if (rb_data.files[i].name != NULL) { - g_free(rb_data.files[i].name); - rb_data.files[i].name = NULL; - } + if (rb_data.files != NULL) { + for (i=0; i < rb_data.num_files; i++) { + if (rb_data.files[i].name != NULL) { + g_free(rb_data.files[i].name); + rb_data.files[i].name = NULL; + } + } + g_free(rb_data.files); + rb_data.files = NULL; + } + if (rb_data.fprefix != NULL) { + g_free(rb_data.fprefix); + rb_data.fprefix = NULL; + } + if (rb_data.fsuffix != NULL) { + g_free(rb_data.fsuffix); + rb_data.fsuffix = NULL; } - g_free(rb_data.files); - rb_data.files = NULL; - } - if (rb_data.fprefix != NULL) { - g_free(rb_data.fprefix); - rb_data.fprefix = NULL; - } - if (rb_data.fsuffix != NULL) { - g_free(rb_data.fsuffix); - rb_data.fsuffix = NULL; - } - CleanupOldCap(NULL); + CleanupOldCap(NULL); } /* @@ -552,53 +559,40 @@ ringbuf_free(void) void ringbuf_error_cleanup(void) { - unsigned int i; + unsigned int i; - /* try to close via wtap */ - if (rb_data.pdh != NULL) { - if (fclose(rb_data.pdh) == 0) { - rb_data.fd = -1; + /* try to close via wtap */ + if (rb_data.pdh != NULL) { + if (fclose(rb_data.pdh) == 0) { + rb_data.fd = -1; + } + rb_data.pdh = NULL; } - rb_data.pdh = NULL; - } - /* close directly if still open */ - if (rb_data.fd != -1) { - ws_close(rb_data.fd); - rb_data.fd = -1; - } - - if (rb_data.files != NULL) { - for (i=0; i < rb_data.num_files; i++) { - if (rb_data.files[i].name != NULL) { - ws_unlink(rb_data.files[i].name); - } + /* close directly if still open */ + if (rb_data.fd != -1) { + ws_close(rb_data.fd); + rb_data.fd = -1; } - } - g_free(rb_data.io_buffer); - rb_data.io_buffer = NULL; - if (rb_data.name_h != NULL) { - if (EOF == fclose(rb_data.name_h)) { - /* Can't really do much about this, can we? */ + if (rb_data.files != NULL) { + for (i=0; i < rb_data.num_files; i++) { + if (rb_data.files[i].name != NULL) { + ws_unlink(rb_data.files[i].name); + } + } } - } + g_free(rb_data.io_buffer); + rb_data.io_buffer = NULL; - /* free the memory */ - ringbuf_free(); + if (rb_data.name_h != NULL) { + if (EOF == fclose(rb_data.name_h)) { + /* Can't really do much about this, can we? */ + } + } + + /* free the memory */ + ringbuf_free(); } #endif /* HAVE_LIBPCAP */ - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local Variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * ex: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/ringbuffer.h b/ringbuffer.h index 07df4c2587..b9d0187093 100644 --- a/ringbuffer.h +++ b/ringbuffer.h @@ -37,16 +37,3 @@ void ringbuf_error_cleanup(void); gboolean ringbuf_set_print_name(gchar *name, int *err); #endif /* ringbuffer.h */ - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local Variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/sharkd.c b/sharkd.c index 3a9cf40363..a0298d2120 100644 --- a/sharkd.c +++ b/sharkd.c @@ -77,391 +77,392 @@ static void sharkd_cmdarg_err(const char *msg_format, va_list ap); static void sharkd_cmdarg_err_cont(const char *msg_format, va_list ap); static void -print_current_user(void) { - gchar *cur_user, *cur_group; +print_current_user(void) +{ + gchar *cur_user, *cur_group; - if (started_with_special_privs()) { - cur_user = get_cur_username(); - cur_group = get_cur_groupname(); - fprintf(stderr, "Running as user \"%s\" and group \"%s\".", - cur_user, cur_group); - g_free(cur_user); - g_free(cur_group); - if (running_with_special_privs()) { - fprintf(stderr, " This could be dangerous."); + if (started_with_special_privs()) { + cur_user = get_cur_username(); + cur_group = get_cur_groupname(); + fprintf(stderr, "Running as user \"%s\" and group \"%s\".", + cur_user, cur_group); + g_free(cur_user); + g_free(cur_group); + if (running_with_special_privs()) { + fprintf(stderr, " This could be dangerous."); + } + fprintf(stderr, "\n"); } - fprintf(stderr, "\n"); - } } int main(int argc, char *argv[]) { - char *init_progfile_dir_error; + char *init_progfile_dir_error; - char *err_msg = NULL; - e_prefs *prefs_p; - int ret = EXIT_SUCCESS; - static const struct report_message_routines sharkd_report_routines = { - failure_message, - failure_message, - open_failure_message, - read_failure_message, - write_failure_message, - cfile_open_failure_message, - cfile_dump_open_failure_message, - cfile_read_failure_message, - cfile_write_failure_message, - cfile_close_failure_message - }; + char *err_msg = NULL; + e_prefs *prefs_p; + int ret = EXIT_SUCCESS; + static const struct report_message_routines sharkd_report_routines = { + failure_message, + failure_message, + open_failure_message, + read_failure_message, + write_failure_message, + cfile_open_failure_message, + cfile_dump_open_failure_message, + cfile_read_failure_message, + cfile_write_failure_message, + cfile_close_failure_message + }; - cmdarg_err_init(sharkd_cmdarg_err, sharkd_cmdarg_err_cont); + cmdarg_err_init(sharkd_cmdarg_err, sharkd_cmdarg_err_cont); - /* Initialize log handler early so we can have proper logging during startup. */ - ws_log_init("sharkd", vcmdarg_err); + /* Initialize log handler early so we can have proper logging during startup. */ + ws_log_init("sharkd", vcmdarg_err); - /* Early logging command-line initialization. */ - ws_log_parse_args(&argc, argv, vcmdarg_err, INIT_FAILED); + /* Early logging command-line initialization. */ + ws_log_parse_args(&argc, argv, vcmdarg_err, INIT_FAILED); - /* - * Get credential information for later use, and drop privileges - * before doing anything else. - * Let the user know if anything happened. - */ - init_process_policies(); - relinquish_special_privs_perm(); - print_current_user(); + /* + * Get credential information for later use, and drop privileges + * before doing anything else. + * Let the user know if anything happened. + */ + init_process_policies(); + relinquish_special_privs_perm(); + print_current_user(); - /* - * Attempt to get the pathname of the executable file. - */ - init_progfile_dir_error = init_progfile_dir(argv[0]); - if (init_progfile_dir_error != NULL) { - fprintf(stderr, "sharkd: Can't get pathname of sharkd program: %s.\n", - init_progfile_dir_error); - } + /* + * Attempt to get the pathname of the executable file. + */ + init_progfile_dir_error = init_progfile_dir(argv[0]); + if (init_progfile_dir_error != NULL) { + fprintf(stderr, "sharkd: Can't get pathname of sharkd program: %s.\n", + init_progfile_dir_error); + } - /* Initialize the version information. */ - ws_init_version_info("Sharkd (Wireshark)", NULL, - epan_get_compiled_version_info, - epan_get_runtime_version_info); + /* Initialize the version information. */ + ws_init_version_info("Sharkd (Wireshark)", NULL, + epan_get_compiled_version_info, + epan_get_runtime_version_info); - if (sharkd_init(argc, argv) < 0) - { - printf("cannot initialize sharkd\n"); - ret = INIT_FAILED; - goto clean_exit; - } + if (sharkd_init(argc, argv) < 0) + { + printf("cannot initialize sharkd\n"); + ret = INIT_FAILED; + goto clean_exit; + } - init_report_message("sharkd", &sharkd_report_routines); + init_report_message("sharkd", &sharkd_report_routines); - timestamp_set_type(TS_RELATIVE); - timestamp_set_precision(TS_PREC_AUTO); - timestamp_set_seconds_type(TS_SECONDS_DEFAULT); + timestamp_set_type(TS_RELATIVE); + timestamp_set_precision(TS_PREC_AUTO); + timestamp_set_seconds_type(TS_SECONDS_DEFAULT); - /* - * Libwiretap must be initialized before libwireshark is, so that - * dissection-time handlers for file-type-dependent blocks can - * register using the file type/subtype value for the file type. - */ - wtap_init(TRUE); + /* + * Libwiretap must be initialized before libwireshark is, so that + * dissection-time handlers for file-type-dependent blocks can + * register using the file type/subtype value for the file type. + */ + wtap_init(TRUE); - /* Register all dissectors; we must do this before checking for the - "-G" flag, as the "-G" flag dumps information registered by the - dissectors, and we must do it before we read the preferences, in - case any dissectors register preferences. */ - if (!epan_init(NULL, NULL, TRUE)) { - ret = EPAN_INIT_FAIL; - goto clean_exit; - } + /* Register all dissectors; we must do this before checking for the + "-G" flag, as the "-G" flag dumps information registered by the + dissectors, and we must do it before we read the preferences, in + case any dissectors register preferences. */ + if (!epan_init(NULL, NULL, TRUE)) { + ret = EPAN_INIT_FAIL; + goto clean_exit; + } - codecs_init(); + codecs_init(); - /* Load libwireshark settings from the current profile. */ - prefs_p = epan_load_settings(); + /* Load libwireshark settings from the current profile. */ + prefs_p = epan_load_settings(); - read_filter_list(CFILTER_LIST); + read_filter_list(CFILTER_LIST); - if (!color_filters_init(&err_msg, NULL)) { - fprintf(stderr, "%s\n", err_msg); - g_free(err_msg); - } + if (!color_filters_init(&err_msg, NULL)) { + fprintf(stderr, "%s\n", err_msg); + g_free(err_msg); + } - cap_file_init(&cfile); + cap_file_init(&cfile); - /* Notify all registered modules that have had any of their preferences - changed either from one of the preferences file or from the command - line that their preferences have changed. */ - prefs_apply_all(); + /* Notify all registered modules that have had any of their preferences + changed either from one of the preferences file or from the command + line that their preferences have changed. */ + prefs_apply_all(); - /* Build the column format array */ - build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE); + /* Build the column format array */ + build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE); #ifdef HAVE_MAXMINDDB - /* mmdbresolve is started from mmdb_resolve_start(), which is called from epan_load_settings via: read_prefs -> (...) uat_load_all -> maxmind_db_post_update_cb. - * Need to stop it, otherwise all sharkd will have same mmdbresolve process, including pipe descriptors to read and write. */ - uat_clear(uat_get_table_by_name("MaxMind Database Paths")); + /* mmdbresolve is started from mmdb_resolve_start(), which is called from epan_load_settings via: read_prefs -> (...) uat_load_all -> maxmind_db_post_update_cb. + * Need to stop it, otherwise all sharkd will have same mmdbresolve process, including pipe descriptors to read and write. */ + uat_clear(uat_get_table_by_name("MaxMind Database Paths")); #endif - ret = sharkd_loop(argc, argv); + ret = sharkd_loop(argc, argv); clean_exit: - col_cleanup(&cfile.cinfo); - free_filter_lists(); - codecs_cleanup(); - wtap_cleanup(); - free_progdirs(); - return ret; + col_cleanup(&cfile.cinfo); + free_filter_lists(); + codecs_cleanup(); + wtap_cleanup(); + free_progdirs(); + return ret; } static const nstime_t * sharkd_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num) { - if (prov->ref && prov->ref->num == frame_num) - return &prov->ref->abs_ts; + if (prov->ref && prov->ref->num == frame_num) + return &prov->ref->abs_ts; - if (prov->prev_dis && prov->prev_dis->num == frame_num) - return &prov->prev_dis->abs_ts; + if (prov->prev_dis && prov->prev_dis->num == frame_num) + return &prov->prev_dis->abs_ts; - if (prov->prev_cap && prov->prev_cap->num == frame_num) - return &prov->prev_cap->abs_ts; + if (prov->prev_cap && prov->prev_cap->num == frame_num) + return &prov->prev_cap->abs_ts; - if (prov->frames) { - frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); + if (prov->frames) { + frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); - return (fd) ? &fd->abs_ts : NULL; - } + return (fd) ? &fd->abs_ts : NULL; + } - return NULL; + return NULL; } static epan_t * sharkd_epan_new(capture_file *cf) { - static const struct packet_provider_funcs funcs = { - sharkd_get_frame_ts, - cap_file_provider_get_interface_name, - cap_file_provider_get_interface_description, - cap_file_provider_get_modified_block - }; + static const struct packet_provider_funcs funcs = { + sharkd_get_frame_ts, + cap_file_provider_get_interface_name, + cap_file_provider_get_interface_description, + cap_file_provider_get_modified_block + }; - return epan_new(&cf->provider, &funcs); + return epan_new(&cf->provider, &funcs); } static gboolean process_packet(capture_file *cf, epan_dissect_t *edt, - gint64 offset, wtap_rec *rec, Buffer *buf) + gint64 offset, wtap_rec *rec, Buffer *buf) { - frame_data fdlocal; - gboolean passed; + frame_data fdlocal; + gboolean passed; - /* If we're not running a display filter and we're not printing any - packet information, we don't need to do a dissection. This means - that all packets can be marked as 'passed'. */ - passed = TRUE; + /* If we're not running a display filter and we're not printing any + packet information, we don't need to do a dissection. This means + that all packets can be marked as 'passed'. */ + passed = TRUE; - /* The frame number of this packet, if we add it to the set of frames, - would be one more than the count of frames in the file so far. */ - frame_data_init(&fdlocal, cf->count + 1, rec, offset, cum_bytes); + /* The frame number of this packet, if we add it to the set of frames, + would be one more than the count of frames in the file so far. */ + frame_data_init(&fdlocal, cf->count + 1, rec, offset, cum_bytes); - /* If we're going to print packet information, or we're going to - run a read filter, or display filter, or we're going to process taps, set up to - do a dissection and do so. */ - if (edt) { - if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name || - gbl_resolv_flags.transport_name) - /* Grab any resolved addresses */ - host_name_lookup_process(); + /* If we're going to print packet information, or we're going to + run a read filter, or display filter, or we're going to process taps, set up to + do a dissection and do so. */ + if (edt) { + if (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name || + gbl_resolv_flags.transport_name) + /* Grab any resolved addresses */ + host_name_lookup_process(); - /* If we're running a read filter, prime the epan_dissect_t with that - filter. */ - if (cf->rfcode) - epan_dissect_prime_with_dfilter(edt, cf->rfcode); + /* If we're running a read filter, prime the epan_dissect_t with that + filter. */ + if (cf->rfcode) + epan_dissect_prime_with_dfilter(edt, cf->rfcode); - if (cf->dfcode) - epan_dissect_prime_with_dfilter(edt, cf->dfcode); + if (cf->dfcode) + epan_dissect_prime_with_dfilter(edt, cf->dfcode); - /* This is the first and only pass, so prime the epan_dissect_t - with the hfids postdissectors want on the first pass. */ - prime_epan_dissect_with_postdissector_wanted_hfids(edt); + /* This is the first and only pass, so prime the epan_dissect_t + with the hfids postdissectors want on the first pass. */ + prime_epan_dissect_with_postdissector_wanted_hfids(edt); - frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time, - &cf->provider.ref, cf->provider.prev_dis); - if (cf->provider.ref == &fdlocal) { - ref_frame = fdlocal; - cf->provider.ref = &ref_frame; + frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time, + &cf->provider.ref, cf->provider.prev_dis); + if (cf->provider.ref == &fdlocal) { + ref_frame = fdlocal; + cf->provider.ref = &ref_frame; + } + + epan_dissect_run(edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf), + &fdlocal, NULL); + + /* Run the read filter if we have one. */ + if (cf->rfcode) + passed = dfilter_apply_edt(cf->rfcode, edt); } - epan_dissect_run(edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf), - &fdlocal, NULL); + if (passed) { + frame_data_set_after_dissect(&fdlocal, &cum_bytes); + cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal); - /* Run the read filter if we have one. */ - if (cf->rfcode) - passed = dfilter_apply_edt(cf->rfcode, edt); - } + /* If we're not doing dissection then there won't be any dependent frames. + * More importantly, edt.pi.dependent_frames won't be initialized because + * epan hasn't been initialized. + * if we *are* doing dissection, then mark the dependent frames, but only + * if a display filter was given and it matches this packet. + */ + if (edt && cf->dfcode) { + if (dfilter_apply_edt(cf->dfcode, edt)) { + g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); + } + } - if (passed) { - frame_data_set_after_dissect(&fdlocal, &cum_bytes); - cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal); - - /* If we're not doing dissection then there won't be any dependent frames. - * More importantly, edt.pi.dependent_frames won't be initialized because - * epan hasn't been initialized. - * if we *are* doing dissection, then mark the dependent frames, but only - * if a display filter was given and it matches this packet. - */ - if (edt && cf->dfcode) { - if (dfilter_apply_edt(cf->dfcode, edt)) { - g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); - } + cf->count++; + } else { + /* if we don't add it to the frame_data_sequence, clean it up right now + * to avoid leaks */ + frame_data_destroy(&fdlocal); } - cf->count++; - } else { - /* if we don't add it to the frame_data_sequence, clean it up right now - * to avoid leaks */ - frame_data_destroy(&fdlocal); - } + if (edt) + epan_dissect_reset(edt); - if (edt) - epan_dissect_reset(edt); - - return passed; + return passed; } static int load_cap_file(capture_file *cf, int max_packet_count, gint64 max_byte_count) { - int err; - gchar *err_info = NULL; - gint64 data_offset; - wtap_rec rec; - Buffer buf; - epan_dissect_t *edt = NULL; - - { - /* Allocate a frame_data_sequence for all the frames. */ - cf->provider.frames = new_frame_data_sequence(); + int err; + gchar *err_info = NULL; + gint64 data_offset; + wtap_rec rec; + Buffer buf; + epan_dissect_t *edt = NULL; { - gboolean create_proto_tree; + /* Allocate a frame_data_sequence for all the frames. */ + cf->provider.frames = new_frame_data_sequence(); - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a read filter; - * - * we're going to apply a display filter; - * - * a postdissector wants field values or protocols - * on the first pass. - */ - create_proto_tree = - (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids()); + { + gboolean create_proto_tree; - /* We're not going to display the protocol tree on this pass, - so it's not going to be "visible". */ - edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE); - } + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a read filter; + * + * we're going to apply a display filter; + * + * a postdissector wants field values or protocols + * on the first pass. + */ + create_proto_tree = + (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids()); - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - - while (wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, &data_offset)) { - if (process_packet(cf, edt, data_offset, &rec, &buf)) { - wtap_rec_reset(&rec); - /* Stop reading if we have the maximum number of packets; - * When the -c option has not been used, max_packet_count - * starts at 0, which practically means, never stop reading. - * (unless we roll over max_packet_count ?) - */ - if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) { - err = 0; /* This is not an error */ - break; + /* We're not going to display the protocol tree on this pass, + so it's not going to be "visible". */ + edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE); } - } + + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + + while (wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, &data_offset)) { + if (process_packet(cf, edt, data_offset, &rec, &buf)) { + wtap_rec_reset(&rec); + /* Stop reading if we have the maximum number of packets; + * When the -c option has not been used, max_packet_count + * starts at 0, which practically means, never stop reading. + * (unless we roll over max_packet_count ?) + */ + if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) { + err = 0; /* This is not an error */ + break; + } + } + } + + if (edt) { + epan_dissect_free(edt); + edt = NULL; + } + + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + + /* Close the sequential I/O side, to free up memory it requires. */ + wtap_sequential_close(cf->provider.wth); + + /* Allow the protocol dissectors to free up memory that they + * don't need after the sequential run-through of the packets. */ + postseq_cleanup_all_protocols(); + + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; } - if (edt) { - epan_dissect_free(edt); - edt = NULL; + if (err != 0) { + cfile_read_failure_message(cf->filename, err, err_info); } - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - - /* Close the sequential I/O side, to free up memory it requires. */ - wtap_sequential_close(cf->provider.wth); - - /* Allow the protocol dissectors to free up memory that they - * don't need after the sequential run-through of the packets. */ - postseq_cleanup_all_protocols(); - - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; - } - - if (err != 0) { - cfile_read_failure_message(cf->filename, err, err_info); - } - - return err; + return err; } cf_status_t cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err) { - wtap *wth; - gchar *err_info; + wtap *wth; + gchar *err_info; - wth = wtap_open_offline(fname, type, err, &err_info, TRUE); - if (wth == NULL) - goto fail; + wth = wtap_open_offline(fname, type, err, &err_info, TRUE); + if (wth == NULL) + goto fail; - /* The open succeeded. Fill in the information for this file. */ + /* The open succeeded. Fill in the information for this file. */ - cf->provider.wth = wth; - cf->f_datalen = 0; /* not used, but set it anyway */ + cf->provider.wth = wth; + cf->f_datalen = 0; /* not used, but set it anyway */ - /* Set the file name because we need it to set the follow stream filter. - XXX - is that still true? We need it for other reasons, though, - in any case. */ - cf->filename = g_strdup(fname); + /* Set the file name because we need it to set the follow stream filter. + XXX - is that still true? We need it for other reasons, though, + in any case. */ + cf->filename = g_strdup(fname); - /* Indicate whether it's a permanent or temporary file. */ - cf->is_tempfile = is_tempfile; + /* Indicate whether it's a permanent or temporary file. */ + cf->is_tempfile = is_tempfile; - /* No user changes yet. */ - cf->unsaved_changes = FALSE; + /* No user changes yet. */ + cf->unsaved_changes = FALSE; - cf->cd_t = wtap_file_type_subtype(cf->provider.wth); - cf->open_type = type; - cf->count = 0; - cf->drops_known = FALSE; - cf->drops = 0; - cf->snap = wtap_snapshot_length(cf->provider.wth); - nstime_set_zero(&cf->elapsed_time); - cf->provider.ref = NULL; - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; + cf->cd_t = wtap_file_type_subtype(cf->provider.wth); + cf->open_type = type; + cf->count = 0; + cf->drops_known = FALSE; + cf->drops = 0; + cf->snap = wtap_snapshot_length(cf->provider.wth); + nstime_set_zero(&cf->elapsed_time); + cf->provider.ref = NULL; + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; - /* Create new epan session for dissection. */ - epan_free(cf->epan); - cf->epan = sharkd_epan_new(cf); + /* Create new epan session for dissection. */ + epan_free(cf->epan); + cf->epan = sharkd_epan_new(cf); - cf->state = FILE_READ_IN_PROGRESS; + cf->state = FILE_READ_IN_PROGRESS; - wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name); - wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name); - wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); + wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name); + wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name); + wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); - return CF_OK; + return CF_OK; fail: - cfile_open_failure_message(fname, *err, err_info); - return CF_ERROR; + cfile_open_failure_message(fname, *err, err_info); + return CF_ERROR; } /* @@ -470,9 +471,9 @@ fail: static void sharkd_cmdarg_err(const char *msg_format, va_list ap) { - fprintf(stderr, "sharkd: "); - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + fprintf(stderr, "sharkd: "); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } /* @@ -481,232 +482,232 @@ sharkd_cmdarg_err(const char *msg_format, va_list ap) static void sharkd_cmdarg_err_cont(const char *msg_format, va_list ap) { - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } cf_status_t sharkd_cf_open(const char *fname, unsigned int type, gboolean is_tempfile, int *err) { - return cf_open(&cfile, fname, type, is_tempfile, err); + return cf_open(&cfile, fname, type, is_tempfile, err); } int sharkd_load_cap_file(void) { - return load_cap_file(&cfile, 0, 0); + return load_cap_file(&cfile, 0, 0); } frame_data * sharkd_get_frame(guint32 framenum) { - return frame_data_sequence_find(cfile.provider.frames, framenum); + return frame_data_sequence_find(cfile.provider.frames, framenum); } enum dissect_request_status sharkd_dissect_request(guint32 framenum, guint32 frame_ref_num, - guint32 prev_dis_num, wtap_rec *rec, Buffer *buf, - column_info *cinfo, guint32 dissect_flags, - sharkd_dissect_func_t cb, void *data, - int *err, gchar **err_info) + guint32 prev_dis_num, wtap_rec *rec, Buffer *buf, + column_info *cinfo, guint32 dissect_flags, + sharkd_dissect_func_t cb, void *data, + int *err, gchar **err_info) { - frame_data *fdata; - epan_dissect_t edt; - gboolean create_proto_tree; + frame_data *fdata; + epan_dissect_t edt; + gboolean create_proto_tree; - fdata = sharkd_get_frame(framenum); - if (fdata == NULL) - return DISSECT_REQUEST_NO_SUCH_FRAME; + fdata = sharkd_get_frame(framenum); + if (fdata == NULL) + return DISSECT_REQUEST_NO_SUCH_FRAME; - if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, rec, buf, err, err_info)) { - if (cinfo != NULL) - col_fill_in_error(cinfo, fdata, FALSE, FALSE /* fill_fd_columns */); - return DISSECT_REQUEST_READ_ERROR; /* error reading the record */ - } + if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, rec, buf, err, err_info)) { + if (cinfo != NULL) + col_fill_in_error(cinfo, fdata, FALSE, FALSE /* fill_fd_columns */); + return DISSECT_REQUEST_READ_ERROR; /* error reading the record */ + } - create_proto_tree = ((dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) || - ((dissect_flags & SHARKD_DISSECT_FLAG_COLOR) && color_filters_used()) || - (cinfo && have_custom_cols(cinfo))); - epan_dissect_init(&edt, cfile.epan, create_proto_tree, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE)); + create_proto_tree = ((dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) || + ((dissect_flags & SHARKD_DISSECT_FLAG_COLOR) && color_filters_used()) || + (cinfo && have_custom_cols(cinfo))); + epan_dissect_init(&edt, cfile.epan, create_proto_tree, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE)); - if (dissect_flags & SHARKD_DISSECT_FLAG_COLOR) { - color_filters_prime_edt(&edt); - fdata->need_colorize = 1; - } + if (dissect_flags & SHARKD_DISSECT_FLAG_COLOR) { + color_filters_prime_edt(&edt); + fdata->need_colorize = 1; + } - if (cinfo) - col_custom_prime_edt(&edt, cinfo); + if (cinfo) + col_custom_prime_edt(&edt, cinfo); - /* - * XXX - need to catch an OutOfMemoryError exception and - * attempt to recover from it. - */ - fdata->ref_time = (framenum == frame_ref_num); - fdata->frame_ref_num = frame_ref_num; - fdata->prev_dis_num = prev_dis_num; - epan_dissect_run(&edt, cfile.cd_t, rec, - frame_tvbuff_new_buffer(&cfile.provider, fdata, buf), - fdata, cinfo); + /* + * XXX - need to catch an OutOfMemoryError exception and + * attempt to recover from it. + */ + fdata->ref_time = (framenum == frame_ref_num); + fdata->frame_ref_num = frame_ref_num; + fdata->prev_dis_num = prev_dis_num; + epan_dissect_run(&edt, cfile.cd_t, rec, + frame_tvbuff_new_buffer(&cfile.provider, fdata, buf), + fdata, cinfo); - if (cinfo) { - /* "Stringify" non frame_data vals */ - epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */); - } + if (cinfo) { + /* "Stringify" non frame_data vals */ + epan_dissect_fill_in_columns(&edt, FALSE, TRUE/* fill_fd_columns */); + } - cb(&edt, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) ? edt.tree : NULL, - cinfo, (dissect_flags & SHARKD_DISSECT_FLAG_BYTES) ? edt.pi.data_src : NULL, - data); + cb(&edt, (dissect_flags & SHARKD_DISSECT_FLAG_PROTO_TREE) ? edt.tree : NULL, + cinfo, (dissect_flags & SHARKD_DISSECT_FLAG_BYTES) ? edt.pi.data_src : NULL, + data); - wtap_rec_reset(rec); - epan_dissect_cleanup(&edt); - return DISSECT_REQUEST_SUCCESS; + wtap_rec_reset(rec); + epan_dissect_cleanup(&edt); + return DISSECT_REQUEST_SUCCESS; } int sharkd_retap(void) { - guint32 framenum; - frame_data *fdata; - Buffer buf; - wtap_rec rec; - int err; - char *err_info = NULL; + guint32 framenum; + frame_data *fdata; + Buffer buf; + wtap_rec rec; + int err; + char *err_info = NULL; - guint tap_flags; - gboolean create_proto_tree; - epan_dissect_t edt; - column_info *cinfo; + guint tap_flags; + gboolean create_proto_tree; + epan_dissect_t edt; + column_info *cinfo; - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - /* If any tap listeners require the columns, construct them. */ - cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cfile.cinfo : NULL; + /* If any tap listeners require the columns, construct them. */ + cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cfile.cinfo : NULL; - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree. - */ - create_proto_tree = - (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE)); + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree. + */ + create_proto_tree = + (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE)); - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + epan_dissect_init(&edt, cfile.epan, create_proto_tree, FALSE); - reset_tap_listeners(); + reset_tap_listeners(); - for (framenum = 1; framenum <= cfile.count; framenum++) { - fdata = sharkd_get_frame(framenum); + for (framenum = 1; framenum <= cfile.count; framenum++) { + fdata = sharkd_get_frame(framenum); - if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info)) - break; + if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info)) + break; - fdata->ref_time = FALSE; - fdata->frame_ref_num = (framenum != 1) ? 1 : 0; - fdata->prev_dis_num = framenum - 1; - epan_dissect_run_with_taps(&edt, cfile.cd_t, &rec, - frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf), - fdata, cinfo); - wtap_rec_reset(&rec); - epan_dissect_reset(&edt); - } + fdata->ref_time = FALSE; + fdata->frame_ref_num = (framenum != 1) ? 1 : 0; + fdata->prev_dis_num = framenum - 1; + epan_dissect_run_with_taps(&edt, cfile.cd_t, &rec, + frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf), + fdata, cinfo); + wtap_rec_reset(&rec); + epan_dissect_reset(&edt); + } - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - epan_dissect_cleanup(&edt); + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + epan_dissect_cleanup(&edt); - draw_tap_listeners(TRUE); + draw_tap_listeners(TRUE); - return 0; + return 0; } int sharkd_filter(const char *dftext, guint8 **result) { - dfilter_t *dfcode = NULL; + dfilter_t *dfcode = NULL; - guint32 framenum, prev_dis_num = 0; - guint32 frames_count; - Buffer buf; - wtap_rec rec; - int err; - char *err_info = NULL; + guint32 framenum, prev_dis_num = 0; + guint32 frames_count; + Buffer buf; + wtap_rec rec; + int err; + char *err_info = NULL; - guint8 *result_bits; - guint8 passed_bits; + guint8 *result_bits; + guint8 passed_bits; - epan_dissect_t edt; + epan_dissect_t edt; - if (!dfilter_compile(dftext, &dfcode, &err_info)) { - g_free(err_info); - return -1; - } - - /* if dfilter_compile() success, but (dfcode == NULL) all frames are matching */ - if (dfcode == NULL) { - *result = NULL; - return 0; - } - - frames_count = cfile.count; - - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - epan_dissect_init(&edt, cfile.epan, TRUE, FALSE); - - passed_bits = 0; - result_bits = (guint8 *) g_malloc(2 + (frames_count / 8)); - - for (framenum = 1; framenum <= frames_count; framenum++) { - frame_data *fdata = sharkd_get_frame(framenum); - - if ((framenum & 7) == 0) { - result_bits[(framenum / 8) - 1] = passed_bits; - passed_bits = 0; + if (!dfilter_compile(dftext, &dfcode, &err_info)) { + g_free(err_info); + return -1; } - if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info)) - break; - - /* frame_data_set_before_dissect */ - epan_dissect_prime_with_dfilter(&edt, dfcode); - - fdata->ref_time = FALSE; - fdata->frame_ref_num = (framenum != 1) ? 1 : 0; - fdata->prev_dis_num = prev_dis_num; - epan_dissect_run(&edt, cfile.cd_t, &rec, - frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf), - fdata, NULL); - - if (dfilter_apply_edt(dfcode, &edt)) { - passed_bits |= (1 << (framenum % 8)); - prev_dis_num = framenum; + /* if dfilter_compile() success, but (dfcode == NULL) all frames are matching */ + if (dfcode == NULL) { + *result = NULL; + return 0; } - /* if passed or ref -> frame_data_set_after_dissect */ + frames_count = cfile.count; - wtap_rec_reset(&rec); - epan_dissect_reset(&edt); - } + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + epan_dissect_init(&edt, cfile.epan, TRUE, FALSE); - if ((framenum & 7) == 0) - framenum--; - result_bits[framenum / 8] = passed_bits; + passed_bits = 0; + result_bits = (guint8 *) g_malloc(2 + (frames_count / 8)); - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - epan_dissect_cleanup(&edt); + for (framenum = 1; framenum <= frames_count; framenum++) { + frame_data *fdata = sharkd_get_frame(framenum); - dfilter_free(dfcode); + if ((framenum & 7) == 0) { + result_bits[(framenum / 8) - 1] = passed_bits; + passed_bits = 0; + } - *result = result_bits; + if (!wtap_seek_read(cfile.provider.wth, fdata->file_off, &rec, &buf, &err, &err_info)) + break; - return framenum; + /* frame_data_set_before_dissect */ + epan_dissect_prime_with_dfilter(&edt, dfcode); + + fdata->ref_time = FALSE; + fdata->frame_ref_num = (framenum != 1) ? 1 : 0; + fdata->prev_dis_num = prev_dis_num; + epan_dissect_run(&edt, cfile.cd_t, &rec, + frame_tvbuff_new_buffer(&cfile.provider, fdata, &buf), + fdata, NULL); + + if (dfilter_apply_edt(dfcode, &edt)) { + passed_bits |= (1 << (framenum % 8)); + prev_dis_num = framenum; + } + + /* if passed or ref -> frame_data_set_after_dissect */ + + wtap_rec_reset(&rec); + epan_dissect_reset(&edt); + } + + if ((framenum & 7) == 0) + framenum--; + result_bits[framenum / 8] = passed_bits; + + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + epan_dissect_cleanup(&edt); + + dfilter_free(dfcode); + + *result = result_bits; + + return framenum; } /* @@ -716,7 +717,7 @@ sharkd_filter(const char *dftext, guint8 **result) wtap_block_t sharkd_get_modified_block(const frame_data *fd) { - return cap_file_provider_get_modified_block(&cfile.provider, fd); + return cap_file_provider_get_modified_block(&cfile.provider, fd); } /* @@ -727,47 +728,34 @@ sharkd_get_modified_block(const frame_data *fd) wtap_block_t sharkd_get_packet_block(const frame_data *fd) { - if (fd->has_modified_block) - return wtap_block_ref(cap_file_provider_get_modified_block(&cfile.provider, fd)); - else - { - wtap_rec rec; /* Record metadata */ - Buffer buf; /* Record data */ - wtap_block_t block; - int err; - gchar *err_info; + if (fd->has_modified_block) + return wtap_block_ref(cap_file_provider_get_modified_block(&cfile.provider, fd)); + else + { + wtap_rec rec; /* Record metadata */ + Buffer buf; /* Record data */ + wtap_block_t block; + int err; + gchar *err_info; - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - if (!wtap_seek_read(cfile.provider.wth, fd->file_off, &rec, &buf, &err, &err_info)) - { /* XXX, what we can do here? */ } + if (!wtap_seek_read(cfile.provider.wth, fd->file_off, &rec, &buf, &err, &err_info)) + { /* XXX, what we can do here? */ } - /* rec.block is owned by the record, steal it before it is gone. */ - block = wtap_block_ref(rec.block); + /* rec.block is owned by the record, steal it before it is gone. */ + block = wtap_block_ref(rec.block); - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - return block; - } + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + return block; + } } int sharkd_set_modified_block(frame_data *fd, wtap_block_t new_block) { - cap_file_provider_set_modified_block(&cfile.provider, fd, new_block); - return 0; + cap_file_provider_set_modified_block(&cfile.provider, fd, new_block); + return 0; } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/sharkd_daemon.c b/sharkd_daemon.c index bd80f68069..e990b931ad 100644 --- a/sharkd_daemon.c +++ b/sharkd_daemon.c @@ -56,303 +56,303 @@ static socket_handle_t _server_fd = INVALID_SOCKET; static socket_handle_t socket_init(char *path) { - socket_handle_t fd = INVALID_SOCKET; - char *err_msg; + socket_handle_t fd = INVALID_SOCKET; + char *err_msg; - err_msg = ws_init_sockets(); - if (err_msg != NULL) { - ws_warning("ERROR: %s", err_msg); - g_free(err_msg); - ws_warning("%s", please_report_bug()); - return fd; - } + err_msg = ws_init_sockets(); + if (err_msg != NULL) { + ws_warning("ERROR: %s", err_msg); + g_free(err_msg); + ws_warning("%s", please_report_bug()); + return fd; + } #ifdef SHARKD_UNIX_SUPPORT - if (!strncmp(path, "unix:", 5)) - { - struct sockaddr_un s_un; - socklen_t s_un_len; + if (!strncmp(path, "unix:", 5)) + { + struct sockaddr_un s_un; + socklen_t s_un_len; - path += 5; + path += 5; - if (strlen(path) + 1 > sizeof(s_un.sun_path)) - return INVALID_SOCKET; + if (strlen(path) + 1 > sizeof(s_un.sun_path)) + return INVALID_SOCKET; - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == INVALID_SOCKET) - return INVALID_SOCKET; + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == INVALID_SOCKET) + return INVALID_SOCKET; - memset(&s_un, 0, sizeof(s_un)); - s_un.sun_family = AF_UNIX; - (void) g_strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)); + memset(&s_un, 0, sizeof(s_un)); + s_un.sun_family = AF_UNIX; + (void) g_strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)); - s_un_len = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen(s_un.sun_path)); + s_un_len = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen(s_un.sun_path)); - if (s_un.sun_path[0] == '@') - s_un.sun_path[0] = '\0'; + if (s_un.sun_path[0] == '@') + s_un.sun_path[0] = '\0'; - if (bind(fd, (struct sockaddr *) &s_un, s_un_len)) - { - closesocket(fd); - return INVALID_SOCKET; - } - } - else + if (bind(fd, (struct sockaddr *) &s_un, s_un_len)) + { + closesocket(fd); + return INVALID_SOCKET; + } + } + else #endif #ifdef SHARKD_TCP_SUPPORT - if (!strncmp(path, "tcp:", 4)) - { - struct sockaddr_in s_in; - int one = 1; - char *port_sep; - guint16 port; + if (!strncmp(path, "tcp:", 4)) + { + struct sockaddr_in s_in; + int one = 1; + char *port_sep; + guint16 port; - path += 4; + path += 4; - port_sep = strchr(path, ':'); - if (!port_sep) - return INVALID_SOCKET; + port_sep = strchr(path, ':'); + if (!port_sep) + return INVALID_SOCKET; - *port_sep = '\0'; + *port_sep = '\0'; - if (ws_strtou16(port_sep + 1, NULL, &port) == FALSE) - return INVALID_SOCKET; + if (ws_strtou16(port_sep + 1, NULL, &port) == FALSE) + return INVALID_SOCKET; #ifdef _WIN32 - /* Need to use WSASocket() to disable overlapped I/O operations, - this way on windows SOCKET can be used as HANDLE for stdin/stdout */ - fd = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0); + /* Need to use WSASocket() to disable overlapped I/O operations, + this way on windows SOCKET can be used as HANDLE for stdin/stdout */ + fd = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0); #else - fd = socket(AF_INET, SOCK_STREAM, 0); + fd = socket(AF_INET, SOCK_STREAM, 0); #endif - if (fd == INVALID_SOCKET) - return INVALID_SOCKET; + if (fd == INVALID_SOCKET) + return INVALID_SOCKET; - s_in.sin_family = AF_INET; - ws_inet_pton4(path, &(s_in.sin_addr.s_addr)); - s_in.sin_port = g_htons(port); - *port_sep = ':'; + s_in.sin_family = AF_INET; + ws_inet_pton4(path, &(s_in.sin_addr.s_addr)); + s_in.sin_port = g_htons(port); + *port_sep = ':'; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one)); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one)); - if (bind(fd, (struct sockaddr *) &s_in, sizeof(struct sockaddr_in))) - { - closesocket(fd); - return INVALID_SOCKET; - } - } - else + if (bind(fd, (struct sockaddr *) &s_in, sizeof(struct sockaddr_in))) + { + closesocket(fd); + return INVALID_SOCKET; + } + } + else #endif - { - return INVALID_SOCKET; - } + { + return INVALID_SOCKET; + } - if (listen(fd, SOMAXCONN)) - { - closesocket(fd); - return INVALID_SOCKET; - } + if (listen(fd, SOMAXCONN)) + { + closesocket(fd); + return INVALID_SOCKET; + } - return fd; + return fd; } static void print_usage(FILE* output) { - fprintf(output, "\n"); - fprintf(output, "Usage: sharkd [|]\n"); + fprintf(output, "\n"); + fprintf(output, "Usage: sharkd [|]\n"); - fprintf(output, "\n"); - fprintf(output, "Classic (classic_options):\n"); - fprintf(output, " [-|]\n"); - fprintf(output, "\n"); - fprintf(output, " examples:\n"); + fprintf(output, "\n"); + fprintf(output, "Classic (classic_options):\n"); + fprintf(output, " [-|]\n"); + fprintf(output, "\n"); + fprintf(output, " examples:\n"); #ifdef SHARKD_UNIX_SUPPORT - fprintf(output, " - unix:/tmp/sharkd.sock - listen on unix file /tmp/sharkd.sock\n"); + fprintf(output, " - unix:/tmp/sharkd.sock - listen on unix file /tmp/sharkd.sock\n"); #endif #ifdef SHARKD_TCP_SUPPORT - fprintf(output, " - tcp:127.0.0.1:4446 - listen on TCP port 4446\n"); + fprintf(output, " - tcp:127.0.0.1:4446 - listen on TCP port 4446\n"); #endif - fprintf(output, "\n"); - fprintf(output, "Gold (gold_options):\n"); - fprintf(output, " -a , --api \n"); - fprintf(output, " listen on this socket\n"); - fprintf(output, " -h, --help show this help information\n"); - fprintf(output, " -v, --version show version information\n"); - fprintf(output, " -C , --config-profile \n"); - fprintf(output, " start with specified configuration profile\n"); + fprintf(output, "\n"); + fprintf(output, "Gold (gold_options):\n"); + fprintf(output, " -a , --api \n"); + fprintf(output, " listen on this socket\n"); + fprintf(output, " -h, --help show this help information\n"); + fprintf(output, " -v, --version show version information\n"); + fprintf(output, " -C , --config-profile \n"); + fprintf(output, " start with specified configuration profile\n"); - fprintf(output, "\n"); - fprintf(output, " Examples:\n"); - fprintf(output, " sharkd -C myprofile\n"); - fprintf(output, " sharkd -a tcp:127.0.0.1:4446 -C myprofile\n"); + fprintf(output, "\n"); + fprintf(output, " Examples:\n"); + fprintf(output, " sharkd -C myprofile\n"); + fprintf(output, " sharkd -a tcp:127.0.0.1:4446 -C myprofile\n"); - fprintf(output, "\n"); - fprintf(output, "See the sharkd page of the Wireshark wiki for full details.\n"); - fprintf(output, "\n"); + fprintf(output, "\n"); + fprintf(output, "See the sharkd page of the Wireshark wiki for full details.\n"); + fprintf(output, "\n"); } int sharkd_init(int argc, char **argv) { - /* - * The leading + ensures that getopt_long() does not permute the argv[] - * entries. - * - * We have to make sure that the first getopt_long() preserves the content - * of argv[] for the subsequent getopt_long() call. - * - * We use getopt_long() in both cases to ensure that we're using a routine - * whose permutation behavior we can control in the same fashion on all - * platforms, and so that, if we ever need to process a long argument before - * doing further initialization, we can do so. - * - * Glibc and Solaris libc document that a leading + disables permutation - * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD - * and macOS don't document it, but do so anyway. - * - * We do *not* use a leading - because the behavior of a leading - is - * platform-dependent. - */ + /* + * The leading + ensures that getopt_long() does not permute the argv[] + * entries. + * + * We have to make sure that the first getopt_long() preserves the content + * of argv[] for the subsequent getopt_long() call. + * + * We use getopt_long() in both cases to ensure that we're using a routine + * whose permutation behavior we can control in the same fashion on all + * platforms, and so that, if we ever need to process a long argument before + * doing further initialization, we can do so. + * + * Glibc and Solaris libc document that a leading + disables permutation + * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD + * and macOS don't document it, but do so anyway. + * + * We do *not* use a leading - because the behavior of a leading - is + * platform-dependent. + */ #define OPTSTRING "+" "a:hmvC:" - static const char optstring[] = OPTSTRING; + static const char optstring[] = OPTSTRING; - // right now we don't have any long options - static const struct ws_option long_options[] = { - {"api", ws_required_argument, NULL, 'a'}, - {"help", ws_no_argument, NULL, 'h'}, - {"version", ws_no_argument, NULL, 'v'}, - {"config-profile", ws_required_argument, NULL, 'C'}, - {0, 0, 0, 0 } - }; + // right now we don't have any long options + static const struct ws_option long_options[] = { + {"api", ws_required_argument, NULL, 'a'}, + {"help", ws_no_argument, NULL, 'h'}, + {"version", ws_no_argument, NULL, 'v'}, + {"config-profile", ws_required_argument, NULL, 'C'}, + {0, 0, 0, 0 } + }; - int opt; + int opt; #ifndef _WIN32 - pid_t pid; + pid_t pid; #endif - socket_handle_t fd; + socket_handle_t fd; - if (argc < 2) - { - print_usage(stderr); - return -1; - } + if (argc < 2) + { + print_usage(stderr); + return -1; + } - // check for classic command line - if (!strcmp(argv[1], "-") || argv[1][0] == 't' || argv[1][0] == 'u') - { - mode = SHARKD_MODE_CLASSIC_CONSOLE; + // check for classic command line + if (!strcmp(argv[1], "-") || argv[1][0] == 't' || argv[1][0] == 'u') + { + mode = SHARKD_MODE_CLASSIC_CONSOLE; #ifndef _WIN32 - signal(SIGCHLD, SIG_IGN); + signal(SIGCHLD, SIG_IGN); #endif - if (!strcmp(argv[1], "-")) - { - mode = SHARKD_MODE_CLASSIC_CONSOLE; - } - else - { - fd = socket_init(argv[1]); - if (fd == INVALID_SOCKET) - return -1; - _server_fd = fd; - mode = SHARKD_MODE_CLASSIC_DAEMON; - } - } - else - mode = SHARKD_MODE_GOLD_CONSOLE; // assume we are running as gold console + if (!strcmp(argv[1], "-")) + { + mode = SHARKD_MODE_CLASSIC_CONSOLE; + } + else + { + fd = socket_init(argv[1]); + if (fd == INVALID_SOCKET) + return -1; + _server_fd = fd; + mode = SHARKD_MODE_CLASSIC_DAEMON; + } + } + else + mode = SHARKD_MODE_GOLD_CONSOLE; // assume we are running as gold console - if (mode >= SHARKD_MODE_GOLD_CONSOLE) - { - /* - In Daemon Mode, we will come through here twice; once when we start the Daemon and - once again after we have forked the session process. The second time through, the - session process has already had its stdin and stdout wired up to the TCP or UNIX - socket and so in the orignal version of sharkd the session process is invoked with - the command line: sharkd - + if (mode >= SHARKD_MODE_GOLD_CONSOLE) + { + /* + In Daemon Mode, we will come through here twice; once when we start the Daemon and + once again after we have forked the session process. The second time through, the + session process has already had its stdin and stdout wired up to the TCP or UNIX + socket and so in the orignal version of sharkd the session process is invoked with + the command line: sharkd - - When not using the classic command line, we want to spawn the session process with - the complete command line with all the new options but with the -a option and - parameter removed. Invoking a second time with the -a option will cause a loop - where we repeatedly spawn a new session process. - */ + When not using the classic command line, we want to spawn the session process with + the complete command line with all the new options but with the -a option and + parameter removed. Invoking a second time with the -a option will cause a loop + where we repeatedly spawn a new session process. + */ - do { - if (ws_optind > (argc - 1)) - break; + do { + if (ws_optind > (argc - 1)) + break; - opt = ws_getopt_long(argc, argv, optstring, long_options, NULL); + opt = ws_getopt_long(argc, argv, optstring, long_options, NULL); - switch (opt) { - case 'C': /* Configuration Profile */ - if (profile_exists(ws_optarg, FALSE)) { - set_profile_name(ws_optarg); // In Daemon Mode, we may need to do this again in the child process - } - else { - fprintf(stderr, "Configuration Profile \"%s\" does not exist\n", ws_optarg); - return -1; - } - break; + switch (opt) { + case 'C': /* Configuration Profile */ + if (profile_exists(ws_optarg, FALSE)) { + set_profile_name(ws_optarg); // In Daemon Mode, we may need to do this again in the child process + } + else { + fprintf(stderr, "Configuration Profile \"%s\" does not exist\n", ws_optarg); + return -1; + } + break; - case 'a': - fd = socket_init(ws_optarg); - if (fd == INVALID_SOCKET) - return -1; - _server_fd = fd; + case 'a': + fd = socket_init(ws_optarg); + if (fd == INVALID_SOCKET) + return -1; + _server_fd = fd; - fprintf(stderr, "Sharkd listening on: %s\n", ws_optarg); + fprintf(stderr, "Sharkd listening on: %s\n", ws_optarg); - mode = SHARKD_MODE_GOLD_DAEMON; - break; + mode = SHARKD_MODE_GOLD_DAEMON; + break; - case 'h': - print_usage(stderr); - exit(0); - break; + case 'h': + print_usage(stderr); + exit(0); + break; - case 'm': - // m is an internal-only option used when the daemon session process is created - mode = SHARKD_MODE_GOLD_CONSOLE; - break; + case 'm': + // m is an internal-only option used when the daemon session process is created + mode = SHARKD_MODE_GOLD_CONSOLE; + break; - case 'v': /* Show version and exit */ - show_version(); - exit(0); - break; + case 'v': /* Show version and exit */ + show_version(); + exit(0); + break; - default: - if (!ws_optopt) - fprintf(stderr, "This option isn't supported: %s\n", argv[ws_optind]); - fprintf(stderr, "Use sharkd -h for details of supported options\n"); - exit(0); - break; - } - } while (opt != -1); - } + default: + if (!ws_optopt) + fprintf(stderr, "This option isn't supported: %s\n", argv[ws_optind]); + fprintf(stderr, "Use sharkd -h for details of supported options\n"); + exit(0); + break; + } + } while (opt != -1); + } - if (mode == SHARKD_MODE_CLASSIC_DAEMON || mode == SHARKD_MODE_GOLD_DAEMON) - { - /* all good - try to daemonize */ + if (mode == SHARKD_MODE_CLASSIC_DAEMON || mode == SHARKD_MODE_GOLD_DAEMON) + { + /* all good - try to daemonize */ #ifndef _WIN32 - pid = fork(); - if (pid == -1) - fprintf(stderr, "cannot go to background fork() failed: %s\n", g_strerror(errno)); + pid = fork(); + if (pid == -1) + fprintf(stderr, "cannot go to background fork() failed: %s\n", g_strerror(errno)); - if (pid != 0) - { - /* parent */ - exit(0); - } + if (pid != 0) + { + /* parent */ + exit(0); + } #endif - } + } - return 0; + return 0; } int @@ -362,118 +362,105 @@ sharkd_loop(int argc _U_, char* argv[] _U_) sharkd_loop(int argc _U_, char* argv[]) #endif { - if (mode == SHARKD_MODE_CLASSIC_CONSOLE || mode == SHARKD_MODE_GOLD_CONSOLE) - { - return sharkd_session_main(mode); - } + if (mode == SHARKD_MODE_CLASSIC_CONSOLE || mode == SHARKD_MODE_GOLD_CONSOLE) + { + return sharkd_session_main(mode); + } - while (1) - { + while (1) + { #ifndef _WIN32 - pid_t pid; + pid_t pid; #else - PROCESS_INFORMATION pi; - STARTUPINFO si; - char *exename; - char command_line[2048]; + PROCESS_INFORMATION pi; + STARTUPINFO si; + char *exename; + char command_line[2048]; #endif - socket_handle_t fd; + socket_handle_t fd; - fd = accept(_server_fd, NULL, NULL); - if (fd == INVALID_SOCKET) - { - fprintf(stderr, "cannot accept(): %s\n", g_strerror(errno)); - continue; - } + fd = accept(_server_fd, NULL, NULL); + if (fd == INVALID_SOCKET) + { + fprintf(stderr, "cannot accept(): %s\n", g_strerror(errno)); + continue; + } - /* wireshark is not ready for handling multiple capture files in single process, so fork(), and handle it in separate process */ + /* wireshark is not ready for handling multiple capture files in single process, so fork(), and handle it in separate process */ #ifndef _WIN32 - pid = fork(); - if (pid == 0) - { - closesocket(_server_fd); - /* redirect stdin, stdout to socket */ - dup2(fd, 0); - dup2(fd, 1); - close(fd); + pid = fork(); + if (pid == 0) + { + closesocket(_server_fd); + /* redirect stdin, stdout to socket */ + dup2(fd, 0); + dup2(fd, 1); + close(fd); - exit(sharkd_session_main(mode)); - } + exit(sharkd_session_main(mode)); + } - if (pid == -1) - { - fprintf(stderr, "cannot fork(): %s\n", g_strerror(errno)); - } + if (pid == -1) + { + fprintf(stderr, "cannot fork(): %s\n", g_strerror(errno)); + } #else - memset(&pi, 0, sizeof(pi)); - memset(&si, 0, sizeof(si)); + memset(&pi, 0, sizeof(pi)); + memset(&si, 0, sizeof(si)); - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - si.hStdInput = (HANDLE) fd; - si.hStdOutput = (HANDLE) fd; - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.hStdInput = (HANDLE) fd; + si.hStdOutput = (HANDLE) fd; + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - exename = ws_strdup_printf("%s\\%s", get_progfile_dir(), "sharkd.exe"); + exename = ws_strdup_printf("%s\\%s", get_progfile_dir(), "sharkd.exe"); - // we need to pass in all of the command line parameters except the -a parameter - // passing in -a at this point would could a loop, each iteration of which would generate a new session process - memset(&command_line, 0, sizeof(command_line)); + // we need to pass in all of the command line parameters except the -a parameter + // passing in -a at this point would could a loop, each iteration of which would generate a new session process + memset(&command_line, 0, sizeof(command_line)); - if (mode <= SHARKD_MODE_CLASSIC_DAEMON) - { - (void) g_strlcat(command_line, "sharkd.exe -", sizeof(command_line)); - } - else - { - // The -m option used here is an internal-only option that notifies the child process that it should - // run in Gold Console mode - (void) g_strlcat(command_line, "sharkd.exe -m", sizeof(command_line)); + if (mode <= SHARKD_MODE_CLASSIC_DAEMON) + { + (void) g_strlcat(command_line, "sharkd.exe -", sizeof(command_line)); + } + else + { + // The -m option used here is an internal-only option that notifies the child process that it should + // run in Gold Console mode + (void) g_strlcat(command_line, "sharkd.exe -m", sizeof(command_line)); - for (int i = 1; i < argc; i++) - { - if ( - !g_ascii_strncasecmp(argv[i], "-a", (guint)strlen(argv[i])) - || !g_ascii_strncasecmp(argv[i], "--api", (guint)strlen(argv[i])) - ) - { - i++; // skip the socket details - } - else - { - (void) g_strlcat(command_line, " ", sizeof(command_line)); - (void) g_strlcat(command_line, argv[i], sizeof(command_line)); - } - } - } + for (int i = 1; i < argc; i++) + { + if ( + !g_ascii_strncasecmp(argv[i], "-a", (guint)strlen(argv[i])) + || !g_ascii_strncasecmp(argv[i], "--api", (guint)strlen(argv[i])) + ) + { + i++; // skip the socket details + } + else + { + (void) g_strlcat(command_line, " ", sizeof(command_line)); + (void) g_strlcat(command_line, argv[i], sizeof(command_line)); + } + } + } - if (!win32_create_process(exename, command_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) - { - fprintf(stderr, "win32_create_process(%s) failed\n", exename); - } - else - { - CloseHandle(pi.hThread); - } + if (!win32_create_process(exename, command_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) + { + fprintf(stderr, "win32_create_process(%s) failed\n", exename); + } + else + { + CloseHandle(pi.hThread); + } - g_free(exename); + g_free(exename); #endif - closesocket(fd); - } - return 0; + closesocket(fd); + } + return 0; } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 8 - * tab-width: 8 - * indent-tabs-mode: t - * End: - * - * vi: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: - */ diff --git a/sharkd_session.c b/sharkd_session.c index 5938824e44..1a5fdaa57a 100644 --- a/sharkd_session.c +++ b/sharkd_session.c @@ -77,7 +77,7 @@ struct sharkd_filter_item { - guint8 *filtered; /* can be NULL if all frames are matching for given filter. */ + guint8 *filtered; /* can be NULL if all frames are matching for given filter. */ }; static GHashTable *filter_table = NULL; @@ -91,234 +91,234 @@ static json_dumper dumper = {0}; static const char * json_find_attr(const char *buf, const jsmntok_t *tokens, int count, const char *attr) { - int i; + int i; - for (i = 0; i < count; i += 2) - { - const char *tok_attr = &buf[tokens[i + 0].start]; - const char *tok_value = &buf[tokens[i + 1].start]; + for (i = 0; i < count; i += 2) + { + const char *tok_attr = &buf[tokens[i + 0].start]; + const char *tok_value = &buf[tokens[i + 1].start]; - if (!strcmp(tok_attr, attr)) - return tok_value; - } + if (!strcmp(tok_attr, attr)) + return tok_value; + } - return NULL; + return NULL; } static void json_print_base64(const guint8 *data, size_t len) { - json_dumper_begin_base64(&dumper); - json_dumper_write_base64(&dumper, data, len); - json_dumper_end_base64(&dumper); + json_dumper_begin_base64(&dumper); + json_dumper_write_base64(&dumper, data, len); + json_dumper_end_base64(&dumper); } static void G_GNUC_PRINTF(2, 3) sharkd_json_value_anyf(const char *key, const char *format, ...) { - if (key) - json_dumper_set_member_name(&dumper, key); + if (key) + json_dumper_set_member_name(&dumper, key); - if (format) { - va_list ap; - va_start(ap, format); - json_dumper_value_va_list(&dumper, format, ap); - va_end(ap); - } + if (format) { + va_list ap; + va_start(ap, format); + json_dumper_value_va_list(&dumper, format, ap); + va_end(ap); + } } static void sharkd_json_value_string(const char *key, const char *str) { - if (key) - json_dumper_set_member_name(&dumper, key); - if (str) - json_dumper_value_string(&dumper, str); + if (key) + json_dumper_set_member_name(&dumper, key); + if (str) + json_dumper_value_string(&dumper, str); } static void sharkd_json_value_base64(const char *key, const guint8 *data, size_t len) { - if (key) - json_dumper_set_member_name(&dumper, key); - json_print_base64(data, len); + if (key) + json_dumper_set_member_name(&dumper, key); + json_print_base64(data, len); } static void G_GNUC_PRINTF(2, 3) sharkd_json_value_stringf(const char *key, const char *format, ...) { - if (key) - json_dumper_set_member_name(&dumper, key); + if (key) + json_dumper_set_member_name(&dumper, key); - if (format) { - va_list ap; - va_start(ap, format); - char* sformat = ws_strdup_printf("\"%s\"", format); - json_dumper_value_va_list(&dumper, sformat, ap); - g_free(sformat); - va_end(ap); - } + if (format) { + va_list ap; + va_start(ap, format); + char* sformat = ws_strdup_printf("\"%s\"", format); + json_dumper_value_va_list(&dumper, sformat, ap); + g_free(sformat); + va_end(ap); + } } static void sharkd_json_array_open(const char *key) { - if (key) - json_dumper_set_member_name(&dumper, key); - json_dumper_begin_array(&dumper); + if (key) + json_dumper_set_member_name(&dumper, key); + json_dumper_begin_array(&dumper); } static void sharkd_json_array_close(void) { - json_dumper_end_array(&dumper); + json_dumper_end_array(&dumper); } static void sharkd_json_response_open(guint32 id) { - json_dumper_begin_object(&dumper); // start the message - sharkd_json_value_string("jsonrpc", "2.0"); - sharkd_json_value_anyf("id", "%d", id); + json_dumper_begin_object(&dumper); // start the message + sharkd_json_value_string("jsonrpc", "2.0"); + sharkd_json_value_anyf("id", "%d", id); } static void sharkd_json_response_close(void) { - json_dumper_finish(&dumper); + json_dumper_finish(&dumper); - /* - * We do an explicit fflush after every line, because - * we want output to be written to the socket as soon - * as the line is complete. - * - * The stream is fully-buffered by default, so it's - * only flushed when the buffer fills or the FILE * - * is closed. On UN*X, we could set it to be line - * buffered, but the MSVC standard I/O routines don't - * support line buffering - they only support *byte* - * buffering, doing a write for every byte written, - * which is too inefficient, and full buffering, - * which is what you get if you request line buffering. - */ - fflush(stdout); + /* + * We do an explicit fflush after every line, because + * we want output to be written to the socket as soon + * as the line is complete. + * + * The stream is fully-buffered by default, so it's + * only flushed when the buffer fills or the FILE * + * is closed. On UN*X, we could set it to be line + * buffered, but the MSVC standard I/O routines don't + * support line buffering - they only support *byte* + * buffering, doing a write for every byte written, + * which is too inefficient, and full buffering, + * which is what you get if you request line buffering. + */ + fflush(stdout); } static void sharkd_json_result_prologue(guint32 id) { - sharkd_json_response_open(id); - sharkd_json_value_anyf("result", NULL); - json_dumper_begin_object(&dumper); // start the result object + sharkd_json_response_open(id); + sharkd_json_value_anyf("result", NULL); + json_dumper_begin_object(&dumper); // start the result object } static void sharkd_json_result_epilogue(void) { - json_dumper_end_object(&dumper); // end the result object - json_dumper_end_object(&dumper); // end the message - sharkd_json_response_close(); + json_dumper_end_object(&dumper); // end the result object + json_dumper_end_object(&dumper); // end the message + sharkd_json_response_close(); } static void sharkd_json_result_array_prologue(guint32 id) { - sharkd_json_response_open(id); - sharkd_json_array_open("result"); // start the result array + sharkd_json_response_open(id); + sharkd_json_array_open("result"); // start the result array } static void sharkd_json_result_array_epilogue(void) { - sharkd_json_array_close(); // end of result array - json_dumper_end_object(&dumper); // end the message - sharkd_json_response_close(); + sharkd_json_array_close(); // end of result array + json_dumper_end_object(&dumper); // end the message + sharkd_json_response_close(); } static void sharkd_json_simple_ok(guint32 id) { - sharkd_json_result_prologue(id); - sharkd_json_value_string("status", "OK"); - sharkd_json_result_epilogue(); + sharkd_json_result_prologue(id); + sharkd_json_value_string("status", "OK"); + sharkd_json_result_epilogue(); } static void sharkd_json_warning(guint32 id, char *warning) { - sharkd_json_result_prologue(id); - sharkd_json_value_string("status", "Warning"); - sharkd_json_value_string("warning", warning); - sharkd_json_result_epilogue(); + sharkd_json_result_prologue(id); + sharkd_json_value_string("status", "Warning"); + sharkd_json_value_string("warning", warning); + sharkd_json_result_epilogue(); } static void G_GNUC_PRINTF(4, 5) sharkd_json_error(guint32 id, int code, char* data, char* format, ...) { - sharkd_json_response_open(id); - sharkd_json_value_anyf("error", NULL); - json_dumper_begin_object(&dumper); - sharkd_json_value_anyf("code", "%d", code); + sharkd_json_response_open(id); + sharkd_json_value_anyf("error", NULL); + json_dumper_begin_object(&dumper); + sharkd_json_value_anyf("code", "%d", code); - if (format) - { - // format the text message - va_list args; + if (format) + { + // format the text message + va_list args; - va_start(args, format); - char *error_msg = ws_strdup_vprintf(format, args); - va_end(args); + va_start(args, format); + char *error_msg = ws_strdup_vprintf(format, args); + va_end(args); - sharkd_json_value_string("message", error_msg); + sharkd_json_value_string("message", error_msg); - g_free(error_msg); - } + g_free(error_msg); + } - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); - if (data) - sharkd_json_value_string("data", data); + if (data) + sharkd_json_value_string("data", data); - json_dumper_end_object(&dumper); - sharkd_json_response_close(); + json_dumper_end_object(&dumper); + sharkd_json_response_close(); } static gboolean is_param_match(const char *param_in, const char *valid_param) { - char* ptr; + char* ptr; - if ((ptr = g_strrstr(valid_param, "*"))) - { - size_t prefix_len = ptr - valid_param; - return !strncmp(param_in, valid_param, prefix_len); - } - else - return !strcmp(param_in, valid_param); + if ((ptr = g_strrstr(valid_param, "*"))) + { + size_t prefix_len = ptr - valid_param; + return !strncmp(param_in, valid_param, prefix_len); + } + else + return !strcmp(param_in, valid_param); } /* -* json_prep does four things: -* -* 1. check the syntax of the root and parameter members -* 2. tokenize the names and values by zero terminating them -* 3. unescape the names and values -* 4. extracts and saves the rpcid -* - we have to do it here as it's needed for the error messages -* -* The objective is to minimise the validation work in the functions -* that process each called method. -* -* This gets a little messy as the JSON parser creates a flat list -* of all members rather than create a tree. -*/ + * json_prep does four things: + * + * 1. check the syntax of the root and parameter members + * 2. tokenize the names and values by zero terminating them + * 3. unescape the names and values + * 4. extracts and saves the rpcid + * - we have to do it here as it's needed for the error messages + * + * The objective is to minimise the validation work in the functions + * that process each called method. + * + * This gets a little messy as the JSON parser creates a flat list + * of all members rather than create a tree. + */ static gboolean json_prep(char* buf, const jsmntok_t* tokens, int count) { - int i; - char* method = NULL; - char* attr_name = NULL; - char* attr_value = NULL; + int i; + char* method = NULL; + char* attr_name = NULL; + char* attr_value = NULL; #define SHARKD_JSON_ANY 0 #define SHARKD_JSON_STRING 1 @@ -330,568 +330,568 @@ json_prep(char* buf, const jsmntok_t* tokens, int count) #define SHARKD_JSON_BOOLEAN 7 #define SHARKD_ARRAY_END 99 - struct member_attribute { - const char* parent_ctx; - const char* name; - int level; - jsmntype_t type; - int value_type; - gboolean is_mandatory; - }; + struct member_attribute { + const char* parent_ctx; + const char* name; + int level; + jsmntype_t type; + int value_type; + gboolean is_mandatory; + }; #define MANDATORY TRUE #define OPTIONAL FALSE - /* - * The member attribute structure is key to the syntax checking. The - * array contains all of the root level (1) member names, the data - * types permissable for the value and a boolean that indicates whether - * or not the member is mandatory. - * - * Once we get into the next layer (2) of the json tree, we need to check - * params member names and data types dependent in the context of the method - * (parent_ctx). - */ + /* + * The member attribute structure is key to the syntax checking. The + * array contains all of the root level (1) member names, the data + * types permissable for the value and a boolean that indicates whether + * or not the member is mandatory. + * + * Once we get into the next layer (2) of the json tree, we need to check + * params member names and data types dependent in the context of the method + * (parent_ctx). + */ - struct member_attribute name_array[] = { - // Root members - {NULL, "jsonrpc", 1, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, - {NULL, "userid", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {NULL, "id", 1, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, MANDATORY}, - {NULL, "method", 1, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, - {NULL, "params", 1, JSMN_OBJECT, SHARKD_JSON_OBJECT, OPTIONAL}, + struct member_attribute name_array[] = { + // Root members + {NULL, "jsonrpc", 1, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, + {NULL, "userid", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {NULL, "id", 1, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, MANDATORY}, + {NULL, "method", 1, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, + {NULL, "params", 1, JSMN_OBJECT, SHARKD_JSON_OBJECT, OPTIONAL}, - // Valid methods - {"method", "analyse", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "bye", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "check", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "complete", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "download", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "dumpconf", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "follow", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "frame", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "frames", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "info", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "intervals", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "iograph", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "load", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "setcomment", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "setconf", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "status", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"method", "tap", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + // Valid methods + {"method", "analyse", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "bye", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "check", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "complete", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "download", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "dumpconf", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "follow", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "frame", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "frames", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "info", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "intervals", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "iograph", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "load", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "setcomment", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "setconf", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "status", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"method", "tap", 1, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - // Parameters and their method context - {"check", "field", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"check", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"complete", "field", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"complete", "pref", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"download", "token", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"dumpconf", "pref", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"follow", "follow", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, - {"follow", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, - {"frame", "frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, MANDATORY}, - {"frame", "proto", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, - {"frame", "ref_frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, - {"frame", "prev_frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, - {"frame", "columns", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, - {"frame", "color", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, - {"frame", "bytes", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, - {"frame", "hidden", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, - {"frames", "column*", 2, JSMN_UNDEFINED, SHARKD_JSON_ANY, OPTIONAL}, - {"frames", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"frames", "skip", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, OPTIONAL}, - {"frames", "limit", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, OPTIONAL}, - {"frames", "refs", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"intervals", "interval", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, OPTIONAL}, - {"intervals", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "interval", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, OPTIONAL}, - {"iograph", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "graph0", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, - {"iograph", "graph1", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "graph2", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "graph3", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "graph4", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "graph5", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "graph6", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "graph7", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "graph8", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "graph9", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter0", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter1", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter2", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter3", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter4", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter5", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter6", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter7", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter8", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"iograph", "filter9", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"load", "file", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, - {"setcomment", "frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, MANDATORY}, - {"setcomment", "comment", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"setconf", "name", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, - {"setconf", "value", 2, JSMN_UNDEFINED, SHARKD_JSON_ANY, MANDATORY}, - {"tap", "tap0", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, - {"tap", "tap1", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap2", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap3", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap4", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap5", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap6", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap7", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap8", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap9", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap10", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap11", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap12", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap13", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap14", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - {"tap", "tap15", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + // Parameters and their method context + {"check", "field", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"check", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"complete", "field", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"complete", "pref", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"download", "token", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"dumpconf", "pref", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"follow", "follow", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, + {"follow", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, + {"frame", "frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, MANDATORY}, + {"frame", "proto", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, + {"frame", "ref_frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, + {"frame", "prev_frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, + {"frame", "columns", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, + {"frame", "color", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, + {"frame", "bytes", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, + {"frame", "hidden", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN, OPTIONAL}, + {"frames", "column*", 2, JSMN_UNDEFINED, SHARKD_JSON_ANY, OPTIONAL}, + {"frames", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"frames", "skip", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, OPTIONAL}, + {"frames", "limit", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, OPTIONAL}, + {"frames", "refs", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"intervals", "interval", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, OPTIONAL}, + {"intervals", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "interval", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, OPTIONAL}, + {"iograph", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "graph0", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, + {"iograph", "graph1", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "graph2", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "graph3", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "graph4", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "graph5", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "graph6", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "graph7", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "graph8", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "graph9", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter0", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter1", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter2", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter3", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter4", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter5", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter6", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter7", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter8", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"iograph", "filter9", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"load", "file", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, + {"setcomment", "frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER, MANDATORY}, + {"setcomment", "comment", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"setconf", "name", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, + {"setconf", "value", 2, JSMN_UNDEFINED, SHARKD_JSON_ANY, MANDATORY}, + {"tap", "tap0", 2, JSMN_STRING, SHARKD_JSON_STRING, MANDATORY}, + {"tap", "tap1", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap2", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap3", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap4", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap5", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap6", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap7", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap8", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap9", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap10", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap11", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap12", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap13", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap14", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, + {"tap", "tap15", 2, JSMN_STRING, SHARKD_JSON_STRING, OPTIONAL}, - // End of the name_array - {NULL, NULL, 0, JSMN_STRING, SHARKD_ARRAY_END, OPTIONAL}, - }; + // End of the name_array + {NULL, NULL, 0, JSMN_STRING, SHARKD_ARRAY_END, OPTIONAL}, + }; - rpcid = 0; + rpcid = 0; - /* sanity check, and split strings */ - if (count < 1 || tokens[0].type != JSMN_OBJECT) - { - sharkd_json_error( - rpcid, -32600, NULL, - "The request must an object" - ); - return FALSE; - } + /* sanity check, and split strings */ + if (count < 1 || tokens[0].type != JSMN_OBJECT) + { + sharkd_json_error( + rpcid, -32600, NULL, + "The request must an object" + ); + return FALSE; + } - /* don't need [0] token */ - tokens++; - count--; + /* don't need [0] token */ + tokens++; + count--; - if (count & 1) - { - sharkd_json_error( - rpcid, -32600, NULL, - "The request must contain name/value pairs" - ); - return FALSE; - } + if (count & 1) + { + sharkd_json_error( + rpcid, -32600, NULL, + "The request must contain name/value pairs" + ); + return FALSE; + } - for (i = 0; i < count; i += 2) - { - if (tokens[i].type != JSMN_STRING) - { - sharkd_json_error( - rpcid, -32600, NULL, - "Member names must be a string - member %d is not string", (i / 2) + 1 - ); - return FALSE; - } + for (i = 0; i < count; i += 2) + { + if (tokens[i].type != JSMN_STRING) + { + sharkd_json_error( + rpcid, -32600, NULL, + "Member names must be a string - member %d is not string", (i / 2) + 1 + ); + return FALSE; + } - buf[tokens[i + 0].end] = '\0'; - buf[tokens[i + 1].end] = '\0'; + buf[tokens[i + 0].end] = '\0'; + buf[tokens[i + 1].end] = '\0'; - attr_name = &buf[tokens[i + 0].start]; - attr_value = &buf[tokens[i + 1].start]; + attr_name = &buf[tokens[i + 0].start]; + attr_value = &buf[tokens[i + 1].start]; - // we must get the id as soon as possible so that it's available in all future error messages - if (!strcmp(attr_name, "id")) - { - if (!ws_strtou32(attr_value, NULL, &rpcid)) - { - sharkd_json_error( - rpcid, -32600, NULL, - "The id value must be a positive integer" - ); - return FALSE; - } - } + // we must get the id as soon as possible so that it's available in all future error messages + if (!strcmp(attr_name, "id")) + { + if (!ws_strtou32(attr_value, NULL, &rpcid)) + { + sharkd_json_error( + rpcid, -32600, NULL, + "The id value must be a positive integer" + ); + return FALSE; + } + } - if (!strcmp(attr_name, "jsonrpc")) - { - if (strcmp(&buf[tokens[i + 1].start], "2.0")) - { - sharkd_json_error( - rpcid, -32600, NULL, - "Only JSON %s is supported", "2.0" - ); - return FALSE; - } - } + if (!strcmp(attr_name, "jsonrpc")) + { + if (strcmp(&buf[tokens[i + 1].start], "2.0")) + { + sharkd_json_error( + rpcid, -32600, NULL, + "Only JSON %s is supported", "2.0" + ); + return FALSE; + } + } - /* unescape only value, as keys are simple strings */ - if (tokens[i + 1].type == JSMN_STRING && !json_decode_string_inplace(attr_value)) - { - sharkd_json_error( - rpcid, -32600, NULL, - "Cannot unescape the value string of member %d", (i / 2) + 1 - ); - return FALSE; - } + /* unescape only value, as keys are simple strings */ + if (tokens[i + 1].type == JSMN_STRING && !json_decode_string_inplace(attr_value)) + { + sharkd_json_error( + rpcid, -32600, NULL, + "Cannot unescape the value string of member %d", (i / 2) + 1 + ); + return FALSE; + } - /* Confirm that the member is valid */ - gboolean match = FALSE; + /* Confirm that the member is valid */ + gboolean match = FALSE; - // We need to check root members (level 1) and parameters (level 2), hence the for loop. + // We need to check root members (level 1) and parameters (level 2), hence the for loop. - for (int level = 1; level < 3; level++) - { - size_t j = 0; + for (int level = 1; level < 3; level++) + { + size_t j = 0; - while (name_array[j].value_type != SHARKD_ARRAY_END) // iterate through the array until we hit the end - { - if (is_param_match(attr_name, name_array[j].name) && name_array[j].level == level) - { - // We need to be sure the match is in the correct context - // i.e. is this a match for a root member (level 1) or for a parameter (level 2). + while (name_array[j].value_type != SHARKD_ARRAY_END) // iterate through the array until we hit the end + { + if (is_param_match(attr_name, name_array[j].name) && name_array[j].level == level) + { + // We need to be sure the match is in the correct context + // i.e. is this a match for a root member (level 1) or for a parameter (level 2). - if (level == 1) - { - // need to guard against a parameter name matching a method name - if (method) - { - if (name_array[j].parent_ctx) - { - j++; - continue; - } + if (level == 1) + { + // need to guard against a parameter name matching a method name + if (method) + { + if (name_array[j].parent_ctx) + { + j++; + continue; + } - if (!strcmp(method, &buf[tokens[i + 0].start])) - { - j++; - continue; - } - } + if (!strcmp(method, &buf[tokens[i + 0].start])) + { + j++; + continue; + } + } - match = TRUE; - } - else if (method) - { - if (level == 2 && !strcmp(name_array[j].parent_ctx, method)) - match = TRUE; - else - { - j++; - continue; - } - } - else - { - j++; - continue; - } + match = TRUE; + } + else if (method) + { + if (level == 2 && !strcmp(name_array[j].parent_ctx, method)) + match = TRUE; + else + { + j++; + continue; + } + } + else + { + j++; + continue; + } - // The match looks good, let's now check the data types + // The match looks good, let's now check the data types - if (tokens[i + 1].type != name_array[j].type && name_array[j].type != SHARKD_JSON_ANY) - { - sharkd_json_error( - rpcid, -32600, NULL, - "The data type for member %s is not a valid", attr_name - ); - return FALSE; - } - else if (name_array[j].type == JSMN_PRIMITIVE && name_array[j].value_type == SHARKD_JSON_UINTEGER) - { - guint32 temp; - if (!ws_strtou32(attr_value, NULL, &temp) || temp <= 0) - { - sharkd_json_error( - rpcid, -32600, NULL, - "The value for %s must be a positive integer", name_array[j].name - ); - return FALSE; - } - } - else if (name_array[j].type == JSMN_PRIMITIVE && name_array[j].value_type == SHARKD_JSON_BOOLEAN) - { - if (strcmp(attr_value, "true") && strcmp(attr_value, "false")) - { - sharkd_json_error( - rpcid, -32600, NULL, - "The value for %s must be a boolean (true or false)", name_array[j].name - ); - return FALSE; - } + if (tokens[i + 1].type != name_array[j].type && name_array[j].type != SHARKD_JSON_ANY) + { + sharkd_json_error( + rpcid, -32600, NULL, + "The data type for member %s is not a valid", attr_name + ); + return FALSE; + } + else if (name_array[j].type == JSMN_PRIMITIVE && name_array[j].value_type == SHARKD_JSON_UINTEGER) + { + guint32 temp; + if (!ws_strtou32(attr_value, NULL, &temp) || temp <= 0) + { + sharkd_json_error( + rpcid, -32600, NULL, + "The value for %s must be a positive integer", name_array[j].name + ); + return FALSE; + } + } + else if (name_array[j].type == JSMN_PRIMITIVE && name_array[j].value_type == SHARKD_JSON_BOOLEAN) + { + if (strcmp(attr_value, "true") && strcmp(attr_value, "false")) + { + sharkd_json_error( + rpcid, -32600, NULL, + "The value for %s must be a boolean (true or false)", name_array[j].name + ); + return FALSE; + } - } - break; // looks like a valid match - } - j++; - } + } + break; // looks like a valid match + } + j++; + } - if (!strcmp(attr_name, "method")) - { - int k = 0; // name array index - // check that the request method is good - while (name_array[k].value_type != SHARKD_ARRAY_END) - { - if (name_array[k].parent_ctx) - { - if (!strcmp(attr_value, name_array[k].name) && !strcmp(name_array[k].parent_ctx, "method")) - method = attr_value; // the method is valid - } + if (!strcmp(attr_name, "method")) + { + int k = 0; // name array index + // check that the request method is good + while (name_array[k].value_type != SHARKD_ARRAY_END) + { + if (name_array[k].parent_ctx) + { + if (!strcmp(attr_value, name_array[k].name) && !strcmp(name_array[k].parent_ctx, "method")) + method = attr_value; // the method is valid + } - k++; - } + k++; + } - if (!method) - { - sharkd_json_error( - rpcid, -32601, NULL, - "The method %s is not supported", attr_value - ); - return FALSE; - } - } - } + if (!method) + { + sharkd_json_error( + rpcid, -32601, NULL, + "The method %s is not supported", attr_value + ); + return FALSE; + } + } + } - if (!match) - { - sharkd_json_error( - rpcid, -32600, NULL, - "%s is not a valid member name", attr_name - ); - return FALSE; - } - } + if (!match) + { + sharkd_json_error( + rpcid, -32600, NULL, + "%s is not a valid member name", attr_name + ); + return FALSE; + } + } - /* check for mandatory members */ - size_t j = 0; + /* check for mandatory members */ + size_t j = 0; - while (name_array[j].value_type != SHARKD_ARRAY_END) - { - if (name_array[j].is_mandatory && name_array[j].level == 1) - { - if (!json_find_attr(buf, tokens, count, name_array[j].name)) - { - sharkd_json_error( - rpcid, -32600, NULL, - "Mandatory member %s is missing", name_array[j].name - ); - return FALSE; - } - } - j++; - } + while (name_array[j].value_type != SHARKD_ARRAY_END) + { + if (name_array[j].is_mandatory && name_array[j].level == 1) + { + if (!json_find_attr(buf, tokens, count, name_array[j].name)) + { + sharkd_json_error( + rpcid, -32600, NULL, + "Mandatory member %s is missing", name_array[j].name + ); + return FALSE; + } + } + j++; + } - // check that the current request contains the mandatory parameters - j = 0; + // check that the current request contains the mandatory parameters + j = 0; - while (name_array[j].value_type != SHARKD_ARRAY_END) - { - if (name_array[j].is_mandatory && name_array[j].level == 2 && !strcmp(method, name_array[j].parent_ctx)) - { - if (!json_find_attr(buf, tokens, count, name_array[j].name)) - { - sharkd_json_error( - rpcid, -32600, NULL, - "Mandatory parameter %s is missing", name_array[j].name - ); - return FALSE; - } - } - j++; - } + while (name_array[j].value_type != SHARKD_ARRAY_END) + { + if (name_array[j].is_mandatory && name_array[j].level == 2 && !strcmp(method, name_array[j].parent_ctx)) + { + if (!json_find_attr(buf, tokens, count, name_array[j].name)) + { + sharkd_json_error( + rpcid, -32600, NULL, + "Mandatory parameter %s is missing", name_array[j].name + ); + return FALSE; + } + } + j++; + } - // check that the parameters for the current request are valid for the method and that the data type for the value is valid + // check that the parameters for the current request are valid for the method and that the data type for the value is valid - return TRUE; + return TRUE; } static void sharkd_session_filter_free(gpointer data) { - struct sharkd_filter_item *l = (struct sharkd_filter_item *) data; + struct sharkd_filter_item *l = (struct sharkd_filter_item *) data; - g_free(l->filtered); - g_free(l); + g_free(l->filtered); + g_free(l); } static const struct sharkd_filter_item * sharkd_session_filter_data(const char *filter) { - struct sharkd_filter_item *l; + struct sharkd_filter_item *l; - l = (struct sharkd_filter_item *) g_hash_table_lookup(filter_table, filter); - if (!l) - { - guint8 *filtered = NULL; + l = (struct sharkd_filter_item *) g_hash_table_lookup(filter_table, filter); + if (!l) + { + guint8 *filtered = NULL; - int ret = sharkd_filter(filter, &filtered); + int ret = sharkd_filter(filter, &filtered); - if (ret == -1) - return NULL; + if (ret == -1) + return NULL; - l = g_new(struct sharkd_filter_item, 1); - l->filtered = filtered; + l = g_new(struct sharkd_filter_item, 1); + l->filtered = filtered; - g_hash_table_insert(filter_table, g_strdup(filter), l); - } + g_hash_table_insert(filter_table, g_strdup(filter), l); + } - return l; + return l; } static gboolean sharkd_rtp_match_init(rtpstream_id_t *id, const char *init_str) { - gboolean ret = FALSE; - char **arr; - guint32 tmp_addr_src, tmp_addr_dst; - address tmp_src_addr, tmp_dst_addr; + gboolean ret = FALSE; + char **arr; + guint32 tmp_addr_src, tmp_addr_dst; + address tmp_src_addr, tmp_dst_addr; - memset(id, 0, sizeof(*id)); + memset(id, 0, sizeof(*id)); - arr = g_strsplit(init_str, "_", 7); /* pass larger value, so we'll catch incorrect input :) */ - if (g_strv_length(arr) != 5) - goto fail; + arr = g_strsplit(init_str, "_", 7); /* pass larger value, so we'll catch incorrect input :) */ + if (g_strv_length(arr) != 5) + goto fail; - /* TODO, for now only IPv4 */ - if (!get_host_ipaddr(arr[0], &tmp_addr_src)) - goto fail; + /* TODO, for now only IPv4 */ + if (!get_host_ipaddr(arr[0], &tmp_addr_src)) + goto fail; - if (!ws_strtou16(arr[1], NULL, &id->src_port)) - goto fail; + if (!ws_strtou16(arr[1], NULL, &id->src_port)) + goto fail; - if (!get_host_ipaddr(arr[2], &tmp_addr_dst)) - goto fail; + if (!get_host_ipaddr(arr[2], &tmp_addr_dst)) + goto fail; - if (!ws_strtou16(arr[3], NULL, &id->dst_port)) - goto fail; + if (!ws_strtou16(arr[3], NULL, &id->dst_port)) + goto fail; - if (!ws_hexstrtou32(arr[4], NULL, &id->ssrc)) - goto fail; + if (!ws_hexstrtou32(arr[4], NULL, &id->ssrc)) + goto fail; - set_address(&tmp_src_addr, AT_IPv4, 4, &tmp_addr_src); - copy_address(&id->src_addr, &tmp_src_addr); - set_address(&tmp_dst_addr, AT_IPv4, 4, &tmp_addr_dst); - copy_address(&id->dst_addr, &tmp_dst_addr); + set_address(&tmp_src_addr, AT_IPv4, 4, &tmp_addr_src); + copy_address(&id->src_addr, &tmp_src_addr); + set_address(&tmp_dst_addr, AT_IPv4, 4, &tmp_addr_dst); + copy_address(&id->dst_addr, &tmp_dst_addr); - ret = TRUE; + ret = TRUE; fail: - g_strfreev(arr); - return ret; + g_strfreev(arr); + return ret; } static gboolean sharkd_session_process_info_nstat_cb(const void *key, void *value, void *userdata _U_) { - stat_tap_table_ui *stat_tap = (stat_tap_table_ui *) value; + stat_tap_table_ui *stat_tap = (stat_tap_table_ui *) value; - json_dumper_begin_object(&dumper); - sharkd_json_value_string("name", stat_tap->title); - sharkd_json_value_stringf("tap", "nstat:%s", (const char *) key); - json_dumper_end_object(&dumper); + json_dumper_begin_object(&dumper); + sharkd_json_value_string("name", stat_tap->title); + sharkd_json_value_stringf("tap", "nstat:%s", (const char *) key); + json_dumper_end_object(&dumper); - return FALSE; + return FALSE; } static gboolean sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata _U_) { - struct register_ct *table = (struct register_ct *) value; + struct register_ct *table = (struct register_ct *) value; - const char *label = (const char *) key; + const char *label = (const char *) key; - if (get_conversation_packet_func(table)) - { - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("name", "Conversation List/%s", label); - sharkd_json_value_stringf("tap", "conv:%s", label); - json_dumper_end_object(&dumper); - } + if (get_conversation_packet_func(table)) + { + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("name", "Conversation List/%s", label); + sharkd_json_value_stringf("tap", "conv:%s", label); + json_dumper_end_object(&dumper); + } - if (get_hostlist_packet_func(table)) - { - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("name", "Endpoint/%s", label); - sharkd_json_value_stringf("tap", "endpt:%s", label); - json_dumper_end_object(&dumper); - } - return FALSE; + if (get_hostlist_packet_func(table)) + { + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("name", "Endpoint/%s", label); + sharkd_json_value_stringf("tap", "endpt:%s", label); + json_dumper_end_object(&dumper); + } + return FALSE; } static gboolean sharkd_session_seq_analysis_cb(const void *key, void *value, void *userdata _U_) { - register_analysis_t *analysis = (register_analysis_t *) value; + register_analysis_t *analysis = (register_analysis_t *) value; - json_dumper_begin_object(&dumper); - sharkd_json_value_string("name", sequence_analysis_get_ui_name(analysis)); - sharkd_json_value_stringf("tap", "seqa:%s", (const char *) key); - json_dumper_end_object(&dumper); + json_dumper_begin_object(&dumper); + sharkd_json_value_string("name", sequence_analysis_get_ui_name(analysis)); + sharkd_json_value_stringf("tap", "seqa:%s", (const char *) key); + json_dumper_end_object(&dumper); - return FALSE; + return FALSE; } static gboolean sharkd_export_object_visit_cb(const void *key _U_, void *value, void *user_data _U_) { - register_eo_t *eo = (register_eo_t *) value; + register_eo_t *eo = (register_eo_t *) value; - const int proto_id = get_eo_proto_id(eo); - const char *filter = proto_get_protocol_filter_name(proto_id); - const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); + const int proto_id = get_eo_proto_id(eo); + const char *filter = proto_get_protocol_filter_name(proto_id); + const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("name", "Export Object/%s", label); - sharkd_json_value_stringf("tap", "eo:%s", filter); - json_dumper_end_object(&dumper); + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("name", "Export Object/%s", label); + sharkd_json_value_stringf("tap", "eo:%s", filter); + json_dumper_end_object(&dumper); - return FALSE; + return FALSE; } static gboolean sharkd_srt_visit_cb(const void *key _U_, void *value, void *user_data _U_) { - register_srt_t *srt = (register_srt_t *) value; + register_srt_t *srt = (register_srt_t *) value; - const int proto_id = get_srt_proto_id(srt); - const char *filter = proto_get_protocol_filter_name(proto_id); - const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); + const int proto_id = get_srt_proto_id(srt); + const char *filter = proto_get_protocol_filter_name(proto_id); + const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("name", "Service Response Time/%s", label); - sharkd_json_value_stringf("tap", "srt:%s", filter); - json_dumper_end_object(&dumper); + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("name", "Service Response Time/%s", label); + sharkd_json_value_stringf("tap", "srt:%s", filter); + json_dumper_end_object(&dumper); - return FALSE; + return FALSE; } static gboolean sharkd_rtd_visit_cb(const void *key _U_, void *value, void *user_data _U_) { - register_rtd_t *rtd = (register_rtd_t *) value; + register_rtd_t *rtd = (register_rtd_t *) value; - const int proto_id = get_rtd_proto_id(rtd); - const char *filter = proto_get_protocol_filter_name(proto_id); - const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); + const int proto_id = get_rtd_proto_id(rtd); + const char *filter = proto_get_protocol_filter_name(proto_id); + const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("name", "Response Time Delay/%s", label); - sharkd_json_value_stringf("tap", "rtd:%s", filter); - json_dumper_end_object(&dumper); + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("name", "Response Time Delay/%s", label); + sharkd_json_value_stringf("tap", "rtd:%s", filter); + json_dumper_end_object(&dumper); - return FALSE; + return FALSE; } static gboolean sharkd_follower_visit_cb(const void *key _U_, void *value, void *user_data _U_) { - register_follow_t *follower = (register_follow_t *) value; + register_follow_t *follower = (register_follow_t *) value; - const int proto_id = get_follow_proto_id(follower); - const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); - const char *filter = label; /* correct: get_follow_by_name() is registered by short name */ + const int proto_id = get_follow_proto_id(follower); + const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); + const char *filter = label; /* correct: get_follow_by_name() is registered by short name */ - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("name", "Follow/%s", label); - sharkd_json_value_stringf("tap", "follow:%s", filter); - json_dumper_end_object(&dumper); + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("name", "Follow/%s", label); + sharkd_json_value_stringf("tap", "follow:%s", filter); + json_dumper_end_object(&dumper); - return FALSE; + return FALSE; } /** @@ -948,99 +948,99 @@ sharkd_follower_visit_cb(const void *key _U_, void *value, void *user_data _U_) static void sharkd_session_process_info(void) { - int i; + int i; - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - sharkd_json_array_open("columns"); - for (i = 0; i < NUM_COL_FMTS; i++) - { - const char *col_format = col_format_to_string(i); - const char *col_descr = col_format_desc(i); + sharkd_json_array_open("columns"); + for (i = 0; i < NUM_COL_FMTS; i++) + { + const char *col_format = col_format_to_string(i); + const char *col_descr = col_format_desc(i); - json_dumper_begin_object(&dumper); - sharkd_json_value_string("name", col_descr); - sharkd_json_value_string("format", col_format); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_begin_object(&dumper); + sharkd_json_value_string("name", col_descr); + sharkd_json_value_string("format", col_format); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - sharkd_json_array_open("stats"); - { - GList *cfg_list = stats_tree_get_cfg_list(); - GList *l; + sharkd_json_array_open("stats"); + { + GList *cfg_list = stats_tree_get_cfg_list(); + GList *l; - for (l = cfg_list; l; l = l->next) - { - stats_tree_cfg *cfg = (stats_tree_cfg *) l->data; + for (l = cfg_list; l; l = l->next) + { + stats_tree_cfg *cfg = (stats_tree_cfg *) l->data; - json_dumper_begin_object(&dumper); - sharkd_json_value_string("name", cfg->name); - sharkd_json_value_stringf("tap", "stat:%s", cfg->abbr); - json_dumper_end_object(&dumper); - } + json_dumper_begin_object(&dumper); + sharkd_json_value_string("name", cfg->name); + sharkd_json_value_stringf("tap", "stat:%s", cfg->abbr); + json_dumper_end_object(&dumper); + } - g_list_free(cfg_list); - } - sharkd_json_array_close(); + g_list_free(cfg_list); + } + sharkd_json_array_close(); - sharkd_json_array_open("ftypes"); - for (i = 0; i < FT_NUM_TYPES; i++) - sharkd_json_value_string(NULL, ftype_name((ftenum_t) i)); - sharkd_json_array_close(); + sharkd_json_array_open("ftypes"); + for (i = 0; i < FT_NUM_TYPES; i++) + sharkd_json_value_string(NULL, ftype_name((ftenum_t) i)); + sharkd_json_array_close(); - sharkd_json_value_string("version", get_ws_vcs_version_info_short()); + sharkd_json_value_string("version", get_ws_vcs_version_info_short()); - sharkd_json_array_open("nstat"); - i = 0; - stat_tap_iterate_tables(sharkd_session_process_info_nstat_cb, &i); - sharkd_json_array_close(); + sharkd_json_array_open("nstat"); + i = 0; + stat_tap_iterate_tables(sharkd_session_process_info_nstat_cb, &i); + sharkd_json_array_close(); - sharkd_json_array_open("convs"); - i = 0; - conversation_table_iterate_tables(sharkd_session_process_info_conv_cb, &i); - sharkd_json_array_close(); + sharkd_json_array_open("convs"); + i = 0; + conversation_table_iterate_tables(sharkd_session_process_info_conv_cb, &i); + sharkd_json_array_close(); - sharkd_json_array_open("seqa"); - i = 0; - sequence_analysis_table_iterate_tables(sharkd_session_seq_analysis_cb, &i); - sharkd_json_array_close(); + sharkd_json_array_open("seqa"); + i = 0; + sequence_analysis_table_iterate_tables(sharkd_session_seq_analysis_cb, &i); + sharkd_json_array_close(); - sharkd_json_array_open("taps"); - { - json_dumper_begin_object(&dumper); - sharkd_json_value_string("name", "RTP streams"); - sharkd_json_value_string("tap", "rtp-streams"); - json_dumper_end_object(&dumper); + sharkd_json_array_open("taps"); + { + json_dumper_begin_object(&dumper); + sharkd_json_value_string("name", "RTP streams"); + sharkd_json_value_string("tap", "rtp-streams"); + json_dumper_end_object(&dumper); - json_dumper_begin_object(&dumper); - sharkd_json_value_string("name", "Expert Information"); - sharkd_json_value_string("tap", "expert"); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_begin_object(&dumper); + sharkd_json_value_string("name", "Expert Information"); + sharkd_json_value_string("tap", "expert"); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - sharkd_json_array_open("eo"); - i = 0; - eo_iterate_tables(sharkd_export_object_visit_cb, &i); - sharkd_json_array_close(); + sharkd_json_array_open("eo"); + i = 0; + eo_iterate_tables(sharkd_export_object_visit_cb, &i); + sharkd_json_array_close(); - sharkd_json_array_open("srt"); - i = 0; - srt_table_iterate_tables(sharkd_srt_visit_cb, &i); - sharkd_json_array_close(); + sharkd_json_array_open("srt"); + i = 0; + srt_table_iterate_tables(sharkd_srt_visit_cb, &i); + sharkd_json_array_close(); - sharkd_json_array_open("rtd"); - i = 0; - rtd_table_iterate_tables(sharkd_rtd_visit_cb, &i); - sharkd_json_array_close(); + sharkd_json_array_open("rtd"); + i = 0; + rtd_table_iterate_tables(sharkd_rtd_visit_cb, &i); + sharkd_json_array_close(); - sharkd_json_array_open("follow"); - i = 0; - follow_iterate_followers(sharkd_follower_visit_cb, &i); - sharkd_json_array_close(); + sharkd_json_array_open("follow"); + i = 0; + follow_iterate_followers(sharkd_follower_visit_cb, &i); + sharkd_json_array_close(); - sharkd_json_result_epilogue(); + sharkd_json_result_epilogue(); } /** @@ -1057,40 +1057,40 @@ sharkd_session_process_info(void) static void sharkd_session_process_load(const char *buf, const jsmntok_t *tokens, int count) { - const char *tok_file = json_find_attr(buf, tokens, count, "file"); - int err = 0; + const char *tok_file = json_find_attr(buf, tokens, count, "file"); + int err = 0; - if (!tok_file) - return; + if (!tok_file) + return; - fprintf(stderr, "load: filename=%s\n", tok_file); + fprintf(stderr, "load: filename=%s\n", tok_file); - if (sharkd_cf_open(tok_file, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) - { - sharkd_json_error( - rpcid, -2001, NULL, - "Unable to open the file" - ); - return; - } + if (sharkd_cf_open(tok_file, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) + { + sharkd_json_error( + rpcid, -2001, NULL, + "Unable to open the file" + ); + return; + } - TRY - { - err = sharkd_load_cap_file(); - } - CATCH(OutOfMemoryError) - { - sharkd_json_error( - rpcid, -32603, NULL, - "Load failed, out of memory" - ); - fprintf(stderr, "load: OutOfMemoryError\n"); - err = ENOMEM; - } - ENDTRY; + TRY + { + err = sharkd_load_cap_file(); + } + CATCH(OutOfMemoryError) + { + sharkd_json_error( + rpcid, -32603, NULL, + "Load failed, out of memory" + ); + fprintf(stderr, "load: OutOfMemoryError\n"); + err = ENOMEM; + } + ENDTRY; - if (err == 0) - sharkd_json_simple_ok(rpcid); + if (err == 0) + sharkd_json_simple_ok(rpcid); } /** @@ -1107,66 +1107,66 @@ sharkd_session_process_load(const char *buf, const jsmntok_t *tokens, int count) static void sharkd_session_process_status(void) { - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - sharkd_json_value_anyf("frames", "%u", cfile.count); - sharkd_json_value_anyf("duration", "%.9f", nstime_to_sec(&cfile.elapsed_time)); + sharkd_json_value_anyf("frames", "%u", cfile.count); + sharkd_json_value_anyf("duration", "%.9f", nstime_to_sec(&cfile.elapsed_time)); - if (cfile.filename) - { - char *name = g_path_get_basename(cfile.filename); + if (cfile.filename) + { + char *name = g_path_get_basename(cfile.filename); - sharkd_json_value_string("filename", name); - g_free(name); - } + sharkd_json_value_string("filename", name); + g_free(name); + } - if (cfile.provider.wth) - { - gint64 file_size = wtap_file_size(cfile.provider.wth, NULL); + if (cfile.provider.wth) + { + gint64 file_size = wtap_file_size(cfile.provider.wth, NULL); - if (file_size > 0) - sharkd_json_value_anyf("filesize", "%" PRId64, file_size); - } + if (file_size > 0) + sharkd_json_value_anyf("filesize", "%" PRId64, file_size); + } - sharkd_json_result_epilogue(); + sharkd_json_result_epilogue(); } struct sharkd_analyse_data { - GHashTable *protocols_set; - nstime_t *first_time; - nstime_t *last_time; + GHashTable *protocols_set; + nstime_t *first_time; + nstime_t *last_time; }; static void sharkd_session_process_analyse_cb(epan_dissect_t *edt, proto_tree *tree _U_, - struct epan_column_info *cinfo _U_, const GSList *data_src _U_, void *data) + struct epan_column_info *cinfo _U_, const GSList *data_src _U_, void *data) { - struct sharkd_analyse_data *analyser = (struct sharkd_analyse_data *) data; - packet_info *pi = &edt->pi; - frame_data *fdata = pi->fd; + struct sharkd_analyse_data *analyser = (struct sharkd_analyse_data *) data; + packet_info *pi = &edt->pi; + frame_data *fdata = pi->fd; - if (analyser->first_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->first_time) < 0) - analyser->first_time = &fdata->abs_ts; + if (analyser->first_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->first_time) < 0) + analyser->first_time = &fdata->abs_ts; - if (analyser->last_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->last_time) > 0) - analyser->last_time = &fdata->abs_ts; + if (analyser->last_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->last_time) > 0) + analyser->last_time = &fdata->abs_ts; - if (pi->layers) - { - wmem_list_frame_t *frame; + if (pi->layers) + { + wmem_list_frame_t *frame; - for (frame = wmem_list_head(pi->layers); frame; frame = wmem_list_frame_next(frame)) - { - int proto_id = GPOINTER_TO_UINT(wmem_list_frame_data(frame)); + for (frame = wmem_list_head(pi->layers); frame; frame = wmem_list_frame_next(frame)) + { + int proto_id = GPOINTER_TO_UINT(wmem_list_frame_data(frame)); - if (!g_hash_table_lookup_extended(analyser->protocols_set, GUINT_TO_POINTER(proto_id), NULL, NULL)) - { - g_hash_table_insert(analyser->protocols_set, GUINT_TO_POINTER(proto_id), GUINT_TO_POINTER(proto_id)); - sharkd_json_value_string(NULL, proto_get_protocol_filter_name(proto_id)); - } - } - } + if (!g_hash_table_lookup_extended(analyser->protocols_set, GUINT_TO_POINTER(proto_id), NULL, NULL)) + { + g_hash_table_insert(analyser->protocols_set, GUINT_TO_POINTER(proto_id), GUINT_TO_POINTER(proto_id)); + sharkd_json_value_string(NULL, proto_get_protocol_filter_name(proto_id)); + } + } + } } @@ -1184,191 +1184,191 @@ sharkd_session_process_analyse_cb(epan_dissect_t *edt, proto_tree *tree _U_, static void sharkd_session_process_analyse(void) { - struct sharkd_analyse_data analyser; - wtap_rec rec; /* Record metadata */ - Buffer rec_buf; /* Record data */ + struct sharkd_analyse_data analyser; + wtap_rec rec; /* Record metadata */ + Buffer rec_buf; /* Record data */ - analyser.first_time = NULL; - analyser.last_time = NULL; - analyser.protocols_set = g_hash_table_new(NULL /* g_direct_hash() */, NULL /* g_direct_equal */); + analyser.first_time = NULL; + analyser.last_time = NULL; + analyser.protocols_set = g_hash_table_new(NULL /* g_direct_hash() */, NULL /* g_direct_equal */); - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - sharkd_json_value_anyf("frames", "%u", cfile.count); + sharkd_json_value_anyf("frames", "%u", cfile.count); - sharkd_json_array_open("protocols"); + sharkd_json_array_open("protocols"); - wtap_rec_init(&rec); - ws_buffer_init(&rec_buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&rec_buf, 1514); - for (guint32 framenum = 1; framenum <= cfile.count; framenum++) - { - enum dissect_request_status status; - int err; - gchar *err_info; + for (guint32 framenum = 1; framenum <= cfile.count; framenum++) + { + enum dissect_request_status status; + int err; + gchar *err_info; - status = sharkd_dissect_request(framenum, - (framenum != 1) ? 1 : 0, framenum - 1, - &rec, &rec_buf, NULL, SHARKD_DISSECT_FLAG_NULL, - &sharkd_session_process_analyse_cb, &analyser, - &err, &err_info); - switch (status) { + status = sharkd_dissect_request(framenum, + (framenum != 1) ? 1 : 0, framenum - 1, + &rec, &rec_buf, NULL, SHARKD_DISSECT_FLAG_NULL, + &sharkd_session_process_analyse_cb, &analyser, + &err, &err_info); + switch (status) { - case DISSECT_REQUEST_SUCCESS: - break; + case DISSECT_REQUEST_SUCCESS: + break; - case DISSECT_REQUEST_NO_SUCH_FRAME: - /* XXX - report the error. */ - break; + case DISSECT_REQUEST_NO_SUCH_FRAME: + /* XXX - report the error. */ + break; - case DISSECT_REQUEST_READ_ERROR: - /* - * Free up the error string. - * XXX - report the error. - */ - g_free(err_info); - break; - } - } + case DISSECT_REQUEST_READ_ERROR: + /* + * Free up the error string. + * XXX - report the error. + */ + g_free(err_info); + break; + } + } - sharkd_json_array_close(); + sharkd_json_array_close(); - if (analyser.first_time) - sharkd_json_value_anyf("first", "%.9f", nstime_to_sec(analyser.first_time)); + if (analyser.first_time) + sharkd_json_value_anyf("first", "%.9f", nstime_to_sec(analyser.first_time)); - if (analyser.last_time) - sharkd_json_value_anyf("last", "%.9f", nstime_to_sec(analyser.last_time)); + if (analyser.last_time) + sharkd_json_value_anyf("last", "%.9f", nstime_to_sec(analyser.last_time)); - sharkd_json_result_epilogue(); + sharkd_json_result_epilogue(); - wtap_rec_cleanup(&rec); - ws_buffer_free(&rec_buf); + wtap_rec_cleanup(&rec); + ws_buffer_free(&rec_buf); - g_hash_table_destroy(analyser.protocols_set); + g_hash_table_destroy(analyser.protocols_set); } static column_info * sharkd_session_create_columns(column_info *cinfo, const char *buf, const jsmntok_t *tokens, int count) { - const char *columns_custom[32]; - guint16 columns_fmt[32]; - gint16 columns_occur[32]; + const char *columns_custom[32]; + guint16 columns_fmt[32]; + gint16 columns_occur[32]; - int i, cols; + int i, cols; - for (i = 0; i < 32; i++) - { - const char *tok_column; - char tok_column_name[64]; - char *custom_sepa; + for (i = 0; i < 32; i++) + { + const char *tok_column; + char tok_column_name[64]; + char *custom_sepa; - snprintf(tok_column_name, sizeof(tok_column_name), "column%d", i); - tok_column = json_find_attr(buf, tokens, count, tok_column_name); - if (tok_column == NULL) - break; + snprintf(tok_column_name, sizeof(tok_column_name), "column%d", i); + tok_column = json_find_attr(buf, tokens, count, tok_column_name); + if (tok_column == NULL) + break; - columns_custom[i] = NULL; - columns_occur[i] = 0; + columns_custom[i] = NULL; + columns_occur[i] = 0; - if ((custom_sepa = strchr(tok_column, ':'))) - { - *custom_sepa = '\0'; /* XXX, C abuse: discarding-const */ + if ((custom_sepa = strchr(tok_column, ':'))) + { + *custom_sepa = '\0'; /* XXX, C abuse: discarding-const */ - columns_fmt[i] = COL_CUSTOM; - columns_custom[i] = tok_column; + columns_fmt[i] = COL_CUSTOM; + columns_custom[i] = tok_column; - if (!ws_strtoi16(custom_sepa + 1, NULL, &columns_occur[i])) - return NULL; - } - else - { - if (!ws_strtou16(tok_column, NULL, &columns_fmt[i])) - return NULL; + if (!ws_strtoi16(custom_sepa + 1, NULL, &columns_occur[i])) + return NULL; + } + else + { + if (!ws_strtou16(tok_column, NULL, &columns_fmt[i])) + return NULL; - if (columns_fmt[i] >= NUM_COL_FMTS) - return NULL; + if (columns_fmt[i] >= NUM_COL_FMTS) + return NULL; - /* if custom, that it shouldn't be just custom number -> error */ - if (columns_fmt[i] == COL_CUSTOM) - return NULL; - } - } + /* if custom, that it shouldn't be just custom number -> error */ + if (columns_fmt[i] == COL_CUSTOM) + return NULL; + } + } - cols = i; + cols = i; - col_setup(cinfo, cols); + col_setup(cinfo, cols); - for (i = 0; i < cols; i++) - { - col_item_t *col_item = &cinfo->columns[i]; + for (i = 0; i < cols; i++) + { + col_item_t *col_item = &cinfo->columns[i]; - col_item->col_fmt = columns_fmt[i]; - col_item->col_title = NULL; /* no need for title */ + col_item->col_fmt = columns_fmt[i]; + col_item->col_title = NULL; /* no need for title */ - if (col_item->col_fmt == COL_CUSTOM) - { - col_item->col_custom_fields = g_strdup(columns_custom[i]); - col_item->col_custom_occurrence = columns_occur[i]; - } + if (col_item->col_fmt == COL_CUSTOM) + { + col_item->col_custom_fields = g_strdup(columns_custom[i]); + col_item->col_custom_occurrence = columns_occur[i]; + } - col_item->col_fence = 0; - } + col_item->col_fence = 0; + } - col_finalize(cinfo); + col_finalize(cinfo); - return cinfo; + return cinfo; } static void sharkd_session_process_frames_cb(epan_dissect_t *edt, proto_tree *tree _U_, - struct epan_column_info *cinfo, const GSList *data_src _U_, void *data _U_) + struct epan_column_info *cinfo, const GSList *data_src _U_, void *data _U_) { - packet_info *pi = &edt->pi; - frame_data *fdata = pi->fd; - wtap_block_t pkt_block = NULL; - char *comment; + packet_info *pi = &edt->pi; + frame_data *fdata = pi->fd; + wtap_block_t pkt_block = NULL; + char *comment; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_array_open("c"); - for (int col = 0; col < cinfo->num_cols; ++col) - { - const col_item_t *col_item = &cinfo->columns[col]; + sharkd_json_array_open("c"); + for (int col = 0; col < cinfo->num_cols; ++col) + { + const col_item_t *col_item = &cinfo->columns[col]; - sharkd_json_value_string(NULL, col_item->col_data); - } - sharkd_json_array_close(); + sharkd_json_value_string(NULL, col_item->col_data); + } + sharkd_json_array_close(); - sharkd_json_value_anyf("num", "%u", pi->num); + sharkd_json_value_anyf("num", "%u", pi->num); - /* - * Get the block for this record, if it has one. - */ - if (fdata->has_modified_block) - pkt_block = sharkd_get_modified_block(fdata); - else - pkt_block = pi->rec->block; + /* + * Get the block for this record, if it has one. + */ + if (fdata->has_modified_block) + pkt_block = sharkd_get_modified_block(fdata); + else + pkt_block = pi->rec->block; - /* - * Does this record have any comments? - */ - if (pkt_block != NULL && - WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT, 0, &comment)) - sharkd_json_value_anyf("ct", "true"); + /* + * Does this record have any comments? + */ + if (pkt_block != NULL && + WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT, 0, &comment)) + sharkd_json_value_anyf("ct", "true"); - if (fdata->ignored) - sharkd_json_value_anyf("i", "true"); + if (fdata->ignored) + sharkd_json_value_anyf("i", "true"); - if (fdata->marked) - sharkd_json_value_anyf("m", "true"); + if (fdata->marked) + sharkd_json_value_anyf("m", "true"); - if (fdata->color_filter) - { - sharkd_json_value_stringf("bg", "%x", color_t_to_rgb(&fdata->color_filter->bg_color)); - sharkd_json_value_stringf("fg", "%x", color_t_to_rgb(&fdata->color_filter->fg_color)); - } + if (fdata->color_filter) + { + sharkd_json_value_stringf("bg", "%x", color_t_to_rgb(&fdata->color_filter->bg_color)); + sharkd_json_value_stringf("fg", "%x", color_t_to_rgb(&fdata->color_filter->fg_color)); + } - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } /** @@ -1396,211 +1396,211 @@ sharkd_session_process_frames_cb(epan_dissect_t *edt, proto_tree *tree _U_, static void sharkd_session_process_frames(const char *buf, const jsmntok_t *tokens, int count) { - const char *tok_filter = json_find_attr(buf, tokens, count, "filter"); - const char *tok_column = json_find_attr(buf, tokens, count, "column0"); - const char *tok_skip = json_find_attr(buf, tokens, count, "skip"); - const char *tok_limit = json_find_attr(buf, tokens, count, "limit"); - const char *tok_refs = json_find_attr(buf, tokens, count, "refs"); + const char *tok_filter = json_find_attr(buf, tokens, count, "filter"); + const char *tok_column = json_find_attr(buf, tokens, count, "column0"); + const char *tok_skip = json_find_attr(buf, tokens, count, "skip"); + const char *tok_limit = json_find_attr(buf, tokens, count, "limit"); + const char *tok_refs = json_find_attr(buf, tokens, count, "refs"); - const guint8 *filter_data = NULL; + const guint8 *filter_data = NULL; - guint32 next_ref_frame = G_MAXUINT32; - guint32 skip; - guint32 limit; + guint32 next_ref_frame = G_MAXUINT32; + guint32 skip; + guint32 limit; - wtap_rec rec; /* Record metadata */ - Buffer rec_buf; /* Record data */ - column_info *cinfo = &cfile.cinfo; - column_info user_cinfo; + wtap_rec rec; /* Record metadata */ + Buffer rec_buf; /* Record data */ + column_info *cinfo = &cfile.cinfo; + column_info user_cinfo; - if (tok_column) - { - memset(&user_cinfo, 0, sizeof(user_cinfo)); - cinfo = sharkd_session_create_columns(&user_cinfo, buf, tokens, count); - if (!cinfo) - { - sharkd_json_error( - rpcid, -13001, NULL, - "Column definition invalid - note column 6 requires a custom definition" - ); - return; - } - } + if (tok_column) + { + memset(&user_cinfo, 0, sizeof(user_cinfo)); + cinfo = sharkd_session_create_columns(&user_cinfo, buf, tokens, count); + if (!cinfo) + { + sharkd_json_error( + rpcid, -13001, NULL, + "Column definition invalid - note column 6 requires a custom definition" + ); + return; + } + } - if (tok_filter) - { - const struct sharkd_filter_item *filter_item; + if (tok_filter) + { + const struct sharkd_filter_item *filter_item; - filter_item = sharkd_session_filter_data(tok_filter); - if (!filter_item) - { - sharkd_json_error( - rpcid, -13002, NULL, - "Filter expression invalid" - ); - return; - } + filter_item = sharkd_session_filter_data(tok_filter); + if (!filter_item) + { + sharkd_json_error( + rpcid, -13002, NULL, + "Filter expression invalid" + ); + return; + } - filter_data = filter_item->filtered; - } + filter_data = filter_item->filtered; + } - skip = 0; - if (tok_skip) - { - if (!ws_strtou32(tok_skip, NULL, &skip)) - return; - } + skip = 0; + if (tok_skip) + { + if (!ws_strtou32(tok_skip, NULL, &skip)) + return; + } - limit = 0; - if (tok_limit) - { - if (!ws_strtou32(tok_limit, NULL, &limit)) - return; - } + limit = 0; + if (tok_limit) + { + if (!ws_strtou32(tok_limit, NULL, &limit)) + return; + } - if (tok_refs) - { - if (!ws_strtou32(tok_refs, &tok_refs, &next_ref_frame)) - return; - } + if (tok_refs) + { + if (!ws_strtou32(tok_refs, &tok_refs, &next_ref_frame)) + return; + } - sharkd_json_result_array_prologue(rpcid); + sharkd_json_result_array_prologue(rpcid); - wtap_rec_init(&rec); - ws_buffer_init(&rec_buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&rec_buf, 1514); - for (guint32 framenum = 1; framenum <= cfile.count; framenum++) - { - frame_data *fdata; - enum dissect_request_status status; - int err; - gchar *err_info; + for (guint32 framenum = 1; framenum <= cfile.count; framenum++) + { + frame_data *fdata; + enum dissect_request_status status; + int err; + gchar *err_info; - if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8)))) - continue; + if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8)))) + continue; - if (skip) - { - skip--; - continue; - } + if (skip) + { + skip--; + continue; + } - if (tok_refs) - { - if (framenum >= next_ref_frame) - { - if (*tok_refs != ',') - next_ref_frame = G_MAXUINT32; + if (tok_refs) + { + if (framenum >= next_ref_frame) + { + if (*tok_refs != ',') + next_ref_frame = G_MAXUINT32; - while (*tok_refs == ',' && framenum >= next_ref_frame) - { - if (!ws_strtou32(tok_refs + 1, &tok_refs, &next_ref_frame)) - { - fprintf(stderr, "sharkd_session_process_frames() wrong format for refs: %s\n", tok_refs); - break; - } - } + while (*tok_refs == ',' && framenum >= next_ref_frame) + { + if (!ws_strtou32(tok_refs + 1, &tok_refs, &next_ref_frame)) + { + fprintf(stderr, "sharkd_session_process_frames() wrong format for refs: %s\n", tok_refs); + break; + } + } - if (*tok_refs == '\0' && framenum >= next_ref_frame) - { - next_ref_frame = G_MAXUINT32; - } - } - } + if (*tok_refs == '\0' && framenum >= next_ref_frame) + { + next_ref_frame = G_MAXUINT32; + } + } + } - fdata = sharkd_get_frame(framenum); - status = sharkd_dissect_request(framenum, - (framenum != 1) ? 1 : 0, framenum - 1, - &rec, &rec_buf, cinfo, - (fdata->color_filter == NULL) ? SHARKD_DISSECT_FLAG_COLOR : SHARKD_DISSECT_FLAG_NULL, - &sharkd_session_process_frames_cb, NULL, - &err, &err_info); - switch (status) { + fdata = sharkd_get_frame(framenum); + status = sharkd_dissect_request(framenum, + (framenum != 1) ? 1 : 0, framenum - 1, + &rec, &rec_buf, cinfo, + (fdata->color_filter == NULL) ? SHARKD_DISSECT_FLAG_COLOR : SHARKD_DISSECT_FLAG_NULL, + &sharkd_session_process_frames_cb, NULL, + &err, &err_info); + switch (status) { - case DISSECT_REQUEST_SUCCESS: - break; + case DISSECT_REQUEST_SUCCESS: + break; - case DISSECT_REQUEST_NO_SUCH_FRAME: - /* XXX - report the error. */ - break; + case DISSECT_REQUEST_NO_SUCH_FRAME: + /* XXX - report the error. */ + break; - case DISSECT_REQUEST_READ_ERROR: - /* - * Free up the error string. - * XXX - report the error. - */ - g_free(err_info); - break; - } + case DISSECT_REQUEST_READ_ERROR: + /* + * Free up the error string. + * XXX - report the error. + */ + g_free(err_info); + break; + } - if (limit && --limit == 0) - break; - } - sharkd_json_result_array_epilogue(); + if (limit && --limit == 0) + break; + } + sharkd_json_result_array_epilogue(); - if (cinfo != &cfile.cinfo) - col_cleanup(cinfo); + if (cinfo != &cfile.cinfo) + col_cleanup(cinfo); - wtap_rec_cleanup(&rec); - ws_buffer_free(&rec_buf); + wtap_rec_cleanup(&rec); + ws_buffer_free(&rec_buf); } static void sharkd_session_process_tap_stats_node_cb(const stat_node *n) { - stat_node *node; + stat_node *node; - sharkd_json_array_open(NULL); - for (node = n->children; node; node = node->next) - { - json_dumper_begin_object(&dumper); + sharkd_json_array_open(NULL); + for (node = n->children; node; node = node->next) + { + json_dumper_begin_object(&dumper); - /* code based on stats_tree_get_values_from_node() */ - sharkd_json_value_string("name", node->name); - sharkd_json_value_anyf("count", "%d", node->counter); - if (node->counter && ((node->st_flags & ST_FLG_AVERAGE) || node->rng)) - { - switch(node->datatype) - { - case STAT_DT_INT: - sharkd_json_value_anyf("avg", "%.2f", ((float)node->total.int_total) / node->counter); - sharkd_json_value_anyf("min", "%d", node->minvalue.int_min); - sharkd_json_value_anyf("max", "%d", node->maxvalue.int_max); - break; - case STAT_DT_FLOAT: - sharkd_json_value_anyf("avg", "%.2f", node->total.float_total / node->counter); - sharkd_json_value_anyf("min", "%f", node->minvalue.float_min); - sharkd_json_value_anyf("max", "%f", node->maxvalue.float_max); - break; - } - } + /* code based on stats_tree_get_values_from_node() */ + sharkd_json_value_string("name", node->name); + sharkd_json_value_anyf("count", "%d", node->counter); + if (node->counter && ((node->st_flags & ST_FLG_AVERAGE) || node->rng)) + { + switch(node->datatype) + { + case STAT_DT_INT: + sharkd_json_value_anyf("avg", "%.2f", ((float)node->total.int_total) / node->counter); + sharkd_json_value_anyf("min", "%d", node->minvalue.int_min); + sharkd_json_value_anyf("max", "%d", node->maxvalue.int_max); + break; + case STAT_DT_FLOAT: + sharkd_json_value_anyf("avg", "%.2f", node->total.float_total / node->counter); + sharkd_json_value_anyf("min", "%f", node->minvalue.float_min); + sharkd_json_value_anyf("max", "%f", node->maxvalue.float_max); + break; + } + } - if (node->st->elapsed) - sharkd_json_value_anyf("rate", "%.4f", ((float)node->counter) / node->st->elapsed); + if (node->st->elapsed) + sharkd_json_value_anyf("rate", "%.4f", ((float)node->counter) / node->st->elapsed); - if (node->parent && node->parent->counter) - sharkd_json_value_anyf("perc", "%.2f", (node->counter * 100.0) / node->parent->counter); - else if (node->parent == &(node->st->root)) - sharkd_json_value_anyf("perc", "100"); + if (node->parent && node->parent->counter) + sharkd_json_value_anyf("perc", "%.2f", (node->counter * 100.0) / node->parent->counter); + else if (node->parent == &(node->st->root)) + sharkd_json_value_anyf("perc", "100"); - if (prefs.st_enable_burstinfo && node->max_burst) - { - if (prefs.st_burst_showcount) - sharkd_json_value_anyf("burstcount", "%d", node->max_burst); - else - sharkd_json_value_anyf("burstrate", "%.4f", ((double)node->max_burst) / prefs.st_burst_windowlen); + if (prefs.st_enable_burstinfo && node->max_burst) + { + if (prefs.st_burst_showcount) + sharkd_json_value_anyf("burstcount", "%d", node->max_burst); + else + sharkd_json_value_anyf("burstrate", "%.4f", ((double)node->max_burst) / prefs.st_burst_windowlen); - sharkd_json_value_anyf("bursttime", "%.3f", (node->burst_time / 1000.0)); - } + sharkd_json_value_anyf("bursttime", "%.3f", (node->burst_time / 1000.0)); + } - if (node->children) - { - sharkd_json_value_anyf("sub", NULL); - sharkd_session_process_tap_stats_node_cb(node); - } - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + if (node->children) + { + sharkd_json_value_anyf("sub", NULL); + sharkd_session_process_tap_stats_node_cb(node); + } + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); } /** @@ -1627,32 +1627,32 @@ sharkd_session_process_tap_stats_node_cb(const stat_node *n) static void sharkd_session_process_tap_stats_cb(void *psp) { - stats_tree *st = (stats_tree *) psp; + stats_tree *st = (stats_tree *) psp; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("tap", "stats:%s", st->cfg->abbr); - sharkd_json_value_string("type", "stats"); - sharkd_json_value_string("name", st->cfg->name); + sharkd_json_value_stringf("tap", "stats:%s", st->cfg->abbr); + sharkd_json_value_string("type", "stats"); + sharkd_json_value_string("name", st->cfg->name); - sharkd_json_value_anyf("stats", NULL); - sharkd_session_process_tap_stats_node_cb(&st->root); + sharkd_json_value_anyf("stats", NULL); + sharkd_session_process_tap_stats_node_cb(&st->root); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } static void sharkd_session_free_tap_stats_cb(void *psp) { - stats_tree *st = (stats_tree *) psp; + stats_tree *st = (stats_tree *) psp; - stats_tree_free(st); + stats_tree_free(st); } struct sharkd_expert_tap { - GSList *details; - GStringChunk *text; + GSList *details; + GStringChunk *text; }; /** @@ -1672,75 +1672,75 @@ struct sharkd_expert_tap static void sharkd_session_process_tap_expert_cb(void *tapdata) { - struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata; - GSList *list; + struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata; + GSList *list; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_string("tap", "expert"); - sharkd_json_value_string("type", "expert"); + sharkd_json_value_string("tap", "expert"); + sharkd_json_value_string("type", "expert"); - sharkd_json_array_open("details"); - for (list = etd->details; list; list = list->next) - { - expert_info_t *ei = (expert_info_t *) list->data; - const char *tmp; + sharkd_json_array_open("details"); + for (list = etd->details; list; list = list->next) + { + expert_info_t *ei = (expert_info_t *) list->data; + const char *tmp; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_anyf("f", "%u", ei->packet_num); + sharkd_json_value_anyf("f", "%u", ei->packet_num); - tmp = try_val_to_str(ei->severity, expert_severity_vals); - if (tmp) - sharkd_json_value_string("s", tmp); + tmp = try_val_to_str(ei->severity, expert_severity_vals); + if (tmp) + sharkd_json_value_string("s", tmp); - tmp = try_val_to_str(ei->group, expert_group_vals); - if (tmp) - sharkd_json_value_string("g", tmp); + tmp = try_val_to_str(ei->group, expert_group_vals); + if (tmp) + sharkd_json_value_string("g", tmp); - sharkd_json_value_string("m", ei->summary); + sharkd_json_value_string("m", ei->summary); - if (ei->protocol) - sharkd_json_value_string("p", ei->protocol); + if (ei->protocol) + sharkd_json_value_string("p", ei->protocol); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } static tap_packet_status sharkd_session_packet_tap_expert_cb(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pointer) { - struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata; - const expert_info_t *ei = (const expert_info_t *) pointer; - expert_info_t *ei_copy; + struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata; + const expert_info_t *ei = (const expert_info_t *) pointer; + expert_info_t *ei_copy; - if (ei == NULL) - return TAP_PACKET_DONT_REDRAW; + if (ei == NULL) + return TAP_PACKET_DONT_REDRAW; - ei_copy = g_new(expert_info_t, 1); - /* Note: this is a shallow copy */ - *ei_copy = *ei; + ei_copy = g_new(expert_info_t, 1); + /* Note: this is a shallow copy */ + *ei_copy = *ei; - /* ei->protocol, ei->summary might be allocated in packet scope, make a copy. */ - ei_copy->protocol = g_string_chunk_insert_const(etd->text, ei_copy->protocol); - ei_copy->summary = g_string_chunk_insert_const(etd->text, ei_copy->summary); + /* ei->protocol, ei->summary might be allocated in packet scope, make a copy. */ + ei_copy->protocol = g_string_chunk_insert_const(etd->text, ei_copy->protocol); + ei_copy->summary = g_string_chunk_insert_const(etd->text, ei_copy->summary); - etd->details = g_slist_prepend(etd->details, ei_copy); + etd->details = g_slist_prepend(etd->details, ei_copy); - return TAP_PACKET_REDRAW; + return TAP_PACKET_REDRAW; } static void sharkd_session_free_tap_expert_cb(void *tapdata) { - struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata; + struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata; - g_slist_free_full(etd->details, g_free); - g_string_chunk_free(etd->text); - g_free(etd); + g_slist_free_full(etd->details, g_free); + g_string_chunk_free(etd->text); + g_free(etd); } /** @@ -1759,217 +1759,217 @@ sharkd_session_free_tap_expert_cb(void *tapdata) static void sharkd_session_process_tap_flow_cb(void *tapdata) { - seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata; - GList *flow_list; - guint i; + seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata; + GList *flow_list; + guint i; - sequence_analysis_get_nodes(graph_analysis); + sequence_analysis_get_nodes(graph_analysis); - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("tap", "seqa:%s", graph_analysis->name); - sharkd_json_value_string("type", "flow"); + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("tap", "seqa:%s", graph_analysis->name); + sharkd_json_value_string("type", "flow"); - sharkd_json_array_open("nodes"); - for (i = 0; i < graph_analysis->num_nodes; i++) - { - char *addr_str; + sharkd_json_array_open("nodes"); + for (i = 0; i < graph_analysis->num_nodes; i++) + { + char *addr_str; - addr_str = address_to_display(NULL, &(graph_analysis->nodes[i])); - sharkd_json_value_string(NULL, addr_str); - wmem_free(NULL, addr_str); - } - sharkd_json_array_close(); + addr_str = address_to_display(NULL, &(graph_analysis->nodes[i])); + sharkd_json_value_string(NULL, addr_str); + wmem_free(NULL, addr_str); + } + sharkd_json_array_close(); - sharkd_json_array_open("flows"); - flow_list = g_queue_peek_nth_link(graph_analysis->items, 0); - while (flow_list) - { - seq_analysis_item_t *sai = (seq_analysis_item_t *) flow_list->data; + sharkd_json_array_open("flows"); + flow_list = g_queue_peek_nth_link(graph_analysis->items, 0); + while (flow_list) + { + seq_analysis_item_t *sai = (seq_analysis_item_t *) flow_list->data; - flow_list = g_list_next(flow_list); + flow_list = g_list_next(flow_list); - if (!sai->display) - continue; + if (!sai->display) + continue; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_string("t", sai->time_str); - sharkd_json_value_anyf("n", "[%u,%u]", sai->src_node, sai->dst_node); - sharkd_json_value_anyf("pn", "[%u,%u]", sai->port_src, sai->port_dst); + sharkd_json_value_string("t", sai->time_str); + sharkd_json_value_anyf("n", "[%u,%u]", sai->src_node, sai->dst_node); + sharkd_json_value_anyf("pn", "[%u,%u]", sai->port_src, sai->port_dst); - if (sai->comment) - sharkd_json_value_string("c", sai->comment); + if (sai->comment) + sharkd_json_value_string("c", sai->comment); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } static void sharkd_session_free_tap_flow_cb(void *tapdata) { - seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata; + seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata; - sequence_analysis_info_free(graph_analysis); + sequence_analysis_info_free(graph_analysis); } struct sharkd_conv_tap_data { - const char *type; - conv_hash_t hash; - gboolean resolve_name; - gboolean resolve_port; + const char *type; + conv_hash_t hash; + gboolean resolve_name; + gboolean resolve_port; }; static gboolean sharkd_session_geoip_addr(address *addr, const char *suffix) { - const mmdb_lookup_t *lookup = NULL; - gboolean with_geoip = FALSE; - char json_key[64]; + const mmdb_lookup_t *lookup = NULL; + gboolean with_geoip = FALSE; + char json_key[64]; - if (addr->type == AT_IPv4) - { - const ws_in4_addr *ip4 = (const ws_in4_addr *) addr->data; + if (addr->type == AT_IPv4) + { + const ws_in4_addr *ip4 = (const ws_in4_addr *) addr->data; - lookup = maxmind_db_lookup_ipv4(ip4); - } - else if (addr->type == AT_IPv6) - { - const ws_in6_addr *ip6 = (const ws_in6_addr *) addr->data; + lookup = maxmind_db_lookup_ipv4(ip4); + } + else if (addr->type == AT_IPv6) + { + const ws_in6_addr *ip6 = (const ws_in6_addr *) addr->data; - lookup = maxmind_db_lookup_ipv6(ip6); - } + lookup = maxmind_db_lookup_ipv6(ip6); + } - if (!lookup || !lookup->found) - return FALSE; + if (!lookup || !lookup->found) + return FALSE; - if (lookup->country) - { - snprintf(json_key, sizeof(json_key), "geoip_country%s", suffix); - sharkd_json_value_string(json_key, lookup->country); - with_geoip = TRUE; - } + if (lookup->country) + { + snprintf(json_key, sizeof(json_key), "geoip_country%s", suffix); + sharkd_json_value_string(json_key, lookup->country); + with_geoip = TRUE; + } - if (lookup->country_iso) - { - snprintf(json_key, sizeof(json_key), "geoip_country_iso%s", suffix); - sharkd_json_value_string(json_key, lookup->country_iso); - with_geoip = TRUE; - } + if (lookup->country_iso) + { + snprintf(json_key, sizeof(json_key), "geoip_country_iso%s", suffix); + sharkd_json_value_string(json_key, lookup->country_iso); + with_geoip = TRUE; + } - if (lookup->city) - { - snprintf(json_key, sizeof(json_key), "geoip_city%s", suffix); - sharkd_json_value_string(json_key, lookup->city); - with_geoip = TRUE; - } + if (lookup->city) + { + snprintf(json_key, sizeof(json_key), "geoip_city%s", suffix); + sharkd_json_value_string(json_key, lookup->city); + with_geoip = TRUE; + } - if (lookup->as_org) - { - snprintf(json_key, sizeof(json_key), "geoip_as_org%s", suffix); - sharkd_json_value_string(json_key, lookup->as_org); - with_geoip = TRUE; - } + if (lookup->as_org) + { + snprintf(json_key, sizeof(json_key), "geoip_as_org%s", suffix); + sharkd_json_value_string(json_key, lookup->as_org); + with_geoip = TRUE; + } - if (lookup->as_number > 0) - { - snprintf(json_key, sizeof(json_key), "geoip_as%s", suffix); - sharkd_json_value_anyf(json_key, "%u", lookup->as_number); - with_geoip = TRUE; - } + if (lookup->as_number > 0) + { + snprintf(json_key, sizeof(json_key), "geoip_as%s", suffix); + sharkd_json_value_anyf(json_key, "%u", lookup->as_number); + with_geoip = TRUE; + } - if (lookup->latitude >= -90.0 && lookup->latitude <= 90.0) - { - snprintf(json_key, sizeof(json_key), "geoip_lat%s", suffix); - sharkd_json_value_anyf(json_key, "%f", lookup->latitude); - with_geoip = TRUE; - } + if (lookup->latitude >= -90.0 && lookup->latitude <= 90.0) + { + snprintf(json_key, sizeof(json_key), "geoip_lat%s", suffix); + sharkd_json_value_anyf(json_key, "%f", lookup->latitude); + with_geoip = TRUE; + } - if (lookup->longitude >= -180.0 && lookup->longitude <= 180.0) - { - snprintf(json_key, sizeof(json_key), "geoip_lon%s", suffix); - sharkd_json_value_anyf(json_key, "%f", lookup->longitude); - with_geoip = TRUE; - } + if (lookup->longitude >= -180.0 && lookup->longitude <= 180.0) + { + snprintf(json_key, sizeof(json_key), "geoip_lon%s", suffix); + sharkd_json_value_anyf(json_key, "%f", lookup->longitude); + with_geoip = TRUE; + } - return with_geoip; + return with_geoip; } struct sharkd_analyse_rtp_items { - guint32 frame_num; - guint32 sequence_num; + guint32 frame_num; + guint32 sequence_num; - double delta; - double jitter; - double skew; - double bandwidth; - gboolean marker; + double delta; + double jitter; + double skew; + double bandwidth; + gboolean marker; - double arrive_offset; + double arrive_offset; - /* from tap_rtp_stat_t */ - guint32 flags; - guint16 pt; + /* from tap_rtp_stat_t */ + guint32 flags; + guint16 pt; }; struct sharkd_analyse_rtp { - const char *tap_name; - rtpstream_id_t id; + const char *tap_name; + rtpstream_id_t id; - GSList *packets; - double start_time; - tap_rtp_stat_t statinfo; + GSList *packets; + double start_time; + tap_rtp_stat_t statinfo; }; static void sharkd_session_process_tap_rtp_free_cb(void *tapdata) { - struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata; + struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata; - g_slist_free_full(rtp_req->packets, g_free); - g_free(rtp_req); + g_slist_free_full(rtp_req->packets, g_free); + g_free(rtp_req); } static tap_packet_status sharkd_session_packet_tap_rtp_analyse_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pointer) { - struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata; - const struct _rtp_info *rtp_info = (const struct _rtp_info *) pointer; + struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata; + const struct _rtp_info *rtp_info = (const struct _rtp_info *) pointer; - if (rtpstream_id_equal_pinfo_rtp_info(&rtp_req->id, pinfo, rtp_info)) - { - tap_rtp_stat_t *statinfo = &(rtp_req->statinfo); - struct sharkd_analyse_rtp_items *item; + if (rtpstream_id_equal_pinfo_rtp_info(&rtp_req->id, pinfo, rtp_info)) + { + tap_rtp_stat_t *statinfo = &(rtp_req->statinfo); + struct sharkd_analyse_rtp_items *item; - rtppacket_analyse(statinfo, pinfo, rtp_info); + rtppacket_analyse(statinfo, pinfo, rtp_info); - item = g_new(struct sharkd_analyse_rtp_items, 1); + item = g_new(struct sharkd_analyse_rtp_items, 1); - if (!rtp_req->packets) - rtp_req->start_time = nstime_to_sec(&pinfo->abs_ts); + if (!rtp_req->packets) + rtp_req->start_time = nstime_to_sec(&pinfo->abs_ts); - item->frame_num = pinfo->num; - item->sequence_num = rtp_info->info_seq_num; - item->delta = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->delta; - item->jitter = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->jitter; - item->skew = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->skew; - item->bandwidth = statinfo->bandwidth; - item->marker = rtp_info->info_marker_set ? TRUE : FALSE; - item->arrive_offset= nstime_to_sec(&pinfo->abs_ts) - rtp_req->start_time; + item->frame_num = pinfo->num; + item->sequence_num = rtp_info->info_seq_num; + item->delta = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->delta; + item->jitter = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->jitter; + item->skew = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->skew; + item->bandwidth = statinfo->bandwidth; + item->marker = rtp_info->info_marker_set ? TRUE : FALSE; + item->arrive_offset= nstime_to_sec(&pinfo->abs_ts) - rtp_req->start_time; - item->flags = statinfo->flags; - item->pt = statinfo->pt; + item->flags = statinfo->flags; + item->pt = statinfo->pt; - /* XXX, O(n) optimize */ - rtp_req->packets = g_slist_append(rtp_req->packets, item); - } + /* XXX, O(n) optimize */ + rtp_req->packets = g_slist_append(rtp_req->packets, item); + } - return TAP_PACKET_REDRAW; + return TAP_PACKET_REDRAW; } /** @@ -2002,105 +2002,105 @@ sharkd_session_packet_tap_rtp_analyse_cb(void *tapdata, packet_info *pinfo, epan static void sharkd_session_process_tap_rtp_analyse_cb(void *tapdata) { - const int RTP_TYPE_CN = 1; - const int RTP_TYPE_ERROR = 2; - const int RTP_TYPE_WARN = 3; - const int RTP_TYPE_PT_EVENT = 4; + const int RTP_TYPE_CN = 1; + const int RTP_TYPE_ERROR = 2; + const int RTP_TYPE_WARN = 3; + const int RTP_TYPE_PT_EVENT = 4; - const struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata; - const tap_rtp_stat_t *statinfo = &rtp_req->statinfo; + const struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata; + const tap_rtp_stat_t *statinfo = &rtp_req->statinfo; - GSList *l; + GSList *l; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_string("tap", rtp_req->tap_name); - sharkd_json_value_string("type", "rtp-analyse"); - sharkd_json_value_anyf("ssrc", "%u", rtp_req->id.ssrc); + sharkd_json_value_string("tap", rtp_req->tap_name); + sharkd_json_value_string("type", "rtp-analyse"); + sharkd_json_value_anyf("ssrc", "%u", rtp_req->id.ssrc); - sharkd_json_value_anyf("max_delta", "%f", statinfo->max_delta); - sharkd_json_value_anyf("max_delta_nr", "%u", statinfo->max_nr); - sharkd_json_value_anyf("max_jitter", "%f", statinfo->max_jitter); - sharkd_json_value_anyf("mean_jitter", "%f", statinfo->mean_jitter); - sharkd_json_value_anyf("max_skew", "%f", statinfo->max_skew); - sharkd_json_value_anyf("total_nr", "%u", statinfo->total_nr); - sharkd_json_value_anyf("seq_err", "%u", statinfo->sequence); - sharkd_json_value_anyf("duration", "%f", statinfo->time - statinfo->start_time); + sharkd_json_value_anyf("max_delta", "%f", statinfo->max_delta); + sharkd_json_value_anyf("max_delta_nr", "%u", statinfo->max_nr); + sharkd_json_value_anyf("max_jitter", "%f", statinfo->max_jitter); + sharkd_json_value_anyf("mean_jitter", "%f", statinfo->mean_jitter); + sharkd_json_value_anyf("max_skew", "%f", statinfo->max_skew); + sharkd_json_value_anyf("total_nr", "%u", statinfo->total_nr); + sharkd_json_value_anyf("seq_err", "%u", statinfo->sequence); + sharkd_json_value_anyf("duration", "%f", statinfo->time - statinfo->start_time); - sharkd_json_array_open("items"); - for (l = rtp_req->packets; l; l = l->next) - { - struct sharkd_analyse_rtp_items *item = (struct sharkd_analyse_rtp_items *) l->data; + sharkd_json_array_open("items"); + for (l = rtp_req->packets; l; l = l->next) + { + struct sharkd_analyse_rtp_items *item = (struct sharkd_analyse_rtp_items *) l->data; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_anyf("f", "%u", item->frame_num); - sharkd_json_value_anyf("o", "%.9f", item->arrive_offset); - sharkd_json_value_anyf("sn", "%u", item->sequence_num); - sharkd_json_value_anyf("d", "%.2f", item->delta); - sharkd_json_value_anyf("j", "%.2f", item->jitter); - sharkd_json_value_anyf("sk", "%.2f", item->skew); - sharkd_json_value_anyf("bw", "%.2f", item->bandwidth); + sharkd_json_value_anyf("f", "%u", item->frame_num); + sharkd_json_value_anyf("o", "%.9f", item->arrive_offset); + sharkd_json_value_anyf("sn", "%u", item->sequence_num); + sharkd_json_value_anyf("d", "%.2f", item->delta); + sharkd_json_value_anyf("j", "%.2f", item->jitter); + sharkd_json_value_anyf("sk", "%.2f", item->skew); + sharkd_json_value_anyf("bw", "%.2f", item->bandwidth); - if (item->pt == PT_CN) - { - sharkd_json_value_string("s", "Comfort noise (PT=13, RFC 3389)"); - sharkd_json_value_anyf("t", "%d", RTP_TYPE_CN); - } - else if (item->pt == PT_CN_OLD) - { - sharkd_json_value_string("s", "Comfort noise (PT=19, reserved)"); - sharkd_json_value_anyf("t", "%d", RTP_TYPE_CN); - } - else if (item->flags & STAT_FLAG_WRONG_SEQ) - { - sharkd_json_value_string("s", "Wrong sequence number"); - sharkd_json_value_anyf("t", "%d", RTP_TYPE_ERROR); - } - else if (item->flags & STAT_FLAG_DUP_PKT) - { - sharkd_json_value_string("s", "Suspected duplicate (MAC address) only delta time calculated"); - sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); - } - else if (item->flags & STAT_FLAG_REG_PT_CHANGE) - { - sharkd_json_value_stringf("s", "Payload changed to PT=%u%s", - item->pt, - (item->flags & STAT_FLAG_PT_T_EVENT) ? " telephone/event" : ""); - sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); - } - else if (item->flags & STAT_FLAG_WRONG_TIMESTAMP) - { - sharkd_json_value_string("s", "Incorrect timestamp"); - sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); - } - else if ((item->flags & STAT_FLAG_PT_CHANGE) - && !(item->flags & STAT_FLAG_FIRST) - && !(item->flags & STAT_FLAG_PT_CN) - && (item->flags & STAT_FLAG_FOLLOW_PT_CN) - && !(item->flags & STAT_FLAG_MARKER)) - { - sharkd_json_value_string("s", "Marker missing?"); - sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); - } - else if (item->flags & STAT_FLAG_PT_T_EVENT) - { - sharkd_json_value_stringf("s", "PT=%u telephone/event", item->pt); - sharkd_json_value_anyf("t", "%d", RTP_TYPE_PT_EVENT); - } - else if (item->flags & STAT_FLAG_MARKER) - { - sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); - } + if (item->pt == PT_CN) + { + sharkd_json_value_string("s", "Comfort noise (PT=13, RFC 3389)"); + sharkd_json_value_anyf("t", "%d", RTP_TYPE_CN); + } + else if (item->pt == PT_CN_OLD) + { + sharkd_json_value_string("s", "Comfort noise (PT=19, reserved)"); + sharkd_json_value_anyf("t", "%d", RTP_TYPE_CN); + } + else if (item->flags & STAT_FLAG_WRONG_SEQ) + { + sharkd_json_value_string("s", "Wrong sequence number"); + sharkd_json_value_anyf("t", "%d", RTP_TYPE_ERROR); + } + else if (item->flags & STAT_FLAG_DUP_PKT) + { + sharkd_json_value_string("s", "Suspected duplicate (MAC address) only delta time calculated"); + sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); + } + else if (item->flags & STAT_FLAG_REG_PT_CHANGE) + { + sharkd_json_value_stringf("s", "Payload changed to PT=%u%s", + item->pt, + (item->flags & STAT_FLAG_PT_T_EVENT) ? " telephone/event" : ""); + sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); + } + else if (item->flags & STAT_FLAG_WRONG_TIMESTAMP) + { + sharkd_json_value_string("s", "Incorrect timestamp"); + sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); + } + else if ((item->flags & STAT_FLAG_PT_CHANGE) + && !(item->flags & STAT_FLAG_FIRST) + && !(item->flags & STAT_FLAG_PT_CN) + && (item->flags & STAT_FLAG_FOLLOW_PT_CN) + && !(item->flags & STAT_FLAG_MARKER)) + { + sharkd_json_value_string("s", "Marker missing?"); + sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); + } + else if (item->flags & STAT_FLAG_PT_T_EVENT) + { + sharkd_json_value_stringf("s", "PT=%u telephone/event", item->pt); + sharkd_json_value_anyf("t", "%d", RTP_TYPE_PT_EVENT); + } + else if (item->flags & STAT_FLAG_MARKER) + { + sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN); + } - if (item->marker) - sharkd_json_value_anyf("mark", "1"); + if (item->marker) + sharkd_json_value_anyf("mark", "1"); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } /** @@ -2137,150 +2137,150 @@ sharkd_session_process_tap_rtp_analyse_cb(void *tapdata) static void sharkd_session_process_tap_conv_cb(void *arg) { - conv_hash_t *hash = (conv_hash_t *) arg; - const struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data; - const char *proto; - int proto_with_port; - guint i; + conv_hash_t *hash = (conv_hash_t *) arg; + const struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data; + const char *proto; + int proto_with_port; + guint i; - int with_geoip = 0; + int with_geoip = 0; - json_dumper_begin_object(&dumper); - sharkd_json_value_string("tap", iu->type); + json_dumper_begin_object(&dumper); + sharkd_json_value_string("tap", iu->type); - if (!strncmp(iu->type, "conv:", 5)) - { - sharkd_json_value_string("type", "conv"); - sharkd_json_array_open("convs"); - proto = iu->type + 5; - } - else if (!strncmp(iu->type, "endpt:", 6)) - { - sharkd_json_value_string("type", "host"); - sharkd_json_array_open("hosts"); - proto = iu->type + 6; - } - else - { - sharkd_json_value_string("type", "err"); - proto = ""; - } + if (!strncmp(iu->type, "conv:", 5)) + { + sharkd_json_value_string("type", "conv"); + sharkd_json_array_open("convs"); + proto = iu->type + 5; + } + else if (!strncmp(iu->type, "endpt:", 6)) + { + sharkd_json_value_string("type", "host"); + sharkd_json_array_open("hosts"); + proto = iu->type + 6; + } + else + { + sharkd_json_value_string("type", "err"); + proto = ""; + } - proto_with_port = (!strcmp(proto, "TCP") || !strcmp(proto, "UDP") || !strcmp(proto, "SCTP")); + proto_with_port = (!strcmp(proto, "TCP") || !strcmp(proto, "UDP") || !strcmp(proto, "SCTP")); - if (iu->hash.conv_array != NULL && !strncmp(iu->type, "conv:", 5)) - { - for (i = 0; i < iu->hash.conv_array->len; i++) - { - conv_item_t *iui = &g_array_index(iu->hash.conv_array, conv_item_t, i); - char *src_addr, *dst_addr; - char *src_port, *dst_port; - char *filter_str; + if (iu->hash.conv_array != NULL && !strncmp(iu->type, "conv:", 5)) + { + for (i = 0; i < iu->hash.conv_array->len; i++) + { + conv_item_t *iui = &g_array_index(iu->hash.conv_array, conv_item_t, i); + char *src_addr, *dst_addr; + char *src_port, *dst_port; + char *filter_str; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_string("saddr", (src_addr = get_conversation_address(NULL, &iui->src_address, iu->resolve_name))); - sharkd_json_value_string("daddr", (dst_addr = get_conversation_address(NULL, &iui->dst_address, iu->resolve_name))); + sharkd_json_value_string("saddr", (src_addr = get_conversation_address(NULL, &iui->src_address, iu->resolve_name))); + sharkd_json_value_string("daddr", (dst_addr = get_conversation_address(NULL, &iui->dst_address, iu->resolve_name))); - if (proto_with_port) - { - sharkd_json_value_string("sport", (src_port = get_conversation_port(NULL, iui->src_port, iui->etype, iu->resolve_port))); - sharkd_json_value_string("dport", (dst_port = get_conversation_port(NULL, iui->dst_port, iui->etype, iu->resolve_port))); + if (proto_with_port) + { + sharkd_json_value_string("sport", (src_port = get_conversation_port(NULL, iui->src_port, iui->etype, iu->resolve_port))); + sharkd_json_value_string("dport", (dst_port = get_conversation_port(NULL, iui->dst_port, iui->etype, iu->resolve_port))); - wmem_free(NULL, src_port); - wmem_free(NULL, dst_port); - } + wmem_free(NULL, src_port); + wmem_free(NULL, dst_port); + } - sharkd_json_value_anyf("rxf", "%" PRIu64, iui->rx_frames); - sharkd_json_value_anyf("rxb", "%" PRIu64, iui->rx_bytes); + sharkd_json_value_anyf("rxf", "%" PRIu64, iui->rx_frames); + sharkd_json_value_anyf("rxb", "%" PRIu64, iui->rx_bytes); - sharkd_json_value_anyf("txf", "%" PRIu64, iui->tx_frames); - sharkd_json_value_anyf("txb", "%" PRIu64, iui->tx_bytes); + sharkd_json_value_anyf("txf", "%" PRIu64, iui->tx_frames); + sharkd_json_value_anyf("txb", "%" PRIu64, iui->tx_bytes); - sharkd_json_value_anyf("start", "%.9f", nstime_to_sec(&iui->start_time)); - sharkd_json_value_anyf("stop", "%.9f", nstime_to_sec(&iui->stop_time)); + sharkd_json_value_anyf("start", "%.9f", nstime_to_sec(&iui->start_time)); + sharkd_json_value_anyf("stop", "%.9f", nstime_to_sec(&iui->stop_time)); - filter_str = get_conversation_filter(iui, CONV_DIR_A_TO_FROM_B); - if (filter_str) - { - sharkd_json_value_string("filter", filter_str); - g_free(filter_str); - } + filter_str = get_conversation_filter(iui, CONV_DIR_A_TO_FROM_B); + if (filter_str) + { + sharkd_json_value_string("filter", filter_str); + g_free(filter_str); + } - wmem_free(NULL, src_addr); - wmem_free(NULL, dst_addr); + wmem_free(NULL, src_addr); + wmem_free(NULL, dst_addr); - if (sharkd_session_geoip_addr(&(iui->src_address), "1")) - with_geoip = 1; - if (sharkd_session_geoip_addr(&(iui->dst_address), "2")) - with_geoip = 1; + if (sharkd_session_geoip_addr(&(iui->src_address), "1")) + with_geoip = 1; + if (sharkd_session_geoip_addr(&(iui->dst_address), "2")) + with_geoip = 1; - json_dumper_end_object(&dumper); - } - } - else if (iu->hash.conv_array != NULL && !strncmp(iu->type, "endpt:", 6)) - { - for (i = 0; i < iu->hash.conv_array->len; i++) - { - hostlist_talker_t *host = &g_array_index(iu->hash.conv_array, hostlist_talker_t, i); - char *host_str, *port_str; - char *filter_str; + json_dumper_end_object(&dumper); + } + } + else if (iu->hash.conv_array != NULL && !strncmp(iu->type, "endpt:", 6)) + { + for (i = 0; i < iu->hash.conv_array->len; i++) + { + hostlist_talker_t *host = &g_array_index(iu->hash.conv_array, hostlist_talker_t, i); + char *host_str, *port_str; + char *filter_str; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_string("host", (host_str = get_conversation_address(NULL, &host->myaddress, iu->resolve_name))); + sharkd_json_value_string("host", (host_str = get_conversation_address(NULL, &host->myaddress, iu->resolve_name))); - if (proto_with_port) - { - sharkd_json_value_string("port", (port_str = get_conversation_port(NULL, host->port, host->etype, iu->resolve_port))); + if (proto_with_port) + { + sharkd_json_value_string("port", (port_str = get_conversation_port(NULL, host->port, host->etype, iu->resolve_port))); - wmem_free(NULL, port_str); - } + wmem_free(NULL, port_str); + } - sharkd_json_value_anyf("rxf", "%" PRIu64, host->rx_frames); - sharkd_json_value_anyf("rxb", "%" PRIu64, host->rx_bytes); + sharkd_json_value_anyf("rxf", "%" PRIu64, host->rx_frames); + sharkd_json_value_anyf("rxb", "%" PRIu64, host->rx_bytes); - sharkd_json_value_anyf("txf", "%" PRIu64, host->tx_frames); - sharkd_json_value_anyf("txb", "%" PRIu64, host->tx_bytes); + sharkd_json_value_anyf("txf", "%" PRIu64, host->tx_frames); + sharkd_json_value_anyf("txb", "%" PRIu64, host->tx_bytes); - filter_str = get_hostlist_filter(host); - if (filter_str) - { - sharkd_json_value_string("filter", filter_str); - g_free(filter_str); - } + filter_str = get_hostlist_filter(host); + if (filter_str) + { + sharkd_json_value_string("filter", filter_str); + g_free(filter_str); + } - wmem_free(NULL, host_str); + wmem_free(NULL, host_str); - if (sharkd_session_geoip_addr(&(host->myaddress), "")) - with_geoip = 1; - json_dumper_end_object(&dumper); - } - } - sharkd_json_array_close(); + if (sharkd_session_geoip_addr(&(host->myaddress), "")) + with_geoip = 1; + json_dumper_end_object(&dumper); + } + } + sharkd_json_array_close(); - sharkd_json_value_string("proto", proto); - sharkd_json_value_anyf("geoip", with_geoip ? "true" : "false"); + sharkd_json_value_string("proto", proto); + sharkd_json_value_anyf("geoip", with_geoip ? "true" : "false"); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } static void sharkd_session_free_tap_conv_cb(void *arg) { - conv_hash_t *hash = (conv_hash_t *) arg; - struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data; + conv_hash_t *hash = (conv_hash_t *) arg; + struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data; - if (!strncmp(iu->type, "conv:", 5)) - { - reset_conversation_table_data(hash); - } - else if (!strncmp(iu->type, "endpt:", 6)) - { - reset_hostlist_table_data(hash); - } + if (!strncmp(iu->type, "conv:", 5)) + { + reset_conversation_table_data(hash); + } + else if (!strncmp(iu->type, "endpt:", 6)) + { + reset_hostlist_table_data(hash); + } - g_free(iu); + g_free(iu); } /** @@ -2299,91 +2299,91 @@ sharkd_session_free_tap_conv_cb(void *arg) static void sharkd_session_process_tap_nstat_cb(void *arg) { - stat_data_t *stat_data = (stat_data_t *) arg; - guint i, j, k; + stat_data_t *stat_data = (stat_data_t *) arg; + guint i, j, k; - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("tap", "nstat:%s", stat_data->stat_tap_data->cli_string); - sharkd_json_value_string("type", "nstat"); + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("tap", "nstat:%s", stat_data->stat_tap_data->cli_string); + sharkd_json_value_string("type", "nstat"); - sharkd_json_array_open("fields"); - for (i = 0; i < stat_data->stat_tap_data->nfields; i++) - { - stat_tap_table_item *field = &(stat_data->stat_tap_data->fields[i]); + sharkd_json_array_open("fields"); + for (i = 0; i < stat_data->stat_tap_data->nfields; i++) + { + stat_tap_table_item *field = &(stat_data->stat_tap_data->fields[i]); - json_dumper_begin_object(&dumper); - sharkd_json_value_string("c", field->column_name); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_begin_object(&dumper); + sharkd_json_value_string("c", field->column_name); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - sharkd_json_array_open("tables"); - for (i = 0; i < stat_data->stat_tap_data->tables->len; i++) - { - stat_tap_table *table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table *, i); + sharkd_json_array_open("tables"); + for (i = 0; i < stat_data->stat_tap_data->tables->len; i++) + { + stat_tap_table *table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table *, i); - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_string("t", table->title); + sharkd_json_value_string("t", table->title); - sharkd_json_array_open("i"); - for (j = 0; j < table->num_elements; j++) - { - stat_tap_table_item_type *field_data; + sharkd_json_array_open("i"); + for (j = 0; j < table->num_elements; j++) + { + stat_tap_table_item_type *field_data; - field_data = stat_tap_get_field_data(table, j, 0); - if (field_data == NULL || field_data->type == TABLE_ITEM_NONE) /* Nothing for us here */ - continue; + field_data = stat_tap_get_field_data(table, j, 0); + if (field_data == NULL || field_data->type == TABLE_ITEM_NONE) /* Nothing for us here */ + continue; - sharkd_json_array_open(NULL); - for (k = 0; k < table->num_fields; k++) - { - field_data = stat_tap_get_field_data(table, j, k); + sharkd_json_array_open(NULL); + for (k = 0; k < table->num_fields; k++) + { + field_data = stat_tap_get_field_data(table, j, k); - switch (field_data->type) - { - case TABLE_ITEM_UINT: - sharkd_json_value_anyf(NULL, "%u", field_data->value.uint_value); - break; + switch (field_data->type) + { + case TABLE_ITEM_UINT: + sharkd_json_value_anyf(NULL, "%u", field_data->value.uint_value); + break; - case TABLE_ITEM_INT: - sharkd_json_value_anyf(NULL, "%d", field_data->value.int_value); - break; + case TABLE_ITEM_INT: + sharkd_json_value_anyf(NULL, "%d", field_data->value.int_value); + break; - case TABLE_ITEM_STRING: - sharkd_json_value_string(NULL, field_data->value.string_value); - break; + case TABLE_ITEM_STRING: + sharkd_json_value_string(NULL, field_data->value.string_value); + break; - case TABLE_ITEM_FLOAT: - sharkd_json_value_anyf(NULL, "%f", field_data->value.float_value); - break; + case TABLE_ITEM_FLOAT: + sharkd_json_value_anyf(NULL, "%f", field_data->value.float_value); + break; - case TABLE_ITEM_ENUM: - sharkd_json_value_anyf(NULL, "%d", field_data->value.enum_value); - break; + case TABLE_ITEM_ENUM: + sharkd_json_value_anyf(NULL, "%d", field_data->value.enum_value); + break; - case TABLE_ITEM_NONE: - sharkd_json_value_anyf(NULL, "null"); - break; - } - } + case TABLE_ITEM_NONE: + sharkd_json_value_anyf(NULL, "null"); + break; + } + } - sharkd_json_array_close(); - } - sharkd_json_array_close(); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + sharkd_json_array_close(); + } + sharkd_json_array_close(); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } static void sharkd_session_free_tap_nstat_cb(void *arg) { - stat_data_t *stat_data = (stat_data_t *) arg; + stat_data_t *stat_data = (stat_data_t *) arg; - free_stat_tables(stat_data->stat_tap_data); + free_stat_tables(stat_data->stat_tap_data); } /** @@ -2412,86 +2412,86 @@ sharkd_session_free_tap_nstat_cb(void *arg) static void sharkd_session_process_tap_rtd_cb(void *arg) { - rtd_data_t *rtd_data = (rtd_data_t *) arg; - register_rtd_t *rtd = (register_rtd_t *) rtd_data->user_data; + rtd_data_t *rtd_data = (rtd_data_t *) arg; + register_rtd_t *rtd = (register_rtd_t *) rtd_data->user_data; - guint i, j; + guint i, j; - const char *filter = proto_get_protocol_filter_name(get_rtd_proto_id(rtd)); + const char *filter = proto_get_protocol_filter_name(get_rtd_proto_id(rtd)); - /* XXX, some dissectors are having single table and multiple timestats (mgcp, megaco), - * some multiple table and single timestat (radius, h225) - * and it seems that value_string is used one for timestamp-ID, other one for table-ID - * I wonder how it will gonna work with multiple timestats and multiple tables... - * (for usage grep for: register_rtd_table) - */ - const value_string *vs = get_rtd_value_string(rtd); + /* XXX, some dissectors are having single table and multiple timestats (mgcp, megaco), + * some multiple table and single timestat (radius, h225) + * and it seems that value_string is used one for timestamp-ID, other one for table-ID + * I wonder how it will gonna work with multiple timestats and multiple tables... + * (for usage grep for: register_rtd_table) + */ + const value_string *vs = get_rtd_value_string(rtd); - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("tap", "rtd:%s", filter); - sharkd_json_value_string("type", "rtd"); + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("tap", "rtd:%s", filter); + sharkd_json_value_string("type", "rtd"); - if (rtd_data->stat_table.num_rtds == 1) - { - const rtd_timestat *ms = &rtd_data->stat_table.time_stats[0]; + if (rtd_data->stat_table.num_rtds == 1) + { + const rtd_timestat *ms = &rtd_data->stat_table.time_stats[0]; - sharkd_json_value_anyf("open_req", "%u", ms->open_req_num); - sharkd_json_value_anyf("disc_rsp", "%u", ms->disc_rsp_num); - sharkd_json_value_anyf("req_dup", "%u", ms->req_dup_num); - sharkd_json_value_anyf("rsp_dup", "%u", ms->rsp_dup_num); - } + sharkd_json_value_anyf("open_req", "%u", ms->open_req_num); + sharkd_json_value_anyf("disc_rsp", "%u", ms->disc_rsp_num); + sharkd_json_value_anyf("req_dup", "%u", ms->req_dup_num); + sharkd_json_value_anyf("rsp_dup", "%u", ms->rsp_dup_num); + } - sharkd_json_array_open("stats"); - for (i = 0; i < rtd_data->stat_table.num_rtds; i++) - { - const rtd_timestat *ms = &rtd_data->stat_table.time_stats[i]; + sharkd_json_array_open("stats"); + for (i = 0; i < rtd_data->stat_table.num_rtds; i++) + { + const rtd_timestat *ms = &rtd_data->stat_table.time_stats[i]; - for (j = 0; j < ms->num_timestat; j++) - { - const char *type_str; + for (j = 0; j < ms->num_timestat; j++) + { + const char *type_str; - if (ms->rtd[j].num == 0) - continue; + if (ms->rtd[j].num == 0) + continue; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - if (rtd_data->stat_table.num_rtds == 1) - type_str = val_to_str_const(j, vs, "Other"); /* 1 table - description per row */ - else - type_str = val_to_str_const(i, vs, "Other"); /* multiple table - description per table */ - sharkd_json_value_string("type", type_str); + if (rtd_data->stat_table.num_rtds == 1) + type_str = val_to_str_const(j, vs, "Other"); /* 1 table - description per row */ + else + type_str = val_to_str_const(i, vs, "Other"); /* multiple table - description per table */ + sharkd_json_value_string("type", type_str); - sharkd_json_value_anyf("num", "%u", ms->rtd[j].num); - sharkd_json_value_anyf("min", "%.9f", nstime_to_sec(&(ms->rtd[j].min))); - sharkd_json_value_anyf("max", "%.9f", nstime_to_sec(&(ms->rtd[j].max))); - sharkd_json_value_anyf("tot", "%.9f", nstime_to_sec(&(ms->rtd[j].tot))); - sharkd_json_value_anyf("min_frame", "%u", ms->rtd[j].min_num); - sharkd_json_value_anyf("max_frame", "%u", ms->rtd[j].max_num); + sharkd_json_value_anyf("num", "%u", ms->rtd[j].num); + sharkd_json_value_anyf("min", "%.9f", nstime_to_sec(&(ms->rtd[j].min))); + sharkd_json_value_anyf("max", "%.9f", nstime_to_sec(&(ms->rtd[j].max))); + sharkd_json_value_anyf("tot", "%.9f", nstime_to_sec(&(ms->rtd[j].tot))); + sharkd_json_value_anyf("min_frame", "%u", ms->rtd[j].min_num); + sharkd_json_value_anyf("max_frame", "%u", ms->rtd[j].max_num); - if (rtd_data->stat_table.num_rtds != 1) - { - /* like in tshark, display it on every row */ - sharkd_json_value_anyf("open_req", "%u", ms->open_req_num); - sharkd_json_value_anyf("disc_rsp", "%u", ms->disc_rsp_num); - sharkd_json_value_anyf("req_dup", "%u", ms->req_dup_num); - sharkd_json_value_anyf("rsp_dup", "%u", ms->rsp_dup_num); - } + if (rtd_data->stat_table.num_rtds != 1) + { + /* like in tshark, display it on every row */ + sharkd_json_value_anyf("open_req", "%u", ms->open_req_num); + sharkd_json_value_anyf("disc_rsp", "%u", ms->disc_rsp_num); + sharkd_json_value_anyf("req_dup", "%u", ms->req_dup_num); + sharkd_json_value_anyf("rsp_dup", "%u", ms->rsp_dup_num); + } - json_dumper_end_object(&dumper); - } - } - sharkd_json_array_close(); + json_dumper_end_object(&dumper); + } + } + sharkd_json_array_close(); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } static void sharkd_session_free_tap_rtd_cb(void *arg) { - rtd_data_t *rtd_data = (rtd_data_t *) arg; + rtd_data_t *rtd_data = (rtd_data_t *) arg; - free_rtd_table(&rtd_data->stat_table); - g_free(rtd_data); + free_rtd_table(&rtd_data->stat_table); + g_free(rtd_data); } /** @@ -2516,91 +2516,91 @@ sharkd_session_free_tap_rtd_cb(void *arg) static void sharkd_session_process_tap_srt_cb(void *arg) { - srt_data_t *srt_data = (srt_data_t *) arg; - register_srt_t *srt = (register_srt_t *) srt_data->user_data; + srt_data_t *srt_data = (srt_data_t *) arg; + register_srt_t *srt = (register_srt_t *) srt_data->user_data; - const char *filter = proto_get_protocol_filter_name(get_srt_proto_id(srt)); + const char *filter = proto_get_protocol_filter_name(get_srt_proto_id(srt)); - guint i; + guint i; - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("tap", "srt:%s", filter); - sharkd_json_value_string("type", "srt"); + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("tap", "srt:%s", filter); + sharkd_json_value_string("type", "srt"); - sharkd_json_array_open("tables"); - for (i = 0; i < srt_data->srt_array->len; i++) - { - /* SRT table */ - srt_stat_table *rst = g_array_index(srt_data->srt_array, srt_stat_table *, i); + sharkd_json_array_open("tables"); + for (i = 0; i < srt_data->srt_array->len; i++) + { + /* SRT table */ + srt_stat_table *rst = g_array_index(srt_data->srt_array, srt_stat_table *, i); - int j; + int j; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - if (rst->name) - sharkd_json_value_string("n", rst->name); - else if (rst->short_name) - sharkd_json_value_string("n", rst->short_name); - else - sharkd_json_value_stringf("n", "table%u", i); + if (rst->name) + sharkd_json_value_string("n", rst->name); + else if (rst->short_name) + sharkd_json_value_string("n", rst->short_name); + else + sharkd_json_value_stringf("n", "table%u", i); - if (rst->filter_string) - sharkd_json_value_string("f", rst->filter_string); + if (rst->filter_string) + sharkd_json_value_string("f", rst->filter_string); - if (rst->proc_column_name) - sharkd_json_value_string("c", rst->proc_column_name); + if (rst->proc_column_name) + sharkd_json_value_string("c", rst->proc_column_name); - sharkd_json_array_open("r"); - for (j = 0; j < rst->num_procs; j++) - { - /* SRT row */ - srt_procedure_t *proc = &rst->procedures[j]; + sharkd_json_array_open("r"); + for (j = 0; j < rst->num_procs; j++) + { + /* SRT row */ + srt_procedure_t *proc = &rst->procedures[j]; - if (proc->stats.num == 0) - continue; + if (proc->stats.num == 0) + continue; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_string("n", proc->procedure); + sharkd_json_value_string("n", proc->procedure); - if (rst->filter_string) - sharkd_json_value_anyf("idx", "%d", proc->proc_index); + if (rst->filter_string) + sharkd_json_value_anyf("idx", "%d", proc->proc_index); - sharkd_json_value_anyf("num", "%u", proc->stats.num); + sharkd_json_value_anyf("num", "%u", proc->stats.num); - sharkd_json_value_anyf("min", "%.9f", nstime_to_sec(&proc->stats.min)); - sharkd_json_value_anyf("max", "%.9f", nstime_to_sec(&proc->stats.max)); - sharkd_json_value_anyf("tot", "%.9f", nstime_to_sec(&proc->stats.tot)); + sharkd_json_value_anyf("min", "%.9f", nstime_to_sec(&proc->stats.min)); + sharkd_json_value_anyf("max", "%.9f", nstime_to_sec(&proc->stats.max)); + sharkd_json_value_anyf("tot", "%.9f", nstime_to_sec(&proc->stats.tot)); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } static void sharkd_session_free_tap_srt_cb(void *arg) { - srt_data_t *srt_data = (srt_data_t *) arg; - register_srt_t *srt = (register_srt_t *) srt_data->user_data; + srt_data_t *srt_data = (srt_data_t *) arg; + register_srt_t *srt = (register_srt_t *) srt_data->user_data; - free_srt_table(srt, srt_data->srt_array); - g_array_free(srt_data->srt_array, TRUE); - g_free(srt_data); + free_srt_table(srt, srt_data->srt_array); + g_array_free(srt_data->srt_array, TRUE); + g_free(srt_data); } struct sharkd_export_object_list { - struct sharkd_export_object_list *next; + struct sharkd_export_object_list *next; - char *type; - const char *proto; - GSList *entries; + char *type; + const char *proto; + GSList *entries; }; static struct sharkd_export_object_list *sharkd_eo_list; @@ -2622,62 +2622,62 @@ static struct sharkd_export_object_list *sharkd_eo_list; static void sharkd_session_process_tap_eo_cb(void *tapdata) { - export_object_list_t *tap_object = (export_object_list_t *) tapdata; - struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) tap_object->gui_data; - GSList *slist; - int i = 0; + export_object_list_t *tap_object = (export_object_list_t *) tapdata; + struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) tap_object->gui_data; + GSList *slist; + int i = 0; - json_dumper_begin_object(&dumper); - sharkd_json_value_string("tap", object_list->type); - sharkd_json_value_string("type", "eo"); + json_dumper_begin_object(&dumper); + sharkd_json_value_string("tap", object_list->type); + sharkd_json_value_string("type", "eo"); - sharkd_json_value_string("proto", object_list->proto); + sharkd_json_value_string("proto", object_list->proto); - sharkd_json_array_open("objects"); - for (slist = object_list->entries; slist; slist = slist->next) - { - const export_object_entry_t *eo_entry = (export_object_entry_t *) slist->data; + sharkd_json_array_open("objects"); + for (slist = object_list->entries; slist; slist = slist->next) + { + const export_object_entry_t *eo_entry = (export_object_entry_t *) slist->data; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_anyf("pkt", "%u", eo_entry->pkt_num); + sharkd_json_value_anyf("pkt", "%u", eo_entry->pkt_num); - if (eo_entry->hostname) - sharkd_json_value_string("hostname", eo_entry->hostname); + if (eo_entry->hostname) + sharkd_json_value_string("hostname", eo_entry->hostname); - if (eo_entry->content_type) - sharkd_json_value_string("type", eo_entry->content_type); + if (eo_entry->content_type) + sharkd_json_value_string("type", eo_entry->content_type); - if (eo_entry->filename) - sharkd_json_value_string("filename", eo_entry->filename); + if (eo_entry->filename) + sharkd_json_value_string("filename", eo_entry->filename); - sharkd_json_value_stringf("_download", "%s_%d", object_list->type, i); + sharkd_json_value_stringf("_download", "%s_%d", object_list->type, i); - sharkd_json_value_anyf("len", "%zu", eo_entry->payload_len); + sharkd_json_value_anyf("len", "%zu", eo_entry->payload_len); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); - i++; - } - sharkd_json_array_close(); + i++; + } + sharkd_json_array_close(); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } static void sharkd_eo_object_list_add_entry(void *gui_data, export_object_entry_t *entry) { - struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data; + struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data; - object_list->entries = g_slist_append(object_list->entries, entry); + object_list->entries = g_slist_append(object_list->entries, entry); } static export_object_entry_t * sharkd_eo_object_list_get_entry(void *gui_data, int row) { - struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data; + struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data; - return (export_object_entry_t *) g_slist_nth_data(object_list->entries, row); + return (export_object_entry_t *) g_slist_nth_data(object_list->entries, row); } /** @@ -2705,53 +2705,53 @@ sharkd_eo_object_list_get_entry(void *gui_data, int row) static void sharkd_session_process_tap_rtp_cb(void *arg) { - rtpstream_tapinfo_t *rtp_tapinfo = (rtpstream_tapinfo_t *) arg; + rtpstream_tapinfo_t *rtp_tapinfo = (rtpstream_tapinfo_t *) arg; - GList *listx; + GList *listx; - json_dumper_begin_object(&dumper); - sharkd_json_value_string("tap", "rtp-streams"); - sharkd_json_value_string("type", "rtp-streams"); + json_dumper_begin_object(&dumper); + sharkd_json_value_string("tap", "rtp-streams"); + sharkd_json_value_string("type", "rtp-streams"); - sharkd_json_array_open("streams"); - for (listx = g_list_first(rtp_tapinfo->strinfo_list); listx; listx = listx->next) - { - rtpstream_info_t *streaminfo = (rtpstream_info_t *) listx->data; - rtpstream_info_calc_t calc; + sharkd_json_array_open("streams"); + for (listx = g_list_first(rtp_tapinfo->strinfo_list); listx; listx = listx->next) + { + rtpstream_info_t *streaminfo = (rtpstream_info_t *) listx->data; + rtpstream_info_calc_t calc; - rtpstream_info_calculate(streaminfo, &calc); + rtpstream_info_calculate(streaminfo, &calc); - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_anyf("ssrc", "%u", calc.ssrc); - sharkd_json_value_string("payload", calc.all_payload_type_names); + sharkd_json_value_anyf("ssrc", "%u", calc.ssrc); + sharkd_json_value_string("payload", calc.all_payload_type_names); - sharkd_json_value_string("saddr", calc.src_addr_str); - sharkd_json_value_anyf("sport", "%u", calc.src_port); - sharkd_json_value_string("daddr", calc.dst_addr_str); - sharkd_json_value_anyf("dport", "%u", calc.dst_port); + sharkd_json_value_string("saddr", calc.src_addr_str); + sharkd_json_value_anyf("sport", "%u", calc.src_port); + sharkd_json_value_string("daddr", calc.dst_addr_str); + sharkd_json_value_anyf("dport", "%u", calc.dst_port); - sharkd_json_value_anyf("pkts", "%u", calc.packet_count); + sharkd_json_value_anyf("pkts", "%u", calc.packet_count); - sharkd_json_value_anyf("max_delta", "%f",calc.max_delta); - sharkd_json_value_anyf("max_jitter", "%f", calc.max_jitter); - sharkd_json_value_anyf("mean_jitter", "%f", calc.mean_jitter); + sharkd_json_value_anyf("max_delta", "%f",calc.max_delta); + sharkd_json_value_anyf("max_jitter", "%f", calc.max_jitter); + sharkd_json_value_anyf("mean_jitter", "%f", calc.mean_jitter); - sharkd_json_value_anyf("expectednr", "%u", calc.packet_expected); - sharkd_json_value_anyf("totalnr", "%u", calc.total_nr); + sharkd_json_value_anyf("expectednr", "%u", calc.packet_expected); + sharkd_json_value_anyf("totalnr", "%u", calc.total_nr); - sharkd_json_value_anyf("problem", calc.problem ? "true" : "false"); + sharkd_json_value_anyf("problem", calc.problem ? "true" : "false"); - /* for filter */ - sharkd_json_value_anyf("ipver", "%d", (streaminfo->id.src_addr.type == AT_IPv6) ? 6 : 4); + /* for filter */ + sharkd_json_value_anyf("ipver", "%d", (streaminfo->id.src_addr.type == AT_IPv6) ? 6 : 4); - rtpstream_info_calc_free(&calc); + rtpstream_info_calc_free(&calc); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); } /** @@ -2785,373 +2785,373 @@ sharkd_session_process_tap_rtp_cb(void *arg) static void sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count) { - void *taps_data[16]; - GFreeFunc taps_free[16]; - int taps_count = 0; - int i; + void *taps_data[16]; + GFreeFunc taps_free[16]; + int taps_count = 0; + int i; - rtpstream_tapinfo_t rtp_tapinfo = - { NULL, NULL, NULL, NULL, 0, NULL, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, FALSE, FALSE}; + rtpstream_tapinfo_t rtp_tapinfo = + { NULL, NULL, NULL, NULL, 0, NULL, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, FALSE, FALSE}; - for (i = 0; i < 16; i++) - { - char tapbuf[32]; - const char *tok_tap; + for (i = 0; i < 16; i++) + { + char tapbuf[32]; + const char *tok_tap; - void *tap_data = NULL; - GFreeFunc tap_free = NULL; - const char *tap_filter = ""; - GString *tap_error = NULL; + void *tap_data = NULL; + GFreeFunc tap_free = NULL; + const char *tap_filter = ""; + GString *tap_error = NULL; - snprintf(tapbuf, sizeof(tapbuf), "tap%d", i); - tok_tap = json_find_attr(buf, tokens, count, tapbuf); - if (!tok_tap) - break; + snprintf(tapbuf, sizeof(tapbuf), "tap%d", i); + tok_tap = json_find_attr(buf, tokens, count, tapbuf); + if (!tok_tap) + break; - if (!strncmp(tok_tap, "stat:", 5)) - { - stats_tree_cfg *cfg = stats_tree_get_cfg_by_abbr(tok_tap + 5); - stats_tree *st; + if (!strncmp(tok_tap, "stat:", 5)) + { + stats_tree_cfg *cfg = stats_tree_get_cfg_by_abbr(tok_tap + 5); + stats_tree *st; - if (!cfg) - { - sharkd_json_error( - rpcid, -11001, NULL, - "sharkd_session_process_tap() stat %s not found", tok_tap + 5 - ); - return; - } + if (!cfg) + { + sharkd_json_error( + rpcid, -11001, NULL, + "sharkd_session_process_tap() stat %s not found", tok_tap + 5 + ); + return; + } - st = stats_tree_new(cfg, NULL, tap_filter); + st = stats_tree_new(cfg, NULL, tap_filter); - tap_error = register_tap_listener(st->cfg->tapname, st, st->filter, st->cfg->flags, stats_tree_reset, stats_tree_packet, sharkd_session_process_tap_stats_cb, NULL); + tap_error = register_tap_listener(st->cfg->tapname, st, st->filter, st->cfg->flags, stats_tree_reset, stats_tree_packet, sharkd_session_process_tap_stats_cb, NULL); - if (!tap_error && cfg->init) - cfg->init(st); + if (!tap_error && cfg->init) + cfg->init(st); - tap_data = st; - tap_free = sharkd_session_free_tap_stats_cb; - } - else if (!strcmp(tok_tap, "expert")) - { - struct sharkd_expert_tap *expert_tap; + tap_data = st; + tap_free = sharkd_session_free_tap_stats_cb; + } + else if (!strcmp(tok_tap, "expert")) + { + struct sharkd_expert_tap *expert_tap; - expert_tap = g_new0(struct sharkd_expert_tap, 1); - expert_tap->text = g_string_chunk_new(100); + expert_tap = g_new0(struct sharkd_expert_tap, 1); + expert_tap->text = g_string_chunk_new(100); - tap_error = register_tap_listener("expert", expert_tap, NULL, 0, NULL, sharkd_session_packet_tap_expert_cb, sharkd_session_process_tap_expert_cb, NULL); + tap_error = register_tap_listener("expert", expert_tap, NULL, 0, NULL, sharkd_session_packet_tap_expert_cb, sharkd_session_process_tap_expert_cb, NULL); - tap_data = expert_tap; - tap_free = sharkd_session_free_tap_expert_cb; - } - else if (!strncmp(tok_tap, "seqa:", 5)) - { - seq_analysis_info_t *graph_analysis; - register_analysis_t *analysis; - const char *tap_name; - tap_packet_cb tap_func; - guint tap_flags; + tap_data = expert_tap; + tap_free = sharkd_session_free_tap_expert_cb; + } + else if (!strncmp(tok_tap, "seqa:", 5)) + { + seq_analysis_info_t *graph_analysis; + register_analysis_t *analysis; + const char *tap_name; + tap_packet_cb tap_func; + guint tap_flags; - analysis = sequence_analysis_find_by_name(tok_tap + 5); - if (!analysis) - { - sharkd_json_error( - rpcid, -11002, NULL, - "sharkd_session_process_tap() seq analysis %s not found", tok_tap + 5 - ); - return; - } + analysis = sequence_analysis_find_by_name(tok_tap + 5); + if (!analysis) + { + sharkd_json_error( + rpcid, -11002, NULL, + "sharkd_session_process_tap() seq analysis %s not found", tok_tap + 5 + ); + return; + } - graph_analysis = sequence_analysis_info_new(); - graph_analysis->name = tok_tap + 5; - /* TODO, make configurable */ - graph_analysis->any_addr = FALSE; + graph_analysis = sequence_analysis_info_new(); + graph_analysis->name = tok_tap + 5; + /* TODO, make configurable */ + graph_analysis->any_addr = FALSE; - tap_name = sequence_analysis_get_tap_listener_name(analysis); - tap_flags = sequence_analysis_get_tap_flags(analysis); - tap_func = sequence_analysis_get_packet_func(analysis); + tap_name = sequence_analysis_get_tap_listener_name(analysis); + tap_flags = sequence_analysis_get_tap_flags(analysis); + tap_func = sequence_analysis_get_packet_func(analysis); - tap_error = register_tap_listener(tap_name, graph_analysis, NULL, tap_flags, NULL, tap_func, sharkd_session_process_tap_flow_cb, NULL); + tap_error = register_tap_listener(tap_name, graph_analysis, NULL, tap_flags, NULL, tap_func, sharkd_session_process_tap_flow_cb, NULL); - tap_data = graph_analysis; - tap_free = sharkd_session_free_tap_flow_cb; - } - else if (!strncmp(tok_tap, "conv:", 5) || !strncmp(tok_tap, "endpt:", 6)) - { - struct register_ct *ct = NULL; - const char *ct_tapname; - struct sharkd_conv_tap_data *ct_data; - tap_packet_cb tap_func = NULL; + tap_data = graph_analysis; + tap_free = sharkd_session_free_tap_flow_cb; + } + else if (!strncmp(tok_tap, "conv:", 5) || !strncmp(tok_tap, "endpt:", 6)) + { + struct register_ct *ct = NULL; + const char *ct_tapname; + struct sharkd_conv_tap_data *ct_data; + tap_packet_cb tap_func = NULL; - if (!strncmp(tok_tap, "conv:", 5)) - { - ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 5)); + if (!strncmp(tok_tap, "conv:", 5)) + { + ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 5)); - if (!ct || !(tap_func = get_conversation_packet_func(ct))) - { - sharkd_json_error( - rpcid, -11003, NULL, - "sharkd_session_process_tap() conv %s not found", tok_tap + 5 - ); - return; - } - } - else if (!strncmp(tok_tap, "endpt:", 6)) - { - ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 6)); + if (!ct || !(tap_func = get_conversation_packet_func(ct))) + { + sharkd_json_error( + rpcid, -11003, NULL, + "sharkd_session_process_tap() conv %s not found", tok_tap + 5 + ); + return; + } + } + else if (!strncmp(tok_tap, "endpt:", 6)) + { + ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 6)); - if (!ct || !(tap_func = get_hostlist_packet_func(ct))) - { - sharkd_json_error( - rpcid, -11004, NULL, - "sharkd_session_process_tap() endpt %s not found", tok_tap + 6 - ); - return; - } - } - else - { - sharkd_json_error( - rpcid, -11005, NULL, - "sharkd_session_process_tap() conv/endpt(?): %s not found", tok_tap - ); - return; - } + if (!ct || !(tap_func = get_hostlist_packet_func(ct))) + { + sharkd_json_error( + rpcid, -11004, NULL, + "sharkd_session_process_tap() endpt %s not found", tok_tap + 6 + ); + return; + } + } + else + { + sharkd_json_error( + rpcid, -11005, NULL, + "sharkd_session_process_tap() conv/endpt(?): %s not found", tok_tap + ); + return; + } - ct_tapname = proto_get_protocol_filter_name(get_conversation_proto_id(ct)); + ct_tapname = proto_get_protocol_filter_name(get_conversation_proto_id(ct)); - ct_data = g_new0(struct sharkd_conv_tap_data, 1); - ct_data->type = tok_tap; - ct_data->hash.user_data = ct_data; + ct_data = g_new0(struct sharkd_conv_tap_data, 1); + ct_data->type = tok_tap; + ct_data->hash.user_data = ct_data; - /* XXX: make configurable */ - ct_data->resolve_name = TRUE; - ct_data->resolve_port = TRUE; + /* XXX: make configurable */ + ct_data->resolve_name = TRUE; + ct_data->resolve_port = TRUE; - tap_error = register_tap_listener(ct_tapname, &ct_data->hash, tap_filter, 0, NULL, tap_func, sharkd_session_process_tap_conv_cb, NULL); + tap_error = register_tap_listener(ct_tapname, &ct_data->hash, tap_filter, 0, NULL, tap_func, sharkd_session_process_tap_conv_cb, NULL); - tap_data = &ct_data->hash; - tap_free = sharkd_session_free_tap_conv_cb; - } - else if (!strncmp(tok_tap, "nstat:", 6)) - { - stat_tap_table_ui *stat_tap = stat_tap_by_name(tok_tap + 6); - stat_data_t *stat_data; + tap_data = &ct_data->hash; + tap_free = sharkd_session_free_tap_conv_cb; + } + else if (!strncmp(tok_tap, "nstat:", 6)) + { + stat_tap_table_ui *stat_tap = stat_tap_by_name(tok_tap + 6); + stat_data_t *stat_data; - if (!stat_tap) - { - sharkd_json_error( - rpcid, -11006, NULL, - "sharkd_session_process_tap() nstat=%s not found", tok_tap + 6 - ); - return; - } + if (!stat_tap) + { + sharkd_json_error( + rpcid, -11006, NULL, + "sharkd_session_process_tap() nstat=%s not found", tok_tap + 6 + ); + return; + } - stat_tap->stat_tap_init_cb(stat_tap); + stat_tap->stat_tap_init_cb(stat_tap); - stat_data = g_new0(stat_data_t, 1); - stat_data->stat_tap_data = stat_tap; - stat_data->user_data = NULL; + stat_data = g_new0(stat_data_t, 1); + stat_data->stat_tap_data = stat_tap; + stat_data->user_data = NULL; - tap_error = register_tap_listener(stat_tap->tap_name, stat_data, tap_filter, 0, NULL, stat_tap->packet_func, sharkd_session_process_tap_nstat_cb, NULL); + tap_error = register_tap_listener(stat_tap->tap_name, stat_data, tap_filter, 0, NULL, stat_tap->packet_func, sharkd_session_process_tap_nstat_cb, NULL); - tap_data = stat_data; - tap_free = sharkd_session_free_tap_nstat_cb; - } - else if (!strncmp(tok_tap, "rtd:", 4)) - { - register_rtd_t *rtd = get_rtd_table_by_name(tok_tap + 4); - rtd_data_t *rtd_data; - char *err; + tap_data = stat_data; + tap_free = sharkd_session_free_tap_nstat_cb; + } + else if (!strncmp(tok_tap, "rtd:", 4)) + { + register_rtd_t *rtd = get_rtd_table_by_name(tok_tap + 4); + rtd_data_t *rtd_data; + char *err; - if (!rtd) - { - sharkd_json_error( - rpcid, -11007, NULL, - "sharkd_session_process_tap() rtd=%s not found", tok_tap + 4 - ); - return; - } + if (!rtd) + { + sharkd_json_error( + rpcid, -11007, NULL, + "sharkd_session_process_tap() rtd=%s not found", tok_tap + 4 + ); + return; + } - rtd_table_get_filter(rtd, "", &tap_filter, &err); - if (err != NULL) - { - sharkd_json_error( - rpcid, -11008, NULL, - "sharkd_session_process_tap() rtd=%s err=%s", tok_tap + 4, err - ); - g_free(err); - return; - } + rtd_table_get_filter(rtd, "", &tap_filter, &err); + if (err != NULL) + { + sharkd_json_error( + rpcid, -11008, NULL, + "sharkd_session_process_tap() rtd=%s err=%s", tok_tap + 4, err + ); + g_free(err); + return; + } - rtd_data = g_new0(rtd_data_t, 1); - rtd_data->user_data = rtd; - rtd_table_dissector_init(rtd, &rtd_data->stat_table, NULL, NULL); + rtd_data = g_new0(rtd_data_t, 1); + rtd_data->user_data = rtd; + rtd_table_dissector_init(rtd, &rtd_data->stat_table, NULL, NULL); - tap_error = register_tap_listener(get_rtd_tap_listener_name(rtd), rtd_data, tap_filter, 0, NULL, get_rtd_packet_func(rtd), sharkd_session_process_tap_rtd_cb, NULL); + tap_error = register_tap_listener(get_rtd_tap_listener_name(rtd), rtd_data, tap_filter, 0, NULL, get_rtd_packet_func(rtd), sharkd_session_process_tap_rtd_cb, NULL); - tap_data = rtd_data; - tap_free = sharkd_session_free_tap_rtd_cb; - } - else if (!strncmp(tok_tap, "srt:", 4)) - { - register_srt_t *srt = get_srt_table_by_name(tok_tap + 4); - srt_data_t *srt_data; - char *err; + tap_data = rtd_data; + tap_free = sharkd_session_free_tap_rtd_cb; + } + else if (!strncmp(tok_tap, "srt:", 4)) + { + register_srt_t *srt = get_srt_table_by_name(tok_tap + 4); + srt_data_t *srt_data; + char *err; - if (!srt) - { - sharkd_json_error( - rpcid, -11009, NULL, - "sharkd_session_process_tap() srt=%s not found", tok_tap + 4 - ); - return; - } + if (!srt) + { + sharkd_json_error( + rpcid, -11009, NULL, + "sharkd_session_process_tap() srt=%s not found", tok_tap + 4 + ); + return; + } - srt_table_get_filter(srt, "", &tap_filter, &err); - if (err != NULL) - { - sharkd_json_error( - rpcid, -11010, NULL, - "sharkd_session_process_tap() srt=%s err=%s", tok_tap + 4, err - ); - g_free(err); - return; - } + srt_table_get_filter(srt, "", &tap_filter, &err); + if (err != NULL) + { + sharkd_json_error( + rpcid, -11010, NULL, + "sharkd_session_process_tap() srt=%s err=%s", tok_tap + 4, err + ); + g_free(err); + return; + } - srt_data = g_new0(srt_data_t, 1); - srt_data->srt_array = g_array_new(FALSE, TRUE, sizeof(srt_stat_table *)); - srt_data->user_data = srt; - srt_table_dissector_init(srt, srt_data->srt_array); + srt_data = g_new0(srt_data_t, 1); + srt_data->srt_array = g_array_new(FALSE, TRUE, sizeof(srt_stat_table *)); + srt_data->user_data = srt; + srt_table_dissector_init(srt, srt_data->srt_array); - tap_error = register_tap_listener(get_srt_tap_listener_name(srt), srt_data, tap_filter, 0, NULL, get_srt_packet_func(srt), sharkd_session_process_tap_srt_cb, NULL); + tap_error = register_tap_listener(get_srt_tap_listener_name(srt), srt_data, tap_filter, 0, NULL, get_srt_packet_func(srt), sharkd_session_process_tap_srt_cb, NULL); - tap_data = srt_data; - tap_free = sharkd_session_free_tap_srt_cb; - } - else if (!strncmp(tok_tap, "eo:", 3)) - { - register_eo_t *eo = get_eo_by_name(tok_tap + 3); - export_object_list_t *eo_object; - struct sharkd_export_object_list *object_list; + tap_data = srt_data; + tap_free = sharkd_session_free_tap_srt_cb; + } + else if (!strncmp(tok_tap, "eo:", 3)) + { + register_eo_t *eo = get_eo_by_name(tok_tap + 3); + export_object_list_t *eo_object; + struct sharkd_export_object_list *object_list; - if (!eo) - { - sharkd_json_error( - rpcid, -11011, NULL, - "sharkd_session_process_tap() eo=%s not found", tok_tap + 3 - ); - return; - } + if (!eo) + { + sharkd_json_error( + rpcid, -11011, NULL, + "sharkd_session_process_tap() eo=%s not found", tok_tap + 3 + ); + return; + } - for (object_list = sharkd_eo_list; object_list; object_list = object_list->next) - { - if (!strcmp(object_list->type, tok_tap)) - { - g_slist_free_full(object_list->entries, (GDestroyNotify) eo_free_entry); - object_list->entries = NULL; - break; - } - } + for (object_list = sharkd_eo_list; object_list; object_list = object_list->next) + { + if (!strcmp(object_list->type, tok_tap)) + { + g_slist_free_full(object_list->entries, (GDestroyNotify) eo_free_entry); + object_list->entries = NULL; + break; + } + } - if (!object_list) - { - object_list = g_new(struct sharkd_export_object_list, 1); - object_list->type = g_strdup(tok_tap); - object_list->proto = proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo))); - object_list->entries = NULL; - object_list->next = sharkd_eo_list; - sharkd_eo_list = object_list; - } + if (!object_list) + { + object_list = g_new(struct sharkd_export_object_list, 1); + object_list->type = g_strdup(tok_tap); + object_list->proto = proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo))); + object_list->entries = NULL; + object_list->next = sharkd_eo_list; + sharkd_eo_list = object_list; + } - eo_object = g_new0(export_object_list_t, 1); - eo_object->add_entry = sharkd_eo_object_list_add_entry; - eo_object->get_entry = sharkd_eo_object_list_get_entry; - eo_object->gui_data = (void *) object_list; + eo_object = g_new0(export_object_list_t, 1); + eo_object->add_entry = sharkd_eo_object_list_add_entry; + eo_object->get_entry = sharkd_eo_object_list_get_entry; + eo_object->gui_data = (void *) object_list; - tap_error = register_tap_listener(get_eo_tap_listener_name(eo), eo_object, NULL, 0, NULL, get_eo_packet_func(eo), sharkd_session_process_tap_eo_cb, NULL); + tap_error = register_tap_listener(get_eo_tap_listener_name(eo), eo_object, NULL, 0, NULL, get_eo_packet_func(eo), sharkd_session_process_tap_eo_cb, NULL); - tap_data = eo_object; - tap_free = g_free; /* need to free only eo_object, object_list need to be kept for potential download */ - } - else if (!strcmp(tok_tap, "rtp-streams")) - { - tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet_cb, sharkd_session_process_tap_rtp_cb, NULL); + tap_data = eo_object; + tap_free = g_free; /* need to free only eo_object, object_list need to be kept for potential download */ + } + else if (!strcmp(tok_tap, "rtp-streams")) + { + tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet_cb, sharkd_session_process_tap_rtp_cb, NULL); - tap_data = &rtp_tapinfo; - tap_free = rtpstream_reset_cb; - } - else if (!strncmp(tok_tap, "rtp-analyse:", 12)) - { - struct sharkd_analyse_rtp *rtp_req; + tap_data = &rtp_tapinfo; + tap_free = rtpstream_reset_cb; + } + else if (!strncmp(tok_tap, "rtp-analyse:", 12)) + { + struct sharkd_analyse_rtp *rtp_req; - rtp_req = (struct sharkd_analyse_rtp *) g_malloc0(sizeof(*rtp_req)); - if (!sharkd_rtp_match_init(&rtp_req->id, tok_tap + 12)) - { - rtpstream_id_free(&rtp_req->id); - g_free(rtp_req); - continue; - } + rtp_req = (struct sharkd_analyse_rtp *) g_malloc0(sizeof(*rtp_req)); + if (!sharkd_rtp_match_init(&rtp_req->id, tok_tap + 12)) + { + rtpstream_id_free(&rtp_req->id); + g_free(rtp_req); + continue; + } - rtp_req->tap_name = tok_tap; - rtp_req->statinfo.first_packet = TRUE; - rtp_req->statinfo.reg_pt = PT_UNDEFINED; + rtp_req->tap_name = tok_tap; + rtp_req->statinfo.first_packet = TRUE; + rtp_req->statinfo.reg_pt = PT_UNDEFINED; - tap_error = register_tap_listener("rtp", rtp_req, tap_filter, 0, NULL, sharkd_session_packet_tap_rtp_analyse_cb, sharkd_session_process_tap_rtp_analyse_cb, NULL); + tap_error = register_tap_listener("rtp", rtp_req, tap_filter, 0, NULL, sharkd_session_packet_tap_rtp_analyse_cb, sharkd_session_process_tap_rtp_analyse_cb, NULL); - tap_data = rtp_req; - tap_free = sharkd_session_process_tap_rtp_free_cb; - } - else - { - sharkd_json_error( - rpcid, -11012, NULL, - "sharkd_session_process_tap() %s not recognized", tok_tap - ); - return; - } + tap_data = rtp_req; + tap_free = sharkd_session_process_tap_rtp_free_cb; + } + else + { + sharkd_json_error( + rpcid, -11012, NULL, + "sharkd_session_process_tap() %s not recognized", tok_tap + ); + return; + } - if (tap_error) - { - sharkd_json_error( - rpcid, -11013, NULL, - "sharkd_session_process_tap() name=%s error=%s", tok_tap, tap_error->str - ); - g_string_free(tap_error, TRUE); - if (tap_free) - tap_free(tap_data); - return; - } + if (tap_error) + { + sharkd_json_error( + rpcid, -11013, NULL, + "sharkd_session_process_tap() name=%s error=%s", tok_tap, tap_error->str + ); + g_string_free(tap_error, TRUE); + if (tap_free) + tap_free(tap_data); + return; + } - taps_data[taps_count] = tap_data; - taps_free[taps_count] = tap_free; - taps_count++; - } + taps_data[taps_count] = tap_data; + taps_free[taps_count] = tap_free; + taps_count++; + } - fprintf(stderr, "sharkd_session_process_tap() count=%d\n", taps_count); - if (taps_count == 0) - { - sharkd_json_result_prologue(rpcid); - sharkd_json_array_open("taps"); - sharkd_json_array_close(); - sharkd_json_result_epilogue(); - return; - } + fprintf(stderr, "sharkd_session_process_tap() count=%d\n", taps_count); + if (taps_count == 0) + { + sharkd_json_result_prologue(rpcid); + sharkd_json_array_open("taps"); + sharkd_json_array_close(); + sharkd_json_result_epilogue(); + return; + } - sharkd_json_result_prologue(rpcid); - sharkd_json_array_open("taps"); - sharkd_retap(); - sharkd_json_array_close(); - sharkd_json_result_epilogue(); + sharkd_json_result_prologue(rpcid); + sharkd_json_array_open("taps"); + sharkd_retap(); + sharkd_json_array_close(); + sharkd_json_result_epilogue(); - for (i = 0; i < taps_count; i++) - { - if (taps_data[i]) - remove_tap_listener(taps_data[i]); + for (i = 0; i < taps_count; i++) + { + if (taps_data[i]) + remove_tap_listener(taps_data[i]); - if (taps_free[i]) - taps_free[i](taps_data[i]); - } + if (taps_free[i]) + taps_free[i](taps_data[i]); + } } /** @@ -3180,453 +3180,453 @@ sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count) static void sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_follow = json_find_attr(buf, tokens, count, "follow"); - const char *tok_filter = json_find_attr(buf, tokens, count, "filter"); + const char *tok_follow = json_find_attr(buf, tokens, count, "follow"); + const char *tok_filter = json_find_attr(buf, tokens, count, "filter"); - register_follow_t *follower; - GString *tap_error; + register_follow_t *follower; + GString *tap_error; - follow_info_t *follow_info; - const char *host; - char *port; + follow_info_t *follow_info; + const char *host; + char *port; - follower = get_follow_by_name(tok_follow); - if (!follower) - { - sharkd_json_error( - rpcid, -12001, NULL, - "sharkd_session_process_follow() follower=%s not found", tok_follow - ); - return; - } + follower = get_follow_by_name(tok_follow); + if (!follower) + { + sharkd_json_error( + rpcid, -12001, NULL, + "sharkd_session_process_follow() follower=%s not found", tok_follow + ); + return; + } - /* follow_reset_stream ? */ - follow_info = g_new0(follow_info_t, 1); - /* gui_data, filter_out_filter not set, but not used by dissector */ + /* follow_reset_stream ? */ + follow_info = g_new0(follow_info_t, 1); + /* gui_data, filter_out_filter not set, but not used by dissector */ - tap_error = register_tap_listener(get_follow_tap_string(follower), follow_info, tok_filter, 0, NULL, get_follow_tap_handler(follower), NULL, NULL); - if (tap_error) - { - sharkd_json_error( - rpcid, -12002, NULL, - "sharkd_session_process_follow() name=%s error=%s", tok_follow, tap_error->str - ); - g_string_free(tap_error, TRUE); - g_free(follow_info); - return; - } + tap_error = register_tap_listener(get_follow_tap_string(follower), follow_info, tok_filter, 0, NULL, get_follow_tap_handler(follower), NULL, NULL); + if (tap_error) + { + sharkd_json_error( + rpcid, -12002, NULL, + "sharkd_session_process_follow() name=%s error=%s", tok_follow, tap_error->str + ); + g_string_free(tap_error, TRUE); + g_free(follow_info); + return; + } - sharkd_retap(); + sharkd_retap(); - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - /* Server information: hostname, port, bytes sent */ - host = address_to_name(&follow_info->server_ip); - sharkd_json_value_string("shost", host); + /* Server information: hostname, port, bytes sent */ + host = address_to_name(&follow_info->server_ip); + sharkd_json_value_string("shost", host); - port = get_follow_port_to_display(follower)(NULL, follow_info->server_port); - sharkd_json_value_string("sport", port); - wmem_free(NULL, port); + port = get_follow_port_to_display(follower)(NULL, follow_info->server_port); + sharkd_json_value_string("sport", port); + wmem_free(NULL, port); - sharkd_json_value_anyf("sbytes", "%u", follow_info->bytes_written[0]); + sharkd_json_value_anyf("sbytes", "%u", follow_info->bytes_written[0]); - /* Client information: hostname, port, bytes sent */ - host = address_to_name(&follow_info->client_ip); - sharkd_json_value_string("chost", host); + /* Client information: hostname, port, bytes sent */ + host = address_to_name(&follow_info->client_ip); + sharkd_json_value_string("chost", host); - port = get_follow_port_to_display(follower)(NULL, follow_info->client_port); - sharkd_json_value_string("cport", port); - wmem_free(NULL, port); + port = get_follow_port_to_display(follower)(NULL, follow_info->client_port); + sharkd_json_value_string("cport", port); + wmem_free(NULL, port); - sharkd_json_value_anyf("cbytes", "%u", follow_info->bytes_written[1]); + sharkd_json_value_anyf("cbytes", "%u", follow_info->bytes_written[1]); - if (follow_info->payload) - { - follow_record_t *follow_record; - GList *cur; + if (follow_info->payload) + { + follow_record_t *follow_record; + GList *cur; - sharkd_json_array_open("payloads"); - for (cur = g_list_last(follow_info->payload); cur; cur = g_list_previous(cur)) - { - follow_record = (follow_record_t *) cur->data; + sharkd_json_array_open("payloads"); + for (cur = g_list_last(follow_info->payload); cur; cur = g_list_previous(cur)) + { + follow_record = (follow_record_t *) cur->data; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - sharkd_json_value_anyf("n", "%u", follow_record->packet_num); - sharkd_json_value_base64("d", follow_record->data->data, follow_record->data->len); + sharkd_json_value_anyf("n", "%u", follow_record->packet_num); + sharkd_json_value_base64("d", follow_record->data->data, follow_record->data->len); - if (follow_record->is_server) - sharkd_json_value_anyf("s", "%d", 1); + if (follow_record->is_server) + sharkd_json_value_anyf("s", "%d", 1); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); - } + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); + } - sharkd_json_result_epilogue(); + sharkd_json_result_epilogue(); - remove_tap_listener(follow_info); - follow_info_free(follow_info); + remove_tap_listener(follow_info); + follow_info_free(follow_info); } static void sharkd_session_process_frame_cb_tree(epan_dissect_t *edt, proto_tree *tree, tvbuff_t **tvbs, gboolean display_hidden) { - proto_node *node; + proto_node *node; - sharkd_json_array_open(NULL); - for (node = tree->first_child; node; node = node->next) - { - field_info *finfo = PNODE_FINFO(node); + sharkd_json_array_open(NULL); + for (node = tree->first_child; node; node = node->next) + { + field_info *finfo = PNODE_FINFO(node); - if (!finfo) - continue; + if (!finfo) + continue; - if (!display_hidden && FI_GET_FLAG(finfo, FI_HIDDEN)) - continue; + if (!display_hidden && FI_GET_FLAG(finfo, FI_HIDDEN)) + continue; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - if (!finfo->rep) - { - char label_str[ITEM_LABEL_LENGTH]; + if (!finfo->rep) + { + char label_str[ITEM_LABEL_LENGTH]; - label_str[0] = '\0'; - proto_item_fill_label(finfo, label_str); - sharkd_json_value_string("l", label_str); - } - else - { - sharkd_json_value_string("l", finfo->rep->representation); - } + label_str[0] = '\0'; + proto_item_fill_label(finfo, label_str); + sharkd_json_value_string("l", label_str); + } + else + { + sharkd_json_value_string("l", finfo->rep->representation); + } - if (finfo->ds_tvb && tvbs && tvbs[0] != finfo->ds_tvb) - { - int idx; + if (finfo->ds_tvb && tvbs && tvbs[0] != finfo->ds_tvb) + { + int idx; - for (idx = 1; tvbs[idx]; idx++) - { - if (tvbs[idx] == finfo->ds_tvb) - { - sharkd_json_value_anyf("ds", "%d", idx); - break; - } - } - } + for (idx = 1; tvbs[idx]; idx++) + { + if (tvbs[idx] == finfo->ds_tvb) + { + sharkd_json_value_anyf("ds", "%d", idx); + break; + } + } + } - if (finfo->start >= 0 && finfo->length > 0) - sharkd_json_value_anyf("h", "[%d,%d]", finfo->start, finfo->length); + if (finfo->start >= 0 && finfo->length > 0) + sharkd_json_value_anyf("h", "[%d,%d]", finfo->start, finfo->length); - if (finfo->appendix_start >= 0 && finfo->appendix_length > 0) - sharkd_json_value_anyf("i", "[%d,%d]", finfo->appendix_start, finfo->appendix_length); + if (finfo->appendix_start >= 0 && finfo->appendix_length > 0) + sharkd_json_value_anyf("i", "[%d,%d]", finfo->appendix_start, finfo->appendix_length); - if (finfo->hfinfo) - { - char *filter; + if (finfo->hfinfo) + { + char *filter; - if (finfo->hfinfo->type == FT_PROTOCOL) - { - sharkd_json_value_string("t", "proto"); - } - else if (finfo->hfinfo->type == FT_FRAMENUM) - { - sharkd_json_value_string("t", "framenum"); - sharkd_json_value_anyf("fnum", "%u", finfo->value.value.uinteger); - } - else if (FI_GET_FLAG(finfo, FI_URL) && IS_FT_STRING(finfo->hfinfo->type)) - { - char *url = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, finfo->hfinfo->display); + if (finfo->hfinfo->type == FT_PROTOCOL) + { + sharkd_json_value_string("t", "proto"); + } + else if (finfo->hfinfo->type == FT_FRAMENUM) + { + sharkd_json_value_string("t", "framenum"); + sharkd_json_value_anyf("fnum", "%u", finfo->value.value.uinteger); + } + else if (FI_GET_FLAG(finfo, FI_URL) && IS_FT_STRING(finfo->hfinfo->type)) + { + char *url = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, finfo->hfinfo->display); - sharkd_json_value_string("t", "url"); - sharkd_json_value_string("url", url); - wmem_free(NULL, url); - } + sharkd_json_value_string("t", "url"); + sharkd_json_value_string("url", url); + wmem_free(NULL, url); + } - filter = proto_construct_match_selected_string(finfo, edt); - if (filter) - { - sharkd_json_value_string("f", filter); - wmem_free(NULL, filter); - } - } + filter = proto_construct_match_selected_string(finfo, edt); + if (filter) + { + sharkd_json_value_string("f", filter); + wmem_free(NULL, filter); + } + } - if (FI_GET_FLAG(finfo, FI_GENERATED)) - sharkd_json_value_anyf("g", "true"); + if (FI_GET_FLAG(finfo, FI_GENERATED)) + sharkd_json_value_anyf("g", "true"); - if (FI_GET_FLAG(finfo, FI_HIDDEN)) - sharkd_json_value_anyf("v", "true"); + if (FI_GET_FLAG(finfo, FI_HIDDEN)) + sharkd_json_value_anyf("v", "true"); - if (FI_GET_FLAG(finfo, PI_SEVERITY_MASK)) - { - const char *severity = try_val_to_str(FI_GET_FLAG(finfo, PI_SEVERITY_MASK), expert_severity_vals); + if (FI_GET_FLAG(finfo, PI_SEVERITY_MASK)) + { + const char *severity = try_val_to_str(FI_GET_FLAG(finfo, PI_SEVERITY_MASK), expert_severity_vals); - ws_assert(severity != NULL); + ws_assert(severity != NULL); - sharkd_json_value_string("s", severity); - } + sharkd_json_value_string("s", severity); + } - if (((proto_tree *) node)->first_child) - { - if (finfo->tree_type != -1) - sharkd_json_value_anyf("e", "%d", finfo->tree_type); + if (((proto_tree *) node)->first_child) + { + if (finfo->tree_type != -1) + sharkd_json_value_anyf("e", "%d", finfo->tree_type); - sharkd_json_value_anyf("n", NULL); - sharkd_session_process_frame_cb_tree(edt, (proto_tree *) node, tvbs, display_hidden); - } + sharkd_json_value_anyf("n", NULL); + sharkd_session_process_frame_cb_tree(edt, (proto_tree *) node, tvbs, display_hidden); + } - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); } static gboolean sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_data) { - register_follow_t *follower = (register_follow_t *) value; - packet_info *pi = (packet_info *) user_data; + register_follow_t *follower = (register_follow_t *) value; + packet_info *pi = (packet_info *) user_data; - const int proto_id = get_follow_proto_id(follower); + const int proto_id = get_follow_proto_id(follower); - guint32 ignore_stream; - guint32 ignore_sub_stream; + guint32 ignore_stream; + guint32 ignore_sub_stream; - if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id))) - { - const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); - char *follow_filter; + if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id))) + { + const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id)); + char *follow_filter; - follow_filter = get_follow_conv_func(follower)(NULL, pi, &ignore_stream, &ignore_sub_stream); + follow_filter = get_follow_conv_func(follower)(NULL, pi, &ignore_stream, &ignore_sub_stream); - json_dumper_begin_array(&dumper); - json_dumper_value_string(&dumper, layer_proto); - json_dumper_value_string(&dumper, follow_filter); - json_dumper_end_array(&dumper); + json_dumper_begin_array(&dumper); + json_dumper_value_string(&dumper, layer_proto); + json_dumper_value_string(&dumper, follow_filter); + json_dumper_end_array(&dumper); - g_free(follow_filter); - } + g_free(follow_filter); + } - return FALSE; + return FALSE; } struct sharkd_frame_request_data { - gboolean display_hidden; + gboolean display_hidden; }; static void sharkd_session_process_frame_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data) { - packet_info *pi = &edt->pi; - frame_data *fdata = pi->fd; - wtap_block_t pkt_block = NULL; + packet_info *pi = &edt->pi; + frame_data *fdata = pi->fd; + wtap_block_t pkt_block = NULL; - const struct sharkd_frame_request_data * const req_data = (const struct sharkd_frame_request_data * const) data; - const gboolean display_hidden = (req_data) ? req_data->display_hidden : FALSE; + const struct sharkd_frame_request_data * const req_data = (const struct sharkd_frame_request_data * const) data; + const gboolean display_hidden = (req_data) ? req_data->display_hidden : FALSE; - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - if (fdata->has_modified_block) - pkt_block = sharkd_get_modified_block(fdata); - else - pkt_block = pi->rec->block; + if (fdata->has_modified_block) + pkt_block = sharkd_get_modified_block(fdata); + else + pkt_block = pi->rec->block; - if (pkt_block) - { - guint i; - guint n; - gchar *comment; + if (pkt_block) + { + guint i; + guint n; + gchar *comment; - n = wtap_block_count_option(pkt_block, OPT_COMMENT); + n = wtap_block_count_option(pkt_block, OPT_COMMENT); - sharkd_json_array_open("comment"); - for (i = 0; i < n; i++) { - if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT, i, &comment)) { - sharkd_json_value_string(NULL, comment); - } - } - sharkd_json_array_close(); - } + sharkd_json_array_open("comment"); + for (i = 0; i < n; i++) { + if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT, i, &comment)) { + sharkd_json_value_string(NULL, comment); + } + } + sharkd_json_array_close(); + } - if (tree) - { - tvbuff_t **tvbs = NULL; + if (tree) + { + tvbuff_t **tvbs = NULL; - /* arrayize data src, to speedup searching for ds_tvb index */ - if (data_src && data_src->next /* only needed if there are more than one data source */) - { - guint count = g_slist_length((GSList *) data_src); - guint i; + /* arrayize data src, to speedup searching for ds_tvb index */ + if (data_src && data_src->next /* only needed if there are more than one data source */) + { + guint count = g_slist_length((GSList *) data_src); + guint i; - tvbs = (tvbuff_t **) g_malloc0((count + 1) * sizeof(*tvbs)); + tvbs = (tvbuff_t **) g_malloc0((count + 1) * sizeof(*tvbs)); - for (i = 0; i < count; i++) - { - const struct data_source *src = (const struct data_source *) g_slist_nth_data((GSList *) data_src, i); + for (i = 0; i < count; i++) + { + const struct data_source *src = (const struct data_source *) g_slist_nth_data((GSList *) data_src, i); - tvbs[i] = get_data_source_tvb(src); - } + tvbs[i] = get_data_source_tvb(src); + } - tvbs[count] = NULL; - } + tvbs[count] = NULL; + } - sharkd_json_value_anyf("tree", NULL); - sharkd_session_process_frame_cb_tree(edt, tree, tvbs, display_hidden); + sharkd_json_value_anyf("tree", NULL); + sharkd_session_process_frame_cb_tree(edt, tree, tvbs, display_hidden); - g_free(tvbs); - } + g_free(tvbs); + } - if (cinfo) - { - int col; + if (cinfo) + { + int col; - sharkd_json_array_open("col"); - for (col = 0; col < cinfo->num_cols; ++col) - { - const col_item_t *col_item = &cinfo->columns[col]; + sharkd_json_array_open("col"); + for (col = 0; col < cinfo->num_cols; ++col) + { + const col_item_t *col_item = &cinfo->columns[col]; - sharkd_json_value_string(NULL, col_item->col_data); - } - sharkd_json_array_close(); - } + sharkd_json_value_string(NULL, col_item->col_data); + } + sharkd_json_array_close(); + } - if (fdata->ignored) - sharkd_json_value_anyf("i", "true"); + if (fdata->ignored) + sharkd_json_value_anyf("i", "true"); - if (fdata->marked) - sharkd_json_value_anyf("m", "true"); + if (fdata->marked) + sharkd_json_value_anyf("m", "true"); - if (fdata->color_filter) - { - sharkd_json_value_stringf("bg", "%x", color_t_to_rgb(&fdata->color_filter->bg_color)); - sharkd_json_value_stringf("fg", "%x", color_t_to_rgb(&fdata->color_filter->fg_color)); - } + if (fdata->color_filter) + { + sharkd_json_value_stringf("bg", "%x", color_t_to_rgb(&fdata->color_filter->bg_color)); + sharkd_json_value_stringf("fg", "%x", color_t_to_rgb(&fdata->color_filter->fg_color)); + } - if (data_src) - { - struct data_source *src = (struct data_source *) data_src->data; - gboolean ds_open = FALSE; + if (data_src) + { + struct data_source *src = (struct data_source *) data_src->data; + gboolean ds_open = FALSE; - tvbuff_t *tvb; - guint length; + tvbuff_t *tvb; + guint length; - tvb = get_data_source_tvb(src); - length = tvb_captured_length(tvb); + tvb = get_data_source_tvb(src); + length = tvb_captured_length(tvb); - if (length != 0) - { - const guchar *cp = tvb_get_ptr(tvb, 0, length); + if (length != 0) + { + const guchar *cp = tvb_get_ptr(tvb, 0, length); - /* XXX pi.fd->encoding */ - sharkd_json_value_base64("bytes", cp, length); - } - else - { - sharkd_json_value_base64("bytes", "", 0); - } + /* XXX pi.fd->encoding */ + sharkd_json_value_base64("bytes", cp, length); + } + else + { + sharkd_json_value_base64("bytes", "", 0); + } - data_src = data_src->next; - if (data_src) - { - sharkd_json_array_open("ds"); - ds_open = TRUE; - } + data_src = data_src->next; + if (data_src) + { + sharkd_json_array_open("ds"); + ds_open = TRUE; + } - while (data_src) - { - src = (struct data_source *) data_src->data; + while (data_src) + { + src = (struct data_source *) data_src->data; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - { - char *src_name = get_data_source_name(src); + { + char *src_name = get_data_source_name(src); - sharkd_json_value_string("name", src_name); - wmem_free(NULL, src_name); - } + sharkd_json_value_string("name", src_name); + wmem_free(NULL, src_name); + } - tvb = get_data_source_tvb(src); - length = tvb_captured_length(tvb); + tvb = get_data_source_tvb(src); + length = tvb_captured_length(tvb); - if (length != 0) - { - const guchar *cp = tvb_get_ptr(tvb, 0, length); + if (length != 0) + { + const guchar *cp = tvb_get_ptr(tvb, 0, length); - /* XXX pi.fd->encoding */ - sharkd_json_value_base64("bytes", cp, length); - } - else - { - sharkd_json_value_base64("bytes", "", 0); - } + /* XXX pi.fd->encoding */ + sharkd_json_value_base64("bytes", cp, length); + } + else + { + sharkd_json_value_base64("bytes", "", 0); + } - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); - data_src = data_src->next; - } + data_src = data_src->next; + } - /* close ds, only if was opened */ - if (ds_open) - sharkd_json_array_close(); - } + /* close ds, only if was opened */ + if (ds_open) + sharkd_json_array_close(); + } - sharkd_json_array_open("fol"); - follow_iterate_followers(sharkd_follower_visit_layers_cb, pi); - sharkd_json_array_close(); + sharkd_json_array_open("fol"); + follow_iterate_followers(sharkd_follower_visit_layers_cb, pi); + sharkd_json_array_close(); - sharkd_json_result_epilogue(); + sharkd_json_result_epilogue(); } #define SHARKD_IOGRAPH_MAX_ITEMS 250000 /* 250k limit of items is taken from wireshark-qt, on x86_64 sizeof(io_graph_item_t) is 152, so single graph can take max 36 MB */ struct sharkd_iograph { - /* config */ - int hf_index; - io_graph_item_unit_t calc_type; - guint32 interval; + /* config */ + int hf_index; + io_graph_item_unit_t calc_type; + guint32 interval; - /* result */ - int space_items; - int num_items; - io_graph_item_t *items; - GString *error; + /* result */ + int space_items; + int num_items; + io_graph_item_t *items; + GString *error; }; static tap_packet_status sharkd_iograph_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, const void *dummy _U_) { - struct sharkd_iograph *graph = (struct sharkd_iograph *) g; - int idx; - gboolean update_succeeded; + struct sharkd_iograph *graph = (struct sharkd_iograph *) g; + int idx; + gboolean update_succeeded; - idx = get_io_graph_index(pinfo, graph->interval); - if (idx < 0 || idx >= SHARKD_IOGRAPH_MAX_ITEMS) - return TAP_PACKET_DONT_REDRAW; + idx = get_io_graph_index(pinfo, graph->interval); + if (idx < 0 || idx >= SHARKD_IOGRAPH_MAX_ITEMS) + return TAP_PACKET_DONT_REDRAW; - if (idx + 1 > graph->num_items) - { - if (idx + 1 > graph->space_items) - { - int new_size = idx + 1024; + if (idx + 1 > graph->num_items) + { + if (idx + 1 > graph->space_items) + { + int new_size = idx + 1024; - graph->items = (io_graph_item_t *) g_realloc(graph->items, sizeof(io_graph_item_t) * new_size); - reset_io_graph_items(&graph->items[graph->space_items], new_size - graph->space_items); + graph->items = (io_graph_item_t *) g_realloc(graph->items, sizeof(io_graph_item_t) * new_size); + reset_io_graph_items(&graph->items[graph->space_items], new_size - graph->space_items); - graph->space_items = new_size; - } - else if (graph->items == NULL) - { - graph->items = g_new(io_graph_item_t, graph->space_items); - reset_io_graph_items(graph->items, graph->space_items); - } + graph->space_items = new_size; + } + else if (graph->items == NULL) + { + graph->items = g_new(io_graph_item_t, graph->space_items); + reset_io_graph_items(graph->items, graph->space_items); + } - graph->num_items = idx + 1; - } + graph->num_items = idx + 1; + } - update_succeeded = update_io_graph_item(graph->items, idx, pinfo, edt, graph->hf_index, graph->calc_type, graph->interval); - /* XXX - TAP_PACKET_FAILED if the item couldn't be updated, with an error message? */ - return update_succeeded ? TAP_PACKET_REDRAW : TAP_PACKET_DONT_REDRAW; + update_succeeded = update_io_graph_item(graph->items, idx, pinfo, edt, graph->hf_index, graph->calc_type, graph->interval); + /* XXX - TAP_PACKET_FAILED if the item couldn't be updated, with an error message? */ + return update_succeeded ? TAP_PACKET_REDRAW : TAP_PACKET_DONT_REDRAW; } /** @@ -3652,141 +3652,141 @@ sharkd_iograph_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, const vo static void sharkd_session_process_iograph(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_interval = json_find_attr(buf, tokens, count, "interval"); - struct sharkd_iograph graphs[10]; - gboolean is_any_ok = FALSE; - int graph_count; + const char *tok_interval = json_find_attr(buf, tokens, count, "interval"); + struct sharkd_iograph graphs[10]; + gboolean is_any_ok = FALSE; + int graph_count; - guint32 interval_ms = 1000; /* default: one per second */ - int i; + guint32 interval_ms = 1000; /* default: one per second */ + int i; - if (tok_interval) - ws_strtou32(tok_interval, NULL, &interval_ms); + if (tok_interval) + ws_strtou32(tok_interval, NULL, &interval_ms); - for (i = graph_count = 0; i < (int) G_N_ELEMENTS(graphs); i++) - { - struct sharkd_iograph *graph = &graphs[graph_count]; + for (i = graph_count = 0; i < (int) G_N_ELEMENTS(graphs); i++) + { + struct sharkd_iograph *graph = &graphs[graph_count]; - const char *tok_graph; - const char *tok_filter; - char tok_format_buf[32]; - const char *field_name; + const char *tok_graph; + const char *tok_filter; + char tok_format_buf[32]; + const char *field_name; - snprintf(tok_format_buf, sizeof(tok_format_buf), "graph%d", i); - tok_graph = json_find_attr(buf, tokens, count, tok_format_buf); - if (!tok_graph) - break; + snprintf(tok_format_buf, sizeof(tok_format_buf), "graph%d", i); + tok_graph = json_find_attr(buf, tokens, count, tok_format_buf); + if (!tok_graph) + break; - snprintf(tok_format_buf, sizeof(tok_format_buf), "filter%d", i); - tok_filter = json_find_attr(buf, tokens, count, tok_format_buf); + snprintf(tok_format_buf, sizeof(tok_format_buf), "filter%d", i); + tok_filter = json_find_attr(buf, tokens, count, tok_format_buf); - if (!strcmp(tok_graph, "packets")) - graph->calc_type = IOG_ITEM_UNIT_PACKETS; - else if (!strcmp(tok_graph, "bytes")) - graph->calc_type = IOG_ITEM_UNIT_BYTES; - else if (!strcmp(tok_graph, "bits")) - graph->calc_type = IOG_ITEM_UNIT_BITS; - else if (g_str_has_prefix(tok_graph, "sum:")) - graph->calc_type = IOG_ITEM_UNIT_CALC_SUM; - else if (g_str_has_prefix(tok_graph, "frames:")) - graph->calc_type = IOG_ITEM_UNIT_CALC_FRAMES; - else if (g_str_has_prefix(tok_graph, "fields:")) - graph->calc_type = IOG_ITEM_UNIT_CALC_FIELDS; - else if (g_str_has_prefix(tok_graph, "max:")) - graph->calc_type = IOG_ITEM_UNIT_CALC_MAX; - else if (g_str_has_prefix(tok_graph, "min:")) - graph->calc_type = IOG_ITEM_UNIT_CALC_MIN; - else if (g_str_has_prefix(tok_graph, "avg:")) - graph->calc_type = IOG_ITEM_UNIT_CALC_AVERAGE; - else if (g_str_has_prefix(tok_graph, "load:")) - graph->calc_type = IOG_ITEM_UNIT_CALC_LOAD; - else - break; + if (!strcmp(tok_graph, "packets")) + graph->calc_type = IOG_ITEM_UNIT_PACKETS; + else if (!strcmp(tok_graph, "bytes")) + graph->calc_type = IOG_ITEM_UNIT_BYTES; + else if (!strcmp(tok_graph, "bits")) + graph->calc_type = IOG_ITEM_UNIT_BITS; + else if (g_str_has_prefix(tok_graph, "sum:")) + graph->calc_type = IOG_ITEM_UNIT_CALC_SUM; + else if (g_str_has_prefix(tok_graph, "frames:")) + graph->calc_type = IOG_ITEM_UNIT_CALC_FRAMES; + else if (g_str_has_prefix(tok_graph, "fields:")) + graph->calc_type = IOG_ITEM_UNIT_CALC_FIELDS; + else if (g_str_has_prefix(tok_graph, "max:")) + graph->calc_type = IOG_ITEM_UNIT_CALC_MAX; + else if (g_str_has_prefix(tok_graph, "min:")) + graph->calc_type = IOG_ITEM_UNIT_CALC_MIN; + else if (g_str_has_prefix(tok_graph, "avg:")) + graph->calc_type = IOG_ITEM_UNIT_CALC_AVERAGE; + else if (g_str_has_prefix(tok_graph, "load:")) + graph->calc_type = IOG_ITEM_UNIT_CALC_LOAD; + else + break; - field_name = strchr(tok_graph, ':'); - if (field_name) - field_name = field_name + 1; + field_name = strchr(tok_graph, ':'); + if (field_name) + field_name = field_name + 1; - graph->interval = interval_ms; + graph->interval = interval_ms; - graph->hf_index = -1; - graph->error = check_field_unit(field_name, &graph->hf_index, graph->calc_type); + graph->hf_index = -1; + graph->error = check_field_unit(field_name, &graph->hf_index, graph->calc_type); - graph->space_items = 0; /* TODO, can avoid realloc()s in sharkd_iograph_packet() by calculating: capture_time / interval */ - graph->num_items = 0; - graph->items = NULL; + graph->space_items = 0; /* TODO, can avoid realloc()s in sharkd_iograph_packet() by calculating: capture_time / interval */ + graph->num_items = 0; + graph->items = NULL; - if (!graph->error) - graph->error = register_tap_listener("frame", graph, tok_filter, TL_REQUIRES_PROTO_TREE, NULL, sharkd_iograph_packet, NULL, NULL); + if (!graph->error) + graph->error = register_tap_listener("frame", graph, tok_filter, TL_REQUIRES_PROTO_TREE, NULL, sharkd_iograph_packet, NULL, NULL); - graph_count++; + graph_count++; - if (graph->error) - { - sharkd_json_error( - rpcid, -6001, NULL, - "%s", graph->error->str - ); - g_string_free(graph->error, TRUE); - return; - } + if (graph->error) + { + sharkd_json_error( + rpcid, -6001, NULL, + "%s", graph->error->str + ); + g_string_free(graph->error, TRUE); + return; + } - if (graph->error == NULL) - is_any_ok = TRUE; - } + if (graph->error == NULL) + is_any_ok = TRUE; + } - /* retap only if we have at least one ok */ - if (is_any_ok) - sharkd_retap(); + /* retap only if we have at least one ok */ + if (is_any_ok) + sharkd_retap(); - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - sharkd_json_array_open("iograph"); - for (i = 0; i < graph_count; i++) - { - struct sharkd_iograph *graph = &graphs[i]; + sharkd_json_array_open("iograph"); + for (i = 0; i < graph_count; i++) + { + struct sharkd_iograph *graph = &graphs[i]; - json_dumper_begin_object(&dumper); + json_dumper_begin_object(&dumper); - if (graph->error) - { - fprintf(stderr, "SNAP 6002 - we should never get to here.\n"); - g_string_free(graph->error, TRUE); - exit(-1); - } - else - { - int idx; - int next_idx = 0; + if (graph->error) + { + fprintf(stderr, "SNAP 6002 - we should never get to here.\n"); + g_string_free(graph->error, TRUE); + exit(-1); + } + else + { + int idx; + int next_idx = 0; - sharkd_json_array_open("items"); - for (idx = 0; idx < graph->num_items; idx++) - { - double val; + sharkd_json_array_open("items"); + for (idx = 0; idx < graph->num_items; idx++) + { + double val; - val = get_io_graph_item(graph->items, graph->calc_type, idx, graph->hf_index, &cfile, graph->interval, graph->num_items); + val = get_io_graph_item(graph->items, graph->calc_type, idx, graph->hf_index, &cfile, graph->interval, graph->num_items); - /* if it's zero, don't display */ - if (val == 0.0) - continue; + /* if it's zero, don't display */ + if (val == 0.0) + continue; - /* cause zeros are not printed, need to output index */ - if (next_idx != idx) - sharkd_json_value_stringf(NULL, "%x", idx); + /* cause zeros are not printed, need to output index */ + if (next_idx != idx) + sharkd_json_value_stringf(NULL, "%x", idx); - sharkd_json_value_anyf(NULL, "%f", val); - next_idx = idx + 1; - } - sharkd_json_array_close(); - } - json_dumper_end_object(&dumper); + sharkd_json_value_anyf(NULL, "%f", val); + next_idx = idx + 1; + } + sharkd_json_array_close(); + } + json_dumper_end_object(&dumper); - remove_tap_listener(graph); - g_free(graph->items); - } - sharkd_json_array_close(); + remove_tap_listener(graph); + g_free(graph->items); + } + sharkd_json_array_close(); - sharkd_json_result_epilogue(); + sharkd_json_result_epilogue(); } /** @@ -3813,103 +3813,103 @@ sharkd_session_process_iograph(char *buf, const jsmntok_t *tokens, int count) static void sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_interval = json_find_attr(buf, tokens, count, "interval"); - const char *tok_filter = json_find_attr(buf, tokens, count, "filter"); + const char *tok_interval = json_find_attr(buf, tokens, count, "interval"); + const char *tok_filter = json_find_attr(buf, tokens, count, "filter"); - const guint8 *filter_data = NULL; + const guint8 *filter_data = NULL; - struct - { - unsigned int frames; - guint64 bytes; - } st, st_total; + struct + { + unsigned int frames; + guint64 bytes; + } st, st_total; - nstime_t *start_ts; + nstime_t *start_ts; - guint32 interval_ms = 1000; /* default: one per second */ + guint32 interval_ms = 1000; /* default: one per second */ - gint64 idx; - gint64 max_idx = 0; + gint64 idx; + gint64 max_idx = 0; - if (tok_interval) - ws_strtou32(tok_interval, NULL, &interval_ms); // already validated + if (tok_interval) + ws_strtou32(tok_interval, NULL, &interval_ms); // already validated - if (tok_filter) - { - const struct sharkd_filter_item *filter_item; + if (tok_filter) + { + const struct sharkd_filter_item *filter_item; - filter_item = sharkd_session_filter_data(tok_filter); - if (!filter_item) - { - sharkd_json_error( - rpcid, -7001, NULL, - "Invalid filter parameter: %s", tok_filter - ); - return; - } - filter_data = filter_item->filtered; - } + filter_item = sharkd_session_filter_data(tok_filter); + if (!filter_item) + { + sharkd_json_error( + rpcid, -7001, NULL, + "Invalid filter parameter: %s", tok_filter + ); + return; + } + filter_data = filter_item->filtered; + } - st_total.frames = 0; - st_total.bytes = 0; + st_total.frames = 0; + st_total.bytes = 0; - st.frames = 0; - st.bytes = 0; + st.frames = 0; + st.bytes = 0; - idx = 0; + idx = 0; - sharkd_json_result_prologue(rpcid); - sharkd_json_array_open("intervals"); + sharkd_json_result_prologue(rpcid); + sharkd_json_array_open("intervals"); - start_ts = (cfile.count >= 1) ? &(sharkd_get_frame(1)->abs_ts) : NULL; + start_ts = (cfile.count >= 1) ? &(sharkd_get_frame(1)->abs_ts) : NULL; - for (guint32 framenum = 1; framenum <= cfile.count; framenum++) - { - frame_data *fdata; - gint64 msec_rel; - gint64 new_idx; + for (guint32 framenum = 1; framenum <= cfile.count; framenum++) + { + frame_data *fdata; + gint64 msec_rel; + gint64 new_idx; - if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8)))) - continue; + if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8)))) + continue; - fdata = sharkd_get_frame(framenum); + fdata = sharkd_get_frame(framenum); - msec_rel = (fdata->abs_ts.secs - start_ts->secs) * (gint64) 1000 + (fdata->abs_ts.nsecs - start_ts->nsecs) / 1000000; - new_idx = msec_rel / interval_ms; + msec_rel = (fdata->abs_ts.secs - start_ts->secs) * (gint64) 1000 + (fdata->abs_ts.nsecs - start_ts->nsecs) / 1000000; + new_idx = msec_rel / interval_ms; - if (idx != new_idx) - { - if (st.frames != 0) - { - sharkd_json_value_anyf(NULL, "[%" PRId64 ",%u,%" PRIu64 "]", idx, st.frames, st.bytes); - } + if (idx != new_idx) + { + if (st.frames != 0) + { + sharkd_json_value_anyf(NULL, "[%" PRId64 ",%u,%" PRIu64 "]", idx, st.frames, st.bytes); + } - idx = new_idx; - if (idx > max_idx) - max_idx = idx; + idx = new_idx; + if (idx > max_idx) + max_idx = idx; - st.frames = 0; - st.bytes = 0; - } + st.frames = 0; + st.bytes = 0; + } - st.frames += 1; - st.bytes += fdata->pkt_len; + st.frames += 1; + st.bytes += fdata->pkt_len; - st_total.frames += 1; - st_total.bytes += fdata->pkt_len; - } + st_total.frames += 1; + st_total.bytes += fdata->pkt_len; + } - if (st.frames != 0) - { - sharkd_json_value_anyf(NULL, "[%" PRId64 ",%u,%" PRIu64 "]", idx, st.frames, st.bytes); - } - sharkd_json_array_close(); + if (st.frames != 0) + { + sharkd_json_value_anyf(NULL, "[%" PRId64 ",%u,%" PRIu64 "]", idx, st.frames, st.bytes); + } + sharkd_json_array_close(); - sharkd_json_value_anyf("last", "%" PRId64, max_idx); - sharkd_json_value_anyf("frames", "%u", st_total.frames); - sharkd_json_value_anyf("bytes", "%" PRIu64, st_total.bytes); + sharkd_json_value_anyf("last", "%" PRId64, max_idx); + sharkd_json_value_anyf("frames", "%u", st_total.frames); + sharkd_json_value_anyf("bytes", "%" PRIu64, st_total.bytes); - sharkd_json_result_epilogue(); + sharkd_json_result_epilogue(); } /** @@ -3960,94 +3960,94 @@ sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count) static void sharkd_session_process_frame(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_frame = json_find_attr(buf, tokens, count, "frame"); - const char *tok_ref_frame = json_find_attr(buf, tokens, count, "ref_frame"); - const char *tok_prev_frame = json_find_attr(buf, tokens, count, "prev_frame"); - column_info *cinfo = NULL; + const char *tok_frame = json_find_attr(buf, tokens, count, "frame"); + const char *tok_ref_frame = json_find_attr(buf, tokens, count, "ref_frame"); + const char *tok_prev_frame = json_find_attr(buf, tokens, count, "prev_frame"); + column_info *cinfo = NULL; - guint32 framenum, ref_frame_num, prev_dis_num; - guint32 dissect_flags = SHARKD_DISSECT_FLAG_NULL; - struct sharkd_frame_request_data req_data; - wtap_rec rec; /* Record metadata */ - Buffer rec_buf; /* Record data */ - enum dissect_request_status status; - int err; - gchar *err_info; + guint32 framenum, ref_frame_num, prev_dis_num; + guint32 dissect_flags = SHARKD_DISSECT_FLAG_NULL; + struct sharkd_frame_request_data req_data; + wtap_rec rec; /* Record metadata */ + Buffer rec_buf; /* Record data */ + enum dissect_request_status status; + int err; + gchar *err_info; - ws_strtou32(tok_frame, NULL, &framenum); // we have already validated this + ws_strtou32(tok_frame, NULL, &framenum); // we have already validated this - ref_frame_num = (framenum != 1) ? 1 : 0; - if (tok_ref_frame) - { - ws_strtou32(tok_ref_frame, NULL, &ref_frame_num); - if (ref_frame_num > framenum) - { - sharkd_json_error( - rpcid, -8001, NULL, - "Invalid ref_frame - The ref_frame occurs after the frame specified" - ); - return; - } - } + ref_frame_num = (framenum != 1) ? 1 : 0; + if (tok_ref_frame) + { + ws_strtou32(tok_ref_frame, NULL, &ref_frame_num); + if (ref_frame_num > framenum) + { + sharkd_json_error( + rpcid, -8001, NULL, + "Invalid ref_frame - The ref_frame occurs after the frame specified" + ); + return; + } + } - prev_dis_num = framenum - 1; - if (tok_prev_frame) - { - ws_strtou32(tok_prev_frame, NULL, &prev_dis_num); - if (prev_dis_num >= framenum) - { - sharkd_json_error( - rpcid, -8002, NULL, - "Invalid prev_frame - The prev_frame occurs on or after the frame specified" - ); - return; - } - } + prev_dis_num = framenum - 1; + if (tok_prev_frame) + { + ws_strtou32(tok_prev_frame, NULL, &prev_dis_num); + if (prev_dis_num >= framenum) + { + sharkd_json_error( + rpcid, -8002, NULL, + "Invalid prev_frame - The prev_frame occurs on or after the frame specified" + ); + return; + } + } - if (json_find_attr(buf, tokens, count, "proto") != NULL) - dissect_flags |= SHARKD_DISSECT_FLAG_PROTO_TREE; - if (json_find_attr(buf, tokens, count, "bytes") != NULL) - dissect_flags |= SHARKD_DISSECT_FLAG_BYTES; - if (json_find_attr(buf, tokens, count, "columns") != NULL) { - dissect_flags |= SHARKD_DISSECT_FLAG_COLUMNS; - cinfo = &cfile.cinfo; - } - if (json_find_attr(buf, tokens, count, "color") != NULL) - dissect_flags |= SHARKD_DISSECT_FLAG_COLOR; + if (json_find_attr(buf, tokens, count, "proto") != NULL) + dissect_flags |= SHARKD_DISSECT_FLAG_PROTO_TREE; + if (json_find_attr(buf, tokens, count, "bytes") != NULL) + dissect_flags |= SHARKD_DISSECT_FLAG_BYTES; + if (json_find_attr(buf, tokens, count, "columns") != NULL) { + dissect_flags |= SHARKD_DISSECT_FLAG_COLUMNS; + cinfo = &cfile.cinfo; + } + if (json_find_attr(buf, tokens, count, "color") != NULL) + dissect_flags |= SHARKD_DISSECT_FLAG_COLOR; - req_data.display_hidden = (json_find_attr(buf, tokens, count, "v") != NULL); + req_data.display_hidden = (json_find_attr(buf, tokens, count, "v") != NULL); - wtap_rec_init(&rec); - ws_buffer_init(&rec_buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&rec_buf, 1514); - status = sharkd_dissect_request(framenum, ref_frame_num, prev_dis_num, - &rec, &rec_buf, cinfo, dissect_flags, - &sharkd_session_process_frame_cb, &req_data, &err, &err_info); - switch (status) { + status = sharkd_dissect_request(framenum, ref_frame_num, prev_dis_num, + &rec, &rec_buf, cinfo, dissect_flags, + &sharkd_session_process_frame_cb, &req_data, &err, &err_info); + switch (status) { - case DISSECT_REQUEST_SUCCESS: - /* success */ - break; + case DISSECT_REQUEST_SUCCESS: + /* success */ + break; - case DISSECT_REQUEST_NO_SUCH_FRAME: - sharkd_json_error( - rpcid, -8003, NULL, - "Invalid frame - The frame number requested is out of range" - ); - break; + case DISSECT_REQUEST_NO_SUCH_FRAME: + sharkd_json_error( + rpcid, -8003, NULL, + "Invalid frame - The frame number requested is out of range" + ); + break; - case DISSECT_REQUEST_READ_ERROR: - sharkd_json_error( - rpcid, -8003, NULL, - /* XXX - show the error details */ - "Read error - The frame could not be read from the file" - ); - g_free(err_info); - break; - } + case DISSECT_REQUEST_READ_ERROR: + sharkd_json_error( + rpcid, -8003, NULL, + /* XXX - show the error details */ + "Read error - The frame could not be read from the file" + ); + g_free(err_info); + break; + } - wtap_rec_cleanup(&rec); - ws_buffer_free(&rec_buf); + wtap_rec_cleanup(&rec); + ws_buffer_free(&rec_buf); } /** @@ -4067,96 +4067,96 @@ sharkd_session_process_frame(char *buf, const jsmntok_t *tokens, int count) static int sharkd_session_process_check(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_filter = json_find_attr(buf, tokens, count, "filter"); - const char *tok_field = json_find_attr(buf, tokens, count, "field"); + const char *tok_filter = json_find_attr(buf, tokens, count, "filter"); + const char *tok_field = json_find_attr(buf, tokens, count, "field"); - if (tok_filter != NULL) - { - char *err_msg = NULL; - dfilter_t *dfp; + if (tok_filter != NULL) + { + char *err_msg = NULL; + dfilter_t *dfp; - if (dfilter_compile(tok_filter, &dfp, &err_msg)) - { - if (dfp && dfilter_deprecated_tokens(dfp)) - sharkd_json_warning(rpcid, err_msg); - else - sharkd_json_simple_ok(rpcid); + if (dfilter_compile(tok_filter, &dfp, &err_msg)) + { + if (dfp && dfilter_deprecated_tokens(dfp)) + sharkd_json_warning(rpcid, err_msg); + else + sharkd_json_simple_ok(rpcid); - dfilter_free(dfp); - g_free(err_msg); - return 0; - } - else - { - sharkd_json_error( - rpcid, -5001, NULL, - "Filter invalid - %s", err_msg - ); - return -5001; - } - } + dfilter_free(dfp); + g_free(err_msg); + return 0; + } + else + { + sharkd_json_error( + rpcid, -5001, NULL, + "Filter invalid - %s", err_msg + ); + return -5001; + } + } - if (tok_field != NULL) - { - header_field_info *hfi = proto_registrar_get_byname(tok_field); + if (tok_field != NULL) + { + header_field_info *hfi = proto_registrar_get_byname(tok_field); - if (!hfi) - { - sharkd_json_error( - rpcid, -5002, NULL, - "Field %s not found", tok_field - ); - return -5002; - } - else - { - sharkd_json_simple_ok(rpcid); - return 0; - } - } + if (!hfi) + { + sharkd_json_error( + rpcid, -5002, NULL, + "Field %s not found", tok_field + ); + return -5002; + } + else + { + sharkd_json_simple_ok(rpcid); + return 0; + } + } - sharkd_json_simple_ok(rpcid); - return 0; + sharkd_json_simple_ok(rpcid); + return 0; } struct sharkd_session_process_complete_pref_data { - const char *module; - const char *pref; + const char *module; + const char *pref; }; static guint sharkd_session_process_complete_pref_cb(module_t *module, gpointer d) { - struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d; + struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d; - if (strncmp(data->pref, module->name, strlen(data->pref)) != 0) - return 0; + if (strncmp(data->pref, module->name, strlen(data->pref)) != 0) + return 0; - json_dumper_begin_object(&dumper); - sharkd_json_value_string("f", module->name); - sharkd_json_value_string("d", module->title); - json_dumper_end_object(&dumper); + json_dumper_begin_object(&dumper); + sharkd_json_value_string("f", module->name); + sharkd_json_value_string("d", module->title); + json_dumper_end_object(&dumper); - return 0; + return 0; } static guint sharkd_session_process_complete_pref_option_cb(pref_t *pref, gpointer d) { - struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d; - const char *pref_name = prefs_get_name(pref); - const char *pref_title = prefs_get_title(pref); + struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d; + const char *pref_name = prefs_get_name(pref); + const char *pref_title = prefs_get_title(pref); - if (strncmp(data->pref, pref_name, strlen(data->pref)) != 0) - return 0; + if (strncmp(data->pref, pref_name, strlen(data->pref)) != 0) + return 0; - json_dumper_begin_object(&dumper); - sharkd_json_value_stringf("f", "%s.%s", data->module, pref_name); - sharkd_json_value_string("d", pref_title); - json_dumper_end_object(&dumper); + json_dumper_begin_object(&dumper); + sharkd_json_value_stringf("f", "%s.%s", data->module, pref_name); + sharkd_json_value_string("d", pref_title); + json_dumper_end_object(&dumper); - return 0; /* continue */ + return 0; /* continue */ } /** @@ -4181,107 +4181,107 @@ sharkd_session_process_complete_pref_option_cb(pref_t *pref, gpointer d) static int sharkd_session_process_complete(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_field = json_find_attr(buf, tokens, count, "field"); - const char *tok_pref = json_find_attr(buf, tokens, count, "pref"); + const char *tok_field = json_find_attr(buf, tokens, count, "field"); + const char *tok_pref = json_find_attr(buf, tokens, count, "pref"); - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - if (tok_field != NULL && tok_field[0]) - { - const size_t filter_length = strlen(tok_field); - const int filter_with_dot = !!strchr(tok_field, '.'); + if (tok_field != NULL && tok_field[0]) + { + const size_t filter_length = strlen(tok_field); + const int filter_with_dot = !!strchr(tok_field, '.'); - void *proto_cookie; - void *field_cookie; - int proto_id; + void *proto_cookie; + void *field_cookie; + int proto_id; - sharkd_json_array_open("field"); + sharkd_json_array_open("field"); - for (proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1; proto_id = proto_get_next_protocol(&proto_cookie)) - { - protocol_t *protocol = find_protocol_by_id(proto_id); - const char *protocol_filter; - const char *protocol_name; - header_field_info *hfinfo; + for (proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1; proto_id = proto_get_next_protocol(&proto_cookie)) + { + protocol_t *protocol = find_protocol_by_id(proto_id); + const char *protocol_filter; + const char *protocol_name; + header_field_info *hfinfo; - if (!proto_is_protocol_enabled(protocol)) - continue; + if (!proto_is_protocol_enabled(protocol)) + continue; - protocol_name = proto_get_protocol_long_name(protocol); - protocol_filter = proto_get_protocol_filter_name(proto_id); + protocol_name = proto_get_protocol_long_name(protocol); + protocol_filter = proto_get_protocol_filter_name(proto_id); - if (strlen(protocol_filter) >= filter_length && !g_ascii_strncasecmp(tok_field, protocol_filter, filter_length)) - { - json_dumper_begin_object(&dumper); - { - sharkd_json_value_string("f", protocol_filter); - sharkd_json_value_anyf("t", "%d", FT_PROTOCOL); - sharkd_json_value_string("n", protocol_name); - } - json_dumper_end_object(&dumper); - } + if (strlen(protocol_filter) >= filter_length && !g_ascii_strncasecmp(tok_field, protocol_filter, filter_length)) + { + json_dumper_begin_object(&dumper); + { + sharkd_json_value_string("f", protocol_filter); + sharkd_json_value_anyf("t", "%d", FT_PROTOCOL); + sharkd_json_value_string("n", protocol_name); + } + json_dumper_end_object(&dumper); + } - if (!filter_with_dot) - continue; + if (!filter_with_dot) + continue; - for (hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo != NULL; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie)) - { - if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */ - continue; + for (hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo != NULL; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie)) + { + if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */ + continue; - if (strlen(hfinfo->abbrev) >= filter_length && !g_ascii_strncasecmp(tok_field, hfinfo->abbrev, filter_length)) - { - json_dumper_begin_object(&dumper); - { - sharkd_json_value_string("f", hfinfo->abbrev); + if (strlen(hfinfo->abbrev) >= filter_length && !g_ascii_strncasecmp(tok_field, hfinfo->abbrev, filter_length)) + { + json_dumper_begin_object(&dumper); + { + sharkd_json_value_string("f", hfinfo->abbrev); - /* XXX, skip displaying name, if there are multiple (to not confuse user) */ - if (hfinfo->same_name_next == NULL) - { - sharkd_json_value_anyf("t", "%d", hfinfo->type); - sharkd_json_value_string("n", hfinfo->name); - } - } - json_dumper_end_object(&dumper); - } - } - } + /* XXX, skip displaying name, if there are multiple (to not confuse user) */ + if (hfinfo->same_name_next == NULL) + { + sharkd_json_value_anyf("t", "%d", hfinfo->type); + sharkd_json_value_string("n", hfinfo->name); + } + } + json_dumper_end_object(&dumper); + } + } + } - sharkd_json_array_close(); - } + sharkd_json_array_close(); + } - if (tok_pref != NULL && tok_pref[0]) - { - struct sharkd_session_process_complete_pref_data data; - char *dot_sepa; + if (tok_pref != NULL && tok_pref[0]) + { + struct sharkd_session_process_complete_pref_data data; + char *dot_sepa; - data.module = tok_pref; - data.pref = tok_pref; + data.module = tok_pref; + data.pref = tok_pref; - sharkd_json_array_open("pref"); - if ((dot_sepa = strchr(tok_pref, '.'))) - { - module_t *pref_mod; + sharkd_json_array_open("pref"); + if ((dot_sepa = strchr(tok_pref, '.'))) + { + module_t *pref_mod; - *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */ - data.pref = dot_sepa + 1; + *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */ + data.pref = dot_sepa + 1; - pref_mod = prefs_find_module(data.module); - if (pref_mod) - prefs_pref_foreach(pref_mod, sharkd_session_process_complete_pref_option_cb, &data); + pref_mod = prefs_find_module(data.module); + if (pref_mod) + prefs_pref_foreach(pref_mod, sharkd_session_process_complete_pref_option_cb, &data); - *dot_sepa = '.'; - } - else - { - prefs_modules_foreach(sharkd_session_process_complete_pref_cb, &data); - } - sharkd_json_array_close(); - } + *dot_sepa = '.'; + } + else + { + prefs_modules_foreach(sharkd_session_process_complete_pref_cb, &data); + } + sharkd_json_array_close(); + } - sharkd_json_result_epilogue(); + sharkd_json_result_epilogue(); - return 0; + return 0; } /** @@ -4302,49 +4302,49 @@ sharkd_session_process_complete(char *buf, const jsmntok_t *tokens, int count) static void sharkd_session_process_setcomment(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_frame = json_find_attr(buf, tokens, count, "frame"); - const char *tok_comment = json_find_attr(buf, tokens, count, "comment"); + const char *tok_frame = json_find_attr(buf, tokens, count, "frame"); + const char *tok_comment = json_find_attr(buf, tokens, count, "comment"); - guint32 framenum; - frame_data *fdata; - wtap_opttype_return_val ret; - wtap_block_t pkt_block = NULL; + guint32 framenum; + frame_data *fdata; + wtap_opttype_return_val ret; + wtap_block_t pkt_block = NULL; - if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0) - { - sharkd_json_error( - rpcid, -3001, NULL, - "Frame number must be a positive integer" - ); - return; - } + if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0) + { + sharkd_json_error( + rpcid, -3001, NULL, + "Frame number must be a positive integer" + ); + return; + } - fdata = sharkd_get_frame(framenum); // BUG HERE - If no file loaded you get a crash - if (!fdata) - { - sharkd_json_error( - rpcid, -3002, NULL, - "Frame number is out of range" - ); - return; - } + fdata = sharkd_get_frame(framenum); // BUG HERE - If no file loaded you get a crash + if (!fdata) + { + sharkd_json_error( + rpcid, -3002, NULL, + "Frame number is out of range" + ); + return; + } - pkt_block = sharkd_get_packet_block(fdata); + pkt_block = sharkd_get_packet_block(fdata); - ret = wtap_block_add_string_option(pkt_block, OPT_COMMENT, tok_comment, strlen(tok_comment)); + ret = wtap_block_add_string_option(pkt_block, OPT_COMMENT, tok_comment, strlen(tok_comment)); - if (ret != WTAP_OPTTYPE_SUCCESS) - { - sharkd_json_error( - rpcid, -3003, NULL, - "Unable to set the comment" - ); - } - else - { - sharkd_set_modified_block(fdata, pkt_block); - sharkd_json_simple_ok(rpcid); - } + if (ret != WTAP_OPTTYPE_SUCCESS) + { + sharkd_json_error( + rpcid, -3003, NULL, + "Unable to set the comment" + ); + } + else + { + sharkd_set_modified_block(fdata, pkt_block); + sharkd_json_simple_ok(rpcid); + } } /** @@ -4362,187 +4362,187 @@ sharkd_session_process_setcomment(char *buf, const jsmntok_t *tokens, int count) static void sharkd_session_process_setconf(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_name = json_find_attr(buf, tokens, count, "name"); - const char *tok_value = json_find_attr(buf, tokens, count, "value"); - char pref[4096]; - char *errmsg = NULL; + const char *tok_name = json_find_attr(buf, tokens, count, "name"); + const char *tok_value = json_find_attr(buf, tokens, count, "value"); + char pref[4096]; + char *errmsg = NULL; - prefs_set_pref_e ret; + prefs_set_pref_e ret; - if (!tok_name || tok_name[0] == '\0') - { - sharkd_json_error( - rpcid, -4001, NULL, - "Preference name missing" - ); - return; - } + if (!tok_name || tok_name[0] == '\0') + { + sharkd_json_error( + rpcid, -4001, NULL, + "Preference name missing" + ); + return; + } - if (!tok_value) - { - sharkd_json_error( - rpcid, -4002, NULL, - "Preference value missing" - ); - return; - } + if (!tok_value) + { + sharkd_json_error( + rpcid, -4002, NULL, + "Preference value missing" + ); + return; + } - snprintf(pref, sizeof(pref), "%s:%s", tok_name, tok_value); + snprintf(pref, sizeof(pref), "%s:%s", tok_name, tok_value); - ret = prefs_set_pref(pref, &errmsg); + ret = prefs_set_pref(pref, &errmsg); - switch (ret) - { - case PREFS_SET_OK: - sharkd_json_simple_ok(rpcid); - break; + switch (ret) + { + case PREFS_SET_OK: + sharkd_json_simple_ok(rpcid); + break; - case PREFS_SET_OBSOLETE: - sharkd_json_error( - rpcid, -4003, NULL, - "The preference specified is obsolete" - ); - break; + case PREFS_SET_OBSOLETE: + sharkd_json_error( + rpcid, -4003, NULL, + "The preference specified is obsolete" + ); + break; - case PREFS_SET_NO_SUCH_PREF: - sharkd_json_error( - rpcid, -4004, NULL, - "No such preference exists" - ); - break; + case PREFS_SET_NO_SUCH_PREF: + sharkd_json_error( + rpcid, -4004, NULL, + "No such preference exists" + ); + break; - default: - sharkd_json_error( - rpcid, -4005, NULL, - "Unable to set the preference" - ); - } + default: + sharkd_json_error( + rpcid, -4005, NULL, + "Unable to set the preference" + ); + } - g_free(errmsg); + g_free(errmsg); } struct sharkd_session_process_dumpconf_data { - module_t *module; + module_t *module; }; static guint sharkd_session_process_dumpconf_cb(pref_t *pref, gpointer d) { - struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d; - const char *pref_name = prefs_get_name(pref); + struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d; + const char *pref_name = prefs_get_name(pref); - char json_pref_key[512]; + char json_pref_key[512]; - snprintf(json_pref_key, sizeof(json_pref_key), "%s.%s", data->module->name, pref_name); - json_dumper_set_member_name(&dumper, json_pref_key); - json_dumper_begin_object(&dumper); + snprintf(json_pref_key, sizeof(json_pref_key), "%s.%s", data->module->name, pref_name); + json_dumper_set_member_name(&dumper, json_pref_key); + json_dumper_begin_object(&dumper); - switch (prefs_get_type(pref)) - { - case PREF_UINT: - case PREF_DECODE_AS_UINT: - sharkd_json_value_anyf("u", "%u", prefs_get_uint_value_real(pref, pref_current)); - if (prefs_get_uint_base(pref) != 10) - sharkd_json_value_anyf("ub", "%u", prefs_get_uint_base(pref)); - break; + switch (prefs_get_type(pref)) + { + case PREF_UINT: + case PREF_DECODE_AS_UINT: + sharkd_json_value_anyf("u", "%u", prefs_get_uint_value_real(pref, pref_current)); + if (prefs_get_uint_base(pref) != 10) + sharkd_json_value_anyf("ub", "%u", prefs_get_uint_base(pref)); + break; - case PREF_BOOL: - sharkd_json_value_anyf("b", prefs_get_bool_value(pref, pref_current) ? "1" : "0"); - break; + case PREF_BOOL: + sharkd_json_value_anyf("b", prefs_get_bool_value(pref, pref_current) ? "1" : "0"); + break; - case PREF_STRING: - case PREF_SAVE_FILENAME: - case PREF_OPEN_FILENAME: - case PREF_DIRNAME: - case PREF_PASSWORD: - sharkd_json_value_string("s", prefs_get_string_value(pref, pref_current)); - break; + case PREF_STRING: + case PREF_SAVE_FILENAME: + case PREF_OPEN_FILENAME: + case PREF_DIRNAME: + case PREF_PASSWORD: + sharkd_json_value_string("s", prefs_get_string_value(pref, pref_current)); + break; - case PREF_ENUM: - { - const enum_val_t *enums; + case PREF_ENUM: + { + const enum_val_t *enums; - sharkd_json_array_open("e"); - for (enums = prefs_get_enumvals(pref); enums->name; enums++) - { - json_dumper_begin_object(&dumper); + sharkd_json_array_open("e"); + for (enums = prefs_get_enumvals(pref); enums->name; enums++) + { + json_dumper_begin_object(&dumper); - sharkd_json_value_anyf("v", "%d", enums->value); + sharkd_json_value_anyf("v", "%d", enums->value); - if (enums->value == prefs_get_enum_value(pref, pref_current)) - sharkd_json_value_anyf("s", "1"); + if (enums->value == prefs_get_enum_value(pref, pref_current)) + sharkd_json_value_anyf("s", "1"); - sharkd_json_value_string("d", enums->description); + sharkd_json_value_string("d", enums->description); - json_dumper_end_object(&dumper); - } - sharkd_json_array_close(); - break; - } + json_dumper_end_object(&dumper); + } + sharkd_json_array_close(); + break; + } - case PREF_RANGE: - case PREF_DECODE_AS_RANGE: - { - char *range_str = range_convert_range(NULL, prefs_get_range_value_real(pref, pref_current)); - sharkd_json_value_string("r", range_str); - wmem_free(NULL, range_str); - break; - } + case PREF_RANGE: + case PREF_DECODE_AS_RANGE: + { + char *range_str = range_convert_range(NULL, prefs_get_range_value_real(pref, pref_current)); + sharkd_json_value_string("r", range_str); + wmem_free(NULL, range_str); + break; + } - case PREF_UAT: - { - uat_t *uat = prefs_get_uat_value(pref); - guint idx; + case PREF_UAT: + { + uat_t *uat = prefs_get_uat_value(pref); + guint idx; - sharkd_json_array_open("t"); - for (idx = 0; idx < uat->raw_data->len; idx++) - { - void *rec = UAT_INDEX_PTR(uat, idx); - guint colnum; + sharkd_json_array_open("t"); + for (idx = 0; idx < uat->raw_data->len; idx++) + { + void *rec = UAT_INDEX_PTR(uat, idx); + guint colnum; - sharkd_json_array_open(NULL); - for (colnum = 0; colnum < uat->ncols; colnum++) - { - char *str = uat_fld_tostr(rec, &(uat->fields[colnum])); + sharkd_json_array_open(NULL); + for (colnum = 0; colnum < uat->ncols; colnum++) + { + char *str = uat_fld_tostr(rec, &(uat->fields[colnum])); - sharkd_json_value_string(NULL, str); - g_free(str); - } + sharkd_json_value_string(NULL, str); + g_free(str); + } - sharkd_json_array_close(); - } + sharkd_json_array_close(); + } - sharkd_json_array_close(); - break; - } + sharkd_json_array_close(); + break; + } - case PREF_COLOR: - case PREF_CUSTOM: - case PREF_STATIC_TEXT: - case PREF_OBSOLETE: - /* TODO */ - break; - } + case PREF_COLOR: + case PREF_CUSTOM: + case PREF_STATIC_TEXT: + case PREF_OBSOLETE: + /* TODO */ + break; + } #if 0 - sharkd_json_value_string("t", prefs_get_title(pref)); + sharkd_json_value_string("t", prefs_get_title(pref)); #endif - json_dumper_end_object(&dumper); + json_dumper_end_object(&dumper); - return 0; /* continue */ + return 0; /* continue */ } static guint sharkd_session_process_dumpconf_mod_cb(module_t *module, gpointer d) { - struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d; + struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d; - data->module = module; - prefs_pref_foreach(module, sharkd_session_process_dumpconf_cb, data); + data->module = module; + prefs_pref_foreach(module, sharkd_session_process_dumpconf_cb, data); - return 0; + return 0; } /** @@ -4567,266 +4567,266 @@ sharkd_session_process_dumpconf_mod_cb(module_t *module, gpointer d) static void sharkd_session_process_dumpconf(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_pref = json_find_attr(buf, tokens, count, "pref"); - module_t *pref_mod; - char *dot_sepa; + const char *tok_pref = json_find_attr(buf, tokens, count, "pref"); + module_t *pref_mod; + char *dot_sepa; - if (!tok_pref) - { - struct sharkd_session_process_dumpconf_data data; + if (!tok_pref) + { + struct sharkd_session_process_dumpconf_data data; - data.module = NULL; + data.module = NULL; - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - sharkd_json_value_anyf("prefs", NULL); - json_dumper_begin_object(&dumper); - prefs_modules_foreach(sharkd_session_process_dumpconf_mod_cb, &data); - json_dumper_end_object(&dumper); + sharkd_json_value_anyf("prefs", NULL); + json_dumper_begin_object(&dumper); + prefs_modules_foreach(sharkd_session_process_dumpconf_mod_cb, &data); + json_dumper_end_object(&dumper); - sharkd_json_result_epilogue(); - return; - } + sharkd_json_result_epilogue(); + return; + } - if ((dot_sepa = strchr(tok_pref, '.'))) - { - pref_t *pref = NULL; + if ((dot_sepa = strchr(tok_pref, '.'))) + { + pref_t *pref = NULL; - *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */ - pref_mod = prefs_find_module(tok_pref); - if (pref_mod) - pref = prefs_find_preference(pref_mod, dot_sepa + 1); - *dot_sepa = '.'; + *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */ + pref_mod = prefs_find_module(tok_pref); + if (pref_mod) + pref = prefs_find_preference(pref_mod, dot_sepa + 1); + *dot_sepa = '.'; - if (pref) - { - struct sharkd_session_process_dumpconf_data data; + if (pref) + { + struct sharkd_session_process_dumpconf_data data; - data.module = pref_mod; + data.module = pref_mod; - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - sharkd_json_value_anyf("prefs", NULL); - json_dumper_begin_object(&dumper); - sharkd_session_process_dumpconf_cb(pref, &data); - json_dumper_end_object(&dumper); + sharkd_json_value_anyf("prefs", NULL); + json_dumper_begin_object(&dumper); + sharkd_session_process_dumpconf_cb(pref, &data); + json_dumper_end_object(&dumper); - sharkd_json_result_epilogue(); - return; - } - else - { - sharkd_json_error( - rpcid, -9001, NULL, - "Invalid pref %s.", tok_pref - ); - return; - } + sharkd_json_result_epilogue(); + return; + } + else + { + sharkd_json_error( + rpcid, -9001, NULL, + "Invalid pref %s.", tok_pref + ); + return; + } - } + } - pref_mod = prefs_find_module(tok_pref); - if (pref_mod) - { - struct sharkd_session_process_dumpconf_data data; + pref_mod = prefs_find_module(tok_pref); + if (pref_mod) + { + struct sharkd_session_process_dumpconf_data data; - data.module = pref_mod; + data.module = pref_mod; - sharkd_json_result_prologue(rpcid); + sharkd_json_result_prologue(rpcid); - sharkd_json_value_anyf("prefs", NULL); - json_dumper_begin_object(&dumper); - prefs_pref_foreach(pref_mod, sharkd_session_process_dumpconf_cb, &data); - json_dumper_end_object(&dumper); + sharkd_json_value_anyf("prefs", NULL); + json_dumper_begin_object(&dumper); + prefs_pref_foreach(pref_mod, sharkd_session_process_dumpconf_cb, &data); + json_dumper_end_object(&dumper); - sharkd_json_result_epilogue(); - } - else - { - sharkd_json_error( - rpcid, -9002, NULL, - "Invalid pref %s.", tok_pref - ); - } + sharkd_json_result_epilogue(); + } + else + { + sharkd_json_error( + rpcid, -9002, NULL, + "Invalid pref %s.", tok_pref + ); + } } struct sharkd_download_rtp { - rtpstream_id_t id; - GSList *packets; - double start_time; + rtpstream_id_t id; + GSList *packets; + double start_time; }; static void sharkd_rtp_download_free_items(void *ptr) { - rtp_packet_t *rtp_packet = (rtp_packet_t *) ptr; + rtp_packet_t *rtp_packet = (rtp_packet_t *) ptr; - g_free(rtp_packet->info); - g_free(rtp_packet->payload_data); - g_free(rtp_packet); + g_free(rtp_packet->info); + g_free(rtp_packet->payload_data); + g_free(rtp_packet); } static void sharkd_rtp_download_decode(struct sharkd_download_rtp *req) { - /* based on RtpAudioStream::decode() 6e29d874f8b5e6ebc59f661a0bb0dab8e56f122a */ - /* TODO, for now only without silence (timing_mode_ = Uninterrupted) */ + /* based on RtpAudioStream::decode() 6e29d874f8b5e6ebc59f661a0bb0dab8e56f122a */ + /* TODO, for now only without silence (timing_mode_ = Uninterrupted) */ - static const int sample_bytes_ = sizeof(SAMPLE) / sizeof(char); + static const int sample_bytes_ = sizeof(SAMPLE) / sizeof(char); - guint32 audio_out_rate_ = 0; - struct _GHashTable *decoders_hash_ = rtp_decoder_hash_table_new(); - struct SpeexResamplerState_ *audio_resampler_ = NULL; + guint32 audio_out_rate_ = 0; + struct _GHashTable *decoders_hash_ = rtp_decoder_hash_table_new(); + struct SpeexResamplerState_ *audio_resampler_ = NULL; - gsize resample_buff_len = 0x1000; - SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_len); - spx_uint32_t cur_in_rate = 0; - char *write_buff = NULL; - size_t write_bytes = 0; - unsigned channels = 0; - unsigned sample_rate = 0; + gsize resample_buff_len = 0x1000; + SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_len); + spx_uint32_t cur_in_rate = 0; + char *write_buff = NULL; + size_t write_bytes = 0; + unsigned channels = 0; + unsigned sample_rate = 0; - GSList *l; + GSList *l; - for (l = req->packets; l; l = l->next) - { - rtp_packet_t *rtp_packet = (rtp_packet_t *) l->data; + for (l = req->packets; l; l = l->next) + { + rtp_packet_t *rtp_packet = (rtp_packet_t *) l->data; - SAMPLE *decode_buff = NULL; - size_t decoded_bytes; + SAMPLE *decode_buff = NULL; + size_t decoded_bytes; - decoded_bytes = decode_rtp_packet(rtp_packet, &decode_buff, decoders_hash_, &channels, &sample_rate); - if (decoded_bytes == 0 || sample_rate == 0) - { - /* We didn't decode anything. Clean up and prep for the next packet. */ - g_free(decode_buff); - continue; - } + decoded_bytes = decode_rtp_packet(rtp_packet, &decode_buff, decoders_hash_, &channels, &sample_rate); + if (decoded_bytes == 0 || sample_rate == 0) + { + /* We didn't decode anything. Clean up and prep for the next packet. */ + g_free(decode_buff); + continue; + } - if (audio_out_rate_ == 0) - { - guint32 tmp32; - guint16 tmp16; - char wav_hdr[44]; + if (audio_out_rate_ == 0) + { + guint32 tmp32; + guint16 tmp16; + char wav_hdr[44]; - /* First non-zero wins */ - audio_out_rate_ = sample_rate; + /* First non-zero wins */ + audio_out_rate_ = sample_rate; - RTP_STREAM_DEBUG("Audio sample rate is %u", audio_out_rate_); + RTP_STREAM_DEBUG("Audio sample rate is %u", audio_out_rate_); - /* write WAVE header */ - memset(&wav_hdr, 0, sizeof(wav_hdr)); - memcpy(&wav_hdr[0], "RIFF", 4); - memcpy(&wav_hdr[4], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */ - memcpy(&wav_hdr[8], "WAVE", 4); + /* write WAVE header */ + memset(&wav_hdr, 0, sizeof(wav_hdr)); + memcpy(&wav_hdr[0], "RIFF", 4); + memcpy(&wav_hdr[4], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */ + memcpy(&wav_hdr[8], "WAVE", 4); - memcpy(&wav_hdr[12], "fmt ", 4); - memcpy(&wav_hdr[16], "\x10\x00\x00\x00", 4); /* PCM */ - memcpy(&wav_hdr[20], "\x01\x00", 2); /* PCM */ - /* # channels */ - tmp16 = channels; - memcpy(&wav_hdr[22], &tmp16, 2); - /* sample rate */ - tmp32 = sample_rate; - memcpy(&wav_hdr[24], &tmp32, 4); - /* byte rate */ - tmp32 = sample_rate * channels * sample_bytes_; - memcpy(&wav_hdr[28], &tmp32, 4); - /* block align */ - tmp16 = channels * sample_bytes_; - memcpy(&wav_hdr[32], &tmp16, 2); - /* bits per sample */ - tmp16 = 8 * sample_bytes_; - memcpy(&wav_hdr[34], &tmp16, 2); + memcpy(&wav_hdr[12], "fmt ", 4); + memcpy(&wav_hdr[16], "\x10\x00\x00\x00", 4); /* PCM */ + memcpy(&wav_hdr[20], "\x01\x00", 2); /* PCM */ + /* # channels */ + tmp16 = channels; + memcpy(&wav_hdr[22], &tmp16, 2); + /* sample rate */ + tmp32 = sample_rate; + memcpy(&wav_hdr[24], &tmp32, 4); + /* byte rate */ + tmp32 = sample_rate * channels * sample_bytes_; + memcpy(&wav_hdr[28], &tmp32, 4); + /* block align */ + tmp16 = channels * sample_bytes_; + memcpy(&wav_hdr[32], &tmp16, 2); + /* bits per sample */ + tmp16 = 8 * sample_bytes_; + memcpy(&wav_hdr[34], &tmp16, 2); - memcpy(&wav_hdr[36], "data", 4); - memcpy(&wav_hdr[40], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */ + memcpy(&wav_hdr[36], "data", 4); + memcpy(&wav_hdr[40], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */ - json_dumper_write_base64(&dumper, wav_hdr, sizeof(wav_hdr)); - } + json_dumper_write_base64(&dumper, wav_hdr, sizeof(wav_hdr)); + } - // Write samples to our file. - write_buff = (char *) decode_buff; - write_bytes = decoded_bytes; + // Write samples to our file. + write_buff = (char *) decode_buff; + write_bytes = decoded_bytes; - if (audio_out_rate_ != sample_rate) - { - spx_uint32_t in_len, out_len; + if (audio_out_rate_ != sample_rate) + { + spx_uint32_t in_len, out_len; - /* Resample the audio to match our previous output rate. */ - if (!audio_resampler_) - { - audio_resampler_ = speex_resampler_init(1, sample_rate, audio_out_rate_, 10, NULL); - speex_resampler_skip_zeros(audio_resampler_); - RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, audio_out_rate_); - } - else - { - spx_uint32_t audio_out_rate; - speex_resampler_get_rate(audio_resampler_, &cur_in_rate, &audio_out_rate); + /* Resample the audio to match our previous output rate. */ + if (!audio_resampler_) + { + audio_resampler_ = speex_resampler_init(1, sample_rate, audio_out_rate_, 10, NULL); + speex_resampler_skip_zeros(audio_resampler_); + RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, audio_out_rate_); + } + else + { + spx_uint32_t audio_out_rate; + speex_resampler_get_rate(audio_resampler_, &cur_in_rate, &audio_out_rate); - if (sample_rate != cur_in_rate) - { - speex_resampler_set_rate(audio_resampler_, sample_rate, audio_out_rate); - RTP_STREAM_DEBUG("Changed input rate from %u to %u Hz. Out is %u.", cur_in_rate, sample_rate, audio_out_rate_); - } - } - in_len = (spx_uint32_t)rtp_packet->info->info_payload_len; - out_len = (audio_out_rate_ * (spx_uint32_t)rtp_packet->info->info_payload_len / sample_rate) + (audio_out_rate_ % sample_rate != 0); - if (out_len * sample_bytes_ > resample_buff_len) - { - while ((out_len * sample_bytes_ > resample_buff_len)) - resample_buff_len *= 2; - resample_buff = (SAMPLE *) g_realloc(resample_buff, resample_buff_len); - } + if (sample_rate != cur_in_rate) + { + speex_resampler_set_rate(audio_resampler_, sample_rate, audio_out_rate); + RTP_STREAM_DEBUG("Changed input rate from %u to %u Hz. Out is %u.", cur_in_rate, sample_rate, audio_out_rate_); + } + } + in_len = (spx_uint32_t)rtp_packet->info->info_payload_len; + out_len = (audio_out_rate_ * (spx_uint32_t)rtp_packet->info->info_payload_len / sample_rate) + (audio_out_rate_ % sample_rate != 0); + if (out_len * sample_bytes_ > resample_buff_len) + { + while ((out_len * sample_bytes_ > resample_buff_len)) + resample_buff_len *= 2; + resample_buff = (SAMPLE *) g_realloc(resample_buff, resample_buff_len); + } - speex_resampler_process_int(audio_resampler_, 0, decode_buff, &in_len, resample_buff, &out_len); - write_buff = (char *) resample_buff; - write_bytes = out_len * sample_bytes_; - } + speex_resampler_process_int(audio_resampler_, 0, decode_buff, &in_len, resample_buff, &out_len); + write_buff = (char *) resample_buff; + write_bytes = out_len * sample_bytes_; + } - /* Write the decoded, possibly-resampled audio */ - json_dumper_write_base64(&dumper, write_buff, write_bytes); + /* Write the decoded, possibly-resampled audio */ + json_dumper_write_base64(&dumper, write_buff, write_bytes); - g_free(decode_buff); - } + g_free(decode_buff); + } - g_free(resample_buff); - g_hash_table_destroy(decoders_hash_); + g_free(resample_buff); + g_hash_table_destroy(decoders_hash_); } static tap_packet_status sharkd_session_packet_download_tap_rtp_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data) { - const struct _rtp_info *rtp_info = (const struct _rtp_info *) data; - struct sharkd_download_rtp *req_rtp = (struct sharkd_download_rtp *) tapdata; + const struct _rtp_info *rtp_info = (const struct _rtp_info *) data; + struct sharkd_download_rtp *req_rtp = (struct sharkd_download_rtp *) tapdata; - /* do not consider RTP packets without a setup frame */ - if (rtp_info->info_setup_frame_num == 0) - return TAP_PACKET_DONT_REDRAW; + /* do not consider RTP packets without a setup frame */ + if (rtp_info->info_setup_frame_num == 0) + return TAP_PACKET_DONT_REDRAW; - if (rtpstream_id_equal_pinfo_rtp_info(&req_rtp->id, pinfo, rtp_info)) - { - rtp_packet_t *rtp_packet; + if (rtpstream_id_equal_pinfo_rtp_info(&req_rtp->id, pinfo, rtp_info)) + { + rtp_packet_t *rtp_packet; - rtp_packet = g_new0(rtp_packet_t, 1); - rtp_packet->info = (struct _rtp_info *) g_memdup2(rtp_info, sizeof(struct _rtp_info)); + rtp_packet = g_new0(rtp_packet_t, 1); + rtp_packet->info = (struct _rtp_info *) g_memdup2(rtp_info, sizeof(struct _rtp_info)); - if (rtp_info->info_all_data_present && rtp_info->info_payload_len != 0) - rtp_packet->payload_data = (guint8 *) g_memdup2(&(rtp_info->info_data[rtp_info->info_payload_offset]), rtp_info->info_payload_len); + if (rtp_info->info_all_data_present && rtp_info->info_payload_len != 0) + rtp_packet->payload_data = (guint8 *) g_memdup2(&(rtp_info->info_data[rtp_info->info_payload_offset]), rtp_info->info_payload_len); - if (!req_rtp->packets) - req_rtp->start_time = nstime_to_sec(&pinfo->abs_ts); + if (!req_rtp->packets) + req_rtp->start_time = nstime_to_sec(&pinfo->abs_ts); - rtp_packet->frame_num = pinfo->num; - rtp_packet->arrive_offset = nstime_to_sec(&pinfo->abs_ts) - req_rtp->start_time; + rtp_packet->frame_num = pinfo->num; + rtp_packet->arrive_offset = nstime_to_sec(&pinfo->abs_ts) - req_rtp->start_time; - /* XXX, O(n) optimize */ - req_rtp->packets = g_slist_append(req_rtp->packets, rtp_packet); - } + /* XXX, O(n) optimize */ + req_rtp->packets = g_slist_append(req_rtp->packets, rtp_packet); + } - return TAP_PACKET_DONT_REDRAW; + return TAP_PACKET_DONT_REDRAW; } /** @@ -4845,257 +4845,244 @@ sharkd_session_packet_download_tap_rtp_cb(void *tapdata, packet_info *pinfo, epa static void sharkd_session_process_download(char *buf, const jsmntok_t *tokens, int count) { - const char *tok_token = json_find_attr(buf, tokens, count, "token"); + const char *tok_token = json_find_attr(buf, tokens, count, "token"); - if (!tok_token) - return; + if (!tok_token) + return; - if (!strncmp(tok_token, "eo:", 3)) - { - struct sharkd_export_object_list *object_list; - const export_object_entry_t *eo_entry = NULL; + if (!strncmp(tok_token, "eo:", 3)) + { + struct sharkd_export_object_list *object_list; + const export_object_entry_t *eo_entry = NULL; - for (object_list = sharkd_eo_list; object_list; object_list = object_list->next) - { - size_t eo_type_len = strlen(object_list->type); + for (object_list = sharkd_eo_list; object_list; object_list = object_list->next) + { + size_t eo_type_len = strlen(object_list->type); - if (!strncmp(tok_token, object_list->type, eo_type_len) && tok_token[eo_type_len] == '_') - { - int row; + if (!strncmp(tok_token, object_list->type, eo_type_len) && tok_token[eo_type_len] == '_') + { + int row; - if (sscanf(&tok_token[eo_type_len + 1], "%d", &row) != 1) - break; + if (sscanf(&tok_token[eo_type_len + 1], "%d", &row) != 1) + break; - eo_entry = (export_object_entry_t *) g_slist_nth_data(object_list->entries, row); - break; - } - } + eo_entry = (export_object_entry_t *) g_slist_nth_data(object_list->entries, row); + break; + } + } - if (eo_entry) - { - const char *mime = (eo_entry->content_type) ? eo_entry->content_type : "application/octet-stream"; - const char *filename = (eo_entry->filename) ? eo_entry->filename : tok_token; + if (eo_entry) + { + const char *mime = (eo_entry->content_type) ? eo_entry->content_type : "application/octet-stream"; + const char *filename = (eo_entry->filename) ? eo_entry->filename : tok_token; - sharkd_json_result_prologue(rpcid); - sharkd_json_value_string("file", filename); - sharkd_json_value_string("mime", mime); - sharkd_json_value_base64("data", eo_entry->payload_data, eo_entry->payload_len); - sharkd_json_result_epilogue(); - } - else - { - sharkd_json_result_prologue(rpcid); - sharkd_json_result_epilogue(); - } - } - else if (!strcmp(tok_token, "ssl-secrets")) - { - gsize str_len; - char *str = ssl_export_sessions(&str_len); + sharkd_json_result_prologue(rpcid); + sharkd_json_value_string("file", filename); + sharkd_json_value_string("mime", mime); + sharkd_json_value_base64("data", eo_entry->payload_data, eo_entry->payload_len); + sharkd_json_result_epilogue(); + } + else + { + sharkd_json_result_prologue(rpcid); + sharkd_json_result_epilogue(); + } + } + else if (!strcmp(tok_token, "ssl-secrets")) + { + gsize str_len; + char *str = ssl_export_sessions(&str_len); - if (str) - { - const char *mime = "text/plain"; - const char *filename = "keylog.txt"; + if (str) + { + const char *mime = "text/plain"; + const char *filename = "keylog.txt"; - sharkd_json_result_prologue(rpcid); - sharkd_json_value_string("file", filename); - sharkd_json_value_string("mime", mime); - sharkd_json_value_base64("data", str, str_len); - sharkd_json_result_epilogue(); - } - g_free(str); - } - else if (!strncmp(tok_token, "rtp:", 4)) - { - struct sharkd_download_rtp rtp_req; - GString *tap_error; + sharkd_json_result_prologue(rpcid); + sharkd_json_value_string("file", filename); + sharkd_json_value_string("mime", mime); + sharkd_json_value_base64("data", str, str_len); + sharkd_json_result_epilogue(); + } + g_free(str); + } + else if (!strncmp(tok_token, "rtp:", 4)) + { + struct sharkd_download_rtp rtp_req; + GString *tap_error; - memset(&rtp_req, 0, sizeof(rtp_req)); - if (!sharkd_rtp_match_init(&rtp_req.id, tok_token + 4)) - { - sharkd_json_error( - rpcid, -10001, NULL, - "sharkd_session_process_download() rtp tokenizing error %s", tok_token - ); - return; - } + memset(&rtp_req, 0, sizeof(rtp_req)); + if (!sharkd_rtp_match_init(&rtp_req.id, tok_token + 4)) + { + sharkd_json_error( + rpcid, -10001, NULL, + "sharkd_session_process_download() rtp tokenizing error %s", tok_token + ); + return; + } - tap_error = register_tap_listener("rtp", &rtp_req, NULL, 0, NULL, sharkd_session_packet_download_tap_rtp_cb, NULL, NULL); - if (tap_error) - { - sharkd_json_error( - rpcid, -10002, NULL, - "sharkd_session_process_download() rtp error %s", tap_error->str - ); - g_string_free(tap_error, TRUE); - return; - } + tap_error = register_tap_listener("rtp", &rtp_req, NULL, 0, NULL, sharkd_session_packet_download_tap_rtp_cb, NULL, NULL); + if (tap_error) + { + sharkd_json_error( + rpcid, -10002, NULL, + "sharkd_session_process_download() rtp error %s", tap_error->str + ); + g_string_free(tap_error, TRUE); + return; + } - sharkd_retap(); - remove_tap_listener(&rtp_req); + sharkd_retap(); + remove_tap_listener(&rtp_req); - if (rtp_req.packets) - { - const char *mime = "audio/x-wav"; - const char *filename = tok_token; + if (rtp_req.packets) + { + const char *mime = "audio/x-wav"; + const char *filename = tok_token; - sharkd_json_result_prologue(rpcid); - sharkd_json_value_string("file", filename); - sharkd_json_value_string("mime", mime); + sharkd_json_result_prologue(rpcid); + sharkd_json_value_string("file", filename); + sharkd_json_value_string("mime", mime); - sharkd_json_value_anyf("data", NULL); - json_dumper_begin_base64(&dumper); - sharkd_rtp_download_decode(&rtp_req); - json_dumper_end_base64(&dumper); + sharkd_json_value_anyf("data", NULL); + json_dumper_begin_base64(&dumper); + sharkd_rtp_download_decode(&rtp_req); + json_dumper_end_base64(&dumper); - sharkd_json_result_epilogue(); + sharkd_json_result_epilogue(); - g_slist_free_full(rtp_req.packets, sharkd_rtp_download_free_items); - } - } + g_slist_free_full(rtp_req.packets, sharkd_rtp_download_free_items); + } + } } static void sharkd_session_process(char *buf, const jsmntok_t *tokens, int count) { - if (json_prep(buf, tokens, count)) - { - /* don't need [0] token */ - tokens++; - count--; + if (json_prep(buf, tokens, count)) + { + /* don't need [0] token */ + tokens++; + count--; - const char* tok_method = json_find_attr(buf, tokens, count, "method"); + const char* tok_method = json_find_attr(buf, tokens, count, "method"); - if (!tok_method) { - sharkd_json_error( - rpcid, -32601, NULL, - "No method found"); - return; - } - if (!strcmp(tok_method, "load")) - sharkd_session_process_load(buf, tokens, count); - else if (!strcmp(tok_method, "status")) - sharkd_session_process_status(); - else if (!strcmp(tok_method, "analyse")) - sharkd_session_process_analyse(); - else if (!strcmp(tok_method, "info")) - sharkd_session_process_info(); - else if (!strcmp(tok_method, "check")) - sharkd_session_process_check(buf, tokens, count); - else if (!strcmp(tok_method, "complete")) - sharkd_session_process_complete(buf, tokens, count); - else if (!strcmp(tok_method, "frames")) - sharkd_session_process_frames(buf, tokens, count); - else if (!strcmp(tok_method, "tap")) - sharkd_session_process_tap(buf, tokens, count); - else if (!strcmp(tok_method, "follow")) - sharkd_session_process_follow(buf, tokens, count); - else if (!strcmp(tok_method, "iograph")) - sharkd_session_process_iograph(buf, tokens, count); - else if (!strcmp(tok_method, "intervals")) - sharkd_session_process_intervals(buf, tokens, count); - else if (!strcmp(tok_method, "frame")) - sharkd_session_process_frame(buf, tokens, count); - else if (!strcmp(tok_method, "setcomment")) - sharkd_session_process_setcomment(buf, tokens, count); - else if (!strcmp(tok_method, "setconf")) - sharkd_session_process_setconf(buf, tokens, count); - else if (!strcmp(tok_method, "dumpconf")) - sharkd_session_process_dumpconf(buf, tokens, count); - else if (!strcmp(tok_method, "download")) - sharkd_session_process_download(buf, tokens, count); - else if (!strcmp(tok_method, "bye")) - { - sharkd_json_simple_ok(rpcid); - exit(0); - } - else - { - sharkd_json_error( - rpcid, -32601, NULL, - "The method \"%s\" is unknown", tok_method - ); - } - } + if (!tok_method) { + sharkd_json_error( + rpcid, -32601, NULL, + "No method found"); + return; + } + if (!strcmp(tok_method, "load")) + sharkd_session_process_load(buf, tokens, count); + else if (!strcmp(tok_method, "status")) + sharkd_session_process_status(); + else if (!strcmp(tok_method, "analyse")) + sharkd_session_process_analyse(); + else if (!strcmp(tok_method, "info")) + sharkd_session_process_info(); + else if (!strcmp(tok_method, "check")) + sharkd_session_process_check(buf, tokens, count); + else if (!strcmp(tok_method, "complete")) + sharkd_session_process_complete(buf, tokens, count); + else if (!strcmp(tok_method, "frames")) + sharkd_session_process_frames(buf, tokens, count); + else if (!strcmp(tok_method, "tap")) + sharkd_session_process_tap(buf, tokens, count); + else if (!strcmp(tok_method, "follow")) + sharkd_session_process_follow(buf, tokens, count); + else if (!strcmp(tok_method, "iograph")) + sharkd_session_process_iograph(buf, tokens, count); + else if (!strcmp(tok_method, "intervals")) + sharkd_session_process_intervals(buf, tokens, count); + else if (!strcmp(tok_method, "frame")) + sharkd_session_process_frame(buf, tokens, count); + else if (!strcmp(tok_method, "setcomment")) + sharkd_session_process_setcomment(buf, tokens, count); + else if (!strcmp(tok_method, "setconf")) + sharkd_session_process_setconf(buf, tokens, count); + else if (!strcmp(tok_method, "dumpconf")) + sharkd_session_process_dumpconf(buf, tokens, count); + else if (!strcmp(tok_method, "download")) + sharkd_session_process_download(buf, tokens, count); + else if (!strcmp(tok_method, "bye")) + { + sharkd_json_simple_ok(rpcid); + exit(0); + } + else + { + sharkd_json_error( + rpcid, -32601, NULL, + "The method \"%s\" is unknown", tok_method + ); + } + } } int sharkd_session_main(int mode_setting) { - char buf[2 * 1024]; - jsmntok_t *tokens = NULL; - int tokens_max = -1; + char buf[2 * 1024]; + jsmntok_t *tokens = NULL; + int tokens_max = -1; - mode = mode_setting; + mode = mode_setting; - fprintf(stderr, "Hello in child.\n"); + fprintf(stderr, "Hello in child.\n"); - dumper.output_file = stdout; + dumper.output_file = stdout; - filter_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, sharkd_session_filter_free); + filter_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, sharkd_session_filter_free); #ifdef HAVE_MAXMINDDB - /* mmdbresolve was stopped before fork(), force starting it */ - uat_get_table_by_name("MaxMind Database Paths")->post_update_cb(); + /* mmdbresolve was stopped before fork(), force starting it */ + uat_get_table_by_name("MaxMind Database Paths")->post_update_cb(); #endif - while (fgets(buf, sizeof(buf), stdin)) - { - /* every command is line seperated JSON */ - int ret; + while (fgets(buf, sizeof(buf), stdin)) + { + /* every command is line seperated JSON */ + int ret; - ret = json_parse(buf, NULL, 0); - if (ret <= 0) - { - sharkd_json_error( - rpcid, -32600, NULL, - "Invalid JSON(1)" - ); - continue; - } + ret = json_parse(buf, NULL, 0); + if (ret <= 0) + { + sharkd_json_error( + rpcid, -32600, NULL, + "Invalid JSON(1)" + ); + continue; + } - /* fprintf(stderr, "JSON: %d tokens\n", ret); */ - ret += 1; + /* fprintf(stderr, "JSON: %d tokens\n", ret); */ + ret += 1; - if (tokens == NULL || tokens_max < ret) - { - tokens_max = ret; - tokens = (jsmntok_t *) g_realloc(tokens, sizeof(jsmntok_t) * tokens_max); - } + if (tokens == NULL || tokens_max < ret) + { + tokens_max = ret; + tokens = (jsmntok_t *) g_realloc(tokens, sizeof(jsmntok_t) * tokens_max); + } - memset(tokens, 0, ret * sizeof(jsmntok_t)); + memset(tokens, 0, ret * sizeof(jsmntok_t)); - ret = json_parse(buf, tokens, ret); - if (ret <= 0) - { - sharkd_json_error( - rpcid, -32600, NULL, - "Invalid JSON(2)" - ); - continue; - } + ret = json_parse(buf, tokens, ret); + if (ret <= 0) + { + sharkd_json_error( + rpcid, -32600, NULL, + "Invalid JSON(2)" + ); + continue; + } - host_name_lookup_process(); + host_name_lookup_process(); - sharkd_session_process(buf, tokens, ret); - } + sharkd_session_process(buf, tokens, ret); + } - g_hash_table_destroy(filter_table); - g_free(tokens); + g_hash_table_destroy(filter_table); + g_free(tokens); - return 0; + return 0; } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 8 - * tab-width: 8 - * indent-tabs-mode: t - * End: - * - * vi: set shiftwidth=8 tabstop=8 noexpandtab: - * :indentSize=8:tabSize=8:noTabs=false: - */ diff --git a/tfshark.c b/tfshark.c index 701f702ce0..1d8a6c8a2f 100644 --- a/tfshark.c +++ b/tfshark.c @@ -91,10 +91,10 @@ static gboolean perform_two_pass_analysis; * The way the packet decode is to be written. */ typedef enum { - WRITE_TEXT, /* summary or detail text */ - WRITE_XML, /* PDML or PSML */ - WRITE_FIELDS /* User defined list of fields */ - /* Add CSV and the like here */ + WRITE_TEXT, /* summary or detail text */ + WRITE_XML, /* PDML or PSML */ + WRITE_FIELDS /* User defined list of fields */ + /* Add CSV and the like here */ } output_action_e; static output_action_e output_action; @@ -116,14 +116,14 @@ static const char *separator = ""; static gboolean process_file(capture_file *, int, gint64); static gboolean process_packet_single_pass(capture_file *cf, - epan_dissect_t *edt, gint64 offset, wtap_rec *rec, - const guchar *pd, guint tap_flags); + epan_dissect_t *edt, gint64 offset, wtap_rec *rec, + const guchar *pd, guint tap_flags); static void show_print_file_io_error(int err); static gboolean write_preamble(capture_file *cf); static gboolean print_packet(capture_file *cf, epan_dissect_t *edt); static gboolean write_finale(void); static const char *cf_open_error_message(int err, gchar *err_info, - gboolean for_writing, int file_type); + gboolean for_writing, int file_type); static void tfshark_cmdarg_err(const char *msg_format, va_list ap); static void tfshark_cmdarg_err_cont(const char *msg_format, va_list ap); @@ -132,852 +132,854 @@ static GHashTable *output_only_tables = NULL; #if 0 struct string_elem { - const char *sstr; /* The short string */ - const char *lstr; /* The long string */ + const char *sstr; /* The short string */ + const char *lstr; /* The long string */ }; static gint string_compare(gconstpointer a, gconstpointer b) { - return strcmp(((const struct string_elem *)a)->sstr, - ((const struct string_elem *)b)->sstr); + return strcmp(((const struct string_elem *)a)->sstr, + ((const struct string_elem *)b)->sstr); } static void string_elem_print(gpointer data, gpointer not_used _U_) { - fprintf(stderr, " %s - %s\n", - ((struct string_elem *)data)->sstr, - ((struct string_elem *)data)->lstr); + fprintf(stderr, " %s - %s\n", + ((struct string_elem *)data)->sstr, + ((struct string_elem *)data)->lstr); } #endif static void print_usage(FILE *output) { - fprintf(output, "\n"); - fprintf(output, "Usage: tfshark [options] ...\n"); - fprintf(output, "\n"); + fprintf(output, "\n"); + fprintf(output, "Usage: tfshark [options] ...\n"); + fprintf(output, "\n"); - /*fprintf(output, "\n");*/ - fprintf(output, "Input file:\n"); - fprintf(output, " -r set the filename to read from (no pipes or stdin)\n"); + /*fprintf(output, "\n");*/ + fprintf(output, "Input file:\n"); + fprintf(output, " -r set the filename to read from (no pipes or stdin)\n"); - fprintf(output, "\n"); - fprintf(output, "Processing:\n"); - fprintf(output, " -2 perform a two-pass analysis\n"); - fprintf(output, " -R packet Read filter in Wireshark display filter syntax\n"); - fprintf(output, " (requires -2)\n"); - fprintf(output, " -Y packet displaY filter in Wireshark display filter\n"); - fprintf(output, " syntax\n"); - fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE); - fprintf(output, " \"Decode As\", see the man page for details\n"); - fprintf(output, " Example: tcp.port==8888,http\n"); + fprintf(output, "\n"); + fprintf(output, "Processing:\n"); + fprintf(output, " -2 perform a two-pass analysis\n"); + fprintf(output, " -R packet Read filter in Wireshark display filter syntax\n"); + fprintf(output, " (requires -2)\n"); + fprintf(output, " -Y packet displaY filter in Wireshark display filter\n"); + fprintf(output, " syntax\n"); + fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE); + fprintf(output, " \"Decode As\", see the man page for details\n"); + fprintf(output, " Example: tcp.port==8888,http\n"); - /*fprintf(output, "\n");*/ - fprintf(output, "Output:\n"); - fprintf(output, " -C start with specified configuration profile\n"); - fprintf(output, " -V add output of packet tree (Packet Details)\n"); - fprintf(output, " -O Only show packet details of these protocols, comma\n"); - fprintf(output, " separated\n"); - fprintf(output, " -S the line separator to print between packets\n"); - fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n"); - fprintf(output, " -T pdml|ps|psml|text|fields\n"); - fprintf(output, " format of text output (def: text)\n"); - fprintf(output, " -e field to print if -Tfields selected (e.g. tcp.port,\n"); - fprintf(output, " _ws.col.Info)\n"); - fprintf(output, " this option can be repeated to print multiple fields\n"); - fprintf(output, " -E= set options for output when -Tfields selected:\n"); - fprintf(output, " header=y|n switch headers on and off\n"); - fprintf(output, " separator=/t|/s| select tab, space, printable character as separator\n"); - fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n"); - fprintf(output, " aggregator=,|/s| select comma, space, printable character as\n"); - fprintf(output, " aggregator\n"); - fprintf(output, " quote=d|s|n select double, single, no quotes for values\n"); - fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n"); - fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n"); - fprintf(output, " -l flush standard output after each packet\n"); - fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n"); - fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n"); - fprintf(output, " -X : eXtension options, see the man page for details\n"); - fprintf(output, " -z various statistics, see the man page for details\n"); - fprintf(output, "\n"); + /*fprintf(output, "\n");*/ + fprintf(output, "Output:\n"); + fprintf(output, " -C start with specified configuration profile\n"); + fprintf(output, " -V add output of packet tree (Packet Details)\n"); + fprintf(output, " -O Only show packet details of these protocols, comma\n"); + fprintf(output, " separated\n"); + fprintf(output, " -S the line separator to print between packets\n"); + fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n"); + fprintf(output, " -T pdml|ps|psml|text|fields\n"); + fprintf(output, " format of text output (def: text)\n"); + fprintf(output, " -e field to print if -Tfields selected (e.g. tcp.port,\n"); + fprintf(output, " _ws.col.Info)\n"); + fprintf(output, " this option can be repeated to print multiple fields\n"); + fprintf(output, " -E= set options for output when -Tfields selected:\n"); + fprintf(output, " header=y|n switch headers on and off\n"); + fprintf(output, " separator=/t|/s| select tab, space, printable character as separator\n"); + fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n"); + fprintf(output, " aggregator=,|/s| select comma, space, printable character as\n"); + fprintf(output, " aggregator\n"); + fprintf(output, " quote=d|s|n select double, single, no quotes for values\n"); + fprintf(output, " -t a|ad|d|dd|e|r|u|ud output format of time stamps (def: r: rel. to first)\n"); + fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n"); + fprintf(output, " -l flush standard output after each packet\n"); + fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n"); + fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n"); + fprintf(output, " -X : eXtension options, see the man page for details\n"); + fprintf(output, " -z various statistics, see the man page for details\n"); + fprintf(output, "\n"); - ws_log_print_usage(output); - fprintf(output, "\n"); + ws_log_print_usage(output); + fprintf(output, "\n"); - fprintf(output, "Miscellaneous:\n"); - fprintf(output, " -h display this help and exit\n"); - fprintf(output, " -v display version info and exit\n"); - fprintf(output, " -o : ... override preference setting\n"); - fprintf(output, " -K keytab file to use for kerberos decryption\n"); - fprintf(output, " -G [report] dump one of several available reports and exit\n"); - fprintf(output, " default report=\"fields\"\n"); - fprintf(output, " use \"-G ?\" for more help\n"); + fprintf(output, "Miscellaneous:\n"); + fprintf(output, " -h display this help and exit\n"); + fprintf(output, " -v display version info and exit\n"); + fprintf(output, " -o : ... override preference setting\n"); + fprintf(output, " -K keytab file to use for kerberos decryption\n"); + fprintf(output, " -G [report] dump one of several available reports and exit\n"); + fprintf(output, " default report=\"fields\"\n"); + fprintf(output, " use \"-G ?\" for more help\n"); } static void glossary_option_help(void) { - FILE *output; + FILE *output; - output = stdout; + output = stdout; - fprintf(output, "%s\n", get_appname_and_version()); + fprintf(output, "%s\n", get_appname_and_version()); - fprintf(output, "\n"); - fprintf(output, "Usage: tfshark -G [report]\n"); - fprintf(output, "\n"); - fprintf(output, "Glossary table reports:\n"); - fprintf(output, " -G column-formats dump column format codes and exit\n"); - fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n"); - fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n"); - fprintf(output, " -G fields dump fields glossary and exit\n"); - fprintf(output, " -G ftypes dump field type basic and descriptive names\n"); - fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n"); - fprintf(output, " -G plugins dump installed plugins and exit\n"); - fprintf(output, " -G protocols dump protocols in registration database and exit\n"); - fprintf(output, " -G values dump value, range, true/false strings and exit\n"); - fprintf(output, "\n"); - fprintf(output, "Preference reports:\n"); - fprintf(output, " -G currentprefs dump current preferences and exit\n"); - fprintf(output, " -G defaultprefs dump default preferences and exit\n"); - fprintf(output, "\n"); + fprintf(output, "\n"); + fprintf(output, "Usage: tfshark -G [report]\n"); + fprintf(output, "\n"); + fprintf(output, "Glossary table reports:\n"); + fprintf(output, " -G column-formats dump column format codes and exit\n"); + fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n"); + fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n"); + fprintf(output, " -G fields dump fields glossary and exit\n"); + fprintf(output, " -G ftypes dump field type basic and descriptive names\n"); + fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n"); + fprintf(output, " -G plugins dump installed plugins and exit\n"); + fprintf(output, " -G protocols dump protocols in registration database and exit\n"); + fprintf(output, " -G values dump value, range, true/false strings and exit\n"); + fprintf(output, "\n"); + fprintf(output, "Preference reports:\n"); + fprintf(output, " -G currentprefs dump current preferences and exit\n"); + fprintf(output, " -G defaultprefs dump default preferences and exit\n"); + fprintf(output, "\n"); } static void -print_current_user(void) { - gchar *cur_user, *cur_group; +print_current_user(void) +{ + gchar *cur_user, *cur_group; - if (started_with_special_privs()) { - cur_user = get_cur_username(); - cur_group = get_cur_groupname(); - fprintf(stderr, "Running as user \"%s\" and group \"%s\".", - cur_user, cur_group); - g_free(cur_user); - g_free(cur_group); - if (running_with_special_privs()) { - fprintf(stderr, " This could be dangerous."); + if (started_with_special_privs()) { + cur_user = get_cur_username(); + cur_group = get_cur_groupname(); + fprintf(stderr, "Running as user \"%s\" and group \"%s\".", + cur_user, cur_group); + g_free(cur_user); + g_free(cur_group); + if (running_with_special_privs()) { + fprintf(stderr, " This could be dangerous."); + } + fprintf(stderr, "\n"); } - fprintf(stderr, "\n"); - } } static void get_tfshark_runtime_version_info(GString *str) { - /* stuff used by libwireshark */ - epan_get_runtime_version_info(str); + /* stuff used by libwireshark */ + epan_get_runtime_version_info(str); } int main(int argc, char *argv[]) { - char *init_progfile_dir_error; - int opt; - static const struct ws_option long_options[] = { - {"help", ws_no_argument, NULL, 'h'}, - {"version", ws_no_argument, NULL, 'v'}, - {0, 0, 0, 0 } - }; - gboolean arg_error = FALSE; + char *init_progfile_dir_error; + int opt; + static const struct ws_option long_options[] = { + {"help", ws_no_argument, NULL, 'h'}, + {"version", ws_no_argument, NULL, 'v'}, + {0, 0, 0, 0 } + }; + gboolean arg_error = FALSE; - int err; - volatile gboolean success; - volatile int exit_status = 0; - gboolean quiet = FALSE; - gchar *volatile cf_name = NULL; - gchar *rfilter = NULL; - gchar *dfilter = NULL; - dfilter_t *rfcode = NULL; - dfilter_t *dfcode = NULL; - gchar *err_msg; - e_prefs *prefs_p; - gchar *output_only = NULL; + int err; + volatile gboolean success; + volatile int exit_status = 0; + gboolean quiet = FALSE; + gchar *volatile cf_name = NULL; + gchar *rfilter = NULL; + gchar *dfilter = NULL; + dfilter_t *rfcode = NULL; + dfilter_t *dfcode = NULL; + gchar *err_msg; + e_prefs *prefs_p; + gchar *output_only = NULL; -/* - * The leading + ensures that getopt_long() does not permute the argv[] - * entries. - * - * We have to make sure that the first getopt_long() preserves the content - * of argv[] for the subsequent getopt_long() call. - * - * We use getopt_long() in both cases to ensure that we're using a routine - * whose permutation behavior we can control in the same fashion on all - * platforms, and so that, if we ever need to process a long argument before - * doing further initialization, we can do so. - * - * Glibc and Solaris libc document that a leading + disables permutation - * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD - * and macOS don't document it, but do so anyway. - * - * We do *not* use a leading - because the behavior of a leading - is - * platform-dependent. - */ + /* + * The leading + ensures that getopt_long() does not permute the argv[] + * entries. + * + * We have to make sure that the first getopt_long() preserves the content + * of argv[] for the subsequent getopt_long() call. + * + * We use getopt_long() in both cases to ensure that we're using a routine + * whose permutation behavior we can control in the same fashion on all + * platforms, and so that, if we ever need to process a long argument before + * doing further initialization, we can do so. + * + * Glibc and Solaris libc document that a leading + disables permutation + * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD + * and macOS don't document it, but do so anyway. + * + * We do *not* use a leading - because the behavior of a leading - is + * platform-dependent. + */ #define OPTSTRING "+2C:d:e:E:hK:lo:O:qQr:R:S:t:T:u:vVxX:Y:z:" - static const char optstring[] = OPTSTRING; - static const struct report_message_routines tfshark_report_routines = { - failure_message, - failure_message, - open_failure_message, - read_failure_message, - write_failure_message, - cfile_open_failure_message, - cfile_dump_open_failure_message, - cfile_read_failure_message, - cfile_write_failure_message, - cfile_close_failure_message - }; + static const char optstring[] = OPTSTRING; + static const struct report_message_routines tfshark_report_routines = { + failure_message, + failure_message, + open_failure_message, + read_failure_message, + write_failure_message, + cfile_open_failure_message, + cfile_dump_open_failure_message, + cfile_read_failure_message, + cfile_write_failure_message, + cfile_close_failure_message + }; - /* - * Set the C-language locale to the native environment and set the - * code page to UTF-8 on Windows. - */ + /* + * Set the C-language locale to the native environment and set the + * code page to UTF-8 on Windows. + */ #ifdef _WIN32 - setlocale(LC_ALL, ".UTF-8"); + setlocale(LC_ALL, ".UTF-8"); #else - setlocale(LC_ALL, ""); + setlocale(LC_ALL, ""); #endif - cmdarg_err_init(tfshark_cmdarg_err, tfshark_cmdarg_err_cont); + cmdarg_err_init(tfshark_cmdarg_err, tfshark_cmdarg_err_cont); - /* Initialize log handler early so we can have proper logging during startup. */ - ws_log_init("tfshark", vcmdarg_err); + /* Initialize log handler early so we can have proper logging during startup. */ + ws_log_init("tfshark", vcmdarg_err); - /* Early logging command-line initialization. */ - ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION); + /* Early logging command-line initialization. */ + ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION); #ifdef _WIN32 - create_app_running_mutex(); + create_app_running_mutex(); #endif /* _WIN32 */ - /* - * Get credential information for later use, and drop privileges - * before doing anything else. - * Let the user know if anything happened. - */ - init_process_policies(); - relinquish_special_privs_perm(); - print_current_user(); + /* + * Get credential information for later use, and drop privileges + * before doing anything else. + * Let the user know if anything happened. + */ + init_process_policies(); + relinquish_special_privs_perm(); + print_current_user(); - /* - * Attempt to get the pathname of the directory containing the - * executable file. - */ - init_progfile_dir_error = init_progfile_dir(argv[0]); - if (init_progfile_dir_error != NULL) { - fprintf(stderr, - "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n", - init_progfile_dir_error); - g_free(init_progfile_dir_error); - } - - initialize_funnel_ops(); - - /* Initialize the version information. */ - ws_init_version_info("TFShark (Wireshark)", NULL, - epan_get_compiled_version_info, - get_tfshark_runtime_version_info); - - /* - * In order to have the -X opts assigned before the wslua machine starts - * we need to call getopts before epan_init() gets called. - * - * In order to handle, for example, -o options, we also need to call it - * *after* epan_init() gets called, so that the dissectors have had a - * chance to register their preferences. - * - * XXX - can we do this all with one getopt_long() call, saving the - * arguments we can't handle until after initializing libwireshark, - * and then process them after initializing libwireshark? - */ - ws_opterr = 0; - - while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { - switch (opt) { - case 'C': /* Configuration Profile */ - if (profile_exists (ws_optarg, FALSE)) { - set_profile_name (ws_optarg); - } else { - cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg); - return 1; - } - break; - case 'O': /* Only output these protocols */ - output_only = g_strdup(ws_optarg); - /* FALLTHROUGH */ - case 'V': /* Verbose */ - print_details = TRUE; - print_packet_info = TRUE; - break; - case 'x': /* Print packet data in hex (and ASCII) */ - print_hex = TRUE; - /* The user asked for hex output, so let's ensure they get it, - * even if they're writing to a file. - */ - print_packet_info = TRUE; - break; - case 'X': - ex_opt_add(ws_optarg); - break; - default: - break; + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + init_progfile_dir_error = init_progfile_dir(argv[0]); + if (init_progfile_dir_error != NULL) { + fprintf(stderr, + "tfshark: Can't get pathname of directory containing the tfshark program: %s.\n", + init_progfile_dir_error); + g_free(init_progfile_dir_error); } - } - /* - * Print packet summary information is the default, unless either -V or -x - * were specified. Note that this is new behavior, which - * allows for the possibility of printing only hex/ascii output without - * necessarily requiring that either the summary or details be printed too. - */ - if (print_summary == -1) - print_summary = (print_details || print_hex) ? FALSE : TRUE; + initialize_funnel_ops(); - init_report_message("tfshark", &tfshark_report_routines); + /* Initialize the version information. */ + ws_init_version_info("TFShark (Wireshark)", NULL, + epan_get_compiled_version_info, + get_tfshark_runtime_version_info); - timestamp_set_type(TS_RELATIVE); - timestamp_set_precision(TS_PREC_AUTO); - timestamp_set_seconds_type(TS_SECONDS_DEFAULT); + /* + * In order to have the -X opts assigned before the wslua machine starts + * we need to call getopts before epan_init() gets called. + * + * In order to handle, for example, -o options, we also need to call it + * *after* epan_init() gets called, so that the dissectors have had a + * chance to register their preferences. + * + * XXX - can we do this all with one getopt_long() call, saving the + * arguments we can't handle until after initializing libwireshark, + * and then process them after initializing libwireshark? + */ + ws_opterr = 0; - /* - * Libwiretap must be initialized before libwireshark is, so that - * dissection-time handlers for file-type-dependent blocks can - * register using the file type/subtype value for the file type. - * - * XXX - TFShark shouldn't use libwiretap, as it's a file dissector - * and should read all files as raw bytes and then try to dissect them. - * It needs to handle file types its own way, because we would want - * to support dissecting file-type-specific blocks when dissecting - * capture files, but that mechanism should support plugins for - * other files, too, if *their* formats are extensible. - */ - wtap_init(TRUE); + while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { + switch (opt) { + case 'C': /* Configuration Profile */ + if (profile_exists (ws_optarg, FALSE)) { + set_profile_name (ws_optarg); + } else { + cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg); + return 1; + } + break; + case 'O': /* Only output these protocols */ + output_only = g_strdup(ws_optarg); + /* FALLTHROUGH */ + case 'V': /* Verbose */ + print_details = TRUE; + print_packet_info = TRUE; + break; + case 'x': /* Print packet data in hex (and ASCII) */ + print_hex = TRUE; + /* The user asked for hex output, so let's ensure they get it, + * even if they're writing to a file. + */ + print_packet_info = TRUE; + break; + case 'X': + ex_opt_add(ws_optarg); + break; + default: + break; + } + } - /* Register all dissectors; we must do this before checking for the - "-G" flag, as the "-G" flag dumps information registered by the - dissectors, and we must do it before we read the preferences, in - case any dissectors register preferences. */ - if (!epan_init(NULL, NULL, TRUE)) { - exit_status = INIT_FAILED; - goto clean_exit; - } + /* + * Print packet summary information is the default, unless either -V or -x + * were specified. Note that this is new behavior, which + * allows for the possibility of printing only hex/ascii output without + * necessarily requiring that either the summary or details be printed too. + */ + if (print_summary == -1) + print_summary = (print_details || print_hex) ? FALSE : TRUE; - /* Register all tap listeners; we do this before we parse the arguments, - as the "-z" argument can specify a registered tap. */ + init_report_message("tfshark", &tfshark_report_routines); - /* we register the plugin taps before the other taps because - stats_tree taps plugins will be registered as tap listeners - by stats_tree_stat.c and need to registered before that */ + timestamp_set_type(TS_RELATIVE); + timestamp_set_precision(TS_PREC_AUTO); + timestamp_set_seconds_type(TS_SECONDS_DEFAULT); - /* XXX Disable tap registration for now until we can get tfshark set up with - * its own set of taps and the necessary registration function etc. - register_all_tap_listeners(); - */ + /* + * Libwiretap must be initialized before libwireshark is, so that + * dissection-time handlers for file-type-dependent blocks can + * register using the file type/subtype value for the file type. + * + * XXX - TFShark shouldn't use libwiretap, as it's a file dissector + * and should read all files as raw bytes and then try to dissect them. + * It needs to handle file types its own way, because we would want + * to support dissecting file-type-specific blocks when dissecting + * capture files, but that mechanism should support plugins for + * other files, too, if *their* formats are extensible. + */ + wtap_init(TRUE); - /* If invoked with the "-G" flag, we dump out information based on - the argument to the "-G" flag; if no argument is specified, - for backwards compatibility we dump out a glossary of display - filter symbols. + /* Register all dissectors; we must do this before checking for the + "-G" flag, as the "-G" flag dumps information registered by the + dissectors, and we must do it before we read the preferences, in + case any dissectors register preferences. */ + if (!epan_init(NULL, NULL, TRUE)) { + exit_status = INIT_FAILED; + goto clean_exit; + } - XXX - we do this here, for now, to support "-G" with no arguments. - If none of our build or other processes uses "-G" with no arguments, - we can just process it with the other arguments. */ - if (argc >= 2 && strcmp(argv[1], "-G") == 0) { - proto_initialize_all_prefixes(); + /* Register all tap listeners; we do this before we parse the arguments, + as the "-z" argument can specify a registered tap. */ - if (argc == 2) - proto_registrar_dump_fields(); - else { - if (strcmp(argv[2], "column-formats") == 0) - column_dump_column_formats(); - else if (strcmp(argv[2], "currentprefs") == 0) { - epan_load_settings(); - write_prefs(NULL); - } - else if (strcmp(argv[2], "decodes") == 0) - dissector_dump_decodes(); - else if (strcmp(argv[2], "defaultprefs") == 0) - write_prefs(NULL); - else if (strcmp(argv[2], "dissector-tables") == 0) - dissector_dump_dissector_tables(); - else if (strcmp(argv[2], "fields") == 0) - proto_registrar_dump_fields(); - else if (strcmp(argv[2], "ftypes") == 0) - proto_registrar_dump_ftypes(); - else if (strcmp(argv[2], "heuristic-decodes") == 0) - dissector_dump_heur_decodes(); - else if (strcmp(argv[2], "plugins") == 0) { + /* we register the plugin taps before the other taps because + stats_tree taps plugins will be registered as tap listeners + by stats_tree_stat.c and need to registered before that */ + + /* XXX Disable tap registration for now until we can get tfshark set up with + * its own set of taps and the necessary registration function etc. + register_all_tap_listeners(); + */ + + /* If invoked with the "-G" flag, we dump out information based on + the argument to the "-G" flag; if no argument is specified, + for backwards compatibility we dump out a glossary of display + filter symbols. + + XXX - we do this here, for now, to support "-G" with no arguments. + If none of our build or other processes uses "-G" with no arguments, + we can just process it with the other arguments. */ + if (argc >= 2 && strcmp(argv[1], "-G") == 0) { + proto_initialize_all_prefixes(); + + if (argc == 2) + proto_registrar_dump_fields(); + else { + if (strcmp(argv[2], "column-formats") == 0) + column_dump_column_formats(); + else if (strcmp(argv[2], "currentprefs") == 0) { + epan_load_settings(); + write_prefs(NULL); + } + else if (strcmp(argv[2], "decodes") == 0) + dissector_dump_decodes(); + else if (strcmp(argv[2], "defaultprefs") == 0) + write_prefs(NULL); + else if (strcmp(argv[2], "dissector-tables") == 0) + dissector_dump_dissector_tables(); + else if (strcmp(argv[2], "fields") == 0) + proto_registrar_dump_fields(); + else if (strcmp(argv[2], "ftypes") == 0) + proto_registrar_dump_ftypes(); + else if (strcmp(argv[2], "heuristic-decodes") == 0) + dissector_dump_heur_decodes(); + else if (strcmp(argv[2], "plugins") == 0) { #ifdef HAVE_PLUGINS - plugins_dump_all(); + plugins_dump_all(); #endif #ifdef HAVE_LUA - wslua_plugins_dump_all(); + wslua_plugins_dump_all(); #endif - } - else if (strcmp(argv[2], "protocols") == 0) - proto_registrar_dump_protocols(); - else if (strcmp(argv[2], "values") == 0) - proto_registrar_dump_values(); - else if (strcmp(argv[2], "?") == 0) - glossary_option_help(); - else if (strcmp(argv[2], "-?") == 0) - glossary_option_help(); - else { - cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]); - exit_status = INVALID_OPTION; + } + else if (strcmp(argv[2], "protocols") == 0) + proto_registrar_dump_protocols(); + else if (strcmp(argv[2], "values") == 0) + proto_registrar_dump_values(); + else if (strcmp(argv[2], "?") == 0) + glossary_option_help(); + else if (strcmp(argv[2], "-?") == 0) + glossary_option_help(); + else { + cmdarg_err("Invalid \"%s\" option for -G flag, enter -G ? for more help.", argv[2]); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } goto clean_exit; - } } - goto clean_exit; - } - /* Load libwireshark settings from the current profile. */ - prefs_p = epan_load_settings(); - prefs_loaded = TRUE; + /* Load libwireshark settings from the current profile. */ + prefs_p = epan_load_settings(); + prefs_loaded = TRUE; - cap_file_init(&cfile); + cap_file_init(&cfile); - /* Print format defaults to this. */ - print_format = PR_FMT_TEXT; + /* Print format defaults to this. */ + print_format = PR_FMT_TEXT; - output_fields = output_fields_new(); + output_fields = output_fields_new(); - /* - * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1. - * - * Also reset ws_opterr to 1, so that error messages are printed by - * getopt_long(). - */ - ws_optreset = 1; - ws_optind = 1; - ws_opterr = 1; + /* + * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1. + * + * Also reset ws_opterr to 1, so that error messages are printed by + * getopt_long(). + */ + ws_optreset = 1; + ws_optind = 1; + ws_opterr = 1; - /* Now get our args */ - while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { - switch (opt) { - case '2': /* Perform two pass analysis */ - perform_two_pass_analysis = TRUE; - break; - case 'C': - /* already processed; just ignore it now */ - break; - case 'e': - /* Field entry */ - output_fields_add(output_fields, ws_optarg); - break; - case 'E': - /* Field option */ - if (!output_fields_set_option(output_fields, ws_optarg)) { - cmdarg_err("\"%s\" is not a valid field output option=value pair.", ws_optarg); - output_fields_list_options(stderr); - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; + /* Now get our args */ + while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { + switch (opt) { + case '2': /* Perform two pass analysis */ + perform_two_pass_analysis = TRUE; + break; + case 'C': + /* already processed; just ignore it now */ + break; + case 'e': + /* Field entry */ + output_fields_add(output_fields, ws_optarg); + break; + case 'E': + /* Field option */ + if (!output_fields_set_option(output_fields, ws_optarg)) { + cmdarg_err("\"%s\" is not a valid field output option=value pair.", ws_optarg); + output_fields_list_options(stderr); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; - case 'h': /* Print help and exit */ - show_help_header("Analyze file structure."); - print_usage(stdout); - goto clean_exit; - break; - case 'l': /* "Line-buffer" standard output */ - /* The ANSI C standard does not appear to *require* that a line-buffered - stream be flushed to the host environment whenever a newline is - written, it just says that, on such a stream, characters "are - intended to be transmitted to or from the host environment as a - block when a new-line character is encountered". + case 'h': /* Print help and exit */ + show_help_header("Analyze file structure."); + print_usage(stdout); + goto clean_exit; + break; + case 'l': /* "Line-buffer" standard output */ + /* The ANSI C standard does not appear to *require* that a + line-buffered stream be flushed to the host environment + whenever a newline is written, it just says that, on such a + stream, characters "are intended to be transmitted to or + from the host environment as a block when a new-line + character is encountered". - The Visual C++ 6.0 C implementation doesn't do what is intended; - even if you set a stream to be line-buffered, it still doesn't - flush the buffer at the end of every line. + The Visual C++ 6.0 C implementation doesn't do what is + intended; even if you set a stream to be line-buffered, it + still doesn't flush the buffer at the end of every line. - The whole reason for the "-l" flag in either tcpdump or TShark - is to allow the output of a live capture to be piped to a program - or script and to have that script see the information for the - packet as soon as it's printed, rather than having to wait until - a standard I/O buffer fills up. + The whole reason for the "-l" flag in either tcpdump or + TShark is to allow the output of a live capture to be piped + to a program or script and to have that script see the + information for the packet as soon as it's printed, rather + than having to wait until a standard I/O buffer fills up. - So, if the "-l" flag is specified, we flush the standard output - at the end of a packet. This will do the right thing if we're - printing packet summary lines, and, as we print the entire protocol - tree for a single packet without waiting for anything to happen, - it should be as good as line-buffered mode if we're printing - protocol trees - arguably even better, as it may do fewer - writes. */ - line_buffered = TRUE; - break; - case 'o': /* Override preference from command line */ - { - char *errmsg = NULL; + So, if the "-l" flag is specified, we flush the standard + output at the end of a packet. This will do the right thing + if we're printing packet summary lines, and, as we print the + entire protocol tree for a single packet without waiting for + anything to happen, it should be as good as line-buffered + mode if we're printing protocol trees - arguably even + better, as it may do fewer writes. */ + line_buffered = TRUE; + break; + case 'o': /* Override preference from command line */ + { + char *errmsg = NULL; - switch (prefs_set_pref(ws_optarg, &errmsg)) { + switch (prefs_set_pref(ws_optarg, &errmsg)) { - case PREFS_SET_OK: - break; + case PREFS_SET_OK: + break; - case PREFS_SET_SYNTAX_ERR: - cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg, - errmsg ? ": " : "", errmsg ? errmsg : ""); - g_free(errmsg); - exit_status = INVALID_OPTION; - goto clean_exit; - break; + case PREFS_SET_SYNTAX_ERR: + cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg, + errmsg ? ": " : "", errmsg ? errmsg : ""); + g_free(errmsg); + exit_status = INVALID_OPTION; + goto clean_exit; + break; - case PREFS_SET_NO_SUCH_PREF: - cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg); - exit_status = INVALID_OPTION; - goto clean_exit; - break; + case PREFS_SET_NO_SUCH_PREF: + cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg); + exit_status = INVALID_OPTION; + goto clean_exit; + break; - case PREFS_SET_OBSOLETE: - cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg); - exit_status = INVALID_OPTION; - goto clean_exit; - break; - } - break; + case PREFS_SET_OBSOLETE: + cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg); + exit_status = INVALID_OPTION; + goto clean_exit; + break; + } + break; + } + case 'q': /* Quiet */ + quiet = TRUE; + break; + case 'Q': /* Really quiet */ + quiet = TRUE; + really_quiet = TRUE; + break; + case 'r': /* Read capture file x */ + cf_name = g_strdup(ws_optarg); + break; + case 'R': /* Read file filter */ + rfilter = ws_optarg; + break; + case 'S': /* Set the line Separator to be printed between packets */ + separator = g_strdup(ws_optarg); + break; + case 'T': /* printing Type */ + if (strcmp(ws_optarg, "text") == 0) { + output_action = WRITE_TEXT; + print_format = PR_FMT_TEXT; + } else if (strcmp(ws_optarg, "ps") == 0) { + output_action = WRITE_TEXT; + print_format = PR_FMT_PS; + } else if (strcmp(ws_optarg, "pdml") == 0) { + output_action = WRITE_XML; + print_details = TRUE; /* Need details */ + print_summary = FALSE; /* Don't allow summary */ + } else if (strcmp(ws_optarg, "psml") == 0) { + output_action = WRITE_XML; + print_details = FALSE; /* Don't allow details */ + print_summary = TRUE; /* Need summary */ + } else if (strcmp(ws_optarg, "fields") == 0) { + output_action = WRITE_FIELDS; + print_details = TRUE; /* Need full tree info */ + print_summary = FALSE; /* Don't allow summary */ + } else { + cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", ws_optarg); /* x */ + cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n" + "\t specified by the -E option.\n" + "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n" + "\t details of a decoded packet. This information is equivalent to\n" + "\t the packet details printed with the -V flag.\n" + "\t\"ps\" PostScript for a human-readable one-line summary of each of\n" + "\t the packets, or a multi-line view of the details of each of\n" + "\t the packets, depending on whether the -V flag was specified.\n" + "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n" + "\t summary information of a decoded packet. This information is\n" + "\t equivalent to the information shown in the one-line summary\n" + "\t printed by default.\n" + "\t\"text\" Text of a human-readable one-line summary of each of the\n" + "\t packets, or a multi-line view of the details of each of the\n" + "\t packets, depending on whether the -V flag was specified.\n" + "\t This is the default."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case 'v': /* Show version and exit */ + show_version(); + goto clean_exit; + case 'O': /* Only output these protocols */ + /* already processed; just ignore it now */ + break; + case 'V': /* Verbose */ + /* already processed; just ignore it now */ + break; + case 'x': /* Print packet data in hex (and ASCII) */ + /* already processed; just ignore it now */ + break; + case 'X': + /* already processed; just ignore it now */ + break; + case 'Y': + dfilter = ws_optarg; + break; + case 'z': + /* We won't call the init function for the stat this soon + as it would disallow MATE's fields (which are registered + by the preferences set callback) from being used as + part of a tap filter. Instead, we just add the argument + to a list of stat arguments. */ + if (strcmp("help", ws_optarg) == 0) { + fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n"); + list_stat_cmd_args(); + goto clean_exit; + } + if (!process_stat_cmd_arg(ws_optarg)) { + cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", ws_optarg); + list_stat_cmd_args(); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case 'd': /* Decode as rule */ + case 'K': /* Kerberos keytab file */ + case 't': /* Time stamp type */ + case 'u': /* Seconds type */ + case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */ + case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */ + case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */ + case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */ + if (!dissect_opts_handle_opt(opt, ws_optarg)) { + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + default: + case '?': /* Bad flag - print usage message */ + print_usage(stderr); + exit_status = INVALID_OPTION; + goto clean_exit; + break; + } } - case 'q': /* Quiet */ - quiet = TRUE; - break; - case 'Q': /* Really quiet */ - quiet = TRUE; - really_quiet = TRUE; - break; - case 'r': /* Read capture file x */ - cf_name = g_strdup(ws_optarg); - break; - case 'R': /* Read file filter */ - rfilter = ws_optarg; - break; - case 'S': /* Set the line Separator to be printed between packets */ - separator = g_strdup(ws_optarg); - break; - case 'T': /* printing Type */ - if (strcmp(ws_optarg, "text") == 0) { - output_action = WRITE_TEXT; - print_format = PR_FMT_TEXT; - } else if (strcmp(ws_optarg, "ps") == 0) { - output_action = WRITE_TEXT; - print_format = PR_FMT_PS; - } else if (strcmp(ws_optarg, "pdml") == 0) { - output_action = WRITE_XML; - print_details = TRUE; /* Need details */ - print_summary = FALSE; /* Don't allow summary */ - } else if (strcmp(ws_optarg, "psml") == 0) { - output_action = WRITE_XML; - print_details = FALSE; /* Don't allow details */ - print_summary = TRUE; /* Need summary */ - } else if (strcmp(ws_optarg, "fields") == 0) { - output_action = WRITE_FIELDS; - print_details = TRUE; /* Need full tree info */ - print_summary = FALSE; /* Don't allow summary */ - } else { - cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", ws_optarg); /* x */ - cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n" - "\t specified by the -E option.\n" - "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n" - "\t details of a decoded packet. This information is equivalent to\n" - "\t the packet details printed with the -V flag.\n" - "\t\"ps\" PostScript for a human-readable one-line summary of each of\n" - "\t the packets, or a multi-line view of the details of each of\n" - "\t the packets, depending on whether the -V flag was specified.\n" - "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n" - "\t summary information of a decoded packet. This information is\n" - "\t equivalent to the information shown in the one-line summary\n" - "\t printed by default.\n" - "\t\"text\" Text of a human-readable one-line summary of each of the\n" - "\t packets, or a multi-line view of the details of each of the\n" - "\t packets, depending on whether the -V flag was specified.\n" - "\t This is the default."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - case 'v': /* Show version and exit */ - show_version(); - goto clean_exit; - case 'O': /* Only output these protocols */ - /* already processed; just ignore it now */ - break; - case 'V': /* Verbose */ - /* already processed; just ignore it now */ - break; - case 'x': /* Print packet data in hex (and ASCII) */ - /* already processed; just ignore it now */ - break; - case 'X': - /* already processed; just ignore it now */ - break; - case 'Y': - dfilter = ws_optarg; - break; - case 'z': - /* We won't call the init function for the stat this soon - as it would disallow MATE's fields (which are registered - by the preferences set callback) from being used as - part of a tap filter. Instead, we just add the argument - to a list of stat arguments. */ - if (strcmp("help", ws_optarg) == 0) { - fprintf(stderr, "tfshark: The available statistics for the \"-z\" option are:\n"); - list_stat_cmd_args(); - goto clean_exit; - } - if (!process_stat_cmd_arg(ws_optarg)) { - cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", ws_optarg); - list_stat_cmd_args(); - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - case 'd': /* Decode as rule */ - case 'K': /* Kerberos keytab file */ - case 't': /* Time stamp type */ - case 'u': /* Seconds type */ - case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */ - case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */ - case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */ - case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */ - if (!dissect_opts_handle_opt(opt, ws_optarg)) { - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - default: - case '?': /* Bad flag - print usage message */ - print_usage(stderr); - exit_status = INVALID_OPTION; - goto clean_exit; - break; - } - } - /* If we specified output fields, but not the output field type... */ - if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) { + /* If we specified output fields, but not the output field type... */ + if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) { cmdarg_err("Output fields were specified with \"-e\", " - "but \"-Tfields\" was not specified."); + "but \"-Tfields\" was not specified."); return 1; - } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) { + } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) { cmdarg_err("\"-Tfields\" was specified, but no fields were " - "specified with \"-e\"."); + "specified with \"-e\"."); exit_status = INVALID_OPTION; goto clean_exit; - } + } - /* We require a -r flag specifying a file to read. */ - if (cf_name == NULL) { - cmdarg_err("A file to read must be specified with \"-r\"."); - exit_status = NO_FILE_SPECIFIED; - goto clean_exit; - } + /* We require a -r flag specifying a file to read. */ + if (cf_name == NULL) { + cmdarg_err("A file to read must be specified with \"-r\"."); + exit_status = NO_FILE_SPECIFIED; + goto clean_exit; + } + + /* If no display filter has been specified, and there are still command- + line arguments, treat them as the tokens of a display filter. */ + if (ws_optind < argc) { + if (dfilter != NULL) { + cmdarg_err("Display filters were specified both with \"-Y\" " + "and with additional command-line arguments."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + dfilter = get_args_as_string(argc, argv, ws_optind); + } + + /* if "-q" wasn't specified, we should print packet information */ + if (!quiet) + print_packet_info = TRUE; + + if (arg_error) { + print_usage(stderr); + exit_status = INVALID_OPTION; + goto clean_exit; + } + + if (print_hex) { + if (output_action != WRITE_TEXT) { + cmdarg_err("Raw packet hex data can only be printed as text or PostScript"); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } + + if (output_only != NULL) { + char *ps; + + if (!print_details) { + cmdarg_err("-O requires -V"); + exit_status = INVALID_OPTION; + goto clean_exit; + } + + output_only_tables = g_hash_table_new (g_str_hash, g_str_equal); + for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) { + g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps); + } + } + + if (rfilter != NULL && !perform_two_pass_analysis) { + cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + + /* Notify all registered modules that have had any of their preferences + changed either from one of the preferences file or from the command + line that their preferences have changed. */ + prefs_apply_all(); + + /* + * Enabled and disabled protocols and heuristic dissectors as per + * command-line options. + */ + if (!setup_enabled_and_disabled_protocols()) { + exit_status = INVALID_OPTION; + goto clean_exit; + } + + /* Build the column format array */ + build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE); + + if (rfilter != NULL) { + if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { + cmdarg_err("%s", err_msg); + g_free(err_msg); + exit_status = INVALID_FILTER; + goto clean_exit; + } + } + cfile.rfcode = rfcode; - /* If no display filter has been specified, and there are still command- - line arguments, treat them as the tokens of a display filter. */ - if (ws_optind < argc) { if (dfilter != NULL) { - cmdarg_err("Display filters were specified both with \"-Y\" " - "and with additional command-line arguments."); - exit_status = INVALID_OPTION; - goto clean_exit; + if (!dfilter_compile(dfilter, &dfcode, &err_msg)) { + cmdarg_err("%s", err_msg); + g_free(err_msg); + exit_status = INVALID_FILTER; + goto clean_exit; + } } - dfilter = get_args_as_string(argc, argv, ws_optind); - } + cfile.dfcode = dfcode; - /* if "-q" wasn't specified, we should print packet information */ - if (!quiet) - print_packet_info = TRUE; + if (print_packet_info) { + /* If we're printing as text or PostScript, we have + to create a print stream. */ + if (output_action == WRITE_TEXT) { + switch (print_format) { - if (arg_error) { - print_usage(stderr); - exit_status = INVALID_OPTION; - goto clean_exit; - } + case PR_FMT_TEXT: + print_stream = print_stream_text_stdio_new(stdout); + break; - if (print_hex) { - if (output_action != WRITE_TEXT) { - cmdarg_err("Raw packet hex data can only be printed as text or PostScript"); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } + case PR_FMT_PS: + print_stream = print_stream_ps_stdio_new(stdout); + break; - if (output_only != NULL) { - char *ps; - - if (!print_details) { - cmdarg_err("-O requires -V"); - exit_status = INVALID_OPTION; - goto clean_exit; + default: + ws_assert_not_reached(); + } + } } - output_only_tables = g_hash_table_new (g_str_hash, g_str_equal); - for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) { - g_hash_table_insert(output_only_tables, (gpointer)ps, (gpointer)ps); + /* We have to dissect each packet if: + + we're printing information about each packet; + + we're using a read filter on the packets; + + we're using a display filter on the packets; + + we're using any taps that need dissection. */ + do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection(); + + /* + * Read the file. + */ + + /* TODO: if tfshark is ever changed to give the user a choice of which + open_routine reader to use, then the following needs to change. */ + if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) { + exit_status = OPEN_ERROR; + goto clean_exit; } - } - if (rfilter != NULL && !perform_two_pass_analysis) { - cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y."); - exit_status = INVALID_OPTION; - goto clean_exit; - } + /* Start statistics taps; we do so after successfully opening the + capture file, so we know we have something to compute stats + on, and after registering all dissectors, so that MATE will + have registered its field array so we can have a tap filter + with one of MATE's late-registered fields as part of the + filter. */ + start_requested_stats(); - /* Notify all registered modules that have had any of their preferences - changed either from one of the preferences file or from the command - line that their preferences have changed. */ - prefs_apply_all(); - - /* - * Enabled and disabled protocols and heuristic dissectors as per - * command-line options. - */ - if (!setup_enabled_and_disabled_protocols()) { - exit_status = INVALID_OPTION; - goto clean_exit; - } - - /* Build the column format array */ - build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE); - - if (rfilter != NULL) { - if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { - cmdarg_err("%s", err_msg); - g_free(err_msg); - exit_status = INVALID_FILTER; - goto clean_exit; + /* Process the packets in the file */ + TRY { + /* XXX - for now there is only 1 packet */ + success = process_file(&cfile, 1, 0); } - } - cfile.rfcode = rfcode; - - if (dfilter != NULL) { - if (!dfilter_compile(dfilter, &dfcode, &err_msg)) { - cmdarg_err("%s", err_msg); - g_free(err_msg); - exit_status = INVALID_FILTER; - goto clean_exit; + CATCH(OutOfMemoryError) { + fprintf(stderr, + "Out Of Memory.\n" + "\n" + "Sorry, but TFShark has to terminate now.\n" + "\n" + "Some infos / workarounds can be found at:\n" + WS_WIKI_URL("KnownBugs/OutOfMemory") "\n"); + success = FALSE; } - } - cfile.dfcode = dfcode; + ENDTRY; - if (print_packet_info) { - /* If we're printing as text or PostScript, we have - to create a print stream. */ - if (output_action == WRITE_TEXT) { - switch (print_format) { - - case PR_FMT_TEXT: - print_stream = print_stream_text_stdio_new(stdout); - break; - - case PR_FMT_PS: - print_stream = print_stream_ps_stdio_new(stdout); - break; - - default: - ws_assert_not_reached(); - } + if (!success) { + /* We still dump out the results of taps, etc., as we might have + read some packets; however, we exit with an error status. */ + exit_status = 2; } - } - /* We have to dissect each packet if: + g_free(cf_name); - we're printing information about each packet; + if (cfile.provider.frames != NULL) { + free_frame_data_sequence(cfile.provider.frames); + cfile.provider.frames = NULL; + } - we're using a read filter on the packets; - - we're using a display filter on the packets; - - we're using any taps that need dissection. */ - do_dissection = print_packet_info || rfcode || dfcode || tap_listeners_require_dissection(); - - /* - * Read the file. - */ - - /* TODO: if tfshark is ever changed to give the user a choice of which - open_routine reader to use, then the following needs to change. */ - if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) { - exit_status = OPEN_ERROR; - goto clean_exit; - } - - /* Start statistics taps; we do so after successfully opening the - capture file, so we know we have something to compute stats - on, and after registering all dissectors, so that MATE will - have registered its field array so we can have a tap filter - with one of MATE's late-registered fields as part of the - filter. */ - start_requested_stats(); - - /* Process the packets in the file */ - TRY { - /* XXX - for now there is only 1 packet */ - success = process_file(&cfile, 1, 0); - } - CATCH(OutOfMemoryError) { - fprintf(stderr, - "Out Of Memory.\n" - "\n" - "Sorry, but TFShark has to terminate now.\n" - "\n" - "Some infos / workarounds can be found at:\n" - WS_WIKI_URL("KnownBugs/OutOfMemory") "\n"); - success = FALSE; - } - ENDTRY; - - if (!success) { - /* We still dump out the results of taps, etc., as we might have - read some packets; however, we exit with an error status. */ - exit_status = 2; - } - - g_free(cf_name); - - if (cfile.provider.frames != NULL) { - free_frame_data_sequence(cfile.provider.frames); - cfile.provider.frames = NULL; - } - - draw_tap_listeners(TRUE); - funnel_dump_all_text_windows(); + draw_tap_listeners(TRUE); + funnel_dump_all_text_windows(); clean_exit: - destroy_print_stream(print_stream); - epan_free(cfile.epan); - epan_cleanup(); - extcap_cleanup(); + destroy_print_stream(print_stream); + epan_free(cfile.epan); + epan_cleanup(); + extcap_cleanup(); - output_fields_free(output_fields); - output_fields = NULL; + output_fields_free(output_fields); + output_fields = NULL; - col_cleanup(&cfile.cinfo); - wtap_cleanup(); - return exit_status; + col_cleanup(&cfile.cinfo); + wtap_cleanup(); + return exit_status; } static const nstime_t * tfshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num) { - if (prov->ref && prov->ref->num == frame_num) - return &prov->ref->abs_ts; + if (prov->ref && prov->ref->num == frame_num) + return &prov->ref->abs_ts; - if (prov->prev_dis && prov->prev_dis->num == frame_num) - return &prov->prev_dis->abs_ts; + if (prov->prev_dis && prov->prev_dis->num == frame_num) + return &prov->prev_dis->abs_ts; - if (prov->prev_cap && prov->prev_cap->num == frame_num) - return &prov->prev_cap->abs_ts; + if (prov->prev_cap && prov->prev_cap->num == frame_num) + return &prov->prev_cap->abs_ts; - if (prov->frames) { - frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); + if (prov->frames) { + frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); - return (fd) ? &fd->abs_ts : NULL; - } + return (fd) ? &fd->abs_ts : NULL; + } - return NULL; + return NULL; } static const char * @@ -989,172 +991,172 @@ no_interface_name(struct packet_provider_data *prov _U_, guint32 interface_id _U static epan_t * tfshark_epan_new(capture_file *cf) { - static const struct packet_provider_funcs funcs = { - tfshark_get_frame_ts, - no_interface_name, - NULL, - NULL, - }; + static const struct packet_provider_funcs funcs = { + tfshark_get_frame_ts, + no_interface_name, + NULL, + NULL, + }; - return epan_new(&cf->provider, &funcs); + return epan_new(&cf->provider, &funcs); } static gboolean process_packet_first_pass(capture_file *cf, epan_dissect_t *edt, - gint64 offset, wtap_rec *rec, - const guchar *pd) + gint64 offset, wtap_rec *rec, + const guchar *pd) { - frame_data fdlocal; - guint32 framenum; - gboolean passed; + frame_data fdlocal; + guint32 framenum; + gboolean passed; - /* The frame number of this packet is one more than the count of - frames in this packet. */ - framenum = cf->count + 1; + /* The frame number of this packet is one more than the count of + frames in this packet. */ + framenum = cf->count + 1; - /* If we're not running a display filter and we're not printing any - packet information, we don't need to do a dissection. This means - that all packets can be marked as 'passed'. */ - passed = TRUE; + /* If we're not running a display filter and we're not printing any + packet information, we don't need to do a dissection. This means + that all packets can be marked as 'passed'. */ + passed = TRUE; - frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes); + frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes); - /* If we're going to print packet information, or we're going to - run a read filter, or display filter, or we're going to process taps, set up to - do a dissection and do so. */ - if (edt) { - /* If we're running a read filter, prime the epan_dissect_t with that - filter. */ - if (cf->rfcode) - epan_dissect_prime_with_dfilter(edt, cf->rfcode); - - /* This is the first pass, so prime the epan_dissect_t with the - hfids postdissectors want on the first pass. */ - prime_epan_dissect_with_postdissector_wanted_hfids(edt); - - frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time, - &cf->provider.ref, cf->provider.prev_dis); - if (cf->provider.ref == &fdlocal) { - ref_frame = fdlocal; - cf->provider.ref = &ref_frame; - } - - epan_dissect_file_run(edt, rec, - file_tvbuff_new(&cf->provider, &fdlocal, pd), - &fdlocal, NULL); - - /* Run the read filter if we have one. */ - if (cf->rfcode) - passed = dfilter_apply_edt(cf->rfcode, edt); - } - - if (passed) { - frame_data_set_after_dissect(&fdlocal, &cum_bytes); - cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal); - - /* If we're not doing dissection then there won't be any dependent frames. - * More importantly, edt.pi.dependent_frames won't be initialized because - * epan hasn't been initialized. - */ + /* If we're going to print packet information, or we're going to + run a read filter, or display filter, or we're going to process taps, set up to + do a dissection and do so. */ if (edt) { - g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); + /* If we're running a read filter, prime the epan_dissect_t with that + filter. */ + if (cf->rfcode) + epan_dissect_prime_with_dfilter(edt, cf->rfcode); + + /* This is the first pass, so prime the epan_dissect_t with the + hfids postdissectors want on the first pass. */ + prime_epan_dissect_with_postdissector_wanted_hfids(edt); + + frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time, + &cf->provider.ref, cf->provider.prev_dis); + if (cf->provider.ref == &fdlocal) { + ref_frame = fdlocal; + cf->provider.ref = &ref_frame; + } + + epan_dissect_file_run(edt, rec, + file_tvbuff_new(&cf->provider, &fdlocal, pd), + &fdlocal, NULL); + + /* Run the read filter if we have one. */ + if (cf->rfcode) + passed = dfilter_apply_edt(cf->rfcode, edt); } - cf->count++; - } else { - /* if we don't add it to the frame_data_sequence, clean it up right now - * to avoid leaks */ - frame_data_destroy(&fdlocal); - } + if (passed) { + frame_data_set_after_dissect(&fdlocal, &cum_bytes); + cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal); - if (edt) - epan_dissect_reset(edt); + /* If we're not doing dissection then there won't be any dependent frames. + * More importantly, edt.pi.dependent_frames won't be initialized because + * epan hasn't been initialized. + */ + if (edt) { + g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); + } - return passed; + cf->count++; + } else { + /* if we don't add it to the frame_data_sequence, clean it up right now + * to avoid leaks */ + frame_data_destroy(&fdlocal); + } + + if (edt) + epan_dissect_reset(edt); + + return passed; } static gboolean process_packet_second_pass(capture_file *cf, epan_dissect_t *edt, - frame_data *fdata, wtap_rec *rec, - Buffer *buf, guint tap_flags) + frame_data *fdata, wtap_rec *rec, + Buffer *buf, guint tap_flags) { - column_info *cinfo; - gboolean passed; + column_info *cinfo; + gboolean passed; - /* If we're not running a display filter and we're not printing any - packet information, we don't need to do a dissection. This means - that all packets can be marked as 'passed'. */ - passed = TRUE; + /* If we're not running a display filter and we're not printing any + packet information, we don't need to do a dissection. This means + that all packets can be marked as 'passed'. */ + passed = TRUE; - /* If we're going to print packet information, or we're going to - run a read filter, or we're going to process taps, set up to - do a dissection and do so. */ - if (edt) { + /* If we're going to print packet information, or we're going to + run a read filter, or we're going to process taps, set up to + do a dissection and do so. */ + if (edt) { - /* If we're running a display filter, prime the epan_dissect_t with that - filter. */ - if (cf->dfcode) - epan_dissect_prime_with_dfilter(edt, cf->dfcode); + /* If we're running a display filter, prime the epan_dissect_t with that + filter. */ + if (cf->dfcode) + epan_dissect_prime_with_dfilter(edt, cf->dfcode); - /* This is the first and only pass, so prime the epan_dissect_t - with the hfids postdissectors want on the first pass. */ - prime_epan_dissect_with_postdissector_wanted_hfids(edt); + /* This is the first and only pass, so prime the epan_dissect_t + with the hfids postdissectors want on the first pass. */ + prime_epan_dissect_with_postdissector_wanted_hfids(edt); - col_custom_prime_edt(edt, &cf->cinfo); + col_custom_prime_edt(edt, &cf->cinfo); - /* We only need the columns if either - 1) some tap needs the columns - or - 2) we're printing packet info but we're *not* verbose; in verbose - mode, we print the protocol tree, not the protocol summary. - */ - if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary)) - cinfo = &cf->cinfo; - else - cinfo = NULL; + /* We only need the columns if either + 1) some tap needs the columns + or + 2) we're printing packet info but we're *not* verbose; in verbose + mode, we print the protocol tree, not the protocol summary. + */ + if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary)) + cinfo = &cf->cinfo; + else + cinfo = NULL; - frame_data_set_before_dissect(fdata, &cf->elapsed_time, - &cf->provider.ref, cf->provider.prev_dis); - if (cf->provider.ref == fdata) { - ref_frame = *fdata; - cf->provider.ref = &ref_frame; + frame_data_set_before_dissect(fdata, &cf->elapsed_time, + &cf->provider.ref, cf->provider.prev_dis); + if (cf->provider.ref == fdata) { + ref_frame = *fdata; + cf->provider.ref = &ref_frame; + } + + epan_dissect_file_run_with_taps(edt, rec, + file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo); + + /* Run the read/display filter if we have one. */ + if (cf->dfcode) + passed = dfilter_apply_edt(cf->dfcode, edt); } - epan_dissect_file_run_with_taps(edt, rec, - file_tvbuff_new_buffer(&cf->provider, fdata, buf), fdata, cinfo); + if (passed) { + frame_data_set_after_dissect(fdata, &cum_bytes); + /* Process this packet. */ + if (print_packet_info) { + /* We're printing packet information; print the information for + this packet. */ + print_packet(cf, edt); - /* Run the read/display filter if we have one. */ - if (cf->dfcode) - passed = dfilter_apply_edt(cf->dfcode, edt); - } + /* If we're doing "line-buffering", flush the standard output + after every packet. See the comment above, for the "-l" + option, for an explanation of why we do that. */ + if (line_buffered) + fflush(stdout); - if (passed) { - frame_data_set_after_dissect(fdata, &cum_bytes); - /* Process this packet. */ - if (print_packet_info) { - /* We're printing packet information; print the information for - this packet. */ - print_packet(cf, edt); - - /* If we're doing "line-buffering", flush the standard output - after every packet. See the comment above, for the "-l" - option, for an explanation of why we do that. */ - if (line_buffered) - fflush(stdout); - - if (ferror(stdout)) { - show_print_file_io_error(errno); - return FALSE; - } + if (ferror(stdout)) { + show_print_file_io_error(errno); + return FALSE; + } + } + cf->provider.prev_dis = fdata; } - cf->provider.prev_dis = fdata; - } - cf->provider.prev_cap = fdata; + cf->provider.prev_cap = fdata; - if (edt) { - epan_dissect_reset(edt); - } - return passed || fdata->dependent_of_displayed; + if (edt) { + epan_dissect_reset(edt); + } + return passed || fdata->dependent_of_displayed; } static gboolean @@ -1229,966 +1231,966 @@ local_wtap_read(capture_file *cf, wtap_rec *file_rec _U_, int *err, gchar **err_ static gboolean process_file(capture_file *cf, int max_packet_count, gint64 max_byte_count) { - guint32 framenum; - int err; - gchar *err_info = NULL; - gint64 data_offset = 0; - gboolean filtering_tap_listeners; - guint tap_flags; - Buffer buf; - epan_dissect_t *edt = NULL; - wtap_rec file_rec; - guint8* raw_data; + guint32 framenum; + int err; + gchar *err_info = NULL; + gint64 data_offset = 0; + gboolean filtering_tap_listeners; + guint tap_flags; + Buffer buf; + epan_dissect_t *edt = NULL; + wtap_rec file_rec; + guint8* raw_data; - if (print_packet_info) { - if (!write_preamble(cf)) { - err = errno; - show_print_file_io_error(err); - goto out; - } - } - - /* Do we have any tap listeners with filters? */ - filtering_tap_listeners = have_filtering_tap_listeners(); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - wtap_rec_init(&file_rec); - - /* XXX - TEMPORARY HACK TO ELF DISSECTOR */ - file_rec.rec_header.packet_header.pkt_encap = 1234; - - if (perform_two_pass_analysis) { - frame_data *fdata; - - /* Allocate a frame_data_sequence for all the frames. */ - cf->provider.frames = new_frame_data_sequence(); - - if (do_dissection) { - gboolean create_proto_tree; - - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a read filter; - * - * a postdissector wants field values or protocols - * on the first pass. - */ - create_proto_tree = - (cf->rfcode != NULL || postdissectors_want_hfids()); - - /* We're not going to display the protocol tree on this pass, - so it's not going to be "visible". */ - edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE); - } - while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) { - if (process_packet_first_pass(cf, edt, data_offset, &file_rec, raw_data)) { - - /* Stop reading if we have the maximum number of packets; - * When the -c option has not been used, max_packet_count - * starts at 0, which practically means, never stop reading. - * (unless we roll over max_packet_count ?) - */ - if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) { - err = 0; /* This is not an error */ - break; + if (print_packet_info) { + if (!write_preamble(cf)) { + err = errno; + show_print_file_io_error(err); + goto out; } - } } - if (edt) { - epan_dissect_free(edt); - edt = NULL; - } + /* Do we have any tap listeners with filters? */ + filtering_tap_listeners = have_filtering_tap_listeners(); + + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); + + wtap_rec_init(&file_rec); + + /* XXX - TEMPORARY HACK TO ELF DISSECTOR */ + file_rec.rec_header.packet_header.pkt_encap = 1234; + + if (perform_two_pass_analysis) { + frame_data *fdata; + + /* Allocate a frame_data_sequence for all the frames. */ + cf->provider.frames = new_frame_data_sequence(); + + if (do_dissection) { + gboolean create_proto_tree; + + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a read filter; + * + * a postdissector wants field values or protocols + * on the first pass. + */ + create_proto_tree = + (cf->rfcode != NULL || postdissectors_want_hfids()); + + /* We're not going to display the protocol tree on this pass, + so it's not going to be "visible". */ + edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE); + } + while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) { + if (process_packet_first_pass(cf, edt, data_offset, &file_rec, raw_data)) { + + /* Stop reading if we have the maximum number of packets; + * When the -c option has not been used, max_packet_count + * starts at 0, which practically means, never stop reading. + * (unless we roll over max_packet_count ?) + */ + if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) { + err = 0; /* This is not an error */ + break; + } + } + } + + if (edt) { + epan_dissect_free(edt); + edt = NULL; + } #if 0 - /* Close the sequential I/O side, to free up memory it requires. */ - wtap_sequential_close(cf->provider.wth); + /* Close the sequential I/O side, to free up memory it requires. */ + wtap_sequential_close(cf->provider.wth); #endif - /* Allow the protocol dissectors to free up memory that they - * don't need after the sequential run-through of the packets. */ - postseq_cleanup_all_protocols(); + /* Allow the protocol dissectors to free up memory that they + * don't need after the sequential run-through of the packets. */ + postseq_cleanup_all_protocols(); - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; - ws_buffer_init(&buf, 1514); + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; + ws_buffer_init(&buf, 1514); - if (do_dissection) { - gboolean create_proto_tree; + if (do_dissection) { + gboolean create_proto_tree; - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * we're going to print the protocol tree; - * - * one of the tap listeners requires a protocol tree; - * - * we have custom columns (which require field values, which - * currently requires that we build a protocol tree). - */ - create_proto_tree = - (cf->dfcode || print_details || filtering_tap_listeners || - (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo)); + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * we're going to print the protocol tree; + * + * one of the tap listeners requires a protocol tree; + * + * we have custom columns (which require field values, which + * currently requires that we build a protocol tree). + */ + create_proto_tree = + (cf->dfcode || print_details || filtering_tap_listeners || + (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo)); - /* 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 - ("packet_details" is true). */ - edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); - } + /* 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 + ("packet_details" is true). */ + edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); + } - for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) { - fdata = frame_data_sequence_find(cf->provider.frames, framenum); + for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) { + fdata = frame_data_sequence_find(cf->provider.frames, framenum); #if 0 - if (wtap_seek_read(cf->provider.wth, fdata->file_off, - &buf, fdata->cap_len, &err, &err_info)) { - process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags); - } + if (wtap_seek_read(cf->provider.wth, fdata->file_off, + &buf, fdata->cap_len, &err, &err_info)) { + process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, tap_flags); + } #else - if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, - tap_flags)) - return FALSE; + if (!process_packet_second_pass(cf, edt, fdata, &cf->rec, &buf, + tap_flags)) + return FALSE; #endif - } - - if (edt) { - epan_dissect_free(edt); - edt = NULL; - } - - ws_buffer_free(&buf); - } - else { - framenum = 0; - - if (do_dissection) { - gboolean create_proto_tree; - - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a read filter; - * - * we're going to apply a display filter; - * - * we're going to print the protocol tree; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * a postdissector wants field values or protocols - * on the first pass; - * - * we have custom columns (which require field values, which - * currently requires that we build a protocol tree). - */ - create_proto_tree = - (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners || - (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() || - have_custom_cols(&cf->cinfo)); - - /* 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 - ("packet_details" is true). */ - edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); - } - - while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) { - - framenum++; - - if (!process_packet_single_pass(cf, edt, data_offset, - &file_rec/*wtap_get_rec(cf->provider.wth)*/, - raw_data, tap_flags)) - return FALSE; - - /* Stop reading if we have the maximum number of packets; - * When the -c option has not been used, max_packet_count - * starts at 0, which practically means, never stop reading. - * (unless we roll over max_packet_count ?) - */ - if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) { - err = 0; /* This is not an error */ - break; - } - } - - if (edt) { - epan_dissect_free(edt); - edt = NULL; - } - } - - wtap_rec_cleanup(&file_rec); - - if (err != 0) { - /* - * Print a message noting that the read failed somewhere along the line. - * - * If we're printing packet data, and the standard output and error are - * going to the same place, flush the standard output, so everything - * buffered up is written, and then print a newline to the standard error - * before printing the error message, to separate it from the packet - * data. (Alas, that only works on UN*X; st_dev is meaningless, and - * the _fstat() documentation at Microsoft doesn't indicate whether - * st_ino is even supported.) - */ -#ifndef _WIN32 - if (print_packet_info) { - ws_statb64 stat_stdout, stat_stderr; - - if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) { - if (stat_stdout.st_dev == stat_stderr.st_dev && - stat_stdout.st_ino == stat_stderr.st_ino) { - fflush(stdout); - fprintf(stderr, "\n"); } - } + + if (edt) { + epan_dissect_free(edt); + edt = NULL; + } + + ws_buffer_free(&buf); } + else { + framenum = 0; + + if (do_dissection) { + gboolean create_proto_tree; + + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a read filter; + * + * we're going to apply a display filter; + * + * we're going to print the protocol tree; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * a postdissector wants field values or protocols + * on the first pass; + * + * we have custom columns (which require field values, which + * currently requires that we build a protocol tree). + */ + create_proto_tree = + (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners || + (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() || + have_custom_cols(&cf->cinfo)); + + /* 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 + ("packet_details" is true). */ + edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); + } + + while (local_wtap_read(cf, &file_rec, &err, &err_info, &data_offset, &raw_data)) { + + framenum++; + + if (!process_packet_single_pass(cf, edt, data_offset, + &file_rec/*wtap_get_rec(cf->provider.wth)*/, + raw_data, tap_flags)) + return FALSE; + + /* Stop reading if we have the maximum number of packets; + * When the -c option has not been used, max_packet_count + * starts at 0, which practically means, never stop reading. + * (unless we roll over max_packet_count ?) + */ + if ( (--max_packet_count == 0) || (max_byte_count != 0 && data_offset >= max_byte_count)) { + err = 0; /* This is not an error */ + break; + } + } + + if (edt) { + epan_dissect_free(edt); + edt = NULL; + } + } + + wtap_rec_cleanup(&file_rec); + + if (err != 0) { + /* + * Print a message noting that the read failed somewhere along the line. + * + * If we're printing packet data, and the standard output and error are + * going to the same place, flush the standard output, so everything + * buffered up is written, and then print a newline to the standard error + * before printing the error message, to separate it from the packet + * data. (Alas, that only works on UN*X; st_dev is meaningless, and + * the _fstat() documentation at Microsoft doesn't indicate whether + * st_ino is even supported.) + */ +#ifndef _WIN32 + if (print_packet_info) { + ws_statb64 stat_stdout, stat_stderr; + + if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) { + if (stat_stdout.st_dev == stat_stderr.st_dev && + stat_stdout.st_ino == stat_stderr.st_ino) { + fflush(stdout); + fprintf(stderr, "\n"); + } + } + } #endif #if 0 - switch (err) { + switch (err) { - case FTAP_ERR_UNSUPPORTED: - cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)", - cf->filename, err_info); - g_free(err_info); - break; + case FTAP_ERR_UNSUPPORTED: + cmdarg_err("The file \"%s\" contains record data that TFShark doesn't support.\n(%s)", + cf->filename, err_info); + g_free(err_info); + break; - case FTAP_ERR_UNSUPPORTED_ENCAP: - cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)", - cf->filename, err_info); - g_free(err_info); - break; + case FTAP_ERR_UNSUPPORTED_ENCAP: + cmdarg_err("The file \"%s\" has a packet with a network type that TFShark doesn't support.\n(%s)", + cf->filename, err_info); + g_free(err_info); + break; - case FTAP_ERR_CANT_READ: - cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.", - cf->filename); - break; + case FTAP_ERR_CANT_READ: + cmdarg_err("An attempt to read from the file \"%s\" failed for some unknown reason.", + cf->filename); + break; - case FTAP_ERR_SHORT_READ: - cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.", - cf->filename); - break; + case FTAP_ERR_SHORT_READ: + cmdarg_err("The file \"%s\" appears to have been cut short in the middle of a packet.", + cf->filename); + break; - case FTAP_ERR_BAD_FILE: - cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)", - cf->filename, err_info); - g_free(err_info); - break; + case FTAP_ERR_BAD_FILE: + cmdarg_err("The file \"%s\" appears to be damaged or corrupt.\n(%s)", + cf->filename, err_info); + g_free(err_info); + break; - case FTAP_ERR_DECOMPRESS: - cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n" - "(%s)", cf->filename, err_info); - break; + case FTAP_ERR_DECOMPRESS: + cmdarg_err("The compressed file \"%s\" appears to be damaged or corrupt.\n" + "(%s)", cf->filename, err_info); + break; - default: - cmdarg_err("An error occurred while reading the file \"%s\": %s.", - cf->filename, ftap_strerror(err)); - break; - } + default: + cmdarg_err("An error occurred while reading the file \"%s\": %s.", + cf->filename, ftap_strerror(err)); + break; + } #endif - } else { - if (print_packet_info) { - if (!write_finale()) { - err = errno; - show_print_file_io_error(err); - } + } else { + if (print_packet_info) { + if (!write_finale()) { + err = errno; + show_print_file_io_error(err); + } + } } - } out: - wtap_close(cf->provider.wth); - cf->provider.wth = NULL; + wtap_close(cf->provider.wth); + cf->provider.wth = NULL; - return (err != 0); + return (err != 0); } static gboolean process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset, - wtap_rec *rec, const guchar *pd, - guint tap_flags) + wtap_rec *rec, const guchar *pd, + guint tap_flags) { - frame_data fdata; - column_info *cinfo; - gboolean passed; + frame_data fdata; + column_info *cinfo; + gboolean passed; - /* Count this packet. */ - cf->count++; + /* Count this packet. */ + cf->count++; - /* If we're not running a display filter and we're not printing any - packet information, we don't need to do a dissection. This means - that all packets can be marked as 'passed'. */ - passed = TRUE; + /* If we're not running a display filter and we're not printing any + packet information, we don't need to do a dissection. This means + that all packets can be marked as 'passed'. */ + passed = TRUE; - frame_data_init(&fdata, cf->count, rec, offset, cum_bytes); + frame_data_init(&fdata, cf->count, rec, offset, cum_bytes); - /* If we're going to print packet information, or we're going to - run a read filter, or we're going to process taps, set up to - do a dissection and do so. */ - if (edt) { - /* If we're running a filter, prime the epan_dissect_t with that - filter. */ - if (cf->dfcode) - epan_dissect_prime_with_dfilter(edt, cf->dfcode); + /* If we're going to print packet information, or we're going to + run a read filter, or we're going to process taps, set up to + do a dissection and do so. */ + if (edt) { + /* If we're running a filter, prime the epan_dissect_t with that + filter. */ + if (cf->dfcode) + epan_dissect_prime_with_dfilter(edt, cf->dfcode); - col_custom_prime_edt(edt, &cf->cinfo); + col_custom_prime_edt(edt, &cf->cinfo); - /* We only need the columns if either - 1) some tap needs the columns - or - 2) we're printing packet info but we're *not* verbose; in verbose - mode, we print the protocol tree, not the protocol summary. - or - 3) there is a column mapped as an individual field */ - if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields)) - cinfo = &cf->cinfo; - else - cinfo = NULL; + /* We only need the columns if either + 1) some tap needs the columns + or + 2) we're printing packet info but we're *not* verbose; in verbose + mode, we print the protocol tree, not the protocol summary. + or + 3) there is a column mapped as an individual field */ + if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields)) + cinfo = &cf->cinfo; + else + cinfo = NULL; - frame_data_set_before_dissect(&fdata, &cf->elapsed_time, - &cf->provider.ref, cf->provider.prev_dis); - if (cf->provider.ref == &fdata) { - ref_frame = fdata; - cf->provider.ref = &ref_frame; + frame_data_set_before_dissect(&fdata, &cf->elapsed_time, + &cf->provider.ref, cf->provider.prev_dis); + if (cf->provider.ref == &fdata) { + ref_frame = fdata; + cf->provider.ref = &ref_frame; + } + + epan_dissect_file_run_with_taps(edt, rec, + frame_tvbuff_new(&cf->provider, &fdata, pd), + &fdata, cinfo); + + /* Run the filter if we have it. */ + if (cf->dfcode) + passed = dfilter_apply_edt(cf->dfcode, edt); } - epan_dissect_file_run_with_taps(edt, rec, - frame_tvbuff_new(&cf->provider, &fdata, pd), - &fdata, cinfo); + if (passed) { + frame_data_set_after_dissect(&fdata, &cum_bytes); - /* Run the filter if we have it. */ - if (cf->dfcode) - passed = dfilter_apply_edt(cf->dfcode, edt); - } + /* Process this packet. */ + if (print_packet_info) { + /* We're printing packet information; print the information for + this packet. */ + print_packet(cf, edt); - if (passed) { - frame_data_set_after_dissect(&fdata, &cum_bytes); + /* If we're doing "line-buffering", flush the standard output + after every packet. See the comment above, for the "-l" + option, for an explanation of why we do that. */ + if (line_buffered) + fflush(stdout); - /* Process this packet. */ - if (print_packet_info) { - /* We're printing packet information; print the information for - this packet. */ - print_packet(cf, edt); + if (ferror(stdout)) { + show_print_file_io_error(errno); + return FALSE; + } + } - /* If we're doing "line-buffering", flush the standard output - after every packet. See the comment above, for the "-l" - option, for an explanation of why we do that. */ - if (line_buffered) - fflush(stdout); - - if (ferror(stdout)) { - show_print_file_io_error(errno); - return FALSE; - } + /* this must be set after print_packet() [bug #8160] */ + prev_dis_frame = fdata; + cf->provider.prev_dis = &prev_dis_frame; } - /* this must be set after print_packet() [bug #8160] */ - prev_dis_frame = fdata; - cf->provider.prev_dis = &prev_dis_frame; - } + prev_cap_frame = fdata; + cf->provider.prev_cap = &prev_cap_frame; - prev_cap_frame = fdata; - cf->provider.prev_cap = &prev_cap_frame; - - if (edt) { - epan_dissect_reset(edt); - frame_data_destroy(&fdata); - } - return passed; + if (edt) { + epan_dissect_reset(edt); + frame_data_destroy(&fdata); + } + return passed; } static gboolean write_preamble(capture_file *cf) { - switch (output_action) { + switch (output_action) { - case WRITE_TEXT: - return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info()); + case WRITE_TEXT: + return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info()); - case WRITE_XML: - if (print_details) - write_pdml_preamble(stdout, cf->filename); - else - write_psml_preamble(&cf->cinfo, stdout); - return !ferror(stdout); + case WRITE_XML: + if (print_details) + write_pdml_preamble(stdout, cf->filename); + else + write_psml_preamble(&cf->cinfo, stdout); + return !ferror(stdout); - case WRITE_FIELDS: - write_fields_preamble(output_fields, stdout); - return !ferror(stdout); + case WRITE_FIELDS: + write_fields_preamble(output_fields, stdout); + return !ferror(stdout); - default: - ws_assert_not_reached(); - return FALSE; - } + default: + ws_assert_not_reached(); + return FALSE; + } } static char * get_line_buf(size_t len) { - static char *line_bufp = NULL; - static size_t line_buf_len = 256; - size_t new_line_buf_len; + static char *line_bufp = NULL; + static size_t line_buf_len = 256; + size_t new_line_buf_len; - for (new_line_buf_len = line_buf_len; len > new_line_buf_len; - new_line_buf_len *= 2) - ; - if (line_bufp == NULL) { - line_buf_len = new_line_buf_len; - line_bufp = (char *)g_malloc(line_buf_len + 1); - } else { - if (new_line_buf_len > line_buf_len) { - line_buf_len = new_line_buf_len; - line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1); + for (new_line_buf_len = line_buf_len; len > new_line_buf_len; + new_line_buf_len *= 2) + ; + if (line_bufp == NULL) { + line_buf_len = new_line_buf_len; + line_bufp = (char *)g_malloc(line_buf_len + 1); + } else { + if (new_line_buf_len > line_buf_len) { + line_buf_len = new_line_buf_len; + line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1); + } } - } - return line_bufp; + return line_bufp; } static inline void put_string(char *dest, const char *str, size_t str_len) { - memcpy(dest, str, str_len); - dest[str_len] = '\0'; + memcpy(dest, str, str_len); + dest[str_len] = '\0'; } static inline void put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces) { - size_t i; + size_t i; - for (i = str_len; i < str_with_spaces; i++) - *dest++ = ' '; + for (i = str_len; i < str_with_spaces; i++) + *dest++ = ' '; - put_string(dest, str, str_len); + put_string(dest, str, str_len); } static inline void put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces) { - size_t i; + size_t i; - memcpy(dest, str, str_len); - for (i = str_len; i < str_with_spaces; i++) - dest[i] = ' '; + memcpy(dest, str, str_len); + for (i = str_len; i < str_with_spaces; i++) + dest[i] = ' '; - dest[str_with_spaces] = '\0'; + dest[str_with_spaces] = '\0'; } static gboolean print_columns(capture_file *cf) { - char *line_bufp; - int i; - size_t buf_offset; - size_t column_len; - size_t col_len; - col_item_t* col_item; + char *line_bufp; + int i; + size_t buf_offset; + size_t column_len; + size_t col_len; + col_item_t* col_item; - line_bufp = get_line_buf(256); - buf_offset = 0; - *line_bufp = '\0'; - for (i = 0; i < cf->cinfo.num_cols; i++) { - col_item = &cf->cinfo.columns[i]; - /* Skip columns not marked as visible. */ - if (!get_column_visible(i)) - continue; - switch (col_item->col_fmt) { - case COL_NUMBER: - column_len = col_len = strlen(col_item->col_data); - if (column_len < 3) - column_len = 3; - line_bufp = get_line_buf(buf_offset + column_len); - put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); - break; + line_bufp = get_line_buf(256); + buf_offset = 0; + *line_bufp = '\0'; + for (i = 0; i < cf->cinfo.num_cols; i++) { + col_item = &cf->cinfo.columns[i]; + /* Skip columns not marked as visible. */ + if (!get_column_visible(i)) + continue; + switch (col_item->col_fmt) { + case COL_NUMBER: + column_len = col_len = strlen(col_item->col_data); + if (column_len < 3) + column_len = 3; + line_bufp = get_line_buf(buf_offset + column_len); + put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); + break; - case COL_CLS_TIME: - case COL_REL_TIME: - case COL_ABS_TIME: - case COL_ABS_YMD_TIME: /* XXX - wider */ - case COL_ABS_YDOY_TIME: /* XXX - wider */ - case COL_UTC_TIME: - case COL_UTC_YMD_TIME: /* XXX - wider */ - case COL_UTC_YDOY_TIME: /* XXX - wider */ - column_len = col_len = strlen(col_item->col_data); - if (column_len < 10) - column_len = 10; - line_bufp = get_line_buf(buf_offset + column_len); - put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); - break; + case COL_CLS_TIME: + case COL_REL_TIME: + case COL_ABS_TIME: + case COL_ABS_YMD_TIME: /* XXX - wider */ + case COL_ABS_YDOY_TIME: /* XXX - wider */ + case COL_UTC_TIME: + case COL_UTC_YMD_TIME: /* XXX - wider */ + case COL_UTC_YDOY_TIME: /* XXX - wider */ + column_len = col_len = strlen(col_item->col_data); + if (column_len < 10) + column_len = 10; + line_bufp = get_line_buf(buf_offset + column_len); + put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); + 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: - column_len = col_len = strlen(col_item->col_data); - if (column_len < 12) - column_len = 12; - line_bufp = get_line_buf(buf_offset + column_len); - put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); - 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: + column_len = col_len = strlen(col_item->col_data); + if (column_len < 12) + column_len = 12; + line_bufp = get_line_buf(buf_offset + column_len); + put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); + 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: - column_len = col_len = strlen(col_item->col_data); - if (column_len < 12) - column_len = 12; - line_bufp = get_line_buf(buf_offset + column_len); - put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len); - 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: + column_len = col_len = strlen(col_item->col_data); + if (column_len < 12) + column_len = 12; + line_bufp = get_line_buf(buf_offset + column_len); + put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len); + break; - default: - column_len = strlen(col_item->col_data); - line_bufp = get_line_buf(buf_offset + column_len); - put_string(line_bufp + buf_offset, col_item->col_data, column_len); - break; + default: + column_len = strlen(col_item->col_data); + line_bufp = get_line_buf(buf_offset + column_len); + put_string(line_bufp + buf_offset, col_item->col_data, column_len); + break; + } + buf_offset += column_len; + 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. + * + * We add enough space to the buffer for " <- " or " -> ", + * even if we're only adding " ". + */ + line_bufp = get_line_buf(buf_offset + 4); + switch (col_item->col_fmt) { + + case COL_DEF_SRC: + case COL_RES_SRC: + case COL_UNRES_SRC: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_DST: + case COL_RES_DST: + case COL_UNRES_DST: + put_string(line_bufp + buf_offset, " -> ", 4); + buf_offset += 4; + break; + + default: + put_string(line_bufp + buf_offset, " ", 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_DL_SRC: + case COL_RES_DL_SRC: + case COL_UNRES_DL_SRC: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_DL_DST: + case COL_RES_DL_DST: + case COL_UNRES_DL_DST: + put_string(line_bufp + buf_offset, " -> ", 4); + buf_offset += 4; + break; + + default: + put_string(line_bufp + buf_offset, " ", 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_NET_SRC: + case COL_RES_NET_SRC: + case COL_UNRES_NET_SRC: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_NET_DST: + case COL_RES_NET_DST: + case COL_UNRES_NET_DST: + put_string(line_bufp + buf_offset, " -> ", 4); + buf_offset += 4; + break; + + default: + put_string(line_bufp + buf_offset, " ", 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_DST: + case COL_RES_DST: + case COL_UNRES_DST: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_SRC: + case COL_RES_SRC: + case COL_UNRES_SRC: + put_string(line_bufp + buf_offset, " <- ", 4); + buf_offset += 4; + break; + + default: + put_string(line_bufp + buf_offset, " ", 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_DL_DST: + case COL_RES_DL_DST: + case COL_UNRES_DL_DST: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_DL_SRC: + case COL_RES_DL_SRC: + case COL_UNRES_DL_SRC: + put_string(line_bufp + buf_offset, " <- ", 4); + buf_offset += 4; + break; + + default: + put_string(line_bufp + buf_offset, " ", 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_NET_DST: + case COL_RES_NET_DST: + case COL_UNRES_NET_DST: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_NET_SRC: + case COL_RES_NET_SRC: + case COL_UNRES_NET_SRC: + put_string(line_bufp + buf_offset, " <- ", 4); + buf_offset += 4; + break; + + default: + put_string(line_bufp + buf_offset, " ", 1); + buf_offset += 1; + break; + } + break; + + default: + put_string(line_bufp + buf_offset, " ", 1); + buf_offset += 1; + break; + } + } } - buf_offset += column_len; - 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. - * - * We add enough space to the buffer for " <- " or " -> ", - * even if we're only adding " ". - */ - line_bufp = get_line_buf(buf_offset + 4); - switch (col_item->col_fmt) { - - case COL_DEF_SRC: - case COL_RES_SRC: - case COL_UNRES_SRC: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_DST: - case COL_RES_DST: - case COL_UNRES_DST: - put_string(line_bufp + buf_offset, " -> ", 4); - buf_offset += 4; - break; - - default: - put_string(line_bufp + buf_offset, " ", 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_DL_SRC: - case COL_RES_DL_SRC: - case COL_UNRES_DL_SRC: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_DL_DST: - case COL_RES_DL_DST: - case COL_UNRES_DL_DST: - put_string(line_bufp + buf_offset, " -> ", 4); - buf_offset += 4; - break; - - default: - put_string(line_bufp + buf_offset, " ", 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_NET_SRC: - case COL_RES_NET_SRC: - case COL_UNRES_NET_SRC: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_NET_DST: - case COL_RES_NET_DST: - case COL_UNRES_NET_DST: - put_string(line_bufp + buf_offset, " -> ", 4); - buf_offset += 4; - break; - - default: - put_string(line_bufp + buf_offset, " ", 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_DST: - case COL_RES_DST: - case COL_UNRES_DST: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_SRC: - case COL_RES_SRC: - case COL_UNRES_SRC: - put_string(line_bufp + buf_offset, " <- ", 4); - buf_offset += 4; - break; - - default: - put_string(line_bufp + buf_offset, " ", 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_DL_DST: - case COL_RES_DL_DST: - case COL_UNRES_DL_DST: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_DL_SRC: - case COL_RES_DL_SRC: - case COL_UNRES_DL_SRC: - put_string(line_bufp + buf_offset, " <- ", 4); - buf_offset += 4; - break; - - default: - put_string(line_bufp + buf_offset, " ", 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_NET_DST: - case COL_RES_NET_DST: - case COL_UNRES_NET_DST: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_NET_SRC: - case COL_RES_NET_SRC: - case COL_UNRES_NET_SRC: - put_string(line_bufp + buf_offset, " <- ", 4); - buf_offset += 4; - break; - - default: - put_string(line_bufp + buf_offset, " ", 1); - buf_offset += 1; - break; - } - break; - - default: - put_string(line_bufp + buf_offset, " ", 1); - buf_offset += 1; - break; - } - } - } - return print_line(print_stream, 0, line_bufp); + return print_line(print_stream, 0, line_bufp); } static gboolean print_packet(capture_file *cf, epan_dissect_t *edt) { - if (print_summary || output_fields_has_cols(output_fields)) { - /* Just fill in the columns. */ - epan_dissect_fill_in_columns(edt, FALSE, TRUE); + if (print_summary || output_fields_has_cols(output_fields)) { + /* Just fill in the columns. */ + epan_dissect_fill_in_columns(edt, FALSE, TRUE); - if (print_summary) { - /* Now print them. */ - switch (output_action) { + if (print_summary) { + /* Now print them. */ + switch (output_action) { - case WRITE_TEXT: - if (!print_columns(cf)) - return FALSE; - break; + case WRITE_TEXT: + if (!print_columns(cf)) + return FALSE; + break; - case WRITE_XML: - write_psml_columns(edt, stdout, FALSE); - return !ferror(stdout); - case WRITE_FIELDS: /*No non-verbose "fields" format */ - ws_assert_not_reached(); - break; - } + case WRITE_XML: + write_psml_columns(edt, stdout, FALSE); + return !ferror(stdout); + case WRITE_FIELDS: /*No non-verbose "fields" format */ + ws_assert_not_reached(); + break; + } + } } - } - if (print_details) { - /* Print the information in the protocol tree. */ - switch (output_action) { + if (print_details) { + /* Print the information in the protocol tree. */ + switch (output_action) { - case WRITE_TEXT: - if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none, + case WRITE_TEXT: + if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none, print_hex, edt, output_only_tables, print_stream)) - return FALSE; - if (!print_hex) { - if (!print_line(print_stream, 0, separator)) - return FALSE; - } - break; + return FALSE; + if (!print_hex) { + if (!print_line(print_stream, 0, separator)) + return FALSE; + } + break; - case WRITE_XML: - write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, &cf->cinfo, stdout, FALSE); - printf("\n"); - return !ferror(stdout); - case WRITE_FIELDS: - write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout); - printf("\n"); - return !ferror(stdout); + case WRITE_XML: + write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, &cf->cinfo, stdout, FALSE); + printf("\n"); + return !ferror(stdout); + case WRITE_FIELDS: + write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout); + printf("\n"); + return !ferror(stdout); + } } - } - if (print_hex) { - if (print_summary || print_details) { - if (!print_line(print_stream, 0, "")) - return FALSE; + if (print_hex) { + if (print_summary || print_details) { + if (!print_line(print_stream, 0, "")) + return FALSE; + } + if (!print_hex_data(print_stream, edt, HEXDUMP_SOURCE_MULTI | HEXDUMP_ASCII_INCLUDE)) + return FALSE; + if (!print_line(print_stream, 0, separator)) + return FALSE; } - if (!print_hex_data(print_stream, edt, HEXDUMP_SOURCE_MULTI | HEXDUMP_ASCII_INCLUDE)) - return FALSE; - if (!print_line(print_stream, 0, separator)) - return FALSE; - } - return TRUE; + return TRUE; } static gboolean write_finale(void) { - switch (output_action) { + switch (output_action) { - case WRITE_TEXT: - return print_finale(print_stream); + case WRITE_TEXT: + return print_finale(print_stream); - case WRITE_XML: - if (print_details) - write_pdml_finale(stdout); - else - write_psml_finale(stdout); - return !ferror(stdout); + case WRITE_XML: + if (print_details) + write_pdml_finale(stdout); + else + write_psml_finale(stdout); + return !ferror(stdout); - case WRITE_FIELDS: - write_fields_finale(output_fields, stdout); - return !ferror(stdout); + case WRITE_FIELDS: + write_fields_finale(output_fields, stdout); + return !ferror(stdout); - default: - ws_assert_not_reached(); - return FALSE; - } + default: + ws_assert_not_reached(); + return FALSE; + } } cf_status_t cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err) { - gchar *err_info; - char err_msg[2048+1]; + gchar *err_info; + char err_msg[2048+1]; - /* The open isn't implemented yet. Fill in the information for this file. */ + /* The open isn't implemented yet. Fill in the information for this file. */ - /* Create new epan session for dissection. */ - epan_free(cf->epan); - cf->epan = tfshark_epan_new(cf); + /* Create new epan session for dissection. */ + epan_free(cf->epan); + cf->epan = tfshark_epan_new(cf); - cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */ - cf->f_datalen = 0; /* not used, but set it anyway */ + cf->provider.wth = NULL; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */ + cf->f_datalen = 0; /* not used, but set it anyway */ - /* Set the file name because we need it to set the follow stream filter. - XXX - is that still true? We need it for other reasons, though, - in any case. */ - cf->filename = g_strdup(fname); + /* Set the file name because we need it to set the follow stream filter. + XXX - is that still true? We need it for other reasons, though, + in any case. */ + cf->filename = g_strdup(fname); - /* Indicate whether it's a permanent or temporary file. */ - cf->is_tempfile = is_tempfile; + /* Indicate whether it's a permanent or temporary file. */ + cf->is_tempfile = is_tempfile; - /* No user changes yet. */ - cf->unsaved_changes = FALSE; + /* No user changes yet. */ + cf->unsaved_changes = FALSE; - cf->cd_t = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */ - cf->open_type = type; - cf->count = 0; - cf->drops_known = FALSE; - cf->drops = 0; - cf->snap = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */ - nstime_set_zero(&cf->elapsed_time); - cf->provider.ref = NULL; - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; + cf->cd_t = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */ + cf->open_type = type; + cf->count = 0; + cf->drops_known = FALSE; + cf->drops = 0; + cf->snap = 0; /**** XXX - DOESN'T WORK RIGHT NOW!!!! */ + nstime_set_zero(&cf->elapsed_time); + cf->provider.ref = NULL; + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; - cf->state = FILE_READ_IN_PROGRESS; + cf->state = FILE_READ_IN_PROGRESS; - return CF_OK; + return CF_OK; /* fail: */ - snprintf(err_msg, sizeof err_msg, - cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname); - cmdarg_err("%s", err_msg); - return CF_ERROR; + snprintf(err_msg, sizeof err_msg, + cf_open_error_message(*err, err_info, FALSE, cf->cd_t), fname); + cmdarg_err("%s", err_msg); + return CF_ERROR; } static void show_print_file_io_error(int err) { - switch (err) { + switch (err) { - case ENOSPC: - cmdarg_err("Not all the packets could be printed because there is " -"no space left on the file system."); - break; + case ENOSPC: + cmdarg_err("Not all the packets could be printed because there is " + "no space left on the file system."); + break; #ifdef EDQUOT - case EDQUOT: - cmdarg_err("Not all the packets could be printed because you are " -"too close to, or over your disk quota."); - break; + case EDQUOT: + cmdarg_err("Not all the packets could be printed because you are " + "too close to, or over your disk quota."); + break; #endif - default: - cmdarg_err("An error occurred while printing packets: %s.", - g_strerror(err)); - break; - } + default: + cmdarg_err("An error occurred while printing packets: %s.", + g_strerror(err)); + break; + } } static const char * cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing, - int file_type _U_) + int file_type _U_) { - const char *errmsg; - /* static char errmsg_errno[1024+1]; */ + const char *errmsg; + /* static char errmsg_errno[1024+1]; */ #if 0 - if (err < 0) { - /* Wiretap error. */ - switch (err) { + if (err < 0) { + /* Wiretap error. */ + switch (err) { - case FTAP_ERR_NOT_REGULAR_FILE: - errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file."; - break; + case FTAP_ERR_NOT_REGULAR_FILE: + errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file."; + break; - case FTAP_ERR_RANDOM_OPEN_PIPE: - /* Seen only when opening a capture file for reading. */ - errmsg = "The file \"%s\" is a pipe or FIFO; TFShark can't read pipe or FIFO files in two-pass mode."; - break; + case FTAP_ERR_RANDOM_OPEN_PIPE: + /* Seen only when opening a capture file for reading. */ + errmsg = "The file \"%s\" is a pipe or FIFO; TFShark can't read pipe or FIFO files in two-pass mode."; + break; - case FTAP_ERR_FILE_UNKNOWN_FORMAT: - /* Seen only when opening a capture file for reading. */ - errmsg = "The file \"%s\" isn't a capture file in a format TFShark understands."; - break; + case FTAP_ERR_FILE_UNKNOWN_FORMAT: + /* Seen only when opening a capture file for reading. */ + errmsg = "The file \"%s\" isn't a capture file in a format TFShark understands."; + break; - case FTAP_ERR_UNSUPPORTED: - /* Seen only when opening a capture file for reading. */ - snprintf(errmsg_errno, sizeof(errmsg_errno), - "The file \"%%s\" isn't a capture file in a format TFShark understands.\n" - "(%s)", err_info); - g_free(err_info); - errmsg = errmsg_errno; - break; + case FTAP_ERR_UNSUPPORTED: + /* Seen only when opening a capture file for reading. */ + snprintf(errmsg_errno, sizeof(errmsg_errno), + "The file \"%%s\" isn't a capture file in a format TFShark understands.\n" + "(%s)", err_info); + g_free(err_info); + errmsg = errmsg_errno; + break; - case FTAP_ERR_CANT_WRITE_TO_PIPE: - /* Seen only when opening a capture file for writing. */ - snprintf(errmsg_errno, sizeof(errmsg_errno), - "The file \"%%s\" is a pipe, and \"%s\" capture files can't be " - "written to a pipe.", ftap_file_type_subtype_short_string(file_type)); - errmsg = errmsg_errno; - break; + case FTAP_ERR_CANT_WRITE_TO_PIPE: + /* Seen only when opening a capture file for writing. */ + snprintf(errmsg_errno, sizeof(errmsg_errno), + "The file \"%%s\" is a pipe, and \"%s\" capture files can't be " + "written to a pipe.", ftap_file_type_subtype_short_string(file_type)); + errmsg = errmsg_errno; + break; - case FTAP_ERR_UNSUPPORTED_FILE_TYPE: - /* Seen only when opening a capture file for writing. */ - errmsg = "TFShark doesn't support writing capture files in that format."; - break; + case FTAP_ERR_UNSUPPORTED_FILE_TYPE: + /* Seen only when opening a capture file for writing. */ + errmsg = "TFShark doesn't support writing capture files in that format."; + break; - case FTAP_ERR_UNSUPPORTED_ENCAP: - if (for_writing) { - snprintf(errmsg_errno, sizeof(errmsg_errno), - "TFShark can't save this capture as a \"%s\" file.", - ftap_file_type_subtype_short_string(file_type)); - } else { - snprintf(errmsg_errno, sizeof(errmsg_errno), - "The file \"%%s\" is a capture for a network type that TFShark doesn't support.\n" - "(%s)", err_info); - g_free(err_info); - } - errmsg = errmsg_errno; - break; + case FTAP_ERR_UNSUPPORTED_ENCAP: + if (for_writing) { + snprintf(errmsg_errno, sizeof(errmsg_errno), + "TFShark can't save this capture as a \"%s\" file.", + ftap_file_type_subtype_short_string(file_type)); + } else { + snprintf(errmsg_errno, sizeof(errmsg_errno), + "The file \"%%s\" is a capture for a network type that TFShark doesn't support.\n" + "(%s)", err_info); + g_free(err_info); + } + errmsg = errmsg_errno; + break; - case FTAP_ERR_ENCAP_PER_RECORD_UNSUPPORTED: - if (for_writing) { - snprintf(errmsg_errno, sizeof(errmsg_errno), - "TFShark can't save this capture as a \"%s\" file.", - ftap_file_type_subtype_short_string(file_type)); - errmsg = errmsg_errno; - } else - errmsg = "The file \"%s\" is a capture for a network type that TFShark doesn't support."; - break; + case FTAP_ERR_ENCAP_PER_RECORD_UNSUPPORTED: + if (for_writing) { + snprintf(errmsg_errno, sizeof(errmsg_errno), + "TFShark can't save this capture as a \"%s\" file.", + ftap_file_type_subtype_short_string(file_type)); + errmsg = errmsg_errno; + } else + errmsg = "The file \"%s\" is a capture for a network type that TFShark doesn't support."; + break; - case FTAP_ERR_BAD_FILE: - /* Seen only when opening a capture file for reading. */ - snprintf(errmsg_errno, sizeof(errmsg_errno), - "The file \"%%s\" appears to be damaged or corrupt.\n" - "(%s)", err_info); - g_free(err_info); - errmsg = errmsg_errno; - break; + case FTAP_ERR_BAD_FILE: + /* Seen only when opening a capture file for reading. */ + snprintf(errmsg_errno, sizeof(errmsg_errno), + "The file \"%%s\" appears to be damaged or corrupt.\n" + "(%s)", err_info); + g_free(err_info); + errmsg = errmsg_errno; + break; - case FTAP_ERR_CANT_OPEN: - if (for_writing) - errmsg = "The file \"%s\" could not be created for some unknown reason."; - else - errmsg = "The file \"%s\" could not be opened for some unknown reason."; - break; + case FTAP_ERR_CANT_OPEN: + if (for_writing) + errmsg = "The file \"%s\" could not be created for some unknown reason."; + else + errmsg = "The file \"%s\" could not be opened for some unknown reason."; + break; - case FTAP_ERR_SHORT_READ: - errmsg = "The file \"%s\" appears to have been cut short" - " in the middle of a packet or other data."; - break; + case FTAP_ERR_SHORT_READ: + errmsg = "The file \"%s\" appears to have been cut short" + " in the middle of a packet or other data."; + break; - case FTAP_ERR_SHORT_WRITE: - errmsg = "A full header couldn't be written to the file \"%s\"."; - break; + case FTAP_ERR_SHORT_WRITE: + errmsg = "A full header couldn't be written to the file \"%s\"."; + break; - case FTAP_ERR_COMPRESSION_NOT_SUPPORTED: - errmsg = "This file type cannot be written as a compressed file."; - break; + case FTAP_ERR_COMPRESSION_NOT_SUPPORTED: + errmsg = "This file type cannot be written as a compressed file."; + break; - case FTAP_ERR_DECOMPRESS: - /* Seen only when opening a capture file for reading. */ - snprintf(errmsg_errno, sizeof(errmsg_errno), - "The compressed file \"%%s\" appears to be damaged or corrupt.\n" - "(%s)", err_info); - g_free(err_info); - errmsg = errmsg_errno; - break; + case FTAP_ERR_DECOMPRESS: + /* Seen only when opening a capture file for reading. */ + snprintf(errmsg_errno, sizeof(errmsg_errno), + "The compressed file \"%%s\" appears to be damaged or corrupt.\n" + "(%s)", err_info); + g_free(err_info); + errmsg = errmsg_errno; + break; - default: - snprintf(errmsg_errno, sizeof(errmsg_errno), - "The file \"%%s\" could not be %s: %s.", - for_writing ? "created" : "opened", - ftap_strerror(err)); - errmsg = errmsg_errno; - break; - } - } else + default: + snprintf(errmsg_errno, sizeof(errmsg_errno), + "The file \"%%s\" could not be %s: %s.", + for_writing ? "created" : "opened", + ftap_strerror(err)); + errmsg = errmsg_errno; + break; + } + } else #endif - errmsg = file_open_error_message(err, for_writing); - return errmsg; + errmsg = file_open_error_message(err, for_writing); + return errmsg; } /* @@ -2197,9 +2199,9 @@ cf_open_error_message(int err, gchar *err_info _U_, gboolean for_writing, static void tfshark_cmdarg_err(const char *msg_format, va_list ap) { - fprintf(stderr, "tfshark: "); - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + fprintf(stderr, "tfshark: "); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } /* @@ -2208,19 +2210,6 @@ tfshark_cmdarg_err(const char *msg_format, va_list ap) static void tfshark_cmdarg_err_cont(const char *msg_format, va_list ap) { - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ diff --git a/tshark.c b/tshark.c index 1e66941ae6..6ab5b449c8 100644 --- a/tshark.c +++ b/tshark.c @@ -151,14 +151,14 @@ static gboolean epan_auto_reset = FALSE; * The way the packet decode is to be written. */ typedef enum { - WRITE_NONE, /* dummy initial state */ - WRITE_TEXT, /* summary or detail text */ - WRITE_XML, /* PDML or PSML */ - WRITE_FIELDS, /* User defined list of fields */ - WRITE_JSON, /* JSON */ - WRITE_JSON_RAW, /* JSON only raw hex */ - WRITE_EK /* JSON bulk insert to Elasticsearch */ - /* Add CSV and the like here */ + WRITE_NONE, /* dummy initial state */ + WRITE_TEXT, /* summary or detail text */ + WRITE_XML, /* PDML or PSML */ + WRITE_FIELDS, /* User defined list of fields */ + WRITE_JSON, /* JSON */ + WRITE_JSON_RAW, /* JSON only raw hex */ + WRITE_EK /* JSON bulk insert to Elasticsearch */ + /* Add CSV and the like here */ } output_action_e; static output_action_e output_action; @@ -214,15 +214,15 @@ static gboolean infoprint; /* if TRUE, print capture info after clearing in static gboolean capture(void); static gboolean capture_input_new_file(capture_session *cap_session, - gchar *new_file); + gchar *new_file); static void capture_input_new_packets(capture_session *cap_session, - int to_read); + int to_read); static void capture_input_drops(capture_session *cap_session, guint32 dropped, - const char* interface_name); + const char* interface_name); static void capture_input_error(capture_session *cap_session, - char *error_msg, char *secondary_error_msg); + char *error_msg, char *secondary_error_msg); static void capture_input_cfilter_error(capture_session *cap_session, - guint i, const char *error_message); + guint i, const char *error_message); static void capture_input_closed(capture_session *cap_session, gchar *msg); static void report_counts(void); @@ -239,16 +239,16 @@ static void report_counts_siginfo(int); static void reset_epan_mem(capture_file *cf, epan_dissect_t *edt, gboolean tree, gboolean visual); typedef enum { - PROCESS_FILE_SUCCEEDED, - PROCESS_FILE_NO_FILE_PROCESSED, - PROCESS_FILE_ERROR, - PROCESS_FILE_INTERRUPTED + PROCESS_FILE_SUCCEEDED, + PROCESS_FILE_NO_FILE_PROCESSED, + PROCESS_FILE_ERROR, + PROCESS_FILE_INTERRUPTED } process_file_status_t; static process_file_status_t process_cap_file(capture_file *, char *, int, gboolean, int, gint64, int); static gboolean process_packet_single_pass(capture_file *cf, - epan_dissect_t *edt, gint64 offset, wtap_rec *rec, Buffer *buf, - guint tap_flags); + epan_dissect_t *edt, gint64 offset, wtap_rec *rec, Buffer *buf, + guint tap_flags); static void show_print_file_io_error(void); static gboolean write_preamble(capture_file *cf); static gboolean print_packet(capture_file *cf, epan_dissect_t *edt); @@ -260,249 +260,252 @@ static void tshark_cmdarg_err_cont(const char *msg_format, va_list ap); static GHashTable *output_only_tables = NULL; static void -list_capture_types(void) { - GArray *writable_type_subtypes; +list_capture_types(void) +{ + GArray *writable_type_subtypes; - fprintf(stderr, "tshark: The available capture file types for the \"-F\" flag are:\n"); - writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME); - for (guint i = 0; i < writable_type_subtypes->len; i++) { - int ft = g_array_index(writable_type_subtypes, int, i); - fprintf(stderr, " %s - %s\n", wtap_file_type_subtype_name(ft), - wtap_file_type_subtype_description(ft)); - } - g_array_free(writable_type_subtypes, TRUE); + fprintf(stderr, "tshark: The available capture file types for the \"-F\" flag are:\n"); + writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME); + for (guint i = 0; i < writable_type_subtypes->len; i++) { + int ft = g_array_index(writable_type_subtypes, int, i); + fprintf(stderr, " %s - %s\n", wtap_file_type_subtype_name(ft), + wtap_file_type_subtype_description(ft)); + } + g_array_free(writable_type_subtypes, TRUE); } struct string_elem { - const char *sstr; /* The short string */ - const char *lstr; /* The long string */ + const char *sstr; /* The short string */ + const char *lstr; /* The long string */ }; static gint string_compare(gconstpointer a, gconstpointer b) { - return strcmp(((const struct string_elem *)a)->sstr, - ((const struct string_elem *)b)->sstr); + return strcmp(((const struct string_elem *)a)->sstr, + ((const struct string_elem *)b)->sstr); } static void string_elem_print(gpointer data) { - fprintf(stderr, " %s - %s\n", - ((struct string_elem *)data)->sstr, - ((struct string_elem *)data)->lstr); + fprintf(stderr, " %s - %s\n", + ((struct string_elem *)data)->sstr, + ((struct string_elem *)data)->lstr); } static void -list_read_capture_types(void) { - guint i; - size_t num_file_types; - struct string_elem *captypes; - GSList *list = NULL; - const char *magic = "Magic-value-based"; - const char *heuristic = "Heuristics-based"; +list_read_capture_types(void) +{ + guint i; + size_t num_file_types; + struct string_elem *captypes; + GSList *list = NULL; + const char *magic = "Magic-value-based"; + const char *heuristic = "Heuristics-based"; - /* How many readable file types are there? */ - num_file_types = 0; - for (i = 0; open_routines[i].name != NULL; i++) - num_file_types++; - captypes = g_new(struct string_elem, num_file_types); + /* How many readable file types are there? */ + num_file_types = 0; + for (i = 0; open_routines[i].name != NULL; i++) + num_file_types++; + captypes = g_new(struct string_elem, num_file_types); - fprintf(stderr, "tshark: The available read file types for the \"-X read_format:\" option are:\n"); - for (i = 0; i < num_file_types && open_routines[i].name != NULL; i++) { - captypes[i].sstr = open_routines[i].name; - captypes[i].lstr = (open_routines[i].type == OPEN_INFO_MAGIC) ? magic : heuristic; - list = g_slist_insert_sorted(list, &captypes[i], string_compare); - } - g_slist_free_full(list, string_elem_print); - g_free(captypes); + fprintf(stderr, "tshark: The available read file types for the \"-X read_format:\" option are:\n"); + for (i = 0; i < num_file_types && open_routines[i].name != NULL; i++) { + captypes[i].sstr = open_routines[i].name; + captypes[i].lstr = (open_routines[i].type == OPEN_INFO_MAGIC) ? magic : heuristic; + list = g_slist_insert_sorted(list, &captypes[i], string_compare); + } + g_slist_free_full(list, string_elem_print); + g_free(captypes); } static void -list_export_pdu_taps(void) { - fprintf(stderr, "tshark: The available export tap names for the \"-U tap_name\" option are:\n"); - for (GSList *export_pdu_tap_name_list = get_export_pdu_tap_list(); - export_pdu_tap_name_list != NULL; - export_pdu_tap_name_list = g_slist_next(export_pdu_tap_name_list)) { - fprintf(stderr, " %s\n", (const char*)(export_pdu_tap_name_list->data)); - } +list_export_pdu_taps(void) +{ + fprintf(stderr, "tshark: The available export tap names for the \"-U tap_name\" option are:\n"); + for (GSList *export_pdu_tap_name_list = get_export_pdu_tap_list(); + export_pdu_tap_name_list != NULL; + export_pdu_tap_name_list = g_slist_next(export_pdu_tap_name_list)) { + fprintf(stderr, " %s\n", (const char*)(export_pdu_tap_name_list->data)); + } } static void print_usage(FILE *output) { - fprintf(output, "\n"); - fprintf(output, "Usage: tshark [options] ...\n"); - fprintf(output, "\n"); + fprintf(output, "\n"); + fprintf(output, "Usage: tshark [options] ...\n"); + fprintf(output, "\n"); #ifdef HAVE_LIBPCAP - fprintf(output, "Capture interface:\n"); - fprintf(output, " -i , --interface \n"); - fprintf(output, " name or idx of interface (def: first non-loopback)\n"); - fprintf(output, " -f packet filter in libpcap filter syntax\n"); - fprintf(output, " -s , --snapshot-length \n"); + fprintf(output, "Capture interface:\n"); + fprintf(output, " -i , --interface \n"); + fprintf(output, " name or idx of interface (def: first non-loopback)\n"); + fprintf(output, " -f packet filter in libpcap filter syntax\n"); + fprintf(output, " -s , --snapshot-length \n"); #ifdef HAVE_PCAP_CREATE - fprintf(output, " packet snapshot length (def: appropriate maximum)\n"); + fprintf(output, " packet snapshot length (def: appropriate maximum)\n"); #else - fprintf(output, " packet snapshot length (def: %u)\n", WTAP_MAX_PACKET_SIZE_STANDARD); + fprintf(output, " packet snapshot length (def: %u)\n", WTAP_MAX_PACKET_SIZE_STANDARD); #endif - fprintf(output, " -p, --no-promiscuous-mode\n"); - fprintf(output, " don't capture in promiscuous mode\n"); + fprintf(output, " -p, --no-promiscuous-mode\n"); + fprintf(output, " don't capture in promiscuous mode\n"); #ifdef HAVE_PCAP_CREATE - fprintf(output, " -I, --monitor-mode capture in monitor mode, if available\n"); + fprintf(output, " -I, --monitor-mode capture in monitor mode, if available\n"); #endif #ifdef CAN_SET_CAPTURE_BUFFER_SIZE - fprintf(output, " -B , --buffer-size \n"); - fprintf(output, " size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE); + fprintf(output, " -B , --buffer-size \n"); + fprintf(output, " size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE); #endif - fprintf(output, " -y , --linktype \n"); - fprintf(output, " link layer type (def: first appropriate)\n"); - fprintf(output, " --time-stamp-type timestamp method for interface\n"); - fprintf(output, " -D, --list-interfaces print list of interfaces and exit\n"); - fprintf(output, " -L, --list-data-link-types\n"); - fprintf(output, " print list of link-layer types of iface and exit\n"); - fprintf(output, " --list-time-stamp-types print list of timestamp types for iface and exit\n"); - fprintf(output, "\n"); - fprintf(output, "Capture stop conditions:\n"); - fprintf(output, " -c stop after n packets (def: infinite)\n"); - fprintf(output, " -a ..., --autostop ...\n"); - fprintf(output, " duration:NUM - stop after NUM seconds\n"); - fprintf(output, " filesize:NUM - stop this file after NUM KB\n"); - fprintf(output, " files:NUM - stop after NUM files\n"); - fprintf(output, " packets:NUM - stop after NUM packets\n"); - /*fprintf(output, "\n");*/ - fprintf(output, "Capture output:\n"); - fprintf(output, " -b ..., --ring-buffer \n"); - fprintf(output, " duration:NUM - switch to next file after NUM secs\n"); - fprintf(output, " filesize:NUM - switch to next file after NUM KB\n"); - fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n"); - fprintf(output, " packets:NUM - switch to next file after NUM packets\n"); - fprintf(output, " interval:NUM - switch to next file when the time is\n"); - fprintf(output, " an exact multiple of NUM secs\n"); + fprintf(output, " -y , --linktype \n"); + fprintf(output, " link layer type (def: first appropriate)\n"); + fprintf(output, " --time-stamp-type timestamp method for interface\n"); + fprintf(output, " -D, --list-interfaces print list of interfaces and exit\n"); + fprintf(output, " -L, --list-data-link-types\n"); + fprintf(output, " print list of link-layer types of iface and exit\n"); + fprintf(output, " --list-time-stamp-types print list of timestamp types for iface and exit\n"); + fprintf(output, "\n"); + fprintf(output, "Capture stop conditions:\n"); + fprintf(output, " -c stop after n packets (def: infinite)\n"); + fprintf(output, " -a ..., --autostop ...\n"); + fprintf(output, " duration:NUM - stop after NUM seconds\n"); + fprintf(output, " filesize:NUM - stop this file after NUM KB\n"); + fprintf(output, " files:NUM - stop after NUM files\n"); + fprintf(output, " packets:NUM - stop after NUM packets\n"); + /*fprintf(output, "\n");*/ + fprintf(output, "Capture output:\n"); + fprintf(output, " -b ..., --ring-buffer \n"); + fprintf(output, " duration:NUM - switch to next file after NUM secs\n"); + fprintf(output, " filesize:NUM - switch to next file after NUM KB\n"); + fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n"); + fprintf(output, " packets:NUM - switch to next file after NUM packets\n"); + fprintf(output, " interval:NUM - switch to next file when the time is\n"); + fprintf(output, " an exact multiple of NUM secs\n"); #endif /* HAVE_LIBPCAP */ #ifdef HAVE_PCAP_REMOTE - fprintf(output, "RPCAP options:\n"); - fprintf(output, " -A : use RPCAP password authentication\n"); + fprintf(output, "RPCAP options:\n"); + fprintf(output, " -A : use RPCAP password authentication\n"); #endif - /*fprintf(output, "\n");*/ - fprintf(output, "Input file:\n"); - fprintf(output, " -r , --read-file \n"); - fprintf(output, " set the filename to read from (or '-' for stdin)\n"); + /*fprintf(output, "\n");*/ + fprintf(output, "Input file:\n"); + fprintf(output, " -r , --read-file \n"); + fprintf(output, " set the filename to read from (or '-' for stdin)\n"); - fprintf(output, "\n"); - fprintf(output, "Processing:\n"); - fprintf(output, " -2 perform a two-pass analysis\n"); - fprintf(output, " -M perform session auto reset\n"); - fprintf(output, " -R , --read-filter \n"); - fprintf(output, " packet Read filter in Wireshark display filter syntax\n"); - fprintf(output, " (requires -2)\n"); - fprintf(output, " -Y , --display-filter \n"); - fprintf(output, " packet displaY filter in Wireshark display filter\n"); - fprintf(output, " syntax\n"); - fprintf(output, " -n disable all name resolutions (def: \"mNd\" enabled, or\n"); - fprintf(output, " as set in preferences)\n"); - fprintf(output, " -N enable specific name resolution(s): \"mnNtdv\"\n"); - fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE); - fprintf(output, " \"Decode As\", see the man page for details\n"); - fprintf(output, " Example: tcp.port==8888,http\n"); - fprintf(output, " -H read a list of entries from a hosts file, which will\n"); - fprintf(output, " then be written to a capture file. (Implies -W n)\n"); - fprintf(output, " --enable-protocol \n"); - fprintf(output, " enable dissection of proto_name\n"); - fprintf(output, " --disable-protocol \n"); - fprintf(output, " disable dissection of proto_name\n"); - fprintf(output, " --enable-heuristic \n"); - fprintf(output, " enable dissection of heuristic protocol\n"); - fprintf(output, " --disable-heuristic \n"); - fprintf(output, " disable dissection of heuristic protocol\n"); + fprintf(output, "\n"); + fprintf(output, "Processing:\n"); + fprintf(output, " -2 perform a two-pass analysis\n"); + fprintf(output, " -M perform session auto reset\n"); + fprintf(output, " -R , --read-filter \n"); + fprintf(output, " packet Read filter in Wireshark display filter syntax\n"); + fprintf(output, " (requires -2)\n"); + fprintf(output, " -Y , --display-filter \n"); + fprintf(output, " packet displaY filter in Wireshark display filter\n"); + fprintf(output, " syntax\n"); + fprintf(output, " -n disable all name resolutions (def: \"mNd\" enabled, or\n"); + fprintf(output, " as set in preferences)\n"); + fprintf(output, " -N enable specific name resolution(s): \"mnNtdv\"\n"); + fprintf(output, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE); + fprintf(output, " \"Decode As\", see the man page for details\n"); + fprintf(output, " Example: tcp.port==8888,http\n"); + fprintf(output, " -H read a list of entries from a hosts file, which will\n"); + fprintf(output, " then be written to a capture file. (Implies -W n)\n"); + fprintf(output, " --enable-protocol \n"); + fprintf(output, " enable dissection of proto_name\n"); + fprintf(output, " --disable-protocol \n"); + fprintf(output, " disable dissection of proto_name\n"); + fprintf(output, " --enable-heuristic \n"); + fprintf(output, " enable dissection of heuristic protocol\n"); + fprintf(output, " --disable-heuristic \n"); + fprintf(output, " disable dissection of heuristic protocol\n"); - /*fprintf(output, "\n");*/ - fprintf(output, "Output:\n"); - fprintf(output, " -w write packets to a pcapng-format file named \"outfile\"\n"); - fprintf(output, " (or '-' for stdout)\n"); - fprintf(output, " --capture-comment \n"); - fprintf(output, " add a capture file comment, if supported\n"); - fprintf(output, " -C start with specified configuration profile\n"); - fprintf(output, " -F set the output file type, default is pcapng\n"); - fprintf(output, " an empty \"-F\" option will list the file types\n"); - fprintf(output, " -V add output of packet tree (Packet Details)\n"); - fprintf(output, " -O Only show packet details of these protocols, comma\n"); - fprintf(output, " separated\n"); - fprintf(output, " -P, --print print packet summary even when writing to a file\n"); - fprintf(output, " -S the line separator to print between packets\n"); - fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n"); - fprintf(output, " --hexdump add hexdump, set options for data source and ASCII dump\n"); - fprintf(output, " all dump all data sources (-x default)\n"); - fprintf(output, " frames dump only frame data source\n"); - fprintf(output, " ascii include ASCII dump text (-x default)\n"); - fprintf(output, " delimit delimit ASCII dump text with '|' characters\n"); - fprintf(output, " noascii exclude ASCII dump text\n"); - fprintf(output, " help display help for --hexdump and exit\n"); - fprintf(output, " -T pdml|ps|psml|json|jsonraw|ek|tabs|text|fields|?\n"); - fprintf(output, " format of text output (def: text)\n"); - fprintf(output, " -j protocols layers filter if -T ek|pdml|json selected\n"); - fprintf(output, " (e.g. \"ip ip.flags text\", filter does not expand child\n"); - fprintf(output, " nodes, unless child is specified also in the filter)\n"); - fprintf(output, " -J top level protocol filter if -T ek|pdml|json selected\n"); - fprintf(output, " (e.g. \"http tcp\", filter which expands all child nodes)\n"); - fprintf(output, " -e field to print if -Tfields selected (e.g. tcp.port,\n"); - fprintf(output, " _ws.col.Info)\n"); - fprintf(output, " this option can be repeated to print multiple fields\n"); - fprintf(output, " -E= set options for output when -Tfields selected:\n"); - fprintf(output, " bom=y|n print a UTF-8 BOM\n"); - fprintf(output, " header=y|n switch headers on and off\n"); - fprintf(output, " separator=/t|/s| select tab, space, printable character as separator\n"); - fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n"); - fprintf(output, " aggregator=,|/s| select comma, space, printable character as\n"); - fprintf(output, " aggregator\n"); - fprintf(output, " quote=d|s|n select double, single, no quotes for values\n"); - fprintf(output, " -t a|ad|adoy|d|dd|e|r|u|ud|udoy\n"); - fprintf(output, " output format of time stamps (def: r: rel. to first)\n"); - fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n"); - fprintf(output, " -l flush standard output after each packet\n"); - fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n"); - fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n"); - fprintf(output, " -g enable group read access on the output file(s)\n"); - fprintf(output, " -W n Save extra information in the file, if supported.\n"); - fprintf(output, " n = write network address resolution information\n"); - fprintf(output, " -X : eXtension options, see the man page for details\n"); - fprintf(output, " -U tap_name PDUs export mode, see the man page for details\n"); - fprintf(output, " -z various statistics, see the man page for details\n"); - fprintf(output, " --export-objects ,\n"); - fprintf(output, " save exported objects for a protocol to a directory\n"); - fprintf(output, " named \"destdir\"\n"); - fprintf(output, " --export-tls-session-keys \n"); - fprintf(output, " export TLS Session Keys to a file named \"keyfile\"\n"); - fprintf(output, " --color color output text similarly to the Wireshark GUI,\n"); - fprintf(output, " requires a terminal with 24-bit color support\n"); - fprintf(output, " Also supplies color attributes to pdml and psml formats\n"); - fprintf(output, " (Note that attributes are nonstandard)\n"); - fprintf(output, " --no-duplicate-keys If -T json is specified, merge duplicate keys in an object\n"); - fprintf(output, " into a single key with as value a json array containing all\n"); - fprintf(output, " values\n"); - fprintf(output, " --elastic-mapping-filter If -G elastic-mapping is specified, put only the\n"); - fprintf(output, " specified protocols within the mapping file\n"); - fprintf(output, " --temp-dir write temporary files to this directory\n"); - fprintf(output, " (default: %s)\n", g_get_tmp_dir()); - fprintf(output, "\n"); + /*fprintf(output, "\n");*/ + fprintf(output, "Output:\n"); + fprintf(output, " -w write packets to a pcapng-format file named \"outfile\"\n"); + fprintf(output, " (or '-' for stdout)\n"); + fprintf(output, " --capture-comment \n"); + fprintf(output, " add a capture file comment, if supported\n"); + fprintf(output, " -C start with specified configuration profile\n"); + fprintf(output, " -F set the output file type, default is pcapng\n"); + fprintf(output, " an empty \"-F\" option will list the file types\n"); + fprintf(output, " -V add output of packet tree (Packet Details)\n"); + fprintf(output, " -O Only show packet details of these protocols, comma\n"); + fprintf(output, " separated\n"); + fprintf(output, " -P, --print print packet summary even when writing to a file\n"); + fprintf(output, " -S the line separator to print between packets\n"); + fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n"); + fprintf(output, " --hexdump add hexdump, set options for data source and ASCII dump\n"); + fprintf(output, " all dump all data sources (-x default)\n"); + fprintf(output, " frames dump only frame data source\n"); + fprintf(output, " ascii include ASCII dump text (-x default)\n"); + fprintf(output, " delimit delimit ASCII dump text with '|' characters\n"); + fprintf(output, " noascii exclude ASCII dump text\n"); + fprintf(output, " help display help for --hexdump and exit\n"); + fprintf(output, " -T pdml|ps|psml|json|jsonraw|ek|tabs|text|fields|?\n"); + fprintf(output, " format of text output (def: text)\n"); + fprintf(output, " -j protocols layers filter if -T ek|pdml|json selected\n"); + fprintf(output, " (e.g. \"ip ip.flags text\", filter does not expand child\n"); + fprintf(output, " nodes, unless child is specified also in the filter)\n"); + fprintf(output, " -J top level protocol filter if -T ek|pdml|json selected\n"); + fprintf(output, " (e.g. \"http tcp\", filter which expands all child nodes)\n"); + fprintf(output, " -e field to print if -Tfields selected (e.g. tcp.port,\n"); + fprintf(output, " _ws.col.Info)\n"); + fprintf(output, " this option can be repeated to print multiple fields\n"); + fprintf(output, " -E= set options for output when -Tfields selected:\n"); + fprintf(output, " bom=y|n print a UTF-8 BOM\n"); + fprintf(output, " header=y|n switch headers on and off\n"); + fprintf(output, " separator=/t|/s| select tab, space, printable character as separator\n"); + fprintf(output, " occurrence=f|l|a print first, last or all occurrences of each field\n"); + fprintf(output, " aggregator=,|/s| select comma, space, printable character as\n"); + fprintf(output, " aggregator\n"); + fprintf(output, " quote=d|s|n select double, single, no quotes for values\n"); + fprintf(output, " -t a|ad|adoy|d|dd|e|r|u|ud|udoy\n"); + fprintf(output, " output format of time stamps (def: r: rel. to first)\n"); + fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n"); + fprintf(output, " -l flush standard output after each packet\n"); + fprintf(output, " -q be more quiet on stdout (e.g. when using statistics)\n"); + fprintf(output, " -Q only log true errors to stderr (quieter than -q)\n"); + fprintf(output, " -g enable group read access on the output file(s)\n"); + fprintf(output, " -W n Save extra information in the file, if supported.\n"); + fprintf(output, " n = write network address resolution information\n"); + fprintf(output, " -X : eXtension options, see the man page for details\n"); + fprintf(output, " -U tap_name PDUs export mode, see the man page for details\n"); + fprintf(output, " -z various statistics, see the man page for details\n"); + fprintf(output, " --export-objects ,\n"); + fprintf(output, " save exported objects for a protocol to a directory\n"); + fprintf(output, " named \"destdir\"\n"); + fprintf(output, " --export-tls-session-keys \n"); + fprintf(output, " export TLS Session Keys to a file named \"keyfile\"\n"); + fprintf(output, " --color color output text similarly to the Wireshark GUI,\n"); + fprintf(output, " requires a terminal with 24-bit color support\n"); + fprintf(output, " Also supplies color attributes to pdml and psml formats\n"); + fprintf(output, " (Note that attributes are nonstandard)\n"); + fprintf(output, " --no-duplicate-keys If -T json is specified, merge duplicate keys in an object\n"); + fprintf(output, " into a single key with as value a json array containing all\n"); + fprintf(output, " values\n"); + fprintf(output, " --elastic-mapping-filter If -G elastic-mapping is specified, put only the\n"); + fprintf(output, " specified protocols within the mapping file\n"); + fprintf(output, " --temp-dir write temporary files to this directory\n"); + fprintf(output, " (default: %s)\n", g_get_tmp_dir()); + fprintf(output, "\n"); - ws_log_print_usage(output); - fprintf(output, "\n"); + ws_log_print_usage(output); + fprintf(output, "\n"); - fprintf(output, "Miscellaneous:\n"); - fprintf(output, " -h, --help display this help and exit\n"); - fprintf(output, " -v, --version display version info and exit\n"); - fprintf(output, " -o : ... override preference setting\n"); - fprintf(output, " -K keytab file to use for kerberos decryption\n"); - fprintf(output, " -G [report] dump one of several available reports and exit\n"); - fprintf(output, " default report=\"fields\"\n"); - fprintf(output, " use \"-G help\" for more help\n"); + fprintf(output, "Miscellaneous:\n"); + fprintf(output, " -h, --help display this help and exit\n"); + fprintf(output, " -v, --version display version info and exit\n"); + fprintf(output, " -o : ... override preference setting\n"); + fprintf(output, " -K keytab file to use for kerberos decryption\n"); + fprintf(output, " -G [report] dump one of several available reports and exit\n"); + fprintf(output, " default report=\"fields\"\n"); + fprintf(output, " use \"-G help\" for more help\n"); #ifdef __linux__ - fprintf(output, "\n"); - fprintf(output, "Dumpcap can benefit from an enabled BPF JIT compiler if available.\n"); - fprintf(output, "You might want to enable it by executing:\n"); - fprintf(output, " \"echo 1 > /proc/sys/net/core/bpf_jit_enable\"\n"); - fprintf(output, "Note that this can make your system less secure!\n"); + fprintf(output, "\n"); + fprintf(output, "Dumpcap can benefit from an enabled BPF JIT compiler if available.\n"); + fprintf(output, "You might want to enable it by executing:\n"); + fprintf(output, " \"echo 1 > /proc/sys/net/core/bpf_jit_enable\"\n"); + fprintf(output, "Note that this can make your system less secure!\n"); #endif } @@ -510,83 +513,84 @@ print_usage(FILE *output) static void glossary_option_help(void) { - FILE *output; + FILE *output; - output = stdout; + output = stdout; - fprintf(output, "%s\n", get_appname_and_version()); + fprintf(output, "%s\n", get_appname_and_version()); - fprintf(output, "\n"); - fprintf(output, "Usage: tshark -G [report]\n"); - fprintf(output, "\n"); - fprintf(output, "Glossary table reports:\n"); - fprintf(output, " -G column-formats dump column format codes and exit\n"); - fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n"); - fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n"); - fprintf(output, " -G elastic-mapping dump ElasticSearch mapping file\n"); - fprintf(output, " -G fieldcount dump count of header fields and exit\n"); - fprintf(output, " -G fields dump fields glossary and exit\n"); - fprintf(output, " -G ftypes dump field type basic and descriptive names\n"); - fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n"); - fprintf(output, " -G plugins dump installed plugins and exit\n"); - fprintf(output, " -G protocols dump protocols in registration database and exit\n"); - fprintf(output, " -G values dump value, range, true/false strings and exit\n"); - fprintf(output, "\n"); - fprintf(output, "Preference reports:\n"); - fprintf(output, " -G currentprefs dump current preferences and exit\n"); - fprintf(output, " -G defaultprefs dump default preferences and exit\n"); - fprintf(output, " -G folders dump about:folders\n"); - fprintf(output, "\n"); + fprintf(output, "\n"); + fprintf(output, "Usage: tshark -G [report]\n"); + fprintf(output, "\n"); + fprintf(output, "Glossary table reports:\n"); + fprintf(output, " -G column-formats dump column format codes and exit\n"); + fprintf(output, " -G decodes dump \"layer type\"/\"decode as\" associations and exit\n"); + fprintf(output, " -G dissector-tables dump dissector table names, types, and properties\n"); + fprintf(output, " -G elastic-mapping dump ElasticSearch mapping file\n"); + fprintf(output, " -G fieldcount dump count of header fields and exit\n"); + fprintf(output, " -G fields dump fields glossary and exit\n"); + fprintf(output, " -G ftypes dump field type basic and descriptive names\n"); + fprintf(output, " -G heuristic-decodes dump heuristic dissector tables\n"); + fprintf(output, " -G plugins dump installed plugins and exit\n"); + fprintf(output, " -G protocols dump protocols in registration database and exit\n"); + fprintf(output, " -G values dump value, range, true/false strings and exit\n"); + fprintf(output, "\n"); + fprintf(output, "Preference reports:\n"); + fprintf(output, " -G currentprefs dump current preferences and exit\n"); + fprintf(output, " -G defaultprefs dump default preferences and exit\n"); + fprintf(output, " -G folders dump about:folders\n"); + fprintf(output, "\n"); } static void hexdump_option_help(FILE *output) { - fprintf(output, "%s\n", get_appname_and_version()); - fprintf(output, "\n"); - fprintf(output, "tshark: Valid --hexdump values include:\n"); - fprintf(output, "\n"); - fprintf(output, "Data source options:\n"); - fprintf(output, " all add hexdump, dump all data sources (-x default)\n"); - fprintf(output, " frames add hexdump, dump only frame data source\n"); - fprintf(output, "\n"); - fprintf(output, "ASCII options:\n"); - fprintf(output, " ascii add hexdump, include ASCII dump text (-x default)\n"); - fprintf(output, " delimit add hexdump, delimit ASCII dump text with '|' characters\n"); - fprintf(output, " noascii add hexdump, exclude ASCII dump text\n"); - fprintf(output, "\n"); - fprintf(output, "Miscellaneous:\n"); - fprintf(output, " help display this help and exit\n"); - fprintf(output, "\n"); - fprintf(output, "Example:\n"); - fprintf(output, "\n"); - fprintf(output, " $ tshark ... --hexdump frames --hexdump delimit ...\n"); - fprintf(output, "\n"); + fprintf(output, "%s\n", get_appname_and_version()); + fprintf(output, "\n"); + fprintf(output, "tshark: Valid --hexdump values include:\n"); + fprintf(output, "\n"); + fprintf(output, "Data source options:\n"); + fprintf(output, " all add hexdump, dump all data sources (-x default)\n"); + fprintf(output, " frames add hexdump, dump only frame data source\n"); + fprintf(output, "\n"); + fprintf(output, "ASCII options:\n"); + fprintf(output, " ascii add hexdump, include ASCII dump text (-x default)\n"); + fprintf(output, " delimit add hexdump, delimit ASCII dump text with '|' characters\n"); + fprintf(output, " noascii add hexdump, exclude ASCII dump text\n"); + fprintf(output, "\n"); + fprintf(output, "Miscellaneous:\n"); + fprintf(output, " help display this help and exit\n"); + fprintf(output, "\n"); + fprintf(output, "Example:\n"); + fprintf(output, "\n"); + fprintf(output, " $ tshark ... --hexdump frames --hexdump delimit ...\n"); + fprintf(output, "\n"); } static void -print_current_user(void) { - gchar *cur_user, *cur_group; +print_current_user(void) +{ + gchar *cur_user, *cur_group; - if (started_with_special_privs()) { - cur_user = get_cur_username(); - cur_group = get_cur_groupname(); - fprintf(stderr, "Running as user \"%s\" and group \"%s\".", - cur_user, cur_group); - g_free(cur_user); - g_free(cur_group); - if (running_with_special_privs()) { - fprintf(stderr, " This could be dangerous."); + if (started_with_special_privs()) { + cur_user = get_cur_username(); + cur_group = get_cur_groupname(); + fprintf(stderr, "Running as user \"%s\" and group \"%s\".", + cur_user, cur_group); + g_free(cur_user); + g_free(cur_group); + if (running_with_special_privs()) { + fprintf(stderr, " This could be dangerous."); + } + fprintf(stderr, "\n"); } - fprintf(stderr, "\n"); - } } static void get_tshark_compiled_version_info(GString *str) { - /* Capture libraries */ - get_compiled_caplibs_version(str); + /* Capture libraries */ + get_compiled_caplibs_version(str); } static void @@ -605,1840 +609,1840 @@ get_tshark_runtime_version_info(GString *str) static void about_folders(void) { - const char *constpath; - char *path; - gint i; - gchar **resultArray; + const char *constpath; + char *path; + gint i; + gchar **resultArray; - /* "file open" */ + /* "file open" */ - /* - * Fetching the "File" dialogs folder not implemented. - * This is arguably just a pwd for a ui/cli . - */ + /* + * Fetching the "File" dialogs folder not implemented. + * This is arguably just a pwd for a ui/cli . + */ - /* temp */ - constpath = g_get_tmp_dir(); + /* temp */ + constpath = g_get_tmp_dir(); #ifdef HAVE_LIBPCAP - /* global_capture_opts only exists in this case */ - if (global_capture_opts.temp_dir) - constpath = global_capture_opts.temp_dir; + /* global_capture_opts only exists in this case */ + if (global_capture_opts.temp_dir) + constpath = global_capture_opts.temp_dir; #endif - printf("%-21s\t%s\n", "Temp:", constpath); + printf("%-21s\t%s\n", "Temp:", constpath); - /* pers conf */ - path = get_persconffile_path("", FALSE); - printf("%-21s\t%s\n", "Personal configuration:", path); - g_free(path); + /* pers conf */ + path = get_persconffile_path("", FALSE); + printf("%-21s\t%s\n", "Personal configuration:", path); + g_free(path); - /* global conf */ - constpath = get_datafile_dir(); - if (constpath != NULL) { - printf("%-21s\t%s\n", "Global configuration:", constpath); - } + /* global conf */ + constpath = get_datafile_dir(); + if (constpath != NULL) { + printf("%-21s\t%s\n", "Global configuration:", constpath); + } - /* system */ - constpath = get_systemfile_dir(); - printf("%-21s\t%s\n", "System:", constpath); + /* system */ + constpath = get_systemfile_dir(); + printf("%-21s\t%s\n", "System:", constpath); - /* program */ - constpath = get_progfile_dir(); - printf("%-21s\t%s\n", "Program:", constpath); + /* program */ + constpath = get_progfile_dir(); + printf("%-21s\t%s\n", "Program:", constpath); #ifdef HAVE_PLUGINS - /* pers plugins */ - printf("%-21s\t%s\n", "Personal Plugins:", get_plugins_pers_dir_with_version()); + /* pers plugins */ + printf("%-21s\t%s\n", "Personal Plugins:", get_plugins_pers_dir_with_version()); - /* global plugins */ - printf("%-21s\t%s\n", "Global Plugins:", get_plugins_dir_with_version()); + /* global plugins */ + printf("%-21s\t%s\n", "Global Plugins:", get_plugins_dir_with_version()); #endif #ifdef HAVE_LUA - /* pers lua plugins */ - printf("%-21s\t%s\n", "Personal Lua Plugins:", get_plugins_pers_dir()); + /* pers lua plugins */ + printf("%-21s\t%s\n", "Personal Lua Plugins:", get_plugins_pers_dir()); - /* global lua plugins */ - printf("%-21s\t%s\n", "Global Lua Plugins:", get_plugins_dir()); + /* global lua plugins */ + printf("%-21s\t%s\n", "Global Lua Plugins:", get_plugins_dir()); #endif - /* Extcap */ - constpath = get_extcap_dir(); + /* Extcap */ + constpath = get_extcap_dir(); - resultArray = g_strsplit(constpath, G_SEARCHPATH_SEPARATOR_S, 10); - for(i = 0; resultArray[i]; i++) - printf("%-21s\t%s\n", "Extcap path:", g_strstrip(resultArray[i])); + resultArray = g_strsplit(constpath, G_SEARCHPATH_SEPARATOR_S, 10); + for(i = 0; resultArray[i]; i++) + printf("%-21s\t%s\n", "Extcap path:", g_strstrip(resultArray[i])); - g_strfreev(resultArray); + g_strfreev(resultArray); - /* MaxMindDB */ - path = maxmind_db_get_paths(); + /* MaxMindDB */ + path = maxmind_db_get_paths(); - resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 10); + resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 10); - for(i = 0; resultArray[i]; i++) - printf("%-21s\t%s\n", "MaxMind database path:", g_strstrip(resultArray[i])); + for(i = 0; resultArray[i]; i++) + printf("%-21s\t%s\n", "MaxMind database path:", g_strstrip(resultArray[i])); - g_strfreev(resultArray); - g_free(path); + g_strfreev(resultArray); + g_free(path); #ifdef HAVE_LIBSMI - /* SMI MIBs/PIBs */ - path = oid_get_default_mib_path(); + /* SMI MIBs/PIBs */ + path = oid_get_default_mib_path(); - resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 20); + resultArray = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 20); - for(i = 0; resultArray[i]; i++) - printf("%-21s\t%s\n", "MIB/PIB path:", g_strstrip(resultArray[i])); + for(i = 0; resultArray[i]; i++) + printf("%-21s\t%s\n", "MIB/PIB path:", g_strstrip(resultArray[i])); - g_strfreev(resultArray); - g_free(path); + g_strfreev(resultArray); + g_free(path); #endif } static gboolean must_do_dissection(dfilter_t *rfcode, dfilter_t *dfcode, - gchar *volatile pdu_export_arg) + gchar *volatile pdu_export_arg) { - /* We have to dissect each packet if: + /* We have to dissect each packet if: - we're printing information about each packet; + we're printing information about each packet; - we're using a read filter on the packets; + we're using a read filter on the packets; - we're using a display filter on the packets; + we're using a display filter on the packets; - we're exporting PDUs; + we're exporting PDUs; - we're using any taps that need dissection. */ - return print_packet_info || rfcode || dfcode || pdu_export_arg || - tap_listeners_require_dissection() || dissect_color; + we're using any taps that need dissection. */ + return print_packet_info || rfcode || dfcode || pdu_export_arg || + tap_listeners_require_dissection() || dissect_color; } int main(int argc, char *argv[]) { - char *err_msg; - static const struct report_message_routines tshark_report_routines = { - failure_message, - failure_message, - open_failure_message, - read_failure_message, - write_failure_message, - cfile_open_failure_message, - cfile_dump_open_failure_message, - cfile_read_failure_message, - cfile_write_failure_message, - cfile_close_failure_message - }; - int opt; - static const struct ws_option long_options[] = { - {"help", ws_no_argument, NULL, 'h'}, - {"version", ws_no_argument, NULL, 'v'}, - LONGOPT_CAPTURE_COMMON - LONGOPT_DISSECT_COMMON - {"print", ws_no_argument, NULL, 'P'}, - {"export-objects", ws_required_argument, NULL, LONGOPT_EXPORT_OBJECTS}, - {"export-tls-session-keys", ws_required_argument, NULL, LONGOPT_EXPORT_TLS_SESSION_KEYS}, - {"color", ws_no_argument, NULL, LONGOPT_COLOR}, - {"no-duplicate-keys", ws_no_argument, NULL, LONGOPT_NO_DUPLICATE_KEYS}, - {"elastic-mapping-filter", ws_required_argument, NULL, LONGOPT_ELASTIC_MAPPING_FILTER}, - {"capture-comment", ws_required_argument, NULL, LONGOPT_CAPTURE_COMMENT}, - {"hexdump", ws_required_argument, NULL, LONGOPT_HEXDUMP}, - {0, 0, 0, 0 } - }; - gboolean arg_error = FALSE; - gboolean has_extcap_options = FALSE; + char *err_msg; + static const struct report_message_routines tshark_report_routines = { + failure_message, + failure_message, + open_failure_message, + read_failure_message, + write_failure_message, + cfile_open_failure_message, + cfile_dump_open_failure_message, + cfile_read_failure_message, + cfile_write_failure_message, + cfile_close_failure_message + }; + int opt; + static const struct ws_option long_options[] = { + {"help", ws_no_argument, NULL, 'h'}, + {"version", ws_no_argument, NULL, 'v'}, + LONGOPT_CAPTURE_COMMON + LONGOPT_DISSECT_COMMON + {"print", ws_no_argument, NULL, 'P'}, + {"export-objects", ws_required_argument, NULL, LONGOPT_EXPORT_OBJECTS}, + {"export-tls-session-keys", ws_required_argument, NULL, LONGOPT_EXPORT_TLS_SESSION_KEYS}, + {"color", ws_no_argument, NULL, LONGOPT_COLOR}, + {"no-duplicate-keys", ws_no_argument, NULL, LONGOPT_NO_DUPLICATE_KEYS}, + {"elastic-mapping-filter", ws_required_argument, NULL, LONGOPT_ELASTIC_MAPPING_FILTER}, + {"capture-comment", ws_required_argument, NULL, LONGOPT_CAPTURE_COMMENT}, + {"hexdump", ws_required_argument, NULL, LONGOPT_HEXDUMP}, + {0, 0, 0, 0} + }; + gboolean arg_error = FALSE; + gboolean has_extcap_options = FALSE; - int err; - gchar *err_info; - gboolean exp_pdu_status; - volatile process_file_status_t status; - volatile gboolean draw_taps = FALSE; - volatile int exit_status = EXIT_SUCCESS; + int err; + gchar *err_info; + gboolean exp_pdu_status; + volatile process_file_status_t status; + volatile gboolean draw_taps = FALSE; + volatile int exit_status = EXIT_SUCCESS; #ifdef HAVE_LIBPCAP - int caps_queries = 0; - GList *if_list; - gchar *err_str, *err_str_secondary; - struct bpf_program fcode; + int caps_queries = 0; + GList *if_list; + gchar *err_str, *err_str_secondary; + struct bpf_program fcode; #else - gboolean capture_option_specified = FALSE; - volatile int max_packet_count = 0; + gboolean capture_option_specified = FALSE; + volatile int max_packet_count = 0; #endif - volatile int out_file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; - volatile gboolean out_file_name_res = FALSE; - volatile int in_file_type = WTAP_TYPE_AUTO; - gchar *volatile cf_name = NULL; - gchar *rfilter = NULL; - gchar *volatile dfilter = NULL; - dfilter_t *rfcode = NULL; - dfilter_t *dfcode = NULL; - e_prefs *prefs_p; - gchar *output_only = NULL; - gchar *volatile pdu_export_arg = NULL; - char *volatile exp_pdu_filename = NULL; - const gchar *volatile tls_session_keys_file = NULL; - exp_pdu_t exp_pdu_tap_data; - const gchar* elastic_mapping_filter = NULL; + volatile int out_file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; + volatile gboolean out_file_name_res = FALSE; + volatile int in_file_type = WTAP_TYPE_AUTO; + gchar *volatile cf_name = NULL; + gchar *rfilter = NULL; + gchar *volatile dfilter = NULL; + dfilter_t *rfcode = NULL; + dfilter_t *dfcode = NULL; + e_prefs *prefs_p; + gchar *output_only = NULL; + gchar *volatile pdu_export_arg = NULL; + char *volatile exp_pdu_filename = NULL; + const gchar *volatile tls_session_keys_file = NULL; + exp_pdu_t exp_pdu_tap_data; + const gchar* elastic_mapping_filter = NULL; -/* - * The leading + ensures that getopt_long() does not permute the argv[] - * entries. - * - * We have to make sure that the first getopt_long() preserves the content - * of argv[] for the subsequent getopt_long() call. - * - * We use getopt_long() in both cases to ensure that we're using a routine - * whose permutation behavior we can control in the same fashion on all - * platforms, and so that, if we ever need to process a long argument before - * doing further initialization, we can do so. - * - * Glibc and Solaris libc document that a leading + disables permutation - * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD - * and macOS don't document it, but do so anyway. - * - * We do *not* use a leading - because the behavior of a leading - is - * platform-dependent. - */ + /* + * The leading + ensures that getopt_long() does not permute the argv[] + * entries. + * + * We have to make sure that the first getopt_long() preserves the content + * of argv[] for the subsequent getopt_long() call. + * + * We use getopt_long() in both cases to ensure that we're using a routine + * whose permutation behavior we can control in the same fashion on all + * platforms, and so that, if we ever need to process a long argument before + * doing further initialization, we can do so. + * + * Glibc and Solaris libc document that a leading + disables permutation + * of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD + * and macOS don't document it, but do so anyway. + * + * We do *not* use a leading - because the behavior of a leading - is + * platform-dependent. + */ #define OPTSTRING "+2" OPTSTRING_CAPTURE_COMMON OPTSTRING_DISSECT_COMMON "M:C:e:E:F:gG:hH:j:J:lo:O:PqQr:R:S:T:U:vVw:W:xX:Y:z:" - static const char optstring[] = OPTSTRING; + static const char optstring[] = OPTSTRING; - /* - * Set the C-language locale to the native environment and set the - * code page to UTF-8 on Windows. - */ + /* + * Set the C-language locale to the native environment and set the + * code page to UTF-8 on Windows. + */ #ifdef _WIN32 - setlocale(LC_ALL, ".UTF-8"); + setlocale(LC_ALL, ".UTF-8"); #else - setlocale(LC_ALL, ""); + setlocale(LC_ALL, ""); #endif - cmdarg_err_init(tshark_cmdarg_err, tshark_cmdarg_err_cont); + cmdarg_err_init(tshark_cmdarg_err, tshark_cmdarg_err_cont); - /* Initialize log handler early so we can have proper logging during startup. */ - ws_log_init("tshark", vcmdarg_err); + /* Initialize log handler early so we can have proper logging during startup. */ + ws_log_init("tshark", vcmdarg_err); - /* Early logging command-line initialization. */ - ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION); + /* Early logging command-line initialization. */ + ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION); - ws_debug("tshark started with %d args", argc); + ws_debug("tshark started with %d args", argc); #ifdef _WIN32 - create_app_running_mutex(); + create_app_running_mutex(); #endif /* _WIN32 */ - /* - * Get credential information for later use, and drop privileges - * before doing anything else. - * Let the user know if anything happened. - */ - init_process_policies(); - relinquish_special_privs_perm(); - print_current_user(); + /* + * Get credential information for later use, and drop privileges + * before doing anything else. + * Let the user know if anything happened. + */ + init_process_policies(); + relinquish_special_privs_perm(); + print_current_user(); - /* - * Attempt to get the pathname of the directory containing the - * executable file. - */ - err_msg = init_progfile_dir(argv[0]); - if (err_msg != NULL) { - fprintf(stderr, - "tshark: Can't get pathname of directory containing the tshark program: %s.\n" - "It won't be possible to capture traffic.\n" - "Report this to the Wireshark developers.", - err_msg); - g_free(err_msg); - } + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + err_msg = init_progfile_dir(argv[0]); + if (err_msg != NULL) { + fprintf(stderr, + "tshark: Can't get pathname of directory containing the tshark program: %s.\n" + "It won't be possible to capture traffic.\n" + "Report this to the Wireshark developers.", + err_msg); + g_free(err_msg); + } - initialize_funnel_ops(); + initialize_funnel_ops(); #ifdef _WIN32 - ws_init_dll_search_path(); + ws_init_dll_search_path(); #ifdef HAVE_LIBPCAP - /* Load wpcap if possible. Do this before collecting the run-time version information */ - load_wpcap(); + /* Load wpcap if possible. Do this before collecting the run-time version information */ + load_wpcap(); #endif /* HAVE_LIBPCAP */ #endif /* _WIN32 */ - /* Initialize the version information. */ - ws_init_version_info("TShark (Wireshark)", get_tshark_compiled_version_info, - epan_get_compiled_version_info, - get_tshark_runtime_version_info); + /* Initialize the version information. */ + ws_init_version_info("TShark (Wireshark)", get_tshark_compiled_version_info, + epan_get_compiled_version_info, + get_tshark_runtime_version_info); - /* Fail sometimes. Useful for testing fuzz scripts. */ - /* if (g_random_int_range(0, 100) < 5) abort(); */ + /* Fail sometimes. Useful for testing fuzz scripts. */ + /* if (g_random_int_range(0, 100) < 5) abort(); */ - /* - * In order to have the -X opts assigned before the wslua machine starts - * we need to call getopt_long before epan_init() gets called. - * - * In order to handle, for example, -o options, we also need to call it - * *after* epan_init() gets called, so that the dissectors have had a - * chance to register their preferences. - * - * Spawning a bunch of extcap processes can delay program startup, - * particularly on Windows. Check to see if we have any options that - * might require extcap and set has_extcap_options = TRUE if that's - * the case. - * - * XXX - can we do this all with one getopt_long() call, saving the - * arguments we can't handle until after initializing libwireshark, - * and then process them after initializing libwireshark? - */ - ws_opterr = 0; + /* + * In order to have the -X opts assigned before the wslua machine starts + * we need to call getopt_long before epan_init() gets called. + * + * In order to handle, for example, -o options, we also need to call it + * *after* epan_init() gets called, so that the dissectors have had a + * chance to register their preferences. + * + * Spawning a bunch of extcap processes can delay program startup, + * particularly on Windows. Check to see if we have any options that + * might require extcap and set has_extcap_options = TRUE if that's + * the case. + * + * XXX - can we do this all with one getopt_long() call, saving the + * arguments we can't handle until after initializing libwireshark, + * and then process them after initializing libwireshark? + */ + ws_opterr = 0; - while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { - switch (opt) { - case 'C': /* Configuration Profile */ - if (profile_exists (ws_optarg, FALSE)) { - set_profile_name (ws_optarg); - } else { - cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg); - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - case 'G': - if (g_str_has_suffix(ws_optarg, "prefs") || strcmp(ws_optarg, "folders") == 0) { - has_extcap_options = TRUE; - } - break; - case 'i': - has_extcap_options = TRUE; - break; - case 'o': - if (g_str_has_prefix(ws_optarg, "extcap.")) { - has_extcap_options = TRUE; - } - break; - case 'P': /* Print packet summary info even when writing to a file */ - print_packet_info = TRUE; - print_summary = TRUE; - break; - case 'r': /* Read capture file x */ - cf_name = g_strdup(ws_optarg); - break; - case 'O': /* Only output these protocols */ - output_only = g_strdup(ws_optarg); - /* FALLTHROUGH */ - case 'V': /* Verbose */ - print_details = TRUE; - print_packet_info = TRUE; - break; - case 'x': /* Print packet data in hex (and ASCII) */ - print_hex = TRUE; - /* The user asked for hex output, so let's ensure they get it, - * even if they're writing to a file. - */ - print_packet_info = TRUE; - break; - case 'X': - ex_opt_add(ws_optarg); - break; - case LONGOPT_ELASTIC_MAPPING_FILTER: - elastic_mapping_filter = ws_optarg; - break; - default: - break; + while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { + switch (opt) { + case 'C': /* Configuration Profile */ + if (profile_exists (ws_optarg, FALSE)) { + set_profile_name (ws_optarg); + } else { + cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case 'G': + if (g_str_has_suffix(ws_optarg, "prefs") || strcmp(ws_optarg, "folders") == 0) { + has_extcap_options = TRUE; + } + break; + case 'i': + has_extcap_options = TRUE; + break; + case 'o': + if (g_str_has_prefix(ws_optarg, "extcap.")) { + has_extcap_options = TRUE; + } + break; + case 'P': /* Print packet summary info even when writing to a file */ + print_packet_info = TRUE; + print_summary = TRUE; + break; + case 'r': /* Read capture file x */ + cf_name = g_strdup(ws_optarg); + break; + case 'O': /* Only output these protocols */ + output_only = g_strdup(ws_optarg); + /* FALLTHROUGH */ + case 'V': /* Verbose */ + print_details = TRUE; + print_packet_info = TRUE; + break; + case 'x': /* Print packet data in hex (and ASCII) */ + print_hex = TRUE; + /* The user asked for hex output, so let's ensure they get it, + * even if they're writing to a file. + */ + print_packet_info = TRUE; + break; + case 'X': + ex_opt_add(ws_optarg); + break; + case LONGOPT_ELASTIC_MAPPING_FILTER: + elastic_mapping_filter = ws_optarg; + break; + default: + break; + } } - } #ifndef HAVE_LUA - if (ex_opt_count("lua_script") > 0) { - cmdarg_err("This version of TShark was not built with support for Lua scripting."); - exit_status = INIT_FAILED; - goto clean_exit; - } + if (ex_opt_count("lua_script") > 0) { + cmdarg_err("This version of TShark was not built with support for Lua scripting."); + exit_status = INIT_FAILED; + goto clean_exit; + } #endif /* HAVE_LUA */ - init_report_message("TShark", &tshark_report_routines); + init_report_message("TShark", &tshark_report_routines); #ifdef HAVE_LIBPCAP - capture_opts_init(&global_capture_opts); - capture_session_init(&global_capture_session, &cfile, - capture_input_new_file, capture_input_new_packets, - capture_input_drops, capture_input_error, - capture_input_cfilter_error, capture_input_closed); + capture_opts_init(&global_capture_opts); + capture_session_init(&global_capture_session, &cfile, + capture_input_new_file, capture_input_new_packets, + capture_input_drops, capture_input_error, + capture_input_cfilter_error, capture_input_closed); #endif - timestamp_set_type(TS_RELATIVE); - timestamp_set_precision(TS_PREC_AUTO); - timestamp_set_seconds_type(TS_SECONDS_DEFAULT); + timestamp_set_type(TS_RELATIVE); + timestamp_set_precision(TS_PREC_AUTO); + timestamp_set_seconds_type(TS_SECONDS_DEFAULT); - /* - * Libwiretap must be initialized before libwireshark is, so that - * dissection-time handlers for file-type-dependent blocks can - * register using the file type/subtype value for the file type. - */ - wtap_init(TRUE); + /* + * Libwiretap must be initialized before libwireshark is, so that + * dissection-time handlers for file-type-dependent blocks can + * register using the file type/subtype value for the file type. + */ + wtap_init(TRUE); - /* Register all dissectors; we must do this before checking for the - "-G" flag, as the "-G" flag dumps information registered by the - dissectors, and we must do it before we read the preferences, in - case any dissectors register preferences. */ - if (!epan_init(NULL, NULL, TRUE)) { - exit_status = INIT_FAILED; - goto clean_exit; - } - - /* Register all tap listeners; we do this before we parse the arguments, - as the "-z" argument can specify a registered tap. */ - - register_all_tap_listeners(tap_reg_listener); - - /* - * An empty cf_name indicates that we're capturing, and we might - * be doing so on an extcap interface. - */ - if (has_extcap_options || !cf_name) { - extcap_register_preferences(); - } - - conversation_table_set_gui_info(init_iousers); - hostlist_table_set_gui_info(init_hostlists); - srt_table_iterate_tables(register_srt_tables, NULL); - rtd_table_iterate_tables(register_rtd_tables, NULL); - stat_tap_iterate_tables(register_simple_stat_tables, NULL); - - /* If invoked with the "-G" flag, we dump out information based on - the argument to the "-G" flag; if no argument is specified, - for backwards compatibility we dump out a glossary of display - filter symbols. - - XXX - we do this here, for now, to support "-G" with no arguments. - If none of our build or other processes uses "-G" with no arguments, - we can just process it with the other arguments. */ - if (argc >= 2 && strcmp(argv[1], "-G") == 0) { - proto_initialize_all_prefixes(); - - if (argc == 2) - proto_registrar_dump_fields(); - else { - if (strcmp(argv[2], "column-formats") == 0) - column_dump_column_formats(); - else if (strcmp(argv[2], "currentprefs") == 0) { - epan_load_settings(); - write_prefs(NULL); - } - else if (strcmp(argv[2], "decodes") == 0) - dissector_dump_decodes(); - else if (strcmp(argv[2], "defaultprefs") == 0) - write_prefs(NULL); - else if (strcmp(argv[2], "dissector-tables") == 0) - dissector_dump_dissector_tables(); - else if (strcmp(argv[2], "elastic-mapping") == 0) - proto_registrar_dump_elastic(elastic_mapping_filter); - else if (strcmp(argv[2], "fieldcount") == 0) { - /* return value for the test suite */ - exit_status = proto_registrar_dump_fieldcount(); + /* Register all dissectors; we must do this before checking for the + "-G" flag, as the "-G" flag dumps information registered by the + dissectors, and we must do it before we read the preferences, in + case any dissectors register preferences. */ + if (!epan_init(NULL, NULL, TRUE)) { + exit_status = INIT_FAILED; goto clean_exit; - } else if (strcmp(argv[2], "fields") == 0) - proto_registrar_dump_fields(); - else if (strcmp(argv[2], "folders") == 0) { - epan_load_settings(); - about_folders(); - } else if (strcmp(argv[2], "ftypes") == 0) - proto_registrar_dump_ftypes(); - else if (strcmp(argv[2], "heuristic-decodes") == 0) - dissector_dump_heur_decodes(); - else if (strcmp(argv[2], "plugins") == 0) { + } + + /* Register all tap listeners; we do this before we parse the arguments, + as the "-z" argument can specify a registered tap. */ + + register_all_tap_listeners(tap_reg_listener); + + /* + * An empty cf_name indicates that we're capturing, and we might + * be doing so on an extcap interface. + */ + if (has_extcap_options || !cf_name) { + extcap_register_preferences(); + } + + conversation_table_set_gui_info(init_iousers); + hostlist_table_set_gui_info(init_hostlists); + srt_table_iterate_tables(register_srt_tables, NULL); + rtd_table_iterate_tables(register_rtd_tables, NULL); + stat_tap_iterate_tables(register_simple_stat_tables, NULL); + + /* If invoked with the "-G" flag, we dump out information based on + the argument to the "-G" flag; if no argument is specified, + for backwards compatibility we dump out a glossary of display + filter symbols. + + XXX - we do this here, for now, to support "-G" with no arguments. + If none of our build or other processes uses "-G" with no arguments, + we can just process it with the other arguments. */ + if (argc >= 2 && strcmp(argv[1], "-G") == 0) { + proto_initialize_all_prefixes(); + + if (argc == 2) + proto_registrar_dump_fields(); + else { + if (strcmp(argv[2], "column-formats") == 0) + column_dump_column_formats(); + else if (strcmp(argv[2], "currentprefs") == 0) { + epan_load_settings(); + write_prefs(NULL); + } + else if (strcmp(argv[2], "decodes") == 0) + dissector_dump_decodes(); + else if (strcmp(argv[2], "defaultprefs") == 0) + write_prefs(NULL); + else if (strcmp(argv[2], "dissector-tables") == 0) + dissector_dump_dissector_tables(); + else if (strcmp(argv[2], "elastic-mapping") == 0) + proto_registrar_dump_elastic(elastic_mapping_filter); + else if (strcmp(argv[2], "fieldcount") == 0) { + /* return value for the test suite */ + exit_status = proto_registrar_dump_fieldcount(); + goto clean_exit; + } else if (strcmp(argv[2], "fields") == 0) + proto_registrar_dump_fields(); + else if (strcmp(argv[2], "folders") == 0) { + epan_load_settings(); + about_folders(); + } else if (strcmp(argv[2], "ftypes") == 0) + proto_registrar_dump_ftypes(); + else if (strcmp(argv[2], "heuristic-decodes") == 0) + dissector_dump_heur_decodes(); + else if (strcmp(argv[2], "plugins") == 0) { #ifdef HAVE_PLUGINS - plugins_dump_all(); + plugins_dump_all(); #endif #ifdef HAVE_LUA - wslua_plugins_dump_all(); + wslua_plugins_dump_all(); #endif - extcap_dump_all(); - } - else if (strcmp(argv[2], "protocols") == 0) - proto_registrar_dump_protocols(); - else if (strcmp(argv[2], "values") == 0) - proto_registrar_dump_values(); - else if (strcmp(argv[2], "help") == 0) - glossary_option_help(); - /* These are supported only for backwards compatibility and may or may not work - * for a given user in a given directory on a given operating system with a given - * command-line interpreter. - */ - else if (strcmp(argv[2], "?") == 0) - glossary_option_help(); - else if (strcmp(argv[2], "-?") == 0) - glossary_option_help(); - else { - cmdarg_err("Invalid \"%s\" option for -G flag, enter -G help for more help.", argv[2]); - exit_status = INVALID_OPTION; + extcap_dump_all(); + } + else if (strcmp(argv[2], "protocols") == 0) + proto_registrar_dump_protocols(); + else if (strcmp(argv[2], "values") == 0) + proto_registrar_dump_values(); + else if (strcmp(argv[2], "help") == 0) + glossary_option_help(); + /* These are supported only for backwards compatibility and may or may not work + * for a given user in a given directory on a given operating system with a given + * command-line interpreter. + */ + else if (strcmp(argv[2], "?") == 0) + glossary_option_help(); + else if (strcmp(argv[2], "-?") == 0) + glossary_option_help(); + else { + cmdarg_err("Invalid \"%s\" option for -G flag, enter -G help for more help.", argv[2]); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } + exit_status = EXIT_SUCCESS; goto clean_exit; - } } - exit_status = EXIT_SUCCESS; - goto clean_exit; - } - ws_debug("tshark reading settings"); + ws_debug("tshark reading settings"); - /* Load libwireshark settings from the current profile. */ - prefs_p = epan_load_settings(); - prefs_loaded = TRUE; + /* Load libwireshark settings from the current profile. */ + prefs_p = epan_load_settings(); + prefs_loaded = TRUE; - read_filter_list(CFILTER_LIST); + read_filter_list(CFILTER_LIST); - cap_file_init(&cfile); + cap_file_init(&cfile); - /* Print format defaults to this. */ - print_format = PR_FMT_TEXT; - delimiter_char = " "; + /* Print format defaults to this. */ + print_format = PR_FMT_TEXT; + delimiter_char = " "; - output_fields = output_fields_new(); + output_fields = output_fields_new(); - /* - * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1. - * - * Also reset ws_opterr to 1, so that error messages are printed by - * getopt_long(). - */ - ws_optreset = 1; - ws_optind = 1; - ws_opterr = 1; + /* + * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1. + * + * Also reset ws_opterr to 1, so that error messages are printed by + * getopt_long(). + */ + ws_optreset = 1; + ws_optind = 1; + ws_opterr = 1; - /* Now get our args */ - while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { - switch (opt) { - case '2': /* Perform two pass analysis */ - if(epan_auto_reset){ - cmdarg_err("-2 does not support auto session reset."); - arg_error=TRUE; - } - perform_two_pass_analysis = TRUE; - break; - case 'M': - if(perform_two_pass_analysis){ - cmdarg_err("-M does not support two pass analysis."); - arg_error=TRUE; - } - epan_auto_reset_count = get_positive_int(ws_optarg, "epan reset count"); - epan_auto_reset = TRUE; - break; - case 'a': /* autostop criteria */ - case 'b': /* Ringbuffer option */ - case 'f': /* capture filter */ - case 'g': /* enable group read access on file(s) */ - case 'i': /* Use interface x */ - case LONGOPT_SET_TSTAMP_TYPE: /* Set capture timestamp type */ - case 'p': /* Don't capture in promiscuous mode */ + /* Now get our args */ + while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { + switch (opt) { + case '2': /* Perform two pass analysis */ + if(epan_auto_reset){ + cmdarg_err("-2 does not support auto session reset."); + arg_error=TRUE; + } + perform_two_pass_analysis = TRUE; + break; + case 'M': + if(perform_two_pass_analysis){ + cmdarg_err("-M does not support two pass analysis."); + arg_error=TRUE; + } + epan_auto_reset_count = get_positive_int(ws_optarg, "epan reset count"); + epan_auto_reset = TRUE; + break; + case 'a': /* autostop criteria */ + case 'b': /* Ringbuffer option */ + case 'f': /* capture filter */ + case 'g': /* enable group read access on file(s) */ + case 'i': /* Use interface x */ + case LONGOPT_SET_TSTAMP_TYPE: /* Set capture timestamp type */ + case 'p': /* Don't capture in promiscuous mode */ #ifdef HAVE_PCAP_REMOTE - case 'A': /* Authentication */ + case 'A': /* Authentication */ #endif #ifdef HAVE_PCAP_CREATE - case 'I': /* Capture in monitor mode, if available */ + case 'I': /* Capture in monitor mode, if available */ #endif - case 's': /* Set the snapshot (capture) length */ - case 'y': /* Set the pcap data link type */ + case 's': /* Set the snapshot (capture) length */ + case 'y': /* Set the pcap data link type */ #ifdef CAN_SET_CAPTURE_BUFFER_SIZE - case 'B': /* Buffer size */ + case 'B': /* Buffer size */ #endif - case LONGOPT_COMPRESS_TYPE: /* compress type */ - case LONGOPT_CAPTURE_TMPDIR: /* capture temp directory */ - /* These are options only for packet capture. */ + case LONGOPT_COMPRESS_TYPE: /* compress type */ + case LONGOPT_CAPTURE_TMPDIR: /* capture temp directory */ + /* These are options only for packet capture. */ #ifdef HAVE_LIBPCAP - exit_status = capture_opts_add_opt(&global_capture_opts, opt, ws_optarg); - if (exit_status != 0) { - goto clean_exit; - } + exit_status = capture_opts_add_opt(&global_capture_opts, opt, ws_optarg); + if (exit_status != 0) { + goto clean_exit; + } #else - capture_option_specified = TRUE; - arg_error = TRUE; + capture_option_specified = TRUE; + arg_error = TRUE; #endif - break; - case 'c': /* Stop after x packets */ + break; + case 'c': /* Stop after x packets */ #ifdef HAVE_LIBPCAP - exit_status = capture_opts_add_opt(&global_capture_opts, opt, ws_optarg); - if (exit_status != 0) { - goto clean_exit; - } + exit_status = capture_opts_add_opt(&global_capture_opts, opt, ws_optarg); + if (exit_status != 0) { + goto clean_exit; + } #else - max_packet_count = get_positive_int(ws_optarg, "packet count"); + max_packet_count = get_positive_int(ws_optarg, "packet count"); #endif - break; - case 'w': /* Write to file x */ - output_file_name = g_strdup(ws_optarg); + break; + case 'w': /* Write to file x */ + output_file_name = g_strdup(ws_optarg); #ifdef HAVE_LIBPCAP - exit_status = capture_opts_add_opt(&global_capture_opts, opt, ws_optarg); - if (exit_status != 0) { - goto clean_exit; - } + exit_status = capture_opts_add_opt(&global_capture_opts, opt, ws_optarg); + if (exit_status != 0) { + goto clean_exit; + } #endif - break; - case 'C': - /* already processed; just ignore it now */ - break; - case 'D': /* Print a list of capture devices and exit */ + break; + case 'C': + /* already processed; just ignore it now */ + break; + case 'D': /* Print a list of capture devices and exit */ #ifdef HAVE_LIBPCAP - if_list = capture_interface_list(&err, &err_str,NULL); - if (if_list == NULL) { - if (err == 0) - cmdarg_err("There are no interfaces on which a capture can be done"); - else { - cmdarg_err("%s", err_str); - g_free(err_str); + if_list = capture_interface_list(&err, &err_str,NULL); + if (if_list == NULL) { + if (err == 0) + cmdarg_err("There are no interfaces on which a capture can be done"); + else { + cmdarg_err("%s", err_str); + g_free(err_str); + } + exit_status = INVALID_INTERFACE; + goto clean_exit; + } + capture_opts_print_interfaces(if_list); + free_interface_list(if_list); + exit_status = EXIT_SUCCESS; + goto clean_exit; +#else + capture_option_specified = TRUE; + arg_error = TRUE; +#endif + break; + case 'e': + /* Field entry */ + output_fields_add(output_fields, ws_optarg); + break; + case 'E': + /* Field option */ + if (!output_fields_set_option(output_fields, ws_optarg)) { + cmdarg_err("\"%s\" is not a valid field output option=value pair.", ws_optarg); + output_fields_list_options(stderr); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case 'F': + out_file_type = wtap_name_to_file_type_subtype(ws_optarg); + if (out_file_type < 0) { + cmdarg_err("\"%s\" isn't a valid capture file type", ws_optarg); + list_capture_types(); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case 'j': + if (protocolfilter) { + cmdarg_err("-j or -J was already specified! Overwriting previous protocol filter"); + } + protocolfilter = wmem_strsplit(wmem_epan_scope(), ws_optarg, " ", -1); + break; + case 'J': + if (protocolfilter) { + cmdarg_err("-j or -J was already specified! Overwriting previous protocol filter"); + } + protocolfilter_flags = PF_INCLUDE_CHILDREN; + protocolfilter = wmem_strsplit(wmem_epan_scope(), ws_optarg, " ", -1); + break; + case 'W': /* Select extra information to save in our capture file */ + /* This is patterned after the -N flag which may not be the best idea. */ + if (strchr(ws_optarg, 'n')) { + out_file_name_res = TRUE; + } else { + cmdarg_err("Invalid -W argument \"%s\"; it must be one of:", ws_optarg); + cmdarg_err_cont("\t'n' write network address resolution information (pcapng only)"); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case 'H': /* Read address to name mappings from a hosts file */ + if (! add_hosts_file(ws_optarg)) + { + cmdarg_err("Can't read host entries from \"%s\"", ws_optarg); + exit_status = INVALID_OPTION; + goto clean_exit; + } + out_file_name_res = TRUE; + break; + + case 'h': /* Print help and exit */ + show_help_header("Dump and analyze network traffic."); + print_usage(stdout); + exit_status = EXIT_SUCCESS; + goto clean_exit; + break; + case 'l': /* "Line-buffer" standard output */ + /* The ANSI C standard does not appear to *require* that a line-buffered + stream be flushed to the host environment whenever a newline is + written, it just says that, on such a stream, characters "are + intended to be transmitted to or from the host environment as a + block when a new-line character is encountered". + + The Visual C++ 6.0 C implementation doesn't do what is intended; + even if you set a stream to be line-buffered, it still doesn't + flush the buffer at the end of every line. + + The whole reason for the "-l" flag in either tcpdump or TShark + is to allow the output of a live capture to be piped to a program + or script and to have that script see the information for the + packet as soon as it's printed, rather than having to wait until + a standard I/O buffer fills up. + + So, if the "-l" flag is specified, we flush the standard output + at the end of a packet. This will do the right thing if we're + printing packet summary lines, and, as we print the entire protocol + tree for a single packet without waiting for anything to happen, + it should be as good as line-buffered mode if we're printing + protocol trees - arguably even better, as it may do fewer + writes. */ + line_buffered = TRUE; + break; + case 'L': /* Print list of link-layer types and exit */ +#ifdef HAVE_LIBPCAP + caps_queries |= CAPS_QUERY_LINK_TYPES; +#else + capture_option_specified = TRUE; + arg_error = TRUE; +#endif + break; + case LONGOPT_LIST_TSTAMP_TYPES: /* List possible timestamp types */ +#ifdef HAVE_LIBPCAP + caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES; +#else + capture_option_specified = TRUE; + arg_error = TRUE; +#endif + break; + case 'o': /* Override preference from command line */ + { + char *errmsg = NULL; + + switch (prefs_set_pref(ws_optarg, &errmsg)) { + + case PREFS_SET_OK: + break; + + case PREFS_SET_SYNTAX_ERR: + cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg, + errmsg ? ": " : "", errmsg ? errmsg : ""); + g_free(errmsg); + exit_status = INVALID_OPTION; + goto clean_exit; + break; + + case PREFS_SET_NO_SUCH_PREF: + cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg); + exit_status = INVALID_OPTION; + goto clean_exit; + break; + + case PREFS_SET_OBSOLETE: + cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg); + exit_status = INVALID_OPTION; + goto clean_exit; + break; + } + break; + } + case 'q': /* Quiet */ + quiet = TRUE; + break; + case 'Q': /* Really quiet */ + quiet = TRUE; + really_quiet = TRUE; + break; + case 'r': + /* already processed; just ignore it now */ + break; + case 'R': /* Read file filter */ + rfilter = ws_optarg; + break; + case 'P': + /* already processed; just ignore it now */ + break; + case 'S': /* Set the line Separator to be printed between packets */ + separator = ws_optarg; + break; + case 'T': /* printing Type */ + /* output_action has been already set. It means multiple -T. */ + if (output_action > WRITE_NONE) { + cmdarg_err("Multiple -T parameters are unsupported"); + exit_status = INVALID_OPTION; + goto clean_exit; + } + print_packet_info = TRUE; + if (strcmp(ws_optarg, "text") == 0) { + output_action = WRITE_TEXT; + print_format = PR_FMT_TEXT; + } else if (strcmp(ws_optarg, "tabs") == 0) { + output_action = WRITE_TEXT; + print_format = PR_FMT_TEXT; + delimiter_char = "\t"; + } else if (strcmp(ws_optarg, "ps") == 0) { + output_action = WRITE_TEXT; + print_format = PR_FMT_PS; + } else if (strcmp(ws_optarg, "pdml") == 0) { + output_action = WRITE_XML; + print_details = TRUE; /* Need details */ + print_summary = FALSE; /* Don't allow summary */ + } else if (strcmp(ws_optarg, "psml") == 0) { + output_action = WRITE_XML; + print_details = FALSE; /* Don't allow details */ + print_summary = TRUE; /* Need summary */ + } else if (strcmp(ws_optarg, "fields") == 0) { + output_action = WRITE_FIELDS; + print_details = TRUE; /* Need full tree info */ + print_summary = FALSE; /* Don't allow summary */ + } else if (strcmp(ws_optarg, "json") == 0) { + output_action = WRITE_JSON; + print_details = TRUE; /* Need details */ + print_summary = FALSE; /* Don't allow summary */ + } else if (strcmp(ws_optarg, "ek") == 0) { + output_action = WRITE_EK; + if (!print_summary) + print_details = TRUE; + } else if (strcmp(ws_optarg, "jsonraw") == 0) { + output_action = WRITE_JSON_RAW; + print_details = TRUE; /* Need details */ + print_summary = FALSE; /* Don't allow summary */ + } + else { + cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", ws_optarg); /* x */ + cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n" + "\t specified by the -E option.\n" + "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n" + "\t details of a decoded packet. This information is equivalent to\n" + "\t the packet details printed with the -V flag.\n" + "\t\"ps\" PostScript for a human-readable one-line summary of each of\n" + "\t the packets, or a multi-line view of the details of each of\n" + "\t the packets, depending on whether the -V flag was specified.\n" + "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n" + "\t summary information of a decoded packet. This information is\n" + "\t equivalent to the information shown in the one-line summary\n" + "\t printed by default.\n" + "\t\"json\" Packet Summary, an JSON-based format for the details\n" + "\t summary information of a decoded packet. This information is \n" + "\t equivalent to the packet details printed with the -V flag.\n" + "\t\"jsonraw\" Packet Details, a JSON-based format for machine parsing\n" + "\t including only raw hex decoded fields (same as -T json -x but\n" + "\t without text decoding, only raw fields included). \n" + "\t\"ek\" Packet Details, an EK JSON-based format for the bulk insert \n" + "\t into elastic search cluster. This information is \n" + "\t equivalent to the packet details printed with the -V flag.\n" + "\t\"text\" Text of a human-readable one-line summary of each of the\n" + "\t packets, or a multi-line view of the details of each of the\n" + "\t packets, depending on whether the -V flag was specified.\n" + "\t This is the default.\n" + "\t\"tabs\" Similar to the text report except that each column of the\n" + "\t human-readable one-line summary is delimited with an ASCII\n" + "\t horizontal tab character."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case 'U': /* Export PDUs to file */ + if (strcmp(ws_optarg, "") == 0 || strcmp(ws_optarg, "?") == 0) { + list_export_pdu_taps(); + exit_status = INVALID_OPTION; + goto clean_exit; + } + pdu_export_arg = g_strdup(ws_optarg); + break; + case 'v': /* Show version and exit */ + show_version(); + /* We don't really have to cleanup here, but it's a convenient way to test + * start-up and shut-down of the epan library without any UI-specific + * cruft getting in the way. Makes the results of running + * $ ./tools/valgrind-wireshark -n + * much more useful. */ + epan_cleanup(); + extcap_cleanup(); + exit_status = EXIT_SUCCESS; + goto clean_exit; + case 'O': /* Only output these protocols */ + /* already processed; just ignore it now */ + break; + case 'V': /* Verbose */ + /* already processed; just ignore it now */ + break; + case 'x': /* Print packet data in hex (and ASCII) */ + /* already processed; just ignore it now */ + break; + case 'X': + /* already processed; just ignore it now */ + break; + case 'Y': + dfilter = g_strdup(ws_optarg); + break; + case 'z': + /* We won't call the init function for the stat this soon + as it would disallow MATE's fields (which are registered + by the preferences set callback) from being used as + part of a tap filter. Instead, we just add the argument + to a list of stat arguments. */ + if (strcmp("help", ws_optarg) == 0) { + fprintf(stderr, "tshark: The available statistics for the \"-z\" option are:\n"); + list_stat_cmd_args(); + exit_status = EXIT_SUCCESS; + goto clean_exit; + } + if (!process_stat_cmd_arg(ws_optarg)) { + cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", ws_optarg); + list_stat_cmd_args(); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case 'd': /* Decode as rule */ + case 'K': /* Kerberos keytab file */ + case 'n': /* No name resolution */ + case 'N': /* Select what types of addresses/port #s to resolve */ + case 't': /* Time stamp type */ + case 'u': /* Seconds type */ + case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */ + case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */ + case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */ + case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */ + if (!dissect_opts_handle_opt(opt, ws_optarg)) { + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case LONGOPT_EXPORT_OBJECTS: /* --export-objects */ + if (strcmp("help", ws_optarg) == 0) { + fprintf(stderr, "tshark: The available export object types for the \"--export-objects\" option are:\n"); + eo_list_object_types(); + exit_status = EXIT_SUCCESS; + goto clean_exit; + } + if (!eo_tap_opt_add(ws_optarg)) { + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + case LONGOPT_EXPORT_TLS_SESSION_KEYS: /* --export-tls-session-keys */ + tls_session_keys_file = ws_optarg; + break; + case LONGOPT_COLOR: /* print in color where appropriate */ + dissect_color = TRUE; + break; + case LONGOPT_NO_DUPLICATE_KEYS: + no_duplicate_keys = TRUE; + node_children_grouper = proto_node_group_children_by_json_key; + break; + case LONGOPT_CAPTURE_COMMENT: /* capture comment */ + if (capture_comments == NULL) { + capture_comments = g_ptr_array_new_with_free_func(g_free); + } + g_ptr_array_add(capture_comments, g_strdup(ws_optarg)); + break; + case LONGOPT_HEXDUMP: + print_hex = TRUE; + print_packet_info = TRUE; + if (strcmp(ws_optarg, "all") == 0) + hexdump_source_option = HEXDUMP_SOURCE_MULTI; + else if (strcmp(ws_optarg, "frames") == 0) + hexdump_source_option = HEXDUMP_SOURCE_PRIMARY; + else if (strcmp(ws_optarg, "ascii") == 0) + hexdump_ascii_option = HEXDUMP_ASCII_INCLUDE; + else if (strcmp(ws_optarg, "delimit") == 0) + hexdump_ascii_option = HEXDUMP_ASCII_DELIMIT; + else if (strcmp(ws_optarg, "noascii") == 0) + hexdump_ascii_option = HEXDUMP_ASCII_EXCLUDE; + else if (strcmp("help", ws_optarg) == 0) { + hexdump_option_help(stdout); + exit_status = EXIT_SUCCESS; + goto clean_exit; + } else { + fprintf(stderr, "tshark: \"%s\" is an invalid value for --hexdump \n", ws_optarg); + fprintf(stderr, "For valid values enter: tshark --hexdump help\n"); + exit_status = INVALID_OPTION; + goto clean_exit; + } + break; + default: + case '?': /* Bad flag - print usage message */ + switch(ws_optopt) { + case 'F': + list_capture_types(); + break; + default: + print_usage(stderr); + } + exit_status = INVALID_OPTION; + goto clean_exit; + break; } - exit_status = INVALID_INTERFACE; - goto clean_exit; - } - capture_opts_print_interfaces(if_list); - free_interface_list(if_list); - exit_status = EXIT_SUCCESS; - goto clean_exit; -#else - capture_option_specified = TRUE; - arg_error = TRUE; -#endif - break; - case 'e': - /* Field entry */ - output_fields_add(output_fields, ws_optarg); - break; - case 'E': - /* Field option */ - if (!output_fields_set_option(output_fields, ws_optarg)) { - cmdarg_err("\"%s\" is not a valid field output option=value pair.", ws_optarg); - output_fields_list_options(stderr); - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - case 'F': - out_file_type = wtap_name_to_file_type_subtype(ws_optarg); - if (out_file_type < 0) { - cmdarg_err("\"%s\" isn't a valid capture file type", ws_optarg); - list_capture_types(); - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - case 'j': - if (protocolfilter) { - cmdarg_err("-j or -J was already specified! Overwriting previous protocol filter"); - } - protocolfilter = wmem_strsplit(wmem_epan_scope(), ws_optarg, " ", -1); - break; - case 'J': - if (protocolfilter) { - cmdarg_err("-j or -J was already specified! Overwriting previous protocol filter"); - } - protocolfilter_flags = PF_INCLUDE_CHILDREN; - protocolfilter = wmem_strsplit(wmem_epan_scope(), ws_optarg, " ", -1); - break; - case 'W': /* Select extra information to save in our capture file */ - /* This is patterned after the -N flag which may not be the best idea. */ - if (strchr(ws_optarg, 'n')) { - out_file_name_res = TRUE; - } else { - cmdarg_err("Invalid -W argument \"%s\"; it must be one of:", ws_optarg); - cmdarg_err_cont("\t'n' write network address resolution information (pcapng only)"); - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - case 'H': /* Read address to name mappings from a hosts file */ - if (! add_hosts_file(ws_optarg)) - { - cmdarg_err("Can't read host entries from \"%s\"", ws_optarg); - exit_status = INVALID_OPTION; - goto clean_exit; - } - out_file_name_res = TRUE; - break; - - case 'h': /* Print help and exit */ - show_help_header("Dump and analyze network traffic."); - print_usage(stdout); - exit_status = EXIT_SUCCESS; - goto clean_exit; - break; - case 'l': /* "Line-buffer" standard output */ - /* The ANSI C standard does not appear to *require* that a line-buffered - stream be flushed to the host environment whenever a newline is - written, it just says that, on such a stream, characters "are - intended to be transmitted to or from the host environment as a - block when a new-line character is encountered". - - The Visual C++ 6.0 C implementation doesn't do what is intended; - even if you set a stream to be line-buffered, it still doesn't - flush the buffer at the end of every line. - - The whole reason for the "-l" flag in either tcpdump or TShark - is to allow the output of a live capture to be piped to a program - or script and to have that script see the information for the - packet as soon as it's printed, rather than having to wait until - a standard I/O buffer fills up. - - So, if the "-l" flag is specified, we flush the standard output - at the end of a packet. This will do the right thing if we're - printing packet summary lines, and, as we print the entire protocol - tree for a single packet without waiting for anything to happen, - it should be as good as line-buffered mode if we're printing - protocol trees - arguably even better, as it may do fewer - writes. */ - line_buffered = TRUE; - break; - case 'L': /* Print list of link-layer types and exit */ -#ifdef HAVE_LIBPCAP - caps_queries |= CAPS_QUERY_LINK_TYPES; -#else - capture_option_specified = TRUE; - arg_error = TRUE; -#endif - break; - case LONGOPT_LIST_TSTAMP_TYPES: /* List possible timestamp types */ -#ifdef HAVE_LIBPCAP - caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES; -#else - capture_option_specified = TRUE; - arg_error = TRUE; -#endif - break; - case 'o': /* Override preference from command line */ - { - char *errmsg = NULL; - - switch (prefs_set_pref(ws_optarg, &errmsg)) { - - case PREFS_SET_OK: - break; - - case PREFS_SET_SYNTAX_ERR: - cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg, - errmsg ? ": " : "", errmsg ? errmsg : ""); - g_free(errmsg); - exit_status = INVALID_OPTION; - goto clean_exit; - break; - - case PREFS_SET_NO_SUCH_PREF: - cmdarg_err("-o flag \"%s\" specifies unknown preference", ws_optarg); - exit_status = INVALID_OPTION; - goto clean_exit; - break; - - case PREFS_SET_OBSOLETE: - cmdarg_err("-o flag \"%s\" specifies obsolete preference", ws_optarg); - exit_status = INVALID_OPTION; - goto clean_exit; - break; - } - break; } - case 'q': /* Quiet */ - quiet = TRUE; - break; - case 'Q': /* Really quiet */ - quiet = TRUE; - really_quiet = TRUE; - break; - case 'r': - /* already processed; just ignore it now */ - break; - case 'R': /* Read file filter */ - rfilter = ws_optarg; - break; - case 'P': - /* already processed; just ignore it now */ - break; - case 'S': /* Set the line Separator to be printed between packets */ - separator = ws_optarg; - break; - case 'T': /* printing Type */ - /* output_action has been already set. It means multiple -T. */ - if (output_action > WRITE_NONE) { - cmdarg_err("Multiple -T parameters are unsupported"); + + /* set the default output action to TEXT */ + if (output_action == WRITE_NONE) + output_action = WRITE_TEXT; + + /* set the default file type to pcapng */ + if (out_file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) + out_file_type = wtap_pcapng_file_type_subtype(); + + /* + * Print packet summary information is the default if neither -V or -x + * were specified. Note that this is new behavior, which allows for the + * possibility of printing only hex/ascii output without necessarily + * requiring that either the summary or details be printed too. + */ + if (!print_summary && !print_details && !print_hex) + print_summary = TRUE; + + if (no_duplicate_keys && output_action != WRITE_JSON && output_action != WRITE_JSON_RAW) { + cmdarg_err("--no-duplicate-keys can only be used with \"-T json\" and \"-T jsonraw\""); exit_status = INVALID_OPTION; goto clean_exit; - } - print_packet_info = TRUE; - if (strcmp(ws_optarg, "text") == 0) { - output_action = WRITE_TEXT; - print_format = PR_FMT_TEXT; - } else if (strcmp(ws_optarg, "tabs") == 0) { - output_action = WRITE_TEXT; - print_format = PR_FMT_TEXT; - delimiter_char = "\t"; - } else if (strcmp(ws_optarg, "ps") == 0) { - output_action = WRITE_TEXT; - print_format = PR_FMT_PS; - } else if (strcmp(ws_optarg, "pdml") == 0) { - output_action = WRITE_XML; - print_details = TRUE; /* Need details */ - print_summary = FALSE; /* Don't allow summary */ - } else if (strcmp(ws_optarg, "psml") == 0) { - output_action = WRITE_XML; - print_details = FALSE; /* Don't allow details */ - print_summary = TRUE; /* Need summary */ - } else if (strcmp(ws_optarg, "fields") == 0) { - output_action = WRITE_FIELDS; - print_details = TRUE; /* Need full tree info */ - print_summary = FALSE; /* Don't allow summary */ - } else if (strcmp(ws_optarg, "json") == 0) { - output_action = WRITE_JSON; - print_details = TRUE; /* Need details */ - print_summary = FALSE; /* Don't allow summary */ - } else if (strcmp(ws_optarg, "ek") == 0) { - output_action = WRITE_EK; - if (!print_summary) - print_details = TRUE; - } else if (strcmp(ws_optarg, "jsonraw") == 0) { - output_action = WRITE_JSON_RAW; - print_details = TRUE; /* Need details */ - print_summary = FALSE; /* Don't allow summary */ - } - else { - cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", ws_optarg); /* x */ - cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n" - "\t specified by the -E option.\n" - "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n" - "\t details of a decoded packet. This information is equivalent to\n" - "\t the packet details printed with the -V flag.\n" - "\t\"ps\" PostScript for a human-readable one-line summary of each of\n" - "\t the packets, or a multi-line view of the details of each of\n" - "\t the packets, depending on whether the -V flag was specified.\n" - "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n" - "\t summary information of a decoded packet. This information is\n" - "\t equivalent to the information shown in the one-line summary\n" - "\t printed by default.\n" - "\t\"json\" Packet Summary, an JSON-based format for the details\n" - "\t summary information of a decoded packet. This information is \n" - "\t equivalent to the packet details printed with the -V flag.\n" - "\t\"jsonraw\" Packet Details, a JSON-based format for machine parsing\n" - "\t including only raw hex decoded fields (same as -T json -x but\n" - "\t without text decoding, only raw fields included). \n" - "\t\"ek\" Packet Details, an EK JSON-based format for the bulk insert \n" - "\t into elastic search cluster. This information is \n" - "\t equivalent to the packet details printed with the -V flag.\n" - "\t\"text\" Text of a human-readable one-line summary of each of the\n" - "\t packets, or a multi-line view of the details of each of the\n" - "\t packets, depending on whether the -V flag was specified.\n" - "\t This is the default.\n" - "\t\"tabs\" Similar to the text report except that each column of the\n" - "\t human-readable one-line summary is delimited with an ASCII\n" - "\t horizontal tab character."); + } + + /* If we specified output fields, but not the output field type... */ + if ((WRITE_FIELDS != output_action && WRITE_XML != output_action && WRITE_JSON != output_action && WRITE_EK != output_action) && 0 != output_fields_num_fields(output_fields)) { + cmdarg_err("Output fields were specified with \"-e\", " + "but \"-Tek, -Tfields, -Tjson or -Tpdml\" was not specified."); exit_status = INVALID_OPTION; goto clean_exit; - } - break; - case 'U': /* Export PDUs to file */ - if (strcmp(ws_optarg, "") == 0 || strcmp(ws_optarg, "?") == 0) { - list_export_pdu_taps(); + } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) { + cmdarg_err("\"-Tfields\" was specified, but no fields were " + "specified with \"-e\"."); + + exit_status = INVALID_OPTION; + goto clean_exit; + } + + if (dissect_color) { + if (!color_filters_init(&err_msg, NULL)) { + fprintf(stderr, "%s\n", err_msg); + g_free(err_msg); + } + } + + /* If no capture filter or display filter has been specified, and there are + still command-line arguments, treat them as the tokens of a capture + filter (if no "-r" flag was specified) or a display filter (if a "-r" + flag was specified. */ + if (ws_optind < argc) { + if (cf_name != NULL) { + if (dfilter != NULL) { + cmdarg_err("Display filters were specified both with \"-Y\" " + "and with additional command-line arguments."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + dfilter = get_args_as_string(argc, argv, ws_optind); + } else { +#ifdef HAVE_LIBPCAP + guint i; + + if (global_capture_opts.default_options.cfilter) { + cmdarg_err("A default capture filter was specified both with \"-f\"" + " and with additional command-line arguments."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + interface_options *interface_opts; + interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i); + if (interface_opts->cfilter == NULL) { + interface_opts->cfilter = get_args_as_string(argc, argv, ws_optind); + } else { + cmdarg_err("A capture filter was specified both with \"-f\"" + " and with additional command-line arguments."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } + global_capture_opts.default_options.cfilter = get_args_as_string(argc, argv, ws_optind); +#else + capture_option_specified = TRUE; +#endif + } + } + + if (!output_file_name) { + /* We're not saving the capture to a file; if "-q" wasn't specified, + we should print packet information */ + if (!quiet) + print_packet_info = TRUE; + } else { + const char *save_file = output_file_name; + /* We're saving to a file; if we're writing to the standard output. + and we'll also be writing dissected packets to the standard + output, reject the request. At best, we could redirect that + to the standard error; we *can't* write both to the standard + output and have either of them be useful. */ + if (strcmp(save_file, "-") == 0 && print_packet_info) { + cmdarg_err("You can't write both raw packet data and dissected packets" + " to the standard output."); exit_status = INVALID_OPTION; goto clean_exit; } - pdu_export_arg = g_strdup(ws_optarg); - break; - case 'v': /* Show version and exit */ - show_version(); - /* We don't really have to cleanup here, but it's a convenient way to test - * start-up and shut-down of the epan library without any UI-specific - * cruft getting in the way. Makes the results of running - * $ ./tools/valgrind-wireshark -n - * much more useful. */ - epan_cleanup(); - extcap_cleanup(); - exit_status = EXIT_SUCCESS; - goto clean_exit; - case 'O': /* Only output these protocols */ - /* already processed; just ignore it now */ - break; - case 'V': /* Verbose */ - /* already processed; just ignore it now */ - break; - case 'x': /* Print packet data in hex (and ASCII) */ - /* already processed; just ignore it now */ - break; - case 'X': - /* already processed; just ignore it now */ - break; - case 'Y': - dfilter = g_strdup(ws_optarg); - break; - case 'z': - /* We won't call the init function for the stat this soon - as it would disallow MATE's fields (which are registered - by the preferences set callback) from being used as - part of a tap filter. Instead, we just add the argument - to a list of stat arguments. */ - if (strcmp("help", ws_optarg) == 0) { - fprintf(stderr, "tshark: The available statistics for the \"-z\" option are:\n"); - list_stat_cmd_args(); - exit_status = EXIT_SUCCESS; - goto clean_exit; - } - if (!process_stat_cmd_arg(ws_optarg)) { - cmdarg_err("Invalid -z argument \"%s\"; it must be one of:", ws_optarg); - list_stat_cmd_args(); - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - case 'd': /* Decode as rule */ - case 'K': /* Kerberos keytab file */ - case 'n': /* No name resolution */ - case 'N': /* Select what types of addresses/port #s to resolve */ - case 't': /* Time stamp type */ - case 'u': /* Seconds type */ - case LONGOPT_DISABLE_PROTOCOL: /* disable dissection of protocol */ - case LONGOPT_ENABLE_HEURISTIC: /* enable heuristic dissection of protocol */ - case LONGOPT_DISABLE_HEURISTIC: /* disable heuristic dissection of protocol */ - case LONGOPT_ENABLE_PROTOCOL: /* enable dissection of protocol (that is disabled by default) */ - if (!dissect_opts_handle_opt(opt, ws_optarg)) { - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - case LONGOPT_EXPORT_OBJECTS: /* --export-objects */ - if (strcmp("help", ws_optarg) == 0) { - fprintf(stderr, "tshark: The available export object types for the \"--export-objects\" option are:\n"); - eo_list_object_types(); - exit_status = EXIT_SUCCESS; - goto clean_exit; - } - if (!eo_tap_opt_add(ws_optarg)) { - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - case LONGOPT_EXPORT_TLS_SESSION_KEYS: /* --export-tls-session-keys */ - tls_session_keys_file = ws_optarg; - break; - case LONGOPT_COLOR: /* print in color where appropriate */ - dissect_color = TRUE; - break; - case LONGOPT_NO_DUPLICATE_KEYS: - no_duplicate_keys = TRUE; - node_children_grouper = proto_node_group_children_by_json_key; - break; - case LONGOPT_CAPTURE_COMMENT: /* capture comment */ - if (capture_comments == NULL) { - capture_comments = g_ptr_array_new_with_free_func(g_free); - } - g_ptr_array_add(capture_comments, g_strdup(ws_optarg)); - break; - case LONGOPT_HEXDUMP: - print_hex = TRUE; - print_packet_info = TRUE; - if (strcmp(ws_optarg, "all") == 0) - hexdump_source_option = HEXDUMP_SOURCE_MULTI; - else if (strcmp(ws_optarg, "frames") == 0) - hexdump_source_option = HEXDUMP_SOURCE_PRIMARY; - else if (strcmp(ws_optarg, "ascii") == 0) - hexdump_ascii_option = HEXDUMP_ASCII_INCLUDE; - else if (strcmp(ws_optarg, "delimit") == 0) - hexdump_ascii_option = HEXDUMP_ASCII_DELIMIT; - else if (strcmp(ws_optarg, "noascii") == 0) - hexdump_ascii_option = HEXDUMP_ASCII_EXCLUDE; - else if (strcmp("help", ws_optarg) == 0) { - hexdump_option_help(stdout); - exit_status = EXIT_SUCCESS; - goto clean_exit; - } else { - fprintf(stderr, "tshark: \"%s\" is an invalid value for --hexdump \n", ws_optarg); - fprintf(stderr, "For valid values enter: tshark --hexdump help\n"); - exit_status = INVALID_OPTION; - goto clean_exit; - } - break; - default: - case '?': /* Bad flag - print usage message */ - switch(ws_optopt) { - case 'F': - list_capture_types(); - break; - default: - print_usage(stderr); - } - exit_status = INVALID_OPTION; - goto clean_exit; - break; } - } - - /* set the default output action to TEXT */ - if (output_action == WRITE_NONE) - output_action = WRITE_TEXT; - - /* set the default file type to pcapng */ - if (out_file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) - out_file_type = wtap_pcapng_file_type_subtype(); - - /* - * Print packet summary information is the default if neither -V or -x - * were specified. Note that this is new behavior, which allows for the - * possibility of printing only hex/ascii output without necessarily - * requiring that either the summary or details be printed too. - */ - if (!print_summary && !print_details && !print_hex) - print_summary = TRUE; - - if (no_duplicate_keys && output_action != WRITE_JSON && output_action != WRITE_JSON_RAW) { - cmdarg_err("--no-duplicate-keys can only be used with \"-T json\" and \"-T jsonraw\""); - exit_status = INVALID_OPTION; - goto clean_exit; - } - - /* If we specified output fields, but not the output field type... */ - if ((WRITE_FIELDS != output_action && WRITE_XML != output_action && WRITE_JSON != output_action && WRITE_EK != output_action) && 0 != output_fields_num_fields(output_fields)) { - cmdarg_err("Output fields were specified with \"-e\", " - "but \"-Tek, -Tfields, -Tjson or -Tpdml\" was not specified."); - exit_status = INVALID_OPTION; - goto clean_exit; - } else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) { - cmdarg_err("\"-Tfields\" was specified, but no fields were " - "specified with \"-e\"."); - - exit_status = INVALID_OPTION; - goto clean_exit; - } - - if (dissect_color) { - if (!color_filters_init(&err_msg, NULL)) { - fprintf(stderr, "%s\n", err_msg); - g_free(err_msg); - } - } - - /* If no capture filter or display filter has been specified, and there are - still command-line arguments, treat them as the tokens of a capture - filter (if no "-r" flag was specified) or a display filter (if a "-r" - flag was specified. */ - if (ws_optind < argc) { - if (cf_name != NULL) { - if (dfilter != NULL) { - cmdarg_err("Display filters were specified both with \"-Y\" " - "and with additional command-line arguments."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - dfilter = get_args_as_string(argc, argv, ws_optind); - } else { -#ifdef HAVE_LIBPCAP - guint i; - - if (global_capture_opts.default_options.cfilter) { - cmdarg_err("A default capture filter was specified both with \"-f\"" - " and with additional command-line arguments."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - for (i = 0; i < global_capture_opts.ifaces->len; i++) { - interface_options *interface_opts; - interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i); - if (interface_opts->cfilter == NULL) { - interface_opts->cfilter = get_args_as_string(argc, argv, ws_optind); - } else { - cmdarg_err("A capture filter was specified both with \"-f\"" - " and with additional command-line arguments."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } - global_capture_opts.default_options.cfilter = get_args_as_string(argc, argv, ws_optind); -#else - capture_option_specified = TRUE; -#endif - } - } - - if (!output_file_name) { - /* We're not saving the capture to a file; if "-q" wasn't specified, - we should print packet information */ - if (!quiet) - print_packet_info = TRUE; - } else { - const char *save_file = output_file_name; - /* We're saving to a file; if we're writing to the standard output. - and we'll also be writing dissected packets to the standard - output, reject the request. At best, we could redirect that - to the standard error; we *can't* write both to the standard - output and have either of them be useful. */ - if (strcmp(save_file, "-") == 0 && print_packet_info) { - cmdarg_err("You can't write both raw packet data and dissected packets" - " to the standard output."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } #ifndef HAVE_LIBPCAP - if (capture_option_specified) - cmdarg_err("This version of TShark was not built with support for capturing packets."); + if (capture_option_specified) + cmdarg_err("This version of TShark was not built with support for capturing packets."); #endif - if (arg_error) { - print_usage(stderr); - exit_status = INVALID_OPTION; - goto clean_exit; - } - - if (print_hex) { - if (output_action != WRITE_TEXT && output_action != WRITE_JSON && output_action != WRITE_JSON_RAW && output_action != WRITE_EK) { - cmdarg_err("Raw packet hex data can only be printed as text, PostScript, JSON, JSONRAW or EK JSON"); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } - - if (output_only != NULL) { - char *ps; - - if (!print_details) { - cmdarg_err("-O requires -V"); - exit_status = INVALID_OPTION; - goto clean_exit; + if (arg_error) { + print_usage(stderr); + exit_status = INVALID_OPTION; + goto clean_exit; } - output_only_tables = g_hash_table_new (g_str_hash, g_str_equal); - for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) { - const char *name = ps; - header_field_info *hfi = proto_registrar_get_byalias(name); - if (hfi) { - name = hfi->abbrev; - } - g_hash_table_insert(output_only_tables, (gpointer)name, (gpointer)name); + if (print_hex) { + if (output_action != WRITE_TEXT && output_action != WRITE_JSON && output_action != WRITE_JSON_RAW && output_action != WRITE_EK) { + cmdarg_err("Raw packet hex data can only be printed as text, PostScript, JSON, JSONRAW or EK JSON"); + exit_status = INVALID_OPTION; + goto clean_exit; + } } - } - if (rfilter != NULL && !perform_two_pass_analysis) { - cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y."); - exit_status = INVALID_OPTION; - goto clean_exit; - } + if (output_only != NULL) { + char *ps; + + if (!print_details) { + cmdarg_err("-O requires -V"); + exit_status = INVALID_OPTION; + goto clean_exit; + } + + output_only_tables = g_hash_table_new (g_str_hash, g_str_equal); + for (ps = strtok (output_only, ","); ps; ps = strtok (NULL, ",")) { + const char *name = ps; + header_field_info *hfi = proto_registrar_get_byalias(name); + if (hfi) { + name = hfi->abbrev; + } + g_hash_table_insert(output_only_tables, (gpointer)name, (gpointer)name); + } + } + + if (rfilter != NULL && !perform_two_pass_analysis) { + cmdarg_err("-R without -2 is deprecated. For single-pass filtering use -Y."); + exit_status = INVALID_OPTION; + goto clean_exit; + } #ifdef HAVE_LIBPCAP - if (caps_queries) { - /* We're supposed to list the link-layer/timestamp types for an interface; - did the user also specify a capture file to be read? */ - if (cf_name) { - /* Yes - that's bogus. */ - cmdarg_err("You can't specify %s and a capture file to be read.", - caps_queries & CAPS_QUERY_LINK_TYPES ? "-L" : "--list-time-stamp-types"); - exit_status = INVALID_OPTION; - goto clean_exit; - } - /* No - did they specify a ring buffer option? */ - if (global_capture_opts.multi_files_on) { - cmdarg_err("Ring buffer requested, but a capture isn't being done."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } else { - if (cf_name) { - /* - * "-r" was specified, so we're reading a capture file. - * Capture options don't apply here. - */ - - /* We don't support capture filters when reading from a capture file - (the BPF compiler doesn't support all link-layer types that we - support in capture files we read). */ - if (global_capture_opts.default_options.cfilter) { - cmdarg_err("Only read filters, not capture filters, " - "can be specified when reading a capture file."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (global_capture_opts.multi_files_on) { - cmdarg_err("Multiple capture files requested, but " - "a capture isn't being done."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (global_capture_opts.has_file_duration) { - cmdarg_err("Switching capture files after a time period was specified, but " - "a capture isn't being done."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (global_capture_opts.has_file_interval) { - cmdarg_err("Switching capture files after a time interval was specified, but " - "a capture isn't being done."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (global_capture_opts.has_ring_num_files) { - cmdarg_err("A ring buffer of capture files was specified, but " - "a capture isn't being done."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (global_capture_opts.has_autostop_files) { - cmdarg_err("A maximum number of capture files was specified, but " - "a capture isn't being done."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - - /* Note: TShark now allows the restriction of a _read_ file by packet count - * and byte count as well as a write file. Other autostop options remain valid - * only for a write file. - */ - if (global_capture_opts.has_autostop_duration) { - cmdarg_err("A maximum capture time was specified, but " - "a capture isn't being done."); - exit_status = INVALID_OPTION; - goto clean_exit; - } + if (caps_queries) { + /* We're supposed to list the link-layer/timestamp types for an interface; + did the user also specify a capture file to be read? */ + if (cf_name) { + /* Yes - that's bogus. */ + cmdarg_err("You can't specify %s and a capture file to be read.", + caps_queries & CAPS_QUERY_LINK_TYPES ? "-L" : "--list-time-stamp-types"); + exit_status = INVALID_OPTION; + goto clean_exit; + } + /* No - did they specify a ring buffer option? */ + if (global_capture_opts.multi_files_on) { + cmdarg_err("Ring buffer requested, but a capture isn't being done."); + exit_status = INVALID_OPTION; + goto clean_exit; + } } else { - /* - * "-r" wasn't specified, so we're doing a live capture. - */ - gboolean use_pcapng = TRUE; + if (cf_name) { + /* + * "-r" was specified, so we're reading a capture file. + * Capture options don't apply here. + */ - if (perform_two_pass_analysis) { - /* Two-pass analysis doesn't work with live capture since it requires us - * to buffer packets until we've read all of them, but a live capture - * has no useful/meaningful definition of "all" */ - cmdarg_err("Live captures do not support two-pass analysis."); - exit_status = INVALID_OPTION; - goto clean_exit; - } + /* We don't support capture filters when reading from a capture file + (the BPF compiler doesn't support all link-layer types that we + support in capture files we read). */ + if (global_capture_opts.default_options.cfilter) { + cmdarg_err("Only read filters, not capture filters, " + "can be specified when reading a capture file."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (global_capture_opts.multi_files_on) { + cmdarg_err("Multiple capture files requested, but " + "a capture isn't being done."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (global_capture_opts.has_file_duration) { + cmdarg_err("Switching capture files after a time period was specified, but " + "a capture isn't being done."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (global_capture_opts.has_file_interval) { + cmdarg_err("Switching capture files after a time interval was specified, but " + "a capture isn't being done."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (global_capture_opts.has_ring_num_files) { + cmdarg_err("A ring buffer of capture files was specified, but " + "a capture isn't being done."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (global_capture_opts.has_autostop_files) { + cmdarg_err("A maximum number of capture files was specified, but " + "a capture isn't being done."); + exit_status = INVALID_OPTION; + goto clean_exit; + } - if (global_capture_opts.saving_to_file) { - /* They specified a "-w" flag, so we'll be saving to a capture file. */ - - /* When capturing, we only support writing pcap or pcapng format. */ - if (out_file_type == wtap_pcapng_file_type_subtype()) { - use_pcapng = TRUE; - } else if (out_file_type == wtap_pcap_file_type_subtype()) { - use_pcapng = FALSE; + /* Note: TShark now allows the restriction of a _read_ file by packet count + * and byte count as well as a write file. Other autostop options remain valid + * only for a write file. + */ + if (global_capture_opts.has_autostop_duration) { + cmdarg_err("A maximum capture time was specified, but " + "a capture isn't being done."); + exit_status = INVALID_OPTION; + goto clean_exit; + } } else { - cmdarg_err("Live captures can only be saved in pcap or pcapng format."); - exit_status = INVALID_OPTION; - goto clean_exit; + /* + * "-r" wasn't specified, so we're doing a live capture. + */ + gboolean use_pcapng = TRUE; + + if (perform_two_pass_analysis) { + /* Two-pass analysis doesn't work with live capture since it requires us + * to buffer packets until we've read all of them, but a live capture + * has no useful/meaningful definition of "all" */ + cmdarg_err("Live captures do not support two-pass analysis."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + + if (global_capture_opts.saving_to_file) { + /* They specified a "-w" flag, so we'll be saving to a capture file. */ + + /* When capturing, we only support writing pcap or pcapng format. */ + if (out_file_type == wtap_pcapng_file_type_subtype()) { + use_pcapng = TRUE; + } else if (out_file_type == wtap_pcap_file_type_subtype()) { + use_pcapng = FALSE; + } else { + cmdarg_err("Live captures can only be saved in pcap or pcapng format."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (capture_comments != NULL && !use_pcapng) { + cmdarg_err("Capture comments can only be written to a pcapng file."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (global_capture_opts.multi_files_on) { + /* Multiple-file mode doesn't work under certain conditions: + a) it doesn't work if you're writing to the standard output; + b) it doesn't work if you're writing to a pipe; + */ + if (strcmp(global_capture_opts.save_file, "-") == 0) { + cmdarg_err("Multiple capture files requested, but " + "the capture is being written to the standard output."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (global_capture_opts.output_to_pipe) { + cmdarg_err("Multiple capture files requested, but " + "the capture file is a pipe."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (!global_capture_opts.has_autostop_filesize && + !global_capture_opts.has_file_duration && + !global_capture_opts.has_file_interval && + !global_capture_opts.has_file_packets) { + cmdarg_err("Multiple capture files requested, but " + "no maximum capture file size, duration, interval or packets were specified."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } + /* Currently, we don't support read or display filters when capturing + and saving the packets. */ + if (rfilter != NULL) { + cmdarg_err("Read filters aren't supported when capturing and saving the captured packets."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (dfilter != NULL) { + cmdarg_err("Display filters aren't supported when capturing and saving the captured packets."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + global_capture_opts.use_pcapng = use_pcapng; + } else { + /* They didn't specify a "-w" flag, so we won't be saving to a + capture file. Check for options that only make sense if + we're saving to a file. */ + if (global_capture_opts.has_autostop_filesize) { + cmdarg_err("Maximum capture file size specified, but " + "capture isn't being saved to a file."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (global_capture_opts.multi_files_on) { + cmdarg_err("Multiple capture files requested, but " + "the capture isn't being saved to a file."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (capture_comments != NULL) { + cmdarg_err("Capture comments were specified, but " + "the capture isn't being saved to a file."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } } - if (capture_comments != NULL && !use_pcapng) { - cmdarg_err("Capture comments can only be written to a pcapng file."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (global_capture_opts.multi_files_on) { - /* Multiple-file mode doesn't work under certain conditions: - a) it doesn't work if you're writing to the standard output; - b) it doesn't work if you're writing to a pipe; - */ - if (strcmp(global_capture_opts.save_file, "-") == 0) { - cmdarg_err("Multiple capture files requested, but " - "the capture is being written to the standard output."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (global_capture_opts.output_to_pipe) { - cmdarg_err("Multiple capture files requested, but " - "the capture file is a pipe."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (!global_capture_opts.has_autostop_filesize && - !global_capture_opts.has_file_duration && - !global_capture_opts.has_file_interval && - !global_capture_opts.has_file_packets) { - cmdarg_err("Multiple capture files requested, but " - "no maximum capture file size, duration, interval or packets were specified."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } - /* Currently, we don't support read or display filters when capturing - and saving the packets. */ - if (rfilter != NULL) { - cmdarg_err("Read filters aren't supported when capturing and saving the captured packets."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (dfilter != NULL) { - cmdarg_err("Display filters aren't supported when capturing and saving the captured packets."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - global_capture_opts.use_pcapng = use_pcapng; - } else { - /* They didn't specify a "-w" flag, so we won't be saving to a - capture file. Check for options that only make sense if - we're saving to a file. */ - if (global_capture_opts.has_autostop_filesize) { - cmdarg_err("Maximum capture file size specified, but " - "capture isn't being saved to a file."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (global_capture_opts.multi_files_on) { - cmdarg_err("Multiple capture files requested, but " - "the capture isn't being saved to a file."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - if (capture_comments != NULL) { - cmdarg_err("Capture comments were specified, but " - "the capture isn't being saved to a file."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } } - } #endif - /* - * If capture comments were specified, -w also has to have been specified. - */ - if (capture_comments != NULL) { - if (output_file_name) { - /* They specified a "-w" flag, so we'll be saving to a capture file. - * This is fine if they're writing in a format that supports - * section block comments. - */ - if (wtap_file_type_subtype_supports_option(out_file_type, - WTAP_BLOCK_SECTION, - OPT_COMMENT) == OPTION_NOT_SUPPORTED) { - GArray *writable_type_subtypes; + /* + * If capture comments were specified, -w also has to have been specified. + */ + if (capture_comments != NULL) { + if (output_file_name) { + /* They specified a "-w" flag, so we'll be saving to a capture file. + * This is fine if they're writing in a format that supports + * section block comments. + */ + if (wtap_file_type_subtype_supports_option(out_file_type, + WTAP_BLOCK_SECTION, + OPT_COMMENT) == OPTION_NOT_SUPPORTED) { + GArray *writable_type_subtypes; - cmdarg_err("Capture comments can only be written to files of the following types:"); - writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME); - for (guint i = 0; i < writable_type_subtypes->len; i++) { - int ft = g_array_index(writable_type_subtypes, int, i); + cmdarg_err("Capture comments can only be written to files of the following types:"); + writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME); + for (guint i = 0; i < writable_type_subtypes->len; i++) { + int ft = g_array_index(writable_type_subtypes, int, i); - if (wtap_file_type_subtype_supports_option(ft, WTAP_BLOCK_SECTION, - OPT_COMMENT) != OPTION_NOT_SUPPORTED) - cmdarg_err_cont(" %s - %s", wtap_file_type_subtype_name(ft), - wtap_file_type_subtype_description(ft)); + if (wtap_file_type_subtype_supports_option(ft, WTAP_BLOCK_SECTION, + OPT_COMMENT) != OPTION_NOT_SUPPORTED) + cmdarg_err_cont(" %s - %s", wtap_file_type_subtype_name(ft), + wtap_file_type_subtype_description(ft)); + } + exit_status = INVALID_OPTION; + goto clean_exit; + } } + else { + cmdarg_err("Capture comments were specified, but you aren't writing a capture file."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } + + err_msg = ws_init_sockets(); + if (err_msg != NULL) + { + cmdarg_err("%s", err_msg); + g_free(err_msg); + cmdarg_err_cont("%s", please_report_bug()); + exit_status = INIT_FAILED; + goto clean_exit; + } + + /* Notify all registered modules that have had any of their preferences + changed either from one of the preferences file or from the command + line that their preferences have changed. */ + prefs_apply_all(); + + /* We can also enable specified taps for export object */ + start_exportobjects(); + + /* At this point MATE will have registered its field array so we can + check if the fields specified by the user are all good. + */ + { + GSList* it = NULL; + GSList *invalid_fields = output_fields_valid(output_fields); + if (invalid_fields != NULL) { + + cmdarg_err("Some fields aren't valid:"); + for (it=invalid_fields; it != NULL; it = g_slist_next(it)) { + cmdarg_err_cont("\t%s", (gchar *)it->data); + } + g_slist_free(invalid_fields); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } +#ifdef HAVE_LIBPCAP + /* We currently don't support taps, or printing dissected packets, + if we're writing to a pipe. */ + if (global_capture_opts.saving_to_file && + global_capture_opts.output_to_pipe) { + if (tap_listeners_require_dissection()) { + cmdarg_err("Taps aren't supported when saving to a pipe."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + if (print_packet_info) { + cmdarg_err("Printing dissected packets isn't supported when saving to a pipe."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } +#endif + + if (ex_opt_count("read_format") > 0) { + const gchar* name = ex_opt_get_next("read_format"); + in_file_type = open_info_name_to_type(name); + if (in_file_type == WTAP_TYPE_AUTO) { + cmdarg_err("\"%s\" isn't a valid read file format type", name? name : ""); + list_read_capture_types(); + exit_status = INVALID_OPTION; + goto clean_exit; + } + } + + timestamp_set_type(global_dissect_options.time_format); + + /* + * Enabled and disabled protocols and heuristic dissectors as per + * command-line options. + */ + if (!setup_enabled_and_disabled_protocols()) { exit_status = INVALID_OPTION; goto clean_exit; - } } - else { - cmdarg_err("Capture comments were specified, but you aren't writing a capture file."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } - err_msg = ws_init_sockets(); - if (err_msg != NULL) - { - cmdarg_err("%s", err_msg); - g_free(err_msg); - cmdarg_err_cont("%s", please_report_bug()); - exit_status = INIT_FAILED; - goto clean_exit; - } + /* Build the column format array */ + build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE); - /* Notify all registered modules that have had any of their preferences - changed either from one of the preferences file or from the command - line that their preferences have changed. */ - prefs_apply_all(); - - /* We can also enable specified taps for export object */ - start_exportobjects(); - - /* At this point MATE will have registered its field array so we can - check if the fields specified by the user are all good. - */ - { - GSList* it = NULL; - GSList *invalid_fields = output_fields_valid(output_fields); - if (invalid_fields != NULL) { - - cmdarg_err("Some fields aren't valid:"); - for (it=invalid_fields; it != NULL; it = g_slist_next(it)) { - cmdarg_err_cont("\t%s", (gchar *)it->data); - } - g_slist_free(invalid_fields); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } #ifdef HAVE_LIBPCAP - /* We currently don't support taps, or printing dissected packets, - if we're writing to a pipe. */ - if (global_capture_opts.saving_to_file && - global_capture_opts.output_to_pipe) { - if (tap_listeners_require_dissection()) { - cmdarg_err("Taps aren't supported when saving to a pipe."); - exit_status = INVALID_OPTION; - goto clean_exit; + capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE); + capture_opts_trim_ring_num_files(&global_capture_opts); +#endif + + if (rfilter != NULL) { + ws_debug("Compiling read filter: '%s'", rfilter); + if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { + cmdarg_err("%s", err_msg); + g_free(err_msg); + epan_cleanup(); + extcap_cleanup(); + +#ifdef HAVE_LIBPCAP + pcap_t *pc; + pc = pcap_open_dead(DLT_EN10MB, MIN_PACKET_SIZE); + if (pc != NULL) { + if (pcap_compile(pc, &fcode, rfilter, 0, 0) != -1) { + cmdarg_err_cont( + " Note: That read filter code looks like a valid capture filter;\n" + " maybe you mixed them up?"); + } + pcap_close(pc); + } +#endif + + exit_status = INVALID_INTERFACE; + goto clean_exit; + } } + cfile.rfcode = rfcode; + + if (dfilter != NULL) { + ws_debug("Compiling display filter: '%s'", dfilter); + if (!dfilter_compile(dfilter, &dfcode, &err_msg)) { + cmdarg_err("%s", err_msg); + g_free(err_msg); + epan_cleanup(); + extcap_cleanup(); + +#ifdef HAVE_LIBPCAP + pcap_t *pc; + pc = pcap_open_dead(DLT_EN10MB, MIN_PACKET_SIZE); + if (pc != NULL) { + if (pcap_compile(pc, &fcode, dfilter, 0, 0) != -1) { + cmdarg_err_cont( + " Note: That display filter code looks like a valid capture filter;\n" + " maybe you mixed them up?"); + } + pcap_close(pc); + } +#endif + + exit_status = INVALID_FILTER; + goto clean_exit; + } + } + cfile.dfcode = dfcode; + if (print_packet_info) { - cmdarg_err("Printing dissected packets isn't supported when saving to a pipe."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } -#endif + /* If we're printing as text or PostScript, we have + to create a print stream. */ + if (output_action == WRITE_TEXT) { + switch (print_format) { - if (ex_opt_count("read_format") > 0) { - const gchar* name = ex_opt_get_next("read_format"); - in_file_type = open_info_name_to_type(name); - if (in_file_type == WTAP_TYPE_AUTO) { - cmdarg_err("\"%s\" isn't a valid read file format type", name? name : ""); - list_read_capture_types(); - exit_status = INVALID_OPTION; - goto clean_exit; - } - } + case PR_FMT_TEXT: + print_stream = print_stream_text_stdio_new(stdout); + break; - timestamp_set_type(global_dissect_options.time_format); + case PR_FMT_PS: + print_stream = print_stream_ps_stdio_new(stdout); + break; - /* - * Enabled and disabled protocols and heuristic dissectors as per - * command-line options. - */ - if (!setup_enabled_and_disabled_protocols()) { - exit_status = INVALID_OPTION; - goto clean_exit; - } - - /* Build the column format array */ - build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE); - -#ifdef HAVE_LIBPCAP - capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE); - capture_opts_trim_ring_num_files(&global_capture_opts); -#endif - - if (rfilter != NULL) { - ws_debug("Compiling read filter: '%s'", rfilter); - if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { - cmdarg_err("%s", err_msg); - g_free(err_msg); - epan_cleanup(); - extcap_cleanup(); - -#ifdef HAVE_LIBPCAP - pcap_t *pc; - pc = pcap_open_dead(DLT_EN10MB, MIN_PACKET_SIZE); - if (pc != NULL) { - if (pcap_compile(pc, &fcode, rfilter, 0, 0) != -1) { - cmdarg_err_cont( - " Note: That read filter code looks like a valid capture filter;\n" - " maybe you mixed them up?"); + default: + ws_assert_not_reached(); + } } - pcap_close(pc); - } -#endif - - exit_status = INVALID_INTERFACE; - goto clean_exit; - } - } - cfile.rfcode = rfcode; - - if (dfilter != NULL) { - ws_debug("Compiling display filter: '%s'", dfilter); - if (!dfilter_compile(dfilter, &dfcode, &err_msg)) { - cmdarg_err("%s", err_msg); - g_free(err_msg); - epan_cleanup(); - extcap_cleanup(); - -#ifdef HAVE_LIBPCAP - pcap_t *pc; - pc = pcap_open_dead(DLT_EN10MB, MIN_PACKET_SIZE); - if (pc != NULL) { - if (pcap_compile(pc, &fcode, dfilter, 0, 0) != -1) { - cmdarg_err_cont( - " Note: That display filter code looks like a valid capture filter;\n" - " maybe you mixed them up?"); - } - pcap_close(pc); - } -#endif - - exit_status = INVALID_FILTER; - goto clean_exit; - } - } - cfile.dfcode = dfcode; - - if (print_packet_info) { - /* If we're printing as text or PostScript, we have - to create a print stream. */ - if (output_action == WRITE_TEXT) { - switch (print_format) { - - case PR_FMT_TEXT: - print_stream = print_stream_text_stdio_new(stdout); - break; - - case PR_FMT_PS: - print_stream = print_stream_ps_stdio_new(stdout); - break; - - default: - ws_assert_not_reached(); - } - } - } - - /* PDU export requested. Take the ownership of the '-w' file, apply tap - * filters and start tapping. */ - if (pdu_export_arg) { - const char *exp_pdu_tap_name = pdu_export_arg; - const char *exp_pdu_filter = dfilter; /* may be NULL to disable filter */ - char *exp_pdu_error; - int exp_fd; - char *comment; - - if (!cf_name) { - cmdarg_err("PDUs export requires a capture file (specify with -r)."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - /* Take ownership of the '-w' output file. */ - exp_pdu_filename = output_file_name; - output_file_name = NULL; -#ifdef HAVE_LIBPCAP - global_capture_opts.save_file = NULL; -#endif - if (exp_pdu_filename == NULL) { - cmdarg_err("PDUs export requires an output file (-w)."); - exit_status = INVALID_OPTION; - goto clean_exit; - } - - exp_pdu_error = exp_pdu_pre_open(exp_pdu_tap_name, exp_pdu_filter, - &exp_pdu_tap_data); - if (exp_pdu_error) { - cmdarg_err("Cannot register tap: %s", exp_pdu_error); - g_free(exp_pdu_error); - list_export_pdu_taps(); - exit_status = INVALID_TAP; - goto clean_exit; - } - - if (strcmp(exp_pdu_filename, "-") == 0) { - /* Write to the standard output. */ - exp_fd = 1; - } else { - exp_fd = ws_open(exp_pdu_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); - if (exp_fd == -1) { - cmdarg_err("%s: %s", exp_pdu_filename, file_open_error_message(errno, TRUE)); - exit_status = INVALID_FILE; - goto clean_exit; - } - } - - /* Activate the export PDU tap */ - /* Write to our output file with this comment (if the type supports it, - * otherwise exp_pdu_open() will ignore the comment) */ - comment = ws_strdup_printf("Dump of PDUs from %s", cf_name); - exp_pdu_status = exp_pdu_open(&exp_pdu_tap_data, exp_pdu_filename, - out_file_type, exp_fd, comment, - &err, &err_info); - g_free(comment); - if (!exp_pdu_status) { - cfile_dump_open_failure_message(exp_pdu_filename, err, err_info, - out_file_type); - exit_status = INVALID_EXPORT; - goto clean_exit; - } - } - - ws_debug("tshark: do_dissection = %s", do_dissection ? "TRUE" : "FALSE"); - - if (cf_name) { - ws_debug("tshark: Opening capture file: %s", cf_name); - /* - * We're reading a capture file. - */ - if (cf_open(&cfile, cf_name, in_file_type, FALSE, &err) != CF_OK) { - epan_cleanup(); - extcap_cleanup(); - exit_status = INVALID_FILE; - goto clean_exit; - } - - /* Start statistics taps; we do so after successfully opening the - capture file, so we know we have something to compute stats - on, and after registering all dissectors, so that MATE will - have registered its field array so we can have a tap filter - with one of MATE's late-registered fields as part of the - filter. */ - start_requested_stats(); - - /* Do we need to do dissection of packets? That depends on, among - other things, what taps are listening, so determine that after - starting the statistics taps. */ - do_dissection = must_do_dissection(rfcode, dfcode, pdu_export_arg); - - /* Process the packets in the file */ - ws_debug("tshark: invoking process_cap_file() to process the packets"); - TRY { - status = process_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res, -#ifdef HAVE_LIBPCAP - global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0, - global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0, - global_capture_opts.has_autostop_written_packets ? global_capture_opts.autostop_written_packets : 0); -#else - max_packet_count, - 0, - 0); -#endif - } - CATCH(OutOfMemoryError) { - fprintf(stderr, - "Out Of Memory.\n" - "\n" - "Sorry, but TShark has to terminate now.\n" - "\n" - "More information and workarounds can be found at\n" - WS_WIKI_URL("KnownBugs/OutOfMemory") "\n"); - status = PROCESS_FILE_ERROR; - } - ENDTRY; - - switch (status) { - - case PROCESS_FILE_SUCCEEDED: - /* Everything worked OK; draw the taps. */ - draw_taps = TRUE; - break; - - case PROCESS_FILE_NO_FILE_PROCESSED: - /* We never got to try to read the file, so there are no tap - results to dump. Exit with an error status. */ - exit_status = 2; - break; - - case PROCESS_FILE_ERROR: - /* We still dump out the results of taps, etc., as we might have - read some packets; however, we exit with an error status. */ - draw_taps = TRUE; - exit_status = 2; - break; - - case PROCESS_FILE_INTERRUPTED: - /* The user interrupted the read process; Don't dump out the - result of taps, etc., and exit with an error status. */ - exit_status = 2; - break; } + /* PDU export requested. Take the ownership of the '-w' file, apply tap + * filters and start tapping. */ if (pdu_export_arg) { - if (!exp_pdu_close(&exp_pdu_tap_data, &err, &err_info)) { - cfile_close_failure_message(exp_pdu_filename, err, err_info); - exit_status = 2; + const char *exp_pdu_tap_name = pdu_export_arg; + const char *exp_pdu_filter = dfilter; /* may be NULL to disable filter */ + char *exp_pdu_error; + int exp_fd; + char *comment; + + if (!cf_name) { + cmdarg_err("PDUs export requires a capture file (specify with -r)."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + /* Take ownership of the '-w' output file. */ + exp_pdu_filename = output_file_name; + output_file_name = NULL; +#ifdef HAVE_LIBPCAP + global_capture_opts.save_file = NULL; +#endif + if (exp_pdu_filename == NULL) { + cmdarg_err("PDUs export requires an output file (-w)."); + exit_status = INVALID_OPTION; + goto clean_exit; + } + + exp_pdu_error = exp_pdu_pre_open(exp_pdu_tap_name, exp_pdu_filter, + &exp_pdu_tap_data); + if (exp_pdu_error) { + cmdarg_err("Cannot register tap: %s", exp_pdu_error); + g_free(exp_pdu_error); + list_export_pdu_taps(); + exit_status = INVALID_TAP; + goto clean_exit; + } + + if (strcmp(exp_pdu_filename, "-") == 0) { + /* Write to the standard output. */ + exp_fd = 1; + } else { + exp_fd = ws_open(exp_pdu_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); + if (exp_fd == -1) { + cmdarg_err("%s: %s", exp_pdu_filename, file_open_error_message(errno, TRUE)); + exit_status = INVALID_FILE; + goto clean_exit; + } + } + + /* Activate the export PDU tap */ + /* Write to our output file with this comment (if the type supports it, + * otherwise exp_pdu_open() will ignore the comment) */ + comment = ws_strdup_printf("Dump of PDUs from %s", cf_name); + exp_pdu_status = exp_pdu_open(&exp_pdu_tap_data, exp_pdu_filename, + out_file_type, exp_fd, comment, + &err, &err_info); + g_free(comment); + if (!exp_pdu_status) { + cfile_dump_open_failure_message(exp_pdu_filename, err, err_info, + out_file_type); + exit_status = INVALID_EXPORT; + goto clean_exit; } - g_free(pdu_export_arg); - g_free(exp_pdu_filename); } - } else { - ws_debug("tshark: no capture file specified"); - /* No capture file specified, so we're supposed to do a live capture - or get a list of link-layer types for a live capture device; - do we have support for live captures? */ + + ws_debug("tshark: do_dissection = %s", do_dissection ? "TRUE" : "FALSE"); + + if (cf_name) { + ws_debug("tshark: Opening capture file: %s", cf_name); + /* + * We're reading a capture file. + */ + if (cf_open(&cfile, cf_name, in_file_type, FALSE, &err) != CF_OK) { + epan_cleanup(); + extcap_cleanup(); + exit_status = INVALID_FILE; + goto clean_exit; + } + + /* Start statistics taps; we do so after successfully opening the + capture file, so we know we have something to compute stats + on, and after registering all dissectors, so that MATE will + have registered its field array so we can have a tap filter + with one of MATE's late-registered fields as part of the + filter. */ + start_requested_stats(); + + /* Do we need to do dissection of packets? That depends on, among + other things, what taps are listening, so determine that after + starting the statistics taps. */ + do_dissection = must_do_dissection(rfcode, dfcode, pdu_export_arg); + + /* Process the packets in the file */ + ws_debug("tshark: invoking process_cap_file() to process the packets"); + TRY { + status = process_cap_file(&cfile, output_file_name, out_file_type, out_file_name_res, +#ifdef HAVE_LIBPCAP + global_capture_opts.has_autostop_packets ? global_capture_opts.autostop_packets : 0, + global_capture_opts.has_autostop_filesize ? global_capture_opts.autostop_filesize : 0, + global_capture_opts.has_autostop_written_packets ? global_capture_opts.autostop_written_packets : 0); +#else + max_packet_count, + 0, + 0); +#endif + } + CATCH(OutOfMemoryError) { + fprintf(stderr, + "Out Of Memory.\n" + "\n" + "Sorry, but TShark has to terminate now.\n" + "\n" + "More information and workarounds can be found at\n" + WS_WIKI_URL("KnownBugs/OutOfMemory") "\n"); + status = PROCESS_FILE_ERROR; + } + ENDTRY; + + switch (status) { + + case PROCESS_FILE_SUCCEEDED: + /* Everything worked OK; draw the taps. */ + draw_taps = TRUE; + break; + + case PROCESS_FILE_NO_FILE_PROCESSED: + /* We never got to try to read the file, so there are no tap + results to dump. Exit with an error status. */ + exit_status = 2; + break; + + case PROCESS_FILE_ERROR: + /* We still dump out the results of taps, etc., as we might have + read some packets; however, we exit with an error status. */ + draw_taps = TRUE; + exit_status = 2; + break; + + case PROCESS_FILE_INTERRUPTED: + /* The user interrupted the read process; Don't dump out the + result of taps, etc., and exit with an error status. */ + exit_status = 2; + break; + } + + if (pdu_export_arg) { + if (!exp_pdu_close(&exp_pdu_tap_data, &err, &err_info)) { + cfile_close_failure_message(exp_pdu_filename, err, err_info); + exit_status = 2; + } + g_free(pdu_export_arg); + g_free(exp_pdu_filename); + } + } else { + ws_debug("tshark: no capture file specified"); + /* No capture file specified, so we're supposed to do a live capture + or get a list of link-layer types for a live capture device; + do we have support for live captures? */ #ifdef HAVE_LIBPCAP #ifdef _WIN32 - /* Warn the user if npf.sys isn't loaded. */ - if (!npf_sys_is_running()) { - fprintf(stderr, "The NPF driver isn't running. You may have trouble " - "capturing or\nlisting interfaces.\n"); - } + /* Warn the user if npf.sys isn't loaded. */ + if (!npf_sys_is_running()) { + fprintf(stderr, "The NPF driver isn't running. You may have trouble " + "capturing or\nlisting interfaces.\n"); + } #endif /* _WIN32 */ - /* if no interface was specified, pick a default */ - exit_status = capture_opts_default_iface_if_necessary(&global_capture_opts, - ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL); - if (exit_status != 0) { - goto clean_exit; - } + /* if no interface was specified, pick a default */ + exit_status = capture_opts_default_iface_if_necessary(&global_capture_opts, + ((prefs_p->capture_device) && (*prefs_p->capture_device != '\0')) ? get_if_name(prefs_p->capture_device) : NULL); + if (exit_status != 0) { + goto clean_exit; + } - /* - * If requested, list the link layer types and/or time stamp types - * and exit. - */ - if (caps_queries) { - guint i; + /* + * If requested, list the link layer types and/or time stamp types + * and exit. + */ + if (caps_queries) { + guint i; - /* Get the list of link-layer types for the capture devices. */ - exit_status = EXIT_SUCCESS; - for (i = 0; i < global_capture_opts.ifaces->len; i++) { - interface_options *interface_opts; - if_capabilities_t *caps; - char *auth_str = NULL; + /* Get the list of link-layer types for the capture devices. */ + exit_status = EXIT_SUCCESS; + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + interface_options *interface_opts; + if_capabilities_t *caps; + char *auth_str = NULL; - interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i); + interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i); #ifdef HAVE_PCAP_REMOTE - if (interface_opts->auth_type == CAPTURE_AUTH_PWD) { - auth_str = ws_strdup_printf("%s:%s", interface_opts->auth_username, interface_opts->auth_password); - } + if (interface_opts->auth_type == CAPTURE_AUTH_PWD) { + auth_str = ws_strdup_printf("%s:%s", interface_opts->auth_username, interface_opts->auth_password); + } #endif - caps = capture_get_if_capabilities(interface_opts->name, interface_opts->monitor_mode, - auth_str, &err_str, &err_str_secondary, NULL); - g_free(auth_str); - if (caps == NULL) { - cmdarg_err("%s%s%s", err_str, err_str_secondary ? "\n" : "", err_str_secondary ? err_str_secondary : ""); - g_free(err_str); - g_free(err_str_secondary); - exit_status = INVALID_CAPABILITY; - break; + caps = capture_get_if_capabilities(interface_opts->name, interface_opts->monitor_mode, + auth_str, &err_str, &err_str_secondary, NULL); + g_free(auth_str); + if (caps == NULL) { + cmdarg_err("%s%s%s", err_str, err_str_secondary ? "\n" : "", err_str_secondary ? err_str_secondary : ""); + g_free(err_str); + g_free(err_str_secondary); + exit_status = INVALID_CAPABILITY; + break; + } + exit_status = capture_opts_print_if_capabilities(caps, interface_opts, + caps_queries); + free_if_capabilities(caps); + if (exit_status != EXIT_SUCCESS) { + break; + } + } + goto clean_exit; } - exit_status = capture_opts_print_if_capabilities(caps, interface_opts, - caps_queries); - free_if_capabilities(caps); - if (exit_status != EXIT_SUCCESS) { - break; + + /* + * If the standard error isn't a terminal, don't print packet counts, + * as they won't show up on the user's terminal and they'll get in + * the way of error messages in the file (to which we assume the + * standard error was redirected; if it's redirected to the null + * device, there's no point in printing packet counts anyway). + * + * Otherwise, if we're printing packet information and the standard + * output is a terminal (which we assume means the standard output and + * error are going to the same terminal), don't print packet counts, + * as they'll get in the way of the packet information. + * + * Otherwise, if the user specified -q, don't print packet counts. + * + * Otherwise, print packet counts. + * + * XXX - what if the user wants to do a live capture, doesn't want + * to save it to a file, doesn't want information printed for each + * packet, does want some "-z" statistic, and wants packet counts + * so they know whether they're seeing any packets? -q will + * suppress the information printed for each packet, but it'll + * also suppress the packet counts. + */ + if (!ws_isatty(ws_fileno(stderr))) + print_packet_counts = FALSE; + else if (print_packet_info && ws_isatty(ws_fileno(stdout))) + print_packet_counts = FALSE; + else if (quiet) + print_packet_counts = FALSE; + else + print_packet_counts = TRUE; + + if (print_packet_info) { + if (!write_preamble(&cfile)) { + show_print_file_io_error(); + exit_status = INVALID_FILE; + goto clean_exit; + } } - } - goto clean_exit; - } - /* - * If the standard error isn't a terminal, don't print packet counts, - * as they won't show up on the user's terminal and they'll get in - * the way of error messages in the file (to which we assume the - * standard error was redirected; if it's redirected to the null - * device, there's no point in printing packet counts anyway). - * - * Otherwise, if we're printing packet information and the standard - * output is a terminal (which we assume means the standard output and - * error are going to the same terminal), don't print packet counts, - * as they'll get in the way of the packet information. - * - * Otherwise, if the user specified -q, don't print packet counts. - * - * Otherwise, print packet counts. - * - * XXX - what if the user wants to do a live capture, doesn't want - * to save it to a file, doesn't want information printed for each - * packet, does want some "-z" statistic, and wants packet counts - * so they know whether they're seeing any packets? -q will - * suppress the information printed for each packet, but it'll - * also suppress the packet counts. - */ - if (!ws_isatty(ws_fileno(stderr))) - print_packet_counts = FALSE; - else if (print_packet_info && ws_isatty(ws_fileno(stdout))) - print_packet_counts = FALSE; - else if (quiet) - print_packet_counts = FALSE; - else - print_packet_counts = TRUE; + ws_debug("tshark: performing live capture"); - if (print_packet_info) { - if (!write_preamble(&cfile)) { - show_print_file_io_error(); - exit_status = INVALID_FILE; - goto clean_exit; - } - } + /* Start statistics taps; we should only do so after the capture + started successfully, so we know we have something to compute + stats, but we currently don't check for that - see below. - ws_debug("tshark: performing live capture"); + We do so after registering all dissectors, so that MATE will + have registered its field array so we can have a tap filter + with one of MATE's late-registered fields as part of the + filter. */ + start_requested_stats(); - /* Start statistics taps; we should only do so after the capture - started successfully, so we know we have something to compute - stats, but we currently don't check for that - see below. + /* Do we need to do dissection of packets? That depends on, among + other things, what taps are listening, so determine that after + starting the statistics taps. */ + do_dissection = must_do_dissection(rfcode, dfcode, pdu_export_arg); - We do so after registering all dissectors, so that MATE will - have registered its field array so we can have a tap filter - with one of MATE's late-registered fields as part of the - filter. */ - start_requested_stats(); + /* + * XXX - this returns FALSE if an error occurred, but it also + * returns FALSE if the capture stops because a time limit + * was reached (and possibly other limits), so we can't assume + * it means an error. + * + * The capture code is a bit twisty, so it doesn't appear to + * be an easy fix. We just ignore the return value for now. + * Instead, pass on the exit status from the capture child. + */ + capture(); + exit_status = global_capture_session.fork_child_status; - /* Do we need to do dissection of packets? That depends on, among - other things, what taps are listening, so determine that after - starting the statistics taps. */ - do_dissection = must_do_dissection(rfcode, dfcode, pdu_export_arg); + if (print_packet_info) { + if (!write_finale()) { + show_print_file_io_error(); + } + } - /* - * XXX - this returns FALSE if an error occurred, but it also - * returns FALSE if the capture stops because a time limit - * was reached (and possibly other limits), so we can't assume - * it means an error. - * - * The capture code is a bit twisty, so it doesn't appear to - * be an easy fix. We just ignore the return value for now. - * Instead, pass on the exit status from the capture child. - */ - capture(); - exit_status = global_capture_session.fork_child_status; - - if (print_packet_info) { - if (!write_finale()) { - show_print_file_io_error(); - } - } - - /* - * If we never got a capture file, don't draw the taps; we not only - * didn't capture any packets, we never even did any capturing. - */ - if (cfile.filename != NULL) - draw_taps = TRUE; + /* + * If we never got a capture file, don't draw the taps; we not only + * didn't capture any packets, we never even did any capturing. + */ + if (cfile.filename != NULL) + draw_taps = TRUE; #else - /* No - complain. */ - cmdarg_err("This version of TShark was not built with support for capturing packets."); - exit_status = INVALID_CAPTURE; - goto clean_exit; + /* No - complain. */ + cmdarg_err("This version of TShark was not built with support for capturing packets."); + exit_status = INVALID_CAPTURE; + goto clean_exit; #endif - } + } - if (cfile.provider.frames != NULL) { - free_frame_data_sequence(cfile.provider.frames); - cfile.provider.frames = NULL; - } + if (cfile.provider.frames != NULL) { + free_frame_data_sequence(cfile.provider.frames); + cfile.provider.frames = NULL; + } - if (draw_taps) - draw_tap_listeners(TRUE); + if (draw_taps) + draw_tap_listeners(TRUE); - if (tls_session_keys_file) { - gsize keylist_length; - gchar *keylist = ssl_export_sessions(&keylist_length); - write_file_binary_mode(tls_session_keys_file, keylist, keylist_length); - g_free(keylist); - } + if (tls_session_keys_file) { + gsize keylist_length; + gchar *keylist = ssl_export_sessions(&keylist_length); + write_file_binary_mode(tls_session_keys_file, keylist, keylist_length); + g_free(keylist); + } - /* Memory cleanup */ - reset_tap_listeners(); - funnel_dump_all_text_windows(); - epan_free(cfile.epan); - epan_cleanup(); - extcap_cleanup(); + /* Memory cleanup */ + reset_tap_listeners(); + funnel_dump_all_text_windows(); + epan_free(cfile.epan); + epan_cleanup(); + extcap_cleanup(); - output_fields_free(output_fields); - output_fields = NULL; + output_fields_free(output_fields); + output_fields = NULL; clean_exit: - cf_close(&cfile); - g_free(cf_name); - destroy_print_stream(print_stream); - g_free(output_file_name); + cf_close(&cfile); + g_free(cf_name); + destroy_print_stream(print_stream); + g_free(output_file_name); #ifdef HAVE_LIBPCAP - capture_opts_cleanup(&global_capture_opts); + capture_opts_cleanup(&global_capture_opts); #endif - col_cleanup(&cfile.cinfo); - free_filter_lists(); - wtap_cleanup(); - free_progdirs(); - dfilter_free(dfcode); - g_free(dfilter); - return exit_status; + col_cleanup(&cfile.cinfo); + free_filter_lists(); + wtap_cleanup(); + free_progdirs(); + dfilter_free(dfcode); + g_free(dfilter); + return exit_status; } /*#define USE_BROKEN_G_MAIN_LOOP*/ #ifdef USE_BROKEN_G_MAIN_LOOP - GMainLoop *loop; + GMainLoop *loop; #else - gboolean loop_running = FALSE; + gboolean loop_running = FALSE; #endif - guint32 packet_count = 0; + guint32 packet_count = 0; typedef struct pipe_input_tag { - gint source; - gpointer user_data; - ws_process_id *child_process; - pipe_input_cb_t input_cb; - guint pipe_input_id; + gint source; + gpointer user_data; + ws_process_id *child_process; + pipe_input_cb_t input_cb; + guint pipe_input_id; #ifdef _WIN32 - GMutex *callback_running; + GMutex *callback_running; #endif } pipe_input_t; @@ -2450,51 +2454,51 @@ static pipe_input_t pipe_input; static gint pipe_timer_cb(gpointer data) { - HANDLE handle; - DWORD avail = 0; - gboolean result; - DWORD childstatus; - pipe_input_t *pipe_input_p = data; - gint iterations = 0; + HANDLE handle; + DWORD avail = 0; + gboolean result; + DWORD childstatus; + pipe_input_t *pipe_input_p = data; + gint iterations = 0; - g_mutex_lock (pipe_input_p->callback_running); + g_mutex_lock (pipe_input_p->callback_running); - /* try to read data from the pipe only 5 times, to avoid blocking */ - while(iterations < 5) { - /* Oddly enough although Named pipes don't work on win9x, - PeekNamedPipe does !!! */ - handle = (HANDLE) _get_osfhandle (pipe_input_p->source); - result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL); + /* try to read data from the pipe only 5 times, to avoid blocking */ + while(iterations < 5) { + /* Oddly enough although Named pipes don't work on win9x, + PeekNamedPipe does !!! */ + handle = (HANDLE) _get_osfhandle (pipe_input_p->source); + result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL); - /* Get the child process exit status */ - GetExitCodeProcess((HANDLE)*(pipe_input_p->child_process), - &childstatus); + /* Get the child process exit status */ + GetExitCodeProcess((HANDLE)*(pipe_input_p->child_process), + &childstatus); - /* If the Peek returned an error, or there are bytes to be read - or the childwatcher thread has terminated then call the normal - callback */ - if (!result || avail > 0 || childstatus != STILL_ACTIVE) { + /* If the Peek returned an error, or there are bytes to be read + or the childwatcher thread has terminated then call the normal + callback */ + if (!result || avail > 0 || childstatus != STILL_ACTIVE) { - /* And call the real handler */ - if (!pipe_input_p->input_cb(pipe_input_p->source, pipe_input_p->user_data)) { - ws_debug("input pipe closed, iterations: %u", iterations); - /* pipe closed, return false so that the timer is stopped */ - g_mutex_unlock (pipe_input_p->callback_running); - return FALSE; - } - } - else { - /* No data, stop now */ - break; + /* And call the real handler */ + if (!pipe_input_p->input_cb(pipe_input_p->source, pipe_input_p->user_data)) { + ws_debug("input pipe closed, iterations: %u", iterations); + /* pipe closed, return false so that the timer is stopped */ + g_mutex_unlock (pipe_input_p->callback_running); + return FALSE; + } + } + else { + /* No data, stop now */ + break; + } + + iterations++; } - iterations++; - } + g_mutex_unlock (pipe_input_p->callback_running); - g_mutex_unlock (pipe_input_p->callback_running); - - /* we didn't stopped the timer, so let it run */ - return TRUE; + /* we didn't stopped the timer, so let it run */ + return TRUE; } #endif @@ -2503,210 +2507,210 @@ void pipe_input_set_handler(gint source, gpointer user_data, ws_process_id *child_process, pipe_input_cb_t input_cb) { - pipe_input.source = source; - pipe_input.child_process = child_process; - pipe_input.user_data = user_data; - pipe_input.input_cb = input_cb; + pipe_input.source = source; + pipe_input.child_process = child_process; + pipe_input.user_data = user_data; + pipe_input.input_cb = input_cb; #ifdef _WIN32 - pipe_input.callback_running = g_new(GMutex, 1); - g_mutex_init(pipe_input.callback_running); - /* Tricky to use pipes in win9x, as no concept of wait. NT can - do this but that doesn't cover all win32 platforms. GTK can do - this but doesn't seem to work over processes. Attempt to do - something similar here, start a timer and check for data on every - timeout. */ - pipe_input.pipe_input_id = g_timeout_add(200, pipe_timer_cb, &pipe_input); + pipe_input.callback_running = g_new(GMutex, 1); + g_mutex_init(pipe_input.callback_running); + /* Tricky to use pipes in win9x, as no concept of wait. NT can + do this but that doesn't cover all win32 platforms. GTK can do + this but doesn't seem to work over processes. Attempt to do + something similar here, start a timer and check for data on every + timeout. */ + pipe_input.pipe_input_id = g_timeout_add(200, pipe_timer_cb, &pipe_input); #endif } static const nstime_t * tshark_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num) { - if (prov->ref && prov->ref->num == frame_num) - return &prov->ref->abs_ts; + if (prov->ref && prov->ref->num == frame_num) + return &prov->ref->abs_ts; - if (prov->prev_dis && prov->prev_dis->num == frame_num) - return &prov->prev_dis->abs_ts; + if (prov->prev_dis && prov->prev_dis->num == frame_num) + return &prov->prev_dis->abs_ts; - if (prov->prev_cap && prov->prev_cap->num == frame_num) - return &prov->prev_cap->abs_ts; + if (prov->prev_cap && prov->prev_cap->num == frame_num) + return &prov->prev_cap->abs_ts; - if (prov->frames) { - frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); + if (prov->frames) { + frame_data *fd = frame_data_sequence_find(prov->frames, frame_num); - return (fd) ? &fd->abs_ts : NULL; - } + return (fd) ? &fd->abs_ts : NULL; + } - return NULL; + return NULL; } static epan_t * tshark_epan_new(capture_file *cf) { - static const struct packet_provider_funcs funcs = { - tshark_get_frame_ts, - cap_file_provider_get_interface_name, - cap_file_provider_get_interface_description, - NULL, - }; + static const struct packet_provider_funcs funcs = { + tshark_get_frame_ts, + cap_file_provider_get_interface_name, + cap_file_provider_get_interface_description, + NULL, + }; - return epan_new(&cf->provider, &funcs); + return epan_new(&cf->provider, &funcs); } #ifdef HAVE_LIBPCAP static gboolean capture(void) { - volatile gboolean ret = TRUE; - guint i; - GString *str; + volatile gboolean ret = TRUE; + guint i; + GString *str; #ifdef USE_TSHARK_SELECT - fd_set readfds; + fd_set readfds; #endif #ifndef _WIN32 - struct sigaction action, oldaction; + struct sigaction action, oldaction; #endif - /* Create new dissection section. */ - epan_free(cfile.epan); - cfile.epan = tshark_epan_new(&cfile); + /* Create new dissection section. */ + epan_free(cfile.epan); + cfile.epan = tshark_epan_new(&cfile); #ifdef _WIN32 - /* Catch a CTRL+C event and, if we get it, clean up and exit. */ - SetConsoleCtrlHandler(capture_cleanup, TRUE); + /* Catch a CTRL+C event and, if we get it, clean up and exit. */ + SetConsoleCtrlHandler(capture_cleanup, TRUE); #else /* _WIN32 */ - /* Catch SIGINT and SIGTERM and, if we get either of them, - clean up and exit. If SIGHUP isn't being ignored, catch - it too and, if we get it, clean up and exit. + /* Catch SIGINT and SIGTERM and, if we get either of them, + clean up and exit. If SIGHUP isn't being ignored, catch + it too and, if we get it, clean up and exit. - We restart any read that was in progress, so that it doesn't - disrupt reading from the sync pipe. The signal handler tells - the capture child to finish; it will report that it finished, - or will exit abnormally, so we'll stop reading from the sync - pipe, pick up the exit status, and quit. */ - memset(&action, 0, sizeof(action)); - action.sa_handler = capture_cleanup; - action.sa_flags = SA_RESTART; - sigemptyset(&action.sa_mask); - sigaction(SIGTERM, &action, NULL); - sigaction(SIGINT, &action, NULL); - sigaction(SIGHUP, NULL, &oldaction); - if (oldaction.sa_handler == SIG_DFL) - sigaction(SIGHUP, &action, NULL); + We restart any read that was in progress, so that it doesn't + disrupt reading from the sync pipe. The signal handler tells + the capture child to finish; it will report that it finished, + or will exit abnormally, so we'll stop reading from the sync + pipe, pick up the exit status, and quit. */ + memset(&action, 0, sizeof(action)); + action.sa_handler = capture_cleanup; + action.sa_flags = SA_RESTART; + sigemptyset(&action.sa_mask); + sigaction(SIGTERM, &action, NULL); + sigaction(SIGINT, &action, NULL); + sigaction(SIGHUP, NULL, &oldaction); + if (oldaction.sa_handler == SIG_DFL) + sigaction(SIGHUP, &action, NULL); #ifdef SIGINFO - /* Catch SIGINFO and, if we get it and we're capturing to a file in - quiet mode, report the number of packets we've captured. + /* Catch SIGINFO and, if we get it and we're capturing to a file in + quiet mode, report the number of packets we've captured. - Again, restart any read that was in progress, so that it doesn't - disrupt reading from the sync pipe. */ - action.sa_handler = report_counts_siginfo; - action.sa_flags = SA_RESTART; - sigemptyset(&action.sa_mask); - sigaction(SIGINFO, &action, NULL); + Again, restart any read that was in progress, so that it doesn't + disrupt reading from the sync pipe. */ + action.sa_handler = report_counts_siginfo; + action.sa_flags = SA_RESTART; + sigemptyset(&action.sa_mask); + sigaction(SIGINFO, &action, NULL); #endif /* SIGINFO */ #endif /* _WIN32 */ - global_capture_session.state = CAPTURE_PREPARING; + global_capture_session.state = CAPTURE_PREPARING; - /* Let the user know which interfaces were chosen. */ - for (i = 0; i < global_capture_opts.ifaces->len; i++) { - interface_options *interface_opts; + /* Let the user know which interfaces were chosen. */ + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + interface_options *interface_opts; - interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i); - g_free(interface_opts->descr); - interface_opts->descr = get_interface_descriptive_name(interface_opts->name); - } - str = get_iface_list_string(&global_capture_opts, IFLIST_QUOTE_IF_DESCRIPTION); - if (really_quiet == FALSE) - fprintf(stderr, "Capturing on %s\n", str->str); - fflush(stderr); - g_string_free(str, TRUE); - - ret = sync_pipe_start(&global_capture_opts, capture_comments, - &global_capture_session, &global_info_data, NULL); - - if (!ret) - return FALSE; - - /* - * Force synchronous resolution of IP addresses; we're doing only - * one pass, so we can't do it in the background and fix up past - * dissections. - */ - set_resolution_synchrony(TRUE); - - /* the actual capture loop - * - * XXX - glib doesn't seem to provide any event based loop handling. - * - * XXX - for whatever reason, - * calling g_main_loop_new() ends up in 100% cpu load. - * - * But that doesn't matter: in UNIX we can use select() to find an input - * source with something to do. - * - * But that doesn't matter because we're in a CLI (that doesn't need to - * update a GUI or something at the same time) so it's OK if we block - * trying to read from the pipe. - * - * So all the stuff in USE_TSHARK_SELECT could be removed unless I'm - * wrong (but I leave it there in case I am...). - */ - -#ifdef USE_TSHARK_SELECT - FD_ZERO(&readfds); - FD_SET(pipe_input.source, &readfds); -#endif - - loop_running = TRUE; - - TRY - { - while (loop_running) - { -#ifdef USE_TSHARK_SELECT - ret = select(pipe_input.source+1, &readfds, NULL, NULL, NULL); - - if (ret == -1) - { - fprintf(stderr, "%s: %s\n", "select()", g_strerror(errno)); - ret = TRUE; - loop_running = FALSE; - } else if (ret == 1) { -#endif - /* Call the real handler */ - if (!pipe_input.input_cb(pipe_input.source, pipe_input.user_data)) { - ws_debug("input pipe closed"); - ret = FALSE; - loop_running = FALSE; - } -#ifdef USE_TSHARK_SELECT - } -#endif + interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i); + g_free(interface_opts->descr); + interface_opts->descr = get_interface_descriptive_name(interface_opts->name); } - } - CATCH(OutOfMemoryError) { - fprintf(stderr, - "Out Of Memory.\n" - "\n" - "Sorry, but TShark has to terminate now.\n" - "\n" - "More information and workarounds can be found at\n" - WS_WIKI_URL("KnownBugs/OutOfMemory") "\n"); - abort(); - } - ENDTRY; - return ret; + str = get_iface_list_string(&global_capture_opts, IFLIST_QUOTE_IF_DESCRIPTION); + if (really_quiet == FALSE) + fprintf(stderr, "Capturing on %s\n", str->str); + fflush(stderr); + g_string_free(str, TRUE); + + ret = sync_pipe_start(&global_capture_opts, capture_comments, + &global_capture_session, &global_info_data, NULL); + + if (!ret) + return FALSE; + + /* + * Force synchronous resolution of IP addresses; we're doing only + * one pass, so we can't do it in the background and fix up past + * dissections. + */ + set_resolution_synchrony(TRUE); + + /* the actual capture loop + * + * XXX - glib doesn't seem to provide any event based loop handling. + * + * XXX - for whatever reason, + * calling g_main_loop_new() ends up in 100% cpu load. + * + * But that doesn't matter: in UNIX we can use select() to find an input + * source with something to do. + * + * But that doesn't matter because we're in a CLI (that doesn't need to + * update a GUI or something at the same time) so it's OK if we block + * trying to read from the pipe. + * + * So all the stuff in USE_TSHARK_SELECT could be removed unless I'm + * wrong (but I leave it there in case I am...). + */ + +#ifdef USE_TSHARK_SELECT + FD_ZERO(&readfds); + FD_SET(pipe_input.source, &readfds); +#endif + + loop_running = TRUE; + + TRY + { + while (loop_running) + { +#ifdef USE_TSHARK_SELECT + ret = select(pipe_input.source+1, &readfds, NULL, NULL, NULL); + + if (ret == -1) + { + fprintf(stderr, "%s: %s\n", "select()", g_strerror(errno)); + ret = TRUE; + loop_running = FALSE; + } else if (ret == 1) { +#endif + /* Call the real handler */ + if (!pipe_input.input_cb(pipe_input.source, pipe_input.user_data)) { + ws_debug("input pipe closed"); + ret = FALSE; + loop_running = FALSE; + } +#ifdef USE_TSHARK_SELECT + } +#endif + } + } + CATCH(OutOfMemoryError) { + fprintf(stderr, + "Out Of Memory.\n" + "\n" + "Sorry, but TShark has to terminate now.\n" + "\n" + "More information and workarounds can be found at\n" + WS_WIKI_URL("KnownBugs/OutOfMemory") "\n"); + abort(); + } + ENDTRY; + return ret; } /* capture child detected an error */ static void capture_input_error(capture_session *cap_session _U_, char *error_msg, char *secondary_error_msg) { - cmdarg_err("%s", error_msg); - cmdarg_err_cont("%s", secondary_error_msg); + cmdarg_err("%s", error_msg); + cmdarg_err_cont("%s", secondary_error_msg); } @@ -2714,34 +2718,34 @@ capture_input_error(capture_session *cap_session _U_, char *error_msg, char *sec static void capture_input_cfilter_error(capture_session *cap_session, guint i, const char *error_message) { - capture_options *capture_opts = cap_session->capture_opts; - dfilter_t *rfcode = NULL; - interface_options *interface_opts; + capture_options *capture_opts = cap_session->capture_opts; + dfilter_t *rfcode = NULL; + interface_options *interface_opts; - ws_assert(i < capture_opts->ifaces->len); - interface_opts = &g_array_index(capture_opts->ifaces, interface_options, i); + ws_assert(i < capture_opts->ifaces->len); + interface_opts = &g_array_index(capture_opts->ifaces, interface_options, i); - if (dfilter_compile(interface_opts->cfilter, &rfcode, NULL) && rfcode != NULL) { - cmdarg_err( - "Invalid capture filter \"%s\" for interface '%s'.\n" - "\n" - "That string looks like a valid display filter; however, it isn't a valid\n" - "capture filter (%s).\n" - "\n" - "Note that display filters and capture filters don't have the same syntax,\n" - "so you can't use most display filter expressions as capture filters.\n" - "\n" - "See the User's Guide for a description of the capture filter syntax.", - interface_opts->cfilter, interface_opts->descr, error_message); - dfilter_free(rfcode); - } else { - cmdarg_err( - "Invalid capture filter \"%s\" for interface '%s'.\n" - "\n" - "That string isn't a valid capture filter (%s).\n" - "See the User's Guide for a description of the capture filter syntax.", - interface_opts->cfilter, interface_opts->descr, error_message); - } + if (dfilter_compile(interface_opts->cfilter, &rfcode, NULL) && rfcode != NULL) { + cmdarg_err( + "Invalid capture filter \"%s\" for interface '%s'.\n" + "\n" + "That string looks like a valid display filter; however, it isn't a valid\n" + "capture filter (%s).\n" + "\n" + "Note that display filters and capture filters don't have the same syntax,\n" + "so you can't use most display filter expressions as capture filters.\n" + "\n" + "See the User's Guide for a description of the capture filter syntax.", + interface_opts->cfilter, interface_opts->descr, error_message); + dfilter_free(rfcode); + } else { + cmdarg_err( + "Invalid capture filter \"%s\" for interface '%s'.\n" + "\n" + "That string isn't a valid capture filter (%s).\n" + "See the User's Guide for a description of the capture filter syntax.", + interface_opts->cfilter, interface_opts->descr, error_message); + } } @@ -2749,63 +2753,63 @@ capture_input_cfilter_error(capture_session *cap_session, guint i, const char *e static gboolean capture_input_new_file(capture_session *cap_session, gchar *new_file) { - capture_options *capture_opts = cap_session->capture_opts; - capture_file *cf = cap_session->cf; - gboolean is_tempfile; - int err; + capture_options *capture_opts = cap_session->capture_opts; + capture_file *cf = cap_session->cf; + gboolean is_tempfile; + int err; - if (cap_session->state == CAPTURE_PREPARING) { - ws_message("Capture started."); - } - ws_message("File: \"%s\"", new_file); + if (cap_session->state == CAPTURE_PREPARING) { + ws_message("Capture started."); + } + ws_message("File: \"%s\"", new_file); - ws_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING); + ws_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING); - /* free the old filename */ - if (capture_opts->save_file != NULL) { + /* free the old filename */ + if (capture_opts->save_file != NULL) { - /* we start a new capture file, close the old one (if we had one before) */ - if (cf->state != FILE_CLOSED) { - cf_close(cf); + /* we start a new capture file, close the old one (if we had one before) */ + if (cf->state != FILE_CLOSED) { + cf_close(cf); + } + + g_free(capture_opts->save_file); + is_tempfile = FALSE; + + epan_free(cf->epan); + cf->epan = tshark_epan_new(cf); + } else { + /* we didn't had a save_file before, must be a tempfile */ + is_tempfile = TRUE; } - g_free(capture_opts->save_file); - is_tempfile = FALSE; + /* save the new filename */ + capture_opts->save_file = g_strdup(new_file); - epan_free(cf->epan); - cf->epan = tshark_epan_new(cf); - } else { - /* we didn't had a save_file before, must be a tempfile */ - is_tempfile = TRUE; - } - - /* save the new filename */ - capture_opts->save_file = g_strdup(new_file); - - /* if we are in real-time mode, open the new file now */ - if (do_dissection) { - /* this is probably unecessary, but better safe than sorry */ - cap_session->cf->open_type = WTAP_TYPE_AUTO; - /* Attempt to open the capture file and set up to read from it. */ - switch(cf_open(cap_session->cf, capture_opts->save_file, WTAP_TYPE_AUTO, is_tempfile, &err)) { - case CF_OK: - break; - case CF_ERROR: - /* Don't unlink (delete) the save file - leave it around, - for debugging purposes. */ - g_free(capture_opts->save_file); - capture_opts->save_file = NULL; - return FALSE; + /* if we are in real-time mode, open the new file now */ + if (do_dissection) { + /* this is probably unecessary, but better safe than sorry */ + cap_session->cf->open_type = WTAP_TYPE_AUTO; + /* Attempt to open the capture file and set up to read from it. */ + switch(cf_open(cap_session->cf, capture_opts->save_file, WTAP_TYPE_AUTO, is_tempfile, &err)) { + case CF_OK: + break; + case CF_ERROR: + /* Don't unlink (delete) the save file - leave it around, + for debugging purposes. */ + g_free(capture_opts->save_file); + capture_opts->save_file = NULL; + return FALSE; + } + } else if (quiet && is_tempfile) { + cf->state = FILE_READ_ABORTED; + cf->filename = g_strdup(new_file); + cf->is_tempfile = is_tempfile; } - } else if (quiet && is_tempfile) { - cf->state = FILE_READ_ABORTED; - cf->filename = g_strdup(new_file); - cf->is_tempfile = is_tempfile; - } - cap_session->state = CAPTURE_RUNNING; + cap_session->state = CAPTURE_RUNNING; - return TRUE; + return TRUE; } @@ -2813,136 +2817,136 @@ capture_input_new_file(capture_session *cap_session, gchar *new_file) static void capture_input_new_packets(capture_session *cap_session, int to_read) { - gboolean ret; - int err; - gchar *err_info; - gint64 data_offset; - capture_file *cf = cap_session->cf; - gboolean filtering_tap_listeners; - guint tap_flags; + gboolean ret; + int err; + gchar *err_info; + gint64 data_offset; + capture_file *cf = cap_session->cf; + gboolean filtering_tap_listeners; + guint tap_flags; #ifdef SIGINFO - /* - * Prevent a SIGINFO handler from writing to the standard error while - * we're doing so or writing to the standard output; instead, have it - * just set a flag telling us to print that information when we're done. - */ - infodelay = TRUE; + /* + * Prevent a SIGINFO handler from writing to the standard error while + * we're doing so or writing to the standard output; instead, have it + * just set a flag telling us to print that information when we're done. + */ + infodelay = TRUE; #endif /* SIGINFO */ - /* Do we have any tap listeners with filters? */ - filtering_tap_listeners = have_filtering_tap_listeners(); + /* Do we have any tap listeners with filters? */ + filtering_tap_listeners = have_filtering_tap_listeners(); - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - if (do_dissection) { - gboolean create_proto_tree; - epan_dissect_t *edt; - wtap_rec rec; - Buffer buf; + if (do_dissection) { + gboolean create_proto_tree; + epan_dissect_t *edt; + wtap_rec rec; + Buffer buf; - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a read filter; - * - * we're going to apply a display filter; - * - * we're going to print the protocol tree; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * a postdissector wants field values or protocols - * on the first pass; - * - * we have custom columns (which require field values, which - * currently requires that we build a protocol tree). - */ - create_proto_tree = - (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners || - (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() || - have_custom_cols(&cf->cinfo) || dissect_color); + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a read filter; + * + * we're going to apply a display filter; + * + * we're going to print the protocol tree; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * a postdissector wants field values or protocols + * on the first pass; + * + * we have custom columns (which require field values, which + * currently requires that we build a protocol tree). + */ + create_proto_tree = + (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners || + (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() || + have_custom_cols(&cf->cinfo) || dissect_color); - /* 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 - ("packet_details" is true). */ - edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); + /* 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 + ("packet_details" is true). */ + edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - while (to_read-- && cf->provider.wth) { - wtap_cleareof(cf->provider.wth); - ret = wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, &data_offset); - reset_epan_mem(cf, edt, create_proto_tree, print_packet_info && print_details); - if (ret == FALSE) { - /* read from file failed, tell the capture child to stop */ - sync_pipe_stop(cap_session); - wtap_close(cf->provider.wth); - cf->provider.wth = NULL; - } else { - ret = process_packet_single_pass(cf, edt, data_offset, &rec, &buf, - tap_flags); - } - if (ret != FALSE) { - /* packet successfully read and gone through the "Read Filter" */ - packet_count++; - } - wtap_rec_reset(&rec); + while (to_read-- && cf->provider.wth) { + wtap_cleareof(cf->provider.wth); + ret = wtap_read(cf->provider.wth, &rec, &buf, &err, &err_info, &data_offset); + reset_epan_mem(cf, edt, create_proto_tree, print_packet_info && print_details); + if (ret == FALSE) { + /* read from file failed, tell the capture child to stop */ + sync_pipe_stop(cap_session); + wtap_close(cf->provider.wth); + cf->provider.wth = NULL; + } else { + ret = process_packet_single_pass(cf, edt, data_offset, &rec, &buf, + tap_flags); + } + if (ret != FALSE) { + /* packet successfully read and gone through the "Read Filter" */ + packet_count++; + } + wtap_rec_reset(&rec); + } + + epan_dissect_free(edt); + + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + + } else { + /* + * Dumpcap's doing all the work; we're not doing any dissection. + * Count all the packets it wrote. + */ + packet_count += to_read; } - epan_dissect_free(edt); - - wtap_rec_cleanup(&rec); - ws_buffer_free(&buf); - - } else { - /* - * Dumpcap's doing all the work; we're not doing any dissection. - * Count all the packets it wrote. - */ - packet_count += to_read; - } - - if (print_packet_counts) { - /* We're printing packet counts. */ - if (packet_count != 0) { - fprintf(stderr, "\r%u ", packet_count); - /* stderr could be line buffered */ - fflush(stderr); - } - } + if (print_packet_counts) { + /* We're printing packet counts. */ + if (packet_count != 0) { + fprintf(stderr, "\r%u ", packet_count); + /* stderr could be line buffered */ + fflush(stderr); + } + } #ifdef SIGINFO - /* - * Allow SIGINFO handlers to write. - */ - infodelay = FALSE; + /* + * Allow SIGINFO handlers to write. + */ + infodelay = FALSE; - /* - * If a SIGINFO handler asked us to write out capture counts, do so. - */ - if (infoprint) - report_counts(); + /* + * If a SIGINFO handler asked us to write out capture counts, do so. + */ + if (infoprint) + report_counts(); #endif /* SIGINFO */ } static void report_counts(void) { - if ((print_packet_counts == FALSE) && (really_quiet == FALSE)) { - /* Report the count only if we aren't printing a packet count - as packets arrive. */ - fprintf(stderr, "%u packet%s captured\n", packet_count, - plurality(packet_count, "", "s")); - } + if ((print_packet_counts == FALSE) && (really_quiet == FALSE)) { + /* Report the count only if we aren't printing a packet count + as packets arrive. */ + fprintf(stderr, "%u packet%s captured\n", packet_count, + plurality(packet_count, "", "s")); + } #ifdef SIGINFO - infoprint = FALSE; /* we just reported it */ + infoprint = FALSE; /* we just reported it */ #endif /* SIGINFO */ } @@ -2950,15 +2954,15 @@ report_counts(void) static void report_counts_siginfo(int signum _U_) { - int sav_errno = errno; - /* If we've been told to delay printing, just set a flag asking - that we print counts (if we're supposed to), otherwise print - the count of packets captured (if we're supposed to). */ - if (infodelay) - infoprint = TRUE; - else - report_counts(); - errno = sav_errno; + int sav_errno = errno; + /* If we've been told to delay printing, just set a flag asking + that we print counts (if we're supposed to), otherwise print + the count of packets captured (if we're supposed to). */ + if (infodelay) + infoprint = TRUE; + else + report_counts(); + errno = sav_errno; } #endif /* SIGINFO */ @@ -2967,21 +2971,21 @@ report_counts_siginfo(int signum _U_) static void capture_input_drops(capture_session *cap_session _U_, guint32 dropped, const char* interface_name) { - if (print_packet_counts) { - /* We're printing packet counts to stderr. - Send a newline so that we move to the line after the packet count. */ - fprintf(stderr, "\n"); - } - - if (dropped != 0) { - /* We're printing packet counts to stderr. - Send a newline so that we move to the line after the packet count. */ - if (interface_name != NULL) { - fprintf(stderr, "%u packet%s dropped from %s\n", dropped, plurality(dropped, "", "s"), interface_name); - } else { - fprintf(stderr, "%u packet%s dropped\n", dropped, plurality(dropped, "", "s")); + if (print_packet_counts) { + /* We're printing packet counts to stderr. + Send a newline so that we move to the line after the packet count. */ + fprintf(stderr, "\n"); + } + + if (dropped != 0) { + /* We're printing packet counts to stderr. + Send a newline so that we move to the line after the packet count. */ + if (interface_name != NULL) { + fprintf(stderr, "%u packet%s dropped from %s\n", dropped, plurality(dropped, "", "s"), interface_name); + } else { + fprintf(stderr, "%u packet%s dropped\n", dropped, plurality(dropped, "", "s")); + } } - } } @@ -2992,16 +2996,16 @@ capture_input_drops(capture_session *cap_session _U_, guint32 dropped, const cha static void capture_input_closed(capture_session *cap_session _U_, gchar *msg) { - if (msg != NULL) - fprintf(stderr, "tshark: %s\n", msg); + if (msg != NULL) + fprintf(stderr, "tshark: %s\n", msg); - report_counts(); + report_counts(); #ifdef USE_BROKEN_G_MAIN_LOOP - /*g_main_loop_quit(loop);*/ - g_main_loop_quit(loop); + /*g_main_loop_quit(loop);*/ + g_main_loop_quit(loop); #else - loop_running = FALSE; + loop_running = FALSE; #endif } @@ -3009,130 +3013,130 @@ capture_input_closed(capture_session *cap_session _U_, gchar *msg) static BOOL WINAPI capture_cleanup(DWORD ctrltype _U_) { - /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to - Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT - is also sort of like SIGHUP, and CTRL_SHUTDOWN_EVENT is sort of - like SIGTERM at least when the machine's shutting down. + /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to + Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT + is also sort of like SIGHUP, and CTRL_SHUTDOWN_EVENT is sort of + like SIGTERM at least when the machine's shutting down. - For now, we handle them all as indications that we should clean up - and quit, just as we handle SIGINT, SIGHUP, and SIGTERM in that - way on UNIX. + For now, we handle them all as indications that we should clean up + and quit, just as we handle SIGINT, SIGHUP, and SIGTERM in that + way on UNIX. - We must return TRUE so that no other handler - such as one that would - terminate the process - gets called. + We must return TRUE so that no other handler - such as one that would + terminate the process - gets called. - XXX - for some reason, typing ^C to TShark, if you run this in - a Cygwin console window in at least some versions of Cygwin, - causes TShark to terminate immediately; this routine gets - called, but the main loop doesn't get a chance to run and - exit cleanly, at least if this is compiled with Microsoft Visual - C++ (i.e., it's a property of the Cygwin console window or Bash; - it happens if TShark is not built with Cygwin - for all I know, - building it with Cygwin may make the problem go away). */ + XXX - for some reason, typing ^C to TShark, if you run this in + a Cygwin console window in at least some versions of Cygwin, + causes TShark to terminate immediately; this routine gets + called, but the main loop doesn't get a chance to run and + exit cleanly, at least if this is compiled with Microsoft Visual + C++ (i.e., it's a property of the Cygwin console window or Bash; + it happens if TShark is not built with Cygwin - for all I know, + building it with Cygwin may make the problem go away). */ - /* tell the capture child to stop */ - sync_pipe_stop(&global_capture_session); + /* tell the capture child to stop */ + sync_pipe_stop(&global_capture_session); - /* don't stop our own loop already here, otherwise status messages and - * cleanup wouldn't be done properly. The child will indicate the stop of - * everything by calling capture_input_closed() later */ + /* don't stop our own loop already here, otherwise status messages and + * cleanup wouldn't be done properly. The child will indicate the stop of + * everything by calling capture_input_closed() later */ - return TRUE; + return TRUE; } #else static void capture_cleanup(int signum _U_) { - /* tell the capture child to stop */ - sync_pipe_stop(&global_capture_session); + /* tell the capture child to stop */ + sync_pipe_stop(&global_capture_session); - /* don't stop our own loop already here, otherwise status messages and - * cleanup wouldn't be done properly. The child will indicate the stop of - * everything by calling capture_input_closed() later */ + /* don't stop our own loop already here, otherwise status messages and + * cleanup wouldn't be done properly. The child will indicate the stop of + * everything by calling capture_input_closed() later */ } #endif /* _WIN32 */ #endif /* HAVE_LIBPCAP */ static gboolean process_packet_first_pass(capture_file *cf, epan_dissect_t *edt, - gint64 offset, wtap_rec *rec, Buffer *buf) + gint64 offset, wtap_rec *rec, Buffer *buf) { - frame_data fdlocal; - guint32 framenum; - gboolean passed; + frame_data fdlocal; + guint32 framenum; + gboolean passed; - /* The frame number of this packet is one more than the count of - frames in this packet. */ - framenum = cf->count + 1; + /* The frame number of this packet is one more than the count of + frames in this packet. */ + framenum = cf->count + 1; - /* If we're not running a display filter and we're not printing any - packet information, we don't need to do a dissection. This means - that all packets can be marked as 'passed'. */ - passed = TRUE; + /* If we're not running a display filter and we're not printing any + packet information, we don't need to do a dissection. This means + that all packets can be marked as 'passed'. */ + passed = TRUE; - frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes); + frame_data_init(&fdlocal, framenum, rec, offset, cum_bytes); - /* If we're going to run a read filter or a display filter, set up to - do a dissection and do so. (This is the first pass of two passes - over the packets, so we will not be printing any information - from the dissection or running taps on the packet; if we're doing - any of that, we'll do it in the second pass.) */ - if (edt) { - /* If we're running a read filter, prime the epan_dissect_t with that - filter. */ - if (cf->rfcode) - epan_dissect_prime_with_dfilter(edt, cf->rfcode); + /* If we're going to run a read filter or a display filter, set up to + do a dissection and do so. (This is the first pass of two passes + over the packets, so we will not be printing any information + from the dissection or running taps on the packet; if we're doing + any of that, we'll do it in the second pass.) */ + if (edt) { + /* If we're running a read filter, prime the epan_dissect_t with that + filter. */ + if (cf->rfcode) + epan_dissect_prime_with_dfilter(edt, cf->rfcode); - if (cf->dfcode) - epan_dissect_prime_with_dfilter(edt, cf->dfcode); + if (cf->dfcode) + epan_dissect_prime_with_dfilter(edt, cf->dfcode); - /* This is the first pass, so prime the epan_dissect_t with the - hfids postdissectors want on the first pass. */ - prime_epan_dissect_with_postdissector_wanted_hfids(edt); + /* This is the first pass, so prime the epan_dissect_t with the + hfids postdissectors want on the first pass. */ + prime_epan_dissect_with_postdissector_wanted_hfids(edt); - frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time, - &cf->provider.ref, cf->provider.prev_dis); - if (cf->provider.ref == &fdlocal) { - ref_frame = fdlocal; - cf->provider.ref = &ref_frame; + frame_data_set_before_dissect(&fdlocal, &cf->elapsed_time, + &cf->provider.ref, cf->provider.prev_dis); + if (cf->provider.ref == &fdlocal) { + ref_frame = fdlocal; + cf->provider.ref = &ref_frame; + } + + epan_dissect_run(edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf), + &fdlocal, NULL); + + /* Run the read filter if we have one. */ + if (cf->rfcode) + passed = dfilter_apply_edt(cf->rfcode, edt); } - epan_dissect_run(edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, &fdlocal, buf), - &fdlocal, NULL); + if (passed) { + frame_data_set_after_dissect(&fdlocal, &cum_bytes); + cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal); - /* Run the read filter if we have one. */ - if (cf->rfcode) - passed = dfilter_apply_edt(cf->rfcode, edt); - } + /* If we're not doing dissection then there won't be any dependent frames. + * More importantly, edt.pi.dependent_frames won't be initialized because + * epan hasn't been initialized. + * if we *are* doing dissection, then mark the dependent frames, but only + * if a display filter was given and it matches this packet. + */ + if (edt && cf->dfcode) { + if (dfilter_apply_edt(cf->dfcode, edt)) { + g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); + } + } - if (passed) { - frame_data_set_after_dissect(&fdlocal, &cum_bytes); - cf->provider.prev_cap = cf->provider.prev_dis = frame_data_sequence_add(cf->provider.frames, &fdlocal); - - /* If we're not doing dissection then there won't be any dependent frames. - * More importantly, edt.pi.dependent_frames won't be initialized because - * epan hasn't been initialized. - * if we *are* doing dissection, then mark the dependent frames, but only - * if a display filter was given and it matches this packet. - */ - if (edt && cf->dfcode) { - if (dfilter_apply_edt(cf->dfcode, edt)) { - g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames); - } + cf->count++; + } else { + /* if we don't add it to the frame_data_sequence, clean it up right now + * to avoid leaks */ + frame_data_destroy(&fdlocal); } - cf->count++; - } else { - /* if we don't add it to the frame_data_sequence, clean it up right now - * to avoid leaks */ - frame_data_destroy(&fdlocal); - } + if (edt) + epan_dissect_reset(edt); - if (edt) - epan_dissect_reset(edt); - - return passed; + return passed; } /* @@ -3145,1479 +3149,1479 @@ static gboolean read_interrupted = FALSE; static BOOL WINAPI read_cleanup(DWORD ctrltype _U_) { - /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to - Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT - is also sort of like SIGHUP, and CTRL_SHUTDOWN_EVENT is sort of - like SIGTERM at least when the machine's shutting down. + /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to + Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT + is also sort of like SIGHUP, and CTRL_SHUTDOWN_EVENT is sort of + like SIGTERM at least when the machine's shutting down. - For now, we handle them all as indications that we should clean up - and quit, just as we handle SIGINT, SIGHUP, and SIGTERM in that - way on UNIX. + For now, we handle them all as indications that we should clean up + and quit, just as we handle SIGINT, SIGHUP, and SIGTERM in that + way on UNIX. - We must return TRUE so that no other handler - such as one that would - terminate the process - gets called. + We must return TRUE so that no other handler - such as one that would + terminate the process - gets called. - XXX - for some reason, typing ^C to TShark, if you run this in - a Cygwin console window in at least some versions of Cygwin, - causes TShark to terminate immediately; this routine gets - called, but the main loop doesn't get a chance to run and - exit cleanly, at least if this is compiled with Microsoft Visual - C++ (i.e., it's a property of the Cygwin console window or Bash; - it happens if TShark is not built with Cygwin - for all I know, - building it with Cygwin may make the problem go away). */ + XXX - for some reason, typing ^C to TShark, if you run this in + a Cygwin console window in at least some versions of Cygwin, + causes TShark to terminate immediately; this routine gets + called, but the main loop doesn't get a chance to run and + exit cleanly, at least if this is compiled with Microsoft Visual + C++ (i.e., it's a property of the Cygwin console window or Bash; + it happens if TShark is not built with Cygwin - for all I know, + building it with Cygwin may make the problem go away). */ - /* tell the read to stop */ - read_interrupted = TRUE; + /* tell the read to stop */ + read_interrupted = TRUE; - return TRUE; + return TRUE; } #else static void read_cleanup(int signum _U_) { - /* tell the read to stop */ - read_interrupted = TRUE; + /* tell the read to stop */ + read_interrupted = TRUE; } #endif /* _WIN32 */ typedef enum { - PASS_SUCCEEDED, - PASS_READ_ERROR, - PASS_WRITE_ERROR, - PASS_INTERRUPTED + PASS_SUCCEEDED, + PASS_READ_ERROR, + PASS_WRITE_ERROR, + PASS_INTERRUPTED } pass_status_t; static pass_status_t process_cap_file_first_pass(capture_file *cf, int max_packet_count, - gint64 max_byte_count, int *err, gchar **err_info) + gint64 max_byte_count, int *err, gchar **err_info) { - wtap_rec rec; - Buffer buf; - epan_dissect_t *edt = NULL; - gint64 data_offset; - pass_status_t status = PASS_SUCCEEDED; - int framenum = 0; + wtap_rec rec; + Buffer buf; + epan_dissect_t *edt = NULL; + gint64 data_offset; + pass_status_t status = PASS_SUCCEEDED; + int framenum = 0; - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - /* Allocate a frame_data_sequence for all the frames. */ - cf->provider.frames = new_frame_data_sequence(); + /* Allocate a frame_data_sequence for all the frames. */ + cf->provider.frames = new_frame_data_sequence(); - if (do_dissection) { - gboolean create_proto_tree; + if (do_dissection) { + gboolean create_proto_tree; - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a read filter; - * - * we're going to apply a display filter; - * - * a postdissector wants field values or protocols - * on the first pass. - */ - create_proto_tree = - (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids() || dissect_color); + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a read filter; + * + * we're going to apply a display filter; + * + * a postdissector wants field values or protocols + * on the first pass. + */ + create_proto_tree = + (cf->rfcode != NULL || cf->dfcode != NULL || postdissectors_want_hfids() || dissect_color); - ws_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE"); + ws_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE"); - /* We're not going to display the protocol tree on this pass, - so it's not going to be "visible". */ - edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE); - } - - ws_debug("tshark: reading records for first pass"); - *err = 0; - while (wtap_read(cf->provider.wth, &rec, &buf, err, err_info, &data_offset)) { - if (read_interrupted) { - status = PASS_INTERRUPTED; - break; + /* We're not going to display the protocol tree on this pass, + so it's not going to be "visible". */ + edt = epan_dissect_new(cf->epan, create_proto_tree, FALSE); } - framenum++; - if (process_packet_first_pass(cf, edt, data_offset, &rec, &buf)) { - /* Stop reading if we hit a stop condition */ - if (max_packet_count > 0 && framenum >= max_packet_count) { - ws_debug("tshark: max_packet_count (%d) reached", max_packet_count); - *err = 0; /* This is not an error */ - break; - } - if (max_byte_count != 0 && data_offset >= max_byte_count) { - ws_debug("tshark: max_byte_count (%" PRId64 "/%" PRId64 ") reached", - data_offset, max_byte_count); - *err = 0; /* This is not an error */ - break; - } + ws_debug("tshark: reading records for first pass"); + *err = 0; + while (wtap_read(cf->provider.wth, &rec, &buf, err, err_info, &data_offset)) { + if (read_interrupted) { + status = PASS_INTERRUPTED; + break; + } + framenum++; + + if (process_packet_first_pass(cf, edt, data_offset, &rec, &buf)) { + /* Stop reading if we hit a stop condition */ + if (max_packet_count > 0 && framenum >= max_packet_count) { + ws_debug("tshark: max_packet_count (%d) reached", max_packet_count); + *err = 0; /* This is not an error */ + break; + } + if (max_byte_count != 0 && data_offset >= max_byte_count) { + ws_debug("tshark: max_byte_count (%" PRId64 "/%" PRId64 ") reached", + data_offset, max_byte_count); + *err = 0; /* This is not an error */ + break; + } + } + wtap_rec_reset(&rec); } - wtap_rec_reset(&rec); - } - if (*err != 0) - status = PASS_READ_ERROR; + if (*err != 0) + status = PASS_READ_ERROR; - if (edt) - epan_dissect_free(edt); + if (edt) + epan_dissect_free(edt); - /* Close the sequential I/O side, to free up memory it requires. */ - wtap_sequential_close(cf->provider.wth); + /* Close the sequential I/O side, to free up memory it requires. */ + wtap_sequential_close(cf->provider.wth); - /* Allow the protocol dissectors to free up memory that they - * don't need after the sequential run-through of the packets. */ - postseq_cleanup_all_protocols(); + /* Allow the protocol dissectors to free up memory that they + * don't need after the sequential run-through of the packets. */ + postseq_cleanup_all_protocols(); - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; - ws_buffer_free(&buf); - wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + wtap_rec_cleanup(&rec); - return status; + return status; } static gboolean process_packet_second_pass(capture_file *cf, epan_dissect_t *edt, - frame_data *fdata, wtap_rec *rec, - Buffer *buf, guint tap_flags) + frame_data *fdata, wtap_rec *rec, + Buffer *buf, guint tap_flags) { - column_info *cinfo; - gboolean passed; + column_info *cinfo; + gboolean passed; - /* If we're not running a display filter and we're not printing any - packet information, we don't need to do a dissection. This means - that all packets can be marked as 'passed'. */ - passed = TRUE; + /* If we're not running a display filter and we're not printing any + packet information, we don't need to do a dissection. This means + that all packets can be marked as 'passed'. */ + passed = TRUE; - /* If we're going to print packet information, or we're going to - run a read filter, or we're going to process taps, set up to - do a dissection and do so. (This is the second pass of two - passes over the packets; that's the pass where we print - packet information or run taps.) */ - if (edt) { - /* If we're running a display filter, prime the epan_dissect_t with that - filter. */ - if (cf->dfcode) - epan_dissect_prime_with_dfilter(edt, cf->dfcode); + /* If we're going to print packet information, or we're going to + run a read filter, or we're going to process taps, set up to + do a dissection and do so. (This is the second pass of two + passes over the packets; that's the pass where we print + packet information or run taps.) */ + if (edt) { + /* If we're running a display filter, prime the epan_dissect_t with that + filter. */ + if (cf->dfcode) + epan_dissect_prime_with_dfilter(edt, cf->dfcode); - col_custom_prime_edt(edt, &cf->cinfo); + col_custom_prime_edt(edt, &cf->cinfo); - /* We only need the columns if either - 1) some tap needs the columns - or - 2) we're printing packet info but we're *not* verbose; in verbose - mode, we print the protocol tree, not the protocol summary. - */ - if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields)) - cinfo = &cf->cinfo; - else - cinfo = NULL; + /* We only need the columns if either + 1) some tap needs the columns + or + 2) we're printing packet info but we're *not* verbose; in verbose + mode, we print the protocol tree, not the protocol summary. + */ + if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields)) + cinfo = &cf->cinfo; + else + cinfo = NULL; - frame_data_set_before_dissect(fdata, &cf->elapsed_time, - &cf->provider.ref, cf->provider.prev_dis); - if (cf->provider.ref == fdata) { - ref_frame = *fdata; - cf->provider.ref = &ref_frame; + frame_data_set_before_dissect(fdata, &cf->elapsed_time, + &cf->provider.ref, cf->provider.prev_dis); + if (cf->provider.ref == fdata) { + ref_frame = *fdata; + cf->provider.ref = &ref_frame; + } + + if (dissect_color) { + color_filters_prime_edt(edt); + fdata->need_colorize = 1; + } + + epan_dissect_run_with_taps(edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, fdata, buf), + fdata, cinfo); + + /* Run the read/display filter if we have one. */ + if (cf->dfcode) + passed = dfilter_apply_edt(cf->dfcode, edt); } - if (dissect_color) { - color_filters_prime_edt(edt); - fdata->need_colorize = 1; + if (passed) { + frame_data_set_after_dissect(fdata, &cum_bytes); + /* Process this packet. */ + if (print_packet_info) { + /* We're printing packet information; print the information for + this packet. */ + print_packet(cf, edt); + + /* If we're doing "line-buffering", flush the standard output + after every packet. See the comment above, for the "-l" + option, for an explanation of why we do that. */ + if (line_buffered) + fflush(stdout); + + if (ferror(stdout)) { + show_print_file_io_error(); + exit(2); + } + } + cf->provider.prev_dis = fdata; } + cf->provider.prev_cap = fdata; - epan_dissect_run_with_taps(edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, fdata, buf), - fdata, cinfo); - - /* Run the read/display filter if we have one. */ - if (cf->dfcode) - passed = dfilter_apply_edt(cf->dfcode, edt); - } - - if (passed) { - frame_data_set_after_dissect(fdata, &cum_bytes); - /* Process this packet. */ - if (print_packet_info) { - /* We're printing packet information; print the information for - this packet. */ - print_packet(cf, edt); - - /* If we're doing "line-buffering", flush the standard output - after every packet. See the comment above, for the "-l" - option, for an explanation of why we do that. */ - if (line_buffered) - fflush(stdout); - - if (ferror(stdout)) { - show_print_file_io_error(); - exit(2); - } + if (edt) { + epan_dissect_reset(edt); } - cf->provider.prev_dis = fdata; - } - cf->provider.prev_cap = fdata; - - if (edt) { - epan_dissect_reset(edt); - } - return passed || fdata->dependent_of_displayed; + return passed || fdata->dependent_of_displayed; } static gboolean process_new_idbs(wtap *wth, wtap_dumper *pdh, int *err, gchar **err_info) { - wtap_block_t if_data; + wtap_block_t if_data; - while ((if_data = wtap_get_next_interface_description(wth)) != NULL) { - /* - * Only add interface blocks if the output file supports (meaning - * *requires*) them. - * - * That mean that the abstract interface provided by libwiretap - * involves WTAP_BLOCK_IF_ID_AND_INFO blocks. - */ - if (pdh != NULL) { - if (wtap_file_type_subtype_supports_block(wtap_dump_file_type_subtype(pdh), WTAP_BLOCK_IF_ID_AND_INFO) != BLOCK_NOT_SUPPORTED) { - if (!wtap_dump_add_idb(pdh, if_data, err, err_info)) - return FALSE; - } + while ((if_data = wtap_get_next_interface_description(wth)) != NULL) { + /* + * Only add interface blocks if the output file supports (meaning + * *requires*) them. + * + * That mean that the abstract interface provided by libwiretap + * involves WTAP_BLOCK_IF_ID_AND_INFO blocks. + */ + if (pdh != NULL) { + if (wtap_file_type_subtype_supports_block(wtap_dump_file_type_subtype(pdh), WTAP_BLOCK_IF_ID_AND_INFO) != BLOCK_NOT_SUPPORTED) { + if (!wtap_dump_add_idb(pdh, if_data, err, err_info)) + return FALSE; + } + } } - } - return TRUE; + return TRUE; } static pass_status_t process_cap_file_second_pass(capture_file *cf, wtap_dumper *pdh, - int *err, gchar **err_info, - volatile guint32 *err_framenum, - int max_write_packet_count) + int *err, gchar **err_info, + volatile guint32 *err_framenum, + int max_write_packet_count) { - wtap_rec rec; - Buffer buf; - int framenum = 0; - int write_framenum = 0; - frame_data *fdata; - gboolean filtering_tap_listeners; - guint tap_flags; - epan_dissect_t *edt = NULL; - pass_status_t status = PASS_SUCCEEDED; - - /* - * Process whatever IDBs we haven't seen yet. This will be all - * the IDBs in the file, as we've finished reading it; they'll - * all be at the beginning of the output file. - */ - if (!process_new_idbs(cf->provider.wth, pdh, err, err_info)) { - *err_framenum = 0; - return PASS_WRITE_ERROR; - } - - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); - - /* Do we have any tap listeners with filters? */ - filtering_tap_listeners = have_filtering_tap_listeners(); - - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); - - if (do_dissection) { - gboolean create_proto_tree; + wtap_rec rec; + Buffer buf; + int framenum = 0; + int write_framenum = 0; + frame_data *fdata; + gboolean filtering_tap_listeners; + guint tap_flags; + epan_dissect_t *edt = NULL; + pass_status_t status = PASS_SUCCEEDED; /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a display filter; - * - * we're going to print the protocol tree; - * - * one of the tap listeners requires a protocol tree; - * - * we have custom columns (which require field values, which - * currently requires that we build a protocol tree). + * Process whatever IDBs we haven't seen yet. This will be all + * the IDBs in the file, as we've finished reading it; they'll + * all be at the beginning of the output file. */ - create_proto_tree = - (cf->dfcode || print_details || filtering_tap_listeners || - (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo) || dissect_color); - - ws_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "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 - ("packet_details" is true). */ - edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); - } - - /* - * Force synchronous resolution of IP addresses; in this pass, we - * can't do it in the background and fix up past dissections. - */ - set_resolution_synchrony(TRUE); - - for (framenum = 1; framenum <= (int)cf->count; framenum++) { - if (read_interrupted) { - status = PASS_INTERRUPTED; - break; + if (!process_new_idbs(cf->provider.wth, pdh, err, err_info)) { + *err_framenum = 0; + return PASS_WRITE_ERROR; } - fdata = frame_data_sequence_find(cf->provider.frames, framenum); - if (!wtap_seek_read(cf->provider.wth, fdata->file_off, &rec, &buf, err, - err_info)) { - /* Error reading from the input file. */ - status = PASS_READ_ERROR; - break; + + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + + /* Do we have any tap listeners with filters? */ + filtering_tap_listeners = have_filtering_tap_listeners(); + + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); + + if (do_dissection) { + gboolean create_proto_tree; + + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a display filter; + * + * we're going to print the protocol tree; + * + * one of the tap listeners requires a protocol tree; + * + * we have custom columns (which require field values, which + * currently requires that we build a protocol tree). + */ + create_proto_tree = + (cf->dfcode || print_details || filtering_tap_listeners || + (tap_flags & TL_REQUIRES_PROTO_TREE) || have_custom_cols(&cf->cinfo) || dissect_color); + + ws_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "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 + ("packet_details" is true). */ + edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); } - ws_debug("tshark: invoking process_packet_second_pass() for frame #%d", framenum); - if (process_packet_second_pass(cf, edt, fdata, &rec, &buf, tap_flags)) { - /* Either there's no read filtering or this packet passed the - filter, so, if we're writing to a capture file, write - this packet out. */ - write_framenum++; - if (pdh != NULL) { - ws_debug("tshark: writing packet #%d to outfile packet #%d", framenum, write_framenum); - if (!wtap_dump(pdh, &rec, ws_buffer_start_ptr(&buf), err, err_info)) { - /* Error writing to the output file. */ - ws_debug("tshark: error writing to a capture file (%d)", *err); - *err_framenum = framenum; - status = PASS_WRITE_ERROR; - break; + + /* + * Force synchronous resolution of IP addresses; in this pass, we + * can't do it in the background and fix up past dissections. + */ + set_resolution_synchrony(TRUE); + + for (framenum = 1; framenum <= (int)cf->count; framenum++) { + if (read_interrupted) { + status = PASS_INTERRUPTED; + break; } - /* Stop reading if we hit a stop condition */ - if (max_write_packet_count > 0 && write_framenum >= max_write_packet_count) { - ws_debug("tshark: max_write_packet_count (%d) reached", max_write_packet_count); - *err = 0; /* This is not an error */ - break; + fdata = frame_data_sequence_find(cf->provider.frames, framenum); + if (!wtap_seek_read(cf->provider.wth, fdata->file_off, &rec, &buf, err, + err_info)) { + /* Error reading from the input file. */ + status = PASS_READ_ERROR; + break; } - } + ws_debug("tshark: invoking process_packet_second_pass() for frame #%d", framenum); + if (process_packet_second_pass(cf, edt, fdata, &rec, &buf, tap_flags)) { + /* Either there's no read filtering or this packet passed the + filter, so, if we're writing to a capture file, write + this packet out. */ + write_framenum++; + if (pdh != NULL) { + ws_debug("tshark: writing packet #%d to outfile packet #%d", framenum, write_framenum); + if (!wtap_dump(pdh, &rec, ws_buffer_start_ptr(&buf), err, err_info)) { + /* Error writing to the output file. */ + ws_debug("tshark: error writing to a capture file (%d)", *err); + *err_framenum = framenum; + status = PASS_WRITE_ERROR; + break; + } + /* Stop reading if we hit a stop condition */ + if (max_write_packet_count > 0 && write_framenum >= max_write_packet_count) { + ws_debug("tshark: max_write_packet_count (%d) reached", max_write_packet_count); + *err = 0; /* This is not an error */ + break; + } + } + } + wtap_rec_reset(&rec); } - wtap_rec_reset(&rec); - } - if (edt) - epan_dissect_free(edt); + if (edt) + epan_dissect_free(edt); - ws_buffer_free(&buf); - wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + wtap_rec_cleanup(&rec); - return status; + return status; } static pass_status_t process_cap_file_single_pass(capture_file *cf, wtap_dumper *pdh, - int max_packet_count, gint64 max_byte_count, - int max_write_packet_count, - int *err, gchar **err_info, - volatile guint32 *err_framenum) + int max_packet_count, gint64 max_byte_count, + int max_write_packet_count, + int *err, gchar **err_info, + volatile guint32 *err_framenum) { - wtap_rec rec; - Buffer buf; - gboolean create_proto_tree = FALSE; - gboolean filtering_tap_listeners; - guint tap_flags; - int framenum = 0; - int write_framenum = 0; - epan_dissect_t *edt = NULL; - gint64 data_offset; - pass_status_t status = PASS_SUCCEEDED; + wtap_rec rec; + Buffer buf; + gboolean create_proto_tree = FALSE; + gboolean filtering_tap_listeners; + guint tap_flags; + int framenum = 0; + int write_framenum = 0; + epan_dissect_t *edt = NULL; + gint64 data_offset; + pass_status_t status = PASS_SUCCEEDED; - wtap_rec_init(&rec); - ws_buffer_init(&buf, 1514); + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); - /* Do we have any tap listeners with filters? */ - filtering_tap_listeners = have_filtering_tap_listeners(); + /* Do we have any tap listeners with filters? */ + filtering_tap_listeners = have_filtering_tap_listeners(); - /* Get the union of the flags for all tap listeners. */ - tap_flags = union_of_tap_listener_flags(); + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); - if (do_dissection) { - /* - * Determine whether we need to create a protocol tree. - * We do if: - * - * we're going to apply a read filter; - * - * we're going to apply a display filter; - * - * we're going to print the protocol tree; - * - * one of the tap listeners is going to apply a filter; - * - * one of the tap listeners requires a protocol tree; - * - * a postdissector wants field values or protocols - * on the first pass; - * - * we have custom columns (which require field values, which - * currently requires that we build a protocol tree). - */ - create_proto_tree = - (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners || - (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() || - have_custom_cols(&cf->cinfo) || dissect_color); + if (do_dissection) { + /* + * Determine whether we need to create a protocol tree. + * We do if: + * + * we're going to apply a read filter; + * + * we're going to apply a display filter; + * + * we're going to print the protocol tree; + * + * one of the tap listeners is going to apply a filter; + * + * one of the tap listeners requires a protocol tree; + * + * a postdissector wants field values or protocols + * on the first pass; + * + * we have custom columns (which require field values, which + * currently requires that we build a protocol tree). + */ + create_proto_tree = + (cf->rfcode || cf->dfcode || print_details || filtering_tap_listeners || + (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids() || + have_custom_cols(&cf->cinfo) || dissect_color); - ws_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "FALSE"); + ws_debug("tshark: create_proto_tree = %s", create_proto_tree ? "TRUE" : "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 - ("packet_details" is true). */ - edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); - } - - /* - * Force synchronous resolution of IP addresses; we're doing only - * one pass, so we can't do it in the background and fix up past - * dissections. - */ - set_resolution_synchrony(TRUE); - - *err = 0; - while (wtap_read(cf->provider.wth, &rec, &buf, err, err_info, &data_offset)) { - if (read_interrupted) { - status = PASS_INTERRUPTED; - break; - } - framenum++; - - /* - * Process whatever IDBs we haven't seen yet. - */ - if (!process_new_idbs(cf->provider.wth, pdh, err, err_info)) { - *err_framenum = framenum; - status = PASS_WRITE_ERROR; - break; + /* 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 + ("packet_details" is true). */ + edt = epan_dissect_new(cf->epan, create_proto_tree, print_packet_info && print_details); } - ws_debug("tshark: processing packet #%d", framenum); + /* + * Force synchronous resolution of IP addresses; we're doing only + * one pass, so we can't do it in the background and fix up past + * dissections. + */ + set_resolution_synchrony(TRUE); - reset_epan_mem(cf, edt, create_proto_tree, print_packet_info && print_details); - - if (process_packet_single_pass(cf, edt, data_offset, &rec, &buf, tap_flags)) { - /* Either there's no read filtering or this packet passed the - filter, so, if we're writing to a capture file, write - this packet out. */ - write_framenum++; - if (pdh != NULL) { - ws_debug("tshark: writing packet #%d to outfile as #%d", - framenum, write_framenum); - if (!wtap_dump(pdh, &rec, ws_buffer_start_ptr(&buf), err, err_info)) { - /* Error writing to the output file. */ - ws_debug("tshark: error writing to a capture file (%d)", *err); - *err_framenum = framenum; - status = PASS_WRITE_ERROR; - break; + *err = 0; + while (wtap_read(cf->provider.wth, &rec, &buf, err, err_info, &data_offset)) { + if (read_interrupted) { + status = PASS_INTERRUPTED; + break; } - } - } - /* Stop reading if we hit a stop condition */ - if (max_packet_count > 0 && framenum >= max_packet_count) { - ws_debug("tshark: max_packet_count (%d) reached", max_packet_count); - *err = 0; /* This is not an error */ - break; - } - if (max_write_packet_count > 0 && write_framenum >= max_write_packet_count) { - ws_debug("tshark: max_write_packet_count (%d) reached", max_write_packet_count); - *err = 0; /* This is not an error */ - break; - } - if (max_byte_count != 0 && data_offset >= max_byte_count) { - ws_debug("tshark: max_byte_count (%" PRId64 "/%" PRId64 ") reached", + framenum++; + + /* + * Process whatever IDBs we haven't seen yet. + */ + if (!process_new_idbs(cf->provider.wth, pdh, err, err_info)) { + *err_framenum = framenum; + status = PASS_WRITE_ERROR; + break; + } + + ws_debug("tshark: processing packet #%d", framenum); + + reset_epan_mem(cf, edt, create_proto_tree, print_packet_info && print_details); + + if (process_packet_single_pass(cf, edt, data_offset, &rec, &buf, tap_flags)) { + /* Either there's no read filtering or this packet passed the + filter, so, if we're writing to a capture file, write + this packet out. */ + write_framenum++; + if (pdh != NULL) { + ws_debug("tshark: writing packet #%d to outfile as #%d", + framenum, write_framenum); + if (!wtap_dump(pdh, &rec, ws_buffer_start_ptr(&buf), err, err_info)) { + /* Error writing to the output file. */ + ws_debug("tshark: error writing to a capture file (%d)", *err); + *err_framenum = framenum; + status = PASS_WRITE_ERROR; + break; + } + } + } + /* Stop reading if we hit a stop condition */ + if (max_packet_count > 0 && framenum >= max_packet_count) { + ws_debug("tshark: max_packet_count (%d) reached", max_packet_count); + *err = 0; /* This is not an error */ + break; + } + if (max_write_packet_count > 0 && write_framenum >= max_write_packet_count) { + ws_debug("tshark: max_write_packet_count (%d) reached", max_write_packet_count); + *err = 0; /* This is not an error */ + break; + } + if (max_byte_count != 0 && data_offset >= max_byte_count) { + ws_debug("tshark: max_byte_count (%" PRId64 "/%" PRId64 ") reached", data_offset, max_byte_count); - *err = 0; /* This is not an error */ - break; + *err = 0; /* This is not an error */ + break; + } + wtap_rec_reset(&rec); + } + if (*err != 0 && status == PASS_SUCCEEDED) { + /* Error reading from the input file. */ + status = PASS_READ_ERROR; } - wtap_rec_reset(&rec); - } - if (*err != 0 && status == PASS_SUCCEEDED) { - /* Error reading from the input file. */ - status = PASS_READ_ERROR; - } - if (edt) - epan_dissect_free(edt); + if (edt) + epan_dissect_free(edt); - ws_buffer_free(&buf); - wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + wtap_rec_cleanup(&rec); - return status; + return status; } static process_file_status_t process_cap_file(capture_file *cf, char *save_file, int out_file_type, - gboolean out_file_name_res, int max_packet_count, gint64 max_byte_count, - int max_write_packet_count) + gboolean out_file_name_res, int max_packet_count, gint64 max_byte_count, + int max_write_packet_count) { - process_file_status_t status = PROCESS_FILE_SUCCEEDED; - wtap_dumper *pdh; + process_file_status_t status = PROCESS_FILE_SUCCEEDED; + wtap_dumper *pdh; #ifndef _WIN32 - struct sigaction action, oldaction; + struct sigaction action, oldaction; #endif - int err = 0, err_pass1 = 0; - gchar *err_info = NULL, *err_info_pass1 = NULL; - volatile guint32 err_framenum; - wtap_dump_params params = WTAP_DUMP_PARAMS_INIT; - char *shb_user_appl; - pass_status_t first_pass_status, second_pass_status; - gboolean pcapng_pcapng_workaround = false; - wtapng_iface_descriptions_t if_tmp; + int err = 0, err_pass1 = 0; + gchar *err_info = NULL, *err_info_pass1 = NULL; + volatile guint32 err_framenum; + wtap_dump_params params = WTAP_DUMP_PARAMS_INIT; + char *shb_user_appl; + pass_status_t first_pass_status, second_pass_status; + gboolean pcapng_pcapng_workaround = false; + wtapng_iface_descriptions_t if_tmp; - if (save_file != NULL) { - /* Set up to write to the capture file. */ - wtap_dump_params_init_no_idbs(¶ms, cf->provider.wth); + if (save_file != NULL) { + /* Set up to write to the capture file. */ + wtap_dump_params_init_no_idbs(¶ms, cf->provider.wth); - /* workaround for pcapng -> pcapng (e.g., when pcapng starts with a custom block) */ - if (out_file_type == wtap_pcapng_file_type_subtype() && params.encap == WTAP_ENCAP_UNKNOWN) { - pcapng_pcapng_workaround = true; - params.encap = WTAP_ENCAP_PER_PACKET; - params.dont_copy_idbs = true; /* make sure this stay true */ - if (params.idb_inf->interface_data != NULL) { - /* lets fake an interface, which is not copied anyway */ - g_array_insert_val(params.idb_inf->interface_data, 0, if_tmp); - } - } + /* workaround for pcapng -> pcapng (e.g., when pcapng starts with a custom block) */ + if (out_file_type == wtap_pcapng_file_type_subtype() && params.encap == WTAP_ENCAP_UNKNOWN) { + pcapng_pcapng_workaround = true; + params.encap = WTAP_ENCAP_PER_PACKET; + params.dont_copy_idbs = true; /* make sure this stay true */ + if (params.idb_inf->interface_data != NULL) { + /* lets fake an interface, which is not copied anyway */ + g_array_insert_val(params.idb_inf->interface_data, 0, if_tmp); + } + } - /* If we don't have an application name add TShark */ - if (wtap_block_get_string_option_value(g_array_index(params.shb_hdrs, wtap_block_t, 0), OPT_SHB_USERAPPL, &shb_user_appl) != WTAP_OPTTYPE_SUCCESS) { - /* this is free'd by wtap_block_unref() later */ - wtap_block_add_string_option_format(g_array_index(params.shb_hdrs, wtap_block_t, 0), OPT_SHB_USERAPPL, "%s", get_appname_and_version()); - } - if (capture_comments != NULL) { - for (guint i = 0; i < capture_comments->len; i++) { - wtap_block_add_string_option_format(g_array_index(params.shb_hdrs, wtap_block_t, 0), - OPT_COMMENT, "%s", - (char *)g_ptr_array_index(capture_comments, i)); - } - } + /* If we don't have an application name add TShark */ + if (wtap_block_get_string_option_value(g_array_index(params.shb_hdrs, wtap_block_t, 0), OPT_SHB_USERAPPL, &shb_user_appl) != WTAP_OPTTYPE_SUCCESS) { + /* this is free'd by wtap_block_unref() later */ + wtap_block_add_string_option_format(g_array_index(params.shb_hdrs, wtap_block_t, 0), OPT_SHB_USERAPPL, "%s", get_appname_and_version()); + } + if (capture_comments != NULL) { + for (guint i = 0; i < capture_comments->len; i++) { + wtap_block_add_string_option_format(g_array_index(params.shb_hdrs, wtap_block_t, 0), + OPT_COMMENT, "%s", + (char *)g_ptr_array_index(capture_comments, i)); + } + } - ws_debug("tshark: writing format type %d, to %s", out_file_type, save_file); - if (strcmp(save_file, "-") == 0) { - /* Write to the standard output. */ - pdh = wtap_dump_open_stdout(out_file_type, WTAP_UNCOMPRESSED, ¶ms, - &err, &err_info); + ws_debug("tshark: writing format type %d, to %s", out_file_type, save_file); + if (strcmp(save_file, "-") == 0) { + /* Write to the standard output. */ + pdh = wtap_dump_open_stdout(out_file_type, WTAP_UNCOMPRESSED, ¶ms, + &err, &err_info); + } else { + pdh = wtap_dump_open(save_file, out_file_type, WTAP_UNCOMPRESSED, ¶ms, + &err, &err_info); + } + + if (pcapng_pcapng_workaround) { + /* remove the fake interface before it will be used */ + g_array_remove_index((params.idb_inf->interface_data), 0); + } + + g_free(params.idb_inf); + params.idb_inf = NULL; + + if (pdh == NULL) { + /* We couldn't set up to write to the capture file. */ + cfile_dump_open_failure_message(save_file, err, err_info, + out_file_type); + status = PROCESS_FILE_NO_FILE_PROCESSED; + goto out; + } } else { - pdh = wtap_dump_open(save_file, out_file_type, WTAP_UNCOMPRESSED, ¶ms, - &err, &err_info); + /* Set up to print packet information. */ + if (print_packet_info) { + if (!write_preamble(cf)) { + show_print_file_io_error(); + status = PROCESS_FILE_NO_FILE_PROCESSED; + goto out; + } + } + pdh = NULL; } - if (pcapng_pcapng_workaround) { - /* remove the fake interface before it will be used */ - g_array_remove_index((params.idb_inf->interface_data), 0); - } - - g_free(params.idb_inf); - params.idb_inf = NULL; - - if (pdh == NULL) { - /* We couldn't set up to write to the capture file. */ - cfile_dump_open_failure_message(save_file, err, err_info, - out_file_type); - status = PROCESS_FILE_NO_FILE_PROCESSED; - goto out; - } - } else { - /* Set up to print packet information. */ - if (print_packet_info) { - if (!write_preamble(cf)) { - show_print_file_io_error(); - status = PROCESS_FILE_NO_FILE_PROCESSED; - goto out; - } - } - pdh = NULL; - } - #ifdef _WIN32 - /* Catch a CTRL+C event and, if we get it, clean up and exit. */ - SetConsoleCtrlHandler(read_cleanup, TRUE); + /* Catch a CTRL+C event and, if we get it, clean up and exit. */ + SetConsoleCtrlHandler(read_cleanup, TRUE); #else /* _WIN32 */ - /* Catch SIGINT and SIGTERM and, if we get either of them, - clean up and exit. If SIGHUP isn't being ignored, catch - it too and, if we get it, clean up and exit. + /* Catch SIGINT and SIGTERM and, if we get either of them, + clean up and exit. If SIGHUP isn't being ignored, catch + it too and, if we get it, clean up and exit. - We restart any read that was in progress, so that it doesn't - disrupt reading from the sync pipe. The signal handler tells - the capture child to finish; it will report that it finished, - or will exit abnormally, so we'll stop reading from the sync - pipe, pick up the exit status, and quit. */ - memset(&action, 0, sizeof(action)); - action.sa_handler = read_cleanup; - action.sa_flags = SA_RESTART; - sigemptyset(&action.sa_mask); - sigaction(SIGTERM, &action, NULL); - sigaction(SIGINT, &action, NULL); - sigaction(SIGHUP, NULL, &oldaction); - if (oldaction.sa_handler == SIG_DFL) - sigaction(SIGHUP, &action, NULL); + We restart any read that was in progress, so that it doesn't + disrupt reading from the sync pipe. The signal handler tells + the capture child to finish; it will report that it finished, + or will exit abnormally, so we'll stop reading from the sync + pipe, pick up the exit status, and quit. */ + memset(&action, 0, sizeof(action)); + action.sa_handler = read_cleanup; + action.sa_flags = SA_RESTART; + sigemptyset(&action.sa_mask); + sigaction(SIGTERM, &action, NULL); + sigaction(SIGINT, &action, NULL); + sigaction(SIGHUP, NULL, &oldaction); + if (oldaction.sa_handler == SIG_DFL) + sigaction(SIGHUP, &action, NULL); #endif /* _WIN32 */ - if (perform_two_pass_analysis) { - ws_debug("tshark: perform_two_pass_analysis, do_dissection=%s", do_dissection ? "TRUE" : "FALSE"); + if (perform_two_pass_analysis) { + ws_debug("tshark: perform_two_pass_analysis, do_dissection=%s", do_dissection ? "TRUE" : "FALSE"); - first_pass_status = process_cap_file_first_pass(cf, max_packet_count, - max_byte_count, - &err_pass1, - &err_info_pass1); + first_pass_status = process_cap_file_first_pass(cf, max_packet_count, + max_byte_count, + &err_pass1, + &err_info_pass1); - ws_debug("tshark: done with first pass"); + ws_debug("tshark: done with first pass"); - if (first_pass_status == PASS_INTERRUPTED) { - /* The first pass was interrupted; skip the second pass. - It won't be run, so it won't get an error. */ - second_pass_status = PASS_SUCCEEDED; - } else { - /* - * If we got a read error on the first pass, we still do the second - * pass, so we can at least process the packets we read, and then - * report the first-pass error after the second pass (and before - * we report any second-pass errors), so all the errors show up - * at the end. - */ - second_pass_status = process_cap_file_second_pass(cf, pdh, &err, &err_info, - &err_framenum, - max_write_packet_count); + if (first_pass_status == PASS_INTERRUPTED) { + /* The first pass was interrupted; skip the second pass. + It won't be run, so it won't get an error. */ + second_pass_status = PASS_SUCCEEDED; + } else { + /* + * If we got a read error on the first pass, we still do the second + * pass, so we can at least process the packets we read, and then + * report the first-pass error after the second pass (and before + * we report any second-pass errors), so all the errors show up + * at the end. + */ + second_pass_status = process_cap_file_second_pass(cf, pdh, &err, &err_info, + &err_framenum, + max_write_packet_count); - ws_debug("tshark: done with second pass"); + ws_debug("tshark: done with second pass"); + } } - } - else { - /* !perform_two_pass_analysis */ - ws_debug("tshark: perform one pass analysis, do_dissection=%s", do_dissection ? "TRUE" : "FALSE"); + else { + /* !perform_two_pass_analysis */ + ws_debug("tshark: perform one pass analysis, do_dissection=%s", do_dissection ? "TRUE" : "FALSE"); - first_pass_status = PASS_SUCCEEDED; /* There is no first pass */ - second_pass_status = process_cap_file_single_pass(cf, pdh, - max_packet_count, - max_byte_count, - max_write_packet_count, - &err, &err_info, - &err_framenum); - } + first_pass_status = PASS_SUCCEEDED; /* There is no first pass */ + second_pass_status = process_cap_file_single_pass(cf, pdh, + max_packet_count, + max_byte_count, + max_write_packet_count, + &err, &err_info, + &err_framenum); + } - if (first_pass_status != PASS_SUCCEEDED || - second_pass_status != PASS_SUCCEEDED) { - /* - * At least one of the passes didn't succeed; either it got a failure - * or it was interrupted. - */ - if (first_pass_status != PASS_INTERRUPTED || - second_pass_status != PASS_INTERRUPTED) { - /* At least one of the passes got an error. */ - ws_debug("tshark: something failed along the line (%d)", err); - /* - * If we're printing packet data, and the standard output and error - * are going to the same place, flush the standard output, so everything - * buffered up is written, and then print a newline to the standard - * error before printing the error message, to separate it from the - * packet data. (Alas, that only works on UN*X; st_dev is meaningless, - * and the _fstat() documentation at Microsoft doesn't indicate whether - * st_ino is even supported.) - */ + if (first_pass_status != PASS_SUCCEEDED || + second_pass_status != PASS_SUCCEEDED) { + /* + * At least one of the passes didn't succeed; either it got a failure + * or it was interrupted. + */ + if (first_pass_status != PASS_INTERRUPTED || + second_pass_status != PASS_INTERRUPTED) { + /* At least one of the passes got an error. */ + ws_debug("tshark: something failed along the line (%d)", err); + /* + * If we're printing packet data, and the standard output and error + * are going to the same place, flush the standard output, so everything + * buffered up is written, and then print a newline to the standard + * error before printing the error message, to separate it from the + * packet data. (Alas, that only works on UN*X; st_dev is meaningless, + * and the _fstat() documentation at Microsoft doesn't indicate whether + * st_ino is even supported.) + */ #ifndef _WIN32 - if (print_packet_info) { - ws_statb64 stat_stdout, stat_stderr; + if (print_packet_info) { + ws_statb64 stat_stdout, stat_stderr; - if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) { - if (stat_stdout.st_dev == stat_stderr.st_dev && - stat_stdout.st_ino == stat_stderr.st_ino) { - fflush(stdout); - fprintf(stderr, "\n"); - } - } - } + if (ws_fstat64(1, &stat_stdout) == 0 && ws_fstat64(2, &stat_stderr) == 0) { + if (stat_stdout.st_dev == stat_stderr.st_dev && + stat_stdout.st_ino == stat_stderr.st_ino) { + fflush(stdout); + fprintf(stderr, "\n"); + } + } + } #endif - } - /* Report status of pass 1 of two-pass processing. */ - switch (first_pass_status) { - - case PASS_SUCCEEDED: - /* No problem. */ - break; - - case PASS_READ_ERROR: - /* Read error. */ - cfile_read_failure_message(cf->filename, err_pass1, err_info_pass1); - status = PROCESS_FILE_ERROR; - break; - - case PASS_WRITE_ERROR: - /* Won't happen on the first pass. */ - break; - - case PASS_INTERRUPTED: - /* Not an error, so nothing to report. */ - status = PROCESS_FILE_INTERRUPTED; - break; - } - - /* Report status of pass 2 of two-pass processing or the only pass - of one-pass processing. */ - switch (second_pass_status) { - - case PASS_SUCCEEDED: - /* No problem. */ - break; - - case PASS_READ_ERROR: - /* Read error. */ - cfile_read_failure_message(cf->filename, err, err_info); - status = PROCESS_FILE_ERROR; - break; - - case PASS_WRITE_ERROR: - /* Write error. - XXX - framenum is not necessarily the frame number in - the input file if there was a read filter. */ - cfile_write_failure_message(cf->filename, save_file, err, err_info, - err_framenum, out_file_type); - status = PROCESS_FILE_ERROR; - break; - - case PASS_INTERRUPTED: - /* Not an error, so nothing to report. */ - status = PROCESS_FILE_INTERRUPTED; - break; - } - } - if (save_file != NULL) { - if (second_pass_status != PASS_WRITE_ERROR) { - if (pdh && out_file_name_res) { - if (!wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list())) { - cmdarg_err("The file format \"%s\" doesn't support name resolution information.", - wtap_file_type_subtype_name(out_file_type)); } - } - /* Now close the capture file. */ - if (!wtap_dump_close(pdh, &err, &err_info)) { - cfile_close_failure_message(save_file, err, err_info); - status = PROCESS_FILE_ERROR; - } + /* Report status of pass 1 of two-pass processing. */ + switch (first_pass_status) { + + case PASS_SUCCEEDED: + /* No problem. */ + break; + + case PASS_READ_ERROR: + /* Read error. */ + cfile_read_failure_message(cf->filename, err_pass1, err_info_pass1); + status = PROCESS_FILE_ERROR; + break; + + case PASS_WRITE_ERROR: + /* Won't happen on the first pass. */ + break; + + case PASS_INTERRUPTED: + /* Not an error, so nothing to report. */ + status = PROCESS_FILE_INTERRUPTED; + break; + } + + /* Report status of pass 2 of two-pass processing or the only pass + of one-pass processing. */ + switch (second_pass_status) { + + case PASS_SUCCEEDED: + /* No problem. */ + break; + + case PASS_READ_ERROR: + /* Read error. */ + cfile_read_failure_message(cf->filename, err, err_info); + status = PROCESS_FILE_ERROR; + break; + + case PASS_WRITE_ERROR: + /* Write error. + XXX - framenum is not necessarily the frame number in + the input file if there was a read filter. */ + cfile_write_failure_message(cf->filename, save_file, err, err_info, + err_framenum, out_file_type); + status = PROCESS_FILE_ERROR; + break; + + case PASS_INTERRUPTED: + /* Not an error, so nothing to report. */ + status = PROCESS_FILE_INTERRUPTED; + break; + } + } + if (save_file != NULL) { + if (second_pass_status != PASS_WRITE_ERROR) { + if (pdh && out_file_name_res) { + if (!wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list())) { + cmdarg_err("The file format \"%s\" doesn't support name resolution information.", + wtap_file_type_subtype_name(out_file_type)); + } + } + /* Now close the capture file. */ + if (!wtap_dump_close(pdh, &err, &err_info)) { + cfile_close_failure_message(save_file, err, err_info); + status = PROCESS_FILE_ERROR; + } + } else { + /* We got a write error; it was reported, so just close the dump file + without bothering to check for further errors. */ + wtap_dump_close(pdh, &err, &err_info); + g_free(err_info); + status = PROCESS_FILE_ERROR; + } } else { - /* We got a write error; it was reported, so just close the dump file - without bothering to check for further errors. */ - wtap_dump_close(pdh, &err, &err_info); - g_free(err_info); - status = PROCESS_FILE_ERROR; + if (print_packet_info) { + if (!write_finale()) { + show_print_file_io_error(); + status = PROCESS_FILE_ERROR; + } + } } - } else { - if (print_packet_info) { - if (!write_finale()) { - show_print_file_io_error(); - status = PROCESS_FILE_ERROR; - } - } - } out: - wtap_close(cf->provider.wth); - cf->provider.wth = NULL; + wtap_close(cf->provider.wth); + cf->provider.wth = NULL; - wtap_dump_params_cleanup(¶ms); + wtap_dump_params_cleanup(¶ms); - return status; + return status; } static gboolean process_packet_single_pass(capture_file *cf, epan_dissect_t *edt, gint64 offset, - wtap_rec *rec, Buffer *buf, guint tap_flags) + wtap_rec *rec, Buffer *buf, guint tap_flags) { - frame_data fdata; - column_info *cinfo; - gboolean passed; + frame_data fdata; + column_info *cinfo; + gboolean passed; - /* Count this packet. */ - cf->count++; + /* Count this packet. */ + cf->count++; - /* If we're not running a display filter and we're not printing any - packet information, we don't need to do a dissection. This means - that all packets can be marked as 'passed'. */ - passed = TRUE; + /* If we're not running a display filter and we're not printing any + packet information, we don't need to do a dissection. This means + that all packets can be marked as 'passed'. */ + passed = TRUE; - frame_data_init(&fdata, cf->count, rec, offset, cum_bytes); + frame_data_init(&fdata, cf->count, rec, offset, cum_bytes); - /* If we're going to print packet information, or we're going to - run a read filter, or we're going to process taps, set up to - do a dissection and do so. (This is the one and only pass - over the packets, so, if we'll be printing packet information - or running taps, we'll be doing it here.) */ - if (edt) { - /* If we're running a filter, prime the epan_dissect_t with that - filter. */ - if (cf->dfcode) - epan_dissect_prime_with_dfilter(edt, cf->dfcode); + /* If we're going to print packet information, or we're going to + run a read filter, or we're going to process taps, set up to + do a dissection and do so. (This is the one and only pass + over the packets, so, if we'll be printing packet information + or running taps, we'll be doing it here.) */ + if (edt) { + /* If we're running a filter, prime the epan_dissect_t with that + filter. */ + if (cf->dfcode) + epan_dissect_prime_with_dfilter(edt, cf->dfcode); - /* This is the first and only pass, so prime the epan_dissect_t - with the hfids postdissectors want on the first pass. */ - prime_epan_dissect_with_postdissector_wanted_hfids(edt); + /* This is the first and only pass, so prime the epan_dissect_t + with the hfids postdissectors want on the first pass. */ + prime_epan_dissect_with_postdissector_wanted_hfids(edt); - col_custom_prime_edt(edt, &cf->cinfo); + col_custom_prime_edt(edt, &cf->cinfo); - /* We only need the columns if either - 1) some tap needs the columns - or - 2) we're printing packet info but we're *not* verbose; in verbose - mode, we print the protocol tree, not the protocol summary. - or - 3) there is a column mapped as an individual field */ - if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields)) - cinfo = &cf->cinfo; - else - cinfo = NULL; + /* We only need the columns if either + 1) some tap needs the columns + or + 2) we're printing packet info but we're *not* verbose; in verbose + mode, we print the protocol tree, not the protocol summary. + or + 3) there is a column mapped as an individual field */ + if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields)) + cinfo = &cf->cinfo; + else + cinfo = NULL; - frame_data_set_before_dissect(&fdata, &cf->elapsed_time, - &cf->provider.ref, cf->provider.prev_dis); - if (cf->provider.ref == &fdata) { - ref_frame = fdata; - cf->provider.ref = &ref_frame; + frame_data_set_before_dissect(&fdata, &cf->elapsed_time, + &cf->provider.ref, cf->provider.prev_dis); + if (cf->provider.ref == &fdata) { + ref_frame = fdata; + cf->provider.ref = &ref_frame; + } + + if (dissect_color) { + color_filters_prime_edt(edt); + fdata.need_colorize = 1; + } + + epan_dissect_run_with_taps(edt, cf->cd_t, rec, + frame_tvbuff_new_buffer(&cf->provider, &fdata, buf), + &fdata, cinfo); + + /* Run the filter if we have it. */ + if (cf->dfcode) + passed = dfilter_apply_edt(cf->dfcode, edt); } - if (dissect_color) { - color_filters_prime_edt(edt); - fdata.need_colorize = 1; + if (passed) { + frame_data_set_after_dissect(&fdata, &cum_bytes); + + /* Process this packet. */ + if (print_packet_info) { + /* We're printing packet information; print the information for + this packet. */ + ws_assert(edt); + print_packet(cf, edt); + + /* If we're doing "line-buffering", flush the standard output + after every packet. See the comment above, for the "-l" + option, for an explanation of why we do that. */ + if (line_buffered) + fflush(stdout); + + if (ferror(stdout)) { + show_print_file_io_error(); + exit(2); + } + } + + /* this must be set after print_packet() [bug #8160] */ + prev_dis_frame = fdata; + cf->provider.prev_dis = &prev_dis_frame; } - epan_dissect_run_with_taps(edt, cf->cd_t, rec, - frame_tvbuff_new_buffer(&cf->provider, &fdata, buf), - &fdata, cinfo); + prev_cap_frame = fdata; + cf->provider.prev_cap = &prev_cap_frame; - /* Run the filter if we have it. */ - if (cf->dfcode) - passed = dfilter_apply_edt(cf->dfcode, edt); - } - - if (passed) { - frame_data_set_after_dissect(&fdata, &cum_bytes); - - /* Process this packet. */ - if (print_packet_info) { - /* We're printing packet information; print the information for - this packet. */ - ws_assert(edt); - print_packet(cf, edt); - - /* If we're doing "line-buffering", flush the standard output - after every packet. See the comment above, for the "-l" - option, for an explanation of why we do that. */ - if (line_buffered) - fflush(stdout); - - if (ferror(stdout)) { - show_print_file_io_error(); - exit(2); - } + if (edt) { + epan_dissect_reset(edt); + frame_data_destroy(&fdata); } - - /* this must be set after print_packet() [bug #8160] */ - prev_dis_frame = fdata; - cf->provider.prev_dis = &prev_dis_frame; - } - - prev_cap_frame = fdata; - cf->provider.prev_cap = &prev_cap_frame; - - if (edt) { - epan_dissect_reset(edt); - frame_data_destroy(&fdata); - } - return passed; + return passed; } static gboolean write_preamble(capture_file *cf) { - switch (output_action) { + switch (output_action) { - case WRITE_TEXT: - return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info()); + case WRITE_TEXT: + return print_preamble(print_stream, cf->filename, get_ws_vcs_version_info()); - case WRITE_XML: - if (print_details) - write_pdml_preamble(stdout, cf->filename); - else - write_psml_preamble(&cf->cinfo, stdout); - return !ferror(stdout); + case WRITE_XML: + if (print_details) + write_pdml_preamble(stdout, cf->filename); + else + write_psml_preamble(&cf->cinfo, stdout); + return !ferror(stdout); - case WRITE_FIELDS: - write_fields_preamble(output_fields, stdout); - return !ferror(stdout); + case WRITE_FIELDS: + write_fields_preamble(output_fields, stdout); + return !ferror(stdout); - case WRITE_JSON: - case WRITE_JSON_RAW: - jdumper = write_json_preamble(stdout); - return !ferror(stdout); + case WRITE_JSON: + case WRITE_JSON_RAW: + jdumper = write_json_preamble(stdout); + return !ferror(stdout); - case WRITE_EK: - return TRUE; + case WRITE_EK: + return TRUE; - default: - ws_assert_not_reached(); - return FALSE; - } + default: + ws_assert_not_reached(); + return FALSE; + } } static char * get_line_buf(size_t len) { - static char *line_bufp = NULL; - static size_t line_buf_len = 256; - size_t new_line_buf_len; + static char *line_bufp = NULL; + static size_t line_buf_len = 256; + size_t new_line_buf_len; - for (new_line_buf_len = line_buf_len; len > new_line_buf_len; - new_line_buf_len *= 2) - ; - if (line_bufp == NULL) { - line_buf_len = new_line_buf_len; - line_bufp = (char *)g_malloc(line_buf_len + 1); - } else { - if (new_line_buf_len > line_buf_len) { - line_buf_len = new_line_buf_len; - line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1); + for (new_line_buf_len = line_buf_len; len > new_line_buf_len; + new_line_buf_len *= 2) + ; + if (line_bufp == NULL) { + line_buf_len = new_line_buf_len; + line_bufp = (char *)g_malloc(line_buf_len + 1); + } else { + if (new_line_buf_len > line_buf_len) { + line_buf_len = new_line_buf_len; + line_bufp = (char *)g_realloc(line_bufp, line_buf_len + 1); + } } - } - return line_bufp; + return line_bufp; } static inline void put_string(char *dest, const char *str, size_t str_len) { - memcpy(dest, str, str_len); - dest[str_len] = '\0'; + memcpy(dest, str, str_len); + dest[str_len] = '\0'; } static inline void put_spaces_string(char *dest, const char *str, size_t str_len, size_t str_with_spaces) { - size_t i; + size_t i; - for (i = str_len; i < str_with_spaces; i++) - *dest++ = ' '; + for (i = str_len; i < str_with_spaces; i++) + *dest++ = ' '; - put_string(dest, str, str_len); + put_string(dest, str, str_len); } static inline void put_string_spaces(char *dest, const char *str, size_t str_len, size_t str_with_spaces) { - size_t i; + size_t i; - memcpy(dest, str, str_len); - for (i = str_len; i < str_with_spaces; i++) - dest[i] = ' '; + memcpy(dest, str, str_len); + for (i = str_len; i < str_with_spaces; i++) + dest[i] = ' '; - dest[str_with_spaces] = '\0'; + dest[str_with_spaces] = '\0'; } static gboolean print_columns(capture_file *cf, const epan_dissect_t *edt) { - char *line_bufp; - int i; - size_t buf_offset; - size_t column_len; - size_t col_len; - col_item_t* col_item; - gchar str_format[11]; - const color_filter_t *color_filter = NULL; + char *line_bufp; + int i; + size_t buf_offset; + size_t column_len; + size_t col_len; + col_item_t* col_item; + gchar str_format[11]; + const color_filter_t *color_filter = NULL; - line_bufp = get_line_buf(256); - buf_offset = 0; - *line_bufp = '\0'; + line_bufp = get_line_buf(256); + buf_offset = 0; + *line_bufp = '\0'; - if (dissect_color) - color_filter = edt->pi.fd->color_filter; + if (dissect_color) + color_filter = edt->pi.fd->color_filter; - for (i = 0; i < cf->cinfo.num_cols; i++) { - col_item = &cf->cinfo.columns[i]; - /* Skip columns not marked as visible. */ - if (!get_column_visible(i)) - continue; - switch (col_item->col_fmt) { - case COL_NUMBER: - column_len = col_len = strlen(col_item->col_data); - if (column_len < 5) - column_len = 5; - line_bufp = get_line_buf(buf_offset + column_len); - put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); - break; + for (i = 0; i < cf->cinfo.num_cols; i++) { + col_item = &cf->cinfo.columns[i]; + /* Skip columns not marked as visible. */ + if (!get_column_visible(i)) + continue; + switch (col_item->col_fmt) { + case COL_NUMBER: + column_len = col_len = strlen(col_item->col_data); + if (column_len < 5) + column_len = 5; + line_bufp = get_line_buf(buf_offset + column_len); + put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); + break; - case COL_CLS_TIME: - case COL_REL_TIME: - case COL_ABS_TIME: - case COL_ABS_YMD_TIME: /* XXX - wider */ - case COL_ABS_YDOY_TIME: /* XXX - wider */ - case COL_UTC_TIME: - case COL_UTC_YMD_TIME: /* XXX - wider */ - case COL_UTC_YDOY_TIME: /* XXX - wider */ - column_len = col_len = strlen(col_item->col_data); - if (column_len < 10) - column_len = 10; - line_bufp = get_line_buf(buf_offset + column_len); - put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); - break; + case COL_CLS_TIME: + case COL_REL_TIME: + case COL_ABS_TIME: + case COL_ABS_YMD_TIME: /* XXX - wider */ + case COL_ABS_YDOY_TIME: /* XXX - wider */ + case COL_UTC_TIME: + case COL_UTC_YMD_TIME: /* XXX - wider */ + case COL_UTC_YDOY_TIME: /* XXX - wider */ + column_len = col_len = strlen(col_item->col_data); + if (column_len < 10) + column_len = 10; + line_bufp = get_line_buf(buf_offset + column_len); + put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); + 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: - column_len = col_len = strlen(col_item->col_data); - if (column_len < 12) - column_len = 12; - line_bufp = get_line_buf(buf_offset + column_len); - put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); - 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: + column_len = col_len = strlen(col_item->col_data); + if (column_len < 12) + column_len = 12; + line_bufp = get_line_buf(buf_offset + column_len); + put_spaces_string(line_bufp + buf_offset, col_item->col_data, col_len, column_len); + 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: - column_len = col_len = strlen(col_item->col_data); - if (column_len < 12) - column_len = 12; - line_bufp = get_line_buf(buf_offset + column_len); - put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len); - 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: + column_len = col_len = strlen(col_item->col_data); + if (column_len < 12) + column_len = 12; + line_bufp = get_line_buf(buf_offset + column_len); + put_string_spaces(line_bufp + buf_offset, col_item->col_data, col_len, column_len); + break; - default: - column_len = strlen(col_item->col_data); - line_bufp = get_line_buf(buf_offset + column_len); - put_string(line_bufp + buf_offset, col_item->col_data, column_len); - break; + default: + column_len = strlen(col_item->col_data); + line_bufp = get_line_buf(buf_offset + column_len); + put_string(line_bufp + buf_offset, col_item->col_data, column_len); + break; + } + buf_offset += column_len; + 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 a UTF-8 right arrow; if we printed a network + * destination and are printing a network source of the same + * type next, separate them with a UTF-8 left arrow; + * otherwise separate them with a space. + * + * We add enough space to the buffer for " \xe2\x86\x90 " + * or " \xe2\x86\x92 ", even if we're only adding " ". + */ + line_bufp = get_line_buf(buf_offset + 5); + switch (col_item->col_fmt) { + + case COL_DEF_SRC: + case COL_RES_SRC: + case COL_UNRES_SRC: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_DST: + case COL_RES_DST: + case COL_UNRES_DST: + snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW, delimiter_char); + put_string(line_bufp + buf_offset, str_format, 5); + buf_offset += 5; + break; + + default: + put_string(line_bufp + buf_offset, delimiter_char, 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_DL_SRC: + case COL_RES_DL_SRC: + case COL_UNRES_DL_SRC: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_DL_DST: + case COL_RES_DL_DST: + case COL_UNRES_DL_DST: + snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW, delimiter_char); + put_string(line_bufp + buf_offset, str_format, 5); + buf_offset += 5; + break; + + default: + put_string(line_bufp + buf_offset, delimiter_char, 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_NET_SRC: + case COL_RES_NET_SRC: + case COL_UNRES_NET_SRC: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_NET_DST: + case COL_RES_NET_DST: + case COL_UNRES_NET_DST: + snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW, delimiter_char); + put_string(line_bufp + buf_offset, str_format, 5); + buf_offset += 5; + break; + + default: + put_string(line_bufp + buf_offset, delimiter_char, 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_DST: + case COL_RES_DST: + case COL_UNRES_DST: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_SRC: + case COL_RES_SRC: + case COL_UNRES_SRC: + snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW, delimiter_char); + put_string(line_bufp + buf_offset, str_format, 5); + buf_offset += 5; + break; + + default: + put_string(line_bufp + buf_offset, delimiter_char, 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_DL_DST: + case COL_RES_DL_DST: + case COL_UNRES_DL_DST: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_DL_SRC: + case COL_RES_DL_SRC: + case COL_UNRES_DL_SRC: + snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW, delimiter_char); + put_string(line_bufp + buf_offset, str_format, 5); + buf_offset += 5; + break; + + default: + put_string(line_bufp + buf_offset, delimiter_char, 1); + buf_offset += 1; + break; + } + break; + + case COL_DEF_NET_DST: + case COL_RES_NET_DST: + case COL_UNRES_NET_DST: + switch (cf->cinfo.columns[i+1].col_fmt) { + + case COL_DEF_NET_SRC: + case COL_RES_NET_SRC: + case COL_UNRES_NET_SRC: + snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW, delimiter_char); + put_string(line_bufp + buf_offset, str_format, 5); + buf_offset += 5; + break; + + default: + put_string(line_bufp + buf_offset, delimiter_char, 1); + buf_offset += 1; + break; + } + break; + + default: + put_string(line_bufp + buf_offset, delimiter_char, 1); + buf_offset += 1; + break; + } + } } - buf_offset += column_len; - 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 a UTF-8 right arrow; if we printed a network - * destination and are printing a network source of the same - * type next, separate them with a UTF-8 left arrow; - * otherwise separate them with a space. - * - * We add enough space to the buffer for " \xe2\x86\x90 " - * or " \xe2\x86\x92 ", even if we're only adding " ". - */ - line_bufp = get_line_buf(buf_offset + 5); - switch (col_item->col_fmt) { - case COL_DEF_SRC: - case COL_RES_SRC: - case COL_UNRES_SRC: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_DST: - case COL_RES_DST: - case COL_UNRES_DST: - snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW, delimiter_char); - put_string(line_bufp + buf_offset, str_format, 5); - buf_offset += 5; - break; - - default: - put_string(line_bufp + buf_offset, delimiter_char, 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_DL_SRC: - case COL_RES_DL_SRC: - case COL_UNRES_DL_SRC: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_DL_DST: - case COL_RES_DL_DST: - case COL_UNRES_DL_DST: - snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW, delimiter_char); - put_string(line_bufp + buf_offset, str_format, 5); - buf_offset += 5; - break; - - default: - put_string(line_bufp + buf_offset, delimiter_char, 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_NET_SRC: - case COL_RES_NET_SRC: - case COL_UNRES_NET_SRC: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_NET_DST: - case COL_RES_NET_DST: - case COL_UNRES_NET_DST: - snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_RIGHTWARDS_ARROW, delimiter_char); - put_string(line_bufp + buf_offset, str_format, 5); - buf_offset += 5; - break; - - default: - put_string(line_bufp + buf_offset, delimiter_char, 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_DST: - case COL_RES_DST: - case COL_UNRES_DST: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_SRC: - case COL_RES_SRC: - case COL_UNRES_SRC: - snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW, delimiter_char); - put_string(line_bufp + buf_offset, str_format, 5); - buf_offset += 5; - break; - - default: - put_string(line_bufp + buf_offset, delimiter_char, 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_DL_DST: - case COL_RES_DL_DST: - case COL_UNRES_DL_DST: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_DL_SRC: - case COL_RES_DL_SRC: - case COL_UNRES_DL_SRC: - snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW, delimiter_char); - put_string(line_bufp + buf_offset, str_format, 5); - buf_offset += 5; - break; - - default: - put_string(line_bufp + buf_offset, delimiter_char, 1); - buf_offset += 1; - break; - } - break; - - case COL_DEF_NET_DST: - case COL_RES_NET_DST: - case COL_UNRES_NET_DST: - switch (cf->cinfo.columns[i+1].col_fmt) { - - case COL_DEF_NET_SRC: - case COL_RES_NET_SRC: - case COL_UNRES_NET_SRC: - snprintf(str_format, sizeof(str_format), "%s%s%s", delimiter_char, UTF8_LEFTWARDS_ARROW, delimiter_char); - put_string(line_bufp + buf_offset, str_format, 5); - buf_offset += 5; - break; - - default: - put_string(line_bufp + buf_offset, delimiter_char, 1); - buf_offset += 1; - break; - } - break; - - default: - put_string(line_bufp + buf_offset, delimiter_char, 1); - buf_offset += 1; - break; - } - } - } - - if (dissect_color && color_filter != NULL) - return print_line_color(print_stream, 0, line_bufp, &color_filter->fg_color, &color_filter->bg_color); - else - return print_line(print_stream, 0, line_bufp); + if (dissect_color && color_filter != NULL) + return print_line_color(print_stream, 0, line_bufp, &color_filter->fg_color, &color_filter->bg_color); + else + return print_line(print_stream, 0, line_bufp); } static gboolean print_packet(capture_file *cf, epan_dissect_t *edt) { - if (print_summary || output_fields_has_cols(output_fields)) - /* Just fill in the columns. */ - epan_dissect_fill_in_columns(edt, FALSE, TRUE); + if (print_summary || output_fields_has_cols(output_fields)) + /* Just fill in the columns. */ + epan_dissect_fill_in_columns(edt, FALSE, TRUE); - /* Print summary columns and/or protocol tree */ - switch (output_action) { + /* Print summary columns and/or protocol tree */ + switch (output_action) { - case WRITE_TEXT: - if (print_summary && !print_columns(cf, edt)) - return FALSE; - if (print_details) { - if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none, + case WRITE_TEXT: + if (print_summary && !print_columns(cf, edt)) + return FALSE; + if (print_details) { + if (!proto_tree_print(print_details ? print_dissections_expanded : print_dissections_none, print_hex, edt, output_only_tables, print_stream)) - return FALSE; - if (!print_hex) { + return FALSE; + if (!print_hex) { + if (!print_line(print_stream, 0, separator)) + return FALSE; + } + } + break; + + case WRITE_XML: + if (print_summary) { + write_psml_columns(edt, stdout, dissect_color); + return !ferror(stdout); + } + if (print_details) { + write_pdml_proto_tree(output_fields, protocolfilter, protocolfilter_flags, edt, &cf->cinfo, stdout, dissect_color); + printf("\n"); + return !ferror(stdout); + } + break; + + case WRITE_FIELDS: + if (print_summary) { + /*No non-verbose "fields" format */ + ws_assert_not_reached(); + } + if (print_details) { + write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout); + printf("\n"); + return !ferror(stdout); + } + break; + + case WRITE_JSON: + if (print_summary) + ws_assert_not_reached(); + if (print_details) { + write_json_proto_tree(output_fields, print_dissections_expanded, + print_hex, protocolfilter, protocolfilter_flags, + edt, &cf->cinfo, node_children_grouper, &jdumper); + return !ferror(stdout); + } + break; + + case WRITE_JSON_RAW: + if (print_summary) + ws_assert_not_reached(); + if (print_details) { + write_json_proto_tree(output_fields, print_dissections_none, TRUE, + protocolfilter, protocolfilter_flags, + edt, &cf->cinfo, node_children_grouper, &jdumper); + return !ferror(stdout); + } + break; + + case WRITE_EK: + write_ek_proto_tree(output_fields, print_summary, print_hex, protocolfilter, + protocolfilter_flags, edt, &cf->cinfo, stdout); + return !ferror(stdout); + + default: + ws_assert_not_reached(); + } + + if (print_hex) { + if (print_summary || print_details) { + if (!print_line(print_stream, 0, "")) + return FALSE; + } + if (!print_hex_data(print_stream, edt, hexdump_source_option | hexdump_ascii_option)) + return FALSE; if (!print_line(print_stream, 0, separator)) - return FALSE; - } + return FALSE; } - break; - - case WRITE_XML: - if (print_summary) { - write_psml_columns(edt, stdout, dissect_color); - return !ferror(stdout); - } - if (print_details) { - write_pdml_proto_tree(output_fields, protocolfilter, protocolfilter_flags, edt, &cf->cinfo, stdout, dissect_color); - printf("\n"); - return !ferror(stdout); - } - break; - - case WRITE_FIELDS: - if (print_summary) { - /*No non-verbose "fields" format */ - ws_assert_not_reached(); - } - if (print_details) { - write_fields_proto_tree(output_fields, edt, &cf->cinfo, stdout); - printf("\n"); - return !ferror(stdout); - } - break; - - case WRITE_JSON: - if (print_summary) - ws_assert_not_reached(); - if (print_details) { - write_json_proto_tree(output_fields, print_dissections_expanded, - print_hex, protocolfilter, protocolfilter_flags, - edt, &cf->cinfo, node_children_grouper, &jdumper); - return !ferror(stdout); - } - break; - - case WRITE_JSON_RAW: - if (print_summary) - ws_assert_not_reached(); - if (print_details) { - write_json_proto_tree(output_fields, print_dissections_none, TRUE, - protocolfilter, protocolfilter_flags, - edt, &cf->cinfo, node_children_grouper, &jdumper); - return !ferror(stdout); - } - break; - - case WRITE_EK: - write_ek_proto_tree(output_fields, print_summary, print_hex, protocolfilter, - protocolfilter_flags, edt, &cf->cinfo, stdout); - return !ferror(stdout); - - default: - ws_assert_not_reached(); - } - - if (print_hex) { - if (print_summary || print_details) { - if (!print_line(print_stream, 0, "")) - return FALSE; - } - if (!print_hex_data(print_stream, edt, hexdump_source_option | hexdump_ascii_option)) - return FALSE; - if (!print_line(print_stream, 0, separator)) - return FALSE; - } - return TRUE; + return TRUE; } static gboolean write_finale(void) { - switch (output_action) { + switch (output_action) { - case WRITE_TEXT: - return print_finale(print_stream); + case WRITE_TEXT: + return print_finale(print_stream); - case WRITE_XML: - if (print_details) - write_pdml_finale(stdout); - else - write_psml_finale(stdout); - return !ferror(stdout); + case WRITE_XML: + if (print_details) + write_pdml_finale(stdout); + else + write_psml_finale(stdout); + return !ferror(stdout); - case WRITE_FIELDS: - write_fields_finale(output_fields, stdout); - return !ferror(stdout); + case WRITE_FIELDS: + write_fields_finale(output_fields, stdout); + return !ferror(stdout); - case WRITE_JSON: - case WRITE_JSON_RAW: - write_json_finale(&jdumper); - return !ferror(stdout); + case WRITE_JSON: + case WRITE_JSON_RAW: + write_json_finale(&jdumper); + return !ferror(stdout); - case WRITE_EK: - return TRUE; + case WRITE_EK: + return TRUE; - default: - ws_assert_not_reached(); - return FALSE; - } + default: + ws_assert_not_reached(); + return FALSE; + } } void cf_close(capture_file *cf) { - if (cf->state == FILE_CLOSED) - return; /* Nothing to do */ + if (cf->state == FILE_CLOSED) + return; /* Nothing to do */ - if (cf->provider.wth != NULL) { - wtap_close(cf->provider.wth); - cf->provider.wth = NULL; - } - /* We have no file open... */ - if (cf->filename != NULL) { - /* If it's a temporary file, remove it. */ - if (cf->is_tempfile) - ws_unlink(cf->filename); - g_free(cf->filename); - cf->filename = NULL; - } + if (cf->provider.wth != NULL) { + wtap_close(cf->provider.wth); + cf->provider.wth = NULL; + } + /* We have no file open... */ + if (cf->filename != NULL) { + /* If it's a temporary file, remove it. */ + if (cf->is_tempfile) + ws_unlink(cf->filename); + g_free(cf->filename); + cf->filename = NULL; + } - /* We have no file open. */ - cf->state = FILE_CLOSED; + /* We have no file open. */ + cf->state = FILE_CLOSED; } cf_status_t cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err) { - wtap *wth; - gchar *err_info; + wtap *wth; + gchar *err_info; - wth = wtap_open_offline(fname, type, err, &err_info, perform_two_pass_analysis); - if (wth == NULL) - goto fail; + wth = wtap_open_offline(fname, type, err, &err_info, perform_two_pass_analysis); + if (wth == NULL) + goto fail; - /* The open succeeded. Fill in the information for this file. */ + /* The open succeeded. Fill in the information for this file. */ - cf->provider.wth = wth; - cf->f_datalen = 0; /* not used, but set it anyway */ + cf->provider.wth = wth; + cf->f_datalen = 0; /* not used, but set it anyway */ - /* Set the file name because we need it to set the follow stream filter. - XXX - is that still true? We need it for other reasons, though, - in any case. */ - cf->filename = g_strdup(fname); + /* Set the file name because we need it to set the follow stream filter. + XXX - is that still true? We need it for other reasons, though, + in any case. */ + cf->filename = g_strdup(fname); - /* Indicate whether it's a permanent or temporary file. */ - cf->is_tempfile = is_tempfile; + /* Indicate whether it's a permanent or temporary file. */ + cf->is_tempfile = is_tempfile; - /* No user changes yet. */ - cf->unsaved_changes = FALSE; + /* No user changes yet. */ + cf->unsaved_changes = FALSE; - cf->cd_t = wtap_file_type_subtype(cf->provider.wth); - cf->open_type = type; - cf->count = 0; - cf->drops_known = FALSE; - cf->drops = 0; - cf->snap = wtap_snapshot_length(cf->provider.wth); - nstime_set_zero(&cf->elapsed_time); - cf->provider.ref = NULL; - cf->provider.prev_dis = NULL; - cf->provider.prev_cap = NULL; + cf->cd_t = wtap_file_type_subtype(cf->provider.wth); + cf->open_type = type; + cf->count = 0; + cf->drops_known = FALSE; + cf->drops = 0; + cf->snap = wtap_snapshot_length(cf->provider.wth); + nstime_set_zero(&cf->elapsed_time); + cf->provider.ref = NULL; + cf->provider.prev_dis = NULL; + cf->provider.prev_cap = NULL; - cf->state = FILE_READ_IN_PROGRESS; + cf->state = FILE_READ_IN_PROGRESS; - /* Create new epan session for dissection. */ - epan_free(cf->epan); - cf->epan = tshark_epan_new(cf); + /* Create new epan session for dissection. */ + epan_free(cf->epan); + cf->epan = tshark_epan_new(cf); - wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name); - wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name); - wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); + wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name); + wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name); + wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback); - return CF_OK; + return CF_OK; fail: - cfile_open_failure_message(fname, *err, err_info); - return CF_ERROR; + cfile_open_failure_message(fname, *err, err_info); + return CF_ERROR; } static void show_print_file_io_error(void) { - switch (errno) { + switch (errno) { - case ENOSPC: - cmdarg_err("Not all the packets could be printed because there is " -"no space left on the file system."); - break; + case ENOSPC: + cmdarg_err("Not all the packets could be printed because there is " + "no space left on the file system."); + break; #ifdef EDQUOT - case EDQUOT: - cmdarg_err("Not all the packets could be printed because you are " -"too close to, or over your disk quota."); - break; + case EDQUOT: + cmdarg_err("Not all the packets could be printed because you are " + "too close to, or over your disk quota."); + break; #endif - case EPIPE: - /* - * This almost certainly means "the next program after us in - * the pipeline exited before we were finished writing", so - * this isn't a real error, it just means we're done. (We - * don't get SIGPIPE because libwireshark ignores SIGPIPE - * to avoid getting killed if writing to the MaxMind process - * gets SIGPIPE because that process died.) - * - * Presumably either that program exited deliberately (for - * example, "head -N" read N lines and printed them), in - * which case there's no error to report, or it terminated - * due to an error or a signal, in which case *that's* the - * error and that error has been reported. - */ - break; + case EPIPE: + /* + * This almost certainly means "the next program after us in + * the pipeline exited before we were finished writing", so + * this isn't a real error, it just means we're done. (We + * don't get SIGPIPE because libwireshark ignores SIGPIPE + * to avoid getting killed if writing to the MaxMind process + * gets SIGPIPE because that process died.) + * + * Presumably either that program exited deliberately (for + * example, "head -N" read N lines and printed them), in + * which case there's no error to report, or it terminated + * due to an error or a signal, in which case *that's* the + * error and that error has been reported. + */ + break; - default: + default: #ifdef _WIN32 - if (errno == EINVAL && _doserrno == ERROR_NO_DATA) { - /* - * XXX - on Windows, a write to a pipe where the read side - * has been closed apparently may return the Windows error - * ERROR_BROKEN_PIPE, which the Visual Studio C library maps - * to EPIPE, or may return the Windows error ERROR_NO_DATA, - * which the Visual Studio C library maps to EINVAL. - * - * Either of those almost certainly means "the next program - * after us in the pipeline exited before we were finished - * writing", so, if _doserrno is ERROR_NO_DATA, this isn't - * a real error, it just means we're done. (Windows doesn't - * SIGPIPE.) - * - * Presumably either that program exited deliberately (for - * example, "head -N" read N lines and printed them), in - * which case there's no error to report, or it terminated - * due to an error or a signal, in which case *that's* the - * error and that error has been reported. - */ - break; - } + if (errno == EINVAL && _doserrno == ERROR_NO_DATA) { + /* + * XXX - on Windows, a write to a pipe where the read side + * has been closed apparently may return the Windows error + * ERROR_BROKEN_PIPE, which the Visual Studio C library maps + * to EPIPE, or may return the Windows error ERROR_NO_DATA, + * which the Visual Studio C library maps to EINVAL. + * + * Either of those almost certainly means "the next program + * after us in the pipeline exited before we were finished + * writing", so, if _doserrno is ERROR_NO_DATA, this isn't + * a real error, it just means we're done. (Windows doesn't + * SIGPIPE.) + * + * Presumably either that program exited deliberately (for + * example, "head -N" read N lines and printed them), in + * which case there's no error to report, or it terminated + * due to an error or a signal, in which case *that's* the + * error and that error has been reported. + */ + break; + } - /* - * It's a different error; report it, but with the error - * message for _doserrno, which will give more detail - * than just "Invalid argument". - */ - cmdarg_err("An error occurred while printing packets: %s.", - win32strerror(_doserrno)); + /* + * It's a different error; report it, but with the error + * message for _doserrno, which will give more detail + * than just "Invalid argument". + */ + cmdarg_err("An error occurred while printing packets: %s.", + win32strerror(_doserrno)); #else - cmdarg_err("An error occurred while printing packets: %s.", - g_strerror(errno)); + cmdarg_err("An error occurred while printing packets: %s.", + g_strerror(errno)); #endif - break; - } + break; + } } /* @@ -4626,9 +4630,9 @@ show_print_file_io_error(void) static void tshark_cmdarg_err(const char *msg_format, va_list ap) { - fprintf(stderr, "tshark: "); - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + fprintf(stderr, "tshark: "); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } /* @@ -4637,34 +4641,22 @@ tshark_cmdarg_err(const char *msg_format, va_list ap) static void tshark_cmdarg_err_cont(const char *msg_format, va_list ap) { - vfprintf(stderr, msg_format, ap); - fprintf(stderr, "\n"); + vfprintf(stderr, msg_format, ap); + fprintf(stderr, "\n"); } -static void reset_epan_mem(capture_file *cf,epan_dissect_t *edt, gboolean tree, gboolean visual) +static void +reset_epan_mem(capture_file *cf,epan_dissect_t *edt, gboolean tree, gboolean visual) { - if (!epan_auto_reset || (cf->count < epan_auto_reset_count)) - return; + if (!epan_auto_reset || (cf->count < epan_auto_reset_count)) + return; - fprintf(stderr, "resetting session.\n"); + fprintf(stderr, "resetting session.\n"); - epan_dissect_cleanup(edt); - epan_free(cf->epan); + epan_dissect_cleanup(edt); + epan_free(cf->epan); - cf->epan = tshark_epan_new(cf); - epan_dissect_init(edt, cf->epan, tree, visual); - cf->count = 0; + cf->epan = tshark_epan_new(cf); + epan_dissect_init(edt, cf->epan, tree, visual); + cf->count = 0; } - -/* - * Editor modelines - https://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */