diff options
-rw-r--r-- | capture.c | 3 | ||||
-rw-r--r-- | capture.h | 2 | ||||
-rw-r--r-- | capture_loop.c | 3 | ||||
-rw-r--r-- | capture_sync.c | 91 | ||||
-rw-r--r-- | dumpcap.c | 81 |
5 files changed, 104 insertions, 76 deletions
@@ -374,9 +374,8 @@ capture_input_drops(capture_options *capture_opts, int dropped) The secondary message might be a null string. */ void -capture_input_error_message(capture_options *capture_opts, char *error_msg) +capture_input_error_message(capture_options *capture_opts, char *error_msg, char *secondary_error_msg) { - char *secondary_error_msg = strchr(error_msg, '\0') + 1; gchar *safe_error_msg; gchar *safe_secondary_error_msg; @@ -68,7 +68,7 @@ extern void capture_input_drops(capture_options *capture_opts, int dropped); /** * Capture child told us that an error has occurred while starting the capture. */ -extern void capture_input_error_message(capture_options *capture_opts, char *error_message); +extern void capture_input_error_message(capture_options *capture_opts, char *error_message, char *secondary_error_msg); /** * Capture child told us that an error has occurred while parsing a diff --git a/capture_loop.c b/capture_loop.c index a908c5b1a7..f3c8564167 100644 --- a/capture_loop.c +++ b/capture_loop.c @@ -556,7 +556,8 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld, Do, however, warn about the lack of 64-bit support, and warn that WAN devices aren't supported. */ g_snprintf(errmsg, errmsg_len, -"The capture session could not be initiated (%s).", +"The capture session could not be initiated.\n" +"\"%s\"", open_err_str); g_snprintf(secondary_errmsg, secondary_errmsg_len, "\n" diff --git a/capture_sync.c b/capture_sync.c index 39bf34f18f..631f870df6 100644 --- a/capture_sync.c +++ b/capture_sync.c @@ -215,34 +215,24 @@ signal_pipe_capquit_to_child(capture_options *capture_opts) } #endif - - -/* read a message from the sending pipe in the standard format - (1-byte message indicator, 3-byte message length (excluding length - and indicator field), and the rest is the message) */ static int -pipe_read_block(int pipe, char *indicator, int len, char *msg) { - int required; +pipe_read_bytes(int pipe, char *bytes, int required) { int newly; - guchar header[4]; - int offset; + int offset = 0; - /* read header (indicator and 3-byte length) */ - required = 4; - offset = 0; while(required) { - newly = read(pipe, &header[offset], required); + newly = read(pipe, &bytes[offset], required); if (newly == 0) { /* EOF */ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, - "read %d header empty (capture closed)", pipe); + "read from pipe %d: EOF (capture closed?)", pipe); return newly; } if (newly < 0) { /* error */ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, - "read %d header error: %s", pipe, strerror(errno)); + "read from pipe %d: error(%u): %s", pipe, errno, strerror(errno)); return newly; } @@ -250,9 +240,40 @@ pipe_read_block(int pipe, char *indicator, int len, char *msg) { offset += newly; } + return newly; +} + +/* convert header values (indicator and 4-byte length) */ +static void +pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) { + + g_assert(header_len == 4); + /* convert header values */ *indicator = header[0]; - required = header[1]<<16 | header[2]<<8 | header[3]; + *block_len = header[1]<<16 | header[2]<<8 | header[3]; +} + +/* read a message from the sending pipe in the standard format + (1-byte message indicator, 3-byte message length (excluding length + and indicator field), and the rest is the message) */ +static int +pipe_read_block(int pipe, char *indicator, int len, char *msg) { + int required; + int newly; + guchar header[4]; + + + /* read header (indicator and 3-byte length) */ + newly = pipe_read_bytes(pipe, header, 4); + if(newly != 4) { + g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, + "read %d failed to read header: %u", pipe, newly); + return -1; + } + + /* convert header values */ + pipe_convert_header(header, 4, indicator, &required); /* only indicator with no value? */ if(required == 0) { @@ -261,6 +282,7 @@ pipe_read_block(int pipe, char *indicator, int len, char *msg) { return 4; } + /* does the data fit into the given buffer? */ if(required > len) { g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "read %d length error, required %d > len %d, indicator: %u", @@ -274,26 +296,17 @@ pipe_read_block(int pipe, char *indicator, int len, char *msg) { } len = required; - /* read value */ - offset = 0; - while(required) { - newly = read(pipe, &msg[offset], required); - if (newly == -1) { - /* error */ - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, - "read %d value error: %s, indicator: %u", pipe, - strerror(errno), *indicator); - return newly; - } - - required -= newly; - offset += newly; + /* read the actual block data */ + newly = pipe_read_bytes(pipe, msg, required); + if(newly != required) { + g_warning("Unknown message from dumpcap, try to show it as a string: %s", msg); + return -1; } g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "read %d ok indicator: %c len: %u msg: %s", pipe, *indicator, len, msg); - return len + 4; + return newly + 4; } @@ -633,7 +646,7 @@ sync_pipe_start(capture_options *capture_opts) { execv(exename, argv); g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s", exename, strerror(errno)); - sync_pipe_errmsg_to_parent(errmsg, NULL); + sync_pipe_errmsg_to_parent(errmsg, ""); /* Exit with "_exit()", so that we don't close the connection to the X server (and cause stuff buffered up by our parent but @@ -697,6 +710,10 @@ sync_pipe_input_cb(gint source, gpointer user_data) char buffer[SP_MAX_MSG_LEN+1]; int nread; char indicator; + int primary_len; + char * primary_msg; + int secondary_len; + char * secondary_msg; nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer); @@ -746,8 +763,16 @@ sync_pipe_input_cb(gint source, gpointer user_data) capture_input_new_packets(capture_opts, nread); break; case SP_ERROR_MSG: - capture_input_error_message(capture_opts, buffer); + /* convert primary message */ + pipe_convert_header(buffer, 4, &indicator, &primary_len); + primary_msg = buffer+4; + /* convert secondary message */ + pipe_convert_header(primary_msg + primary_len, 4, &indicator, &secondary_len); + secondary_msg = primary_msg + primary_len + 4; + /* message output */ + capture_input_error_message(capture_opts, primary_msg, secondary_msg); /* the capture child will close the sync_pipe, nothing to do for now */ + /* (an error message doesn't mean we have to stop capturing) */ break; case SP_BAD_FILTER: capture_input_cfilter_error_message(capture_opts, buffer); @@ -337,6 +337,10 @@ main(int argc, char *argv[]) /*** hidden option: Ethereal child mode (using binary output messages) ***/ case 'Z': capture_child = TRUE; +#ifdef _WIN32 + /* set output pipe to binary mode, to avoid ugly text conversions */ + _setmode(1, O_BINARY); +#endif break; /*** all non capture option specific ***/ @@ -505,51 +509,51 @@ console_log_handler(const char *log_domain, GLogLevelFlags log_level, /* * Maximum length of sync pipe message data. Must be < 2^24, as the * message length is 3 bytes. - * XXX - this must be large enough to handle a Really Big Filter + * XXX - this should be large enough to handle a Really Big Filter * Expression, as the error message for an incorrect filter expression * is a bit larger than the filter expression. */ #define SP_MAX_MSG_LEN 4096 +/* write a single message header to the recipient pipe */ +static int +pipe_write_header(int pipe, char indicator, int length) +{ + guchar header[1+3]; /* indicator + 3-byte len */ + + + g_assert(length <= SP_MAX_MSG_LEN); + + /* write header (indicator + 3-byte len) */ + header[0] = indicator; + header[1] = (length >> 16) & 0xFF; + header[2] = (length >> 8) & 0xFF; + header[3] = (length >> 0) & 0xFF; + + /* write header */ + return write(pipe, header, sizeof header); +} /* write a message to the recipient pipe in the standard format (3 digit message length (excluding length and indicator field), 1 byte message indicator and the rest is the message). - If msg is NULL, the message has only a length and indicator. - Otherwise, if secondary_msg isn't NULL, send both msg and - secondary_msg as null-terminated strings, otherwise just send - msg as a null-terminated string and follow it with an empty string. */ + If msg is NULL, the message has only a length and indicator. */ static void -pipe_write_block(int pipe, char indicator, const char *msg, - const char *secondary_msg) +pipe_write_block(int pipe, char indicator, const char *msg) { - guchar header[3+1]; /* indicator + 3-byte len */ int ret; - size_t len, secondary_len, total_len; + size_t len; /*g_warning("write %d enter", pipe);*/ - len = 0; - secondary_len = 0; - total_len = 0; if(msg != NULL) { - len = strlen(msg) + 1; /* include the terminating '\0' */ - total_len = len; - if(secondary_msg == NULL) - secondary_msg = ""; /* default to an empty string */ - secondary_len = strlen(secondary_msg) + 1; - total_len += secondary_len; + len = strlen(msg) + 1; /* including the terminating '\0'! */ + } else { + len = 0; } - g_assert(indicator < '0' || indicator > '9'); - g_assert(total_len <= SP_MAX_MSG_LEN); /* write header (indicator + 3-byte len) */ - header[0] = indicator; - header[1] = (total_len >> 16) & 0xFF; - header[2] = (total_len >> 8) & 0xFF; - header[3] = (total_len >> 0) & 0xFF; - - ret = write(pipe, header, sizeof header); + ret = pipe_write_header(pipe, indicator, len); if(ret == -1) { return; } @@ -561,10 +565,6 @@ pipe_write_block(int pipe, char indicator, const char *msg, if(ret == -1) { return; } - ret = write(pipe, secondary_msg, secondary_len); - if(ret == -1) { - return; - } } else { /*g_warning("write %d indicator: %c no value", pipe, indicator);*/ } @@ -583,7 +583,7 @@ sync_pipe_packet_count_to_parent(int packet_count) if(capture_child) { g_snprintf(tmp, sizeof(tmp), "%d", packet_count); g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Packets: %s", tmp); - pipe_write_block(1, SP_PACKET_COUNT, tmp, NULL); + pipe_write_block(1, SP_PACKET_COUNT, tmp); } else { count += packet_count; fprintf(stderr, "\rPackets: %u ", count); @@ -600,7 +600,7 @@ sync_pipe_filename_to_parent(const char *filename) g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "File: %s", filename); if(capture_child) { - pipe_write_block(1, SP_FILE, filename, NULL); + pipe_write_block(1, SP_FILE, filename); } } @@ -612,7 +612,7 @@ sync_pipe_cfilter_error_to_parent(const char *cfilter _U_, const char *errmsg) g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Capture filter error: %s", errmsg); if (capture_child) { - pipe_write_block(1, SP_BAD_FILTER, errmsg, NULL); + pipe_write_block(1, SP_BAD_FILTER, errmsg); } } @@ -620,13 +620,16 @@ void sync_pipe_errmsg_to_parent(const char *error_msg, const char *secondary_error_msg) { - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "Error: %s", error_msg); - if (secondary_error_msg != NULL) - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "Secondary error: %s", - secondary_error_msg); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, + "Primary Error: %s", error_msg); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, + "Secondary Error: %s", secondary_error_msg); if(capture_child) { - pipe_write_block(1, SP_ERROR_MSG, error_msg, secondary_error_msg); + /* first write a "master header" with the length of the two messages plus their "slave headers" */ + pipe_write_header(1, SP_ERROR_MSG, strlen(error_msg) + 1 + 4 + strlen(secondary_error_msg) + 1 + 4); + pipe_write_block(1, SP_ERROR_MSG, error_msg); + pipe_write_block(1, SP_ERROR_MSG, secondary_error_msg); } } @@ -640,7 +643,7 @@ sync_pipe_drops_to_parent(int drops) g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "Packets dropped: %s", tmp); if(capture_child) { - pipe_write_block(1, SP_DROPS, tmp, NULL); + pipe_write_block(1, SP_DROPS, tmp); } } |