2005-01-07 12:58:43 +00:00
|
|
|
/* packet-jxta.c
|
|
|
|
* Routines for JXTA packet dissection
|
|
|
|
* Copyright 2004, Mike Duigou <bondolo@jxta.org>
|
|
|
|
* Heavily based on packet-jabber.c, which in turn is heavily based on
|
|
|
|
* on packet-acap.c, which in turn is heavily based on
|
|
|
|
* packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
|
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
* Copied from packet-pop.c, packet-jabber.c, packet-udp.c
|
|
|
|
*
|
|
|
|
* JXTA specification from http://spec.jxta.org
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include <epan/packet.h>
|
2005-03-15 10:18:54 +00:00
|
|
|
#include <epan/conversation.h>
|
2005-01-07 12:58:43 +00:00
|
|
|
#include <epan/strutil.h>
|
|
|
|
#include <epan/prefs.h>
|
|
|
|
#include "packet-tcp.h"
|
|
|
|
|
2005-03-05 21:00:41 +00:00
|
|
|
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' };
|
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
static const char JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' };
|
|
|
|
|
2005-01-07 12:58:43 +00:00
|
|
|
static int proto_jxta = -1;
|
2005-03-15 10:18:54 +00:00
|
|
|
static int proto_message_jxta = -1;
|
|
|
|
|
2005-03-25 22:37:58 +00:00
|
|
|
static dissector_table_t media_type_dissector_table=NULL;
|
|
|
|
static dissector_handle_t tcp_jxta_handle=NULL;
|
2005-01-07 12:58:43 +00:00
|
|
|
|
|
|
|
static int hf_jxta_udp = -1;
|
|
|
|
static int hf_jxta_udpsig = -1;
|
|
|
|
static int hf_jxta_welcome = -1;
|
|
|
|
static int hf_jxta_framing = -1;
|
2005-03-05 21:00:41 +00:00
|
|
|
static int hf_jxta_framing_header = -1;
|
2005-01-07 12:58:43 +00:00
|
|
|
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;
|
|
|
|
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_name = -1;
|
|
|
|
static int hf_jxta_message_element_count = -1;
|
|
|
|
static int hf_jxta_element = -1;
|
|
|
|
static int hf_jxta_element_sig = -1;
|
|
|
|
static int hf_jxta_element_namespaceid = -1;
|
|
|
|
static int hf_jxta_element_flags = -1;
|
2005-03-05 21:00:41 +00:00
|
|
|
static int hf_jxta_element_flag_hasType = -1;
|
|
|
|
static int hf_jxta_element_flag_hasEncoding = -1;
|
|
|
|
static int hf_jxta_element_flag_hasSignature = -1;
|
2005-01-07 12:58:43 +00:00
|
|
|
static int hf_jxta_element_name = -1;
|
|
|
|
static int hf_jxta_element_type = -1;
|
|
|
|
static int hf_jxta_element_encoding = -1;
|
|
|
|
static int hf_jxta_element_content_len = -1;
|
|
|
|
static int hf_jxta_element_content = -1;
|
2005-03-15 10:18:54 +00:00
|
|
|
static int hf_jxta_element_content_text = -1;
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
/** 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
|
|
|
|
**/
|
2005-01-07 12:58:43 +00:00
|
|
|
static gint ett_jxta_welcome = -1;
|
|
|
|
static gint ett_jxta_udp = -1;
|
|
|
|
static gint ett_jxta_framing = -1;
|
2005-03-05 21:00:41 +00:00
|
|
|
static gint ett_jxta_framing_header = -1;
|
2005-01-07 12:58:43 +00:00
|
|
|
static gint ett_jxta_msg = -1;
|
|
|
|
static gint ett_jxta_elem = -1;
|
2005-03-05 21:00:41 +00:00
|
|
|
static gint ett_jxta_elem_flags = -1;
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
/**
|
|
|
|
* 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
|
2005-01-07 12:58:43 +00:00
|
|
|
};
|
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
/**
|
|
|
|
* global preferences
|
|
|
|
**/
|
|
|
|
static gboolean gDESEGMENT = TRUE;
|
|
|
|
static gboolean gUDP_HEUR = FALSE;
|
|
|
|
static gboolean gTCP_HEUR = FALSE;
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
/**
|
|
|
|
* 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);
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
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);
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
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,
|
2005-03-25 22:37:58 +00:00
|
|
|
char **content_type);
|
2005-03-15 10:18:54 +00:00
|
|
|
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);
|
2005-01-07 12:58:43 +00:00
|
|
|
|
|
|
|
void proto_reg_handoff_jxta(void);
|
2005-03-15 10:18:54 +00:00
|
|
|
void proto_reg_handoff_message_jxta(void);
|
2005-01-07 12:58:43 +00:00
|
|
|
|
|
|
|
/**
|
2005-03-15 10:18:54 +00:00
|
|
|
* 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
|
2005-01-07 12:58:43 +00:00
|
|
|
**/
|
2005-03-15 10:18:54 +00:00
|
|
|
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!
|
|
|
|
*/
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
if (!gUDP_HEUR)
|
|
|
|
return FALSE;
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
|
|
|
|
return FALSE;
|
2005-03-05 21:00:41 +00:00
|
|
|
}
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
return dissect_jxta_udp(tvb, pinfo, tree) > 0;
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
/**
|
|
|
|
* 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;
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2005-03-15 10:18:54 +00:00
|
|
|
* 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.
|
2005-01-07 12:58:43 +00:00
|
|
|
**/
|
2005-03-15 10:18:54 +00:00
|
|
|
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);
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
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) {
|
2005-03-20 12:07:00 +00:00
|
|
|
needed = available - (int)content_length;
|
2005-03-15 10:18:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-03-20 12:07:00 +00:00
|
|
|
offset += (int)content_length;
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
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");
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
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;
|
2005-03-25 22:37:58 +00:00
|
|
|
char *content_type = NULL;
|
2005-03-15 10:18:54 +00:00
|
|
|
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;
|
|
|
|
|
2005-03-20 12:07:00 +00:00
|
|
|
jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length);
|
2005-03-15 10:18:54 +00:00
|
|
|
dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, jxta_udp_tree);
|
2005-03-25 22:37:58 +00:00
|
|
|
g_free(content_type);
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
if (!dissected) {
|
|
|
|
dissector_handle_t data_handle = find_dissector("data");
|
|
|
|
call_dissector(data_handle, jxta_message_tvb, pinfo, jxta_udp_tree);
|
|
|
|
}
|
|
|
|
|
2005-03-20 12:07:00 +00:00
|
|
|
tree_offset += (int)content_length;
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
|
|
|
|
|
|
|
|
g_assert(offset == tree_offset);
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
return offset;
|
|
|
|
}
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
/**
|
|
|
|
* 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);
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
if (conversation == NULL) {
|
2005-01-07 12:58:43 +00:00
|
|
|
/*
|
2005-03-15 10:18:54 +00:00
|
|
|
* No conversation exists yet - create one.
|
2005-01-07 12:58:43 +00:00
|
|
|
*/
|
2005-03-15 10:18:54 +00:00
|
|
|
conversation =
|
|
|
|
conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
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;
|
2005-03-25 22:37:58 +00:00
|
|
|
char *content_type = NULL;
|
2005-03-15 10:18:54 +00:00
|
|
|
gboolean dissected;
|
|
|
|
|
|
|
|
processed = dissect_jxta_message_framing(tvb, pinfo, tree, &content_length, &content_type);
|
|
|
|
|
2005-03-25 22:37:58 +00:00
|
|
|
|
|
|
|
if ((processed > 0) && (NULL != content_type) && (-1 != (gint) content_length)) {
|
2005-03-15 10:18:54 +00:00
|
|
|
int msg_offset = offset + processed;
|
|
|
|
|
|
|
|
available = tvb_reported_length_remaining(tvb, msg_offset);
|
|
|
|
if (available >= (int)content_length) {
|
2005-03-20 12:07:00 +00:00
|
|
|
tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, msg_offset, (gint)content_length, (gint)content_length);
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2005-03-20 12:07:00 +00:00
|
|
|
processed += (int)content_length;
|
2005-03-15 10:18:54 +00:00
|
|
|
} else {
|
2005-03-20 12:07:00 +00:00
|
|
|
processed = available - (int)content_length;
|
2005-03-15 10:18:54 +00:00
|
|
|
}
|
|
|
|
|
2005-03-25 22:37:58 +00:00
|
|
|
g_free(content_type);
|
2005-03-15 10:18:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2005-03-05 21:00:41 +00:00
|
|
|
}
|
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)) {
|
|
|
|
col_set_str(pinfo->cinfo, COL_INFO, "Welcome Message");
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
2005-03-05 21:00:41 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
if (tree) {
|
|
|
|
/* FIXME bondolo dissect the welcome line */
|
|
|
|
proto_tree_add_item(tree, hf_jxta_welcome, tvb, offset, afterwelcome, FALSE);
|
|
|
|
}
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
return afterwelcome;
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2005-03-15 10:18:54 +00:00
|
|
|
* 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.
|
2005-01-07 12:58:43 +00:00
|
|
|
**/
|
2005-03-15 10:18:54 +00:00
|
|
|
static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
|
2005-03-25 22:37:58 +00:00
|
|
|
char **content_type)
|
2005-03-15 10:18:54 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
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;
|
|
|
|
}
|
2005-01-07 12:58:43 +00:00
|
|
|
|
|
|
|
/*
|
2005-03-15 10:18:54 +00:00
|
|
|
* Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree.
|
2005-01-07 12:58:43 +00:00
|
|
|
*/
|
2005-03-15 10:18:54 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-03-05 21:00:41 +00:00
|
|
|
offset += sizeof(JXTA_MSG_SIG);
|
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
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;
|
|
|
|
|
2005-03-05 21:00:41 +00:00
|
|
|
offset += sizeof(guint16);
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
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;
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
2005-03-15 10:18:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
2005-01-07 12:58:43 +00:00
|
|
|
offset += sizeof(guint16);
|
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
/* parse elements */
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
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;
|
2005-01-07 19:29:54 +00:00
|
|
|
}
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
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]);
|
|
|
|
}
|
|
|
|
|
2005-03-20 12:07:00 +00:00
|
|
|
g_free((char *)namespaces);
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
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';
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
|
|
|
}
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
/* 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);
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
2005-03-15 10:18:54 +00:00
|
|
|
|
|
|
|
proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
|
|
|
|
|
|
|
|
g_assert(tree_offset == offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
/**
|
|
|
|
* Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
|
|
|
|
**/
|
2005-01-07 12:58:43 +00:00
|
|
|
void proto_register_jxta(void)
|
|
|
|
{
|
2005-03-15 10:18:54 +00:00
|
|
|
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);
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
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);
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
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);
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
init_done = TRUE;
|
|
|
|
}
|
|
|
|
}
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
void proto_reg_handoff_message_jxta(void)
|
|
|
|
{
|
|
|
|
static gboolean init_done = FALSE;
|
|
|
|
static dissector_handle_t message_jxta_handle;
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
if (!init_done) {
|
|
|
|
message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta);
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
media_type_dissector_table = find_dissector_table("media_type");
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle);
|
2005-01-07 12:58:43 +00:00
|
|
|
|
2005-03-15 10:18:54 +00:00
|
|
|
init_done = TRUE;
|
|
|
|
}
|
2005-01-07 12:58:43 +00:00
|
|
|
}
|