forked from osmocom/wireshark
Remove editor modelines and .editorconfig exceptions from root files
This commit is contained in:
parent
695ce22b0d
commit
70d432c357
|
@ -71,51 +71,3 @@ indent_size = 8
|
||||||
[*.{c,cpp,h}]
|
[*.{c,cpp,h}]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
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
|
|
||||||
|
|
2824
capinfos.c
2824
capinfos.c
File diff suppressed because it is too large
Load Diff
229
captype.c
229
captype.c
|
@ -46,12 +46,12 @@
|
||||||
static void
|
static void
|
||||||
print_usage(FILE *output)
|
print_usage(FILE *output)
|
||||||
{
|
{
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Usage: captype [options] <infile> ...\n");
|
fprintf(output, "Usage: captype [options] <infile> ...\n");
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Miscellaneous:\n");
|
fprintf(output, "Miscellaneous:\n");
|
||||||
fprintf(output, " -h, --help display this help and exit\n");
|
fprintf(output, " -h, --help display this help and exit\n");
|
||||||
fprintf(output, " -v, --version display version info and exit\n");
|
fprintf(output, " -v, --version display version info and exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -60,9 +60,9 @@ print_usage(FILE *output)
|
||||||
static void
|
static void
|
||||||
captype_cmdarg_err(const char *msg_format, va_list ap)
|
captype_cmdarg_err(const char *msg_format, va_list ap)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "captype: ");
|
fprintf(stderr, "captype: ");
|
||||||
vfprintf(stderr, msg_format, ap);
|
vfprintf(stderr, msg_format, ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -71,145 +71,132 @@ captype_cmdarg_err(const char *msg_format, va_list ap)
|
||||||
static void
|
static void
|
||||||
captype_cmdarg_err_cont(const char *msg_format, va_list ap)
|
captype_cmdarg_err_cont(const char *msg_format, va_list ap)
|
||||||
{
|
{
|
||||||
vfprintf(stderr, msg_format, ap);
|
vfprintf(stderr, msg_format, ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *init_progfile_dir_error;
|
char *init_progfile_dir_error;
|
||||||
static const struct report_message_routines captype_report_routines = {
|
static const struct report_message_routines captype_report_routines = {
|
||||||
failure_message,
|
failure_message,
|
||||||
failure_message,
|
failure_message,
|
||||||
open_failure_message,
|
open_failure_message,
|
||||||
read_failure_message,
|
read_failure_message,
|
||||||
write_failure_message,
|
write_failure_message,
|
||||||
cfile_open_failure_message,
|
cfile_open_failure_message,
|
||||||
cfile_dump_open_failure_message,
|
cfile_dump_open_failure_message,
|
||||||
cfile_read_failure_message,
|
cfile_read_failure_message,
|
||||||
cfile_write_failure_message,
|
cfile_write_failure_message,
|
||||||
cfile_close_failure_message
|
cfile_close_failure_message
|
||||||
};
|
};
|
||||||
wtap *wth;
|
wtap *wth;
|
||||||
int err;
|
int err;
|
||||||
gchar *err_info;
|
gchar *err_info;
|
||||||
int i;
|
int i;
|
||||||
int opt;
|
int opt;
|
||||||
int overall_error_status;
|
int overall_error_status;
|
||||||
static const struct ws_option long_options[] = {
|
static const struct ws_option long_options[] = {
|
||||||
{"help", ws_no_argument, NULL, 'h'},
|
{"help", ws_no_argument, NULL, 'h'},
|
||||||
{"version", ws_no_argument, NULL, 'v'},
|
{"version", ws_no_argument, NULL, 'v'},
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the C-language locale to the native environment and set the
|
* Set the C-language locale to the native environment and set the
|
||||||
* code page to UTF-8 on Windows.
|
* code page to UTF-8 on Windows.
|
||||||
*/
|
*/
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
setlocale(LC_ALL, ".UTF-8");
|
setlocale(LC_ALL, ".UTF-8");
|
||||||
#else
|
#else
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
#endif
|
#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. */
|
/* Initialize log handler early so we can have proper logging during startup. */
|
||||||
ws_log_init("captype", vcmdarg_err);
|
ws_log_init("captype", vcmdarg_err);
|
||||||
|
|
||||||
/* Early logging command-line initialization. */
|
/* Early logging command-line initialization. */
|
||||||
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
|
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
|
||||||
|
|
||||||
/* Initialize the version information. */
|
/* Initialize the version information. */
|
||||||
ws_init_version_info("Captype (Wireshark)", NULL, NULL, NULL);
|
ws_init_version_info("Captype (Wireshark)", NULL, NULL, NULL);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
create_app_running_mutex();
|
create_app_running_mutex();
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get credential information for later use.
|
* Get credential information for later use.
|
||||||
*/
|
*/
|
||||||
init_process_policies();
|
init_process_policies();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to get the pathname of the directory containing the
|
* Attempt to get the pathname of the directory containing the
|
||||||
* executable file.
|
* executable file.
|
||||||
*/
|
*/
|
||||||
init_progfile_dir_error = init_progfile_dir(argv[0]);
|
init_progfile_dir_error = init_progfile_dir(argv[0]);
|
||||||
if (init_progfile_dir_error != NULL) {
|
if (init_progfile_dir_error != NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"captype: Can't get pathname of directory containing the captype program: %s.\n",
|
"captype: Can't get pathname of directory containing the captype program: %s.\n",
|
||||||
init_progfile_dir_error);
|
init_progfile_dir_error);
|
||||||
g_free(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 */
|
/* Process the options */
|
||||||
while ((opt = ws_getopt_long(argc, argv, "hv", long_options, NULL)) !=-1) {
|
while ((opt = ws_getopt_long(argc, argv, "hv", long_options, NULL)) !=-1) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
show_help_header("Print the file types of capture files.");
|
show_help_header("Print the file types of capture files.");
|
||||||
print_usage(stdout);
|
print_usage(stdout);
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
show_version();
|
show_version();
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
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);
|
print_usage(stderr);
|
||||||
exit(1);
|
return 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 */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
overall_error_status = 0;
|
||||||
|
|
||||||
wtap_cleanup();
|
for (i = 1; i < argc; i++) {
|
||||||
free_progdirs();
|
wth = wtap_open_offline(argv[i], WTAP_TYPE_AUTO, &err, &err_info, FALSE);
|
||||||
return overall_error_status;
|
|
||||||
|
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:
|
|
||||||
*/
|
|
||||||
|
|
17
cfile.c
17
cfile.c
|
@ -20,19 +20,6 @@
|
||||||
void
|
void
|
||||||
cap_file_init(capture_file *cf)
|
cap_file_init(capture_file *cf)
|
||||||
{
|
{
|
||||||
/* Initialize the capture file struct */
|
/* Initialize the capture file struct */
|
||||||
memset(cf, 0, sizeof(capture_file));
|
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:
|
|
||||||
*/
|
|
||||||
|
|
169
cfile.h
169
cfile.h
|
@ -25,107 +25,107 @@ extern "C" {
|
||||||
|
|
||||||
/* Current state of file. */
|
/* Current state of file. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FILE_CLOSED, /* No file open */
|
FILE_CLOSED, /* No file open */
|
||||||
FILE_READ_IN_PROGRESS, /* Reading a file we've opened */
|
FILE_READ_IN_PROGRESS, /* Reading a file we've opened */
|
||||||
FILE_READ_ABORTED, /* Read aborted by user */
|
FILE_READ_ABORTED, /* Read aborted by user */
|
||||||
FILE_READ_DONE /* Read completed */
|
FILE_READ_DONE /* Read completed */
|
||||||
} file_state;
|
} file_state;
|
||||||
|
|
||||||
/* Requested packets rescan action. */
|
/* Requested packets rescan action. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RESCAN_NONE = 0, /* No rescan requested */
|
RESCAN_NONE = 0, /* No rescan requested */
|
||||||
RESCAN_SCAN, /* Request rescan without full redissection. */
|
RESCAN_SCAN, /* Request rescan without full redissection. */
|
||||||
RESCAN_REDISSECT /* Request full redissection. */
|
RESCAN_REDISSECT /* Request full redissection. */
|
||||||
} rescan_type;
|
} rescan_type;
|
||||||
|
|
||||||
/* Character set for text search. */
|
/* Character set for text search. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SCS_NARROW_AND_WIDE,
|
SCS_NARROW_AND_WIDE,
|
||||||
SCS_NARROW,
|
SCS_NARROW,
|
||||||
SCS_WIDE
|
SCS_WIDE
|
||||||
/* add EBCDIC when it's implemented */
|
/* add EBCDIC when it's implemented */
|
||||||
} search_charset_t;
|
} search_charset_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SD_FORWARD,
|
SD_FORWARD,
|
||||||
SD_BACKWARD
|
SD_BACKWARD
|
||||||
} search_direction;
|
} search_direction;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Packet provider for programs using a capture file.
|
* Packet provider for programs using a capture file.
|
||||||
*/
|
*/
|
||||||
struct packet_provider_data {
|
struct packet_provider_data {
|
||||||
wtap *wth; /* Wiretap session */
|
wtap *wth; /* Wiretap session */
|
||||||
const frame_data *ref;
|
const frame_data *ref;
|
||||||
frame_data *prev_dis;
|
frame_data *prev_dis;
|
||||||
frame_data *prev_cap;
|
frame_data *prev_cap;
|
||||||
frame_data_sequence *frames; /* Sequence of frames, if we're keeping that information */
|
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) */
|
GTree *frames_modified_blocks; /* BST with modified blocks for frames (key = frame_data) */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _capture_file {
|
typedef struct _capture_file {
|
||||||
epan_t *epan;
|
epan_t *epan;
|
||||||
file_state state; /* Current state of capture file */
|
file_state state; /* Current state of capture file */
|
||||||
gchar *filename; /* Name of capture file */
|
gchar *filename; /* Name of capture file */
|
||||||
gchar *source; /* Temp file source, e.g. "Pipe from elsewhere" */
|
gchar *source; /* Temp file source, e.g. "Pipe from elsewhere" */
|
||||||
gboolean is_tempfile; /* Is capture file a temporary file? */
|
gboolean is_tempfile; /* Is capture file a temporary file? */
|
||||||
gboolean unsaved_changes; /* Does the capture file have changes that have not been saved? */
|
gboolean unsaved_changes; /* Does the capture file have changes that have not been saved? */
|
||||||
gboolean stop_flag; /* Stop current processing (loading, searching, etc.) */
|
gboolean stop_flag; /* Stop current processing (loading, searching, etc.) */
|
||||||
|
|
||||||
gint64 f_datalen; /* Size of capture file data (uncompressed) */
|
gint64 f_datalen; /* Size of capture file data (uncompressed) */
|
||||||
guint16 cd_t; /* File type of capture file */
|
guint16 cd_t; /* File type of capture file */
|
||||||
unsigned int open_type; /* open_routine index+1 used, if selected, or WTAP_TYPE_AUTO */
|
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 */
|
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 */
|
int lnk_t; /* File link-layer type; could be WTAP_ENCAP_PER_PACKET */
|
||||||
GArray *linktypes; /* Array of packet link-layer types */
|
GArray *linktypes; /* Array of packet link-layer types */
|
||||||
guint32 count; /* Total number of frames */
|
guint32 count; /* Total number of frames */
|
||||||
guint64 packet_comment_count; /* Number of comments in frames (could be >1 per frame... */
|
guint64 packet_comment_count; /* Number of comments in frames (could be >1 per frame... */
|
||||||
guint32 displayed_count; /* Number of displayed frames */
|
guint32 displayed_count; /* Number of displayed frames */
|
||||||
guint32 marked_count; /* Number of marked frames */
|
guint32 marked_count; /* Number of marked frames */
|
||||||
guint32 ignored_count; /* Number of ignored frames */
|
guint32 ignored_count; /* Number of ignored frames */
|
||||||
guint32 ref_time_count; /* Number of time referenced frames */
|
guint32 ref_time_count; /* Number of time referenced frames */
|
||||||
gboolean drops_known; /* TRUE if we know how many packets were dropped */
|
gboolean drops_known; /* TRUE if we know how many packets were dropped */
|
||||||
guint32 drops; /* Dropped packets */
|
guint32 drops; /* Dropped packets */
|
||||||
nstime_t elapsed_time; /* Elapsed time */
|
nstime_t elapsed_time; /* Elapsed time */
|
||||||
int snap; /* Maximum captured packet length; 0 if unknown */
|
int snap; /* Maximum captured packet length; 0 if unknown */
|
||||||
dfilter_t *rfcode; /* Compiled read filter program */
|
dfilter_t *rfcode; /* Compiled read filter program */
|
||||||
dfilter_t *dfcode; /* Compiled display filter program */
|
dfilter_t *dfcode; /* Compiled display filter program */
|
||||||
gchar *dfilter; /* Display filter string */
|
gchar *dfilter; /* Display filter string */
|
||||||
gboolean redissecting; /* TRUE if currently redissecting (cf_redissect_packets) */
|
gboolean redissecting; /* TRUE if currently redissecting (cf_redissect_packets) */
|
||||||
gboolean read_lock; /* TRUE if currently processing a file (cf_read) */
|
gboolean read_lock; /* TRUE if currently processing a file (cf_read) */
|
||||||
rescan_type redissection_queued; /* Queued redissection type. */
|
rescan_type redissection_queued; /* Queued redissection type. */
|
||||||
/* search */
|
/* search */
|
||||||
gchar *sfilter; /* Filter, hex value, or string being searched */
|
gchar *sfilter; /* Filter, hex value, or string being searched */
|
||||||
gboolean hex; /* TRUE if "Hex value" search was last selected */
|
gboolean hex; /* TRUE if "Hex value" search was last selected */
|
||||||
gboolean string; /* TRUE if "String" 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 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 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 */
|
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_pos; /* Byte position of last byte found in a hex search */
|
||||||
guint32 search_len; /* Length of bytes matching the search */
|
guint32 search_len; /* Length of bytes matching the search */
|
||||||
gboolean case_type; /* TRUE if case-insensitive text search */
|
gboolean case_type; /* TRUE if case-insensitive text search */
|
||||||
GRegex *regex; /* Set if regular expression search */
|
GRegex *regex; /* Set if regular expression search */
|
||||||
search_charset_t scs_type; /* Character set for text search */
|
search_charset_t scs_type; /* Character set for text search */
|
||||||
search_direction dir; /* Direction in which to do searches */
|
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 <control>N/B */
|
gboolean search_in_progress; /* TRUE if user just clicked OK in the Find dialog or hit <control>N/B */
|
||||||
/* packet provider */
|
/* packet provider */
|
||||||
struct packet_provider_data provider;
|
struct packet_provider_data provider;
|
||||||
/* frames */
|
/* frames */
|
||||||
guint32 first_displayed; /* Frame number of first frame displayed */
|
guint32 first_displayed; /* Frame number of first frame displayed */
|
||||||
guint32 last_displayed; /* Frame number of last frame displayed */
|
guint32 last_displayed; /* Frame number of last frame displayed */
|
||||||
/* Data for currently selected frame */
|
/* Data for currently selected frame */
|
||||||
column_info cinfo; /* Column formatting information */
|
column_info cinfo; /* Column formatting information */
|
||||||
frame_data *current_frame; /* Frame data */
|
frame_data *current_frame; /* Frame data */
|
||||||
gint current_row; /* Row number */
|
gint current_row; /* Row number */
|
||||||
epan_dissect_t *edt; /* Protocol dissection */
|
epan_dissect_t *edt; /* Protocol dissection */
|
||||||
field_info *finfo_selected; /* Field info */
|
field_info *finfo_selected; /* Field info */
|
||||||
wtap_rec rec; /* Record header */
|
wtap_rec rec; /* Record header */
|
||||||
Buffer buf; /* Record data */
|
Buffer buf; /* Record data */
|
||||||
|
|
||||||
gpointer window; /* Top-level window associated with file */
|
gpointer window; /* Top-level window associated with file */
|
||||||
gulong computed_elapsed; /* Elapsed time to load the file (in msec). */
|
gulong computed_elapsed; /* Elapsed time to load the file (in msec). */
|
||||||
|
|
||||||
guint32 cum_bytes;
|
guint32 cum_bytes;
|
||||||
} capture_file;
|
} capture_file;
|
||||||
|
|
||||||
extern void cap_file_init(capture_file *cf);
|
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 /* __cplusplus */
|
||||||
|
|
||||||
#endif /* cfile.h */
|
#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:
|
|
||||||
*/
|
|
||||||
|
|
197
dftest.c
197
dftest.c
|
@ -43,115 +43,115 @@ static void dftest_cmdarg_err_cont(const char *fmt, va_list ap);
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *init_progfile_dir_error;
|
char *init_progfile_dir_error;
|
||||||
static const struct report_message_routines dftest_report_routines = {
|
static const struct report_message_routines dftest_report_routines = {
|
||||||
failure_message,
|
failure_message,
|
||||||
failure_message,
|
failure_message,
|
||||||
open_failure_message,
|
open_failure_message,
|
||||||
read_failure_message,
|
read_failure_message,
|
||||||
write_failure_message,
|
write_failure_message,
|
||||||
cfile_open_failure_message,
|
cfile_open_failure_message,
|
||||||
cfile_dump_open_failure_message,
|
cfile_dump_open_failure_message,
|
||||||
cfile_read_failure_message,
|
cfile_read_failure_message,
|
||||||
cfile_write_failure_message,
|
cfile_write_failure_message,
|
||||||
cfile_close_failure_message
|
cfile_close_failure_message
|
||||||
};
|
};
|
||||||
char *text;
|
char *text;
|
||||||
dfilter_t *df;
|
dfilter_t *df;
|
||||||
gchar *err_msg;
|
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. */
|
/* Initialize log handler early so we can have proper logging during startup. */
|
||||||
ws_log_init("dftest", vcmdarg_err);
|
ws_log_init("dftest", vcmdarg_err);
|
||||||
|
|
||||||
/* Early logging command-line initialization. */
|
/* Early logging command-line initialization. */
|
||||||
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
|
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get credential information for later use.
|
* Get credential information for later use.
|
||||||
*/
|
*/
|
||||||
init_process_policies();
|
init_process_policies();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to get the pathname of the directory containing the
|
* Attempt to get the pathname of the directory containing the
|
||||||
* executable file.
|
* executable file.
|
||||||
*/
|
*/
|
||||||
init_progfile_dir_error = init_progfile_dir(argv[0]);
|
init_progfile_dir_error = init_progfile_dir(argv[0]);
|
||||||
if (init_progfile_dir_error != NULL) {
|
if (init_progfile_dir_error != NULL) {
|
||||||
fprintf(stderr, "dftest: Can't get pathname of directory containing the dftest program: %s.\n",
|
fprintf(stderr, "dftest: Can't get pathname of directory containing the dftest program: %s.\n",
|
||||||
init_progfile_dir_error);
|
init_progfile_dir_error);
|
||||||
g_free(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_type(TS_RELATIVE);
|
||||||
timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
|
timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Libwiretap must be initialized before libwireshark is, so that
|
* Libwiretap must be initialized before libwireshark is, so that
|
||||||
* dissection-time handlers for file-type-dependent blocks can
|
* dissection-time handlers for file-type-dependent blocks can
|
||||||
* register using the file type/subtype value for the file type.
|
* register using the file type/subtype value for the file type.
|
||||||
*/
|
*/
|
||||||
wtap_init(TRUE);
|
wtap_init(TRUE);
|
||||||
|
|
||||||
/* Register all dissectors; we must do this before checking for the
|
/* Register all dissectors; we must do this before checking for the
|
||||||
"-g" flag, as the "-g" flag dumps a list of fields registered
|
"-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,
|
by the dissectors, and we must do it before we read the preferences,
|
||||||
in case any dissectors register preferences. */
|
in case any dissectors register preferences. */
|
||||||
if (!epan_init(NULL, NULL, FALSE))
|
if (!epan_init(NULL, NULL, FALSE))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the C-language locale to the native environment and set the
|
* Set the C-language locale to the native environment and set the
|
||||||
* code page to UTF-8 on Windows.
|
* code page to UTF-8 on Windows.
|
||||||
*/
|
*/
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
setlocale(LC_ALL, ".UTF-8");
|
setlocale(LC_ALL, ".UTF-8");
|
||||||
#else
|
#else
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Load libwireshark settings from the current profile. */
|
/* Load libwireshark settings from the current profile. */
|
||||||
epan_load_settings();
|
epan_load_settings();
|
||||||
|
|
||||||
/* notify all registered modules that have had any of their preferences
|
/* notify all registered modules that have had any of their preferences
|
||||||
changed either from one of the preferences file or from the command
|
changed either from one of the preferences file or from the command
|
||||||
line that its preferences have changed. */
|
line that its preferences have changed. */
|
||||||
prefs_apply_all();
|
prefs_apply_all();
|
||||||
|
|
||||||
/* Check for filter on command line */
|
/* Check for filter on command line */
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
fprintf(stderr, "Usage: dftest <filter>\n");
|
fprintf(stderr, "Usage: dftest <filter>\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get filter text */
|
/* Get filter text */
|
||||||
text = get_args_as_string(argc, argv, 1);
|
text = get_args_as_string(argc, argv, 1);
|
||||||
|
|
||||||
printf("Filter: %s\n", text);
|
printf("Filter: %s\n", text);
|
||||||
|
|
||||||
/* Compile it */
|
/* Compile it */
|
||||||
if (!dfilter_compile(text, &df, &err_msg)) {
|
if (!dfilter_compile(text, &df, &err_msg)) {
|
||||||
fprintf(stderr, "dftest: %s\n", err_msg);
|
fprintf(stderr, "dftest: %s\n", err_msg);
|
||||||
g_free(err_msg);
|
g_free(err_msg);
|
||||||
epan_cleanup();
|
epan_cleanup();
|
||||||
g_free(text);
|
g_free(text);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if (df == NULL)
|
if (df == NULL)
|
||||||
printf("Filter is empty\n");
|
printf("Filter is empty\n");
|
||||||
else
|
else
|
||||||
dfilter_dump(df);
|
dfilter_dump(df);
|
||||||
|
|
||||||
dfilter_free(df);
|
dfilter_free(df);
|
||||||
epan_cleanup();
|
epan_cleanup();
|
||||||
g_free(text);
|
g_free(text);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -160,9 +160,9 @@ main(int argc, char **argv)
|
||||||
static void
|
static void
|
||||||
dftest_cmdarg_err(const char *fmt, va_list ap)
|
dftest_cmdarg_err(const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dftest: ");
|
fprintf(stderr, "dftest: ");
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -171,19 +171,6 @@ dftest_cmdarg_err(const char *fmt, va_list ap)
|
||||||
static void
|
static void
|
||||||
dftest_cmdarg_err_cont(const char *fmt, va_list ap)
|
dftest_cmdarg_err_cont(const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
fprintf(stderr, "\n");
|
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:
|
|
||||||
*/
|
|
||||||
|
|
13
file.h
13
file.h
|
@ -735,16 +735,3 @@ gboolean cf_add_ip_name_from_string(capture_file *cf, const char *addr, const ch
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif /* file.h */
|
#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:
|
|
||||||
*/
|
|
||||||
|
|
387
frame_tvbuff.c
387
frame_tvbuff.c
|
@ -21,36 +21,36 @@
|
||||||
#include "wiretap/wtap-int.h" /* for ->random_fh */
|
#include "wiretap/wtap-int.h" /* for ->random_fh */
|
||||||
|
|
||||||
struct tvb_frame {
|
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 */
|
const struct packet_provider_data *prov; /* provider of packet information */
|
||||||
gint64 file_off; /**< File offset */
|
gint64 file_off; /**< File offset */
|
||||||
|
|
||||||
guint offset;
|
guint offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
frame_read(struct tvb_frame *frame_tvb, wtap_rec *rec, Buffer *buf)
|
frame_read(struct tvb_frame *frame_tvb, wtap_rec *rec, Buffer *buf)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
gchar *err_info;
|
gchar *err_info;
|
||||||
gboolean ok = TRUE;
|
gboolean ok = TRUE;
|
||||||
|
|
||||||
/* XXX, what if phdr->caplen isn't equal to
|
/* XXX, what if phdr->caplen isn't equal to
|
||||||
* frame_tvb->tvb.length + frame_tvb->offset?
|
* frame_tvb->tvb.length + frame_tvb->offset?
|
||||||
*/
|
*/
|
||||||
if (!wtap_seek_read(frame_tvb->prov->wth, frame_tvb->file_off, rec, buf, &err, &err_info)) {
|
if (!wtap_seek_read(frame_tvb->prov->wth, frame_tvb->file_off, rec, buf, &err, &err_info)) {
|
||||||
/* XXX - report error! */
|
/* XXX - report error! */
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case WTAP_ERR_BAD_FILE:
|
case WTAP_ERR_BAD_FILE:
|
||||||
g_free(err_info);
|
g_free(err_info);
|
||||||
ok = FALSE;
|
ok = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GPtrArray *buffer_cache = NULL;
|
static GPtrArray *buffer_cache = NULL;
|
||||||
|
@ -58,287 +58,274 @@ static GPtrArray *buffer_cache = NULL;
|
||||||
static void
|
static void
|
||||||
frame_cache(struct tvb_frame *frame_tvb)
|
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 (frame_tvb->buf == NULL) {
|
||||||
if (G_UNLIKELY(!buffer_cache)) buffer_cache = g_ptr_array_sized_new(1024);
|
if (G_UNLIKELY(!buffer_cache)) buffer_cache = g_ptr_array_sized_new(1024);
|
||||||
|
|
||||||
if (buffer_cache->len > 0) {
|
if (buffer_cache->len > 0) {
|
||||||
frame_tvb->buf = (struct Buffer *) g_ptr_array_remove_index(buffer_cache, buffer_cache->len - 1);
|
frame_tvb->buf = (struct Buffer *) g_ptr_array_remove_index(buffer_cache, buffer_cache->len - 1);
|
||||||
} else {
|
} else {
|
||||||
frame_tvb->buf = g_new(struct Buffer, 1);
|
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))
|
if (!frame_read(frame_tvb, &rec, frame_tvb->buf))
|
||||||
{ /* TODO: THROW(???); */ }
|
{ /* 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
|
static void
|
||||||
frame_free(tvbuff_t *tvb)
|
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) {
|
if (frame_tvb->buf) {
|
||||||
ws_buffer_free(frame_tvb->buf);
|
ws_buffer_free(frame_tvb->buf);
|
||||||
g_ptr_array_add(buffer_cache, frame_tvb->buf);
|
g_ptr_array_add(buffer_cache, frame_tvb->buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const guint8 *
|
static const guint8 *
|
||||||
frame_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length _U_)
|
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 *
|
static void *
|
||||||
frame_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
|
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
|
static gint
|
||||||
frame_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
|
frame_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
|
||||||
{
|
{
|
||||||
struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
|
struct tvb_frame *frame_tvb = (struct tvb_frame *) tvb;
|
||||||
const guint8 *result;
|
const guint8 *result;
|
||||||
|
|
||||||
frame_cache(frame_tvb);
|
frame_cache(frame_tvb);
|
||||||
|
|
||||||
result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit);
|
result = (const guint8 *)memchr(tvb->real_data + abs_offset, needle, limit);
|
||||||
if (result)
|
if (result)
|
||||||
return (gint) (result - tvb->real_data);
|
return (gint) (result - tvb->real_data);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
frame_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle)
|
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
|
static guint
|
||||||
frame_offset(const tvbuff_t *tvb _U_, const guint counter)
|
frame_offset(const tvbuff_t *tvb _U_, const guint counter)
|
||||||
{
|
{
|
||||||
/* XXX: frame_tvb->offset */
|
/* XXX: frame_tvb->offset */
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tvbuff_t *frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length);
|
static tvbuff_t *frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length);
|
||||||
|
|
||||||
static const struct tvb_ops tvb_frame_ops = {
|
static const struct tvb_ops tvb_frame_ops = {
|
||||||
sizeof(struct tvb_frame), /* size */
|
sizeof(struct tvb_frame), /* size */
|
||||||
|
|
||||||
frame_free, /* free */
|
frame_free, /* free */
|
||||||
frame_offset, /* offset */
|
frame_offset, /* offset */
|
||||||
frame_get_ptr, /* get_ptr */
|
frame_get_ptr, /* get_ptr */
|
||||||
frame_memcpy, /* memcpy */
|
frame_memcpy, /* memcpy */
|
||||||
frame_find_guint8, /* find_guint8 */
|
frame_find_guint8, /* find_guint8 */
|
||||||
frame_pbrk_guint8, /* pbrk_guint8 */
|
frame_pbrk_guint8, /* pbrk_guint8 */
|
||||||
frame_clone, /* clone */
|
frame_clone, /* clone */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* based on tvb_new_real_data() */
|
/* based on tvb_new_real_data() */
|
||||||
tvbuff_t *
|
tvbuff_t *
|
||||||
frame_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd,
|
frame_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd,
|
||||||
const guint8 *buf)
|
const guint8 *buf)
|
||||||
{
|
{
|
||||||
struct tvb_frame *frame_tvb;
|
struct tvb_frame *frame_tvb;
|
||||||
tvbuff_t *tvb;
|
tvbuff_t *tvb;
|
||||||
|
|
||||||
tvb = tvb_new(&tvb_frame_ops);
|
tvb = tvb_new(&tvb_frame_ops);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX - currently, the length arguments in
|
* XXX - currently, the length arguments in
|
||||||
* tvbuff structure are signed, but the captured
|
* tvbuff structure are signed, but the captured
|
||||||
* and reported length values are unsigned; this means
|
* and reported length values are unsigned; this means
|
||||||
* that length values > 2^31 - 1 will appear as
|
* that length values > 2^31 - 1 will appear as
|
||||||
* negative lengths
|
* negative lengths
|
||||||
*
|
*
|
||||||
* Captured length values that large will already
|
* Captured length values that large will already
|
||||||
* have been filtered out by the Wiretap modules
|
* have been filtered out by the Wiretap modules
|
||||||
* (the file will be reported as corrupted), to
|
* (the file will be reported as corrupted), to
|
||||||
* avoid trying to allocate large chunks of data.
|
* avoid trying to allocate large chunks of data.
|
||||||
*
|
*
|
||||||
* Reported length values will not have been
|
* Reported length values will not have been
|
||||||
* filtered out, and should not be filtered out,
|
* filtered out, and should not be filtered out,
|
||||||
* as those lengths are not necessarily invalid.
|
* as those lengths are not necessarily invalid.
|
||||||
*
|
*
|
||||||
* For now, we clip the reported length at G_MAXINT
|
* For now, we clip the reported length at G_MAXINT
|
||||||
*
|
*
|
||||||
* (XXX, is this still a problem?) There was an exception when we call
|
* (XXX, is this still a problem?) There was an exception when we call
|
||||||
* tvb_new_real_data() now there's no one
|
* tvb_new_real_data() now there's no one
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tvb->real_data = buf;
|
tvb->real_data = buf;
|
||||||
tvb->length = fd->cap_len;
|
tvb->length = fd->cap_len;
|
||||||
tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
|
tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
|
||||||
tvb->contained_length = tvb->reported_length;
|
tvb->contained_length = tvb->reported_length;
|
||||||
tvb->initialized = TRUE;
|
tvb->initialized = TRUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the top-level real tvbuff for this data source,
|
* This is the top-level real tvbuff for this data source,
|
||||||
* so its data source tvbuff is itself.
|
* so its data source tvbuff is itself.
|
||||||
*/
|
*/
|
||||||
tvb->ds_tvb = tvb;
|
tvb->ds_tvb = tvb;
|
||||||
|
|
||||||
frame_tvb = (struct tvb_frame *) tvb;
|
frame_tvb = (struct tvb_frame *) tvb;
|
||||||
|
|
||||||
/* XXX, wtap_can_seek() */
|
/* XXX, wtap_can_seek() */
|
||||||
if (prov->wth && prov->wth->random_fh) {
|
if (prov->wth && prov->wth->random_fh) {
|
||||||
frame_tvb->prov = prov;
|
frame_tvb->prov = prov;
|
||||||
frame_tvb->file_off = fd->file_off;
|
frame_tvb->file_off = fd->file_off;
|
||||||
frame_tvb->offset = 0;
|
frame_tvb->offset = 0;
|
||||||
} else
|
} else
|
||||||
frame_tvb->prov = NULL;
|
frame_tvb->prov = NULL;
|
||||||
|
|
||||||
frame_tvb->buf = NULL;
|
frame_tvb->buf = NULL;
|
||||||
|
|
||||||
return tvb;
|
return tvb;
|
||||||
}
|
}
|
||||||
|
|
||||||
tvbuff_t *
|
tvbuff_t *
|
||||||
frame_tvbuff_new_buffer(const struct packet_provider_data *prov,
|
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 *
|
static tvbuff_t *
|
||||||
frame_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
|
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;
|
tvbuff_t *cloned_tvb;
|
||||||
struct tvb_frame *cloned_frame_tvb;
|
struct tvb_frame *cloned_frame_tvb;
|
||||||
|
|
||||||
/* file not seekable */
|
/* file not seekable */
|
||||||
if (!frame_tvb->prov)
|
if (!frame_tvb->prov)
|
||||||
return NULL;
|
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 */
|
/* data will be read when needed */
|
||||||
cloned_tvb->real_data = NULL;
|
cloned_tvb->real_data = NULL;
|
||||||
cloned_tvb->length = abs_length;
|
cloned_tvb->length = abs_length;
|
||||||
cloned_tvb->reported_length = abs_length; /* XXX? */
|
cloned_tvb->reported_length = abs_length; /* XXX? */
|
||||||
cloned_tvb->contained_length = cloned_tvb->reported_length;
|
cloned_tvb->contained_length = cloned_tvb->reported_length;
|
||||||
cloned_tvb->initialized = TRUE;
|
cloned_tvb->initialized = TRUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the top-level real tvbuff for this data source,
|
* This is the top-level real tvbuff for this data source,
|
||||||
* so its data source tvbuff is itself.
|
* so its data source tvbuff is itself.
|
||||||
*/
|
*/
|
||||||
cloned_tvb->ds_tvb = cloned_tvb;
|
cloned_tvb->ds_tvb = cloned_tvb;
|
||||||
|
|
||||||
cloned_frame_tvb = (struct tvb_frame *) cloned_tvb;
|
cloned_frame_tvb = (struct tvb_frame *) cloned_tvb;
|
||||||
cloned_frame_tvb->prov = frame_tvb->prov;
|
cloned_frame_tvb->prov = frame_tvb->prov;
|
||||||
cloned_frame_tvb->file_off = frame_tvb->file_off;
|
cloned_frame_tvb->file_off = frame_tvb->file_off;
|
||||||
cloned_frame_tvb->offset = abs_offset;
|
cloned_frame_tvb->offset = abs_offset;
|
||||||
cloned_frame_tvb->buf = NULL;
|
cloned_frame_tvb->buf = NULL;
|
||||||
|
|
||||||
return cloned_tvb;
|
return cloned_tvb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* based on tvb_new_real_data() */
|
/* based on tvb_new_real_data() */
|
||||||
tvbuff_t *
|
tvbuff_t *
|
||||||
file_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd,
|
file_tvbuff_new(const struct packet_provider_data *prov, const frame_data *fd,
|
||||||
const guint8 *buf)
|
const guint8 *buf)
|
||||||
{
|
{
|
||||||
struct tvb_frame *frame_tvb;
|
struct tvb_frame *frame_tvb;
|
||||||
tvbuff_t *tvb;
|
tvbuff_t *tvb;
|
||||||
|
|
||||||
tvb = tvb_new(&tvb_frame_ops);
|
tvb = tvb_new(&tvb_frame_ops);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX - currently, the length arguments in
|
* XXX - currently, the length arguments in
|
||||||
* tvbuff structure are signed, but the captured
|
* tvbuff structure are signed, but the captured
|
||||||
* and reported length values are unsigned; this means
|
* and reported length values are unsigned; this means
|
||||||
* that length values > 2^31 - 1 will appear as
|
* that length values > 2^31 - 1 will appear as
|
||||||
* negative lengths
|
* negative lengths
|
||||||
*
|
*
|
||||||
* Captured length values that large will already
|
* Captured length values that large will already
|
||||||
* have been filtered out by the Wiretap modules
|
* have been filtered out by the Wiretap modules
|
||||||
* (the file will be reported as corrupted), to
|
* (the file will be reported as corrupted), to
|
||||||
* avoid trying to allocate large chunks of data.
|
* avoid trying to allocate large chunks of data.
|
||||||
*
|
*
|
||||||
* Reported length values will not have been
|
* Reported length values will not have been
|
||||||
* filtered out, and should not be filtered out,
|
* filtered out, and should not be filtered out,
|
||||||
* as those lengths are not necessarily invalid.
|
* as those lengths are not necessarily invalid.
|
||||||
*
|
*
|
||||||
* For now, we clip the reported length at G_MAXINT
|
* For now, we clip the reported length at G_MAXINT
|
||||||
*
|
*
|
||||||
* (XXX, is this still a problem?) There was an exception when we call
|
* (XXX, is this still a problem?) There was an exception when we call
|
||||||
* tvb_new_real_data() now there's no one
|
* tvb_new_real_data() now there's no one
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tvb->real_data = buf;
|
tvb->real_data = buf;
|
||||||
tvb->length = fd->cap_len;
|
tvb->length = fd->cap_len;
|
||||||
tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
|
tvb->reported_length = fd->pkt_len > G_MAXINT ? G_MAXINT : fd->pkt_len;
|
||||||
tvb->contained_length = tvb->reported_length;
|
tvb->contained_length = tvb->reported_length;
|
||||||
tvb->initialized = TRUE;
|
tvb->initialized = TRUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the top-level real tvbuff for this data source,
|
* This is the top-level real tvbuff for this data source,
|
||||||
* so its data source tvbuff is itself.
|
* so its data source tvbuff is itself.
|
||||||
*/
|
*/
|
||||||
tvb->ds_tvb = tvb;
|
tvb->ds_tvb = tvb;
|
||||||
|
|
||||||
frame_tvb = (struct tvb_frame *) tvb;
|
frame_tvb = (struct tvb_frame *) tvb;
|
||||||
|
|
||||||
/* XXX, wtap_can_seek() */
|
/* XXX, wtap_can_seek() */
|
||||||
if (prov->wth && prov->wth->random_fh) {
|
if (prov->wth && prov->wth->random_fh) {
|
||||||
frame_tvb->prov = prov;
|
frame_tvb->prov = prov;
|
||||||
frame_tvb->file_off = fd->file_off;
|
frame_tvb->file_off = fd->file_off;
|
||||||
frame_tvb->offset = 0;
|
frame_tvb->offset = 0;
|
||||||
} else
|
} else
|
||||||
frame_tvb->prov = NULL;
|
frame_tvb->prov = NULL;
|
||||||
|
|
||||||
frame_tvb->buf = NULL;
|
frame_tvb->buf = NULL;
|
||||||
|
|
||||||
return tvb;
|
return tvb;
|
||||||
}
|
}
|
||||||
|
|
||||||
tvbuff_t *
|
tvbuff_t *
|
||||||
file_tvbuff_new_buffer(const struct packet_provider_data *prov,
|
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:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -37,16 +37,3 @@ extern tvbuff_t *file_tvbuff_new_buffer(const struct packet_provider_data *prov,
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif /* __FRAME_TVBUFF_H__ */
|
#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:
|
|
||||||
*/
|
|
||||||
|
|
615
mergecap.c
615
mergecap.c
|
@ -52,23 +52,23 @@
|
||||||
static void
|
static void
|
||||||
print_usage(FILE *output)
|
print_usage(FILE *output)
|
||||||
{
|
{
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Usage: mergecap [options] -w <outfile>|- <infile> [<infile> ...]\n");
|
fprintf(output, "Usage: mergecap [options] -w <outfile>|- <infile> [<infile> ...]\n");
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Output:\n");
|
fprintf(output, "Output:\n");
|
||||||
fprintf(output, " -a concatenate rather than merge files.\n");
|
fprintf(output, " -a concatenate rather than merge files.\n");
|
||||||
fprintf(output, " default is to merge based on frame timestamps.\n");
|
fprintf(output, " default is to merge based on frame timestamps.\n");
|
||||||
fprintf(output, " -s <snaplen> truncate packets to <snaplen> bytes of data.\n");
|
fprintf(output, " -s <snaplen> truncate packets to <snaplen> bytes of data.\n");
|
||||||
fprintf(output, " -w <outfile>|- set the output filename to <outfile> or '-' for stdout.\n");
|
fprintf(output, " -w <outfile>|- set the output filename to <outfile> or '-' for stdout.\n");
|
||||||
fprintf(output, " -F <capture type> set the output file type; default is pcapng.\n");
|
fprintf(output, " -F <capture type> set the output file type; default is pcapng.\n");
|
||||||
fprintf(output, " an empty \"-F\" option will list the file types.\n");
|
fprintf(output, " an empty \"-F\" option will list the file types.\n");
|
||||||
fprintf(output, " -I <IDB merge mode> set the merge mode for Interface Description Blocks; default is 'all'.\n");
|
fprintf(output, " -I <IDB merge mode> 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, " an empty \"-I\" option will list the merge modes.\n");
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Miscellaneous:\n");
|
fprintf(output, "Miscellaneous:\n");
|
||||||
fprintf(output, " -h display this help and exit.\n");
|
fprintf(output, " -h display this help and exit.\n");
|
||||||
fprintf(output, " -v verbose output.\n");
|
fprintf(output, " -v verbose output.\n");
|
||||||
fprintf(output, " -V print version information and exit.\n");
|
fprintf(output, " -V print version information and exit.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -77,9 +77,9 @@ print_usage(FILE *output)
|
||||||
static void
|
static void
|
||||||
mergecap_cmdarg_err(const char *fmt, va_list ap)
|
mergecap_cmdarg_err(const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "mergecap: ");
|
fprintf(stderr, "mergecap: ");
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -88,352 +88,339 @@ mergecap_cmdarg_err(const char *fmt, va_list ap)
|
||||||
static void
|
static void
|
||||||
mergecap_cmdarg_err_cont(const char *fmt, va_list ap)
|
mergecap_cmdarg_err_cont(const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
list_capture_types(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");
|
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);
|
writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME);
|
||||||
for (guint i = 0; i < writable_type_subtypes->len; i++) {
|
for (guint i = 0; i < writable_type_subtypes->len; i++) {
|
||||||
int ft = g_array_index(writable_type_subtypes, int, i);
|
int ft = g_array_index(writable_type_subtypes, int, i);
|
||||||
fprintf(stderr, " %s - %s\n", wtap_file_type_subtype_name(ft),
|
fprintf(stderr, " %s - %s\n", wtap_file_type_subtype_name(ft),
|
||||||
wtap_file_type_subtype_description(ft));
|
wtap_file_type_subtype_description(ft));
|
||||||
}
|
}
|
||||||
g_array_free(writable_type_subtypes, TRUE);
|
g_array_free(writable_type_subtypes, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
list_idb_merge_modes(void) {
|
list_idb_merge_modes(void) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf(stderr, "mergecap: The available IDB merge modes for the \"-I\" flag are:\n");
|
fprintf(stderr, "mergecap: The available IDB merge modes for the \"-I\" flag are:\n");
|
||||||
for (i = 0; i < IDB_MERGE_MODE_MAX; i++) {
|
for (i = 0; i < IDB_MERGE_MODE_MAX; i++) {
|
||||||
fprintf(stderr, " %s\n", merge_idb_merge_mode_to_string(i));
|
fprintf(stderr, " %s\n", merge_idb_merge_mode_to_string(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
merge_callback(merge_event event, int num,
|
merge_callback(merge_event event, int num,
|
||||||
const merge_in_file_t in_files[], const guint in_file_count,
|
const merge_in_file_t in_files[], const guint in_file_count,
|
||||||
void *data _U_)
|
void *data _U_)
|
||||||
{
|
{
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
|
|
||||||
case MERGE_EVENT_INPUT_FILES_OPENED:
|
case MERGE_EVENT_INPUT_FILES_OPENED:
|
||||||
for (i = 0; i < in_file_count; i++) {
|
for (i = 0; i < in_file_count; i++) {
|
||||||
fprintf(stderr, "mergecap: %s is type %s.\n", in_files[i].filename,
|
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)));
|
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));
|
|
||||||
break;
|
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:
|
case MERGE_EVENT_FRAME_TYPE_SELECTED:
|
||||||
fprintf(stderr, "mergecap: ready to merge records\n");
|
/* for this event, num = frame_type */
|
||||||
break;
|
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:
|
first_frame_type = wtap_file_encap(in_files[0].wth);
|
||||||
/* for this event, num = count */
|
for (i = 1; i < in_file_count; i++) {
|
||||||
fprintf(stderr, "Record: %d\n", num);
|
this_frame_type = wtap_file_encap(in_files[i].wth);
|
||||||
break;
|
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:
|
case MERGE_EVENT_READY_TO_MERGE:
|
||||||
fprintf(stderr, "mergecap: merging complete\n");
|
fprintf(stderr, "mergecap: ready to merge records\n");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* false = do not stop merging */
|
case MERGE_EVENT_RECORD_WAS_READ:
|
||||||
return FALSE;
|
/* 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
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *init_progfile_dir_error;
|
char *init_progfile_dir_error;
|
||||||
static const struct report_message_routines mergecap_report_routines = {
|
static const struct report_message_routines mergecap_report_routines = {
|
||||||
failure_message,
|
failure_message,
|
||||||
failure_message,
|
failure_message,
|
||||||
open_failure_message,
|
open_failure_message,
|
||||||
read_failure_message,
|
read_failure_message,
|
||||||
write_failure_message,
|
write_failure_message,
|
||||||
cfile_open_failure_message,
|
cfile_open_failure_message,
|
||||||
cfile_dump_open_failure_message,
|
cfile_dump_open_failure_message,
|
||||||
cfile_read_failure_message,
|
cfile_read_failure_message,
|
||||||
cfile_write_failure_message,
|
cfile_write_failure_message,
|
||||||
cfile_close_failure_message
|
cfile_close_failure_message
|
||||||
};
|
};
|
||||||
int opt;
|
int opt;
|
||||||
static const struct ws_option long_options[] = {
|
static const struct ws_option long_options[] = {
|
||||||
{"help", ws_no_argument, NULL, 'h'},
|
{"help", ws_no_argument, NULL, 'h'},
|
||||||
{"version", ws_no_argument, NULL, 'V'},
|
{"version", ws_no_argument, NULL, 'V'},
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
gboolean do_append = FALSE;
|
gboolean do_append = FALSE;
|
||||||
gboolean verbose = FALSE;
|
gboolean verbose = FALSE;
|
||||||
int in_file_count = 0;
|
int in_file_count = 0;
|
||||||
guint32 snaplen = 0;
|
guint32 snaplen = 0;
|
||||||
int file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
|
int file_type = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
gchar *err_info = NULL;
|
gchar *err_info = NULL;
|
||||||
int err_fileno;
|
int err_fileno;
|
||||||
guint32 err_framenum;
|
guint32 err_framenum;
|
||||||
char *out_filename = NULL;
|
char *out_filename = NULL;
|
||||||
merge_result status = MERGE_OK;
|
merge_result status = MERGE_OK;
|
||||||
idb_merge_mode mode = IDB_MERGE_MODE_MAX;
|
idb_merge_mode mode = IDB_MERGE_MODE_MAX;
|
||||||
merge_progress_callback_t cb;
|
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. */
|
/* Initialize log handler early so we can have proper logging during startup. */
|
||||||
ws_log_init("mergecap", vcmdarg_err);
|
ws_log_init("mergecap", vcmdarg_err);
|
||||||
|
|
||||||
/* Early logging command-line initialization. */
|
/* Early logging command-line initialization. */
|
||||||
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
|
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
create_app_running_mutex();
|
create_app_running_mutex();
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
/* Initialize the version information. */
|
/* Initialize the version information. */
|
||||||
ws_init_version_info("Mergecap (Wireshark)", NULL, NULL, NULL);
|
ws_init_version_info("Mergecap (Wireshark)", NULL, NULL, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get credential information for later use.
|
* Get credential information for later use.
|
||||||
*/
|
*/
|
||||||
init_process_policies();
|
init_process_policies();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to get the pathname of the directory containing the
|
* Attempt to get the pathname of the directory containing the
|
||||||
* executable file.
|
* executable file.
|
||||||
*/
|
*/
|
||||||
init_progfile_dir_error = init_progfile_dir(argv[0]);
|
init_progfile_dir_error = init_progfile_dir(argv[0]);
|
||||||
if (init_progfile_dir_error != NULL) {
|
if (init_progfile_dir_error != NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"mergecap: Can't get pathname of directory containing the mergecap program: %s.\n",
|
"mergecap: Can't get pathname of directory containing the mergecap program: %s.\n",
|
||||||
init_progfile_dir_error);
|
init_progfile_dir_error);
|
||||||
g_free(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;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Default to pcapng when writing. */
|
init_report_message("mergecap", &mergecap_report_routines);
|
||||||
if (file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN)
|
|
||||||
file_type = wtap_pcapng_file_type_subtype();
|
|
||||||
|
|
||||||
cb.callback_func = merge_callback;
|
wtap_init(TRUE);
|
||||||
cb.data = NULL;
|
|
||||||
|
|
||||||
/* check for proper args; at a minimum, must have an output
|
/* Process the options first */
|
||||||
* filename and one input file
|
while ((opt = ws_getopt_long(argc, argv, "aF:hI:s:vVw:", long_options, NULL)) != -1) {
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
switch (opt) {
|
||||||
* Setting IDB merge mode must use a file format that supports
|
case 'a':
|
||||||
* (and thus requires) interface ID and information blocks.
|
do_append = !do_append;
|
||||||
*/
|
break;
|
||||||
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 */
|
case 'F':
|
||||||
if (mode == IDB_MERGE_MODE_MAX) {
|
file_type = wtap_name_to_file_type_subtype(ws_optarg);
|
||||||
mode = IDB_MERGE_MODE_ALL_SAME;
|
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 */
|
case 'h':
|
||||||
if (strcmp(out_filename, "-") == 0) {
|
show_help_header("Merge two or more capture files into one.");
|
||||||
/* merge the files to the standard output */
|
print_usage(stdout);
|
||||||
status = merge_files_to_stdout(file_type,
|
goto clean_exit;
|
||||||
(const char *const *) &argv[ws_optind],
|
break;
|
||||||
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 'I':
|
||||||
case MERGE_OK:
|
mode = merge_string_to_idb_merge_mode(ws_optarg);
|
||||||
break;
|
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:
|
case 's':
|
||||||
/* we don't catch SIGINT/SIGTERM (yet?), so we couldn't have aborted */
|
snaplen = get_nonzero_guint32(ws_optarg, "snapshot length");
|
||||||
ws_assert_not_reached();
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case MERGE_ERR_CANT_OPEN_INFILE:
|
case 'v':
|
||||||
cfile_open_failure_message(argv[ws_optind + err_fileno], err, err_info);
|
verbose = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MERGE_ERR_CANT_OPEN_OUTFILE:
|
case 'V':
|
||||||
cfile_dump_open_failure_message(out_filename, err, err_info, file_type);
|
show_version();
|
||||||
break;
|
goto clean_exit;
|
||||||
|
break;
|
||||||
|
|
||||||
case MERGE_ERR_CANT_READ_INFILE:
|
case 'w':
|
||||||
cfile_read_failure_message(argv[ws_optind + err_fileno], err, err_info);
|
out_filename = ws_optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
|
case '?': /* Bad options if GNU getopt */
|
||||||
cmdarg_err("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
|
switch(ws_optopt) {
|
||||||
err_framenum, argv[ws_optind + err_fileno]);
|
case'F':
|
||||||
break;
|
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:
|
/* Default to pcapng when writing. */
|
||||||
cfile_write_failure_message(argv[ws_optind + err_fileno], out_filename,
|
if (file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN)
|
||||||
err, err_info, err_framenum, file_type);
|
file_type = wtap_pcapng_file_type_subtype();
|
||||||
break;
|
|
||||||
|
|
||||||
case MERGE_ERR_CANT_CLOSE_OUTFILE:
|
cb.callback_func = merge_callback;
|
||||||
cfile_close_failure_message(out_filename, err, err_info);
|
cb.data = NULL;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
/* check for proper args; at a minimum, must have an output
|
||||||
cmdarg_err("Unknown merge_files error %d", status);
|
* filename and one input file
|
||||||
break;
|
*/
|
||||||
}
|
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:
|
clean_exit:
|
||||||
wtap_cleanup();
|
wtap_cleanup();
|
||||||
free_progdirs();
|
free_progdirs();
|
||||||
return (status == MERGE_OK) ? 0 : 2;
|
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:
|
|
||||||
*/
|
|
||||||
|
|
339
randpkt.c
339
randpkt.c
|
@ -45,9 +45,9 @@
|
||||||
static void
|
static void
|
||||||
randpkt_cmdarg_err(const char *msg_format, va_list ap)
|
randpkt_cmdarg_err(const char *msg_format, va_list ap)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "randpkt: ");
|
fprintf(stderr, "randpkt: ");
|
||||||
vfprintf(stderr, msg_format, ap);
|
vfprintf(stderr, msg_format, ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -56,219 +56,206 @@ randpkt_cmdarg_err(const char *msg_format, va_list ap)
|
||||||
static void
|
static void
|
||||||
randpkt_cmdarg_err_cont(const char *msg_format, va_list ap)
|
randpkt_cmdarg_err_cont(const char *msg_format, va_list ap)
|
||||||
{
|
{
|
||||||
vfprintf(stderr, msg_format, ap);
|
vfprintf(stderr, msg_format, ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print usage statement and exit program */
|
/* Print usage statement and exit program */
|
||||||
static void
|
static void
|
||||||
usage(gboolean is_error)
|
usage(gboolean is_error)
|
||||||
{
|
{
|
||||||
FILE *output;
|
FILE *output;
|
||||||
char** abbrev_list;
|
char** abbrev_list;
|
||||||
char** longname_list;
|
char** longname_list;
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
|
|
||||||
if (!is_error) {
|
if (!is_error) {
|
||||||
output = stdout;
|
output = stdout;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
output = stderr;
|
output = stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(output, "Usage: randpkt [-b maxbytes] [-c count] [-t type] [-r] filename\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 max bytes (per packet) is 5000\n");
|
||||||
fprintf(output, "Default count is 1000.\n");
|
fprintf(output, "Default count is 1000.\n");
|
||||||
fprintf(output, "-r: random packet type selection\n");
|
fprintf(output, "-r: random packet type selection\n");
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Types:\n");
|
fprintf(output, "Types:\n");
|
||||||
|
|
||||||
/* Get the examples list */
|
/* Get the examples list */
|
||||||
randpkt_example_list(&abbrev_list, &longname_list);
|
randpkt_example_list(&abbrev_list, &longname_list);
|
||||||
while (abbrev_list[i] && longname_list[i]) {
|
while (abbrev_list[i] && longname_list[i]) {
|
||||||
fprintf(output, "\t%-16s%s\n", abbrev_list[i], longname_list[i]);
|
fprintf(output, "\t%-16s%s\n", abbrev_list[i], longname_list[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_strfreev(abbrev_list);
|
g_strfreev(abbrev_list);
|
||||||
g_strfreev(longname_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
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *init_progfile_dir_error;
|
char *init_progfile_dir_error;
|
||||||
static const struct report_message_routines randpkt_report_routines = {
|
static const struct report_message_routines randpkt_report_routines = {
|
||||||
failure_message,
|
failure_message,
|
||||||
failure_message,
|
failure_message,
|
||||||
open_failure_message,
|
open_failure_message,
|
||||||
read_failure_message,
|
read_failure_message,
|
||||||
write_failure_message,
|
write_failure_message,
|
||||||
cfile_open_failure_message,
|
cfile_open_failure_message,
|
||||||
cfile_dump_open_failure_message,
|
cfile_dump_open_failure_message,
|
||||||
cfile_read_failure_message,
|
cfile_read_failure_message,
|
||||||
cfile_write_failure_message,
|
cfile_write_failure_message,
|
||||||
cfile_close_failure_message
|
cfile_close_failure_message
|
||||||
};
|
};
|
||||||
int opt;
|
int opt;
|
||||||
int produce_type = -1;
|
int produce_type = -1;
|
||||||
char *produce_filename = NULL;
|
char *produce_filename = NULL;
|
||||||
int produce_max_bytes = 5000;
|
int produce_max_bytes = 5000;
|
||||||
int produce_count = 1000;
|
int produce_count = 1000;
|
||||||
randpkt_example *example;
|
randpkt_example *example;
|
||||||
guint8* type = NULL;
|
guint8* type = NULL;
|
||||||
int allrandom = FALSE;
|
int allrandom = FALSE;
|
||||||
wtap_dumper *savedump;
|
wtap_dumper *savedump;
|
||||||
int ret = EXIT_SUCCESS;
|
int ret = EXIT_SUCCESS;
|
||||||
static const struct ws_option long_options[] = {
|
static const struct ws_option long_options[] = {
|
||||||
{"help", ws_no_argument, NULL, 'h'},
|
{"help", ws_no_argument, NULL, 'h'},
|
||||||
{0, 0, 0, 0 }
|
{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. */
|
/* Initialize log handler early so we can have proper logging during startup. */
|
||||||
ws_log_init("randpkt", vcmdarg_err);
|
ws_log_init("randpkt", vcmdarg_err);
|
||||||
|
|
||||||
/* Early logging command-line initialization. */
|
/* Early logging command-line initialization. */
|
||||||
ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);
|
ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get credential information for later use.
|
* Get credential information for later use.
|
||||||
*/
|
*/
|
||||||
init_process_policies();
|
init_process_policies();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to get the pathname of the directory containing the
|
* Attempt to get the pathname of the directory containing the
|
||||||
* executable file.
|
* executable file.
|
||||||
*/
|
*/
|
||||||
init_progfile_dir_error = init_progfile_dir(argv[0]);
|
init_progfile_dir_error = init_progfile_dir(argv[0]);
|
||||||
if (init_progfile_dir_error != NULL) {
|
if (init_progfile_dir_error != NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"capinfos: Can't get pathname of directory containing the capinfos program: %s.\n",
|
"capinfos: Can't get pathname of directory containing the capinfos program: %s.\n",
|
||||||
init_progfile_dir_error);
|
init_progfile_dir_error);
|
||||||
g_free(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
|
#ifdef _WIN32
|
||||||
create_app_running_mutex();
|
create_app_running_mutex();
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
while ((opt = ws_getopt_long(argc, argv, "b:c:ht:r", long_options, NULL)) != -1) {
|
while ((opt = ws_getopt_long(argc, argv, "b:c:ht:r", long_options, NULL)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'b': /* max bytes */
|
case 'b': /* max bytes */
|
||||||
produce_max_bytes = get_positive_int(ws_optarg, "max bytes");
|
produce_max_bytes = get_positive_int(ws_optarg, "max bytes");
|
||||||
if (produce_max_bytes > 65536) {
|
if (produce_max_bytes > 65536) {
|
||||||
cmdarg_err("max bytes is > 65536");
|
cmdarg_err("max bytes is > 65536");
|
||||||
ret = INVALID_OPTION;
|
ret = INVALID_OPTION;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c': /* count */
|
case 'c': /* count */
|
||||||
produce_count = get_positive_int(ws_optarg, "count");
|
produce_count = get_positive_int(ws_optarg, "count");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't': /* type of packet to produce */
|
case 't': /* type of packet to produce */
|
||||||
type = g_strdup(ws_optarg);
|
type = g_strdup(ws_optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(FALSE);
|
usage(FALSE);
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
allrandom = TRUE;
|
allrandom = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
usage(TRUE);
|
usage(TRUE);
|
||||||
ret = INVALID_OPTION;
|
ret = INVALID_OPTION;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* any more command line parameters? */
|
/* any more command line parameters? */
|
||||||
if (argc > ws_optind) {
|
if (argc > ws_optind) {
|
||||||
produce_filename = argv[ws_optind];
|
produce_filename = argv[ws_optind];
|
||||||
} else {
|
} else {
|
||||||
usage(TRUE);
|
usage(TRUE);
|
||||||
ret = INVALID_OPTION;
|
ret = INVALID_OPTION;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!allrandom) {
|
if (!allrandom) {
|
||||||
produce_type = randpkt_parse_type(type);
|
produce_type = randpkt_parse_type(type);
|
||||||
g_free(type);
|
g_free(type);
|
||||||
|
|
||||||
example = randpkt_find_example(produce_type);
|
example = randpkt_find_example(produce_type);
|
||||||
if (!example) {
|
if (!example) {
|
||||||
ret = INVALID_OPTION;
|
ret = INVALID_OPTION;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = randpkt_example_init(example, produce_filename, produce_max_bytes);
|
ret = randpkt_example_init(example, produce_filename, produce_max_bytes);
|
||||||
if (ret != EXIT_SUCCESS)
|
if (ret != EXIT_SUCCESS)
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
randpkt_loop(example, produce_count, 0);
|
randpkt_loop(example, produce_count, 0);
|
||||||
} else {
|
} else {
|
||||||
if (type) {
|
if (type) {
|
||||||
fprintf(stderr, "Can't set type in random mode\n");
|
fprintf(stderr, "Can't set type in random mode\n");
|
||||||
ret = INVALID_TYPE;
|
ret = INVALID_TYPE;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
produce_type = randpkt_parse_type(NULL);
|
produce_type = randpkt_parse_type(NULL);
|
||||||
example = randpkt_find_example(produce_type);
|
example = randpkt_find_example(produce_type);
|
||||||
if (!example) {
|
if (!example) {
|
||||||
ret = INVALID_OPTION;
|
ret = INVALID_OPTION;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
ret = randpkt_example_init(example, produce_filename, produce_max_bytes);
|
ret = randpkt_example_init(example, produce_filename, produce_max_bytes);
|
||||||
if (ret != EXIT_SUCCESS)
|
if (ret != EXIT_SUCCESS)
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
|
|
||||||
while (produce_count-- > 0) {
|
while (produce_count-- > 0) {
|
||||||
randpkt_loop(example, 1, 0);
|
randpkt_loop(example, 1, 0);
|
||||||
produce_type = randpkt_parse_type(NULL);
|
produce_type = randpkt_parse_type(NULL);
|
||||||
|
|
||||||
savedump = example->dump;
|
savedump = example->dump;
|
||||||
|
|
||||||
example = randpkt_find_example(produce_type);
|
example = randpkt_find_example(produce_type);
|
||||||
if (!example) {
|
if (!example) {
|
||||||
ret = INVALID_OPTION;
|
ret = INVALID_OPTION;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
example->dump = savedump;
|
example->dump = savedump;
|
||||||
example->filename = produce_filename;
|
example->filename = produce_filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!randpkt_example_close(example)) {
|
if (!randpkt_example_close(example)) {
|
||||||
ret = CLOSE_ERROR;
|
ret = CLOSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
clean_exit:
|
clean_exit:
|
||||||
wtap_cleanup();
|
wtap_cleanup();
|
||||||
return ret;
|
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:
|
|
||||||
*/
|
|
||||||
|
|
726
ringbuffer.c
726
ringbuffer.c
|
@ -60,30 +60,30 @@
|
||||||
|
|
||||||
/* Ringbuffer file structure */
|
/* Ringbuffer file structure */
|
||||||
typedef struct _rb_file {
|
typedef struct _rb_file {
|
||||||
gchar *name;
|
gchar *name;
|
||||||
} rb_file;
|
} rb_file;
|
||||||
|
|
||||||
#define MAX_FILENAME_QUEUE 100
|
#define MAX_FILENAME_QUEUE 100
|
||||||
|
|
||||||
/** Ringbuffer data structure */
|
/** Ringbuffer data structure */
|
||||||
typedef struct _ringbuf_data {
|
typedef struct _ringbuf_data {
|
||||||
rb_file *files;
|
rb_file *files;
|
||||||
guint num_files; /**< Number of ringbuffer files (1 to ...) */
|
guint num_files; /**< Number of ringbuffer files (1 to ...) */
|
||||||
guint curr_file_num; /**< Number of the current file (ever increasing) */
|
guint curr_file_num; /**< Number of the current file (ever increasing) */
|
||||||
gchar *fprefix; /**< Filename prefix */
|
gchar *fprefix; /**< Filename prefix */
|
||||||
gchar *fsuffix; /**< Filename suffix */
|
gchar *fsuffix; /**< Filename suffix */
|
||||||
gboolean nametimenum; /**< ...num_time... or ...time_num... */
|
gboolean nametimenum; /**< ...num_time... or ...time_num... */
|
||||||
gboolean unlimited; /**< TRUE if unlimited number of files */
|
gboolean unlimited; /**< TRUE if unlimited number of files */
|
||||||
|
|
||||||
int fd; /**< Current ringbuffer file descriptor */
|
int fd; /**< Current ringbuffer file descriptor */
|
||||||
FILE *pdh;
|
FILE *pdh;
|
||||||
char *io_buffer; /**< The IO buffer used to write to the file */
|
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 */
|
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 */
|
FILE *name_h; /**< write names of completed files to this handle */
|
||||||
gchar *compress_type; /**< compress type */
|
gchar *compress_type; /**< compress type */
|
||||||
|
|
||||||
GMutex mutex; /**< mutex for oldnames */
|
GMutex mutex; /**< mutex for oldnames */
|
||||||
gchar *oldnames[MAX_FILENAME_QUEUE]; /**< filename list of pending to be deleted */
|
gchar *oldnames[MAX_FILENAME_QUEUE]; /**< filename list of pending to be deleted */
|
||||||
} ringbuf_data;
|
} ringbuf_data;
|
||||||
|
|
||||||
static ringbuf_data rb_data;
|
static ringbuf_data rb_data;
|
||||||
|
@ -91,172 +91,177 @@ static ringbuf_data rb_data;
|
||||||
/*
|
/*
|
||||||
* delete pending uncompressed pcap files.
|
* delete pending uncompressed pcap files.
|
||||||
*/
|
*/
|
||||||
static void CleanupOldCap(gchar* name)
|
static void
|
||||||
|
CleanupOldCap(gchar* name)
|
||||||
{
|
{
|
||||||
ws_statb64 statb;
|
ws_statb64 statb;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
g_mutex_lock(&rb_data.mutex);
|
g_mutex_lock(&rb_data.mutex);
|
||||||
|
|
||||||
/* Delete pending delete file */
|
/* Delete pending delete file */
|
||||||
for (i = 0; i < sizeof(rb_data.oldnames) / sizeof(rb_data.oldnames[0]); i++) {
|
for (i = 0; i < sizeof(rb_data.oldnames) / sizeof(rb_data.oldnames[0]); i++) {
|
||||||
if (rb_data.oldnames[i] != NULL) {
|
if (rb_data.oldnames[i] != NULL) {
|
||||||
ws_unlink(rb_data.oldnames[i]);
|
ws_unlink(rb_data.oldnames[i]);
|
||||||
if (ws_stat64(rb_data.oldnames[i], &statb) != 0) {
|
if (ws_stat64(rb_data.oldnames[i], &statb) != 0) {
|
||||||
g_free(rb_data.oldnames[i]);
|
g_free(rb_data.oldnames[i]);
|
||||||
rb_data.oldnames[i] = NULL;
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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
|
#ifdef HAVE_ZLIB
|
||||||
/*
|
/*
|
||||||
* compress capture file
|
* compress capture file
|
||||||
*/
|
*/
|
||||||
static int ringbuf_exec_compress(gchar* name)
|
static int
|
||||||
|
ringbuf_exec_compress(gchar* name)
|
||||||
{
|
{
|
||||||
guint8 *buffer = NULL;
|
guint8 *buffer = NULL;
|
||||||
gchar* outgz = NULL;
|
gchar* outgz = NULL;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
gboolean delete_org_file = TRUE;
|
gboolean delete_org_file = TRUE;
|
||||||
gzFile fi = NULL;
|
gzFile fi = NULL;
|
||||||
|
|
||||||
fd = ws_open(name, O_RDONLY | O_BINARY, 0000);
|
fd = ws_open(name, O_RDONLY | O_BINARY, 0000);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
outgz = ws_strdup_printf("%s.gz", name);
|
outgz = ws_strdup_printf("%s.gz", name);
|
||||||
fi = gzopen(outgz, "wb");
|
fi = gzopen(outgz, "wb");
|
||||||
g_free(outgz);
|
g_free(outgz);
|
||||||
if (fi == NULL) {
|
if (fi == NULL) {
|
||||||
ws_close(fd);
|
ws_close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FS_READ_SIZE 65536
|
#define FS_READ_SIZE 65536
|
||||||
buffer = (guint8*)g_malloc(FS_READ_SIZE);
|
buffer = (guint8*)g_malloc(FS_READ_SIZE);
|
||||||
if (buffer == NULL) {
|
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);
|
ws_close(fd);
|
||||||
gzclose(fi);
|
gzclose(fi);
|
||||||
return -1;
|
g_free(buffer);
|
||||||
}
|
|
||||||
|
|
||||||
while ((nread = ws_read(fd, buffer, FS_READ_SIZE)) > 0) {
|
/* delete the original file only if compression succeeds */
|
||||||
int n = gzwrite(fi, buffer, (unsigned int)nread);
|
if (delete_org_file) {
|
||||||
if (n <= 0) {
|
ws_unlink(name);
|
||||||
/* mark compression as failed */
|
CleanupOldCap(name);
|
||||||
delete_org_file = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
g_free(name);
|
||||||
if (nread < 0) {
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* thread to compress capture file
|
* thread to compress capture file
|
||||||
*/
|
*/
|
||||||
static void* exec_compress_thread(void* arg)
|
static void*
|
||||||
|
exec_compress_thread(void* arg)
|
||||||
{
|
{
|
||||||
ringbuf_exec_compress((gchar*)arg);
|
ringbuf_exec_compress((gchar*)arg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* start a thread to compress capture file
|
* 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);
|
gchar* name = g_strdup(rfile->name);
|
||||||
g_thread_new("exec_compress", &exec_compress_thread, name);
|
g_thread_new("exec_compress", &exec_compress_thread, name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* create the next filename and open a new binary file with that name
|
* 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 filenum[5+1];
|
||||||
char timestr[14+1];
|
char timestr[14+1];
|
||||||
time_t current_time;
|
time_t current_time;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
|
||||||
if (rfile->name != NULL) {
|
if (rfile->name != NULL) {
|
||||||
if (rb_data.unlimited == FALSE) {
|
if (rb_data.unlimited == FALSE) {
|
||||||
/* remove old file (if any, so ignore error) */
|
/* remove old file (if any, so ignore error) */
|
||||||
ws_unlink(rfile->name);
|
ws_unlink(rfile->name);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_ZLIB
|
#ifdef HAVE_ZLIB
|
||||||
else if (rb_data.compress_type != NULL && strcmp(rb_data.compress_type, "gzip") == 0) {
|
else if (rb_data.compress_type != NULL && strcmp(rb_data.compress_type, "gzip") == 0) {
|
||||||
ringbuf_start_compress_file(rfile);
|
ringbuf_start_compress_file(rfile);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
g_free(rfile->name);
|
g_free(rfile->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
_tzset();
|
_tzset();
|
||||||
#endif
|
#endif
|
||||||
current_time = time(NULL);
|
current_time = time(NULL);
|
||||||
|
|
||||||
snprintf(filenum, sizeof(filenum), "%05u", (rb_data.curr_file_num + 1) % RINGBUFFER_MAX_NUM_FILES);
|
snprintf(filenum, sizeof(filenum), "%05u", (rb_data.curr_file_num + 1) % RINGBUFFER_MAX_NUM_FILES);
|
||||||
tm = localtime(¤t_time);
|
tm = localtime(¤t_time);
|
||||||
if (tm != NULL)
|
if (tm != NULL)
|
||||||
strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", tm);
|
strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", tm);
|
||||||
else
|
else
|
||||||
(void) g_strlcpy(timestr, "196912312359", sizeof(timestr)); /* second before the Epoch */
|
(void) g_strlcpy(timestr, "196912312359", sizeof(timestr)); /* second before the Epoch */
|
||||||
if (rb_data.nametimenum) {
|
if (rb_data.nametimenum) {
|
||||||
rfile->name = g_strconcat(rb_data.fprefix, "_", timestr, "_", filenum, rb_data.fsuffix, NULL);
|
rfile->name = g_strconcat(rb_data.fprefix, "_", timestr, "_", filenum, rb_data.fsuffix, NULL);
|
||||||
} else {
|
} else {
|
||||||
rfile->name = g_strconcat(rb_data.fprefix, "_", filenum, "_", timestr, rb_data.fsuffix, NULL);
|
rfile->name = g_strconcat(rb_data.fprefix, "_", filenum, "_", timestr, rb_data.fsuffix, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rfile->name == NULL) {
|
if (rfile->name == NULL) {
|
||||||
if (err != NULL)
|
if (err != NULL)
|
||||||
*err = ENOMEM;
|
*err = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_data.fd = ws_open(rfile->name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
|
rb_data.fd = ws_open(rfile->name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
|
||||||
rb_data.group_read_access ? 0640 : 0600);
|
rb_data.group_read_access ? 0640 : 0600);
|
||||||
|
|
||||||
if (rb_data.fd == -1 && err != NULL) {
|
if (rb_data.fd == -1 && err != NULL) {
|
||||||
*err = errno;
|
*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
|
int
|
||||||
ringbuf_init(const char *capfile_name, guint num_files, gboolean group_read_access,
|
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;
|
unsigned int i;
|
||||||
char *pfx, *last_pathsep;
|
char *pfx, *last_pathsep;
|
||||||
gchar *save_file;
|
gchar *save_file;
|
||||||
|
|
||||||
rb_data.files = NULL;
|
rb_data.files = NULL;
|
||||||
rb_data.curr_file_num = 0;
|
rb_data.curr_file_num = 0;
|
||||||
rb_data.fprefix = NULL;
|
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.fsuffix = NULL;
|
rb_data.fsuffix = NULL;
|
||||||
}
|
rb_data.nametimenum = has_nametimenum;
|
||||||
g_free(save_file);
|
rb_data.unlimited = FALSE;
|
||||||
save_file = NULL;
|
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
|
/* just to be sure ... */
|
||||||
need to save all file names in that case) */
|
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) {
|
/* Check file name */
|
||||||
rb_data.unlimited = TRUE;
|
if (capfile_name == NULL) {
|
||||||
rb_data.num_files = 1;
|
/* ringbuffer does not work with temporary files! */
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
rb_data.files = g_new(rb_file, rb_data.num_files);
|
/* set file name prefix/suffix */
|
||||||
if (rb_data.files == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i < rb_data.num_files; i++) {
|
save_file = g_strdup(capfile_name);
|
||||||
rb_data.files[i].name = NULL;
|
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 */
|
Treat it as a separator between the rest of the file name and
|
||||||
if (ringbuf_open_file(&rb_data.files[0], NULL) == -1) {
|
the file name suffix, and arrange that the names given to the
|
||||||
ringbuf_error_cleanup();
|
ring buffer files have the specified suffix, i.e. put the
|
||||||
return -1;
|
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
|
gboolean
|
||||||
ringbuf_set_print_name(gchar *name, int *err)
|
ringbuf_set_print_name(gchar *name, int *err)
|
||||||
{
|
{
|
||||||
if (rb_data.name_h != NULL) {
|
if (rb_data.name_h != NULL) {
|
||||||
if (EOF == fclose(rb_data.name_h)) {
|
if (EOF == fclose(rb_data.name_h)) {
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
*err = errno;
|
*err = errno;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!strcmp(name, "-") || !strcmp(name, "stdout")) {
|
||||||
if (!strcmp(name, "-") || !strcmp(name, "stdout")) {
|
rb_data.name_h = stdout;
|
||||||
rb_data.name_h = stdout;
|
} else if (!strcmp(name, "stderr")) {
|
||||||
} else if (!strcmp(name, "stderr")) {
|
rb_data.name_h = stderr;
|
||||||
rb_data.name_h = stderr;
|
} else {
|
||||||
} else {
|
if (NULL == (rb_data.name_h = ws_fopen(name, "wt"))) {
|
||||||
if (NULL == (rb_data.name_h = ws_fopen(name, "wt"))) {
|
if (err != NULL) {
|
||||||
if (err != NULL) {
|
*err = errno;
|
||||||
*err = errno;
|
}
|
||||||
}
|
return FALSE;
|
||||||
return FALSE;
|
}
|
||||||
}
|
}
|
||||||
}
|
return TRUE;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Whether the ringbuf filenames are ready.
|
* Whether the ringbuf filenames are ready.
|
||||||
* (Whether ringbuf_init is called and ringbuf_free is not called.)
|
* (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 *
|
FILE *
|
||||||
ringbuf_init_libpcap_fdopen(int *err)
|
ringbuf_init_libpcap_fdopen(int *err)
|
||||||
{
|
{
|
||||||
rb_data.pdh = ws_fdopen(rb_data.fd, "wb");
|
rb_data.pdh = ws_fdopen(rb_data.fd, "wb");
|
||||||
if (rb_data.pdh == NULL) {
|
if (rb_data.pdh == NULL) {
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
*err = errno;
|
*err = errno;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size_t buffsize = IO_BUF_SIZE;
|
size_t buffsize = IO_BUF_SIZE;
|
||||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||||
ws_statb64 statb;
|
ws_statb64 statb;
|
||||||
|
|
||||||
if (ws_fstat64(rb_data.fd, &statb) == 0) {
|
if (ws_fstat64(rb_data.fd, &statb) == 0) {
|
||||||
if (statb.st_blksize > IO_BUF_SIZE) {
|
if (statb.st_blksize > IO_BUF_SIZE) {
|
||||||
buffsize = statb.st_blksize;
|
buffsize = statb.st_blksize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Increase the size of the IO buffer */
|
/* Increase the size of the IO buffer */
|
||||||
rb_data.io_buffer = (char *)g_realloc(rb_data.io_buffer, buffsize);
|
rb_data.io_buffer = (char *)g_realloc(rb_data.io_buffer, buffsize);
|
||||||
setvbuf(rb_data.pdh, rb_data.io_buffer, _IOFBF, 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
|
gboolean
|
||||||
ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err)
|
ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err)
|
||||||
{
|
{
|
||||||
int next_file_index;
|
int next_file_index;
|
||||||
rb_file *next_rfile = NULL;
|
rb_file *next_rfile = NULL;
|
||||||
|
|
||||||
/* close current file */
|
/* close current file */
|
||||||
|
|
||||||
if (fclose(rb_data.pdh) == EOF) {
|
if (fclose(rb_data.pdh) == EOF) {
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
*err = errno;
|
*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.pdh = NULL;
|
||||||
rb_data.fd = -1;
|
rb_data.fd = -1;
|
||||||
|
|
||||||
if (rb_data.name_h != NULL) {
|
if (rb_data.name_h != NULL) {
|
||||||
fprintf(rb_data.name_h, "%s\n", ringbuf_current_filename());
|
fprintf(rb_data.name_h, "%s\n", ringbuf_current_filename());
|
||||||
fflush(rb_data.name_h);
|
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*/;
|
rb_data.curr_file_num++ /* = next_file_num*/;
|
||||||
next_file_index = (rb_data.curr_file_num) % rb_data.num_files;
|
next_file_index = (rb_data.curr_file_num) % rb_data.num_files;
|
||||||
next_rfile = &rb_data.files[next_file_index];
|
next_rfile = &rb_data.files[next_file_index];
|
||||||
|
|
||||||
if (ringbuf_open_file(next_rfile, err) == -1) {
|
if (ringbuf_open_file(next_rfile, err) == -1) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ringbuf_init_libpcap_fdopen(err) == NULL) {
|
if (ringbuf_init_libpcap_fdopen(err) == NULL) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* switch to the new file */
|
/* switch to the new file */
|
||||||
*save_file = next_rfile->name;
|
*save_file = next_rfile->name;
|
||||||
*save_file_fd = rb_data.fd;
|
*save_file_fd = rb_data.fd;
|
||||||
(*pdh) = rb_data.pdh;
|
(*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
|
gboolean
|
||||||
ringbuf_libpcap_dump_close(gchar **save_file, int *err)
|
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) {
|
if (EOF == fclose(rb_data.name_h)) {
|
||||||
fprintf(rb_data.name_h, "%s\n", ringbuf_current_filename());
|
/* Can't really do much about this, can we? */
|
||||||
fflush(rb_data.name_h);
|
}
|
||||||
|
|
||||||
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 */
|
/* set the save file name to the current file */
|
||||||
*save_file = rb_data.files[rb_data.curr_file_num % rb_data.num_files].name;
|
*save_file = rb_data.files[rb_data.curr_file_num % rb_data.num_files].name;
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -522,28 +529,28 @@ ringbuf_libpcap_dump_close(gchar **save_file, int *err)
|
||||||
void
|
void
|
||||||
ringbuf_free(void)
|
ringbuf_free(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (rb_data.files != NULL) {
|
if (rb_data.files != NULL) {
|
||||||
for (i=0; i < rb_data.num_files; i++) {
|
for (i=0; i < rb_data.num_files; i++) {
|
||||||
if (rb_data.files[i].name != NULL) {
|
if (rb_data.files[i].name != NULL) {
|
||||||
g_free(rb_data.files[i].name);
|
g_free(rb_data.files[i].name);
|
||||||
rb_data.files[i].name = NULL;
|
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
|
void
|
||||||
ringbuf_error_cleanup(void)
|
ringbuf_error_cleanup(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* try to close via wtap */
|
/* try to close via wtap */
|
||||||
if (rb_data.pdh != NULL) {
|
if (rb_data.pdh != NULL) {
|
||||||
if (fclose(rb_data.pdh) == 0) {
|
if (fclose(rb_data.pdh) == 0) {
|
||||||
rb_data.fd = -1;
|
rb_data.fd = -1;
|
||||||
|
}
|
||||||
|
rb_data.pdh = NULL;
|
||||||
}
|
}
|
||||||
rb_data.pdh = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* close directly if still open */
|
/* close directly if still open */
|
||||||
if (rb_data.fd != -1) {
|
if (rb_data.fd != -1) {
|
||||||
ws_close(rb_data.fd);
|
ws_close(rb_data.fd);
|
||||||
rb_data.fd = -1;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
g_free(rb_data.io_buffer);
|
|
||||||
rb_data.io_buffer = NULL;
|
|
||||||
|
|
||||||
if (rb_data.name_h != NULL) {
|
if (rb_data.files != NULL) {
|
||||||
if (EOF == fclose(rb_data.name_h)) {
|
for (i=0; i < rb_data.num_files; i++) {
|
||||||
/* Can't really do much about this, can we? */
|
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 */
|
if (rb_data.name_h != NULL) {
|
||||||
ringbuf_free();
|
if (EOF == fclose(rb_data.name_h)) {
|
||||||
|
/* Can't really do much about this, can we? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free the memory */
|
||||||
|
ringbuf_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_LIBPCAP */
|
#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:
|
|
||||||
*/
|
|
||||||
|
|
13
ringbuffer.h
13
ringbuffer.h
|
@ -37,16 +37,3 @@ void ringbuf_error_cleanup(void);
|
||||||
gboolean ringbuf_set_print_name(gchar *name, int *err);
|
gboolean ringbuf_set_print_name(gchar *name, int *err);
|
||||||
|
|
||||||
#endif /* ringbuffer.h */
|
#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:
|
|
||||||
*/
|
|
||||||
|
|
617
sharkd_daemon.c
617
sharkd_daemon.c
|
@ -56,303 +56,303 @@ static socket_handle_t _server_fd = INVALID_SOCKET;
|
||||||
static socket_handle_t
|
static socket_handle_t
|
||||||
socket_init(char *path)
|
socket_init(char *path)
|
||||||
{
|
{
|
||||||
socket_handle_t fd = INVALID_SOCKET;
|
socket_handle_t fd = INVALID_SOCKET;
|
||||||
char *err_msg;
|
char *err_msg;
|
||||||
|
|
||||||
err_msg = ws_init_sockets();
|
err_msg = ws_init_sockets();
|
||||||
if (err_msg != NULL) {
|
if (err_msg != NULL) {
|
||||||
ws_warning("ERROR: %s", err_msg);
|
ws_warning("ERROR: %s", err_msg);
|
||||||
g_free(err_msg);
|
g_free(err_msg);
|
||||||
ws_warning("%s", please_report_bug());
|
ws_warning("%s", please_report_bug());
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHARKD_UNIX_SUPPORT
|
#ifdef SHARKD_UNIX_SUPPORT
|
||||||
if (!strncmp(path, "unix:", 5))
|
if (!strncmp(path, "unix:", 5))
|
||||||
{
|
{
|
||||||
struct sockaddr_un s_un;
|
struct sockaddr_un s_un;
|
||||||
socklen_t s_un_len;
|
socklen_t s_un_len;
|
||||||
|
|
||||||
path += 5;
|
path += 5;
|
||||||
|
|
||||||
if (strlen(path) + 1 > sizeof(s_un.sun_path))
|
if (strlen(path) + 1 > sizeof(s_un.sun_path))
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
|
|
||||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (fd == INVALID_SOCKET)
|
if (fd == INVALID_SOCKET)
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
|
|
||||||
memset(&s_un, 0, sizeof(s_un));
|
memset(&s_un, 0, sizeof(s_un));
|
||||||
s_un.sun_family = AF_UNIX;
|
s_un.sun_family = AF_UNIX;
|
||||||
(void) g_strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path));
|
(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] == '@')
|
if (s_un.sun_path[0] == '@')
|
||||||
s_un.sun_path[0] = '\0';
|
s_un.sun_path[0] = '\0';
|
||||||
|
|
||||||
if (bind(fd, (struct sockaddr *) &s_un, s_un_len))
|
if (bind(fd, (struct sockaddr *) &s_un, s_un_len))
|
||||||
{
|
{
|
||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SHARKD_TCP_SUPPORT
|
#ifdef SHARKD_TCP_SUPPORT
|
||||||
if (!strncmp(path, "tcp:", 4))
|
if (!strncmp(path, "tcp:", 4))
|
||||||
{
|
{
|
||||||
struct sockaddr_in s_in;
|
struct sockaddr_in s_in;
|
||||||
int one = 1;
|
int one = 1;
|
||||||
char *port_sep;
|
char *port_sep;
|
||||||
guint16 port;
|
guint16 port;
|
||||||
|
|
||||||
path += 4;
|
path += 4;
|
||||||
|
|
||||||
port_sep = strchr(path, ':');
|
port_sep = strchr(path, ':');
|
||||||
if (!port_sep)
|
if (!port_sep)
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
|
|
||||||
*port_sep = '\0';
|
*port_sep = '\0';
|
||||||
|
|
||||||
if (ws_strtou16(port_sep + 1, NULL, &port) == FALSE)
|
if (ws_strtou16(port_sep + 1, NULL, &port) == FALSE)
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/* Need to use WSASocket() to disable overlapped I/O operations,
|
/* Need to use WSASocket() to disable overlapped I/O operations,
|
||||||
this way on windows SOCKET can be used as HANDLE for stdin/stdout */
|
this way on windows SOCKET can be used as HANDLE for stdin/stdout */
|
||||||
fd = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
|
fd = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
|
||||||
#else
|
#else
|
||||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
#endif
|
#endif
|
||||||
if (fd == INVALID_SOCKET)
|
if (fd == INVALID_SOCKET)
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
|
|
||||||
s_in.sin_family = AF_INET;
|
s_in.sin_family = AF_INET;
|
||||||
ws_inet_pton4(path, &(s_in.sin_addr.s_addr));
|
ws_inet_pton4(path, &(s_in.sin_addr.s_addr));
|
||||||
s_in.sin_port = g_htons(port);
|
s_in.sin_port = g_htons(port);
|
||||||
*port_sep = ':';
|
*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)))
|
if (bind(fd, (struct sockaddr *) &s_in, sizeof(struct sockaddr_in)))
|
||||||
{
|
{
|
||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(fd, SOMAXCONN))
|
if (listen(fd, SOMAXCONN))
|
||||||
{
|
{
|
||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_usage(FILE* output)
|
print_usage(FILE* output)
|
||||||
{
|
{
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Usage: sharkd [<classic_options>|<gold_options>]\n");
|
fprintf(output, "Usage: sharkd [<classic_options>|<gold_options>]\n");
|
||||||
|
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Classic (classic_options):\n");
|
fprintf(output, "Classic (classic_options):\n");
|
||||||
fprintf(output, " [-|<socket>]\n");
|
fprintf(output, " [-|<socket>]\n");
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, " <socket> examples:\n");
|
fprintf(output, " <socket> examples:\n");
|
||||||
#ifdef SHARKD_UNIX_SUPPORT
|
#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
|
#endif
|
||||||
#ifdef SHARKD_TCP_SUPPORT
|
#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
|
#endif
|
||||||
|
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Gold (gold_options):\n");
|
fprintf(output, "Gold (gold_options):\n");
|
||||||
fprintf(output, " -a <socket>, --api <socket>\n");
|
fprintf(output, " -a <socket>, --api <socket>\n");
|
||||||
fprintf(output, " listen on this socket\n");
|
fprintf(output, " listen on this socket\n");
|
||||||
fprintf(output, " -h, --help show this help information\n");
|
fprintf(output, " -h, --help show this help information\n");
|
||||||
fprintf(output, " -v, --version show version information\n");
|
fprintf(output, " -v, --version show version information\n");
|
||||||
fprintf(output, " -C <config profile>, --config-profile <config profile>\n");
|
fprintf(output, " -C <config profile>, --config-profile <config profile>\n");
|
||||||
fprintf(output, " start with specified configuration profile\n");
|
fprintf(output, " start with specified configuration profile\n");
|
||||||
|
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, " Examples:\n");
|
fprintf(output, " Examples:\n");
|
||||||
fprintf(output, " sharkd -C myprofile\n");
|
fprintf(output, " sharkd -C myprofile\n");
|
||||||
fprintf(output, " sharkd -a tcp:127.0.0.1:4446 -C myprofile\n");
|
fprintf(output, " sharkd -a tcp:127.0.0.1:4446 -C myprofile\n");
|
||||||
|
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "See the sharkd page of the Wireshark wiki for full details.\n");
|
fprintf(output, "See the sharkd page of the Wireshark wiki for full details.\n");
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sharkd_init(int argc, char **argv)
|
sharkd_init(int argc, char **argv)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The leading + ensures that getopt_long() does not permute the argv[]
|
* The leading + ensures that getopt_long() does not permute the argv[]
|
||||||
* entries.
|
* entries.
|
||||||
*
|
*
|
||||||
* We have to make sure that the first getopt_long() preserves the content
|
* We have to make sure that the first getopt_long() preserves the content
|
||||||
* of argv[] for the subsequent getopt_long() call.
|
* of argv[] for the subsequent getopt_long() call.
|
||||||
*
|
*
|
||||||
* We use getopt_long() in both cases to ensure that we're using a routine
|
* 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
|
* 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
|
* platforms, and so that, if we ever need to process a long argument before
|
||||||
* doing further initialization, we can do so.
|
* doing further initialization, we can do so.
|
||||||
*
|
*
|
||||||
* Glibc and Solaris libc document that a leading + disables permutation
|
* Glibc and Solaris libc document that a leading + disables permutation
|
||||||
* of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
|
* of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
|
||||||
* and macOS don't document it, but do so anyway.
|
* and macOS don't document it, but do so anyway.
|
||||||
*
|
*
|
||||||
* We do *not* use a leading - because the behavior of a leading - is
|
* We do *not* use a leading - because the behavior of a leading - is
|
||||||
* platform-dependent.
|
* platform-dependent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define OPTSTRING "+" "a:hmvC:"
|
#define OPTSTRING "+" "a:hmvC:"
|
||||||
|
|
||||||
static const char optstring[] = OPTSTRING;
|
static const char optstring[] = OPTSTRING;
|
||||||
|
|
||||||
// right now we don't have any long options
|
// right now we don't have any long options
|
||||||
static const struct ws_option long_options[] = {
|
static const struct ws_option long_options[] = {
|
||||||
{"api", ws_required_argument, NULL, 'a'},
|
{"api", ws_required_argument, NULL, 'a'},
|
||||||
{"help", ws_no_argument, NULL, 'h'},
|
{"help", ws_no_argument, NULL, 'h'},
|
||||||
{"version", ws_no_argument, NULL, 'v'},
|
{"version", ws_no_argument, NULL, 'v'},
|
||||||
{"config-profile", ws_required_argument, NULL, 'C'},
|
{"config-profile", ws_required_argument, NULL, 'C'},
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
#endif
|
#endif
|
||||||
socket_handle_t fd;
|
socket_handle_t fd;
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
print_usage(stderr);
|
print_usage(stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for classic command line
|
// check for classic command line
|
||||||
if (!strcmp(argv[1], "-") || argv[1][0] == 't' || argv[1][0] == 'u')
|
if (!strcmp(argv[1], "-") || argv[1][0] == 't' || argv[1][0] == 'u')
|
||||||
{
|
{
|
||||||
mode = SHARKD_MODE_CLASSIC_CONSOLE;
|
mode = SHARKD_MODE_CLASSIC_CONSOLE;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
signal(SIGCHLD, SIG_IGN);
|
signal(SIGCHLD, SIG_IGN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!strcmp(argv[1], "-"))
|
if (!strcmp(argv[1], "-"))
|
||||||
{
|
{
|
||||||
mode = SHARKD_MODE_CLASSIC_CONSOLE;
|
mode = SHARKD_MODE_CLASSIC_CONSOLE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fd = socket_init(argv[1]);
|
fd = socket_init(argv[1]);
|
||||||
if (fd == INVALID_SOCKET)
|
if (fd == INVALID_SOCKET)
|
||||||
return -1;
|
return -1;
|
||||||
_server_fd = fd;
|
_server_fd = fd;
|
||||||
mode = SHARKD_MODE_CLASSIC_DAEMON;
|
mode = SHARKD_MODE_CLASSIC_DAEMON;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mode = SHARKD_MODE_GOLD_CONSOLE; // assume we are running as gold console
|
mode = SHARKD_MODE_GOLD_CONSOLE; // assume we are running as gold console
|
||||||
|
|
||||||
if (mode >= SHARKD_MODE_GOLD_CONSOLE)
|
if (mode >= SHARKD_MODE_GOLD_CONSOLE)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
In Daemon Mode, we will come through here twice; once when we start the Daemon and
|
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
|
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
|
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
|
socket and so in the orignal version of sharkd the session process is invoked with
|
||||||
the command line: sharkd -
|
the command line: sharkd -
|
||||||
|
|
||||||
When not using the classic command line, we want to spawn the session process with
|
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
|
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
|
parameter removed. Invoking a second time with the -a option will cause a loop
|
||||||
where we repeatedly spawn a new session process.
|
where we repeatedly spawn a new session process.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (ws_optind > (argc - 1))
|
if (ws_optind > (argc - 1))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
opt = ws_getopt_long(argc, argv, optstring, long_options, NULL);
|
opt = ws_getopt_long(argc, argv, optstring, long_options, NULL);
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'C': /* Configuration Profile */
|
case 'C': /* Configuration Profile */
|
||||||
if (profile_exists(ws_optarg, FALSE)) {
|
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
|
set_profile_name(ws_optarg); // In Daemon Mode, we may need to do this again in the child process
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "Configuration Profile \"%s\" does not exist\n", ws_optarg);
|
fprintf(stderr, "Configuration Profile \"%s\" does not exist\n", ws_optarg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
fd = socket_init(ws_optarg);
|
fd = socket_init(ws_optarg);
|
||||||
if (fd == INVALID_SOCKET)
|
if (fd == INVALID_SOCKET)
|
||||||
return -1;
|
return -1;
|
||||||
_server_fd = fd;
|
_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;
|
mode = SHARKD_MODE_GOLD_DAEMON;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
print_usage(stderr);
|
print_usage(stderr);
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
// m is an internal-only option used when the daemon session process is created
|
// m is an internal-only option used when the daemon session process is created
|
||||||
mode = SHARKD_MODE_GOLD_CONSOLE;
|
mode = SHARKD_MODE_GOLD_CONSOLE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v': /* Show version and exit */
|
case 'v': /* Show version and exit */
|
||||||
show_version();
|
show_version();
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!ws_optopt)
|
if (!ws_optopt)
|
||||||
fprintf(stderr, "This option isn't supported: %s\n", argv[ws_optind]);
|
fprintf(stderr, "This option isn't supported: %s\n", argv[ws_optind]);
|
||||||
fprintf(stderr, "Use sharkd -h for details of supported options\n");
|
fprintf(stderr, "Use sharkd -h for details of supported options\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (opt != -1);
|
} while (opt != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == SHARKD_MODE_CLASSIC_DAEMON || mode == SHARKD_MODE_GOLD_DAEMON)
|
if (mode == SHARKD_MODE_CLASSIC_DAEMON || mode == SHARKD_MODE_GOLD_DAEMON)
|
||||||
{
|
{
|
||||||
/* all good - try to daemonize */
|
/* all good - try to daemonize */
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
fprintf(stderr, "cannot go to background fork() failed: %s\n", g_strerror(errno));
|
fprintf(stderr, "cannot go to background fork() failed: %s\n", g_strerror(errno));
|
||||||
|
|
||||||
if (pid != 0)
|
if (pid != 0)
|
||||||
{
|
{
|
||||||
/* parent */
|
/* parent */
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -362,118 +362,105 @@ sharkd_loop(int argc _U_, char* argv[] _U_)
|
||||||
sharkd_loop(int argc _U_, char* argv[])
|
sharkd_loop(int argc _U_, char* argv[])
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (mode == SHARKD_MODE_CLASSIC_CONSOLE || mode == SHARKD_MODE_GOLD_CONSOLE)
|
if (mode == SHARKD_MODE_CLASSIC_CONSOLE || mode == SHARKD_MODE_GOLD_CONSOLE)
|
||||||
{
|
{
|
||||||
return sharkd_session_main(mode);
|
return sharkd_session_main(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
#else
|
#else
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
char *exename;
|
char *exename;
|
||||||
char command_line[2048];
|
char command_line[2048];
|
||||||
#endif
|
#endif
|
||||||
socket_handle_t fd;
|
socket_handle_t fd;
|
||||||
|
|
||||||
fd = accept(_server_fd, NULL, NULL);
|
fd = accept(_server_fd, NULL, NULL);
|
||||||
if (fd == INVALID_SOCKET)
|
if (fd == INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "cannot accept(): %s\n", g_strerror(errno));
|
fprintf(stderr, "cannot accept(): %s\n", g_strerror(errno));
|
||||||
continue;
|
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
|
#ifndef _WIN32
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
{
|
{
|
||||||
closesocket(_server_fd);
|
closesocket(_server_fd);
|
||||||
/* redirect stdin, stdout to socket */
|
/* redirect stdin, stdout to socket */
|
||||||
dup2(fd, 0);
|
dup2(fd, 0);
|
||||||
dup2(fd, 1);
|
dup2(fd, 1);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
exit(sharkd_session_main(mode));
|
exit(sharkd_session_main(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "cannot fork(): %s\n", g_strerror(errno));
|
fprintf(stderr, "cannot fork(): %s\n", g_strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
memset(&pi, 0, sizeof(pi));
|
memset(&pi, 0, sizeof(pi));
|
||||||
memset(&si, 0, sizeof(si));
|
memset(&si, 0, sizeof(si));
|
||||||
|
|
||||||
si.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||||
si.hStdInput = (HANDLE) fd;
|
si.hStdInput = (HANDLE) fd;
|
||||||
si.hStdOutput = (HANDLE) fd;
|
si.hStdOutput = (HANDLE) fd;
|
||||||
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
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
|
// 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
|
// 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));
|
memset(&command_line, 0, sizeof(command_line));
|
||||||
|
|
||||||
if (mode <= SHARKD_MODE_CLASSIC_DAEMON)
|
if (mode <= SHARKD_MODE_CLASSIC_DAEMON)
|
||||||
{
|
{
|
||||||
(void) g_strlcat(command_line, "sharkd.exe -", sizeof(command_line));
|
(void) g_strlcat(command_line, "sharkd.exe -", sizeof(command_line));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The -m option used here is an internal-only option that notifies the child process that it should
|
// The -m option used here is an internal-only option that notifies the child process that it should
|
||||||
// run in Gold Console mode
|
// run in Gold Console mode
|
||||||
(void) g_strlcat(command_line, "sharkd.exe -m", sizeof(command_line));
|
(void) g_strlcat(command_line, "sharkd.exe -m", sizeof(command_line));
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
!g_ascii_strncasecmp(argv[i], "-a", (guint)strlen(argv[i]))
|
!g_ascii_strncasecmp(argv[i], "-a", (guint)strlen(argv[i]))
|
||||||
|| !g_ascii_strncasecmp(argv[i], "--api", (guint)strlen(argv[i]))
|
|| !g_ascii_strncasecmp(argv[i], "--api", (guint)strlen(argv[i]))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
i++; // skip the socket details
|
i++; // skip the socket details
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(void) g_strlcat(command_line, " ", sizeof(command_line));
|
(void) g_strlcat(command_line, " ", sizeof(command_line));
|
||||||
(void) g_strlcat(command_line, argv[i], 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))
|
if (!win32_create_process(exename, command_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "win32_create_process(%s) failed\n", exename);
|
fprintf(stderr, "win32_create_process(%s) failed\n", exename);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(exename);
|
g_free(exename);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
}
|
}
|
||||||
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:
|
|
||||||
*/
|
|
||||||
|
|
6447
sharkd_session.c
6447
sharkd_session.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue