diff options
-rw-r--r-- | AUTHORS | 4 | ||||
-rw-r--r-- | epan/CMakeLists.txt | 6 | ||||
-rw-r--r-- | epan/dissectors/Makefile.common | 13 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-conference.c | 293 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-conference.h | 33 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-core.c | 755 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-core.h | 43 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-gtalk.c | 701 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-gtalk.h | 40 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-jingle.c | 952 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-jingle.h | 34 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-other.c | 1357 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-other.h | 68 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-utils.c | 1139 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp-utils.h | 287 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp.c | 1485 | ||||
-rw-r--r-- | epan/dissectors/packet-xmpp.h | 344 |
17 files changed, 7456 insertions, 98 deletions
@@ -3343,7 +3343,9 @@ Martin Renold <reld [AT] zhaw.ch> { Iain Arnell <iarnell [AT] epo.org> { ajp13 enhancements } - +Mariusz Okrój <okrojmariusz [AT]gmail.com>{ + XMPP enhancements +} and by: Pavel Roskin <proski [AT] gnu.org> diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index 4e7186d44a..2a1486f352 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -1118,6 +1118,12 @@ set(DISSECTOR_SRC dissectors/packet-xml.c dissectors/packet-xmcp.c dissectors/packet-xmpp.c + dissectors/packet-xmpp-conference.c + dissectors/packet-xmpp-core.c + dissectors/packet-xmpp-gtalk.c + dissectors/packet-xmpp-jingle.c + dissectors/packet-xmpp-other.c + dissectors/packet-xmpp-utils.c dissectors/packet-xot.c dissectors/packet-xtp.c dissectors/packet-xyplex.c diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index cf1ba5e774..c548f88811 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -1037,6 +1037,12 @@ DISSECTOR_SRC = \ packet-xml.c \ packet-xmcp.c \ packet-xmpp.c \ + packet-xmpp-conference.c \ + packet-xmpp-core.c \ + packet-xmpp-gtalk.c \ + packet-xmpp-jingle.c \ + packet-xmpp-other.c \ + packet-xmpp-utils.c \ packet-xot.c \ packet-xtp.c \ packet-xyplex.c \ @@ -1399,6 +1405,13 @@ DISSECTOR_INCLUDES = \ packet-x509if.h \ packet-x509sat.h \ packet-xml.h \ + packet-xmpp-conference.h \ + packet-xmpp-core.h \ + packet-xmpp-gtalk.h \ + packet-xmpp.h \ + packet-xmpp-jingle.h \ + packet-xmpp-other.h \ + packet-xmpp-utils.h \ packet-ypbind.h \ packet-yppasswd.h \ packet-ypserv.h \ diff --git a/epan/dissectors/packet-xmpp-conference.c b/epan/dissectors/packet-xmpp-conference.c new file mode 100644 index 0000000000..0d6ad51bfd --- /dev/null +++ b/epan/dissectors/packet-xmpp-conference.c @@ -0,0 +1,293 @@ +/* xmpp-conference.c + * Wireshark's XMPP dissector. + * + * XEP-0298: Delivering Conference Information to Jingle Participants (Coin) + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <glib.h> +#include <stdio.h> + +#include <epan/proto.h> +#include <epan/packet.h> +#include <epan/packet_info.h> +#include <epan/epan.h> +#include <epan/expert.h> +#include <epan/dissectors/packet-xml.h> + +#include <packet-xmpp.h> +#include <packet-xmpp-utils.h> +#include <packet-xmpp-conference.h> + + +static void xmpp_conf_desc(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_conf_state(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_conf_users(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_conf_user(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_conf_endpoint(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_conf_media(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +void +xmpp_conferece_info_advert(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *cinfo_item; + proto_tree *cinfo_tree; + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"isfocus", -1, TRUE, TRUE, NULL, NULL} + }; + + cinfo_item = proto_tree_add_item(tree, hf_xmpp_conf_info, tvb, element->offset, element->length, + ENC_BIG_ENDIAN); + cinfo_tree = proto_item_add_subtree(cinfo_item, ett_xmpp_conf_info); + + display_attrs(cinfo_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(cinfo_tree, element, pinfo, tvb, NULL, 0); +} + +void +xmpp_conference_info(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *cinfo_item; + proto_tree *cinfo_tree; + + const gchar *state_enums[] = {"full", "partial", "deleted"}; + array_t *state_array = ep_init_array_t(state_enums, array_length(state_enums)); + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"entity", -1, TRUE, TRUE, NULL, NULL}, + {"state", -1, FALSE, TRUE, val_enum_list, state_array}, + {"version", -1, FALSE, TRUE, NULL, NULL}, + {"sid", hf_xmpp_conf_info_sid, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "conference-description", xmpp_conf_desc, ONE}, + {NAME, "conference-state", xmpp_conf_state, ONE}, + /*{NAME, "host-info", xmpp_conf_host_info, ONE},*/ + {NAME, "users", xmpp_conf_users, ONE}, + /*{NAME, "sidebars-by-ref", xmpp_conf_sidebars_by_ref, ONE},*/ + /*{NAME, "sidebars-by-val", xmpp_conf_sidebars_by_val, ONE},*/ + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "CONFERENC-INFO "); + + cinfo_item = proto_tree_add_item(tree, hf_xmpp_conf_info, tvb, element->offset, element->length, + ENC_BIG_ENDIAN); + cinfo_tree = proto_item_add_subtree(cinfo_item, ett_xmpp_conf_info); + + display_attrs(cinfo_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(cinfo_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_conf_desc(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *desc_item; + proto_tree *desc_tree; + + attr_info attrs_info [] = { + {"subject", -1, FALSE, TRUE, NULL, NULL}, + {"display-text", -1, FALSE, FALSE, NULL, NULL}, + {"free-text", -1, FALSE, FALSE, NULL, NULL}, + {"max-user-count", -1, FALSE, FALSE, NULL, NULL}, + }; + +/* + elem_info elems_info [] = { + {NAME, "keywords", xmpp_conf_desc_keywords, ONE}, + {NAME, "conf-uris", xmpp_conf_desc_conf_uris, ONE}, + {NAME, "service-uris", xmpp_conf_desc_serv_uris, ONE}, + {NAME, "available-media", xmpp_conf_desc_avil_media, ONE}, + }; +*/ + + desc_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "CONFERENCE DESCRIPTION"); + desc_tree = proto_item_add_subtree(desc_item, ett_xmpp_conf_desc); + + change_elem_to_attrib("subject", "subject", element, transform_func_cdata); + change_elem_to_attrib("display-text", "display-text", element, transform_func_cdata); + change_elem_to_attrib("free-text", "free-text", element, transform_func_cdata); + change_elem_to_attrib("maximum-user-count", "max-user-count", element, transform_func_cdata); + + display_attrs(desc_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(desc_tree, element, pinfo, tvb, NULL,0); +} + +static void +xmpp_conf_state(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *state_item; + proto_tree *state_tree; + + attr_info attrs_info [] = { + {"user-count", -1, FALSE, TRUE, NULL, NULL}, + {"active", -1, FALSE, TRUE, NULL, NULL}, + {"locked", -1, FALSE, TRUE, NULL, NULL} + }; + + state_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "CONFERENCE STATE"); + state_tree = proto_item_add_subtree(state_item, ett_xmpp_conf_state); + + change_elem_to_attrib("user-count", "user-count", element, transform_func_cdata); + change_elem_to_attrib("active", "active", element, transform_func_cdata); + change_elem_to_attrib("locked", "locked", element, transform_func_cdata); + + display_attrs(state_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(state_tree, element, pinfo, tvb, NULL,0); + +} + +static void +xmpp_conf_users(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *users_item; + proto_tree *users_tree; + + attr_info attrs_info [] = { + {"state", -1, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "user", xmpp_conf_user, MANY} + }; + + users_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "USERS"); + users_tree = proto_item_add_subtree(users_item, ett_xmpp_conf_users); + + display_attrs(users_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(users_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} +static void +xmpp_conf_user(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *user_item; + proto_tree *user_tree; + + attr_info attrs_info [] = { + {"entity", -1, FALSE, TRUE, NULL, NULL}, + {"state", -1, FALSE, TRUE, NULL, NULL}, + {"display-text", -1, FALSE, TRUE, NULL, NULL}, + {"cascaded-focus", -1, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + /*{NAME, "associated-aors", xmpp_conf_assoc_aors, ONE},*/ + /*{NAME, "roles", xmpp_conf_roles, ONE},*/ + /*{NAME, "languages", xmpp_conf_langs, ONE},*/ + {NAME, "endpoint", xmpp_conf_endpoint, MANY}, + }; + + user_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "USERS"); + user_tree = proto_item_add_subtree(user_item, ett_xmpp_conf_user); + + change_elem_to_attrib("display-text", "display-text", element, transform_func_cdata); + change_elem_to_attrib("cascaded-focus", "cascaded-focus", element, transform_func_cdata); + + display_attrs(user_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(user_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_conf_endpoint(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *endpoint_item; + proto_tree *endpoint_tree; + + attr_info attrs_info [] = { + {"entity", -1, FALSE, TRUE, NULL, NULL}, + {"state", -1, FALSE, TRUE, NULL, NULL}, + {"display-text", -1, FALSE, TRUE, NULL, NULL}, + {"status", -1, FALSE, TRUE, NULL, NULL}, + {"joining-method", -1, FALSE, TRUE, NULL, NULL}, + {"disconnection-method", -1, FALSE, TRUE, NULL, NULL}, + }; + + elem_info elems_info [] = { + /*{NAME,"referred",...,ONE},*/ + /*{NAME,"joining-info",...,ONE},*/ + /*{NAME,"disconnection-info",...,ONE},*/ + {NAME,"media", xmpp_conf_media, ONE}, + /*{NAME,"call-info",...,ONE},*/ + + }; + + endpoint_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "ENDPOINT"); + endpoint_tree = proto_item_add_subtree(endpoint_item, ett_xmpp_conf_endpoint); + + change_elem_to_attrib("display-text", "display-text", element, transform_func_cdata); + change_elem_to_attrib("status", "status", element, transform_func_cdata); + change_elem_to_attrib("joining-method", "joining-method", element, transform_func_cdata); + change_elem_to_attrib("disconnection-method", "disconnection-method", element, transform_func_cdata); + + + display_attrs(endpoint_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(endpoint_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_conf_media(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *media_item; + proto_tree *media_tree; + + attr_info attrs_info[] = { + {"id", -1, TRUE, TRUE, NULL, NULL}, + {"display-text", -1, FALSE, TRUE, NULL, NULL}, + {"type", -1, FALSE, TRUE, NULL, NULL}, + {"label", -1, FALSE, TRUE, NULL, NULL}, + {"src-id", -1, FALSE, TRUE, NULL, NULL}, + {"status", -1, FALSE, TRUE, NULL, NULL}, + }; + + media_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "MEDIA"); + media_tree = proto_item_add_subtree(media_item, ett_xmpp_conf_media); + + change_elem_to_attrib("display-text", "display-text", element, transform_func_cdata); + change_elem_to_attrib("type", "type", element, transform_func_cdata); + change_elem_to_attrib("label", "label", element, transform_func_cdata); + change_elem_to_attrib("src-id", "src-id", element, transform_func_cdata); + change_elem_to_attrib("status", "status", element, transform_func_cdata); + + display_attrs(media_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(media_tree, element, pinfo, tvb, NULL, 0); +} +/* +* Editor modelines - http://www.wireshark.org/tools/modelines.html +* +* Local variables: +* c-basic-offset: 4 +* tab-width: 8 +* indent-tabs-mode: nil +* End: +* +* ex: set shiftwidth=4 tabstop=8 expandtab: +* :indentSize=4:tabSize=8:noTabs=true: +*/ diff --git a/epan/dissectors/packet-xmpp-conference.h b/epan/dissectors/packet-xmpp-conference.h new file mode 100644 index 0000000000..9f8d48b169 --- /dev/null +++ b/epan/dissectors/packet-xmpp-conference.h @@ -0,0 +1,33 @@ +/* xmpp-conference.h + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef XMPP_CONFERENCE_H +#define XMPP_CONFERENCE_H + +extern void xmpp_conferece_info_advert(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_conference_info(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +#endif /* XMPP_CONFERENCE_H */ + diff --git a/epan/dissectors/packet-xmpp-core.c b/epan/dissectors/packet-xmpp-core.c new file mode 100644 index 0000000000..3a1cf4c8b9 --- /dev/null +++ b/epan/dissectors/packet-xmpp-core.c @@ -0,0 +1,755 @@ +/* xmpp-core.c + * Wireshark's XMPP dissector. + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include<stdio.h> +#include<string.h> +#include <glib.h> + +#include <epan/packet.h> +#include <epan/proto.h> +#include <epan/tvbuff.h> +#include <epan/emem.h> +#include <epan/conversation.h> +#include <epan/strutil.h> +#include <epan/expert.h> + +#include <epan/dissectors/packet-xml.h> + +#include <packet-xmpp-utils.h> +#include <packet-xmpp.h> +#include <packet-xmpp-core.h> +#include <packet-xmpp-jingle.h> +#include <packet-xmpp-other.h> +#include <packet-xmpp-gtalk.h> +#include <packet-xmpp-conference.h> + +#include <epan/strutil.h> + +#include "epan/tvbparse.h" + + +void xmpp_auth(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +void xmpp_challenge_response_success(proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, element_t *packet, gint hf, gint ett, const char *col_info); + +void xmpp_iq(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); + +static void xmpp_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_error_text(proto_tree *tree, tvbuff_t *tvb, element_t *element); + +void xmpp_presence(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +static void xmpp_presence_status(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +void xmpp_message(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +static void xmpp_message_thread(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_message_body(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_message_subject(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +void xmpp_failure(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +static void xmpp_failure_text(proto_tree *tree, tvbuff_t *tvb, element_t *element); + +static void xmpp_features_mechanisms(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); + +void +xmpp_iq(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *xmpp_iq_item; + proto_tree *xmpp_iq_tree; + + attr_t *attr_id, *attr_type; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"id", hf_xmpp_id, TRUE, TRUE, NULL, NULL}, + {"type", hf_xmpp_type, TRUE, TRUE, NULL, NULL}, + {"from", hf_xmpp_from, FALSE, TRUE, NULL, NULL}, + {"to", hf_xmpp_to, FALSE, TRUE, NULL, NULL}, + {"xml:lang", -1, FALSE, FALSE, NULL, NULL} + }; + + conversation_t *conversation = NULL; + xmpp_conv_info_t *xmpp_info = NULL; + xmpp_transaction_t *reqresp_trans = NULL; + + elem_info elems_info [] = { + {NAME_AND_ATTR, name_attr_struct("query", "xmlns","http://jabber.org/protocol/disco#items"), xmpp_disco_items_query, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns", "jabber:iq:roster"), xmpp_roster_query, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns", "http://jabber.org/protocol/disco#info"), xmpp_disco_info_query, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns", "http://jabber.org/protocol/bytestreams"), xmpp_bytestreams_query, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns", "http://jabber.org/protocol/muc#owner"), xmpp_muc_owner_query, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns", "http://jabber.org/protocol/muc#admin"), xmpp_muc_admin_query, ONE}, + {NAME, "bind", xmpp_iq_bind, ONE}, + {NAME_AND_ATTR, name_attr_struct("session", "xmlns", "urn:ietf:params:xml:ns:xmpp-session"), xmpp_session, ONE}, + {NAME, "vCard", xmpp_vcard, ONE}, + {NAME, "jingle", xmpp_jingle, ONE}, + {NAME_AND_ATTR, name_attr_struct("services", "xmlns", "http://jabber.org/protocol/jinglenodes"), xmpp_jinglenodes_services, ONE}, + {NAME_AND_ATTR, name_attr_struct("channel", "xmlns", "http://jabber.org/protocol/jinglenodes#channel"), xmpp_jinglenodes_channel, ONE}, + {NAME_AND_ATTR, name_attr_struct("open", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_open, ONE}, + {NAME_AND_ATTR, name_attr_struct("close", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_close, ONE}, + {NAME_AND_ATTR, name_attr_struct("data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data, ONE}, + {NAME, "si", xmpp_si, ONE}, + {NAME, "error", xmpp_error, ONE}, + {NAME_AND_ATTR, name_attr_struct("session", "xmlns", "http://www.google.com/session"), xmpp_gtalk_session, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns","google:jingleinfo"), xmpp_gtalk_jingleinfo_query, ONE}, + {NAME_AND_ATTR, name_attr_struct("usersetting", "xmlns","google:setting"), xmpp_gtalk_usersetting, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns","jabber:iq:last"), xmpp_last_query, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns","jabber:iq:version"), xmpp_version_query, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns","google:mail:notify"), xmpp_gtalk_mail_query, ONE}, + {NAME, "mailbox", xmpp_gtalk_mail_mailbox, ONE}, + {NAME, "new-mail", xmpp_gtalk_mail_new_mail, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns","google:shared-status"), xmpp_gtalk_status_query, ONE}, + {NAME, "conference-info", xmpp_conference_info, ONE}, + {NAME_AND_ATTR, name_attr_struct("ping", "xmlns","urn:xmpp:ping"), xmpp_ping, ONE}, + {NAME_AND_ATTR, name_attr_struct("inputevt", "xmlns","http://jitsi.org/protocol/inputevt"), xmpp_jitsi_inputevt, ONE}, + }; + + attr_id = get_attr(packet, "id"); + attr_type = get_attr(packet, "type"); + + conversation = find_or_create_conversation(pinfo); + xmpp_info = conversation_get_proto_data(conversation, proto_xmpp); + + xmpp_iq_item = proto_tree_add_item(tree, hf_xmpp_iq, tvb, packet->offset, packet->length, ENC_LITTLE_ENDIAN); + xmpp_iq_tree = proto_item_add_subtree(xmpp_iq_item,ett_xmpp_iq); + + display_attrs(xmpp_iq_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + + + col_clear(pinfo->cinfo, COL_INFO); + col_add_fstr(pinfo->cinfo, COL_INFO, "IQ(%s) ", attr_type?attr_type->value:""); + + display_elems(xmpp_iq_tree, packet, pinfo, tvb, elems_info, array_length(elems_info)); + + /*displays generated info such as req/resp tracking, jingle sid + * in each packet related to specified jingle session and IBB sid in packet related to it*/ + if(xmpp_info && attr_id) + { + gchar *jingle_sid, *ibb_sid, *gtalk_sid; + + jingle_sid = se_tree_lookup_string(xmpp_info->jingle_sessions, attr_id->value, EMEM_TREE_STRING_NOCASE); + + if (jingle_sid) { + proto_item *it = proto_tree_add_string(tree, hf_xmpp_jingle_session, tvb, 0, 0, jingle_sid); + PROTO_ITEM_SET_GENERATED(it); + } + + ibb_sid = se_tree_lookup_string(xmpp_info->ibb_sessions, attr_id->value, EMEM_TREE_STRING_NOCASE); + + if (ibb_sid) { + proto_item *it = proto_tree_add_string(tree, hf_xmpp_ibb, tvb, 0, 0, ibb_sid); + PROTO_ITEM_SET_GENERATED(it); + } + + gtalk_sid = se_tree_lookup_string(xmpp_info->gtalk_sessions, attr_id->value, EMEM_TREE_STRING_NOCASE); + + if (gtalk_sid) { + proto_item *it = proto_tree_add_string(tree, hf_xmpp_gtalk, tvb, 0, 0, gtalk_sid); + PROTO_ITEM_SET_GENERATED(it); + } + + reqresp_trans = se_tree_lookup_string(xmpp_info->req_resp, attr_id->value, EMEM_TREE_STRING_NOCASE); + /*displays request/response field in each iq packet*/ + if (reqresp_trans) { + + if (reqresp_trans->req_frame == pinfo->fd->num) { + if (reqresp_trans->resp_frame) { + proto_item *it = proto_tree_add_uint(tree, hf_xmpp_response_in, tvb, 0, 0, reqresp_trans->resp_frame); + PROTO_ITEM_SET_GENERATED(it); + } else + { + expert_add_info_format(pinfo, xmpp_iq_item , PI_PROTOCOL, PI_CHAT, "Packet without response"); + } + + } else { + if (reqresp_trans->req_frame) { + proto_item *it = proto_tree_add_uint(tree, hf_xmpp_response_to, tvb, 0, 0, reqresp_trans->req_frame); + PROTO_ITEM_SET_GENERATED(it); + } else + { + expert_add_info_format(pinfo, xmpp_iq_item , PI_PROTOCOL, PI_CHAT, "Packet without response"); + } + } + } + } + + +} + + +static void +xmpp_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *error_item; + proto_tree *error_tree; + + element_t *text_element, *cond_element; + + attr_info attrs_info[] = { + {"type", hf_xmpp_error_type, TRUE, TRUE, NULL, NULL}, + {"code", hf_xmpp_error_code, FALSE, TRUE, NULL, NULL}, + {"condition", hf_xmpp_error_condition, TRUE, TRUE, NULL, NULL} /*TODO: validate list to the condition element*/ + }; + + gchar *error_info; + + attr_t *fake_condition = NULL; + + error_info = ep_strdup("Stanza error"); + + error_item = proto_tree_add_item(tree, hf_xmpp_error, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + error_tree = proto_item_add_subtree(error_item, ett_xmpp_query_item); + + cond_element = steal_element_by_attr(element, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); + if(cond_element) + { + fake_condition = ep_init_attr_t(cond_element->name, cond_element->offset, cond_element->length); + g_hash_table_insert(element->attrs,"condition", fake_condition); + + error_info = ep_strdup_printf("%s: %s;", error_info, cond_element->name); + } + + + display_attrs(error_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + while((text_element = steal_element_by_name(element, "text")) != NULL) + { + xmpp_error_text(error_tree, tvb, text_element); + + error_info = ep_strdup_printf("%s Text: %s", error_info, text_element->data?text_element->data->value:""); + } + + expert_add_info_format(pinfo, error_item, PI_RESPONSE_CODE, PI_CHAT,"%s", error_info); + + xmpp_unknown(error_tree, tvb, pinfo, element); +} + +static void +xmpp_error_text(proto_tree *tree, tvbuff_t *tvb, element_t *element) +{ + proto_tree_add_string(tree, hf_xmpp_error_text, tvb, element->offset, element->length, element->data?element->data->value:""); +} + + +void +xmpp_presence(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *presence_item; + proto_tree *presence_tree; + + const gchar *type_enums[] = {"error", "probe", "subscribe", "subscribed", + "unavailable", "unsubscribe", "unsubscribed"}; + array_t *type_array = ep_init_array_t(type_enums, array_length(type_enums)); + + const gchar *show_enums[] = {"away", "chat", "dnd", "xa"}; + array_t *show_array = ep_init_array_t(show_enums, array_length(show_enums)); + + attr_info attrs_info[] = { + {"from", hf_xmpp_from, FALSE, FALSE, NULL, NULL}, + {"id", hf_xmpp_id, FALSE, TRUE, NULL, NULL}, + {"to", hf_xmpp_to, FALSE, FALSE, NULL, NULL}, + {"type", hf_xmpp_type, FALSE, TRUE, val_enum_list, type_array}, + {"xml:lang",-1, FALSE, FALSE, NULL,NULL}, + {"show", hf_xmpp_presence_show, FALSE, TRUE, val_enum_list, show_array}, + {"priority", -1, FALSE, FALSE, NULL, NULL} + }; + + elem_info elems_info[] = { + {NAME, "status", xmpp_presence_status, MANY}, + {NAME_AND_ATTR, name_attr_struct("c","xmlns","http://jabber.org/protocol/caps"), xmpp_presence_caps, ONE}, + {NAME, "delay", xmpp_delay, ONE}, + {NAME_AND_ATTR, name_attr_struct("x","xmlns", "jabber:x:delay"), xmpp_delay, ONE}, + {NAME_AND_ATTR, name_attr_struct("x","xmlns", "vcard-temp:x:update"), xmpp_vcard_x_update, ONE}, + {NAME_AND_ATTR, name_attr_struct("x","xmlns","http://jabber.org/protocol/muc"), xmpp_muc_x, ONE}, + {NAME_AND_ATTR, name_attr_struct("x","xmlns","http://jabber.org/protocol/muc#user"), xmpp_muc_user_x, ONE}, + {NAME, "error", xmpp_error, ONE}, + {NAME_AND_ATTR, name_attr_struct("query", "xmlns","jabber:iq:last"), xmpp_last_query, ONE} + }; + + + element_t *show, *priority; + + col_clear(pinfo->cinfo, COL_INFO); + col_append_fstr(pinfo->cinfo, COL_INFO, "PRESENCE "); + + presence_item = proto_tree_add_item(tree, hf_xmpp_presence, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN); + presence_tree = proto_item_add_subtree(presence_item, ett_xmpp_presence); + + if((show = steal_element_by_name(packet, "show"))!=NULL) + { + attr_t *fake_show = ep_init_attr_t(show->data?show->data->value:"",show->offset, show->length); + g_hash_table_insert(packet->attrs, "show", fake_show); + } + + if((priority = steal_element_by_name(packet, "priority"))!=NULL) + { + attr_t *fake_priority = ep_init_attr_t(priority->data?priority->data->value:"",priority->offset, priority->length); + g_hash_table_insert(packet->attrs, "priority", fake_priority); + } + display_attrs(presence_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + + display_elems(presence_tree, packet, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_presence_status(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *status_item; + proto_tree *status_tree; + + attr_info attrs_info[] = { + {"xml:lang", -1, FALSE, TRUE, NULL, NULL}, + {"value", -1, TRUE, TRUE, NULL, NULL} + }; + + attr_t *fake_value; + + status_item = proto_tree_add_item(tree, hf_xmpp_presence_status, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + status_tree = proto_item_add_subtree(status_item, ett_xmpp_presence_status); + + if(element->data) + fake_value = ep_init_attr_t(element->data->value, element->offset, element->length); + else + fake_value = ep_init_attr_t("(empty)", element->offset, element->length); + + + g_hash_table_insert(element->attrs, "value", fake_value); + + display_attrs(status_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(status_tree, tvb, pinfo, element); +} + + +void +xmpp_message(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *message_item; + proto_tree *message_tree; + + const gchar *type_enums[] = {"chat", "error", "groupchat", "headline", "normal"}; + array_t *type_array = ep_init_array_t(type_enums, array_length(type_enums)); + + attr_info attrs_info[] = { + {"from", hf_xmpp_from, FALSE, FALSE, NULL, NULL}, + {"id", hf_xmpp_id, FALSE, TRUE, NULL, NULL}, + {"to", hf_xmpp_to, FALSE, FALSE, NULL, NULL}, + {"type", hf_xmpp_type, FALSE, TRUE, val_enum_list, type_array}, + {"xml:lang",-1, FALSE, FALSE, NULL,NULL}, + {"chatstate", hf_xmpp_message_chatstate, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME_AND_ATTR, name_attr_struct("data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data, ONE}, + {NAME, "thread", xmpp_message_thread, ONE}, + {NAME, "body", xmpp_message_body, MANY}, + {NAME, "subject", xmpp_message_subject, MANY}, + {NAME, "delay", xmpp_delay, ONE}, + {NAME_AND_ATTR, name_attr_struct("x","xmlns","jabber:x:event"), xmpp_x_event, ONE}, + {NAME_AND_ATTR, name_attr_struct("x","xmlns","http://jabber.org/protocol/muc#user"), xmpp_muc_user_x, ONE}, + {NAME_AND_ATTR, name_attr_struct("x","xmlns","google:nosave"), xmpp_gtalk_nosave_x, ONE}, + {NAME, "error", xmpp_error, ONE} + }; + + element_t *chatstate; + + attr_t *id = NULL; + + conversation_t *conversation = NULL; + xmpp_conv_info_t *xmpp_info = NULL; + + col_clear(pinfo->cinfo, COL_INFO); + col_append_fstr(pinfo->cinfo, COL_INFO, "MESSAGE "); + + id = get_attr(packet, "id"); + + conversation = find_or_create_conversation(pinfo); + xmpp_info = conversation_get_proto_data(conversation, proto_xmpp); + + message_item = proto_tree_add_item(tree, hf_xmpp_message, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN); + message_tree = proto_item_add_subtree(message_item, ett_xmpp_message); + + if((chatstate = steal_element_by_attr(packet, "xmlns", "http://jabber.org/protocol/chatstates"))!=NULL) + { + attr_t *fake_chatstate_attr = ep_init_attr_t(chatstate->name, chatstate->offset, chatstate->length); + g_hash_table_insert(packet->attrs, "chatstate", fake_chatstate_attr); + } + + display_attrs(message_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + + display_elems(message_tree, packet, pinfo, tvb, elems_info, array_length(elems_info)); + + /*Displays data about IBB session*/ + if(xmpp_info && id) + { + gchar *ibb_sid; + + ibb_sid = se_tree_lookup_string(xmpp_info->ibb_sessions, id->value, EMEM_TREE_STRING_NOCASE); + + if (ibb_sid) { + proto_item *it = proto_tree_add_string(tree, hf_xmpp_ibb, tvb, 0, 0, ibb_sid); + PROTO_ITEM_SET_GENERATED(it); + } + + } +} + +static void +xmpp_message_body(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *body_item; + proto_tree *body_tree; + + attr_info attrs_info[] = { + {"xml:lang", -1, FALSE, TRUE, NULL, NULL}, + {"value", -1, TRUE, TRUE, NULL, NULL} + }; + + attr_t *fake_data_attr; + + body_item = proto_tree_add_item(tree, hf_xmpp_message_body, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + body_tree = proto_item_add_subtree(body_item, ett_xmpp_message_body); + + fake_data_attr = ep_init_attr_t(element->data?element->data->value:"", element->offset, element->length); + g_hash_table_insert(element->attrs, "value", fake_data_attr); + + + display_attrs(body_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(body_tree, tvb, pinfo, element); +} + +static void +xmpp_message_subject(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) { + proto_item *subject_item; + proto_tree *subject_tree; + + attr_info attrs_info[] = { + {"xml:lang", -1, FALSE, TRUE, NULL, NULL}, + {"value", -1, TRUE, FALSE, NULL, NULL} + }; + + attr_t *fake_data_attr; + + subject_item = proto_tree_add_item(tree, hf_xmpp_message_subject, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + subject_tree = proto_item_add_subtree(subject_item, ett_xmpp_message_subject); + + fake_data_attr = ep_init_attr_t(element->data?element->data->value:"", element->offset, element->length); + g_hash_table_insert(element->attrs, "value", fake_data_attr); + + + display_attrs(subject_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(subject_tree, tvb, pinfo, element); +} + +static void +xmpp_message_thread(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *thread_item; + proto_tree *thread_tree; + + attr_info attrs_info[] = { + {"parent", hf_xmpp_message_thread_parent, FALSE, TRUE, NULL, NULL}, + {"value", -1, TRUE, TRUE, NULL, NULL} + }; + + attr_t *fake_value; + + thread_item = proto_tree_add_item(tree, hf_xmpp_message_thread, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + thread_tree = proto_item_add_subtree(thread_item, ett_xmpp_message_thread); + + fake_value = ep_init_attr_t(element->data?element->data->value:"", element->offset, element->length); + g_hash_table_insert(element->attrs, "value", fake_value); + + + display_attrs(thread_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(thread_tree, tvb, pinfo, element); +} + +void +xmpp_auth(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *auth_item; + proto_tree *auth_tree; + + attr_info_ext attrs_info[]={ + {"urn:ietf:params:xml:ns:xmpp-sasl", {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}}, + {"urn:ietf:params:xml:ns:xmpp-sasl", {"mechanism", -1, TRUE, TRUE, NULL, NULL}}, + {"http://www.google.com/talk/protocol/auth", {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}}, + {"http://www.google.com/talk/protocol/auth", {"client-uses-full-bind-result", -1, TRUE, TRUE, NULL, NULL}}, + }; + + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "AUTH"); + + auth_item = proto_tree_add_item(tree, hf_xmpp_auth, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN); + auth_tree = proto_item_add_subtree(auth_item, ett_xmpp_auth); + + display_attrs_ext(auth_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_cdata(auth_tree, tvb, packet, -1); + + xmpp_unknown(auth_tree, tvb, pinfo, packet); +} + +void +xmpp_challenge_response_success(proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, element_t *packet, gint hf, gint ett, const char *col_info) +{ + proto_item *item; + proto_tree *subtree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, col_info); + + item = proto_tree_add_item(tree, hf, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN); + subtree = proto_item_add_subtree(item, ett); + + display_attrs(subtree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + xmpp_cdata(subtree, tvb, packet, -1); + + xmpp_unknown(subtree, tvb, pinfo, packet); +} + +void +xmpp_failure(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *fail_item; + proto_tree *fail_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"condition", -1, FALSE, TRUE, NULL, NULL} + }; + + const gchar *fail_names[] = {"aborted","account-disabled", "credentials-expired", + "encryption-required", "incorrect-encoding", "invalid-authzid", "invalid-mechanism", + "malformed-request", "mechanism-too-weak", "not-authorized", "temporary-auth-failure", + "transition-needed" + }; + + element_t *fail_condition, *text; + + col_add_fstr(pinfo->cinfo, COL_INFO, "FAILURE "); + + fail_item = proto_tree_add_item(tree, hf_xmpp_failure, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN); + fail_tree = proto_item_add_subtree(fail_item, ett_xmpp_failure); + + if((fail_condition = steal_element_by_names(packet, fail_names, array_length(fail_names)))!=NULL) + { + attr_t *fake_cond = ep_init_attr_t(fail_condition->name, fail_condition->offset, fail_condition->length); + g_hash_table_insert(packet->attrs, "condition", fake_cond); + } + + if((text = steal_element_by_name(packet, "text"))!=NULL) + { + xmpp_failure_text(fail_tree, tvb, text); + } + + display_attrs(fail_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(fail_tree, tvb, pinfo, packet); +} + +static void +xmpp_failure_text(proto_tree *tree, tvbuff_t *tvb, element_t *element) +{ + attr_t *lang = get_attr(element,"xml:lang"); + + proto_tree_add_text(tree, tvb, element->offset, element->length, "TEXT%s: %s", + lang?ep_strdup_printf("(%s)",lang->value):"", + element->data?element->data->value:""); +} + +void +xmpp_xml_header(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, element_t *packet) +{ + col_add_fstr(pinfo->cinfo, COL_INFO, "XML "); + proto_tree_add_text(tree, tvb, packet->offset, packet->length, "XML HEADER VER. %s","1.0"); +} + +void +xmpp_stream(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *stream_item; + proto_tree *stream_tree; + + attr_info_ext attrs_info [] = { + {"http://etherx.jabber.org/streams",{"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL}}, + {"http://etherx.jabber.org/streams",{"version", -1, FALSE, TRUE, NULL, NULL}}, + {"http://etherx.jabber.org/streams",{"from",-1, FALSE, TRUE, NULL, NULL}}, + {"http://etherx.jabber.org/streams",{"to",-1, FALSE, TRUE, NULL, NULL}}, + {"http://etherx.jabber.org/streams",{"id",-1, FALSE, TRUE, NULL, NULL}}, + {"http://etherx.jabber.org/streams",{"xml:lang",-1, FALSE, TRUE, NULL, NULL}}, + {"jabber:client",{"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL}}, + + }; + + col_add_fstr(pinfo->cinfo, COL_INFO, "STREAM "); + + stream_item = proto_tree_add_item(tree, hf_xmpp_stream, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN); + stream_tree = proto_item_add_subtree(stream_item, ett_xmpp_stream); + + display_attrs_ext(stream_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(stream_tree, packet, pinfo, tvb, NULL, 0); +} + +/*returns TRUE if stream end occurs*/ +gboolean +xmpp_stream_close(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo) +{ + tvbparse_t* tt; + tvbparse_elem_t* elem; + tvbparse_wanted_t* want_ignore = tvbparse_chars(1,1,0," \t\r\n",NULL,NULL,NULL); + tvbparse_wanted_t* want_name = tvbparse_chars(2,1,0,"abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",NULL,NULL,NULL); + tvbparse_wanted_t* want_stream_end_with_ns = tvbparse_set_seq(3, NULL, NULL, NULL, + want_name, + tvbparse_char(4, ":", NULL, NULL, NULL), + want_name, + NULL); + + tvbparse_wanted_t* want_stream_end = tvbparse_set_oneof(5, NULL, NULL, NULL, + want_stream_end_with_ns, + want_name, + NULL); + + tvbparse_wanted_t* want_stream_end_tag = tvbparse_set_seq(6, NULL, NULL, NULL, + tvbparse_string(-1,"</",NULL,NULL,NULL), + want_stream_end, + tvbparse_char(-1,">",NULL,NULL,NULL), + NULL); + tt = tvbparse_init(tvb,0,-1,NULL,want_ignore); + + if((elem = tvbparse_get(tt,want_stream_end_tag))!=NULL) + { + proto_tree_add_text(tree, tvb, elem->offset, elem->len, "STREAM END"); + col_add_fstr(pinfo->cinfo, COL_INFO, "STREAM END"); + + return TRUE; + } + return FALSE; +} + +void +xmpp_features(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *features_item; + proto_tree *features_tree; + + elem_info elems_info [] = { + {NAME, "mechanisms", xmpp_features_mechanisms, MANY} + }; + + features_item = proto_tree_add_item(tree, hf_xmpp_features, tvb, packet->offset, packet->length, + ENC_BIG_ENDIAN); + features_tree = proto_item_add_subtree(features_item, ett_xmpp_features); + + col_add_fstr(pinfo->cinfo, COL_INFO, "FEATURES "); + + display_attrs(features_tree, packet, pinfo, tvb, NULL, 0); + display_elems(features_tree, packet, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_features_mechanisms(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *mechanisms_item; + proto_tree *mechanisms_tree; + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "mechanism", xmpp_simple_cdata_elem, MANY}, + }; + + mechanisms_item = proto_tree_add_text(tree, tvb, packet->offset, packet->length, "MECHANISMS"); + mechanisms_tree = proto_item_add_subtree(mechanisms_item, ett_xmpp_features_mechanisms); + + display_attrs(mechanisms_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(mechanisms_tree, packet, pinfo, tvb, elems_info, array_length(elems_info)); +} + +void +xmpp_starttls(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *tls_item; + proto_tree *tls_tree; + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + }; + + col_add_fstr(pinfo->cinfo, COL_INFO, "STARTTLS "); + + tls_item = proto_tree_add_item(tree, hf_xmpp_starttls, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN); + tls_tree = proto_item_add_subtree(tls_item, ett_xmpp_starttls); + + display_attrs(tls_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(tls_tree, packet, pinfo, tvb, NULL, 0); +} + +void +xmpp_proceed(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet) +{ + proto_item *proceed_item; + proto_tree *proceed_tree; + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + }; + + col_add_fstr(pinfo->cinfo, COL_INFO, "PROCEED "); + + proceed_item = proto_tree_add_item(tree, hf_xmpp_proceed, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN); + proceed_tree = proto_item_add_subtree(proceed_item, ett_xmpp_proceed); + + display_attrs(proceed_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(proceed_tree, packet, pinfo, tvb, NULL, 0); +} +/* +* Editor modelines - http://www.wireshark.org/tools/modelines.html +* +* Local variables: +* c-basic-offset: 4 +* tab-width: 8 +* indent-tabs-mode: nil +* End: +* +* ex: set shiftwidth=4 tabstop=8 expandtab: +* :indentSize=4:tabSize=8:noTabs=true: +*/ diff --git a/epan/dissectors/packet-xmpp-core.h b/epan/dissectors/packet-xmpp-core.h new file mode 100644 index 0000000000..e3de62854e --- /dev/null +++ b/epan/dissectors/packet-xmpp-core.h @@ -0,0 +1,43 @@ +/* xmpp-core.h + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef XMPP_CORE_H +#define XMPP_CORE_H + +extern void xmpp_iq(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +extern void xmpp_presence(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +extern void xmpp_message(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +extern void xmpp_auth(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +extern void xmpp_challenge_response_success(proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, element_t *packet, gint hf, gint ett, const char *col_info); +extern void xmpp_failure(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +extern void xmpp_xml_header(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +extern void xmpp_stream(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +extern gboolean xmpp_stream_close(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo); +extern void xmpp_features(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +extern void xmpp_starttls(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +extern void xmpp_proceed(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *packet); +#endif /* XMPP_CORE_H */ + diff --git a/epan/dissectors/packet-xmpp-gtalk.c b/epan/dissectors/packet-xmpp-gtalk.c new file mode 100644 index 0000000000..462c97261f --- /dev/null +++ b/epan/dissectors/packet-xmpp-gtalk.c @@ -0,0 +1,701 @@ +/* xmpp-gtalk.c + * Wireshark's XMPP dissector. + * + * GTalk extensions. + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include<stdio.h> +#include<string.h> +#include <glib.h> + +#include <epan/packet.h> +#include <epan/proto.h> +#include <epan/tvbuff.h> +#include <epan/emem.h> +#include <epan/conversation.h> +#include <epan/strutil.h> +#include <epan/expert.h> +#include <epan/dissectors/packet-xml.h> + +#include <packet-xmpp.h> +#include <packet-xmpp-utils.h> +#include <packet-xmpp-gtalk.h> +#include <packet-xmpp-conference.h> + + +static void xmpp_gtalk_session_desc(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_session_desc_payload(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_session_cand(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_session_reason(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_jingleinfo_stun(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_jingleinfo_server(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_jingleinfo_relay(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_jingleinfo_relay_serv(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_nosave_item(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_mail_mail_info(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_mail_senders(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_mail_sender(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_mail_snippet(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_status_status_list(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_gtalk_transport_p2p_cand(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); + +void +xmpp_gtalk_session(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *session_item; + proto_tree *session_tree; + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"type", hf_xmpp_gtalk_session_type, TRUE, TRUE, NULL, NULL}, + {"initiator", -1, FALSE, TRUE, NULL, NULL}, + {"id", -1, TRUE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME,"description", xmpp_gtalk_session_desc, ONE}, + {NAME, "candidate", xmpp_gtalk_session_cand, MANY}, + {NAME, "reason", xmpp_gtalk_session_reason, ONE}, + {NAME_AND_ATTR, name_attr_struct("transport", "xmlns", "http://www.google.com/transport/p2p"), xmpp_gtalk_transport_p2p, ONE}, + {NAME, "conference-info", xmpp_conferece_info_advert, ONE} + }; + + attr_t *attr_type = get_attr(element, "type"); + + col_append_fstr(pinfo->cinfo, COL_INFO, "GTALK-SESSION(%s) ", attr_type?attr_type->value:""); + + session_item = proto_tree_add_item(tree, hf_xmpp_gtalk_session, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + session_tree = proto_item_add_subtree(session_item, ett_xmpp_gtalk_session); + + display_attrs(session_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + display_elems(session_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_gtalk_session_desc(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *desc_item; + proto_tree *desc_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"xml:lang", -1, FALSE, FALSE, NULL, NULL} + }; + + elem_info elems_info[] = { + {NAME, "payload-type", xmpp_gtalk_session_desc_payload, MANY} + }; + + desc_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "DESCRIPTION"); + desc_tree = proto_item_add_subtree(desc_item, ett_xmpp_gtalk_session_desc); + + display_attrs(desc_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(desc_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_gtalk_session_desc_payload(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *payload_item; + proto_tree *payload_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL}, + {"id", -1, FALSE, TRUE, NULL, NULL}, + {"name", -1, FALSE, TRUE, NULL, NULL}, + {"channels", -1, FALSE, FALSE, NULL, NULL}, + {"clockrate", -1, FALSE, FALSE, NULL, NULL}, + {"bitrate", -1, FALSE, FALSE, NULL, NULL}, + {"width", -1, FALSE, FALSE, NULL, NULL}, + {"height", -1, FALSE, FALSE, NULL, NULL}, + {"framerate", -1, FALSE, FALSE, NULL, NULL}, + }; + + payload_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "PAYLOAD-TYPE"); + payload_tree = proto_item_add_subtree(payload_item, ett_xmpp_gtalk_session_desc_payload); + + display_attrs(payload_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(payload_tree, element, pinfo, tvb, NULL, 0); +} + +static void +xmpp_gtalk_session_cand(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *cand_item; + proto_tree *cand_tree; + + attr_info attrs_info[] = { + {"name", -1, TRUE, TRUE, NULL, NULL}, + {"address", -1, TRUE, FALSE, NULL, NULL}, + {"port", -1, TRUE, FALSE, NULL, NULL}, + {"preference", -1, TRUE, FALSE, NULL, NULL}, + {"type", -1, TRUE, TRUE, NULL, NULL}, + {"protocol", -1, TRUE, TRUE, NULL, NULL}, + {"network", -1, TRUE, FALSE, NULL, NULL}, + {"username", -1, TRUE, FALSE, NULL, NULL}, + {"password", -1, TRUE, FALSE, NULL, NULL}, + {"generation", -1, TRUE, FALSE, NULL, NULL}, + {"foundation", -1, FALSE, FALSE, NULL, NULL}, + {"component", -1, FALSE, FALSE, NULL, NULL} + }; + + cand_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "CANDIDATE"); + cand_tree = proto_item_add_subtree(cand_item, ett_xmpp_gtalk_session_cand); + + display_attrs(cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(cand_tree, element, pinfo, tvb, NULL, 0); +} + +static void +xmpp_gtalk_session_reason(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *reason_item; + proto_tree *reason_tree; + + attr_info attrs_info[] = { + {"condition", -1, TRUE, TRUE, NULL, NULL}, + {"text", -1, FALSE, FALSE, NULL, NULL} + }; + + element_t *condition; + element_t *text; + + const gchar *reason_names[] = { "success", "busy", "cancel"}; + + reason_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "REASON"); + reason_tree = proto_item_add_subtree(reason_item, ett_xmpp_gtalk_session_reason); + + + /*Looks for reason description.*/ + if((condition = steal_element_by_names(element, reason_names, array_length(reason_names)))!=NULL) + { + attr_t *fake_cond = ep_init_attr_t(condition->name, condition->offset, condition->length); + g_hash_table_insert(element->attrs, "condition", fake_cond); + + } + + if((text = steal_element_by_name(element, "text"))!=NULL) + { + attr_t *fake_text = ep_init_attr_t(text->data?text->data->value:"", text->offset, text->length); + g_hash_table_insert(element->attrs, "text", fake_text); + } + + display_attrs(reason_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(reason_tree, tvb, pinfo, element); +} + +void +xmpp_gtalk_jingleinfo_query(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "stun", xmpp_gtalk_jingleinfo_stun, ONE}, + {NAME, "relay", xmpp_gtalk_jingleinfo_relay, ONE} + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(google:jingleinfo) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, + ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(query_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_gtalk_jingleinfo_stun(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *stun_item; + proto_tree *stun_tree; + + elem_info elems_info [] = { + {NAME, "server", xmpp_gtalk_jingleinfo_server, MANY}, + }; + + stun_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "STUN"); + stun_tree = proto_item_add_subtree(stun_item, ett_xmpp_gtalk_jingleinfo_stun); + + display_attrs(stun_tree, element, pinfo, tvb, NULL, 0); + display_elems(stun_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); + +} + +static void +xmpp_gtalk_jingleinfo_server(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *serv_item; + proto_tree *serv_tree; + + attr_info attrs_info[] = { + {"host", -1, TRUE, TRUE, NULL, NULL}, + {"udp", -1, TRUE, TRUE, NULL, NULL} + }; + + serv_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "SERVER"); + serv_tree = proto_item_add_subtree(serv_item, ett_xmpp_gtalk_jingleinfo_server); + + display_attrs(serv_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(serv_tree, element, pinfo, tvb, NULL, 0); +} + +static void +xmpp_gtalk_jingleinfo_relay(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *relay_item; + proto_tree *relay_tree; + + attr_info attrs_info[] = { + {"token", -1, FALSE, FALSE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "server", xmpp_gtalk_jingleinfo_relay_serv, ONE} + }; + + element_t *token; + + relay_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "RELAY"); + relay_tree = proto_item_add_subtree(relay_item, ett_xmpp_gtalk_jingleinfo_relay); + + if((token = steal_element_by_name(element, "token"))!=NULL) + { + attr_t *fake_token = ep_init_attr_t(token->data?token->data->value:"", token->offset, token->length); + g_hash_table_insert(element->attrs, "token", fake_token); + } + + display_attrs(relay_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(relay_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_gtalk_jingleinfo_relay_serv(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *serv_item; + proto_tree *serv_tree; + + attr_info attrs_info[] = { + {"host", -1, TRUE, TRUE, NULL, NULL}, + {"udp", -1, FALSE, TRUE, NULL, NULL}, + {"tcp", -1, FALSE, TRUE, NULL, NULL}, + {"tcpssl", -1, FALSE, TRUE, NULL, NULL} + }; + + serv_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "SERVER"); + serv_tree = proto_item_add_subtree(serv_item, ett_xmpp_gtalk_jingleinfo_relay_serv); + + display_attrs(serv_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(serv_tree, element, pinfo, tvb, NULL, 0); +} + +void +xmpp_gtalk_usersetting(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *sett_item; + proto_tree *sett_tree; + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + guint i; + + sett_item = proto_tree_add_item(tree, hf_xmpp_gtalk_setting, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + sett_tree = proto_item_add_subtree(sett_item, ett_xmpp_gtalk_setting); + + display_attrs(sett_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + for(i = 0; i < g_list_length(element->elements); i++) + { + GList *elem_l = g_list_nth(element->elements,i); + element_t *elem = elem_l?elem_l->data:NULL; + + if(elem) + { + attr_t *val = get_attr(elem,"value"); + proto_tree_add_text(sett_tree, tvb, elem->offset, elem->length, "%s [%s]",elem->name,val?val->value:""); + } + } +} + +void +xmpp_gtalk_nosave_query(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) { + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "item", xmpp_gtalk_nosave_item, MANY}, + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(google:nosave) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, + ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(query_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_gtalk_nosave_item(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *item_item; + proto_tree *item_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL,NULL}, + {"jid", -1, TRUE, TRUE, NULL, NULL}, + {"source", -1, FALSE, TRUE, NULL, NULL}, + {"value", -1, TRUE, TRUE, NULL, NULL} + }; + + item_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "ITEM"); + item_tree = proto_item_add_subtree(item_item, ett_xmpp_query_item); + + display_attrs(item_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(item_tree, element, pinfo, tvb, NULL, 0); +} + +void +xmpp_gtalk_nosave_x(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *x_item; + proto_tree *x_tree; + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"value", -1, FALSE, TRUE, NULL, NULL} + }; + + x_item = proto_tree_add_item(tree, hf_xmpp_gtalk_nosave_x, tvb, element->offset, element->length, + ENC_BIG_ENDIAN); + x_tree = proto_item_add_subtree(x_item, ett_xmpp_gtalk_nosave_x); + + display_attrs(x_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(x_tree, element, pinfo, tvb, NULL, 0); +} + +void +xmpp_gtalk_mail_query(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"newer-than-time", -1, FALSE, TRUE, NULL, NULL}, + {"newer-than-tid", -1, FALSE, TRUE, NULL, NULL}, + {"q", -1, FALSE, TRUE, NULL, NULL} + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(google:mail:notify) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, + ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(query_tree, element, pinfo, tvb, NULL, 0); +} + +void +xmpp_gtalk_mail_mailbox(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *mail_item; + proto_tree *mail_tree; + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL}, + {"result-time", -1, FALSE, TRUE, NULL, NULL}, + {"total-matched", -1, FALSE, TRUE, NULL, NULL}, + {"total-estimate", -1, FALSE, TRUE, NULL, NULL}, + {"url", -1, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME,"mail-thread-info", xmpp_gtalk_mail_mail_info, MANY} + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "MAILBOX "); + + mail_item = proto_tree_add_item(tree, hf_xmpp_gtalk_mail_mailbox, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + mail_tree = proto_item_add_subtree(mail_item, ett_xmpp_gtalk_mail_mailbox); + + display_attrs(mail_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(mail_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_gtalk_mail_mail_info(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *mail_info_item; + proto_tree *mail_info_tree; + + attr_info attrs_info [] = { + {"tid", -1, FALSE, FALSE, NULL, NULL}, + {"participation", -1, FALSE, FALSE, NULL, NULL}, + {"messages", -1, FALSE, TRUE, NULL, NULL}, + {"date", -1, FALSE, TRUE, NULL, NULL}, + {"url", -1, FALSE, FALSE, NULL, NULL}, + {"labels", -1, FALSE, FALSE, NULL, NULL}, + {"subject", -1, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "senders", xmpp_gtalk_mail_senders, ONE}, + {NAME, "snippet", xmpp_gtalk_mail_snippet, ONE}/*or MANY?*/ + }; + + element_t *labels, *subject; + + mail_info_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "MAIL-THREAD-INFO"); + mail_info_tree = proto_item_add_subtree(mail_info_item,ett_xmpp_gtalk_mail_mail_info); + + if((labels = steal_element_by_name(element,"labels"))!=NULL) + { + attr_t *fake_labels = ep_init_attr_t(labels->data?labels->data->value:"",labels->offset, labels->length); + g_hash_table_insert(element->attrs, "labels", fake_labels); + } + if((subject = steal_element_by_name(element,"subject"))!=NULL) + { + attr_t *fake_subject = ep_init_attr_t(subject->data?subject->data->value:"",subject->offset, subject->length); + g_hash_table_insert(element->attrs, "subject", fake_subject); + } + + display_attrs(mail_info_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(mail_info_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + + +static void +xmpp_gtalk_mail_senders(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *senders_item; + proto_tree *senders_tree; + + elem_info elems_info [] = { + {NAME, "sender", xmpp_gtalk_mail_sender, MANY} + }; + + senders_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "SENDERS"); + senders_tree = proto_item_add_subtree(senders_item, ett_xmpp_gtalk_mail_senders); + + display_attrs(senders_tree, element, pinfo, tvb, NULL, 0); + display_elems(senders_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_gtalk_mail_sender(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *sender_item; + proto_tree *sender_tree; + + attr_info attrs_info [] = { + {"name", -1, FALSE, TRUE, NULL, NULL}, + {"address", -1, FALSE, TRUE, NULL, NULL}, + {"originator", -1, FALSE, TRUE, NULL, NULL}, + {"unread", -1, FALSE, TRUE, NULL, NULL} + }; + + sender_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "SENDER"); + sender_tree = proto_item_add_subtree(sender_item, ett_xmpp_gtalk_mail_sender); + + display_attrs(sender_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(sender_tree, element, pinfo, tvb, NULL, 0); +} + +static void +xmpp_gtalk_mail_snippet(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_tree_add_text(tree, tvb, element->offset, element->length, "SNIPPET: %s",element->data?element->data->value:""); + xmpp_unknown(tree, tvb, pinfo, element); +} + +void +xmpp_gtalk_mail_new_mail(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + col_append_fstr(pinfo->cinfo, COL_INFO, "NEW-MAIL "); + proto_tree_add_item(tree, hf_xmpp_gtalk_mail_new_mail, tvb, element->offset, element->length, + ENC_BIG_ENDIAN); + xmpp_unknown(tree, tvb, pinfo, element); +} + + +void +xmpp_gtalk_status_query(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"version", -1, FALSE, TRUE, NULL, NULL}, + {"status-max", -1, FALSE, FALSE, NULL, NULL}, + {"status-list-max", -1, FALSE, FALSE, NULL, NULL}, + {"status-list-contents-max", -1, FALSE, FALSE, NULL, NULL}, + {"status-min-ver", -1, FALSE, TRUE, NULL, NULL}, + {"show", -1, FALSE, TRUE, NULL, NULL}, + {"status", -1, FALSE, TRUE, NULL, NULL}, + {"invisible", -1, FALSE, TRUE, NULL, NULL}, + }; + + elem_info elems_info [] = { + {NAME, "status-list", xmpp_gtalk_status_status_list, MANY} + }; + + element_t *status, *show, *invisible; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(google:shared-status) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, + ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + if((status = steal_element_by_name(element,"status"))!=NULL) + { + attr_t *fake_status = ep_init_attr_t(status->data?status->data->value:"",status->offset, status->length); + g_hash_table_insert(element->attrs, "status", fake_status); + } + + if((show = steal_element_by_name(element,"show"))!=NULL) + { + attr_t *fake_show = ep_init_attr_t(show->data?show->data->value:"",show->offset, show->length); + g_hash_table_insert(element->attrs, "show", fake_show); + } + + if((invisible = steal_element_by_name(element,"invisible"))!=NULL) + { + attr_t *value = get_attr(invisible, "value"); + attr_t *fake_invisible = ep_init_attr_t(value?value->value:"",invisible->offset, invisible->length); + g_hash_table_insert(element->attrs, "invisible", fake_invisible); + } + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(query_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_gtalk_status_status_list(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *list_item; + proto_tree *list_tree; + + attr_info attrs_info [] = { + {"show", -1, TRUE, TRUE, NULL, NULL} + }; + + element_t *status; + + list_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "STATUS LIST"); + list_tree = proto_item_add_subtree(list_item, ett_xmpp_gtalk_status_status_list); + + while((status = steal_element_by_name(element, "status"))!=NULL) + { + proto_tree_add_text(list_tree, tvb, status->offset, status->length, "STATUS: %s",status->data?status->data->value:""); + } + + display_attrs(list_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(list_tree, element, pinfo, tvb, NULL, 0); +} + +/*http://www.google.com/transport/p2p*/ +void +xmpp_gtalk_transport_p2p(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *trans_item; + proto_tree *trans_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "candidate", xmpp_gtalk_transport_p2p_cand, MANY} + }; + + trans_item = proto_tree_add_item(tree, hf_xmpp_gtalk_transport_p2p, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + trans_tree = proto_item_add_subtree(trans_item, ett_xmpp_gtalk_transport_p2p); + + display_attrs(trans_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + display_elems(trans_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_gtalk_transport_p2p_cand(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) { + proto_item *cand_item; + proto_tree *cand_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"name", -1, FALSE, TRUE, NULL, NULL}, + {"generation", -1, FALSE, FALSE, NULL, NULL}, + {"network", -1, FALSE, FALSE, NULL, NULL}, + {"component", -1, FALSE, FALSE, NULL, NULL}, + {"type", -1, FALSE, FALSE, NULL, NULL}, + {"protocol", -1, FALSE, TRUE, NULL, NULL}, + {"preference", -1, FALSE, FALSE, NULL, NULL}, + {"password", -1, FALSE, FALSE, NULL, NULL}, + {"username", -1, FALSE, FALSE, NULL, NULL}, + {"port", -1, FALSE, TRUE, NULL, NULL}, + {"address", -1, FALSE, TRUE, NULL, NULL} + }; + + cand_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "CANDIDATE"); + cand_tree = proto_item_add_subtree(cand_item, ett_xmpp_gtalk_transport_p2p_cand); + + display_attrs(cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(cand_tree, element, pinfo, tvb, NULL, 0); + +} +/* +* Editor modelines - http://www.wireshark.org/tools/modelines.html +* +* Local variables: +* c-basic-offset: 4 +* tab-width: 8 +* indent-tabs-mode: nil +* End: +* +* ex: set shiftwidth=4 tabstop=8 expandtab: +* :indentSize=4:tabSize=8:noTabs=true: +*/ diff --git a/epan/dissectors/packet-xmpp-gtalk.h b/epan/dissectors/packet-xmpp-gtalk.h new file mode 100644 index 0000000000..f699feb23f --- /dev/null +++ b/epan/dissectors/packet-xmpp-gtalk.h @@ -0,0 +1,40 @@ +/* xmpp-gtalk.h + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef XMPP_GTALK_H +#define XMPP_GTALK_H + +extern void xmpp_gtalk_session(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_gtalk_jingleinfo_query(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_gtalk_usersetting(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_gtalk_nosave_query(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_gtalk_nosave_x(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_gtalk_mail_query(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_gtalk_mail_mailbox(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_gtalk_mail_new_mail(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_gtalk_status_query(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_gtalk_transport_p2p(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +#endif /* XMPP_GTALK_H */ + diff --git a/epan/dissectors/packet-xmpp-jingle.c b/epan/dissectors/packet-xmpp-jingle.c new file mode 100644 index 0000000000..d0c79997b4 --- /dev/null +++ b/epan/dissectors/packet-xmpp-jingle.c @@ -0,0 +1,952 @@ +/* xmpp-jingle.c + * Wireshark's XMPP dissector. + * + * urn:xmpp:jingle:1 + * urn:xmpp:jingle:apps:rtp:1 + * urn:xmpp:jingle:apps:rtp:errors:1 + * urn:xmpp:jingle:apps:rtp:info:1 + * urn:xmpp:jingle:apps:rtp:rtp-hdrext:0 + * urn:xmpp:jingle:apps:rtp:izrtp:1 + * + * urn:xmpp:jingle:transports:ice-udp:1 + * urn:xmpp:jingle:transports:raw-udp:1 + * urn:xmpp:jingle:transports:s5b:1 + * urn:xmpp:jingle:transports:ibb:1 + * + * http://jabber.org/protocol/jinglenodes + * http://jabber.org/protocol/jinglenodes#channel + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <glib.h> +#include <stdio.h> + +#include <epan/proto.h> +#include <epan/packet.h> +#include <epan/packet_info.h> +#include <epan/epan.h> +#include <epan/expert.h> +#include <epan/dissectors/packet-xml.h> + +#include <packet-xmpp.h> +#include <packet-xmpp-utils.h> +#include <packet-xmpp-jingle.h> +#include <packet-xmpp-conference.h> +#include <packet-xmpp-gtalk.h> +#include <packet-xmpp-other.h> + +void xmpp_jingle(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +static void xmpp_jingle_content(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_content_description_rtp(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_cont_desc_rtp_payload(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_cont_desc_rtp_payload_param(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element); +static void xmpp_jingle_cont_desc_rtp_enc(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element); +static void xmpp_jingle_cont_desc_rtp_enc_zrtp_hash(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element); +static void xmpp_jingle_cont_desc_rtp_enc_crypto(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element); +static void xmpp_jingle_cont_desc_rtp_bandwidth(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element); +static void xmpp_jingle_cont_desc_rtp_hdrext(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element); +static void xmpp_jingle_cont_trans_ice(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_jingle_cont_trans_ice_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_cont_trans_ice_remote_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_reason(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_rtp_info(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jinglenodes_relay_stun_tracker(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_jingle_cont_trans_raw(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_jingle_cont_trans_raw_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_cont_trans_s5b(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_jingle_cont_trans_s5b_candidate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_jingle_cont_trans_s5b_activated(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_jingle_cont_trans_s5b_cand_used(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_jingle_cont_trans_s5b_cand_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_jingle_cont_trans_s5b_proxy_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_jingle_cont_trans_ibb(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +static void xmpp_jingle_file_transfer_desc(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_file_transfer_offer(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_file_transfer_file(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_file_transfer_request(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_file_transfer_received(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_file_transfer_abort(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_jingle_file_transfer_checksum(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); + +/*XEP-0166: Jingle urn:xmpp:jingle:1*/ +void +xmpp_jingle(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *jingle_item; + proto_tree *jingle_tree; + + const gchar *rtp_info_msgs[] = {"active", "hold", "mute", "ringing", "unhold", "unmute"}; + + const gchar *action_enums[] = {"content-accept","content-add", "content-modify", + "content-modify", "content-remove", "description-info", "security-info", + "session-accept", "session-info", "session-initiate", "session-terminate", + "transport-accept", "transport-info", "transport-reject", "transport-replace" + }; + + array_t *action_array = ep_init_array_t(action_enums,array_length(action_enums)); + array_t *rtp_info_array = ep_init_array_t(rtp_info_msgs, array_length(rtp_info_msgs)); + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"action", hf_xmpp_jingle_action, TRUE, TRUE, val_enum_list, action_array}, + {"sid", hf_xmpp_jingle_sid, TRUE, FALSE, NULL, NULL}, + {"initiator", hf_xmpp_jingle_initiator, FALSE, FALSE, NULL, NULL}, + {"responder", hf_xmpp_jingle_responder, FALSE, FALSE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "content", xmpp_jingle_content, MANY}, + {NAME, "reason", xmpp_jingle_reason, MANY}, + {NAMES, rtp_info_array, xmpp_jingle_rtp_info, ONE}, + {NAME, "conference-info", xmpp_conferece_info_advert, ONE} + }; + + attr_t *action = get_attr(element,"action"); + col_append_fstr(pinfo->cinfo, COL_INFO, "JINGLE(%s) ", action?action->value:""); + + + jingle_item = proto_tree_add_item(tree, hf_xmpp_jingle, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + jingle_tree = proto_item_add_subtree(jingle_item, ett_xmpp_jingle); + + display_attrs(jingle_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + display_elems(jingle_item, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_content(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *content_item; + proto_tree *content_tree; + + const gchar *creator_enums[] = {"initiator","responder"}; + array_t *creator_enums_array = ep_init_array_t(creator_enums,array_length(creator_enums)); + + attr_info attrs_info[] = { + {"creator", hf_xmpp_jingle_content_creator, TRUE, FALSE, val_enum_list, creator_enums_array}, + {"name", hf_xmpp_jingle_content_name, TRUE, TRUE, NULL, NULL}, + {"disposition", hf_xmpp_jingle_content_disposition, FALSE, FALSE, NULL, NULL}, + {"senders", hf_xmpp_jingle_content_senders, FALSE, FALSE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME_AND_ATTR, name_attr_struct("description", "xmlns", "urn:xmpp:jingle:apps:rtp:1"), xmpp_jingle_content_description_rtp, MANY}, + {NAME_AND_ATTR, name_attr_struct("description", "xmlns", "urn:xmpp:jingle:apps:file-transfer:3"), xmpp_jingle_file_transfer_desc, MANY}, + {NAME_AND_ATTR, name_attr_struct("transport", "xmlns", "urn:xmpp:jingle:transports:ice-udp:1"), xmpp_jingle_cont_trans_ice, MANY}, + {NAME_AND_ATTR, name_attr_struct("transport", "xmlns", "urn:xmpp:jingle:transports:raw-udp:1"), xmpp_jingle_cont_trans_raw, MANY}, + {NAME_AND_ATTR, name_attr_struct("transport", "xmlns", "urn:xmpp:jingle:transports:s5b:1"), xmpp_jingle_cont_trans_s5b, MANY}, + {NAME_AND_ATTR, name_attr_struct("transport", "xmlns", "urn:xmpp:jingle:transports:ibb:1"), xmpp_jingle_cont_trans_ibb, MANY}, + {NAME_AND_ATTR, name_attr_struct("transport", "xmlns", "http://www.google.com/transport/p2p"), xmpp_gtalk_transport_p2p, MANY}, + {NAME_AND_ATTR, name_attr_struct("received", "xmlns", "urn:xmpp:jingle:apps:file-transfer:3"), xmpp_jingle_file_transfer_received, MANY}, + {NAME_AND_ATTR, name_attr_struct("abort", "xmlns", "urn:xmpp:jingle:apps:file-transfer:3"), xmpp_jingle_file_transfer_abort, MANY}, + {NAME_AND_ATTR, name_attr_struct("checksum", "xmlns", "urn:xmpp:jingle:apps:file-transfer:3"), xmpp_jingle_file_transfer_checksum, MANY}, + {NAME_AND_ATTR, name_attr_struct("inputevt", "xmlns","http://jitsi.org/protocol/inputevt"), xmpp_jitsi_inputevt, ONE}, + }; + + content_item = proto_tree_add_item(tree, hf_xmpp_jingle_content, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + content_tree = proto_item_add_subtree(content_item, ett_xmpp_jingle_content); + + display_attrs(content_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + display_elems(content_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_reason(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *reason_item; + proto_tree *reason_tree; + + attr_info attrs_info[] = { + {"condition", hf_xmpp_jingle_reason_condition, TRUE, TRUE, NULL, NULL}, + {"sid", -1, FALSE, TRUE, NULL, NULL}, + {"rtp-error", -1, FALSE, TRUE, NULL, NULL}, + {"text", hf_xmpp_jingle_reason_text, FALSE, FALSE, NULL, NULL} + }; + + element_t *condition; /*1?*/ + element_t *text; /*0-1*/ + element_t *rtp_error; + + const gchar *reason_names[] = { "success", "busy", "failed-application", "cancel", "connectivity-error", + "decline", "expired", "failed-transport", "general-error", "gone", "incompatible-parameters", + "media-error", "security-error", "timeout", "unsupported-applications", "unsupported-transports"}; + + const gchar *rtp_error_names[] = {"crypto-required", "invalid-crypto"}; + + reason_item = proto_tree_add_item(tree, hf_xmpp_jingle_reason, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + reason_tree = proto_item_add_subtree(reason_item, ett_xmpp_jingle_reason); + + + /*Looks for reason description. "alternative-session" may contain "sid" element + Elements are changed into attribute*/ + if((condition = steal_element_by_names(element, reason_names, array_length(reason_names)))!=NULL) + { + attr_t *fake_cond = ep_init_attr_t(condition->name, condition->offset, condition->length); + g_hash_table_insert(element->attrs, "condition", fake_cond); + + } else if((condition = steal_element_by_name(element, "alternative-session"))!=NULL) + { + attr_t *fake_cond,*fake_alter_sid; + element_t *sid; + + fake_cond = ep_init_attr_t(condition->name, condition->offset, condition->length); + g_hash_table_insert(element->attrs, "condition", fake_cond); + + + if((sid = steal_element_by_name(condition, "sid"))!=NULL) + { + fake_alter_sid = ep_init_attr_t(sid->name, sid->offset, sid->length); + g_hash_table_insert(element->attrs, "sid", fake_alter_sid); + } + } + + if((rtp_error = steal_element_by_names(element, rtp_error_names, array_length(rtp_error_names)))!=NULL) + { + attr_t *fake_rtp_error = ep_init_attr_t(rtp_error->name, rtp_error->offset, rtp_error->length); + g_hash_table_insert(element->attrs, "rtp-error", fake_rtp_error); + } + + if((text = steal_element_by_name(element, "text"))!=NULL) + { + attr_t *fake_text = ep_init_attr_t(text->data?text->data->value:"", text->offset, text->length); + g_hash_table_insert(element->attrs, "text", fake_text); + } + + display_attrs(reason_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(reason_tree, tvb, pinfo, element); +} + +/*XEP-0167: Jingle RTP Sessions urn:xmpp:jingle:apps:rtp:1*/ +static void +xmpp_jingle_content_description_rtp(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *desc_item; + proto_tree *desc_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"media", hf_xmpp_jingle_content_description_media, TRUE, TRUE, NULL, NULL}, + {"ssrc", hf_xmpp_jingle_content_description_ssrc , FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info[] = { + {NAME, "payload-type", xmpp_jingle_cont_desc_rtp_payload, MANY}, + {NAME, "bandwidth", xmpp_jingle_cont_desc_rtp_bandwidth, ONE}, + {NAME, "encryption", xmpp_jingle_cont_desc_rtp_enc, ONE}, + {NAME, "rtp-hdrext", xmpp_jingle_cont_desc_rtp_hdrext, MANY}, + {NAME, "zrtp-hash", xmpp_jingle_cont_desc_rtp_enc_zrtp_hash, MANY}/*IMHO it shouldn't appear in description*/ + + }; + + desc_item = proto_tree_add_item(tree, hf_xmpp_jingle_content_description, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + desc_tree = proto_item_add_subtree(desc_item, ett_xmpp_jingle_content_description); + + display_attrs(desc_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + display_elems(desc_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_cont_desc_rtp_payload(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *payload_item; + proto_tree *payload_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"id", hf_xmpp_jingle_cont_desc_payload_id, TRUE, TRUE, NULL, NULL}, + {"channels", hf_xmpp_jingle_cont_desc_payload_channels, FALSE, FALSE, NULL, NULL}, + {"clockrate", hf_xmpp_jingle_cont_desc_payload_clockrate, FALSE, FALSE, NULL, NULL}, + {"maxptime", hf_xmpp_jingle_cont_desc_payload_maxptime, FALSE, FALSE, NULL, NULL}, + {"name", hf_xmpp_jingle_cont_desc_payload_name, FALSE, TRUE, NULL, NULL}, + {"ptime", hf_xmpp_jingle_cont_desc_payload_ptime, FALSE, FALSE, NULL, NULL} + }; + + elem_info elems_info [] = + { + {NAME, "parameter", xmpp_jingle_cont_desc_rtp_payload_param, MANY} + }; + + payload_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_payload, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + payload_tree = proto_item_add_subtree(payload_item, ett_xmpp_jingle_cont_desc_payload); + + display_attrs(payload_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + display_elems(payload_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_cont_desc_rtp_payload_param(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element) +{ + proto_item *param_item; + proto_tree *param_tree; + + proto_item *parent_item; + attr_t *name, *value; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"name", hf_xmpp_jingle_cont_desc_payload_param_name, TRUE, TRUE, NULL, NULL}, + {"value", hf_xmpp_jingle_cont_desc_payload_param_value, TRUE, TRUE, NULL, NULL} + }; + + name = get_attr(element, "name"); + value = get_attr(element, "value"); + + if(name && value) + { + gchar *parent_item_label; + + parent_item = proto_tree_get_parent(tree); + + parent_item_label = proto_item_get_text(parent_item); + + if(parent_item_label) + { + parent_item_label[strlen(parent_item_label)-1]= '\0'; + proto_item_set_text(parent_item, "%s param(\"%s\")=%s]", parent_item_label ,name->value, value->value); + } + } + + param_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_payload_param, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + param_tree = proto_item_add_subtree(param_item, ett_xmpp_jingle_cont_desc_payload_param); + + display_attrs(param_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(param_tree, tvb, pinfo, element); + +} + +static void +xmpp_jingle_cont_desc_rtp_enc(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element) +{ + proto_item *enc_item; + proto_tree *enc_tree; + + elem_info elems_info [] = { + {NAME, "zrtp-hash", xmpp_jingle_cont_desc_rtp_enc_zrtp_hash, MANY}, + {NAME, "crypto", xmpp_jingle_cont_desc_rtp_enc_crypto, MANY} + }; + + enc_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_enc, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + enc_tree = proto_item_add_subtree(enc_item, ett_xmpp_jingle_cont_desc_enc); + + display_attrs(enc_tree, element, pinfo, tvb, NULL, 0); + display_elems(enc_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +/*urn:xmpp:jingle:apps:rtp:zrtp:1*/ +static void +xmpp_jingle_cont_desc_rtp_enc_zrtp_hash(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element) +{ + proto_item *zrtp_hash_item; + proto_tree *zrtp_hash_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"version", -1, TRUE, TRUE,NULL,NULL}, + {"hash", -1, TRUE, FALSE, NULL, NULL} + }; + + zrtp_hash_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_enc_zrtp_hash, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + zrtp_hash_tree = proto_item_add_subtree(zrtp_hash_item, ett_xmpp_jingle_cont_desc_enc_zrtp_hash); + + if(element->data) + { + attr_t *fake_hash = ep_init_attr_t(element->data->value, element->offset, element->length); + g_hash_table_insert(element->attrs, "hash", fake_hash); + } + + display_attrs(zrtp_hash_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(zrtp_hash_tree, tvb, pinfo, element); +} + +static void +xmpp_jingle_cont_desc_rtp_enc_crypto(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element) +{ + proto_item *crypto_item; + proto_tree *crypto_tree; + + attr_info attrs_info[] = { + {"crypto-suite", -1, TRUE, TRUE, NULL, NULL}, + {"key-params", -1, TRUE, FALSE,NULL,NULL}, + {"session-params", -1, FALSE, TRUE, NULL, NULL}, + {"tag", -1, TRUE, FALSE, NULL, NULL} + }; + + crypto_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_enc_crypto, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + crypto_tree = proto_item_add_subtree(crypto_item, ett_xmpp_jingle_cont_desc_enc_crypto); + + + display_attrs(crypto_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(crypto_tree, tvb, pinfo, element); +} + +static void +xmpp_jingle_cont_desc_rtp_bandwidth(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element) +{ + proto_item *bandwidth_item; + proto_tree *bandwidth_tree; + + attr_info attrs_info[] = { + {"type", -1, TRUE, TRUE, NULL, NULL}, + {"value", -1, TRUE, TRUE, NULL, NULL} + }; + + bandwidth_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_bandwidth, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + bandwidth_tree = proto_item_add_subtree(bandwidth_item, ett_xmpp_jingle_cont_desc_bandwidth); + + if(element->data) + { + attr_t *fake_value = ep_init_attr_t(element->data->value, element->offset, element->length); + g_hash_table_insert(element->attrs, "value", fake_value); + } + + display_attrs(bandwidth_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + xmpp_unknown(bandwidth_tree, tvb, pinfo, element); +} + +/*urn:xmpp:jingle:apps:rtp:rtp-hdrext:0*/ +static void +xmpp_jingle_cont_desc_rtp_hdrext(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element) +{ + proto_item *rtp_hdr_item; + proto_tree *rtp_hdr_tree; + + const gchar *senders[] = {"both", "initiator", "responder"}; + array_t *senders_enums = ep_init_array_t(senders, 3); + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"id", -1, TRUE, FALSE, NULL, NULL}, + {"uri", -1, TRUE, TRUE, NULL, NULL}, + {"senders", -1, FALSE, TRUE, val_enum_list, senders_enums}, + {"parameter", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t *parameter; + + rtp_hdr_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_rtp_hdr, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + rtp_hdr_tree = proto_item_add_subtree(rtp_hdr_item, ett_xmpp_jingle_cont_desc_rtp_hdr); + + if((parameter = steal_element_by_name(element, "parameter"))!=NULL) + { + attr_t *name = get_attr(element, "name"); + attr_t *fake_attr = ep_init_attr_t(name?name->value:"", parameter->offset, parameter->length); + g_hash_table_insert(element->attrs, "parameter", fake_attr); + } + + display_attrs(rtp_hdr_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(rtp_hdr_tree, tvb, pinfo, element); +} + +/*urn:xmpp:jingle:apps:rtp:info:1*/ +static void +xmpp_jingle_rtp_info(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *rtp_info_item; + proto_tree *rtp_info_tree; + + const gchar *creator[] = {"initiator","responder"}; + array_t *creator_enums = ep_init_array_t(creator, array_length(creator)); + + attr_info mute_attrs_info[] = { + {"creator", -1, TRUE, TRUE, val_enum_list, creator_enums}, + {"name", -1, TRUE, TRUE, NULL, NULL} + }; + + rtp_info_item = proto_tree_add_string(tree, hf_xmpp_jingle_rtp_info, tvb, element->offset, element->length, element->name); + rtp_info_tree = proto_item_add_subtree(rtp_info_item, ett_xmpp_jingle_rtp_info); + + if(strcmp("mute", element->name) == 0 || strcmp("unmute", element->name) == 0) + display_attrs(rtp_info_tree, element, pinfo, tvb, mute_attrs_info, array_length(mute_attrs_info)); + + xmpp_unknown(rtp_info_tree, tvb, pinfo, element); +} + +/*XEP-0176: Jingle ICE-UDP Transport Method urn:xmpp:jingle:transports:ice-udp:1*/ +static void +xmpp_jingle_cont_trans_ice(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *trans_item; + proto_tree *trans_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL}, + {"pwd", hf_xmpp_jingle_cont_trans_pwd, FALSE, FALSE, NULL, NULL}, + {"ufrag", hf_xmpp_jingle_cont_trans_ufrag, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "candidate", xmpp_jingle_cont_trans_ice_candidate, MANY}, + {NAME, "remote-candidate", xmpp_jingle_cont_trans_ice_remote_candidate, ONE} + }; + + trans_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + trans_tree = proto_item_add_subtree(trans_item, ett_xmpp_jingle_cont_trans); + + display_attrs(trans_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + display_elems(trans_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_cont_trans_ice_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *cand_item; + proto_tree *cand_tree; + + const gchar *type_enums[] = {"host", "prflx", "relay", "srflx"}; + array_t *type_enums_array = ep_init_array_t(type_enums,array_length(type_enums)); + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"component", -1, TRUE, FALSE, NULL, NULL}, + {"foundation", -1, TRUE, FALSE, NULL, NULL}, + {"generation", -1, TRUE, FALSE, NULL, NULL}, + {"id", -1, FALSE, FALSE, NULL, NULL}, /*in schemas id is marked as required, but in jitsi logs it doesn't appear*/ + {"ip", -1, TRUE, TRUE, NULL, NULL}, + {"network", -1, TRUE, FALSE, NULL, NULL}, + {"port", -1, TRUE, FALSE, NULL, NULL}, + {"priority", -1, TRUE, TRUE, NULL, NULL}, + {"protocol", -1, TRUE, TRUE, NULL, NULL}, + {"rel-addr", -1, FALSE, FALSE, NULL, NULL}, + {"rel-port", -1, FALSE, FALSE, NULL, NULL}, + {"type", -1, TRUE, TRUE, val_enum_list, type_enums_array} + }; + + cand_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_cand, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + cand_tree = proto_item_add_subtree(cand_item, ett_xmpp_jingle_cont_trans_cand); + + display_attrs(cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(cand_tree, tvb, pinfo, element); +} + +static void +xmpp_jingle_cont_trans_ice_remote_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *remote_cand_item; + proto_tree *remote_cand_tree; + + attr_info attrs_info[] = { + {"component", -1, TRUE, FALSE, NULL, NULL}, + {"ip", -1, TRUE, FALSE, NULL, NULL}, + {"port", -1, TRUE, FALSE, NULL, NULL} + }; + + remote_cand_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_rem_cand, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + remote_cand_tree = proto_item_add_subtree(remote_cand_item, ett_xmpp_jingle_cont_trans_rem_cand); + + display_attrs(remote_cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(remote_cand_tree, tvb, pinfo, element); +} + +/*XEP-0177: Jingle Raw UDP Transport Method urn:xmpp:jingle:transports:raw-udp:1*/ +static void +xmpp_jingle_cont_trans_raw(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *trans_item; + proto_tree *trans_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info [] = { + {NAME, "candidate", xmpp_jingle_cont_trans_raw_candidate, MANY} + }; + + trans_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + trans_tree = proto_item_add_subtree(trans_item, ett_xmpp_jingle_cont_trans); + + display_attrs(trans_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(trans_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_cont_trans_raw_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *cand_item; + proto_tree *cand_tree; + + const gchar *type_enums[] = {"host", "prflx", "relay", "srflx"}; + array_t *type_enums_array = ep_init_array_t(type_enums,array_length(type_enums)); + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"component", -1, TRUE, FALSE, NULL, NULL}, + {"generation", -1, TRUE, FALSE, NULL, NULL}, + {"id", -1, TRUE, FALSE, NULL, NULL}, + {"ip", -1, TRUE, TRUE, NULL, NULL}, + {"port", -1, TRUE, TRUE, NULL, NULL}, + {"type", -1, TRUE, TRUE, val_enum_list, type_enums_array} + }; + + cand_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_cand, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + cand_tree = proto_item_add_subtree(cand_item, ett_xmpp_jingle_cont_trans_cand); + + display_attrs(cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(cand_tree, element, pinfo, tvb, NULL, 0); +} + +/*XEP-0260: Jingle SOCKS5 Bytestreams Transport Method urn:xmpp:jingle:transports:s5b:1*/ +static void +xmpp_jingle_cont_trans_s5b(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *trans_item; + proto_tree *trans_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL}, + {"mode", -1, FALSE, TRUE, NULL, NULL}, + {"sid", -1, FALSE, TRUE, NULL, NULL}, + }; + + elem_info elems_info [] = { + {NAME, "candidate", xmpp_jingle_cont_trans_s5b_candidate, MANY}, + {NAME, "activated", xmpp_jingle_cont_trans_s5b_activated, ONE}, + {NAME, "candidate-used", xmpp_jingle_cont_trans_s5b_cand_used, ONE}, + {NAME, "candidate-error", xmpp_jingle_cont_trans_s5b_cand_error, ONE}, + {NAME, "proxy-error", xmpp_jingle_cont_trans_s5b_proxy_error, ONE}, + }; + + trans_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + trans_tree = proto_item_add_subtree(trans_item, ett_xmpp_jingle_cont_trans); + + display_attrs(trans_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(trans_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_cont_trans_s5b_candidate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *cand_item; + proto_tree *cand_tree; + + const gchar * type_enums[] = {"assisted", "direct", "proxy", "tunnel"}; + array_t *type_enums_array = ep_init_array_t(type_enums, array_length(type_enums)); + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"cid", -1, TRUE, TRUE, NULL, NULL}, + {"jid", -1, TRUE, TRUE, NULL, NULL}, + {"port", -1, FALSE, TRUE, NULL, NULL}, + {"priority", -1, TRUE, TRUE, NULL, NULL}, + {"type", -1, TRUE, TRUE, val_enum_list, type_enums_array} + }; + + cand_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_cand, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + cand_tree = proto_item_add_subtree(cand_item, ett_xmpp_jingle_cont_trans_cand); + + display_attrs(cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(cand_tree, element, pinfo, tvb, NULL, 0); +} + +static void +xmpp_jingle_cont_trans_s5b_activated(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *activated_item; + attr_t *cid = get_attr(element, "cid"); + + activated_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_activated, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + proto_item_append_text(activated_item, " [cid=\"%s\"]",cid?cid->value:""); + + xmpp_unknown(tree, tvb, pinfo, element); +} + +static void +xmpp_jingle_cont_trans_s5b_cand_used(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *cand_used_item; + attr_t *cid = get_attr(element, "cid"); + + cand_used_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_candidate_used, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + proto_item_append_text(cand_used_item, " [cid=\"%s\"]",cid?cid->value:""); + + xmpp_unknown(tree, tvb, pinfo, element); +} + +static void +xmpp_jingle_cont_trans_s5b_cand_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_candidate_error, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + xmpp_unknown(tree, tvb, pinfo, element); +} + +static void +xmpp_jingle_cont_trans_s5b_proxy_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_proxy_error, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + xmpp_unknown(tree, tvb, pinfo, element); +} + +/*XEP-0261: Jingle In-Band Bytestreams Transport Method urn:xmpp:jingle:transports:ibb:1*/ +static void +xmpp_jingle_cont_trans_ibb(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) { + proto_item *trans_item; + proto_tree *trans_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL}, + {"block-size", -1, TRUE, TRUE, NULL, NULL}, + {"sid", -1, TRUE, TRUE, NULL, NULL}, + {"stanza", -1, FALSE, TRUE, NULL, NULL} + }; + + trans_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + trans_tree = proto_item_add_subtree(trans_item, ett_xmpp_jingle_cont_trans); + + display_attrs(trans_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(trans_tree, element, pinfo, tvb, NULL, 0); +} + +/*XEP-0234: Jingle File Transfer urn:xmpp:jingle:apps:file-transfer:3*/ +static void +xmpp_jingle_file_transfer_desc(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *desc_item; + proto_tree *desc_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + elem_info elems_info[] = { + {NAME, "offer", xmpp_jingle_file_transfer_offer, ONE}, + {NAME, "request", xmpp_jingle_file_transfer_request, ONE} + }; + + desc_item = proto_tree_add_item(tree, hf_xmpp_jingle_content_description, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + desc_tree = proto_item_add_subtree(desc_item, ett_xmpp_jingle_content_description); + + display_attrs(desc_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(desc_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_file_transfer_offer(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *offer_item; + proto_tree *offer_tree; + + elem_info elems_info[] = { + {NAME, "file", xmpp_jingle_file_transfer_file, MANY}, + }; + + offer_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_offer, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + offer_tree = proto_item_add_subtree(offer_item, ett_xmpp_jingle_file_transfer_offer); + + display_attrs(offer_tree, element, pinfo, tvb, NULL, 0); + display_elems(offer_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_file_transfer_request(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *request_item; + proto_tree *request_tree; + + elem_info elems_info[] = { + {NAME, "file", xmpp_jingle_file_transfer_file, MANY}, + }; + + request_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_request, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + request_tree = proto_item_add_subtree(request_item, ett_xmpp_jingle_file_transfer_request); + + display_attrs(request_tree, element, pinfo, tvb, NULL, 0); + display_elems(request_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_file_transfer_received(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *received_item; + proto_tree *received_tree; + + elem_info elems_info[] = { + {NAME, "file", xmpp_jingle_file_transfer_file, MANY}, + }; + + received_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_received, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + received_tree = proto_item_add_subtree(received_item, ett_xmpp_jingle_file_transfer_received); + + display_attrs(received_tree, element, pinfo, tvb, NULL, 0); + display_elems(received_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_file_transfer_abort(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *abort_item; + proto_tree *abort_tree; + + elem_info elems_info[] = { + {NAME, "file", xmpp_jingle_file_transfer_file, MANY}, + }; + + abort_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_abort, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + abort_tree = proto_item_add_subtree(abort_item, ett_xmpp_jingle_file_transfer_abort); + + display_attrs(abort_tree, element, pinfo, tvb, NULL, 0); + display_elems(abort_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_file_transfer_checksum(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *checksum_item; + proto_tree *checksum_tree; + + elem_info elems_info[] = { + {NAME, "file", xmpp_jingle_file_transfer_file, MANY}, + }; + + checksum_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_checksum, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + checksum_tree = proto_item_add_subtree(checksum_item, ett_xmpp_jingle_file_transfer_checksum); + + display_attrs(checksum_tree, element, pinfo, tvb, NULL, 0); + display_elems(checksum_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jingle_file_transfer_file(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *file_item; + proto_tree *file_tree; + + attr_info attrs_info[] = { + {"name", -1, FALSE, TRUE, NULL, NULL}, + {"size", -1, FALSE, TRUE, NULL, NULL}, + {"date", -1, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info[] = { + {NAME, "hashes", xmpp_hashes, ONE} + }; + + file_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "FILE"); + file_tree = proto_item_add_subtree(file_item, ett_xmpp_jingle_file_transfer_file); + + change_elem_to_attrib("name", "name", element, transform_func_cdata); + change_elem_to_attrib("size", "size", element, transform_func_cdata); + change_elem_to_attrib("date", "date", element, transform_func_cdata); + + display_attrs(file_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(file_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +/*XEP-0278: Jingle Relay Nodes http://jabber.org/protocol/jinglenodes*/ +void +xmpp_jinglenodes_services(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *services_item; + proto_tree *services_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + elem_info elems_info[] = { + {NAME, "relay", xmpp_jinglenodes_relay_stun_tracker, ONE}, + {NAME, "tracker", xmpp_jinglenodes_relay_stun_tracker, ONE}, + {NAME, "stun", xmpp_jinglenodes_relay_stun_tracker, ONE}, + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "SERVICES "); + + services_item = proto_tree_add_item(tree, hf_xmpp_services, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + services_tree = proto_item_add_subtree(services_item, ett_xmpp_services); + + display_attrs(services_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(services_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jinglenodes_relay_stun_tracker(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *relay_item; + proto_tree *relay_tree; + + attr_info attrs_info[] = { + {"address", -1, TRUE, TRUE, NULL, NULL}, + {"port", -1, FALSE, TRUE, NULL, NULL}, + {"policy", -1, TRUE, TRUE, NULL, NULL}, + {"protocol", -1, TRUE, TRUE, NULL, NULL}, + }; + + relay_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "%s", element->name); + relay_tree = proto_item_add_subtree(relay_item, ett_xmpp_services_relay); + + display_attrs(relay_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(relay_tree, element, pinfo, tvb, NULL, 0); +} + +void +xmpp_jinglenodes_channel(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *channel_item; + proto_tree *channel_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"id", -1, FALSE, FALSE, NULL, NULL}, + {"host", -1, FALSE, TRUE, NULL, NULL}, + {"localport", -1, FALSE, TRUE, NULL, NULL}, + {"remoteport", -1, FALSE, TRUE, NULL, NULL}, + {"protocol", -1, TRUE, TRUE, NULL, NULL}, + {"maxkbps", -1, FALSE, FALSE, NULL, NULL}, + {"expire", -1, FALSE, FALSE, NULL, NULL}, + }; + + channel_item = proto_tree_add_item(tree, hf_xmpp_channel, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + channel_tree = proto_item_add_subtree(channel_item, ett_xmpp_channel); + + display_attrs(channel_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(channel_tree, element, pinfo, tvb, NULL, 0); +} +/* +* Editor modelines - http://www.wireshark.org/tools/modelines.html +* +* Local variables: +* c-basic-offset: 4 +* tab-width: 8 +* indent-tabs-mode: nil +* End: +* +* ex: set shiftwidth=4 tabstop=8 expandtab: +* :indentSize=4:tabSize=8:noTabs=true: +*/ diff --git a/epan/dissectors/packet-xmpp-jingle.h b/epan/dissectors/packet-xmpp-jingle.h new file mode 100644 index 0000000000..e2ef77b806 --- /dev/null +++ b/epan/dissectors/packet-xmpp-jingle.h @@ -0,0 +1,34 @@ +/* xmpp-jingle.h + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef XMPP_JINGLE_H +#define XMPP_JINGLE_H + +extern void xmpp_jingle(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_jinglenodes_services(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_jinglenodes_channel(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +#endif /* XMPP_JINGLE_H */ + diff --git a/epan/dissectors/packet-xmpp-other.c b/epan/dissectors/packet-xmpp-other.c new file mode 100644 index 0000000000..9e1a24d012 --- /dev/null +++ b/epan/dissectors/packet-xmpp-other.c @@ -0,0 +1,1357 @@ +/* xmpp-other.c + * Wireshark's XMPP dissector. + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include<stdio.h> +#include<string.h> +#include <glib.h> + +#include <epan/packet.h> +#include <epan/proto.h> +#include <epan/tvbuff.h> +#include <epan/emem.h> +#include <epan/conversation.h> +#include <epan/strutil.h> +#include <epan/expert.h> + +#include <epan/dissectors/packet-xml.h> + +#include <packet-xmpp-utils.h> +#include <packet-xmpp.h> +#include <packet-xmpp-jingle.h> +#include <packet-xmpp-other.h> + +static void xmpp_disco_items_item(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element); + +static void xmpp_roster_item(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element); + +static void xmpp_disco_info_identity(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element); +static void xmpp_disco_info_feature(proto_tree *tree, tvbuff_t *tvb, element_t *element); + +static void xmpp_bytestreams_streamhost(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_bytestreams_streamhost_used(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_bytestreams_activate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_bytestreams_udpsuccess(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +static void xmpp_si_file(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_si_file_range(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); + +static void xmpp_x_data_field(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_x_data_field_option(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_x_data_field_value(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +static void xmpp_x_data_instr(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); + +static void xmpp_muc_history(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +static void xmpp_muc_user_item(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_muc_user_status(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +static void xmpp_muc_user_invite(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +static void xmpp_hashes_hash(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +static void xmpp_jitsi_inputevt_rmt_ctrl(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +void +xmpp_iq_bind(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *bind_item; + proto_tree *bind_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"resource", hf_xmpp_iq_bind_resource, FALSE, TRUE, NULL, NULL}, + {"jid", hf_xmpp_iq_bind_jid, FALSE, TRUE, NULL, NULL} + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "BIND "); + + bind_item = proto_tree_add_item(tree, hf_xmpp_iq_bind, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + bind_tree = proto_item_add_subtree(bind_item, ett_xmpp_iq_bind); + + change_elem_to_attrib("resource", "resource", element, transform_func_cdata); + change_elem_to_attrib("jid", "jid", element, transform_func_cdata); + + display_attrs(bind_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(bind_tree, tvb, pinfo, element); +} + +void +xmpp_session(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *session_item; + proto_tree *session_tree; + + attr_info attrs_info [] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + session_item = proto_tree_add_item(tree, hf_xmpp_iq_session, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + session_tree = proto_item_add_subtree(session_item, ett_xmpp_iq_session); + + col_append_fstr(pinfo->cinfo, COL_INFO, "SESSION "); + + display_attrs(session_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(session_tree, element, pinfo, tvb, NULL, 0); +} + +void +xmpp_vcard(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *vcard_item; + proto_tree *vcard_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"value", -1, FALSE, FALSE, NULL, NULL} + }; + + element_t *cdata; + + col_append_fstr(pinfo->cinfo, COL_INFO, "VCARD "); + + vcard_item = proto_tree_add_item(tree, hf_xmpp_vcard, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + vcard_tree = proto_item_add_subtree(vcard_item, ett_xmpp_vcard); + + cdata = get_first_element(element); + + if(cdata) + { + attr_t *fake_cdata; + fake_cdata = ep_init_attr_t(element_to_string(tvb, cdata), cdata->offset, cdata->length); + g_hash_table_insert(element->attrs,"value", fake_cdata); + + } + display_attrs(vcard_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + +} + +void +xmpp_vcard_x_update(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *x_item; + proto_tree *x_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"photo", -1, FALSE, FALSE, NULL, NULL} + }; + + element_t *photo; + + x_item = proto_tree_add_item(tree, hf_xmpp_vcard_x_update, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + x_tree = proto_item_add_subtree(x_item, ett_xmpp_vcard_x_update); + + if((photo = steal_element_by_name(element, "photo"))!=NULL) + { + attr_t *fake_photo = ep_init_attr_t(photo->data?photo->data->value:"", photo->offset, photo->length); + g_hash_table_insert(element->attrs, "photo", fake_photo); + } + + display_attrs(x_tree, element,pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(x_tree, tvb, pinfo, element); +} + +void +xmpp_disco_items_query(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"node", hf_xmpp_query_node, FALSE, TRUE, NULL, NULL} + }; + + element_t *item; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(disco#items) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + while((item = steal_element_by_name(element, "item")) != NULL) + { + xmpp_disco_items_item(query_tree, tvb, pinfo, item); + } + + xmpp_unknown(query_tree, tvb, pinfo, element); +} + +static void +xmpp_disco_items_item(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element) +{ + proto_item *item_item; + proto_tree *item_tree; + + attr_info attrs_info[] = { + {"jid", hf_xmpp_query_item_jid, TRUE, TRUE, NULL, NULL}, + {"name", hf_xmpp_query_item_name, FALSE, TRUE, NULL, NULL}, + {"node", hf_xmpp_query_item_node, FALSE, TRUE, NULL, NULL} + }; + + item_item = proto_tree_add_item(tree, hf_xmpp_query_item, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + item_tree = proto_item_add_subtree(item_item, ett_xmpp_query_item); + + display_attrs(item_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(item_tree, tvb, pinfo, element); +} + +void +xmpp_roster_query(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"ver", -1, FALSE, TRUE, NULL, NULL}, + }; + + elem_info elems_info[] = { + {NAME, "item", xmpp_roster_item, MANY}, + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(jabber:iq:roster) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(query_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_roster_item(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element) +{ + proto_item *item_item; + proto_tree *item_tree; + + const gchar *ask_enums[] = {"subscribe"}; + const gchar *subscription_enums[] = {"both","from","none","remove","to"}; + + array_t *ask_enums_array = ep_init_array_t(ask_enums,array_length(ask_enums)); + array_t *subscription_array = ep_init_array_t(subscription_enums,array_length(subscription_enums)); + + attr_info attrs_info[] = { + {"jid", hf_xmpp_query_item_jid, TRUE, TRUE, NULL, NULL}, + {"name", hf_xmpp_query_item_name, FALSE, TRUE, NULL, NULL}, + {"ask", hf_xmpp_query_item_ask, FALSE, TRUE, val_enum_list, ask_enums_array}, + {"approved", hf_xmpp_query_item_approved, FALSE, TRUE, NULL, NULL}, + {"subscription", hf_xmpp_query_item_subscription, FALSE, TRUE, val_enum_list, subscription_array}, + }; + + element_t *group; + + item_item = proto_tree_add_item(tree, hf_xmpp_query_item, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + item_tree = proto_item_add_subtree(item_item, ett_xmpp_query_item); + + display_attrs(item_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + while((group = steal_element_by_name(element,"group"))!=NULL) + { + proto_tree_add_string(item_tree, hf_xmpp_query_item_group, tvb, group->offset, group->length, elem_cdata(group)); + } + + xmpp_unknown(item_tree, tvb, pinfo, element); +} + +void +xmpp_disco_info_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"node", hf_xmpp_query_node, FALSE, TRUE, NULL, NULL} + }; + + element_t *identity, *feature, *x_data; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(disco#info) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + + while((identity = steal_element_by_name(element, "identity")) != NULL) + { + xmpp_disco_info_identity(query_tree, tvb, pinfo, identity); + } + + while((feature = steal_element_by_name(element, "feature")) != NULL) + { + xmpp_disco_info_feature(query_tree, tvb, feature); + } + + if((x_data = steal_element_by_name_and_attr(element, "x", "xmlns", "jabber:x:data")) != NULL) + { + xmpp_x_data(query_tree, tvb, pinfo, x_data); + } + + xmpp_unknown(query_tree, tvb, pinfo, element); +} + +static void +xmpp_disco_info_identity(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element) +{ + proto_item *identity_item; + proto_tree *identity_tree; + + attr_info attrs_info[] = { + {"category", hf_xmpp_query_identity_category, TRUE, TRUE, NULL, NULL}, + {"name", hf_xmpp_query_identity_name, FALSE, TRUE, NULL, NULL}, + {"type", hf_xmpp_query_identity_type, TRUE, TRUE, NULL, NULL} + }; + + identity_item = proto_tree_add_item(tree, hf_xmpp_query_identity, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + identity_tree = proto_item_add_subtree(identity_item, ett_xmpp_query_identity); + + display_attrs(identity_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(identity_tree, tvb, pinfo, element); + +} + +static void +xmpp_disco_info_feature(proto_tree *tree, tvbuff_t *tvb, element_t *element) +{ + + attr_t *var = get_attr(element, "var"); + + if(var) + { + proto_tree_add_string_format(tree, hf_xmpp_query_feature, tvb, var->offset, var->length, var->value, "FEATURE [%s]", var->value); + } +} + +void +xmpp_bytestreams_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *query_item; + proto_tree *query_tree; + + const gchar *mode_enums[] = {"tcp", "udp"}; + array_t *mode_array = ep_init_array_t(mode_enums, array_length(mode_enums)); + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"sid", -1, FALSE, TRUE, NULL, NULL}, + {"mode", -1, FALSE, TRUE, val_enum_list, mode_array}, + {"dstaddr", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t *streamhost, *streamhost_used, *activate, *udpsuccess; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(bytestreams) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + + while((streamhost = steal_element_by_name(element, "streamhost")) != NULL) + { + xmpp_bytestreams_streamhost(query_tree, tvb, pinfo, streamhost); + } + + if((streamhost_used = steal_element_by_name(element, "streamhost-used")) != NULL) + { + xmpp_bytestreams_streamhost_used(query_tree, tvb, pinfo, streamhost_used); + } + + if((activate = steal_element_by_name(element, "activate")) != NULL) + { + xmpp_bytestreams_activate(query_tree, tvb, pinfo, activate); + } + + if((udpsuccess = steal_element_by_name(element, "udpsuccess")) != NULL) + { + xmpp_bytestreams_udpsuccess(query_tree, tvb, pinfo, udpsuccess); + } + + xmpp_unknown(query_tree, tvb, pinfo, element); +} + +static void +xmpp_bytestreams_streamhost(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *sh_item; + proto_tree *sh_tree; + + attr_info attrs_info[] = { + {"jid", -1, TRUE, TRUE, NULL, NULL}, + {"host", -1, TRUE, TRUE, NULL, NULL}, + {"port", -1, FALSE, TRUE, NULL, NULL} + }; + + sh_item = proto_tree_add_item(tree, hf_xmpp_query_streamhost, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + sh_tree = proto_item_add_subtree(sh_item, ett_xmpp_query_streamhost); + + display_attrs(sh_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(sh_tree, tvb, pinfo, element); +} + +static void +xmpp_bytestreams_streamhost_used(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *shu_item; + proto_tree *shu_tree; + + attr_info attrs_info[] = { + {"jid", -1, TRUE, TRUE, NULL, NULL} + }; + + shu_item = proto_tree_add_item(tree, hf_xmpp_query_streamhost_used, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + shu_tree = proto_item_add_subtree(shu_item, ett_xmpp_query_streamhost_used); + + display_attrs(shu_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(shu_tree, tvb, pinfo, element); +} + +static void +xmpp_bytestreams_activate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_tree_add_string(tree, hf_xmpp_query_activate, tvb, element->offset, element->length, elem_cdata(element)); + xmpp_unknown(tree, tvb, pinfo, element); +} + +static void +xmpp_bytestreams_udpsuccess(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *udps_item; + proto_tree *udps_tree; + + attr_info attrs_info[] = { + {"dstaddr", -1, TRUE, TRUE, NULL, NULL} + }; + + udps_item = proto_tree_add_item(tree, hf_xmpp_query_udpsuccess, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + udps_tree =proto_item_add_subtree(udps_item, ett_xmpp_query_udpsuccess); + + display_attrs(udps_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(udps_tree, tvb, pinfo, element); +} + + + +/*SI File Transfer*/ +void +xmpp_si(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *si_item; + proto_tree *si_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"id", -1, FALSE, FALSE, NULL, NULL}, + {"mime-type", -1, FALSE, TRUE, NULL, NULL}, + {"profile", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t *file, *feature_neg; + + col_append_fstr(pinfo->cinfo, COL_INFO, "SI "); + + si_item = proto_tree_add_item(tree, hf_xmpp_si, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + si_tree = proto_item_add_subtree(si_item, ett_xmpp_si); + + display_attrs(si_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + while((file = steal_element_by_name(element, "file"))!=NULL) + { + xmpp_si_file(si_tree, tvb, pinfo, file); + } + + while((feature_neg = steal_element_by_name(element, "feature"))!=NULL) + { + xmpp_feature_neg(si_tree, tvb, pinfo, feature_neg); + } + + + + xmpp_unknown(si_tree, tvb, pinfo, element); +} + +static void +xmpp_si_file(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *file_item; + proto_tree *file_tree; + + attr_info attrs_info[] ={ + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"name", -1, TRUE, TRUE, NULL, NULL}, + {"size", -1, TRUE, TRUE, NULL, NULL}, + {"date", -1, FALSE, FALSE, NULL, NULL}, + {"hash", -1, FALSE, FALSE, NULL, NULL}, + {"desc", -1, FALSE, FALSE, NULL, NULL} + }; + + element_t *desc, *range; + + file_item = proto_tree_add_item(tree, hf_xmpp_si_file, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + file_tree = proto_item_add_subtree(file_item, ett_xmpp_si_file); + + if((desc = steal_element_by_name(element, "desc"))!=NULL) + { + attr_t *fake_desc = ep_init_attr_t(desc->data?desc->data->value:"", desc->offset, desc->length); + g_hash_table_insert(element->attrs, "desc", fake_desc); + } + + if((range = steal_element_by_name(element, "range"))!=NULL) + { + xmpp_si_file_range(file_tree, tvb, pinfo, range); + } + + display_attrs(file_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(file_tree, tvb, pinfo, element); +} + +static void +xmpp_si_file_range(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *range_item; + proto_tree *range_tree; + + attr_info attrs_info[] = { + {"offset", -1, FALSE, TRUE, NULL, NULL}, + {"length", -1, FALSE, TRUE, NULL, NULL} + }; + + range_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "RANGE: "); + range_tree = proto_item_add_subtree(range_item, ett_xmpp_si_file_range); + + display_attrs(range_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(range_tree, tvb, pinfo, element); + +} + +/*Feature Negotiation*/ +void +xmpp_feature_neg(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *feature_item; + proto_tree *feature_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + element_t *x_data; + + feature_item = proto_tree_add_item(tree, hf_xmpp_iq_feature_neg, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + feature_tree = proto_item_add_subtree(feature_item, ett_xmpp_iq_feature_neg); + + display_attrs(feature_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + while((x_data = steal_element_by_name_and_attr(element, "x", "xmlns", "jabber:x:data"))!=NULL) + { + xmpp_x_data(feature_tree, tvb, pinfo, x_data); + } + + xmpp_unknown(feature_tree, tvb, pinfo, element); +} + + +/*jabber:x:data*/ +void +xmpp_x_data(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *x_item; + proto_tree *x_tree; + + const gchar *type_enums[] = {"cancel", "form", "result", "submit"}; + array_t *type_array = ep_init_array_t(type_enums, array_length(type_enums)); + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"type", -1, TRUE, TRUE, val_enum_list, type_array}, + {"TITLE", -1, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info[] = { + {NAME, "instructions", xmpp_x_data_instr, MANY}, + {NAME, "field", xmpp_x_data_field, MANY}, + }; + /*TODO reported, item*/ + + x_item = proto_tree_add_item(tree, hf_xmpp_x_data, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + x_tree = proto_item_add_subtree(x_item, ett_xmpp_x_data); + + change_elem_to_attrib("title", "TITLE", element, transform_func_cdata); + + display_attrs(x_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(x_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_x_data_field(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *field_item; + proto_tree *field_tree; + + const gchar *type_enums[] = {"boolean", "fixed", "hidden", "jid-multi", + "jid-single", "list-multi", "list-single", "text-multi", "text-single", + "text-private" + }; + array_t *type_array = ep_init_array_t(type_enums, array_length(type_enums)); + + attr_info attrs_info[] = + { + {"label", -1, FALSE, TRUE, NULL, NULL}, + {"type", -1, FALSE, TRUE, val_enum_list, type_array}, + {"var", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t /**desc, *required,*/ *value, *option; + + field_item = proto_tree_add_item(tree, hf_xmpp_x_data_field, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + field_tree = proto_item_add_subtree(field_item, ett_xmpp_x_data_field); + + display_attrs(field_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + while((option = steal_element_by_name(element, "option"))!=NULL) + { + xmpp_x_data_field_option(field_tree, tvb, pinfo, option); + } + + while((value = steal_element_by_name(element, "value"))!=NULL) + { + xmpp_x_data_field_value(field_tree, tvb, pinfo, value); + } + + xmpp_unknown(field_item, tvb, pinfo, element); + +} + +static void +xmpp_x_data_field_option(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *option_item; + proto_tree *option_tree; + + attr_info attrs_info[] = { + {"label", -1, FALSE, TRUE, NULL, NULL}, + {"value", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t *value; + + option_item = proto_tree_add_item(tree, hf_xmpp_x_data_field_value, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + option_tree = proto_item_add_subtree(option_item, ett_xmpp_x_data_field_value); + + if((value = steal_element_by_name(element, "value"))!=NULL) + { + attr_t *fake_value = ep_init_attr_t(value->data?value->data->value:"",value->offset, value->length); + g_hash_table_insert(element->attrs, "value", fake_value); + } + + display_attrs(option_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(option_tree, tvb, pinfo, element); +} + +static void +xmpp_x_data_field_value(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element) +{ + proto_item *value_item; + proto_tree *value_tree; + + attr_info attrs_info[] = { + {"label", -1, FALSE, TRUE, NULL, NULL}, + {"value", -1, TRUE, TRUE, NULL, NULL} + }; + attr_t *fake_value; + + value_item = proto_tree_add_item(tree, hf_xmpp_x_data_field_value, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + value_tree = proto_item_add_subtree(value_item, ett_xmpp_x_data_field_value); + + + + fake_value = ep_init_attr_t(element->data?element->data->value:"",element->offset, element->length); + g_hash_table_insert(element->attrs, "value", fake_value); + + + display_attrs(value_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(value_tree, tvb, pinfo, element); +} + +static void +xmpp_x_data_instr(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo _U_, element_t* element) +{ + proto_tree_add_text(tree, tvb, element->offset, element->length, "INSTRUCTIONS: %s",elem_cdata(element)); +} + +/*In-Band Bytestreams*/ +void +xmpp_ibb_open(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *open_item; + proto_tree *open_tree; + + const gchar *stanza_enums[] = {"iq","message"}; + array_t *stanza_array = ep_init_array_t(stanza_enums, array_length(stanza_enums)); + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"sid", -1, TRUE, TRUE, NULL, NULL}, + {"block-size", -1, TRUE, TRUE, NULL, NULL}, + {"stanza", -1, FALSE, TRUE, val_enum_list, stanza_array} + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "IBB-OPEN "); + + open_item = proto_tree_add_item(tree, hf_xmpp_ibb_open, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + open_tree = proto_item_add_subtree(open_item, ett_xmpp_ibb_open); + + display_attrs(open_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + xmpp_unknown(open_tree, tvb, pinfo, element); +} + +void +xmpp_ibb_close(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *close_item; + proto_tree *close_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"sid", -1, TRUE, TRUE, NULL, NULL} + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "IBB-CLOSE "); + + close_item = proto_tree_add_item(tree, hf_xmpp_ibb_close, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + close_tree = proto_item_add_subtree(close_item, ett_xmpp_ibb_close); + + display_attrs(close_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + xmpp_unknown(close_tree, tvb, pinfo, element); +} + +void +xmpp_ibb_data(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *data_item; + proto_tree *data_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"sid", -1, TRUE, TRUE, NULL, NULL}, + {"seq", -1, TRUE, TRUE, NULL, NULL}, + {"value", -1, FALSE, FALSE, NULL, NULL} + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "IBB-DATA "); + + data_item = proto_tree_add_item(tree, hf_xmpp_ibb_data, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + data_tree = proto_item_add_subtree(data_item, ett_xmpp_ibb_data); + + if(element->data) + { + attr_t *fake_data = ep_init_attr_t(element->data->value, element->offset, element->length); + g_hash_table_insert(element->attrs, "value", fake_data); + } + + display_attrs(data_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + xmpp_unknown(data_tree, tvb, pinfo, element); +} + + +/*Delayed Delivery urn:xmpp:delay and jabber:x:delay*/ +void +xmpp_delay(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *delay_item; + proto_tree *delay_tree; + + attr_info attrs_info[]={ + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"from", -1, FALSE, TRUE, NULL, NULL}, + {"stamp", -1, TRUE, TRUE, NULL, NULL}, + {"value", -1, FALSE, TRUE, NULL, NULL} + }; + + delay_item = proto_tree_add_item(tree, hf_xmpp_delay, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + delay_tree = proto_item_add_subtree(delay_item, ett_xmpp_delay); + + if(element->data) + { + attr_t *fake_value = ep_init_attr_t(element->data->value, element->offset, element->length); + g_hash_table_insert(element->attrs, "value", fake_value); + } + + display_attrs(delay_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(delay_tree, tvb, pinfo, element); +} + +/*Entity Capabilities http://jabber.org/protocol/caps*/ +void +xmpp_presence_caps(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *caps_item; + proto_tree *caps_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"ext", -1, FALSE, FALSE, NULL, NULL}, + {"hash", -1, TRUE, TRUE, NULL, NULL}, + {"node", -1, TRUE, TRUE, NULL, NULL}, + {"ver", -1, TRUE, FALSE, NULL, NULL} + }; + + caps_item = proto_tree_add_item(tree, hf_xmpp_presence_caps, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + caps_tree = proto_item_add_subtree(caps_item, ett_xmpp_presence_caps); + + display_attrs(caps_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(caps_tree, tvb, pinfo, element); +} + +/*Message Events jabber:x:event*/ +void +xmpp_x_event(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *x_item; + proto_tree *x_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"condition", hf_xmpp_x_event_condition, TRUE, TRUE, NULL, NULL}, + {"id", -1, FALSE, TRUE, NULL, NULL} + }; + + const gchar *cond_names[] = {"offline", "delivered", "displayed", "composing"}; + + attr_t *fake_cond; + + element_t *cond, *id; + + gchar *cond_value = ep_strdup(""); + + x_item = proto_tree_add_item(tree, hf_xmpp_x_event, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + x_tree = proto_item_add_subtree(x_item, ett_xmpp_x_event); + + if((id = steal_element_by_name(element, "id"))!=NULL) + { + attr_t *fake_id = ep_init_attr_t(id->data?id->data->value:"", id->offset, id->length); + g_hash_table_insert(element->attrs, "id", fake_id); + } + + while((cond = steal_element_by_names(element, cond_names, array_length(cond_names))) != NULL) + { + if(strcmp(cond_value,"") != 0) + cond_value = ep_strdup_printf("%s/%s",cond_value, cond->name); + else + cond_value = ep_strdup(cond->name); + } + + fake_cond = ep_init_attr_t(cond_value, element->offset, element->length); + g_hash_table_insert(element->attrs, "condition", fake_cond); + + + display_attrs(x_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(x_tree, tvb, pinfo, element); +} + +/*Multi-User Chat http://jabber.org/protocol/muc*/ +void +xmpp_muc_x(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *x_item; + proto_tree *x_tree; + + attr_info attrs_info [] ={ + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"password", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t *pass, *hist; + + x_item = proto_tree_add_item(tree, hf_xmpp_muc_x, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + x_tree = proto_item_add_subtree(x_item, ett_xmpp_muc_x); + + if((pass = steal_element_by_name(element, "password"))!=NULL) + { + attr_t *fake_pass = ep_init_attr_t(pass->data?pass->data->value:"",pass->offset, pass->length); + g_hash_table_insert(element->attrs, "password", fake_pass); + } + + display_attrs(x_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + if((hist = steal_element_by_name(element, "history"))!=NULL) + { + xmpp_muc_history(x_tree, tvb, pinfo, hist); + } + + xmpp_unknown(x_tree, tvb, pinfo, element); +} + +static void +xmpp_muc_history(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *hist_item; + proto_tree *hist_tree; + + attr_info attrs_info[] = { + {"maxchars", -1, FALSE, TRUE, NULL, NULL}, + {"maxstanzas", -1, FALSE, TRUE, NULL, NULL}, + {"seconds", -1, FALSE, TRUE, NULL, NULL}, + {"since", -1, FALSE, TRUE, NULL, NULL} + }; + + hist_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "HISTORY: "); + hist_tree = proto_item_add_subtree(hist_item, ett_xmpp_muc_hist); + + display_attrs(hist_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(hist_tree, tvb, pinfo, element); +} + +/*Multi-User Chat http://jabber.org/protocol/muc#user*/ +void +xmpp_muc_user_x(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *x_item; + proto_tree *x_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL}, + {"password", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t *item, *status, *invite, *password; + /*TODO decline destroy*/ + + x_item = proto_tree_add_item(tree, hf_xmpp_muc_user_x, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + x_tree = proto_item_add_subtree(x_item, ett_xmpp_muc_user_x); + + if((password = steal_element_by_name(element, "password"))!=NULL) + { + attr_t *fake_pass = ep_init_attr_t(password->data?password->data->value:"",password->offset, password->length); + g_hash_table_insert(element->attrs, "password", fake_pass); + } + + display_attrs(x_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + while((item = steal_element_by_name(element, "item"))!=NULL) + { + xmpp_muc_user_item(x_tree, tvb, pinfo, item); + } + + while((status = steal_element_by_name(element, "status"))!=NULL) + { + xmpp_muc_user_status(x_tree, tvb, pinfo, status); + } + + while((invite = steal_element_by_name(element, "invite"))!=NULL) + { + xmpp_muc_user_invite(x_tree, tvb, pinfo, invite); + } + + xmpp_unknown(x_tree, tvb, pinfo, element); +} + +static void +xmpp_muc_user_item(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *item_item; + proto_tree *item_tree; + + const gchar *affiliation_enums[] = {"admin", "member", "none", "outcast", "owner"}; + array_t *affil_array = ep_init_array_t(affiliation_enums, array_length(affiliation_enums)); + + const gchar *role_enums[] = {"none", "moderator", "participant", "visitor"}; + array_t *role_array = ep_init_array_t(role_enums, array_length(role_enums)); + + attr_info attrs_info [] ={ + {"affiliation", -1, FALSE, TRUE, val_enum_list, affil_array}, + {"jid", -1, FALSE, TRUE, NULL, NULL}, + {"nick", -1, FALSE, TRUE, NULL, NULL}, + {"role", -1, FALSE, TRUE, val_enum_list, role_array}, + {"reason", -1, FALSE, TRUE, NULL, NULL}, + {"actor_jid", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t *reason, *actor; + /*TODO continue - it's not clear to me, in schema it's marked as empty, but in examples it has CDATA*/ + + item_item = proto_tree_add_item(tree, hf_xmpp_muc_user_item, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + item_tree = proto_item_add_subtree(item_item, ett_xmpp_muc_user_item); + + if((reason = steal_element_by_name(element, "reason"))!=NULL) + { + attr_t *fake_reason = ep_init_attr_t(reason->data?reason->data->value:"",reason->offset, reason->length); + g_hash_table_insert(element->attrs,"reason",fake_reason); + } + + if((actor = steal_element_by_name(element, "actor"))!=NULL) + { + attr_t *jid = get_attr(actor, "jid"); + attr_t *fake_actor_jid = ep_init_attr_t(jid?jid->value:"",actor->offset, actor->length); + g_hash_table_insert(element->attrs, "actor_jid", fake_actor_jid); + } + + display_attrs(item_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(item_tree, tvb, pinfo, element); +} + +static void +xmpp_muc_user_status(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + attr_t *code = get_attr(element, "code"); + proto_tree_add_text(tree, tvb, element->offset, element->length, "STATUS [code=\"%s\"]",code?code->value:""); + + xmpp_unknown(tree, tvb, pinfo, element); +} + +static void +xmpp_muc_user_invite(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *invite_item; + proto_tree *invite_tree; + + attr_info attrs_info[] = { + {"from", -1, FALSE, TRUE, NULL, NULL}, + {"to", -1, FALSE, TRUE, NULL, NULL}, + {"reason", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t *reason; + + invite_item = proto_tree_add_item(tree, hf_xmpp_muc_user_invite, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + invite_tree = proto_item_add_subtree(invite_item, ett_xmpp_muc_user_invite); + + if((reason = steal_element_by_name(element, "reason"))!=NULL) + { + attr_t *fake_reason = ep_init_attr_t(reason->data?reason->data->value:"",reason->offset, reason->length); + g_hash_table_insert(element->attrs, "reason", fake_reason); + } + + display_attrs(invite_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + xmpp_unknown(invite_tree, tvb, pinfo, element); +} + +/*Multi-User Chat http://jabber.org/protocol/muc#owner*/ +void +xmpp_muc_owner_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + element_t *x_data; + /*TODO destroy*/ + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(muc#owner) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + if((x_data = steal_element_by_name_and_attr(element, "x", "xmlns", "jabber:x:data"))!=NULL) + { + xmpp_x_data(query_tree, tvb, pinfo, x_data); + } + + xmpp_unknown(query_tree, tvb, pinfo, element); + +} + +/*Multi-User Chat http://jabber.org/protocol/muc#admin*/ +void +xmpp_muc_admin_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL} + }; + + element_t *item; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(muc#admin) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + + while((item = steal_element_by_name(element, "item"))!=NULL) + { + /*from muc#user, because it is the same except continue element*/ + xmpp_muc_user_item(query_tree, tvb, pinfo, item); + } + + xmpp_unknown(query_tree, tvb, pinfo, element); +} + +/*Last Activity jabber:iq:last*/ +void +xmpp_last_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"seconds", -1, FALSE, TRUE, NULL, NULL}, + {"value", -1, FALSE, TRUE, NULL, NULL} + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(jabber:iq:last) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + if(element->data) + { + attr_t *fake_data = ep_init_attr_t(element->data->value, element->data->offset, element->data->length); + g_hash_table_insert(element->attrs, "value", fake_data); + } + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(query_tree, element, pinfo, tvb, NULL, 0); +} + +/*XEP-0092: Software Version jabber:iq:version*/ +void +xmpp_version_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *query_item; + proto_tree *query_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"name", -1, FALSE, TRUE, NULL, NULL}, + {"version", -1, FALSE, TRUE, NULL, NULL}, + {"os", -1, FALSE, TRUE, NULL, NULL} + }; + + element_t *name, *version, *os; + + col_append_fstr(pinfo->cinfo, COL_INFO, "QUERY(jabber:iq:version) "); + + query_item = proto_tree_add_item(tree, hf_xmpp_query, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + query_tree = proto_item_add_subtree(query_item, ett_xmpp_query); + + if((name = steal_element_by_name(element,"name"))!=NULL) + { + attr_t *fake_name = ep_init_attr_t(name->data?name->data->value:"", name->offset, name->length); + g_hash_table_insert(element->attrs, "name", fake_name); + } + + if((version = steal_element_by_name(element,"version"))!=NULL) + { + attr_t *fake_version = ep_init_attr_t(version->data?version->data->value:"", version->offset, version->length); + g_hash_table_insert(element->attrs, "version", fake_version); + } + + if((os = steal_element_by_name(element,"os"))!=NULL) + { + attr_t *fake_os = ep_init_attr_t(os->data?os->data->value:"", os->offset, os->length); + g_hash_table_insert(element->attrs, "os", fake_os); + } + + display_attrs(query_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(query_tree, element, pinfo, tvb, NULL, 0); +} +/*XEP-0199: XMPP Ping*/ +void +xmpp_ping(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *ping_item; + proto_tree *ping_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + }; + + col_append_fstr(pinfo->cinfo, COL_INFO, "PING "); + + ping_item = proto_tree_add_item(tree, hf_xmpp_ping, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + ping_tree = proto_item_add_subtree(ping_item, ett_xmpp_ping); + + display_attrs(ping_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(ping_tree, element, pinfo, tvb, NULL, 0); +} + +/*XEP-0300: Use of Cryptographic Hash Functions in XMPP urn:xmpp:hashes:0*/ +void +xmpp_hashes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) { + proto_item *hashes_item; + proto_tree *hashes_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + }; + elem_info elems_info[] = { + {NAME, "hash", xmpp_hashes_hash, MANY} + }; + + hashes_item = proto_tree_add_item(tree, hf_xmpp_hashes, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + hashes_tree = proto_item_add_subtree(hashes_item, ett_xmpp_hashes); + + display_attrs(hashes_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(hashes_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_hashes_hash(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *hash_item; + proto_tree *hash_tree; + + attr_info attrs_info[] = { + {"algo", -1, TRUE, TRUE, NULL, NULL}, + {"value", -1, TRUE, TRUE, NULL, NULL} + }; + + attr_t *fake_cdata = ep_init_attr_t(elem_cdata(element), element->offset, element->length); + g_hash_table_insert(element->attrs, "value", fake_cdata); + + hash_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "HASH"); + hash_tree = proto_item_add_subtree(hash_item, ett_xmpp_hashes_hash); + + display_attrs(hash_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(hash_tree, element, pinfo, tvb, NULL, 0); +} + +/*http://jitsi.org/protocol/inputevt*/ +void +xmpp_jitsi_inputevt(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *inputevt_item; + proto_tree *inputevt_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}, + {"action", -1, FALSE, TRUE, NULL, NULL} + }; + + elem_info elems_info[] = { + {NAME, "remote-control", xmpp_jitsi_inputevt_rmt_ctrl, MANY} + }; + + inputevt_item = proto_tree_add_item(tree, hf_xmpp_jitsi_inputevt, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + inputevt_tree = proto_item_add_subtree(inputevt_item, ett_xmpp_jitsi_inputevt); + + display_attrs(inputevt_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(inputevt_tree, element, pinfo, tvb, elems_info, array_length(elems_info)); +} + +static void +xmpp_jitsi_inputevt_rmt_ctrl(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + proto_item *rmt_ctrl_item; + proto_tree *rmt_ctrl_tree; + + attr_info attrs_info[] = { + {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL}, + {"action", -1, TRUE, TRUE, NULL, NULL}, + {"x", -1, FALSE, TRUE, NULL, NULL}, + {"y", -1, FALSE, TRUE, NULL, NULL}, + {"btns", -1, FALSE, TRUE, NULL, NULL}, + {"keycode", -1, FALSE, TRUE, NULL, NULL}, + }; + + element_t *action; + const gchar *action_names[] = {"mouse-move","mouse-press", "mouse-release", "key-press", "key-release"}; + + if((action = steal_element_by_names(element, action_names, array_length(action_names)))!=NULL) + { + attr_t *fake_action = ep_init_attr_t(action->name, action->offset, action->length); + g_hash_table_insert(element->attrs,"action", fake_action); + + if(strcmp(action->name,"mouse-move") == 0) + { + attr_t *x = get_attr(action,"x"); + attr_t *y = get_attr(action,"y"); + + if(x) + g_hash_table_insert(element->attrs,"x",x); + if(y) + g_hash_table_insert(element->attrs,"y",y); + } else if(strcmp(action->name,"mouse-press") == 0 || strcmp(action->name,"mouse-release") == 0) + { + attr_t *btns = get_attr(action,"btns"); + + if(btns) + g_hash_table_insert(element->attrs,"btns",btns); + } else if(strcmp(action->name,"key-press") == 0 || strcmp(action->name,"key-release") == 0) + { + attr_t *keycode = get_attr(action,"keycode"); + + if(keycode) + g_hash_table_insert(element->attrs,"keycode",keycode); + } + + } + + rmt_ctrl_item = proto_tree_add_item(tree, hf_xmpp_jitsi_inputevt_rmt_ctrl, tvb, element->offset, element->length, ENC_BIG_ENDIAN); + rmt_ctrl_tree = proto_item_add_subtree(rmt_ctrl_item, ett_xmpp_jitsi_inputevt_rmt_ctrl); + + display_attrs(rmt_ctrl_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info)); + display_elems(rmt_ctrl_tree, element, pinfo, tvb, NULL, 0); +} +/* +* Editor modelines - http://www.wireshark.org/tools/modelines.html +* +* Local variables: +* c-basic-offset: 4 +* tab-width: 8 +* indent-tabs-mode: nil +* End: +* +* ex: set shiftwidth=4 tabstop=8 expandtab: +* :indentSize=4:tabSize=8:noTabs=true: +*/ diff --git a/epan/dissectors/packet-xmpp-other.h b/epan/dissectors/packet-xmpp-other.h new file mode 100644 index 0000000000..8b13d47e48 --- /dev/null +++ b/epan/dissectors/packet-xmpp-other.h @@ -0,0 +1,68 @@ +/* xmpp-others.h + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef XMPP_OTHER_H +#define XMPP_OTHER_H + +extern void xmpp_iq_bind(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_session(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_vcard(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_disco_items_query(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element); +extern void xmpp_roster_query(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, element_t *element); +extern void xmpp_disco_info_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_bytestreams_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_si(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); + +extern void xmpp_feature_neg(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); +extern void xmpp_x_data(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); + +extern void xmpp_ibb_open(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_ibb_close(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_ibb_data(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_delay(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_presence_caps(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_vcard_x_update(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); + +extern void xmpp_x_event(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_muc_x(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_muc_user_x(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_muc_owner_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_muc_admin_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_last_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_version_query(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_ping(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +extern void xmpp_hashes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_jitsi_inputevt(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); +#endif /* XMPP_OTHER_H */ + diff --git a/epan/dissectors/packet-xmpp-utils.c b/epan/dissectors/packet-xmpp-utils.c new file mode 100644 index 0000000000..e89af2df3b --- /dev/null +++ b/epan/dissectors/packet-xmpp-utils.c @@ -0,0 +1,1139 @@ +/* xmpp-utils.c + * Wireshark's XMPP dissector. + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include <glib.h> +#include <stdio.h> + +#include <epan/conversation.h> +#include <epan/proto.h> +#include <epan/packet_info.h> +#include <epan/epan.h> +#include <epan/expert.h> +#include <epan/tvbuff.h> +#include <epan/tvbparse.h> + +#include <epan/dissectors/packet-xml.h> + +#include <packet-xmpp.h> +#include <packet-xmpp-utils.h> + +#include <epan/strutil.h> + +void +xmpp_iq_reqresp_track(packet_info *pinfo, element_t *packet, xmpp_conv_info_t *xmpp_info) +{ + xmpp_transaction_t *xmpp_trans = NULL; + + attr_t *attr_id; + char *id; + + attr_id = get_attr(packet, "id"); + DISSECTOR_ASSERT(attr_id); + id = ep_strdup(attr_id->value); + + if (!pinfo->fd->flags.visited) { + xmpp_trans = se_tree_lookup_string(xmpp_info->req_resp, id, EMEM_TREE_STRING_NOCASE); + if (xmpp_trans) { + xmpp_trans->resp_frame = pinfo->fd->num; + + } else { + char *se_id = se_strdup(id); + + xmpp_trans = se_alloc(sizeof (xmpp_transaction_t)); + xmpp_trans->req_frame = pinfo->fd->num; + xmpp_trans->resp_frame = 0; + + se_tree_insert_string(xmpp_info->req_resp, se_id, (void *) xmpp_trans, EMEM_TREE_STRING_NOCASE); + + } + + } else { + se_tree_lookup_string(xmpp_info->req_resp, id, EMEM_TREE_STRING_NOCASE); + } +} + +void +xmpp_jingle_session_track(packet_info *pinfo, element_t *packet, xmpp_conv_info_t *xmpp_info) +{ + element_t *jingle_packet; + GList *jingle_packet_l; + + jingle_packet_l = find_element_by_name(packet,"jingle"); + jingle_packet = jingle_packet_l?jingle_packet_l->data:NULL; + + if (jingle_packet && !pinfo->fd->flags.visited) { + attr_t *attr_id; + attr_t *attr_sid; + + char *se_id; + char *se_sid; + + + attr_id = get_attr(packet, "id"); + DISSECTOR_ASSERT(attr_id); + + se_id = se_strdup(attr_id->value); + + attr_sid = get_attr(jingle_packet, "sid"); + DISSECTOR_ASSERT(attr_sid); + + se_sid = se_strdup(attr_sid->value); + + se_tree_insert_string(xmpp_info->jingle_sessions, se_id, (void*) se_sid, EMEM_TREE_STRING_NOCASE); + } +} + +void +xmpp_gtalk_session_track(packet_info *pinfo, element_t *packet, xmpp_conv_info_t *xmpp_info) +{ + element_t *gtalk_packet; + GList *gtalk_packet_l; + + gtalk_packet_l = find_element_by_name(packet,"session"); + gtalk_packet = gtalk_packet_l?gtalk_packet_l->data:NULL; + + + if (gtalk_packet && !pinfo->fd->flags.visited) { + attr_t *attr_id; + attr_t *attr_sid; + + char *se_id; + char *se_sid; + + attr_t *xmlns = get_attr(gtalk_packet, "xmlns"); + if(xmlns && strcmp(xmlns->value,"http://www.google.com/session") != 0) + return; + + + attr_id = get_attr(packet, "id"); + DISSECTOR_ASSERT(attr_id); + + se_id = se_strdup(attr_id->value); + + attr_sid = get_attr(gtalk_packet, "id"); + DISSECTOR_ASSERT(attr_sid); + se_sid = se_strdup(attr_sid->value); + + se_tree_insert_string(xmpp_info->gtalk_sessions, se_id, (void*) se_sid, EMEM_TREE_STRING_NOCASE); + } +} + +void +xmpp_ibb_session_track(packet_info *pinfo, element_t *packet, xmpp_conv_info_t *xmpp_info) +{ + element_t *ibb_packet = NULL; + GList *ibb_packet_l; + + if(strcmp(packet->name, "message") == 0) + { + ibb_packet_l = find_element_by_name(packet,"data"); + ibb_packet = ibb_packet_l?ibb_packet_l->data:NULL; + + } else if(strcmp(packet->name, "iq") == 0) + { + ibb_packet_l = find_element_by_name(packet,"open"); + + if(!ibb_packet_l) + ibb_packet_l = find_element_by_name(packet,"close"); + if(!ibb_packet_l) + ibb_packet_l = find_element_by_name(packet,"data"); + + ibb_packet = ibb_packet_l?ibb_packet_l->data:NULL; + } + + if (ibb_packet && !pinfo->fd->flags.visited) { + attr_t *attr_id; + attr_t *attr_sid; + + char *se_id; + char *se_sid; + + + attr_id = get_attr(packet, "id"); + attr_sid = get_attr(ibb_packet, "sid"); + if(attr_id && attr_sid) + { + se_id = se_strdup(attr_id->value); + se_sid = se_strdup(attr_sid->value); + se_tree_insert_string(xmpp_info->ibb_sessions, se_id, (void*) se_sid, EMEM_TREE_STRING_NOCASE); + } + } +} + +static void +xmpp_unknown_items(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element, guint level) +{ + GList *childs = element->elements; + + DISSECTOR_ASSERT( level < ETT_UNKNOWN_LEN ); + + xmpp_unknown_attrs(tree, tvb, pinfo, element, TRUE); + + if(element->data) + { + proto_tree_add_text(tree, tvb, element->data->offset, element->data->length, "CDATA: %s",element->data->value); + } + + while(childs) + { + element_t *child = childs->data; + proto_item *child_item = proto_tree_add_text(tree, tvb, child->offset, child->length, "%s", ep_string_upcase(child->name)); + proto_tree *child_tree = proto_item_add_subtree(child_item, ett_unknown[level]); + + if(child->default_ns_abbrev) + proto_item_append_text(child_item, "(%s)", child->default_ns_abbrev); + + xmpp_unknown_items(child_tree, tvb, pinfo, child, level +1); + + childs = childs->next; + } +} + +void +xmpp_unknown(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) +{ + GList *childs = element->elements; + + /*element has unrecognized elements*/ + while(childs) + { + element_t *child = childs->data; + if(!child->was_read) + { + proto_item *unknown_item; + proto_tree *unknown_tree; + +#ifdef XMPP_DEBUG + unknown_item = proto_tree_add_string_format(tree, + hf_xmpp_unknown, tvb, child->offset, child->length, child->name, + "%s", ep_string_upcase(child->name)); +#else + unknown_item = proto_tree_add_text(tree, tvb, child->offset, child->length, + "%s", ep_string_upcase(child->name)); +#endif + unknown_tree = proto_item_add_subtree(unknown_item, ett_unknown[0]); + + /*Add COL_INFO only if root element is IQ*/ + if(strcmp(element->name,"iq")==0) + col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", ep_string_upcase(child->name)); + + if(child->default_ns_abbrev) + proto_item_append_text(unknown_item,"(%s)",child->default_ns_abbrev); + + xmpp_unknown_items(unknown_tree, tvb, pinfo, child, 1); +#ifdef XMPP_DEBUG + proto_item_append_text(unknown_item, " [UNKNOWN]"); + + expert_add_info_format(pinfo, unknown_item, PI_UNDECODED, PI_NOTE,"Unknown element: %s", child->name); +#endif + } + childs = childs->next; + } +} + +void +xmpp_unknown_attrs(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, element_t *element, gboolean displ_short_list) +{ + proto_item *item = proto_tree_get_parent(tree); + + GList *keys = g_hash_table_get_keys(element->attrs); + GList *values = g_hash_table_get_values(element->attrs); + + GList *keys_head = keys, *values_head = values; + + gboolean short_list_started = FALSE; + + while(keys && values) + { + attr_t *attr = (attr_t*) values->data; + if (!attr->was_read) { + if (displ_short_list) { + if (!short_list_started) + proto_item_append_text(item, " ["); + else + proto_item_append_text(item, " "); + proto_item_append_text(item, "%s=\"%s\"", (gchar*) keys->data, attr->value); + + short_list_started = TRUE; + } + + /*If unknown element has xmlns attrib then header field hf_xmpp_xmlns is added to the tree. + In other case only text.*/ + if (strcmp(keys->data, "xmlns") == 0) + proto_tree_add_string(tree, hf_xmpp_xmlns, tvb, attr->offset, attr->length, attr->value); + else { + /*xmlns may looks like xmlns:abbrev="sth"*/ + gchar* xmlns_needle = epan_strcasestr(keys->data, "xmlns:"); + if (xmlns_needle && xmlns_needle == keys->data) { + proto_tree_add_string_format(tree, hf_xmpp_xmlns, tvb, attr->offset, attr->length, attr->value,"%s: %s", (gchar*)keys->data, attr->value); + } else { + +#ifdef XMPP_DEBUG + proto_item* unknown_attr_item; + unknown_attr_item = proto_tree_add_string_format(tree, + hf_xmpp_unknown_attr, tvb, attr->offset, attr->length, + attr->name, "%s: %s", attr->name, attr->value); + proto_item_append_text(unknown_attr_item, " [UNKNOWN ATTR]"); + expert_add_info_format(pinfo, unknown_attr_item, PI_UNDECODED, PI_NOTE, "Unknown attribute %s.", attr->name); +#else + proto_tree_add_text(tree, tvb, attr->offset, attr->length, + "%s: %s", attr->name, attr->value); +#endif + } + } + } + keys = keys->next; + values = values->next; + } + + if(short_list_started && displ_short_list) + proto_item_append_text(item, "]"); + + g_list_free(keys_head); + g_list_free(values_head); +} + +void +xmpp_cdata(proto_tree *tree, tvbuff_t *tvb, element_t *element, gint hf) +{ + if(element->data) +{ + if (hf == -1) { + proto_tree_add_text(tree, tvb, element->data->offset, element->data->length, "CDATA: %s", element->data->value); + } else { + proto_tree_add_string(tree, hf, tvb, element->data->offset, element->data->length, element->data->value); + } + } else + { + if (hf == -1) { + proto_tree_add_text(tree, tvb, 0, 0, "CDATA: (empty)"); + } else { + proto_tree_add_string(tree, hf, tvb, 0, 0, ""); + } + } +} + +/* displays element that looks like <element_name>element_value</element_name> + * ELEMENT_NAME: element_value as TEXT(proto_tree_add_text) int PROTO_TREE + */ +void +xmpp_simple_cdata_elem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, element_t *element) +{ + proto_tree_add_text(tree, tvb, element->offset, element->length, "%s: %s", ep_string_upcase(element->name), elem_cdata(element)); +} + +array_t* +ep_init_array_t(const gchar** array, gint len) +{ + array_t *result; + + result = ep_alloc(sizeof(array_t)); + result->data = (gpointer) array; + result->length = len; + + return result; +} + +attr_t* +ep_init_attr_t(gchar *value, gint offset, gint length) +{ + attr_t *result; + result = ep_alloc(sizeof(attr_t)); + result->value = value; + result->offset = offset; + result->length = length; + result->name = NULL; + + return result; +} + +gchar* +ep_string_upcase(const gchar* string) +{ + gint len = strlen(string); + gint i; + gchar* result = ep_alloc0(len+1); + for(i=0; i<len; i++) + { + result[i] = string[i]; + + if(string[i]>='a' && string[i]<='z') + result[i]-='a'-'A'; + + } + return result; +} + +gint +element_t_cmp(gconstpointer a, gconstpointer b) +{ + gint result = strcmp(((element_t*)a)->name,((element_t*)b)->name); + + if(result == 0 && ((element_t*)a)->was_read) + result = -1; + + return result; +} + +GList* +find_element_by_name(element_t *packet,const gchar *name) +{ + GList *found_elements; + element_t *search_element; + + /*create fake element only with name*/ + search_element = ep_alloc(sizeof(element_t)); + search_element->name = ep_strdup(name); + + found_elements = g_list_find_custom(packet->elements, search_element, element_t_cmp); + + if(found_elements) + return found_elements; + else + return NULL; +} + + +/* steal_* + * function searches element in packet and sets it as read. + * if element doesn't exist, NULL is returned. + * If element is set as read, it is invisible for these functions.*/ +element_t* +steal_element_by_name(element_t *packet,const gchar *name) +{ + GList *element_l; + element_t *element = NULL; + + element_l = find_element_by_name(packet, name); + + if(element_l) + { + element = element_l->data; + element->was_read = TRUE; + } + + return element; + +} + +element_t* +steal_element_by_names(element_t *packet, const gchar **names, gint names_len) +{ + gint i; + element_t *el = NULL; + + for(i = 0; i<names_len; i++) + { + if((el = steal_element_by_name(packet, names[i]))) + break; + } + + return el; +} + +element_t* +steal_element_by_attr(element_t *packet, const gchar *attr_name, const gchar *attr_value) +{ + GList *childs = packet->elements; + element_t *result = NULL; + + while (childs) { + element_t *child_elem = childs->data; + attr_t *attr = get_attr(child_elem, attr_name); + + if(attr) + attr->was_read = FALSE; + + if (!child_elem->was_read && attr && strcmp(attr->value, attr_value) == 0) { + + result = childs->data; + + result->was_read = TRUE; + + break; + } else + childs = childs->next; + } + + return result; +} + +element_t* +steal_element_by_name_and_attr(element_t *packet, const gchar *name, const gchar *attr_name, const gchar *attr_value) +{ + GList *childs = packet->elements; + element_t *result = NULL; + + while (childs) { + element_t *child_elem = childs->data; + attr_t *attr = get_attr(child_elem, attr_name); + + if(attr) + attr->was_read = FALSE; + + if (!child_elem->was_read && attr && strcmp(child_elem->name, name) == 0 && strcmp(attr->value, attr_value) == 0) { + + result = childs->data; + + result->was_read = TRUE; + + break; + } else + childs = childs->next; + } + return result; +} + +element_t* +get_first_element(element_t *packet) +{ + if(packet->elements && packet->elements->data) + return packet->elements->data; + else + return NULL; +} + +/* +Function converts xml_frame_t structure to element_t (simpler representation) +*/ +element_t* +xml_frame_to_element_t(xml_frame_t *xml_frame, element_t *parent, tvbuff_t *tvb) +{ + xml_frame_t *child; + element_t *node = ep_alloc0(sizeof(element_t)); + + tvbparse_wanted_t *want_ignore, *want_name, *want_scoped_name; + tvbparse_t* tt; + tvbparse_elem_t* elem; + + node->attrs = g_hash_table_new(g_str_hash, g_str_equal); + node->elements = NULL; + node->data = NULL; + node->was_read = FALSE; + node->default_ns_abbrev = NULL; + + node->name = ep_strdup(xml_frame->name_orig_case); + node->offset = 0; + node->length = 0; + + node->namespaces = g_hash_table_new(g_str_hash, g_str_equal); + if(parent) + { + copy_hash_table(parent->namespaces, node->namespaces); + } else + { + g_hash_table_insert(node->namespaces, "", "jabber:client"); + } + + if(xml_frame->item != NULL) + { + node->length = xml_frame->item->finfo->length; + } + + node->offset = xml_frame->start_offset; + + /*looking for element's names that looks like ns:tag_name*/ + want_ignore = tvbparse_chars(-1,1,0," \t\r\n</",NULL,NULL,NULL); + want_name = tvbparse_chars(-1,1,0,"abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",NULL,NULL,NULL); + want_scoped_name = tvbparse_set_seq(-1, NULL, NULL, NULL, want_name, tvbparse_char(-1,":",NULL,NULL,NULL), want_name, NULL); + + tt = tvbparse_init(tvb,node->offset,-1,NULL,want_ignore); + + if((elem = tvbparse_get(tt,want_scoped_name))!=NULL) + { + node->default_ns_abbrev = tvb_get_ephemeral_string(elem->sub->tvb, elem->sub->offset, elem->sub->len); + } + + child = xml_frame->first_child; + + while(child) + { + if(child->type != XML_FRAME_TAG) + { + if(child->type == XML_FRAME_ATTRIB) + { + gint l; + gchar *value = NULL; + gchar *xmlns_needle = NULL; + + attr_t *attr = ep_alloc(sizeof(attr_t)); + attr->length = 0; + attr->offset = 0; + attr->was_read = FALSE; + + if (child->value != NULL) { + l = tvb_reported_length(child->value); + value = ep_alloc0(l + 1); + tvb_memcpy(child->value, value, 0, l); + } + + if(child->item) + { + attr->length = child->item->finfo->length; + } + + attr->offset = child->start_offset; + attr->value = value; + attr->name = ep_strdup(child->name_orig_case); + + g_hash_table_insert(node->attrs,(gpointer)attr->name,(gpointer)attr); + + /*checking that attr->name looks like xmlns:ns*/ + xmlns_needle = epan_strcasestr(attr->name, "xmlns"); + + if(xmlns_needle == attr->name) + { + if(attr->name[5] == ':' && strlen(attr->name) > 6) + { + g_hash_table_insert(node->namespaces, (gpointer)ep_strdup(&attr->name[6]), (gpointer)ep_strdup(attr->value)); + } else if(attr->name[5] == '\0') + { + g_hash_table_insert(node->namespaces, "", (gpointer)ep_strdup(attr->value)); + } + } + + + } + else if( child->type == XML_FRAME_CDATA) + { + data_t *data = NULL; + gint l; + gchar* value = NULL; + + data = ep_alloc(sizeof(data_t)); + data->length = 0; + data->offset = 0; + + if (child->value != NULL) { + l = tvb_reported_length(child->value); + value = ep_alloc0(l + 1); + tvb_memcpy(child->value, value, 0, l); + } + + data->value = value; + + if(child->item) + { + data->length = child->item->finfo->length; + } + data->offset = child->start_offset; + node->data = data; + } + } else + { + node->elements = g_list_append(node->elements,(gpointer)xml_frame_to_element_t(child, node,tvb)); + } + + child = child->next_sibling; + } + return node; +} + +void +element_t_tree_free(element_t *root) +{ + GList *childs = root->elements; + + g_hash_table_destroy(root->attrs); + g_hash_table_destroy(root->namespaces); + + while(childs) + { + element_t *child = childs->data; + + element_t_tree_free(child); + childs = childs->next; + } + g_list_free(root->elements); +} + +/*Function recognize attribute names if they looks like xmlns:ns*/ +static gboolean +attr_find_pred(gpointer key, gpointer value _U_, gpointer user_data) +{ + gchar *attr_name = (gchar*) user_data; + + if( strcmp(attr_name, "xmlns") == 0 ) + { + gchar *first_occur = epan_strcasestr(key, "xmlns:"); + if(first_occur && first_occur == key) + return TRUE; + else + return FALSE; + } + return FALSE; +} + +/*Functions returns element's attibute by name and set as read*/ +attr_t* +get_attr(element_t *element, const gchar* attr_name) +{ + attr_t *result = g_hash_table_lookup(element->attrs, attr_name); + + if(!result) + { + result = g_hash_table_find(element->attrs, attr_find_pred, (gpointer)attr_name); + } + + if(result) + result->was_read = TRUE; + + return result; +} + +/*Functions returns element's attibute by name and namespace abbrev*/ +static attr_t* +get_attr_ext(element_t *element, const gchar* attr_name, const gchar* ns_abbrev) +{ + gchar* search_phrase; + attr_t *result; + + if(strcmp(ns_abbrev,"")==0) + search_phrase = ep_strdup(attr_name); + else if(strcmp(attr_name, "xmlns") == 0) + search_phrase = ep_strdup_printf("%s:%s",attr_name, ns_abbrev); + else + search_phrase = ep_strdup_printf("%s:%s", ns_abbrev, attr_name); + + result = g_hash_table_lookup(element->attrs, search_phrase); + + if(!result) + { + result = g_hash_table_find(element->attrs, attr_find_pred, (gpointer)attr_name); + } + + if(result) + result->was_read = TRUE; + + return result; +} + + + +gchar* +element_to_string(tvbuff_t *tvb, element_t *element) +{ + gchar *buff = NULL; + + if(tvb_offset_exists(tvb, element->offset+element->length-1)) + { + buff = tvb_get_ephemeral_string(tvb, element->offset, element->length); + } + return buff; +} + +gchar* +attr_to_string(tvbuff_t *tvb, attr_t *attr) +{ + gchar *buff = NULL; + + if(tvb_offset_exists(tvb, attr->offset + attr->length-1)) + { + buff = tvb_get_ephemeral_string(tvb, attr->offset, attr->length); + } + return buff; +} + +static void +children_foreach_hide_func(proto_node *node, gpointer data) +{ + int *i = data; + if((*i) == 0) + PROTO_ITEM_SET_HIDDEN(node); + (*i)++; +} + +static void +children_foreach_show_func(proto_node *node, gpointer data) +{ + int *i = data; + if((*i) == 0) + PROTO_ITEM_SET_VISIBLE(node); + (*i)++; +} + +void +proto_tree_hide_first_child(proto_tree *tree) +{ + int i = 0; + proto_tree_children_foreach(tree, children_foreach_hide_func, &i); +} + +void +proto_tree_show_first_child(proto_tree *tree) +{ + int i = 0; + proto_tree_children_foreach(tree, children_foreach_show_func, &i); +} + +gchar* +proto_item_get_text(proto_item *item) +{ + field_info *fi = NULL; + gchar *result; + + if(item == NULL) + return NULL; + + fi = PITEM_FINFO(item); + + if(fi==NULL) + return NULL; + + if (fi->rep == NULL) + return NULL; + + + result = ep_strdup(fi->rep->representation); + return result; +} + + +void +display_attrs(proto_tree *tree, element_t *element, packet_info *pinfo, tvbuff_t *tvb, attr_info *attrs, guint n) +{ + proto_item *item = proto_tree_get_parent(tree); + attr_t *attr; + guint i; + gboolean short_list_started = FALSE; + + if(element->default_ns_abbrev) + proto_item_append_text(item, "(%s)",element->default_ns_abbrev); + + proto_item_append_text(item," ["); + for(i = 0; i < n && attrs!=NULL; i++) + { + attr = get_attr(element, attrs[i].name); + if(attr) + { + if(attrs[i].hf != -1) + { + if(attr->name) + proto_tree_add_string_format(tree, attrs[i].hf, tvb, attr->offset, attr->length, attr->value,"%s: %s", attr->name, attr->value); + else + proto_tree_add_string(tree, attrs[i].hf, tvb, attr->offset, attr->length, attr->value); + } + else + { + proto_tree_add_text(tree, tvb, attr->offset, attr->length, "%s: %s", attr->name?attr->name:attrs[i].name, attr->value); + } + + if(attrs[i].in_short_list) + { + if(short_list_started) + { + proto_item_append_text(item," "); + } + proto_item_append_text(item,"%s=\"%s\"",attr->name?attr->name:attrs[i].name, attr->value); + short_list_started = TRUE; + } + + } else if(attrs[i].is_required) + { + expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, + "Required attribute \"%s\" doesn't appear in \"%s\".",attrs[i].name, + element->name); + } + + if(attrs[i].val_func) + { + if(attr) + attrs[i].val_func(pinfo, item, attrs[i].name, attr->value, attrs[i].data); + else + attrs[i].val_func(pinfo, item, attrs[i].name, NULL, attrs[i].data); + } + } + proto_item_append_text(item,"]"); + + /*displays attributes that weren't recognized*/ + xmpp_unknown_attrs(tree, tvb, pinfo, element, FALSE); +} + +void +display_attrs_ext(proto_tree *tree, element_t *element, packet_info *pinfo, tvbuff_t *tvb, attr_info_ext *attrs, guint n) +{ + proto_item *item = proto_tree_get_parent(tree); + attr_t *attr; + guint i; + gboolean short_list_started = FALSE; + + GList *ns_abbrevs_head, *ns_abbrevs = g_hash_table_get_keys(element->namespaces); + GList *ns_fullnames_head, *ns_fullnames = g_hash_table_get_values(element->namespaces); + ns_abbrevs_head = ns_abbrevs; + ns_fullnames_head = ns_fullnames; + + if(element->default_ns_abbrev) + proto_item_append_text(item, "(%s)",element->default_ns_abbrev); + + proto_item_append_text(item," ["); + while(ns_abbrevs && ns_fullnames) + { + for (i = 0; i < n && attrs != NULL; i++) { + if(strcmp(ns_fullnames->data, attrs[i].ns) == 0) + { + attr = get_attr_ext(element, attrs[i].info.name, ns_abbrevs->data); + if(!attr && element->default_ns_abbrev && strcmp(ns_abbrevs->data, element->default_ns_abbrev)==0) + attr = get_attr_ext(element, attrs[i].info.name, ""); + + if (attr) { + if (attrs[i].info.hf != -1) { + if (attr->name) + proto_tree_add_string_format(tree, attrs[i].info.hf, tvb, attr->offset, attr->length, attr->value, "%s: %s", attr->name, attr->value); + else + proto_tree_add_string(tree, attrs[i].info.hf, tvb, attr->offset, attr->length, attr->value); + } else { + proto_tree_add_text(tree, tvb, attr->offset, attr->length, "%s: %s", attr->name ? attr->name : attrs[i].info.name, attr->value); + } + + if (attrs[i].info.in_short_list) { + if (short_list_started) { + proto_item_append_text(item, " "); + } + proto_item_append_text(item, "%s=\"%s\"", attr->name ? attr->name : attrs[i].info.name, attr->value); + short_list_started = TRUE; + } + + } else if (attrs[i].info.is_required) { + expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, + "Required attribute \"%s\" doesn't appear in \"%s\".", attrs[i].info.name, + element->name); + } + + if (attrs[i].info.val_func) { + if (attr) + attrs[i].info.val_func(pinfo, item, attrs[i].info.name, attr->value, attrs[i].info.data); + else + attrs[i].info.val_func(pinfo, item, attrs[i].info.name, NULL, attrs[i].info.data); + } + } + } + ns_abbrevs = ns_abbrevs->next; + ns_fullnames = ns_fullnames->next; + } + proto_item_append_text(item,"]"); + + /*displays attributes that weren't recognized*/ + xmpp_unknown_attrs(tree, tvb, pinfo, element, FALSE); + + g_list_free(ns_abbrevs_head); + g_list_free(ns_fullnames_head); +} + +struct name_attr_t +{ + gchar *name; + gchar *attr_name; + gchar *attr_value; +}; + +/* +returns pointer to the struct that contains 3 strings(element name, attribute name, attribute value) +*/ +gpointer +name_attr_struct(gchar *name, gchar *attr_name, gchar *attr_value) +{ + struct name_attr_t *result; + + result = ep_alloc(sizeof(struct name_attr_t)); + result->name = name; + result->attr_name = attr_name; + result->attr_value = attr_value; + return result; +} + +void +display_elems(proto_tree *tree, element_t *parent, packet_info *pinfo, tvbuff_t *tvb, elem_info *elems, guint n) +{ + guint i; + + for(i = 0; i < n && elems!=NULL; i++) + { + element_t *elem = NULL; + + if(elems[i].type == NAME_AND_ATTR) + { + gboolean loop = TRUE; + + struct + { + gchar *name; + gchar *attr_name; + gchar *attr_value; + } *a; + + a = elems[i].data; + + while(loop && (elem = steal_element_by_name_and_attr(parent, a->name, a->attr_name, a->attr_value))!=NULL) + { + elems[i].elem_func(tree, tvb, pinfo, elem); + if(elems[i].occurrence == ONE) + loop = FALSE; + } + } else if(elems[i].type == NAME) + { + gboolean loop = TRUE; + gchar *name = elems[i].data; + + while(loop && (elem = steal_element_by_name(parent, name))!=NULL) + { + elems[i].elem_func(tree, tvb, pinfo, elem); + if(elems[i].occurrence == ONE) + loop = FALSE; + } + } + else if(elems[i].type == ATTR) + { + gboolean loop = TRUE; + struct { + gchar *name; + gchar *attr_name; + gchar *attr_value; + } *attr = elems[i].data; + + while(loop && (elem = steal_element_by_attr(parent, attr->attr_name, attr->attr_value))!=NULL) + { + elems[i].elem_func(tree, tvb, pinfo, elem); + if(elems[i].occurrence == ONE) + loop = FALSE; + } + + } else if(elems[i].type == NAMES) + { + gboolean loop = TRUE; + array_t *names = elems[i].data; + + while(loop && (elem = steal_element_by_names(parent, (const gchar**)names->data, names->length))!=NULL) + { + elems[i].elem_func(tree, tvb, pinfo, elem); + if(elems[i].occurrence == ONE) + loop = FALSE; + } + } + } + + xmpp_unknown(tree, tvb, pinfo, parent); +} + +/* +function checks that variable value is in array ((array_t)data)->data +*/ +void +val_enum_list(packet_info *pinfo, proto_item *item, gchar *name, gchar *value, gpointer data) +{ + array_t *enums_array = data; + + gint i; + gboolean value_in_enums = FALSE; + + gchar **enums = (char**)enums_array->data; + + if (value != NULL) { + for (i = 0; i < enums_array->length; i++) { + if (strcmp(value, enums[i]) == 0) { + value_in_enums = TRUE; + break; + } + } + if (!value_in_enums) { + expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, + "Field \"%s\" has unexpected value \"%s\"", + name, value); + } + } +} + + +void +change_elem_to_attrib(const gchar *elem_name, const gchar *attr_name, element_t *parent, attr_t* (*transform_func)(element_t *element)) +{ + element_t *element = NULL; + attr_t *fake_attr = NULL; + + element = steal_element_by_name(parent, elem_name); + if(element) + fake_attr = transform_func(element); + + if(fake_attr) + g_hash_table_insert(parent->attrs, (gpointer)attr_name, fake_attr); +} + +attr_t* +transform_func_cdata(element_t *elem) +{ + attr_t *result = ep_init_attr_t(elem->data?elem->data->value:"", elem->offset, elem->length); + return result; +} + +static void +copy_hash_table_func(gpointer key, gpointer value, gpointer user_data) +{ + GHashTable *dst = user_data; + g_hash_table_insert(dst, key, value); +} + +void copy_hash_table(GHashTable *src, GHashTable *dst) +{ + g_hash_table_foreach(src, copy_hash_table_func, dst); +} + +/* +static void +printf_hash_table_func(gpointer key, gpointer value, gpointer user_data _U_) +{ + printf("'%s' '%s'\n", (gchar*)key, (gchar*)value); +} + +void +printf_elements(element_t *root) +{ + GList *elems = root->elements; + + printf("%s\n", root->name); + g_hash_table_foreach(root->namespaces, printf_hash_table_func, NULL); + while(elems) + { + printf_elements(elems->data); + elems = elems->next; + } +} +*/ +/* +* Editor modelines - http://www.wireshark.org/tools/modelines.html +* +* Local variables: +* c-basic-offset: 4 +* tab-width: 8 +* indent-tabs-mode: nil +* End: +* +* ex: set shiftwidth=4 tabstop=8 expandtab: +* :indentSize=4:tabSize=8:noTabs=true: +*/ diff --git a/epan/dissectors/packet-xmpp-utils.h b/epan/dissectors/packet-xmpp-utils.h new file mode 100644 index 0000000000..b6e18ebd53 --- /dev/null +++ b/epan/dissectors/packet-xmpp-utils.h @@ -0,0 +1,287 @@ +/* xmpp-utils.h + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef XMPP_UTILS_H +#define XMPP_UTILS_H + +#define FI_RESET_FLAG(fi, flag) \ + do { \ + if (fi) \ + (fi)->flags = (fi)->flags & !(flag); \ + } while(0) + +#define PROTO_ITEM_SET_VISIBLE(proto_item) \ + do { \ + if (proto_item) \ + FI_RESET_FLAG(PITEM_FINFO(proto_item), FI_HIDDEN); \ + } while(0) + +#define elem_cdata(elem) \ +elem->data?elem->data->value:"" + +typedef struct _array_t +{ + gpointer data; + gint length; +} array_t; + +typedef struct _attr_t{ + gchar *value; + gchar *name; + gint offset; + gint length; + + gboolean was_read; +} attr_t; + +typedef struct _data_t{ + gchar *value; + + gint offset; + gint length; +} data_t; + +typedef struct _element_t{ + gchar* name; + + /*abbreviation that apprears before tag name (<nos:x .../>) + if abbrev doesn't appear then NULL*/ + gchar* default_ns_abbrev; + /*pair of namespace abbrev and namespace*/ + GHashTable *namespaces; + + GHashTable *attrs; + GList *elements; + data_t *data; + + gint offset; + gint length; + + gboolean was_read; +} element_t; + +/*informations about attributes that are displayed in proto tree*/ +typedef struct _attr_info{ + gchar *name; + gint hf; + gboolean is_required; + gboolean in_short_list; + + /*function validates this attribute + it may impose other restrictions (e.g. validating atribut's name, ...)*/ + void (*val_func)(packet_info *pinfo, proto_item *item, gchar *name, gchar *value, gpointer data); + gpointer data; +} attr_info; + +typedef struct _attr_info_ext{ + gchar* ns; + attr_info info; +} attr_info_ext; + +typedef enum _elem_info_type{ + NAME, + ATTR, + NAME_AND_ATTR, + NAMES +} elem_info_type; + +typedef enum _elem_info_occurrence +{ + ONE,MANY +} elem_info_occurrence; + +/*informations about elements that are displayed in proto tree*/ +typedef struct _elem_info{ + elem_info_type type; + gpointer data; + /*function that displays element in tree*/ + void (*elem_func)(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element); + elem_info_occurrence occurrence; +} elem_info; + +typedef struct _xmpp_conv_info_t { + emem_tree_t *req_resp; + emem_tree_t *jingle_sessions; + emem_tree_t *ibb_sessions; + emem_tree_t *gtalk_sessions; +} xmpp_conv_info_t; + +/** Struct conatins frame numbers (request frame(IQ set/get) and + * response frame(IQ result/error)). + */ +typedef struct _xmpp_reqresp_transaction_t { + guint32 req_frame; + guint32 resp_frame; +} xmpp_transaction_t; + +/** Function that is responsibe for request/response tracking in IQ packets. + * Each IQ set/get packet should have the response in other IQ result/error packet. + * Both packet should have the same id attribute. Function saves in emem_tree pairs of + * packet id and struct xmpp_transaction_t. + */ +extern void xmpp_iq_reqresp_track(packet_info *pinfo, element_t *packet, xmpp_conv_info_t *xmpp_info); + +/** Function that is responsibe for jingle session tracking in IQ packets. + * Function saves in emem_tree pairs of packet's id and Jingle session's id. + */ +extern void xmpp_jingle_session_track(packet_info *pinfo, element_t *packet, xmpp_conv_info_t *xmpp_info); + +/** Function that is responsibe for ibb(in band bytestreams) session tracking in IQ packets. + * Function saves in emem_tree pairs of packet's id and In-Band Bytestreams session's id. + */ +extern void xmpp_ibb_session_track(packet_info *pinfo, element_t *packet, xmpp_conv_info_t *xmpp_info); + +/** Function that is responsibe for GTalk session(voice/video) tracking in IQ packets. + * Function saves in emem_tree pairs of packet's id and GTalk session's id. + */ +extern void xmpp_gtalk_session_track(packet_info *pinfo, element_t *packet, xmpp_conv_info_t *xmpp_info); + +/** Function detects unrecognized elements and displays them in tree. + * It uses ett_unknown to display packets. ett_unknown has const size described by + * ETT_UNKNOWN_LEN in packet-xmpp.h + */ +extern void xmpp_unknown(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +extern void xmpp_unknown_attrs(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element, gboolean displ_short_list); + +/** Displays CDATA from element in tree. You can use your own header field hf or + * pass -1. If you pass -1 then CDATA will be display as text(proto_tree_add_text): + * ELEMENT_NAME: CDATA + * ELEMENT_NAME = element->name, if element is empty CDATA = "(empty)" + */ +extern void xmpp_cdata(proto_tree *tree, tvbuff_t *tvb, element_t *element, gint hf); + +/** Function is similar to xmpp_cdata. But it display items only as a text and it is + * compatibile with function display_elems + */ +extern void xmpp_simple_cdata_elem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element); + +/** Converts xml_frame_t struct to element_t. Should be call with parent==NULL. + */ +extern element_t* xml_frame_to_element_t(xml_frame_t *xml_frame, element_t *parent, tvbuff_t *tvb); + +/** Frees all GLib structs in element_t struct. Should be call only for root element. + * It works recursively. + */ +extern void element_t_tree_free(element_t *root); + +/** Allocs ephemeral memory for array_t struct.*/ +extern array_t* ep_init_array_t(const gchar** array, gint len); + +/*Allocs ephemeral memory for attr_t struct*/ +extern attr_t* ep_init_attr_t(gchar *value, gint offset, gint length); + +/*Allocs ephemeral memory for upcased string*/ +extern gchar* ep_string_upcase(const gchar* string); + +/*Compares 2 element_t struct by names. Returns value is similar to the returned by strcmp*/ +extern gint element_t_cmp(gconstpointer a, gconstpointer b); + +/*Searches child element in parent element by name. GList element is returned.*/ +extern GList* find_element_by_name(element_t *packet,const gchar *name); + +/** steal_* + * Functions searches and marks as read found elements. + * If element is set as read, it is invisible for these functions.*/ + +extern element_t* steal_element_by_name(element_t *packet, const gchar *name); +extern element_t* steal_element_by_names(element_t *packet, const gchar **names, gint names_len); +extern element_t* steal_element_by_attr(element_t *packet, const gchar *attr_name, const gchar *attr_value); +extern element_t* steal_element_by_name_and_attr(element_t *packet, const gchar *name, const gchar *attr_name, const gchar *attr_value); + +/*Returns first child in element*/ +extern element_t* get_first_element(element_t *packet); + +/*Converts element to string. Returns memory allocated as ephemeral.*/ +extern gchar* element_to_string(tvbuff_t *tvb, element_t *element); + +/*Converts attribute to string. Returns memory allocated as ephemeral.*/ +extern gchar* attr_to_string(tvbuff_t *tvb, attr_t *attr); + +/* Returns attribute by name and set as read. If attrib is set as read, it may be found + * one more time, but it is invisible for function xmpp_unknown_attrib*/ +extern attr_t* get_attr(element_t *element, const gchar* attr_name); + +/*Function hides first element in tree.*/ +extern void proto_tree_hide_first_child(proto_tree *tree); + +/*Function shows first element in tree.*/ +extern void proto_tree_show_first_child(proto_tree *tree); + +/*Function returns item as text. Memory is allocated as ephemeral.*/ +extern gchar* proto_item_get_text(proto_item *item); + +/*Function returns struct that contains 3 strings. It is used to build attr_info struct.*/ +extern gpointer name_attr_struct(gchar *name, gchar *attr_name, gchar *attr_value); + +/** Function displays attributes from element in way described in attrs. + * Elements that doesn't exist in attrs are displayed as text. + * In ATTR_INFO struct you can define several things: + * - is_in_short_list - attribute should be displayed in short list e.g. ELEMENT_NAME [ATTR1='value' ATTR2='value'] + * - is_required - attribute is required. If attribute doesn't appear then EXPERT INFO will be displayed + * - val_func - validate function + * - data - data passes to the val_func + */ +extern void display_attrs(proto_tree *tree, element_t *element, packet_info *pinfo, tvbuff_t *tvb, attr_info *attrs, guint n); + +/** Function does the same as shown above. It takes attrs(ATTR_INFO_EXT) argument + * that contains ATTR_INFO struct and string with namespace. It is used when packet + * contains several namespaces and each attribute belongs to particular namespace. + * E.g. + * <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' + * mechanism='PLAIN' + * xmlns:ga='http://www.google.com/talk/protocol/auth' + * ga:client-uses-full-bind-result='true'> + * </auth> + */ +extern void display_attrs_ext(proto_tree *tree, element_t *element, packet_info *pinfo, tvbuff_t *tvb, attr_info_ext *attrs, guint n); + +/** Displays elements from parent element in a way described in elems(ELEM_INFO). + * ELEM_INFO describes how to find particular element and what action should be done + * for this element. + * Function calls xmpp_unknown. + */ +extern void display_elems(proto_tree *tree, element_t *parent, packet_info *pinfo, tvbuff_t *tvb, elem_info *elems, guint n); + +/* Validates attribute value. Takes string array(gchar**) in parameter data. + * Is used in ATTR_INFO struct. + */ +extern void val_enum_list(packet_info *pinfo, proto_item *item, gchar *name, gchar *value, gpointer data); + +/** Function changes element to attribute. It searches element by name in parent element, + * next it create attribute using transform_func and inserts it to parent attributes hash table + * using attr_name as key. + */ +extern void change_elem_to_attrib(const gchar *elem_name, const gchar *attr_name, element_t *parent, attr_t* (*transform_func)(element_t *element)); + +/** transform_func that creates attribute with element's cdata as value + */ +extern attr_t* transform_func_cdata(element_t *elem); + +/*Copys keys and values from one hash table to another. + Hash tables must be initialized.*/ +extern void copy_hash_table(GHashTable *src, GHashTable *dst); + +#endif /* XMPP_UTILS_H */ diff --git a/epan/dissectors/packet-xmpp.c b/epan/dissectors/packet-xmpp.c index 529d31b569..7edd166454 100644 --- a/epan/dissectors/packet-xmpp.c +++ b/epan/dissectors/packet-xmpp.c @@ -1,8 +1,7 @@ /* packet-xmpp.c - * Routines for XMPP packet dissection - * Copyright 2003, Brad Hards <bradh@frogmouth.net> - * Heavily based in packet-acap.c, which in turn is heavily based on - * packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com> + * Wireshark's XMPP dissector. + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> * * $Id$ * @@ -10,8 +9,6 @@ * By Gerald Combs <gerald@wireshark.org> * Copyright 1998 Gerald Combs * - * Copied from packet-acap.c - * * 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 @@ -25,116 +22,1410 @@ * 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. - * - * Ref http://xmpp.org/ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include "config.h" #endif +#include<stdio.h> +#include<string.h> #include <glib.h> + #include <epan/packet.h> +#include <epan/proto.h> +#include <epan/emem.h> +#include <epan/conversation.h> #include <epan/strutil.h> +#include <epan/expert.h> +#include <epan/prefs.h> + +#include <epan/dissectors/packet-xml.h> + +#include <packet-xmpp-utils.h> +#include <packet-xmpp.h> +#include <packet-xmpp-core.h> +#include <packet-xmpp-jingle.h> + +#define XMPP_PORT 5222 + +static dissector_handle_t xml_handle = NULL; + +int proto_xmpp = -1; + +static gboolean xmpp_desegment = TRUE; + +gint hf_xmpp_xmlns = -1; +gint hf_xmpp_id = -1; +gint hf_xmpp_from = -1; +gint hf_xmpp_to = -1; +gint hf_xmpp_type = -1; + +gint hf_xmpp_iq = -1; + +gint hf_xmpp_query = -1; +gint hf_xmpp_query_node = -1; + +gint hf_xmpp_query_item = -1; +gint hf_xmpp_query_item_jid = -1; +gint hf_xmpp_query_item_name = -1; +gint hf_xmpp_query_item_subscription = -1; +gint hf_xmpp_query_item_ask = -1; +gint hf_xmpp_query_item_group = -1; +gint hf_xmpp_query_item_node = -1; +gint hf_xmpp_query_item_approved = -1; + +gint hf_xmpp_query_identity = -1; +gint hf_xmpp_query_identity_category = -1; +gint hf_xmpp_query_identity_type = -1; +gint hf_xmpp_query_identity_name = -1; +gint hf_xmpp_query_identity_lang = -1; + +gint hf_xmpp_query_feature = -1; + +gint hf_xmpp_query_streamhost = -1; +gint hf_xmpp_query_streamhost_used = -1; +gint hf_xmpp_query_activate = -1; +gint hf_xmpp_query_udpsuccess = -1; + +gint hf_xmpp_error = -1; +gint hf_xmpp_error_type = -1; +gint hf_xmpp_error_code = -1; +gint hf_xmpp_error_condition = -1; +gint hf_xmpp_error_text = -1; + +gint hf_xmpp_iq_bind = -1; +gint hf_xmpp_iq_bind_jid = -1; +gint hf_xmpp_iq_bind_resource = -1; + +gint hf_xmpp_services = -1; +gint hf_xmpp_channel = -1; + +gint hf_xmpp_iq_session = -1; +gint hf_xmpp_stream = -1; +gint hf_xmpp_features = -1; + +gint hf_xmpp_vcard = -1; +gint hf_xmpp_vcard_x_update = -1; + +gint hf_xmpp_jingle = -1; +gint hf_xmpp_jingle_sid = -1; +gint hf_xmpp_jingle_initiator = -1; +gint hf_xmpp_jingle_responder = -1; +gint hf_xmpp_jingle_action = -1; + +gint hf_xmpp_jingle_content = -1; +gint hf_xmpp_jingle_content_creator = -1; +gint hf_xmpp_jingle_content_name = -1; +gint hf_xmpp_jingle_content_disposition = -1; +gint hf_xmpp_jingle_content_senders = -1; + +gint hf_xmpp_jingle_content_description = -1; +gint hf_xmpp_jingle_content_description_media = -1; +gint hf_xmpp_jingle_content_description_ssrc = -1; + +gint hf_xmpp_jingle_cont_desc_payload = -1; +gint hf_xmpp_jingle_cont_desc_payload_id = -1; +gint hf_xmpp_jingle_cont_desc_payload_channels = -1; +gint hf_xmpp_jingle_cont_desc_payload_clockrate = -1; +gint hf_xmpp_jingle_cont_desc_payload_maxptime = -1; +gint hf_xmpp_jingle_cont_desc_payload_name = -1; +gint hf_xmpp_jingle_cont_desc_payload_ptime = -1; + +gint hf_xmpp_jingle_cont_desc_payload_param = -1; +gint hf_xmpp_jingle_cont_desc_payload_param_value = -1; +gint hf_xmpp_jingle_cont_desc_payload_param_name = -1; + +gint hf_xmpp_jingle_cont_desc_enc = -1; +gint hf_xmpp_jingle_cont_desc_enc_zrtp_hash = -1; +gint hf_xmpp_jingle_cont_desc_enc_crypto = -1; + +gint hf_xmpp_jingle_cont_desc_rtp_hdr = -1; +gint hf_xmpp_jingle_cont_desc_bandwidth = -1; + +gint hf_xmpp_jingle_cont_trans = -1; +gint hf_xmpp_jingle_cont_trans_pwd = -1; +gint hf_xmpp_jingle_cont_trans_ufrag = -1; + +gint hf_xmpp_jingle_cont_trans_cand = -1; +gint hf_xmpp_jingle_cont_trans_rem_cand = -1; +gint hf_xmpp_jingle_cont_trans_activated = -1; +gint hf_xmpp_jingle_cont_trans_candidate_error = -1; +gint hf_xmpp_jingle_cont_trans_candidate_used = -1; +gint hf_xmpp_jingle_cont_trans_proxy_error = -1; + + +gint hf_xmpp_jingle_reason = -1; +gint hf_xmpp_jingle_reason_condition = -1; +gint hf_xmpp_jingle_reason_text = -1; + +gint hf_xmpp_jingle_rtp_info = -1; + +gint hf_xmpp_jingle_file_transfer_offer = -1; +gint hf_xmpp_jingle_file_transfer_request = -1; +gint hf_xmpp_jingle_file_transfer_received = -1; +gint hf_xmpp_jingle_file_transfer_abort = -1; +gint hf_xmpp_jingle_file_transfer_checksum = -1; + +gint hf_xmpp_si = -1; +gint hf_xmpp_si_file = -1; + +gint hf_xmpp_iq_feature_neg = -1; +gint hf_xmpp_x_data = -1; +gint hf_xmpp_x_data_field = -1; +gint hf_xmpp_x_data_field_value = -1; + +gint hf_xmpp_message = -1; +gint hf_xmpp_message_chatstate = -1; + +gint hf_xmpp_message_thread = -1; +gint hf_xmpp_message_thread_parent = -1; + +gint hf_xmpp_message_body = -1; +gint hf_xmpp_message_subject = -1; + +gint hf_xmpp_ibb_open = -1; +gint hf_xmpp_ibb_close = -1; +gint hf_xmpp_ibb_data = -1; + +gint hf_xmpp_delay = -1; + +gint hf_xmpp_x_event = -1; +gint hf_xmpp_x_event_condition = -1; + +gint hf_xmpp_presence = -1; +gint hf_xmpp_presence_show = -1; +gint hf_xmpp_presence_status = -1; +gint hf_xmpp_presence_caps = -1; + +gint hf_xmpp_auth = -1; +gint hf_xmpp_challenge = -1; +gint hf_xmpp_response = -1; +gint hf_xmpp_success = -1; +gint hf_xmpp_failure = -1; +gint hf_xmpp_starttls = -1; +gint hf_xmpp_proceed = -1; + +gint hf_xmpp_muc_x = -1; +gint hf_xmpp_muc_user_x = -1; +gint hf_xmpp_muc_user_item = -1; +gint hf_xmpp_muc_user_invite = -1; + +gint hf_xmpp_gtalk_session = -1; +gint hf_xmpp_gtalk_session_type = -1; +gint hf_xmpp_gtalk = -1; +gint hf_xmpp_gtalk_setting = -1; +gint hf_xmpp_gtalk_nosave_x = -1; +gint hf_xmpp_gtalk_mail_mailbox = -1; +gint hf_xmpp_gtalk_mail_new_mail = -1; +gint hf_xmpp_gtalk_transport_p2p = -1; + + +gint hf_xmpp_conf_info = -1; +gint hf_xmpp_conf_info_sid = -1; + +gint hf_xmpp_unknown = -1; +gint hf_xmpp_unknown_attr = -1; + +gint hf_xmpp_out = -1; +gint hf_xmpp_in = -1; +gint hf_xmpp_response_in = -1; +gint hf_xmpp_response_to = -1; +gint hf_xmpp_jingle_session = -1; +gint hf_xmpp_ibb = -1; + +gint hf_xmpp_ping = -1; +gint hf_xmpp_hashes = -1; + +gint hf_xmpp_jitsi_inputevt = -1; +gint hf_xmpp_jitsi_inputevt_rmt_ctrl = -1; + +gint ett_xmpp = -1; +gint ett_xmpp_iq = -1; +gint ett_xmpp_query = -1; +gint ett_xmpp_query_item = -1; +gint ett_xmpp_query_identity = -1; +gint ett_xmpp_query_feature = -1; + +gint ett_xmpp_query_streamhost = -1; +gint ett_xmpp_query_streamhost_used = -1; +gint ett_xmpp_query_udpsuccess = -1; + +gint ett_xmpp_iq_error = -1; +gint ett_xmpp_iq_bind = -1; +gint ett_xmpp_iq_session = -1; +gint ett_xmpp_vcard = -1; +gint ett_xmpp_vcard_x_update = -1; + +gint ett_xmpp_jingle = -1; +gint ett_xmpp_jingle_content = -1; +gint ett_xmpp_jingle_content_description = -1; +gint ett_xmpp_jingle_cont_desc_enc = -1; +gint ett_xmpp_jingle_cont_desc_enc_zrtp_hash = -1; +gint ett_xmpp_jingle_cont_desc_enc_crypto = -1; +gint ett_xmpp_jingle_cont_desc_rtp_hdr = -1; +gint ett_xmpp_jingle_cont_desc_bandwidth = -1; +gint ett_xmpp_jingle_cont_desc_payload = -1; +gint ett_xmpp_jingle_cont_desc_payload_param = -1; +gint ett_xmpp_jingle_cont_trans = -1; +gint ett_xmpp_jingle_cont_trans_cand = -1; +gint ett_xmpp_jingle_cont_trans_rem_cand = -1; +gint ett_xmpp_jingle_reason = -1; +gint ett_xmpp_jingle_rtp_info = -1; + +gint ett_xmpp_jingle_file_transfer_offer = -1; +gint ett_xmpp_jingle_file_transfer_request = -1; +gint ett_xmpp_jingle_file_transfer_abort = -1; +gint ett_xmpp_jingle_file_transfer_received = -1; +gint ett_xmpp_jingle_file_transfer_checksum = -1; +gint ett_xmpp_jingle_file_transfer_file = -1; + +gint ett_xmpp_services = -1; +gint ett_xmpp_services_relay = -1; +gint ett_xmpp_channel = -1; + +gint ett_xmpp_si = -1; +gint ett_xmpp_si_file = -1; +gint ett_xmpp_si_file_range = -1; + +gint ett_xmpp_iq_feature_neg = -1; +gint ett_xmpp_x_data = -1; +gint ett_xmpp_x_data_field = -1; +gint ett_xmpp_x_data_field_value = -1; + +gint ett_xmpp_ibb_open = -1; +gint ett_xmpp_ibb_close = -1; +gint ett_xmpp_ibb_data = -1; + +gint ett_xmpp_delay = -1; + +gint ett_xmpp_x_event = -1; + +gint ett_xmpp_message = -1; +gint ett_xmpp_message_thread = -1; +gint ett_xmpp_message_body = -1; +gint ett_xmpp_message_subject = -1; + +gint ett_xmpp_presence = -1; +gint ett_xmpp_presence_status = -1; +gint ett_xmpp_presence_caps = -1; -static int proto_xmpp = -1; -static int hf_xmpp_response = -1; -static int hf_xmpp_request = -1; +gint ett_xmpp_auth = -1; +gint ett_xmpp_challenge = -1; +gint ett_xmpp_response = -1; +gint ett_xmpp_success = -1; +gint ett_xmpp_failure = -1; +gint ett_xmpp_stream = -1; +gint ett_xmpp_features = -1; +gint ett_xmpp_features_mechanisms = -1; +gint ett_xmpp_starttls = -1; +gint ett_xmpp_proceed = -1; -static gint ett_xmpp = -1; -static gint ett_xmpp_reqresp = -1; +gint ett_xmpp_muc_x = -1; +gint ett_xmpp_muc_hist = -1; +gint ett_xmpp_muc_user_x = -1; +gint ett_xmpp_muc_user_item = -1; +gint ett_xmpp_muc_user_invite = -1; -#define TCP_PORT_XMPP 5222 -static dissector_handle_t xml_handle=NULL; +gint ett_xmpp_gtalk_session = -1; +gint ett_xmpp_gtalk_session_desc = -1; +gint ett_xmpp_gtalk_session_cand = -1; +gint ett_xmpp_gtalk_session_desc_payload = -1; +gint ett_xmpp_gtalk_session_reason = -1; +gint ett_xmpp_gtalk_jingleinfo_stun = -1; +gint ett_xmpp_gtalk_jingleinfo_server = -1; +gint ett_xmpp_gtalk_jingleinfo_relay = -1; +gint ett_xmpp_gtalk_jingleinfo_relay_serv = -1; +gint ett_xmpp_gtalk_setting = -1; +gint ett_xmpp_gtalk_nosave_x = -1; +gint ett_xmpp_gtalk_mail_mailbox = -1; +gint ett_xmpp_gtalk_mail_mail_info = -1; +gint ett_xmpp_gtalk_mail_senders = -1; +gint ett_xmpp_gtalk_mail_sender = -1; +gint ett_xmpp_gtalk_status_status_list = -1; +gint ett_xmpp_gtalk_transport_p2p = -1; +gint ett_xmpp_gtalk_transport_p2p_cand = -1; + +gint ett_xmpp_conf_info = -1; +gint ett_xmpp_conf_desc = -1; +gint ett_xmpp_conf_state = -1; +gint ett_xmpp_conf_users = -1; +gint ett_xmpp_conf_user = -1; +gint ett_xmpp_conf_endpoint = -1; +gint ett_xmpp_conf_media = -1; + +gint ett_xmpp_ping = -1; +gint ett_xmpp_hashes = -1; +gint ett_xmpp_hashes_hash = -1; + +gint ett_xmpp_jitsi_inputevt = -1; +gint ett_xmpp_jitsi_inputevt_rmt_ctrl = -1; + +gint ett_unknown[ETT_UNKNOWN_LEN]; static void -dissect_xmpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) -{ - gboolean is_request; - proto_tree *xmpp_tree = NULL; - proto_item *ti, *hidden_item; - gint offset = 0; - const guchar *line; - gint next_offset; - int linelen; - tvbuff_t *xmltvb; - - col_set_str(pinfo->cinfo, COL_PROTOCOL, "XMPP"); - - /* - * Find the end of the first line. - * - * Note that "tvb_find_line_end()" will return a value that is - * not longer than what's in the buffer, so the "tvb_get_ptr()" - * call won't throw an exception. - */ - linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); - line = tvb_get_ptr(tvb, offset, linelen); - - if (pinfo->match_uint == pinfo->destport) - is_request = TRUE; - else - is_request = FALSE; - - /* - * Put the first line from the buffer into the summary - * (but leave out the line terminator). - */ - col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", - is_request ? "Request" : "Response", - format_text(line, linelen)); - - if (tree) { - ti = proto_tree_add_item(tree, proto_xmpp, tvb, offset, -1, - ENC_NA) ; - xmpp_tree = proto_item_add_subtree(ti, ett_xmpp); - - if (is_request) { - hidden_item = proto_tree_add_boolean(xmpp_tree, - hf_xmpp_request, tvb, 0, 0, TRUE); - } else { - hidden_item = proto_tree_add_boolean(xmpp_tree, - hf_xmpp_response, tvb, 0, 0, TRUE); - } - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - - xmltvb = tvb_new_subset_remaining(tvb, offset); - call_dissector(xml_handle, xmltvb, pinfo, xmpp_tree); +dissect_xmpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { + + xml_frame_t *xml_frame; + gboolean out_packet; + + conversation_t *conversation; + xmpp_conv_info_t *xmpp_info; + + proto_tree *xmpp_tree = NULL; + proto_item *xmpp_item = NULL; + + element_t *packet = NULL; + + /*check if desegment + * now it checks that last char is '>', + * TODO checks that first element in packet is closed*/ + int index; + gchar last_char; + + if (xmpp_desegment) + { + index = tvb_reported_length(tvb) - 1; + if (index >= 0) + { + last_char = tvb_get_guint8(tvb, index); + + while (last_char <= ' ' && index - 1 >= 0) + { + index--; + last_char = tvb_get_guint8(tvb, index); + } + + if (index >= 0 && last_char != '>') + { + pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; + return; + } + } + } + + if(check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "XMPP"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + /*if tree == NULL then xmpp_item and xmpp_tree will also NULL*/ + xmpp_item = proto_tree_add_item(tree, proto_xmpp, tvb, 0, -1, ENC_NA); + xmpp_tree = proto_item_add_subtree(xmpp_item, ett_xmpp); + + call_dissector(xml_handle,tvb,pinfo,xmpp_tree); + + /*if stream end occurs then return*/ + if(xmpp_stream_close(xmpp_tree,tvb, pinfo)) + { + if(xmpp_tree) + proto_tree_hide_first_child(xmpp_tree); + return; + } + + if(!pinfo->private_data) + return; + + /*data from XML dissector*/ + xml_frame = ((xml_frame_t*)pinfo->private_data)->first_child; + + if(!xml_frame) + return; + + conversation = find_or_create_conversation(pinfo); + xmpp_info = conversation_get_proto_data(conversation, proto_xmpp); + + if (!xmpp_info) { + xmpp_info = se_alloc(sizeof (xmpp_conv_info_t)); + xmpp_info->req_resp = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_req_resp"); + xmpp_info->jingle_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_jingle_sessions"); + xmpp_info->ibb_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_ibb_sessions"); + xmpp_info->gtalk_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_gtalk_sessions"); + conversation_add_proto_data(conversation, proto_xmpp, (void *) xmpp_info); + } + + + if (pinfo->match_uint == pinfo->destport) + out_packet = TRUE; + else + out_packet = FALSE; + + while(xml_frame) + { + packet = xml_frame_to_element_t(xml_frame, NULL, tvb); + DISSECTOR_ASSERT(packet); + + if (strcmp(packet->name, "iq") == 0) { + xmpp_iq_reqresp_track(pinfo, packet, xmpp_info); + xmpp_jingle_session_track(pinfo, packet, xmpp_info); + xmpp_gtalk_session_track(pinfo, packet, xmpp_info); + } + + if (strcmp(packet->name, "iq") == 0 || strcmp(packet->name, "message") == 0) { + xmpp_ibb_session_track(pinfo, packet, xmpp_info); + } + + if (tree) { /* we are being asked for details */ + proto_item *outin_item; + + if (out_packet) + outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_out, tvb, 0, 0, ENC_LITTLE_ENDIAN); + else + outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_in, tvb, 0, 0, ENC_LITTLE_ENDIAN); + + PROTO_ITEM_SET_HIDDEN(outin_item); + + + /*it hides tree generated by XML dissector*/ + proto_tree_hide_first_child(xmpp_tree); + + if (strcmp(packet->name, "iq") == 0) { + xmpp_iq(xmpp_tree, tvb, pinfo, packet); + } else if (strcmp(packet->name, "presence") == 0) { + xmpp_presence(xmpp_tree, tvb, pinfo, packet); + } else if (strcmp(packet->name, "message") == 0) { + xmpp_message(xmpp_tree, tvb, pinfo, packet); + } else if (strcmp(packet->name, "auth") == 0) { + xmpp_auth(xmpp_tree, tvb, pinfo, packet); + } else if (strcmp(packet->name, "challenge") == 0) { + xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_challenge, ett_xmpp_challenge, "CHALLENGE"); + } else if (strcmp(packet->name, "response") == 0) { + xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_response, ett_xmpp_response, "RESPONSE"); + } else if (strcmp(packet->name, "success") == 0) { + xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_success, ett_xmpp_success, "SUCCESS"); + } else if (strcmp(packet->name, "failure") == 0) { + xmpp_failure(xmpp_tree, tvb, pinfo, packet); + } else if (strcmp(packet->name, "xml") == 0) { + xmpp_xml_header(xmpp_tree, tvb, pinfo, packet); + } else if (strcmp(packet->name, "stream") == 0) { + xmpp_stream(xmpp_tree, tvb, pinfo, packet); + } else if (strcmp(packet->name, "features") == 0) { + xmpp_features(xmpp_tree, tvb, pinfo, packet); + } else if (strcmp(packet->name, "starttls") == 0) { + xmpp_starttls(xmpp_tree, tvb, pinfo, packet); + }else if (strcmp(packet->name, "proceed") == 0) { + xmpp_proceed(xmpp_tree, tvb, pinfo, packet); + }else { + proto_tree_show_first_child(xmpp_tree); + expert_add_info_format(pinfo, xmpp_tree, PI_UNDECODED, PI_NOTE, "Unknown packet: %s", packet->name); + col_clear(pinfo->cinfo, COL_INFO); + col_append_fstr(pinfo->cinfo, COL_INFO, "UNKNOWN PACKET "); + } + + /*appends to COL_INFO information about src or dst*/ + if (pinfo->match_uint == pinfo->destport) { + attr_t *to = get_attr(packet, "to"); + if (to) + col_append_fstr(pinfo->cinfo, COL_INFO, "> %s ", to->value); + } else { + attr_t *from = get_attr(packet, "from"); + if (from) + col_append_fstr(pinfo->cinfo, COL_INFO, "< %s ", from->value); + } + } + + element_t_tree_free(packet); + xml_frame = xml_frame->next_sibling; + } } + void -proto_register_xmpp(void) -{ - static hf_register_info hf[] = { - { &hf_xmpp_response, - { "Response", "xmpp.response", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "TRUE if XMPP response", HFILL }}, - - { &hf_xmpp_request, - { "Request", "xmpp.request", - FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "TRUE if XMPP request", HFILL }} - }; - static gint *ett[] = { - &ett_xmpp, - &ett_xmpp_reqresp, - }; - - proto_xmpp = proto_register_protocol("Extensible Messaging and Presence Protocol", - "XMPP", "xmpp"); - proto_register_field_array(proto_xmpp, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); +proto_register_xmpp(void) { + static hf_register_info hf[] = { + { &hf_xmpp_iq, + { + "IQ", "xmpp.iq", FT_NONE, BASE_NONE, NULL, 0x0, + "iq packet", HFILL + }}, + {&hf_xmpp_xmlns, + { + "xmlns", "xmpp.xmlns", FT_STRING, BASE_NONE, NULL, 0x0, + "element namespace", HFILL + }}, + { &hf_xmpp_id, + { + "id", "xmpp.id", FT_STRING, BASE_NONE, NULL, 0x0, + "packet id", HFILL + }}, + { &hf_xmpp_type, + { + "type", "xmpp.type", FT_STRING, BASE_NONE, NULL, 0x0, + "packet type", HFILL + }}, + { &hf_xmpp_from, + { + "from", "xmpp.from", FT_STRING, BASE_NONE, NULL, 0x0, + "packet from", HFILL + }}, + { &hf_xmpp_to, + { + "to", "xmpp.to", FT_STRING, BASE_NONE, NULL, 0x0, + "packet to", HFILL + }}, + { &hf_xmpp_query, + { + "QUERY", "xmpp.query", FT_NONE, BASE_NONE, NULL, 0x0, + "iq query", HFILL + }}, + { &hf_xmpp_query_node, + { + "node", "xmpp.query.node", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query node", HFILL + }}, + { &hf_xmpp_query_item, + { + "ITEM", "xmpp.query.item", FT_NONE, BASE_NONE, NULL, 0x0, + "iq query item", HFILL + + }}, + { &hf_xmpp_query_item_jid, + { + "jid", "xmpp.query.item.jid", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query item jid", HFILL + + }}, + { &hf_xmpp_query_item_name, + { + "name", "xmpp.query.item.name", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query item name", HFILL + }}, + { &hf_xmpp_query_item_subscription, + { + "subscription", "xmpp.query.item.subscription", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query item subscription", HFILL + }}, + { &hf_xmpp_query_item_ask, + { + "ask", "xmpp.query.item.ask", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query item ask", HFILL + }}, + { &hf_xmpp_query_item_group, + { + "GROUP", "xmpp.query.item.group", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query item group", HFILL + + }}, + { &hf_xmpp_query_item_approved, + { + "approved", "xmpp.query.item.approved", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query item approved", HFILL + + }}, + { &hf_xmpp_query_item_node, + { + "node", "xmpp.query.item.node", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query item node", HFILL + + }}, + { &hf_xmpp_query_identity, + { + "IDENTITY", "xmpp.query.identity", FT_NONE, BASE_NONE, NULL, 0x0, + "iq query identity", HFILL + + }}, + { &hf_xmpp_query_identity_category, + { + "category", "xmpp.query.identity.category", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query identity category", HFILL + + }}, + { &hf_xmpp_query_identity_type, + { + "type", "xmpp.query.identity.type", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query identity type", HFILL + + }}, + { &hf_xmpp_query_identity_name, + { + "name", "xmpp.query.identity.name", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query identity name", HFILL + + }}, + { &hf_xmpp_query_identity_lang, + { + "lang", "xmpp.query.identity.lang", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query identity lang", HFILL + + }}, + { &hf_xmpp_query_feature, + { + "FEATURE", "xmpp.query.feature", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query feature", HFILL + + }}, + { &hf_xmpp_query_streamhost, + { + "STREAMHOST", "xmpp.query.streamhost", FT_NONE, BASE_NONE, NULL, 0x0, + "iq query streamhost", HFILL + + }}, + { &hf_xmpp_query_streamhost_used, + { + "STREAMHOST-USED", "xmpp.query.streamhost-used", FT_NONE, BASE_NONE, NULL, 0x0, + "iq query streamhost-used", HFILL + + }}, + { &hf_xmpp_query_activate, + { + "ACTIVATE", "xmpp.query.activate", FT_STRING, BASE_NONE, NULL, 0x0, + "iq query activate", HFILL + + }}, + { &hf_xmpp_query_udpsuccess, + { + "UDPSUCCESS", "xmpp.query.udpsuccess", FT_NONE, BASE_NONE, NULL, 0x0, + "iq query streamhost-used", HFILL + + }}, + { &hf_xmpp_error, + { + "ERROR", "xmpp.error", FT_NONE, BASE_NONE, NULL, 0x0, + "iq error", HFILL + }}, + { &hf_xmpp_error_code, + { + "code", "xmpp.error.code", FT_STRING, BASE_NONE, NULL, 0x0, + "iq stanza error code", HFILL + + }}, + { &hf_xmpp_error_type, + { + "type", "xmpp.error.type", FT_STRING, BASE_NONE, NULL, 0x0, + "iq error type", HFILL + + }}, + { &hf_xmpp_error_condition, + { + "CONDITION", "xmpp.error.condition", FT_STRING, BASE_NONE, NULL, 0x0, + "iq error condition", HFILL + + }}, + { &hf_xmpp_error_text, + { + "TEXT", "xmpp.error.text", FT_STRING, BASE_NONE, NULL, 0x0, + "iq error text", HFILL + + }}, + { &hf_xmpp_iq_bind, + { + "BIND", "xmpp.iq.bind", FT_NONE, BASE_NONE, NULL, 0x0, + "iq bind", HFILL + + }}, + { &hf_xmpp_iq_bind_jid, + { + "jid", "xmpp.iq.bind.jid", FT_STRING, BASE_NONE, NULL, 0x0, + "iq bind jid", HFILL + + }}, + { &hf_xmpp_iq_bind_resource, + { + "resource", "xmpp.iq.bind.resource", FT_STRING, BASE_NONE, NULL, 0x0, + "iq bind resource", HFILL + + }}, + { &hf_xmpp_services, + { + "SERVICES", "xmpp.services", FT_NONE, BASE_NONE, NULL, 0x0, + "http://jabber.org/protocol/jinglenodes services", HFILL + }}, + { &hf_xmpp_channel, + { + "CHANNEL", "xmpp.channel", FT_NONE, BASE_NONE, NULL, 0x0, + "http://jabber.org/protocol/jinglenodes#channel", HFILL + }}, + { &hf_xmpp_iq_session, + { + "SESSION", "xmpp.iq.session", FT_NONE, BASE_NONE, NULL, 0x0, + "iq session", HFILL + }}, + { &hf_xmpp_vcard, + { + "VCARD", "xmpp.vcard", FT_NONE, BASE_NONE, NULL, 0x0, + "vcard-temp", HFILL + }}, + { &hf_xmpp_vcard_x_update, + { + "X VCARD-UPDATE", "xmpp.vcard-update", FT_NONE, BASE_NONE, NULL, 0x0, + "vcard-temp:x:update", HFILL + }}, + { &hf_xmpp_jingle, + { + "JINGLE", "xmpp.jingle", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle", HFILL + }}, + { &hf_xmpp_jingle_action, + { + "action", "xmpp.jingle.action", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle action", HFILL + }}, + { &hf_xmpp_jingle_sid, + { + "sid", "xmpp.jingle.sid", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle sid", HFILL + }}, + { &hf_xmpp_jingle_initiator, + { + "initiator", "xmpp.jingle.initiator", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle initiator", HFILL + }}, + { &hf_xmpp_jingle_responder, + { + "responder", "xmpp.jingle.responder", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle responder", HFILL + }}, + { &hf_xmpp_jingle_content, + { + "CONTENT", "xmpp.jingle.content", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content", HFILL + }}, + { &hf_xmpp_jingle_content_creator, + { + "creator", "xmpp.jingle.content.creator", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content creator", HFILL + }}, + { &hf_xmpp_jingle_content_name, + { + "name", "xmpp.jingle.content.name", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content name", HFILL + }}, + { &hf_xmpp_jingle_content_disposition, + { + "disposition", "xmpp.jingle.content.disposition", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content disposition", HFILL + }}, + { &hf_xmpp_jingle_content_senders, + { + "senders", "xmpp.jingle.content.senders", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content senders", HFILL + }}, + { &hf_xmpp_jingle_content_description, + { + "DESCRIPTION", "xmpp.jingle.content.description", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content description", HFILL + }}, + { &hf_xmpp_jingle_content_description_media, + { + "media", "xmpp.jingle.content.description.media", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description", HFILL + }}, + { &hf_xmpp_jingle_content_description_ssrc, + { + "ssrc", "xmpp.jingle.content.description.ssrc", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description ssrc", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload, + { + "PAYLOAD-TYPE", "xmpp.jingle.content.description.payload-type", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload_id, + { + "id", "xmpp.jingle.content.description.payload-type.id", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type id", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload_channels, + { + "channels", "xmpp.jingle.content.description.payload-type.channels", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type channels", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload_clockrate, + { + "clockrate", "xmpp.jingle.content.description.payload-type.clockrate", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type clockrate", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload_maxptime, + { + "maxptime", "xmpp.jingle.content.description.payload-type.maxptime", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type maxptime", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload_name, + { + "name", "xmpp.jingle.content.description.payload-type.name", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type name", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload_ptime, + { + "ptime", "xmpp.jingle.content.description.payload-type.ptime", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type ptime", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload_param, + { + "PARAMETER", "xmpp.jingle.content.description.payload-type.parameter", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type parameter", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload_param_name, + { + "name", "xmpp.jingle.content.description.payload-type.parameter.name", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type parameter name", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_payload_param_value, + { + "value", "xmpp.jingle.content.description.payload-type.parameter.value", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content description payload-type parameter value", HFILL + }}, + { &hf_xmpp_jingle_cont_trans, + { + "TRANSPORT", "xmpp.jingle.content.transport", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content transport", HFILL + }}, + { &hf_xmpp_jingle_cont_trans_ufrag, + { + "ufrag", "xmpp.jingle.content.transport.ufrag", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content transport ufrag", HFILL + }}, + { &hf_xmpp_jingle_cont_trans_pwd, + { + "pwd", "xmpp.jingle.content.transport.pwd", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle content transport pwd", HFILL + }}, + { &hf_xmpp_jingle_cont_trans_cand, + { + "CANDIDATE", "xmpp.jingle.content.transport.candidate", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content transport candidate", HFILL + }}, + { &hf_xmpp_jingle_cont_trans_rem_cand, + { + "REMOTE-CANDIDATE", "xmpp.jingle.content.transport.remote-candidate", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content transport remote-candidate", HFILL + }}, + { &hf_xmpp_jingle_cont_trans_activated, + { + "ACTIVATED", "xmpp.jingle.content.transport.activated", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:jingle:transports:s5b:1 activated", HFILL + }}, + { &hf_xmpp_jingle_cont_trans_candidate_used, + { + "CANDIDATE-USED", "xmpp.jingle.content.transport.candidate-used", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:jingle:transports:s5b:1 candidate-used", HFILL + }}, + { &hf_xmpp_jingle_cont_trans_candidate_error, + { + "CANDIDATE-ERROR", "xmpp.jingle.content.transport.candidate-error", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:jingle:transports:s5b:1 candidate-error", HFILL + }}, + { &hf_xmpp_jingle_cont_trans_proxy_error, + { + "PROXY-ERROR", "xmpp.jingle.content.transport.proxy-error", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:jingle:transports:s5b:1 proxy-error", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_enc, + { + "ENCRYPTION", "xmpp.jingle.content.description.encryption", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content descryption encryption", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_enc_zrtp_hash, + { + "ZRTP-HASH", "xmpp.jingle.content.description.encryption.zrtp-hash", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content descryption encryption zrtp-hash", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_enc_crypto, + { + "CRYPTO", "xmpp.jingle.content.description.encryption.crypto", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content descryption encryption crypto", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_bandwidth, + { + "BANDWIDTH", "xmpp.jingle.content.description.bandwidth", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content descryption bandwidth", HFILL + }}, + { &hf_xmpp_jingle_cont_desc_rtp_hdr, + { + "RTP-HDREXT", "xmpp.jingle.content.description.rtp-hdrext", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle content descryption rtp-hdrext", HFILL + }}, + { &hf_xmpp_jingle_reason, + { + "REASON", "xmpp.jingle.reason", FT_NONE, BASE_NONE, NULL, 0x0, + "iq jingle reason", HFILL + }}, + { &hf_xmpp_jingle_reason_condition, + { + "CONDITION", "xmpp.jingle.reason.condition", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle reason condition", HFILL + }}, + { &hf_xmpp_jingle_reason_text, + { + "TEXT", "xmpp.jingle.reason.text", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle reason text", HFILL + }}, + { &hf_xmpp_jingle_rtp_info, + { + "RTP-INFO", "xmpp.jingle.rtp_info", FT_STRING, BASE_NONE, NULL, 0x0, + "iq jingle rtp-info(ringing, active, hold, mute, ...)", HFILL + }}, + { &hf_xmpp_jingle_file_transfer_offer, + { + "OFFER", "xmpp.jingle.content.description.offer", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:jingle:apps:file-transfer:3 offer", HFILL + }}, + { &hf_xmpp_jingle_file_transfer_request, + { + "REQUEST", "xmpp.jingle.content.description.request", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:jingle:apps:file-transfer:3 request", HFILL + }}, + { &hf_xmpp_jingle_file_transfer_received, + { + "RECEIVED", "xmpp.jingle.content.received", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:jingle:apps:file-transfer:3 received", HFILL + }}, + { &hf_xmpp_jingle_file_transfer_abort, + { + "ABORT", "xmpp.jingle.content.abort", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:jingle:apps:file-transfer:3 abort", HFILL + }}, + { &hf_xmpp_jingle_file_transfer_checksum, + { + "CHECKSUM", "xmpp.jingle.content.checksum", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:jingle:apps:file-transfer:3 checksum", HFILL + }}, + { &hf_xmpp_si, + { + "SI", "xmpp.si", FT_NONE, BASE_NONE, NULL, 0x0, + "iq si", HFILL + }}, + { &hf_xmpp_si_file, + { + "FILE", "xmpp.si.file", FT_NONE, BASE_NONE, NULL, 0x0, + "iq si file", HFILL + }}, + { &hf_xmpp_iq_feature_neg, + { + "FEATURE", "xmpp.feature-neg", FT_NONE, BASE_NONE, NULL, 0x0, + "http://jabber.org/protocol/feature-neg", HFILL + }}, + { &hf_xmpp_x_data, + { + "X-DATA", "xmpp.x-data", FT_NONE, BASE_NONE, NULL, 0x0, + "jabber:x:data", HFILL + }}, + { &hf_xmpp_x_data_field, + { + "FIELD", "xmpp.x-data.field", FT_NONE, BASE_NONE, NULL, 0x0, + "jabber:x:data field", HFILL + }}, + { &hf_xmpp_x_data_field_value, + { + "VALUE", "xmpp.x-data.field.value", FT_NONE, BASE_NONE, NULL, 0x0, + "jabber:x:data field value", HFILL + }}, + { &hf_xmpp_delay, + { + "DELAY", "xmpp.delay", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:delay", HFILL + }}, + { &hf_xmpp_x_event, + { + "X EVENT", "xmpp.x-event", FT_NONE, BASE_NONE, NULL, 0x0, + "jabber:x:event", HFILL + }}, + { &hf_xmpp_x_event_condition, + { + "CONDITION", "xmpp.x-event.condition", FT_STRING, BASE_NONE, NULL, 0x0, + "jabber:x:event condition", HFILL + }}, + { &hf_xmpp_presence, + { + "PRESENCE", "xmpp.presence", FT_NONE, BASE_NONE, NULL, 0x0, + "presence packet", HFILL + }}, + { &hf_xmpp_presence_show, + { + "SHOW", "xmpp.presence.show", FT_STRING, BASE_NONE, NULL, 0x0, + "presence show", HFILL + }}, + { &hf_xmpp_presence_status, + { + "STATUS", "xmpp.presence.status", FT_NONE, BASE_NONE, NULL, 0x0, + "presence status", HFILL + }}, + { &hf_xmpp_presence_caps, + { + "CAPS", "xmpp.presence.caps", FT_NONE, BASE_NONE, NULL, 0x0, + "presence caps", HFILL + }}, + { &hf_xmpp_message, + { + "MESSAGE", "xmpp.message", FT_NONE, BASE_NONE, NULL, 0x0, + "message packet", HFILL + }}, + { &hf_xmpp_message_chatstate, + { + "CHATSTATE", "xmpp.message.chatstate", FT_STRING, BASE_NONE, NULL, 0x0, + "message chatstate", HFILL + }}, + { &hf_xmpp_message_thread, + { + "THREAD", "xmpp.message.thread", FT_NONE, BASE_NONE, NULL, 0x0, + "message thread", HFILL + }}, + { &hf_xmpp_message_body, + { + "BODY", "xmpp.message.body", FT_NONE, BASE_NONE, NULL, 0x0, + "message body", HFILL + }}, + { &hf_xmpp_message_subject, + { + "SUBJECT", "xmpp.message.subject", FT_NONE, BASE_NONE, NULL, 0x0, + "message subject", HFILL + }}, + { &hf_xmpp_message_thread_parent, + { + "parent", "xmpp.message.thread.parent", FT_STRING, BASE_NONE, NULL, 0x0, + "message thread parent", HFILL + }}, + { &hf_xmpp_auth, + { + "AUTH", "xmpp.auth", FT_NONE, BASE_NONE, NULL, 0x0, + "auth packet", HFILL + }}, + { &hf_xmpp_stream, + { + "STREAM", "xmpp.stream", FT_NONE, BASE_NONE, NULL, 0x0, + "XMPP stream", HFILL + }}, + { &hf_xmpp_challenge, + { + "CHALLENGE", "xmpp.challenge", FT_NONE, BASE_NONE, NULL, 0x0, + "challenge packet", HFILL + }}, + { &hf_xmpp_response, + { + "RESPONSE", "xmpp.response", FT_NONE, BASE_NONE, NULL, 0x0, + "response packet", HFILL + }}, + { &hf_xmpp_success, + { + "SUCCESS", "xmpp.success", FT_NONE, BASE_NONE, NULL, 0x0, + "success packet", HFILL + }}, + { &hf_xmpp_failure, + { + "FAILURE", "xmpp.failure", FT_NONE, BASE_NONE, NULL, 0x0, + "failure packet", HFILL + }}, + { &hf_xmpp_features, + { + "FEATURES", "xmpp.features", FT_NONE, BASE_NONE, NULL, 0x0, + "stream features", HFILL + }}, + { &hf_xmpp_starttls, + { + "STARTTLS", "xmpp.starttls", FT_NONE, BASE_NONE, NULL, 0x0, + "starttls packet", HFILL + }}, + { &hf_xmpp_proceed, + { + "PROCEED", "xmpp.proceed", FT_NONE, BASE_NONE, NULL, 0x0, + "proceed packet", HFILL + }}, + { &hf_xmpp_unknown, + { + "UNKNOWN", "xmpp.unknown", FT_STRING, BASE_NONE, NULL, 0x0, + "unknown element", HFILL + }}, + { &hf_xmpp_unknown_attr, + { + "UNKNOWN ATTR", "xmpp.unknown_attr", FT_STRING, BASE_NONE, NULL, 0x0, + "unknown attribute", HFILL + }}, + { &hf_xmpp_ibb_open, + { + "IBB-OPEN", "xmpp.ibb.open", FT_NONE, BASE_NONE, NULL, 0x0, + "xmpp ibb open", HFILL + }}, + { &hf_xmpp_ibb_close, + { + "IBB-CLOSE", "xmpp.ibb.close", FT_NONE, BASE_NONE, NULL, 0x0, + "xmpp ibb close", HFILL + }}, + { &hf_xmpp_ibb_data, + { + "IBB-DATA", "xmpp.ibb.data", FT_NONE, BASE_NONE, NULL, 0x0, + "xmpp ibb data", HFILL + }}, + { &hf_xmpp_muc_x, + { + "X MUC", "xmpp.muc-x", FT_NONE, BASE_NONE, NULL, 0x0, + "http://jabber.org/protocol/muc", HFILL + }}, + { &hf_xmpp_muc_user_x, + { + "X MUC-USER", "xmpp.muc-user-x", FT_NONE, BASE_NONE, NULL, 0x0, + "http://jabber.org/protocol/muc#user", HFILL + }}, + { &hf_xmpp_muc_user_item, + { + "ITEM", "xmpp.muc-user-x.item", FT_NONE, BASE_NONE, NULL, 0x0, + "muc#user item", HFILL + }}, + { &hf_xmpp_muc_user_invite, + { + "INVITE", "xmpp.muc-user-x.invite", FT_NONE, BASE_NONE, NULL, 0x0, + "muc#user invite", HFILL + }}, + { &hf_xmpp_gtalk_session, + { + "GTALK-SESSION", "xmpp.gtalk.session", FT_NONE, BASE_NONE, NULL, 0x0, + "GTalk session", HFILL + }}, + { &hf_xmpp_gtalk_session_type, + { + "type", "xmpp.gtalk.session.type", FT_STRING, BASE_NONE, NULL, 0x0, + "GTalk session type", HFILL + }}, + { &hf_xmpp_gtalk, + { + "GTALK SESSION", "xmpp.gtalk", FT_STRING, BASE_NONE, NULL, 0x0, + "GTalk SID", HFILL + }}, + { &hf_xmpp_gtalk_setting, + { + "USERSETTING", "xmpp.gtalk.setting", FT_NONE, BASE_NONE, NULL, 0x0, + "google:setting usersetting", HFILL + }}, + { &hf_xmpp_gtalk_nosave_x, + { + "X-NOSAVE", "xmpp.gtalk.nosave.x", FT_NONE, BASE_NONE, NULL, 0x0, + "google:nosave x", HFILL + }}, + { &hf_xmpp_gtalk_mail_mailbox, + { + "MAILBOX", "xmpp.gtalk.mailbox", FT_NONE, BASE_NONE, NULL, 0x0, + "google:mail:notify mailbox", HFILL + }}, + { &hf_xmpp_gtalk_mail_new_mail, + { + "NEW MAIL", "xmpp.gtalk.new-mail", FT_NONE, BASE_NONE, NULL, 0x0, + "google:mail:notify new-mail", HFILL + }}, + { &hf_xmpp_gtalk_transport_p2p, + { + "TRANSPORT", "xmpp.gtalk.transport-p2p", FT_NONE, BASE_NONE, NULL, 0x0, + "google/transport/p2p", HFILL + }}, + { &hf_xmpp_conf_info, + { + "CONFERENCE INFO", "xmpp.conf-info", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:ietf:params:xml:ns:conference-info", HFILL + }}, + { &hf_xmpp_conf_info_sid, + { + "sid", "xmpp.conf-info.sid", FT_STRING, BASE_NONE, NULL, 0x0, + "urn:ietf:params:xml:ns:conference-info sid", HFILL + }}, + { &hf_xmpp_response_in, + { "Response In", "xmpp.response_in", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "The response to this request is in this frame", HFILL } + }, + { &hf_xmpp_response_to, + { "Request In", "xmpp.response_to", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "This is a response to the request in this frame", HFILL } + }, + { &hf_xmpp_out, + { + "Out", "xmpp.out", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Outgoing packet", HFILL + }}, + { &hf_xmpp_in, + { + "In", "xmpp.in", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Ingoing packet", HFILL + }}, + { &hf_xmpp_ibb, + { + "IBB SESSION", "xmpp.ibb", FT_STRING, BASE_NONE, NULL, 0x0, + "In-Band Bytestreams session", HFILL + }}, + { &hf_xmpp_jingle_session, + { + "JINGLE SESSION", "xmpp.jingle_session", FT_STRING, BASE_NONE, NULL, 0x0, + "Jingle SID", HFILL + }}, + { &hf_xmpp_ping, + { + "PING", "xmpp.ping", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:ping", HFILL + }}, + { &hf_xmpp_hashes, + { + "HASHES", "xmpp.hashes", FT_NONE, BASE_NONE, NULL, 0x0, + "urn:xmpp:hashes:0", HFILL + }}, + { &hf_xmpp_jitsi_inputevt, + { + "INPUTEVT", "xmpp.inputevt", FT_NONE, BASE_NONE, NULL, 0x0, + "http://jitsi.org/protocol/inputevt", HFILL + }}, + { &hf_xmpp_jitsi_inputevt_rmt_ctrl, + { + "REMOTE-CONTROL", "xmpp.inputevt.remote-control", FT_NONE, BASE_NONE, NULL, 0x0, + "http://jitsi.org/protocol/inputevt remote-control", HFILL + }}, + }; + + static gint * ett[] = { + &ett_xmpp, + &ett_xmpp_iq, + &ett_xmpp_query, + &ett_xmpp_query_item, + &ett_xmpp_query_identity, + &ett_xmpp_query_feature, + &ett_xmpp_query_streamhost, + &ett_xmpp_query_streamhost_used, + &ett_xmpp_query_udpsuccess, + &ett_xmpp_iq_error, + &ett_xmpp_iq_bind, + &ett_xmpp_iq_session, + &ett_xmpp_vcard, + &ett_xmpp_vcard_x_update, + &ett_xmpp_jingle, + &ett_xmpp_jingle_content, + &ett_xmpp_jingle_content_description, + &ett_xmpp_jingle_cont_desc_payload, + &ett_xmpp_jingle_cont_desc_payload_param, + &ett_xmpp_jingle_cont_desc_enc, + &ett_xmpp_jingle_cont_desc_enc_zrtp_hash, + &ett_xmpp_jingle_cont_desc_enc_crypto, + &ett_xmpp_jingle_cont_desc_bandwidth, + &ett_xmpp_jingle_cont_desc_rtp_hdr, + &ett_xmpp_jingle_cont_trans, + &ett_xmpp_jingle_cont_trans_cand, + &ett_xmpp_jingle_cont_trans_rem_cand, + &ett_xmpp_jingle_reason, + &ett_xmpp_jingle_rtp_info, + &ett_xmpp_services, + &ett_xmpp_services_relay, + &ett_xmpp_channel, + &ett_xmpp_si, + &ett_xmpp_si_file, + &ett_xmpp_si_file_range, + &ett_xmpp_iq_feature_neg, + &ett_xmpp_x_data, + &ett_xmpp_x_data_field, + &ett_xmpp_x_data_field_value, + &ett_xmpp_ibb_open, + &ett_xmpp_ibb_close, + &ett_xmpp_ibb_data, + &ett_xmpp_delay, + &ett_xmpp_x_event, + &ett_xmpp_message, + &ett_xmpp_message_thread, + &ett_xmpp_message_subject, + &ett_xmpp_message_body, + &ett_xmpp_presence, + &ett_xmpp_presence_status, + &ett_xmpp_presence_caps, + &ett_xmpp_auth, + &ett_xmpp_challenge, + &ett_xmpp_response, + &ett_xmpp_success, + &ett_xmpp_failure, + &ett_xmpp_muc_x, + &ett_xmpp_muc_hist, + &ett_xmpp_muc_user_x, + &ett_xmpp_muc_user_item, + &ett_xmpp_muc_user_invite, + &ett_xmpp_gtalk_session, + &ett_xmpp_gtalk_session_desc, + &ett_xmpp_gtalk_session_desc_payload, + &ett_xmpp_gtalk_session_cand, + &ett_xmpp_gtalk_session_reason, + &ett_xmpp_gtalk_jingleinfo_stun, + &ett_xmpp_gtalk_jingleinfo_server, + &ett_xmpp_gtalk_jingleinfo_relay, + &ett_xmpp_gtalk_jingleinfo_relay_serv, + &ett_xmpp_gtalk_setting, + &ett_xmpp_gtalk_nosave_x, + &ett_xmpp_gtalk_mail_mailbox, + &ett_xmpp_gtalk_mail_mail_info, + &ett_xmpp_gtalk_mail_senders, + &ett_xmpp_gtalk_mail_sender, + &ett_xmpp_gtalk_status_status_list, + &ett_xmpp_conf_info, + &ett_xmpp_conf_desc, + &ett_xmpp_conf_state, + &ett_xmpp_conf_users, + &ett_xmpp_conf_user, + &ett_xmpp_conf_endpoint, + &ett_xmpp_conf_media, + &ett_xmpp_gtalk_transport_p2p, + &ett_xmpp_gtalk_transport_p2p_cand, + &ett_xmpp_ping, + &ett_xmpp_hashes_hash, + &ett_xmpp_hashes, + &ett_xmpp_jingle_file_transfer_offer, + &ett_xmpp_jingle_file_transfer_request, + &ett_xmpp_jingle_file_transfer_received, + &ett_xmpp_jingle_file_transfer_abort, + &ett_xmpp_jingle_file_transfer_checksum, + &ett_xmpp_jingle_file_transfer_file, + &ett_xmpp_jitsi_inputevt, + &ett_xmpp_jitsi_inputevt_rmt_ctrl, + &ett_xmpp_stream, + &ett_xmpp_features, + &ett_xmpp_features_mechanisms, + &ett_xmpp_starttls, + &ett_xmpp_proceed, + }; + + module_t *xmpp_module; + + static gint* ett_unknown_ptr[ETT_UNKNOWN_LEN]; + gint i; + for(i=0;i<ETT_UNKNOWN_LEN;i++) + { + ett_unknown[i] = -1; + ett_unknown_ptr[i] = &ett_unknown[i]; + } + + + + proto_xmpp = proto_register_protocol( + "XMPP Protocol", /* name */ + "XMPP", /* short name */ + "xmpp" /* abbrev */ + ); + + xmpp_module = prefs_register_protocol(proto_xmpp, NULL); + prefs_register_bool_preference(xmpp_module, "desegment", + "Reasemble XMPP messages", + "Whether the XMPP dissector should reassemble messages. " + "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings", + &xmpp_desegment); + + proto_register_field_array(proto_xmpp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + proto_register_subtree_array(ett_unknown_ptr, array_length(ett_unknown_ptr)); + + register_dissector("xmpp", dissect_xmpp, proto_xmpp); } void -proto_reg_handoff_xmpp(void) -{ - dissector_handle_t xmpp_handle; +proto_reg_handoff_xmpp(void) { + static dissector_handle_t xmpp_handle; + + xml_handle = find_dissector("xml"); + + /*xmpp_handle = create_dissector_handle(dissect_xmpp, proto_xmpp);*/ + xmpp_handle = find_dissector("xmpp"); - xml_handle = find_dissector("xml"); + dissector_add_uint("tcp.port", XMPP_PORT, xmpp_handle); - xmpp_handle = create_dissector_handle(dissect_xmpp, proto_xmpp); - dissector_add_uint("tcp.port", TCP_PORT_XMPP, xmpp_handle); } +/* +* Editor modelines - http://www.wireshark.org/tools/modelines.html +* +* Local variables: +* c-basic-offset: 4 +* tab-width: 8 +* indent-tabs-mode: nil +* End: +* +* ex: set shiftwidth=4 tabstop=8 expandtab: +* :indentSize=4:tabSize=8:noTabs=true: +*/ diff --git a/epan/dissectors/packet-xmpp.h b/epan/dissectors/packet-xmpp.h new file mode 100644 index 0000000000..d9350523e0 --- /dev/null +++ b/epan/dissectors/packet-xmpp.h @@ -0,0 +1,344 @@ +/* packet-xmpp.h + * + * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com> + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef PACKET_XMPP_H +#define PACKET_XMPP_H + +#define ETT_UNKNOWN_LEN 20 + +/*#define XMPP_DEBUG*/ + +extern int proto_xmpp; + +extern gint hf_xmpp_xmlns; +extern gint hf_xmpp_id; +extern gint hf_xmpp_from; +extern gint hf_xmpp_to; +extern gint hf_xmpp_type; + +extern gint hf_xmpp_iq; + + +extern gint hf_xmpp_query; +extern gint hf_xmpp_query_node; + +extern gint hf_xmpp_query_item; +extern gint hf_xmpp_query_item_jid; +extern gint hf_xmpp_query_item_name; +extern gint hf_xmpp_query_item_subscription; +extern gint hf_xmpp_query_item_ask; +extern gint hf_xmpp_query_item_group; +extern gint hf_xmpp_query_item_node; +extern gint hf_xmpp_query_item_approved; + +extern gint hf_xmpp_query_identity; +extern gint hf_xmpp_query_identity_category; +extern gint hf_xmpp_query_identity_type; +extern gint hf_xmpp_query_identity_name; +extern gint hf_xmpp_query_identity_lang; + +extern gint hf_xmpp_query_feature; + +extern gint hf_xmpp_query_streamhost; +extern gint hf_xmpp_query_streamhost_used; +extern gint hf_xmpp_query_activate; +extern gint hf_xmpp_query_udpsuccess; + +extern gint hf_xmpp_error; +extern gint hf_xmpp_error_type; +extern gint hf_xmpp_error_code; +extern gint hf_xmpp_error_condition; +extern gint hf_xmpp_error_text; + +extern gint hf_xmpp_iq_bind; +extern gint hf_xmpp_iq_bind_jid; +extern gint hf_xmpp_iq_bind_resource; + +extern gint hf_xmpp_services; +extern gint hf_xmpp_channel; + +extern gint hf_xmpp_iq_session; +extern gint hf_xmpp_features; + +extern gint hf_xmpp_vcard; +extern gint hf_xmpp_vcard_x_update; + + +extern gint hf_xmpp_jingle; +extern gint hf_xmpp_jingle_sid; +extern gint hf_xmpp_jingle_initiator; +extern gint hf_xmpp_jingle_responder; +extern gint hf_xmpp_jingle_action; + +extern gint hf_xmpp_jingle_content; +extern gint hf_xmpp_jingle_content_creator; +extern gint hf_xmpp_jingle_content_name; +extern gint hf_xmpp_jingle_content_disposition; +extern gint hf_xmpp_jingle_content_senders; + +extern gint hf_xmpp_jingle_content_description; +extern gint hf_xmpp_jingle_content_description_media; +extern gint hf_xmpp_jingle_content_description_ssrc; + +extern gint hf_xmpp_jingle_cont_desc_payload; +extern gint hf_xmpp_jingle_cont_desc_payload_id; +extern gint hf_xmpp_jingle_cont_desc_payload_channels; +extern gint hf_xmpp_jingle_cont_desc_payload_clockrate; +extern gint hf_xmpp_jingle_cont_desc_payload_maxptime; +extern gint hf_xmpp_jingle_cont_desc_payload_name; +extern gint hf_xmpp_jingle_cont_desc_payload_ptime; + +extern gint hf_xmpp_jingle_cont_desc_payload_param; +extern gint hf_xmpp_jingle_cont_desc_payload_param_value; +extern gint hf_xmpp_jingle_cont_desc_payload_param_name; + +extern gint hf_xmpp_jingle_cont_desc_enc; +extern gint hf_xmpp_jingle_cont_desc_enc_zrtp_hash; +extern gint hf_xmpp_jingle_cont_desc_enc_crypto; + +extern gint hf_xmpp_jingle_cont_desc_rtp_hdr; +extern gint hf_xmpp_jingle_cont_desc_bandwidth; + +extern gint hf_xmpp_jingle_cont_trans; +extern gint hf_xmpp_jingle_cont_trans_pwd; +extern gint hf_xmpp_jingle_cont_trans_ufrag; + +extern gint hf_xmpp_jingle_cont_trans_cand; +extern gint hf_xmpp_jingle_cont_trans_rem_cand; + +extern gint hf_xmpp_jingle_cont_trans_activated; +extern gint hf_xmpp_jingle_cont_trans_candidate_used; +extern gint hf_xmpp_jingle_cont_trans_candidate_error; +extern gint hf_xmpp_jingle_cont_trans_proxy_error; + +extern gint hf_xmpp_jingle_reason; +extern gint hf_xmpp_jingle_reason_condition; +extern gint hf_xmpp_jingle_reason_text; + +extern gint hf_xmpp_jingle_rtp_info; + +extern gint hf_xmpp_jingle_file_transfer_offer; +extern gint hf_xmpp_jingle_file_transfer_request; +extern gint hf_xmpp_jingle_file_transfer_received; +extern gint hf_xmpp_jingle_file_transfer_abort; +extern gint hf_xmpp_jingle_file_transfer_checksum; + +extern gint hf_xmpp_si; +extern gint hf_xmpp_si_file; + +extern gint hf_xmpp_iq_feature_neg; +extern gint hf_xmpp_x_data; +extern gint hf_xmpp_x_data_field; +extern gint hf_xmpp_x_data_field_value; + +extern gint hf_xmpp_message; +extern gint hf_xmpp_message_chatstate; + +extern gint hf_xmpp_message_thread; +extern gint hf_xmpp_message_thread_parent; + +extern gint hf_xmpp_message_body; +extern gint hf_xmpp_message_subject; + +extern gint hf_xmpp_ibb_open; +extern gint hf_xmpp_ibb_close; +extern gint hf_xmpp_ibb_data; + +extern gint hf_xmpp_delay; + +extern gint hf_xmpp_x_event; +extern gint hf_xmpp_x_event_condition; + +extern gint hf_xmpp_presence; +extern gint hf_xmpp_presence_show; +extern gint hf_xmpp_presence_status; +extern gint hf_xmpp_presence_caps; + +extern gint hf_xmpp_auth; +extern gint hf_xmpp_challenge; +extern gint hf_xmpp_response; +extern gint hf_xmpp_success; +extern gint hf_xmpp_failure; +extern gint hf_xmpp_stream; +extern gint hf_xmpp_starttls; +extern gint hf_xmpp_proceed; + +extern gint hf_xmpp_muc_x; +extern gint hf_xmpp_muc_user_x; +extern gint hf_xmpp_muc_user_item; +extern gint hf_xmpp_muc_user_invite; + +extern gint hf_xmpp_gtalk_session; +extern gint hf_xmpp_gtalk_session_type; +extern gint hf_xmpp_gtalk; +extern gint hf_xmpp_gtalk_setting; +extern gint hf_xmpp_gtalk_nosave_x; +extern gint hf_xmpp_gtalk_mail_mailbox; +extern gint hf_xmpp_gtalk_mail_new_mail; +extern gint hf_xmpp_gtalk_transport_p2p; + +extern gint hf_xmpp_conf_info; +extern gint hf_xmpp_conf_info_sid; + +extern gint hf_xmpp_unknown; +extern gint hf_xmpp_unknown_attr; + +extern gint hf_xmpp_out; +extern gint hf_xmpp_in; +extern gint hf_xmpp_response_in; +extern gint hf_xmpp_response_to; +extern gint hf_xmpp_jingle_session; +extern gint hf_xmpp_ibb; + +extern gint hf_xmpp_ping; +extern gint hf_xmpp_hashes; + +extern gint hf_xmpp_jitsi_inputevt; +extern gint hf_xmpp_jitsi_inputevt_rmt_ctrl; + +extern gint ett_xmpp; +extern gint ett_xmpp_iq; +extern gint ett_xmpp_query; +extern gint ett_xmpp_query_item; +extern gint ett_xmpp_query_identity; +extern gint ett_xmpp_query_feature; + +extern gint ett_xmpp_query_streamhost; +extern gint ett_xmpp_query_streamhost_used; +extern gint ett_xmpp_query_udpsuccess; + +extern gint ett_xmpp_iq_error; +extern gint ett_xmpp_iq_bind; +extern gint ett_xmpp_iq_session; +extern gint ett_xmpp_vcard; +extern gint ett_xmpp_vcard_x_update; + +extern gint ett_xmpp_jingle; +extern gint ett_xmpp_jingle_content; +extern gint ett_xmpp_jingle_content_description; +extern gint ett_xmpp_jingle_cont_desc_enc; +extern gint ett_xmpp_jingle_cont_desc_enc_zrtp_hash; +extern gint ett_xmpp_jingle_cont_desc_enc_crypto; +extern gint ett_xmpp_jingle_cont_desc_rtp_hdr; +extern gint ett_xmpp_jingle_cont_desc_bandwidth; +extern gint ett_xmpp_jingle_cont_desc_payload; +extern gint ett_xmpp_jingle_cont_desc_payload_param; +extern gint ett_xmpp_jingle_cont_trans; +extern gint ett_xmpp_jingle_cont_trans_cand; +extern gint ett_xmpp_jingle_cont_trans_rem_cand; +extern gint ett_xmpp_jingle_reason; +extern gint ett_xmpp_jingle_rtp_info; +extern gint ett_xmpp_jingle_file_transfer_offer; +extern gint ett_xmpp_jingle_file_transfer_request; +extern gint ett_xmpp_jingle_file_transfer_received; +extern gint ett_xmpp_jingle_file_transfer_abort; +extern gint ett_xmpp_jingle_file_transfer_checksum; +extern gint ett_xmpp_jingle_file_transfer_file; + +extern gint ett_xmpp_services; +extern gint ett_xmpp_services_relay; +extern gint ett_xmpp_channel; + +extern gint ett_xmpp_si; +extern gint ett_xmpp_si_file; +extern gint ett_xmpp_si_file_range; + +extern gint ett_xmpp_iq_feature_neg; +extern gint ett_xmpp_x_data; +extern gint ett_xmpp_x_data_field; +extern gint ett_xmpp_x_data_field_value; + +extern gint ett_xmpp_ibb_open; +extern gint ett_xmpp_ibb_close; +extern gint ett_xmpp_ibb_data; + +extern gint ett_xmpp_delay; + +extern gint ett_xmpp_x_event; + +extern gint ett_xmpp_message; +extern gint ett_xmpp_message_thread; +extern gint ett_xmpp_message_body; +extern gint ett_xmpp_message_subject; + +extern gint ett_xmpp_presence; +extern gint ett_xmpp_presence_status; +extern gint ett_xmpp_presence_caps; + +extern gint ett_xmpp_auth; +extern gint ett_xmpp_challenge; +extern gint ett_xmpp_response; +extern gint ett_xmpp_success; +extern gint ett_xmpp_failure; +extern gint ett_xmpp_stream; +extern gint ett_xmpp_features; +extern gint ett_xmpp_features_mechanisms; +extern gint ett_xmpp_proceed; +extern gint ett_xmpp_starttls; + +extern gint ett_xmpp_muc_x; +extern gint ett_xmpp_muc_hist; +extern gint ett_xmpp_muc_user_x; +extern gint ett_xmpp_muc_user_item; +extern gint ett_xmpp_muc_user_invite; + +extern gint ett_xmpp_gtalk_session; +extern gint ett_xmpp_gtalk_session_desc; +extern gint ett_xmpp_gtalk_session_desc_payload; +extern gint ett_xmpp_gtalk_session_cand; +extern gint ett_xmpp_gtalk_session_reason; +extern gint ett_xmpp_gtalk_jingleinfo_stun; +extern gint ett_xmpp_gtalk_jingleinfo_server; +extern gint ett_xmpp_gtalk_jingleinfo_relay; +extern gint ett_xmpp_gtalk_jingleinfo_relay_serv; +extern gint ett_xmpp_gtalk_setting; +extern gint ett_xmpp_gtalk_nosave_x; +extern gint ett_xmpp_gtalk_mail_mailbox; +extern gint ett_xmpp_gtalk_mail_mail_info; +extern gint ett_xmpp_gtalk_mail_senders; +extern gint ett_xmpp_gtalk_mail_sender; +extern gint ett_xmpp_gtalk_status_status_list; +extern gint ett_xmpp_gtalk_transport_p2p; +extern gint ett_xmpp_gtalk_transport_p2p_cand; + + +extern gint ett_xmpp_conf_info; +extern gint ett_xmpp_conf_desc; +extern gint ett_xmpp_conf_state; +extern gint ett_xmpp_conf_users; +extern gint ett_xmpp_conf_user; +extern gint ett_xmpp_conf_endpoint; +extern gint ett_xmpp_conf_media; + +extern gint ett_xmpp_ping; +extern gint ett_xmpp_hashes; +extern gint ett_xmpp_hashes_hash; + +extern gint ett_xmpp_jitsi_inputevt; +extern gint ett_xmpp_jitsi_inputevt_rmt_ctrl; + +extern gint ett_unknown[ETT_UNKNOWN_LEN]; +#endif /* PACKET_XMPP_H */ + |