epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-xmpp-core.c
blob4e20574b5bc76c84a3695e1c791e3161e1783eaa
1 /* xmpp-core.c
2 * Wireshark's XMPP dissector.
4 * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <epan/conversation.h>
18 #include "packet-xmpp.h"
19 #include "packet-xmpp-core.h"
20 #include "packet-xmpp-jingle.h"
21 #include "packet-xmpp-other.h"
22 #include "packet-xmpp-gtalk.h"
23 #include "packet-xmpp-conference.h"
24 #include "packet-tls-utils.h"
26 tvbparse_wanted_t *want_ignore;
27 tvbparse_wanted_t *want_stream_end_tag;
28 tvbparse_wanted_t *want_stream_end_with_ns;
30 static void xmpp_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element);
31 static void xmpp_error_text(proto_tree *tree, tvbuff_t *tvb, xmpp_element_t *element);
33 static void xmpp_presence_status(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element);
35 static void xmpp_message_thread(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element);
36 static void xmpp_message_body(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element);
37 static void xmpp_message_subject(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element);
39 static void xmpp_failure_text(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element);
41 static void xmpp_features_mechanisms(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet);
43 void
44 xmpp_init_parsers(void)
46 tvbparse_wanted_t *want_name;
47 tvbparse_wanted_t *want_stream_end;
49 want_name = tvbparse_chars(2,1,0,"abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",NULL,NULL,NULL);
51 want_stream_end_with_ns = tvbparse_set_seq(3, NULL, NULL, NULL,
52 want_name,
53 tvbparse_char(4, ":", NULL, NULL, NULL),
54 want_name,
55 NULL);
57 want_stream_end = tvbparse_set_oneof(5, NULL, NULL, NULL,
58 want_stream_end_with_ns,
59 want_name,
60 NULL);
62 want_ignore = tvbparse_chars(1,1,0," \t\r\n",NULL,NULL,NULL);
64 want_stream_end_tag = tvbparse_set_seq(6, NULL, NULL, NULL,
65 tvbparse_string(-1,"</",NULL,NULL,NULL),
66 want_stream_end,
67 tvbparse_char(-1,">",NULL,NULL,NULL),
68 NULL);
71 void
72 xmpp_iq(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet)
74 proto_item *xmpp_iq_item;
75 proto_tree *xmpp_iq_tree;
77 xmpp_attr_t *attr_id, *attr_type;
79 xmpp_attr_info attrs_info[] = {
80 {"xmlns", &hf_xmpp_xmlns, false, false, NULL, NULL},
81 {"id", &hf_xmpp_id, true, true, NULL, NULL},
82 {"type", &hf_xmpp_type, true, true, NULL, NULL},
83 {"from", &hf_xmpp_from, false, true, NULL, NULL},
84 {"to", &hf_xmpp_to, false, true, NULL, NULL},
85 {"xml:lang", NULL, false, false, NULL, NULL}
88 conversation_t *conversation;
89 xmpp_conv_info_t *xmpp_info;
90 xmpp_transaction_t *reqresp_trans;
92 xmpp_elem_info elems_info [] = {
93 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns","http://jabber.org/protocol/disco#items"), xmpp_disco_items_query, ONE},
94 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns", "jabber:iq:roster"), xmpp_roster_query, ONE},
95 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns", "http://jabber.org/protocol/disco#info"), xmpp_disco_info_query, ONE},
96 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns", "http://jabber.org/protocol/bytestreams"), xmpp_bytestreams_query, ONE},
97 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns", "http://jabber.org/protocol/muc#owner"), xmpp_muc_owner_query, ONE},
98 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns", "http://jabber.org/protocol/muc#admin"), xmpp_muc_admin_query, ONE},
99 {NAME, "bind", xmpp_iq_bind, ONE},
100 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "session", "xmlns", "urn:ietf:params:xml:ns:xmpp-session"), xmpp_session, ONE},
101 {NAME, "vCard", xmpp_vcard, ONE},
102 {NAME, "jingle", xmpp_jingle, ONE},
103 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "services", "xmlns", "http://jabber.org/protocol/jinglenodes"), xmpp_jinglenodes_services, ONE},
104 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "channel", "xmlns", "http://jabber.org/protocol/jinglenodes#channel"), xmpp_jinglenodes_channel, ONE},
105 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "open", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_open, ONE},
106 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "close", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_close, ONE},
107 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data, ONE},
108 {NAME, "si", xmpp_si, ONE},
109 {NAME, "error", xmpp_error, ONE},
110 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "session", "xmlns", "http://www.google.com/session"), xmpp_gtalk_session, ONE},
111 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns","google:jingleinfo"), xmpp_gtalk_jingleinfo_query, ONE},
112 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "usersetting", "xmlns","google:setting"), xmpp_gtalk_usersetting, ONE},
113 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns","jabber:iq:last"), xmpp_last_query, ONE},
114 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns","jabber:iq:version"), xmpp_version_query, ONE},
115 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns","google:mail:notify"), xmpp_gtalk_mail_query, ONE},
116 {NAME, "mailbox", xmpp_gtalk_mail_mailbox, ONE},
117 {NAME, "new-mail", xmpp_gtalk_mail_new_mail, ONE},
118 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns","google:shared-status"), xmpp_gtalk_status_query, ONE},
119 {NAME, "conference-info", xmpp_conference_info, ONE},
120 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "ping", "xmlns","urn:xmpp:ping"), xmpp_ping, ONE},
121 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "inputevt", "xmlns","http://jitsi.org/protocol/inputevt"), xmpp_jitsi_inputevt, ONE},
124 attr_id = xmpp_get_attr(packet, "id");
125 attr_type = xmpp_get_attr(packet, "type");
127 conversation = find_or_create_conversation(pinfo);
128 xmpp_info = (xmpp_conv_info_t *)conversation_get_proto_data(conversation, proto_xmpp);
130 xmpp_iq_item = proto_tree_add_item(tree, hf_xmpp_iq, tvb, packet->offset, packet->length, ENC_LITTLE_ENDIAN);
131 xmpp_iq_tree = proto_item_add_subtree(xmpp_iq_item,ett_xmpp_iq);
133 xmpp_display_attrs(xmpp_iq_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
136 col_add_fstr(pinfo->cinfo, COL_INFO, "IQ(%s) ", attr_type?attr_type->value:"");
138 xmpp_display_elems(xmpp_iq_tree, packet, pinfo, tvb, elems_info, array_length(elems_info));
140 /*displays generated info such as req/resp tracking, jingle sid
141 * in each packet related to specified jingle session and IBB sid in packet related to it*/
142 if(xmpp_info && attr_id)
144 char *jingle_sid, *ibb_sid, *gtalk_sid;
146 jingle_sid = (char *)wmem_tree_lookup_string(xmpp_info->jingle_sessions, attr_id->value, WMEM_TREE_STRING_NOCASE);
148 if (jingle_sid) {
149 proto_item *it = proto_tree_add_string(tree, hf_xmpp_jingle_session, tvb, 0, 0, jingle_sid);
150 proto_item_set_generated(it);
153 ibb_sid = (char *)wmem_tree_lookup_string(xmpp_info->ibb_sessions, attr_id->value, WMEM_TREE_STRING_NOCASE);
155 if (ibb_sid) {
156 proto_item *it = proto_tree_add_string(tree, hf_xmpp_ibb, tvb, 0, 0, ibb_sid);
157 proto_item_set_generated(it);
160 gtalk_sid = (char *)wmem_tree_lookup_string(xmpp_info->gtalk_sessions, attr_id->value, WMEM_TREE_STRING_NOCASE);
162 if (gtalk_sid) {
163 proto_item *it = proto_tree_add_string(tree, hf_xmpp_gtalk, tvb, 0, 0, gtalk_sid);
164 proto_item_set_generated(it);
167 reqresp_trans = (xmpp_transaction_t *)wmem_tree_lookup_string(xmpp_info->req_resp, attr_id->value, WMEM_TREE_STRING_NOCASE);
168 /*displays request/response field in each iq packet*/
169 if (reqresp_trans) {
171 if (reqresp_trans->req_frame == pinfo->num) {
172 if (reqresp_trans->resp_frame) {
173 proto_item *it = proto_tree_add_uint(tree, hf_xmpp_response_in, tvb, 0, 0, reqresp_trans->resp_frame);
174 proto_item_set_generated(it);
175 } else
177 expert_add_info(pinfo, xmpp_iq_item, &ei_xmpp_packet_without_response);
180 } else {
181 if (reqresp_trans->req_frame) {
182 proto_item *it = proto_tree_add_uint(tree, hf_xmpp_response_to, tvb, 0, 0, reqresp_trans->req_frame);
183 proto_item_set_generated(it);
184 } else
186 expert_add_info(pinfo, xmpp_iq_item, &ei_xmpp_packet_without_response);
194 static void
195 xmpp_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element)
197 proto_item *error_item;
198 proto_tree *error_tree;
200 xmpp_element_t *text_element, *cond_element;
202 xmpp_attr_info attrs_info[] = {
203 {"type", &hf_xmpp_error_type, true, true, NULL, NULL},
204 {"code", &hf_xmpp_error_code, false, true, NULL, NULL},
205 {"condition", &hf_xmpp_error_condition, true, true, NULL, NULL} /*TODO: validate list to the condition element*/
208 char *error_info;
210 xmpp_attr_t *fake_condition = NULL;
212 error_info = wmem_strdup(pinfo->pool, "Stanza error");
214 error_item = proto_tree_add_item(tree, hf_xmpp_error, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
215 error_tree = proto_item_add_subtree(error_item, ett_xmpp_query_item);
217 cond_element = xmpp_steal_element_by_attr(element, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
218 if(cond_element)
220 fake_condition = xmpp_ep_init_attr_t(pinfo->pool, cond_element->name, cond_element->offset, cond_element->length);
221 g_hash_table_insert(element->attrs, (void *)"condition", fake_condition);
223 error_info = wmem_strdup_printf(pinfo->pool, "%s: %s;", error_info, cond_element->name);
227 xmpp_display_attrs(error_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
229 while((text_element = xmpp_steal_element_by_name(element, "text")) != NULL)
231 xmpp_error_text(error_tree, tvb, text_element);
233 error_info = wmem_strdup_printf(pinfo->pool, "%s Text: %s", error_info, text_element->data?text_element->data->value:"");
236 expert_add_info_format(pinfo, error_item, &ei_xmpp_response, "%s", error_info);
238 xmpp_unknown(error_tree, tvb, pinfo, element);
241 static void
242 xmpp_error_text(proto_tree *tree, tvbuff_t *tvb, xmpp_element_t *element)
244 proto_tree_add_string(tree, hf_xmpp_error_text, tvb, element->offset, element->length, element->data?element->data->value:"");
248 void
249 xmpp_presence(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet)
251 proto_item *presence_item;
252 proto_tree *presence_tree;
254 static const char *type_enums[] = {"error", "probe", "subscribe", "subscribed",
255 "unavailable", "unsubscribe", "unsubscribed"};
256 xmpp_array_t *type_array = xmpp_ep_init_array_t(pinfo->pool, type_enums, array_length(type_enums));
258 static const char *show_enums[] = {"away", "chat", "dnd", "xa"};
259 xmpp_array_t *show_array = xmpp_ep_init_array_t(pinfo->pool, show_enums, array_length(show_enums));
261 xmpp_attr_info attrs_info[] = {
262 {"from", &hf_xmpp_from, false, false, NULL, NULL},
263 {"id", &hf_xmpp_id, false, true, NULL, NULL},
264 {"to", &hf_xmpp_to, false, false, NULL, NULL},
265 {"type", &hf_xmpp_type, false, true, xmpp_val_enum_list, type_array},
266 {"xml:lang", NULL, false, false, NULL,NULL},
267 {"show", &hf_xmpp_presence_show, false, true, xmpp_val_enum_list, show_array},
268 {"priority", NULL, false, false, NULL, NULL}
271 xmpp_elem_info elems_info[] = {
272 {NAME, "status", xmpp_presence_status, MANY},
273 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "c","xmlns","http://jabber.org/protocol/caps"), xmpp_presence_caps, ONE},
274 {NAME, "delay", xmpp_delay, ONE},
275 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "x","xmlns", "jabber:x:delay"), xmpp_delay, ONE},
276 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "x","xmlns", "vcard-temp:x:update"), xmpp_vcard_x_update, ONE},
277 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "x","xmlns","http://jabber.org/protocol/muc"), xmpp_muc_x, ONE},
278 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "x","xmlns","http://jabber.org/protocol/muc#user"), xmpp_muc_user_x, ONE},
279 {NAME, "error", xmpp_error, ONE},
280 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "query", "xmlns","jabber:iq:last"), xmpp_last_query, ONE}
284 xmpp_element_t *show, *priority;
286 col_set_str(pinfo->cinfo, COL_INFO, "PRESENCE ");
288 presence_item = proto_tree_add_item(tree, hf_xmpp_presence, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN);
289 presence_tree = proto_item_add_subtree(presence_item, ett_xmpp_presence);
291 if((show = xmpp_steal_element_by_name(packet, "show"))!=NULL)
293 xmpp_attr_t *fake_show = xmpp_ep_init_attr_t(pinfo->pool, show->data?show->data->value:"",show->offset, show->length);
294 g_hash_table_insert(packet->attrs, (void *)"show", fake_show);
297 if((priority = xmpp_steal_element_by_name(packet, "priority"))!=NULL)
299 xmpp_attr_t *fake_priority = xmpp_ep_init_attr_t(pinfo->pool, priority->data?priority->data->value:"",priority->offset, priority->length);
300 g_hash_table_insert(packet->attrs, (void *)"priority", fake_priority);
302 xmpp_display_attrs(presence_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
304 xmpp_display_elems(presence_tree, packet, pinfo, tvb, elems_info, array_length(elems_info));
307 static void
308 xmpp_presence_status(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element)
310 proto_item *status_item;
311 proto_tree *status_tree;
313 xmpp_attr_info attrs_info[] = {
314 {"xml:lang", NULL, false, true, NULL, NULL},
315 {"value", NULL, true, true, NULL, NULL}
318 xmpp_attr_t *fake_value;
320 status_item = proto_tree_add_item(tree, hf_xmpp_presence_status, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
321 status_tree = proto_item_add_subtree(status_item, ett_xmpp_presence_status);
323 if(element->data)
324 fake_value = xmpp_ep_init_attr_t(pinfo->pool, element->data->value, element->offset, element->length);
325 else
326 fake_value = xmpp_ep_init_attr_t(pinfo->pool, "(empty)", element->offset, element->length);
329 g_hash_table_insert(element->attrs, (void *)"value", fake_value);
331 xmpp_display_attrs(status_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
333 xmpp_unknown(status_tree, tvb, pinfo, element);
337 void
338 xmpp_message(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet)
340 proto_item *message_item;
341 proto_tree *message_tree;
343 static const char *type_enums[] = {"chat", "error", "groupchat", "headline", "normal"};
344 xmpp_array_t *type_array = xmpp_ep_init_array_t(pinfo->pool, type_enums, array_length(type_enums));
346 xmpp_attr_info attrs_info[] = {
347 {"from", &hf_xmpp_from, false, false, NULL, NULL},
348 {"id", &hf_xmpp_id, false, true, NULL, NULL},
349 {"to", &hf_xmpp_to, false, false, NULL, NULL},
350 {"type", &hf_xmpp_type, false, true, xmpp_val_enum_list, type_array},
351 {"xml:lang", NULL, false, false, NULL,NULL},
352 {"chatstate", &hf_xmpp_message_chatstate, false, true, NULL, NULL}
355 xmpp_elem_info elems_info [] = {
356 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data, ONE},
357 {NAME, "thread", xmpp_message_thread, ONE},
358 {NAME, "body", xmpp_message_body, MANY},
359 {NAME, "subject", xmpp_message_subject, MANY},
360 {NAME, "delay", xmpp_delay, ONE},
361 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "x","xmlns","jabber:x:event"), xmpp_x_event, ONE},
362 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "x","xmlns","http://jabber.org/protocol/muc#user"), xmpp_muc_user_x, ONE},
363 {NAME_AND_ATTR, xmpp_name_attr_struct(pinfo->pool, "x","xmlns","google:nosave"), xmpp_gtalk_nosave_x, ONE},
364 {NAME, "error", xmpp_error, ONE}
367 xmpp_element_t *chatstate;
369 xmpp_attr_t *id;
371 conversation_t *conversation;
372 xmpp_conv_info_t *xmpp_info;
374 col_set_str(pinfo->cinfo, COL_INFO, "MESSAGE ");
376 id = xmpp_get_attr(packet, "id");
378 conversation = find_or_create_conversation(pinfo);
379 xmpp_info = (xmpp_conv_info_t *)conversation_get_proto_data(conversation, proto_xmpp);
381 message_item = proto_tree_add_item(tree, hf_xmpp_message, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN);
382 message_tree = proto_item_add_subtree(message_item, ett_xmpp_message);
384 if((chatstate = xmpp_steal_element_by_attr(packet, "xmlns", "http://jabber.org/protocol/chatstates"))!=NULL)
386 xmpp_attr_t *fake_chatstate_attr = xmpp_ep_init_attr_t(pinfo->pool, chatstate->name, chatstate->offset, chatstate->length);
387 g_hash_table_insert(packet->attrs, (void *)"chatstate", fake_chatstate_attr);
390 xmpp_display_attrs(message_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
392 xmpp_display_elems(message_tree, packet, pinfo, tvb, elems_info, array_length(elems_info));
394 /*Displays data about IBB session*/
395 if(xmpp_info && id)
397 char *ibb_sid;
399 ibb_sid = (char *)wmem_tree_lookup_string(xmpp_info->ibb_sessions, id->value, WMEM_TREE_STRING_NOCASE);
401 if (ibb_sid) {
402 proto_item *it = proto_tree_add_string(tree, hf_xmpp_ibb, tvb, 0, 0, ibb_sid);
403 proto_item_set_generated(it);
409 static void
410 xmpp_message_body(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element)
412 proto_item *body_item;
413 proto_tree *body_tree;
415 xmpp_attr_info attrs_info[] = {
416 {"xml:lang", NULL, false, true, NULL, NULL},
417 {"value", NULL, true, true, NULL, NULL}
420 xmpp_attr_t *fake_data_attr;
422 body_item = proto_tree_add_item(tree, hf_xmpp_message_body, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
423 body_tree = proto_item_add_subtree(body_item, ett_xmpp_message_body);
425 fake_data_attr = xmpp_ep_init_attr_t(pinfo->pool, element->data?element->data->value:"", element->offset, element->length);
426 g_hash_table_insert(element->attrs, (void *)"value", fake_data_attr);
429 xmpp_display_attrs(body_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
431 xmpp_unknown(body_tree, tvb, pinfo, element);
434 static void
435 xmpp_message_subject(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element) {
436 proto_item *subject_item;
437 proto_tree *subject_tree;
439 xmpp_attr_info attrs_info[] = {
440 {"xml:lang", NULL, false, true, NULL, NULL},
441 {"value", NULL, true, false, NULL, NULL}
444 xmpp_attr_t *fake_data_attr;
446 subject_item = proto_tree_add_item(tree, hf_xmpp_message_subject, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
447 subject_tree = proto_item_add_subtree(subject_item, ett_xmpp_message_subject);
449 fake_data_attr = xmpp_ep_init_attr_t(pinfo->pool, element->data?element->data->value:"", element->offset, element->length);
450 g_hash_table_insert(element->attrs, (void *)"value", fake_data_attr);
453 xmpp_display_attrs(subject_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
455 xmpp_unknown(subject_tree, tvb, pinfo, element);
458 static void
459 xmpp_message_thread(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element)
461 proto_item *thread_item;
462 proto_tree *thread_tree;
464 xmpp_attr_info attrs_info[] = {
465 {"parent", &hf_xmpp_message_thread_parent, false, true, NULL, NULL},
466 {"value", NULL, true, true, NULL, NULL}
469 xmpp_attr_t *fake_value;
471 thread_item = proto_tree_add_item(tree, hf_xmpp_message_thread, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
472 thread_tree = proto_item_add_subtree(thread_item, ett_xmpp_message_thread);
474 fake_value = xmpp_ep_init_attr_t(pinfo->pool, element->data?element->data->value:"", element->offset, element->length);
475 g_hash_table_insert(element->attrs, (void *)"value", fake_value);
478 xmpp_display_attrs(thread_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
480 xmpp_unknown(thread_tree, tvb, pinfo, element);
483 void
484 xmpp_auth(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet)
486 proto_item *auth_item;
487 proto_tree *auth_tree;
489 xmpp_attr_info_ext attrs_info[]={
490 {"urn:ietf:params:xml:ns:xmpp-sasl", {"xmlns", &hf_xmpp_xmlns, true, true, NULL, NULL}},
491 {"urn:ietf:params:xml:ns:xmpp-sasl", {"mechanism", NULL, true, true, NULL, NULL}},
492 {"http://www.google.com/talk/protocol/auth", {"xmlns", &hf_xmpp_xmlns, true, true, NULL, NULL}},
493 {"http://www.google.com/talk/protocol/auth", {"client-uses-full-bind-result", NULL, true, true, NULL, NULL}},
496 col_set_str(pinfo->cinfo, COL_INFO, "AUTH");
498 auth_item = proto_tree_add_item(tree, hf_xmpp_auth, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN);
499 auth_tree = proto_item_add_subtree(auth_item, ett_xmpp_auth);
501 xmpp_display_attrs_ext(auth_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
503 xmpp_cdata(auth_tree, tvb, packet, -1);
505 xmpp_unknown(auth_tree, tvb, pinfo, packet);
508 void
509 xmpp_challenge_response_success(proto_tree *tree, tvbuff_t *tvb,
510 packet_info *pinfo, xmpp_element_t *packet, expert_field* ei, int ett, const char *col_info)
512 proto_item *item;
513 proto_tree *subtree;
515 xmpp_attr_info attrs_info[] = {
516 {"xmlns", &hf_xmpp_xmlns, true, true, NULL, NULL}
519 col_set_str(pinfo->cinfo, COL_INFO, col_info);
521 item = proto_tree_add_expert(tree, pinfo, ei, tvb, packet->offset, packet->length);
522 subtree = proto_item_add_subtree(item, ett);
524 xmpp_display_attrs(subtree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
525 xmpp_cdata(subtree, tvb, packet, -1);
527 xmpp_unknown(subtree, tvb, pinfo, packet);
530 void
531 xmpp_failure(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet)
533 proto_item *fail_item;
534 proto_tree *fail_tree;
536 xmpp_attr_info attrs_info[] = {
537 {"xmlns", &hf_xmpp_xmlns, true, true, NULL, NULL},
538 {"condition", NULL, false, true, NULL, NULL}
541 static const char *fail_names[] = {"aborted","account-disabled", "credentials-expired",
542 "encryption-required", "incorrect-encoding", "invalid-authzid", "invalid-mechanism",
543 "malformed-request", "mechanism-too-weak", "not-authorized", "temporary-auth-failure",
544 "transition-needed"
547 xmpp_element_t *fail_condition, *text;
549 col_set_str(pinfo->cinfo, COL_INFO, "FAILURE ");
551 fail_item = proto_tree_add_item(tree, hf_xmpp_failure, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN);
552 fail_tree = proto_item_add_subtree(fail_item, ett_xmpp_failure);
554 if((fail_condition = xmpp_steal_element_by_names(packet, fail_names, array_length(fail_names)))!=NULL)
556 xmpp_attr_t *fake_cond = xmpp_ep_init_attr_t(pinfo->pool, fail_condition->name, fail_condition->offset, fail_condition->length);
557 g_hash_table_insert(packet->attrs, (void *)"condition", fake_cond);
560 if((text = xmpp_steal_element_by_name(packet, "text"))!=NULL)
562 xmpp_failure_text(fail_tree, tvb, pinfo, text);
565 xmpp_display_attrs(fail_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
567 xmpp_unknown(fail_tree, tvb, pinfo, packet);
570 static void
571 xmpp_failure_text(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *element)
573 xmpp_attr_t *lang = xmpp_get_attr(element,"xml:lang");
575 proto_tree_add_string_format(tree, hf_xmpp_failure_text, tvb, element->offset, element->length,
576 element->data?element->data->value:"", "TEXT%s: %s",
577 lang?wmem_strdup_printf(pinfo->pool, "(%s)",lang->value):"",
578 element->data?element->data->value:"");
581 void
582 xmpp_xml_header(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, xmpp_element_t *packet)
584 col_set_str(pinfo->cinfo, COL_INFO, "XML ");
585 proto_tree_add_string(tree, hf_xmpp_xml_header_version, tvb, packet->offset, packet->length, "1.0");
588 void
589 xmpp_stream(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet)
591 proto_item *stream_item;
592 proto_tree *stream_tree;
594 xmpp_attr_info_ext attrs_info [] = {
595 {"http://etherx.jabber.org/streams",{"xmlns", &hf_xmpp_xmlns, false, true, NULL, NULL}},
596 {"http://etherx.jabber.org/streams",{"version", NULL, false, true, NULL, NULL}},
597 {"http://etherx.jabber.org/streams",{"from", NULL, false, true, NULL, NULL}},
598 {"http://etherx.jabber.org/streams",{"to", NULL, false, true, NULL, NULL}},
599 {"http://etherx.jabber.org/streams",{"id", NULL, false, true, NULL, NULL}},
600 {"http://etherx.jabber.org/streams",{"xml:lang", NULL, false, true, NULL, NULL}},
601 {"jabber:client",{"xmlns", &hf_xmpp_xmlns, false, true, NULL, NULL}},
605 col_set_str(pinfo->cinfo, COL_INFO, "STREAM ");
607 stream_item = proto_tree_add_item(tree, hf_xmpp_stream, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN);
608 stream_tree = proto_item_add_subtree(stream_item, ett_xmpp_stream);
610 xmpp_display_attrs_ext(stream_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
611 xmpp_display_elems(stream_tree, packet, pinfo, tvb, NULL, 0);
614 /*returns true if stream end occurs*/
615 bool
616 xmpp_stream_close(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo)
618 tvbparse_t *tt;
619 tvbparse_elem_t *elem;
621 tt = tvbparse_init(pinfo->pool, tvb,0,-1,NULL,want_ignore);
623 if((elem = tvbparse_get(tt,want_stream_end_tag))!=NULL)
625 proto_tree_add_item(tree, hf_xmpp_stream_end, tvb, elem->offset, elem->len, ENC_NA);
626 col_set_str(pinfo->cinfo, COL_INFO, "STREAM END");
628 return true;
630 return false;
633 void
634 xmpp_features(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet)
636 proto_item *features_item;
637 proto_tree *features_tree;
639 xmpp_elem_info elems_info [] = {
640 {NAME, "mechanisms", xmpp_features_mechanisms, MANY}
643 features_item = proto_tree_add_item(tree, hf_xmpp_features, tvb, packet->offset, packet->length,
644 ENC_BIG_ENDIAN);
645 features_tree = proto_item_add_subtree(features_item, ett_xmpp_features);
647 col_set_str(pinfo->cinfo, COL_INFO, "FEATURES ");
649 xmpp_display_attrs(features_tree, packet, pinfo, tvb, NULL, 0);
650 xmpp_display_elems(features_tree, packet, pinfo, tvb, elems_info, array_length(elems_info));
653 static void
654 xmpp_features_mechanisms(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, xmpp_element_t *packet)
656 proto_tree *mechanisms_tree;
658 xmpp_attr_info attrs_info [] = {
659 {"xmlns", &hf_xmpp_xmlns, true, true, NULL, NULL}
662 xmpp_elem_info elems_info [] = {
663 {NAME, "mechanism", xmpp_simple_cdata_elem, MANY},
666 mechanisms_tree = proto_tree_add_subtree(tree, tvb, packet->offset, packet->length, ett_xmpp_features_mechanisms, NULL, "MECHANISMS");
668 xmpp_display_attrs(mechanisms_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
669 xmpp_display_elems(mechanisms_tree, packet, pinfo, tvb, elems_info, array_length(elems_info));
672 void
673 xmpp_starttls(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
674 xmpp_element_t *packet, xmpp_conv_info_t *xmpp_info)
676 proto_item *tls_item;
677 proto_tree *tls_tree;
679 xmpp_attr_info attrs_info [] = {
680 {"xmlns", &hf_xmpp_xmlns, true, true, NULL, NULL},
683 col_set_str(pinfo->cinfo, COL_INFO, "STARTTLS ");
685 tls_item = proto_tree_add_item(tree, hf_xmpp_starttls, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN);
686 tls_tree = proto_item_add_subtree(tls_item, ett_xmpp_starttls);
688 if (xmpp_info->ssl_start && xmpp_info->ssl_start != pinfo->num) {
689 expert_add_info_format(pinfo, tls_item, &ei_xmpp_starttls_already_in_frame, "Already saw STARTTLS in frame %u", xmpp_info->ssl_start);
691 else {
692 xmpp_info->ssl_start = pinfo->num;
695 xmpp_display_attrs(tls_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
696 xmpp_display_elems(tls_tree, packet, pinfo, tvb, NULL, 0);
699 void
700 xmpp_proceed(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
701 xmpp_element_t *packet, xmpp_conv_info_t *xmpp_info)
703 proto_item *proceed_item;
704 proto_tree *proceed_tree;
705 uint32_t ssl_proceed;
707 xmpp_attr_info attrs_info [] = {
708 {"xmlns", &hf_xmpp_xmlns, true, true, NULL, NULL},
711 col_set_str(pinfo->cinfo, COL_INFO, "PROCEED ");
713 proceed_item = proto_tree_add_item(tree, hf_xmpp_proceed, tvb, packet->offset, packet->length, ENC_BIG_ENDIAN);
714 proceed_tree = proto_item_add_subtree(proceed_item, ett_xmpp_proceed);
716 if (!xmpp_info->ssl_start) {
717 expert_add_info(pinfo, proceed_item, &ei_xmpp_starttls_missing);
720 ssl_proceed =
721 ssl_starttls_ack(find_dissector("tls"), pinfo, find_dissector("xmpp"));
722 if (ssl_proceed > 0 && ssl_proceed != pinfo->num) {
723 expert_add_info_format(pinfo, proceed_item, &ei_xmpp_proceed_already_in_frame,
724 "Already saw PROCEED in frame %u", ssl_proceed);
727 xmpp_display_attrs(proceed_tree, packet, pinfo, tvb, attrs_info, array_length(attrs_info));
728 xmpp_display_elems(proceed_tree, packet, pinfo, tvb, NULL, 0);
731 * Editor modelines - https://www.wireshark.org/tools/modelines.html
733 * Local variables:
734 * c-basic-offset: 4
735 * tab-width: 8
736 * indent-tabs-mode: nil
737 * End:
739 * ex: set shiftwidth=4 tabstop=8 expandtab:
740 * :indentSize=4:tabSize=8:noTabs=true: