static void dissect_componentstatusprotocol_componentstatusreport_message(tvbuff_t *message_tvb, proto_tree *message_tree) { tvbuff_t *association_tvb; proto_tree *association_tree; /* gint associations; - variable set but not used, so commented out */ int i; gint offset; proto_tree_add_item(message_tree, hf_componentstatusreport_reportinterval, message_tvb, COMPONENTSTATUSREPORT_REPORTINTERVAL_OFFSET, COMPONENTSTATUSREPORT_REPORTINTERVAL_LENGTH, ENC_BIG_ENDIAN); proto_tree_add_item(message_tree, hf_componentstatusreport_location, message_tvb, COMPONENTSTATUSREPORT_LOCATION_OFFSET, COMPONENTSTATUSREPORT_LOCATION_LENGTH, ENC_ASCII|ENC_NA); proto_tree_add_item(message_tree, hf_componentstatusreport_status, message_tvb, COMPONENTSTATUSREPORT_STATUS_OFFSET, COMPONENTSTATUSREPORT_STATUS_LENGTH, ENC_ASCII|ENC_NA); proto_tree_add_item(message_tree, hf_componentstatusreport_workload, message_tvb, COMPONENTSTATUSREPORT_WORKLOAD_OFFSET, COMPONENTSTATUSREPORT_WORKLOAD_LENGTH, ENC_BIG_ENDIAN); proto_tree_add_item(message_tree, hf_componentstatusreport_associations, message_tvb, COMPONENTSTATUSREPORT_ASSOCIATIONS_OFFSET, COMPONENTSTATUSREPORT_ASSOCIATIONS_LENGTH, ENC_BIG_ENDIAN); /* associations = tvb_get_ntohs(message_tvb, COMPONENTSTATUSREPORT_ASSOCIATIONS_OFFSET); */ offset = COMPONENTSTATUSREPORT_ASSOCIATIONARRAY_OFFSET; i = 1; while(tvb_reported_length_remaining(message_tvb, offset) >= COMPONENTASSOCIATION_LENGTH) { association_tree = proto_tree_add_subtree_format(message_tree, message_tvb, offset, COMPONENTASSOCIATION_LENGTH, ett_association, NULL, "Association #%d", i++); association_tvb = tvb_new_subset_length_caplen(message_tvb, offset, MIN(COMPONENTASSOCIATION_LENGTH, tvb_reported_length_remaining(message_tvb, offset)), COMPONENTASSOCIATION_LENGTH); dissect_componentstatusprotocol_componentassociation_message(association_tvb, association_tree); offset += COMPONENTASSOCIATION_LENGTH; } }
static int krb5rpc_dissect_sendto_kdc_rqst (tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, dcerpc_info *di, guint8 *drep) { guint32 keysize, spare1, remain; proto_item *item; tvbuff_t *krb5_tvb; proto_tree *subtree; /* * [in] handle_t h, * [in] unsigned32 len, * [in, size_is(len)] * byte message[], * [in] unsigned32 out_buf_len, */ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_krb5rpc_sendto_kdc_rqst_keysize, &keysize); offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_krb5rpc_sendto_kdc_rqst_spare1, &spare1); item = proto_tree_add_item (tree, hf_krb5rpc_krb5, tvb, offset, -1, ENC_NA); subtree = proto_item_add_subtree (item, ett_krb5rpc_krb5); remain = tvb_captured_length_remaining(tvb, offset); krb5_tvb = tvb_new_subset_length_caplen (tvb, offset, remain, remain); offset = dissect_kerberos_main (krb5_tvb, pinfo, subtree, TRUE, NULL); return offset; }
static int krb5rpc_dissect_sendto_kdc_resp (tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, dcerpc_info *di, guint8 *drep) { guint32 resp_len, maxsize, spare1, keysize, remain; proto_item *item; tvbuff_t *krb5_tvb; proto_tree *subtree; /* * * [out] unsigned32 *resp_len, * [out, length_is(*resp_len), size_is(out_buf_len)] * byte out_buf[], * [out] error_status_t *st unsigned long * */ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_krb5rpc_sendto_kdc_resp_len, &resp_len); offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_krb5rpc_sendto_kdc_resp_max, &maxsize); offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_krb5rpc_sendto_kdc_resp_spare1, &spare1); offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_krb5rpc_sendto_kdc_resp_keysize, &keysize); item = proto_tree_add_item (tree, hf_krb5rpc_krb5, tvb, offset, -1, ENC_NA); subtree = proto_item_add_subtree (item, ett_krb5rpc_krb5); remain = tvb_captured_length_remaining(tvb, offset); krb5_tvb = tvb_new_subset_length_caplen (tvb, offset, remain, remain); offset = dissect_kerberos_main (krb5_tvb, pinfo, subtree, TRUE, NULL); offset += 16; /* no idea what this is, probably just extended encrypted text. */ return offset; }
static void gcsna_message_GCSNA1xCircuitService(proto_item *item, tvbuff_t *tvb, packet_info *pinfo, proto_tree *mainTree, proto_tree *tree, guint *offset) { guint16 alt_gcsna_incl = 0, num_alt_gcsna_opt = -1, iws_incl = 0; guint8 num_res; guint bit_offset = *offset * 8; proto_tree *subtree = NULL; tvbuff_t *new_tvb; /* GCSNAOption 8 bits */ item = proto_tree_add_item(tree, hf_gcsna_gcsna_option, tvb, *offset, 1, ENC_BIG_ENDIAN); subtree = proto_item_add_subtree(item, ett_gcsna_option); proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClass, tvb, bit_offset, 5, ENC_BIG_ENDIAN); bit_offset += 5; proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClassRev, tvb, bit_offset, 3, ENC_BIG_ENDIAN); bit_offset += 3; alt_gcsna_incl = tvb_get_bits8(tvb, bit_offset, 1); proto_tree_add_bits_item(subtree, hf_gcsna_altGCSNAOptionIncluded, tvb, bit_offset, 1, ENC_BIG_ENDIAN); bit_offset += 1; if (alt_gcsna_incl) { num_alt_gcsna_opt = tvb_get_bits8(tvb, bit_offset, 8); proto_tree_add_bits_item(subtree, hf_gcsna_NumaltGCSNAOption, tvb, bit_offset, 8, ENC_BIG_ENDIAN); bit_offset += 8; while (num_alt_gcsna_opt != 0) { proto_tree_add_bits_item(subtree, hf_gcsna_altGCSNAOption, tvb, bit_offset, 8, ENC_BIG_ENDIAN); bit_offset += 8; num_alt_gcsna_opt--; } } iws_incl = tvb_get_bits8(tvb, bit_offset, 1); proto_tree_add_bits_item(subtree, hf_gcsna_iwsidIncluded, tvb, bit_offset, 1, ENC_BIG_ENDIAN); bit_offset++; if (iws_incl) { proto_tree_add_bits_item(subtree, hf_gcsna_iwsidValue, tvb, bit_offset, 16, ENC_BIG_ENDIAN); bit_offset += 16; } proto_tree_add_bits_item(subtree, hf_gcsna_ackRequired, tvb, bit_offset, 1, ENC_BIG_ENDIAN); bit_offset++; proto_tree_add_bits_item(subtree, hf_gcsna_stopDupDetect, tvb, bit_offset, 1, ENC_BIG_ENDIAN); bit_offset++; proto_tree_add_bits_item(subtree, hf_gcsna_msgSequence, tvb, bit_offset, 6, ENC_BIG_ENDIAN); bit_offset += 6; proto_tree_add_bits_item(subtree, hf_gcsna_NumTLACEncapsulated1xL3PDU, tvb, bit_offset, 2, ENC_BIG_ENDIAN); bit_offset += 2; /* The sender shall include reserved bits to make this message integral number of octets up to TLACEncapsulated1xL3PDU field. * The sender 5 shall set all bits in this field to '0'. The receiver shall ignore this field. */ /* calculate number of reserved bits */ num_res = 8 - (bit_offset & 0x3); proto_tree_add_bits_item(subtree, hf_gcsna_tlacReserved, tvb, bit_offset, num_res, ENC_BIG_ENDIAN); bit_offset = bit_offset + num_res; *offset = bit_offset >> 3; proto_tree_add_item(subtree, hf_gcsna_tlacEncapsulated, tvb, *offset, -1, ENC_NA); if (cdma2k_handle) { new_tvb = tvb_new_subset_length_caplen(tvb, *offset, -1, -1); call_dissector(cdma2k_handle, new_tvb, pinfo, mainTree); } /* set the offset to the end of the message */ *offset += tvb_reported_length_remaining(tvb, *offset); }
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 gint dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *arg0_item; proto_tree *arg0_tree; proto_item *arg1_item; proto_tree *arg1_tree; proto_item *magic_item; proto_item *crc_item; proto_tree *crc_tree = NULL; proto_item *sub_item; gint offset = 0; guint32 command; guint32 arg0; guint32 arg1; guint32 data_length = 0; guint32 crc32 = 0; usb_conv_info_t *usb_conv_info = NULL; wmem_tree_key_t key[5]; guint32 interface_id; guint32 bus_id; guint32 device_address; guint32 side_id; guint32 frame_number; gboolean is_command = TRUE; gboolean is_next_fragment = FALSE; gboolean is_service = FALSE; gint proto; gint direction = P2P_DIR_UNKNOWN; wmem_tree_t *wmem_tree; command_data_t *command_data = NULL; service_data_t *service_data = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ADB"); col_clear(pinfo->cinfo, COL_INFO); main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_adb); frame_number = pinfo->num; /* XXX: Why? If interface is USB only first try is correct * (and seems strange...), in other cases standard check for * previous protocol is correct */ proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers)))); if (proto != proto_usb) { proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers)))); } if (proto == proto_usb) { usb_conv_info = (usb_conv_info_t *) data; DISSECTOR_ASSERT(usb_conv_info); direction = usb_conv_info->direction; } else if (proto == proto_tcp) { if (pinfo->destport == ADB_TCP_PORT) direction = P2P_DIR_SENT; else direction = P2P_DIR_RECV; } else { return offset; } if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) interface_id = pinfo->phdr->interface_id; else interface_id = 0; if (proto == proto_usb) { bus_id = usb_conv_info->bus_id; device_address = usb_conv_info->device_address; key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[1].key = &bus_id; key[2].length = 1; key[2].key = &device_address; key[3].length = 0; key[3].key = NULL; } else { /* tcp */ key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[2].length = 1; if (direction == P2P_DIR_SENT) { key[1].key = &pinfo->srcport; key[2].key = &pinfo->destport; } else { key[1].key = &pinfo->destport; key[2].key = &pinfo->srcport; } key[3].length = 0; key[3].key = NULL; } wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key); if (wmem_tree) { command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (command_data && command_data->completed_in_frame >= frame_number && command_data->command_in_frame <= frame_number) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if (direction == P2P_DIR_SENT) { if (command_data->command == A_CLSE) side_id = command_data->arg1; /* OUT: local id */ else side_id = command_data->arg0; /* OUT: local id */ } else { side_id = command_data->arg1; /* IN: remote id */ } key[3].length = 1; key[3].key = &side_id; key[4].length = 0; key[4].key = NULL; wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key); if (wmem_tree) { service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (service_data && command_data->command == A_OPEN) { is_service = TRUE; } } } } /* Simple heuristics to check if packet is command or data */ if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) { if (tvb_reported_length(tvb) < 24) { is_command = FALSE; } else if (tvb_reported_length(tvb) >= 24) { command = tvb_get_letohl(tvb, offset); if (command != A_SYNC && command != A_CLSE && command != A_WRTE && command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY) is_command = FALSE; else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20))) is_command = FALSE; if (is_command) { data_length = tvb_get_letohl(tvb, offset + 12); crc32 = tvb_get_letohl(tvb, offset + 16); } if (command == A_OPEN) is_service = TRUE; } } if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) { sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data) { sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); if (service_data->close_local_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data->close_remote_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } } if (is_command) { proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN); command = tvb_get_letohl(tvb, offset); offset += 4; col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command")); arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0); arg0 = tvb_get_letohl(tvb, offset); offset += 4; arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1); arg1 = tvb_get_letohl(tvb, offset); offset += 4; switch (command) { case A_CNXN: proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4)); break; case A_AUTH: proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown")); break; case A_OPEN: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8)); break; case A_WRTE: proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4)); break; case A_CLSE: case A_OKAY: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4)); break; case A_SYNC: proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4)); break; } proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (data_length > 0) col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length); crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); crc32 = tvb_get_letohl(tvb, offset); offset += 4; magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN); if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) { proto_tree *expert_tree; expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic); proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4); } if (!pinfo->fd->flags.visited) save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data); offset += 4; } if (!pinfo->fd->flags.visited && command_data) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) || (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24) ) { command_data->reassemble_data_length = command_data->data_length; command_data->completed_in_frame = frame_number; } } if (is_next_fragment && command_data) { sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length); PROTO_ITEM_SET_GENERATED(sub_item); crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); PROTO_ITEM_SET_GENERATED(crc_item); } if (command_data && command_data->completed_in_frame != frame_number) { sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) { guint32 crc = 0; guint32 i_offset; if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */ if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) { tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset)); command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset); if (command_data->reassemble_data_length >= command_data->data_length) command_data->completed_in_frame = frame_number; } proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment"); offset = tvb_captured_length(tvb); if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length); add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data"); adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } } else { /* full message */ for (i_offset = 0; i_offset < data_length; ++i_offset) crc += tvb_get_guint8(tvb, offset + i_offset); if (crc32 > 0 && crc32 != crc) proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1); if (is_service) { proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA); if (!pinfo->fd->flags.visited && service_data) { service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII); } col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII)); offset = tvb_captured_length(tvb); } else if (command_data && command_data->command == A_CNXN) { gchar *info; gint len; info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info); proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA); offset += len; } else { col_append_str(pinfo->cinfo, COL_INFO, "Data"); /* Decode service payload */ if (service_data) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset)); call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } else { proto_item *data_item; gchar *data_str; data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA); data_str = tvb_format_text(tvb, offset, data_length); proto_item_append_text(data_item, ": %s", data_str); col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str); } offset = tvb_captured_length(tvb); } } } return offset; }
/* * Dissect TPKT-encapsulated data in a TCP stream. */ void dissect_tpkt_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean desegment, dissector_handle_t subdissector_handle) { proto_item *ti = NULL; proto_tree *tpkt_tree = NULL; volatile int offset = 0; int length_remaining; int data_len; volatile int length; tvbuff_t *volatile next_tvb; const char *saved_proto; /* * If we're reassembling segmented TPKT PDUs, empty the COL_INFO * column, so subdissectors can append information * without having to worry about emptying the column. * * We use "col_add_str()" because the subdissector * might be appending information to the column, in * which case we'd have to zero the buffer out explicitly * anyway. */ if (desegment) col_set_str(pinfo->cinfo, COL_INFO, ""); while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * Is the first byte of this putative TPKT header * a valid TPKT version number, i.e. 3? */ if (tvb_get_guint8(tvb, offset) != 3) { /* * No, so don't assume this is a TPKT header; * we might be in the middle of TPKT data, * so don't get the length and don't try to * do reassembly. */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, -1, ENC_NA); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA); } return; } length_remaining = tvb_captured_length_remaining(tvb, offset); /* * Can we do reassembly? */ if (desegment && pinfo->can_desegment) { /* * Yes - is the TPKT header split across segment * boundaries? */ if (length_remaining < 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; return; } } /* * Get the length from the TPKT header. */ data_len = tvb_get_ntohs(tvb, offset + 2); /* * Can we do reassembly? */ if (desegment && pinfo->can_desegment) { /* * Yes - is the payload split across segment * boundaries? */ if (length_remaining < data_len) { /* * Yes. Tell the TCP dissector where * the data for this message starts in * the data it handed us, and how many * more bytes we need, and return. */ pinfo->desegment_offset = offset; pinfo->desegment_len = data_len - length_remaining; return; } } /* * Dissect the TPKT header. * Save and restore "pinfo->current_proto". */ saved_proto = pinfo->current_proto; pinfo->current_proto = "TPKT"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); /* * Don't add the TPKT header information if we're * reassembling segmented TPKT PDUs or if this * PDU isn't reassembled. * * XXX - the first is so that subdissectors can append * information without getting TPKT stuff in the middle; * why the second? */ if (!desegment && !pinfo->fragmented) { col_add_fstr(pinfo->cinfo, COL_INFO, "TPKT Data length = %u", data_len); } if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, 4, ENC_NA); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_item_set_text(ti, "TPKT"); /* Version */ proto_tree_add_item(tpkt_tree, hf_tpkt_version, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(ti, ", Version: 3"); /* Reserved octet*/ proto_tree_add_item(tpkt_tree, hf_tpkt_reserved, tvb, offset + 1, 1, ENC_BIG_ENDIAN); /* Length */ proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb, offset + 2, 2, data_len); proto_item_append_text(ti, ", Length: %u", data_len); } pinfo->current_proto = saved_proto; /* Skip the TPKT header. */ offset += 4; data_len -= 4; /* * Construct a tvbuff containing the amount of the payload * we have available. Make its reported length the * amount of data in this TPKT packet. * * XXX - if reassembly isn't enabled. the subdissector * will throw a BoundsError exception, rather than a * ReportedBoundsError exception. We really want * a tvbuff where the length is "length", the reported * length is "plen + 2", and the "if the snapshot length * were infinite" length were the minimum of the * reported length of the tvbuff handed to us and "plen+2", * with a new type of exception thrown if the offset is * within the reported length but beyond that third length, * with that exception getting the "Unreassembled Packet" * error. */ length = length_remaining - 4; if (length > data_len) length = data_len; next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, data_len); /* * Call the subdissector. * * If it gets an error that means there's no point in * dissecting any more TPKT messages, rethrow the * exception in question. * * If it gets any other error, report it and continue, * as that means that TPKT message got an error, but * that doesn't mean we should stop dissecting TPKT * messages within this frame or chunk of reassembled * data. */ TRY { call_dissector(subdissector_handle, next_tvb, pinfo, tree); } CATCH_NONFATAL_ERRORS { show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; /* * Skip the payload. */ offset += length; } }
/* * Dissect ASCII TPKT-encapsulated data in a TCP stream. */ void dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, dissector_handle_t subdissector_handle) { proto_item *ti = NULL; proto_tree *tpkt_tree = NULL; volatile int offset = 0; int length_remaining; int data_len; volatile int mgcp_packet_len = 0; int mgcp_version = 0; int mgcp_reserved = 0; volatile int length; tvbuff_t *volatile next_tvb; const char *saved_proto; guint8 string[4]; /* * If we're reassembling segmented TPKT PDUs, empty the COL_INFO * column, so subdissectors can append information * without having to worry about emptying the column. * * We use "col_add_str()" because the subdissector * might be appending information to the column, in * which case we'd have to zero the buffer out explicitly * anyway. */ if (tpkt_desegment) col_set_str(pinfo->cinfo, COL_INFO, ""); while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * Is the first byte of this putative TPKT header * a valid TPKT version number, i.e. 3? */ if (tvb_get_guint8(tvb, offset) != 48) { /* * No, so don't assume this is a TPKT header; * we might be in the middle of TPKT data, * so don't get the length and don't try to * do reassembly. */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, -1, ENC_NA); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_tree_add_item(tpkt_tree, hf_tpkt_continuation_data, tvb, offset, -1, ENC_NA); } return; } length_remaining = tvb_captured_length_remaining(tvb, offset); /* * Get the length from the TPKT header. */ tvb_memcpy(tvb, (guint8 *)string, offset, 2); mgcp_version = parseVersionText(string); tvb_memcpy(tvb, (guint8 *)string, offset +2, 2); mgcp_reserved = parseReservedText(string); tvb_memcpy(tvb, (guint8 *)string, offset + 4, 4); mgcp_packet_len = parseLengthText(string); data_len = mgcp_packet_len; /* * Dissect the TPKT header. * Save and restore "pinfo->current_proto". */ saved_proto = pinfo->current_proto; pinfo->current_proto = "TPKT"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); /* * Don't add the TPKT header information if we're * reassembling segmented TPKT PDUs or if this * PDU isn't reassembled. * * XXX - the first is so that subdissectors can append * information without getting TPKT stuff in the middle; * why the second? */ if (!tpkt_desegment && !pinfo->fragmented) { col_add_fstr(pinfo->cinfo, COL_INFO, "TPKT Data length = %u", data_len); } if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, 8, ENC_NA); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_item_set_text(ti, "TPKT"); /* Version */ proto_tree_add_uint(tpkt_tree, hf_tpkt_version, tvb, offset, 2, mgcp_version); /* Reserved octet*/ proto_tree_add_uint(tpkt_tree, hf_tpkt_reserved, tvb, offset + 2, 2, mgcp_reserved); /* Length */ proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb, offset + 4, 4, mgcp_packet_len); } pinfo->current_proto = saved_proto; /* Skip the TPKT header. */ offset += TEXT_LAYER_LENGTH; length = length_remaining - TEXT_LAYER_LENGTH; if (length > data_len) length = data_len; next_tvb = tvb_new_subset_length_caplen(tvb, offset,length, data_len); /* * Call the subdissector. * * If it gets an error that means there's no point in * dissecting any more TPKT messages, rethrow the * exception in question. * * If it gets any other error, report it and continue, as that * means that TPKT message got an error, but that doesn't mean * we should stop dissecting TPKT messages within this frame * or chunk of reassembled data. */ TRY { call_dissector(subdissector_handle, next_tvb, pinfo, tree); } CATCH_NONFATAL_ERRORS { show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; /* * Skip the payload. */ offset += data_len; } }
static void dissect_rpl_container(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 len, type, sublen, subtyp; proto_tree *rpl_container_tree; guint16 offset; gint ett_type; gint length, reported_length; len = tvb_get_ntohs(tvb, 0); proto_tree_add_item(tree, hf_rpl_len, tvb, 0, 2, ENC_BIG_ENDIAN); type = tvb_get_ntohs(tvb, 2); proto_tree_add_item(tree, hf_rpl_type, tvb, 2, 2, ENC_BIG_ENDIAN); offset = 4; switch (type) { case 1: case 2: case 4: case 8: case 0x10: case 0x20: while (len >= offset+4) { sublen = tvb_get_ntohs(tvb, offset); subtyp = tvb_get_ntohs(tvb, offset+2); ett_type = ett_rpl_unkn; if(subtyp == 0x0004) ett_type = ett_rpl_0004; if(subtyp == 0x0008) ett_type = ett_rpl_0008; if(subtyp == 0x4003) ett_type = ett_rpl_4003; if(subtyp == 0x4006) ett_type = ett_rpl_4006; if(subtyp == 0x4007) ett_type = ett_rpl_4007; if(subtyp == 0x4009) ett_type = ett_rpl_4009; if(subtyp == 0x400a) ett_type = ett_rpl_400a; if(subtyp == 0x400b) ett_type = ett_rpl_400b; if(subtyp == 0x400c) ett_type = ett_rpl_400c; if(subtyp == 0x4011) ett_type = ett_rpl_4011; if(subtyp == 0x4018) ett_type = ett_rpl_4018; if(subtyp == 0xc005) ett_type = ett_rpl_c005; if(subtyp == 0xc014) ett_type = ett_rpl_c014; rpl_container_tree = proto_tree_add_subtree(tree, tvb, offset, sublen, ett_type, NULL, val_to_str_const(subtyp, rpl_type_vals, "Unknown Type")); length = tvb_captured_length_remaining(tvb, offset); if (length > sublen) length = sublen; reported_length = tvb_reported_length_remaining(tvb, offset); if (reported_length > sublen) reported_length = sublen; if ( length > 0) { dissect_rpl_container(tvb_new_subset_length_caplen(tvb, offset, length, reported_length), pinfo, rpl_container_tree); offset += reported_length; } else { /* no more data, exit the loop */ offset += reported_length; break; } } break; case 0x4003: proto_tree_add_item(tree, hf_rpl_corrval, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case 0x4006: proto_tree_add_item(tree, hf_rpl_lmac, tvb, offset, 6, ENC_NA); offset += 6; break; case 0x4007: proto_tree_add_item(tree, hf_rpl_sap, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; break; case 0x4009: proto_tree_add_item(tree, hf_rpl_maxframe, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; case 0x400a: proto_tree_add_item(tree, hf_rpl_connclass, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; case 0x400b: proto_tree_add_item(tree, hf_rpl_respval, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; break; case 0x400c: proto_tree_add_item(tree, hf_rpl_smac, tvb, offset, 6, ENC_NA); offset += 6; break; case 0x4011: proto_tree_add_item(tree, hf_rpl_sequence, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case 0x4018: proto_tree_add_item(tree, hf_rpl_data, tvb, offset, len-4, ENC_NA); offset += len - 4; break; case 0xc005: proto_tree_add_item(tree, hf_rpl_config, tvb, offset, 8, ENC_NA); offset += 8; proto_tree_add_item(tree, hf_rpl_equipment, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_memsize, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_bsmversion, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_ec, tvb, offset, 6, ENC_NA); offset += 6; proto_tree_add_item(tree, hf_rpl_adapterid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_shortname, tvb, offset, 10, ENC_NA); offset += 10; break; case 0xc014: proto_tree_add_item(tree, hf_rpl_laddress, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_rpl_xaddress, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_rpl_flags, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; break; default: call_data_dissector(tvb_new_subset_remaining(tvb, 4), pinfo, tree); break; } if (tvb_reported_length(tvb) > offset) call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree); }
/* * Function for AVP dissector. */ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree) { gint offset; guint16 avp_code; guint16 avp_flags; guint32 avp_length; guint16 avp_type; guint32 vendor_id; guint32 avp_hdr_length; guint32 avp_data_length, result_code; guint32 padding; gint32 buffer_length; tvbuff_t *group_tvb; tvbuff_t *eap_tvb; tvbuff_t *encap_tvb; proto_tree *single_avp_tree; proto_tree *avp_eap_tree; proto_tree *avp_encap_tree; offset = 0; buffer_length = tvb_reported_length(tvb); /* Go through all AVPs */ while (buffer_length > 0) { avp_code = tvb_get_ntohs(tvb, offset); avp_flags = tvb_get_ntohs(tvb, offset + 2); avp_data_length = tvb_get_ntohs(tvb, offset + 4); /* Check AVP flags for vendor specific AVP */ if (avp_flags & PANA_AVP_FLAG_V) { vendor_id = tvb_get_ntohl(tvb, 8); avp_hdr_length = 12; } else { vendor_id = 0; avp_hdr_length = 8; } avp_length = avp_hdr_length + avp_data_length; /* Check AVP type */ avp_type = pana_avp_get_type(avp_code, vendor_id); /* Check padding */ padding = (4 - (avp_length % 4)) % 4; single_avp_tree = proto_tree_add_subtree_format(avp_tree, tvb, offset, avp_length + padding, ett_pana_avp_info, NULL, "%s (%s) length: %d bytes (%d padded bytes)", val_to_str(avp_code, avp_code_names, "Unknown (%d)"), val_to_str(avp_type, avp_type_names, "Unknown (%d)"), avp_length, avp_length + padding); /* AVP Code */ proto_tree_add_uint_format_value(single_avp_tree, hf_pana_avp_code, tvb, offset, 2, avp_code, "%s (%u)", val_to_str(avp_code, avp_code_names, "Unknown (%d)"), avp_code); offset += 2; /* AVP Flags */ dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags); offset += 2; /* AVP Length */ proto_tree_add_item(single_avp_tree, hf_pana_avp_data_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Reserved */ proto_tree_add_item(single_avp_tree, hf_pana_avp_reserved, tvb, offset, 2, ENC_NA); offset += 2; if (avp_flags & PANA_AVP_FLAG_V) { /* Vendor ID */ proto_tree_add_item(single_avp_tree, hf_pana_avp_vendorid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } if (! (avp_flags & PANA_AVP_FLAG_V)) { /* AVP Value */ switch(avp_type) { case PANA_GROUPED: { proto_tree *avp_group_tree; avp_group_tree = proto_tree_add_subtree(single_avp_tree, tvb, offset, avp_data_length, ett_pana_avp, NULL, "Grouped AVP"); group_tvb = tvb_new_subset_length_caplen(tvb, offset, MIN(avp_data_length, tvb_reported_length(tvb)-offset), avp_data_length); dissect_avps(group_tvb, pinfo, avp_group_tree); break; } case PANA_UTF8STRING: { proto_tree_add_item(single_avp_tree, hf_pana_avp_data_string, tvb, offset, avp_data_length, ENC_UTF_8|ENC_NA); break; } case PANA_OCTET_STRING: { proto_tree_add_item(single_avp_tree, hf_pana_avp_data_bytes, tvb, offset, avp_data_length, ENC_NA); break; } case PANA_INTEGER32: { proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int32, tvb, offset, 4, ENC_BIG_ENDIAN); break; } case PANA_UNSIGNED32: { proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint32, tvb, offset, 4, ENC_BIG_ENDIAN); break; } case PANA_INTEGER64: { proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int64, tvb, offset, 8, ENC_BIG_ENDIAN); break; } case PANA_UNSIGNED64: { proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint64, tvb, offset, 8, ENC_BIG_ENDIAN); break; } case PANA_ENUMERATED: { proto_tree_add_item(single_avp_tree, hf_pana_avp_data_enumerated, tvb, offset, 4, ENC_BIG_ENDIAN); break; } case PANA_RESULT_CODE: { result_code = tvb_get_ntohl(tvb, offset); proto_tree_add_uint_format(single_avp_tree, hf_pana_avp_code, tvb, offset, avp_data_length, result_code, "Value: %d (%s)", result_code, val_to_str(result_code, avp_code_names, "Unknown (%d)")); break; } case PANA_EAP: { avp_eap_tree = proto_tree_add_subtree(single_avp_tree, tvb, offset, avp_data_length, ett_pana_avp, NULL, "AVP Value (EAP packet)"); eap_tvb = tvb_new_subset_length(tvb, offset, avp_data_length); DISSECTOR_ASSERT_HINT(eap_handle, "EAP Dissector not available"); call_dissector(eap_handle, eap_tvb, pinfo, avp_eap_tree); break; } case PANA_ENCAPSULATED: { avp_encap_tree = proto_tree_add_subtree(single_avp_tree, tvb, offset, avp_data_length, ett_pana_avp, NULL, "AVP Value (PANA packet)"); encap_tvb = tvb_new_subset_length(tvb, offset, avp_data_length); dissect_pana_pdu(encap_tvb, pinfo, avp_encap_tree); break; } } } offset += avp_data_length + padding; /* Update the buffer length */ buffer_length -= avp_length + padding; } }
static void display_xip_serval(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *xip_serval_tree; proto_item *ti, *hl_ti; tvbuff_t *next_tvb; vec_t cksum_vec; gint offset; guint8 xsh_len, protocol, bytes_remaining; /* Get XIP Serval header length, stored as number of 32-bit words. */ xsh_len = tvb_get_guint8(tvb, XSRVL_LEN) << 2; /* Create XIP Serval header tree. */ ti = proto_tree_add_item(tree, proto_xip_serval, tvb, 0, xsh_len, ENC_NA); xip_serval_tree = proto_item_add_subtree(ti, ett_xip_serval_tree); /* Add XIP Serval header length. */ hl_ti = proto_tree_add_item(xip_serval_tree, hf_xip_serval_hl, tvb, XSRVL_LEN, 1, ENC_BIG_ENDIAN); if (tvb_captured_length(tvb) < xsh_len) expert_add_info_format(pinfo, hl_ti, &ei_xip_serval_bad_len, "Header Length field (%d bytes) cannot be greater than actual number of bytes left in packet (%d bytes)", xsh_len, tvb_captured_length(tvb)); /* Add XIP Serval protocol. If it's not data, TCP, or UDP, the * packet is malformed. */ proto_tree_add_item(xip_serval_tree, hf_xip_serval_proto, tvb, XSRVL_PRO, 1, ENC_BIG_ENDIAN); protocol = tvb_get_guint8(tvb, XSRVL_PRO); if (!try_val_to_str(protocol, xip_serval_proto_vals)) expert_add_info_format(pinfo, ti, &ei_xip_serval_bad_proto, "Unrecognized protocol type: %d", protocol); /* Compute checksum. */ SET_CKSUM_VEC_TVB(cksum_vec, tvb, 0, xsh_len); proto_tree_add_checksum(xip_serval_tree, tvb, XSRVL_CHK, hf_xip_serval_check, hf_xip_serval_check_status, &ei_xip_serval_bad_checksum, pinfo, in_cksum(&cksum_vec, 1), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM); offset = XSRVL_EXT; /* If there's still more room, check for extension headers. */ bytes_remaining = xsh_len - offset; while (bytes_remaining >= XIP_SERVAL_EXT_MIN_LEN) { gint8 bytes_displayed = display_xip_serval_ext(tvb, pinfo, ti, xip_serval_tree, offset); /* Extension headers are malformed, so we can't say * what the rest of the packet holds. Stop dissecting. */ if (bytes_displayed <= 0) return; offset += bytes_displayed; bytes_remaining -= bytes_displayed; } switch (protocol) { case XIP_SERVAL_PROTO_DATA: next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, tree); break; case IP_PROTO_TCP: { /* Get the Data Offset field of the TCP header, which is * the high nibble of the 12th octet and represents the * size of the TCP header of 32-bit words. */ guint8 tcp_len = hi_nibble(tvb_get_guint8(tvb, offset + 12))*4; next_tvb = tvb_new_subset_length_caplen(tvb, offset, tcp_len, tcp_len); call_dissector(tcp_handle, next_tvb, pinfo, tree); break; } case IP_PROTO_UDP: /* The UDP header is always 8 bytes. */ next_tvb = tvb_new_subset_length_caplen(tvb, offset, 8, 8); call_dissector(udp_handle, next_tvb, pinfo, tree); break; default: break; } }