diff options
author | sahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7> | 2005-03-15 10:18:54 +0000 |
---|---|---|
committer | sahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7> | 2005-03-15 10:18:54 +0000 |
commit | eba0b148746d60ef89bc4b50ba426a8b1944f249 (patch) | |
tree | 696d0e52817779868810198c16d0c00f9871f2d3 /epan | |
parent | 2db5115594eae5d3ead022050286f1af3bd58ee8 (diff) |
jxta updates from duigou
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@13762 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-jxta.c | 1521 |
1 files changed, 1058 insertions, 463 deletions
diff --git a/epan/dissectors/packet-jxta.c b/epan/dissectors/packet-jxta.c index 18356f2972..7cb83943d6 100644 --- a/epan/dissectors/packet-jxta.c +++ b/epan/dissectors/packet-jxta.c @@ -39,6 +39,7 @@ #include <string.h> #include <glib.h> #include <epan/packet.h> +#include <epan/conversation.h> #include <epan/strutil.h> #include <epan/prefs.h> #include "packet-tcp.h" @@ -47,14 +48,19 @@ static const char JXTA_UDP_SIG[] = { 'J', 'X', 'T', 'A' }; static const char JXTA_MSG_SIG[] = { 'j', 'x', 'm', 'g' }; static const char JXTA_MSGELEM_SIG[] = { 'j', 'x', 'e', 'l' }; +static const char JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' }; + static int proto_jxta = -1; +static int proto_message_jxta = -1; + +static dissector_table_t media_type_dissector_table; +static dissector_handle_t tcp_jxta_handle; static int hf_jxta_udp = -1; static int hf_jxta_udpsig = -1; static int hf_jxta_welcome = -1; static int hf_jxta_framing = -1; static int hf_jxta_framing_header = -1; -static int hf_jxta_framing_header_name_length = -1; static int hf_jxta_framing_header_name = -1; static int hf_jxta_framing_header_value_length = -1; static int hf_jxta_framing_header_value = -1; @@ -62,7 +68,6 @@ static int hf_jxta_message = -1; static int hf_jxta_message_sig = -1; static int hf_jxta_message_version = -1; static int hf_jxta_message_namespaces_count = -1; -static int hf_jxta_message_namespace_len = -1; static int hf_jxta_message_namespace_name = -1; static int hf_jxta_message_element_count = -1; static int hf_jxta_element = -1; @@ -72,15 +77,128 @@ static int hf_jxta_element_flags = -1; static int hf_jxta_element_flag_hasType = -1; static int hf_jxta_element_flag_hasEncoding = -1; static int hf_jxta_element_flag_hasSignature = -1; -static int hf_jxta_element_name_len = -1; static int hf_jxta_element_name = -1; -static int hf_jxta_element_type_len = -1; static int hf_jxta_element_type = -1; -static int hf_jxta_element_encoding_len = -1; static int hf_jxta_element_encoding = -1; static int hf_jxta_element_content_len = -1; static int hf_jxta_element_content = -1; +static int hf_jxta_element_content_text = -1; +/** our header fields */ +static hf_register_info hf[] = { + {&hf_jxta_udp, + {"JXTA UDP Message", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0, + "JXTA UDP Message", HFILL} + }, + {&hf_jxta_udpsig, + {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0, + "JXTA UDP Signature", HFILL} + }, + {&hf_jxta_welcome, + {"Welcome Message", "jxta.welcome", FT_STRING, BASE_NONE, NULL, 0x0, + "JXTA Connection Welcome Message", HFILL} + }, + {&hf_jxta_framing, + {"JXTA Message Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0, + "JXTA Message Framing Headers", HFILL} + }, + {&hf_jxta_framing_header, + {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0, + "JXTA Message Framing Header", HFILL} + }, + {&hf_jxta_framing_header_name, + {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0, + "JXTA Message Framing Header Name", HFILL} + }, + {&hf_jxta_framing_header_value_length, + {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0, + "JXTA Message Framing Header Value Length", HFILL} + }, + {&hf_jxta_framing_header_value, + {"Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0, + "JXTA Message Framing Header Value", HFILL} + }, + {&hf_jxta_message, + {"JXTA Message", "jxta.message", FT_NONE, BASE_NONE, NULL, 0x0, + "JXTA Message", HFILL} + }, + {&hf_jxta_message_sig, + {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0, + "JXTA Message Signature", HFILL} + }, + {&hf_jxta_message_version, + {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0, + "JXTA Message Version", HFILL} + }, + {&hf_jxta_message_namespaces_count, + {"Namespace Count", "jxta.message.namespaces", FT_UINT16, BASE_DEC, NULL, 0x0, + "JXTA Message Namespaces", HFILL} + }, + {&hf_jxta_message_namespace_name, + {"Namespace Name", "jxta.message.namespace.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0, + "JXTA Message Namespace Name", HFILL} + }, + {&hf_jxta_message_element_count, + {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0, + "JXTA Message Element Count", HFILL} + }, + {&hf_jxta_element, + {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0, + "JXTA Message Element", HFILL} + }, + {&hf_jxta_element_sig, + {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0, + "JXTA Message Element Signature", HFILL} + }, + {&hf_jxta_element_namespaceid, + {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0, + "JXTA Message Element Namespace ID", HFILL} + }, + {&hf_jxta_element_flags, + {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0, + "JXTA Message Element Flags", HFILL} + }, + {&hf_jxta_element_flag_hasType, + {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x01, + "JXTA Message Element Flag -- hasType", HFILL} + }, + {&hf_jxta_element_flag_hasEncoding, + {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x02, + "JXTA Message Element Flag -- hasEncoding", HFILL} + }, + {&hf_jxta_element_flag_hasSignature, + {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x04, + "JXTA Message Element Flag -- hasSignature", HFILL} + }, + {&hf_jxta_element_name, + {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0, + "JXTA Message Element Name", HFILL} + }, + {&hf_jxta_element_type, + {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0, + "JXTA Message Element Name", HFILL} + }, + {&hf_jxta_element_encoding, + {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0, + "JXTA Message Element Encoding", HFILL} + }, + {&hf_jxta_element_content_text, + {"Element Content", "jxta.message.element.text_content", FT_UINT_STRING, BASE_HEX, NULL, 0x0, + "JXTA Message Element Text Content", HFILL} + }, + {&hf_jxta_element_content_len, + {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0, + "JXTA Message Element Content Length", HFILL} + }, + {&hf_jxta_element_content, + {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0, + "JXTA Message Element Content", HFILL} + }, +}; + +/** +* JXTA Protocol subtree handles +**/ static gint ett_jxta_welcome = -1; static gint ett_jxta_udp = -1; static gint ett_jxta_framing = -1; @@ -89,528 +207,1005 @@ static gint ett_jxta_msg = -1; static gint ett_jxta_elem = -1; static gint ett_jxta_elem_flags = -1; -static dissector_handle_t udpm_jxta_handle; -static dissector_handle_t tcp_jxta_handle; -static dissector_handle_t http_jxta_handle; - -static const true_false_string boolstringname = { - "True", - "False" - }; - -/** our header fields */ -static hf_register_info hf[] = { - { &hf_jxta_udp, - { "JXTA UDP Message", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0, - "JXTA UDP Message", HFILL } - }, - { &hf_jxta_udpsig, - { "Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0, - "JXTA UDP Signature", HFILL } - }, - { &hf_jxta_welcome, - { "Welcome Message", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x0, - "JXTA Connection Welcome Message", HFILL } - }, - { &hf_jxta_framing, - { "JXTA Message Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0, - "JXTA Message Framing Headers", HFILL } - }, - { &hf_jxta_framing_header, - { "Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0, - "JXTA Message Framing Header", HFILL } - }, - { &hf_jxta_framing_header_name_length, - { "Name Length", "jxta.framing.header.namelen", FT_UINT8, BASE_DEC, NULL, 0x0, - "JXTA Message Framing Header Name Length", HFILL } - }, - { &hf_jxta_framing_header_name, - { "Name", "jxta.framing.header.name", FT_STRING, BASE_NONE, NULL, 0x0, - "JXTA Message Framing Header Name", HFILL } - }, - { &hf_jxta_framing_header_value_length, - { "Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0, - "JXTA Message Framing Header Value Length", HFILL } - }, - { &hf_jxta_framing_header_value, - { "Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0, - "JXTA Message Framing Header Value", HFILL } - }, - { &hf_jxta_message, - { "JXTA Message", "jxta.message", FT_NONE, BASE_NONE, NULL, 0x0, - "JXTA Message", HFILL } - }, - { &hf_jxta_message_sig, - { "Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0, - "JXTA Message Signature", HFILL } - }, - { &hf_jxta_message_version, - { "Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0, - "JXTA Message Version", HFILL } - }, - { &hf_jxta_message_namespaces_count, - { "Namespace Count", "jxta.message.namespaces", FT_UINT16, BASE_DEC, NULL, 0x0, - "JXTA Message Namespaces", HFILL } - }, - { &hf_jxta_message_namespace_len, - { "Namespace Name Length", "jxta.message.namespace.len", FT_UINT16, BASE_DEC, NULL, 0x0, - "JXTA Message Namespace Name Length", HFILL } - }, - { &hf_jxta_message_namespace_name, - { "Namespace Name", "jxta.message.namespace.name", FT_STRING, BASE_NONE, NULL, 0x0, - "JXTA Message Namespace Name", HFILL } - }, - { &hf_jxta_message_element_count, - { "Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0, - "JXTA Message Element Count", HFILL } - }, - { &hf_jxta_element, - { "JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0, - "JXTA Message Element", HFILL } - }, - { &hf_jxta_element_sig, - { "Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0, - "JXTA Message Element Signature", HFILL } - }, - { &hf_jxta_element_namespaceid, - { "Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0, - "JXTA Message Element Namespace ID", HFILL } - }, - - /* TODO 20050104 bondolo This should be a bitfield */ - - { &hf_jxta_element_flags, - { "Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0, - "JXTA Message Element Flags", HFILL } - }, - { &hf_jxta_element_flag_hasType, - { "hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&boolstringname), 0x01, - "JXTA Message Element Flag -- hasType", HFILL } - }, - { &hf_jxta_element_flag_hasEncoding, - { "hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&boolstringname), 0x02, - "JXTA Message Element Flag -- hasEncoding", HFILL } - }, - { &hf_jxta_element_flag_hasSignature, - { "hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&boolstringname), 0x04, - "JXTA Message Element Flag -- hasSignature", HFILL } - }, - { &hf_jxta_element_name_len, - { "Element Name Length", "jxta.message.element.name.length", FT_UINT16, BASE_DEC, NULL, 0x0, - "JXTA Message Element Name Length", HFILL } - }, - { &hf_jxta_element_name, - { "Element Name", "jxta.message.element.name", FT_STRING, BASE_NONE, NULL, 0x0, - "JXTA Message Element Name", HFILL } - }, - { &hf_jxta_element_type_len, - { "Element Type Length", "jxta.message.element.type.length", FT_UINT16, BASE_DEC, NULL, 0x0, - "JXTA Message Element Name Length", HFILL } - }, - { &hf_jxta_element_type, - { "Element Type", "jxta.message.element.type", FT_STRING, BASE_NONE, NULL, 0x0, - "JXTA Message Element Name", HFILL } - }, - { &hf_jxta_element_encoding_len, - { "Element Type Length", "jxta.message.element.encoding.length", FT_UINT16, BASE_DEC, NULL, 0x0, - "JXTA Message Element Encoding Length", HFILL } - }, - { &hf_jxta_element_encoding, - { "Element Type", "jxta.message.element.encoding", FT_STRING, BASE_NONE, NULL, 0x0, - "JXTA Message Element Encoding", HFILL } - }, - { &hf_jxta_element_content_len, - { "Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0, - "JXTA Message Element Content Length", HFILL } - }, - { &hf_jxta_element_content, - { "Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0, - "JXTA Message Element Content", HFILL } - }, -}; - -/** setup protocol subtree array */ -static gint * const ett[] = { - &ett_jxta_welcome, - &ett_jxta_udp, - &ett_jxta_framing, - &ett_jxta_framing_header, - &ett_jxta_msg, - &ett_jxta_elem, - &ett_jxta_elem_flags +/** +* JXTA Protocol subtree array +**/ +static gint *const ett[] = { + &ett_jxta_welcome, + &ett_jxta_udp, + &ett_jxta_framing, + &ett_jxta_framing_header, + &ett_jxta_msg, + &ett_jxta_elem, + &ett_jxta_elem_flags }; -static int gUDP_MULTICAST_PORT_JXTA = 1234; -static int gHTTP_PORT_JXTA = 9700; -static int gTCP_PORT_JXTA = 9701; - -static int regUDP_MULTICAST_PORT_JXTA = -1; -static int regHTTP_PORT_JXTA = -1; -static int regTCP_PORT_JXTA = -1; +/** +* global preferences +**/ +static gboolean gDESEGMENT = TRUE; +static gboolean gUDP_HEUR = FALSE; +static gboolean gTCP_HEUR = FALSE; +/** +* Prototypes +**/ +static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); +static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); -static void dissect_jxta_framing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); +static int dissect_jxta_tcp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); -static void dissect_jxta_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); +static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length, + const char **content_type); +static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree); +static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, int ns_count, + const char **namespaces); void proto_reg_handoff_jxta(void); +void proto_reg_handoff_message_jxta(void); /** - Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message +* Heuristically dissect a tvbuff containing a JXTA UDP Message +* +* @param tvb The buffer to dissect. +* @param pinfo Packet Info. +* @param tree The protocol tree. +* @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE **/ -static void dissect_jxta_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - proto_tree *jxta_udp_tree = NULL; - proto_item *jxta_udp_tree_item; - proto_item *signature_item = NULL; +static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + /* This is a heuristic dissector, which means we get all the UDP + * traffic not sent to a known dissector and not claimed by + * a heuristic dissector called before us! + */ - if (check_col(pinfo->cinfo, COL_PROTOCOL)) { - col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA"); - } + if (!gUDP_HEUR) + return FALSE; - if (check_col(pinfo->cinfo, COL_INFO)) { - /* - * bondolo For now just say its a message. eventually put in dest addr. - * XXX - if "dest addr" means the IP destination address, that's - * already going to be in the "destination address" column if you're - * displaying that. - */ - col_add_fstr(pinfo->cinfo, COL_INFO, "%s", "UDP Message"); - } - - if (tree) { - jxta_udp_tree_item = proto_tree_add_item(tree, hf_jxta_udp, tvb, 0, -1, FALSE); - jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp); - - signature_item = proto_tree_add_item( jxta_udp_tree, hf_jxta_udpsig, tvb, 0, sizeof(JXTA_UDP_SIG), FALSE ); - } - - if( tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) == 0 ) { - tvbuff_t* jxta_framed_message_tvb = tvb_new_subset( tvb, sizeof(JXTA_UDP_SIG), -1, -1 ); - - dissect_jxta_framing( jxta_framed_message_tvb, pinfo, jxta_udp_tree ); - } else { - if( tree ) { - proto_item_append_text(signature_item, " * BAD *" ); + if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) { + return FALSE; } - } -} -static void dissect_jxta_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - dissect_jxta_message( tvb, pinfo, tree ); + return dissect_jxta_udp(tvb, pinfo, tree) > 0; } -static void dissect_jxta_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - /* XXX this is broken. - you MUST provide a header dissector and not NULL - the header dissector MUST do heuristict to verify it really is a - proper jxta header. - you SHOULD also specify desegmentation as a variable and not always TRUE - tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 0, NULL, dissect_jxta_tcp_pdu); - */ - dissect_jxta_tcp_pdu(tvb, pinfo, tree); +/** +* Heuristically dissect a tvbuff containing a JXTA TCP Stream +* +* @param tvb The buffer to dissect. +* @param pinfo Packet Info. +* @param tree The protocol tree. +* @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE +**/ +static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + /* This is a heuristic dissector, which means we get all the TCP + * traffic not sent to a known dissector and not claimed by + * a heuristic dissector called before us! + */ + + if (!gTCP_HEUR) + return FALSE; + + if (tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG)) != 0) { + return FALSE; + } + + return dissect_jxta_tcp(tvb, pinfo, tree) > 0; } /** - Dissect a tvbuff containing a JXTA Message framing and a JXTA Message +* Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message +* +* @param tvb The buffer to dissect. +* @param pinfo Packet Info. +* @param tree The protocol tree. +* @return number of bytes from the tvbuff_t which were processed. **/ -static void dissect_jxta_framing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - proto_item *framing_tree_item = NULL; - proto_tree *framing_tree = NULL; - guint offset = 0; - tvbuff_t* jxta_message_tvb; - - if (tree) { - framing_tree_item = proto_tree_add_item(tree, hf_jxta_framing, tvb, 0, -1, FALSE); - framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing); +static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + int offset = 0; + int available; + int needed = 0; + + conversation_t *conversation = + find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); + + if (conversation == NULL) { + /* + * No conversation exists yet - create one. + */ + conversation = + conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } - - /* parse framing headers */ - do { - guint8 headernamelen = tvb_get_guint8( tvb, offset ); - proto_item *framing_header_tree_item = NULL; - proto_tree *framing_header_tree = NULL; - - if(tree) { - framing_header_tree_item = proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, 0, -1, FALSE); - framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header); - - proto_tree_add_item( framing_header_tree, hf_jxta_framing_header_name_length, tvb, offset, 1, headernamelen ); + + g_assert(find_dissector("jxta.udp")); + + conversation_set_dissector(conversation, find_dissector("jxta.udp")); + + while (TRUE) { + tvbuff_t *jxta_message_framing_tvb; + int processed = 0; + guint64 content_length = -1; + + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(JXTA_UDP_SIG)) { + needed = available - sizeof(JXTA_UDP_SIG); + break; + } + + if (tvb_memeql(tvb, offset, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) { + /* not ours */ + return 0; + } + + offset += sizeof(JXTA_UDP_SIG); + + jxta_message_framing_tvb = tvb_new_subset(tvb, offset, -1, -1); + processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, NULL); + + if (0 == processed) { + /* rejected! */ + return 0; + } + + if (processed < 0) { + needed = -processed; + break; + } + + offset += processed; + + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)content_length) { + needed = available - content_length; + break; + } + + offset += content_length; + + break; + } + + if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { + pinfo->desegment_offset = 0; + pinfo->desegment_len = needed; + return -needed; + } + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) { + col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA"); + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_set_str(pinfo->cinfo, COL_INFO, "UDP Message"); } - - if( tree && (headernamelen != 0) ) { - /* - * Put header name into protocol tree. - */ - guint8* headername = tvb_memdup( tvb, offset + 1, headernamelen ); - - proto_item_append_text(framing_header_tree_item, " \"%*.*s\"", headernamelen, headernamelen, headername ); - - proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, offset+1, headernamelen, FALSE); - - free(headername); + + col_set_writable(pinfo->cinfo, FALSE); + + if (tree) { + int tree_offset = 0; + proto_item *jxta_udp_tree_item = proto_tree_add_item(tree, hf_jxta_udp, tvb, tree_offset, -1, FALSE); + proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp); + tvbuff_t *jxta_message_framing_tvb; + guint64 content_length = -1; + const char *content_type = NULL; + tvbuff_t *jxta_message_tvb; + gboolean dissected = FALSE; + int processed = 0; + + + proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, sizeof(JXTA_UDP_SIG), FALSE); + tree_offset += sizeof(JXTA_UDP_SIG); + + jxta_message_framing_tvb = tvb_new_subset(tvb, tree_offset, -1, -1); + processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, jxta_udp_tree, &content_length, &content_type); + tree_offset += processed; + + jxta_message_tvb = tvb_new_subset(tvb, tree_offset, content_length, content_length); + dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, jxta_udp_tree); + g_free((char *)content_type); + + if (!dissected) { + dissector_handle_t data_handle = find_dissector("data"); + call_dissector(data_handle, jxta_message_tvb, pinfo, jxta_udp_tree); + } + + tree_offset += content_length; + + proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset); + + g_assert(offset == tree_offset); } - - offset += 1 + headernamelen; - - if( headernamelen > 0 ) { - guint16 headervaluelen = tvb_get_ntohs( tvb, offset ); - if( tree ) { - proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, offset, 2, headervaluelen ); + return offset; +} - /** TODO bondolo Add specific handling for known header types */ +/** +* Dissect a tvbuff containing JXTA TCP PDUs +* +* @param tvb The buffer to dissect. +* @param pinfo Packet Info. +* @param tree The protocol tree. +* @return number of bytes from the tvbuff_t which were processed. +**/ +static int dissect_jxta_tcp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + int offset = 0; + int available = 0; + int processed; + gboolean first = TRUE; + conversation_t *conversation = + find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); + if (conversation == NULL) { /* - * Put header value into protocol tree. + * No conversation exists yet - create one. */ - proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, offset+2, headervaluelen, FALSE ); - } - - offset += 2 + headervaluelen; + conversation = + conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } - - if( tree ) { - proto_item_set_end( framing_header_tree_item, tvb, offset ); + + conversation_set_dissector(conversation, tcp_jxta_handle); + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + if (first) { + if (check_col(pinfo->cinfo, COL_PROTOCOL)) { + col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA"); + } + } + + if (0 == tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) { + processed = dissect_jxta_welcome(tvb, pinfo, tree); + } else { + guint64 content_length = -1; + const char *content_type = NULL; + gboolean dissected; + + processed = dissect_jxta_message_framing(tvb, pinfo, tree, &content_length, &content_type); + + if (processed > 0) { + int msg_offset = offset + processed; + + available = tvb_reported_length_remaining(tvb, msg_offset); + if (available >= (int)content_length) { + tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, msg_offset, content_length, content_length); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_set_str(pinfo->cinfo, COL_INFO, "Message"); + } + + col_set_writable(pinfo->cinfo, FALSE); + + dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree); + + if (!dissected) { + dissector_handle_t data_handle = find_dissector("data"); + call_dissector(data_handle, jxta_message_tvb, pinfo, tree); + } + + processed += content_length; + } else { + processed = available - content_length; + } + + g_free((char *)content_type); + } + } + + if (processed <= 0) { + pinfo->desegment_offset = offset; + pinfo->desegment_len = -processed; + return processed; + } + + offset += processed; + + first = FALSE; + } + + return offset; +} + +/** +* Dissect a tvbuff containing a JXTA Welcome Message +* +* @param tvb The buffer to dissect. +* @param pinfo Packet Info. +* @param tree The protocol tree. +* @return number of bytes from the tvbuff_t which were processed. +**/ +static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + guint offset = 0; + int afterwelcome; + int first_linelen; + int available = tvb_reported_length_remaining(tvb, offset); + + if (available < (int)sizeof(JXTA_WELCOME_MSG_SIG)) { + return available - sizeof(JXTA_WELCOME_MSG_SIG); + } + + if (0 != tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) { + /* not ours! */ + return 0; + } + + first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment); + + if (-1 == first_linelen) { + if (available > 4096) { + /* it's too far too be reasonable */ + return 0; + } else { + /* ask for more bytes */ + return -1; + } } - if( 0 == headernamelen ) { - break; + if (check_col(pinfo->cinfo, COL_INFO)) { + col_set_str(pinfo->cinfo, COL_INFO, "Welcome Message"); } - } while( TRUE ); - - if( tree ) { - proto_item_set_end( framing_tree_item, tvb, offset ); - } - jxta_message_tvb = tvb_new_subset( tvb, offset, -1, -1 ); + if (tree) { + /* FIXME bondolo dissect the welcome line */ + proto_tree_add_item(tree, hf_jxta_welcome, tvb, offset, afterwelcome, FALSE); + } - /* Call it a new layer and pass the tree as we got it */ - dissect_jxta_message( jxta_message_tvb, pinfo, tree ); + return afterwelcome; } /** - Dissect a tvbuff containing a JXTA Message +* Dissect a tvbuff containing JXTA Message framing. +* +* @param tvb The buffer to dissect. +* @param pinfo Packet Info. +* @param tree The protocol tree. +* @return number of bytes from the tvbuff_t which were processed. **/ -static void dissect_jxta_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - proto_tree *jxta_tree = NULL; - proto_item *ti; - unsigned int offset = 0; +static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length, + const char **content_type) +{ + int offset = 0; + int available; + int needed = 0; + + /* + * First go around. Make sure all of the bytes are there. + */ + do { + guint8 headername_len; + guint8 headername_offset; + guint16 headervalue_len; + guint16 headervalue_offset; + + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint8)) { + needed = available - sizeof(guint8); + break; + } else { + headername_len = tvb_get_guint8(tvb, offset); + offset += sizeof(guint8); + headername_offset = offset; + + available = tvb_reported_length_remaining(tvb, offset); + if (available < headername_len) { + needed = available - headername_len; + break; + } + + if (0 == headername_len) { + break; + } + offset += headername_len; + } + + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint16)) { + needed = available - sizeof(guint16); + break; + } else { + headervalue_len = tvb_get_ntohs(tvb, offset); + offset += sizeof(guint16); + headervalue_offset = offset; + + available = tvb_reported_length_remaining(tvb, offset); + if (available < headervalue_len) { + needed = available - headervalue_len; + break; + } + + offset += headervalue_len; + } - if (check_col(pinfo->cinfo, COL_PROTOCOL)) { - col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA"); - } + if (content_type && (sizeof("content-type") - 1) == headername_len) { + if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) { + *content_type = tvb_get_string(tvb, headervalue_offset, headervalue_len); + } + } + + + if (content_length && (sizeof(guint64) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) { + if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) { + *content_length = tvb_get_ntoh64(tvb, headervalue_offset); + } + } + } while (TRUE); + + if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { + return -needed; + } - if (check_col(pinfo->cinfo, COL_INFO)) { /* - * TODO bondolo For now just say its a message. eventually put in dest addr. - * XXX - if "dest addr" means the IP destination address, that's - * already going to be in the "destination address" column if you're - * displaying that. + * Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree. */ - col_add_fstr(pinfo->cinfo, COL_INFO, "%s", "Message"); - } - - if (tree) { - ti = proto_tree_add_item(tree, hf_jxta_message, tvb, 0, -1, FALSE); - jxta_tree = proto_item_add_subtree(ti, ett_jxta_msg); - } - - if( tree ) { - proto_tree_add_item( jxta_tree, hf_jxta_message_sig, tvb, 0, sizeof(JXTA_MSG_SIG), FALSE); - - if( tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) == 0) { - guint8 messageVersion; - + if (tree) { + int tree_offset = 0; + proto_item *framing_tree_item = proto_tree_add_item(tree, hf_jxta_framing, tvb, tree_offset, -1, FALSE); + proto_tree *framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing); + + /* parse framing headers */ + do { + guint8 headernamelen = tvb_get_guint8(tvb, tree_offset); + proto_item *framing_header_tree_item = + proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, FALSE); + proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header); + + /* + * Put header name into the protocol tree + */ + proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, 1, headernamelen); + + /* + * Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers. + */ + if (headernamelen > 0) { + proto_item_append_text(framing_header_tree_item, " \"%s\"", + tvb_format_text(tvb, tree_offset + sizeof(guint8), headernamelen)); + } + + tree_offset += sizeof(guint8) + headernamelen; + + if (headernamelen > 0) { + guint16 headervaluelen = tvb_get_ntohs(tvb, tree_offset); + + if (tree) { + proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset, + sizeof(guint16), headervaluelen); + + /** TODO bondolo Add specific handling for known header types */ + + /* + * Put header value into protocol tree. + */ + proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + sizeof(guint16), + headervaluelen, FALSE); + } + + tree_offset += sizeof(guint16) + headervaluelen; + } + + proto_item_set_end(framing_header_tree_item, tvb, tree_offset); + + if (0 == headernamelen) { + break; + } + } while (TRUE); + + proto_item_set_end(framing_tree_item, tvb, tree_offset); + + g_assert(offset == tree_offset); + } + + /* return how many bytes we used up. */ + return offset; +} + +/** +* Dissect a tvbuff containing a JXTA Message. +* +* @param tvb The buffer to dissect. +* @param pinfo Packet Info. +* @param tree The protocol tree. +* @return number of bytes from the tvbuff_t which were processed. +**/ +static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) +{ + int offset = 0; + int available; + int needed = 0; + + while (TRUE) { + /* First pass. Make sure all of the bytes we need are available */ + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(JXTA_MSG_SIG)) { + needed = available - sizeof(JXTA_MSG_SIG); + break; + } + + if (tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) { + /* It is not one of ours */ + return 0; + } + offset += sizeof(JXTA_MSG_SIG); - messageVersion = tvb_get_guint8( tvb, offset ); - proto_tree_add_uint( jxta_tree, hf_jxta_message_version, tvb, offset, sizeof(guint8), messageVersion ); - offset += sizeof(guint8); - - if( 0 == messageVersion ) { - int eachNamespace; - guint16 numberOfElements; - guint16 messageNamespaceCount = tvb_get_ntohs( tvb, offset ); - char **namespaces = calloc( messageNamespaceCount + 2, sizeof(char *) ); - + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint8)) { + needed = available - sizeof(guint8); + break; + } else { + guint8 message_version = tvb_get_guint8(tvb, offset); + + offset += sizeof(guint8); + + if (0 != message_version) { + /* Sort of a lie, we say that we don't recognize it at all. */ + return 0; + } + } + + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint16)) { + needed = available - sizeof(guint16); + break; + } else { + guint16 msg_ns_count = tvb_get_ntohs(tvb, offset); + int each_namespace; + offset += sizeof(guint16); - namespaces[0] = ""; - namespaces[1] = "jxta"; - - proto_tree_add_uint( jxta_tree, hf_jxta_message_namespaces_count, tvb, offset, sizeof(guint16), messageNamespaceCount ); - - /* parse namespaces */ - /* TODO 20050103 bondolo Should record the namespaces and number them. */ - for( eachNamespace = 0; eachNamespace < messageNamespaceCount; eachNamespace++ ) { - guint8 namespaceLen = tvb_get_guint8( tvb, offset ); - - proto_tree_add_uint(jxta_tree, hf_jxta_message_namespace_len, tvb, offset++, namespaceLen, namespaceLen ); - - proto_tree_add_item(jxta_tree, hf_jxta_message_namespace_name, tvb, offset, namespaceLen, FALSE); - - namespaces[2 + eachNamespace] = calloc( namespaceLen + 1, sizeof(char *) ); - - tvb_memcpy( tvb, namespaces[2 + eachNamespace], offset, namespaceLen ); - - offset += namespaceLen; + + for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) { + guint8 namespace_len; + + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint8)) { + needed = available - sizeof(guint8); + break; + } + + namespace_len = tvb_get_guint8(tvb, offset); + + available = tvb_reported_length_remaining(tvb, offset + 1); + if (available < namespace_len) { + needed = available - namespace_len; + break; + } + + offset += sizeof(guint8) + namespace_len; } - - /* parse elements */ - numberOfElements = tvb_get_ntohs( tvb, offset ); - proto_tree_add_item(jxta_tree, hf_jxta_message_element_count, tvb, offset, sizeof(guint16), FALSE ); + } + + /* parse element count */ + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint16)) { + needed = available - sizeof(guint16); + break; + } else { + guint16 elem_count = tvb_get_ntohs(tvb, offset); + int each_elem; + offset += sizeof(guint16); - - while( offset < tvb_reported_length(tvb) ) { - proto_tree *jxta_elem_tree = NULL; - proto_item *elem_ti; - - elem_ti = proto_tree_add_item(jxta_tree, hf_jxta_element, tvb, offset, -1, FALSE); - jxta_elem_tree = proto_item_add_subtree(elem_ti, ett_jxta_elem); - - /* gross hack for parsing of signature element */ - element_parse : - { - proto_tree_add_item( jxta_elem_tree, hf_jxta_element_sig, tvb, offset, sizeof(JXTA_MSGELEM_SIG), FALSE ); - if( tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) == 0 ) { - guint8 namespaceID; - guint8 flags; - guint16 nameLen; - guint32 elemContentLength; - proto_item *namespace_ti; - proto_item *flags_ti; - proto_tree *jxta_elem_flags_tree = NULL; - - offset += sizeof(JXTA_MSGELEM_SIG); - - namespaceID = tvb_get_guint8( tvb, offset ); - namespace_ti = proto_tree_add_uint( jxta_elem_tree, hf_jxta_element_namespaceid, tvb, offset, sizeof(guint8), namespaceID ); - if( namespaceID <= (messageNamespaceCount + 2) ) { - proto_item_append_text(namespace_ti, " (%s)", namespaces[namespaceID] ); - } else { - proto_item_append_text(namespace_ti, " * BAD *" ); - } - offset += sizeof(guint8); - - flags = tvb_get_guint8( tvb, offset ); - flags_ti = proto_tree_add_uint( jxta_elem_tree, hf_jxta_element_flags, tvb, offset, sizeof(guint8), flags ); - jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_flags); - proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasType, tvb, offset, 1, flags); - proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasEncoding, tvb, offset, 1, flags); - proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasSignature, tvb, offset, 1, flags); - offset += sizeof(guint8); - - nameLen = tvb_get_ntohs( tvb, offset ); - proto_tree_add_uint( jxta_elem_tree, hf_jxta_element_name_len, tvb, offset, sizeof(guint16), nameLen ); - offset += sizeof(guint16); - - proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, offset, nameLen, FALSE); - - offset += nameLen; - - /* process type */ - if( (flags & 0x01) != 0 ) { - guint16 typeLen = tvb_get_ntohs( tvb, offset ); - proto_tree_add_uint( jxta_elem_tree, hf_jxta_element_type_len, tvb, offset, sizeof(guint16), typeLen ); - offset += sizeof(guint16); - - proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, offset, typeLen, FALSE); - - offset += typeLen; - } - - /* process encoding */ - if( (flags & 0x02) != 0 ) { - guint16 encodingLen = tvb_get_ntohs( tvb, offset ); - ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_encoding_len, tvb, offset, sizeof(guint16), FALSE ); - offset += sizeof(guint16); - proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, offset, encodingLen, FALSE); + /* parse elements */ - offset += encodingLen; - } - - /* content */ - elemContentLength = tvb_get_ntohl( tvb, offset ); - ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_content_len, tvb, offset, sizeof(guint32), FALSE ); - offset += sizeof(guint32); - - ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_content, tvb, offset, elemContentLength, FALSE ); - offset += elemContentLength; - - /* XXX Evil Hack Warning : handle parsing of signature element. Would be better with recursion.*/ - if( (flags & 0x04) != 0 ) { - goto element_parse; - } + for (each_elem = 0; each_elem < elem_count; each_elem++) { + tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, offset, -1, -1); + int processed = dissect_jxta_message_element(jxta_message_element_tvb, pinfo, NULL, 0, NULL); + + if (processed <= 0) { + return processed; } - - proto_item_set_end( elem_ti, tvb, offset ); + + offset += processed; + } + } + + break; + } + + if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { + return -needed; + } + + if (tree) { + int tree_offset = 0; + proto_item *jxta_msg_tree_item = proto_tree_add_item(tree, hf_jxta_message, tvb, tree_offset, -1, FALSE); + proto_tree *jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg); + + guint8 message_version; + const char **namespaces = NULL; + guint16 msg_ns_count; + int each_namespace; + guint16 elem_count; + int each_elem; + + proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, sizeof(JXTA_MSG_SIG), FALSE); + tree_offset += sizeof(JXTA_MSG_SIG); + + message_version = tvb_get_guint8(tvb, tree_offset); + proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, sizeof(guint8), message_version); + tree_offset += sizeof(guint8); + + msg_ns_count = tvb_get_ntohs(tvb, tree_offset); + proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_namespaces_count, tvb, tree_offset, sizeof(guint16), msg_ns_count); + tree_offset += sizeof(guint16); + + namespaces = g_malloc((msg_ns_count + 2) * sizeof(const char *)); + namespaces[0] = ""; + namespaces[1] = "jxta"; + + /* parse namespaces */ + for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) { + guint8 namespace_len = tvb_get_guint8(tvb, tree_offset); + + namespaces[2 + each_namespace] = tvb_get_string(tvb, tree_offset + 1, namespace_len); + proto_tree_add_item(jxta_msg_tree, hf_jxta_message_namespace_name, tvb, tree_offset, sizeof(guint8), FALSE); + tree_offset += sizeof(guint8) + namespace_len; + } + + /* parse element count */ + elem_count = tvb_get_ntohs(tvb, tree_offset); + proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, sizeof(guint16), FALSE); + tree_offset += sizeof(guint16); + + /* parse elements */ + for (each_elem = 0; each_elem < elem_count; each_elem++) { + tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1); + + tree_offset += + dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_ns_count + 2, namespaces); + } + + for (each_namespace = 2; each_namespace < msg_ns_count; each_namespace++) { + g_free((char *)namespaces[each_namespace]); + } + + g_free(namespaces); + + proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset); + + g_assert(tree_offset == offset); + } + + return offset; +} + +/** +* Dissect a tvbuff containing a JXTA Message Element. +* +* @param tvb The buffer to dissect. +* @param pinfo Packet Info. +* @param tree The protocol tree. +* @return number of bytes from the tvbuff_t which were processed. +**/ +static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, int ns_count, + const char **namespaces) +{ + int offset = 0; + int available; + int needed = 0; + guint8 flags; + + /* First pass. Make sure all of the bytes we need are available */ + + /* signature field */ + while (TRUE) { + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(JXTA_MSGELEM_SIG)) { + needed = available - sizeof(JXTA_MSGELEM_SIG); + } + + if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) { + /* It is not one of ours */ + return 0; + } + + offset += sizeof(JXTA_MSGELEM_SIG); + + /* namespace id field */ + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint8)) { + needed = available - sizeof(guint8); + break; + } + + offset += sizeof(guint8); + + /* flags field */ + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint8)) { + needed = available - sizeof(guint8); + break; + } else { + flags = tvb_get_guint8(tvb, offset); + offset += sizeof(guint8); + } + + /* name field */ + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint16)) { + needed = available - sizeof(guint16); + break; + } else { + guint16 name_len = tvb_get_ntohs(tvb, offset); + offset += sizeof(guint16); + + available = tvb_reported_length_remaining(tvb, offset); + if (available < name_len) { + needed = available - name_len; + break; + } + + offset += name_len; + } + + /* type field */ + if ((flags & 0x01) != 0) { + guint16 type_len; + + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint16)) { + needed = available - sizeof(guint16); + break; + } + + type_len = tvb_get_ntohs(tvb, offset); + offset += sizeof(guint16); + + available = tvb_reported_length_remaining(tvb, offset); + if (available < type_len) { + needed = available - type_len; + break; + } + + offset += type_len; + } + + /* encoding field */ + if ((flags & 0x02) != 0) { + guint16 encoding_len; + + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint16)) { + needed = available - sizeof(guint16); + break; + } + + encoding_len = tvb_get_ntohs(tvb, offset); + offset += sizeof(guint16); + + available = tvb_reported_length_remaining(tvb, offset); + if (available < encoding_len) { + needed = available - encoding_len; + break; + } + + offset += encoding_len; + } + + /* content field */ + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)sizeof(guint16)) { + needed = available - sizeof(guint16); + break; + } else { + guint32 content_len = tvb_get_ntohl(tvb, offset); + offset += sizeof(guint32); + + available = tvb_reported_length_remaining(tvb, offset); + if (available < (int)content_len) { + needed = available - content_len; + break; + } + + offset += content_len; + } + + /* signature element field */ + if ((flags & 0x04) != 0) { + tvbuff_t *jxta_signature_element_tvb; + int processed; + + jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1); + + processed = dissect_jxta_message_element(jxta_signature_element_tvb, pinfo, NULL, 0, NULL); + + if (processed == 0) { + return offset; + } + + if (processed < 0) { + needed = -processed; + break; + } + + offset += processed; + } + + break; + } + + if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) { + return -needed; + } + + /* Second (optional) pass : build the proto tree */ + if (tree) { + int tree_offset = 0; + proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE); + proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem); + guint8 namespaceID; + proto_item *namespace_ti; + guint16 name_len; + proto_item *flags_ti; + proto_tree *jxta_elem_flags_tree = NULL; + guint32 content_len; + gchar *mediatype = NULL; + gboolean media_type_recognized = FALSE; + tvbuff_t *element_content_tvb; + + proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE); + tree_offset += sizeof(JXTA_MSGELEM_SIG); + + namespaceID = tvb_get_guint8(tvb, tree_offset); + namespace_ti = + proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_namespaceid, tvb, tree_offset, sizeof(guint8), namespaceID); + if (namespaceID < ns_count) { + proto_item_append_text(namespace_ti, " (%s)", namespaces[namespaceID]); + } else { + proto_item_append_text(namespace_ti, " * BAD *"); + } + tree_offset += sizeof(guint8); + + flags = tvb_get_guint8(tvb, tree_offset); + flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags); + jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_flags); + proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasType, tvb, tree_offset, 1, flags); + proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasEncoding, tvb, tree_offset, 1, flags); + proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasSignature, tvb, tree_offset, 1, flags); + tree_offset += sizeof(guint8); + + name_len = tvb_get_ntohs(tvb, tree_offset); + proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len)); + proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE); + tree_offset += sizeof(guint16) + name_len; + + /* process type */ + if ((flags & 0x01) != 0) { + guint16 type_len = tvb_get_ntohs(tvb, tree_offset); + proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, sizeof(guint16), FALSE); + tree_offset += sizeof(guint16); + + mediatype = tvb_get_string(tvb, tree_offset, type_len); + + /* remove any params */ + { + gchar *parms_at = strchr(mediatype, ';'); + + if (NULL != parms_at) { + *parms_at = '\0'; } } - - for( eachNamespace = 2; eachNamespace < messageNamespaceCount; eachNamespace++ ) { - free( namespaces[eachNamespace] ); + + /* force to lower case */ +#if GLIB_MAJOR_VERSION < 2 + g_strdown(mediatype); +#else + { + gchar *mediatype_lowercase = g_ascii_strdown(mediatype, -1); + g_free(mediatype); + mediatype = mediatype_lowercase; + } +#endif + tree_offset += type_len; + } + + /* process encoding */ + if ((flags & 0x02) != 0) { + guint16 encoding_len = tvb_get_ntohs(tvb, tree_offset); + proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, sizeof(guint16), FALSE); + tree_offset += sizeof(guint16) + encoding_len; + } + + /* content */ + content_len = tvb_get_ntohl(tvb, tree_offset); + proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE); + tree_offset += sizeof(guint32); + + element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len); + + if (NULL != mediatype) { + media_type_recognized = dissector_try_string(media_type_dissector_table, + mediatype, element_content_tvb, pinfo, jxta_elem_tree); + g_free(mediatype); + } + + if (!media_type_recognized) { + dissector_handle_t data_handle = find_dissector("data"); + call_dissector(data_handle, element_content_tvb, pinfo, jxta_elem_tree); + } + tree_offset += content_len; + + if ((flags & 0x04) != 0) { + tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1); + + tree_offset += dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, namespaces); } - } - } - } + + proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset); + + g_assert(tree_offset == offset); + } + + return offset; } +/** +* Register jxta protocol and jxta message protocol, header fields, subtree types, preferences. +**/ void proto_register_jxta(void) { - module_t *jxta_module; - - proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta"); - - /* Register header fields */ - proto_register_field_array(proto_jxta, hf, array_length(hf)); - - /* Register JXTA Sub-tree */ - proto_register_subtree_array(ett, array_length(ett)); - - /* Register preferences */ - jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta); - - prefs_register_uint_preference(jxta_module, "tcp.port", "JXTA TCP Port", - "Set the port for JXTA TCP messages", - 10, &gTCP_PORT_JXTA); - - prefs_register_uint_preference(jxta_module, "http.port", "JXTA HTTP Port", - "Set the port for JXTA HTTP messages", - 10, &gHTTP_PORT_JXTA); - - prefs_register_uint_preference(jxta_module, "udp.port", "JXTA UDP Multicast Port", - "Set the port for JXTA UDP Multicast messages", - 10, &gUDP_MULTICAST_PORT_JXTA); + module_t *jxta_module; + + proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta"); + + proto_message_jxta = proto_register_protocol("Media Type: application/x-jxta-msg", + "application/x-jxta-msg", "application-x-jxta-msg"); + + /* Register header fields */ + proto_register_field_array(proto_jxta, hf, array_length(hf)); + + /* Register JXTA Sub-tree */ + proto_register_subtree_array(ett, array_length(ett)); + + /* Register preferences */ + jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta); + + prefs_register_bool_preference(jxta_module, "desegment", + "Reassemble JXTA messages spanning multiple UDP/TCP/HTTP segments", + "Whether the JXTA dissector should reassemble messages spanning multiple UDP/TCP segments." + " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings " + " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.", + &gDESEGMENT); + + prefs_register_bool_preference(jxta_module, "udp.heuristic", "Try to discover JXTA in UDP datagrams", + "Enable to inspect UDP datagrams for JXTA messages.", &gUDP_HEUR); + + prefs_register_bool_preference(jxta_module, "tcp.heuristic", "Try to discover JXTA in TCP connections", + "Enable to inspect TCP connections for JXTA conversations.", &gTCP_HEUR); } -void proto_reg_handoff_jxta(void) { - static gboolean jxta_prefs_initialized = FALSE; +void proto_reg_handoff_jxta(void) +{ + static gboolean init_done = FALSE; + + if (!init_done) { + new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta); + heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_jxta); - if (!jxta_prefs_initialized) { - udpm_jxta_handle = create_dissector_handle(dissect_jxta_udp, proto_jxta); - tcp_jxta_handle = create_dissector_handle(dissect_jxta_tcp, proto_jxta); - http_jxta_handle = create_dissector_handle(dissect_jxta_message, proto_jxta); + new_register_dissector("jxta.tcp", dissect_jxta_tcp, proto_jxta); + tcp_jxta_handle = find_dissector("jxta.tcp"); + heur_dissector_add("tcp", dissect_jxta_TCP_heur, proto_jxta); - jxta_prefs_initialized = TRUE; - } else { - dissector_delete("udp.port", regUDP_MULTICAST_PORT_JXTA, udpm_jxta_handle); + init_done = TRUE; + } +} - dissector_delete("tcp.port", regTCP_PORT_JXTA, tcp_jxta_handle); +void proto_reg_handoff_message_jxta(void) +{ + static gboolean init_done = FALSE; + static dissector_handle_t message_jxta_handle; - dissector_delete("http.port", regHTTP_PORT_JXTA, http_jxta_handle); - } + if (!init_done) { + message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta); - /* remember what ports we registered on for later removal */ - regUDP_MULTICAST_PORT_JXTA = gUDP_MULTICAST_PORT_JXTA; - regTCP_PORT_JXTA = gTCP_PORT_JXTA; - regHTTP_PORT_JXTA = gHTTP_PORT_JXTA; - - /* register as a sub-dissector of UDP tagged on port field */ - dissector_add("udp.port", regUDP_MULTICAST_PORT_JXTA, udpm_jxta_handle); + media_type_dissector_table = find_dissector_table("media_type"); - /* register as a sub-dissector of TCP tagged on port field*/ - dissector_add("tcp.port", regTCP_PORT_JXTA, tcp_jxta_handle); + dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle); - /* register as a sub-dissector of HTTP tagged on port field */ - dissector_add("http.port", regHTTP_PORT_JXTA, http_jxta_handle); + init_done = TRUE; + } } |