static void dissect_v8_user_data_message(tvbuff_t *message_data_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree) { proto_item *m2pa_li_item; proto_tree *m2pa_li_tree; tvbuff_t *payload_tvb; if (tvb_length(message_data_tvb) > 0) { if (m2pa_tree) { m2pa_li_item = proto_tree_add_text(m2pa_tree, message_data_tvb, LI_OFFSET, LI_LENGTH, "Length Indicator"); m2pa_li_tree = proto_item_add_subtree(m2pa_li_item, ett_m2pa_li); proto_tree_add_item(m2pa_li_tree, hf_v8_li_prio, message_data_tvb, LI_OFFSET, LI_LENGTH, ENC_BIG_ENDIAN); proto_tree_add_item(m2pa_li_tree, hf_v8_li_spare, message_data_tvb, LI_OFFSET, LI_LENGTH, ENC_BIG_ENDIAN); /* Re-adjust length of M2PA item since it will be dissected as MTP3 */ proto_item_set_len(m2pa_item, V8_HEADER_LENGTH + LI_LENGTH); } payload_tvb = tvb_new_subset_remaining(message_data_tvb, MTP3_OFFSET); call_dissector(mtp3_handle, payload_tvb, pinfo, tree); } }
static void dissect_v12_user_data_message(tvbuff_t *message_data_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree) { proto_item *m2pa_li_item; proto_tree *m2pa_li_tree; tvbuff_t *payload_tvb; if (tvb_length(message_data_tvb) > 0) { if (m2pa_tree) { m2pa_li_item = proto_tree_add_text(m2pa_tree, message_data_tvb, PRI_OFFSET, PRI_LENGTH, "Priority"); m2pa_li_tree = proto_item_add_subtree(m2pa_li_item, ett_m2pa_li); proto_tree_add_item(m2pa_li_tree, hf_pri_prio, message_data_tvb, PRI_OFFSET, PRI_LENGTH, NETWORK_BYTE_ORDER); proto_tree_add_item(m2pa_li_tree, hf_pri_spare, message_data_tvb, PRI_OFFSET, PRI_LENGTH, NETWORK_BYTE_ORDER); /* Re-adjust length of M2PA item since it will be dissected as MTP3 */ proto_item_set_len(m2pa_item, V12_HEADER_LENGTH + PRI_LENGTH); } payload_tvb = tvb_new_subset_remaining(message_data_tvb, MTP3_OFFSET); call_dissector(mtp3_handle, payload_tvb, pinfo, tree); } }
static int dissect_rx_challenge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber) { proto_tree *tree; proto_item *item; guint32 version; int old_offset=offset; col_add_fstr(pinfo->cinfo, COL_INFO, "CHALLENGE " "Seq: %lu " "Call: %lu " "Source Port: %s " "Destination Port: %s ", (unsigned long)seq, (unsigned long)callnumber, udp_port_to_display(wmem_packet_scope(), pinfo->srcport), udp_port_to_display(wmem_packet_scope(), pinfo->destport) ); item = proto_tree_add_item(parent_tree, hf_rx_challenge, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_rx_challenge); version = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(tree, hf_rx_version, tvb, offset, 4, version); offset += 4; if (version==2) { proto_tree_add_item(tree, hf_rx_nonce, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_rx_min_level, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } proto_item_set_len(item, offset-old_offset); return offset; }
static void dissect_dvb_tot(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint offset = 0; guint descriptor_len; proto_item *ti; proto_tree *dvb_tot_tree; nstime_t utc_time; col_set_str(pinfo->cinfo, COL_INFO, "Time Offset Table (TOT)"); ti = proto_tree_add_item(tree, proto_dvb_tot, tvb, offset, -1, ENC_NA); dvb_tot_tree = proto_item_add_subtree(ti, ett_dvb_tot); offset += packet_mpeg_sect_header(tvb, offset, dvb_tot_tree, NULL, NULL); if (packet_mpeg_sect_mjd_to_utc_time(tvb, offset, &utc_time) < 0) { proto_tree_add_text(dvb_tot_tree, tvb, offset, 5, "UTC Time : Unparseable time"); } else { proto_tree_add_time_format(dvb_tot_tree, hf_dvb_tot_utc_time, tvb, offset, 5, &utc_time, "UTC Time : %s UTC", abs_time_to_str(&utc_time, ABSOLUTE_TIME_UTC, FALSE)); } offset += 5; descriptor_len = tvb_get_ntohs(tvb, offset) & DVB_TOT_DESCRIPTORS_LOOP_LENGTH_MASK; proto_tree_add_item(dvb_tot_tree, hf_dvb_tot_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(dvb_tot_tree, hf_dvb_tot_descriptors_loop_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; offset += proto_mpeg_descriptor_loop_dissect(tvb, offset, descriptor_len, dvb_tot_tree); offset += packet_mpeg_sect_crc(tvb, pinfo, dvb_tot_tree, 0, offset); proto_item_set_len(ti, offset); }
static void dissect_mpeg_ca(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint offset = 0, length = 0; proto_item *ti; proto_tree *mpeg_ca_tree; /* The TVB should start right after the section_length in the Section packet */ col_set_str(pinfo->cinfo, COL_INFO, "Conditional Access Table (CA)"); ti = proto_tree_add_item(tree, proto_mpeg_ca, tvb, offset, -1, ENC_NA); mpeg_ca_tree = proto_item_add_subtree(ti, ett_mpeg_ca); offset += packet_mpeg_sect_header(tvb, offset, mpeg_ca_tree, &length, NULL); length -= 4; proto_tree_add_item(mpeg_ca_tree, hf_mpeg_ca_reserved, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(mpeg_ca_tree, hf_mpeg_ca_version_number, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(mpeg_ca_tree, hf_mpeg_ca_current_next_indicator, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; proto_tree_add_item(mpeg_ca_tree, hf_mpeg_ca_section_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(mpeg_ca_tree, hf_mpeg_ca_last_section_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Parse all the programs */ while (offset < length) offset += proto_mpeg_descriptor_dissect(tvb, offset, mpeg_ca_tree); offset += packet_mpeg_sect_crc(tvb, pinfo, mpeg_ca_tree, 0, offset); proto_item_set_len(ti, offset); }
static int dissect_rs_pgo_result_t (tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * parent_tree, dcerpc_info *di, guint8 * drep) { /* typedef struct { sec_rgy_name_t name; sec_rgy_pgo_item_t item; } rs_pgo_result_t; */ proto_item *item = NULL; proto_tree *tree = NULL; int old_offset = offset; if (di->conformant_run) { return offset; } if (parent_tree) { item = proto_tree_add_text (parent_tree, tvb, offset, -1, "rs_pgo_result_t "); tree = proto_item_add_subtree (item, ett_rs_pgo_result_t); } offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, di, drep); offset = dissect_sec_rgy_pgo_item_t (tvb, offset, pinfo, tree, di, drep); proto_item_set_len (item, offset - old_offset); return offset; }
/* EcDoRpc Function 0x2 */ static int mapi_dissect_element_EcDoRpc_MAPI_REPL_UNION_OpenFolder(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, dcerpc_info* di, guint8 *drep) { proto_item *item = NULL; proto_tree *tree = NULL; int old_offset; int origin_offset; origin_offset = offset; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_mapi_EcDoRpc_MAPI_REPL_UNION_mapi_OpenFolder, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_mapi_OpenFolder_repl); } old_offset = offset; proto_tree_add_item(tree, hf_mapi_EcDoRpc_unknown1, tvb, old_offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_item_set_len(item, offset - origin_offset); return offset; }
int dssetup_dissect_struct_DsRoleOpStatus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, int hf_index, guint32 param _U_) { proto_item *item = NULL; proto_tree *tree = NULL; int old_offset; ALIGN_TO_2_BYTES; old_offset = offset; if(parent_tree){ item = proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, TRUE); tree = proto_item_add_subtree(item, ett_dssetup_dssetup_DsRoleOpStatus); } offset = dssetup_dissect_element_DsRoleOpStatus_status(tvb, offset, pinfo, tree, drep); proto_item_set_len(item, offset-old_offset); return offset; }
int misc_dissect_struct_GUID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, dcerpc_info* di, guint8 *drep, int hf_index, guint32 param) { proto_item *item = NULL; proto_tree *tree = NULL; int old_offset; ALIGN_TO_4_BYTES; old_offset = offset; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_misc_GUID); } offset = misc_dissect_element_GUID_time_low(tvb, offset, pinfo, tree, di, drep); offset = misc_dissect_element_GUID_time_mid(tvb, offset, pinfo, tree, di, drep); offset = misc_dissect_element_GUID_time_hi_and_version(tvb, offset, pinfo, tree, di, drep); offset = misc_dissect_element_GUID_clock_seq(tvb, offset, pinfo, tree, di, drep); offset = misc_dissect_element_GUID_node(tvb, offset, pinfo, tree, di, drep); proto_item_set_len(item, offset-old_offset); if (di->call_data->flags & DCERPC_IS_NDR64) { ALIGN_TO_4_BYTES; } return offset; }
static gint xdmcp_add_authorization_names(proto_tree *tree, tvbuff_t *tvb, gint offset) { proto_tree *anames_tree; proto_item *anames_ti; gint anames_len, anames_start_offset; anames_start_offset = offset; anames_len = tvb_get_guint8(tvb, offset); anames_tree = proto_tree_add_subtree_format(tree, tvb, anames_start_offset, -1, ett_xdmcp_authorization_names, &anames_ti, "Authorization names (%d)", anames_len); anames_len = tvb_get_guint8(tvb, offset); offset++; while (anames_len > 0) { offset += xdmcp_add_string(anames_tree, hf_xdmcp_authorization_name, tvb, offset); anames_len--; } proto_item_set_len(anames_ti, offset - anames_start_offset); return offset - anames_start_offset; }
static int dissect_error_status_t (tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * parent_tree, guint8 * drep) { proto_item *item = NULL; proto_tree *tree = NULL; int old_offset = offset; guint32 st; dcerpc_info *di; const char *st_str; di = (dcerpc_info *)pinfo->private_data; if (di->conformant_run) { return offset; } if (parent_tree) { item = proto_tree_add_text (parent_tree, tvb, offset, -1, "error_status_t"); tree = proto_item_add_subtree (item, ett_error_status_t); } offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_error_status_t, &st); st_str = val_to_str_ext (st, &dce_error_vals_ext, "%u"); if (check_col (pinfo->cinfo, COL_INFO)) col_append_fstr (pinfo->cinfo, COL_INFO, " st:%s ", st_str); proto_item_set_len (item, offset - old_offset); return offset; }
static int dissect_rs_pgo_query_t (tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * parent_tree, dcerpc_info *di, guint8 * drep) { enum { rs_pgo_query_name, rs_pgo_query_id, rs_pgo_query_unix_num, rs_pgo_query_next, rs_pgo_query_none }; proto_item *item = NULL; proto_tree *tree = NULL; int old_offset = offset; guint8 query_t; if (di->conformant_run) { return offset; } if (parent_tree) { item = proto_tree_add_text (parent_tree, tvb, offset, -1, "rs_pgo_query_t "); tree = proto_item_add_subtree (item, ett_rs_pgo_query_t); } offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, di, drep, hf_rs_pgo_query_t, &query_t); col_append_str (pinfo->cinfo, COL_INFO, " rs_pgo_query_t:"); switch (query_t) { case rs_pgo_query_name: col_append_str (pinfo->cinfo, COL_INFO, "NAME"); break; case rs_pgo_query_id: col_append_str (pinfo->cinfo, COL_INFO, "ID"); break; case rs_pgo_query_unix_num: col_append_str (pinfo->cinfo, COL_INFO, "UNIX_NUM"); break; case rs_pgo_query_next: col_append_str (pinfo->cinfo, COL_INFO, "NEXT"); break; case rs_pgo_query_none: col_append_str (pinfo->cinfo, COL_INFO, "NONE"); break; default: col_append_fstr (pinfo->cinfo, COL_INFO, " unknown:%u", query_t); break; ; } proto_item_set_len (item, offset - old_offset); return offset; }
static int dissect_sec_rgy_pgo_flags_t (tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * parent_tree, dcerpc_info *di, guint8 * drep) { /* */ proto_item *item = NULL; proto_tree *tree = NULL; int old_offset = offset; guint32 flags; /* typedef bitset sec_rgy_pgo_flags_t; */ if (di->conformant_run) { return offset; } if (parent_tree) { item = proto_tree_add_text (parent_tree, tvb, offset, -1, "sec_rgy_pgo_flags_t "); tree = proto_item_add_subtree (item, ett_sec_rgy_pgo_flags_t); } offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_sec_rgy_pgo_flags_t, &flags); /* * * s e c _ r g y _ p g o _ f l a g s _ t * * pgo item is an alias * const unsigned32 sec_rgy_pgo_is_an_alias = 0x1; * pgo item is required - cannot be deleted * const unsigned32 sec_rgy_pgo_is_required = 0x2; * * projlist_ok: on person items indicates person can have a concurrent * group set on group items indicates this group can appear on a * concurrent group set. On org items this flag is undefined. * const unsigned32 sec_rgy_pgo_projlist_ok = 0x4; * * bits 4-32 unused * const unsigned32 sec_rgy_pgo_flags_none = 0; */ #define sec_rgy_pgo_is_an_alias 0x01 #define sec_rgy_pgo_is_required 0x02 #define sec_rgy_pgo_projlist_ok 0x04 #define sec_rgy_pgo_flags_none 0x00 col_append_str (pinfo->cinfo, COL_INFO, " PgoFlags="); if ((flags & sec_rgy_pgo_is_an_alias) == sec_rgy_pgo_is_an_alias) { col_append_str (pinfo->cinfo, COL_INFO, ":IS_AN_ALIAS"); } if ((flags & sec_rgy_pgo_is_required) == sec_rgy_pgo_is_required) { col_append_str (pinfo->cinfo, COL_INFO, ":IS_REQUIRED"); } if ((flags & sec_rgy_pgo_projlist_ok) == sec_rgy_pgo_projlist_ok) { col_append_str (pinfo->cinfo, COL_INFO, ":PROJLIST_OK"); } if ((flags & sec_rgy_acct_admin_client) == sec_rgy_acct_admin_client) { col_append_str (pinfo->cinfo, COL_INFO, ":NONE"); } if ((flags & sec_rgy_pgo_flags_none) == sec_rgy_pgo_flags_none) { col_append_str (pinfo->cinfo, COL_INFO, ":NONE"); } proto_item_set_len (item, offset - old_offset); return offset; }
static int dissect_bencoded_dict_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset ) { proto_item *ti; proto_tree *sub_tree; gboolean tohex; char *key, *val; guint orig_offset = offset; key = NULL; val = NULL; ti = proto_tree_add_item( tree, hf_bencoded_dict_entry, tvb, offset, 0, ENC_NA ); sub_tree = proto_item_add_subtree( ti, ett_bencoded_dict_entry); /* dissect the key, it must be a string */ offset = dissect_bencoded_string( tvb, pinfo, sub_tree, offset, &key, FALSE, "Key" ); /* If it is a dict, then just do recursion */ switch( tvb_get_guint8(tvb,offset) ) { case 'd': offset = dissect_bencoded_dict( tvb, pinfo, sub_tree, offset, "Value" ); val = (char*)dict_str; break; case 'l': if( strcmp(key,"e")==0 ) offset = dissect_bt_dht_error( tvb, pinfo, sub_tree, offset, &val, "Value" ); else if( strcmp(key,"values")==0 ) offset = dissect_bt_dht_values( tvb, pinfo, sub_tree, offset, &val, "Value" ); /* other unfamiliar lists */ else { offset = dissect_bencoded_list( tvb, pinfo, sub_tree, offset, "Value" ); val = (char*)list_str; } break; case 'i': offset = dissect_bencoded_int( tvb, pinfo, sub_tree, offset, &val, "Value" ); break; /* it's a string */ default: /* special process */ if( strcmp(key,"nodes")==0 ) offset = dissect_bt_dht_nodes( tvb, pinfo, sub_tree, offset, &val, "Value" ); /* some need to return hex string */ else { tohex = strcmp(key,"id")==0 || strcmp(key,"target")==0 || strcmp(key,"info_hash")==0 || strcmp(key,"t")==0 || strcmp(key,"v")==0; offset = dissect_bencoded_string( tvb, pinfo, sub_tree, offset, &val, tohex, "Value" ); } } if( strlen(key)==1 ) key = (char*)val_to_str( key[0], short_key_name_value_string, key ); if( strlen(val)==1 ) val = (char*)val_to_str( val[0], short_val_name_value_string, val ); proto_item_set_text( ti, "%s: %s", key, val ); proto_item_set_len( ti, offset-orig_offset ); if( strcmp(key,"message_type")==0 || strcmp(key,"request_type")==0 ) col_append_fstr(pinfo->cinfo, COL_INFO, "%s=%s ", key, val); return offset; }
/* Code to actually dissect the packets */ static void dissect_gvrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *gvrp_tree; guint16 protocol_id; guint8 octet; int msg_index; int attr_index; int offset = 0; int length = tvb_reported_length(tvb); col_set_str(pinfo->cinfo, COL_PROTOCOL, "GVRP"); col_set_str(pinfo->cinfo, COL_INFO, "GVRP"); if (tree) { ti = proto_tree_add_item(tree, proto_gvrp, tvb, 0, length, ENC_NA); gvrp_tree = proto_item_add_subtree(ti, ett_gvrp); /* Read in GARP protocol ID */ protocol_id = tvb_get_ntohs(tvb, GARP_PROTOCOL_ID); proto_tree_add_uint_format(gvrp_tree, hf_gvrp_proto_id, tvb, GARP_PROTOCOL_ID, sizeof(guint16), protocol_id, "Protocol Identifier: 0x%04x (%s)", protocol_id, protocol_id == GARP_DEFAULT_PROTOCOL_ID ? "GARP VLAN Registration Protocol" : "Unknown Protocol"); /* Currently only one protocol ID is supported */ if (protocol_id != GARP_DEFAULT_PROTOCOL_ID) { proto_tree_add_text(gvrp_tree, tvb, GARP_PROTOCOL_ID, sizeof(guint16), " (Warning: this version of Wireshark only knows about protocol id = 1)"); call_dissector(data_handle, tvb_new_subset(tvb, GARP_PROTOCOL_ID + sizeof(guint16), -1, -1), pinfo, tree); return; } offset += sizeof(guint16); length -= sizeof(guint16); msg_index = 0; /* Begin to parse GARP messages */ while (length) { proto_item *msg_item; int msg_start = offset; /* Read in attribute type. */ octet = tvb_get_guint8(tvb, offset); /* Check for end of mark */ if (octet == GARP_END_OF_MARK) { /* End of GARP PDU */ if (msg_index) { proto_tree_add_text(gvrp_tree, tvb, offset, sizeof(guint8), "End of mark"); break; } else { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } } offset += sizeof(guint8); length -= sizeof(guint8); msg_item = proto_tree_add_text(gvrp_tree, tvb, msg_start, -1, "Message %d", msg_index + 1); proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_type, tvb, msg_start, sizeof(guint8), octet); /* GVRP only supports one attribute type. */ if (octet != GVRP_ATTRIBUTE_TYPE) { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } attr_index = 0; while (length) { int attr_start = offset; proto_item *attr_item; /* Read in attribute length. */ octet = tvb_get_guint8(tvb, offset); /* Check for end of mark */ if (octet == GARP_END_OF_MARK) { /* If at least one message has been already read, * check for another end of mark. */ if (attr_index) { proto_tree_add_text(gvrp_tree, tvb, offset, sizeof(guint8), " End of mark"); offset += sizeof(guint8); length -= sizeof(guint8); proto_item_set_len(msg_item, offset - msg_start); break; } else { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } } else { guint8 event; offset += sizeof(guint8); length -= sizeof(guint8); attr_item = proto_tree_add_text(gvrp_tree, tvb, attr_start, -1, " Attribute %d", attr_index + 1); proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_length, tvb, attr_start, sizeof(guint8), octet); /* Read in attribute event */ event = tvb_get_guint8(tvb, offset); proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_event, tvb, offset, sizeof(guint8), event); offset += sizeof(guint8); length -= sizeof(guint8); switch (event) { case GVRP_EVENT_LEAVEALL: if (octet != GVRP_LENGTH_LEAVEALL) { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } break; case GVRP_EVENT_JOINEMPTY: case GVRP_EVENT_JOININ: case GVRP_EVENT_LEAVEEMPTY: case GVRP_EVENT_LEAVEIN: case GVRP_EVENT_EMPTY: if (octet != GVRP_LENGTH_NON_LEAVEALL) { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset),pinfo, tree); return; } /* Show attribute value */ proto_tree_add_item(gvrp_tree, hf_gvrp_attribute_value, tvb, offset, sizeof(guint16), ENC_BIG_ENDIAN); offset += sizeof(guint16); length -= sizeof(guint16); break; default: call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } } proto_item_set_len(attr_item, offset - attr_start); attr_index++; } msg_index++; } } }
static int dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int frame_offset,int ltp_type, guint64 session_num) { guint64 client_id; guint64 data_offset; guint64 data_length; guint64 chkp_sno = 0; guint64 rpt_sno = 0; guint64 sda_client_id = 0; unsigned segment_size = 0; int sdnv_length; int sdnv_status; proto_tree *ltp_data_tree; proto_item *ti; fragment_head *frag_msg = NULL; gboolean more_frags = TRUE; tvbuff_t *new_tvb = NULL; /* Create a subtree for data segment and add the other fields under it */ ltp_data_tree = proto_tree_add_subtree(ltp_tree, tvb, frame_offset, tvb_captured_length_remaining(tvb, frame_offset), ett_data_segm, NULL, "Data Segment"); /* Client ID - 0 = Bundle Protocol, 1 = CCSDS LTP Service Data Aggregation */ sdnv_status = evaluate_sdnv64(tvb, frame_offset, &sdnv_length, &client_id); ti = proto_tree_add_uint64_format_value(ltp_data_tree, hf_ltp_data_clid, tvb, frame_offset, sdnv_length, client_id, "%" G_GINT64_MODIFIER "u (%s)", client_id, val_to_str_const((const guint32) client_id, client_service_id_info, "Invalid")); if (!sdnv_status) { expert_add_info(pinfo, ti, &ei_ltp_sdnv_length); return 0; } frame_offset += sdnv_length; segment_size += sdnv_length; /* data segment offset */ if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_offset, &data_offset, &ti)) > 0) { frame_offset += sdnv_length; segment_size += sdnv_length; } else { return 0; } /* data segment length */ if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_length, &data_length, &ti)) > 0) { frame_offset += sdnv_length; segment_size += sdnv_length; /* add in the data length also */ segment_size += (unsigned int) data_length; } else { return 0; } more_frags = FALSE; if (ltp_type != 0 && ltp_type < 4) { /* checkpoint serial number - 32 bits per CCSDS */ if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_chkp, &chkp_sno, &ti)) > 0) { frame_offset += sdnv_length; segment_size += sdnv_length; if (chkp_sno > 4294967295U) { /* just a warning - continue processing */ expert_add_info(pinfo, ti, &ei_ltp_sno_larger_than_ccsds); } } else { return 0; } /* report serial number - 32 bits per CCSDS */ if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_rpt, &rpt_sno, &ti)) > 0) { frame_offset += sdnv_length; segment_size += sdnv_length; if (rpt_sno > 4294967295U) { /* just a warning - continue processing */ expert_add_info(pinfo, ti, &ei_ltp_sno_larger_than_ccsds); } } else { return 0; } } else if (ltp_type != 7) { more_frags = TRUE; } if (segment_size >= tvb_captured_length(tvb)) { /* did not capture the entire packet */ proto_tree_add_string(ltp_data_tree, hf_ltp_partial_packet, tvb, 0, 0, "<increase capture size?>"); return tvb_captured_length(tvb); } frag_msg = fragment_add_check(<p_reassembly_table, tvb, frame_offset, pinfo, (guint32)session_num, NULL, (guint32)data_offset, (guint32)data_length, more_frags); if(frag_msg) { /* Checking if the segment is completely reassembled */ if(!(frag_msg->flags & FD_PARTIAL_REASSEMBLY)) { /* if the segment has not been fragmented, then no reassembly is needed */ if(!more_frags && data_offset == 0) { new_tvb = tvb_new_subset_remaining(tvb, frame_offset); } else { new_tvb = process_reassembled_data(tvb, frame_offset, pinfo, "Reassembled LTP Segment", frag_msg, <p_frag_items,NULL, ltp_data_tree); } } } if(new_tvb) { int data_count = 1; int parse_length; int parse_offset = 0; parse_length = tvb_captured_length(new_tvb); while(parse_offset < parse_length) { int bundle_size; int sda_header_size; proto_tree *ltp_data_data_tree; tvbuff_t *datatvb; ltp_data_data_tree = proto_tree_add_subtree_format(ltp_data_tree, tvb,frame_offset, 0, ett_data_data_segm, NULL, "Data[%d]",data_count); sda_header_size = 0; if (client_id == 2) { sdnv_status = evaluate_sdnv64(tvb, frame_offset+parse_offset, &sdnv_length, &sda_client_id); ti = proto_tree_add_uint64_format_value(ltp_data_data_tree, hf_ltp_data_sda_clid, tvb, frame_offset+parse_offset, sdnv_length, sda_client_id, "%" G_GINT64_MODIFIER "u (%s)", sda_client_id, val_to_str_const((const guint32) sda_client_id, client_service_id_info, "Invalid")); if (!sdnv_status) { expert_add_info(pinfo, ti, &ei_ltp_sdnv_length); return 0; } sda_header_size = sdnv_length; parse_offset += sdnv_length; if (parse_offset == parse_length) { col_set_str(pinfo->cinfo, COL_INFO, "CCSDS LTP SDA Protocol Error"); return 0; /* Give up*/ } } datatvb = tvb_new_subset_length_caplen(new_tvb, parse_offset, (int)parse_length - parse_offset, tvb_captured_length(new_tvb)); bundle_size = call_dissector(bundle_handle, datatvb, pinfo, ltp_data_data_tree); if(bundle_size == 0) { /*Couldn't parse bundle*/ col_set_str(pinfo->cinfo, COL_INFO, "Dissection Failed"); return 0; /*Give up*/ } /* update the length of the data set */ proto_item_set_len(ltp_data_data_tree, bundle_size+sda_header_size); parse_offset += bundle_size; data_count++; } } else { if(frag_msg && more_frags) { col_append_frame_number(pinfo, COL_INFO, "[Reassembled in %d] ",frag_msg->reassembled_in); } else { col_append_str(pinfo->cinfo, COL_INFO, "[Unfinished LTP Segment] "); } } return segment_size; }
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; http_message_info_t *message_info; 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); 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; sub = proto_tree_add_subtree(url_tree, tvb, offset, 0, ett_form_keyvalue, &ti, "Form item"); 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 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); } }
static void dissect_packetlogger (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *packetlogger_tree = NULL; tvbuff_t *next_tvb; proto_item *ti = NULL; guint8 pl_type; gint len; col_set_str (pinfo->cinfo, COL_PROTOCOL, PSNAME); col_clear (pinfo->cinfo, COL_INFO); ti = proto_tree_add_item (tree, proto_packetlogger, tvb, 0, -1, ENC_NA); packetlogger_tree = proto_item_add_subtree (ti, ett_packetlogger); pl_type = tvb_get_guint8 (tvb, 0); proto_tree_add_item (packetlogger_tree, hf_type, tvb, 0, 1, ENC_BIG_ENDIAN); proto_item_append_text (ti, " %s", val_to_str (pl_type, type_vals, "Unknown 0x%02x")); len = tvb_length_remaining (tvb, 1); next_tvb = tvb_new_subset (tvb, 1, len, len); if (pl_type <= PKT_RECV_ACL_DATA) { /* HCI H1 packages */ switch (pl_type) { case PKT_HCI_COMMAND: pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_COMMAND; pinfo->pseudo_header->bthci.sent = P2P_DIR_SENT; pinfo->p2p_dir = P2P_DIR_SENT; break; case PKT_HCI_EVENT: pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_EVENT; pinfo->pseudo_header->bthci.sent = P2P_DIR_RECV; pinfo->p2p_dir = P2P_DIR_RECV; break; case PKT_SENT_ACL_DATA: pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_ACL; pinfo->pseudo_header->bthci.sent = P2P_DIR_SENT; pinfo->p2p_dir = P2P_DIR_SENT; break; case PKT_RECV_ACL_DATA: pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_ACL; pinfo->pseudo_header->bthci.sent = P2P_DIR_RECV; pinfo->p2p_dir = P2P_DIR_RECV; break; default: pinfo->pseudo_header->bthci.channel = pl_type; pinfo->pseudo_header->bthci.sent = P2P_DIR_UNKNOWN; pinfo->p2p_dir = P2P_DIR_UNKNOWN; break; } proto_item_set_len (ti, 1); col_add_fstr (pinfo->cinfo, COL_INFO, "%s", val_to_str(pl_type, type_vals, "Unknown 0x%02x")); if (!dissector_try_uint (hci_h1_table, pinfo->pseudo_header->bthci.channel, next_tvb, pinfo, tree)) { call_dissector (data_handle, next_tvb, pinfo, tree); } } else { /* PacketLogger data */ switch (pl_type) { case PKT_POWER: case PKT_NOTE: case PKT_NEW_CONTROLLER: proto_tree_add_item (packetlogger_tree, hf_info, next_tvb, 0, len, ENC_ASCII|ENC_NA); col_add_fstr (pinfo->cinfo, COL_INFO, "%s", tvb_format_stringzpad_wsp (next_tvb, 0, len)); break; default: call_dissector (data_handle, next_tvb, pinfo, tree); col_add_fstr (pinfo->cinfo, COL_INFO, "Unknown 0x%02x", pl_type); break; } } }
static int dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { gboolean has_routes; proto_tree *nbipx_tree = NULL; proto_item *ti = NULL; int offset = 0; guint8 packet_type; proto_tree *name_type_flag_tree; proto_item *tf; char name[(NETBIOS_NAME_LEN - 1)*4 + 1]; int name_type; gboolean has_payload; tvbuff_t *next_tvb; ipxhdr_t *ipxh; /* Reject the packet if data is NULL */ if (data == NULL) return 0; ipxh = (ipxhdr_t*)data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBIPX"); col_clear(pinfo->cinfo, COL_INFO); if (ipxh->ipx_type == IPX_PACKET_TYPE_WANBCAST) { /* * This is a WAN Broadcast packet; we assume it will have * 8 IPX addresses at the beginning. */ has_routes = TRUE; } else { /* * This isn't a WAN Broadcast packet, but it still might * have the 8 addresses. * * If it's the right length for a name operation, * and, if we assume it has routes, the packet type * is a name operation, assume it has routes. * * NOTE: this will throw an exception if the byte that * would be the packet type byte if this has the 8 * addresses isn't present; if that's the case, we don't * know how to interpret this packet, so we can't dissect * it anyway. */ has_routes = FALSE; /* start out assuming it doesn't */ if (tvb_reported_length(tvb) == 50) { packet_type = tvb_get_guint8(tvb, offset + 32 + 1); switch (packet_type) { case NBIPX_FIND_NAME: case NBIPX_NAME_RECOGNIZED: case NBIPX_CHECK_NAME: case NBIPX_NAME_IN_USE: case NBIPX_DEREGISTER_NAME: has_routes = TRUE; break; } } } if (tree) { ti = proto_tree_add_item(tree, proto_nbipx, tvb, 0, -1, ENC_NA); nbipx_tree = proto_item_add_subtree(ti, ett_nbipx); } if (has_routes) { if (tree) add_routers(nbipx_tree, tvb, 0); offset += 32; } packet_type = tvb_get_guint8(tvb, offset + 1); switch (packet_type) { case NBIPX_FIND_NAME: case NBIPX_NAME_RECOGNIZED: case NBIPX_CHECK_NAME: case NBIPX_NAME_IN_USE: case NBIPX_DEREGISTER_NAME: name_type = get_netbios_name(tvb, offset+2, name, (NETBIOS_NAME_LEN - 1)*4 + 1); col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s<%02x>", val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"), name, name_type); if (nbipx_tree) { tf = proto_tree_add_item(nbipx_tree, hf_nbipx_name_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); name_type_flag_tree = proto_item_add_subtree(tf, ett_nbipx_name_type_flags); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_group, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_in_use, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_registered, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_duplicated, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_deregistered, tvb, offset, 1, ENC_LITTLE_ENDIAN); } offset += 1; proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type); offset += 1; if (nbipx_tree) netbios_add_name("Name", tvb, offset, nbipx_tree); offset += NETBIOS_NAME_LEN; /* * No payload to be interpreted by another protocol. */ has_payload = FALSE; break; case NBIPX_SESSION_DATA: case NBIPX_SESSION_END: case NBIPX_SESSION_END_ACK: col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown")); dissect_conn_control(tvb, offset, nbipx_tree); offset += 1; proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type); offset += 1; proto_tree_add_item(nbipx_tree, hf_nbipx_session_src_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_dest_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_send_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_total_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_recv_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(nbipx_tree, hf_nbipx_session_bytes_received, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* * We may have payload to dissect. */ has_payload = TRUE; break; case NBIPX_DIRECTED_DATAGRAM: col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown")); dissect_conn_control(tvb, offset, nbipx_tree); offset += 1; proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type); offset += 1; if (nbipx_tree) netbios_add_name("Receiver's Name", tvb, offset, nbipx_tree); offset += NETBIOS_NAME_LEN; if (nbipx_tree) netbios_add_name("Sender's Name", tvb, offset, nbipx_tree); offset += NETBIOS_NAME_LEN; /* * We may have payload to dissect. */ has_payload = TRUE; break; default: col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown")); /* * We don't know what the first byte is. */ offset += 1; /* * The second byte is a data stream type byte. */ proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type); offset += 1; /* * We don't know what the rest of the packet is. */ has_payload = FALSE; } /* * Set the length of the NBIPX tree item. */ if (ti != NULL) proto_item_set_len(ti, offset); if (has_payload && tvb_offset_exists(tvb, offset)) { next_tvb = tvb_new_subset_remaining(tvb, offset); dissect_netbios_payload(next_tvb, pinfo, tree); } return tvb_captured_length(tvb); }
static void client_display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, socks_hash_entry_t *hash_info, sock_state_t* state_info) { /* Display the protocol tree for the version. This routine uses the */ /* stored conversation information to decide what to do with the row. */ /* Per packet information would have been better to do this, but we */ /* didn't have that when I wrote this. And I didn't expect this to get */ /* so messy. */ unsigned int i; const char *AuthMethodStr; sock_state_t new_state_info; /* Either there is an error, or we're done with the state machine (so there's nothing to display) */ if (state_info == NULL) return; proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (state_info->client == clientStart) { proto_tree *AuthTree; proto_item *ti; guint8 num_auth_methods, auth; ti = proto_tree_add_text( tree, tvb, offset, -1, "Client Authentication Methods"); AuthTree = proto_item_add_subtree(ti, ett_socks_auth); num_auth_methods = tvb_get_guint8(tvb, offset); proto_item_set_len(ti, num_auth_methods+1); proto_tree_add_item( AuthTree, hf_client_auth_method_count, tvb, offset, 1, ENC_NA); offset += 1; for( i = 0; i < num_auth_methods; ++i) { auth = tvb_get_guint8( tvb, offset); AuthMethodStr = get_auth_method_name(auth); proto_tree_add_uint_format(AuthTree, hf_client_auth_method, tvb, offset, 1, auth, "Method[%u]: %u (%s)", i, auth, AuthMethodStr); offset += 1; } if ((num_auth_methods == 1) && (tvb_bytes_exist(tvb, offset + 2, 1)) && (tvb_get_guint8(tvb, offset + 2) == 0) && (tvb_reported_length_remaining(tvb, offset + 2 + num_auth_methods) > 0)) { new_state_info.client = clientV5Command; client_display_socks_v5(tvb, offset, pinfo, tree, hash_info, &new_state_info); } } else if (state_info->client == clientV5Command) { proto_tree_add_item( tree, hf_socks_cmd, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item( tree, hf_socks_reserved, tvb, offset, 1, ENC_NA); offset += 1; offset = display_address(tvb, offset, tree); proto_tree_add_item( tree, hf_client_port, tvb, offset, 2, ENC_BIG_ENDIAN); } else if ((state_info->client == clientWaitForAuthReply) && (state_info->server == serverInitReply)) { guint16 len; gchar* str; switch(hash_info->authentication_method) { case NO_AUTHENTICATION: break; case USER_NAME_AUTHENTICATION: /* process user name */ len = tvb_get_guint8(tvb, offset); str = tvb_get_string(wmem_packet_scope(), tvb, offset+1, len); proto_tree_add_string(tree, hf_socks_username, tvb, offset, len+1, str); offset += (len+1); len = tvb_get_guint8(tvb, offset); str = tvb_get_string(wmem_packet_scope(), tvb, offset+1, len); proto_tree_add_string(tree, hf_socks_password, tvb, offset, len+1, str); /* offset += (len+1); */ break; case GSS_API_AUTHENTICATION: proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, ENC_BIG_ENDIAN); len = tvb_get_ntohs(tvb, offset+1); if (len > 0) proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, ENC_NA); break; default: break; } } }
static void dissect_bacnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_item *ct; proto_tree *bacnet_tree; proto_tree *control_tree; gint offset; guint8 bacnet_version; guint8 bacnet_control; guint8 bacnet_dlen; guint8 bacnet_slen; guint8 bacnet_mesgtyp; guint8 bacnet_rejectreason; guint8 bacnet_rportnum; guint8 bacnet_pinfolen; guint8 i; tvbuff_t *next_tvb; guint32 vendor_id; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-NPDU"); col_set_str(pinfo->cinfo, COL_INFO, "Building Automation and Control Network NPDU"); offset = 0; bacnet_version = tvb_get_guint8(tvb, offset); bacnet_control = tvb_get_guint8(tvb, offset+1); /* I don't know the length of the NPDU yet; Setting the length after dissection */ ti = proto_tree_add_item(tree, proto_bacnet, tvb, 0, -1, ENC_NA); bacnet_tree = proto_item_add_subtree(ti, ett_bacnet); proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_version, tvb, offset, 1, bacnet_version,"0x%02x (%s)",bacnet_version, (bacnet_version == 0x01)?"ASHRAE 135-1995":"unknown"); offset ++; ct = proto_tree_add_uint(bacnet_tree, hf_bacnet_control, tvb, offset, 1, bacnet_control); control_tree = proto_item_add_subtree(ct, ett_bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_net, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_res1, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_dest, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_res2, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_src, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_expect, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_high, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_low, tvb, offset, 1, bacnet_control); offset ++; if (bacnet_control & BAC_CONTROL_DEST) { /* DNET, DLEN, DADR */ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; bacnet_dlen = tvb_get_guint8(tvb, offset); /* DLEN = 0 is broadcast on dest.network */ if( bacnet_dlen == 0) { /* append to hf_bacnet_dlen: broadcast */ proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen, "%d indicates Broadcast on Destination Network", bacnet_dlen); offset ++; /* going to SNET */ } else if (bacnet_dlen==6) { proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen); offset ++; /* Ethernet MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_dadr_eth, tvb, offset, bacnet_dlen, ENC_NA); offset += bacnet_dlen; } else if (bacnet_dlen==1) { proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen); offset ++; /* MS/TP or ARCNET MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_dadr_mstp, tvb, offset, bacnet_dlen, ENC_BIG_ENDIAN); offset += bacnet_dlen; } else if (bacnet_dlen<7) { proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen); offset ++; /* Other MAC formats should be included here */ proto_tree_add_item(bacnet_tree, hf_bacnet_dadr_tmp, tvb, offset, bacnet_dlen, ENC_NA); offset += bacnet_dlen; } else { proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen, "%d invalid!", bacnet_dlen); } } if (bacnet_control & BAC_CONTROL_SRC) { /* SNET, SLEN, SADR */ /* SNET */ proto_tree_add_uint(bacnet_tree, hf_bacnet_snet, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset += 2; bacnet_slen = tvb_get_guint8(tvb, offset); if( bacnet_slen == 0) { /* SLEN = 0 invalid */ proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen, "%d invalid!", bacnet_slen); offset ++; } else if (bacnet_slen==6) { /* SLEN */ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen); offset ++; /* Ethernet MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_sadr_eth, tvb, offset, bacnet_slen, ENC_NA); offset += bacnet_slen; } else if (bacnet_slen==1) { /* SLEN */ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen); offset ++; /* MS/TP or ARCNET MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_sadr_mstp, tvb, offset, bacnet_slen, ENC_BIG_ENDIAN); offset += bacnet_slen; } else if (bacnet_slen<6) { /* LON MAC */ /* SLEN */ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen); offset ++; /* Other MAC formats should be included here */ proto_tree_add_item(bacnet_tree, hf_bacnet_sadr_tmp, tvb, offset, bacnet_slen, ENC_NA); offset += bacnet_slen; } else { proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen, "%d invalid!", bacnet_slen); offset ++; } } if (bacnet_control & BAC_CONTROL_DEST) { /* Hopcount */ proto_tree_add_item(bacnet_tree, hf_bacnet_hopc, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; } /* Network Layer Message Type */ if (bacnet_control & BAC_CONTROL_NET) { bacnet_mesgtyp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_mesgtyp, tvb, offset, 1, bacnet_mesgtyp, "%02x (%s)", bacnet_mesgtyp, bacnet_mesgtyp_name(bacnet_mesgtyp)); /* Put the NPDU Type in the info column */ col_add_str(pinfo->cinfo, COL_INFO, bacnet_mesgtyp_name(bacnet_mesgtyp)); offset ++; /* Vendor ID * The standard says: "If Bit 7 of the control octet is 1 and * the Message Type field contains a value in the range * X'80' - X'FF', then a Vendor ID field shall be present (...)." * We should not go any further in dissecting the packet if it's * not present, but we don't know about that: No length field... */ if (bacnet_mesgtyp > 0x7f) { /* Note: our next_tvb includes message type and vendor id! */ next_tvb = tvb_new_subset_remaining(tvb, offset-1); vendor_id = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(bacnet_tree, hf_bacnet_vendor, tvb, offset, 2, vendor_id); offset += 2; /* vendor_id */ if (dissector_try_uint(bacnet_dissector_table, vendor_id, next_tvb, pinfo, bacnet_tree)) { /* we parsed it so skip over length and we are done */ /* Note: offset has now been bumped for message type and vendor id so we take that out of our next_tvb size */ offset += tvb_length(next_tvb) -3; } } /* Performance Index (in I-Could-Be-Router-To-Network) */ if (bacnet_mesgtyp == BAC_NET_ICB_R) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(bacnet_tree, hf_bacnet_perf, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; } /* Reason, DNET (in Reject-Message-To-Network) */ if (bacnet_mesgtyp == BAC_NET_REJ) { bacnet_rejectreason = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_rejectreason, tvb, offset, 1, bacnet_rejectreason, "%d (%s)", bacnet_rejectreason, bacnet_rejectreason_name(bacnet_rejectreason)); offset ++; proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } /* N*DNET (in Router-Busy-To-Network,Router-Available-To-Network) */ if ((bacnet_mesgtyp == BAC_NET_R_BUSY) || (bacnet_mesgtyp == BAC_NET_WHO_R) || (bacnet_mesgtyp == BAC_NET_R_AVA) || (bacnet_mesgtyp == BAC_NET_IAM_R) ) { while(tvb_reported_length_remaining(tvb, offset) > 1 ) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } } /* Initialize-Routing-Table */ if ( (bacnet_mesgtyp == BAC_NET_INIT_RTAB) || (bacnet_mesgtyp == BAC_NET_INIT_RTAB_ACK) ) { bacnet_rportnum = tvb_get_guint8(tvb, offset); /* number of ports */ proto_tree_add_uint(bacnet_tree, hf_bacnet_rportnum, tvb, offset, 1, bacnet_rportnum); offset ++; for(i=0; i<bacnet_rportnum; i++) { /* Connected DNET */ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Port ID */ proto_tree_add_item(bacnet_tree, hf_bacnet_portid, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; /* Port Info Length */ bacnet_pinfolen = tvb_get_guint8(tvb, offset); proto_tree_add_uint(bacnet_tree, hf_bacnet_pinfolen, tvb, offset, 1, bacnet_pinfolen); offset ++; proto_tree_add_text(bacnet_tree, tvb, offset, bacnet_pinfolen, "Port Info: %s", tvb_bytes_to_str(tvb, offset, bacnet_pinfolen)); offset += bacnet_pinfolen; } } /* Establish-Connection-To-Network */ if (bacnet_mesgtyp == BAC_NET_EST_CON) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(bacnet_tree, hf_bacnet_term_time_value, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; } /* Disconnect-Connection-To-Network */ if (bacnet_mesgtyp == BAC_NET_DISC_CON) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } } /* Now set NPDU length */ proto_item_set_len(ti, offset); /* dissect BACnet APDU */ next_tvb = tvb_new_subset_remaining(tvb,offset); if (bacnet_control & BAC_CONTROL_NET) { /* Unknown function - dissect the payload as data */ call_dissector(data_handle, next_tvb, pinfo, tree); } else { /* APDU - call the APDU dissector */ call_dissector(bacapp_handle, next_tvb, pinfo, tree); } }
/*FUNCTION:------------------------------------------------------ * NAME * zdp_parse_bind_table_entry * DESCRIPTION * Parses and displays a single binding table entry. * PARAMETERS * tvbuff_t *tvb - pointer to buffer containing raw packet. * packet_into *pinfo - pointer to packet information fields * proto_tree *tree - pointer to data tree Wireshark uses to display packet. * RETURNS * void *--------------------------------------------------------------- */ void zdp_parse_bind_table_entry(proto_tree *tree, tvbuff_t *tvb, guint *offset, packet_info *pinfo) { proto_item *ti = NULL; guint len = 0; guint64 src64; guint8 src_ep; guint16 cluster; guint8 mode; guint64 dst64; guint16 dst; guint8 dst_ep; /* Add the source address. */ src64 = tvb_get_letoh64(tvb, *offset + len); if (tree) ti = proto_tree_add_text(tree, tvb, *offset, 0, "Bind {Src: %s", get_eui64_name(src64)); len += sizeof(guint64); /* Add the source endpoint. */ src_ep = tvb_get_guint8(tvb, *offset + len); if (tree) proto_item_append_text(ti, ", Src Endpoint: %d", src_ep); len += sizeof(guint8); /* Add the cluster ID. */ if (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) { cluster = tvb_get_letohs(tvb, *offset + len); len += sizeof(guint16); } else { cluster = tvb_get_guint8(tvb, *offset + len); len += sizeof(guint8); } if (tree) proto_item_append_text(ti, ", Cluster: %d", cluster); /* Get the destination address mode. */ if (pinfo->zbee_stack_vers >= ZBEE_VERSION_2007) { mode = tvb_get_guint8(tvb, *offset + len); len += sizeof(guint8); } else { /* Mode field doesn't exist and always uses unicast in 2003 & earlier. */ mode = ZBEE_ZDP_ADDR_MODE_UNICAST; } /* Add the destination address. */ if (mode == ZBEE_ZDP_ADDR_MODE_GROUP) { dst = tvb_get_letohs(tvb, *offset + len); if (tree) proto_item_append_text(ti, ", Dst: 0x%04x}", dst); len += sizeof(guint16); } else if (mode == ZBEE_ZDP_ADDR_MODE_UNICAST) { dst64 = tvb_get_letoh64(tvb, *offset + len); if (tree) proto_item_append_text(ti, ", Dst: %s", get_eui64_name(dst64)); len += sizeof(guint64); dst_ep = tvb_get_guint8(tvb, *offset + len); if (tree) proto_item_append_text(ti, ", Dst Endpoint: %d}", dst_ep); len += sizeof(guint8); } else { if (tree) proto_item_append_text(ti, "}"); } if (tree) { proto_item_set_len(ti, len); } *offset += len; } /* zdp_parse_bind_table_entry */
static int dissect_rs_pgo_query_key_t (tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * parent_tree, dcerpc_info *di, guint8 * drep) { enum { rs_pgo_query_name, rs_pgo_query_id, rs_pgo_query_unix_num, rs_pgo_query_next, rs_pgo_query_none }; /* typedef union switch (rs_pgo_query_t query) tagged_union { case rs_pgo_query_name: sec_rgy_name_t name; case rs_pgo_query_id: rs_pgo_id_key_t id_key; case rs_pgo_query_unix_num: rs_pgo_unix_num_key_t unix_num_key; case rs_pgo_query_next: sec_rgy_name_t scope; default: ; * empty branch of union * } rs_pgo_query_key_t; */ proto_item *item = NULL; proto_tree *tree = NULL; int old_offset = offset; guint16 query_t; if (di->conformant_run) { return offset; } if (parent_tree) { item = proto_tree_add_text (parent_tree, tvb, offset, -1, "rs_pgo_query_key_t "); tree = proto_item_add_subtree (item, ett_rs_pgo_query_key_t); } offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, di, drep, hf_rs_pgo_query_key_t, &query_t); col_append_str (pinfo->cinfo, COL_INFO, " rs_pgo_query_key_t:"); offset += 4; switch (query_t) { case rs_pgo_query_name: col_append_str (pinfo->cinfo, COL_INFO, "NAME"); offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, di, drep); break; case rs_pgo_query_id: col_append_str (pinfo->cinfo, COL_INFO, "ID"); offset = dissect_rs_pgo_id_key_t (tvb, offset, pinfo, tree, di, drep); break; case rs_pgo_query_unix_num: col_append_str (pinfo->cinfo, COL_INFO, "UNIX_NUM"); offset = dissect_rs_pgo_unix_num_key_t (tvb, offset, pinfo, tree, di, drep); break; case rs_pgo_query_next: col_append_str (pinfo->cinfo, COL_INFO, "NEXT"); offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, di, drep); break; case rs_pgo_query_none: col_append_str (pinfo->cinfo, COL_INFO, "NONE"); break; default: col_append_fstr (pinfo->cinfo, COL_INFO, " unknown:%u", query_t); break; } proto_item_set_len (item, offset - old_offset); return offset; }
/* * Process a multipart body-part: * MIME-part-headers [ line-end *OCTET ] * line-end dashed-boundary transport-padding line-end * * If applicable, call a media subdissector. * * Return the offset to the start of the next body-part. */ static gint process_body_part(proto_tree *tree, tvbuff_t *tvb, const guint8 *boundary, gint boundary_len, packet_info *pinfo, gint start, gboolean *last_boundary) { proto_tree *subtree; proto_item *ti; gint offset = start, next_offset = 0; char *parameters = NULL; gint body_start, boundary_start, boundary_line_len; gchar *content_type_str = NULL; gchar *content_encoding_str = NULL; char *filename = NULL; char *mimetypename = NULL; int len = 0; gboolean last_field = FALSE; ti = proto_tree_add_item(tree, hf_multipart_part, tvb, start, 0, ENC_ASCII|ENC_NA); subtree = proto_item_add_subtree(ti, ett_multipart_body); /* * Process the MIME-part-headers */ while (!last_field) { gint colon_offset; char *hdr_str; char *header_str; /* Look for the end of the header (denoted by cr) * 3:d argument to imf_find_field_end() maxlen; must be last offset in the tvb. */ next_offset = imf_find_field_end(tvb, offset, tvb_length_remaining(tvb, offset)+offset, &last_field); /* If cr not found, won't have advanced - get out to avoid infinite loop! */ if (next_offset == offset) { break; } hdr_str = tvb_get_string(wmem_packet_scope(), tvb, offset, next_offset - offset); header_str = unfold_and_compact_mime_header(hdr_str, &colon_offset); if (colon_offset <= 0) { proto_tree_add_text(subtree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); } else { gint hf_index; /* Split header name from header value */ header_str[colon_offset] = '\0'; hf_index = is_known_multipart_header(header_str, colon_offset); if (hf_index == -1) { proto_tree_add_text(subtree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, next_offset - offset)); } else { char *value_str = header_str + colon_offset + 1; proto_tree_add_string_format(subtree, hf_header_array[hf_index], tvb, offset, next_offset - offset, (const char *)value_str, "%s", tvb_format_text(tvb, offset, next_offset - offset)); switch (hf_index) { case POS_CONTENT_TYPE: { /* The Content-Type starts at colon_offset + 1 */ gint semicolon_offset = index_of_char( value_str, ';'); if (semicolon_offset > 0) { value_str[semicolon_offset] = '\0'; parameters = wmem_strdup(wmem_packet_scope(), value_str + semicolon_offset + 1); } else { parameters = NULL; } content_type_str = wmem_ascii_strdown(wmem_packet_scope(), value_str, -1); /* Show content-type in root 'part' label */ proto_item_append_text(ti, " (%s)", content_type_str); /* find the "name" parameter in case we don't find a content disposition "filename" */ if((mimetypename = find_parameter(parameters, "name=", &len)) != NULL) { mimetypename = g_strndup(mimetypename, len); } } break; case POS_CONTENT_TRANSFER_ENCODING: { /* The Content-Transfeing starts at colon_offset + 1 */ gint cr_offset = index_of_char(value_str, '\r'); if (cr_offset > 0) { value_str[cr_offset] = '\0'; } content_encoding_str = wmem_ascii_strdown(wmem_packet_scope(), value_str, -1); } break; case POS_CONTENT_DISPOSITION: { /* find the "filename" parameter */ if((filename = find_parameter(value_str, "filename=", &len)) != NULL) { filename = g_strndup(filename, len); } } break; default: break; } } } offset = next_offset; } body_start = next_offset; /* * Process the body */ boundary_start = find_next_boundary(tvb, body_start, boundary, boundary_len, &boundary_line_len, last_boundary); if (boundary_start > 0) { gint body_len = boundary_start - body_start; tvbuff_t *tmp_tvb = tvb_new_subset(tvb, body_start, body_len, body_len); if (content_type_str) { /* * subdissection */ void *save_private_data = pinfo->private_data; gboolean dissected; /* * Try and remove any content transfer encoding so that each sub-dissector * doesn't have to do it itself * */ if(content_encoding_str && remove_base64_encoding) { if(!g_ascii_strncasecmp(content_encoding_str, "base64", 6)) tmp_tvb = base64_decode(pinfo, tmp_tvb, filename ? filename : (mimetypename ? mimetypename : content_type_str)); } pinfo->private_data = parameters; /* * First try the dedicated multipart dissector table */ dissected = dissector_try_string(multipart_media_subdissector_table, content_type_str, tmp_tvb, pinfo, subtree, NULL); if (! dissected) { /* * Fall back to the default media dissector table */ dissected = dissector_try_string(media_type_dissector_table, content_type_str, tmp_tvb, pinfo, subtree, NULL); } if (! dissected) { const char *save_match_string = pinfo->match_string; pinfo->match_string = content_type_str; call_dissector(media_handle, tmp_tvb, pinfo, subtree); pinfo->match_string = save_match_string; } pinfo->private_data = save_private_data; parameters = NULL; /* Shares same memory as content_type_str */ } else { call_dissector(data_handle, tmp_tvb, pinfo, subtree); } proto_item_set_len(ti, boundary_start - start); if (*last_boundary == TRUE) { proto_tree_add_text(tree, tvb, boundary_start, boundary_line_len, "Last boundary: %s", tvb_format_text(tvb, boundary_start, boundary_line_len)); } else { proto_tree_add_text(tree, tvb, boundary_start, boundary_line_len, "Boundary: %s", tvb_format_text(tvb, boundary_start, boundary_line_len)); } g_free(filename); g_free(mimetypename); return boundary_start + boundary_line_len; } g_free(filename); g_free(mimetypename); return -1; }
static void dissect_redirecttlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset) { proto_tree *meta_data_tree, *meta_data_ilv_tree, *redirect_data_tree; gint start_offset; gint length_meta, length_ilv, length_redirect; proto_item *ti; address src_addr, src_net_addr; address dst_addr, dst_net_addr; copy_address_shallow(&src_addr, &pinfo->src); copy_address_shallow(&src_net_addr, &pinfo->net_src); copy_address_shallow(&dst_addr, &pinfo->dst); copy_address_shallow(&dst_net_addr, &pinfo->net_dst); meta_data_tree = proto_tree_add_subtree(tree, tvb, offset, TLV_TL_LENGTH, ett_forces_redirect_tlv_meta_data_tlv, &ti, "Meta Data TLV"); proto_tree_add_item(meta_data_tree, hf_forces_redirect_tlv_meta_data_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN); length_meta = tvb_get_ntohs(tvb, offset+2); proto_tree_add_uint(meta_data_tree, hf_forces_redirect_tlv_meta_data_tlv_length, tvb, offset+2, 2, length_meta); proto_item_set_len(ti, length_meta); start_offset = offset; while ((tvb_reported_length_remaining(tvb, offset) >= 8) && (start_offset+length_meta > offset)) { meta_data_ilv_tree = proto_tree_add_subtree(tree, tvb, offset, TLV_TL_LENGTH, ett_forces_redirect_tlv_meta_data_tlv_meta_data_ilv, &ti, "Meta Data ILV"); proto_tree_add_item(meta_data_ilv_tree, hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_id, tvb, offset+8, 4, ENC_BIG_ENDIAN); length_ilv = tvb_get_ntohl(tvb, offset+12); proto_tree_add_uint(meta_data_ilv_tree, hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv_length, tvb, offset+12, 4, length_ilv); offset += 8; if (length_ilv > 0) { proto_tree_add_item(meta_data_ilv_tree, hf_forces_redirect_tlv_meta_data_tlv_meta_data_ilv, tvb, offset, length_ilv, ENC_NA); if (offset + length_ilv > offset) { offset += length_ilv; } } proto_item_set_len(ti, length_ilv + 8); } if (tvb_reported_length_remaining(tvb, offset) > 0) { redirect_data_tree = proto_tree_add_subtree(tree, tvb, offset, TLV_TL_LENGTH, ett_forces_redirect_tlv_redirect_data_tlv, &ti, "Redirect Data TLV"); proto_tree_add_item(redirect_data_tree, hf_forces_redirect_tlv_redirect_data_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN); length_redirect = tvb_get_ntohs(tvb, offset+2); proto_tree_add_uint(redirect_data_tree, hf_forces_redirect_tlv_redirect_data_tlv_length, tvb, offset+2, 2, length_redirect); if (tvb_reported_length_remaining(tvb, offset) < length_redirect) { expert_add_info_format(pinfo, ti, &ei_forces_redirect_tlv_redirect_data_tlv_length, "Bogus: Redirect Data TLV length (%u bytes) is wrong", length_redirect); } else if (length_redirect < TLV_TL_LENGTH + MIN_IP_HEADER_LENGTH) { expert_add_info_format(pinfo, ti, &ei_forces_redirect_tlv_redirect_data_tlv_length, "Bogus: Redirect Data TLV length (%u bytes) not big enough for IP layer", length_redirect); } else { tvbuff_t *next_tvb; next_tvb = tvb_new_subset_length(tvb, offset+4, length_redirect-TLV_TL_LENGTH); call_dissector(ip_handle, next_tvb, pinfo, redirect_data_tree); /* Restore IP info */ copy_address_shallow(&pinfo->src, &src_addr); copy_address_shallow(&pinfo->net_src, &src_net_addr); copy_address_shallow(&pinfo->dst, &dst_addr); copy_address_shallow(&pinfo->net_dst, &dst_net_addr); } } }
static void dissect_v5dl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *v5dl_tree, *addr_tree; proto_item *v5dl_ti, *addr_ti; int direction; guint v5dl_header_len; guint16 control; #if 0 proto_tree *checksum_tree; proto_item *checksum_ti; guint16 checksum, checksum_calculated; guint checksum_offset; #endif guint16 addr, cr, eah, eal, v5addr; gboolean is_response = 0; #if 0 guint length, reported_length; #endif tvbuff_t *next_tvb; const char *srcname = "?"; const char *dstname = "?"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "V5DL"); col_clear(pinfo->cinfo, COL_INFO); addr = tvb_get_ntohs(tvb, 0); cr = addr & V5DL_CR; eal = (addr & V5DL_EAL) >> V5DL_EAL_SHIFT; eah = (addr & V5DL_EAH) >> V5DL_EAH_SHIFT; v5addr = (eah << 7) + eal; v5dl_header_len = 2; /* addr */ direction = pinfo->p2p_dir; if (pinfo->p2p_dir == P2P_DIR_RECV) { is_response = cr ? FALSE : TRUE; srcname = "Network"; dstname = "User"; } else if (pinfo->p2p_dir == P2P_DIR_SENT) { is_response = cr ? TRUE : FALSE; srcname = "User"; dstname = "Network"; } col_set_str(pinfo->cinfo, COL_RES_DL_SRC, srcname); col_set_str(pinfo->cinfo, COL_RES_DL_DST, dstname); if (tree) { proto_item *direction_ti; v5dl_ti = proto_tree_add_item(tree, proto_v5dl, tvb, 0, -1, ENC_NA); v5dl_tree = proto_item_add_subtree(v5dl_ti, ett_v5dl); /* * Don't show the direction if we don't know it. */ if (direction != P2P_DIR_UNKNOWN) { direction_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_direction, tvb, 0, 0, pinfo->p2p_dir); PROTO_ITEM_SET_GENERATED(direction_ti); } addr_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_ef, tvb, 0, 2, v5addr); addr_tree = proto_item_add_subtree(addr_ti, ett_v5dl_address); proto_tree_add_uint(addr_tree, hf_v5dl_eah, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_cr, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_ea1, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_eal, tvb, 1, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_ea2, tvb, 1, 1, addr); } else { v5dl_ti = NULL; v5dl_tree = NULL; } control = dissect_xdlc_control(tvb, 2, pinfo, v5dl_tree, hf_v5dl_control, ett_v5dl_control, &v5dl_cf_items, &v5dl_cf_items_ext, NULL, NULL, is_response, TRUE, FALSE); v5dl_header_len += XDLC_CONTROL_LEN(control, TRUE); if (tree) proto_item_set_len(v5dl_ti, v5dl_header_len); /* * XXX - the sample capture supplied with bug 7027 does not * appear to include checksums in the packets. */ #if 0 /* * Check the checksum, if available. * The checksum is a CCITT CRC-16 at the end of the packet, so * if we don't have the entire packet in the capture - i.e., if * tvb_captured_length(tvb) != tvb_reported_length(tvb) we can't check it. */ length = tvb_captured_length(tvb); reported_length = tvb_reported_length(tvb); /* * If the reported length isn't big enough for the V5DL header * and 2 bytes of checksum, the packet is malformed, as the * checksum overlaps the header. */ if (reported_length < v5dl_header_len + 2) THROW(ReportedBoundsError); if (length == reported_length) { /* * There's no snapshot length cutting off any of the * packet. */ checksum_offset = reported_length - 2; checksum = tvb_get_ntohs(tvb, checksum_offset); checksum_calculated = crc16_ccitt_tvb(tvb, checksum_offset); checksum_calculated = g_htons(checksum_calculated); /* Note: g_htons() macro may eval arg multiple times */ if (checksum == checksum_calculated) { checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset, 2, 0, "0x%04x [correct]", checksum); checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, TRUE); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, FALSE); } else { checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset, 2, 0, "0x%04x [incorrect, should be 0x%04x]", checksum, checksum_calculated); checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, FALSE); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, TRUE); } /* * Remove the V5DL header *and* the checksum. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_captured_length_remaining(tvb, v5dl_header_len) - 2, tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } else { /* * Some or all of the packet is cut off by a snapshot * length. */ if (length == reported_length - 1) { /* * One byte is cut off, so there's only one * byte of checksum in the captured data. * Remove that byte from the captured length * and both bytes from the reported length. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_captured_length_remaining(tvb, v5dl_header_len) - 1, tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } else { /* * Two or more bytes are cut off, so there are * no bytes of checksum in the captured data. * Just remove the checksum from the reported * length. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_captured_length_remaining(tvb, v5dl_header_len), tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } } #else next_tvb = tvb_new_subset_remaining(tvb, v5dl_header_len); #endif if (XDLC_IS_INFORMATION(control)) { /* call V5.2 dissector */ call_dissector(v52_handle, next_tvb, pinfo, tree); } }
static void dissect_forces(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti, *tlv_item; proto_tree *forces_tree, *forces_flags_tree; proto_tree *forces_main_header_tree, *forces_tlv_tree, *tlv_tree; gint length_count; guint8 message_type; guint16 tlv_type; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ForCES"); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(tree, proto_forces, tvb, 0, -1, ENC_NA); forces_tree = proto_item_add_subtree(ti, ett_forces); forces_main_header_tree = proto_tree_add_subtree(forces_tree, tvb, 0, ForCES_HEADER_LENGTH, ett_forces_main_header, NULL, "Common Header"); proto_tree_add_item(forces_main_header_tree, hf_forces_version, tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(forces_main_header_tree, hf_forces_rsvd, tvb, 0, 1, ENC_BIG_ENDIAN); message_type = tvb_get_guint8(tvb, offset+1); proto_tree_add_item( forces_main_header_tree, hf_forces_messagetype, tvb, offset+1, 1, ENC_BIG_ENDIAN); length_count = tvb_get_ntohs(tvb, offset+2) * 4; /*multiply 4 DWORD*/ ti = proto_tree_add_uint_format( forces_main_header_tree, hf_forces_length, tvb, offset+2, 2, length_count, "Length: %u Bytes", length_count); if (length_count != tvb_reported_length_remaining(tvb, offset)) expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is wrong),should be (%u bytes)", length_count, tvb_reported_length_remaining(tvb, offset)); if (length_count < 24) expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is less than 24bytes)", length_count); col_add_fstr(pinfo->cinfo, COL_INFO, "Message Type: %s, Total Length: %u Bytes", val_to_str(message_type, message_type_vals, "Unknown messagetype 0x%x"), length_count); proto_tree_add_item( forces_main_header_tree, hf_forces_sid, tvb, offset+4, 4, ENC_BIG_ENDIAN); proto_tree_add_item( forces_main_header_tree, hf_forces_did, tvb, offset+8, 4, ENC_BIG_ENDIAN); proto_tree_add_item( forces_main_header_tree, hf_forces_correlator, tvb, offset+12, 8, ENC_BIG_ENDIAN); /*Add flags tree*/ ti = proto_tree_add_item(forces_main_header_tree, hf_forces_flags, tvb, offset+20, 4, ENC_BIG_ENDIAN); forces_flags_tree = proto_item_add_subtree(ti, ett_forces_flags); proto_tree_add_item(forces_flags_tree, hf_forces_flags_ack, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_at, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_em, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_pri, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_reserved, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_rsrvd, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_tp, tvb, offset+20, 4, ENC_BIG_ENDIAN); offset += 24; while (tvb_reported_length_remaining(tvb, offset) >= TLV_TL_LENGTH) { forces_tlv_tree = proto_tree_add_subtree(forces_tree, tvb, offset, TLV_TL_LENGTH, ett_forces_tlv, &ti, "TLV"); tlv_type = tvb_get_ntohs(tvb, offset); tlv_item = proto_tree_add_item(forces_tlv_tree, hf_forces_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN); length_count = tvb_get_ntohs(tvb, offset+2) * 4; proto_item_set_len(ti, length_count); ti = proto_tree_add_uint(forces_tlv_tree, hf_forces_tlv_length, tvb, offset+2, 2, length_count); if (tvb_reported_length_remaining(tvb, offset) < length_count) expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus: Main TLV length (%u bytes) is wrong", length_count); if (length_count < TLV_TL_LENGTH) { expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus TLV length: %u", length_count); break; } offset += TLV_TL_LENGTH; length_count -= TLV_TL_LENGTH; switch(tlv_type) { case LFBselect_TLV: tlv_tree = proto_tree_add_subtree(forces_tlv_tree, tvb, offset, length_count, ett_forces_lfbselect_tlv_type, NULL, "LFB select TLV"); dissect_lfbselecttlv(tvb, pinfo, tlv_tree, offset, length_count); break; case REDIRECT_TLV: tlv_tree = proto_tree_add_subtree(forces_tlv_tree, tvb, offset, length_count, ett_forces_redirect_tlv_type, NULL, "Redirect TLV"); dissect_redirecttlv(tvb, pinfo, tlv_tree, offset); break; case ASResult_TLV: tlv_tree = proto_tree_add_subtree(forces_tlv_tree, tvb, offset, length_count, ett_forces_asresult_tlv, NULL, "ASResult TLV"); proto_tree_add_item(tlv_tree, hf_forces_asresult_association_setup_result, tvb, offset, 4, ENC_BIG_ENDIAN); break; case ASTreason_TLV: tlv_tree = proto_tree_add_subtree(forces_tlv_tree, tvb, offset, length_count, ett_forces_astreason_tlv, NULL, "ASTreason TLV"); proto_tree_add_item(tlv_tree, hf_forces_astreason_tlv_teardown_reason, tvb, offset, 4, ENC_BIG_ENDIAN); break; default: expert_add_info(pinfo, tlv_item, &ei_forces_tlv_type); tlv_tree = proto_tree_add_subtree(forces_tlv_tree, tvb, offset, length_count, ett_forces_unknown_tlv, NULL, "Unknown TLV"); proto_tree_add_item(tlv_tree, hf_forces_unknown_tlv, tvb, offset, length_count, ENC_NA); break; } offset += length_count; } }
/* 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 */ void fec_dissector(struct _fec_ptr f, tvbuff_t *tvb, proto_tree *tree, guint *offset) { proto_item *ti; proto_tree *fec_tree; guint offset_save = *offset; /* Create the FEC subtree */ if (tree) { ti = proto_tree_add_item(tree, f.hf->header, tvb, *offset, -1, FALSE); fec_tree = proto_item_add_subtree(ti, f.ett->main); } else { ti = NULL; fec_tree = NULL; } /* FEC Encoding ID and FEC Instance ID processing */ if (f.fec->encoding_id_present) { if (tree) { proto_tree_add_uint(fec_tree, f.hf->encoding_id, tvb, *offset, 0, f.fec->encoding_id); if (f.fec->encoding_id >= 128 && f.fec->instance_id_present) proto_tree_add_uint(fec_tree, f.hf->instance_id, tvb, *offset, 0, f.fec->instance_id); } switch (f.fec->encoding_id) { case 0: case 130: f.fec->sbn = tvb_get_ntohs(tvb, *offset); f.fec->esi = tvb_get_ntohs(tvb, *offset+2); if (tree) { proto_tree_add_uint(fec_tree, f.hf->sbn, tvb, *offset, 2, f.fec->sbn); proto_tree_add_uint(fec_tree, f.hf->esi, tvb, *offset+2, 2, f.fec->esi); } f.fec->sbn_present = TRUE; f.fec->esi_present = TRUE; *offset += 4; break; case 2: case 128: case 132: f.fec->sbn = tvb_get_ntohl(tvb, *offset); f.fec->esi = tvb_get_ntohl(tvb, *offset+4); if (tree) { proto_tree_add_uint(fec_tree, f.hf->sbn, tvb, *offset, 4, f.fec->sbn); proto_tree_add_uint(fec_tree, f.hf->esi, tvb, *offset+4, 4, f.fec->esi); } f.fec->sbn_present = TRUE; f.fec->esi_present = TRUE; *offset += 8; break; case 129: f.fec->sbn = tvb_get_ntohl(tvb, *offset); f.fec->sbl = tvb_get_ntohs(tvb, *offset+4); f.fec->esi = tvb_get_ntohs(tvb, *offset+6); if (tree) { proto_tree_add_uint(fec_tree, f.hf->sbn, tvb, *offset, 4, f.fec->sbn); proto_tree_add_uint(fec_tree, f.hf->sbl, tvb, *offset+4, 2, f.fec->sbl); proto_tree_add_uint(fec_tree, f.hf->esi, tvb, *offset+6, 2, f.fec->esi); } f.fec->sbn_present = TRUE; f.fec->sbl_present = TRUE; f.fec->esi_present = TRUE; *offset += 8; break; } } if (tree) proto_item_set_len(ti, *offset - offset_save); }
/* * Returns TRUE if there's a User Information field in this SPDU, FALSE * otherwise. */ static gboolean dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree, proto_tree *ses_tree, packet_info *pinfo, guint8 *enclosure_item_flags, struct SESSION_DATA_STRUCTURE *session) { gboolean has_user_information = TRUE; proto_item *ti; proto_tree *param_tree; guint8 param_type; const char *param_str; int len_len; guint16 param_len; while (len != 0) { param_type = tvb_get_guint8(tvb, offset); param_tree = proto_tree_add_subtree(ses_tree, tvb, offset, -1, ett_ses_param, &ti, val_to_str(param_type, param_vals, "Unknown parameter type (0x%02x)")); param_str = val_to_str_const(param_type, param_vals, "Unknown"); proto_tree_add_text(param_tree, tvb, offset, 1, "Parameter type: %s", param_str); offset++; len--; param_len = get_item_len(tvb, offset, &len_len); if (len_len > len) { proto_item_set_len(ti, len + 1 ); proto_tree_add_text(param_tree, tvb, offset, len, "Parameter length doesn't fit in parameter"); return has_user_information; } len -= len_len; if (param_len > len) { proto_item_set_len(ti, len + 1 + len_len); proto_tree_add_text(param_tree, tvb, offset, len, "Parameter length: %u, should be <= %u", param_len, len); return has_user_information; } proto_item_set_len(ti, 1 + len_len + param_len); proto_tree_add_text(param_tree, tvb, offset, len_len, "Parameter length: %u", param_len); offset += len_len; if (param_str != NULL) { switch(param_type) { case Extended_User_Data: call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); break; case User_Data: call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); break; /* handle PGI's */ case Connect_Accept_Item: case Connection_Identifier: case Linking_Information: /* Yes. */ if (!dissect_parameter_group(tvb, offset, tree, param_tree, pinfo, param_len, enclosure_item_flags, session)) has_user_information = FALSE; break; /* everything else is a PI */ default: if (!dissect_parameter(tvb, offset, tree, param_tree, pinfo, param_type, param_len, enclosure_item_flags, session)) has_user_information = FALSE; break; } } offset += param_len; len -= param_len; } return has_user_information; }