2 * Wireshark's XMPP dissector.
4 * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include <epan/wmem/wmem.h>
33 #include <epan/conversation.h>
34 #include <epan/expert.h>
36 #include <epan/dissectors/packet-xml.h>
38 #include <packet-xmpp-utils.h>
39 #include <packet-xmpp.h>
40 #include <packet-xmpp-core.h>
41 #include <packet-xmpp-jingle.h>
42 #include <packet-xmpp-other.h>
43 #include <packet-xmpp-gtalk.h>
44 #include <packet-xmpp-conference.h>
46 #include <epan/strutil.h>
48 #include "epan/tvbparse.h"
50 tvbparse_wanted_t
*want_ignore
;
51 tvbparse_wanted_t
*want_stream_end_tag
;
52 tvbparse_wanted_t
*want_stream_end_with_ns
;
54 static void xmpp_error(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
55 static void xmpp_error_text(proto_tree
*tree
, tvbuff_t
*tvb
, xmpp_element_t
*element
);
57 static void xmpp_presence_status(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
59 static void xmpp_message_thread(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
60 static void xmpp_message_body(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
61 static void xmpp_message_subject(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
63 static void xmpp_failure_text(proto_tree
*tree
, tvbuff_t
*tvb
, xmpp_element_t
*element
);
65 static void xmpp_features_mechanisms(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
);
68 xmpp_init_parsers(void)
70 tvbparse_wanted_t
*want_name
;
71 tvbparse_wanted_t
*want_stream_end
;
73 want_name
= tvbparse_chars(2,1,0,"abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",NULL
,NULL
,NULL
);
75 want_stream_end_with_ns
= tvbparse_set_seq(3, NULL
, NULL
, NULL
,
77 tvbparse_char(4, ":", NULL
, NULL
, NULL
),
81 want_stream_end
= tvbparse_set_oneof(5, NULL
, NULL
, NULL
,
82 want_stream_end_with_ns
,
86 want_ignore
= tvbparse_chars(1,1,0," \t\r\n",NULL
,NULL
,NULL
);
88 want_stream_end_tag
= tvbparse_set_seq(6, NULL
, NULL
, NULL
,
89 tvbparse_string(-1,"</",NULL
,NULL
,NULL
),
91 tvbparse_char(-1,">",NULL
,NULL
,NULL
),
96 xmpp_iq(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
98 proto_item
*xmpp_iq_item
;
99 proto_tree
*xmpp_iq_tree
;
101 xmpp_attr_t
*attr_id
, *attr_type
;
103 xmpp_attr_info attrs_info
[] = {
104 {"xmlns", hf_xmpp_xmlns
, FALSE
, FALSE
, NULL
, NULL
},
105 {"id", hf_xmpp_id
, TRUE
, TRUE
, NULL
, NULL
},
106 {"type", hf_xmpp_type
, TRUE
, TRUE
, NULL
, NULL
},
107 {"from", hf_xmpp_from
, FALSE
, TRUE
, NULL
, NULL
},
108 {"to", hf_xmpp_to
, FALSE
, TRUE
, NULL
, NULL
},
109 {"xml:lang", -1, FALSE
, FALSE
, NULL
, NULL
}
112 conversation_t
*conversation
;
113 xmpp_conv_info_t
*xmpp_info
;
114 xmpp_transaction_t
*reqresp_trans
;
116 xmpp_elem_info elems_info
[] = {
117 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns","http://jabber.org/protocol/disco#items"), xmpp_disco_items_query
, ONE
},
118 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns", "jabber:iq:roster"), xmpp_roster_query
, ONE
},
119 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns", "http://jabber.org/protocol/disco#info"), xmpp_disco_info_query
, ONE
},
120 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns", "http://jabber.org/protocol/bytestreams"), xmpp_bytestreams_query
, ONE
},
121 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns", "http://jabber.org/protocol/muc#owner"), xmpp_muc_owner_query
, ONE
},
122 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns", "http://jabber.org/protocol/muc#admin"), xmpp_muc_admin_query
, ONE
},
123 {NAME
, "bind", xmpp_iq_bind
, ONE
},
124 {NAME_AND_ATTR
, xmpp_name_attr_struct("session", "xmlns", "urn:ietf:params:xml:ns:xmpp-session"), xmpp_session
, ONE
},
125 {NAME
, "vCard", xmpp_vcard
, ONE
},
126 {NAME
, "jingle", xmpp_jingle
, ONE
},
127 {NAME_AND_ATTR
, xmpp_name_attr_struct("services", "xmlns", "http://jabber.org/protocol/jinglenodes"), xmpp_jinglenodes_services
, ONE
},
128 {NAME_AND_ATTR
, xmpp_name_attr_struct("channel", "xmlns", "http://jabber.org/protocol/jinglenodes#channel"), xmpp_jinglenodes_channel
, ONE
},
129 {NAME_AND_ATTR
, xmpp_name_attr_struct("open", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_open
, ONE
},
130 {NAME_AND_ATTR
, xmpp_name_attr_struct("close", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_close
, ONE
},
131 {NAME_AND_ATTR
, xmpp_name_attr_struct("data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data
, ONE
},
132 {NAME
, "si", xmpp_si
, ONE
},
133 {NAME
, "error", xmpp_error
, ONE
},
134 {NAME_AND_ATTR
, xmpp_name_attr_struct("session", "xmlns", "http://www.google.com/session"), xmpp_gtalk_session
, ONE
},
135 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns","google:jingleinfo"), xmpp_gtalk_jingleinfo_query
, ONE
},
136 {NAME_AND_ATTR
, xmpp_name_attr_struct("usersetting", "xmlns","google:setting"), xmpp_gtalk_usersetting
, ONE
},
137 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns","jabber:iq:last"), xmpp_last_query
, ONE
},
138 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns","jabber:iq:version"), xmpp_version_query
, ONE
},
139 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns","google:mail:notify"), xmpp_gtalk_mail_query
, ONE
},
140 {NAME
, "mailbox", xmpp_gtalk_mail_mailbox
, ONE
},
141 {NAME
, "new-mail", xmpp_gtalk_mail_new_mail
, ONE
},
142 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns","google:shared-status"), xmpp_gtalk_status_query
, ONE
},
143 {NAME
, "conference-info", xmpp_conference_info
, ONE
},
144 {NAME_AND_ATTR
, xmpp_name_attr_struct("ping", "xmlns","urn:xmpp:ping"), xmpp_ping
, ONE
},
145 {NAME_AND_ATTR
, xmpp_name_attr_struct("inputevt", "xmlns","http://jitsi.org/protocol/inputevt"), xmpp_jitsi_inputevt
, ONE
},
148 attr_id
= xmpp_get_attr(packet
, "id");
149 attr_type
= xmpp_get_attr(packet
, "type");
151 conversation
= find_or_create_conversation(pinfo
);
152 xmpp_info
= (xmpp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_xmpp
);
154 xmpp_iq_item
= proto_tree_add_item(tree
, hf_xmpp_iq
, tvb
, packet
->offset
, packet
->length
, ENC_LITTLE_ENDIAN
);
155 xmpp_iq_tree
= proto_item_add_subtree(xmpp_iq_item
,ett_xmpp_iq
);
157 xmpp_display_attrs(xmpp_iq_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
160 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "IQ(%s) ", attr_type
?attr_type
->value
:"");
162 xmpp_display_elems(xmpp_iq_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
164 /*displays generated info such as req/resp tracking, jingle sid
165 * in each packet related to specified jingle session and IBB sid in packet related to it*/
166 if(xmpp_info
&& attr_id
)
168 gchar
*jingle_sid
, *ibb_sid
, *gtalk_sid
;
170 jingle_sid
= (gchar
*)wmem_tree_lookup_string(xmpp_info
->jingle_sessions
, attr_id
->value
, WMEM_TREE_STRING_NOCASE
);
173 proto_item
*it
= proto_tree_add_string(tree
, hf_xmpp_jingle_session
, tvb
, 0, 0, jingle_sid
);
174 PROTO_ITEM_SET_GENERATED(it
);
177 ibb_sid
= (gchar
*)wmem_tree_lookup_string(xmpp_info
->ibb_sessions
, attr_id
->value
, WMEM_TREE_STRING_NOCASE
);
180 proto_item
*it
= proto_tree_add_string(tree
, hf_xmpp_ibb
, tvb
, 0, 0, ibb_sid
);
181 PROTO_ITEM_SET_GENERATED(it
);
184 gtalk_sid
= (gchar
*)wmem_tree_lookup_string(xmpp_info
->gtalk_sessions
, attr_id
->value
, WMEM_TREE_STRING_NOCASE
);
187 proto_item
*it
= proto_tree_add_string(tree
, hf_xmpp_gtalk
, tvb
, 0, 0, gtalk_sid
);
188 PROTO_ITEM_SET_GENERATED(it
);
191 reqresp_trans
= (xmpp_transaction_t
*)wmem_tree_lookup_string(xmpp_info
->req_resp
, attr_id
->value
, WMEM_TREE_STRING_NOCASE
);
192 /*displays request/response field in each iq packet*/
195 if (reqresp_trans
->req_frame
== pinfo
->fd
->num
) {
196 if (reqresp_trans
->resp_frame
) {
197 proto_item
*it
= proto_tree_add_uint(tree
, hf_xmpp_response_in
, tvb
, 0, 0, reqresp_trans
->resp_frame
);
198 PROTO_ITEM_SET_GENERATED(it
);
201 expert_add_info(pinfo
, xmpp_iq_item
, &ei_xmpp_packet_without_response
);
205 if (reqresp_trans
->req_frame
) {
206 proto_item
*it
= proto_tree_add_uint(tree
, hf_xmpp_response_to
, tvb
, 0, 0, reqresp_trans
->req_frame
);
207 PROTO_ITEM_SET_GENERATED(it
);
210 expert_add_info(pinfo
, xmpp_iq_item
, &ei_xmpp_packet_without_response
);
219 xmpp_error(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
221 proto_item
*error_item
;
222 proto_tree
*error_tree
;
224 xmpp_element_t
*text_element
, *cond_element
;
226 xmpp_attr_info attrs_info
[] = {
227 {"type", hf_xmpp_error_type
, TRUE
, TRUE
, NULL
, NULL
},
228 {"code", hf_xmpp_error_code
, FALSE
, TRUE
, NULL
, NULL
},
229 {"condition", hf_xmpp_error_condition
, TRUE
, TRUE
, NULL
, NULL
} /*TODO: validate list to the condition element*/
234 xmpp_attr_t
*fake_condition
= NULL
;
236 error_info
= wmem_strdup(wmem_packet_scope(), "Stanza error");
238 error_item
= proto_tree_add_item(tree
, hf_xmpp_error
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
239 error_tree
= proto_item_add_subtree(error_item
, ett_xmpp_query_item
);
241 cond_element
= xmpp_steal_element_by_attr(element
, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
244 fake_condition
= xmpp_ep_init_attr_t(cond_element
->name
, cond_element
->offset
, cond_element
->length
);
245 g_hash_table_insert(element
->attrs
, (gpointer
)"condition", fake_condition
);
247 error_info
= wmem_strdup_printf(wmem_packet_scope(), "%s: %s;", error_info
, cond_element
->name
);
251 xmpp_display_attrs(error_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
253 while((text_element
= xmpp_steal_element_by_name(element
, "text")) != NULL
)
255 xmpp_error_text(error_tree
, tvb
, text_element
);
257 error_info
= wmem_strdup_printf(wmem_packet_scope(), "%s Text: %s", error_info
, text_element
->data
?text_element
->data
->value
:"");
260 expert_add_info_format(pinfo
, error_item
, &ei_xmpp_response
, "%s", error_info
);
262 xmpp_unknown(error_tree
, tvb
, pinfo
, element
);
266 xmpp_error_text(proto_tree
*tree
, tvbuff_t
*tvb
, xmpp_element_t
*element
)
268 proto_tree_add_string(tree
, hf_xmpp_error_text
, tvb
, element
->offset
, element
->length
, element
->data
?element
->data
->value
:"");
273 xmpp_presence(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
275 proto_item
*presence_item
;
276 proto_tree
*presence_tree
;
278 static const gchar
*type_enums
[] = {"error", "probe", "subscribe", "subscribed",
279 "unavailable", "unsubscribe", "unsubscribed"};
280 xmpp_array_t
*type_array
= xmpp_ep_init_array_t(type_enums
, array_length(type_enums
));
282 static const gchar
*show_enums
[] = {"away", "chat", "dnd", "xa"};
283 xmpp_array_t
*show_array
= xmpp_ep_init_array_t(show_enums
, array_length(show_enums
));
285 xmpp_attr_info attrs_info
[] = {
286 {"from", hf_xmpp_from
, FALSE
, FALSE
, NULL
, NULL
},
287 {"id", hf_xmpp_id
, FALSE
, TRUE
, NULL
, NULL
},
288 {"to", hf_xmpp_to
, FALSE
, FALSE
, NULL
, NULL
},
289 {"type", hf_xmpp_type
, FALSE
, TRUE
, xmpp_val_enum_list
, type_array
},
290 {"xml:lang",-1, FALSE
, FALSE
, NULL
,NULL
},
291 {"show", hf_xmpp_presence_show
, FALSE
, TRUE
, xmpp_val_enum_list
, show_array
},
292 {"priority", -1, FALSE
, FALSE
, NULL
, NULL
}
295 xmpp_elem_info elems_info
[] = {
296 {NAME
, "status", xmpp_presence_status
, MANY
},
297 {NAME_AND_ATTR
, xmpp_name_attr_struct("c","xmlns","http://jabber.org/protocol/caps"), xmpp_presence_caps
, ONE
},
298 {NAME
, "delay", xmpp_delay
, ONE
},
299 {NAME_AND_ATTR
, xmpp_name_attr_struct("x","xmlns", "jabber:x:delay"), xmpp_delay
, ONE
},
300 {NAME_AND_ATTR
, xmpp_name_attr_struct("x","xmlns", "vcard-temp:x:update"), xmpp_vcard_x_update
, ONE
},
301 {NAME_AND_ATTR
, xmpp_name_attr_struct("x","xmlns","http://jabber.org/protocol/muc"), xmpp_muc_x
, ONE
},
302 {NAME_AND_ATTR
, xmpp_name_attr_struct("x","xmlns","http://jabber.org/protocol/muc#user"), xmpp_muc_user_x
, ONE
},
303 {NAME
, "error", xmpp_error
, ONE
},
304 {NAME_AND_ATTR
, xmpp_name_attr_struct("query", "xmlns","jabber:iq:last"), xmpp_last_query
, ONE
}
308 xmpp_element_t
*show
, *priority
;
310 col_set_str(pinfo
->cinfo
, COL_INFO
, "PRESENCE ");
312 presence_item
= proto_tree_add_item(tree
, hf_xmpp_presence
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
313 presence_tree
= proto_item_add_subtree(presence_item
, ett_xmpp_presence
);
315 if((show
= xmpp_steal_element_by_name(packet
, "show"))!=NULL
)
317 xmpp_attr_t
*fake_show
= xmpp_ep_init_attr_t(show
->data
?show
->data
->value
:"",show
->offset
, show
->length
);
318 g_hash_table_insert(packet
->attrs
, (gpointer
)"show", fake_show
);
321 if((priority
= xmpp_steal_element_by_name(packet
, "priority"))!=NULL
)
323 xmpp_attr_t
*fake_priority
= xmpp_ep_init_attr_t(priority
->data
?priority
->data
->value
:"",priority
->offset
, priority
->length
);
324 g_hash_table_insert(packet
->attrs
, (gpointer
)"priority", fake_priority
);
326 xmpp_display_attrs(presence_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
328 xmpp_display_elems(presence_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
332 xmpp_presence_status(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
334 proto_item
*status_item
;
335 proto_tree
*status_tree
;
337 xmpp_attr_info attrs_info
[] = {
338 {"xml:lang", -1, FALSE
, TRUE
, NULL
, NULL
},
339 {"value", -1, TRUE
, TRUE
, NULL
, NULL
}
342 xmpp_attr_t
*fake_value
;
344 status_item
= proto_tree_add_item(tree
, hf_xmpp_presence_status
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
345 status_tree
= proto_item_add_subtree(status_item
, ett_xmpp_presence_status
);
348 fake_value
= xmpp_ep_init_attr_t(element
->data
->value
, element
->offset
, element
->length
);
350 fake_value
= xmpp_ep_init_attr_t("(empty)", element
->offset
, element
->length
);
353 g_hash_table_insert(element
->attrs
, (gpointer
)"value", fake_value
);
355 xmpp_display_attrs(status_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
357 xmpp_unknown(status_tree
, tvb
, pinfo
, element
);
362 xmpp_message(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
364 proto_item
*message_item
;
365 proto_tree
*message_tree
;
367 static const gchar
*type_enums
[] = {"chat", "error", "groupchat", "headline", "normal"};
368 xmpp_array_t
*type_array
= xmpp_ep_init_array_t(type_enums
, array_length(type_enums
));
370 xmpp_attr_info attrs_info
[] = {
371 {"from", hf_xmpp_from
, FALSE
, FALSE
, NULL
, NULL
},
372 {"id", hf_xmpp_id
, FALSE
, TRUE
, NULL
, NULL
},
373 {"to", hf_xmpp_to
, FALSE
, FALSE
, NULL
, NULL
},
374 {"type", hf_xmpp_type
, FALSE
, TRUE
, xmpp_val_enum_list
, type_array
},
375 {"xml:lang",-1, FALSE
, FALSE
, NULL
,NULL
},
376 {"chatstate", hf_xmpp_message_chatstate
, FALSE
, TRUE
, NULL
, NULL
}
379 xmpp_elem_info elems_info
[] = {
380 {NAME_AND_ATTR
, xmpp_name_attr_struct("data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data
, ONE
},
381 {NAME
, "thread", xmpp_message_thread
, ONE
},
382 {NAME
, "body", xmpp_message_body
, MANY
},
383 {NAME
, "subject", xmpp_message_subject
, MANY
},
384 {NAME
, "delay", xmpp_delay
, ONE
},
385 {NAME_AND_ATTR
, xmpp_name_attr_struct("x","xmlns","jabber:x:event"), xmpp_x_event
, ONE
},
386 {NAME_AND_ATTR
, xmpp_name_attr_struct("x","xmlns","http://jabber.org/protocol/muc#user"), xmpp_muc_user_x
, ONE
},
387 {NAME_AND_ATTR
, xmpp_name_attr_struct("x","xmlns","google:nosave"), xmpp_gtalk_nosave_x
, ONE
},
388 {NAME
, "error", xmpp_error
, ONE
}
391 xmpp_element_t
*chatstate
;
395 conversation_t
*conversation
;
396 xmpp_conv_info_t
*xmpp_info
;
398 col_set_str(pinfo
->cinfo
, COL_INFO
, "MESSAGE ");
400 id
= xmpp_get_attr(packet
, "id");
402 conversation
= find_or_create_conversation(pinfo
);
403 xmpp_info
= (xmpp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_xmpp
);
405 message_item
= proto_tree_add_item(tree
, hf_xmpp_message
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
406 message_tree
= proto_item_add_subtree(message_item
, ett_xmpp_message
);
408 if((chatstate
= xmpp_steal_element_by_attr(packet
, "xmlns", "http://jabber.org/protocol/chatstates"))!=NULL
)
410 xmpp_attr_t
*fake_chatstate_attr
= xmpp_ep_init_attr_t(chatstate
->name
, chatstate
->offset
, chatstate
->length
);
411 g_hash_table_insert(packet
->attrs
, (gpointer
)"chatstate", fake_chatstate_attr
);
414 xmpp_display_attrs(message_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
416 xmpp_display_elems(message_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
418 /*Displays data about IBB session*/
423 ibb_sid
= (gchar
*)wmem_tree_lookup_string(xmpp_info
->ibb_sessions
, id
->value
, WMEM_TREE_STRING_NOCASE
);
426 proto_item
*it
= proto_tree_add_string(tree
, hf_xmpp_ibb
, tvb
, 0, 0, ibb_sid
);
427 PROTO_ITEM_SET_GENERATED(it
);
434 xmpp_message_body(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
436 proto_item
*body_item
;
437 proto_tree
*body_tree
;
439 xmpp_attr_info attrs_info
[] = {
440 {"xml:lang", -1, FALSE
, TRUE
, NULL
, NULL
},
441 {"value", -1, TRUE
, TRUE
, NULL
, NULL
}
444 xmpp_attr_t
*fake_data_attr
;
446 body_item
= proto_tree_add_item(tree
, hf_xmpp_message_body
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
447 body_tree
= proto_item_add_subtree(body_item
, ett_xmpp_message_body
);
449 fake_data_attr
= xmpp_ep_init_attr_t(element
->data
?element
->data
->value
:"", element
->offset
, element
->length
);
450 g_hash_table_insert(element
->attrs
, (gpointer
)"value", fake_data_attr
);
453 xmpp_display_attrs(body_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
455 xmpp_unknown(body_tree
, tvb
, pinfo
, element
);
459 xmpp_message_subject(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
) {
460 proto_item
*subject_item
;
461 proto_tree
*subject_tree
;
463 xmpp_attr_info attrs_info
[] = {
464 {"xml:lang", -1, FALSE
, TRUE
, NULL
, NULL
},
465 {"value", -1, TRUE
, FALSE
, NULL
, NULL
}
468 xmpp_attr_t
*fake_data_attr
;
470 subject_item
= proto_tree_add_item(tree
, hf_xmpp_message_subject
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
471 subject_tree
= proto_item_add_subtree(subject_item
, ett_xmpp_message_subject
);
473 fake_data_attr
= xmpp_ep_init_attr_t(element
->data
?element
->data
->value
:"", element
->offset
, element
->length
);
474 g_hash_table_insert(element
->attrs
, (gpointer
)"value", fake_data_attr
);
477 xmpp_display_attrs(subject_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
479 xmpp_unknown(subject_tree
, tvb
, pinfo
, element
);
483 xmpp_message_thread(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
485 proto_item
*thread_item
;
486 proto_tree
*thread_tree
;
488 xmpp_attr_info attrs_info
[] = {
489 {"parent", hf_xmpp_message_thread_parent
, FALSE
, TRUE
, NULL
, NULL
},
490 {"value", -1, TRUE
, TRUE
, NULL
, NULL
}
493 xmpp_attr_t
*fake_value
;
495 thread_item
= proto_tree_add_item(tree
, hf_xmpp_message_thread
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
496 thread_tree
= proto_item_add_subtree(thread_item
, ett_xmpp_message_thread
);
498 fake_value
= xmpp_ep_init_attr_t(element
->data
?element
->data
->value
:"", element
->offset
, element
->length
);
499 g_hash_table_insert(element
->attrs
, (gpointer
)"value", fake_value
);
502 xmpp_display_attrs(thread_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
504 xmpp_unknown(thread_tree
, tvb
, pinfo
, element
);
508 xmpp_auth(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
510 proto_item
*auth_item
;
511 proto_tree
*auth_tree
;
513 xmpp_attr_info_ext attrs_info
[]={
514 {"urn:ietf:params:xml:ns:xmpp-sasl", {"xmlns", hf_xmpp_xmlns
, TRUE
, TRUE
, NULL
, NULL
}},
515 {"urn:ietf:params:xml:ns:xmpp-sasl", {"mechanism", -1, TRUE
, TRUE
, NULL
, NULL
}},
516 {"http://www.google.com/talk/protocol/auth", {"xmlns", hf_xmpp_xmlns
, TRUE
, TRUE
, NULL
, NULL
}},
517 {"http://www.google.com/talk/protocol/auth", {"client-uses-full-bind-result", -1, TRUE
, TRUE
, NULL
, NULL
}},
520 col_set_str(pinfo
->cinfo
, COL_INFO
, "AUTH");
522 auth_item
= proto_tree_add_item(tree
, hf_xmpp_auth
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
523 auth_tree
= proto_item_add_subtree(auth_item
, ett_xmpp_auth
);
525 xmpp_display_attrs_ext(auth_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
527 xmpp_cdata(auth_tree
, tvb
, packet
, -1);
529 xmpp_unknown(auth_tree
, tvb
, pinfo
, packet
);
533 xmpp_challenge_response_success(proto_tree
*tree
, tvbuff_t
*tvb
,
534 packet_info
*pinfo
, xmpp_element_t
*packet
, expert_field
* ei
, gint ett
, const char *col_info
)
539 xmpp_attr_info attrs_info
[] = {
540 {"xmlns", hf_xmpp_xmlns
, TRUE
, TRUE
, NULL
, NULL
}
543 col_set_str(pinfo
->cinfo
, COL_INFO
, col_info
);
545 item
= proto_tree_add_expert(tree
, pinfo
, ei
, tvb
, packet
->offset
, packet
->length
);
546 subtree
= proto_item_add_subtree(item
, ett
);
548 xmpp_display_attrs(subtree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
549 xmpp_cdata(subtree
, tvb
, packet
, -1);
551 xmpp_unknown(subtree
, tvb
, pinfo
, packet
);
555 xmpp_failure(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
557 proto_item
*fail_item
;
558 proto_tree
*fail_tree
;
560 xmpp_attr_info attrs_info
[] = {
561 {"xmlns", hf_xmpp_xmlns
, TRUE
, TRUE
, NULL
, NULL
},
562 {"condition", -1, FALSE
, TRUE
, NULL
, NULL
}
565 static const gchar
*fail_names
[] = {"aborted","account-disabled", "credentials-expired",
566 "encryption-required", "incorrect-encoding", "invalid-authzid", "invalid-mechanism",
567 "malformed-request", "mechanism-too-weak", "not-authorized", "temporary-auth-failure",
571 xmpp_element_t
*fail_condition
, *text
;
573 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "FAILURE ");
575 fail_item
= proto_tree_add_item(tree
, hf_xmpp_failure
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
576 fail_tree
= proto_item_add_subtree(fail_item
, ett_xmpp_failure
);
578 if((fail_condition
= xmpp_steal_element_by_names(packet
, fail_names
, array_length(fail_names
)))!=NULL
)
580 xmpp_attr_t
*fake_cond
= xmpp_ep_init_attr_t(fail_condition
->name
, fail_condition
->offset
, fail_condition
->length
);
581 g_hash_table_insert(packet
->attrs
, (gpointer
)"condition", fake_cond
);
584 if((text
= xmpp_steal_element_by_name(packet
, "text"))!=NULL
)
586 xmpp_failure_text(fail_tree
, tvb
, text
);
589 xmpp_display_attrs(fail_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
591 xmpp_unknown(fail_tree
, tvb
, pinfo
, packet
);
595 xmpp_failure_text(proto_tree
*tree
, tvbuff_t
*tvb
, xmpp_element_t
*element
)
597 xmpp_attr_t
*lang
= xmpp_get_attr(element
,"xml:lang");
599 proto_tree_add_text(tree
, tvb
, element
->offset
, element
->length
, "TEXT%s: %s",
600 lang
?wmem_strdup_printf(wmem_packet_scope(), "(%s)",lang
->value
):"",
601 element
->data
?element
->data
->value
:"");
605 xmpp_xml_header(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo _U_
, xmpp_element_t
*packet
)
607 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "XML ");
608 proto_tree_add_text(tree
, tvb
, packet
->offset
, packet
->length
, "XML HEADER VER. %s","1.0");
612 xmpp_stream(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
614 proto_item
*stream_item
;
615 proto_tree
*stream_tree
;
617 xmpp_attr_info_ext attrs_info
[] = {
618 {"http://etherx.jabber.org/streams",{"xmlns", hf_xmpp_xmlns
, FALSE
, TRUE
, NULL
, NULL
}},
619 {"http://etherx.jabber.org/streams",{"version", -1, FALSE
, TRUE
, NULL
, NULL
}},
620 {"http://etherx.jabber.org/streams",{"from",-1, FALSE
, TRUE
, NULL
, NULL
}},
621 {"http://etherx.jabber.org/streams",{"to",-1, FALSE
, TRUE
, NULL
, NULL
}},
622 {"http://etherx.jabber.org/streams",{"id",-1, FALSE
, TRUE
, NULL
, NULL
}},
623 {"http://etherx.jabber.org/streams",{"xml:lang",-1, FALSE
, TRUE
, NULL
, NULL
}},
624 {"jabber:client",{"xmlns", hf_xmpp_xmlns
, FALSE
, TRUE
, NULL
, NULL
}},
628 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "STREAM ");
630 stream_item
= proto_tree_add_item(tree
, hf_xmpp_stream
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
631 stream_tree
= proto_item_add_subtree(stream_item
, ett_xmpp_stream
);
633 xmpp_display_attrs_ext(stream_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
634 xmpp_display_elems(stream_tree
, packet
, pinfo
, tvb
, NULL
, 0);
637 /*returns TRUE if stream end occurs*/
639 xmpp_stream_close(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
* pinfo
)
642 tvbparse_elem_t
*elem
;
644 tt
= tvbparse_init(tvb
,0,-1,NULL
,want_ignore
);
646 if((elem
= tvbparse_get(tt
,want_stream_end_tag
))!=NULL
)
648 proto_tree_add_text(tree
, tvb
, elem
->offset
, elem
->len
, "STREAM END");
649 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "STREAM END");
657 xmpp_features(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
659 proto_item
*features_item
;
660 proto_tree
*features_tree
;
662 xmpp_elem_info elems_info
[] = {
663 {NAME
, "mechanisms", xmpp_features_mechanisms
, MANY
}
666 features_item
= proto_tree_add_item(tree
, hf_xmpp_features
, tvb
, packet
->offset
, packet
->length
,
668 features_tree
= proto_item_add_subtree(features_item
, ett_xmpp_features
);
670 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "FEATURES ");
672 xmpp_display_attrs(features_tree
, packet
, pinfo
, tvb
, NULL
, 0);
673 xmpp_display_elems(features_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
677 xmpp_features_mechanisms(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
679 proto_item
*mechanisms_item
;
680 proto_tree
*mechanisms_tree
;
682 xmpp_attr_info attrs_info
[] = {
683 {"xmlns", hf_xmpp_xmlns
, TRUE
, TRUE
, NULL
, NULL
}
686 xmpp_elem_info elems_info
[] = {
687 {NAME
, "mechanism", xmpp_simple_cdata_elem
, MANY
},
690 mechanisms_item
= proto_tree_add_text(tree
, tvb
, packet
->offset
, packet
->length
, "MECHANISMS");
691 mechanisms_tree
= proto_item_add_subtree(mechanisms_item
, ett_xmpp_features_mechanisms
);
693 xmpp_display_attrs(mechanisms_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
694 xmpp_display_elems(mechanisms_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
698 xmpp_starttls(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
,
699 xmpp_element_t
*packet
, xmpp_conv_info_t
*xmpp_info
)
701 proto_item
*tls_item
;
702 proto_tree
*tls_tree
;
704 xmpp_attr_info attrs_info
[] = {
705 {"xmlns", hf_xmpp_xmlns
, TRUE
, TRUE
, NULL
, NULL
},
708 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "STARTTLS ");
710 tls_item
= proto_tree_add_item(tree
, hf_xmpp_starttls
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
711 tls_tree
= proto_item_add_subtree(tls_item
, ett_xmpp_starttls
);
713 if (xmpp_info
->ssl_start
&& xmpp_info
->ssl_start
!= pinfo
->fd
->num
) {
714 expert_add_info_format(pinfo
, tls_item
, &ei_xmpp_starttls_already_in_frame
, "Already saw STARTTLS in frame %u", xmpp_info
->ssl_start
);
717 xmpp_info
->ssl_start
= pinfo
->fd
->num
;
720 xmpp_display_attrs(tls_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
721 xmpp_display_elems(tls_tree
, packet
, pinfo
, tvb
, NULL
, 0);
725 xmpp_proceed(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
,
726 xmpp_element_t
*packet
, xmpp_conv_info_t
*xmpp_info
)
728 proto_item
*proceed_item
;
729 proto_tree
*proceed_tree
;
731 xmpp_attr_info attrs_info
[] = {
732 {"xmlns", hf_xmpp_xmlns
, TRUE
, TRUE
, NULL
, NULL
},
735 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "PROCEED ");
737 proceed_item
= proto_tree_add_item(tree
, hf_xmpp_proceed
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
738 proceed_tree
= proto_item_add_subtree(proceed_item
, ett_xmpp_proceed
);
740 if (!xmpp_info
->ssl_start
) {
741 expert_add_info(pinfo
, proceed_item
, &ei_xmpp_starttls_missing
);
744 if (xmpp_info
->ssl_proceed
&& xmpp_info
->ssl_proceed
!= pinfo
->fd
->num
) {
745 expert_add_info_format(pinfo
, proceed_item
, &ei_xmpp_proceed_already_in_frame
, "Already saw PROCEED in frame %u", xmpp_info
->ssl_proceed
);
748 xmpp_info
->ssl_proceed
= pinfo
->fd
->num
;
751 xmpp_display_attrs(proceed_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
752 xmpp_display_elems(proceed_tree
, packet
, pinfo
, tvb
, NULL
, 0);
755 * Editor modelines - http://www.wireshark.org/tools/modelines.html
760 * indent-tabs-mode: nil
763 * ex: set shiftwidth=4 tabstop=8 expandtab:
764 * :indentSize=4:tabSize=8:noTabs=true: