void fec_info_column(struct _fec *fec, packet_info *pinfo) { if (fec->sbn_present) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SBN: %u", fec->sbn); if (fec->esi_present) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ESI: 0x%X", fec->esi); }
/* Decode and display the PDU Burst */ static void pdu_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo, gint burst_number, gint frag_type, gint frag_number) { fragment_head *pdu_frag; tvbuff_t *pdu_tvb = NULL; /* update the info column */ switch (frag_type) { case TLV_FIRST_FRAG: col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "First TLV Fragment (%d)", frag_number); break; case TLV_LAST_FRAG: col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Last TLV Fragment (%d)", frag_number); break; case TLV_MIDDLE_FRAG: col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Middle TLV Fragment %d", frag_number); break; } if(frag_type == TLV_NO_FRAG) { /* not fragmented PDU */ pdu_tvb = tvb_new_subset_length(tvb, offset, length); } else /* fragmented PDU */ { /* add the fragment */ pdu_frag = fragment_add_seq(&pdu_reassembly_table, tvb, offset, pinfo, burst_number, NULL, frag_number - 1, length, ((frag_type==TLV_LAST_FRAG)?0:1), 0); if(pdu_frag && frag_type == TLV_LAST_FRAG) { /* create the new tvb for defragmented frame */ pdu_tvb = tvb_new_chain(tvb, pdu_frag->tvb_data); /* add the defragmented data to the data source list */ add_new_data_source(pinfo, pdu_tvb, "Reassembled WiMax PDU Frame"); } else { pdu_tvb = NULL; if(frag_type == TLV_LAST_FRAG) { /* update the info column */ col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Incomplete PDU frame"); } } } /* process the defragmented PDU burst */ if(pdu_tvb) { if(wimax_pdu_burst_handle) {/* decode and display PDU Burst */ call_dissector(wimax_pdu_burst_handle, pdu_tvb, pinfo, tree); } else /* display PDU Burst info */ { /* update the info column */ col_append_str(pinfo->cinfo, COL_INFO, "PDU Burst"); } } }
static void decode_iei_reset_flag(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { guint8 flag; proto_item *tf; proto_tree *field_tree; flag = tvb_get_guint8(bi->tvb, bi->offset); if (bi->nsip_tree) { tf = proto_tree_add_text(bi->nsip_tree, bi->tvb, ie_start_offset, ie->total_length, "Reset Flag: %#02x", flag); field_tree = proto_item_add_subtree(tf, ett_nsip_reset_flag); proto_tree_add_boolean(field_tree, hf_nsip_reset_flag, bi->tvb, bi->offset, 1, flag & NSIP_MASK_RESET_FLAG); if (flag & NSIP_MASK_RESET_FLAG) { col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Reset"); proto_item_append_text(bi->ti, ", Reset"); } proto_tree_add_uint(field_tree, hf_nsip_reset_flag_spare, bi->tvb, bi->offset, 1, flag & NSIP_MASK_RESET_FLAG_SPARE); } bi->offset += 1; }
static int dissect_form_urlencoded(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { proto_tree *url_tree; proto_tree *sub; proto_item *ti; gint offset = 0, next_offset; const char *data_name; data_name = pinfo->match_string; if (! (data_name && data_name[0])) { /* * No information from "match_string" */ data_name = (char *)data; if (! (data_name && data_name[0])) { /* * No information from dissector data */ data_name = NULL; } } if (data_name) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name); ti = proto_tree_add_item(tree, hfi_urlencoded, tvb, 0, -1, ENC_NA); if (data_name) proto_item_append_text(ti, ": %s", data_name); url_tree = proto_item_add_subtree(ti, ett_form_urlencoded); while (tvb_reported_length_remaining(tvb, offset) > 0) { const int start_offset = offset; char *key, *value; ti = proto_tree_add_item(url_tree, &hfi_form_keyvalue, tvb, offset, 0, ENC_NA); sub = proto_item_add_subtree(ti, ett_form_keyvalue); next_offset = get_form_key_value(tvb, &key, offset, '='); if (next_offset == -1) break; proto_tree_add_string(sub, &hfi_form_key, tvb, offset, next_offset - offset, key); proto_item_append_text(sub, ": \"%s\"", key); offset = next_offset+1; next_offset = get_form_key_value(tvb, &value, offset, '&'); if (next_offset == -1) break; proto_tree_add_string(sub, &hfi_form_value, tvb, offset, next_offset - offset, value); proto_item_append_text(sub, " = \"%s\"", value); offset = next_offset+1; proto_item_set_len(ti, offset - start_offset); } return tvb_captured_length(tvb); }
static void decode_iei_transaction_id(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { guint8 id; id = tvb_get_guint8(bi->tvb, bi->offset); proto_tree_add_uint(bi->nsip_tree, hf_nsip_transaction_id, bi->tvb, ie_start_offset, ie->total_length, id); col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Transaction Id: %d", id); bi->offset += 1; }
static void decode_iei_bvci(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { guint16 bvci = tvb_get_ntohs(bi->tvb, bi->offset); proto_tree_add_uint(bi->nsip_tree, hf_nsip_bvci, bi->tvb, ie_start_offset, ie->total_length, bvci); bi->offset += ie->value_length; col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "BVCI %u", bvci); proto_item_append_text(bi->ti, ", BVCI %u", bvci); }
static void decode_iei_nsei(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { guint16 nsei = tvb_get_ntohs(bi->tvb, bi->offset); if (bi->nsip_tree) { proto_tree_add_uint(bi->nsip_tree, hf_nsip_nsei, bi->tvb, ie_start_offset, ie->total_length, nsei); } bi->offset += ie->value_length; if (check_col(bi->pinfo->cinfo, COL_INFO)) { col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "NSEI %u", nsei); } proto_item_append_text(bi->ti, ", NSEI %u", nsei); }
static void decode_iei_ns_vci(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { guint16 ns_vci; if (bi->nsip_tree) { ns_vci = tvb_get_ntohs(bi->tvb, bi->offset); proto_tree_add_uint_format(bi->nsip_tree, hf_nsip_ns_vci, bi->tvb, ie_start_offset, ie->total_length, ns_vci, "NS VCI: %#04x", ns_vci); col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "NS VCI: %#04x", ns_vci); proto_item_append_text(bi->ti, ", NS VCI: %#04x", ns_vci); } bi->offset += ie->value_length; }
/** * dissect_messageid is a utility function which * calculates the ID of the message. * * @see dissect_packetid() * @see dissect_reliable_message_index_base() * @see dissect_content_length() * @see dissect_reliable_message_number() * @see dissect_payload() * @param buffer the buffer to the data * @param offset the offset where to start reading the data * @param tree the parent tree where the dissected data is going to be inserted * @return int returns the messageid * */ static int dissect_messageid(tvbuff_t *buffer, int *offset, proto_tree *tree, packet_info *pinfo, gboolean separator) { gint messageid_length; guint8 messageid; gboolean col_write; messageid = tvb_get_guint8(buffer, (*offset)); switch(messageid) { case DISCONNECT: case DISCONNECTACK: case CONNECTSYN: case CONNECTSYNACK: case CONNECTACK: messageid_length = 4; break; default: messageid_length = 1; break; } proto_tree_add_uint_format_value(tree, hf_knet_messageid, buffer, *offset, messageid_length, messageid, "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData or Malformed Message ID"), messageid); /* XXX - TCP reassembly disables writing columns which prevents populating COL_INFO if multiple KNET messages appear in a single packet that needed to be reassembled. Force making columns writable. */ if (separator) { col_write = col_get_writable(pinfo->cinfo); col_set_writable(pinfo->cinfo, TRUE); col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid); col_set_writable(pinfo->cinfo, col_write); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid); } *offset += messageid_length; return messageid; }
static void decode_iei_cause(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) { guint8 cause; cause = tvb_get_guint8(bi->tvb, bi->offset); proto_tree_add_uint(bi->nsip_tree, hf_nsip_cause, bi->tvb, ie_start_offset, ie->total_length, cause); col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP, "Cause: %s", val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)")); proto_item_append_text(bi->ti, ", Cause: %s", val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)")); bi->offset += ie->value_length; }
/* Display the raw WiMax TLV */ void proto_tree_add_tlv(tlv_info_t *self, tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, gint hf, guint encoding) { guint tlv_offset; gint tlv_type, tlv_len; /* make sure the TLV information is valid */ if(!self->valid) { /* invalid TLV info */ col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Invalid TLV"); return; } tlv_offset = offset; /* display TLV type */ proto_tree_add_item(tree, hf_m2m_type, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); tlv_offset++; /* check the TLV length type */ if( self->length_type ) { /* multiple bytes TLV length */ /* display the length of the TLV length with MSB */ proto_tree_add_item(tree, hf_m2m_len_size, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); tlv_offset++; if(self->size_of_length) /* display the multiple byte TLV length */ proto_tree_add_item(tree, hf_m2m_len, tvb, tlv_offset, self->size_of_length, ENC_BIG_ENDIAN); else return; } else /* display the single byte TLV length */ proto_tree_add_item(tree, hf_m2m_len, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); tlv_type = get_tlv_type(self); /* Display Frame Number as special case for filter */ if ( tlv_type == TLV_FRAME_NUM ) { return; } /* get the TLV length */ tlv_len = get_tlv_length(self); proto_tree_add_item(tree, hf, tvb, (offset + self->value_offset), tlv_len, encoding); }
/* The dissector itself */ static void dissect_at(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *item; proto_tree *at_tree; gint len; len = tvb_reported_length(tvb); col_append_str(pinfo->cinfo, COL_PROTOCOL, "/AT"); col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "AT Command: %s", tvb_format_text_wsp(tvb, 0, len)); if (tree) { /* Start with a top-level item to add everything else to */ item = proto_tree_add_item(tree, proto_at, tvb, 0, -1, ENC_NA); at_tree = proto_item_add_subtree(item, ett_at); /* Command */ proto_tree_add_item(at_tree, hf_at_command, tvb, 0, len, ENC_ASCII|ENC_NA); proto_item_append_text(item, ": %s", tvb_format_text_wsp(tvb, 0, len)); } }
static void dissect_nsip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 pdu_type; build_info_t bi = { NULL, 0, NULL, NULL, NULL, NULL }; proto_tree *nsip_tree; bi.tvb = tvb; bi.pinfo = pinfo; bi.parent_tree = tree; pinfo->current_proto = "GPRS-NS"; if (!nsip_is_recursive) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-NS"); col_clear(pinfo->cinfo, COL_INFO); } pdu_type = tvb_get_guint8(tvb, 0); bi.offset++; if (tree) { bi.ti = proto_tree_add_item(tree, proto_nsip, tvb, 0, -1, ENC_NA); nsip_tree = proto_item_add_subtree(bi.ti, ett_nsip); proto_tree_add_item(nsip_tree, hf_nsip_pdu_type, tvb, 0, 1, ENC_NA); proto_item_append_text(bi.ti, ", PDU type: %s", val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown")); bi.nsip_tree = nsip_tree; } if (!nsip_is_recursive) { col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown PDU type")); } else { col_append_sep_fstr(pinfo->cinfo, COL_INFO, NSIP_SEP, "%s", val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown PDU type")); } decode_pdu(pdu_type, &bi); }
static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo, struct ssh_peer_data *peer_data, int offset, proto_tree *tree) { gint len; guint plen; len = tvb_reported_length_remaining(tvb, offset); col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len); if (tree) { gint encrypted_len = len; if (len > 4 && peer_data->length_is_plaintext) { plen = tvb_get_ntohl(tvb, offset) ; proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen); encrypted_len -= 4; } else if (len > 4) { proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA); encrypted_len -= 4; } if (peer_data->mac_length>0) encrypted_len -= peer_data->mac_length; proto_tree_add_item(tree, hf_ssh_encrypted_packet, tvb, offset+4, encrypted_len, ENC_NA); if (peer_data->mac_length>0) proto_tree_add_item(tree, hf_ssh_mac_string, tvb, offset+4+encrypted_len, peer_data->mac_length, ENC_NA); } offset+=len; return offset; }
void dissect_nvme_data_response(tvbuff_t *nvme_tvb, packet_info *pinfo, proto_tree *root_tree, struct nvme_q_ctx *q_ctx, struct nvme_cmd_ctx *cmd_ctx, guint len) { proto_tree *cmd_tree; proto_item *ti; const guint8 *str_opcode; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NVMe"); ti = proto_tree_add_item(root_tree, proto_nvme, nvme_tvb, 0, len, ENC_NA); cmd_tree = proto_item_add_subtree(ti, ett_data); if (q_ctx->qid) { //IOQ str_opcode = val_to_str(cmd_ctx->opcode, ioq_opc_tbl, "Unknown IOQ Opcode"); switch (cmd_ctx->opcode) { case NVME_IOQ_OPC_READ: case NVME_IOQ_OPC_WRITE: default: proto_tree_add_bytes_format_value(cmd_tree, hf_nvme_gen_data, nvme_tvb, 0, len, NULL, "%s", str_opcode); break; } } else { //AQ str_opcode = val_to_str(cmd_ctx->opcode, aq_opc_tbl, "Unknown AQ Opcode"); switch (cmd_ctx->opcode) { default: proto_tree_add_bytes_format_value(cmd_tree, hf_nvme_gen_data, nvme_tvb, 0, len, NULL, "%s", str_opcode); break; } } col_append_sep_fstr(pinfo->cinfo, COL_INFO, " | ", "NVMe %s: Data", str_opcode); }
/* The dissector itself */ static void dissect_chdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { // Here are all the variables proto_item *item; proto_item *stream_item; proto_tree *chdr_tree; proto_item *header_item; proto_tree *header_tree; proto_tree *stream_tree; proto_item *response_item; proto_tree *response_tree; proto_item *cmd_item; proto_tree *cmd_tree; gint len; gint flag_offset; guint8 *bytes; guint8 hdr_bits = 0; guint8 pkt_type = 0; gboolean flag_has_time = 0; gboolean flag_is_data = 0; gboolean flag_is_fc = 0; gboolean flag_is_cmd = 0; gboolean flag_is_resp = 0; gboolean flag_is_eob = 0; gboolean flag_is_error = 0; unsigned long long timestamp; gboolean is_network; gint endianness; gint id_pos_usb[4] = {7, 6, 5, 4}; gint id_pos_net[4] = {4, 5, 6, 7}; gint id_pos[4] = {7, 6, 5, 4}; if(pinfo->match_uint == CHDR_PORT){ is_network = TRUE; flag_offset = 0; endianness = ENC_BIG_ENDIAN; memcpy(id_pos, id_pos_net, 4 * sizeof(gint)); } else{ // Parsing a USB capture is_network = FALSE; flag_offset = 3; endianness = ENC_LITTLE_ENDIAN; memcpy(id_pos, id_pos_usb, 4 * sizeof(gint)); } len = tvb_reported_length(tvb); col_append_str(pinfo->cinfo, COL_PROTOCOL, "/CHDR"); /* This throws a warning: */ /*col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR", tvb_format_text_wsp(tvb, 0, len));*/ col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR"); if (tree){ int chdr_size = -1; if (len >= 4){ chdr_size = 8; bytes = tvb_get_string(wmem_packet_scope(), tvb, 0, 4); hdr_bits = (bytes[flag_offset] & 0xF0) >> 4; pkt_type = hdr_bits >> 2; flag_is_data = (pkt_type == 0); flag_is_fc = (pkt_type == 1); flag_is_cmd = (pkt_type == 2); flag_is_resp = (pkt_type == 3); flag_is_eob = flag_is_data && (hdr_bits & 0x1); flag_is_error = flag_is_resp && (hdr_bits & 0x1); flag_has_time = hdr_bits & 0x2; if (flag_has_time) chdr_size += 8; // 64-bit timestamp } /* Start with a top-level item to add everything else to */ item = proto_tree_add_item(tree, proto_chdr, tvb, 0, min(len, chdr_size), ENC_NA); if (len >= 4) { chdr_tree = proto_item_add_subtree(item, ett_chdr); /* Header info. First, a top-level header tree item: */ header_item = proto_tree_add_item(chdr_tree, hf_chdr_hdr, tvb, flag_offset, 1, endianness); header_tree = proto_item_add_subtree(header_item, ett_chdr_header); proto_item_append_text(header_item, ", Packet type: %s", val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES, "Unknown (0x%x)") ); /* Let us query hdr.type */ proto_tree_add_string( header_tree, hf_chdr_type, tvb, flag_offset, 1, val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES_SHORT, "invalid") ); /* And other flags */ proto_tree_add_boolean(header_tree, hf_chdr_has_time, tvb, flag_offset, 1, flag_has_time); if (flag_is_data) { proto_tree_add_boolean(header_tree, hf_chdr_eob, tvb, flag_offset, 1, flag_is_eob); } if (flag_is_resp) { proto_tree_add_boolean(header_tree, hf_chdr_error, tvb, flag_offset, 1, flag_is_error); } /* These lines add sequence, packet_size and stream ID */ proto_tree_add_item(chdr_tree, hf_chdr_sequence, tvb, (is_network ? 0:2), 2, endianness); proto_tree_add_item(chdr_tree, hf_chdr_packet_size, tvb, (is_network ? 2:0), 2, endianness); if (len >= 8){ /* stream id can be broken down to 4 sections. these are collapsed in a subtree */ stream_item = proto_tree_add_item(chdr_tree, hf_chdr_stream_id, tvb, 4, 4, endianness); stream_tree = proto_item_add_subtree(stream_item, ett_chdr_id); proto_tree_add_item(stream_tree, hf_chdr_src_dev, tvb, id_pos[0], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_src_ep, tvb, id_pos[1], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_dst_dev, tvb, id_pos[2], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_dst_ep, tvb, id_pos[3], 1, ENC_NA); /* Block ports (only add them if address points to a device) */ bytes = tvb_get_string(wmem_packet_scope(), tvb, 0, 8); if (bytes[id_pos[0]] != 0) { proto_tree_add_item(stream_tree, hf_chdr_src_blockport, tvb, id_pos[1], 1, ENC_NA); } if (bytes[id_pos[2]] != 0) { proto_tree_add_item(stream_tree, hf_chdr_dst_blockport, tvb, id_pos[3], 1, ENC_NA); } /* Append SID in sid_t hex format */ proto_item_append_text(stream_item, " (%02X:%02X>%02X:%02X)", bytes[id_pos[0]], bytes[id_pos[1]], bytes[id_pos[2]], bytes[id_pos[3]] ); /* if has_time flag is present interpret timestamp */ if ((flag_has_time) && (len >= 16)){ if (is_network) item = proto_tree_add_item(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, endianness); else{ bytes = (guint8*) tvb_get_string(wmem_packet_scope(), tvb, 8, sizeof(unsigned long long)); timestamp = get_timestamp(bytes, sizeof(unsigned long long)); proto_tree_add_uint64(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, timestamp); } } int remaining_bytes = (len - chdr_size); int show_raw_payload = (remaining_bytes > 0); if (flag_is_cmd && remaining_bytes == 8) { cmd_item = proto_tree_add_item(chdr_tree, hf_chdr_cmd, tvb, chdr_size, 8, endianness); cmd_tree = proto_item_add_subtree(cmd_item, ett_chdr_cmd); proto_tree_add_item(cmd_tree, hf_chdr_cmd_address, tvb, chdr_size, 4, endianness); proto_tree_add_item(cmd_tree, hf_chdr_cmd_value, tvb, chdr_size + 4, 4, endianness); } else if (flag_is_resp) { response_item = proto_tree_add_item(chdr_tree, hf_chdr_ext_response, tvb, chdr_size, 8, endianness); response_tree = proto_item_add_subtree(response_item, ett_chdr_response); proto_tree_add_item(response_tree, hf_chdr_ext_status_code, tvb, chdr_size, 4, endianness); /* This will show the 12-bits of sequence ID in the last 2 bytes */ proto_tree_add_item(response_tree, hf_chdr_ext_seq_num, tvb, (chdr_size + 4 + (is_network ? 2 : 0)), 2, endianness); } else if (show_raw_payload) { proto_tree_add_item(chdr_tree, hf_chdr_payload, tvb, chdr_size, -1, ENC_NA); } } } }
static int dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { proto_tree *json_tree = NULL; proto_item *ti = NULL; json_parser_data_t parser_data; tvbparse_t *tt; const char *data_name; int offset; /* JSON dissector can be called in a JSON native file or when transported * by another protocol. We set the column values only if they've not been * already set by someone else. */ wmem_list_frame_t *proto = wmem_list_frame_prev(wmem_list_tail(pinfo->layers)); if (proto) { const char *name = proto_get_protocol_filter_name(GPOINTER_TO_INT(wmem_list_frame_data(proto))); if (!strcmp(name, "frame")) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "JSON"); col_set_str(pinfo->cinfo, COL_INFO, "JavaScript Object Notation"); } } data_name = pinfo->match_string; if (! (data_name && data_name[0])) { /* * No information from "match_string" */ data_name = (char *)data; if (! (data_name && data_name[0])) { /* * No information from dissector data */ data_name = NULL; } } if (tree) { ti = proto_tree_add_item(tree, hfi_json, tvb, 0, -1, ENC_NA); json_tree = proto_item_add_subtree(ti, ett_json); if (data_name) proto_item_append_text(ti, ": %s", data_name); } offset = 0; parser_data.stack = wmem_stack_new(wmem_packet_scope()); wmem_stack_push(parser_data.stack, json_tree); tt = tvbparse_init(tvb, offset, -1, &parser_data, want_ignore); /* XXX, only one json in packet? */ while ((tvbparse_get(tt, want))) ; offset = tvbparse_curr_offset(tt); proto_item_set_len(ti, offset); /* if we have some unparsed data, pass to data-text-lines dissector (?) */ if (tvb_reported_length_remaining(tvb, offset) > 0) { tvbuff_t *next_tvb; next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector_with_data(text_lines_handle, next_tvb, pinfo, tree, data); } else if (data_name) { col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name); } return tvb_captured_length(tvb); }
/* Dissect a FEC header: * fec - ptr to the logical FEC packet representation to fill * hf - ptr to header fields array * ett - ptr to ett array * prefs - ptr to FEC prefs array * tvb - buffer * pinfo - packet info * tree - tree where to add FEC header subtree * offset - ptr to offset to use and update */ static int dissect_fec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *ti; proto_tree *fec_tree; guint offset = 0; fec_data_exchange_t *fec = (fec_data_exchange_t*)data; guint8 encoding_id = 0; fec_packet_data_t *packet_data = (fec_packet_data_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_rmt_fec, 0); if (fec != NULL) { encoding_id = fec->encoding_id; } /* Create the FEC subtree */ ti = proto_tree_add_item(tree, proto_rmt_fec, tvb, offset, -1, ENC_NA); fec_tree = proto_item_add_subtree(ti, ett_main); proto_tree_add_uint(fec_tree, hf_encoding_id, tvb, offset, 0, encoding_id); if (encoding_id >= 128 && (packet_data != NULL)) proto_tree_add_uint(fec_tree, hf_instance_id, tvb, offset, 0, packet_data->instance_id); switch (encoding_id) { case 0: case 1: case 130: proto_tree_add_item(fec_tree, hf_sbn, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(fec_tree, hf_esi, tvb, offset+2, 2, ENC_BIG_ENDIAN); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SBN: %u", tvb_get_ntohs(tvb, offset)); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ESI: 0x%X", tvb_get_ntohs(tvb, offset+2)); offset += 4; break; case 2: case 128: case 132: proto_tree_add_item(fec_tree, hf_sbn, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(fec_tree, hf_esi, tvb, offset+4, 4, ENC_BIG_ENDIAN); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SBN: %u", tvb_get_ntohl(tvb, offset)); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ESI: 0x%X", tvb_get_ntohl(tvb, offset+4)); offset += 8; break; case 3: case 4: proto_tree_add_item(fec_tree, hf_sbn_with_mask, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(fec_tree, hf_esi_with_mask, tvb, offset, 4, ENC_BIG_ENDIAN); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SBN: %u", tvb_get_ntohl(tvb, offset) >> 20); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ESI: 0x%X", tvb_get_ntohl(tvb, offset) & 0xfffff); offset += 4; break; case 6: proto_tree_add_item(fec_tree, hf_sbn, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(fec_tree, hf_esi, tvb, offset+1, 3, ENC_BIG_ENDIAN); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SBN: %u", tvb_get_guint8(tvb, offset)); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ESI: 0x%X", tvb_get_ntoh24(tvb, offset+1)); offset += 4; break; case 129: proto_tree_add_item(fec_tree, hf_sbn, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(fec_tree, hf_sbl, tvb, offset+4, 2, ENC_BIG_ENDIAN); proto_tree_add_item(fec_tree, hf_esi, tvb, offset+6, 2, ENC_BIG_ENDIAN); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SBN: %u", tvb_get_ntohl(tvb, offset)); col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ESI: 0x%X", tvb_get_ntohs(tvb, offset+6)); offset += 8; break; } return offset; }
static void dissect_rtmpt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *rtmpt_tree = NULL; proto_tree *rtmptroot_tree = NULL; proto_item *ti = NULL; gint offset = 0; struct tcpinfo* tcpinfo = pinfo->private_data; guint8 iCommand = -1; guint32 iLength = 1; guint16 iHeaderType = 4; guint16 iHeaderLength; guint8 iID; guint rtmp_index; conversation_t * current_conversation; rtmpt_conversation_data_t * conversation_data; rtmpt_packet_data_t * packet_data; rtmpt_chunk_data_t *current_chunk_data = NULL; rtmpt_chunk_data_t *initial_chunk_data = NULL; tvbuff_t* amf_tvb; current_conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if (NULL != current_conversation) { conversation_data = (rtmpt_conversation_data_t*)conversation_get_proto_data(current_conversation, proto_rtmpt); if (NULL == conversation_data) { conversation_data = se_alloc(sizeof(rtmpt_conversation_data_t)); memset((void*)conversation_data, 0, sizeof(rtmpt_conversation_data_t)); conversation_add_proto_data(current_conversation, proto_rtmpt, conversation_data); conversation_data->current_chunks = g_hash_table_new(g_direct_hash, g_direct_equal); conversation_data->previous_frame_number = -1; conversation_data->current_chunk_size = RTMPT_DEFAULT_CHUNK_SIZE; conversation_data->is_rtmpe = 0; } packet_data = p_get_proto_data(pinfo->fd, proto_rtmpt); if (NULL == packet_data) { packet_data = se_alloc(sizeof(rtmpt_packet_data_t)); memset((void*)packet_data, 0, sizeof(rtmpt_packet_data_t)); p_add_proto_data(pinfo->fd, proto_rtmpt, packet_data); packet_data->initial_chunks = g_hash_table_new(g_direct_hash, g_direct_equal); packet_data->initial_chunk_size = conversation_data->current_chunk_size; } if (conversation_data->is_rtmpe == 1) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMPE"); return; } else { col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMP"); } if (conversation_data->previous_frame_number != (guint) pinfo->fd->num) { conversation_data->current_chunk_size = packet_data->initial_chunk_size; } col_set_writable(pinfo->cinfo, TRUE); col_clear(pinfo->cinfo, COL_INFO); conversation_data->previous_frame_number = pinfo->fd->num; if (tvb_length_remaining(tvb, offset) >= 1) { if (tcpinfo->lastackseq == RTMPT_HANDSHAKE_OFFSET_1 && tcpinfo->seq == RTMPT_HANDSHAKE_OFFSET_1) { iCommand = RTMPT_TYPE_HANDSHAKE_1; } else if (tcpinfo->lastackseq == RTMPT_HANDSHAKE_OFFSET_2 && tcpinfo->seq == RTMPT_HANDSHAKE_OFFSET_1) iCommand = RTMPT_TYPE_HANDSHAKE_2; else if (tcpinfo->seq == RTMPT_HANDSHAKE_OFFSET_2 && tvb_length(tvb) == RTMPT_HANDSHAKE_LENGTH_3) iCommand = RTMPT_TYPE_HANDSHAKE_3; else { iID = tvb_get_guint8(tvb, offset + 0); iHeaderType = iID >> 6; rtmp_index = iID & 0x3F; current_chunk_data = g_hash_table_lookup(conversation_data->current_chunks, GUINT_TO_POINTER(rtmp_index)); initial_chunk_data = g_hash_table_lookup(packet_data->initial_chunks, GUINT_TO_POINTER(rtmp_index)); if (iHeaderType <= 2) iLength = tvb_get_ntoh24(tvb, offset + 4); if (iHeaderType <= 1) { iCommand = tvb_get_guint8(tvb, offset + 7); if (NULL == current_chunk_data) { current_chunk_data = se_alloc(sizeof(rtmpt_chunk_data_t)); memset((void*)current_chunk_data, 0, sizeof(rtmpt_chunk_data_t)); g_hash_table_insert(conversation_data->current_chunks, GUINT_TO_POINTER(rtmp_index), current_chunk_data); } current_chunk_data->data_type = iCommand; current_chunk_data->last_length = iLength; current_chunk_data->frame_modified = pinfo->fd->num; } else { /* must get the command type from the previous entries in the hash table */ /* try to use the current_chunk_data unless it is from a different frame */ if (NULL != current_chunk_data && NULL != initial_chunk_data) { /* we have precedent data (we should)*/ if (current_chunk_data->frame_modified != pinfo->fd->num) { iCommand = initial_chunk_data->data_type; iLength = initial_chunk_data->length_remaining; current_chunk_data->frame_modified = pinfo->fd->num; current_chunk_data->data_type = iCommand; current_chunk_data->last_length = iLength; current_chunk_data->dechunk_buffer = initial_chunk_data->dechunk_buffer; } else { iCommand = current_chunk_data->data_type; iLength = current_chunk_data->length_remaining; } if (iLength > conversation_data->current_chunk_size) { iLength = conversation_data->current_chunk_size; } } } } iHeaderLength = rtmpt_header_length_from_type(iHeaderType); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_sep_fstr(pinfo->cinfo, COL_INFO, " | ", "%s", val_to_str(iCommand, rtmpt_opcode_vals, "Unknown (0x%01x)")); col_set_fence(pinfo->cinfo, COL_INFO); } if (tree) { ti = proto_tree_add_item(tree, proto_rtmpt, tvb, offset, -1, FALSE); proto_item_append_text(ti, " (%s)", val_to_str(iCommand, rtmpt_opcode_vals, "Unknown (0x%01x)")); rtmptroot_tree = proto_item_add_subtree(ti, ett_rtmpt); ti = proto_tree_add_text(rtmptroot_tree, tvb, offset, iHeaderLength, RTMPT_TEXT_RTMP_HEADER); proto_item_append_text(ti, " (%s)", val_to_str(iCommand, rtmpt_opcode_vals, "Unknown (0x%01x)")); rtmpt_tree = proto_item_add_subtree(ti, ett_rtmpt_header); if (iHeaderType <= 3) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_objid, tvb, offset + 0, 1, FALSE); if (iHeaderType <= 2) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_timestamp, tvb, offset + 1, 3, FALSE); if (iHeaderType <= 1) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_body_size, tvb, offset + 4, 3, FALSE); if (iHeaderType <= 1) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_function, tvb, offset + 7, 1, FALSE); if (iHeaderType <= 0) proto_tree_add_item(rtmpt_tree, hf_rtmpt_header_source, tvb, offset + 8, 4, TRUE); if (iCommand == RTMPT_TYPE_HANDSHAKE_1) { proto_tree_add_item(rtmpt_tree, hf_rtmpt_handshake_data, tvb, 1, 1536, FALSE); } else if (iCommand == RTMPT_TYPE_HANDSHAKE_2) { proto_tree_add_item(rtmpt_tree, hf_rtmpt_handshake_data, tvb, 1, 1536, FALSE); proto_tree_add_item(rtmpt_tree, hf_rtmpt_handshake_data, tvb, 1537, 1536, FALSE); } else if (iCommand == RTMPT_TYPE_HANDSHAKE_3) { proto_tree_add_item(rtmpt_tree, hf_rtmpt_handshake_data, tvb, 0, -1, FALSE); } else if (iCommand == RTMPT_TYPE_CHUNK_SIZE) { conversation_data->current_chunk_size = tvb_get_ntohl (tvb, offset + iHeaderLength); } offset = iHeaderLength; if (tvb_length_remaining(tvb, offset)) { ti = proto_tree_add_text(rtmptroot_tree, tvb, offset, -1, RTMPT_TEXT_RTMP_BODY); } if (iCommand == RTMPT_TYPE_INVOKE || iCommand == RTMPT_TYPE_NOTIFY) { guint iChunkSize = tvb_length_remaining(tvb, iHeaderLength); /* we have data which will be AMF */ /* we should add it to a new tvb */ if (NULL != current_chunk_data) { if (NULL == current_chunk_data->dechunk_buffer) { /* we have to create a new tvbuffer */ current_chunk_data->dechunk_buffer = tvb_new_composite(); } if (!(current_chunk_data->dechunk_buffer->initialized)) { /* add the existing data to the new buffer */ tvb_composite_append(current_chunk_data->dechunk_buffer, tvb_new_real_data(tvb_memdup(tvb, iHeaderLength, iChunkSize), iChunkSize, iChunkSize)); if (current_chunk_data->length_remaining <= 0) { guint amf_length; guint8* amf_data; tvb_composite_finalize(current_chunk_data->dechunk_buffer); amf_length = tvb_length(current_chunk_data->dechunk_buffer); if (amf_length == 0) { return; } amf_data = tvb_memdup(current_chunk_data->dechunk_buffer, 0, amf_length); amf_tvb = tvb_new_real_data(amf_data, tvb_length_remaining(current_chunk_data->dechunk_buffer, 0), tvb_length_remaining(current_chunk_data->dechunk_buffer, 0)); add_new_data_source(pinfo, amf_tvb, "Dechunked AMF data"); ti = proto_tree_add_item(tree, proto_rtmpt, amf_tvb, 0, -1, FALSE); rtmpt_tree = proto_item_add_subtree(ti, ett_rtmpt_body); proto_tree_set_appendix(rtmpt_tree, amf_tvb, 0, tvb_length_remaining(amf_tvb, 0)); proto_item_append_text(rtmpt_tree, " (%s)", "AMF Data"); dissect_rtmpt_amf(amf_tvb, rtmpt_tree); current_chunk_data->dechunk_buffer = NULL; } } } } } } }
static int dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { proto_tree *subtree; proto_item *ti; gint offset = 0, next_offset; gint len; http_message_info_t *message_info; const char *data_name; int length = tvb_captured_length(tvb); /* Check if this is actually xml * If there is less than 38 characters this is not XML * <?xml version="1.0" encoding="UTF-8"?> */ if(length > 38){ if (tvb_strncaseeql(tvb, 0, "<?xml", 5) == 0){ call_dissector(xml_handle, tvb, pinfo, tree); return length; } } data_name = pinfo->match_string; if (! (data_name && data_name[0])) { /* * No information from "match_string" */ message_info = (http_message_info_t *)data; if (message_info == NULL) { /* * No information from dissector data */ data_name = NULL; } else { data_name = message_info->media_str; if (! (data_name && data_name[0])) { /* * No information from dissector data */ data_name = NULL; } } } if (data_name) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name); if (tree) { guint lines_read = 0; ti = proto_tree_add_item(tree, proto_text_lines, tvb, 0, -1, ENC_NA); if (data_name) proto_item_append_text(ti, ": %s", data_name); subtree = proto_item_add_subtree(ti, ett_text_lines); /* Read the media line by line */ while (tvb_offset_exists(tvb, offset)) { /* * XXX - we need to be passed the parameters * of the content type via data parameter, * so that we know the character set. We'd * have to handle that character set, which * might be a multibyte character set such * as "iso-10646-ucs-2", or might require other * special processing. */ len = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); if (len == -1) break; /* We use next_offset - offset instead of len in the * call to proto_tree_add_format_text() so it will include the * line terminator(s) (\r and/or \n) in the display. */ proto_tree_add_format_text(subtree, tvb, offset, next_offset - offset); lines_read++; offset = next_offset; } proto_item_append_text(subtree, " (%u lines)", lines_read); } return length; }
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; }
static int dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { proto_tree *subtree; proto_item *ti; gint offset = 0, next_offset; gint len; const char *data_name; guint8 word[6]; int length = tvb_length(tvb); /* Check if this is actually xml * If there is less than 38 characters this is not XML * <?xml version="1.0" encoding="UTF-8"?> */ if(length > 38){ tvb_get_nstringz0(tvb, 0, sizeof(word),word); if (g_ascii_strncasecmp(word, "<?xml", 5) == 0){ call_dissector(xml_handle, tvb, pinfo, tree); return tvb_length(tvb); } } data_name = pinfo->match_string; if (! (data_name && data_name[0])) { /* * No information from "match_string" */ data_name = (char *)data; if (! (data_name && data_name[0])) { /* * No information from dissector data */ data_name = (char *)(pinfo->private_data); if (! (data_name && data_name[0])) { /* * No information from "private_data" */ data_name = NULL; } } } if (data_name) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name); if (tree) { ti = proto_tree_add_item(tree, proto_text_lines, tvb, 0, -1, ENC_NA); if (data_name) proto_item_append_text(ti, ": %s", data_name); subtree = proto_item_add_subtree(ti, ett_text_lines); /* Read the media line by line */ while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * XXX - we need to be passed the parameters * of the content type via "pinfo->private_data", * so that we know the character set. We'd * have to handle that character set, which * might be a multibyte character set such * as "iso-10646-ucs-2", or might require other * special processing. */ len = tvb_find_line_end(tvb, offset, tvb_ensure_length_remaining(tvb, offset), &next_offset, FALSE); if (len == -1) break; /* We use next_offset - offset instead of len in the * call to tvb_format_text() so it will include the * line terminator(s) (\r and/or \n) in the display. */ proto_tree_add_text(subtree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; } } return tvb_length(tvb); }
static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo, struct ssh_flow_data *global_data, int offset, proto_tree *tree, int is_response, gboolean *need_desegmentation) { guint plen, padding_length, len; guint8 msg_code; guint remain_length; proto_item *ssh1_tree; struct ssh_peer_data *peer_data = &global_data->peer_data[is_response]; ssh1_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh1, NULL, "SSH Version 1"); /* * We use "tvb_ensure_length_remaining()" to make sure there * actually *is* data remaining. * * This means we're guaranteed that "remain_length" is positive. */ remain_length = tvb_ensure_length_remaining(tvb, offset); /* * Can we do reassembly? */ if (ssh_desegment && pinfo->can_desegment) { /* * Yes - would an SSH header starting at this offset be split * across segment boundaries? */ if (remain_length < 4) { /* * Yes. Tell the TCP dissector where the data for * this message starts in the data it handed us and * that we need "some more data." Don't tell it * exactly how many bytes we need because if/when we * ask for even more (after the header) that will * break reassembly. */ pinfo->desegment_offset = offset; pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; *need_desegmentation = TRUE; return offset; } } plen = tvb_get_ntohl(tvb, offset) ; padding_length = 8 - plen%8; if (ssh_desegment && pinfo->can_desegment) { if (plen+4+padding_length > remain_length) { pinfo->desegment_offset = offset; pinfo->desegment_len = plen+padding_length - remain_length; *need_desegmentation = TRUE; return offset; } } if (plen >= 0xffff) { if (ssh1_tree && plen > 0) { proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb, offset, 4, plen, "Overly large length %x", plen); } plen = remain_length-4-padding_length; } else { if (ssh1_tree && plen > 0) { proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb, offset, 4, plen); } } offset+=4; /* padding length */ if (tree) { proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb, offset, padding_length, padding_length); } offset += padding_length; /* msg_code */ if ((peer_data->frame_key_start == 0) || ((peer_data->frame_key_start >= pinfo->fd->num) && (pinfo->fd->num <= peer_data->frame_key_end))) { msg_code = tvb_get_guint8(tvb, offset); proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_NA); col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)")); offset += 1; len = plen -1; if (!pinfo->fd->flags.visited) { if (peer_data->frame_key_start == 0) peer_data->frame_key_start = pinfo->fd->num; peer_data->frame_key_end = pinfo->fd->num; } } else { len = plen; col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len); } /* payload */ if (ssh1_tree) { proto_tree_add_item(ssh1_tree, hf_ssh_payload, tvb, offset, len, ENC_NA); } offset+=len; return offset; }
static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo, struct ssh_flow_data *global_data, int offset, proto_tree *tree, int is_response, guint * version, gboolean *need_desegmentation) { guint remain_length; gint linelen, protolen; /* * If the first packet do not contain the banner, * it is dump in the middle of a flow or not a ssh at all */ if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) { offset = ssh_dissect_encrypted_packet(tvb, pinfo, &global_data->peer_data[is_response], offset, tree); return offset; } if (!is_response) { if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) { *(version) = SSH_VERSION_2; } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) { *(version) = SSH_VERSION_2; } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) { *(version) = SSH_VERSION_1; } } /* * We use "tvb_ensure_length_remaining()" to make sure there * actually *is* data remaining. * * This means we're guaranteed that "remain_length" is positive. */ remain_length = tvb_ensure_length_remaining(tvb, offset); /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); */ linelen = tvb_find_guint8(tvb, offset, -1, '\n'); if (ssh_desegment && pinfo->can_desegment) { if (linelen == -1 || remain_length < (guint)linelen-offset) { pinfo->desegment_offset = offset; pinfo->desegment_len = linelen-remain_length; *need_desegmentation = TRUE; return offset; } } if (linelen == -1) { /* XXX - reassemble across segment boundaries? */ linelen = remain_length; protolen = linelen; } else { linelen = linelen - offset + 1; if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r') protolen = linelen - 2; else protolen = linelen - 1; } col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)", tvb_format_text(tvb, offset, protolen)); proto_tree_add_item(tree, hf_ssh_protocol, tvb, offset, linelen, ENC_ASCII|ENC_NA); offset+=linelen; return offset; }
static void dissect_fefd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *fefd_tree = NULL; int offset = 0; guint16 type; guint16 length; proto_item *tlvi; proto_tree *tlv_tree; int real_length; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FEFD"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { proto_item *flags_ti; proto_tree *flags_tree; ti = proto_tree_add_item(tree, proto_fefd, tvb, offset, -1, FALSE); fefd_tree = proto_item_add_subtree(ti, ett_fefd); /* FEFD header */ proto_tree_add_item(fefd_tree, hf_fefd_version, tvb, offset, 1, FALSE); proto_tree_add_item(fefd_tree, hf_fefd_opcode, tvb, offset, 1, FALSE); offset += 1; flags_ti = proto_tree_add_item(fefd_tree, hf_fefd_flags, tvb, offset, 1, FALSE); flags_tree = proto_item_add_subtree(ti, ett_fefd_flags); proto_tree_add_item(flags_tree, hf_fefd_flags_rt, tvb, offset, 1, FALSE); proto_tree_add_item(flags_tree, hf_fefd_flags_rsy, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(fefd_tree, hf_fefd_checksum, tvb, offset, 2, FALSE); offset += 2; } else { offset += 4; /* The version/opcode/flags/checksum fields from above */ } while (tvb_reported_length_remaining(tvb, offset) != 0) { type = tvb_get_ntohs(tvb, offset + TLV_TYPE); length = tvb_get_ntohs(tvb, offset + TLV_LENGTH); if (length < 4) { if (tree) { tlvi = proto_tree_add_text(fefd_tree, tvb, offset, 4, "TLV with invalid length %u (< 4)", length); tlv_tree = proto_item_add_subtree(tlvi, ett_fefd_tlv); proto_tree_add_uint(tlv_tree, hf_fefd_tlvtype, tvb, offset + TLV_TYPE, 2, type); proto_tree_add_uint(tlv_tree, hf_fefd_tlvlength, tvb, offset + TLV_LENGTH, 2, length); } offset += 4; break; } switch (type) { case TYPE_DEVICE_ID: /* Device ID */ if (check_col(pinfo->cinfo, COL_INFO)) col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Device ID: %s", tvb_format_stringzpad(tvb, offset + 4, length - 4)); if (tree) { tlvi = proto_tree_add_text(fefd_tree, tvb, offset, length, "Device ID: %s", tvb_format_stringzpad(tvb, offset + 4, length - 4)); tlv_tree = proto_item_add_subtree(tlvi, ett_fefd_tlv); proto_tree_add_uint(tlv_tree, hf_fefd_tlvtype, tvb, offset + TLV_TYPE, 2, type); proto_tree_add_uint(tlv_tree, hf_fefd_tlvlength, tvb, offset + TLV_LENGTH, 2, length); proto_tree_add_text(tlv_tree, tvb, offset + 4, length - 4, "Device ID: %s", tvb_format_stringzpad(tvb, offset + 4, length - 4)); } offset += length; break; case TYPE_PORT_ID: real_length = length; if (tvb_get_guint8(tvb, offset + real_length) != 0x00) { /* The length in the TLV doesn't appear to be the length of the TLV, as the byte just past it isn't the first byte of a 2-byte big-endian small integer; make the length of the TLV the length in the TLV, plus 4 bytes for the TLV type and length, minus 1 because that's what makes one capture work. */ real_length = length + 3; } if (check_col(pinfo->cinfo, COL_INFO)) col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Port ID: %s", tvb_format_stringzpad(tvb, offset + 4, real_length - 4)); if (tree) { tlvi = proto_tree_add_text(fefd_tree, tvb, offset, real_length, "Port ID: %s", tvb_format_text(tvb, offset + 4, real_length - 4)); tlv_tree = proto_item_add_subtree(tlvi, ett_fefd_tlv); proto_tree_add_uint(tlv_tree, hf_fefd_tlvtype, tvb, offset + TLV_TYPE, 2, type); proto_tree_add_uint(tlv_tree, hf_fefd_tlvlength, tvb, offset + TLV_LENGTH, 2, length); proto_tree_add_text(tlv_tree, tvb, offset + 4, real_length - 4, "Sent through Interface: %s", tvb_format_text(tvb, offset + 4, real_length - 4)); } offset += real_length; break; case TYPE_ECHO: case TYPE_MESSAGE_INTERVAL: case TYPE_TIMEOUT_INTERVAL: case TYPE_DEVICE_NAME: case TYPE_SEQUENCE_NUMBER: default: tlvi = proto_tree_add_text(fefd_tree, tvb, offset, length, "Type: %s, length: %u", val_to_str(type, type_vals, "Unknown (0x%04x)"), length); tlv_tree = proto_item_add_subtree(tlvi, ett_fefd_tlv); proto_tree_add_uint(tlv_tree, hf_fefd_tlvtype, tvb, offset + TLV_TYPE, 2, type); proto_tree_add_uint(tlv_tree, hf_fefd_tlvlength, tvb, offset + TLV_LENGTH, 2, length); if (length > 4) { proto_tree_add_text(tlv_tree, tvb, offset + 4, length - 4, "Data"); } else { return; } offset += length; } } call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, fefd_tree); }
static void dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *subtree; proto_item *ti; gint offset = 0, next_offset; gint len; const char *data_name; data_name = pinfo->match_string; if (! (data_name && data_name[0])) { /* * No information from "match_string" */ data_name = (char *)(pinfo->private_data); if (! (data_name && data_name[0])) { /* * No information from "private_data" */ data_name = NULL; } } if (data_name && check_col(pinfo->cinfo, COL_INFO)) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name); if (tree) { ti = proto_tree_add_item(tree, proto_text_lines, tvb, 0, -1, FALSE); if (data_name) proto_item_append_text(ti, ": %s", data_name); subtree = proto_item_add_subtree(ti, ett_text_lines); /* Read the media line by line */ while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * XXX - we need to be passed the parameters * of the content type via "pinfo->private_data", * so that we know the character set. We'd * have to handle that character set, which * might be a multibyte character set such * as "iso-10646-ucs-2", or might require other * special processing. */ len = tvb_find_line_end(tvb, offset, tvb_ensure_length_remaining(tvb, offset), &next_offset, FALSE); if (len == -1) break; /* We use next_offset - offset instead of len in the * call to tvb_format_text() so it will include the * line terminator(s) (\r and/or \n) in the display. */ proto_tree_add_text(subtree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); offset = next_offset; } } }
static void dissect_http2_frame_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) { proto_item *ti; proto_tree *http2_tree; guint32 offset = 0; http2_frame_header frame; /* tvb_memeql makes certain there are enough bytes in the buffer. * returns -1 if there are not enough bytes or if there is not a * match. Returns 0 on a match */ if ( tvb_memeql( tvb, offset, kMagicHello, MAGIC_FRAME_LENGTH ) == 0 ) { col_append_sep_str( pinfo->cinfo, COL_INFO, ", ", "Magic" ); ti = proto_tree_add_item(tree, proto_http2, tvb, offset, MAGIC_FRAME_LENGTH, ENC_NA); proto_item_append_text( ti, ", Magic" ); http2_tree = proto_item_add_subtree(ti, ett_http2); proto_tree_add_item(http2_tree, hf_http2_magic, tvb, offset, MAGIC_FRAME_LENGTH, ENC_BIG_ENDIAN); return; } frame.length = tvb_get_ntohs( tvb, offset + 0 ); frame.type = tvb_get_guint8( tvb, offset + 2 ); frame.flags = tvb_get_guint8( tvb, offset + 3 ); frame.streamid = tvb_get_ntohl( tvb, offset + 4 ); col_append_sep_fstr( pinfo->cinfo, COL_INFO, ", ", "%s", val_to_str( frame.type, frametypenames, "Unknown (0x%02X)" ) ); /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_http2, tvb, offset, FRAME_HEADER_LENGTH + frame.length, ENC_NA); proto_item_append_text( ti, ", %s", val_to_str( frame.type, frametypenames, "Unknown (0x%02X)" ) ); proto_item_append_text( ti, ", Length: %d, Flags: %d, streamid: %d", frame.length, frame.flags, frame.streamid ); http2_tree = proto_item_add_subtree(ti, ett_http2); /* Add an item to the subtree, see section 1.6 of README.developer for more * information. */ proto_tree_add_item(http2_tree, hf_http2_length, tvb, offset + 0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_type, tvb, offset + 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_flags, tvb, offset + 3, 1, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_streamid, tvb, offset + 4, 4, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_payload, tvb, offset + 8, frame.length, ENC_BIG_ENDIAN); offset += frame.length + FRAME_HEADER_LENGTH; return; }
static int dissect_dlm_controld(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, const gchar* col_str) { guint length; int offset; proto_tree *dlm_controld_tree, *tree, *version_tree; proto_item *item, *version_item; guint32 type; length = tvb_length(tvb); if ( length < ( 2 * 3 ) + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 8) return 0; type = tvb_get_letohs(tvb, ( 2 * 3 )); if (check_col(pinfo->cinfo, COL_INFO)) col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s :%s)", col_str, val_to_str(type, vals_header_type, "UNKNOWN-TYPE")); if (!parent_tree) goto out; offset = 0; item = proto_tree_add_item(parent_tree, proto_dlm_controld, tvb, offset, -1, TRUE); dlm_controld_tree = proto_item_add_subtree(item, ett_dlm_controld); offset += 0; item = proto_tree_add_item(dlm_controld_tree, hf_dlm_controld_header, tvb, offset, -1, TRUE); tree = proto_item_add_subtree(item, ett_dlm_controld_header); offset += 0; version_item = proto_tree_add_item(tree, hf_dlm_controld_header_version, tvb, offset, -1, TRUE); version_tree = proto_item_add_subtree(version_item, ett_dlm_controld_header_version); offset += 0; proto_tree_add_item(version_tree, hf_dlm_controld_header_version_major, tvb, offset, 2, TRUE); offset += 2; proto_tree_add_item(version_tree, hf_dlm_controld_header_version_minor, tvb, offset, 2, TRUE); offset += 2; proto_tree_add_item(version_tree, hf_dlm_controld_header_version_patch, tvb, offset, 2, TRUE); offset += 2; type = tvb_get_letohs(tvb, offset); proto_tree_add_item(tree, hf_dlm_controld_header_type, tvb, offset, 2, TRUE); offset += 2; proto_tree_add_item(tree, hf_dlm_controld_header_nodeid, tvb, offset, 4, TRUE); offset += 4; proto_tree_add_item(tree, hf_dlm_controld_header_to_nodeid, tvb, offset, 4, TRUE); offset += 4; proto_tree_add_item(tree, hf_dlm_controld_header_global_id, tvb, offset, 4, TRUE); offset += 4; proto_tree_add_bitmask(tree, tvb, offset, hf_dlm_controld_header_flags, ett_dlm_controld_header_flags, header_flags_fields, TRUE); offset += 4; switch (type) { default: proto_tree_add_item(tree, hf_dlm_controld_header_msgdata, tvb, offset, 4, TRUE); break; } offset += 4; proto_tree_add_item(tree, hf_dlm_controld_header_pad1, tvb, offset, 4, TRUE); offset += 4; proto_tree_add_item(tree, hf_dlm_controld_header_pad2, tvb, offset, 8, TRUE); offset += 8; switch (type) { case DLM_MSG_PROTOCOL: offset += dissect_dlm_controld_protocol(tvb, pinfo, dlm_controld_tree, offset, length); break; case DLM_MSG_START: case DLM_MSG_PLOCKS_STORED: offset += dissect_dlm_controld_start_or_plocks_stored(tvb, pinfo, dlm_controld_tree, offset, length); break; default: break; } out: return offset; }
/* The dissector itself */ static void dissect_chdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { // Here are all the variables proto_item *item; proto_item *stream_item; proto_tree *chdr_tree; proto_tree *stream_tree; gint len; gint flag_offset; guint8 *bytes; gboolean flag_has_time; guint64 timestamp; gboolean is_network; gint endianness; gint id_pos_usb[4] = {7, 6, 5, 4}; gint id_pos_net[4] = {4, 5, 6, 7}; gint id_pos[4] = {7, 6, 5, 4}; if(pinfo->match_uint == CHDR_PORT) { is_network = TRUE; flag_offset = 0; endianness = ENC_BIG_ENDIAN; memcpy(id_pos, id_pos_net, 4 * sizeof(gint)); } else { is_network = FALSE; flag_offset = 3; endianness = ENC_LITTLE_ENDIAN; memcpy(id_pos, id_pos_usb, 4 * sizeof(gint)); } len = tvb_reported_length(tvb); col_append_str(pinfo->cinfo, COL_PROTOCOL, "/CHDR"); col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR", tvb_format_text_wsp(tvb, 0, len)); if (tree) { /* Start with a top-level item to add everything else to */ item = proto_tree_add_item(tree, proto_chdr, tvb, 0, 16, ENC_NA); chdr_tree = proto_item_add_subtree(item, ett_chdr); bytes = tvb_get_string(tvb, 0, 4); flag_has_time = bytes[flag_offset] & 0x20; /* These lines add flag info to tree */ proto_tree_add_item(chdr_tree, hf_chdr_is_extension, tvb, flag_offset, 1, ENC_NA); proto_tree_add_item(chdr_tree, hf_chdr_reserved, tvb, flag_offset, 1, ENC_NA); proto_tree_add_item(chdr_tree, hf_chdr_has_time, tvb, flag_offset, 1, ENC_NA); proto_tree_add_item(chdr_tree, hf_chdr_eob, tvb, flag_offset, 1, ENC_NA); /* These lines add sequence, packet_size and stream ID */ proto_tree_add_item(chdr_tree, hf_chdr_sequence, tvb, is_network ? 0:2, 2, endianness); proto_tree_add_item(chdr_tree, hf_chdr_packet_size, tvb, is_network ? 2:0, 2, endianness); /* stream id can be broken down to 4 sections. these are collapsed in a subtree */ stream_item = proto_tree_add_item(chdr_tree, hf_chdr_stream_id, tvb, 4, 4, endianness); stream_tree = proto_item_add_subtree(stream_item, ett_chdr_id); proto_tree_add_item(stream_tree, hf_chdr_src_dev, tvb, id_pos[0], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_src_ep, tvb, id_pos[1], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_dst_dev, tvb, id_pos[2], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_dst_ep, tvb, id_pos[3], 1, ENC_NA); /* if has_time flag is present interpret timestamp */ if(flag_has_time) { item = proto_tree_add_item(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, endianness); if(!is_network) { bytes = (guint8*) tvb_get_string(tvb, 8, 8); timestamp = get_timestamp(bytes, 8); } } } }
static void dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *json_tree = NULL; proto_item *ti = NULL; json_parser_data_t parser_data; tvbparse_t *tt; const char *data_name; int offset; data_name = pinfo->match_string; if (!(data_name && data_name[0])) { /* * No information from "match_string" */ data_name = (char *)(pinfo->private_data); if (!(data_name && data_name[0])) { /* * No information from "private_data" */ data_name = NULL; } } if (tree) { ti = proto_tree_add_item(tree, proto_json, tvb, 0, -1, ENC_NA); json_tree = proto_item_add_subtree(ti, ett_json); if (data_name) proto_item_append_text(ti, ": %s", data_name); } offset = 0; parser_data.stack = ep_stack_new(); ep_stack_push(parser_data.stack, json_tree); tt = tvbparse_init(tvb, offset, -1, &parser_data, want_ignore); /* XXX, only one json in packet? */ while ((tvbparse_get(tt, want))) ; offset = tvbparse_curr_offset(tt); proto_item_set_len(ti, offset); /* if we have some unparsed data, pass to data-text-lines dissector (?) */ if (tvb_length_remaining(tvb, offset) > 0) { int datalen, reported_datalen; tvbuff_t *next_tvb; datalen = tvb_length_remaining(tvb, offset); reported_datalen = tvb_reported_length_remaining(tvb, offset); next_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen); call_dissector(text_lines_handle, next_tvb, pinfo, tree); } else if (data_name) { col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name); } }