static void dissect_dsmcc_ddb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *top_tree, guint offset) { tvbuff_t *sub_tvb; proto_item *pi; guint8 reserved; proto_tree_add_item(tree, hf_dsmcc_ddb_module_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_dsmcc_ddb_version, tvb, offset, 1, ENC_BIG_ENDIAN); offset +=1; reserved = tvb_get_guint8(tvb, offset); pi = proto_tree_add_item(tree, hf_dsmcc_ddb_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); if (0xff != reserved) { PROTO_ITEM_SET_GENERATED(pi); expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Invalid value - should be 0xff"); } offset +=1; proto_tree_add_item(tree, hf_dsmcc_ddb_block_number, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; sub_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, sub_tvb, pinfo, top_tree); }
guint packet_mpeg_sect_crc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint start, guint end) { guint32 crc, calculated_crc; const char *label; crc = tvb_get_ntohl(tvb, end); calculated_crc = crc; label = "Unverified"; if (mpeg_sect_check_crc) { label = "Verified"; calculated_crc = crc32_mpeg2_tvb_offset(tvb, start, end); } if (calculated_crc == crc) { proto_tree_add_uint_format( tree, hf_mpeg_sect_crc, tvb, end, 4, crc, "CRC: 0x%08x [%s]", crc, label); } else { proto_item *msg_error = NULL; msg_error = proto_tree_add_uint_format( tree, hf_mpeg_sect_crc, tvb, end, 4, crc, "CRC: 0x%08x [Failed Verification (Calculated: 0x%08x)]", crc, calculated_crc ); PROTO_ITEM_SET_GENERATED(msg_error); expert_add_info_format( pinfo, msg_error, PI_MALFORMED, PI_ERROR, "Invalid CRC" ); } return 4; }
static void rtpproxy_add_notify_addr(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint end) { gint offset = 0; gint tmp = 0; gboolean ipv6 = FALSE; proto_item *ti; /* Check for at least one colon */ offset = tvb_find_guint8(tvb, begin, end, ':'); if(offset != -1) { /* Find if it's the latest colon (not in case of a IPv6) */ while((tmp = tvb_find_guint8(tvb, offset+1, end, ':')) != -1) { ipv6 = TRUE; offset = tmp; } /* We have ip:port */ if(ipv6) proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv6, tvb, begin, offset - begin, ENC_ASCII | ENC_NA); else proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, offset - begin, ENC_ASCII | ENC_NA); proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, offset+1, end - (offset+1), (guint16) g_ascii_strtoull((gchar*)tvb_get_string(wmem_packet_scope(), tvb, offset+1, end - (offset+1)), NULL, 10)); } else { /* Only port is supplied */ ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_notify_ipv4, tvb, begin, 0, ENC_ASCII | ENC_NA); proto_item_append_text(ti, "<skipped>"); PROTO_ITEM_SET_GENERATED(ti); proto_tree_add_uint(rtpproxy_tree, hf_rtpproxy_notify_port, tvb, begin, end - begin, (guint16) g_ascii_strtoull((gchar*)tvb_get_string(wmem_packet_scope(), tvb, begin, end - begin), NULL, 10)); } }
/** General parsing function for arrays of enums. * All arrays have one 4 byte signed integer length information, * followed by n data elements. */ void parseArrayEnum(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, fctEnumParser pParserFunction) { static const char szFieldName[] = "Array of Enum Type"; proto_item *ti = proto_tree_add_text(tree, tvb, *pOffset, -1, "%s", szFieldName); proto_tree *subtree = proto_item_add_subtree(ti, ett_opcua_array); int i; gint32 iLen; /* read array length */ iLen = tvb_get_letohl(tvb, *pOffset); proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); if (iLen > MAX_ARRAY_LEN) { proto_item *pi; pi = proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen); PROTO_ITEM_SET_GENERATED(pi); return; } *pOffset += 4; for (i=0; i<iLen; i++) { (*pParserFunction)(subtree, tvb, pOffset); } proto_item_set_end(ti, tvb, *pOffset); }
/** General parsing function for arrays of complex types. * All arrays have one 4 byte signed integer length information, * followed by n data elements. */ void parseArrayComplex(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, const char *szFieldName, fctComplexTypeParser pParserFunction) { proto_item *ti = proto_tree_add_text(tree, tvb, *pOffset, -1, "Array of %s", szFieldName); proto_tree *subtree = proto_item_add_subtree(ti, ett_opcua_array); int i; gint32 iLen; /* read array length */ iLen = tvb_get_letohl(tvb, *pOffset); proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); if (iLen > MAX_ARRAY_LEN) { proto_item *pi; pi = proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen); PROTO_ITEM_SET_GENERATED(pi); return; } *pOffset += 4; for (i=0; i<iLen; i++) { char szNum[20]; g_snprintf(szNum, 20, "[%i]", i); (*pParserFunction)(subtree, tvb, pOffset, szNum); } proto_item_set_end(ti, tvb, *pOffset); }
/* Has storm request rate been exceeded with this request? */ static void check_for_storm_count(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean report_storm = FALSE; if (p_get_proto_data(pinfo->fd, proto_arp) != 0) { /* Read any previous stored packet setting */ report_storm = (p_get_proto_data(pinfo->fd, proto_arp) == (void*)STORM); } else { /* Seeing packet for first time - check against preference settings */ gint seconds_delta = (gint) (pinfo->fd->abs_ts.secs - time_at_start_of_count.secs); gint nseconds_delta = pinfo->fd->abs_ts.nsecs - time_at_start_of_count.nsecs; gint gap = (seconds_delta*1000) + (nseconds_delta / 1000000); /* Reset if gap exceeds period or -ve gap (indicates we're rescanning from start) */ if ((gap > (gint)global_arp_detect_request_storm_period) || (gap < 0)) { /* Time period elapsed without threshold being exceeded */ arp_request_count = 1; time_at_start_of_count = pinfo->fd->abs_ts; p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM); return; } else if (arp_request_count > global_arp_detect_request_storm_packets) { /* Storm detected, record and reset start time. */ report_storm = TRUE; p_add_proto_data(pinfo->fd, proto_arp, (void*)STORM); time_at_start_of_count = pinfo->fd->abs_ts; } else { /* Threshold not exceeded yet - no storm */ p_add_proto_data(pinfo->fd, proto_arp, (void*)NO_STORM); } } if (report_storm) { /* Report storm and reset counter */ proto_item *ti = proto_tree_add_none_format(tree, hf_arp_packet_storm, tvb, 0, 0, "Packet storm detected (%u packets in < %u ms)", global_arp_detect_request_storm_packets, global_arp_detect_request_storm_period); PROTO_ITEM_SET_GENERATED(ti); expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_NOTE, "ARP packet storm detected (%u packets in < %u ms)", global_arp_detect_request_storm_packets, global_arp_detect_request_storm_period); arp_request_count = 0; } }
/* Code to dissect a message block */ guint dissect_moldudp_msgblk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint32 sequence) { proto_item *ti; proto_tree *blk_tree; guint16 msglen, real_msglen, whole_len; guint remaining; if (tvb_reported_length(tvb) - offset < MOLDUDP_MSGLEN_LEN) return 0; msglen = tvb_get_letohs(tvb, offset); remaining = tvb_reported_length(tvb) - offset - MOLDUDP_MSGLEN_LEN; if (msglen == 0) col_set_str(pinfo->cinfo, COL_INFO, "MoldUDP Messages (End Of Session)"); if (tvb_reported_length(tvb) < (offset + MOLDUDP_MSGLEN_LEN)) real_msglen = 0; else if (msglen <= remaining) real_msglen = msglen; else real_msglen = remaining; /* msglen and real_msglen only count the data section, and don't * include the two bytes for the length field itself. */ whole_len = real_msglen + MOLDUDP_MSGLEN_LEN; ti = proto_tree_add_item(tree, hf_moldudp_msgblk, tvb, offset, whole_len, ENC_NA); blk_tree = proto_item_add_subtree(ti, ett_moldudp_msgblk); ti = proto_tree_add_uint(blk_tree, hf_moldudp_msgseq, tvb, offset, 0, sequence); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_item(blk_tree, hf_moldudp_msglen, tvb, offset, MOLDUDP_MSGLEN_LEN, ENC_LITTLE_ENDIAN); if (msglen != real_msglen) expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Invalid Message Length (claimed %u, found %u)", msglen, real_msglen); offset += MOLDUDP_MSGLEN_LEN; proto_tree_add_item(blk_tree, hf_moldudp_msgdata, tvb, offset, real_msglen, ENC_NA); return whole_len; }
static rtpproxy_info_t * rtpproxy_add_tid(gboolean is_request, tvbuff_t *tvb, packet_info *pinfo, proto_tree *rtpproxy_tree, rtpproxy_conv_info_t *rtpproxy_conv, gchar* cookie) { rtpproxy_info_t *rtpproxy_info; proto_item *pi; if (!PINFO_FD_VISITED(pinfo)) { if (is_request) { rtpproxy_info = wmem_new(wmem_file_scope(), rtpproxy_info_t); rtpproxy_info->req_frame = PINFO_FD_NUM(pinfo); rtpproxy_info->resp_frame = 0; rtpproxy_info->req_time = pinfo->fd->abs_ts; rtpproxy_info->callid = NULL; wmem_tree_insert_string(rtpproxy_conv->trans, cookie, rtpproxy_info, 0); } else { rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0); if (rtpproxy_info) { rtpproxy_info->resp_frame = PINFO_FD_NUM(pinfo); } } } else { rtpproxy_info = (rtpproxy_info_t *)wmem_tree_lookup_string(rtpproxy_conv->trans, cookie, 0); if (rtpproxy_info && (is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame)) { nstime_t ns; pi = proto_tree_add_uint(rtpproxy_tree, is_request ? hf_rtpproxy_response_in : hf_rtpproxy_request_in, tvb, 0, 0, is_request ? rtpproxy_info->resp_frame : rtpproxy_info->req_frame); PROTO_ITEM_SET_GENERATED(pi); /* If reply then calculate response time */ if (!is_request) { nstime_delta(&ns, &pinfo->fd->abs_ts, &rtpproxy_info->req_time); pi = proto_tree_add_time(rtpproxy_tree, hf_rtpproxy_response_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(pi); if (nstime_cmp(&rtpproxy_timeout_ns, &ns) < 0) expert_add_info_format(pinfo, rtpproxy_tree, &ei_rtpproxy_timeout, "Response timeout %.3f seconds", nstime_to_sec(&ns)); } } } /* Could be NULL so we should check it before dereferencing */ return rtpproxy_info; }
static int dissect_device_list_response(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) { proto_item *ti_intf; proto_item *ti_dev; proto_tree *intf_tree = NULL; proto_tree *dev_tree = NULL; guint32 num_of_devs; guint32 i; guint8 num_of_intf; guint8 j; col_set_str(pinfo->cinfo, COL_INFO, "Device List Response"); proto_tree_add_item_ret_uint(tree, hf_usbip_number_devices, tvb, offset, 4, ENC_BIG_ENDIAN, &num_of_devs); offset += 4; for (i = 0; i < num_of_devs; i++) { num_of_intf = tvb_get_guint8(tvb, offset + 0x137); ti_dev = proto_tree_add_uint(tree, hf_usbip_device, tvb, offset, 0x138 + 4 * num_of_intf, i + 1); PROTO_ITEM_SET_GENERATED(ti_dev); dev_tree = proto_item_add_subtree(ti_dev, ett_usbip_dev); offset = dissect_device(dev_tree, tvb, offset); for (j = 0; j < num_of_intf; j++) { ti_intf = proto_tree_add_uint(dev_tree, hf_usbip_interface, tvb, offset, 3, j + 1); intf_tree = proto_item_add_subtree(ti_intf, ett_usbip_intf); proto_tree_add_item(intf_tree, hf_usbip_bInterfaceClass, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(intf_tree, hf_usbip_bInterfaceSubClass, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(intf_tree, hf_usbip_bInterfaceProtocol, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(intf_tree, hf_usbip_padding, tvb, offset, 1, ENC_NA); offset += 1; } } return offset; }
void expert_add_undecoded_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int length, const int severity) { proto_item *expert_item; expert_item = proto_tree_add_text(tree, tvb, offset, length, "Not dissected yet"); expert_add_info_format(pinfo, expert_item, PI_UNDECODED, severity, "Not dissected yet(report to wireshark.org)"); \ PROTO_ITEM_SET_GENERATED(expert_item); \ }
static gint dissect_hci_h4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { guint8 type; tvbuff_t *next_tvb; proto_item *main_item; proto_tree *main_tree; proto_item *sub_item; bluetooth_data_t *bluetooth_data; bluetooth_data = (bluetooth_data_t *) data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI H4"); switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_add_fstr(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_add_fstr(pinfo->cinfo, COL_INFO, "Rcvd "); break; case P2P_DIR_UNKNOWN: break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ", pinfo->p2p_dir); break; } type = tvb_get_guint8(tvb, 0); main_item = proto_tree_add_item(tree, proto_hci_h4, tvb, 0, 1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_hci_h4); sub_item = proto_tree_add_uint(main_tree, hf_hci_h4_direction, tvb, 0, 0, pinfo->p2p_dir); PROTO_ITEM_SET_GENERATED(sub_item); proto_tree_add_item(main_tree, hf_hci_h4_type, tvb, 0, 1, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(type, hci_h4_type_vals, "Unknown HCI packet type 0x%02x")); next_tvb = tvb_new_subset_remaining(tvb, 1); if (!dissector_try_uint_new(hci_h4_table, type, next_tvb, pinfo, tree, TRUE, bluetooth_data)) { call_dissector(data_handle, next_tvb, pinfo, tree); } return 1; }
/* Code to dissect a message block */ guint dissect_moldudp64_msgblk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint64 sequence) { proto_item *ti; proto_tree *blk_tree; guint16 msglen, real_msglen, whole_len; guint remaining; if (tvb_length_remaining(tvb, offset) < MOLDUDP64_MSGLEN_LEN) return 0; msglen = tvb_get_ntohs(tvb, offset); remaining = tvb_reported_length(tvb) - offset - MOLDUDP64_MSGLEN_LEN; if (remaining < (offset + MOLDUDP64_MSGLEN_LEN)) real_msglen = 0; else if (msglen <= remaining) real_msglen = msglen; else real_msglen = remaining; /* msglen and real_msglen only count the data section, and don't * include the two bytes for the length field itself. */ whole_len = real_msglen + MOLDUDP64_MSGLEN_LEN; ti = proto_tree_add_item(tree, hf_moldudp64_msgblk, tvb, offset, whole_len, ENC_NA); blk_tree = proto_item_add_subtree(ti, ett_moldudp64_msgblk); ti = proto_tree_add_uint64(blk_tree, hf_moldudp64_msgseq, tvb, offset, 0, sequence); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_item(blk_tree, hf_moldudp64_msglen, tvb, offset, MOLDUDP64_MSGLEN_LEN, ENC_BIG_ENDIAN); if (msglen != real_msglen) expert_add_info_format_text(pinfo, ti, &ei_moldudp64_msglen_invalid, "Invalid Message Length (claimed %u, found %u)", msglen, real_msglen); offset += MOLDUDP64_MSGLEN_LEN; proto_tree_add_item(blk_tree, hf_moldudp64_msgdata, tvb, offset, real_msglen, ENC_NA); return whole_len; }
static gint rtpproxy_add_tag(proto_tree *rtpproxy_tree, tvbuff_t *tvb, guint begin, guint realsize) { proto_item *ti = NULL; proto_tree *another_tree = NULL; gint new_offset; guint end; new_offset = tvb_find_guint8(tvb, begin, -1, ' '); if(new_offset < 0) end = realsize; /* No more parameters */ else end = new_offset; /* SER/OpenSER/OpenSIPS/Kamailio adds Media-ID right after the Tag * separated by a semicolon */ new_offset = tvb_find_guint8(tvb, begin, end, ';'); if(new_offset == -1) { ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, end - begin, ENC_ASCII | ENC_NA); another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag); ti = proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, 0, ENC_ASCII | ENC_NA); proto_item_append_text(ti, "<skipped>"); PROTO_ITEM_SET_GENERATED(ti); } else { ti = proto_tree_add_item(rtpproxy_tree, hf_rtpproxy_tag, tvb, begin, new_offset - begin, ENC_ASCII | ENC_NA); if ((guint)new_offset == begin) { proto_item_append_text(ti, "<skipped>"); /* A very first Offer/Update command */ PROTO_ITEM_SET_GENERATED(ti); } another_tree = proto_item_add_subtree(ti, ett_rtpproxy_tag); proto_tree_add_item(another_tree, hf_rtpproxy_mediaid, tvb, new_offset+1, end - (new_offset+1), ENC_ASCII | ENC_NA); } return (end == realsize ? -1 : (gint)end); }
static void dissect_hci_h4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 type; tvbuff_t *next_tvb; proto_item *ti=NULL; proto_tree *hci_h4_tree=NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI H4"); switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_add_fstr(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_add_fstr(pinfo->cinfo, COL_INFO, "Rcvd "); break; case P2P_DIR_UNKNOWN: break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ", pinfo->p2p_dir); break; } type = tvb_get_guint8(tvb, 0); if(tree){ ti = proto_tree_add_item(tree, proto_hci_h4, tvb, 0, 1, ENC_NA); hci_h4_tree = proto_item_add_subtree(ti, ett_hci_h4); } ti=proto_tree_add_uint(hci_h4_tree, hf_hci_h4_direction, tvb, 0, 0, pinfo->p2p_dir); PROTO_ITEM_SET_GENERATED(ti); proto_tree_add_item(hci_h4_tree, hf_hci_h4_type, tvb, 0, 1, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(type, hci_h4_type_vals, "Unknown HCI packet type 0x%02x")); next_tvb = tvb_new_subset_remaining(tvb, 1); if(!dissector_try_uint(hci_h4_table, type, next_tvb, pinfo, tree)) { call_dissector(data_handle, next_tvb, pinfo, tree); } }
static int dissect_kt_replication(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset) { gint new_offset; guint32 next32, size; guint64 ts; nstime_t ns_ts; proto_item *pi; new_offset = offset; proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN); new_offset++; if (tvb_reported_length_remaining(tvb, new_offset) > 0) { next32 = tvb_get_ntohl(tvb, new_offset); if (next32 <= 1) { /* This means request. the 32 bits are flags */ proto_tree_add_item(tree, hf_kt_flags, tvb, new_offset, 4, ENC_BIG_ENDIAN); new_offset += 4; proto_tree_add_item(tree, hf_kt_ts, tvb, new_offset, 8, ENC_BIG_ENDIAN); new_offset += 8; proto_tree_add_item(tree, hf_kt_sid, tvb, new_offset, 2, ENC_BIG_ENDIAN); new_offset += 2; } else { /* This is a response. The 32 bits are the first half of the ts */ ts = tvb_get_ntoh64(tvb, new_offset); ns_ts.secs = (time_t)(ts/1000000000); ns_ts.nsecs = (int)(ts%1000000000); proto_tree_add_time(tree, hf_kt_ts, tvb, new_offset, 8, &ns_ts); new_offset += 8; size = tvb_get_ntohl(tvb, new_offset); proto_tree_add_uint(tree, hf_kt_size, tvb, new_offset, 4, size); new_offset += 4; proto_tree_add_item(tree, hf_kt_log, tvb, new_offset, size, ENC_NA); new_offset += size; } } else { /* This is an empty ack to the message with magic 0xB0. */ pi = proto_tree_add_uint(tree, hf_kt_type, tvb, offset, 1, KT_OPER_RESPONSE); PROTO_ITEM_SET_GENERATED(pi); col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[response]"); } return new_offset; }
void dvb_add_chartbl(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset, gint length, dvb_encoding_e encoding) { if (length==0) { proto_item *pi; pi = proto_tree_add_bytes_format(tree, hf, tvb, 0, 0, NULL, "Default character table (Latin)"); PROTO_ITEM_SET_GENERATED(pi); } else { proto_tree_add_bytes_format_value(tree, hf, tvb, offset, length, NULL, "%s (%s)", val_to_str_const(encoding, dvb_string_encoding_vals, "Unknown"), tvb_bytes_to_str_punct(wmem_packet_scope(), tvb, offset, length, ' ')); } }
static int dissect_corosync_totemnet_security_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean check_crypt_type, const gchar* key) { proto_item *item; proto_tree *tree; col_set_str(pinfo->cinfo, COL_PROTOCOL, "COROSYNC/TOTEMNET"); col_clear(pinfo->cinfo, COL_INFO); if (parent_tree) { item = proto_tree_add_item(parent_tree, proto_corosync_totemnet, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_corosync_totemnet_security_header); proto_tree_add_item(tree, hf_corosync_totemnet_security_header_hash_digest, tvb, 0, SHA1_DIGEST_LEN, ENC_NA); proto_tree_add_item(tree, hf_corosync_totemnet_security_header_salt, tvb, SHA1_DIGEST_LEN, SALT_SIZE, ENC_NA); if (check_crypt_type) { int io_len = tvb_reported_length(tvb); proto_item * key_item; proto_tree_add_item(tree, hf_corosync_totemnet_security_crypto_type, tvb, io_len - 1, 1, ENC_BIG_ENDIAN); key_item = proto_tree_add_string(tree, hf_corosync_totemnet_security_crypto_key, tvb, 0, 0, key); PROTO_ITEM_SET_GENERATED(key_item); } } return SHA1_DIGEST_LEN + SALT_SIZE; }
static proto_tree* expert_create_tree(proto_item *pi, int group, int severity, const char *msg) { proto_tree *tree; proto_item *ti; tree = proto_item_add_subtree(pi, ett_expert); ti = proto_tree_add_protocol_format(tree, proto_expert, NULL, 0, 0, "Expert Info (%s/%s): %s", val_to_str(severity, expert_severity_vals, "Unknown (%u)"), val_to_str(group, expert_group_vals, "Unknown (%u)"), msg); PROTO_ITEM_SET_GENERATED(ti); if (group == PI_MALFORMED) { /* Add hidden malformed protocol filter */ proto_item *malformed_ti = proto_tree_add_item(tree, proto_malformed, NULL, 0, 0, ENC_NA); PROTO_ITEM_SET_HIDDEN(malformed_ti); } return proto_item_add_subtree(ti, ett_subexpert); }
/* Dissection routines */ static int dissect_kt_replication_wait(tvbuff_t *tvb, proto_tree *tree) { int offset; guint64 ts; nstime_t ns_ts; proto_item *pi; pi = proto_tree_add_uint(tree, hf_kt_type, tvb, 0, 1, KT_OPER_REQUEST); PROTO_ITEM_SET_GENERATED(pi); offset = 1; ts = tvb_get_ntoh64(tvb, offset); ns_ts.secs = (time_t)(ts/1000000000); ns_ts.nsecs = (int)(ts%1000000000); proto_tree_add_time(tree, hf_kt_ts, tvb, offset, 8, &ns_ts); offset += 8; return offset; }
static int dissect_ret_unlink(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usbip_conv_info_t *usbip_info, guint32 seqnum) { usbip_transaction_t *victim; col_set_str(pinfo->cinfo, COL_INFO, "URB Unlink Response"); victim = (usbip_transaction_t *) wmem_tree_lookup32(usbip_info->pdus, seqnum); if (victim) { proto_item *ti; victim->ret_frame = pinfo->num; ti = proto_tree_add_uint(tree, hf_usbip_vic_frame, NULL, 0, 0, victim->cmd_frame); PROTO_ITEM_SET_GENERATED(ti); } proto_tree_add_item(tree, hf_usbip_status, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; return offset; }
/* ---------------------------------------------- */ static void dissect_fix_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *fix_tree; int pdu_len; int offset = 0; int field_offset, ctrla_offset; int tag_value; char *value; char *tag_str; fix_parameter *tag; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FIX"); col_clear(pinfo->cinfo, COL_INFO); /* get at least the fix version: 8=FIX.x.x */ if (fix_marker(tvb, 0) != 0) { /* not a fix packet start but it's a fix packet */ col_set_str(pinfo->cinfo, COL_INFO, "[FIX continuation]"); ti = proto_tree_add_item(tree, proto_fix, tvb, 0, -1, ENC_NA); fix_tree = proto_item_add_subtree(ti, ett_fix); proto_tree_add_item(fix_tree, hf_fix_data, tvb, 0, -1, ENC_NA); return; } pdu_len = tvb_reported_length(tvb); ti = proto_tree_add_item(tree, proto_fix, tvb, 0, -1, ENC_NA); fix_tree = proto_item_add_subtree(ti, ett_fix); /* begin string */ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01); if (ctrla_offset == -1) { return; } offset = ctrla_offset + 1; /* msg length */ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01); if (ctrla_offset == -1) { return; } offset = ctrla_offset + 1; /* msg type */ if (!(tag = fix_param(tvb, offset)) || tag->value_len < 1) { return; } if (check_col(pinfo->cinfo, COL_INFO)) { const char *msg_type; value = tvb_get_ephemeral_string(tvb, tag->value_offset, tag->value_len); msg_type = str_to_str(value, messages_val, "FIX Message (%s)"); col_add_str(pinfo->cinfo, COL_INFO, msg_type); } /* In the interest of speed, if "tree" is NULL, don't do any work not * necessary to generate protocol tree items. */ field_offset = 0; while(field_offset < pdu_len && (tag = fix_param(tvb, field_offset)) ) { int i, found; if (tag->tag_len < 1) { field_offset = tag->ctrla_offset + 1; continue; } tag_str = tvb_get_ephemeral_string(tvb, field_offset, tag->tag_len); tag_value = atoi(tag_str); if (tag->value_len < 1) { proto_tree *field_tree; /* XXX - put an error indication here. It's too late to return FALSE; we've already started dissecting, and if a heuristic dissector starts dissecting (either updating the columns or creating a protocol tree) and then gives up, it leaves crud behind that messes up other dissectors that might process the packet. */ ti = proto_tree_add_text(fix_tree, tvb, field_offset, tag->field_len, "%i: <missing value>", tag_value); field_tree = proto_item_add_subtree(ti, ett_badfield); proto_tree_add_uint(field_tree, hf_fix_field_tag, tvb, field_offset, tag->tag_len, tag_value); field_offset = tag->ctrla_offset + 1; continue; } /* fix_fields array is sorted by tag_value */ found = 0; if ((i = tag_search(tag_value)) >= 0) { found = 1; } value = tvb_get_ephemeral_string(tvb, tag->value_offset, tag->value_len); if (found) { if (fix_fields[i].table) { if (tree) { switch (fix_fields[i].type) { case 1: /* strings */ proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s (%s)", value, str_to_str(value, fix_fields[i].table, "unknown %s")); break; case 2: /* char */ proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s (%s)", value, val_to_str(*value, fix_fields[i].table, "unknown %d")); break; default: proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s (%s)", value, val_to_str(atoi(value), fix_fields[i].table, "unknown %d")); break; } } } else { proto_item *item; /* checksum */ switch(tag_value) { case 10: { proto_tree *checksum_tree; guint8 sum = 0; const guint8 *data = tvb_get_ptr(tvb, 0, field_offset); gboolean sum_ok; int j; for (j = 0; j < field_offset; j++, data++) { sum += *data; } sum_ok = (atoi(value) == sum); if (sum_ok) { item = proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s [correct]", value); } else { item = proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s [incorrect should be %d]", value, sum); } checksum_tree = proto_item_add_subtree(item, ett_checksum); item = proto_tree_add_boolean(checksum_tree, hf_fix_checksum_good, tvb, field_offset, tag->field_len, sum_ok); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_fix_checksum_bad, tvb, field_offset, tag->field_len, !sum_ok); PROTO_ITEM_SET_GENERATED(item); if (!sum_ok) expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); } break; default: proto_tree_add_string(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value); break; } } } else if (tree) { proto_tree *field_tree; /* XXX - it could be -1 if the tag isn't a number */ ti = proto_tree_add_text(fix_tree, tvb, field_offset, tag->field_len, "%i: %s", tag_value, value); field_tree = proto_item_add_subtree(ti, ett_unknow); proto_tree_add_uint(field_tree, hf_fix_field_tag, tvb, field_offset, tag->tag_len, tag_value); proto_tree_add_item(field_tree, hf_fix_field_value, tvb, tag->value_offset, tag->value_len, ENC_ASCII|ENC_NA); } field_offset = tag->ctrla_offset + 1; tag_str = NULL; } return; }
static ros_call_response_t * ros_match_call_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint invokeId, gboolean isInvoke) { ros_call_response_t rcr, *rcrp=NULL; ros_conv_info_t *ros_info = ros_info_items; /* first see if we have already matched this */ rcr.invokeId=invokeId; rcr.is_request = isInvoke; if(isInvoke) { rcr.req_frame=pinfo->fd->num; rcr.rep_frame=0; } else { rcr.req_frame=0; rcr.rep_frame=pinfo->fd->num; } rcrp=(ros_call_response_t *)g_hash_table_lookup(ros_info->matched, &rcr); if(rcrp) { /* we have found a match */ rcrp->is_request=rcr.is_request; } else { /* we haven't found a match - try and match it up */ if(isInvoke) { /* this a a request - add it to the unmatched list */ /* check that we dont already have one of those in the unmatched list and if so remove it */ rcr.invokeId=invokeId; rcrp=(ros_call_response_t *)g_hash_table_lookup(ros_info->unmatched, &rcr); if(rcrp){ g_hash_table_remove(ros_info->unmatched, rcrp); } /* if we cant reuse the old one, grab a new chunk */ if(!rcrp){ rcrp=wmem_new(wmem_file_scope(), ros_call_response_t); } rcrp->invokeId=invokeId; rcrp->req_frame=pinfo->fd->num; rcrp->req_time=pinfo->fd->abs_ts; rcrp->rep_frame=0; rcrp->is_request=TRUE; g_hash_table_insert(ros_info->unmatched, rcrp, rcrp); return NULL; } else { /* this is a result - it should be in our unmatched list */ rcr.invokeId=invokeId; rcrp=(ros_call_response_t *)g_hash_table_lookup(ros_info->unmatched, &rcr); if(rcrp){ if(!rcrp->rep_frame){ g_hash_table_remove(ros_info->unmatched, rcrp); rcrp->rep_frame=pinfo->fd->num; rcrp->is_request=FALSE; g_hash_table_insert(ros_info->matched, rcrp, rcrp); } } } } if(rcrp){ /* we have found a match */ proto_item *item = NULL; if(rcrp->is_request){ item=proto_tree_add_uint(tree, hf_ros_response_in, tvb, 0, 0, rcrp->rep_frame); PROTO_ITEM_SET_GENERATED (item); } else { nstime_t ns; item=proto_tree_add_uint(tree, hf_ros_response_to, tvb, 0, 0, rcrp->req_frame); PROTO_ITEM_SET_GENERATED (item); nstime_delta(&ns, &pinfo->fd->abs_ts, &rcrp->req_time); item=proto_tree_add_time(tree, hf_ros_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED (item); } } return rcrp; }
static void dissect_v5dl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *v5dl_tree, *addr_tree; proto_item *v5dl_ti, *addr_ti; int direction; guint v5dl_header_len; guint16 control; #if 0 proto_tree *checksum_tree; proto_item *checksum_ti; guint16 checksum, checksum_calculated; guint checksum_offset; #endif guint16 addr, cr, eah, eal, v5addr; gboolean is_response = 0; #if 0 guint length, reported_length; #endif tvbuff_t *next_tvb; const char *srcname = "?"; const char *dstname = "?"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "V5DL"); col_clear(pinfo->cinfo, COL_INFO); addr = tvb_get_ntohs(tvb, 0); cr = addr & V5DL_CR; eal = (addr & V5DL_EAL) >> V5DL_EAL_SHIFT; eah = (addr & V5DL_EAH) >> V5DL_EAH_SHIFT; v5addr = (eah << 7) + eal; v5dl_header_len = 2; /* addr */ direction = pinfo->p2p_dir; if (pinfo->p2p_dir == P2P_DIR_RECV) { is_response = cr ? FALSE : TRUE; srcname = "Network"; dstname = "User"; } else if (pinfo->p2p_dir == P2P_DIR_SENT) { is_response = cr ? TRUE : FALSE; srcname = "User"; dstname = "Network"; } col_set_str(pinfo->cinfo, COL_RES_DL_SRC, srcname); col_set_str(pinfo->cinfo, COL_RES_DL_DST, dstname); if (tree) { proto_item *direction_ti; v5dl_ti = proto_tree_add_item(tree, proto_v5dl, tvb, 0, -1, ENC_NA); v5dl_tree = proto_item_add_subtree(v5dl_ti, ett_v5dl); /* * Don't show the direction if we don't know it. */ if (direction != P2P_DIR_UNKNOWN) { direction_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_direction, tvb, 0, 0, pinfo->p2p_dir); PROTO_ITEM_SET_GENERATED(direction_ti); } addr_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_ef, tvb, 0, 2, v5addr); addr_tree = proto_item_add_subtree(addr_ti, ett_v5dl_address); proto_tree_add_uint(addr_tree, hf_v5dl_eah, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_cr, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_ea1, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_eal, tvb, 1, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_ea2, tvb, 1, 1, addr); } else { v5dl_ti = NULL; v5dl_tree = NULL; } control = dissect_xdlc_control(tvb, 2, pinfo, v5dl_tree, hf_v5dl_control, ett_v5dl_control, &v5dl_cf_items, &v5dl_cf_items_ext, NULL, NULL, is_response, TRUE, FALSE); v5dl_header_len += XDLC_CONTROL_LEN(control, TRUE); if (tree) proto_item_set_len(v5dl_ti, v5dl_header_len); /* * XXX - the sample capture supplied with bug 7027 does not * appear to include checksums in the packets. */ #if 0 /* * Check the checksum, if available. * The checksum is a CCITT CRC-16 at the end of the packet, so * if we don't have the entire packet in the capture - i.e., if * tvb_captured_length(tvb) != tvb_reported_length(tvb) we can't check it. */ length = tvb_captured_length(tvb); reported_length = tvb_reported_length(tvb); /* * If the reported length isn't big enough for the V5DL header * and 2 bytes of checksum, the packet is malformed, as the * checksum overlaps the header. */ if (reported_length < v5dl_header_len + 2) THROW(ReportedBoundsError); if (length == reported_length) { /* * There's no snapshot length cutting off any of the * packet. */ checksum_offset = reported_length - 2; checksum = tvb_get_ntohs(tvb, checksum_offset); checksum_calculated = crc16_ccitt_tvb(tvb, checksum_offset); checksum_calculated = g_htons(checksum_calculated); /* Note: g_htons() macro may eval arg multiple times */ if (checksum == checksum_calculated) { checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset, 2, 0, "0x%04x [correct]", checksum); checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, TRUE); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, FALSE); } else { checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset, 2, 0, "0x%04x [incorrect, should be 0x%04x]", checksum, checksum_calculated); checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, FALSE); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, TRUE); } /* * Remove the V5DL header *and* the checksum. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_captured_length_remaining(tvb, v5dl_header_len) - 2, tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } else { /* * Some or all of the packet is cut off by a snapshot * length. */ if (length == reported_length - 1) { /* * One byte is cut off, so there's only one * byte of checksum in the captured data. * Remove that byte from the captured length * and both bytes from the reported length. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_captured_length_remaining(tvb, v5dl_header_len) - 1, tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } else { /* * Two or more bytes are cut off, so there are * no bytes of checksum in the captured data. * Just remove the checksum from the reported * length. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_captured_length_remaining(tvb, v5dl_header_len), tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } } #else next_tvb = tvb_new_subset_remaining(tvb, v5dl_header_len); #endif if (XDLC_IS_INFORMATION(control)) { /* call V5.2 dissector */ call_dissector(v52_handle, next_tvb, pinfo, tree); } }
static void dissect_zrtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *zrtp_tree; proto_tree *zrtp_msg_tree; proto_tree *zrtp_msg_data_tree; proto_tree *checksum_tree; proto_item *ti; int linelen; int checksum_offset; unsigned char message_type[9]; unsigned int prime_offset = 0; unsigned int msg_offset = 12; guint32 sent_crc, calc_crc; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZRTP"); col_set_str(pinfo->cinfo, COL_INFO, "Unknown ZRTP Packet"); ti = proto_tree_add_protocol_format(tree, proto_zrtp, tvb, 0, -1, "ZRTP protocol"); zrtp_tree = proto_item_add_subtree(ti, ett_zrtp); proto_tree_add_item(zrtp_tree, hf_zrtp_rtpversion, tvb, prime_offset+0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(zrtp_tree, hf_zrtp_rtppadding, tvb, prime_offset+0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(zrtp_tree, hf_zrtp_rtpextension, tvb, prime_offset+0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(zrtp_tree, hf_zrtp_sequence, tvb, prime_offset+2, 2, ENC_BIG_ENDIAN); proto_tree_add_item(zrtp_tree, hf_zrtp_cookie, tvb, prime_offset+4, 4, ENC_ASCII|ENC_NA); proto_tree_add_item(zrtp_tree, hf_zrtp_source_id, tvb, prime_offset+8, 4, ENC_BIG_ENDIAN); linelen = tvb_reported_length_remaining(tvb, msg_offset); checksum_offset = linelen-4; ti = proto_tree_add_protocol_format(zrtp_tree, proto_zrtp, tvb, msg_offset, linelen-4, "Message"); zrtp_msg_tree = proto_item_add_subtree(ti, ett_zrtp_msg); proto_tree_add_item(zrtp_msg_tree, hf_zrtp_signature, tvb, msg_offset+0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(zrtp_msg_tree, hf_zrtp_msg_length, tvb, msg_offset+2, 2, ENC_BIG_ENDIAN); tvb_memcpy(tvb, (void *)message_type, msg_offset+4, 8); message_type[8] = '\0'; proto_tree_add_item(zrtp_msg_tree, hf_zrtp_msg_type, tvb, msg_offset+4, 8, ENC_ASCII|ENC_NA); linelen = tvb_reported_length_remaining(tvb, msg_offset+12); if (!strncmp(message_type, "Hello ", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_Hello(tvb, pinfo, zrtp_msg_data_tree); } else if (!strncmp(message_type, "HelloACK", 8)) { dissect_HelloACK(pinfo); } else if (!strncmp(message_type, "Commit ", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_Commit(tvb, pinfo, zrtp_msg_data_tree); } else if (!strncmp(message_type, "DHPart1 ", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_DHPart(tvb, pinfo, zrtp_msg_data_tree, 1); } else if (!strncmp(message_type, "DHPart2 ", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_DHPart(tvb, pinfo, zrtp_msg_data_tree, 2); } else if (!strncmp(message_type, "Confirm1", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_Confirm(tvb, pinfo, zrtp_msg_data_tree, 1); } else if (!strncmp(message_type, "Confirm2", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_Confirm(tvb, pinfo, zrtp_msg_data_tree, 2); } else if (!strncmp(message_type, "Conf2ACK", 8)) { dissect_Conf2ACK(pinfo); } else if (!strncmp(message_type, "Error ", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_Error(tvb, pinfo, zrtp_msg_data_tree); } else if (!strncmp(message_type, "ErrorACK", 8)) { dissect_ErrorACK(pinfo); } else if (!strncmp(message_type, "GoClear ", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_GoClear(tvb, pinfo, zrtp_msg_data_tree); } else if (!strncmp(message_type, "ClearACK", 8)) { dissect_ClearACK(pinfo); } else if (!strncmp(message_type, "SASrelay", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_SASrelay(tvb, pinfo, zrtp_msg_data_tree); } else if (!strncmp(message_type, "RelayACK", 8)) { dissect_RelayACK(pinfo); } else if (!strncmp(message_type, "Ping ", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_Ping(tvb, pinfo, zrtp_msg_data_tree); } else if (!strncmp(message_type, "PingACK ", 8)) { ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data"); zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data); dissect_PingACK(tvb, pinfo, zrtp_msg_data_tree); } sent_crc = tvb_get_ntohl(tvb, msg_offset+checksum_offset); calc_crc = ~crc32c_calculate(tvb_get_ptr(tvb, 0, msg_offset+checksum_offset), msg_offset+checksum_offset, CRC32C_PRELOAD); if (sent_crc == calc_crc) { ti = proto_tree_add_uint_format_value(zrtp_tree, hf_zrtp_checksum, tvb, msg_offset+checksum_offset, 4, sent_crc, "0x%04x [correct]", sent_crc); checksum_tree = proto_item_add_subtree(ti, ett_zrtp_checksum); ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_good, tvb, msg_offset+checksum_offset, 4, TRUE); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_bad, tvb, msg_offset+checksum_offset, 4, FALSE); PROTO_ITEM_SET_GENERATED(ti); } else { ti = proto_tree_add_uint_format_value(zrtp_tree, hf_zrtp_checksum, tvb, msg_offset+checksum_offset, 4, sent_crc, "0x%04x [incorrect, should be 0x%04x]", sent_crc, calc_crc); checksum_tree = proto_item_add_subtree(ti, ett_zrtp_checksum); ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_good, tvb, msg_offset+checksum_offset, 4, FALSE); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_boolean(checksum_tree, hf_zrtp_checksum_bad, tvb, msg_offset+checksum_offset, 4, TRUE); PROTO_ITEM_SET_GENERATED(ti); } }
static void dissect_etv_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto, int hf_filter_info, int hf_reserved ) { tvbuff_t *sub_tvb; guint offset = 0; proto_item *ti; proto_item *pi; proto_tree *etv_tree; proto_item *items[PACKET_MPEG_SECT_PI__SIZE]; gboolean ssi; guint reserved; guint8 reserved2; guint16 filter_info; guint sect_len; ti = proto_tree_add_item(tree, proto, tvb, offset, -1, ENC_NA); etv_tree = proto_item_add_subtree(ti, ett_etv); offset += packet_mpeg_sect_header_extra(tvb, offset, etv_tree, §_len, &reserved, &ssi, items); if (FALSE != ssi) { proto_item *msg_error; msg_error = items[PACKET_MPEG_SECT_PI__SSI]; PROTO_ITEM_SET_GENERATED(msg_error); expert_add_info_format(pinfo, msg_error, PI_MALFORMED, PI_ERROR, "Invalid section_syntax_indicator (should be 0)"); } if (4 != reserved) { proto_item *msg_error; msg_error = items[PACKET_MPEG_SECT_PI__RESERVED]; PROTO_ITEM_SET_GENERATED(msg_error); expert_add_info_format(pinfo, msg_error, PI_MALFORMED, PI_ERROR, "Invalid reserved1 bits (should all be 100)"); } col_append_fstr(pinfo->cinfo, COL_INFO, ", Length: %u", sect_len); proto_item_append_text(ti, " Length=%u", sect_len); if (1021 < sect_len) { proto_item *msg_error; msg_error = items[PACKET_MPEG_SECT_PI__LENGTH]; PROTO_ITEM_SET_GENERATED(msg_error); expert_add_info_format(pinfo, msg_error, PI_MALFORMED, PI_ERROR, "Invalid section_length (must not exceed 1021)"); } filter_info = tvb_get_ntohs(tvb, offset); col_append_fstr(pinfo->cinfo, COL_INFO, ", Filter: 0x%x", filter_info); proto_item_append_text(ti, " Filter=0x%x", filter_info); pi = proto_tree_add_item(etv_tree, hf_filter_info, tvb, offset, 2, ENC_BIG_ENDIAN); if ((proto_etv_dii == proto) && (0xFBFB != filter_info)) { PROTO_ITEM_SET_GENERATED(pi); expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Invalid filter_info value (must be 0xFBFB)"); } else if ((proto_etv_ddb == proto) && ((filter_info < 1) || (0xfbef < filter_info))) { PROTO_ITEM_SET_GENERATED(pi); expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Invalid filter_info value (must be [0x0001-0xFBEF] inclusive)"); } offset += 2; reserved2 = tvb_get_guint8(tvb, offset); pi = proto_tree_add_item(etv_tree, hf_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); if (0 != reserved2) { PROTO_ITEM_SET_GENERATED(pi); expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_ERROR, "Invalid reserved2 bits (should all be 0)"); } offset += 1; sub_tvb = tvb_new_subset(tvb, offset, sect_len-7, sect_len-7); call_dissector(dsmcc_handle, sub_tvb, pinfo, tree); sect_len += 3 - 4; /* add header, remove crc */ packet_mpeg_sect_crc(tvb, pinfo, etv_tree, 0, sect_len); }
static void dissect_tftp_message(tftp_conv_info_t *tftp_info, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *tftp_tree; proto_item *ti; gint offset = 0; guint16 opcode; guint16 bytes; guint16 blocknum; guint i1; guint16 error; tvbuff_t *data_tvb = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFTP"); /* Protocol root */ ti = proto_tree_add_item(tree, proto_tftp, tvb, offset, -1, ENC_NA); tftp_tree = proto_item_add_subtree(ti, ett_tftp); /* Opcode */ opcode = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tftp_tree, hf_tftp_opcode, tvb, offset, 2, opcode); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, tftp_opcode_vals, "Unknown (0x%04x)")); offset += 2; /* read and write requests contain file names for other messages, we add the filenames from the conversation */ if (opcode!=TFTP_RRQ && opcode!=TFTP_WRQ) { if (tftp_info->source_file) { ti = proto_tree_add_string(tftp_tree, hf_tftp_source_file, tvb, 0, 0, tftp_info->source_file); PROTO_ITEM_SET_GENERATED(ti); } if (tftp_info->destination_file) { ti = proto_tree_add_string(tftp_tree, hf_tftp_destination_file, tvb, 0, 0, tftp_info->destination_file); PROTO_ITEM_SET_GENERATED(ti); } } switch (opcode) { case TFTP_RRQ: i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_source_file, tvb, offset, i1, ENC_ASCII|ENC_NA); tftp_info->source_file = tvb_get_string_enc(wmem_file_scope(), tvb, offset, i1, ENC_ASCII); /* we either have a source file name (for read requests) or a destination file name (for write requests) when we set one of the names, we clear the other */ tftp_info->destination_file = NULL; col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s", tvb_format_stringzpad(tvb, offset, i1)); offset += i1; i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_transfer_type, tvb, offset, i1, ENC_ASCII|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s", tvb_format_stringzpad(tvb, offset, i1)); offset += i1; tftp_dissect_options(tvb, pinfo, offset, tftp_tree, opcode, tftp_info); break; case TFTP_WRQ: i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_destination_file, tvb, offset, i1, ENC_ASCII|ENC_NA); tftp_info->destination_file = tvb_get_string_enc(wmem_file_scope(), tvb, offset, i1, ENC_ASCII); tftp_info->source_file = NULL; /* see above */ col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s", tvb_format_stringzpad(tvb, offset, i1)); offset += i1; i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_transfer_type, tvb, offset, i1, ENC_ASCII|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s", tvb_format_stringzpad(tvb, offset, i1)); offset += i1; tftp_dissect_options(tvb, pinfo, offset, tftp_tree, opcode, tftp_info); break; case TFTP_INFO: tftp_dissect_options(tvb, pinfo, offset, tftp_tree, opcode, tftp_info); break; case TFTP_DATA: blocknum = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2, blocknum); /* Sequence analysis on blocknums (first pass only) */ if (!pinfo->fd->flags.visited) { if (blocknum > tftp_info->next_block_num) { /* There is a gap. Don't try to recover from this. */ tftp_info->next_block_num = blocknum + 1; tftp_info->blocks_missing = TRUE; /* TODO: add info to a result table for showing expert info in later passes */ } else if (blocknum == tftp_info->next_block_num) { /* OK, inc what we expect next */ tftp_info->next_block_num++; } } offset += 2; /* Show number of bytes in this block, and whether it is the end of the file */ bytes = tvb_reported_length_remaining(tvb, offset); col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i%s", blocknum, (bytes < tftp_info->blocksize)?" (last)":"" ); /* Show data in tree */ if (bytes > 0) { data_tvb = tvb_new_subset(tvb, offset, -1, bytes); call_dissector(data_handle, data_tvb, pinfo, tree); } /* If Export Object tap is listening, need to accumulate blocks info list to send to tap. But if already know there are blocks missing, there is no point in trying. */ if (have_tap_listener(tftp_eo_tap) && !tftp_info->blocks_missing) { file_block_t *block; if (blocknum == 1) { /* Reset data for this conversation, freeing any accumulated blocks! */ cleanup_tftp_blocks(tftp_info); tftp_info->next_tap_block_num = 1; } if (blocknum != tftp_info->next_tap_block_num) { /* Ignore. Could be missing frames, or just clicking previous frame */ return; } if (bytes > 0) { /* Create a block for this block */ block = (file_block_t*)g_malloc(sizeof(file_block_t)); block->length = bytes; block->data = tvb_memdup(NULL, data_tvb, 0, bytes); /* Add to the end of the list (does involve traversing whole list..) */ tftp_info->block_list = g_slist_append(tftp_info->block_list, block); tftp_info->file_length += bytes; /* Look for next blocknum next time */ tftp_info->next_tap_block_num++; } /* Tap export object only when reach end of file */ if (bytes < tftp_info->blocksize) { tftp_eo_t *eo_info; /* If don't have a filename, won't tap file info */ if ((tftp_info->source_file == NULL) && (tftp_info->destination_file == NULL)) { cleanup_tftp_blocks(tftp_info); return; } /* Create the eo_info to pass to the listener */ eo_info = wmem_new(wmem_packet_scope(), tftp_eo_t); /* Set filename */ if (tftp_info->source_file) { eo_info->filename = g_strdup(tftp_info->source_file); } else if (tftp_info->destination_file) { eo_info->filename = g_strdup(tftp_info->destination_file); } /* Send block list, which will be combined and freed at tap. */ eo_info->payload_len = tftp_info->file_length; eo_info->pkt_num = blocknum; eo_info->block_list = tftp_info->block_list; /* Send to tap */ tap_queue_packet(tftp_eo_tap, pinfo, eo_info); /* Have sent, so forget list of blocks, and only pay attention if we get back to the first block again. */ tftp_info->block_list = NULL; tftp_info->next_tap_block_num = 1; } } break; case TFTP_ACK: blocknum = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2, blocknum); col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i", blocknum); break; case TFTP_ERROR: error = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tftp_tree, hf_tftp_error_code, tvb, offset, 2, error); col_append_fstr(pinfo->cinfo, COL_INFO, ", Code: %s", val_to_str(error, tftp_error_code_vals, "Unknown (%u)")); offset += 2; i1 = tvb_strsize(tvb, offset); proto_tree_add_item(tftp_tree, hf_tftp_error_string, tvb, offset, i1, ENC_ASCII|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ", Message: %s", tvb_format_stringzpad(tvb, offset, i1)); expert_add_info(pinfo, NULL, &ei_tftp_blocksize_range); break; case TFTP_OACK: tftp_dissect_options(tvb, pinfo, offset, tftp_tree, opcode, tftp_info); break; default: proto_tree_add_item(tftp_tree, hf_tftp_data, tvb, offset, -1, ENC_NA); break; } }
static void dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 ar_hrd; guint16 ar_pro; guint8 ar_hln; guint8 ar_pln; guint16 ar_op; int tot_len; proto_tree *arp_tree = NULL; proto_item *ti, *item; const gchar *op_str; int sha_offset, spa_offset, tha_offset, tpa_offset; const guint8 *spa_val, *tpa_val; gboolean is_gratuitous; gboolean duplicate_detected = FALSE; guint32 duplicate_ip = 0; /* Call it ARP, for now, so that if we throw an exception before we decide whether it's ARP or RARP or IARP or ATMARP, it shows up in the packet list as ARP. Clear the Info column so that, if we throw an exception, it shows up as a short or malformed ARP frame. */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP"); col_clear(pinfo->cinfo, COL_INFO); /* Hardware Address Type */ ar_hrd = tvb_get_ntohs(tvb, AR_HRD); if (ar_hrd == ARPHRD_ATM2225) { call_dissector(atmarp_handle, tvb, pinfo, tree); return; } /* Protocol Address Type */ ar_pro = tvb_get_ntohs(tvb, AR_PRO); /* Hardware Address Size */ ar_hln = tvb_get_guint8(tvb, AR_HLN); /* Protocol Address Size */ ar_pln = tvb_get_guint8(tvb, AR_PLN); /* Operation */ ar_op = tvb_get_ntohs(tvb, AR_OP); tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2; /* Adjust the length of this tvbuff to include only the ARP datagram. Our caller may use that to determine how much of its packet was padding. */ tvb_set_reported_length(tvb, tot_len); if (check_col(pinfo->cinfo, COL_PROTOCOL)) { switch (ar_op) { case ARPOP_REQUEST: if (global_arp_detect_request_storm) { request_seen(pinfo); } /* FALLTHRU */ case ARPOP_REPLY: default: col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP"); break; case ARPOP_RREQUEST: case ARPOP_RREPLY: col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP"); break; case ARPOP_IREQUEST: case ARPOP_IREPLY: col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP"); break; } } /* Get the offsets of the addresses. */ /* Source Hardware Address */ sha_offset = MIN_ARP_HEADER_SIZE; /* Source Protocol Address */ spa_offset = sha_offset + ar_hln; /* Target Hardware Address */ tha_offset = spa_offset + ar_pln; /* Target Protocol Address */ tpa_offset = tha_offset + ar_hln; if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) && ARP_HW_IS_ETHER(ar_hrd, ar_hln) && ARP_PRO_IS_IPv4(ar_pro, ar_pln)) { /* inform resolv.c module of the new discovered addresses */ guint32 ip; const guint8 *mac; /* Add sender address if sender MAC address is neither a broadcast/ multicast address nor an all-zero address and if sender IP address isn't all zeroes. */ ip = tvb_get_ipv4(tvb, spa_offset); mac = tvb_get_ptr(tvb, sha_offset, 6); if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0) { add_ether_byip(ip, mac); if (global_arp_detect_duplicate_ip_addresses) { duplicate_detected = check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip, &duplicate_ip); } } /* Add target address if target MAC address is neither a broadcast/ multicast address nor an all-zero address and if target IP address isn't all zeroes. */ /* Do not add target address if the packet is a Request. According to the RFC, target addresses in requests have no meaning */ ip = tvb_get_ipv4(tvb, tpa_offset); mac = tvb_get_ptr(tvb, tha_offset, 6); if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0 && ar_op != ARPOP_REQUEST) { add_ether_byip(ip, mac); if (global_arp_detect_duplicate_ip_addresses) { duplicate_detected = check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip, &duplicate_ip); } } } if (!tree && !check_col(pinfo->cinfo, COL_INFO)) { /* We're not building a protocol tree and we're not setting the Info column, so we don't have any more work to do. */ return; } spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln); tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln); /* ARP requests/replies with the same sender and target protocol address are flagged as "gratuitous ARPs", i.e. ARPs sent out as, in effect, an announcement that the machine has MAC address XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY. Requests are to provoke complaints if some other machine has the same IPv4 address, replies are used to announce relocation of network address, like in failover solutions. */ if (((ar_op == ARPOP_REQUEST) || (ar_op == ARPOP_REPLY)) && (memcmp(spa_val, tpa_val, ar_pln) == 0)) is_gratuitous = TRUE; else is_gratuitous = FALSE; if (check_col(pinfo->cinfo, COL_INFO)) { switch (ar_op) { case ARPOP_REQUEST: if (is_gratuitous) col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Request)", arpproaddr_to_str(tpa_val, ar_pln, ar_pro)); else col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", arpproaddr_to_str(tpa_val, ar_pln, ar_pro), arpproaddr_to_str(spa_val, ar_pln, ar_pro)); break; case ARPOP_REPLY: if (is_gratuitous) col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Reply)", arpproaddr_to_str(spa_val, ar_pln, ar_pro)); else col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", arpproaddr_to_str(spa_val, ar_pln, ar_pro), tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd)); break; case ARPOP_RREQUEST: case ARPOP_IREQUEST: col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s", tvb_arphrdaddr_to_str(tvb, tha_offset, ar_hln, ar_hrd), tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd)); break; case ARPOP_RREPLY: col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", tvb_arphrdaddr_to_str(tvb, tha_offset, ar_hln, ar_hrd), arpproaddr_to_str(tpa_val, ar_pln, ar_pro)); break; case ARPOP_IREPLY: col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd), arpproaddr_to_str(spa_val, ar_pln, ar_pro)); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op); break; } } if (tree) { if ((op_str = match_strval(ar_op, op_vals))) { if (is_gratuitous && (ar_op == ARPOP_REQUEST)) op_str = "request/gratuitous ARP"; if (is_gratuitous && (ar_op == ARPOP_REPLY)) op_str = "reply/gratuitous ARP"; ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len, "Address Resolution Protocol (%s)", op_str); } else ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len, "Address Resolution Protocol (opcode 0x%04x)", ar_op); arp_tree = proto_item_add_subtree(ti, ett_arp); proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd); proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro); proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln); proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln); proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op); item = proto_tree_add_boolean(arp_tree, hf_arp_isgratuitous, tvb, 0, 0, is_gratuitous); PROTO_ITEM_SET_GENERATED(item); if (ar_hln != 0) { proto_tree_add_item(arp_tree, ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw, tvb, sha_offset, ar_hln, FALSE); } if (ar_pln != 0) { proto_tree_add_item(arp_tree, ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4 : hf_arp_src_proto, tvb, spa_offset, ar_pln, FALSE); } if (ar_hln != 0) { proto_tree_add_item(arp_tree, ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw, tvb, tha_offset, ar_hln, FALSE); } if (ar_pln != 0) { proto_tree_add_item(arp_tree, ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4 : hf_arp_dst_proto, tvb, tpa_offset, ar_pln, FALSE); } } if (global_arp_detect_request_storm) { check_for_storm_count(tvb, pinfo, arp_tree); } if (duplicate_detected) { /* Also indicate in info column */ if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " (duplicate use of %s detected!)", arpproaddr_to_str((guint8*)&duplicate_ip, 4, ETHERTYPE_IP)); } } }
/* Check to see if this mac & ip pair represent 2 devices trying to share the same IP address - report if found (+ return TRUE and set out param) */ static gboolean check_for_duplicate_addresses(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, const guint8 *mac, guint32 ip, guint32 *duplicate_ip) { struct address_hash_value *value; gboolean return_value = FALSE; /* Look up any existing entries */ value = g_hash_table_lookup(address_hash_table, GUINT_TO_POINTER(ip)); /* If MAC matches table, just update details */ if (value != NULL) { if (pinfo->fd->num > value->frame_num) { if ((memcmp(value->mac, mac, 6) == 0)) { /* Same MAC as before - update existing entry */ value->frame_num = pinfo->fd->num; value->time_of_entry = pinfo->fd->abs_ts.secs; } else { /* Doesn't match earlier MAC - report! */ proto_tree *duplicate_tree; /* Create subtree */ proto_item *ti = proto_tree_add_none_format(tree, hf_arp_duplicate_ip_address, tvb, 0, 0, "Duplicate IP address detected for %s (%s) - also in use by %s (frame %u)", arpproaddr_to_str((guint8*)&ip, 4, ETHERTYPE_IP), ether_to_str(mac), ether_to_str(value->mac), value->frame_num); PROTO_ITEM_SET_GENERATED(ti); duplicate_tree = proto_item_add_subtree(ti, ett_arp_duplicate_address); /* Add item for navigating to earlier frame */ ti = proto_tree_add_uint(duplicate_tree, hf_arp_duplicate_ip_address_earlier_frame, tvb, 0, 0, value->frame_num); PROTO_ITEM_SET_GENERATED(ti); expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN, "Duplicate IP address configured (%s)", arpproaddr_to_str((guint8*)&ip, 4, ETHERTYPE_IP)); /* Time since that frame was seen */ ti = proto_tree_add_uint(duplicate_tree, hf_arp_duplicate_ip_address_seconds_since_earlier_frame, tvb, 0, 0, (guint32)(pinfo->fd->abs_ts.secs - value->time_of_entry)); PROTO_ITEM_SET_GENERATED(ti); *duplicate_ip = ip; return_value = TRUE; } } } else { /* No existing entry. Prepare one */ value = se_alloc(sizeof(struct address_hash_value)); memcpy(value->mac, mac, 6); value->frame_num = pinfo->fd->num; value->time_of_entry = pinfo->fd->abs_ts.secs; /* Add it */ g_hash_table_insert(address_hash_table, GUINT_TO_POINTER(ip), value); } return return_value; }
/* XXX - "packet comment" is passed into dissector as data, but currently doesn't have a use */ static int dissect_file_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data) { proto_item *volatile ti = NULL; guint cap_len = 0, frame_len = 0; proto_tree *volatile fh_tree = NULL; proto_tree *volatile tree; proto_item *item; const gchar *cap_plurality, *frame_plurality; const color_filter_t *color_filter; file_data_t *file_data = (file_data_t*)data; tree=parent_tree; pinfo->current_proto = "File"; /* if FILE is not referenced from any filters we don't need to worry about generating any tree items. */ if(!proto_field_is_referenced(tree, proto_file)) { tree=NULL; } else { /* Put in frame header information. */ cap_len = tvb_captured_length(tvb); frame_len = tvb_reported_length(tvb); cap_plurality = plurality(cap_len, "", "s"); frame_plurality = plurality(frame_len, "", "s"); ti = proto_tree_add_protocol_format(tree, proto_file, tvb, 0, -1, "File record %u: %u byte%s", pinfo->num, frame_len, frame_plurality); proto_item_append_text(ti, ", %u byte%s", cap_len, cap_plurality); fh_tree = proto_item_add_subtree(ti, ett_file); proto_tree_add_int(fh_tree, hf_file_ftap_encap, tvb, 0, 0, pinfo->pkt_encap); proto_tree_add_uint(fh_tree, hf_file_record_number, tvb, 0, 0, pinfo->num); proto_tree_add_uint_format(fh_tree, hf_file_record_len, tvb, 0, 0, frame_len, "Record Length: %u byte%s (%u bits)", frame_len, frame_plurality, frame_len * 8); ti = proto_tree_add_boolean(fh_tree, hf_file_marked, tvb, 0, 0,pinfo->fd->flags.marked); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_boolean(fh_tree, hf_file_ignored, tvb, 0, 0,pinfo->fd->flags.ignored); PROTO_ITEM_SET_GENERATED(ti); if(pinfo->fd->pfd != 0){ proto_item *ppd_item; guint num_entries = g_slist_length(pinfo->fd->pfd); guint i; ppd_item = proto_tree_add_uint(fh_tree, hf_file_num_p_prot_data, tvb, 0, 0, num_entries); PROTO_ITEM_SET_GENERATED(ppd_item); for(i=0; i<num_entries; i++){ gchar* str = p_get_proto_name_and_key(wmem_file_scope(), pinfo, i); proto_tree_add_string_format(fh_tree, hf_file_proto_name_and_key, tvb, 0, 0, str, "%s", str); } } #if 0 if (show_file_off) { proto_tree_add_int64_format_value(fh_tree, hf_frame_file_off, tvb, 0, 0, pinfo->fd->file_off, "%" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)", pinfo->fd->file_off, pinfo->fd->file_off); } #endif } if (pinfo->fd->flags.ignored) { /* Ignored package, stop handling here */ col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>"); proto_tree_add_boolean_format(tree, hf_file_ignored, tvb, 0, -1, TRUE, "This record is marked as ignored"); return tvb_captured_length(tvb); } /* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */ TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations. (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif if (!dissector_try_uint(file_encap_dissector_table, pinfo->pkt_encap, tvb, pinfo, parent_tree)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN"); col_add_fstr(pinfo->cinfo, COL_INFO, "FTAP_ENCAP = %d", pinfo->pkt_encap); call_data_dissector(tvb, pinfo, parent_tree); } #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch(GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; if(proto_field_is_referenced(tree, hf_file_protocols)) { wmem_strbuf_t *val = wmem_strbuf_new(wmem_packet_scope(), ""); wmem_list_frame_t *frame; /* skip the first entry, it's always the "frame" protocol */ frame = wmem_list_frame_next(wmem_list_head(pinfo->layers)); if (frame) { wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } while (frame) { wmem_strbuf_append_c(val, ':'); wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } ti = proto_tree_add_string(fh_tree, hf_file_protocols, tvb, 0, 0, wmem_strbuf_get_str(val)); PROTO_ITEM_SET_GENERATED(ti); } /* Call postdissectors if we have any (while trying to avoid another * TRY/CATCH) */ if (have_postdissector()) { TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations */ /* (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif call_all_postdissectors(tvb, pinfo, parent_tree); #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch(GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; } /* Attempt to (re-)calculate color filters (if any). */ if (pinfo->fd->flags.need_colorize) { color_filter = color_filters_colorize_packet(file_data->color_edt); pinfo->fd->color_filter = color_filter; pinfo->fd->flags.need_colorize = 0; } else { color_filter = pinfo->fd->color_filter; } if (color_filter) { pinfo->fd->color_filter = color_filter; item = proto_tree_add_string(fh_tree, hf_file_color_filter_name, tvb, 0, 0, color_filter->filter_name); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_string(fh_tree, hf_file_color_filter_text, tvb, 0, 0, color_filter->filter_text); PROTO_ITEM_SET_GENERATED(item); } tap_queue_packet(file_tap, pinfo, NULL); if (pinfo->frame_end_routines) { g_slist_foreach(pinfo->frame_end_routines, &call_file_record_end_routine, NULL); g_slist_free(pinfo->frame_end_routines); pinfo->frame_end_routines = NULL; } return tvb_captured_length(tvb); }
/* * Add an Ethernet trailer - which, for some captures, might be the FCS * rather than a pad-to-60-bytes trailer. * * If fcs_len is 0, we assume the frame has no FCS; if it's 4, we assume * it has an FCS; if it's anything else (such as -1, which means "maybe * it does, maybe it doesn't"), we try to infer whether it has an FCS. */ void add_ethernet_trailer(packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb, tvbuff_t *trailer_tvb, int fcs_len) { /* If there're some bytes left over, it could be a combination of: - padding to meet the minimum 64 byte frame length - an FCS, if present (if fcs_len is 0, we know it's not present; if fcs_len is 4, we know it's present; if fcs_len is -1, we need some heuristics to determine whether it's present) - information inserted by TAPs or other network monitoring equipment. If we don't know whether the FCS is present, then, if we don't have a network monitoring trailer, and if the Ethernet frame was claimed to have had 64 or more bytes - i.e., it was at least an FCS worth of data longer than the minimum payload size - we could assume the last 4 bytes of the trailer are an FCS. */ proto_item *item; proto_tree *checksum_tree; if (trailer_tvb) { guint trailer_length, trailer_reported_length; guint padding_length = 0; gboolean has_fcs = FALSE; tvbuff_t *real_trailer_tvb; trailer_length = tvb_length(trailer_tvb); trailer_reported_length = tvb_reported_length(trailer_tvb); /* There can not have been padding when the length of the frame (including the trailer) is less than 60 bytes. */ if (eth_assume_padding && pinfo->fd->pkt_len>=60) { /* Calculate the amount of padding needed for a minimum sized frame */ if ( (pinfo->fd->pkt_len - trailer_reported_length) < 60 ) padding_length = 60 - (pinfo->fd->pkt_len - trailer_reported_length); /* Add the padding to the tree, unless it should be treated as part of the trailer and therefor be handed over to (one of) the ethernet-trailer dissectors */ if (padding_length > 0) { tvb_ensure_bytes_exist(tvb, 0, padding_length); proto_tree_add_item(fh_tree, hf_eth_padding, trailer_tvb, 0, padding_length, ENC_NA); trailer_length -= padding_length; trailer_reported_length -= padding_length; } } if (fcs_len != 0) { /* If fcs_len is 4, we assume we definitely have an FCS. Otherwise, then, if the frame is big enough that, if we have a trailer, it probably inclues an FCS, and we have enough space in the trailer for the FCS, we assume we have an FCS. "Big enough" means 64 bytes or more; any frame that big needs no trailer, as there's no need to pad an Ethernet packet past 60 bytes. The trailer must be at least 4 bytes long to have enough space for an FCS. */ if (fcs_len == 4 || (tvb_reported_length(tvb) >= 64 && trailer_reported_length >= 4)) { /* Either we know we have an FCS, or we believe we have an FCS. */ if (trailer_length < trailer_reported_length) { /* The packet is claimed to have enough data for a 4-byte FCS, but we didn't capture all of the packet. Slice off the 4-byte FCS from the reported length, and trim the captured length so it's no more than the reported length; that will slice off what of the FCS, if any, is in the captured packet. */ trailer_reported_length -= 4; if (trailer_length > trailer_reported_length) trailer_length = trailer_reported_length; has_fcs = TRUE; } else { /* We captured all of the packet, including what appears to be a 4-byte FCS. Slice it off. */ trailer_length -= 4; trailer_reported_length -= 4; has_fcs = TRUE; } } } /* Create a new tvb without the padding and/or the (assumed) fcs */ if (fcs_len==4) real_trailer_tvb = tvb_new_subset(trailer_tvb, padding_length, trailer_length, trailer_reported_length); else real_trailer_tvb = tvb_new_subset_remaining(trailer_tvb, padding_length); /* Call all ethernet trailer dissectors to dissect the trailer if we actually have a trailer. */ if (tvb_reported_length(real_trailer_tvb) != 0) { if (dissector_try_heuristic(eth_trailer_subdissector_list, real_trailer_tvb, pinfo, tree, NULL) ) { /* If we're not sure that there is a FCS, all trailer data has been given to the ethernet-trailer dissector, so stop dissecting here */ if (fcs_len!=4) return; } else { /* No luck with the trailer dissectors, so just display the extra bytes as general trailer */ if (trailer_length != 0) { tvb_ensure_bytes_exist(tvb, 0, trailer_length); proto_tree_add_item(fh_tree, trailer_id, real_trailer_tvb, 0, trailer_length, ENC_NA); } } } if (has_fcs) { guint32 sent_fcs = tvb_get_ntohl(trailer_tvb, padding_length+trailer_length); if(eth_check_fcs){ guint32 fcs = crc32_802_tvb(tvb, tvb_length(tvb) - 4); if (fcs == sent_fcs) { item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "Frame check sequence: 0x%08x [correct]", sent_fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, TRUE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "Frame check sequence: 0x%08x [incorrect, should be 0x%08x]", sent_fcs, fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, TRUE); PROTO_ITEM_SET_GENERATED(item); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); col_append_str(pinfo->cinfo, COL_INFO, " [ETHERNET FRAME CHECK SEQUENCE INCORRECT]"); } }else{ item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "Frame check sequence: 0x%08x [validiation disabled]", sent_fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); } trailer_length += 4; } proto_tree_set_appendix(fh_tree, tvb, tvb_length(tvb) - padding_length - trailer_length, padding_length + trailer_length); } }