static void mate_pdu_tree(mate_pdu *pdu, tvbuff_t *tvb, proto_tree* tree) { proto_item *pdu_item; proto_tree *pdu_tree; if ( ! pdu ) return; if (pdu->gop && pdu->gop->gog) { proto_item_append_text(mate_i," %s:%d->%s:%d->%s:%d", pdu->cfg->name,pdu->id, pdu->gop->cfg->name,pdu->gop->id, pdu->gop->gog->cfg->name,pdu->gop->gog->id); } else if (pdu->gop) { proto_item_append_text(mate_i," %s:%d->%s:%d", pdu->cfg->name,pdu->id, pdu->gop->cfg->name,pdu->gop->id); } else { proto_item_append_text(mate_i," %s:%d",pdu->cfg->name,pdu->id); } pdu_item = proto_tree_add_uint(tree,pdu->cfg->hfid,tvb,0,0,pdu->id); pdu_tree = proto_item_add_subtree(pdu_item, pdu->cfg->ett); proto_tree_add_float(pdu_tree,pdu->cfg->hfid_pdu_rel_time, tvb, 0, 0, pdu->rel_time); if (pdu->gop) { proto_tree_add_float(pdu_tree,pdu->cfg->hfid_pdu_time_in_gop, tvb, 0, 0, pdu->time_in_gop); mate_gop_tree(tree,tvb,pdu->gop); if (pdu->gop->gog) mate_gog_tree(tree,tvb,pdu->gop->gog,pdu->gop); } if (pdu->avpl) { pdu_attrs_tree(pdu_tree,tvb,pdu); } }
bool dissect_protobuf_field(const FieldDescriptor* field, const Message* message, tvbuff_t *tvb, guint* offset, proto_tree *leaf) { int len = WireFormat::FieldByteSize( field, *message ); map<string, Handles*>::iterator it = g_mapHandles.find( field->full_name() ); if( it == g_mapHandles.end() ) { return false; // bug } Handles* handles = it->second; const Reflection *reflection = message->GetReflection(); const EnumValueDescriptor* enumDesc = NULL; switch( field->cpp_type() ) { case FieldDescriptor::CPPTYPE_UINT32: proto_tree_add_uint( leaf, handles->p_id, tvb, *offset, len, reflection->GetUInt32( *message, field ) ); break; case FieldDescriptor::CPPTYPE_INT32: proto_tree_add_int( leaf, handles->p_id, tvb, *offset, len, reflection->GetInt32( *message, field ) ); break; case FieldDescriptor::CPPTYPE_FLOAT: proto_tree_add_float( leaf, handles->p_id, tvb, *offset, len, reflection->GetFloat( *message, field ) ); break; case FieldDescriptor::CPPTYPE_UINT64: proto_tree_add_uint64( leaf, handles->p_id, tvb, *offset, len, reflection->GetUInt64( *message, field ) ); break; case FieldDescriptor::CPPTYPE_INT64: proto_tree_add_int64( leaf, handles->p_id, tvb, *offset, len, reflection->GetInt64( *message, field ) ); break; case FieldDescriptor::CPPTYPE_DOUBLE: proto_tree_add_double( leaf, handles->p_id, tvb, *offset, len, reflection->GetDouble( *message, field ) ); break; case FieldDescriptor::CPPTYPE_BOOL: proto_tree_add_boolean( leaf, handles->p_id, tvb, *offset, len, reflection->GetBool( *message, field ) ); break; case FieldDescriptor::CPPTYPE_ENUM: enumDesc = reflection->GetEnum( *message, field ); proto_tree_add_int_format_value( leaf, handles->p_id, tvb, *offset, len, enumDesc->number(), "%d ( %s )", enumDesc->number(), enumDesc->name().c_str() ); break; case FieldDescriptor::CPPTYPE_STRING: proto_tree_add_string( leaf, handles->p_id, tvb, *offset, len, reflection->GetString( *message, field ).c_str() ); break; default: proto_tree_add_item( leaf, handles->p_id, tvb, *offset, len, true ); }; *offset += len; return true; }
/** *Helper function to dissect a Thermostat schedule, which has * *@param tree pointer to data tree Wireshark uses to display packet. *@param tvb pointer to buffer containing raw packet. *@param offset payload offset of the ZoneStatus value. *@return length of parsed data. */ static int dissect_zcl_thermostat_schedule(proto_tree *tree, tvbuff_t *tvb, guint offset) { guint start = offset; guint8 num_transitions; guint8 mode_sequence; int i; num_transitions = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_zbee_zcl_thermostat_schedule_num_trans, tvb, offset, 1, num_transitions); offset++; dissect_zcl_thermostat_schedule_days(tree, tvb, offset); offset++; mode_sequence = tvb_get_guint8(tvb, offset); dissect_zcl_thermostat_schedule_mode(tree, tvb, offset); offset++; /* Parse the list of setpoint transitions. */ for (i = 0; i < num_transitions; i++) { nstime_t tv; tv.secs = tvb_get_letohs(tvb, offset) * 60; tv.nsecs = 0; proto_tree_add_time(tree, hf_zbee_zcl_thermostat_schedule_time, tvb, offset, 2, &tv); offset += 2; if (mode_sequence & ZBEE_ZCL_CMD_THERMOSTAT_SCHEDULE_MODE_SEQUENCE_HEAT) { float setpoint = (gint16)tvb_get_letohs(tvb, offset); proto_tree_add_float(tree, hf_zbee_zcl_thermostat_schedule_heat, tvb, offset, 2, (setpoint / 100.0f)); offset += 2; } if (mode_sequence & ZBEE_ZCL_CMD_THERMOSTAT_SCHEDULE_MODE_SEQUENCE_COOL) { float setpoint = (gint16)tvb_get_letohs(tvb, offset); proto_tree_add_float(tree, hf_zbee_zcl_thermostat_schedule_cool, tvb, offset, 2, (setpoint / 100.0f)); offset += 2; } } /* for */ /* Return the number of bytes parsed. */ return (offset - start); } /* dissect_zcl_thermostat_cmd_schedule */
/** *ZigBee ZCL Thermostat cluster dissector for wireshark. * *@param tvb pointer to buffer containing raw packet. *@param pinfo pointer to packet information fields *@param tree pointer to data tree Wireshark uses to display packet. *@param data pointer to ZCL packet structure. *@return length of parsed data. */ static int dissect_zbee_zcl_thermostat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { zbee_zcl_packet *zcl; guint offset = 0; guint8 cmd_id; float amount; /* Reject the packet if data is NULL */ if (data == NULL) return 0; zcl = (zbee_zcl_packet *)data; cmd_id = zcl->cmd_id; if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) { /* Append the command name to the info column. */ col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", val_to_str_const(cmd_id, zbee_zcl_thermostat_srv_rx_cmd_names, "Unknown Command"), zcl->tran_seqno); /* Add the command ID. */ proto_tree_add_item(tree, hf_zbee_zcl_thermostat_srv_rx_cmd_id, tvb, offset, 1, cmd_id); offset++; /* Handle the command dissection. */ switch (cmd_id) { case ZBEE_ZCL_CMD_ID_THERMOSTAT_SETPOINT: /* Setpoint Raise/Lower. */ proto_tree_add_item(tree, hf_zbee_zcl_thermostat_setpoint_mode, tvb, offset, 1, ENC_NA); offset++; amount = (gint8)tvb_get_guint8(tvb, offset); proto_tree_add_float(tree, hf_zbee_zcl_thermostat_setpoint_amount, tvb, offset, 1, (amount / 100.0f)); offset++; break; case ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_SCHEDULE: /* Get Weekly Schedule. */ dissect_zcl_thermostat_schedule_days(tree, tvb, offset); offset++; dissect_zcl_thermostat_schedule_mode(tree, tvb, offset); offset++; break; case ZBEE_ZCL_CMD_ID_THERMOSTAT_SET_SCHEDULE: /* Set Weekly Schedule. */ dissect_zcl_thermostat_schedule(tree, tvb, offset); break; case ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_RELAY_LOG: /* No Payload - fall-through. */ default: break; } /* switch */ } else { /* Append the command name to the info column. */ col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", val_to_str_const(cmd_id, zbee_zcl_thermostat_srv_tx_cmd_names, "Unknown Command"), zcl->tran_seqno); /* Add the command ID. */ proto_tree_add_item(tree, hf_zbee_zcl_thermostat_srv_tx_cmd_id, tvb, offset, 1, cmd_id); offset++; /* Handle the command dissection. */ switch (cmd_id) { case ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_SCHEDULE_RESPONSE: /* Get Weekly Schedule Response. */ dissect_zcl_thermostat_schedule(tree, tvb, offset); break; case ZBEE_ZCL_CMD_ID_THERMOSTAT_GET_RELAY_LOG_RESPONSE: /* TODO: Implement Me! */ default: break; } /* switch */ } return tvb_captured_length(tvb); } /* dissect_zbee_zcl_thermostat */
static void mate_gop_tree(proto_tree* tree, tvbuff_t *tvb, mate_gop* gop) { proto_item *gop_item; proto_tree *gop_time_tree; proto_item *gop_time_item; proto_tree *gop_tree; proto_item *gop_pdu_item; proto_tree *gop_pdu_tree; mate_pdu* gop_pdus; float rel_time; float gop_time; float pdu_rel_time; const gchar* pdu_str; const gchar* type_str; guint32 pdu_item; gop_item = proto_tree_add_uint(tree,gop->cfg->hfid,tvb,0,0,gop->id); gop_tree = proto_item_add_subtree(gop_item, gop->cfg->ett); if (gop->gop_key) proto_tree_add_text(gop_tree,tvb,0,0,"GOP Key: %s",gop->gop_key); gop_attrs_tree(gop_tree,tvb,gop); if (gop->cfg->show_times) { gop_time_item = proto_tree_add_text(gop_tree,tvb,0,0,"%s Times",gop->cfg->name); gop_time_tree = proto_item_add_subtree(gop_time_item, gop->cfg->ett_times); proto_tree_add_float(gop_time_tree, gop->cfg->hfid_start_time, tvb, 0, 0, gop->start_time); if (gop->released) { proto_tree_add_float(gop_time_tree, gop->cfg->hfid_stop_time, tvb, 0, 0, gop->release_time - gop->start_time); proto_tree_add_float(gop_time_tree, gop->cfg->hfid_last_time, tvb, 0, 0, gop->last_time - gop->start_time); } else { proto_tree_add_float(gop_time_tree, gop->cfg->hfid_last_time, tvb, 0, 0, gop->last_time - gop->start_time); } } gop_pdu_item = proto_tree_add_uint(gop_tree, gop->cfg->hfid_gop_num_pdus, tvb, 0, 0,gop->num_of_pdus); if (gop->cfg->pdu_tree_mode != GOP_NO_TREE) { gop_pdu_tree = proto_item_add_subtree(gop_pdu_item, gop->cfg->ett_children); rel_time = gop_time = gop->start_time; type_str = (gop->cfg->pdu_tree_mode == GOP_FRAME_TREE ) ? "in frame:" : "id:"; for (gop_pdus = gop->pdus; gop_pdus; gop_pdus = gop_pdus->next) { pdu_item = (gop->cfg->pdu_tree_mode == GOP_FRAME_TREE ) ? gop_pdus->frame : gop_pdus->id; if (gop_pdus->is_start) { pdu_str = "Start "; } else if (gop_pdus->is_stop) { pdu_str = "Stop "; } else if (gop_pdus->after_release) { pdu_str = "After stop "; } else { pdu_str = ""; } pdu_rel_time = gop_pdus->time_in_gop != 0.0 ? gop_pdus->time_in_gop - rel_time : (float) 0.0; proto_tree_add_uint_format(gop_pdu_tree,gop->cfg->hfid_gop_pdu,tvb,0,0,pdu_item, "%sPDU: %s %i (%f : %f)",pdu_str, type_str, pdu_item, gop_pdus->time_in_gop, pdu_rel_time); rel_time = gop_pdus->time_in_gop; } } }
static void mate_gog_tree(proto_tree* tree, tvbuff_t *tvb, mate_gog* gog, mate_gop* gop) { proto_item *gog_item; proto_tree *gog_tree; proto_item *gog_time_item; proto_tree *gog_time_tree; proto_item *gog_gops_item; proto_tree *gog_gops_tree; mate_gop* gog_gops; proto_item *gog_gop_item; proto_tree *gog_gop_tree; mate_pdu* pdu; #ifdef _MATE_DEBUGGING proto_item* gog_key_item; proto_tree* gog_key_tree; guint i; #endif gog_item = proto_tree_add_uint(tree,gog->cfg->hfid,tvb,0,0,gog->id); gog_tree = proto_item_add_subtree(gog_item,gog->cfg->ett); gog_attrs_tree(gog_tree,tvb,gog); if (gog->cfg->show_times) { gog_time_item = proto_tree_add_text(gog_tree,tvb,0,0,"%s Times",gog->cfg->name); gog_time_tree = proto_item_add_subtree(gog_time_item, gog->cfg->ett_times); proto_tree_add_float(gog_time_tree, gog->cfg->hfid_start_time, tvb, 0, 0, gog->start_time); proto_tree_add_float(gog_time_tree, gog->cfg->hfid_last_time, tvb, 0, 0, gog->last_time - gog->start_time); } gog_gops_item = proto_tree_add_uint(gog_tree, gog->cfg->hfid_gog_num_of_gops, tvb, 0, 0, gog->num_of_gops); gog_gops_tree = proto_item_add_subtree(gog_gops_item, gog->cfg->ett_children); for (gog_gops = gog->gops; gog_gops; gog_gops = gog_gops->next) { if (gop != gog_gops) { if (gog->cfg->gop_tree_mode == GOP_FULL_TREE) { mate_gop_tree(gog_gops_tree, tvb, gog_gops); } else { gog_gop_item = proto_tree_add_uint(gog_gops_tree,gog_gops->cfg->hfid,tvb,0,0,gog_gops->id); if (gog->cfg->gop_tree_mode == GOP_BASIC_TREE) { gog_gop_tree = proto_item_add_subtree(gog_gop_item, gog->cfg->ett_gog_gop); proto_tree_add_text(gog_gop_tree, tvb,0,0, "Started at: %f", gog_gops->start_time); proto_tree_add_text(gog_gop_tree, tvb,0,0, "%s Duration: %f", gog_gops->cfg->name, gog_gops->last_time - gog_gops->start_time); if (gog_gops->released) proto_tree_add_text(gog_gop_tree, tvb,0,0, "%s has been released, Time: %f", gog_gops->cfg->name, gog_gops->release_time - gog_gops->start_time); proto_tree_add_text(gog_gop_tree, tvb,0,0, "Number of Pdus: %u",gog_gops->num_of_pdus); if (gop->pdus && gop->cfg->pdu_tree_mode != GOP_NO_TREE) { proto_tree_add_uint(gog_gop_tree,gog->cfg->hfid_gog_gopstart,tvb,0,0,gog_gops->pdus->frame); for (pdu = gog_gops->pdus->next ; pdu; pdu = pdu->next) { if (pdu->is_stop) { proto_tree_add_uint(gog_gop_tree,gog->cfg->hfid_gog_gopstop,tvb,0,0,pdu->frame); break; } } } } } } else { proto_tree_add_uint_format(gog_gops_tree,gop->cfg->hfid,tvb,0,0,gop->id,"current %s Gop: %d",gop->cfg->name,gop->id); } } }
bool dissect_protobuf_repeated_field(const FieldDescriptor* field, const Message* message, tvbuff_t *tvb, guint* offset, proto_tree *leaf, int iRepeatedIndex) { int len = 0; string scratch; if( !field->options().packed() ) { len += WireFormat::TagSize( field->number(), field->type() ); } map<string, Handles*>::iterator it = g_mapHandles.find( field->full_name() ); if( it == g_mapHandles.end() ) { return false; // bug } Handles* handles = it->second; const Reflection *reflection = message->GetReflection(); const EnumValueDescriptor* enumDesc = NULL; switch( field->cpp_type() ) { case FieldDescriptor::CPPTYPE_UINT32: if( field->type() == FieldDescriptor::TYPE_FIXED32 ) { len += WireFormatLite::kFixed32Size; } else { len += WireFormatLite::UInt32Size( reflection->GetRepeatedUInt32( *message, field, iRepeatedIndex ) ); } proto_tree_add_uint( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedUInt32( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_INT32: if( field->type() == FieldDescriptor::TYPE_SFIXED32 ) { len += WireFormatLite::kSFixed32Size; } else if( field->type() == FieldDescriptor::TYPE_SINT32 ) { len += WireFormatLite::SInt32Size( reflection->GetRepeatedInt32( *message, field, iRepeatedIndex ) ); } else { len += WireFormatLite::Int32Size( reflection->GetRepeatedInt32( *message, field, iRepeatedIndex ) ); } proto_tree_add_int( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedInt32( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_FLOAT: len += WireFormatLite::kFloatSize; proto_tree_add_float( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedFloat( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_UINT64: if( field->type() == FieldDescriptor::TYPE_FIXED64 ) { len += WireFormatLite::kFixed64Size; } else { len += WireFormatLite::UInt64Size( reflection->GetRepeatedUInt64( *message, field, iRepeatedIndex ) ); } proto_tree_add_uint64( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedUInt64( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_INT64: if( field->type() == FieldDescriptor::TYPE_SFIXED64 ) { len += WireFormatLite::kSFixed64Size; } else if( field->type() == FieldDescriptor::TYPE_SINT64 ) { len += WireFormatLite::SInt64Size( reflection->GetRepeatedInt64( *message, field, iRepeatedIndex ) ); } else { len += WireFormatLite::Int64Size( reflection->GetRepeatedInt64( *message, field, iRepeatedIndex ) ); } proto_tree_add_int64( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedInt64( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_DOUBLE: len += WireFormatLite::kDoubleSize; proto_tree_add_double( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedDouble( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_BOOL: len += WireFormatLite::kBoolSize; proto_tree_add_boolean( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedBool( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_ENUM: enumDesc = reflection->GetRepeatedEnum( *message, field, iRepeatedIndex ); len += WireFormatLite::EnumSize( enumDesc->number() ); proto_tree_add_int_format_value( leaf, handles->p_id, tvb, *offset, len, enumDesc->number(), "%d ( %s )", enumDesc->number(), enumDesc->name().c_str() ); break; case FieldDescriptor::CPPTYPE_STRING: len += WireFormatLite::StringSize( reflection->GetRepeatedStringReference( *message, field, iRepeatedIndex, &scratch ) ); proto_tree_add_string( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedString( *message, field, iRepeatedIndex ).c_str() ); break; default: proto_tree_add_item( leaf, handles->p_id, tvb, *offset, len, true ); }; *offset += len; return true; }
static void mate_gog_tree(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, mate_gog* gog, mate_gop* gop) { proto_item *gog_item; proto_tree *gog_tree; proto_tree *gog_time_tree; proto_item *gog_gops_item; proto_tree *gog_gops_tree; mate_gop* gog_gops; proto_item *gog_gop_item; proto_tree *gog_gop_tree; mate_pdu* pdu; gog_item = proto_tree_add_uint(tree,gog->cfg->hfid,tvb,0,0,gog->id); gog_tree = proto_item_add_subtree(gog_item,gog->cfg->ett); gog_attrs_tree(gog_tree,pinfo,tvb,gog); if (gog->cfg->show_times) { gog_time_tree = proto_tree_add_subtree_format(gog_tree,tvb,0,0,gog->cfg->ett_times,NULL,"%s Times",gog->cfg->name); proto_tree_add_float(gog_time_tree, gog->cfg->hfid_start_time, tvb, 0, 0, gog->start_time); proto_tree_add_float(gog_time_tree, gog->cfg->hfid_last_time, tvb, 0, 0, gog->last_time - gog->start_time); } gog_gops_item = proto_tree_add_uint(gog_tree, gog->cfg->hfid_gog_num_of_gops, tvb, 0, 0, gog->num_of_gops); gog_gops_tree = proto_item_add_subtree(gog_gops_item, gog->cfg->ett_children); for (gog_gops = gog->gops; gog_gops; gog_gops = gog_gops->next) { if (gop != gog_gops) { if (gog->cfg->gop_tree_mode == GOP_FULL_TREE) { mate_gop_tree(gog_gops_tree, pinfo, tvb, gog_gops); } else { gog_gop_item = proto_tree_add_uint(gog_gops_tree,gog_gops->cfg->hfid,tvb,0,0,gog_gops->id); if (gog->cfg->gop_tree_mode == GOP_BASIC_TREE) { gog_gop_tree = proto_item_add_subtree(gog_gop_item, gog->cfg->ett_gog_gop); proto_tree_add_float(gog_gop_tree, hf_mate_started_at, tvb,0,0,gog_gops->start_time); proto_tree_add_float_format(gog_gop_tree, hf_mate_duration, tvb,0,0, gog_gops->last_time - gog_gops->start_time, "%s Duration: %f", gog_gops->cfg->name, gog_gops->last_time - gog_gops->start_time); if (gog_gops->released) proto_tree_add_float_format(gog_gop_tree, hf_mate_released_time, tvb,0,0, gog_gops->release_time - gog_gops->start_time, "%s has been released, Time: %f", gog_gops->cfg->name, gog_gops->release_time - gog_gops->start_time); proto_tree_add_uint(gog_gop_tree, hf_mate_number_of_pdus, tvb,0,0, gog_gops->num_of_pdus); if (gop->pdus && gop->cfg->pdu_tree_mode != GOP_NO_TREE) { proto_tree_add_uint(gog_gop_tree,gog->cfg->hfid_gog_gopstart,tvb,0,0,gog_gops->pdus->frame); for (pdu = gog_gops->pdus->next ; pdu; pdu = pdu->next) { if (pdu->is_stop) { proto_tree_add_uint(gog_gop_tree,gog->cfg->hfid_gog_gopstop,tvb,0,0,pdu->frame); break; } } } } } } else { proto_tree_add_uint_format(gog_gops_tree,gop->cfg->hfid,tvb,0,0,gop->id,"current %s Gop: %d",gop->cfg->name,gop->id); } } }