diff --git a/epan/column-utils.c b/epan/column-utils.c index de134a7e03..109ecbdc7f 100644 --- a/epan/column-utils.c +++ b/epan/column-utils.c @@ -380,6 +380,51 @@ col_prepend_fstr(column_info *cinfo, gint el, const gchar *format, ...) } va_end(ap); } +void +col_prepend_fence_fstr(column_info *cinfo, gint el, const gchar *format, ...) +{ + va_list ap; + int i; + char orig_buf[COL_BUF_MAX_LEN]; + const char *orig; + size_t max_len; + + g_assert(cinfo->col_first[el] >= 0); + if (el == COL_INFO) + max_len = COL_MAX_INFO_LEN; + else + max_len = COL_MAX_LEN; + + va_start(ap, format); + for (i = cinfo->col_first[el]; i <= cinfo->col_last[el]; i++) { + if (cinfo->fmt_matx[i][el]) { + if (cinfo->col_data[i] != cinfo->col_buf[i]) { + /* This was set with "col_set_str()"; which is effectively const */ + orig = cinfo->col_data[i]; + } else { + strncpy(orig_buf, cinfo->col_buf[i], max_len); + orig_buf[max_len - 1] = '\0'; + orig = orig_buf; + } + g_vsnprintf(cinfo->col_buf[i], max_len, format, ap); + cinfo->col_buf[i][max_len - 1] = '\0'; + + /* + * Move the fence if it exists, else create a new fence at the + * end of the prepended data. + */ + if (cinfo->col_fence[i] > 0) { + cinfo->col_fence[i] += strlen(cinfo->col_buf[i]); + } else { + cinfo->col_fence[i] = strlen(cinfo->col_buf[i]); + } + strncat(cinfo->col_buf[i], orig, max_len); + cinfo->col_buf[i][max_len - 1] = '\0'; + cinfo->col_data[i] = cinfo->col_buf[i]; + } + } + va_end(ap); +} /* Use this if "str" points to something that won't stay around (and must thus be copied). */ diff --git a/epan/column-utils.h b/epan/column-utils.h index f5dda5c560..c80706084d 100644 --- a/epan/column-utils.h +++ b/epan/column-utils.h @@ -168,6 +168,17 @@ extern void col_append_fstr(column_info *cinfo, gint col, const gchar *format, . extern void col_prepend_fstr(column_info *cinfo, gint col, const gchar *format, ...) GNUC_FORMAT_CHECK(printf, 3, 4); +/**Prepend the given text to a column element, the text will be formatted and copied. + * This function is similar to col_prepend_fstr() but this function will + * unconditionally set a fence to the end of the prepended data even if there + * were no fence before. + * The col_prepend_fstr() will only prepend the data before the fence IFF + * there is already a fence created. This function will create a fence in case + * it does not yet exist. + */ +extern void col_prepend_fence_fstr(column_info *cinfo, gint col, const gchar *format, ...) + GNUC_FORMAT_CHECK(printf, 3, 4); + /** Append the given text (prepended by a separator) to a column element. * * Much like col_append_str() but will prepend the given separator if the column isn't empty. diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index b44f085b30..514b651144 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -400,7 +400,7 @@ print_pdu_tracking_data(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tcp_tree, proto_item *item; if (check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", tnp->first_frame); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", tnp->first_frame); } item=proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to, tvb, 0, 0, tnp->first_frame); @@ -1309,7 +1309,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Retransmission (suspected)"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] "); } if( ta->rto_ts.secs || ta->rto_ts.nsecs ){ item = proto_tree_add_time(flags_tree, hf_tcp_analysis_rto, @@ -1326,7 +1326,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_retransmission, tvb, 0, 0, "This frame is a (suspected) retransmission"); PROTO_ITEM_SET_GENERATED(flags_item); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Fast Retransmission] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Fast Retransmission] "); } } if( ta->flags&TCP_A_OUT_OF_ORDER ){ @@ -1334,7 +1334,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN, "Out-Of-Order segment"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] "); } } if( ta->flags&TCP_A_LOST_PACKET ){ @@ -1342,7 +1342,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN, "Previous segment lost (common at capture start)"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Previous segment lost] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Previous segment lost] "); } } if( ta->flags&TCP_A_ACK_LOST_PACKET ){ @@ -1350,7 +1350,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_WARN, "ACKed lost segment (common at capture start)"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ACKed lost segment] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ACKed lost segment] "); } } if( ta->flags&TCP_A_WINDOW_UPDATE ){ @@ -1358,7 +1358,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Window update"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Update] "); } } if( ta->flags&TCP_A_WINDOW_FULL ){ @@ -1366,7 +1366,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Window is full"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Window Full] "); } } if( ta->flags&TCP_A_KEEP_ALIVE ){ @@ -1374,7 +1374,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Keep-Alive"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] "); } } if( ta->flags&TCP_A_KEEP_ALIVE_ACK ){ @@ -1382,7 +1382,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Keep-Alive ACK"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] "); } } if( ta->dupack_num){ @@ -1390,7 +1390,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_duplicate_ack, tvb, 0, 0, "This is a TCP duplicate ack"); PROTO_ITEM_SET_GENERATED(flags_item); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Dup ACK %u#%u] ", ta->dupack_frame, ta->dupack_num); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP Dup ACK %u#%u] ", ta->dupack_frame, ta->dupack_num); } } flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num, @@ -1407,7 +1407,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Zero window probe"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] "); } } if( ta->flags&TCP_A_ZERO_WINDOW ){ @@ -1415,7 +1415,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Zero window"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] "); } } if( ta->flags&TCP_A_ZERO_WINDOW_VIOLATION ){ @@ -1423,7 +1423,7 @@ tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree PROTO_ITEM_SET_GENERATED(flags_item); expert_add_info_format(pinfo, flags_item, PI_SEQUENCE, PI_NOTE, "Zero window violation"); if(check_col(pinfo->cinfo, COL_INFO)){ - col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowViolation] "); + col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowViolation] "); } } } diff --git a/epan/libethereal.def b/epan/libethereal.def index 801c3b3b6e..5114395919 100644 --- a/epan/libethereal.def +++ b/epan/libethereal.def @@ -73,6 +73,7 @@ col_format_desc col_format_to_string col_get_writable col_prepend_fstr +col_prepend_fence_fstr col_setup col_set_cls_time col_set_fence