From Mariusz Okrój and Sebastien Vincent via https://bugs.wireshark.org/bugzilla...
[obnox/wireshark/wip.git] / epan / dissectors / packet-xmpp-jingle.c
1 /* xmpp-jingle.c
2  * Wireshark's XMPP dissector.
3  *
4  * urn:xmpp:jingle:1
5  * urn:xmpp:jingle:apps:rtp:1
6  * urn:xmpp:jingle:apps:rtp:errors:1
7  * urn:xmpp:jingle:apps:rtp:info:1
8  * urn:xmpp:jingle:apps:rtp:rtp-hdrext:0
9  * urn:xmpp:jingle:apps:rtp:izrtp:1
10  *
11  * urn:xmpp:jingle:transports:ice-udp:1
12  * urn:xmpp:jingle:transports:raw-udp:1
13  * urn:xmpp:jingle:transports:s5b:1
14  * urn:xmpp:jingle:transports:ibb:1
15  *
16  * http://jabber.org/protocol/jinglenodes
17  * http://jabber.org/protocol/jinglenodes#channel
18  *
19  * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com>
20  *
21  * $Id$
22  *
23  * Wireshark - Network traffic analyzer
24  * By Gerald Combs <gerald@wireshark.org>
25  * Copyright 1998 Gerald Combs
26  *
27  * This program is free software; you can redistribute it and/or
28  * modify it under the terms of the GNU General Public License
29  * as published by the Free Software Foundation; either version 2
30  * of the License, or (at your option) any later version.
31  *
32  * This program is distributed in the hope that it will be useful,
33  * but WITHOUT ANY WARRANTY; without even the implied warranty of
34  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35  * GNU General Public License for more details.
36  *
37  * You should have received a copy of the GNU General Public License
38  * along with this program; if not, write to the Free Software
39  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
40  */
41
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45
46 #include <glib.h>
47 #include <stdio.h>
48
49 #include <epan/proto.h>
50 #include <epan/packet.h>
51 #include <epan/packet_info.h>
52 #include <epan/epan.h>
53 #include <epan/expert.h>
54 #include <epan/dissectors/packet-xml.h>
55
56 #include <packet-xmpp.h>
57 #include <packet-xmpp-utils.h>
58 #include <packet-xmpp-jingle.h>
59 #include <packet-xmpp-conference.h>
60 #include <packet-xmpp-gtalk.h>
61 #include <packet-xmpp-other.h>
62
63 void xmpp_jingle(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
64
65 static void xmpp_jingle_content(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
66 static void xmpp_jingle_content_description_rtp(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
67 static void xmpp_jingle_cont_desc_rtp_payload(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
68 static void xmpp_jingle_cont_desc_rtp_payload_param(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element);
69 static void xmpp_jingle_cont_desc_rtp_enc(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element);
70 static void xmpp_jingle_cont_desc_rtp_enc_zrtp_hash(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element);
71 static void xmpp_jingle_cont_desc_rtp_enc_crypto(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element);
72 static void xmpp_jingle_cont_desc_rtp_bandwidth(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element);
73 static void xmpp_jingle_cont_desc_rtp_hdrext(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element);
74 static void xmpp_jingle_cont_trans_ice(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
75 static void xmpp_jingle_cont_trans_ice_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
76 static void xmpp_jingle_cont_trans_ice_remote_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
77 static void xmpp_jingle_reason(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
78 static void xmpp_jingle_rtp_info(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
79 static void xmpp_jinglenodes_relay_stun_tracker(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
80 static void xmpp_jingle_cont_trans_raw(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
81 static void xmpp_jingle_cont_trans_raw_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
82 static void xmpp_jingle_cont_trans_s5b(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
83 static void xmpp_jingle_cont_trans_s5b_candidate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
84 static void xmpp_jingle_cont_trans_s5b_activated(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
85 static void xmpp_jingle_cont_trans_s5b_cand_used(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
86 static void xmpp_jingle_cont_trans_s5b_cand_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
87 static void xmpp_jingle_cont_trans_s5b_proxy_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
88 static void xmpp_jingle_cont_trans_ibb(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element);
89
90 static void xmpp_jingle_file_transfer_desc(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
91 static void xmpp_jingle_file_transfer_offer(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
92 static void xmpp_jingle_file_transfer_file(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
93 static void xmpp_jingle_file_transfer_request(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
94 static void xmpp_jingle_file_transfer_received(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
95 static void xmpp_jingle_file_transfer_abort(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
96 static void xmpp_jingle_file_transfer_checksum(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element);
97
98 /*XEP-0166: Jingle urn:xmpp:jingle:1*/
99 void
100 xmpp_jingle(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
101 {
102     proto_item *jingle_item;
103     proto_tree *jingle_tree;
104
105     const gchar *rtp_info_msgs[] = {"active", "hold", "mute", "ringing", "unhold", "unmute"};
106
107     const gchar *action_enums[] = {"content-accept","content-add", "content-modify",
108         "content-modify", "content-remove", "description-info", "security-info",
109         "session-accept", "session-info", "session-initiate", "session-terminate",
110         "transport-accept", "transport-info", "transport-reject", "transport-replace"
111     };
112
113     array_t *action_array = ep_init_array_t(action_enums,array_length(action_enums));
114     array_t *rtp_info_array = ep_init_array_t(rtp_info_msgs, array_length(rtp_info_msgs));
115
116     attr_info attrs_info[] = {
117         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
118         {"action", hf_xmpp_jingle_action, TRUE, TRUE, val_enum_list, action_array},
119         {"sid", hf_xmpp_jingle_sid, TRUE, FALSE, NULL, NULL},
120         {"initiator", hf_xmpp_jingle_initiator, FALSE, FALSE, NULL, NULL},
121         {"responder", hf_xmpp_jingle_responder, FALSE, FALSE, NULL, NULL}
122     };
123
124     elem_info elems_info [] = {
125         {NAME, "content", xmpp_jingle_content, MANY},
126         {NAME, "reason", xmpp_jingle_reason, MANY},
127         {NAMES, rtp_info_array, xmpp_jingle_rtp_info, ONE},
128         {NAME, "conference-info", xmpp_conferece_info_advert, ONE}
129     };
130
131      attr_t *action = get_attr(element,"action");
132      col_append_fstr(pinfo->cinfo, COL_INFO, "JINGLE(%s) ", action?action->value:"");
133
134
135     jingle_item = proto_tree_add_item(tree, hf_xmpp_jingle, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
136     jingle_tree = proto_item_add_subtree(jingle_item, ett_xmpp_jingle);
137
138     display_attrs(jingle_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
139
140     display_elems(jingle_item, element, pinfo, tvb, elems_info, array_length(elems_info));
141 }
142
143 static void
144 xmpp_jingle_content(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
145 {
146     proto_item *content_item;
147     proto_tree *content_tree;
148
149     const gchar *creator_enums[] = {"initiator","responder"};
150     array_t *creator_enums_array = ep_init_array_t(creator_enums,array_length(creator_enums));
151
152     attr_info attrs_info[] = {
153         {"creator", hf_xmpp_jingle_content_creator, TRUE, FALSE, val_enum_list, creator_enums_array},
154         {"name", hf_xmpp_jingle_content_name, TRUE, TRUE, NULL, NULL},
155         {"disposition", hf_xmpp_jingle_content_disposition, FALSE, FALSE, NULL, NULL},
156         {"senders", hf_xmpp_jingle_content_senders, FALSE, FALSE, NULL, NULL}
157     };
158
159     elem_info elems_info [] = {
160         {NAME_AND_ATTR, name_attr_struct("description", "xmlns", "urn:xmpp:jingle:apps:rtp:1"), xmpp_jingle_content_description_rtp, MANY},
161         {NAME_AND_ATTR, name_attr_struct("description", "xmlns", "urn:xmpp:jingle:apps:file-transfer:3"), xmpp_jingle_file_transfer_desc, MANY},
162         {NAME_AND_ATTR,  name_attr_struct("transport", "xmlns", "urn:xmpp:jingle:transports:ice-udp:1"), xmpp_jingle_cont_trans_ice, MANY},
163         {NAME_AND_ATTR,  name_attr_struct("transport", "xmlns", "urn:xmpp:jingle:transports:raw-udp:1"), xmpp_jingle_cont_trans_raw, MANY},
164         {NAME_AND_ATTR,  name_attr_struct("transport", "xmlns", "urn:xmpp:jingle:transports:s5b:1"), xmpp_jingle_cont_trans_s5b, MANY},
165         {NAME_AND_ATTR,  name_attr_struct("transport", "xmlns", "urn:xmpp:jingle:transports:ibb:1"), xmpp_jingle_cont_trans_ibb, MANY},
166         {NAME_AND_ATTR,  name_attr_struct("transport", "xmlns", "http://www.google.com/transport/p2p"), xmpp_gtalk_transport_p2p, MANY},
167         {NAME_AND_ATTR,  name_attr_struct("received", "xmlns", "urn:xmpp:jingle:apps:file-transfer:3"), xmpp_jingle_file_transfer_received, MANY},
168         {NAME_AND_ATTR,  name_attr_struct("abort", "xmlns", "urn:xmpp:jingle:apps:file-transfer:3"), xmpp_jingle_file_transfer_abort, MANY},
169         {NAME_AND_ATTR,  name_attr_struct("checksum", "xmlns", "urn:xmpp:jingle:apps:file-transfer:3"), xmpp_jingle_file_transfer_checksum, MANY},
170         {NAME_AND_ATTR, name_attr_struct("inputevt", "xmlns","http://jitsi.org/protocol/inputevt"), xmpp_jitsi_inputevt, ONE},
171     };
172
173     content_item = proto_tree_add_item(tree, hf_xmpp_jingle_content, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
174     content_tree = proto_item_add_subtree(content_item, ett_xmpp_jingle_content);
175
176     display_attrs(content_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
177
178     display_elems(content_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
179 }
180
181 static void
182 xmpp_jingle_reason(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
183 {
184     proto_item *reason_item;
185     proto_tree *reason_tree;
186
187     attr_info attrs_info[] = {
188         {"condition", hf_xmpp_jingle_reason_condition, TRUE, TRUE, NULL, NULL},
189         {"sid", -1, FALSE, TRUE, NULL, NULL},
190         {"rtp-error", -1, FALSE, TRUE, NULL, NULL},
191         {"text", hf_xmpp_jingle_reason_text, FALSE, FALSE, NULL, NULL}
192    };
193
194     element_t *condition; /*1?*/
195     element_t *text; /*0-1*/
196     element_t *rtp_error;
197
198     const gchar *reason_names[] = { "success", "busy", "failed-application", "cancel", "connectivity-error",
199         "decline", "expired", "failed-transport", "general-error", "gone", "incompatible-parameters",
200         "media-error", "security-error", "timeout", "unsupported-applications", "unsupported-transports"};
201
202     const gchar *rtp_error_names[] = {"crypto-required", "invalid-crypto"};
203
204     reason_item = proto_tree_add_item(tree, hf_xmpp_jingle_reason, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
205     reason_tree = proto_item_add_subtree(reason_item, ett_xmpp_jingle_reason);
206
207
208     /*Looks for reason description. "alternative-session" may contain "sid" element
209      Elements are changed into attribute*/
210     if((condition = steal_element_by_names(element, reason_names, array_length(reason_names)))!=NULL)
211     {
212         attr_t *fake_cond = ep_init_attr_t(condition->name, condition->offset, condition->length);
213         g_hash_table_insert(element->attrs, "condition", fake_cond);
214
215     } else if((condition = steal_element_by_name(element, "alternative-session"))!=NULL)
216     {
217         attr_t *fake_cond,*fake_alter_sid;
218         element_t *sid;
219
220         fake_cond = ep_init_attr_t(condition->name, condition->offset, condition->length);
221         g_hash_table_insert(element->attrs, "condition", fake_cond);
222
223
224         if((sid = steal_element_by_name(condition, "sid"))!=NULL)
225         {
226             fake_alter_sid = ep_init_attr_t(sid->name, sid->offset, sid->length);
227             g_hash_table_insert(element->attrs, "sid", fake_alter_sid);
228         }
229     }
230
231     if((rtp_error = steal_element_by_names(element, rtp_error_names, array_length(rtp_error_names)))!=NULL)
232     {
233         attr_t *fake_rtp_error = ep_init_attr_t(rtp_error->name, rtp_error->offset, rtp_error->length);
234         g_hash_table_insert(element->attrs, "rtp-error", fake_rtp_error);
235     }
236
237     if((text = steal_element_by_name(element, "text"))!=NULL)
238     {
239         attr_t *fake_text = ep_init_attr_t(text->data?text->data->value:"", text->offset, text->length);
240         g_hash_table_insert(element->attrs, "text", fake_text);
241     }
242
243     display_attrs(reason_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
244
245     xmpp_unknown(reason_tree, tvb, pinfo, element);
246 }
247
248 /*XEP-0167: Jingle RTP Sessions urn:xmpp:jingle:apps:rtp:1*/
249 static void
250 xmpp_jingle_content_description_rtp(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
251 {
252     proto_item *desc_item;
253     proto_tree *desc_tree;
254
255     attr_info attrs_info[] = {
256         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL},
257         {"media", hf_xmpp_jingle_content_description_media, TRUE, TRUE, NULL, NULL},
258         {"ssrc", hf_xmpp_jingle_content_description_ssrc , FALSE, TRUE, NULL, NULL}
259     };
260
261     elem_info elems_info[] = {
262         {NAME, "payload-type", xmpp_jingle_cont_desc_rtp_payload, MANY},
263         {NAME, "bandwidth", xmpp_jingle_cont_desc_rtp_bandwidth, ONE},
264         {NAME, "encryption", xmpp_jingle_cont_desc_rtp_enc, ONE},
265         {NAME, "rtp-hdrext", xmpp_jingle_cont_desc_rtp_hdrext, MANY},
266         {NAME, "zrtp-hash", xmpp_jingle_cont_desc_rtp_enc_zrtp_hash, MANY}/*IMHO it shouldn't appear in description*/
267         
268     };
269
270     desc_item = proto_tree_add_item(tree, hf_xmpp_jingle_content_description, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
271     desc_tree = proto_item_add_subtree(desc_item, ett_xmpp_jingle_content_description);
272
273     display_attrs(desc_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
274
275     display_elems(desc_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
276 }
277
278 static void
279 xmpp_jingle_cont_desc_rtp_payload(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
280 {
281     proto_item *payload_item;
282     proto_tree *payload_tree;
283
284     attr_info attrs_info[] = {
285         {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL},
286         {"id", hf_xmpp_jingle_cont_desc_payload_id, TRUE, TRUE, NULL, NULL},
287         {"channels", hf_xmpp_jingle_cont_desc_payload_channels, FALSE, FALSE, NULL, NULL},
288         {"clockrate", hf_xmpp_jingle_cont_desc_payload_clockrate, FALSE, FALSE, NULL, NULL},
289         {"maxptime", hf_xmpp_jingle_cont_desc_payload_maxptime, FALSE, FALSE, NULL, NULL},
290         {"name", hf_xmpp_jingle_cont_desc_payload_name, FALSE, TRUE, NULL, NULL},
291         {"ptime", hf_xmpp_jingle_cont_desc_payload_ptime, FALSE, FALSE, NULL, NULL}
292     };
293
294     elem_info elems_info [] =
295     {
296         {NAME, "parameter", xmpp_jingle_cont_desc_rtp_payload_param, MANY}
297     };
298
299     payload_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_payload, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
300     payload_tree = proto_item_add_subtree(payload_item, ett_xmpp_jingle_cont_desc_payload);
301
302     display_attrs(payload_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
303
304     display_elems(payload_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
305 }
306
307 static void
308 xmpp_jingle_cont_desc_rtp_payload_param(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element)
309 {
310     proto_item *param_item;
311     proto_tree *param_tree;
312
313     proto_item *parent_item;
314     attr_t *name, *value;
315
316     attr_info attrs_info[] = {
317         {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL},
318         {"name", hf_xmpp_jingle_cont_desc_payload_param_name, TRUE, TRUE, NULL, NULL},
319         {"value", hf_xmpp_jingle_cont_desc_payload_param_value, TRUE, TRUE, NULL, NULL}
320     };
321
322     name = get_attr(element, "name");
323     value = get_attr(element, "value");
324
325     if(name && value)
326     {
327         gchar *parent_item_label;
328
329         parent_item = proto_tree_get_parent(tree);
330
331         parent_item_label = proto_item_get_text(parent_item);
332
333         if(parent_item_label)
334         {
335             parent_item_label[strlen(parent_item_label)-1]= '\0';
336             proto_item_set_text(parent_item, "%s param(\"%s\")=%s]", parent_item_label ,name->value, value->value);
337         }
338     }
339
340     param_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_payload_param, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
341     param_tree = proto_item_add_subtree(param_item, ett_xmpp_jingle_cont_desc_payload_param);
342
343     display_attrs(param_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
344
345     xmpp_unknown(param_tree, tvb, pinfo, element);
346
347 }
348
349 static void
350 xmpp_jingle_cont_desc_rtp_enc(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element)
351 {
352     proto_item *enc_item;
353     proto_tree *enc_tree;
354
355     elem_info elems_info [] = {
356         {NAME, "zrtp-hash", xmpp_jingle_cont_desc_rtp_enc_zrtp_hash, MANY},
357         {NAME, "crypto", xmpp_jingle_cont_desc_rtp_enc_crypto, MANY}
358     };
359
360     enc_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_enc, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
361     enc_tree = proto_item_add_subtree(enc_item, ett_xmpp_jingle_cont_desc_enc);
362
363     display_attrs(enc_tree, element, pinfo, tvb, NULL, 0);
364     display_elems(enc_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
365 }
366
367 /*urn:xmpp:jingle:apps:rtp:zrtp:1*/
368 static void
369 xmpp_jingle_cont_desc_rtp_enc_zrtp_hash(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element)
370 {
371     proto_item *zrtp_hash_item;
372     proto_tree *zrtp_hash_tree;
373
374      attr_info attrs_info[] = {
375         {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL},
376         {"version", -1, TRUE, TRUE,NULL,NULL},
377         {"hash", -1, TRUE, FALSE, NULL, NULL}
378     };
379
380     zrtp_hash_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_enc_zrtp_hash, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
381     zrtp_hash_tree = proto_item_add_subtree(zrtp_hash_item, ett_xmpp_jingle_cont_desc_enc_zrtp_hash);
382
383     if(element->data)
384     {
385         attr_t *fake_hash = ep_init_attr_t(element->data->value, element->offset, element->length);
386         g_hash_table_insert(element->attrs, "hash", fake_hash);
387     }
388
389     display_attrs(zrtp_hash_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
390
391     xmpp_unknown(zrtp_hash_tree, tvb, pinfo, element);
392 }
393
394 static void
395 xmpp_jingle_cont_desc_rtp_enc_crypto(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element)
396 {
397     proto_item *crypto_item;
398     proto_tree *crypto_tree;
399
400      attr_info attrs_info[] = {
401         {"crypto-suite", -1, TRUE, TRUE, NULL, NULL},
402         {"key-params", -1, TRUE, FALSE,NULL,NULL},
403         {"session-params", -1, FALSE, TRUE, NULL, NULL},
404         {"tag", -1, TRUE, FALSE, NULL, NULL}
405     };
406
407     crypto_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_enc_crypto, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
408     crypto_tree = proto_item_add_subtree(crypto_item, ett_xmpp_jingle_cont_desc_enc_crypto);
409
410
411     display_attrs(crypto_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
412
413     xmpp_unknown(crypto_tree, tvb, pinfo, element);
414 }
415
416 static void
417 xmpp_jingle_cont_desc_rtp_bandwidth(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element)
418 {
419     proto_item *bandwidth_item;
420     proto_tree *bandwidth_tree;
421
422     attr_info attrs_info[] = {
423         {"type", -1, TRUE, TRUE, NULL, NULL},
424         {"value", -1, TRUE, TRUE, NULL, NULL}
425     };
426
427     bandwidth_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_bandwidth, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
428     bandwidth_tree = proto_item_add_subtree(bandwidth_item, ett_xmpp_jingle_cont_desc_bandwidth);
429
430     if(element->data)
431     {
432         attr_t *fake_value = ep_init_attr_t(element->data->value, element->offset, element->length);
433         g_hash_table_insert(element->attrs, "value", fake_value);
434     }
435
436     display_attrs(bandwidth_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
437     xmpp_unknown(bandwidth_tree, tvb, pinfo, element);
438 }
439
440 /*urn:xmpp:jingle:apps:rtp:rtp-hdrext:0*/
441 static void
442 xmpp_jingle_cont_desc_rtp_hdrext(proto_tree* tree, tvbuff_t* tvb, packet_info *pinfo, element_t* element)
443 {
444     proto_item *rtp_hdr_item;
445     proto_tree *rtp_hdr_tree;
446
447     const gchar *senders[] = {"both", "initiator", "responder"};
448     array_t *senders_enums = ep_init_array_t(senders, 3);
449
450     attr_info attrs_info[] = {
451         {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL},
452         {"id", -1, TRUE, FALSE, NULL, NULL},
453         {"uri", -1, TRUE, TRUE, NULL, NULL},
454         {"senders", -1, FALSE, TRUE, val_enum_list, senders_enums},
455         {"parameter", -1, FALSE, TRUE, NULL, NULL}
456     };
457
458     element_t *parameter;
459
460     rtp_hdr_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_desc_rtp_hdr, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
461     rtp_hdr_tree = proto_item_add_subtree(rtp_hdr_item, ett_xmpp_jingle_cont_desc_rtp_hdr);
462
463     if((parameter = steal_element_by_name(element, "parameter"))!=NULL)
464     {
465         attr_t *name = get_attr(element, "name");
466         attr_t *fake_attr = ep_init_attr_t(name?name->value:"", parameter->offset, parameter->length);
467         g_hash_table_insert(element->attrs, "parameter", fake_attr);
468     }
469
470     display_attrs(rtp_hdr_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
471
472     xmpp_unknown(rtp_hdr_tree, tvb, pinfo, element);
473 }
474
475 /*urn:xmpp:jingle:apps:rtp:info:1*/
476 static void
477 xmpp_jingle_rtp_info(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
478 {
479     proto_item *rtp_info_item;
480     proto_tree *rtp_info_tree;
481
482     const gchar *creator[] = {"initiator","responder"};
483     array_t *creator_enums = ep_init_array_t(creator, array_length(creator));
484
485     attr_info mute_attrs_info[] = {
486         {"creator", -1, TRUE, TRUE, val_enum_list, creator_enums},
487         {"name", -1, TRUE, TRUE, NULL, NULL}
488     };
489
490     rtp_info_item = proto_tree_add_string(tree, hf_xmpp_jingle_rtp_info, tvb, element->offset, element->length, element->name);
491     rtp_info_tree = proto_item_add_subtree(rtp_info_item, ett_xmpp_jingle_rtp_info);
492
493     if(strcmp("mute", element->name) == 0 || strcmp("unmute", element->name) == 0)
494         display_attrs(rtp_info_tree, element, pinfo, tvb, mute_attrs_info, array_length(mute_attrs_info));
495
496     xmpp_unknown(rtp_info_tree, tvb, pinfo, element);
497 }
498
499 /*XEP-0176: Jingle ICE-UDP Transport Method urn:xmpp:jingle:transports:ice-udp:1*/
500 static void
501 xmpp_jingle_cont_trans_ice(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
502 {
503     proto_item *trans_item;
504     proto_tree *trans_tree;
505
506     attr_info attrs_info[] = {
507         {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL},
508         {"pwd", hf_xmpp_jingle_cont_trans_pwd, FALSE, FALSE, NULL, NULL},
509         {"ufrag", hf_xmpp_jingle_cont_trans_ufrag, FALSE, TRUE, NULL, NULL}
510     };
511
512     elem_info elems_info [] = {
513         {NAME, "candidate", xmpp_jingle_cont_trans_ice_candidate, MANY},
514         {NAME, "remote-candidate", xmpp_jingle_cont_trans_ice_remote_candidate, ONE}
515     };
516
517     trans_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
518     trans_tree = proto_item_add_subtree(trans_item, ett_xmpp_jingle_cont_trans);
519
520     display_attrs(trans_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
521
522     display_elems(trans_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
523 }
524
525 static void
526 xmpp_jingle_cont_trans_ice_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
527 {
528     proto_item *cand_item;
529     proto_tree *cand_tree;
530
531     const gchar *type_enums[] = {"host", "prflx", "relay", "srflx"};
532     array_t *type_enums_array = ep_init_array_t(type_enums,array_length(type_enums));
533
534     attr_info attrs_info[] = {
535         {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL},
536         {"component", -1, TRUE, FALSE, NULL, NULL},
537         {"foundation", -1, TRUE, FALSE, NULL, NULL},
538         {"generation", -1, TRUE, FALSE, NULL, NULL},
539         {"id", -1, FALSE, FALSE, NULL, NULL}, /*in schemas id is marked as required, but in jitsi logs it doesn't appear*/
540         {"ip", -1, TRUE, TRUE, NULL, NULL},
541         {"network", -1, TRUE, FALSE, NULL, NULL},
542         {"port", -1, TRUE, FALSE, NULL, NULL},
543         {"priority", -1, TRUE, TRUE, NULL, NULL},
544         {"protocol", -1, TRUE, TRUE, NULL, NULL},
545         {"rel-addr", -1, FALSE, FALSE, NULL, NULL},
546         {"rel-port", -1, FALSE, FALSE, NULL, NULL},
547         {"type", -1, TRUE, TRUE, val_enum_list, type_enums_array}
548     };
549
550     cand_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_cand, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
551     cand_tree = proto_item_add_subtree(cand_item, ett_xmpp_jingle_cont_trans_cand);
552
553     display_attrs(cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
554
555     xmpp_unknown(cand_tree, tvb, pinfo, element);
556 }
557
558 static void
559 xmpp_jingle_cont_trans_ice_remote_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
560 {
561     proto_item *remote_cand_item;
562     proto_tree *remote_cand_tree;
563
564     attr_info attrs_info[] = {
565         {"component", -1, TRUE, FALSE, NULL, NULL},
566         {"ip", -1, TRUE, FALSE, NULL, NULL},
567         {"port", -1, TRUE, FALSE, NULL, NULL}
568     };
569
570     remote_cand_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_rem_cand, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
571     remote_cand_tree = proto_item_add_subtree(remote_cand_item, ett_xmpp_jingle_cont_trans_rem_cand);
572
573     display_attrs(remote_cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
574
575     xmpp_unknown(remote_cand_tree, tvb, pinfo, element);
576 }
577
578 /*XEP-0177: Jingle Raw UDP Transport Method urn:xmpp:jingle:transports:raw-udp:1*/
579 static void
580 xmpp_jingle_cont_trans_raw(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
581 {
582     proto_item *trans_item;
583     proto_tree *trans_tree;
584
585     attr_info attrs_info[] = {
586         {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL}
587     };
588
589     elem_info elems_info [] = {
590         {NAME, "candidate", xmpp_jingle_cont_trans_raw_candidate, MANY}
591     };
592
593     trans_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
594     trans_tree = proto_item_add_subtree(trans_item, ett_xmpp_jingle_cont_trans);
595
596     display_attrs(trans_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
597     display_elems(trans_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
598 }
599
600 static void
601 xmpp_jingle_cont_trans_raw_candidate(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
602 {
603     proto_item *cand_item;
604     proto_tree *cand_tree;
605
606     const gchar *type_enums[] = {"host", "prflx", "relay", "srflx"};
607     array_t *type_enums_array = ep_init_array_t(type_enums,array_length(type_enums));
608
609     attr_info attrs_info[] = {
610         {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL},
611         {"component", -1, TRUE, FALSE, NULL, NULL},
612         {"generation", -1, TRUE, FALSE, NULL, NULL},
613         {"id", -1, TRUE, FALSE, NULL, NULL},
614         {"ip", -1, TRUE, TRUE, NULL, NULL},
615         {"port", -1, TRUE, TRUE, NULL, NULL},
616         {"type", -1, TRUE, TRUE, val_enum_list, type_enums_array}
617     };
618
619     cand_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_cand, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
620     cand_tree = proto_item_add_subtree(cand_item, ett_xmpp_jingle_cont_trans_cand);
621
622     display_attrs(cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
623     display_elems(cand_tree, element, pinfo, tvb, NULL, 0);
624 }
625
626 /*XEP-0260: Jingle SOCKS5 Bytestreams Transport Method urn:xmpp:jingle:transports:s5b:1*/
627 static void
628 xmpp_jingle_cont_trans_s5b(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
629 {
630     proto_item *trans_item;
631     proto_tree *trans_tree;
632
633     attr_info attrs_info[] = {
634         {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL},
635         {"mode", -1, FALSE, TRUE, NULL, NULL},
636         {"sid", -1, FALSE, TRUE, NULL, NULL},
637     };
638
639     elem_info elems_info [] = {
640         {NAME, "candidate", xmpp_jingle_cont_trans_s5b_candidate, MANY},
641         {NAME, "activated", xmpp_jingle_cont_trans_s5b_activated, ONE},
642         {NAME, "candidate-used", xmpp_jingle_cont_trans_s5b_cand_used, ONE},
643         {NAME, "candidate-error", xmpp_jingle_cont_trans_s5b_cand_error, ONE},
644         {NAME, "proxy-error", xmpp_jingle_cont_trans_s5b_proxy_error, ONE},
645     };
646
647     trans_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
648     trans_tree = proto_item_add_subtree(trans_item, ett_xmpp_jingle_cont_trans);
649
650     display_attrs(trans_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
651     display_elems(trans_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
652 }
653
654 static void
655 xmpp_jingle_cont_trans_s5b_candidate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
656 {
657     proto_item *cand_item;
658     proto_tree *cand_tree;
659
660     const gchar * type_enums[] = {"assisted", "direct", "proxy", "tunnel"};
661     array_t *type_enums_array = ep_init_array_t(type_enums, array_length(type_enums));
662
663     attr_info attrs_info[] = {
664         {"xmlns", hf_xmpp_xmlns, FALSE, FALSE, NULL, NULL},
665         {"cid", -1, TRUE, TRUE, NULL, NULL},
666         {"jid", -1, TRUE, TRUE, NULL, NULL},
667         {"port", -1, FALSE, TRUE, NULL, NULL},
668         {"priority", -1, TRUE, TRUE, NULL, NULL},
669         {"type", -1, TRUE, TRUE, val_enum_list, type_enums_array}
670     };
671
672     cand_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_cand, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
673     cand_tree = proto_item_add_subtree(cand_item, ett_xmpp_jingle_cont_trans_cand);
674
675     display_attrs(cand_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
676     display_elems(cand_tree, element, pinfo, tvb, NULL, 0);
677 }
678
679 static void
680 xmpp_jingle_cont_trans_s5b_activated(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
681 {
682     proto_item *activated_item;
683     attr_t *cid = get_attr(element, "cid");
684
685     activated_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_activated, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
686     proto_item_append_text(activated_item, " [cid=\"%s\"]",cid?cid->value:"");
687     
688     xmpp_unknown(tree, tvb, pinfo, element);
689 }
690
691 static void
692 xmpp_jingle_cont_trans_s5b_cand_used(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
693 {
694     proto_item *cand_used_item;
695     attr_t *cid = get_attr(element, "cid");
696
697     cand_used_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_candidate_used, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
698     proto_item_append_text(cand_used_item, " [cid=\"%s\"]",cid?cid->value:"");
699
700     xmpp_unknown(tree, tvb, pinfo, element);
701 }
702
703 static void
704 xmpp_jingle_cont_trans_s5b_cand_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
705 {
706     proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_candidate_error, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
707     xmpp_unknown(tree, tvb, pinfo, element);
708 }
709
710 static void
711 xmpp_jingle_cont_trans_s5b_proxy_error(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
712 {
713     proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans_proxy_error, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
714     xmpp_unknown(tree, tvb, pinfo, element);
715 }
716
717 /*XEP-0261: Jingle In-Band Bytestreams Transport Method urn:xmpp:jingle:transports:ibb:1*/
718 static void
719 xmpp_jingle_cont_trans_ibb(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element) {
720     proto_item *trans_item;
721     proto_tree *trans_tree;
722
723     attr_info attrs_info[] = {
724         {"xmlns", hf_xmpp_xmlns, FALSE, TRUE, NULL, NULL},
725         {"block-size", -1, TRUE, TRUE, NULL, NULL},
726         {"sid", -1, TRUE, TRUE, NULL, NULL},
727         {"stanza", -1, FALSE, TRUE, NULL, NULL}
728     };
729
730     trans_item = proto_tree_add_item(tree, hf_xmpp_jingle_cont_trans, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
731     trans_tree = proto_item_add_subtree(trans_item, ett_xmpp_jingle_cont_trans);
732
733     display_attrs(trans_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
734     display_elems(trans_tree, element, pinfo, tvb, NULL, 0);
735 }
736
737 /*XEP-0234: Jingle File Transfer urn:xmpp:jingle:apps:file-transfer:3*/
738 static void
739 xmpp_jingle_file_transfer_desc(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
740 {
741     proto_item *desc_item;
742     proto_tree *desc_tree;
743
744     attr_info attrs_info[] = {
745         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}
746     };
747
748     elem_info elems_info[] = {
749         {NAME, "offer", xmpp_jingle_file_transfer_offer, ONE},
750         {NAME, "request", xmpp_jingle_file_transfer_request, ONE}
751     };
752
753     desc_item = proto_tree_add_item(tree, hf_xmpp_jingle_content_description, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
754     desc_tree = proto_item_add_subtree(desc_item, ett_xmpp_jingle_content_description);
755
756     display_attrs(desc_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
757     display_elems(desc_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
758 }
759
760 static void
761 xmpp_jingle_file_transfer_offer(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
762 {
763     proto_item *offer_item;
764     proto_tree *offer_tree;
765
766     elem_info elems_info[] = {
767         {NAME, "file", xmpp_jingle_file_transfer_file, MANY},
768     };
769
770     offer_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_offer, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
771     offer_tree = proto_item_add_subtree(offer_item, ett_xmpp_jingle_file_transfer_offer);
772
773     display_attrs(offer_tree, element, pinfo, tvb, NULL, 0);
774     display_elems(offer_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
775 }
776
777 static void
778 xmpp_jingle_file_transfer_request(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
779 {
780     proto_item *request_item;
781     proto_tree *request_tree;
782
783     elem_info elems_info[] = {
784         {NAME, "file", xmpp_jingle_file_transfer_file, MANY},
785     };
786
787     request_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_request, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
788     request_tree = proto_item_add_subtree(request_item, ett_xmpp_jingle_file_transfer_request);
789
790     display_attrs(request_tree, element, pinfo, tvb, NULL, 0);
791     display_elems(request_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
792 }
793
794 static void
795 xmpp_jingle_file_transfer_received(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
796 {
797     proto_item *received_item;
798     proto_tree *received_tree;
799
800     elem_info elems_info[] = {
801         {NAME, "file", xmpp_jingle_file_transfer_file, MANY},
802     };
803
804     received_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_received, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
805     received_tree = proto_item_add_subtree(received_item, ett_xmpp_jingle_file_transfer_received);
806
807     display_attrs(received_tree, element, pinfo, tvb, NULL, 0);
808     display_elems(received_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
809 }
810
811 static void
812 xmpp_jingle_file_transfer_abort(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
813 {
814     proto_item *abort_item;
815     proto_tree *abort_tree;
816
817     elem_info elems_info[] = {
818         {NAME, "file", xmpp_jingle_file_transfer_file, MANY},
819     };
820
821     abort_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_abort, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
822     abort_tree = proto_item_add_subtree(abort_item, ett_xmpp_jingle_file_transfer_abort);
823
824     display_attrs(abort_tree, element, pinfo, tvb, NULL, 0);
825     display_elems(abort_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
826 }
827
828 static void
829 xmpp_jingle_file_transfer_checksum(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
830 {
831     proto_item *checksum_item;
832     proto_tree *checksum_tree;
833
834     elem_info elems_info[] = {
835         {NAME, "file", xmpp_jingle_file_transfer_file, MANY},
836     };
837
838     checksum_item = proto_tree_add_item(tree, hf_xmpp_jingle_file_transfer_checksum, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
839     checksum_tree = proto_item_add_subtree(checksum_item, ett_xmpp_jingle_file_transfer_checksum);
840
841     display_attrs(checksum_tree, element, pinfo, tvb, NULL, 0);
842     display_elems(checksum_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
843 }
844
845 static void
846 xmpp_jingle_file_transfer_file(proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo, element_t* element)
847 {
848     proto_item *file_item;
849     proto_tree *file_tree;
850
851     attr_info attrs_info[] = {
852         {"name", -1, FALSE, TRUE, NULL, NULL},
853         {"size", -1, FALSE, TRUE, NULL, NULL},
854         {"date", -1, FALSE, TRUE, NULL, NULL}
855     };
856
857     elem_info elems_info[] = {
858         {NAME, "hashes", xmpp_hashes, ONE}
859     };
860
861     file_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "FILE");
862     file_tree = proto_item_add_subtree(file_item, ett_xmpp_jingle_file_transfer_file);
863
864     change_elem_to_attrib("name", "name", element, transform_func_cdata);
865     change_elem_to_attrib("size", "size", element, transform_func_cdata);
866     change_elem_to_attrib("date", "date", element, transform_func_cdata);
867
868     display_attrs(file_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
869     display_elems(file_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
870 }
871
872 /*XEP-0278: Jingle Relay Nodes http://jabber.org/protocol/jinglenodes*/
873 void
874 xmpp_jinglenodes_services(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
875 {
876     proto_item *services_item;
877     proto_tree *services_tree;
878
879     attr_info attrs_info[] = {
880         {"xmlns", hf_xmpp_xmlns, TRUE, TRUE, NULL, NULL}
881     };
882
883     elem_info elems_info[] = {
884         {NAME, "relay", xmpp_jinglenodes_relay_stun_tracker, ONE},
885         {NAME, "tracker", xmpp_jinglenodes_relay_stun_tracker, ONE},
886         {NAME, "stun", xmpp_jinglenodes_relay_stun_tracker, ONE},
887     };
888
889     col_append_fstr(pinfo->cinfo, COL_INFO, "SERVICES ");
890
891     services_item = proto_tree_add_item(tree, hf_xmpp_services, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
892     services_tree = proto_item_add_subtree(services_item, ett_xmpp_services);
893
894     display_attrs(services_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
895     display_elems(services_tree, element, pinfo, tvb, elems_info, array_length(elems_info));
896 }
897
898 static void
899 xmpp_jinglenodes_relay_stun_tracker(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
900 {
901     proto_item *relay_item;
902     proto_tree *relay_tree;
903
904     attr_info attrs_info[] = {
905         {"address", -1, TRUE, TRUE, NULL, NULL},
906         {"port", -1, FALSE, TRUE, NULL, NULL},
907         {"policy", -1, TRUE, TRUE, NULL, NULL},
908         {"protocol", -1, TRUE, TRUE, NULL, NULL},
909     };
910
911     relay_item = proto_tree_add_text(tree, tvb, element->offset, element->length, "%s", element->name);
912     relay_tree = proto_item_add_subtree(relay_item, ett_xmpp_services_relay);
913
914     display_attrs(relay_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
915     display_elems(relay_tree, element, pinfo, tvb, NULL, 0);
916 }
917
918 void
919 xmpp_jinglenodes_channel(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, element_t *element)
920 {
921     proto_item *channel_item;
922     proto_tree *channel_tree;
923
924     attr_info attrs_info[] = {
925         {"xmlns", hf_xmpp_xmlns, TRUE, FALSE, NULL, NULL},
926         {"id", -1, FALSE, FALSE, NULL, NULL},
927         {"host", -1, FALSE, TRUE, NULL, NULL},
928         {"localport", -1, FALSE, TRUE, NULL, NULL},
929         {"remoteport", -1, FALSE, TRUE, NULL, NULL},
930         {"protocol", -1, TRUE, TRUE, NULL, NULL},
931         {"maxkbps", -1, FALSE, FALSE, NULL, NULL},
932         {"expire", -1, FALSE, FALSE, NULL, NULL},
933     };
934
935     channel_item = proto_tree_add_item(tree, hf_xmpp_channel, tvb, element->offset, element->length, ENC_BIG_ENDIAN);
936     channel_tree = proto_item_add_subtree(channel_item, ett_xmpp_channel);
937
938     display_attrs(channel_tree, element, pinfo, tvb, attrs_info, array_length(attrs_info));
939     display_elems(channel_tree, element, pinfo, tvb, NULL, 0);
940 }
941 /*
942 * Editor modelines - http://www.wireshark.org/tools/modelines.html
943 *
944 * Local variables:
945 * c-basic-offset: 4
946 * tab-width: 8
947 * indent-tabs-mode: nil
948 * End:
949 *
950 * ex: set shiftwidth=4 tabstop=8 expandtab:
951 * :indentSize=4:tabSize=8:noTabs=true:
952 */