/* -*- Mode: C; tab-width: 2 -*- */ /* packet-reload.c * Routines forREsource LOcation And Discovery (RELOAD) Base Protocol * Author: Stephane Bryant * Copyright 2010 Stonyfish Inc. * * $Id$ * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Please refer to the following specs for protocol detail: * - draft-ietf-p2psip-base-12 */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include /* Initialize the protocol and registered fields */ static int proto_reload = -1; static gboolean reload_defragment = TRUE; static int hf_reload_response_in = -1; static int hf_reload_response_to = -1; static int hf_reload_time = -1; static int hf_reload_duplicate = -1; static int hf_reload_token = -1; static int hf_reload_forwarding = -1; static int hf_reload_overlay = -1; static int hf_reload_configuration_sequence = -1; static int hf_reload_version = -1; static int hf_reload_ttl = -1; static int hf_reload_fragment_flag = -1; static int hf_reload_fragment_fragmented = -1; static int hf_reload_fragment_last_fragment = -1; static int hf_reload_fragment_reserved = -1; static int hf_reload_fragment_offset = -1; static int hf_reload_length = -1; static int hf_reload_trans_id = -1; static int hf_reload_max_response_length = -1; static int hf_reload_via_list_length = -1; static int hf_reload_destination_list_length = -1; static int hf_reload_options_length = -1; static int hf_reload_via_list = -1; static int hf_reload_destination = -1; static int hf_reload_destination_compressed = -1; static int hf_reload_destination_type = -1; static int hf_reload_destination_length = -1; static int hf_reload_node_id = -1; static int hf_reload_resource_id = -1; static int hf_reload_destination_data_compressed_id = -1; static int hf_reload_destination_list = -1; static int hf_reload_forwarding_option = -1; static int hf_reload_forwarding_option_type = -1; static int hf_reload_forwarding_option_flags = -1; static int hf_reload_forwarding_option_flag_response_copy = -1; static int hf_reload_forwarding_option_flag_destination_critical = -1; static int hf_reload_forwarding_option_flag_forward_critical = -1; static int hf_reload_forwarding_option_length = -1; static int hf_reload_forwarding_option_data = -1; static int hf_reload_forwarding_option_directresponseforwarding = -1; static int hf_reload_attachreqans = -1; static int hf_reload_ufrag = -1; static int hf_reload_password = -1; static int hf_reload_role = -1; static int hf_reload_sendupdate = -1; static int hf_reload_icecandidates = -1; static int hf_reload_icecandidates_length = -1; static int hf_reload_icecandidate = -1; static int hf_reload_icecandidate_srflx_addr = -1; static int hf_reload_icecandidate_prflx_addr = -1; static int hf_reload_icecandidate_relay_addr = -1; static int hf_reload_icecandidate_foundation = -1; static int hf_reload_icecandidate_priority = -1; static int hf_reload_icecandidate_type = -1; static int hf_reload_overlaylink_type = -1; static int hf_reload_icecandidate_extensions_length = -1; static int hf_reload_iceextension = -1; static int hf_reload_iceextension_name = -1; static int hf_reload_iceextension_value = -1; static int hf_reload_ipaddressport = -1; static int hf_reload_ipaddressport_type = -1; static int hf_reload_ipaddressport_length = -1; static int hf_reload_ipv4addr = -1; static int hf_reload_port = -1; static int hf_reload_ipv6addr = -1; static int hf_reload_message_contents = -1; static int hf_reload_message_code = -1; static int hf_reload_message_body = -1; static int hf_reload_message_extensions_length = -1; static int hf_reload_message_extension = -1; static int hf_reload_message_extension_type = -1; static int hf_reload_message_extension_critical = -1; static int hf_reload_message_extension_content = -1; static int hf_reload_error_response = -1; static int hf_reload_error_response_code = -1; static int hf_reload_error_response_info = -1; static int hf_reload_security_block = -1; static int hf_reload_certificates_length = -1; static int hf_reload_certificate = -1; static int hf_reload_certificate_type = -1; static int hf_reload_certificate_data = -1; static int hf_reload_signature = -1; static int hf_reload_hash_algorithm = -1; static int hf_reload_signature_algorithm = -1; static int hf_reload_signature_identity = -1; static int hf_reload_signature_identity_type = -1; static int hf_reload_signature_identity_length = -1; static int hf_reload_signature_identity_value = -1; static int hf_reload_signature_identity_value_certificate_hash = -1; static int hf_reload_signature_value = -1; static int hf_reload_opaque_length_uint8 = -1; static int hf_reload_opaque_length_uint16 = -1; static int hf_reload_opaque_length_uint32 = -1; static int hf_reload_opaque_data = -1; static int hf_reload_routequeryreq = -1; static int hf_reload_overlay_specific = -1; static int hf_reload_probereq = -1; static int hf_reload_probe_information_type = -1; static int hf_reload_probe_information = -1; static int hf_reload_responsible_set = -1; static int hf_reload_num_resources = -1; static int hf_reload_uptime = -1; static int hf_reload_probeans = -1; static int hf_reload_appattach = -1; static int hf_reload_application = -1; static int hf_reload_ping_response_id = -1; static int hf_reload_ping_time = -1; static int hf_reload_storeddata = -1; static int hf_reload_storeddata_length = -1; static int hf_reload_storeddata_storage_time = -1; static int hf_reload_storeddata_lifetime = -1; static int hf_reload_kinddata = -1; static int hf_reload_kindid = -1; static int hf_reload_kinddata_generation_counter = -1; static int hf_reload_kinddata_values_length = -1; static int hf_reload_storereq = -1; static int hf_reload_store_replica_num = -1; static int hf_reload_store_kind_data_length = -1; static int hf_reload_storeans_kind_responses = -1; static int hf_reload_storeans_kind_responses_length = -1; static int hf_reload_storekindresponse = -1; static int hf_reload_storekindresponse_replicas = -1; static int hf_reload_storeddataspecifiers = -1; static int hf_reload_fetchans = -1; static int hf_reload_kind_responses_length = -1; static int hf_reload_statans = -1; static int hf_reload_findreq_kinds_length = -1; static int hf_reload_findkinddata = -1; static int hf_reload_findans_results_length = -1; static int hf_reload_fragments = -1; static int hf_reload_fragment = -1; static int hf_reload_fragment_overlap = -1; static int hf_reload_fragment_overlap_conflict = -1; static int hf_reload_fragment_multiple_tails = -1; static int hf_reload_fragment_too_long_fragment = -1; static int hf_reload_fragment_error = -1; static int hf_reload_reassembled_in = -1; static int hf_reload_reassembled_length = -1; static int hf_reload_configupdatereq = -1; static int hf_reload_configupdatereq_type = -1; static int hf_reload_configupdatereq_length = -1; static int hf_reload_configupdatereq_configdata = -1; static int hf_reload_configupdatereq_kinds = -1; static dissector_handle_t data_handle; /* Structure containing transaction specific information */ typedef struct _reload_transaction_t { guint32 req_frame; guint32 rep_frame; nstime_t req_time; } reload_transaction_t; /* Structure containing conversation specific information */ typedef struct _reload_conv_info_t { emem_tree_t *transaction_pdus; } reload_conv_info_t; /* ReLOAD Message classes = (message_code & 0x1) (response = request +1) */ #define REQUEST 0x0001 #define RESPONSE 0x0000 #define ERROR 0xffff /* ReLOAD Message Methods = (message_code +1) & 0xfffe*/ #define METHOD_INVALID 0 #define METHOD_PROBE 2 #define METHOD_ATTACH 4 #define METHOD_STORE 8 #define METHOD_FETCH 10 #define METHOD_REMOVE 12 #define METHOD_FIND 14 #define METHOD_JOIN 16 #define METHOD_LEAVE 18 #define METHOD_UPDATE 20 #define METHOD_ROUTEQUERY 22 #define METHOD_PING 24 #define METHOD_STAT 26 #define METHOD_APPATTACH 30 #define METHOD_CONFIGUPDATE 34 /* ReLOAD Destinationtype */ #define DESTINATIONTYPE_RESERVED 0 #define DESTINATIONTYPE_NODE 1 #define DESTINATIONTYPE_RESOURCE 2 #define DESTINATIONTYPE_COMPRESSED 3 /* ReLOAD forwarding option type */ #define OPTIONTYPE_DIRECTRESPONSEFORWARDING 1 /* ReLOAD CandTypes */ #define CANDTYPE_RESERVED 0 #define CANDTYPE_HOST 1 #define CANDTYPE_SRFLX 2 #define CANDTYPE_PRFLX 3 #define CANDTYPE_RELAY 4 /* IpAddressPort types */ #define IPADDRESSPORTTYPE_RESERVED 0 #define IPADDRESSPORTTYPE_IPV4 1 #define IPADDRESSPORTTYPE_IPV6 2 /* OverlayLink types */ #define OVERLAYLINKTYPE_RESERVEDOVERLAYLINK 0 #define OVERLAYLINKTYPE_DTLS_UDP_SR 1 #define OVERLAYLINKTYPE_DTLS_UDP_SR_NO_ICE 3 #define OVERLAYLINKTYPE_TLS_TCP_FH_NO_ICE 4 #define ERRORCODE_INVALID 0 #define ERRORCODE_UNUSED 1 #define ERRORCODE_FORBIDDEN 2 #define ERRORCODE_NOTFOUND 3 #define ERRORCODE_REQUESTTIMEOUT 4 #define ERRORCODE_GENERATIONCOUNTERTOOLOW 5 #define ERRORCODE_INCOMPATIBLEWITHOVERLAY 6 #define ERRORCODE_UNSUPPORTEDFORWARDINGOPTION 7 #define ERRORCODE_DATATOOLARGE 8 #define ERRORCODE_DATATOOOLD 9 #define ERRORCODE_TTLEXCEEDED 10 #define ERRORCODE_MESSAGETOOLARGE 11 #define ERRORCODE_UNKNOWNKIND 12 #define ERRORCODE_UNKNOWNEXTENSION 13 #define ERRORCODE_RESPONSETOOLARGE 14 #define ERRORCODE_CONFIGTOOOLD 15 #define ERRORCODE_CONFIGTOONEW 16 /* Certificate types */ #define CERTIFICATETYPE_X509 0 /* Hash Algorithm */ #define HASHALGORITHM_NONE 0 #define HASHALGORITHM_MD5 1 #define HASHALGORITHM_SHA1 2 #define HASHALGORITHM_SHA224 3 #define HASHALGORITHM_SHA256 4 #define HASHALGORITHM_SHA384 5 #define HASHALGORITHM_SHA512 6 /* Signature algorithm */ #define SIGNATUREALGORITHM_ANONYMOUS 0 #define SIGNATUREALGORITHM_RSA 1 #define SIGNATUREALGORITHM_DSA 2 #define SIGNATUREALGORITHM_ECDSA 3 #define SIGNATUREIDENTITYTYPE_RESERVED 0 #define SIGNATUREIDENTITYTYPE_CERTHASH 1 /* Probe information type */ #define PROBEINFORMATIONTYPE_RESERVED 0 #define PROBEINFORMATIONTYPE_RESPONSIBLESET 1 #define PROBEINFORMATIONTYPE_NUMRESOURCES 2 #define PROBEINFORMATIONTYPE_UPTIME 3 /* Data Kind ID */ #define DATAKINDID_INVALID 0 #define DATAKINDID_TURNSERVICE 2 #define DATAKINDID_CERTIFICATE_BY_NODE 4 #define DATAKINDID_CERTIFICATE_BY_USER 6 /* Message Extension Type */ #define MESSAGEEXTENSIONTYPE_RESERVED 0 /* Config Update Type */ #define CONFIGUPDATETYPE_RESERVED 0 #define CONFIGUPDATETYPE_CONFIG 1 #define CONFIGUPDATETYPE_KIND 2 /* Initialize the subtree pointers */ static gint ett_reload = -1; static gint ett_reload_forwarding = -1; static gint ett_reload_message = -1; static gint ett_reload_security=-1; static gint ett_reload_fragment_flag=-1; static gint ett_reload_destination = -1; static gint ett_reload_via_list = -1; static gint ett_reload_destination_list = -1; static gint ett_reload_forwarding_option = -1; static gint ett_reload_forwarding_option_flags = -1; static gint ett_reload_forwarding_option_directresponseforwarding = -1; static gint ett_reload_attachreqans = -1; static gint ett_reload_icecandidates = -1; static gint ett_reload_icecandidate = -1; static gint ett_reload_icecandidate_computed_address = -1; static gint ett_reload_iceextension = -1; static gint ett_reload_ipaddressport = -1; static gint ett_reload_message_contents = -1; static gint ett_reload_message_extension = -1; static gint ett_reload_error_response = -1; static gint ett_reload_security_block = -1; static gint ett_reload_certificate = -1; static gint ett_reload_signature = -1; static gint ett_reload_signature_identity = -1; static gint ett_reload_signature_identity_value = -1; static gint ett_reload_opaque = -1; static gint ett_reload_message_body = -1; static gint ett_reload_routequeryreq = -1; static gint ett_reload_probereq = -1; static gint ett_reload_probe_information = -1; static gint ett_reload_probeans = -1; static gint ett_reload_appattach = -1; static gint ett_reload_storeddata = -1; static gint ett_reload_kinddata = -1; static gint ett_reload_storereq = -1; static gint ett_reload_storeans_kind_responses = -1; static gint ett_reload_storekindresponse = -1; static gint ett_reload_fetchans = -1; static gint ett_reload_statans = -1; static gint ett_reload_findkinddata = -1; static gint ett_reload_fragments = -1; static gint ett_reload_fragment = -1; static gint ett_reload_configupdatereq = -1; static const fragment_items reload_frag_items = { &ett_reload_fragment, &ett_reload_fragments, &hf_reload_fragments, &hf_reload_fragment, &hf_reload_fragment_overlap, &hf_reload_fragment_overlap_conflict, &hf_reload_fragment_multiple_tails, &hf_reload_fragment_too_long_fragment, &hf_reload_fragment_error, &hf_reload_reassembled_in, &hf_reload_reassembled_length, "ReLOAD fragments" }; #define MSG_LENGH_OFFSET 16 #define MIN_HDR_LENGTH 38 /* Forwarding header till options_length member (included) */ #define RELOAD_TOKEN 0xd2454c4f #define IS_REQUEST(code) (code & 0x0001) #define MSGCODE_TO_METHOD(code) ((code + 1) & 0xfffe) #define MSGCODE_TO_CLASS(code) (code & 0x0001) static const value_string classes[] = { {REQUEST, "Request"}, {RESPONSE, "Response"}, {0x00, NULL} }; static const value_string methods[] = { {METHOD_INVALID, "Invalid"}, {METHOD_PROBE, "Probe"}, {METHOD_ATTACH, "Attach"}, {METHOD_STORE, "Store"}, {METHOD_FETCH, "Fetch"}, {METHOD_REMOVE, "Remove"}, {METHOD_FIND, "Find"}, {METHOD_JOIN, "Join"}, {METHOD_LEAVE, "Leave"}, {METHOD_UPDATE, "Update"}, {METHOD_ROUTEQUERY, "Route Query"}, {METHOD_PING, "Ping"}, {METHOD_STAT, "Stat"}, {METHOD_APPATTACH, "App-Attach"}, {METHOD_CONFIGUPDATE, "Config Update"}, {0x00, NULL} }; static const value_string destinationtypes[] = { {DESTINATIONTYPE_RESERVED, "Reserved"}, {DESTINATIONTYPE_NODE, "Node"}, {DESTINATIONTYPE_RESOURCE, "Resource"}, {DESTINATIONTYPE_COMPRESSED, "Compressed"}, {0x00, NULL} }; static const value_string forwardingoptiontypes[] = { {OPTIONTYPE_DIRECTRESPONSEFORWARDING, "directResponseForwarding"}, {0x00, NULL} }; static const value_string candtypes[] = { {CANDTYPE_RESERVED, "reservedCand"}, {CANDTYPE_HOST, "host"}, {CANDTYPE_SRFLX, "srflx"}, {CANDTYPE_PRFLX, "prflx"}, {CANDTYPE_RELAY, "relay"}, {0x00, NULL} }; static const value_string ipaddressporttypes [] = { {IPADDRESSPORTTYPE_RESERVED, "reserved"}, {IPADDRESSPORTTYPE_IPV4, "ipv4"}, {IPADDRESSPORTTYPE_IPV6, "ipv6"}, {0x00, NULL} }; static const value_string overlaylinktypes [] ={ {OVERLAYLINKTYPE_RESERVEDOVERLAYLINK, "ReservedOverLayLink"}, {OVERLAYLINKTYPE_DTLS_UDP_SR, "DTLS-UDP-SR"}, {OVERLAYLINKTYPE_DTLS_UDP_SR_NO_ICE, "DTLS-UDP-SR-NO-ICE"}, {OVERLAYLINKTYPE_TLS_TCP_FH_NO_ICE, "TLS-TCP-FH-NO-ICE"}, {0x00, NULL} }; static const value_string errorcodes [] ={ {ERRORCODE_INVALID, "invalid"}, {ERRORCODE_UNUSED, "Unused"}, {ERRORCODE_FORBIDDEN, "Forbidden"}, {ERRORCODE_NOTFOUND, "Not Found"}, {ERRORCODE_REQUESTTIMEOUT, "Request Timeout"}, {ERRORCODE_GENERATIONCOUNTERTOOLOW, "Generation Counter Too Low"}, {ERRORCODE_INCOMPATIBLEWITHOVERLAY, "Incompatible with Overlay"}, {ERRORCODE_UNSUPPORTEDFORWARDINGOPTION, "Unsupported Forwarding Option"}, {ERRORCODE_DATATOOLARGE, "Data Too Large"}, {ERRORCODE_DATATOOOLD, "Data Too Old"}, {ERRORCODE_TTLEXCEEDED, "TTL Exceeded"}, {ERRORCODE_MESSAGETOOLARGE, "Message Too Large"}, {ERRORCODE_UNKNOWNKIND, "Unknown Kind"}, {ERRORCODE_UNKNOWNEXTENSION, "Unknown Extension"}, {ERRORCODE_RESPONSETOOLARGE, "Response Too Large"}, {ERRORCODE_CONFIGTOOOLD, "Config Too Old"}, {ERRORCODE_CONFIGTOONEW, "Config Too New"}, {0x00, NULL} }; static const value_string certificatetypes[] = { {CERTIFICATETYPE_X509, "x509"}, {0x00, NULL} }; static const value_string hashalgorithms[] = { {HASHALGORITHM_NONE, "none"}, {HASHALGORITHM_MD5, "md5"}, {HASHALGORITHM_SHA1, "sha1"}, {HASHALGORITHM_SHA224, "sha224"}, {HASHALGORITHM_SHA256, "sha256"}, {HASHALGORITHM_SHA384, "sha384"}, {HASHALGORITHM_SHA512 , "sha512"}, {0x00, NULL} }; static const value_string signaturealgorithms[] = { {SIGNATUREALGORITHM_ANONYMOUS, "anonymous"}, {SIGNATUREALGORITHM_RSA, "rsa"}, {SIGNATUREALGORITHM_DSA, "dsa"}, {SIGNATUREALGORITHM_ECDSA, "ecdsa"}, {0x00, NULL} }; static const value_string signatureidentitytypes[] = { {SIGNATUREIDENTITYTYPE_RESERVED, "reserved"}, {SIGNATUREIDENTITYTYPE_CERTHASH, "cert hash"}, {0x00, NULL} }; static const value_string probeinformationtypes[] = { {PROBEINFORMATIONTYPE_RESERVED, "reservedProbeInformation"}, {PROBEINFORMATIONTYPE_RESPONSIBLESET, "responsible_set"}, {PROBEINFORMATIONTYPE_NUMRESOURCES, "num_resources"}, {PROBEINFORMATIONTYPE_UPTIME, "uptime"}, {0x00, NULL} }; static const value_string datakindids[] = { {DATAKINDID_INVALID, "invalid"}, {DATAKINDID_TURNSERVICE, "turn-service"}, {DATAKINDID_CERTIFICATE_BY_NODE, "certificate-by-node"}, {DATAKINDID_CERTIFICATE_BY_USER, "certificate-by-user"}, {0x00, NULL} }; static const value_string messageextensiontypes[] = { {MESSAGEEXTENSIONTYPE_RESERVED, "reservedMessageExtension"}, {0x00, NULL} }; static const value_string configupdatetypes[] = { {CONFIGUPDATETYPE_RESERVED, "reservedConfigUpdate"}, {CONFIGUPDATETYPE_CONFIG, "config"}, {CONFIGUPDATETYPE_KIND, "kind"}, {0x00, NULL} }; /* * defragmentation of IPv4 */ static GHashTable *reload_fragment_table = NULL; static GHashTable *reload_reassembled_table = NULL; static void reload_defragment_init(void) { fragment_table_init(&reload_fragment_table); reassembled_table_init(&reload_reassembled_table); } static guint get_reload_message_length(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) { guint32 length = tvb_get_ntohl(tvb, offset + MSG_LENGH_OFFSET); return length; } static int get_opaque_length(tvbuff_t *tvb, guint16 offset, guint16 length_size) { int length = -1; switch (length_size) { case 1: length = (gint32)tvb_get_guint8(tvb,offset); break; case 2: length = (gint32)tvb_get_ntohs(tvb, offset); break; case 4: length = (gint32)tvb_get_ntohl(tvb, offset); break; default: break; } return length; } static int dissect_opaque(tvbuff_t *tvb, packet_info *pinfo,proto_tree *tree, int anchor_index, guint16 offset, guint16 length_size, gint32 field_length) { proto_tree *opaque_tree; proto_item *ti_anchor; gint length_index = -1; gint32 length = -1; switch (length_size) { case 1: length_index = hf_reload_opaque_length_uint8; length = (gint32)tvb_get_guint8(tvb,offset); break; case 2: length_index = hf_reload_opaque_length_uint16; length = (gint32)tvb_get_ntohs(tvb, offset); break; case 3: length_index = hf_reload_opaque_length_uint32; length = ((gint32) (tvb_get_ntohs(tvb, offset) <<8) + (tvb_get_guint8(tvb, offset+2))); break; case 4: length_index = hf_reload_opaque_length_uint32; length = (gint32)tvb_get_ntohl(tvb, offset); break; default: break; } if (length_index < 0) return 0; ti_anchor = proto_tree_add_item(tree, anchor_index, tvb, offset, length_size + length, FALSE); if (field_length > 0) { if ((length + length_size) > field_length) { expert_add_info_format(pinfo, ti_anchor, PI_PROTOCOL, PI_ERROR, "computed length > field length"); length = field_length - length_size; } else if ((length + length_size) != field_length) { expert_add_info_format(pinfo, ti_anchor, PI_PROTOCOL, PI_WARN, "computed length != field length"); } } opaque_tree = proto_item_add_subtree(ti_anchor, ett_reload_opaque); proto_tree_add_uint(opaque_tree, length_index, tvb, offset, length_size, (guint)length); proto_tree_add_item(opaque_tree, hf_reload_opaque_data, tvb, offset + length_size, length, FALSE); return (length_size + length); } static int dissect_destination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 offset, guint16 length) { guint8 destination_length; guint8 destination_type; destination_type = tvb_get_guint8(tvb,offset); if (destination_type & 0x80) { /* simple compressed case */ destination_length = 2; proto_tree_add_item(tree, hf_reload_destination_compressed, tvb, offset, 2, FALSE); return 2; } else { /* normal case */ proto_tree *destination_tree; proto_item *ti_destination; destination_length = tvb_get_guint8(tvb,offset+1); ti_destination = proto_tree_add_item(tree, hf_reload_destination, tvb, offset, 2+destination_length, FALSE); destination_tree = proto_item_add_subtree(ti_destination, ett_reload_destination); proto_item_append_text(ti_destination, " (%s)", val_to_str(destination_type, destinationtypes, "Unknown")); proto_tree_add_item(destination_tree, hf_reload_destination_type, tvb, offset, 1, FALSE); proto_tree_add_uint(destination_tree, hf_reload_destination_length, tvb, offset+1, 1, destination_length); if (2 + destination_length > length) { expert_add_info_format(pinfo, ti_destination, PI_PROTOCOL, PI_ERROR, "Truncated destination field"); return length; } switch(destination_type) { case DESTINATIONTYPE_NODE: { proto_item *ti_node_id; /* We don't know the node ID. Just assume that all the data is part of it */ ti_node_id = proto_tree_add_item(destination_tree, hf_reload_node_id, tvb, offset+ 2, destination_length, FALSE); if ((destination_length < 16) || (destination_length > 20)) { expert_add_info_format(pinfo, ti_node_id, PI_PROTOCOL, PI_ERROR, "node id length is not in the correct range"); } } break; case DESTINATIONTYPE_RESOURCE: dissect_opaque(tvb, pinfo, destination_tree, hf_reload_resource_id, offset +2, 1, destination_length); break; case DESTINATIONTYPE_COMPRESSED: dissect_opaque(tvb, pinfo, destination_tree, hf_reload_destination_data_compressed_id, offset+2, 1, destination_length); break; default: break; } } return (2+destination_length); } static int dissect_destination_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *list_tree, guint16 offset, guint16 length) { gint local_offset = 0; gint local_increment; while (local_offset +2 <= length) { local_increment = dissect_destination(tvb, pinfo, list_tree, offset + local_offset, length-local_offset); if (local_increment == 0) break; local_offset += local_increment; } return local_offset; } static int dissect_probe_information(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 offset, guint16 length) { proto_item *ti_probe_information; proto_tree *probe_information_tree; guint8 type; guint8 probe_length; type = tvb_get_guint8(tvb, offset); probe_length = tvb_get_guint8(tvb, offset + 1); if (probe_length + 2 > length) { ti_probe_information = proto_tree_add_item(tree, hf_reload_probe_information, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_probe_information, PI_PROTOCOL, PI_ERROR, "Truncated probe information"); return length; } ti_probe_information = proto_tree_add_item(tree, hf_reload_probe_information, tvb, offset, 2 + probe_length, FALSE); probe_information_tree = proto_item_add_subtree(ti_probe_information, ett_reload_probe_information); proto_tree_add_item(probe_information_tree, hf_reload_probe_information_type, tvb, offset, 1, FALSE); proto_tree_add_uint(probe_information_tree, hf_reload_opaque_length_uint8, tvb, offset + 1, 1, probe_length); switch(type) { case PROBEINFORMATIONTYPE_RESPONSIBLESET: if (probe_length < 4) { expert_add_info_format(pinfo, ti_probe_information, PI_PROTOCOL, PI_ERROR, "Truncated Responsible Set Info"); return 2 + probe_length; } proto_tree_add_item(probe_information_tree, hf_reload_responsible_set, tvb, offset + 2, 4, FALSE); break; case PROBEINFORMATIONTYPE_NUMRESOURCES: if (probe_length < 4) { expert_add_info_format(pinfo, ti_probe_information, PI_PROTOCOL, PI_ERROR, "Truncated Num Resource Info"); return 2 + probe_length; } proto_tree_add_item(probe_information_tree, hf_reload_num_resources, tvb, offset + 2, 4, FALSE); break; case PROBEINFORMATIONTYPE_UPTIME: if (probe_length < 4) { expert_add_info_format(pinfo, ti_probe_information, PI_PROTOCOL, PI_ERROR, "Truncated Uptime Info"); return 2 + probe_length; } proto_tree_add_item(probe_information_tree, hf_reload_uptime, tvb, offset + 2, 4, FALSE); break; default: break; } return probe_length + 2; } static int dissect_ipaddressport(tvbuff_t *tvb, proto_tree *tree, guint16 offset) { proto_item *ti_ipaddressport; proto_tree *ipaddressport_tree; guint8 ipaddressport_type; guint8 ipaddressport_length; ipaddressport_length = tvb_get_guint8(tvb, offset+1); ti_ipaddressport = proto_tree_add_item(tree, hf_reload_ipaddressport, tvb, offset, ipaddressport_length+2, FALSE); ipaddressport_type = tvb_get_guint8(tvb, offset); proto_item_append_text(ti_ipaddressport, " %s ", val_to_str(ipaddressport_type, ipaddressporttypes,"Unknown Type")); ipaddressport_tree = proto_item_add_subtree(ti_ipaddressport, ett_reload_ipaddressport); proto_tree_add_item(ipaddressport_tree, hf_reload_ipaddressport_type, tvb, offset, 1, FALSE); offset +=1; proto_tree_add_uint(ipaddressport_tree, hf_reload_ipaddressport_length, tvb, offset, 1, ipaddressport_length); offset +=1; switch (ipaddressport_type) { case IPADDRESSPORTTYPE_IPV4: proto_tree_add_item(ipaddressport_tree, hf_reload_ipv4addr, tvb, offset, 4, FALSE); proto_tree_add_item(ipaddressport_tree, hf_reload_port, tvb, offset + 4, 2, FALSE); break; case IPADDRESSPORTTYPE_IPV6: proto_tree_add_item(ipaddressport_tree, hf_reload_ipv6addr, tvb, offset, 16, FALSE); proto_tree_add_item(ipaddressport_tree, hf_reload_port, tvb, offset + 16, 2, FALSE); break; default: break; } return (int) (2 + ipaddressport_length); } static int dissect_icecandidates(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 offset, guint16 length) { proto_item *ti_icecandidates; proto_tree *icecandidates_tree; guint16 icecandidates_offset = 0; guint16 icecandidates_length; guint16 local_offset = 0; icecandidates_length = tvb_get_ntohs(tvb, offset); /* Precalculate the length of the icecandidate list */ if (2+icecandidates_length > length) { ti_icecandidates = proto_tree_add_item(tree, hf_reload_icecandidates, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_icecandidates, PI_PROTOCOL, PI_ERROR, "Truncated Ice candidates"); return length; } ti_icecandidates = proto_tree_add_item(tree, hf_reload_icecandidates, tvb, offset, 2+icecandidates_length, FALSE); icecandidates_tree = proto_item_add_subtree(ti_icecandidates, ett_reload_icecandidates); proto_tree_add_uint(icecandidates_tree, hf_reload_icecandidates_length, tvb, offset+local_offset, 2, icecandidates_length); local_offset += 2; while (icecandidates_offset < icecandidates_length) { proto_item *ti_icecandidate; proto_tree *icecandidate_tree; guint8 ipaddressport_length; guint8 computed_ipaddressport_length; guint16 iceextensions_length; guint8 foundation_length; guint8 candtype; guint16 icecandidate_offset = 0; /* compute the length */ ipaddressport_length = tvb_get_guint8(tvb, offset+local_offset+icecandidates_offset+icecandidate_offset+1); icecandidate_offset += 2 + ipaddressport_length; icecandidate_offset += 1;/* OverlayLink */ foundation_length = tvb_get_guint8(tvb, offset+local_offset+icecandidates_offset+icecandidate_offset); icecandidate_offset += 1 + foundation_length; icecandidate_offset += 4;/* priority */ candtype = tvb_get_guint8(tvb, offset+local_offset+icecandidates_offset+icecandidate_offset); icecandidate_offset += 1;/* candType */ computed_ipaddressport_length = 0; switch (candtype) { case CANDTYPE_HOST: break; case CANDTYPE_SRFLX: case CANDTYPE_PRFLX: case CANDTYPE_RELAY: /* IpAddressPort */ computed_ipaddressport_length = tvb_get_guint8(tvb, offset+local_offset+icecandidates_offset+icecandidate_offset+1); icecandidate_offset += computed_ipaddressport_length+2; break; default: break; } iceextensions_length = tvb_get_ntohs(tvb, offset+local_offset+icecandidates_offset+icecandidate_offset); icecandidate_offset += iceextensions_length + 2; /* icecandidate_offset is now equal to the length of this icecandicate */ if (icecandidates_offset + icecandidate_offset > icecandidates_length) { expert_add_info_format(pinfo, ti_icecandidates, PI_PROTOCOL, PI_ERROR, "Truncated ice candidate"); break; } ti_icecandidate = proto_tree_add_item(icecandidates_tree, hf_reload_icecandidate, tvb, offset+local_offset+ icecandidates_offset, icecandidate_offset, FALSE); icecandidate_tree = proto_item_add_subtree(ti_icecandidate, ett_reload_icecandidate); /* parse from start */ icecandidate_offset = 0; dissect_ipaddressport(tvb, icecandidate_tree, offset+local_offset+icecandidates_offset+icecandidate_offset); icecandidate_offset += 2 + ipaddressport_length; proto_tree_add_item(icecandidate_tree, hf_reload_overlaylink_type, tvb, offset+local_offset+icecandidates_offset+icecandidate_offset, 1, FALSE); icecandidate_offset += 1; icecandidate_offset += dissect_opaque(tvb, pinfo,icecandidate_tree, hf_reload_icecandidate_foundation,offset+local_offset+icecandidates_offset + icecandidate_offset, 1, -1); { guint32 priority; priority = tvb_get_ntohl(tvb, offset+local_offset + icecandidates_offset); proto_tree_add_item(icecandidate_tree, hf_reload_icecandidate_priority, tvb, offset+local_offset + icecandidates_offset, 4, FALSE); icecandidate_offset += 4; proto_tree_add_item(icecandidate_tree, hf_reload_icecandidate_type, tvb, offset+local_offset+icecandidates_offset+icecandidate_offset, 1, FALSE); proto_item_append_text(ti_icecandidate, ": %s, priority=%d", val_to_str(candtype, candtypes, "Unknown"), priority); } icecandidate_offset += 1; { int item_index = -1; switch (candtype) { case CANDTYPE_HOST: break; case CANDTYPE_SRFLX: item_index = hf_reload_icecandidate_srflx_addr; break; case CANDTYPE_PRFLX: item_index = hf_reload_icecandidate_prflx_addr; break; case CANDTYPE_RELAY: item_index = hf_reload_icecandidate_relay_addr; break; default: break; } if (item_index != -1) { proto_item *ti_computed_address; proto_tree *computed_address_tree; ti_computed_address = proto_tree_add_item(icecandidate_tree, item_index, tvb, offset+local_offset+icecandidates_offset+icecandidate_offset, computed_ipaddressport_length + 2, FALSE); computed_address_tree = proto_item_add_subtree(ti_computed_address, ett_reload_icecandidate_computed_address); dissect_ipaddressport(tvb, computed_address_tree, offset+local_offset+icecandidates_offset+icecandidate_offset); icecandidate_offset += computed_ipaddressport_length + 2; } } /* Ice extensions */ { guint16 iceextensions_offset = 0; proto_item *ti_iceextension, *ti_iceextensions_length; proto_tree *iceextension_tree; guint16 iceextension_name_length; guint16 iceextension_value_length; ti_iceextensions_length = proto_tree_add_uint(icecandidate_tree, hf_reload_icecandidate_extensions_length, tvb, offset+local_offset+icecandidates_offset+icecandidate_offset, 2, iceextensions_length); icecandidate_offset += 2; while (iceextensions_offset < iceextensions_length) { iceextension_name_length = tvb_get_ntohs(tvb, offset+local_offset+icecandidates_offset+icecandidate_offset+iceextensions_offset); iceextension_value_length = tvb_get_ntohs(tvb, offset+local_offset+icecandidates_offset+icecandidate_offset+iceextensions_offset+iceextension_name_length + 2); if ((iceextensions_offset + 4 + iceextension_name_length + iceextension_value_length) > iceextensions_length) { expert_add_info_format(pinfo, ti_iceextensions_length, PI_PROTOCOL, PI_ERROR, "Truncated ice extension"); break; } ti_iceextension = proto_tree_add_item(icecandidate_tree, hf_reload_iceextension, tvb, offset+local_offset + icecandidates_offset + icecandidate_offset + iceextensions_offset, 4 + iceextension_name_length + iceextension_value_length, FALSE); iceextension_tree = proto_item_add_subtree(ti_iceextension, ett_reload_iceextension); proto_tree_add_item(iceextension_tree, hf_reload_iceextension_name, tvb, offset+local_offset+ icecandidates_offset + icecandidate_offset + iceextensions_offset, 2 + iceextension_name_length, FALSE); proto_tree_add_item(iceextension_tree, hf_reload_iceextension_value, tvb, offset+local_offset + icecandidates_offset + icecandidate_offset + iceextensions_offset +2 + iceextension_name_length, 2 + iceextension_value_length, FALSE); iceextensions_offset += 4 + iceextension_name_length + iceextension_value_length; } } icecandidate_offset += iceextensions_length; icecandidates_offset += icecandidate_offset; } return (2 + icecandidates_length); } static int dissect_attachreqans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 offset, guint16 length) { proto_item *ti_attachreqans; proto_tree *attachreqans_tree; guint8 ufrag_length; guint8 password_length; guint8 role_length; guint16 icecandidates_length; guint16 local_offset = 0; /* variable length structures: must 1st compute the length ... */ ufrag_length = tvb_get_guint8(tvb,offset+local_offset); local_offset += 1; if (local_offset + ufrag_length > length) { ti_attachreqans = proto_tree_add_item(tree, hf_reload_attachreqans, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_attachreqans, PI_PROTOCOL, PI_ERROR, "Truncated attach_reqans"); return length; } local_offset += ufrag_length; password_length = tvb_get_guint8(tvb,offset+local_offset); local_offset += 1; if (local_offset + password_length > length) { ti_attachreqans = proto_tree_add_item(tree, hf_reload_attachreqans, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_attachreqans, PI_PROTOCOL, PI_ERROR, "Truncated attach_reqans"); return length; } local_offset += password_length; role_length = tvb_get_guint8(tvb,offset+local_offset); local_offset += 1; if (local_offset + role_length > length) { ti_attachreqans = proto_tree_add_item(tree, hf_reload_attachreqans, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_attachreqans, PI_PROTOCOL, PI_ERROR, "Truncated attach_reqans"); return length; } local_offset += role_length; icecandidates_length = tvb_get_ntohs(tvb, offset+local_offset); local_offset += 2; if (local_offset +icecandidates_length > length) { ti_attachreqans = proto_tree_add_item(tree, hf_reload_attachreqans, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_attachreqans, PI_PROTOCOL, PI_ERROR, "Truncated attach_reqans"); return length; } local_offset += icecandidates_length; ti_attachreqans = proto_tree_add_item(tree, hf_reload_attachreqans, tvb, offset, local_offset, FALSE); attachreqans_tree = proto_item_add_subtree(ti_attachreqans, ett_reload_attachreqans); /* restart parsing, field by field */ local_offset = 0; local_offset += dissect_opaque(tvb, pinfo,attachreqans_tree, hf_reload_ufrag,offset+local_offset, 1, -1); local_offset += dissect_opaque(tvb, pinfo,attachreqans_tree, hf_reload_password,offset+local_offset, 1, -1); local_offset += dissect_opaque(tvb, pinfo,attachreqans_tree, hf_reload_role,offset+local_offset, 1, -1); local_offset += dissect_icecandidates(tvb, pinfo, attachreqans_tree, offset + local_offset, 2+icecandidates_length); proto_tree_add_item(attachreqans_tree, hf_reload_sendupdate, tvb, offset+local_offset, 1, FALSE); local_offset += 1; return local_offset; } static int dissect_storeddata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 offset, guint16 length) { proto_item *ti_storeddata; proto_item *storeddata_tree; guint32 storeddata_length; guint32 local_offset = 0; storeddata_length = tvb_get_ntohl(tvb, offset); local_offset += 4; if (storeddata_length + 4 > length) { ti_storeddata = proto_tree_add_item(tree, hf_reload_storeddata, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_storeddata, PI_PROTOCOL, PI_ERROR, "Truncated storeddata"); return length; } local_offset = 0; ti_storeddata = proto_tree_add_item(tree, hf_reload_storeddata, tvb, offset, 4 + storeddata_length, FALSE); storeddata_tree = proto_item_add_subtree(ti_storeddata, ett_reload_storeddata); proto_tree_add_uint(storeddata_tree, hf_reload_storeddata_length, tvb, offset + local_offset, 4, storeddata_length); local_offset += 4; proto_tree_add_item(storeddata_tree, hf_reload_storeddata_storage_time, tvb, offset + local_offset, 8, FALSE); local_offset += 8; proto_tree_add_item(storeddata_tree, hf_reload_storeddata_lifetime, tvb, offset + local_offset, 4, FALSE); /* Can not parse the value and signature fields, as we do not know what is the data model for a given kind id */ return (storeddata_length + 4); } static int dissect_kinddata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 offset, guint16 length) { proto_item *ti_kinddata; proto_item *kinddata_tree; guint32 values_length; guint32 local_offset = 0; values_length = tvb_get_ntohl(tvb, offset + 4 + 8); if (12 + values_length > length) { ti_kinddata = proto_tree_add_item(tree, hf_reload_kinddata, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_kinddata, PI_PROTOCOL, PI_ERROR, "Truncated storereq"); return length; } ti_kinddata = proto_tree_add_item(tree, hf_reload_kinddata, tvb, offset, 12+values_length, FALSE); kinddata_tree = proto_item_add_subtree(ti_kinddata, ett_reload_kinddata); proto_tree_add_item(kinddata_tree, hf_reload_kindid, tvb, offset+local_offset, 4, FALSE); local_offset += 4; proto_tree_add_item(kinddata_tree, hf_reload_kinddata_generation_counter, tvb, offset+local_offset, 8, FALSE); local_offset += 8; proto_tree_add_uint(kinddata_tree, hf_reload_kinddata_values_length, tvb, offset +local_offset, 4, values_length); local_offset += 4; { guint32 values_offset = 0; guint32 values_increment; while (values_offset < values_length) { values_increment = dissect_storeddata(tvb, pinfo, kinddata_tree, offset+local_offset+values_offset, values_length - values_offset); if (values_increment == 0) { break; } values_offset += values_increment; } } local_offset += values_length; return local_offset; } static int dissect_storereq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 offset, guint16 length) { proto_item * ti_storereq; proto_tree * storereq_tree; guint32 local_offset = 0; guint32 kind_data_length; local_offset += get_opaque_length(tvb, offset, 1); /* resource id length */ local_offset += 1; /* replica_num */ if (local_offset > length) { ti_storereq = proto_tree_add_item(tree, hf_reload_storereq, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_storereq, PI_PROTOCOL, PI_ERROR, "Truncated storereq"); return length; } kind_data_length = tvb_get_ntohl(tvb, offset + local_offset); local_offset += 4; if (local_offset + kind_data_length > length) { ti_storereq = proto_tree_add_item(tree, hf_reload_storereq, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_storereq, PI_PROTOCOL, PI_ERROR, "Truncated storereq"); return length; } local_offset += kind_data_length; ti_storereq = proto_tree_add_item(tree, hf_reload_storereq, tvb, offset, local_offset, FALSE); storereq_tree = proto_item_add_subtree(ti_storereq, ett_reload_storereq); /* Parse from start */ local_offset = 0; local_offset += dissect_opaque(tvb, pinfo, storereq_tree, hf_reload_resource_id, offset +4, 1, length); proto_tree_add_item(storereq_tree, hf_reload_store_replica_num, tvb, offset + local_offset, 1, FALSE); local_offset += 1; proto_tree_add_item(storereq_tree, hf_reload_store_kind_data_length, tvb, offset + local_offset, 4, FALSE); local_offset += 4; { guint32 kind_data_offset = 0; guint32 kind_data_increment; while (kind_data_offset < kind_data_length) { kind_data_increment = dissect_kinddata(tvb, pinfo, storereq_tree, offset+local_offset+kind_data_offset, kind_data_length - kind_data_offset); if (kind_data_increment == 0) { break; } kind_data_offset += kind_data_increment; } } local_offset += kind_data_length; return local_offset; } static int dissect_fetchans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 offset, guint16 length) { proto_item *ti_fetchans; proto_tree *fetchans_tree; guint32 kind_responses_length; guint32 kind_responses_offset = 0; kind_responses_length = tvb_get_ntohl(tvb, offset); if (4 + kind_responses_length > length) { ti_fetchans = proto_tree_add_item(tree, hf_reload_fetchans, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_fetchans, PI_PROTOCOL, PI_ERROR, "Truncated storereq"); return length; } ti_fetchans = proto_tree_add_item(tree, hf_reload_fetchans, tvb, offset, 4 + kind_responses_length, FALSE); fetchans_tree = proto_item_add_subtree(ti_fetchans, ett_reload_fetchans); proto_tree_add_uint(fetchans_tree, hf_reload_kind_responses_length, tvb, offset, 4, FALSE); while (kind_responses_offset < kind_responses_length) { guint32 kind_responses_increment; kind_responses_increment = dissect_kinddata(tvb, pinfo, fetchans_tree, offset + 4 + kind_responses_offset, kind_responses_length - kind_responses_offset); if (kind_responses_increment == 0) { break; } kind_responses_offset += kind_responses_increment; } return 4 + kind_responses_length; } static int dissect_statans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 offset, guint16 length) { proto_item *ti_statans; proto_tree *statans_tree; guint32 kind_responses_length; guint32 kind_responses_offset = 0; kind_responses_length = tvb_get_ntohl(tvb, offset); if (4 + kind_responses_length > length) { ti_statans = proto_tree_add_item(tree, hf_reload_statans, tvb, offset, length, FALSE); expert_add_info_format(pinfo, ti_statans, PI_PROTOCOL, PI_ERROR, "Truncated storereq"); return length; } ti_statans = proto_tree_add_item(tree, hf_reload_statans, tvb, offset, 4 + kind_responses_length, FALSE); statans_tree = proto_item_add_subtree(ti_statans, ett_reload_statans); proto_tree_add_uint(statans_tree, hf_reload_kind_responses_length, tvb, offset, 4, FALSE); while (kind_responses_offset < kind_responses_length) { /* assume metadata is a form of stored data */ guint32 kind_responses_increment; kind_responses_increment = dissect_kinddata(tvb, pinfo, statans_tree, offset + 4 + kind_responses_offset, kind_responses_length - kind_responses_offset); if (kind_responses_increment == 0) { break; } kind_responses_offset += kind_responses_increment; } return 4 + kind_responses_length; } static int dissect_reload_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *reload_tree; guint32 relo_token; guint effective_length; guint msg_length; guint16 offset; conversation_t *conversation; reload_conv_info_t *reload_info; reload_transaction_t * reload_trans; emem_tree_key_t transaction_id_key[2]; guint32 transaction_id[2]; guint16 options_length; guint16 via_list_length; guint16 destination_list_length; guint16 message_code; guint16 error_code = 0; guint32 forwarding_length; proto_tree *reload_forwarding_tree; const char *msg_class_str; const char *msg_method_str = NULL; gboolean fragmented = FALSE; gboolean last_fragment = FALSE; fragment_data *reload_fd_head = NULL; gboolean save_fragmented; guint32 fragment = 0; gboolean update_col_info = TRUE; offset = 0; effective_length = tvb_length(tvb); /* First, make sure we have enough data to do the check. */ if (effective_length < MIN_HDR_LENGTH) return 0; /* * First check if the frame is really meant for us. */ relo_token = tvb_get_ntohl(tvb,0); if (relo_token != RELOAD_TOKEN) { return 0; } msg_length = get_reload_message_length(pinfo, tvb, offset); if (effective_length < msg_length) { /* The effective length is too small for the packet */ expert_add_info_format(pinfo, NULL, PI_PROTOCOL, PI_ERROR, "Truncated reload packet"); return 0; } /* The message seems to be a valid reLOAD message! */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RELOAD"); col_clear(pinfo->cinfo, COL_INFO); /* Create the transaction key which may be used to track the conversation */ transaction_id[0] = tvb_get_ntohl(tvb, 20); transaction_id[1] = tvb_get_ntohl(tvb, 24); transaction_id_key[0].length = 2; transaction_id_key[0].key = transaction_id; transaction_id_key[1].length = 0; transaction_id_key[1].key = NULL; via_list_length = tvb_get_ntohs(tvb, 32); destination_list_length = tvb_get_ntohs(tvb, 34); options_length = tvb_get_ntohs(tvb, 36); forwarding_length = MIN_HDR_LENGTH + (via_list_length + destination_list_length + options_length); message_code = tvb_get_ntohs(tvb, forwarding_length); conversation = find_or_create_conversation(pinfo); /* * Do we already have a state structure for this conv */ reload_info = conversation_get_proto_data(conversation, proto_reload); if (!reload_info) { /* No. Attach that information to the conversation, and add * it to the list of information structures. */ reload_info = se_alloc(sizeof(reload_conv_info_t)); reload_info->transaction_pdus = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "reload_transaction_pdus"); conversation_add_proto_data(conversation, proto_reload, reload_info); } if (!pinfo->fd->flags.visited) { if ((reload_trans = se_tree_lookup32_array(reload_info->transaction_pdus, transaction_id_key)) == NULL) { reload_trans = se_alloc(sizeof(reload_transaction_t)); reload_trans->req_frame = 0; reload_trans->rep_frame = 0; reload_trans->req_time = pinfo->fd->abs_ts; se_tree_insert32_array(reload_info->transaction_pdus, transaction_id_key, (void *)reload_trans); } /* check whether the message is a request or a response */ if (IS_REQUEST(message_code) && (message_code != ERROR)) { /* This is a request */ if (reload_trans->req_frame == 0) { reload_trans->req_frame = pinfo->fd->num; } } else { /* This is a catch-all for all non-request messages */ if (reload_trans->rep_frame == 0) { reload_trans->rep_frame = pinfo->fd->num; } } } else { reload_trans=se_tree_lookup32_array(reload_info->transaction_pdus, transaction_id_key); } if (!reload_trans) { /* create a "fake" pana_trans structure */ reload_trans = ep_alloc(sizeof(reload_transaction_t)); reload_trans->req_frame = 0; reload_trans->rep_frame = 0; reload_trans->req_time = pinfo->fd->abs_ts; } ti = proto_tree_add_item(tree, proto_reload, tvb, 0, -1, FALSE); if (message_code == ERROR) { error_code = tvb_get_ntohs(tvb, forwarding_length + 2); msg_class_str = "ERROR Response"; col_add_fstr(pinfo->cinfo, COL_INFO, " %s %s", msg_class_str, val_to_str(error_code, errorcodes, "Unknown")); proto_item_append_text(ti, ": %s %s", msg_class_str, val_to_str(error_code, errorcodes, "Unknown")); } else { msg_class_str = match_strval(MSGCODE_TO_CLASS(message_code), classes); msg_method_str = match_strval(MSGCODE_TO_METHOD(message_code), methods); if (msg_method_str == NULL) msg_method_str = "Unknown"; col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s", msg_method_str, msg_class_str); proto_item_append_text(ti, ": %s %s", msg_method_str, msg_class_str); } reload_tree = proto_item_add_subtree(ti, ett_reload); /* Retransmission control */ if (IS_REQUEST(message_code) && (message_code != ERROR)) { if (reload_trans->req_frame != pinfo->fd->num) { proto_item *it; it = proto_tree_add_uint(reload_tree, hf_reload_duplicate, tvb, 0, 0, reload_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); } if (reload_trans->rep_frame) { proto_item *it; it = proto_tree_add_uint(reload_tree, hf_reload_response_in, tvb, 0, 0, reload_trans->rep_frame); PROTO_ITEM_SET_GENERATED(it); } } else { /* This is a response */ if (reload_trans->rep_frame != pinfo->fd->num) { proto_item *it; it = proto_tree_add_uint(reload_tree, hf_reload_duplicate, tvb, 0, 0, reload_trans->rep_frame); PROTO_ITEM_SET_GENERATED(it); } if (reload_trans->req_frame) { proto_item *it; nstime_t ns; it = proto_tree_add_uint(reload_tree, hf_reload_response_to, tvb, 0, 0, reload_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); nstime_delta(&ns, &pinfo->fd->abs_ts, &reload_trans->req_time); it = proto_tree_add_time(reload_tree, hf_reload_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(it); } } /* * Message dissection */ /* * Forwarding Header */ ti = proto_tree_add_item(reload_tree, hf_reload_forwarding, tvb, 0, forwarding_length, FALSE); reload_forwarding_tree = proto_item_add_subtree(ti, ett_reload_forwarding); proto_tree_add_uint(reload_forwarding_tree, hf_reload_token, tvb, 0, 4, relo_token); proto_tree_add_item(reload_forwarding_tree, hf_reload_overlay, tvb, 4, 4, FALSE); proto_tree_add_item(reload_forwarding_tree, hf_reload_configuration_sequence, tvb, 8, 2, FALSE); { guint8 version = tvb_get_guint8(tvb,10); proto_tree_add_uint_format_value(reload_forwarding_tree, hf_reload_version, tvb, 10, 1, version, "%u.%u", (version & 0xF0)>>4, (version & 0xF)); } proto_tree_add_item(reload_forwarding_tree, hf_reload_ttl, tvb, 11, 1, FALSE); { proto_item *ti_fragment; proto_tree *fragment_tree; guint32 bit_offset; fragment = tvb_get_ntohl(tvb,12); ti_fragment = proto_tree_add_uint(reload_forwarding_tree, hf_reload_fragment_flag, tvb, 12, 4, fragment); fragment_tree = proto_item_add_subtree(ti_fragment, ett_reload_fragment_flag); bit_offset = (12) * 8; if (fragment & 0x80000000) { proto_item_append_text(ti_fragment, " (Fragment)"); fragmented = TRUE; } if (fragment & 0x40000000) { proto_item_append_text(ti_fragment, " (Last)"); last_fragment = TRUE; } proto_tree_add_bits_item(fragment_tree, hf_reload_fragment_fragmented, tvb, bit_offset, 1, FALSE); proto_tree_add_bits_item(fragment_tree, hf_reload_fragment_last_fragment, tvb, bit_offset+1, 1, FALSE); proto_tree_add_bits_item(fragment_tree, hf_reload_fragment_reserved, tvb, bit_offset+2, 6, FALSE); fragment = fragment & 0x00ffffff; proto_tree_add_uint(fragment_tree, hf_reload_fragment_offset, tvb, 13, 3, fragment); } /* msg_length is already parsed */ proto_tree_add_uint(reload_forwarding_tree, hf_reload_length, tvb, 16, 4, msg_length); proto_tree_add_item(reload_forwarding_tree, hf_reload_trans_id, tvb, 20, 8, FALSE); proto_tree_add_item(reload_forwarding_tree, hf_reload_max_response_length, tvb, 28, 4, FALSE); /* variable lengths fields lengths are already parsed */ proto_tree_add_uint(reload_forwarding_tree, hf_reload_via_list_length, tvb, 32, 2, via_list_length); proto_tree_add_uint(reload_forwarding_tree, hf_reload_destination_list_length, tvb, 34, 2, destination_list_length); proto_tree_add_uint(reload_forwarding_tree, hf_reload_options_length, tvb, 36, 2, options_length); offset += MIN_HDR_LENGTH; if (((guint)offset + via_list_length) > msg_length) { expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_ERROR, "Truncated reload packet"); return MIN_HDR_LENGTH; } if (via_list_length > 0) { proto_item *ti_vialist; proto_tree *vialist_tree; ti_vialist = proto_tree_add_item(reload_forwarding_tree, hf_reload_via_list, tvb, offset, via_list_length, FALSE); vialist_tree = proto_item_add_subtree(ti_vialist, ett_reload_via_list); dissect_destination_list(tvb, pinfo, vialist_tree, offset, via_list_length); } offset += via_list_length; if (((guint)offset + destination_list_length) > msg_length) { expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_ERROR, "Truncated reload packet"); return offset; } if (destination_list_length > 0) { proto_item *ti_destination_list; proto_tree *destination_list_tree; ti_destination_list = proto_tree_add_item(reload_forwarding_tree, hf_reload_destination_list, tvb, offset, destination_list_length, FALSE); destination_list_tree = proto_item_add_subtree(ti_destination_list, ett_reload_destination_list); dissect_destination_list(tvb, pinfo, destination_list_tree, offset, destination_list_length); } offset += destination_list_length; if (((guint)offset + options_length) > msg_length) { expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_ERROR, "Truncated reload packet"); return offset; } if (options_length > 0) { guint16 local_offset = 0; while ((local_offset +4) <= options_length) { proto_item *ti_option; guint8 option_type = tvb_get_guint8(tvb,offset+local_offset); guint8 option_flags = tvb_get_guint8(tvb, offset+local_offset + 1); guint16 option_length = tvb_get_ntohs(tvb, offset+local_offset + 2); proto_tree *option_tree; ti_option = proto_tree_add_item(reload_forwarding_tree, hf_reload_forwarding_option, tvb, offset+local_offset, option_length + 4, FALSE); proto_item_append_text(ti_option, " type=%s, flags=%02x, length=%d", val_to_str(option_type, forwardingoptiontypes, "Unknown"), option_flags, option_length); option_tree = proto_item_add_subtree(ti_option, ett_reload_forwarding_option); proto_tree_add_item(option_tree, hf_reload_forwarding_option_type, tvb, offset+local_offset, 1, FALSE); { proto_item *ti_flags; proto_tree *flags_tree; guint32 bit_offset; ti_flags = proto_tree_add_uint(option_tree, hf_reload_forwarding_option_flags, tvb, offset+local_offset+1, 1, option_flags); flags_tree = proto_item_add_subtree(ti_flags, ett_reload_forwarding_option_flags); bit_offset = 8*(offset+local_offset+1); proto_tree_add_bits_item(flags_tree, hf_reload_forwarding_option_flag_response_copy, tvb, bit_offset+5, 1, FALSE); proto_tree_add_bits_item(flags_tree, hf_reload_forwarding_option_flag_destination_critical, tvb, bit_offset+6, 1, FALSE); proto_tree_add_bits_item(flags_tree, hf_reload_forwarding_option_flag_forward_critical, tvb, bit_offset+7, 1, FALSE); } proto_tree_add_uint(option_tree, hf_reload_forwarding_option_length, tvb, offset+local_offset+2, 2, option_length); local_offset += 4; if (local_offset + option_length > options_length) { expert_add_info_format(pinfo, ti_option, PI_PROTOCOL, PI_ERROR, "Bad option len"); break; } switch (option_type) { case OPTIONTYPE_DIRECTRESPONSEFORWARDING: { proto_item *ti_directresponseforwarding; proto_tree *directresponseforwarding_tree; guint16 option_offset = 0; ti_directresponseforwarding = proto_tree_add_item(option_tree, hf_reload_forwarding_option_directresponseforwarding, tvb, offset+local_offset, option_length, FALSE); directresponseforwarding_tree = proto_item_add_subtree(ti_directresponseforwarding, ett_reload_forwarding_option_directresponseforwarding); /* Connection_information handling */ option_offset += dissect_attachreqans(tvb, pinfo, directresponseforwarding_tree, offset + local_offset + option_offset, option_length); /* requesting node */ { gint node_id_length = option_length - option_offset; proto_item *ti_node_id; /* We don't know the node ID. Just assume that all the data is part of it */ ti_node_id = proto_tree_add_item(option_tree, hf_reload_node_id, tvb, offset+local_offset+option_offset, node_id_length, FALSE); if ((node_id_length < 16) || (node_id_length > 20)) { expert_add_info_format(pinfo, ti_node_id, PI_PROTOCOL, PI_ERROR, "node id length is not in the correct range"); } } } break; default: proto_tree_add_item(option_tree, hf_reload_forwarding_option_data, tvb, offset+local_offset, option_length, FALSE); break; } local_offset += option_length; } } offset += options_length; save_fragmented = pinfo->fragmented; if ((reload_defragment) && (fragmented != FALSE)) { tvbuff_t *next_tvb = NULL; pinfo->fragmented = TRUE; if (tvb_bytes_exist(tvb, offset, msg_length - offset)) { fragment_add_check(tvb, offset, pinfo, transaction_id[0]^transaction_id[1], reload_fragment_table, reload_reassembled_table, fragment, msg_length - offset, !last_fragment); next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled ReLOAD", reload_fd_head, &reload_frag_items, &update_col_info, reload_tree); } if (next_tvb == NULL) { /* Just show this as a fragment. */ col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented ReLOAD protocol (trans id=%x%x off=%u)", transaction_id[0],transaction_id[1], fragment); if (reload_fd_head && reload_fd_head->reassembled_in != pinfo->fd->num) { col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]", reload_fd_head->reassembled_in); } call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); pinfo->fragmented = save_fragmented; return effective_length; } tvb = next_tvb; offset = 0; } else { pinfo->fragmented = FALSE; } /* Message Contents */ if (message_code != ERROR) { guint32 message_body_length; guint32 extensions_length; proto_item *ti_message_contents; proto_tree *message_contents_tree; message_body_length = tvb_get_ntohl(tvb, offset + 2); extensions_length = tvb_get_ntohl(tvb, offset + 2 + 4 + message_body_length); if (forwarding_length + 2 + 4 + message_body_length + 4 + extensions_length > msg_length) { ti_message_contents = proto_tree_add_item(reload_tree, hf_reload_message_contents, tvb, offset, (msg_length - forwarding_length), FALSE); expert_add_info_format(pinfo, ti_message_contents, PI_PROTOCOL, PI_ERROR, "truncated message contents"); return msg_length; } ti_message_contents = proto_tree_add_item(reload_tree, hf_reload_message_contents, tvb, offset, 2 + 4 + message_body_length + 4 + extensions_length, FALSE); message_contents_tree = proto_item_add_subtree(ti_message_contents, ett_reload_message_contents); /* message_code was already parsed */ proto_tree_add_uint_format_value(message_contents_tree, hf_reload_message_code, tvb, offset, 2, message_code, "%s-%s", msg_method_str, msg_class_str); offset += 2; switch(MSGCODE_TO_METHOD(message_code)) { case METHOD_ROUTEQUERY: { if (IS_REQUEST(message_code)) { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); { proto_item * ti_routequeryreq; proto_tree * routequeryreq_tree; int destination_length; ti_routequeryreq = proto_tree_add_item(message_body_tree, hf_reload_routequeryreq, tvb, offset+4, message_body_length, FALSE); routequeryreq_tree = proto_item_add_subtree(ti_routequeryreq, ett_reload_routequeryreq); proto_tree_add_item(routequeryreq_tree, hf_reload_sendupdate, tvb, offset+4, 1, FALSE); destination_length = dissect_destination(tvb, pinfo, routequeryreq_tree, offset + 4 + 1, message_body_length - 1 - 2); dissect_opaque(tvb, pinfo, routequeryreq_tree, hf_reload_overlay_specific, offset + 4 + 1 + destination_length, 2, (message_body_length - 1 - destination_length)); } } /* Answer is entirely Overlay-specific */ } break; case METHOD_PROBE: { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); if (IS_REQUEST(message_code)) { proto_item * ti_probereq; proto_tree * probereq_tree; guint8 info_list_length = 0; ti_probereq = proto_tree_add_item(message_body_tree, hf_reload_probereq, tvb, offset+4, message_body_length, FALSE); probereq_tree = proto_item_add_subtree(ti_probereq, ett_reload_probereq); info_list_length = tvb_get_guint8(tvb, offset + 4); proto_tree_add_uint(probereq_tree, hf_reload_opaque_length_uint8, tvb, offset+4, 1, info_list_length); if (info_list_length > message_body_length - 1) { expert_add_info_format(pinfo, ti_probereq, PI_PROTOCOL, PI_ERROR, "requested info list too long for field size"); info_list_length = message_body_length - 1; } { int probe_offset = 0; while (probe_offset < info_list_length) { proto_tree_add_item(probereq_tree, hf_reload_probe_information_type, tvb, offset + 4 + 1 + probe_offset, 1, FALSE); probe_offset += 1; } } } else { /* response */ proto_item * ti_probeans; proto_tree * probeans_tree; guint16 info_list_length = 0; ti_probeans = proto_tree_add_item(message_body_tree, hf_reload_probeans, tvb, offset+4, message_body_length, FALSE); probeans_tree = proto_item_add_subtree(ti_probeans, ett_reload_probeans); info_list_length = tvb_get_ntohs(tvb, offset + 4); proto_tree_add_uint(probeans_tree, hf_reload_opaque_length_uint16, tvb, offset+4, 2, info_list_length); if (info_list_length > message_body_length - 2) { expert_add_info_format(pinfo, ti_probeans, PI_PROTOCOL, PI_ERROR, "requested info list too long for field size"); info_list_length = message_body_length - 2; } { int probe_offset = 0; int probe_increment; while (probe_offset < info_list_length) { probe_increment = dissect_probe_information(tvb, pinfo, probeans_tree, offset + 4 + 2 + probe_offset, info_list_length - probe_offset); if (probe_increment == 0) { break; } probe_offset += probe_increment; } } } } break; case METHOD_ATTACH: { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); dissect_attachreqans(tvb, pinfo, message_body_tree, offset+4, message_body_length); } break; case METHOD_APPATTACH: { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); /* Parse AppAttachReq/Ans */ { guint16 local_offset = 0; proto_item *ti_appattach; proto_tree *appattach_tree; ti_appattach = proto_tree_add_item(tree, hf_reload_appattach, tvb, offset+4+local_offset, message_body_length, FALSE); appattach_tree = proto_item_add_subtree(ti_appattach, ett_reload_appattach); local_offset += dissect_opaque(tvb, pinfo,appattach_tree, hf_reload_ufrag,offset+4+local_offset, 1, message_body_length); local_offset += dissect_opaque(tvb, pinfo,appattach_tree, hf_reload_password,offset+4+local_offset, 1, message_body_length-local_offset); proto_tree_add_item(appattach_tree, hf_reload_application, tvb, offset+4+local_offset, message_body_length-local_offset, FALSE); local_offset += 2; local_offset += dissect_opaque(tvb, pinfo,appattach_tree, hf_reload_role,offset+4+local_offset, 1, message_body_length-local_offset); dissect_icecandidates(tvb, pinfo, appattach_tree, offset+4+local_offset, message_body_length-local_offset); } } break; case METHOD_PING: { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); if (IS_REQUEST(message_code)) { if (message_body_length != 0) { expert_add_info_format(pinfo, ti_message_contents, PI_PROTOCOL, PI_WARN, "ping request body should be empty"); } } else { if (message_body_length < 16) { expert_add_info_format(pinfo, ti_message_contents, PI_PROTOCOL, PI_ERROR, "Truncated ping Answer"); } else { proto_tree_add_item(message_body_tree, hf_reload_ping_response_id, tvb, offset + 4, 8, FALSE); proto_tree_add_item(message_body_tree, hf_reload_ping_time, tvb, offset + 12, 8, FALSE); } } } break; case METHOD_CONFIGUPDATE: { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); if (IS_REQUEST(message_code)) { guint16 local_offset = 0; proto_item *ti_configupdate; proto_tree *configupdate_tree; guint8 configupdate_type; guint32 configupdate_length; ti_configupdate = proto_tree_add_item(message_body_tree, hf_reload_configupdatereq, tvb, offset+4+local_offset, message_body_length, FALSE); configupdate_tree = proto_item_add_subtree(ti_configupdate, ett_reload_configupdatereq); configupdate_type = tvb_get_guint8(tvb, offset + 4 + local_offset); proto_tree_add_uint(configupdate_tree, hf_reload_configupdatereq_type, tvb, offset+4+local_offset, 1, configupdate_type); local_offset += 1; configupdate_length = tvb_get_ntohl(tvb, offset + 4 + local_offset); proto_tree_add_uint(configupdate_tree, hf_reload_configupdatereq_length, tvb, offset + 4 + local_offset, 4, configupdate_length); if (5 + configupdate_length > message_body_length) { expert_add_info_format(pinfo, ti_configupdate, PI_PROTOCOL, PI_ERROR, "Truncated ConfigupdateReq"); break; } local_offset += 4; switch(configupdate_type) { case CONFIGUPDATETYPE_CONFIG: local_offset += dissect_opaque(tvb, pinfo, configupdate_tree, hf_reload_configupdatereq_configdata, offset + 4 + local_offset, 3, configupdate_length); break; case CONFIGUPDATETYPE_KIND: local_offset += dissect_opaque(tvb, pinfo, configupdate_tree, hf_reload_configupdatereq_kinds, offset + 4 + local_offset, 3, configupdate_length); break; } } } case METHOD_STORE: { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); if (IS_REQUEST(message_code)) { dissect_storereq(tvb, pinfo, message_body_tree, offset + 4, message_body_length); } else { guint16 storeans_kind_responses_length; guint32 local_offset = 0; proto_item *ti_storeans_kind_responses; proto_tree *storeans_kind_responses_tree; ti_storeans_kind_responses = proto_tree_add_item(message_body_tree, hf_reload_storeans_kind_responses, tvb, offset + 4, message_body_length, FALSE); storeans_kind_responses_tree = proto_item_add_subtree(ti_storeans_kind_responses, ett_reload_storeans_kind_responses); storeans_kind_responses_length = tvb_get_ntohs(tvb, offset + 4); proto_tree_add_uint(storeans_kind_responses_tree, hf_reload_storeans_kind_responses_length, tvb, offset + 4, 2, storeans_kind_responses_length); if ((guint32)storeans_kind_responses_length + 2 > message_body_length) { expert_add_info_format(pinfo, ti_storeans_kind_responses, PI_PROTOCOL, PI_ERROR, "Truncated StoreAns"); break; } while (local_offset + 4 + 8 + 2< storeans_kind_responses_length) { proto_item *ti_storekindresponse; proto_tree *storekindresponse_tree; guint16 replicas_length; replicas_length = tvb_get_ntohs(tvb, offset + 4 + local_offset +4 + 8); if (local_offset + 4 + 8 + 2 +replicas_length > storeans_kind_responses_length) { expert_add_info_format(pinfo, ti_storeans_kind_responses, PI_PROTOCOL, PI_ERROR, "Truncated StoreKindResponse"); break; } ti_storekindresponse = proto_tree_add_item(storeans_kind_responses_tree, hf_reload_storekindresponse, tvb, offset+4+local_offset, 4+ 8 + 2 + replicas_length, FALSE); storekindresponse_tree = proto_item_add_subtree(ti_storekindresponse, ett_reload_storekindresponse); proto_tree_add_item(storekindresponse_tree, hf_reload_kindid, tvb, offset+4+local_offset, 4, FALSE); local_offset += 4; proto_tree_add_item(storekindresponse_tree, hf_reload_kinddata_generation_counter, tvb, offset+4+local_offset, 8, FALSE); local_offset += 8; local_offset += dissect_opaque(tvb, pinfo, storekindresponse_tree, hf_reload_storekindresponse_replicas, offset + 4 + local_offset, 2, (storeans_kind_responses_length-(local_offset+4+8))); } } } break; case METHOD_FETCH: { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); if (IS_REQUEST(message_code)) { guint16 fetch_offset = 0; fetch_offset += dissect_opaque(tvb, pinfo, message_body_tree, hf_reload_resource_id, offset + 4, 1, message_body_length); fetch_offset += dissect_opaque(tvb, pinfo, message_body_tree, hf_reload_storeddataspecifiers, offset + fetch_offset, 2, message_body_length - fetch_offset); } else { /* response */ dissect_fetchans(tvb, pinfo, message_body_tree, offset + 4, message_body_length); } } break; case METHOD_STAT: { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); if (IS_REQUEST(message_code)) { guint16 stat_offset = 0; stat_offset += dissect_opaque(tvb, pinfo, message_body_tree, hf_reload_resource_id, offset + 4, 1, message_body_length); stat_offset += dissect_opaque(tvb, pinfo, message_body_tree, hf_reload_storeddataspecifiers, offset + stat_offset, 2, message_body_length - stat_offset); } else { dissect_statans(tvb, pinfo, message_body_tree, offset + 4, message_body_length); } } break; case METHOD_FIND: { proto_item *ti_message_body; proto_tree *message_body_tree; ti_message_body = proto_tree_add_item(message_contents_tree, hf_reload_message_body, tvb, offset, 4 + message_body_length, FALSE); message_body_tree = proto_item_add_subtree(ti_message_body, ett_reload_message_body); proto_tree_add_uint(message_body_tree, hf_reload_opaque_length_uint32, tvb, offset, 4, message_body_length); if (IS_REQUEST(message_code)) { guint32 find_offset = 0; guint8 kinds_length; find_offset += dissect_opaque(tvb, pinfo, message_body_tree, hf_reload_resource_id, offset + 4, 1, message_body_length); kinds_length = tvb_get_guint8(tvb, offset + 4 + find_offset); if (find_offset + 1 + kinds_length > message_body_length) { expert_add_info_format(pinfo, ti_message_body, PI_PROTOCOL, PI_ERROR, "Truncated Find Request"); break; } proto_tree_add_uint(message_body_tree, hf_reload_findreq_kinds_length, tvb, offset + 4 + find_offset, 1, kinds_length); find_offset += 1; { guint8 kinds_offset = 0; while (kinds_offset < kinds_length) { proto_tree_add_item(message_body_tree, hf_reload_kindid, tvb, offset+find_offset+kinds_offset, 4, FALSE); kinds_offset += 4; } } } else { guint16 results_length; results_length = tvb_get_ntohs(tvb, offset + 4); if ((guint32)results_length + 2 > message_body_length) { expert_add_info_format(pinfo, ti_message_body, PI_PROTOCOL, PI_ERROR, "Truncated Find Answer"); break; } proto_tree_add_uint(message_body_tree, hf_reload_findans_results_length, tvb, offset + 4, 2, results_length); { guint16 results_offset = 0; while (results_offset < results_length) { proto_item *ti_findkinddata; proto_tree *findkinddata_tree; guint16 findkinddata_length; findkinddata_length = 4 + get_opaque_length(tvb,offset + 4 + results_offset + 4, 1); if (results_offset + findkinddata_length > results_length) { ti_findkinddata = proto_tree_add_item(tree, hf_reload_findkinddata, tvb, offset + 4 + results_offset, results_length - results_offset, FALSE); expert_add_info_format(pinfo, ti_findkinddata, PI_PROTOCOL, PI_ERROR, "Truncated FindKindData"); break; } ti_findkinddata = proto_tree_add_item(tree, hf_reload_findkinddata, tvb, offset + 4 + results_offset, findkinddata_length, FALSE); findkinddata_tree = proto_item_add_subtree(ti_findkinddata, ett_reload_findkinddata); proto_tree_add_item(findkinddata_tree, hf_reload_kindid, tvb, offset + 4 + results_offset, 4, FALSE); dissect_opaque(tvb, pinfo, findkinddata_tree, hf_reload_resource_id, offset + 4 + results_offset + 4, 1, results_length - 4 - results_offset); results_offset += findkinddata_length; } } } } break; default: dissect_opaque(tvb, pinfo, message_contents_tree, hf_reload_message_body, offset, 4, -1); break; } offset += 4 + message_body_length; { proto_tree *extension_tree; guint16 extension_offset = 0; proto_tree_add_item(message_contents_tree, hf_reload_message_extensions_length, tvb, offset, 4, FALSE); offset += 4; while (extension_offset < extensions_length) { proto_item *ti_extension; guint32 extension_content_length = tvb_get_ntohl(tvb, offset + extension_offset + 3); if ((extension_offset + 3 + 4 + extension_content_length) > extensions_length) { expert_add_info_format(pinfo, ti_message_contents, PI_PROTOCOL, PI_ERROR, "truncated message extensions"); break; } ti_extension = proto_tree_add_item(message_contents_tree, hf_reload_message_extension, tvb, offset+ extension_offset, 3 + 4 + extension_content_length, FALSE); extension_tree = proto_item_add_subtree(ti_extension, ett_reload_message_extension); proto_tree_add_item(extension_tree, hf_reload_message_extension_type, tvb, offset+ extension_offset, 2, FALSE); proto_tree_add_item(extension_tree, hf_reload_message_extension_critical, tvb, offset+ extension_offset + 2, 1, FALSE); dissect_opaque(tvb, pinfo, extension_tree, hf_reload_message_extension_content, offset + extension_offset + 3, 4, -1); extension_offset += 3 + 4 + extension_content_length; } } offset += extensions_length; } else { /* Error Response */ guint16 error_length; proto_item *ti_message_contents; proto_tree *message_contents_tree; proto_item *ti_error; proto_tree *error_tree; error_length = tvb_get_ntohs(tvb, offset + 2 + 2); if ((guint)offset + 2 + 2 + 2 + error_length > msg_length) { expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_ERROR, "truncated error message"); return msg_length; } ti_message_contents = proto_tree_add_item(reload_tree, hf_reload_message_contents, tvb, offset, 2 + 2 + 2 + error_length , FALSE); message_contents_tree = proto_item_add_subtree(ti_message_contents, ett_reload_message_contents); /* message_code was already parsed */ proto_tree_add_uint_format_value(message_contents_tree, hf_reload_message_code, tvb, offset, 2, message_code, "ERROR Response"); offset += 2; ti_error = proto_tree_add_item(message_contents_tree, hf_reload_error_response, tvb, offset, 2 + 2 + error_length, FALSE); error_tree = proto_item_add_subtree(ti_error, ett_reload_error_response); proto_tree_add_item(error_tree, hf_reload_error_response_code, tvb, offset, 2, FALSE); offset += 2; dissect_opaque(tvb, pinfo, error_tree, hf_reload_error_response_info, offset, 2, -1); proto_item_append_text(error_tree, ": %s (%s)", val_to_str(error_code, errorcodes, "Unknown"), tvb_get_ephemeral_string(tvb, offset+2, error_length)); offset += 2 + error_length; } /* Security Block */ { proto_item *ti_security_block; proto_tree *security_block_tree; guint16 certificates_length; guint16 signatureidentityvalue_length; guint16 signaturevalue_length; guint16 security_block_offset = 0; certificates_length = tvb_get_ntohs(tvb, offset); security_block_offset += 2 + certificates_length; security_block_offset += 2; /* SignatureAndHashAlgorithm algorithm; */ security_block_offset += 1; /* SignerIdentityType identity_type; */ signatureidentityvalue_length = tvb_get_ntohs(tvb, offset +security_block_offset); security_block_offset += 2; security_block_offset += signatureidentityvalue_length; signaturevalue_length = tvb_get_ntohs(tvb, offset +security_block_offset); security_block_offset += 2; security_block_offset += signaturevalue_length; ti_security_block = proto_tree_add_item(reload_tree, hf_reload_security_block, tvb, offset, security_block_offset, FALSE); security_block_tree = proto_item_add_subtree(ti_security_block, ett_reload_security_block); /* start parsing from the beginning */ security_block_offset = 0; proto_tree_add_uint(security_block_tree, hf_reload_certificates_length, tvb, offset, 2, certificates_length); security_block_offset += 2; /* certificates */ { guint16 certificate_offset = 0; while (certificate_offset < certificates_length) { proto_item *ti_certificate; proto_tree *certificate_tree; guint16 certificate_length; certificate_length = tvb_get_ntohs(tvb, offset + security_block_offset + certificate_offset + 1); if (certificate_offset + 1 + 2 + certificate_length > certificates_length) { expert_add_info_format(pinfo, ti_security_block, PI_PROTOCOL, PI_ERROR, "truncated certificate"); break; } ti_certificate = proto_tree_add_item(security_block_tree, hf_reload_certificate, tvb, offset+security_block_offset + certificate_offset, 1 + 2 + certificate_length, FALSE); certificate_tree = proto_item_add_subtree(ti_certificate, ett_reload_certificate); proto_tree_add_item(certificate_tree, hf_reload_certificate_type, tvb, offset + security_block_offset + certificate_offset, 1, FALSE); dissect_opaque(tvb, pinfo, certificate_tree, hf_reload_certificate_data, offset+security_block_offset + certificate_offset+1, 2, -1); certificate_offset += 1 + 2 + certificate_length; } } security_block_offset += certificates_length; /* Signature */ { proto_item *ti_signature; proto_tree *signature_tree; ti_signature = proto_tree_add_item(security_block_tree, hf_reload_signature, tvb, offset+security_block_offset , 2 +/* SignatureAndHashAlgorithm */ 1 + 2 + signatureidentityvalue_length +/* SignatureIdenty length*/ 2 + signaturevalue_length, FALSE); signature_tree = proto_item_add_subtree(ti_signature, ett_reload_signature); proto_tree_add_item(signature_tree, hf_reload_hash_algorithm, tvb, offset + security_block_offset, 1, FALSE); security_block_offset += 1; proto_tree_add_item(signature_tree, hf_reload_signature_algorithm, tvb, offset + security_block_offset, 1, FALSE); security_block_offset += 1; /* SignatureIdentity */ { proto_item *ti_signatureidentity; proto_tree *signatureidentity_tree; guint8 identity_type; ti_signatureidentity = proto_tree_add_item(signature_tree, hf_reload_signature_identity, tvb, offset+security_block_offset, 1 + 2 + signatureidentityvalue_length, FALSE); signatureidentity_tree = proto_item_add_subtree(ti_signatureidentity, ett_reload_signature_identity); identity_type = tvb_get_guint8(tvb, offset + security_block_offset); proto_tree_add_item(signatureidentity_tree, hf_reload_signature_identity_type, tvb, offset + security_block_offset, 1, FALSE); security_block_offset += 1; proto_tree_add_uint(signatureidentity_tree, hf_reload_signature_identity_length, tvb, offset + security_block_offset, 2, signatureidentityvalue_length); security_block_offset += 2; { guint16 signatureidentityvalue_offset = 0; while (signatureidentityvalue_offset < signatureidentityvalue_length) { proto_item *ti_signatureidentityvalue; proto_tree *signatureidentityvalue_tree; if (identity_type == SIGNATUREIDENTITYTYPE_CERTHASH) { guint8 certificate_hash_length; certificate_hash_length = tvb_get_guint8(tvb, offset + security_block_offset + signatureidentityvalue_offset + 1); if (signatureidentityvalue_offset + 1 + 1 + certificate_hash_length > signatureidentityvalue_length) { expert_add_info_format(pinfo, ti_signatureidentity, PI_PROTOCOL, PI_ERROR, "truncated signature identity value"); break; } ti_signatureidentityvalue= proto_tree_add_item(signatureidentity_tree, hf_reload_signature_identity_value, tvb, offset + security_block_offset + signatureidentityvalue_offset, 1 + 1 + certificate_hash_length, FALSE); signatureidentityvalue_tree = proto_item_add_subtree(ti_signatureidentityvalue, ett_reload_signature_identity_value); proto_tree_add_item(signatureidentityvalue_tree, hf_reload_hash_algorithm, tvb, offset + security_block_offset +signatureidentityvalue_offset, 1, FALSE); dissect_opaque(tvb, pinfo, signatureidentityvalue_tree, hf_reload_signature_identity_value_certificate_hash, offset + security_block_offset + signatureidentityvalue_offset+1, 1, -1); signatureidentityvalue_offset += 1 + 1 + certificate_hash_length; } else { expert_add_info_format(pinfo, ti_signatureidentity, PI_PROTOCOL, PI_ERROR, "Unknown identity type"); break; } } } security_block_offset += signatureidentityvalue_length; } dissect_opaque(tvb, pinfo, signature_tree, hf_reload_signature_value, offset + security_block_offset, 2, -1); } } return msg_length; } static int dissect_reload_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { return dissect_reload_message(tvb, pinfo, tree); } static void dissect_reload_message_no_return(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { dissect_reload_message(tvb, pinfo, tree); } static void dissect_reload_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tcp_dissect_pdus(tvb, pinfo, tree, TRUE, MIN_HDR_LENGTH, get_reload_message_length, dissect_reload_message_no_return); } static gboolean dissect_reload_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { if (dissect_reload_message(tvb, pinfo, tree) == 0) { /* * It wasn't a valid RELOAD message, and wasn't * dissected as such. */ return FALSE; } return TRUE; } void proto_register_reload(void) { module_t *reload_module; static hf_register_info hf[] = { { &hf_reload_response_in, { "Response In", "reload.response-in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "The response to this ReLOAD Request is in this frame", HFILL } }, { &hf_reload_response_to, { "Request In", "reload.response-to", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "This is a response to the ReLOAD Request in this frame", HFILL } }, { &hf_reload_time, { "Time", "reload.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, "The time between the Request and the Response", HFILL } }, { &hf_reload_duplicate, { "Duplicated original message in", "reload.duplicate", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "This is a duplicate of ReLOAD message in this frame", HFILL } }, { &hf_reload_forwarding, { "Forwarding Header", "reload.forwarding", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_token, { "ReLOAD token", "reload.forwarding.token", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_reload_overlay, { "Overlay", "reload.forwarding.overlay", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_reload_configuration_sequence, { "Configuration Sequence", "reload.forwarding.configuration_sequence", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_version, { "Version", "reload.forwarding.version", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_reload_ttl, { "TTL", "reload.forwarding.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_fragment_flag, { "Fragment", "reload.forwarding.fragment", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_reload_fragment_fragmented, { "Fragmented Bit", "reload.forwarding.fragment.fragmented", FT_BOOLEAN, 1, TFS(&tfs_set_notset), 0x0, NULL, HFILL } }, { &hf_reload_fragment_last_fragment, { "Last fragment bit", "reload.forwarding.fragment.last", FT_BOOLEAN, 1, TFS(&tfs_set_notset), 0x0, NULL, HFILL } }, { &hf_reload_fragment_reserved, { "Reserved", "reload.forwarding.fragment.reserved", FT_BOOLEAN, 1, NULL, 0x0, NULL, HFILL } }, { &hf_reload_fragment_offset, { "Fragment offset","reload.forwarding.fragment.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_length, { "Length", "reload.forwarding.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_trans_id, { "Transaction ID", "reload.forwarding.trans_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_max_response_length, { "Max response length", "reload.forwarding.max_response_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_via_list_length, { "Via-list length", "reload.forwarding.via_list.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_destination_list_length, { "Destination list length", "reload.forwarding.destination_list.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_options_length, { "Options length", "reload.forwarding.options.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_via_list, { "via list", "reload.forwarding.via_list", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_destination, { "Destination", "reload.forwarding.destination", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_destination_compressed, { "Destination (compressed)", "reload.forwarding.destination.compressed_id", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_reload_destination_type, { "Destination type", "reload.forwarding.destination.type", FT_UINT8, BASE_HEX, VALS(destinationtypes), 0x0, NULL, HFILL } }, { &hf_reload_destination_length, { "Destination length", "reload.forwarding.destination.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_node_id, { "node id", "reload.node_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_resource_id, { "resource id", "reload.resource_id", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_destination_data_compressed_id, { "compressed id", "reload.destination.data.compressed_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_destination_list, { "destination list", "reload.forwarding.destination_list", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_forwarding_option, { "forwarding option", "reload.forwarding.option", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_forwarding_option_type, { "forwarding option type", "reload.forwarding.option.type", FT_UINT8, BASE_DEC, VALS(forwardingoptiontypes), 0x0, NULL, HFILL } }, { &hf_reload_forwarding_option_flags, { "forwarding option flags", "reload.forwarding.option.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_reload_forwarding_option_length, { "forwarding option length", "forwarding.option.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_forwarding_option_data, { "forwarding option data", "reload.forwarding.option.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_forwarding_option_flag_response_copy, { "Response Copy", "reload.forwarding.option.flag.response_copy", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x0, NULL, HFILL } }, { &hf_reload_forwarding_option_flag_destination_critical, { "Response destination critical", "reload.forwarding.option.flags.destination_critical", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x0, NULL, HFILL } }, { &hf_reload_forwarding_option_flag_forward_critical, { "Forward Critical", "reload.forwarding.option.flags.forward_critical", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x0, NULL, HFILL } }, { &hf_reload_forwarding_option_directresponseforwarding, { "Direct Response Forwarding", "reload.forwarding.option.direct_response_forwarding", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_attachreqans, { "AttachReqAns", "reload.attachreqans", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_ufrag, { "ufrag", "reload.ufrag", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_password, { "password", "reload.password", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_role, { "Role", "reload.role", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_icecandidates, { "ice candidates", "reload.icecandidates", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_icecandidates_length, { "ice candidates length", "reload.icecandidates.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_icecandidate, { "ice candidate", "reload.icecandidate", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_icecandidate_relay_addr, { "relay address", "reload.icecandidate.relay_addr", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_icecandidate_srflx_addr, { "srflx address", "reload.icecandidate.srflx_addr", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_icecandidate_prflx_addr, { "prfkx address", "reload.icecandidate.prflx_addr", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_ipaddressport, { "Ip Address Port", "reload.ipaddressport", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_ipaddressport_type, { "Ip Address-Port Type", "reload.ipaddressport.type", FT_UINT8, BASE_HEX, VALS(ipaddressporttypes), 0x0, NULL, HFILL } }, { &hf_reload_ipaddressport_length, { "Ip Address-Port Length", "reload.ipaddressport.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_ipv4addr, { "Ipv4 Address", "reload.ipv4addr", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_ipv6addr, { "Ipv6 Address", "reload.ipv6addr", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_port, { "port", "reload.port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_overlaylink_type, { "Overlay Link Type", "reload.overlaylink.type", FT_UINT8, BASE_DEC, VALS(overlaylinktypes), 0x0, NULL, HFILL } }, { &hf_reload_icecandidate_foundation, { "Ice Candidate foundation", "reload.icecandidate.foundation", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_icecandidate_priority, { "Ice Candidate Priority", "reload.icecandidate.priority", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_icecandidate_type, { "Ice Candidate type", "reload.icecandidate.type", FT_UINT8, BASE_DEC, VALS(candtypes), 0x0, NULL, HFILL } }, { &hf_reload_icecandidate_extensions_length, { "Ice Candidate Extensions Length", "reload.icecandidate.extensions_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_iceextension, { "ice Extension", "reload.iceextension", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_iceextension_name, { "Ice Extension Name", "reload.iceextension.name", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_iceextension_value, { "Ice Extension Value", "reload.iceextension.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_sendupdate, { "SendUpdate", "reload.sendupdate", FT_BOOLEAN, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_message_contents, { "message contents", "reload.message.contents", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_message_code, { "Message Code", "reload.message.code", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_message_body, { "Message Body", "reload.message.body", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_message_extensions_length, { "Message extensions length", "reload.message.extensions.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_message_extension, { "message extension", "reload.message_extension", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_message_extension_type, { "Message extension type", "reload.message_extension.type", FT_UINT16, BASE_DEC, VALS(messageextensiontypes), 0x0, NULL, HFILL } }, { &hf_reload_message_extension_critical, { "Message extension critical", "reload.message_extension.critical", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_message_extension_content, { "Message extension content", "reload.message_extension.content", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_error_response, { "error response", "reload.error_response", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_error_response_code, { "error code", "reload.error_response.code", FT_UINT16, BASE_DEC, VALS(errorcodes), 0x0, NULL, HFILL } }, { &hf_reload_error_response_info, { "error info", "reload.error_response_info", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_security_block, { "Security Block", "reload.security_block", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_certificates_length, { "certificates length", "reload.certificates.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_certificate, { "Certificate", "reload.certificate", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_certificate_type, { "Certificate type", "reload.certificate.type", FT_UINT8, BASE_DEC, VALS(certificatetypes), 0x0, NULL, HFILL } }, { &hf_reload_certificate_data, { "certificate data", "reload.certificate.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_signature, { "Signature", "reload.signature", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_hash_algorithm, { "Hash Algorithm", "reload.hash_algorithm", FT_UINT8, BASE_DEC, VALS(hashalgorithms), 0x0, NULL, HFILL } }, { &hf_reload_signature_algorithm, { "Signature Algorithm", "reload.signature_algorithm", FT_UINT8, BASE_DEC, VALS(signaturealgorithms), 0x0, NULL, HFILL } }, { &hf_reload_signature_identity, { "Signature Identity", "reload.signature.identity", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_signature_identity_type, { "Signature Identity Type", "reload.signature.identity.type", FT_UINT8, BASE_DEC, VALS(signatureidentitytypes), 0x0, NULL, HFILL } }, { &hf_reload_signature_identity_length, { "Signature Identity Length", "reload.signature.identity.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_signature_identity_value, { "Signature Identity Value", "reload.signature.identity.value", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_signature_identity_value_certificate_hash, { "Signature Identity Value Certificate Hash", "reload.signature.identity.value.certificate_hash", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_signature_value, { "Signature Value", "reload.signature.value.", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_opaque_length_uint8, { "length", "reload.opaque.length.8", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_opaque_length_uint16, { "length", "reload.opaque.length.6", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_opaque_length_uint32, { "length", "reload.opaque.length.32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_opaque_data, { "data", "reload.opaque.length.8", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_routequeryreq, { "RouteQueryReq", "reload.routequeryreq", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_overlay_specific, { "Overlay Specific Data", "reload.overlay.specific.data", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_probereq, { "ProbeReq", "reload.probereq", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_probe_information, { "Probe Information", "reload.probe_information", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_probe_information_type, { "Probe Information Type", "reload.probe_information.type", FT_UINT8, BASE_HEX, VALS(probeinformationtypes), 0x0, NULL, HFILL } }, { &hf_reload_responsible_set, { "Responsible Set", "reload.responsible_set", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_reload_num_resources, { "Num Resources", "reload.num_resources", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_uptime, { "Uptime", "reload.uptime", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_probeans, { "Probe Ans", "reload.probeans", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_appattach, { "App Attach Req/Ans", "reload.appattach", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_application, { "Uptime", "reload.uptime", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_ping_response_id, { "Ping Response Id", "reload.ping.response_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_ping_time, { "Ping Time", "reload.ping.time", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storeddata, { "Stored Data", "reload.storeddata", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storeddata_length, { "Stored Data length", "reload.storeddata.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storeddata_storage_time, { "Stored Data storage time", "reload.storeddata.storage_time", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storeddata_lifetime, { "Stored Lifetime", "reload.storeddata.lifetime", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_kinddata, { "Kind Data", "reload.kinddata", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_kindid, { "Kind Id", "reload.kindid", FT_UINT32, BASE_DEC, VALS(datakindids), 0x0, NULL, HFILL } }, { &hf_reload_kinddata_generation_counter, { "Generation Counter", "reload.kinddata.generation_counter", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_kinddata_values_length, { "Values Length", "reload.kinddata.values_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storereq, { "StoreReq", "reload.storereq", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_store_replica_num, { "replica num", "reload.store.replica_num", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_store_kind_data_length, { "replica num", "reload.store.kind_data.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storeans_kind_responses, { "Kind Responses", "reload.storeans.kind_responses", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storeans_kind_responses_length, { "Kind Responses Length", "reload.storeans.kind_responses.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storekindresponse, { "Store Kind Response", "reload.storekindresponse", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storekindresponse_replicas, { "Store Kind Response Replicas", "reload.storekindresponse.replicas", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_storeddataspecifiers, { "StoredDataSpecifiers", "reload.storeddataspecifiers", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_fetchans, { "FetchAns", "reload.fetchans", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_kind_responses_length, { "Kind Responses Length", "reload.fetchans.kind_responses.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_statans, { "StatAns", "reload.statans", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_findreq_kinds_length, { "Kinds Length", "reload.findreq.kindslength", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_findans_results_length, { "Results Length", "reload.findans.resultsslength", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_findkinddata, { "FindKindData", "reload.findkinddata", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_fragment_overlap, { "Fragment overlap", "reload.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment overlaps with other fragments", HFILL }}, { &hf_reload_fragment_overlap_conflict, { "Conflicting data in fragment overlap", "reload.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }}, { &hf_reload_fragment_multiple_tails, { "Multiple tail fragments found", "reload.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }}, { &hf_reload_fragment_too_long_fragment, { "Fragment too long", "reload.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment contained data past end of packet", HFILL }}, { &hf_reload_fragment_error, { "Defragmentation error", "reload.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }}, { &hf_reload_fragment, { "ReLOAD Fragment", "reload.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_reload_fragments, { "ReLOAD Fragments", "reload.fragments", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_reload_reassembled_in, { "Reassembled ReLOAD in frame", "reload.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "This ReLOAD packet is reassembled in this frame", HFILL }}, { &hf_reload_reassembled_length, { "Reassembled ReLOAD length", "reload.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0, "The total length of the reassembled payload", HFILL }}, { &hf_reload_configupdatereq, { "ConfigUpdate Req", "reload.configupdatereq.", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_configupdatereq_type, { "ConfigUpdate Req Type", "reload.configupdatereq.type", FT_UINT8, BASE_DEC, VALS(configupdatetypes), 0x0, NULL, HFILL } }, { &hf_reload_configupdatereq_length, { "ConfigUpdate Req Length", "reload.configupdatereq.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_reload_configupdatereq_configdata, { "ConfigUpdate Req Config Data", "reload.configupdatereq.config_data", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_reload_configupdatereq_kinds, { "ConfigUpdate Req Kinds", "reload.configupdatereq.kinds", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, }; /* Setup protocol subtree array */ static gint *ett[] = { &ett_reload, &ett_reload_forwarding, &ett_reload_message, &ett_reload_security, &ett_reload_fragment_flag, &ett_reload_destination, &ett_reload_via_list, &ett_reload_destination_list, &ett_reload_forwarding_option, &ett_reload_forwarding_option_flags, &ett_reload_forwarding_option_directresponseforwarding, &ett_reload_attachreqans, &ett_reload_icecandidates, &ett_reload_icecandidate, &ett_reload_icecandidate_computed_address, &ett_reload_iceextension, &ett_reload_ipaddressport, &ett_reload_message_contents, &ett_reload_message_extension, &ett_reload_error_response, &ett_reload_security_block, &ett_reload_certificate, &ett_reload_signature, &ett_reload_signature_identity, &ett_reload_signature_identity_value, &ett_reload_opaque, &ett_reload_message_body, &ett_reload_routequeryreq, &ett_reload_probereq, &ett_reload_probe_information, &ett_reload_probeans, &ett_reload_appattach, &ett_reload_storeddata, &ett_reload_kinddata, &ett_reload_storereq, &ett_reload_storeans_kind_responses, &ett_reload_storekindresponse, &ett_reload_fetchans, &ett_reload_statans, &ett_reload_findkinddata, &ett_reload_fragments, &ett_reload_fragment, &ett_reload_configupdatereq, }; /* Register the protocol name and description */ proto_reload = proto_register_protocol("REsource LOcation And Discovery", "RELOAD", "reload"); register_dissector("reload", dissect_reload_message_no_return, proto_reload); /* Required function calls to register the header fields and subtrees used */ proto_register_field_array(proto_reload, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); reload_module = prefs_register_protocol(proto_reload, NULL); prefs_register_bool_preference(reload_module, "defragment", "Reassemble fragmented reload datagrams", "Whether fragmented ReLOAD datagrams should be reassembled", &reload_defragment); register_init_routine(reload_defragment_init); } void proto_reg_handoff_reload(void) { dissector_handle_t reload_tcp_handle; dissector_handle_t reload_udp_handle; reload_tcp_handle = create_dissector_handle(dissect_reload_tcp, proto_reload); reload_udp_handle = new_create_dissector_handle(dissect_reload_udp, proto_reload); data_handle = find_dissector("data"); heur_dissector_add("udp", dissect_reload_heur, proto_reload); heur_dissector_add("tcp", dissect_reload_heur, proto_reload); }