dumpcap: Make capture child logging work

Distinguish log messages from SP_ERROR_MSG; log messages don't
necessarily represent a failure, and they have a level. This
doesn't affect logging while capturing much, as SP_ERROR_MSGs
are just printed to the console, but it makes it possible to log
while retrieving interface information or the stats, where SP_ERROR_MSG
indicates that the command failed.
This commit is contained in:
John Thacker 2023-12-31 16:38:37 -05:00
parent 2bf14f5fe6
commit 3fbefe9c36
3 changed files with 63 additions and 22 deletions

View File

@ -218,6 +218,23 @@ sync_pipe_add_arg(char **args, int *argc, const char *arg)
return args; return args;
} }
/* Take a buffer from an SP_LOG_MSG from dumpcap and send it to our
* current logger. Keep this in sync with the format used in
* dumpcap_log_writer. (We might want to do more proper serialization
* of more than just the log level.)
*/
static void
sync_pipe_handle_log_msg(const char *buffer) {
const char *log_msg = NULL;
const char* end;
uint32_t level = 0;
if (ws_strtou32(buffer, &end, &level) && end[0] == ':') {
log_msg = end + 1;
}
ws_log(LOG_DOMAIN_CAPCHILD, level, "%s", log_msg);
}
/* Initialize an argument list and add dumpcap to it. */ /* Initialize an argument list and add dumpcap to it. */
static char ** static char **
init_pipe_args(int *argc) { init_pipe_args(int *argc) {
@ -1140,6 +1157,13 @@ sync_pipe_run_command_actual(char **argv, char **data, char **primary_msg,
*data = NULL; *data = NULL;
break; break;
case SP_LOG_MSG:
/*
* Log from dumpcap; pass to our log
*/
sync_pipe_handle_log_msg(buffer);
break;
case SP_SUCCESS: case SP_SUCCESS:
/* read the output from the command */ /* read the output from the command */
data_buf = g_string_new(""); data_buf = g_string_new("");
@ -1566,6 +1590,13 @@ sync_interface_stats_open(int *data_read_fd, ws_process_id *fork_child, char **d
} }
return ret; return ret;
case SP_LOG_MSG:
/*
* Log from dumpcap; pass to our log
*/
sync_pipe_handle_log_msg(buffer);
break;
case SP_IFACE_LIST: case SP_IFACE_LIST:
/* /*
* Dumpcap giving us the interface list * Dumpcap giving us the interface list
@ -1910,6 +1941,12 @@ sync_pipe_input_cb(GIOChannel *pipe_io, capture_session *cap_session)
/* the capture child will close the sync_pipe, nothing to do for now */ /* the capture child will close the sync_pipe, nothing to do for now */
/* (an error message doesn't mean we have to stop capturing) */ /* (an error message doesn't mean we have to stop capturing) */
break; break;
case SP_LOG_MSG:
/*
* Log from dumpcap; pass to our log
*/
sync_pipe_handle_log_msg(buffer);
break;
case SP_BAD_FILTER: { case SP_BAD_FILTER: {
const char *message=NULL; const char *message=NULL;
uint32_t indx = 0; uint32_t indx = 0;

View File

@ -5980,18 +5980,36 @@ dumpcap_log_writer(const char *domain, enum ws_log_level level,
const char *user_format, va_list user_ap, const char *user_format, va_list user_ap,
void *user_data _U_) void *user_data _U_)
{ {
/* DEBUG & INFO msgs (if we're debugging today) */ if (ws_log_msg_is_active(domain, level)) {
#if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP) /* log messages go to stderr or */
if (level <= LOG_LEVEL_INFO && ws_log_msg_is_active(domain, level)) { /* to parent especially formatted if dumpcap running as child. */
#ifdef DEBUG_DUMPCAP
#ifdef DEBUG_CHILD_DUMPCAP #ifdef DEBUG_CHILD_DUMPCAP
va_list user_ap_copy; va_list user_ap_copy;
va_copy(user_ap_copy, user_ap); va_copy(user_ap_copy, user_ap);
#endif #endif
if (capture_child) { if (capture_child) {
gchar *msg = ws_strdup_vprintf(user_format, user_ap); /* Format the log mesage as the numeric level, followed
sync_pipe_write_errmsgs_to_parent(sync_pipe_fd, msg, ""); * by a colon and then a string matching the standard log
g_free(msg); * string. In the future perhaps we serialize file, line,
* and func (which can be NULL) instead.
*/
GString *msg = g_string_new(NULL);
g_string_append_printf(msg, "%u:", level);
if (file != NULL) {
g_string_append_printf(msg, "%s", file);
if (line >= 0) {
g_string_append_printf(msg, ":%ld", line);
}
}
g_string_append(msg, " --");
if (func != NULL) {
g_string_append_printf(msg, " %s():", func);
}
g_string_append_c(msg, ' ');
g_string_append_vprintf(msg, user_format, user_ap);
sync_pipe_write_string_msg(sync_pipe_fd, SP_LOG_MSG, msg->str);
g_string_free(msg, TRUE);
} else { } else {
ws_log_console_writer(domain, level, file, line, func, mft, user_format, user_ap); ws_log_console_writer(domain, level, file, line, func, mft, user_format, user_ap);
} }
@ -5999,21 +6017,6 @@ dumpcap_log_writer(const char *domain, enum ws_log_level level,
ws_log_file_writer(debug_log, domain, level, file, line, func, mft, user_format, user_ap_copy); ws_log_file_writer(debug_log, domain, level, file, line, func, mft, user_format, user_ap_copy);
va_end(user_ap_copy); va_end(user_ap_copy);
#endif #endif
#elif defined(DEBUG_CHILD_DUMPCAP)
ws_log_file_writer(debug_log, domain, level, file, line, func, mft, user_format, user_ap);
#endif
return;
}
#endif
/* ERROR, CRITICAL, WARNING, MESSAGE messages goto stderr or */
/* to parent especially formatted if dumpcap running as child. */
if (capture_child) {
gchar *msg = ws_strdup_vprintf(user_format, user_ap);
sync_pipe_write_errmsgs_to_parent(sync_pipe_fd, msg, "");
g_free(msg);
} else if(ws_log_msg_is_active(domain, level)) {
ws_log_console_writer(domain, level, file, line, func, mft, user_format, user_ap);
} }
} }

View File

@ -42,6 +42,7 @@
#define SP_EXEC_FAILED 'X' /* errno value for the exec failing */ #define SP_EXEC_FAILED 'X' /* errno value for the exec failing */
#define SP_FILE 'F' /* the name of the recently opened file */ #define SP_FILE 'F' /* the name of the recently opened file */
#define SP_ERROR_MSG 'E' /* error message */ #define SP_ERROR_MSG 'E' /* error message */
#define SP_LOG_MSG 'L' /* log message */
#define SP_BAD_FILTER 'B' /* error message for bad capture filter */ #define SP_BAD_FILTER 'B' /* error message for bad capture filter */
#define SP_PACKET_COUNT 'P' /* count of packets captured since last message */ #define SP_PACKET_COUNT 'P' /* count of packets captured since last message */
#define SP_DROPS 'D' /* count of packets dropped in capture */ #define SP_DROPS 'D' /* count of packets dropped in capture */