static void dissect_wfd_subelem_coupled_sink(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, int len) { if (len < 1) { expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid, "Too short Wi-Fi Display Coupled Sink"); return; } proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_status_bitmap, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); if (len < 1 + 6) { expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid, "Too short Wi-Fi Display Coupled Sink"); return; } proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_mac_addr, tvb, offset + 1, 6, ENC_NA); }
static void dissect_wfd_subelem_associated_bssid(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, int len) { if (len < 6) { expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid, "Too short Wi-Fi Display Associated BSSID"); return; } proto_tree_add_item(tree, hf_wfd_subelem_assoc_bssid, tvb, offset, 6, ENC_NA); }
static void dissect_bthcrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *main_item; proto_tree *main_tree; btl2cap_data_t *l2cap_data; gint offset = 0; gboolean is_client_message; l2cap_data = (btl2cap_data_t *) pinfo->private_data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCRP"); col_clear(pinfo->cinfo, COL_INFO); switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_add_str(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_add_str(pinfo->cinfo, COL_INFO, "Rcvd "); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ", pinfo->p2p_dir); break; } main_item = proto_tree_add_item(tree, proto_bthcrp, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_bthcrp); /* TODO: Implement streams reconizing by SDP * Server provide SDP record for Control and Data PSM * Client provide SDP record for Notification PSM (optional) */ is_client_message = (is_client && pinfo->p2p_dir == P2P_DIR_SENT) || (!is_client && pinfo->p2p_dir == P2P_DIR_RECV); if (psm_control != 0 && l2cap_data->psm == psm_control) { offset = dissect_control(tvb, pinfo, main_tree, offset, is_client_message); } else if (psm_data_stream != 0 && l2cap_data->psm == psm_data_stream) { offset = dissect_data(tvb, pinfo, main_tree, offset); } else if (psm_notification != 0 && l2cap_data->psm == psm_notification) { offset = dissect_notification(tvb, pinfo, main_tree, offset, is_client_message); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "HCRP stream (CID: 0x%04X)", l2cap_data->cid); } if (tvb_length_remaining(tvb, offset)) { proto_item *pitem; pitem = proto_tree_add_item(main_tree, hf_bthcrp_data, tvb, offset, -1, ENC_NA); expert_add_info_format(pinfo, pitem, PI_PROTOCOL, PI_WARN, "Unexpected data"); } }
/* 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; }
void show_reported_bounds_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *item; col_append_str(pinfo->cinfo, COL_INFO, "[Malformed Packet]"); item = proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Malformed Packet (Exception occurred)"); }
static void dissect_payload_kink_ap_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){ proto_tree *payload_kink_ap_rep_tree; proto_item *ti; guint8 next_payload; guint payload_length; guint16 krb_ap_rep_length; int start_payload_offset = 0; /* Keep beginning of payload offset */ payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH); start_payload_offset = offset; /* Make the subtree */ ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_AP_REP"); payload_kink_ap_rep_tree = proto_item_add_subtree(ti, ett_payload_kink_ap_rep); next_payload = tvb_get_guint8(tvb, offset); proto_tree_add_uint(payload_kink_ap_rep_tree, hf_kink_next_payload, tvb, offset, 1, next_payload); offset ++; proto_tree_add_item(payload_kink_ap_rep_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; ti = proto_tree_add_uint(payload_kink_ap_rep_tree, hf_kink_payload_length, tvb, offset, 2, payload_length); if(payload_length <= PAYLOAD_HEADER){ expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "This Payload Length is too small"); } offset += 2; /* Show time as UTC, not local time. */ proto_tree_add_item(payload_kink_ap_rep_tree, hf_kink_epoch, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; if(payload_length > PAYLOAD_HEADER){ tvbuff_t *krb_tvb; krb_ap_rep_length = payload_length - PAYLOAD_HEADER; krb_tvb=tvb_new_subset(tvb, offset, (krb_ap_rep_length>tvb_length_remaining(tvb, offset))?tvb_length_remaining(tvb, offset):krb_ap_rep_length, krb_ap_rep_length); keytype=kerberos_output_keytype(); dissect_kerberos_main(krb_tvb, pinfo, payload_kink_ap_rep_tree, FALSE, NULL); offset += krb_ap_rep_length; } /* This part consider the padding. Payload_length don't contain the padding. */ if(payload_length % PADDING != 0){ payload_length += (PADDING - (payload_length % PADDING)); } offset = start_payload_offset + payload_length; if(payload_length > 0) { control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */ } }
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 void dissect_wfd_subelem_alt_mac_addr(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, int len) { if (len<6) { expert_add_info_format(pinfo, tree, &ei_wfd_subelem_len_invalid, "Too short Wi-Fi Display Alternative MAC Address"); return; } proto_tree_add_item(tree, hf_wfd_subelem_alt_mac_addr, tvb, offset, 6, ENC_NA); }
static int check_term(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree) { proto_item *ti; /* First, check for CRLF, or, if global_beep_strict_term is false, * one of CR or LF ... If neither of these hold, we add an element * that complains of a protocol violation, and return -1, else * we add a terminator to the tree (possibly non-standard) and return * the count of characters we saw ... This may throw off the rest of the * dissection ... so-be-it! */ if ((tvb_get_guint8(tvb, offset) == 0x0d && tvb_get_guint8(tvb, offset + 1) == 0x0a)){ /* Correct terminator */ proto_tree_add_text(tree, tvb, offset, 2, "Terminator: CRLF"); return 2; } if ((tvb_get_guint8(tvb, offset) == 0x0d) && !global_beep_strict_term) { ti = proto_tree_add_text(tree, tvb, offset, 1, "Terminator: CR"); expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Nonstandard Terminator: CR"); return 1; } if ((tvb_get_guint8(tvb, offset) == 0x0a) && !global_beep_strict_term) { ti = proto_tree_add_text(tree, tvb, offset, 1, "Terminator: LF"); expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Nonstandard Terminator: LF"); return 1; } ti = proto_tree_add_text(tree, tvb, offset, 1, "Terminator: %s", tvb_format_text(tvb, offset, 2)); expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Invalid Terminator: %s", tvb_format_text(tvb, offset, 2)); return -1; }
static void dissect_etherip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tvbuff_t *next_tvb; proto_tree *etherip_tree; proto_item *ti; guint16 field, version; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ETHERIP"); field = tvb_get_ntohs(tvb, 0); version = (field & ETHERIP_VERS_MASK) >> 12; if (tree) { ti = proto_tree_add_protocol_format(tree, proto_etherip, tvb, 0, 2, "EtherIP, Version %d", version ); etherip_tree = proto_item_add_subtree(ti, ett_etherip); ti = proto_tree_add_item(etherip_tree, hf_etherip_ver, tvb, 0, 2, ENC_BIG_ENDIAN); if (version != 3) { expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Version must be 3"); } ti = proto_tree_add_item(etherip_tree, hf_etherip_reserved, tvb, 0, 2, ENC_BIG_ENDIAN); if ((field & ETHERIP_RESERVE_MASK) != 0) { expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Reserved field must be 0"); } } /* Set the tvbuff for the payload after the header */ next_tvb = tvb_new_subset_remaining(tvb, 2); call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree); }
static int usbip_dissect_op(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int offset) { proto_item *ti = NULL; guint32 operation; gint32 status; proto_tree_add_item(tree, hf_usbip_version, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item_ret_uint(tree, hf_usbip_operation, tvb, offset, 2, ENC_BIG_ENDIAN, &operation); offset += 2; proto_tree_add_item_ret_int(tree, hf_usbip_status, tvb, offset, 4, ENC_BIG_ENDIAN, &status); offset += 4; switch (operation) { case OP_REQ_IMPORT: offset = dissect_import_request(pinfo, tree, tvb, offset); break; case OP_REP_IMPORT: offset = dissect_import_response(pinfo, tree, tvb, offset, status); break; case OP_REQ_DEVLIST: offset = dissect_device_list_request(pinfo); break; case OP_REP_DEVLIST: offset = dissect_device_list_response(pinfo, tree, tvb, offset); break; default: proto_tree_add_item(tree, hf_usbip_urb_data, tvb, offset, -1, ENC_NA); offset = tvb_reported_length_remaining(tvb, offset); expert_add_info_format( pinfo, ti, &ei_usbip, "Dissector for USBIP Operation" " (%x) code not implemented, Contact" " Wireshark developers if you want this supported", operation); proto_item_append_text(ti, ": Undecoded"); break; } return offset; }
/* Code to actually dissect the packets */ static int dissect_llrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *llrp_tree; guint16 type; guint32 len; guint offset = 0; /* Check that there's enough data */ if (tvb_reported_length(tvb) < LLRP_LEN_MIN) return 0; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLRP"); col_set_str(pinfo->cinfo, COL_INFO, "LLRP Message"); type = tvb_get_ntohs(tvb, offset) & 0x03FF; col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str(type, message_types, "Unknown Type: %d")); ti = proto_tree_add_item(tree, proto_llrp, tvb, offset, -1, ENC_NA); llrp_tree = proto_item_add_subtree(ti, ett_llrp); proto_tree_add_item(llrp_tree, hf_llrp_version, tvb, offset, 1, ENC_NA); proto_tree_add_item(llrp_tree, hf_llrp_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ti = proto_tree_add_item(llrp_tree, hf_llrp_length, tvb, offset, 4, ENC_BIG_ENDIAN); len = tvb_get_ntohl(tvb, offset); if (len > tvb_reported_length(tvb)) { expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Incorrect length field: claimed %u, but only have %u.", len, tvb_reported_length(tvb)); } offset += 4; proto_tree_add_item(llrp_tree, hf_llrp_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; if (match_strval(type, message_types)) dissect_llrp_message(tvb, pinfo, llrp_tree, type, offset); return tvb_length(tvb); }
static void xmpp_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element) { proto_item *error_item; proto_tree *error_tree; xmpp_element_t *text_element, *cond_element; xmpp_attr_info attrs_info[] = { {"type", &hf_xmpp_error_type, TRUE, TRUE, NULL, NULL}, {"code", &hf_xmpp_error_code, FALSE, TRUE, NULL, NULL}, {"condition", &hf_xmpp_error_condition, TRUE, TRUE, NULL, NULL} /*TODO: validate list to the condition element*/ }; gchar *error_info; xmpp_attr_t *fake_condition = NULL; error_info = wmem_strdup(wmem_packet_scope(), "Stanza error"); error_item = proto_tree_add_item(tree, hf_xmpp_error, tvb, element->offset, element->length, ENC_BIG_ENDIAN); error_tree = proto_item_add_subtree(error_item, ett_xmpp_query_item); cond_element = xmpp_steal_element_by_attr(element, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); if(cond_element) { fake_condition = xmpp_ep_init_attr_t(cond_element->name, cond_element->offset, cond_element->length); g_hash_table_insert(element->attrs, (gpointer)"condition", fake_condition); error_info = wmem_strdup_printf(wmem_packet_scope(), "%s: %s;", error_info, cond_element->name); } xmpp_display_attrs(error_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); while((text_element = xmpp_steal_element_by_name(element, "text")) != NULL) { xmpp_error_text(error_tree, tvb, text_element); error_info = wmem_strdup_printf(wmem_packet_scope(), "%s Text: %s", error_info, text_element->data?text_element->data->value:""); } expert_add_info_format(pinfo, error_item, &ei_xmpp_response, "%s", error_info); xmpp_unknown(error_tree, tvb, pinfo, element); }
static void dissect_rpcap_error (tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gint offset) { proto_item *ti; gint len; len = tvb_captured_length_remaining (tvb, offset); if (len <= 0) return; col_append_fstr (pinfo->cinfo, COL_INFO, ": %s", tvb_format_text_wsp (tvb, offset, len)); ti = proto_tree_add_item (parent_tree, hf_error, tvb, offset, len, ENC_ASCII|ENC_NA); expert_add_info_format(pinfo, ti, &ei_error, "Error: %s", tvb_format_text_wsp (tvb, offset, len)); }
static void dissect_rpcap_error (tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gint offset) { proto_item *ti; gint len; len = tvb_length_remaining (tvb, offset); if (check_col (pinfo->cinfo, COL_INFO)) { col_append_fstr (pinfo->cinfo, COL_INFO, ": %s", tvb_format_text_wsp (tvb, offset, len)); } ti = proto_tree_add_item (parent_tree, hf_error, tvb, offset, len, ENC_ASCII|ENC_NA); expert_add_info_format (pinfo, ti, PI_SEQUENCE, PI_NOTE, "Error: %s", tvb_format_text_wsp (tvb, offset, len)); }
static gint dissect_rpcap_ifaddr (tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gint offset, int hf_id, proto_item *parent_item) { proto_tree *tree; proto_item *ti; gchar ipaddr[MAX_ADDR_STR_LEN]; guint32 ipv4; guint16 af; ti = proto_tree_add_item (parent_tree, hf_id, tvb, offset, 128, ENC_BIG_ENDIAN); tree = proto_item_add_subtree (ti, ett_ifaddr); af = tvb_get_ntohs (tvb, offset); proto_tree_add_item (tree, hf_if_af, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (af == COMMON_AF_INET) { proto_tree_add_item (tree, hf_if_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ipv4 = tvb_get_ipv4 (tvb, offset); ip_to_str_buf((guint8 *)&ipv4, ipaddr, MAX_ADDR_STR_LEN); proto_item_append_text (ti, ": %s", ipaddr); if (parent_item) { proto_item_append_text (parent_item, ": %s", ipaddr); } proto_tree_add_item (tree, hf_if_ip, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item (tree, hf_if_padding, tvb, offset, 120, ENC_NA); offset += 120; } else { ti = proto_tree_add_item (tree, hf_if_unknown, tvb, offset, 126, ENC_NA); if (af != COMMON_AF_UNSPEC) { expert_add_info_format(pinfo, ti, &ei_if_unknown, "Unknown address family: %d", af); } offset += 126; } return offset; }
/* * entry point of the roofnet dissector */ static void dissect_roofnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item * it= NULL; proto_tree * roofnet_tree= NULL; guint offset= 0; guint8 roofnet_msg_type= 0; guint8 roofnet_nlinks= 0; guint8 nlink= 1; col_set_str(pinfo->cinfo, COL_PROTOCOL, "Roofnet"); roofnet_msg_type = tvb_get_guint8(tvb, ROOFNET_OFFSET_TYPE); /* Clear out stuff in the info column */ if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "Message Type: %s", val_to_str(roofnet_msg_type, roofnet_pt_vals, "Unknown (%d)")); } if (tree) { it = proto_tree_add_item(tree, proto_roofnet, tvb, offset, -1, FALSE); roofnet_tree = proto_item_add_subtree(it, ett_roofnet); } dissect_roofnet_header(roofnet_tree, tvb, &offset); roofnet_nlinks= tvb_get_guint8(tvb, ROOFNET_OFFSET_NLINKS); /* Check that we do not have a malformed roofnet packet */ if ((roofnet_nlinks*6*4)+ROOFNET_HEADER_LENGTH > ROOFNET_MAX_LENGTH) { if (tree) { expert_add_info_format(pinfo, it, PI_MALFORMED, PI_ERROR, "Too many links (%u)\n", roofnet_nlinks); } return; } for (; roofnet_nlinks > 0; roofnet_nlinks--) { /* Do we have enough buffer to decode the next link ? */ if (tvb_reported_length_remaining(tvb, offset) < ROOFNET_LINK_DESCRIPTION_LENGTH) return; dissect_roofnet_link(roofnet_tree, tvb, &offset, nlink++); } dissect_roofnet_data(tree, tvb, pinfo, offset+4); }
static int dissect_distcc_doti(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, gint parameter) { gint len=parameter; proto_item* ti; CHECK_PDU_LEN("DOTI"); /* see if we need to desegment the PDU */ DESEGMENT_TCP("DOTI"); col_append_str(pinfo->cinfo, COL_INFO, "DOTI source "); ti = proto_tree_add_item(tree, hf_distcc_doti_source, tvb, offset, len, ENC_ASCII|ENC_NA); if(len!=parameter){ expert_add_info_format(pinfo, ti, &ei_distcc_short_pdu, "[Short DOTI PDU]"); } return offset+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; }
/* returns TRUE if this TCP segment carries a MPA REPLY and FALSE otherwise */ static gboolean is_mpa_rep(tvbuff_t *tvb, packet_info *pinfo) { conversation_t *conversation = NULL; mpa_state_t *state = NULL; guint8 mcrres; if (tvb_get_ntoh64(tvb, 0) != MPA_REQ_REP_FRAME || tvb_get_ntoh64(tvb, 8) != MPA_ID_REP_FRAME) { return FALSE; } conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (!conversation) { return FALSE; } state = get_mpa_state(conversation); if (!state) { return FALSE; } if (!state->full_operation) { /* update state of this conversation */ mcrres = tvb_get_guint8(tvb, 16); state->res_exp_m_ini = mcrres & MPA_MARKER_FLAG; state->crc = state->crc | (mcrres & MPA_CRC_FLAG); state->rep_frame_num = pinfo->fd->num; /* enter Full Operation Phase only if the Reject bit is not set */ if (!(mcrres & MPA_REJECT_FLAG)) state->full_operation = TRUE; else expert_add_info_format(pinfo, NULL, PI_RESPONSE_CODE, PI_NOTE, "Reject bit set by Responder"); } return TRUE; }
void xmpp_unknown(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element) { GList *childs = element->elements; /*element has unrecognized elements*/ while(childs) { xmpp_element_t *child = (xmpp_element_t *)childs->data; if(!child->was_read) { proto_item *unknown_item; proto_tree *unknown_tree; #ifdef XMPP_DEBUG unknown_item = proto_tree_add_string_format(tree, hf_xmpp_unknown, tvb, child->offset, child->length, child->name, "%s", xmpp_ep_string_upcase(child->name)); #else unknown_item = proto_tree_add_text(tree, tvb, child->offset, child->length, "%s", xmpp_ep_string_upcase(child->name)); #endif unknown_tree = proto_item_add_subtree(unknown_item, ett_unknown[0]); /*Add COL_INFO only if root element is IQ*/ if(strcmp(element->name,"iq")==0) col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", xmpp_ep_string_upcase(child->name)); if(child->default_ns_abbrev) proto_item_append_text(unknown_item,"(%s)",child->default_ns_abbrev); xmpp_unknown_items(unknown_tree, tvb, pinfo, child, 1); #ifdef XMPP_DEBUG proto_item_append_text(unknown_item, " [UNKNOWN]"); expert_add_info_format(pinfo, unknown_item, PI_UNDECODED, PI_NOTE,"Unknown element: %s", child->name); #endif } childs = childs->next; } }
static guint8 display_xip_serval_ext(tvbuff_t *tvb, packet_info *pinfo, proto_item *ti, proto_tree *xip_serval_tree, gint offset) { guint8 type = tvb_get_guint8(tvb, offset) & XIP_SERVAL_EXT_TYPE_MASK; guint8 length = tvb_get_guint8(tvb, offset + 1); /* For now, the only type of extension header in XIP Serval is * the control extension header. */ switch (type) { case XIP_SERVAL_EXT_TYPE_CONTROL: return display_xip_serval_control_ext(tvb, xip_serval_tree, offset, type, length); default: expert_add_info_format(pinfo, ti, &ei_xip_serval_bad_ext, "Unrecognized Serval extension header type: 0x%02x", type); return 0; } }
void dissect_pyreshark(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int i; for (i=0;i<g_num_dissectors; i++) { if (strcmp(g_dissectors[i]->name, pinfo->current_proto) == 0) { dissect_proto(g_dissectors[i], tvb, pinfo, tree); return; } } if (tree) { expert_add_info_format(pinfo, NULL, PI_MALFORMED, PI_ERROR, "PyreShark: protocol %s not found", pinfo->current_proto); } }
static int call_rtse_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { tvbuff_t *next_tvb; next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset)); if(!dissector_try_string(rtse_oid_dissector_table, oid, next_tvb, pinfo, tree)){ proto_item *item=proto_tree_add_text(tree, next_tvb, 0, tvb_length_remaining(tvb, offset), "RTSE: Dissector for OID:%s not implemented. Contact Wireshark developers if you want this supported", oid); proto_tree *next_tree=proto_item_add_subtree(item, ett_rtse_unknown); expert_add_info_format (pinfo, item, PI_UNDECODED, PI_WARN, "RTSE: Dissector for OID %s not implemented", oid); dissect_unknown_ber(pinfo, next_tvb, offset, next_tree); } /*XXX until we change the #.REGISTER signature for _PDU()s * into new_dissector_t we have to do this kludge with * manually step past the content in the ANY type. */ offset+=tvb_length_remaining(tvb, offset); return offset; }
static void dissect_message_data(tvbuff_t *message_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree) { guint32 length, message_data_length, actual_length; guint8 type; tvbuff_t *message_data_tvb; length = tvb_get_ntohl(message_tvb, LENGTH_OFFSET); message_data_length = length - HEADER_LENGTH; message_data_tvb = tvb_new_subset(message_tvb, MESSAGE_DATA_OFFSET, message_data_length, message_data_length); type = tvb_get_guint8(message_tvb, TYPE_OFFSET); switch(type) { case USER_DATA_TYPE: dissect_user_data_message(message_data_tvb, pinfo, m2pa_item, m2pa_tree, tree); break; case LINK_STATUS_TYPE: dissect_link_status_message(message_data_tvb, pinfo, m2pa_tree); break; default: dissect_unknown_message(message_data_tvb, m2pa_tree); } actual_length = tvb_reported_length(message_tvb); if (actual_length > length) { proto_item *pi; pi = proto_tree_add_item(m2pa_tree, hf_undecode_data, message_tvb, length, (actual_length - length), ENC_NA); expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_WARN, "There are %d bytes of data which is greater than M2PA's length parameter (%d)", actual_length, length); } }
static int call_rtse_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data) { tvbuff_t *next_tvb; int len; next_tvb = tvb_new_subset_remaining(tvb, offset); if ((len = dissector_try_string(rtse_oid_dissector_table, oid, next_tvb, pinfo, tree, data)) == 0) { proto_item *item; proto_tree *next_tree; next_tree = proto_tree_add_subtree_format(tree, next_tvb, 0, -1, ett_rtse_unknown, &item, "RTSE: Dissector for OID:%s not implemented. Contact Wireshark developers if you want this supported", oid); expert_add_info_format(pinfo, item, &ei_rtse_dissector_oid_not_implemented, "RTSE: Dissector for OID %s not implemented", oid); len = dissect_unknown_ber(pinfo, next_tvb, offset, next_tree); } offset += len; return offset; }
static int dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree, int frame_offset) { guint64 rpt_sno; guint64 chkp_sno; guint64 upper_bound; guint64 lower_bound; int rcpt_clm_cnt; guint64 offset; guint64 length; int rpt_sno_size; int chkp_sno_size; int upper_bound_size; int lower_bound_size; int rcpt_clm_cnt_size; int offset_size; int length_size; int segment_offset = 0; int i; proto_item *ltp_rpt_item; proto_item *ltp_rpt_clm_item; proto_tree *ltp_rpt_tree; proto_tree *ltp_rpt_clm_tree; /* Create the subtree for report segment under the main LTP tree and all the report segment fields under it */ ltp_rpt_item = proto_tree_add_text(ltp_tree, tvb, frame_offset, -1, "Report Segment"); ltp_rpt_tree = proto_item_add_subtree(ltp_rpt_item, ett_rpt_segm); /* Extract the report segment info */ rpt_sno = evaluate_sdnv_64(tvb, frame_offset, &rpt_sno_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_sno, tvb, frame_offset + segment_offset, rpt_sno_size, rpt_sno); segment_offset += rpt_sno_size; chkp_sno = evaluate_sdnv_64(tvb, frame_offset + segment_offset, &chkp_sno_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_chkp, tvb, frame_offset + segment_offset, chkp_sno_size, chkp_sno); segment_offset += chkp_sno_size; upper_bound = evaluate_sdnv(tvb, frame_offset + segment_offset, &upper_bound_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_ub, tvb, frame_offset + segment_offset, upper_bound_size, upper_bound); segment_offset += upper_bound_size; lower_bound = evaluate_sdnv(tvb, frame_offset + segment_offset, &lower_bound_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_lb, tvb, frame_offset + segment_offset, lower_bound_size, lower_bound); segment_offset += lower_bound_size; rcpt_clm_cnt = evaluate_sdnv(tvb, frame_offset + segment_offset, &rcpt_clm_cnt_size); if (rcpt_clm_cnt < 0){ proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); expert_add_info_format(pinfo, ltp_tree, PI_UNDECODED, PI_ERROR, "Negative reception claim count: %d", rcpt_clm_cnt); return 0; } /* Each reception claim is at least 2 bytes, so if the count is larger than the * max number of claims we can possibly squeeze into the remaining tvbuff, then * the packet is malformed. */ if (rcpt_clm_cnt > tvb_length_remaining(tvb, frame_offset + segment_offset) / 2) { proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); expert_add_info_format(pinfo, ltp_tree, PI_MALFORMED, PI_ERROR, "Reception claim count impossibly large: %d > %d", rcpt_clm_cnt, tvb_length_remaining(tvb, frame_offset + segment_offset) / 2); return 0; } proto_tree_add_uint(ltp_rpt_tree, hf_ltp_rpt_clm_cnt, tvb, frame_offset + segment_offset, rcpt_clm_cnt_size, rcpt_clm_cnt); segment_offset += rcpt_clm_cnt_size; ltp_rpt_clm_item = proto_tree_add_text(ltp_rpt_tree, tvb, frame_offset + segment_offset, -1, "Reception claims"); ltp_rpt_clm_tree = proto_item_add_subtree(ltp_rpt_clm_item, ett_rpt_clm); /* There can be multiple reception claims in the same report segment */ for(i = 0; i<rcpt_clm_cnt; i++){ offset = evaluate_sdnv(tvb,frame_offset + segment_offset, &offset_size); proto_tree_add_uint64_format(ltp_rpt_clm_tree, hf_ltp_rpt_clm_off, tvb, frame_offset + segment_offset, offset_size, offset, "Offset[%d] : %"G_GINT64_MODIFIER"d", i, offset); segment_offset += offset_size; length = evaluate_sdnv(tvb,frame_offset + segment_offset, &length_size); proto_tree_add_uint64_format(ltp_rpt_clm_tree, hf_ltp_rpt_clm_len, tvb, frame_offset + segment_offset, length_size, length, "Length[%d] : %"G_GINT64_MODIFIER"d",i, length); segment_offset += length_size; } proto_item_set_end(ltp_rpt_clm_item, tvb, frame_offset + segment_offset); proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); return segment_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; }
/* echo(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_cntl_echo, tvb, offset, 4, cntl->echo); return; } static void dissect_xtp_first(tvbuff_t *tvb, proto_tree *tree, guint32 offset) { if (!dissect_xtp_aseg(tvb, tree, offset)) return; offset += XTP_IP_ADDR_SEG_LEN; dissect_xtp_tspec(tvb, tree, offset); return; } #define XTP_MAX_NSPANS 10000 /* Arbitrary. (Documentation link is dead.) */ static void dissect_xtp_ecntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *top_ti; proto_tree *xtp_subtree; struct xtp_ecntl ecntl[1]; guint spans_len; guint i; top_ti = proto_tree_add_text(tree, tvb, offset, len, "Error Control Segment"); xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_ecntl); if (len < MIN_XTP_ECNTL_PKT_LEN) { proto_item_append_text(top_ti, ", bogus length (%u, must be at least %u)", len, MIN_XTP_ECNTL_PKT_LEN); return; } /** parse **/ /* rseq(8) */ ecntl->rseq = tvb_get_ntohl(tvb, offset); ecntl->rseq <<= 32; ecntl->rseq += tvb_get_ntohl(tvb, offset+4); offset += 8; /* alloc(8) */ ecntl->alloc = tvb_get_ntohl(tvb, offset); ecntl->alloc <<= 32; ecntl->alloc += tvb_get_ntohl(tvb, offset+4); offset += 8; /* echo(4) */ ecntl->echo = tvb_get_ntohl(tvb, offset); offset += 4; /* nspan(4) */ ecntl->nspan = tvb_get_ntohl(tvb, offset); offset += 4; len = len + XTP_HEADER_LEN - offset; spans_len = 16 * ecntl->nspan; if (len != spans_len) { expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Number of spans (%u) incorrect. Should be %u.", ecntl->nspan, len); THROW(ReportedBoundsError); } if (ecntl->nspan > XTP_MAX_NSPANS) { expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Too many spans: %u", ecntl->nspan); THROW(ReportedBoundsError); } /** add summary **/ col_append_fstr(pinfo->cinfo, COL_INFO, " Recv-Seq=%" G_GINT64_MODIFIER "u", ecntl->rseq); col_append_fstr(pinfo->cinfo, COL_INFO, " Alloc=%" G_GINT64_MODIFIER "u", ecntl->alloc); proto_item_append_text(top_ti, ", Recv-Seq: %" G_GINT64_MODIFIER "u", ecntl->rseq); /** display **/ offset = start; /* rseq(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_rseq, tvb, offset, 8, ecntl->rseq); offset += 8; /* alloc(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_alloc, tvb, offset, 8, ecntl->alloc); offset += 8; /* echo(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_echo, tvb, offset, 4, ecntl->echo); offset += 4; /* nspan(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_nspan, tvb, offset, 4, ecntl->nspan); offset += 4; /* spans(16n) */ for (i = 0; i < ecntl->nspan; i++) { proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_left, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_right, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; } return; }
static int dissect_iso7816_atr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint offset=0; guint i=0; /* loop index for TA(i)...TD(i) */ proto_item *td_it; proto_tree *td_tree=NULL; guint8 ta, tb, tc, td, k=0; gint tck_len; proto_item *err_it; col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "ATR sequence"); /* ISO 7816-4, section 4 indicates that concatenations are big endian */ proto_tree_add_item(tree, hf_iso7816_atr_init_char, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; do { /* for i==0, this is the T0 byte, otherwise it's the TD(i) byte in each loop, we dissect T0/TD(i) and TA(i+1), TB(i+1), TC(i+1) */ td = tvb_get_guint8(tvb, offset); if (i==0) { td_it = proto_tree_add_item(tree, hf_iso7816_atr_t0, tvb, offset, 1, ENC_BIG_ENDIAN); } else { td_it = proto_tree_add_uint_format(tree, hf_iso7816_atr_td, tvb, offset, 1, td, "Interface character TD(%d): 0x%02x", i, td); } td_tree = proto_item_add_subtree(td_it, ett_iso7816_atr_td); proto_tree_add_boolean_format(td_tree, hf_iso7816_atr_next_ta_present, tvb, offset, 1, td&0x10, "TA(%d) present: %s", i+1, td&0x10 ? "True" : "False"); proto_tree_add_boolean_format(td_tree, hf_iso7816_atr_next_tb_present, tvb, offset, 1, td&0x20, "TB(%d) present: %s", i+1, td&0x20 ? "True" : "False"); proto_tree_add_boolean_format(td_tree, hf_iso7816_atr_next_tc_present, tvb, offset, 1, td&0x40, "TC(%d) present: %s", i+1, td&0x40 ? "True" : "False"); proto_tree_add_boolean_format(td_tree, hf_iso7816_atr_next_td_present, tvb, offset, 1, td&0x80, "TD(%d) present: %s", i+1, td&0x80 ? "True" : "False"); if (i==0) { k = td&0x0F; /* number of historical bytes */ proto_tree_add_item(td_tree, hf_iso7816_atr_k, tvb, offset, 1, ENC_BIG_ENDIAN); } else { proto_tree_add_item(td_tree, hf_iso7816_atr_t, tvb, offset, 1, ENC_BIG_ENDIAN); } offset++; if (td&0x10) { ta = tvb_get_guint8(tvb, offset); /* we read TA(i+1), see comment above */ proto_tree_add_uint_format(tree, hf_iso7816_atr_ta, tvb, offset, 1, ta, "Interface character TA(%d): 0x%02x", i+1, ta); offset++; } if (td&0x20) { tb = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format(tree, hf_iso7816_atr_tb, tvb, offset, 1, tb, "Interface character TB(%d): 0x%02x", i+1, tb); offset++; } if (td&0x40) { tc = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format(tree, hf_iso7816_atr_tc, tvb, offset, 1, tc, "Interface character TC(%d): 0x%02x", i+1, tc); offset++; } i++; } while (td&0x80); if (k>0) { proto_tree_add_item(tree, hf_iso7816_atr_hist_bytes, tvb, offset, k, ENC_NA); offset += k; } tck_len = tvb_reported_length_remaining(tvb, offset); /* tck is either absent or exactly one byte */ if (tck_len==1) { proto_tree_add_item(tree, hf_iso7816_atr_tck, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; } else if (tck_len>1) { err_it = proto_tree_add_text(tree, tvb, offset, tck_len, "Invalid TCK byte"); expert_add_info_format(pinfo, err_it, PI_PROTOCOL, PI_WARN, "TCK byte must either be absent or exactly one byte"); } return offset; }