From edcc2f019e3729293d9410e1bb30dae6bc9b790a Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Sat, 23 Jul 2016 21:25:05 -0400 Subject: [PATCH] Add OSI Layer 4 to exported PDU to handle TCP and UDP payloads. This allows for much easier anonymized captures for protocols running atop TCP/UDP. Added support for "TCP dissector data" tag within export PDU (34) so that the tcpinfo struct that TCP dissector normally passes to its subdissectors can be saved. Change-Id: Icd63c049162332e5bcb2720159e5cf8aac893788 Reviewed-on: https://code.wireshark.org/review/16285 Reviewed-by: Michael Mann --- debian/libwireshark0.symbols | 2 + epan/dissectors/packet-exported_pdu.c | 35 +++++- epan/dissectors/packet-tcp.c | 163 ++++++++++++++++++++++++++ epan/dissectors/packet-tcp.h | 7 +- epan/dissectors/packet-udp.c | 102 +++++++++++++++- epan/exported_pdu.c | 24 +++- epan/exported_pdu.h | 19 ++- 7 files changed, 342 insertions(+), 10 deletions(-) diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols index 23ed83067c..5e2bd7e6f2 100644 --- a/debian/libwireshark0.symbols +++ b/debian/libwireshark0.symbols @@ -541,6 +541,8 @@ libwireshark.so.0 libwireshark0 #MINVER# expert_update_comment_count@Base 1.12.0~rc1 export_pdu_create_common_tags@Base 2.1.1 export_pdu_create_tags@Base 2.1.1 + exp_pdu_data_dissector_table_num_value_size@Base 2.1.1 + exp_pdu_data_dissector_table_num_value_populate_data@Base 2.1.1 ext_menubar_add_entry@Base 1.99.8 ext_menubar_add_separator@Base 1.99.8 ext_menubar_add_submenu@Base 1.99.8 diff --git a/epan/dissectors/packet-exported_pdu.c b/epan/dissectors/packet-exported_pdu.c index dcedd3409d..d61074a4f9 100644 --- a/epan/dissectors/packet-exported_pdu.c +++ b/epan/dissectors/packet-exported_pdu.c @@ -30,6 +30,7 @@ #include #include "packet-mtp3.h" #include "packet-dvbci.h" +#include "packet-tcp.h" void proto_register_exported_pdu(void); void proto_reg_handoff_exported_pdu(void); @@ -48,6 +49,7 @@ static int hf_exported_pdu_unknown_tag_val = -1; static int hf_exported_pdu_prot_name = -1; static int hf_exported_pdu_heur_prot_name = -1; static int hf_exported_pdu_dis_table_name = -1; +static int hf_exported_pdu_dissector_data = -1; static int hf_exported_pdu_ipv4_src = -1; static int hf_exported_pdu_ipv4_dst = -1; static int hf_exported_pdu_ipv6_src = -1; @@ -101,6 +103,7 @@ static const value_string exported_pdu_tag_vals[] = { { EXP_PDU_TAG_DVBCI_EVT, "DVB-CI event" }, { EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL, "Dissector table value" }, { EXP_PDU_TAG_COL_PROT_TEXT, "Column Protocol String" }, + { EXP_PDU_TAG_TCP_INFO_DATA, "TCP Dissector Data" }, { 0, NULL } }; @@ -124,6 +127,7 @@ dissect_exported_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* guint8 dvb_ci_dir; guint32 dissector_table_val=0; dissector_table_t dis_tbl; + void* dissector_data = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "Exported PDU"); @@ -239,6 +243,25 @@ dissect_exported_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* case EXP_PDU_TAG_COL_PROT_TEXT: proto_tree_add_item_ret_string(tag_tree, hf_exported_pdu_col_proto_str, tvb, offset, tag_len, ENC_UTF_8 | ENC_NA, wmem_packet_scope(), &col_proto_str); break; + case EXP_PDU_TAG_TCP_INFO_DATA: + { + struct tcpinfo* tcpdata = wmem_new0(wmem_packet_scope(), struct tcpinfo); + guint16 version; + proto_tree_add_item(tag_tree, hf_exported_pdu_dissector_data, tvb, offset, tag_len, ENC_NA); + + version = tvb_get_ntohs(tvb, offset); + DISSECTOR_ASSERT(version == 1); /* Only version 1 is currently supported */ + + tcpdata->seq = tvb_get_ntohl(tvb, offset+2); + tcpdata->nxtseq = tvb_get_ntohl(tvb, offset+6); + tcpdata->lastackseq = tvb_get_ntohl(tvb, offset+10); + tcpdata->is_reassembled = tvb_get_guint8(tvb, offset+14); + tcpdata->flags = tvb_get_ntohs(tvb, offset+15); + tcpdata->urgent_pointer = tvb_get_ntohs(tvb, offset+17); + + dissector_data = tcpdata; + } + break; case EXP_PDU_TAG_END_OF_OPT: break; default: @@ -258,7 +281,7 @@ dissect_exported_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* proto_handle = find_dissector(proto_name); if (proto_handle) { col_clear(pinfo->cinfo, COL_PROTOCOL); - call_dissector(proto_handle, payload_tvb, pinfo, tree); + call_dissector_with_data(proto_handle, payload_tvb, pinfo, tree, dissector_data); } break; case EXPORTED_PDU_NEXT_HEUR_PROTO_STR: @@ -266,7 +289,7 @@ dissect_exported_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* heur_dtbl_entry_t *heur_diss = find_heur_dissector_by_unique_short_name(proto_name); if (heur_diss) { col_clear(pinfo->cinfo, COL_PROTOCOL); - call_heur_dissector_direct(heur_diss, payload_tvb, pinfo, tree, NULL); + call_heur_dissector_direct(heur_diss, payload_tvb, pinfo, tree, dissector_data); } break; } @@ -278,7 +301,7 @@ dissect_exported_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* if (col_proto_str) { col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "%s",col_proto_str); } - dissector_try_uint_new(dis_tbl, dissector_table_val, payload_tvb, pinfo, tree, FALSE, NULL); + dissector_try_uint_new(dis_tbl, dissector_table_val, payload_tvb, pinfo, tree, FALSE, dissector_data); } } default: @@ -328,6 +351,11 @@ proto_register_exported_pdu(void) FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } }, + { &hf_exported_pdu_dissector_data, + { "Dissector Data", "exported_pdu.dissector_data", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL } + }, { &hf_exported_pdu_ipv4_src, { "IPv4 Src", "exported_pdu.ipv4_src", FT_IPv4, BASE_NONE, NULL, 0, @@ -442,6 +470,7 @@ proto_register_exported_pdu(void) * want to export their PDUs, see packet-sip.c */ register_export_pdu_tap(EXPORT_PDU_TAP_NAME_LAYER_3); + register_export_pdu_tap(EXPORT_PDU_TAP_NAME_LAYER_4); register_export_pdu_tap(EXPORT_PDU_TAP_NAME_LAYER_7); } diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c index ce68526df4..bc7f4fd26c 100644 --- a/epan/dissectors/packet-tcp.c +++ b/epan/dissectors/packet-tcp.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,7 @@ void proto_reg_handoff_tcp(void); static int tcp_tap = -1; static int tcp_follow_tap = -1; static int mptcp_tap = -1; +static int exported_pdu_tap = -1; /* Place TCP summary in proto tree */ static gboolean tcp_summary_in_tree = TRUE; @@ -810,6 +812,151 @@ gchar* tcp_follow_address_filter(address* src_addr, address* dst_addr, int src_p } +#define EXP_PDU_TCP_INFO_DATA_LEN 19 +#define EXP_PDU_TCP_INFO_VERSION 1 + +int exp_pdu_tcp_dissector_data_size(packet_info *pinfo _U_, void* data _U_) +{ + return EXP_PDU_TCP_INFO_DATA_LEN+4; +} + +int exp_pdu_tcp_dissector_data_populate_data(packet_info *pinfo _U_, void* data, guint8 *tlv_buffer, guint32 buffer_size _U_) +{ + struct tcpinfo* dissector_data = (struct tcpinfo*)data; + + tlv_buffer[0] = 0; + tlv_buffer[1] = EXP_PDU_TAG_TCP_INFO_DATA; + tlv_buffer[2] = 0; + tlv_buffer[3] = EXP_PDU_TCP_INFO_DATA_LEN; /* tag length */ + tlv_buffer[4] = 0; + tlv_buffer[5] = EXP_PDU_TCP_INFO_VERSION; + tlv_buffer[6] = (dissector_data->seq & 0xff000000) >> 24; + tlv_buffer[7] = (dissector_data->seq & 0x00ff0000) >> 16; + tlv_buffer[8] = (dissector_data->seq & 0x0000ff00) >> 8; + tlv_buffer[9] = (dissector_data->seq & 0x000000ff); + tlv_buffer[10] = (dissector_data->nxtseq & 0xff000000) >> 24; + tlv_buffer[11] = (dissector_data->nxtseq & 0x00ff0000) >> 16; + tlv_buffer[12] = (dissector_data->nxtseq & 0x0000ff00) >> 8; + tlv_buffer[13] = (dissector_data->nxtseq & 0x000000ff); + tlv_buffer[14] = (dissector_data->lastackseq & 0xff000000) >> 24; + tlv_buffer[15] = (dissector_data->lastackseq & 0x00ff0000) >> 16; + tlv_buffer[16] = (dissector_data->lastackseq & 0x0000ff00) >> 8; + tlv_buffer[17] = (dissector_data->lastackseq & 0x000000ff); + tlv_buffer[18] = dissector_data->is_reassembled; + tlv_buffer[19] = (dissector_data->flags & 0xff00) >> 8; + tlv_buffer[20] = (dissector_data->flags & 0x00ff); + tlv_buffer[21] = (dissector_data->urgent_pointer & 0xff00) >> 8; + tlv_buffer[22] = (dissector_data->urgent_pointer & 0x00ff); + + return exp_pdu_tcp_dissector_data_size(pinfo, data); +} + +static void +handle_export_pdu_dissection_table(packet_info *pinfo, tvbuff_t *tvb, guint32 port, struct tcpinfo *tcpinfo) +{ + if (have_tap_listener(exported_pdu_tap)) { + exp_pdu_data_item_t exp_pdu_data_table_value = {exp_pdu_data_dissector_table_num_value_size, exp_pdu_data_dissector_table_num_value_populate_data, NULL}; + exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL}; + const exp_pdu_data_item_t *tcp_exp_pdu_items[] = { + &exp_pdu_data_src_ip, + &exp_pdu_data_dst_ip, + &exp_pdu_data_port_type, + &exp_pdu_data_src_port, + &exp_pdu_data_dst_port, + &exp_pdu_data_orig_frame_num, + &exp_pdu_data_table_value, + &exp_pdu_data_dissector_data, + NULL + }; + + exp_pdu_data_t *exp_pdu_data; + + exp_pdu_data_table_value.data = GUINT_TO_POINTER(port); + exp_pdu_data_dissector_data.data = tcpinfo; + + exp_pdu_data = export_pdu_create_tags(pinfo, "tcp.port", EXP_PDU_TAG_DISSECTOR_TABLE_NAME, tcp_exp_pdu_items); + exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); + exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); + exp_pdu_data->pdu_tvb = tvb; + + tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); + } +} + +static void +handle_export_pdu_heuristic(packet_info *pinfo, tvbuff_t *tvb, heur_dtbl_entry_t *hdtbl_entry, struct tcpinfo *tcpinfo) +{ + exp_pdu_data_t *exp_pdu_data = NULL; + + if (have_tap_listener(exported_pdu_tap)) { + if ((!hdtbl_entry->enabled) || + (hdtbl_entry->protocol != NULL && !proto_is_protocol_enabled(hdtbl_entry->protocol))) { + exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_PROTO_NAME); + } else if (hdtbl_entry->protocol != NULL) { + exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL}; + const exp_pdu_data_item_t *tcp_exp_pdu_items[] = { + &exp_pdu_data_src_ip, + &exp_pdu_data_dst_ip, + &exp_pdu_data_port_type, + &exp_pdu_data_src_port, + &exp_pdu_data_dst_port, + &exp_pdu_data_orig_frame_num, + &exp_pdu_data_dissector_data, + NULL + }; + + exp_pdu_data_dissector_data.data = tcpinfo; + + exp_pdu_data = export_pdu_create_tags(pinfo, hdtbl_entry->short_name, EXP_PDU_TAG_HEUR_PROTO_NAME, tcp_exp_pdu_items); + } + + if (exp_pdu_data != NULL) { + exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); + exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); + exp_pdu_data->pdu_tvb = tvb; + + tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); + } + } +} + +static void +handle_export_pdu_conversation(packet_info *pinfo, tvbuff_t *tvb, int src_port, int dst_port, struct tcpinfo *tcpinfo) +{ + if (have_tap_listener(exported_pdu_tap)) { + conversation_t *conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, PT_TCP, src_port, dst_port, 0); + if (conversation != NULL) + { + dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num); + if (handle != NULL) + { + exp_pdu_data_item_t exp_pdu_data_dissector_data = {exp_pdu_tcp_dissector_data_size, exp_pdu_tcp_dissector_data_populate_data, NULL}; + const exp_pdu_data_item_t *tcp_exp_pdu_items[] = { + &exp_pdu_data_src_ip, + &exp_pdu_data_dst_ip, + &exp_pdu_data_port_type, + &exp_pdu_data_src_port, + &exp_pdu_data_dst_port, + &exp_pdu_data_orig_frame_num, + &exp_pdu_data_dissector_data, + NULL + }; + + exp_pdu_data_t *exp_pdu_data; + + exp_pdu_data_dissector_data.data = tcpinfo; + + exp_pdu_data = export_pdu_create_tags(pinfo, dissector_handle_get_dissector_name(handle), EXP_PDU_TAG_PROTO_NAME, tcp_exp_pdu_items); + exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); + exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); + exp_pdu_data->pdu_tvb = tvb; + + tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); + } + } + } +} + /* TCP structs and definitions */ /* ************************************************************************** @@ -4963,6 +5110,7 @@ decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, int save_desegment_offset; guint32 save_desegment_len; heur_dtbl_entry_t *hdtbl_entry; + exp_pdu_data_t *exp_pdu_data; /* Don't call subdissectors for keepalives. Even though they do contain * payload "data", it's just garbage. Display any data the keepalive @@ -4994,6 +5142,7 @@ decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_TCP, src_port, dst_port, next_tvb, pinfo, tree, tcpinfo)) { pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); + handle_export_pdu_conversation(pinfo, next_tvb, src_port, dst_port, tcpinfo); return TRUE; } @@ -5001,6 +5150,7 @@ decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, /* do lookup with the heuristic subdissector table */ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) { pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); + handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo); return TRUE; } } @@ -5025,6 +5175,7 @@ decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, if (tcpd && tcpd->server_port != 0 && dissector_try_uint_new(subdissector_table, tcpd->server_port, next_tvb, pinfo, tree, TRUE, tcpinfo)) { pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); + handle_export_pdu_dissection_table(pinfo, next_tvb, tcpd->server_port, tcpinfo); return TRUE; } @@ -5039,11 +5190,13 @@ decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, if (low_port != 0 && dissector_try_uint_new(subdissector_table, low_port, next_tvb, pinfo, tree, TRUE, tcpinfo)) { pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); + handle_export_pdu_dissection_table(pinfo, next_tvb, low_port, tcpinfo); return TRUE; } if (high_port != 0 && dissector_try_uint_new(subdissector_table, high_port, next_tvb, pinfo, tree, TRUE, tcpinfo)) { pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); + handle_export_pdu_dissection_table(pinfo, next_tvb, high_port, tcpinfo); return TRUE; } @@ -5051,6 +5204,7 @@ decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, /* do lookup with the heuristic subdissector table */ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, tcpinfo)) { pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); + handle_export_pdu_heuristic(pinfo, next_tvb, hdtbl_entry, tcpinfo); return TRUE; } } @@ -5069,6 +5223,14 @@ decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, call_dissector(data_handle,next_tvb, pinfo, tree); pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking); + if (have_tap_listener(exported_pdu_tap)) { + exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_PROTO_NAME); + exp_pdu_data->tvb_captured_length = tvb_captured_length(next_tvb); + exp_pdu_data->tvb_reported_length = tvb_reported_length(next_tvb); + exp_pdu_data->pdu_tvb = next_tvb; + + tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); + } return FALSE; } @@ -7145,6 +7307,7 @@ proto_reg_handoff_tcp(void) register_capture_dissector("ip.proto", IP_PROTO_TCP, capture_tcp, proto_tcp); mptcp_tap = register_tap("mptcp"); + exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_4); } /* diff --git a/epan/dissectors/packet-tcp.h b/epan/dissectors/packet-tcp.h index b3a068ac54..3d51fca444 100644 --- a/epan/dissectors/packet-tcp.h +++ b/epan/dissectors/packet-tcp.h @@ -113,14 +113,17 @@ typedef struct tcpheader { /* * Private data passed from the TCP dissector to subdissectors. + * NOTE: This structure is used by Export PDU functionality so + * make sure that handling is also updated if this structure + * changes! */ struct tcpinfo { guint32 seq; /* Sequence number of first byte in the data */ guint32 nxtseq; /* Sequence number of first byte after data */ guint32 lastackseq; /* Sequence number of last ack */ gboolean is_reassembled; /* This is reassembled data. */ - guint16 flags; /* TCP flags */ - guint16 urgent_pointer; /* Urgent pointer value for the current packet. */ + guint16 flags; /* TCP flags */ + guint16 urgent_pointer; /* Urgent pointer value for the current packet. */ }; /* diff --git a/epan/dissectors/packet-udp.c b/epan/dissectors/packet-udp.c index 8d925ea695..937fd215aa 100644 --- a/epan/dissectors/packet-udp.c +++ b/epan/dissectors/packet-udp.c @@ -48,6 +48,7 @@ #include #include #include +#include #include void proto_register_udp(void); @@ -58,6 +59,7 @@ static dissector_handle_t udplite_handle; static int udp_tap = -1; static int udp_follow_tap = -1; +static int exported_pdu_tap = -1; static header_field_info *hfi_udp = NULL; static header_field_info *hfi_udplite = NULL; @@ -490,6 +492,80 @@ guint32 get_udp_stream_count(void) return udp_stream_count; } +static void +handle_export_pdu_dissection_table(packet_info *pinfo, tvbuff_t *tvb, guint32 port) +{ + if (have_tap_listener(exported_pdu_tap)) { + exp_pdu_data_item_t exp_pdu_data_table_value = {exp_pdu_data_dissector_table_num_value_size, exp_pdu_data_dissector_table_num_value_populate_data, NULL}; + + const exp_pdu_data_item_t *udp_exp_pdu_items[] = { + &exp_pdu_data_src_ip, + &exp_pdu_data_dst_ip, + &exp_pdu_data_port_type, + &exp_pdu_data_src_port, + &exp_pdu_data_dst_port, + &exp_pdu_data_orig_frame_num, + &exp_pdu_data_table_value, + NULL + }; + + exp_pdu_data_t *exp_pdu_data; + + exp_pdu_data_table_value.data = GUINT_TO_POINTER(port); + + exp_pdu_data = export_pdu_create_tags(pinfo, "udp.port", EXP_PDU_TAG_DISSECTOR_TABLE_NAME, udp_exp_pdu_items); + exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); + exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); + exp_pdu_data->pdu_tvb = tvb; + + tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); + } +} + +static void +handle_export_pdu_heuristic(packet_info *pinfo, tvbuff_t *tvb, heur_dtbl_entry_t *hdtbl_entry) +{ + exp_pdu_data_t *exp_pdu_data = NULL; + + if (have_tap_listener(exported_pdu_tap)) { + if ((!hdtbl_entry->enabled) || + (hdtbl_entry->protocol != NULL && !proto_is_protocol_enabled(hdtbl_entry->protocol))) { + exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_PROTO_NAME); + } else if (hdtbl_entry->protocol != NULL) { + exp_pdu_data = export_pdu_create_common_tags(pinfo, hdtbl_entry->short_name, EXP_PDU_TAG_HEUR_PROTO_NAME); + } + + if (exp_pdu_data != NULL) { + exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); + exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); + exp_pdu_data->pdu_tvb = tvb; + + tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); + } + } +} + +static void +handle_export_pdu_conversation(packet_info *pinfo, tvbuff_t *tvb, int uh_dport, int uh_sport) +{ + if (have_tap_listener(exported_pdu_tap)) { + conversation_t *conversation = find_conversation(pinfo->num, &pinfo->dst, &pinfo->src, PT_UDP, uh_dport, uh_sport, 0); + if (conversation != NULL) + { + dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num); + if (handle != NULL) + { + exp_pdu_data_t *exp_pdu_data = export_pdu_create_common_tags(pinfo, dissector_handle_get_dissector_name(handle), EXP_PDU_TAG_PROTO_NAME); + exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); + exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); + exp_pdu_data->pdu_tvb = tvb; + + tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); + } + } + } +} + void decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int uh_sport, int uh_dport, int uh_ulen) @@ -501,6 +577,7 @@ decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, /* Save curr_layer_num as it might be changed by subdissector */ guint8 curr_layer_num = pinfo->curr_layer_num; heur_dtbl_entry_t *hdtbl_entry; + exp_pdu_data_t *exp_pdu_data; len = tvb_captured_length_remaining(tvb, offset); reported_len = tvb_reported_length_remaining(tvb, offset); @@ -527,15 +604,16 @@ decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, udp_p_info = (udp_p_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, pinfo->curr_layer_num); if (udp_p_info) { call_heur_dissector_direct(udp_p_info->heur_dtbl_entry, next_tvb, pinfo, tree, NULL); + handle_export_pdu_heuristic(pinfo, next_tvb, udp_p_info->heur_dtbl_entry); return; } } /* determine if this packet is part of a conversation and call dissector */ /* for the conversation if available */ - if (try_conversation_dissector(&pinfo->dst, &pinfo->src, PT_UDP, uh_dport, uh_sport, next_tvb, pinfo, tree, NULL)) { + handle_export_pdu_conversation(pinfo, next_tvb, uh_dport, uh_sport); return; } @@ -547,6 +625,8 @@ decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, udp_p_info->heur_dtbl_entry = hdtbl_entry; p_add_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, curr_layer_num, udp_p_info); } + + handle_export_pdu_heuristic(pinfo, next_tvb, udp_p_info->heur_dtbl_entry); return; } } @@ -575,11 +655,15 @@ decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, high_port = uh_dport; } if ((low_port != 0) && - dissector_try_uint(udp_dissector_table, low_port, next_tvb, pinfo, tree)) + dissector_try_uint(udp_dissector_table, low_port, next_tvb, pinfo, tree)) { + handle_export_pdu_dissection_table(pinfo, next_tvb, low_port); return; + } if ((high_port != 0) && - dissector_try_uint(udp_dissector_table, high_port, next_tvb, pinfo, tree)) + dissector_try_uint(udp_dissector_table, high_port, next_tvb, pinfo, tree)) { + handle_export_pdu_dissection_table(pinfo, next_tvb, high_port); return; + } if (!try_heuristic_first) { /* Do lookup with the heuristic subdissector table */ @@ -589,11 +673,22 @@ decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, udp_p_info->heur_dtbl_entry = hdtbl_entry; p_add_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, curr_layer_num, udp_p_info); } + + handle_export_pdu_heuristic(pinfo, next_tvb, udp_p_info->heur_dtbl_entry); return; } } call_data_dissector(next_tvb, pinfo, tree); + + if (have_tap_listener(exported_pdu_tap)) { + exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_PROTO_NAME); + exp_pdu_data->tvb_captured_length = tvb_captured_length(next_tvb); + exp_pdu_data->tvb_reported_length = tvb_reported_length(next_tvb); + exp_pdu_data->pdu_tvb = next_tvb; + + tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); + } } int @@ -1180,6 +1275,7 @@ proto_reg_handoff_udp(void) udp_tap = register_tap("udp"); udp_follow_tap = register_tap("udp_follow"); + exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_4); } /* diff --git a/epan/exported_pdu.c b/epan/exported_pdu.c index c17a55a0f2..523770b229 100644 --- a/epan/exported_pdu.c +++ b/epan/exported_pdu.c @@ -162,6 +162,28 @@ static int exp_pdu_data_orig_frame_num_populate_data(packet_info *pinfo, void* d return exp_pdu_data_orig_frame_num_size(pinfo, data); } +WS_DLL_PUBLIC int exp_pdu_data_dissector_table_num_value_size(packet_info *pinfo _U_, void* data _U_) +{ + return EXP_PDU_TAG_DISSECTOR_TABLE_NUM_VAL_LEN + 4; +} + +WS_DLL_PUBLIC int exp_pdu_data_dissector_table_num_value_populate_data(packet_info *pinfo _U_, void* data, guint8 *tlv_buffer, guint32 buffer_size _U_) +{ + guint32 value = GPOINTER_TO_UINT(data); + + tlv_buffer[0] = 0; + tlv_buffer[1] = EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL; + tlv_buffer[2] = 0; + tlv_buffer[3] = EXP_PDU_TAG_DISSECTOR_TABLE_NUM_VAL_LEN; /* tag length */ + tlv_buffer[4] = (value & 0xff000000) >> 24; + tlv_buffer[5] = (value & 0x00ff0000) >> 16; + tlv_buffer[6] = (value & 0x0000ff00) >> 8; + tlv_buffer[7] = (value & 0x000000ff); + + return exp_pdu_data_dissector_table_num_value_size(pinfo, data); +} + + exp_pdu_data_item_t exp_pdu_data_src_ip = {exp_pdu_data_src_ip_size, exp_pdu_data_src_ip_populate_data, NULL}; exp_pdu_data_item_t exp_pdu_data_dst_ip = {exp_pdu_data_dst_ip_size, exp_pdu_data_dst_ip_populate_data, NULL}; exp_pdu_data_item_t exp_pdu_data_port_type = {exp_pdu_data_port_type_size, exp_pdu_data_port_type_populate_data, NULL}; @@ -199,7 +221,7 @@ export_pdu_create_tags(packet_info *pinfo, const char* proto_name, guint16 tag_t guint8* buffer_data; DISSECTOR_ASSERT(proto_name != NULL); - DISSECTOR_ASSERT((tag_type == EXP_PDU_TAG_PROTO_NAME) || (tag_type == EXP_PDU_TAG_HEUR_PROTO_NAME)); + DISSECTOR_ASSERT((tag_type == EXP_PDU_TAG_PROTO_NAME) || (tag_type == EXP_PDU_TAG_HEUR_PROTO_NAME) || (tag_type == EXP_PDU_TAG_DISSECTOR_TABLE_NAME)); exp_pdu_data = (exp_pdu_data_t *)g_malloc(sizeof(exp_pdu_data_t)); diff --git a/epan/exported_pdu.h b/epan/exported_pdu.h index 26f22932d6..0512ba1684 100644 --- a/epan/exported_pdu.h +++ b/epan/exported_pdu.h @@ -41,6 +41,7 @@ extern "C" { * if all taps are run. */ #define EXPORT_PDU_TAP_NAME_LAYER_3 "OSI layer 3" +#define EXPORT_PDU_TAP_NAME_LAYER_4 "OSI layer 4" #define EXPORT_PDU_TAP_NAME_LAYER_7 "OSI layer 7" /* To add dynamically an export name, call the following function @@ -127,6 +128,17 @@ WS_DLL_PUBLIC GSList *get_export_pdu_tap_list(void); * COL_PROTOCOL might not be filled in. */ +/**< value part is structure passed into TCP subdissectors. Format is: + guint16 version Export PDU version of structure (for backwards/forwards compatibility) + guint32 seq Sequence number of first byte in the data + guint32 nxtseq Sequence number of first byte after data + guint32 lastackseq Sequence number of last ack + guint8 is_reassembled This is reassembled data. + guint16 flags TCP flags + guint16 urgent_pointer Urgent pointer value for the current packet. +*/ +#define EXP_PDU_TAG_TCP_INFO_DATA 34 + typedef struct _exp_pdu_data_t { guint tlv_buffer_len; guint8 *tlv_buffer; @@ -148,6 +160,8 @@ typedef struct _exp_pdu_data_t { #define EXP_PDU_TAG_DVBCI_EVT_LEN 1 +#define EXP_PDU_TAG_DISSECTOR_TABLE_NUM_VAL_LEN 4 + /** Compute the size (in bytes) of a pdu item * @param pinfo Packet info that may contain data for the pdu item @@ -197,12 +211,15 @@ WS_DLL_PUBLIC exp_pdu_data_t *export_pdu_create_tags(packet_info *pinfo, const c 6. Original frame number @param pinfo Packet info that may contain data for the PDU items - @param tag_type Tag type for protocol's PDU. Must be EXP_PDU_TAG_PROTO_NAME or EXP_PDU_TAG_HEUR_PROTO_NAME. + @param tag_type Tag type for protocol's PDU. Must be EXP_PDU_TAG_PROTO_NAME, EXP_PDU_TAG_HEUR_PROTO_NAME or EXP_PDU_TAG_DISSECTOR_TABLE_NAME @param proto_name Name of protocol that is exporting PDU @return filled exp_pdu_data_t struct */ WS_DLL_PUBLIC exp_pdu_data_t *export_pdu_create_common_tags(packet_info *pinfo, const char *proto_name, guint16 tag_type); +WS_DLL_PUBLIC int exp_pdu_data_dissector_table_num_value_size(packet_info *pinfo, void* data); +WS_DLL_PUBLIC int exp_pdu_data_dissector_table_num_value_populate_data(packet_info *pinfo, void* data, guint8 *tlv_buffer, guint32 buffer_size); + WS_DLL_PUBLIC exp_pdu_data_item_t exp_pdu_data_src_ip; WS_DLL_PUBLIC exp_pdu_data_item_t exp_pdu_data_dst_ip; WS_DLL_PUBLIC exp_pdu_data_item_t exp_pdu_data_port_type;