1 /* packet-allJoyn.c
2  * Routines for AllJoyn (AllJoyn.org) packet dissection
3  * Copyright (c) 2013-2014, The Linux Foundation.
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11 
12 #include "config.h"
13 #include <epan/packet.h>
14 #include <epan/expert.h>
15 #include <wsutil/ws_roundup.h>
16 
17 void proto_register_AllJoyn(void);
18 void proto_reg_handoff_AllJoyn(void);
19 
20 #define ALLJOYN_NAME_SERVER_PORT      9956 /* IANA lists only UDP as being registered (dissector also uses TCP port) */
21 #define ALLJOYN_MESSAGE_PORT      9955
22 
23 /* DBus limits array length to 2^26. AllJoyn limits it to 2^17 */
24 #define MAX_ARRAY_LEN 131072
25 /* DBus limits packet length to 2^27. AllJoyn limits it further to 2^17 + 4096 to allow for 2^17 payload */
26 #define MAX_PACKET_LEN (MAX_ARRAY_LEN + 4096)
27 
28 /* The following are protocols within a frame.
29    The actual value of the handle is set when the various fields are
30    registered in proto_register_AllJoyn() with a call to
31    proto_register_protocol().
32 */
33 static int proto_AllJoyn_mess = -1; /* The top level. Entire AllJoyn message protocol. */
34 
35 /* These are Wireshark header fields. You can search/filter on these values. */
36 /* The initial byte sent when first connecting. */
37 static int hf_alljoyn_connect_byte_value = -1;
38 
39 /* SASL fields. */
40 static int hf_alljoyn_sasl_command = -1;
41 static int hf_alljoyn_sasl_parameter = -1;
42 /* Message header fields.
43 See http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
44 for details. */
45 static int hf_alljoyn_mess_header = -1;              /* The complete header. */
46 static int hf_alljoyn_mess_header_endian = -1;       /* 1st byte. */
47 static int hf_alljoyn_mess_header_type = -1;         /* 2nd byte. */
48 static int hf_alljoyn_mess_header_flags = -1;        /* 3rd byte. */
49 static int hf_alljoyn_mess_header_majorversion = -1; /* 4th byte. */
50 static int hf_alljoyn_mess_header_body_length = -1;  /* 1st uint32. */
51 static int hf_alljoyn_mess_header_serial = -1;       /* 2nd uint32. */
52 static int hf_alljoyn_mess_header_header_length = -1;/* 3rd uint32. AllJoyn extension. */
53 
54 static int hf_alljoyn_mess_header_flags_no_reply = -1;          /* Part of 3rd byte. */
55 static int hf_alljoyn_mess_header_flags_no_auto_start = -1;     /* Part of 3rd byte. */
56 static int hf_alljoyn_mess_header_flags_allow_remote_msg = -1;  /* Part of 3rd byte. */
57 static int hf_alljoyn_mess_header_flags_sessionless = -1;       /* Part of 3rd byte. */
58 static int hf_alljoyn_mess_header_flags_global_broadcast = -1;  /* Part of 3rd byte. */
59 static int hf_alljoyn_mess_header_flags_compressed = -1;        /* Part of 3rd byte. */
60 static int hf_alljoyn_mess_header_flags_encrypted = -1;         /* Part of 3rd byte. */
61 static int hf_alljoyn_mess_header_field = -1;
62 static int hf_alljoyn_mess_header_fields = -1;
63 static int hf_alljoyn_mess_body_header_fieldcode = -1;
64 static int hf_alljoyn_mess_body_header_typeid = -1;
65 static int hf_alljoyn_mess_body_array = -1;
66 static int hf_alljoyn_mess_body_structure = -1;
67 static int hf_alljoyn_mess_body_dictionary_entry = -1;
68 static int hf_alljoyn_mess_body_parameters = -1;
69 static int hf_alljoyn_mess_body_variant = -1;
70 static int hf_alljoyn_mess_body_signature = -1;
71 static int hf_alljoyn_mess_body_signature_length = -1;
72 
73 static int hf_alljoyn_boolean = -1;
74 static int hf_alljoyn_uint8 = -1;
75 static int hf_alljoyn_int16 = -1;
76 static int hf_alljoyn_uint16 = -1;
77 static int hf_alljoyn_int32 = -1;
78 static int hf_alljoyn_handle = -1;
79 static int hf_alljoyn_uint32 = -1;
80 static int hf_alljoyn_int64 = -1;
81 static int hf_alljoyn_uint64 = -1;
82 static int hf_alljoyn_double = -1;
83 static int hf_padding = -1;         /* Some fields are padded to an even number of 2, 4, or 8 bytes. */
84 
85 #define MESSAGE_HEADER_FLAG_NO_REPLY_EXPECTED 0x01
86 #define MESSAGE_HEADER_FLAG_NO_AUTO_START     0x02
87 #define MESSAGE_HEADER_FLAG_ALLOW_REMOTE_MSG  0x04
88 #define MESSAGE_HEADER_FLAG_SESSIONLESS       0x10
89 #define MESSAGE_HEADER_FLAG_GLOBAL_BROADCAST  0x20
90 #define MESSAGE_HEADER_FLAG_COMPRESSED        0x40
91 #define MESSAGE_HEADER_FLAG_ENCRYPTED         0x80
92 
93 /* Protocol identifiers. */
94 static int proto_AllJoyn_ns = -1;  /* The top level. Entire AllJoyn Name Service protocol. */
95 
96 static int hf_alljoyn_answer = -1;
97 static int hf_alljoyn_isat_entry = -1;
98 static int hf_alljoyn_isat_guid_string = -1;
99 
100 static int hf_alljoyn_ns_header = -1;
101 static int hf_alljoyn_ns_sender_version = -1;
102 static int hf_alljoyn_ns_message_version = -1;
103 static int hf_alljoyn_ns_questions = -1;
104 static int hf_alljoyn_ns_answers = -1;
105 static int hf_alljoyn_ns_timer = -1;
106 
107 /* These are bit masks for version 0 "who has" records. */
108 /* These bits are deprecated and do not exist for version 1. */
109 #define WHOHAS_T 0x08
110 #define WHOHAS_U 0x04
111 #define WHOHAS_S 0x02
112 #define WHOHAS_F 0x01
113 
114 static int hf_alljoyn_ns_whohas = -1;
115 static int hf_alljoyn_ns_whohas_t_flag = -1;   /* 0x8 -- TCP  */
116 static int hf_alljoyn_ns_whohas_u_flag = -1;   /* 0x4 -- UDP  */
117 static int hf_alljoyn_ns_whohas_s_flag = -1;   /* 0x2 -- IPV6 */
118 static int hf_alljoyn_ns_whohas_f_flag = -1;   /* 0x1 -- IPV4 */
119 /* End of version 0 bit masks. */
120 
121 static int hf_alljoyn_ns_whohas_count = -1;    /* octet count of bus names */
122 
123 /* Bitmasks common to v0 and v1 IS-AT messages. */
124 #define ISAT_C 0x10
125 #define ISAT_G 0x20
126 
127 /* Bitmasks for v0 IS-AT messages. */
128 #define ISAT_F 0x01
129 #define ISAT_S 0x02
130 #define ISAT_U 0x04
131 #define ISAT_T 0x08
132 
133 /* Bitmasks for v1 IS-AT messages. */
134 #define ISAT_U6 0x01
135 #define ISAT_R6 0x02
136 #define ISAT_U4 0x04
137 #define ISAT_R4 0x08
138 
139 /* Bitmasks for v1 transports. */
140 #define TRANSPORT_LOCAL     0x0001  /* Local (same device) transport. */
141 #define TRANSPORT_BLUETOOTH 0x0002  /* Bluetooth transport. */
142 #define TRANSPORT_TCP       0x0004  /* Transport using TCP (same as TRANSPORT_WLAN). */
143 #define TRANSPORT_WWAN      0x0008  /* Wireless wide-area network transport. */
144 #define TRANSPORT_LAN       0x0010  /* Wired local-area network transport. */
145 #define TRANSPORT_ICE       0x0020  /* Transport using ICE protocol. */
146 #define TRANSPORT_WFD       0x0080  /* Transport using Wi-Fi Direct transport. */
147 
148 /* Tree indexes common to v0 and v1 IS-AT messages. */
149 static int hf_alljoyn_ns_isat_g_flag = -1;     /* 0x20 -- GUID present */
150 static int hf_alljoyn_ns_isat_c_flag = -1;     /* 0x10 -- Complete */
151 
152 /* Tree indexes for v0 IS-AT messages. */
153 static int hf_alljoyn_ns_isat_t_flag = -1;     /* 0x8 -- TCP */
154 static int hf_alljoyn_ns_isat_u_flag = -1;     /* 0x4 -- UDP */
155 static int hf_alljoyn_ns_isat_s_flag = -1;     /* 0x2 -- IPV6 */
156 static int hf_alljoyn_ns_isat_f_flag = -1;     /* 0x1 -- IPV4 */
157 static int hf_alljoyn_ns_isat_count = -1;      /* octet count of bus names */
158 static int hf_alljoyn_ns_isat_port = -1;       /* two octets of port number */
159 static int hf_alljoyn_ns_isat_ipv4 = -1;       /* four octets of IPv4 address */
160 static int hf_alljoyn_ns_isat_ipv6 = -1;       /* sixteen octets of IPv6 address */
161 
162 /* Tree indexes for v1 IS-AT messages. */
163 static int hf_alljoyn_ns_isat_u6_flag = -1;    /* 0x8 -- UDP IPV6 */
164 static int hf_alljoyn_ns_isat_r6_flag = -1;    /* 0x4 -- TCP IPV6 */
165 static int hf_alljoyn_ns_isat_u4_flag = -1;    /* 0x2 -- UDP IPV4 */
166 static int hf_alljoyn_ns_isat_r4_flag = -1;    /* 0x1 -- TCP IPV4 */
167 
168 static int hf_alljoyn_ns_isat_transport_mask = -1; /* All bits of the transport mask. */
169 
170 /* Individual bits of the mask. */
171 static int hf_alljoyn_ns_isat_transport_mask_local = -1;    /* Local (same device) transport */
172 static int hf_alljoyn_ns_isat_transport_mask_bluetooth = -1;/* Bluetooth transport */
173 static int hf_alljoyn_ns_isat_transport_mask_tcp = -1;      /* Transport using TCP (same as TRANSPORT_WLAN) */
174 static int hf_alljoyn_ns_isat_transport_mask_wwan = -1;     /* Wireless wide-area network transport */
175 static int hf_alljoyn_ns_isat_transport_mask_lan = -1;      /* Wired local-area network transport */
176 static int hf_alljoyn_ns_isat_transport_mask_ice = -1;      /* Transport using ICE protocol */
177 static int hf_alljoyn_ns_isat_transport_mask_wfd = -1;      /* Transport using Wi-Fi Direct transport */
178 
179 static int hf_alljoyn_string = -1;
180 static int hf_alljoyn_string_size_8bit = -1;    /* 8-bit size of string */
181 static int hf_alljoyn_string_size_32bit = -1;   /* 32-bit size of string */
182 static int hf_alljoyn_string_data = -1;         /* string characters */
183 
184 /* Protocol identifiers. */
185 static int proto_AllJoyn_ardp = -1;  /* The top level. Entire AllJoyn Reliable Datagram Protocol. */
186 
187 #define ARDP_SYN_FIXED_HDR_LEN  28 /* Size of the fixed part for the ARDP connection packet header. */
188 #define ARDP_FIXED_HDR_LEN      34 /* Size of the fixed part for the ARDP header. */
189 #define ARDP_DATA_LENGTH_OFFSET  6 /* Offset into the ARDP header for the data length. */
190 #define ARDP_HEADER_LEN_OFFSET   1 /* Offset into the ARDP header for the actual length of the header. */
191 
192 /* These are bit masks for ARDP flags. */
193 /* These bits are deprecated and do not exist for version 1. */
194 #define ARDP_SYN 0x01
195 #define ARDP_ACK 0x02
196 #define ARDP_EAK 0x04
197 #define ARDP_RST 0x08
198 #define ARDP_NUL 0x10
199 #define ARDP_UNUSED 0x20
200 #define ARDP_VER0 0x40
201 #define ARDP_VER1 0x80
202 #define ARDP_VER (ARDP_VER0 | ARDP_VER1)
203 
204 static int hf_ardp_syn_flag = -1;       /* 0x01 -- SYN */
205 static int hf_ardp_ack_flag = -1;       /* 0x02 -- ACK */
206 static int hf_ardp_eak_flag = -1;       /* 0x04 -- EAK */
207 static int hf_ardp_rst_flag = -1;       /* 0x08 -- RST */
208 static int hf_ardp_nul_flag = -1;       /* 0x10 -- NUL */
209 static int hf_ardp_unused_flag = -1;    /* 0x20 -- UNUSED */
210 static int hf_ardp_version_field = -1;  /* 0xc0 */
211 
212 static int hf_ardp_hlen = -1;   /* header length */
213 static int hf_ardp_src = -1;    /* source port */
214 static int hf_ardp_dst = -1;    /* destination port */
215 static int hf_ardp_dlen = -1;   /* data length */
216 static int hf_ardp_seq = -1;    /* sequence number */
217 static int hf_ardp_ack = -1;    /* acknowledge number */
218 static int hf_ardp_ttl = -1;    /* time to live (ms) */
219 static int hf_ardp_lcs = -1;    /* last consumed sequence number */
220 static int hf_ardp_nsa = -1;    /* next sequence to ack */
221 static int hf_ardp_fss = -1;    /* fragment starting sequence number */
222 static int hf_ardp_fcnt = -1;   /* fragment count */
223 static int hf_ardp_bmp = -1;    /* EACK bitmap */
224 static int hf_ardp_segmax = -1; /* The maximum number of outstanding segments the other side can send without acknowledgment. */
225 static int hf_ardp_segbmax = -1;/* The maximum segment size we are willing to receive. */
226 static int hf_ardp_dackt = -1;  /* Receiver's delayed ACK timeout. Used in TTL estimate prior to sending a message. */
227 static int hf_ardp_options = -1;/* Options for the connection. Always Sequenced Delivery Mode (SDM). */
228 
229 static expert_field ei_alljoyn_empty_arg = EI_INIT;
230 
231 /* These are the ids of the subtrees we will be creating */
232 static gint ett_alljoyn_ns = -1;    /* This is the top NS tree. */
233 static gint ett_alljoyn_ns_header = -1;
234 static gint ett_alljoyn_ns_answers = -1;
235 static gint ett_alljoyn_ns_guid_string = -1;
236 static gint ett_alljoyn_ns_isat_entry = -1;
237 static gint ett_alljoyn_ns_string = -1;
238 static gint ett_alljoyn_whohas = -1;
239 static gint ett_alljoyn_string = -1;
240 static gint ett_alljoyn_isat_entry = -1;
241 static gint ett_alljoyn_mess = -1;  /* This is the top message tree. */
242 static gint ett_alljoyn_header = -1;
243 static gint ett_alljoyn_header_flags = -1;
244 static gint ett_alljoyn_mess_header_field = -1;
245 static gint ett_alljoyn_mess_header = -1;
246 static gint ett_alljoyn_mess_body_parameters = -1;
247 static gint ett_alljoyn_ardp = -1;  /* This is the top ARDP tree. */
248 
249 #define ROUND_TO_2BYTE(len) WS_ROUNDUP_2(len)
250 #define ROUND_TO_4BYTE(len) WS_ROUNDUP_4(len)
251 #define ROUND_TO_8BYTE(len) WS_ROUNDUP_8(len)
252 
253 static const value_string endian_encoding_vals[] = {
254     { 'B', "Big endian" },
255     { 'l', "Little endian" },
256     { 0, NULL },
257 };
258 
259 #define MESSAGE_TYPE_INVALID        0
260 #define MESSAGE_TYPE_METHOD_CALL    1
261 #define MESSAGE_TYPE_METHOD_REPLY   2
262 #define MESSAGE_TYPE_ERROR_REPLY    3
263 #define MESSAGE_TYPE_SIGNAL         4
264 
265 static const value_string message_header_encoding_vals[] = {
266     { MESSAGE_TYPE_INVALID,      "Invalid type" },
267     { MESSAGE_TYPE_METHOD_CALL,  "Method call" },
268     { MESSAGE_TYPE_METHOD_REPLY, "Method reply with returned data" },
269     { MESSAGE_TYPE_ERROR_REPLY,  "Error reply" },
270     { MESSAGE_TYPE_SIGNAL,       "Signal emission" },
271     { 0, NULL }
272 };
273 
274 /*
275  * The array at the end of the header contains header fields,
276  * where each field is a 1-byte field code followed by a field value.
277  * See also: http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
278  *
279  * In the D-Bus world these are the "field codes".
280  * In the AllJoyn world these are called "field types".
281  */
282 #define HDR_INVALID               0x00
283 #define HDR_OBJ_PATH              0x01
284 #define HDR_INTERFACE             0x02
285 #define HDR_MEMBER                0x03
286 #define HDR_ERROR_NAME            0x04
287 #define HDR_REPLY_SERIAL          0x05
288 #define HDR_DESTINATION           0x06
289 #define HDR_SENDER                0x07
290 #define HDR_SIGNATURE             0x08
291 #define HDR_HANDLES               0x09
292 #define HDR_TIMESTAMP             0x10 /* AllJoyn specific headers start at 0x10 */
293 #define HDR_TIME_TO_LIVE          0x11
294 #define HDR_COMPRESSION_TOKEN     0x12
295 #define HDR_SESSION_ID            0x13
296 
297 static const value_string mess_header_field_encoding_vals[] = {
298     { HDR_INVALID,           "Invalid" },           /* Not a valid field name (error if it appears in a message). */
299     { HDR_OBJ_PATH,          "Object Path" },       /* The object to send a call to, or the object a signal
300                                                        is emitted from. */
301     { HDR_INTERFACE,         "Interface" },         /* The interface to invoke a method call on, or that a
302                                                        signal is emitted from. Optional for method calls,
303                                                        required for signals. */
304     { HDR_MEMBER,            "Member" },            /* The member, either the method name or signal name. */
305     { HDR_ERROR_NAME,        "Error Name" },        /* The name of the error that occurred, for errors. */
306     { HDR_REPLY_SERIAL,      "Reply Serial" },      /* The serial number of the message this message is a reply to. */
307     { HDR_DESTINATION,       "Destination" },       /* The name of the connection this message is intended for. */
308     { HDR_SENDER,            "Sender" },            /* Unique name of the sending connection. */
309     { HDR_SIGNATURE,         "Signature" },         /* The signature of the message body. */
310     { HDR_HANDLES,           "Handles" },           /* The number of handles (Unix file descriptors) that
311                                                        accompany the message.  */
312     { HDR_TIMESTAMP,         "Time stamp" },
313     { HDR_TIME_TO_LIVE,      "Time to live" },
314     { HDR_COMPRESSION_TOKEN, "Compression token" },
315     { HDR_SESSION_ID,        "Session ID" },
316     { 0, NULL }
317 };
318 
319 /* This is used to round up offsets into a packet to an even two byte
320  * boundary from starting_offset.
321  * @param current_offset is the current offset into the packet.
322  * @param starting_offset is offset into the packet from the beginning of
323  *        the message.
324  * @returns the offset rounded up to the next even two byte boundary from
325             start of the message.
326  */
327 static gint round_to_2byte(gint current_offset,
328                            gint starting_offset)
329 {
330     gint length = current_offset - starting_offset;
331 
332     return starting_offset + ROUND_TO_2BYTE(length);
333 }
334 
335 /* This is used to round up offsets into a packet to an even four byte
336  * boundary from starting_offset.
337  * @param current_offset is the current offset into the packet.
338  * @param starting_offset is offset into the packet from the beginning of
339  *        the message.
340  * @returns the offset rounded up to the next even four byte boundary from
341             start of the message.
342  */
343 static gint round_to_4byte(gint current_offset,
344                            gint starting_offset)
345 {
346     gint length = current_offset - starting_offset;
347 
348     return starting_offset + ROUND_TO_4BYTE(length);
349 }
350 
351 /* This is used to round up offsets into a packet to an even eight byte
352  * boundary from starting_offset.
353  * @param current_offset is the current offset into the packet.
354  * @param starting_offset is offset into the packet from the beginning of
355  *        the message.
356  * @returns the offset rounded up to the next even eight byte boundary from
357             start of the message.
358  */
359 static gint round_to_8byte(gint current_offset,
360                            gint starting_offset)
361 {
362     gint length = current_offset - starting_offset;
363 
364     return starting_offset + ROUND_TO_8BYTE(length);
365 }
366 
367 /* This is the maximum number of rounding bytes that is ever used.
368  * This define is used for error checking. */
369 #define MAX_ROUND_TO_BYTES 7
370 
371 /* Gets a 32-bit unsigned integer from the packet buffer with
372  * the proper byte-swap.
373  * @param tvb is the incoming network data buffer.
374  * @param offset is the offset into the buffer.
375  * @param encoding is ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN.
376  * @return The 32-bit unsigned int interpretation of the bits
377  *         in the buffer.
378  */
379 static guint32
380 get_uint32(tvbuff_t *tvb,
381            gint32    offset,
382            gint      encoding)
383 {
384     return (ENC_BIG_ENDIAN == encoding) ?
385         tvb_get_ntohl(tvb, offset) :
386         tvb_get_letohl(tvb, offset);
387 }
388 
389 /* This is called by dissect_AllJoyn_message() to handle the initial byte for
390  * a connect message.
391  * If it was the initial byte for a connect message and was handled then return
392  * the number of bytes consumed out of the packet. If not an connect initial
393  * byte message or unhandled return 0.
394  * @param tvb is the incoming network data buffer.
395  * @param pinfo contains information about the incoming packet which
396  *         we update as we dissect the packet.
397  * @param offset is the offset into the packet to check for the connect message.
398  * @param message_tree is the subtree that any connect data items should be added to.
399  * @returns the offset into the packet that has successfully been handled or
400  * the input offset value if it was not the connect initial byte of 0.
401  */
402 static gint
403 handle_message_connect(tvbuff_t    *tvb,
404                        packet_info *pinfo,
405                        gint         offset,
406                        proto_tree  *message_tree)
407 {
408     guint8 the_one_byte;
409 
410     the_one_byte = tvb_get_guint8(tvb, offset);
411 
412     if(0 == the_one_byte) {
413         col_set_str(pinfo->cinfo, COL_INFO, "CONNECT-initial byte");
414 
415         /* Now add the value as a subtree to the initial byte. */
416         proto_tree_add_item(message_tree, hf_alljoyn_connect_byte_value, tvb, offset, 1, ENC_NA);
417         offset += 1;
418     }
419 
420     return offset;
421 }
422 
423 typedef struct _sasl_cmd
424 {
425     const gchar *text;
426     guint        length;
427 } sasl_cmd;
428 
429 static const gchar CMD_AUTH[]     = "AUTH";
430 static const gchar CMD_CANCEL[]   = "CANCEL";
431 static const gchar CMD_BEGIN[]    = "BEGIN";
432 static const gchar CMD_DATA[]     = "DATA";
433 static const gchar CMD_ERROR[]    = "ERROR";
434 static const gchar CMD_REJECTED[] = "REJECTED";
435 static const gchar CMD_OK[]       = "OK";
436 
437 #define MAX_SASL_COMMAND_LENGTH sizeof(CMD_REJECTED)
438 /* The 256 is just something I pulled out of the air. */
439 #define MAX_SASL_PACKET_LENGTH (MAX_SASL_COMMAND_LENGTH + 256)
440 
441 static const sasl_cmd sasl_commands[] = {
442     {CMD_AUTH,      G_N_ELEMENTS(CMD_AUTH) - 1},
443     {CMD_CANCEL,    G_N_ELEMENTS(CMD_CANCEL) - 1},
444     {CMD_BEGIN,     G_N_ELEMENTS(CMD_BEGIN) - 1},
445     {CMD_DATA,      G_N_ELEMENTS(CMD_DATA) - 1},
446     {CMD_ERROR,     G_N_ELEMENTS(CMD_ERROR) - 1},
447     {CMD_REJECTED,  G_N_ELEMENTS(CMD_REJECTED) - 1},
448     {CMD_OK,        G_N_ELEMENTS(CMD_OK) - 1},
449 };
450 
451 static const gint sasl_commands_count = G_N_ELEMENTS(sasl_commands);
452 
453 static const sasl_cmd *
454 find_sasl_command(tvbuff_t *tvb,
455                   gint      offset)
456 {
457     gint command_index;
458 
459     for(command_index = 0; command_index < sasl_commands_count; command_index++) {
460         const sasl_cmd *cmd;
461 
462         cmd = &sasl_commands[command_index];
463 
464         if(0 == tvb_strneql(tvb, offset, cmd->text, cmd->length)) {
465             return cmd;
466         }
467     }
468 
469     return NULL;
470 }
471 
472 /* Call this to test whether desegmentation is possible and if so correctly
473  * set the pinfo structure with the applicable data.
474  * @param pinfo contains information about the incoming packet.
475  * @param next_offset is the offset into the tvbuff where it is desired to start processing next time.
476  * @param addition_bytes_needed is the additional bytes required beyond what is already available.
477  * @returns TRUE if desegmentation is possible. FALSE if not.
478  */
479 static gboolean set_pinfo_desegment(packet_info *pinfo, gint next_offset, gint addition_bytes_needed)
480 {
481     if(pinfo->can_desegment) {
482         pinfo->desegment_offset = next_offset;
483         pinfo->desegment_len = addition_bytes_needed;
484 
485         return TRUE;
486     }
487 
488     return FALSE;
489 }
490 
491 /* This is called by dissect_AllJoyn_message() to handle SASL messages.
492  * If it was a SASL message and was handled then return the number of bytes
493  * used (should be the entire packet). If not a SASL message or unhandled return 0.
494  * If more bytes are needed then return the negative of the bytes expected.
495  * @param tvb is the incoming network data buffer.
496  * @param pinfo contains information about the incoming packet which
497  *         we update as we dissect the packet.
498  * @param offset is the offset into the packet to start processing.
499  * @param message_tree is the subtree that any connect data items should be added to.
500  * @returns the offset into the packet that has successfully been handled or
501  *         the input offset value if it was not a sasl message.
502  */
503 static gint
504 handle_message_sasl(tvbuff_t    *tvb,
505                     packet_info *pinfo,
506                     gint         offset,
507                     proto_tree  *message_tree)
508 {
509     gint            return_value = offset;
510     const sasl_cmd *command;
511 
512     command = find_sasl_command(tvb, offset);
513 
514     if(command) {
515         /* This gives us the offset into the buffer of the terminating character of
516          * the command, the '\n'. + 1 to get the number of bytes used for the
517          * command in the buffer. tvb_find_guint8() returns -1 if not found so the + 1
518          * will result in a newline_offset of 0 if not found.
519          */
520         gint newline_offset = tvb_find_guint8(tvb, offset + command->length, -1, '\n') + 1;
521 
522         /* If not found see if we should request another segment. */
523         if(0 == newline_offset) {
524             if((guint)tvb_captured_length_remaining(tvb, offset) < MAX_SASL_PACKET_LENGTH &&
525                 set_pinfo_desegment(pinfo, offset, DESEGMENT_ONE_MORE_SEGMENT)) {
526 
527                 /* Return the length of the buffer we successfully parsed. */
528                 return_value = offset + command->length;
529             } else {
530                 /* If we can't desegment then return 0 meaning we didn't do anything. */
531                 return_value = 0;
532             }
533 
534             return return_value;
535         }
536 
537         if(newline_offset > 0) {
538             gint length = command->length;
539 
540             col_add_fstr(pinfo->cinfo, COL_INFO, "SASL-%s", command->text);
541 
542             /* Add a subtree/row for the command. */
543             proto_tree_add_item(message_tree, hf_alljoyn_sasl_command, tvb, offset, length, ENC_ASCII|ENC_NA);
544             offset += length;
545             length = newline_offset - offset;
546 
547             /* Add a subtree for the parameter. */
548             proto_tree_add_item(message_tree, hf_alljoyn_sasl_parameter, tvb, offset, length, ENC_ASCII|ENC_NA);
549 
550             return_value = newline_offset;
551         }
552     }
553 
554     return return_value;
555 }
556 
557 #define ENC_ALLJOYN_BAD_ENCODING 0xBADF00D
558 
559 #define ENDIANNESS_OFFSET 0 /* The offset for endianness is always 0. */
560 
561 /* This is called by handle_message_header_body() to get the endianness from
562  * message headers.
563  * @param tvb is the incoming network data buffer.
564  * @param offset is the current offset into network data buffer.
565  * @return The type of encoding, ENC_LITTLE_ENDIAN or ENC_BIG_ENDIAN, for
566  * the message.
567  */
568 static guint32
569 get_message_header_endianness(tvbuff_t *tvb,
570                               gint      offset)
571 {
572     guint8 endianness;
573     guint  encoding;
574 
575     /* The endianness field. */
576     endianness = tvb_get_guint8(tvb, offset + ENDIANNESS_OFFSET);
577 
578     switch(endianness)
579     {
580     case 'l':
581         encoding = ENC_LITTLE_ENDIAN;
582         break;
583     case 'B':
584         encoding = ENC_BIG_ENDIAN;
585         break;
586     default:
587         encoding = ENC_ALLJOYN_BAD_ENCODING;
588         break;
589     }
590 
591     return encoding;
592 }
593 
594 /* This is called by handle_message_field() to handle bytes of particular values
595  * in messages.
596  * @param tvb is the incoming network data buffer.
597  * @param offset is the offset into the packet to start processing.
598  * @param field_tree is the subtree that we connect data items to.
599  * @param expected_value is the value the byte is expected to have.
600  */
601 static void
602 handle_message_header_expected_byte(tvbuff_t   *tvb,
603                                     gint        offset,
604                                     proto_tree *field_tree,
605                                     guint8      expected_value)
606 {
607     proto_item *item;
608     guint8      byte_value;
609 
610     item = proto_tree_add_item(field_tree, hf_alljoyn_uint8, tvb, offset, 1, ENC_NA);
611     byte_value = tvb_get_guint8(tvb, offset);
612 
613     if(expected_value == byte_value) {
614         proto_item_set_text(item, "0x%02x byte", expected_value);
615     } else {
616         proto_item_set_text(item, "Expected '0x%02x byte' but found '0x%02x'", expected_value, byte_value);
617     }
618 }
619 
620 /*
621  * Message argument types
622  */
623 #define ARG_INVALID           '\0'
624 #define ARG_ARRAY             'a'    /* AllJoyn array container type */
625 #define ARG_BOOLEAN           'b'    /* AllJoyn boolean basic type */
626 #define ARG_DOUBLE            'd'    /* AllJoyn IEEE 754 double basic type */
627 #define ARG_SIGNATURE         'g'    /* AllJoyn signature basic type */
628 #define ARG_HANDLE            'h'    /* AllJoyn socket handle basic type */
629 #define ARG_INT32             'i'    /* AllJoyn 32-bit signed integer basic type */
630 #define ARG_INT16             'n'    /* AllJoyn 16-bit signed integer basic type */
631 #define ARG_OBJ_PATH          'o'    /* AllJoyn Name of an AllJoyn object instance basic type */
632 #define ARG_UINT16            'q'    /* AllJoyn 16-bit unsigned integer basic type */
633 #define ARG_STRING            's'    /* AllJoyn UTF-8 NULL terminated string basic type */
634 #define ARG_UINT64            't'    /* AllJoyn 64-bit unsigned integer basic type */
635 #define ARG_UINT32            'u'    /* AllJoyn 32-bit unsigned integer basic type */
636 #define ARG_VARIANT           'v'    /* AllJoyn variant container type */
637 #define ARG_INT64             'x'    /* AllJoyn 64-bit signed integer basic type */
638 #define ARG_BYTE              'y'    /* AllJoyn 8-bit unsigned integer basic type */
639 #define ARG_STRUCT            '('    /* AllJoyn struct container type */
640 #define ARG_DICT_ENTRY        '{'    /* AllJoyn dictionary or map container type - an array of key-value pairs */
641 
642 static gint
643 pad_according_to_type(gint offset, gint field_starting_offset, gint max_offset, guint8 type)
644 {
645     switch(type)
646     {
647     case ARG_BYTE:
648         break;
649 
650     case ARG_DOUBLE:
651     case ARG_UINT64:
652     case ARG_INT64:
653     case ARG_STRUCT:
654     case ARG_DICT_ENTRY:
655         offset = round_to_8byte(offset, field_starting_offset);
656         break;
657 
658     case ARG_SIGNATURE:
659         break;
660 
661     case ARG_HANDLE:
662         break;
663 
664     case ARG_INT32:
665     case ARG_UINT32:
666     case ARG_BOOLEAN:
667         offset = round_to_4byte(offset, field_starting_offset);
668         break;
669 
670     case ARG_INT16:
671     case ARG_UINT16:
672         offset = round_to_2byte(offset, field_starting_offset);
673         break;
674 
675     case ARG_STRING:
676         break;
677 
678     case ARG_VARIANT:
679         break;
680 
681     case ARG_OBJ_PATH:
682         break;
683 
684     default:
685         break;
686     }
687 
688     if(offset > max_offset) {
689         offset = max_offset;
690     }
691 
692     return offset;
693 }
694 
695 /* This is called by parse_arg to append the signature of structure or dictionary
696  * to an item. This is complicated a bit by the fact that structures can be nested.
697  * @param item is the item to append the signature data to.
698  * @param signature points to the signature to be appended.
699  * @param signature_max_length is the specified maximum length of this signature.
700  * @param type_stop is the character when indicates the end of the signature.
701  */
702 static void
703 append_struct_signature(proto_item   *item,
704                         const guint8 *signature,
705                         gint          signature_max_length,
706                         const guint8  type_stop)
707 {
708     int    depth            = 0;
709     guint8 type_start;
710     gint   signature_length = 0;
711 
712     proto_item_append_text(item, "%c", ' ');
713     type_start = *signature;
714 
715     do {
716         if(type_start == *signature) {
717             depth++;
718         }
719 
720         if(type_stop == *signature) {
721             depth--;
722         }
723 
724         proto_item_append_text(item, "%c", *signature++);
725     } while(depth > 0 && ++signature_length < signature_max_length);
726 
727     if(signature_length >= signature_max_length) {
728         proto_item_append_text(item, "... Invalid signature!");
729     }
730 }
731 
732 /* This is called to advance the signature pointer to the end of the signature
733  * it is currently pointing at. signature_length is decreased by the appropriate
734  * amount before returning.
735  * @param signature is a pointer to the signature. It could be simple data type
736  * such as 'i', 'b', etc. In these cases *signature is advanced by 1 and
737  * *signature_length is decreased by 1. Or it could be an array, structure, dictionary,
738  * array of arrays or even more complex things. In these cases the advancement could
739  * be much larger. For example with the signature "a(bdas)i" *signature will be advanced
740  * to the 'i' and *signature_length will be set to '1'.
741  * @param signature_length is a pointer to the length of the signature.
742  */
743 static void
744 advance_to_end_of_signature(const guint8 **signature,
745                             guint8  *signature_length)
746 {
747     gboolean done = FALSE;
748     gint8 current_type;
749     gint8 end_type = ARG_INVALID;
750 
751     while (*signature_length > 0 && **signature && !done) {
752         current_type = *(++(*signature));
753         --*signature_length;
754 
755         /* Were we looking for the end of a structure or dictionary? If so, did we find it? */
756         if(end_type != ARG_INVALID) {
757             if(end_type == current_type) {
758                 done = TRUE; /* Found the end of the structure or dictionary. All done. */
759             }
760 
761             continue;
762         }
763 
764         switch(current_type)
765         {
766         case ARG_ARRAY:
767             advance_to_end_of_signature(signature, signature_length);
768             break;
769         case ARG_STRUCT:
770             end_type = ')';
771             advance_to_end_of_signature(signature, signature_length);
772             break;
773         case ARG_DICT_ENTRY:
774             end_type = '}';
775             advance_to_end_of_signature(signature, signature_length);
776             break;
777 
778         case ARG_BYTE:
779         case ARG_DOUBLE:
780         case ARG_UINT64:
781         case ARG_INT64:
782         case ARG_SIGNATURE:
783         case ARG_HANDLE:
784         case ARG_INT32:
785         case ARG_UINT32:
786         case ARG_BOOLEAN:
787         case ARG_INT16:
788         case ARG_UINT16:
789         case ARG_STRING:
790         case ARG_VARIANT:
791         case ARG_OBJ_PATH:
792             done = TRUE;
793             break;
794 
795         default:    /* Unrecognized signature. Bail out. */
796             done = TRUE;
797             break;
798         }
799     }
800 }
801 
802 /* This is called to add a padding item. There is not padding done for each call made.
803  * There is testing for the padding length which must be greater than zero. It's also possible,
804  * in the case of bad packets, that the end of the padding is wrong so range checking is
805  * also done. In the case of something being obviously wrong this function returns
806  * without adding the padding item.
807  * @param padding_start is the offset into tvb at which the (possible) padding starts.
808  * @param padding_end is the offset into tvb at which the (possible) padding ends.
809  * @param tvb is the incoming network data buffer.
810  * @param tree is the tree to which the new item should be attached.
811  */
812 static void add_padding_item(gint padding_start, gint padding_end, tvbuff_t *tvb, proto_tree *tree)
813 {
814     if(padding_end > padding_start && padding_end < (gint)tvb_reported_length(tvb)) {
815         gint padding_length = padding_end - padding_start;
816 
817         if (padding_length <= MAX_ROUND_TO_BYTES) {
818             proto_tree_add_item(tree, hf_padding, tvb, padding_start, padding_length, ENC_NA);
819         }
820     }
821 }
822 
823 /* This is called to handle a single typed argument. Recursion is used
824  * to handle arrays and structures.
825  * @param tvb is the incoming network data buffer.
826  * @param pinfo contains information about the incoming packet which
827  *         we update as we dissect the packet.
828  * @param header_item, if not NULL, is appended with the text name of the data type.
829  * @param encoding indicates big (ENC_BIG_ENDIAN) or little (ENC_LITTLE_ENDIAN)
830  * @param offset is the offset into tvb to get the field from.
831  * @param field_tree is the tree to which this argument should be attached.
832  * @param is_reply_to, if TRUE, means this uint32 value should be used to update
833  *         header_item and pinfo->cinfo with a special message.
834  * @param type_id is the type of this argument.
835  * @param field_code is the type of header, or HDR_INVALID if not used, which this
836  *         arg is a part of. If field_code is HDR_MEMBER or HDR_SIGNATURE then
837  *         pinfo->cinfo is updated with information.
838  * @param signature is a pointer to the signature of the parameters. If type_id is
839  *         ARG_SIGNATURE this is a return value for the caller to pass to the function
840  *         that parses the parameters. If type_id is something like ARG_STRUCT then it points
841  *         to the actual signature of the type.
842  * @param signature_length is a pointer to the length of the signature and if type_id is
843  *         ARG_SIGNATURE this is a return value for the caller to pass to the function
844  *         that parses the parameters.
845  * @param field_starting_offset is the offset at the beginning of the field that contains
846  *         this arg. When rounding this starting_offset is used rather than the absolute offset.
847  * @return The new offset into the buffer after removing the field code and value.
848  *         the message or the packet length to stop further processing if "really bad"
849  *         parameters come in.
850  */
851 static gint
852 parse_arg(tvbuff_t      *tvb,
853           packet_info   *pinfo,
854           proto_item    *header_item,
855           guint          encoding,
856           gint           offset,
857           proto_tree    *field_tree,
858           gboolean       is_reply_to,
859           guint8         type_id,
860           guint8         field_code,
861           const guint8 **signature,
862           guint8        *signature_length,
863           gint           field_starting_offset)
864 {
865     gint length;
866     gint padding_start;
867     gint saved_offset = offset;
868     const gchar *header_type_name = NULL;
869 
870     switch(type_id)
871     {
872     case ARG_INVALID:
873         header_type_name = "invalid";
874         offset = round_to_8byte(offset + 1, field_starting_offset);
875         break;
876 
877     case ARG_ARRAY:      /* AllJoyn array container type */
878         {
879             static gchar  bad_array_format[]  = "BAD DATA: Array length (in bytes) is %d. Remaining packet length is %d.";
880             proto_item   *item;
881             proto_tree   *tree;
882             const guint8 *sig_saved;
883             gint          starting_offset;
884             gint          number_of_items      = 0;
885             gint          packet_length        = (gint)tvb_reported_length(tvb);
886 
887             header_type_name = "array";
888 
889             if(*signature == NULL || *signature_length < 1) {
890                 col_add_fstr(pinfo->cinfo, COL_INFO, "BAD DATA: A %s argument needs a signature.", header_type_name);
891                 return tvb_reported_length(tvb);
892             }
893 
894             /* *sig_saved will now be the element type after the 'a'. */
895             sig_saved = (*signature) + 1;
896 
897             padding_start = offset;
898             offset = round_to_4byte(offset, field_starting_offset);
899             add_padding_item(padding_start, offset, tvb, field_tree);
900 
901             /* This is the length of the entire array in bytes but does not include the length field. */
902             length = (gint)get_uint32(tvb, offset, encoding);
903 
904             padding_start = offset + 4;
905             starting_offset = pad_according_to_type(padding_start, field_starting_offset, packet_length, *sig_saved); /* Advance to the data elements. */
906 
907             if(length < 0 || length > MAX_ARRAY_LEN || starting_offset + length > packet_length) {
908                 col_add_fstr(pinfo->cinfo, COL_INFO, bad_array_format, length, tvb_reported_length_remaining(tvb, starting_offset));
909                 return tvb_reported_length(tvb);
910             }
911 
912             /* This item is the entire array including the length specifier plus any pad bytes. */
913             item = proto_tree_add_item(field_tree, hf_alljoyn_mess_body_array, tvb, offset, (starting_offset-offset) + length, encoding);
914             tree = proto_item_add_subtree(item, ett_alljoyn_mess_body_parameters);
915 
916             offset = starting_offset;
917             add_padding_item(padding_start, offset, tvb, tree);
918 
919             if(0 == length) {
920                 advance_to_end_of_signature(signature, signature_length);
921             } else {
922                 guint8 sig_length_saved = *signature_length - 1;
923 
924                 while((offset - starting_offset) < length) {
925                     const guint8 *sig_pointer;
926                     guint8        remaining_sig_length;
927 
928                     number_of_items++;
929                     sig_pointer = sig_saved;
930                     remaining_sig_length = sig_length_saved;
931 
932                     offset = parse_arg(tvb,
933                                        pinfo,
934                                        header_item,
935                                        encoding,
936                                        offset,
937                                        tree,
938                                        is_reply_to,
939                                        *sig_pointer,
940                                        field_code,
941                                        &sig_pointer,
942                                        &remaining_sig_length,
943                                        field_starting_offset);
944 
945                     /* Set the signature pointer to be just past the type just handled. */
946                     *signature = sig_pointer;
947                     *signature_length = remaining_sig_length;
948                 }
949             }
950 
951             if(item) {
952                 proto_item_append_text(item, " of %d '%c' elements", number_of_items, *sig_saved);
953             }
954         }
955         break;
956 
957     case ARG_BOOLEAN:    /* AllJoyn boolean basic type */
958         header_type_name = "boolean";
959         padding_start = offset;
960         offset = round_to_4byte(offset, field_starting_offset);
961         add_padding_item(padding_start, offset, tvb, field_tree);
962 
963         proto_tree_add_item(field_tree, hf_alljoyn_boolean, tvb, offset, 4, encoding);
964         offset += 4;
965         break;
966 
967     case ARG_DOUBLE:     /* AllJoyn IEEE 754 double basic type */
968         header_type_name = "IEEE 754 double";
969         padding_start = offset;
970         offset = round_to_8byte(offset, field_starting_offset);
971         add_padding_item(padding_start, offset, tvb, field_tree);
972 
973         proto_tree_add_item(field_tree, hf_alljoyn_double, tvb, offset, 8, encoding);
974         offset += 8;
975         break;
976 
977     case ARG_SIGNATURE:  /* AllJoyn signature basic type */
978         header_type_name  = "signature";
979         length = tvb_get_guint8(tvb, offset);
980 
981         if (length + 2 > tvb_reported_length_remaining(tvb, offset)) {
982             gint bytes_left = tvb_reported_length_remaining(tvb, offset);
983 
984             col_add_fstr(pinfo->cinfo, COL_INFO, "BAD DATA: Signature length is %d. Only %d bytes left in packet.",
985                          length, bytes_left);
986             return tvb_reported_length(tvb);
987         }
988 
989         /* Include the terminating '/0'. */
990         length++;
991 
992         proto_tree_add_item(field_tree, hf_alljoyn_mess_body_signature_length, tvb, offset, 1, encoding);
993         offset += 1;
994 
995         /* Extract signature from tvb and return to caller. */
996         /* XXX should this extract "length - 1" since we always expect /0? */
997         proto_tree_add_item_ret_string(field_tree, hf_alljoyn_mess_body_signature, tvb, offset, length, ENC_ASCII|ENC_NA, pinfo->pool, signature);
998         *signature_length = length;
999 
1000         if(HDR_SIGNATURE == field_code) {
1001             col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", *signature);
1002         }
1003 
1004         offset += length;
1005         break;
1006 
1007     case ARG_HANDLE:     /* AllJoyn socket handle basic type. */
1008         header_type_name = "socket handle";
1009         padding_start = offset;
1010         offset = round_to_4byte(offset, field_starting_offset);
1011         add_padding_item(padding_start, offset, tvb, field_tree);
1012 
1013         proto_tree_add_item(field_tree, hf_alljoyn_handle, tvb, offset, 4, encoding);
1014         offset += 4;
1015         break;
1016 
1017     case ARG_INT32:      /* AllJoyn 32-bit signed integer basic type. */
1018         header_type_name = "int32";
1019         padding_start = offset;
1020         offset = round_to_4byte(offset, field_starting_offset);
1021         add_padding_item(padding_start, offset, tvb, field_tree);
1022 
1023         proto_tree_add_item(field_tree, hf_alljoyn_int32, tvb, offset, 4, encoding);
1024         offset += 4;
1025         break;
1026 
1027     case ARG_INT16:      /* AllJoyn 16-bit signed integer basic type. */
1028         header_type_name = "int16";
1029         padding_start = offset;
1030         offset = round_to_2byte(offset, field_starting_offset);
1031         add_padding_item(padding_start, offset, tvb, field_tree);
1032 
1033         proto_tree_add_item(field_tree, hf_alljoyn_int16, tvb, offset, 2, encoding);
1034         offset += 2;
1035         break;
1036 
1037     case ARG_OBJ_PATH:   /* AllJoyn Name of an AllJoyn object instance basic type */
1038         header_type_name = "object path";
1039         length = get_uint32(tvb, offset, encoding) + 1;
1040 
1041         /* The + 4 is for the length specifier. Object paths may be of "any length"
1042            according to D-Bus spec. But there are practical limits. */
1043         if(length < 0 || length > MAX_ARRAY_LEN || length + 4 > tvb_reported_length_remaining(tvb, offset)) {
1044             col_add_fstr(pinfo->cinfo, COL_INFO, "BAD DATA: Object path length is %d. Only %d bytes left in packet.",
1045                 length, tvb_reported_length_remaining(tvb, offset + 4));
1046             return tvb_reported_length(tvb);
1047         }
1048 
1049         proto_tree_add_item(field_tree, hf_alljoyn_uint32, tvb, offset, 4, encoding);
1050         offset += 4;
1051 
1052         proto_tree_add_item(field_tree, hf_alljoyn_string_data, tvb, offset, length, ENC_ASCII|ENC_NA);
1053         offset += length;
1054         break;
1055 
1056     case ARG_UINT16:     /* AllJoyn 16-bit unsigned integer basic type */
1057         header_type_name = "uint16";
1058         padding_start = offset;
1059         offset = round_to_2byte(offset, field_starting_offset);
1060         add_padding_item(padding_start, offset, tvb, field_tree);
1061 
1062         proto_tree_add_item(field_tree, hf_alljoyn_uint16, tvb, offset, 2, encoding);
1063         offset += 2;
1064         break;
1065 
1066     case ARG_STRING:     /* AllJoyn UTF-8 NULL terminated string basic type */
1067         {
1068         const guint8 *member_name;
1069 
1070         header_type_name = "string";
1071         padding_start = offset;
1072         offset = round_to_4byte(offset, field_starting_offset);
1073         add_padding_item(padding_start, offset, tvb, field_tree);
1074 
1075         proto_tree_add_item(field_tree, hf_alljoyn_string_size_32bit, tvb, offset, 4, encoding);
1076 
1077         /* Get the length so we can display the string. */
1078         length = (gint)get_uint32(tvb, offset, encoding);
1079 
1080         if(length < 0 || length > tvb_reported_length_remaining(tvb, offset)) {
1081             col_add_fstr(pinfo->cinfo, COL_INFO, "BAD DATA: String length is %d. Remaining packet length is %d.",
1082                 length, (gint)tvb_reported_length_remaining(tvb, offset));
1083             return tvb_reported_length(tvb);
1084         }
1085 
1086         length += 1;    /* Include the '\0'. */
1087         offset += 4;
1088 
1089         proto_tree_add_item_ret_string(field_tree, hf_alljoyn_string_data, tvb, offset, length, ENC_UTF_8|ENC_NA, pinfo->pool, &member_name);
1090 
1091         if(HDR_MEMBER == field_code) {
1092             col_append_fstr(pinfo->cinfo, COL_INFO, " %s", member_name);
1093         }
1094 
1095         offset += length;
1096         }
1097         break;
1098 
1099     case ARG_UINT64:     /* AllJoyn 64-bit unsigned integer basic type */
1100         header_type_name = "uint64";
1101         padding_start = offset;
1102         offset = round_to_8byte(offset, field_starting_offset);
1103         add_padding_item(padding_start, offset, tvb, field_tree);
1104 
1105         proto_tree_add_item(field_tree, hf_alljoyn_uint64, tvb, offset, 8, encoding);
1106         offset += 8;
1107         break;
1108 
1109     case ARG_UINT32:     /* AllJoyn 32-bit unsigned integer basic type */
1110         header_type_name = "uint32";
1111         padding_start = offset;
1112         offset = round_to_4byte(offset, field_starting_offset);
1113         add_padding_item(padding_start, offset, tvb, field_tree);
1114 
1115         if(is_reply_to) {
1116             static const gchar format[] = " Replies to: %09u";
1117             guint32 replies_to;
1118 
1119             replies_to = get_uint32(tvb, offset, encoding);
1120             col_append_fstr(pinfo->cinfo, COL_INFO, format, replies_to);
1121 
1122             if(header_item) {
1123                 proto_item *item;
1124 
1125                 item = proto_tree_add_item(field_tree, hf_alljoyn_uint32, tvb, offset, 4, encoding);
1126                 proto_item_set_text(item, format + 1, replies_to);
1127             }
1128         } else {
1129             proto_tree_add_item(field_tree, hf_alljoyn_uint32, tvb, offset, 4, encoding);
1130         }
1131 
1132         offset += 4;
1133         break;
1134 
1135     case ARG_VARIANT:    /* AllJoyn variant container type */
1136         {
1137             proto_item   *item;
1138             proto_tree   *tree;
1139             const guint8 *sig_saved;
1140             const guint8 *sig_pointer;
1141             guint8        variant_sig_length;
1142 
1143             header_type_name = "variant";
1144 
1145             variant_sig_length = tvb_get_guint8(tvb, offset);
1146             length = variant_sig_length;
1147 
1148             if(length > tvb_reported_length_remaining(tvb, offset)) {
1149                 gint bytes_left = tvb_reported_length_remaining(tvb, offset);
1150 
1151                 col_add_fstr(pinfo->cinfo, COL_INFO, "BAD DATA: Variant signature length is %d. Only %d bytes left in packet.",
1152                              length, bytes_left);
1153                 offset = tvb_reported_length(tvb);
1154             }
1155 
1156             length += 1;    /* Include the terminating '\0'. */
1157 
1158             /* This length (4) will be updated later with the length of the entire variant object. */
1159             item = proto_tree_add_item(field_tree, hf_alljoyn_mess_body_variant, tvb, offset, 4, encoding);
1160             tree = proto_item_add_subtree(item, ett_alljoyn_mess_body_parameters);
1161 
1162             proto_tree_add_item(tree, hf_alljoyn_mess_body_signature_length, tvb, offset, 1, encoding);
1163 
1164             offset += 1;
1165 
1166             tree = proto_item_add_subtree(item, ett_alljoyn_mess_body_parameters);
1167             proto_tree_add_item_ret_string(tree, hf_alljoyn_mess_body_signature, tvb, offset, length, ENC_ASCII|ENC_NA, pinfo->pool, &sig_saved);
1168 
1169             offset += length;
1170             sig_pointer = sig_saved;
1171 
1172             /* The signature of the variant has now been taken care of.  So now take care of the variant data. */
1173             while(((sig_pointer - sig_saved) < (length - 1)) && (tvb_reported_length_remaining(tvb, offset) > 0)) {
1174                 proto_item_append_text(item, "%c", *sig_pointer);
1175 
1176                 offset = parse_arg(tvb, pinfo, header_item, encoding, offset, tree, is_reply_to,
1177                                    *sig_pointer, field_code, &sig_pointer, &variant_sig_length, field_starting_offset);
1178             }
1179 
1180             proto_item_append_text(item, "'");
1181             proto_item_set_end(item, tvb, offset);
1182         }
1183         break;
1184 
1185     case ARG_INT64:      /* AllJoyn 64-bit signed integer basic type */
1186         header_type_name = "int64";
1187         padding_start = offset;
1188         offset = round_to_8byte(offset, field_starting_offset);
1189         add_padding_item(padding_start, offset, tvb, field_tree);
1190 
1191         proto_tree_add_item(field_tree, hf_alljoyn_int64, tvb, offset, 8, encoding);
1192         offset += 8;
1193         break;
1194 
1195     case ARG_BYTE:       /* AllJoyn 8-bit unsigned integer basic type */
1196         header_type_name = "byte";
1197 
1198         proto_tree_add_item(field_tree, hf_alljoyn_uint8, tvb, offset, 1, encoding);
1199         offset += 1;
1200         break;
1201 
1202     case ARG_DICT_ENTRY: /* AllJoyn dictionary or map container type - an array of key-value pairs */
1203     case ARG_STRUCT:     /* AllJoyn struct container type */
1204         {
1205             proto_item *item;
1206             proto_tree *tree;
1207             int         hf;
1208             guint8      type_stop;
1209 
1210             if(type_id == ARG_STRUCT) {
1211                 header_type_name = "structure";
1212                 hf = hf_alljoyn_mess_body_structure;
1213                 type_stop = ')';
1214             } else {
1215                 header_type_name = "dictionary";
1216                 hf = hf_alljoyn_mess_body_dictionary_entry;
1217                 type_stop = '}';
1218             }
1219 
1220             if(*signature == NULL || *signature_length < 1) {
1221                 col_add_fstr(pinfo->cinfo, COL_INFO, "BAD DATA: A %s argument needs a signature.", header_type_name);
1222                 return tvb_reported_length(tvb);
1223             }
1224 
1225             /* This length (4) will be updated later with the length of the entire struct. */
1226             item = proto_tree_add_item(field_tree, hf, tvb, offset, 4, encoding);
1227             append_struct_signature(item, *signature, *signature_length, type_stop);
1228             tree = proto_item_add_subtree(item, ett_alljoyn_mess_body_parameters);
1229 
1230             padding_start = offset;
1231             offset = pad_according_to_type(offset, field_starting_offset, tvb_reported_length(tvb), type_id);
1232             add_padding_item(padding_start, offset, tvb, tree);
1233 
1234             (*signature)++; /* Advance past the '(' or '{'. */
1235             (*signature_length)--;
1236 
1237             /* *signature should never be NULL but just make sure to avoid potential issues. */
1238             while(*signature && **signature && **signature != type_stop
1239                     && tvb_reported_length_remaining(tvb, offset) > 0) {
1240                 offset = parse_arg(tvb,
1241                                    pinfo,
1242                                    header_item,
1243                                    encoding,
1244                                    offset,
1245                                    tree,
1246                                    is_reply_to,
1247                                    **signature,
1248                                    field_code,
1249                                    signature,
1250                                    signature_length,
1251                                    field_starting_offset);
1252             }
1253 
1254             proto_item_set_end(item, tvb, offset);
1255         }
1256         break;
1257 
1258     default:
1259         header_type_name = "unexpected";
1260         /* Just say we are done with this packet. */
1261         offset = tvb_reported_length(tvb);
1262         break;
1263     }
1264 
1265     if (*signature && *signature_length > 0 && ARG_ARRAY != type_id && HDR_INVALID == field_code) {
1266         (*signature)++;
1267         (*signature_length)--;
1268     }
1269 
1270     if(NULL != header_item && NULL != header_type_name) {
1271         /* Using "%s" and the argument "header_type_name" because some compilers don't like
1272            "header_type_name" by itself. */
1273         proto_item_append_text(header_item, "%s", header_type_name);
1274     }
1275 
1276     /* Make sure we never return something longer than the buffer for an offset. */
1277     if(offset > (gint)tvb_reported_length(tvb)) {
1278         offset = (gint)tvb_reported_length(tvb);
1279     } else if (offset == saved_offset) {
1280         /* The argument has a null size. Let's report the packet length to avoid an infinite loop. */
1281         /*expert_add_info(pinfo, header_item, &ei_alljoyn_empty_arg);*/
1282         proto_tree_add_expert(field_tree, pinfo, &ei_alljoyn_empty_arg, tvb, offset, 0);
1283         offset = (gint)tvb_reported_length(tvb);
1284     }
1285 
1286     return offset;
1287 }
1288 
1289 static void
1290 alljoyn_typeid( gchar *result, guint32 type )
1291 {
1292    g_snprintf( result, ITEM_LABEL_LENGTH, "'%c' => ", type);
1293 }
1294 
1295 /* This is called by handle_message_header_fields() to handle a single
1296  * message header field.
1297  * @param tvb is the incoming network data buffer.
1298  * @param pinfo contains information about the incoming packet which
1299  *         we update as we dissect the packet.
1300  * @param header_item is the subtree that we connect data items to.
1301  * @param encoding indicates big (ENC_BIG_ENDIAN) or little (ENC_LITTLE_ENDIAN)
1302  * @param offset is the offset into tvb to get the field from.
1303  *         endianness.
1304  * @param signature pointer to the signature of the parameters. This is a return
1305  *         value for the caller to pass to the function that parses the parameters.
1306  * @param signature_length pointer to the length of the signature. This is a return
1307  *         value for the caller to pass to the function that parses the parameters.
1308  * @return The new offset into the buffer after removing the field code and value.
1309  *         the message.
1310  */
1311 static gint
1312 handle_message_field(tvbuff_t      *tvb,
1313                      packet_info   *pinfo,
1314                      proto_item    *header_tree,
1315                      guint          encoding,
1316                      gint           offset,
1317                      const guint8 **signature,
1318                      guint8        *signature_length)
1319 {
1320     proto_tree *field_tree;
1321     proto_item *item, *field_item;
1322     guint8      field_code;
1323     guint8      type_id;
1324     gboolean    is_reply_to = FALSE;
1325     gint        starting_offset = offset;
1326     gint        padding_start;
1327 
1328     field_code = tvb_get_guint8(tvb, offset);
1329 
1330     if(HDR_REPLY_SERIAL == field_code) {
1331         is_reply_to = TRUE;
1332     }
1333 
1334     field_item = proto_tree_add_item(header_tree, hf_alljoyn_mess_header_field, tvb, offset, 1, ENC_NA);
1335     field_tree = proto_item_add_subtree(field_item, ett_alljoyn_mess_header_field);
1336 
1337     proto_tree_add_item(field_tree, hf_alljoyn_mess_body_header_fieldcode, tvb, offset, 1, ENC_NA);
1338     offset += 1;
1339 
1340     /* We expect a byte of 0x01 here. */
1341     handle_message_header_expected_byte(tvb, offset, field_tree, 0x01);
1342     offset += 1;
1343 
1344     item = proto_tree_add_item(field_tree, hf_alljoyn_mess_body_header_typeid, tvb, offset, 1, ENC_NA);
1345     type_id = tvb_get_guint8(tvb, offset);
1346     offset += 1;
1347 
1348     /* We expect a byte of 0x00 here. */
1349     handle_message_header_expected_byte(tvb, offset, field_tree, 0x00);
1350     offset += 1;
1351 
1352     offset = parse_arg(tvb,
1353                        pinfo,
1354                        item,
1355                        encoding,
1356                        offset,
1357                        field_tree,
1358                        is_reply_to,
1359                        type_id,
1360                        field_code,
1361                        signature,
1362                        signature_length,
1363                        starting_offset);
1364 
1365     padding_start = offset;
1366     offset = round_to_8byte(offset, starting_offset);
1367     add_padding_item(padding_start, offset, tvb, field_tree);
1368 
1369     if(offset < 0 || offset > (gint)tvb_reported_length(tvb)) {
1370         offset = (gint)tvb_reported_length(tvb);
1371     }
1372 
1373     proto_item_set_end(field_tree, tvb, offset);
1374 
1375     return offset;
1376 }
1377 
1378 /* This is called by handle_message() to handle the message body.
1379  * @param tvb is the incoming network data buffer.
1380  * @param pinfo contains information about the incoming packet which
1381  *         we update as we dissect the packet.
1382  * @param header_tree is the subtree that we connect data items to.
1383  * @param encoding indicates big (ENC_BIG_ENDIAN) or little (ENC_LITTLE_ENDIAN)
1384  * @param offset contains the offset into tvb for the start of the header fields.
1385  * @param header_length contains the length of the message fields.
1386  * @param signature_length contains the signature field length.
1387  */
1388 static const guint8 *
1389 handle_message_header_fields(tvbuff_t    *tvb,
1390                              packet_info *pinfo,
1391                              proto_item  *header_tree,
1392                              guint       encoding,
1393                              gint        offset,
1394                              guint32     header_length,
1395                              guint8      *signature_length)
1396 {
1397     gint        end_of_header;
1398     proto_item *item;
1399     proto_tree *tree;
1400     const guint8 *signature = NULL;
1401 
1402     item = proto_tree_add_item(header_tree, hf_alljoyn_mess_header_fields, tvb, offset, header_length, ENC_NA);
1403     tree = proto_item_add_subtree(item, ett_alljoyn_mess_header);
1404 
1405     end_of_header = offset + header_length;
1406 
1407     while(offset < end_of_header) {
1408         offset = handle_message_field(tvb, pinfo, tree, encoding, offset, &signature, signature_length);
1409     }
1410 
1411     return signature;
1412 }
1413 
1414 /* This is called by handle_message() to handle the message body.
1415  * @param tvb is the incoming network data buffer.
1416  * @param header_tree is the subtree that we connect data items to.
1417  * @param encoding indicates big (ENC_BIG_ENDIAN) or little (ENC_LITTLE_ENDIAN)
1418  * @param offset contains the offset into tvb for the start of the parameters.
1419  * @param body_length contains the length of the body parameters.
1420  * @param signature the signature of the parameters.
1421  * @param signature_length contains the signature field length.
1422  */
1423 static gint
1424 handle_message_body_parameters(tvbuff_t     *tvb,
1425                                packet_info  *pinfo,
1426                                proto_tree   *header_tree,
1427                                guint         encoding,
1428                                gint          offset,
1429                                gint32        body_length,
1430                                const guint8 *signature,
1431                                guint8        signature_length)
1432 {
1433     gint        packet_length, end_of_body;
1434     proto_tree *tree;
1435     proto_item *item;
1436     const gint  starting_offset = offset;
1437 
1438     packet_length = tvb_reported_length(tvb);
1439 
1440     /* Add a subtree/row for the message body parameters. */
1441     item = proto_tree_add_item(header_tree, hf_alljoyn_mess_body_parameters, tvb, offset, body_length, ENC_NA);
1442     tree = proto_item_add_subtree(item, ett_alljoyn_mess_body_parameters);
1443 
1444     end_of_body = offset + body_length;
1445 
1446     if(end_of_body > packet_length) {
1447         end_of_body = packet_length;
1448     }
1449 
1450     while(offset < end_of_body && signature_length > 0 && signature && *signature) {
1451         offset = parse_arg(tvb,
1452                            pinfo,
1453                            NULL,
1454                            encoding,
1455                            offset,
1456                            tree,    /* Add the args to the Parameters tree. */
1457                            FALSE,
1458                            *signature,
1459                            HDR_INVALID,
1460                            &signature,
1461                            &signature_length,
1462                            starting_offset);
1463     }
1464 
1465     return offset;
1466 }
1467 
1468 #define MESSAGE_HEADER_LENGTH   16
1469 #define TYPE_OFFSET              1
1470 #define FLAGS_OFFSET             2
1471 #define MAJORVERSION_OFFSET      3
1472 #define BODY_LENGTH_OFFSET       4
1473 #define SERIAL_OFFSET            8
1474 #define HEADER_LENGTH_OFFSET    12
1475 
1476 /* This is called by dissect_AllJoyn_message() to handle the actual message.
1477  * If it was a message with valid header and optional body then return TRUE.
1478  * If not a valid message return false.
1479  * @param tvb is the incoming network data buffer.
1480  * @param pinfo contains information about the incoming packet.
1481  * @param offset is the offset into the packet to start processing.
1482  * @param message_tree is the subtree that any connect data items should be added to.
1483  * @param is_ardp is true if this is an ARDP packet.
1484  * @returns the offset into the packet that has successfully been handled or
1485  *         the input offset value if it was not a message header body.
1486  */
1487 static gint
1488 handle_message_header_body(tvbuff_t    *tvb,
1489                            packet_info *pinfo,
1490                            gint         offset,
1491                            proto_item  *message_tree,
1492                            gboolean    is_ardp)
1493 {
1494     gint          remaining_packet_length;
1495     const guint8 *signature;
1496     guint8        signature_length = 0;
1497     proto_tree   *header_tree, *flag_tree;
1498     proto_item   *header_item, *flag_item;
1499     guint         encoding;
1500     gint          packet_length_needed;
1501     gint          header_length = 0, body_length = 0;
1502 
1503     remaining_packet_length = tvb_reported_length_remaining(tvb, offset);
1504     encoding = get_message_header_endianness(tvb, offset);
1505 
1506     if(ENC_ALLJOYN_BAD_ENCODING == encoding) {
1507         col_add_fstr(pinfo->cinfo, COL_INFO, "BAD DATA: Endian encoding '0x%0x'. Expected 'l' or 'B'",
1508             tvb_get_guint8(tvb, offset + ENDIANNESS_OFFSET));
1509 
1510         /* We are done with everything in this packet don't try anymore. */
1511         return offset + remaining_packet_length;
1512     }
1513 
1514     if(remaining_packet_length < MESSAGE_HEADER_LENGTH) {
1515         if(!set_pinfo_desegment(pinfo, offset, MESSAGE_HEADER_LENGTH - remaining_packet_length)) {
1516             col_add_fstr(pinfo->cinfo, COL_INFO, "BAD DATA: Remaining packet length is %d. Expected >= %d && <= %d",
1517             remaining_packet_length, MESSAGE_HEADER_LENGTH, MAX_PACKET_LEN);
1518         }
1519 
1520         return offset + remaining_packet_length;
1521     }
1522 
1523     header_length = get_uint32(tvb, offset + HEADER_LENGTH_OFFSET, encoding);
1524     body_length = get_uint32(tvb, offset + BODY_LENGTH_OFFSET, encoding);
1525     packet_length_needed = ROUND_TO_8BYTE(header_length) + body_length + MESSAGE_HEADER_LENGTH;
1526 
1527     /* ARDP (UDP) packets can't be desegmented by Wireshark and it is normal to see them in
1528      * fragments. Don't scare the user when they occur. Dissect as much as we easily can.
1529      * It should be possible to desegment TCIP packets. If not then something is wrong so tell
1530      * the user.
1531      */
1532     if(packet_length_needed > remaining_packet_length) {
1533         if(!set_pinfo_desegment(pinfo, offset, packet_length_needed - remaining_packet_length)) {
1534             if(!is_ardp) {
1535                 col_add_fstr(pinfo->cinfo, COL_INFO, "BAD DATA: Remaining packet length is %d. Expected %d",
1536                     remaining_packet_length, packet_length_needed);
1537 
1538                 return offset + remaining_packet_length;
1539             }
1540 
1541             /* In this case we can't desegment but it is an ARDP message so we want to dissect
1542              * at least the header. Therefore we fall through to the header parsing code if the packet size
1543              * is greater than or equal to the header size. Otherwise we return and report what we know.
1544              */
1545             if (remaining_packet_length < header_length) {
1546                 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented ARDP message: Remaining packet length is %d. Expected %d",
1547                     remaining_packet_length, packet_length_needed);
1548                 return offset + remaining_packet_length;
1549             }
1550         }
1551         else {
1552             /* In this case we can desegment */
1553             return offset + remaining_packet_length;
1554         }
1555     }
1556 
1557     /* Add a subtree/row for the header. */
1558     header_item = proto_tree_add_item(message_tree, hf_alljoyn_mess_header, tvb, offset, MESSAGE_HEADER_LENGTH, ENC_NA);
1559     header_tree = proto_item_add_subtree(header_item, ett_alljoyn_header);
1560 
1561     proto_tree_add_item(header_tree, hf_alljoyn_mess_header_endian, tvb, offset + ENDIANNESS_OFFSET, 1, ENC_ASCII|ENC_NA);
1562     proto_tree_add_item(header_tree, hf_alljoyn_mess_header_type, tvb, offset + TYPE_OFFSET, 1, ENC_NA);
1563 
1564     /* The flags byte. */
1565     flag_item = proto_tree_add_item(header_tree, hf_alljoyn_mess_header_flags,    tvb, offset + FLAGS_OFFSET, 1, ENC_NA);
1566     flag_tree = proto_item_add_subtree(flag_item, ett_alljoyn_header_flags);
1567 
1568     /* Now the individual bits. */
1569     proto_tree_add_item(flag_tree, hf_alljoyn_mess_header_flags_encrypted,        tvb, offset + FLAGS_OFFSET, 1, ENC_NA);
1570     proto_tree_add_item(flag_tree, hf_alljoyn_mess_header_flags_compressed,       tvb, offset + FLAGS_OFFSET, 1, ENC_NA);
1571     proto_tree_add_item(flag_tree, hf_alljoyn_mess_header_flags_global_broadcast, tvb, offset + FLAGS_OFFSET, 1, ENC_NA);
1572     proto_tree_add_item(flag_tree, hf_alljoyn_mess_header_flags_sessionless,      tvb, offset + FLAGS_OFFSET, 1, ENC_NA);
1573     proto_tree_add_item(flag_tree, hf_alljoyn_mess_header_flags_allow_remote_msg, tvb, offset + FLAGS_OFFSET, 1, ENC_NA);
1574     proto_tree_add_item(flag_tree, hf_alljoyn_mess_header_flags_no_auto_start,    tvb, offset + FLAGS_OFFSET, 1, ENC_NA);
1575     proto_tree_add_item(flag_tree, hf_alljoyn_mess_header_flags_no_reply,         tvb, offset + FLAGS_OFFSET, 1, ENC_NA);
1576 
1577     proto_tree_add_item(header_tree, hf_alljoyn_mess_header_majorversion,         tvb, offset + MAJORVERSION_OFFSET, 1, ENC_NA);
1578     proto_tree_add_item(header_tree, hf_alljoyn_mess_header_body_length,          tvb, offset + BODY_LENGTH_OFFSET, 4, encoding);
1579 
1580     proto_tree_add_item(header_tree, hf_alljoyn_mess_header_serial,               tvb, offset + SERIAL_OFFSET, 4, encoding);
1581     col_add_fstr(pinfo->cinfo, COL_INFO, "Message %010u: '%s'", get_uint32(tvb, offset + SERIAL_OFFSET, encoding),
1582             val_to_str_const(tvb_get_guint8(tvb, offset + TYPE_OFFSET), message_header_encoding_vals, "Unexpected message type"));
1583 
1584     proto_tree_add_item(header_tree, hf_alljoyn_mess_header_header_length, tvb, offset + HEADER_LENGTH_OFFSET, 4, encoding);
1585     offset += MESSAGE_HEADER_LENGTH;
1586     packet_length_needed -= MESSAGE_HEADER_LENGTH;
1587 
1588     signature = handle_message_header_fields(tvb, pinfo, message_tree, encoding,
1589                                              offset, header_length, &signature_length);
1590     /* No need to call add_padding_item() after the following operation. It's not needed
1591      * because all message header fields widths are multiples of 8 and are padded as necessary.
1592      * Because the padding is taken care of in the individual message header field there is no
1593      * need for it here. The rounding here just gets the offset to the end of the last header
1594      * field and its (possible) padding.
1595      */
1596     offset += ROUND_TO_8BYTE(header_length);
1597     packet_length_needed -= ROUND_TO_8BYTE(header_length);
1598     remaining_packet_length = tvb_reported_length_remaining(tvb, offset);
1599 
1600     if (packet_length_needed > remaining_packet_length) {
1601         col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Fragmented ARDP message or bad data: Remaining packet length is %d. Expected %d",
1602             remaining_packet_length, packet_length_needed);
1603         return offset + remaining_packet_length;
1604     }
1605 
1606     if(body_length > 0 && signature != NULL && signature_length > 0) {
1607         offset = handle_message_body_parameters(tvb,
1608                                                 pinfo,
1609                                                 message_tree,
1610                                                 encoding,
1611                                                 offset,
1612                                                 body_length,
1613                                                 signature,
1614                                                 signature_length);
1615     }
1616 
1617     return offset;
1618 }
1619 
1620 /* Test to see if this buffer contains something that might be an AllJoyn message.
1621  * @param tvb is the incoming network data buffer.
1622  * @param offset where to start parsing the buffer.
1623  * @param is_ardp If true then this is an ARDP packet which needs special treatment.
1624  * @returns TRUE if probably an AllJoyn message.
1625  *          FALSE if probably not an AllJoyn message.
1626  */
1627 static gboolean
1628 protocol_is_alljoyn_message(tvbuff_t *tvb, gint offset, gboolean is_ardp)
1629 {
1630     gint length = tvb_captured_length(tvb);
1631 
1632     if(length < offset + 1)
1633         return FALSE;
1634 
1635     /* There is no initial connect byte or SASL when using ARDP. */
1636     if(!is_ardp) {
1637         /* initial byte for a connect message. */
1638         if(tvb_get_guint8(tvb, offset) == 0)
1639             return TRUE;
1640 
1641         if(find_sasl_command(tvb, offset) != NULL)
1642             return TRUE;
1643     }
1644 
1645     if(get_message_header_endianness(tvb, offset) == ENC_ALLJOYN_BAD_ENCODING)
1646         return FALSE;
1647 
1648     if((length < offset + 2) || (try_val_to_str(tvb_get_guint8(tvb, offset + 1), message_header_encoding_vals) == NULL))
1649         return FALSE;
1650 
1651     return TRUE;
1652 }
1653 
1654 /* This is called by Wireshark for packet types that are registered
1655  * in the proto_reg_handoff_AllJoyn() function. This function handles
1656  * the packets for the traffic on port 9955.
1657  * @param tvb is the incoming network data buffer.
1658  * @param pinfo contains information about the incoming packet which
1659  *         we update as we dissect the packet.
1660  * @param tree is the tree data items should be added to.
1661  * @param offset is the offset into the already partial dissected buffer
1662  *         from dissect_AllJoyn_ardp() or 0 because this is just a bare
1663  *         AllJoyn message.
1664  * @return 0 if not AllJoyn message protocol, or
1665  *         the offset into the buffer we have successfully dissected (which
1666  *         should normally be the packet length), or
1667  *         the offset into the buffer we have dissected with
1668  *         pinfo->desegment_len == additional bytes needed from the next packet
1669  *         before we can dissect, or
1670  *         0 with pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT if another
1671  *         segment is needed, or
1672  *         packet_length if "really bad" parameters come in.
1673  */
1674 static gint
1675 dissect_AllJoyn_message(tvbuff_t    *tvb,
1676                         packet_info *pinfo,
1677                         proto_tree  *tree,
1678                         gint        offset)
1679 {
1680     proto_item *message_item;
1681     proto_tree *message_tree;
1682     gint        last_offset = -1;
1683     gint        packet_length;
1684     gboolean    is_ardp = FALSE;
1685 
1686     /* If called after dissecting the ARDP protocol. This is the only time the offset will not be zero. */
1687     if(offset != 0) {
1688         is_ardp = TRUE;
1689     }
1690 
1691     pinfo->desegment_len = 0;
1692     packet_length = tvb_reported_length(tvb);
1693 
1694     col_clear(pinfo->cinfo, COL_INFO);
1695     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ALLJOYN");
1696 
1697     /* Add a subtree covering the remainder of the packet */
1698     message_item = proto_tree_add_item(tree, proto_AllJoyn_mess, tvb, offset, -1, ENC_NA);
1699     message_tree = proto_item_add_subtree(message_item, ett_alljoyn_mess);
1700 
1701     /* Continue as long as we are making progress and we haven't finished with the packet. */
1702     while(offset < packet_length && offset > last_offset) {
1703         last_offset = offset;
1704 
1705         /* There is no initial connect byte or SASL when using ARDP. */
1706         if(!is_ardp) {
1707             offset = handle_message_connect(tvb, pinfo, offset, message_tree);
1708 
1709             if(offset >= packet_length) {
1710                 break;
1711             }
1712 
1713             offset = handle_message_sasl(tvb, pinfo, offset, message_tree);
1714 
1715             if(offset >= packet_length) {
1716                 break;
1717             }
1718         }
1719 
1720         offset = handle_message_header_body(tvb, pinfo, offset, message_tree, is_ardp);
1721     }
1722 
1723     return offset;
1724 }
1725 
1726 static void
1727 ns_parse_questions(tvbuff_t *tvb, gint* offset, proto_tree* alljoyn_tree, guint8 questions, guint message_version)
1728 {
1729     while(questions--) {
1730         proto_item *alljoyn_questions_ti;
1731         proto_tree *alljoyn_questions_tree;
1732         gint        count;
1733 
1734         alljoyn_questions_ti = proto_tree_add_item(alljoyn_tree, hf_alljoyn_ns_whohas, tvb, *offset, 2, ENC_NA); /* "Who-Has Message" */
1735         alljoyn_questions_tree = proto_item_add_subtree(alljoyn_questions_ti, ett_alljoyn_whohas);
1736 
1737         if(0 == message_version) {
1738             proto_tree_add_item(alljoyn_questions_tree, hf_alljoyn_ns_whohas_t_flag, tvb, *offset, 1, ENC_NA);
1739             proto_tree_add_item(alljoyn_questions_tree, hf_alljoyn_ns_whohas_u_flag, tvb, *offset, 1, ENC_NA);
1740             proto_tree_add_item(alljoyn_questions_tree, hf_alljoyn_ns_whohas_s_flag, tvb, *offset, 1, ENC_NA);
1741             proto_tree_add_item(alljoyn_questions_tree, hf_alljoyn_ns_whohas_f_flag, tvb, *offset, 1, ENC_NA);
1742         }
1743 
1744         (*offset) += 1;
1745 
1746         proto_tree_add_item(alljoyn_questions_tree, hf_alljoyn_ns_whohas_count, tvb, *offset, 1, ENC_NA);
1747         count = tvb_get_guint8(tvb, *offset);
1748         (*offset) += 1;
1749 
1750         while(count--) {
1751             proto_item *alljoyn_bus_name_ti;
1752             proto_tree *alljoyn_bus_name_tree;
1753             gint        bus_name_size = 0;
1754 
1755             bus_name_size = tvb_get_guint8(tvb, *offset);
1756 
1757             alljoyn_bus_name_ti = proto_tree_add_item(alljoyn_questions_tree, hf_alljoyn_string, tvb,
1758                 *offset, 1 + bus_name_size, ENC_NA);
1759             alljoyn_bus_name_tree = proto_item_add_subtree(alljoyn_bus_name_ti, ett_alljoyn_ns_string);
1760 
1761             proto_tree_add_item(alljoyn_bus_name_tree, hf_alljoyn_string_size_8bit, tvb, *offset, 1, ENC_NA);
1762             (*offset) += 1;
1763 
1764             proto_tree_add_item(alljoyn_bus_name_tree, hf_alljoyn_string_data, tvb, *offset, bus_name_size, ENC_ASCII|ENC_NA);
1765             (*offset) += bus_name_size;
1766         }
1767 
1768     }
1769 }
1770 
1771 /* The version 0 protocol looks like this:
1772  * Byte 0:
1773  *      Bit 0 (ISAT_F): If '1' indicates the daemon is listening on an IPv4
1774  *      address and that an IPv4 address is present in the message.  If '0'
1775  *      there is no IPv4 address present.
1776  *
1777  *      Bit 1 (ISAT_S): If '1' the responding daemon is listening on an IPv6
1778  *      address and that an IPv6 address is present in the message.  If '0'
1779  *      there is no IPv6 address present.
1780  *
1781  *      Bit 2 (ISAT_U): If '1' the daemon is listening on UDP.
1782  *
1783  *      Bit 3 (ISAT_T): If '1' the daemon is listening on TCP.
1784  *
1785  *      Bit 4 (ISAT_C): If '1' the list of StringData records is a complete
1786  *      list of all well-known names exported by the daemon.
1787  *
1788  *      Bit 5 (ISAT_G): If '1' a variable length daemon GUID string is present.
1789  *
1790  *      Bits 6-7: The message type of the IS-AT message.  Defined to be '01' (1).
1791  *
1792  * Byte 1 (Count): The number of StringData items.  Each StringData item
1793  * describes one well-known bus name supported by the daemon.
1794  *
1795  * Bytes 2-3 (Port): The port on which the daemon is listening.
1796  *
1797  * If the ISAT_F bit is set then the next four bytes is the IPv4 address on
1798  * which the daemon is listening.
1799  *
1800  * If the ISAT_S bit is set then the next 16 bytes is the IPv6 address on
1801  * which the daemon is listening.
1802  *
1803  * If the ISAT_G bit is set then the next data is daemon GUID StringData.
1804  *
1805  * The next data is a variable number of StringData records.
1806  */
1807 static void
1808 ns_parse_answers_v0(tvbuff_t *tvb, gint* offset, proto_tree* alljoyn_tree, guint8 answers)
1809 {
1810     while(answers--) {
1811         proto_item *alljoyn_answers_ti;
1812         proto_tree *alljoyn_answers_tree;
1813         gint        flags;
1814         gint        count;
1815 
1816         alljoyn_answers_ti = proto_tree_add_item(alljoyn_tree, hf_alljoyn_answer, tvb, *offset, 2, ENC_NA);
1817         alljoyn_answers_tree = proto_item_add_subtree(alljoyn_answers_ti, ett_alljoyn_ns_answers);
1818 
1819         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_g_flag, tvb, *offset, 1, ENC_NA);
1820         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_c_flag, tvb, *offset, 1, ENC_NA);
1821         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_t_flag, tvb, *offset, 1, ENC_NA);
1822         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_u_flag, tvb, *offset, 1, ENC_NA);
1823         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_s_flag, tvb, *offset, 1, ENC_NA);
1824         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_f_flag, tvb, *offset, 1, ENC_NA);
1825         flags = tvb_get_guint8(tvb, *offset);
1826         (*offset) += 1;
1827 
1828         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_count,  tvb, *offset, 1, ENC_NA);
1829         count = tvb_get_guint8(tvb, *offset);
1830         (*offset) += 1;
1831 
1832         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_port,   tvb, *offset, 2, ENC_BIG_ENDIAN);
1833         (*offset) += 2;
1834 
1835         if(flags & ISAT_S) {
1836             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_ipv6, tvb, *offset, 16, ENC_NA);
1837             (*offset) += 16;
1838         }
1839 
1840         if(flags & ISAT_F) {
1841             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_ipv4, tvb, *offset, 4, ENC_BIG_ENDIAN);
1842             (*offset) += 4;
1843         }
1844 
1845         if(flags & ISAT_G) {
1846             proto_item *alljoyn_string_ti;
1847             proto_tree *alljoyn_string_tree;
1848             gint        guid_size = 0;
1849 
1850             guid_size = tvb_get_guint8(tvb, *offset);
1851 
1852             alljoyn_string_ti = proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_isat_guid_string, tvb,
1853                 *offset, 1 + guid_size, ENC_NA);
1854             alljoyn_string_tree = proto_item_add_subtree(alljoyn_string_ti, ett_alljoyn_ns_guid_string);
1855 
1856             proto_tree_add_item(alljoyn_string_tree, hf_alljoyn_string_size_8bit, tvb, *offset, 1, ENC_NA);
1857             (*offset) += 1;
1858 
1859             proto_tree_add_item(alljoyn_string_tree, hf_alljoyn_string_data, tvb, *offset, guid_size, ENC_ASCII|ENC_NA);
1860             (*offset) += guid_size;
1861         }
1862 
1863         while(count--) {
1864             proto_item *alljoyn_entry_ti;
1865             proto_tree *alljoyn_entry_tree;
1866             proto_item *alljoyn_bus_name_ti;
1867             proto_tree *alljoyn_bus_name_tree;
1868             gint        bus_name_size = tvb_get_guint8(tvb, *offset);
1869 
1870             alljoyn_entry_ti = proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_isat_entry, tvb,
1871                 *offset, 1 + bus_name_size, ENC_NA);
1872             alljoyn_entry_tree = proto_item_add_subtree(alljoyn_entry_ti, ett_alljoyn_ns_isat_entry);
1873 
1874             alljoyn_bus_name_ti = proto_tree_add_item(alljoyn_entry_tree, hf_alljoyn_string, tvb, *offset,
1875                 1 + bus_name_size, ENC_NA);
1876             alljoyn_bus_name_tree = proto_item_add_subtree(alljoyn_bus_name_ti, ett_alljoyn_string);
1877 
1878             proto_tree_add_item(alljoyn_bus_name_tree, hf_alljoyn_string_size_8bit, tvb, *offset, 1, ENC_NA);
1879             (*offset) += 1;
1880 
1881             proto_tree_add_item(alljoyn_bus_name_tree, hf_alljoyn_string_data, tvb, *offset, bus_name_size, ENC_ASCII|ENC_NA);
1882             (*offset) += bus_name_size;
1883         }
1884     }
1885 }
1886 
1887 /* The version 1 protocol looks like this:
1888  * Byte 0:
1889  *      Bit 0 (ISAT_U6): If '1' then the IPv6 endpoint of an unreliable method
1890  *      (UDP) transport (IP address and port) is present.
1891  *
1892  *      Bit 1 (ISAT_R6): If '1' the the IPv6 endpoint of a reliable method
1893  *      (TCP) transport (IP address and port) is present.
1894  *
1895  *      Bit 2 (ISAT_U4): If '1' then the IPv4 endpoint of an unreliable method
1896  *      (UDP) transport (IP address and port) is present.
1897  *
1898  *      Bit 3 (ISAT_R4): If '1' then the IPv4 endpoint of a reliable method
1899  *      (TCP) transport (IP address and port) is present.
1900  *
1901  *      Bit 4 (ISAT_C): If '1' the list of StringData records is a complete
1902  *      list of all well-known names exported by the daemon.
1903  *
1904  *      Bit 5 (ISAT_G): If '1' a variable length daemon GUID string is present.
1905  *
1906  *      Bits 6-7: The message type of the IS-AT message.  Defined to be '01' (1).
1907  *
1908  * Byte 1 (Count): The number of StringData items.  Each StringData item
1909  * describes one well-known bus name supported by the daemon.
1910  *
1911  * Bytes 2-3 (TransportMask): The bit mask of transport identifiers that
1912  * indicates which AllJoyn transport is making the advertisement.
1913  *
1914  * If the ISAT_R4 bit is set then the next four bytes is the IPv4 address on
1915  * which the daemon is listening.
1916  *
1917  * If the ISAT_R4 bit is set then the next two bytes is the IPv4 port on
1918  * which the daemon is listening.
1919  *
1920  * If the ISAT_R6 bit is set then the next 16 bytes is the IPv6 address on
1921  * which the daemon is listening for TCP traffic.
1922  *
1923  * If the ISAT_R6 bit is set then the next two bytes is the IPv6 port on
1924  * which the daemon is listening for TCP traffic.
1925  *
1926  * If the ISAT_U6 bit is set then the next 16 bytes is the IPv6 address on
1927  * which the daemon is listening for UDP traffic.
1928  *
1929  * If the ISAT_U6 bit is set then the next two bytes is the IPv6 port on
1930  * which the daemon is listening for UDP traffic.
1931  *
1932  * If the ISAT_G bit is set then the next data is daemon GUID StringData.
1933  *
1934  * The next data is a variable number of StringData records.
1935  */
1936 static void
1937 ns_parse_answers_v1(tvbuff_t *tvb, gint* offset, proto_tree* alljoyn_tree, guint8 answers)
1938 {
1939     while(answers--) {
1940         proto_item *alljoyn_answers_ti;
1941         proto_tree *alljoyn_answers_tree;
1942         gint        flags;
1943         gint        count;
1944 
1945         alljoyn_answers_ti = proto_tree_add_item(alljoyn_tree, hf_alljoyn_answer, tvb, *offset, 2, ENC_NA);
1946         alljoyn_answers_tree = proto_item_add_subtree(alljoyn_answers_ti, ett_alljoyn_ns_answers);
1947 
1948         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_g_flag,  tvb, *offset, 1, ENC_NA);
1949         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_c_flag,  tvb, *offset, 1, ENC_NA);
1950 
1951         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_r4_flag, tvb, *offset, 1, ENC_NA);
1952         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_u4_flag, tvb, *offset, 1, ENC_NA);
1953 
1954         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_r6_flag, tvb, *offset, 1, ENC_NA);
1955         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_u6_flag, tvb, *offset, 1, ENC_NA);
1956 
1957         flags = tvb_get_guint8(tvb, *offset);
1958         (*offset) += 1;
1959 
1960         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_count,   tvb, *offset, 1, ENC_NA);
1961         count = tvb_get_guint8(tvb, *offset);
1962         (*offset) += 1;
1963 
1964         /* The entire transport mask. */
1965         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_transport_mask, tvb, *offset, 2, ENC_BIG_ENDIAN);
1966 
1967         /* The individual bits of the transport mask. */
1968         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_transport_mask_wfd,       tvb, *offset, 2, ENC_NA);
1969         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_transport_mask_ice,       tvb, *offset, 2, ENC_NA);
1970         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_transport_mask_lan,       tvb, *offset, 2, ENC_NA);
1971         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_transport_mask_wwan,      tvb, *offset, 2, ENC_NA);
1972         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_transport_mask_tcp,       tvb, *offset, 2, ENC_NA);
1973         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_transport_mask_bluetooth, tvb, *offset, 2, ENC_NA);
1974         proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_transport_mask_local,     tvb, *offset, 2, ENC_NA);
1975 
1976         (*offset) += 2;
1977 
1978         if(flags & ISAT_R4) {
1979             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_ipv4, tvb, *offset, 4, ENC_BIG_ENDIAN);
1980             (*offset) += 4;
1981 
1982             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
1983             (*offset) += 2;
1984         }
1985 
1986         if(flags & ISAT_U4) {
1987             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_ipv4, tvb, *offset, 4, ENC_BIG_ENDIAN);
1988             (*offset) += 4;
1989 
1990             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
1991             (*offset) += 2;
1992         }
1993 
1994         if(flags & ISAT_R6) {
1995             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_ipv6, tvb, *offset, 16, ENC_NA);
1996             (*offset) += 16;
1997 
1998             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
1999             (*offset) += 2;
2000         }
2001 
2002         if(flags & ISAT_U6) {
2003             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_ipv6, tvb, *offset, 16, ENC_NA);
2004             (*offset) += 16;
2005 
2006             proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_ns_isat_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
2007             (*offset) += 2;
2008         }
2009 
2010         if(flags & ISAT_G) {
2011             proto_item *alljoyn_string_ti;
2012             proto_tree *alljoyn_string_tree;
2013             gint        guid_size;
2014 
2015             guid_size = tvb_get_guint8(tvb, *offset);
2016 
2017             alljoyn_string_ti = proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_isat_guid_string, tvb,
2018                 *offset, 1 + guid_size, ENC_NA);
2019             alljoyn_string_tree = proto_item_add_subtree(alljoyn_string_ti, ett_alljoyn_ns_guid_string);
2020 
2021             proto_tree_add_item(alljoyn_string_tree, hf_alljoyn_string_size_8bit, tvb, *offset, 1, ENC_NA);
2022             (*offset) += 1;
2023 
2024             proto_tree_add_item(alljoyn_string_tree, hf_alljoyn_string_data, tvb, *offset, guid_size, ENC_ASCII|ENC_NA);
2025             (*offset) += guid_size;
2026         }
2027 
2028         /* The string data records. */
2029         while(count--) {
2030             proto_item *alljoyn_entry_ti;
2031             proto_tree *alljoyn_entry_tree;
2032 
2033             proto_tree *alljoyn_bus_name_ti;
2034             proto_tree *alljoyn_bus_name_tree;
2035             gint        bus_name_size = tvb_get_guint8(tvb, *offset);
2036 
2037             alljoyn_entry_ti = proto_tree_add_item(alljoyn_answers_tree, hf_alljoyn_isat_entry, tvb,
2038                 *offset, 1 + bus_name_size, ENC_NA);
2039             alljoyn_entry_tree = proto_item_add_subtree(alljoyn_entry_ti, ett_alljoyn_isat_entry);
2040 
2041             alljoyn_bus_name_ti = proto_tree_add_item(alljoyn_entry_tree, hf_alljoyn_string, tvb, *offset,
2042                 1 + bus_name_size, ENC_NA);
2043             alljoyn_bus_name_tree = proto_item_add_subtree(alljoyn_bus_name_ti, ett_alljoyn_string);
2044 
2045             proto_tree_add_item(alljoyn_bus_name_tree, hf_alljoyn_string_size_8bit, tvb, *offset, 1, ENC_NA);
2046             (*offset) += 1;
2047 
2048             proto_tree_add_item(alljoyn_bus_name_tree, hf_alljoyn_string_data, tvb, *offset, bus_name_size, ENC_ASCII|ENC_NA);
2049             (*offset) += bus_name_size;
2050         }
2051     }
2052 }
2053 
2054 /* This is called by Wireshark for packet types that are registered
2055    in the proto_reg_handoff_AllJoyn() function. This function handles
2056    the packets for the name server traffic.
2057  * @param tvb is the incoming network data buffer.
2058  * @param pinfo contains information about the incoming packet which
2059  *         we update as we dissect the packet.
2060  * @param tree is the tree data items should be added to.
2061  */
2062 static int
2063 dissect_AllJoyn_name_server(tvbuff_t    *tvb,
2064                             packet_info *pinfo,
2065                             proto_tree  *tree,
2066                             void *data   _U_)
2067 {
2068     proto_item *alljoyn_item, *header_item;
2069     proto_tree *alljoyn_tree, *header_tree;
2070     guint8      questions, answers;
2071     guint8      version;
2072     int         offset = 0;
2073 
2074     /* This is name service traffic. Mark it as such at the top level. */
2075     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ALLJOYN-NS");
2076     col_clear(pinfo->cinfo, COL_INFO);
2077 
2078     /* Add a subtree covering the remainder of the packet */
2079     alljoyn_item = proto_tree_add_item(tree, proto_AllJoyn_ns, tvb, 0, -1, ENC_NA);
2080     alljoyn_tree = proto_item_add_subtree(alljoyn_item, ett_alljoyn_ns);
2081 
2082     /* Add the "header protocol" as a subtree from the AllJoyn Name Service Protocol. */
2083     header_item = proto_tree_add_item(alljoyn_tree, hf_alljoyn_ns_header, tvb, offset, 4, ENC_NA);
2084     header_tree = proto_item_add_subtree(header_item, ett_alljoyn_ns_header);
2085 
2086     /* The the sender and message versions as fields for the header protocol. */
2087     proto_tree_add_item(header_tree, hf_alljoyn_ns_sender_version, tvb, offset, 1, ENC_NA);
2088     proto_tree_add_item(header_tree, hf_alljoyn_ns_message_version, tvb, offset, 1, ENC_NA);
2089     version = tvb_get_guint8(tvb, offset) & 0xF;
2090     offset += 1;
2091 
2092     col_add_fstr(pinfo->cinfo, COL_INFO, "VERSION %u", version);
2093     if(version > 1)
2094         col_append_str(pinfo->cinfo, COL_INFO, " (UNSUPPORTED)");
2095 
2096     proto_tree_add_item(header_tree, hf_alljoyn_ns_questions, tvb, offset, 1, ENC_NA);
2097     questions = tvb_get_guint8(tvb, offset);
2098     offset += 1;
2099 
2100     proto_tree_add_item(header_tree, hf_alljoyn_ns_answers, tvb, offset, 1, ENC_NA);
2101     answers = tvb_get_guint8(tvb, offset);
2102     offset += 1;
2103 
2104     if(answers > 0)
2105         col_append_str(pinfo->cinfo, COL_INFO, " ISAT");
2106 
2107     if(questions > 0)
2108         col_append_str(pinfo->cinfo, COL_INFO, " WHOHAS");
2109 
2110     proto_tree_add_item(header_tree, hf_alljoyn_ns_timer, tvb, offset, 1, ENC_NA);
2111     offset += 1;
2112 
2113 
2114     if(tree) {  /* we are being asked for details */
2115         ns_parse_questions(tvb, &offset, alljoyn_tree, questions, version);
2116 
2117         switch(version) {
2118         case 0:
2119             ns_parse_answers_v0(tvb, &offset, alljoyn_tree, answers);
2120             break;
2121         case 1:
2122             ns_parse_answers_v1(tvb, &offset, alljoyn_tree, answers);
2123             break;
2124         default:
2125             /* XXX - expert info */
2126             /* This case being unsupported is reported in the column info by
2127              * the caller of this function. */
2128             break;
2129         }
2130     }
2131 
2132     return tvb_reported_length(tvb);
2133 }
2134 
2135 /* This is a container for the ARDP info and Wireshark tree information.
2136  */
2137 typedef struct _alljoyn_ardp_tree_data
2138 {
2139     gint offset;
2140     gboolean syn;
2141     gboolean ack;
2142     gboolean eak;
2143     gboolean rst;
2144     gboolean nul;
2145     guint sequence;
2146     guint start_sequence;
2147     guint16 fragment_count;
2148     gint acknowledge;
2149     proto_tree *alljoyn_tree;
2150 } alljoyn_ardp_tree_data;
2151 
2152 /* This is called by dissect_AllJoyn_ardp() to read the header
2153  * and fill out most of tree_data.
2154  * @param tvb is the incoming network data buffer.
2155  * @param pinfo contains information about the incoming packet which
2156  *         we update as we dissect the packet.
2157  * @param tree_data is the destination of the data..
2158  */
2159 static void
2160 ardp_parse_header(tvbuff_t *tvb,
2161                   packet_info *pinfo,
2162                   alljoyn_ardp_tree_data *tree_data)
2163 {
2164     guint8      flags, header_length;
2165     gint        eaklen, packet_length;
2166     guint16     data_length;
2167 
2168     packet_length = tvb_reported_length(tvb);
2169 
2170     flags = tvb_get_guint8(tvb, 0);
2171 
2172     tree_data->syn = (flags & ARDP_SYN) != 0;
2173     tree_data->ack = (flags & ARDP_ACK) != 0;
2174     tree_data->eak = (flags & ARDP_EAK) != 0;
2175     tree_data->rst = (flags & ARDP_RST) != 0;
2176     tree_data->nul = (flags & ARDP_NUL) != 0;
2177 
2178     /* The packet length has to be ARDP_HEADER_LEN_OFFSET long or protocol_is_ardp() would
2179        have returned false. Length is expressed in words so multiply by 2. */
2180     header_length = 2 * tvb_get_guint8(tvb, ARDP_HEADER_LEN_OFFSET);
2181 
2182     if(packet_length < ARDP_DATA_LENGTH_OFFSET + 2) {
2183         /* If we need more data before dissecting then communicate the number of additional bytes needed. */
2184         set_pinfo_desegment(pinfo, 0, ARDP_DATA_LENGTH_OFFSET + 2 - packet_length);
2185 
2186         /* Inform the caller we made it this far. Returning zero means we made no progress.
2187            This is the offset just past the last byte we successfully retrieved. */
2188         tree_data->offset = ARDP_HEADER_LEN_OFFSET + 1;
2189 
2190         return;
2191     }
2192 
2193     data_length = tvb_get_ntohs(tvb, ARDP_DATA_LENGTH_OFFSET);
2194 
2195     if(packet_length < header_length + data_length) {
2196         /* If we need more data before dissecting then communicate the number of additional bytes needed. */
2197         set_pinfo_desegment(pinfo, 0, header_length + data_length - packet_length);
2198 
2199         /* Inform the caller we made it this far. Returning zero it means we made no progress.
2200            This is the offset just past the last byte we successfully retrieved. */
2201         tree_data->offset = ARDP_DATA_LENGTH_OFFSET + 2;
2202         return;
2203     }
2204 
2205     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_syn_flag, tvb, tree_data->offset, 1, ENC_NA);
2206     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_ack_flag, tvb, tree_data->offset, 1, ENC_NA);
2207     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_eak_flag, tvb, tree_data->offset, 1, ENC_NA);
2208     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_rst_flag, tvb, tree_data->offset, 1, ENC_NA);
2209     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_nul_flag, tvb, tree_data->offset, 1, ENC_NA);
2210     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_unused_flag, tvb, tree_data->offset, 1, ENC_NA);
2211     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_version_field, tvb, tree_data->offset, 1, ENC_NA);
2212 
2213     tree_data->offset += 1;
2214 
2215     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_hlen, tvb, tree_data->offset, 1, ENC_NA);
2216     tree_data->offset += 1;
2217 
2218     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_src, tvb, tree_data->offset, 2, ENC_BIG_ENDIAN);
2219     tree_data->offset += 2;
2220 
2221     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_dst, tvb, tree_data->offset, 2, ENC_BIG_ENDIAN);
2222     tree_data->offset += 2;
2223 
2224     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_dlen, tvb, tree_data->offset, 2, ENC_BIG_ENDIAN);
2225     tree_data->offset += 2;
2226 
2227     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_seq, tvb, tree_data->offset, 4, ENC_BIG_ENDIAN);
2228     tree_data->sequence = tvb_get_ntohl(tvb, tree_data->offset);
2229     tree_data->offset += 4;
2230 
2231     proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_ack, tvb, tree_data->offset, 4, ENC_BIG_ENDIAN);
2232     tree_data->acknowledge = tvb_get_ntohl(tvb, tree_data->offset);
2233     tree_data->offset += 4;
2234 
2235     if(tree_data->syn) {
2236         proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_segmax, tvb, tree_data->offset, 2, ENC_BIG_ENDIAN);
2237         tree_data->offset += 2;
2238 
2239         proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_segbmax, tvb, tree_data->offset, 2, ENC_BIG_ENDIAN);
2240         tree_data->offset += 2;
2241 
2242         proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_dackt, tvb, tree_data->offset, 4, ENC_BIG_ENDIAN);
2243         tree_data->offset += 4;
2244 
2245         proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_options, tvb, tree_data->offset, 2, ENC_BIG_ENDIAN);
2246         tree_data->offset += 2;
2247     } else {
2248         proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_ttl, tvb, tree_data->offset, 4, ENC_BIG_ENDIAN);
2249         tree_data->offset += 4;
2250 
2251         proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_lcs, tvb, tree_data->offset, 4, ENC_BIG_ENDIAN);
2252         tree_data->offset += 4;
2253 
2254         proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_nsa, tvb, tree_data->offset, 4, ENC_BIG_ENDIAN);
2255         tree_data->offset += 4;
2256 
2257         proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_fss, tvb, tree_data->offset, 4, ENC_BIG_ENDIAN);
2258         tree_data->start_sequence = tvb_get_ntohl(tvb, tree_data->offset);
2259         tree_data->offset += 4;
2260 
2261         proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_fcnt, tvb, tree_data->offset, 2, ENC_BIG_ENDIAN);
2262         tree_data->fragment_count = tvb_get_ntohs(tvb, tree_data->offset);
2263         tree_data->offset += 2;
2264 
2265         eaklen = header_length - ARDP_FIXED_HDR_LEN;
2266 
2267         /* In the case of a corrupted packet eaklen could be < 0 and bad things could happen. */
2268         if(eaklen > 0) {
2269             if(tree_data->eak) {
2270                 proto_tree_add_item(tree_data->alljoyn_tree, hf_ardp_bmp, tvb, tree_data->offset, eaklen, ENC_NA);
2271             }
2272 
2273             tree_data->offset += eaklen;
2274         }
2275 
2276         /* The data_length bytes, if any, will be passed on to the dissect_AllJoyn_message() handler. */
2277     }
2278 }
2279 
2280 /* Test to see if this buffer contains something that might be the AllJoyn ARDP protocol.
2281  * @param tvb is the incoming network data buffer.
2282  * @returns TRUE if probably the AllJoyn ARDP protocol.
2283  *          FALSE if probably not the AllJoyn ARDP protocol.
2284  */
2285 static gboolean
2286 protocol_is_ardp(tvbuff_t *tvb)
2287 {
2288     guint8      flags, header_length;
2289     gint length = tvb_captured_length(tvb);
2290 
2291     /* We must be able to get the byte value at this offset to determine if it is an ARDP protocol. */
2292     if(length < ARDP_HEADER_LEN_OFFSET + 1) {
2293         return FALSE;
2294     }
2295 
2296     /* Length is expressed in words. */
2297     header_length = 2 * tvb_get_guint8(tvb, ARDP_HEADER_LEN_OFFSET);
2298 
2299     flags = tvb_get_guint8(tvb, 0);
2300 
2301     if((flags & ARDP_SYN) && header_length != ARDP_SYN_FIXED_HDR_LEN) {
2302         return FALSE;
2303     }
2304 
2305     if(!(flags & ARDP_SYN) && header_length < ARDP_FIXED_HDR_LEN) {
2306         return FALSE;
2307     }
2308 
2309     return TRUE;
2310 }
2311 
2312 /* This is called by Wireshark for packet types that are registered
2313    in the proto_reg_handoff_AllJoyn() function. This function handles
2314    the packets for the ARDP and bare AllJoyn message protocols. A test
2315    for bare AllJoyn message protocol is done first. If it is an AllJoyn
2316    packet then only dissect_AllJoyn_message() is called to dissect the
2317    data. If protocol_is_alljoyn_message() returns FALSE then a test for
2318    the ARDP protocol is performed. If it succeeds then ARDP dissection
2319    proceeds and may call dissect_AllJoyn_message() with the offset just
2320    past the ARDP protocol.
2321  * @param tvb is the incoming network data buffer.
2322  * @param pinfo contains information about the incoming packet which
2323  * we update as we dissect the packet.
2324  * @param tree is the tree data items should be added to.
2325  * @return 0 if not AllJoyn ARDP protocol, or
2326  *         the offset into the buffer we have dissected (which should normally
2327  *         be the packet length), or
2328  *         the offset into the buffer we have dissected with
2329  *         pinfo->desegment_len == additional bytes needed from the next packet
2330  *         before we can dissect.
2331  */
2332 static int
2333 dissect_AllJoyn_ardp(tvbuff_t    *tvb,
2334                      packet_info *pinfo,
2335                      proto_tree  *tree,
2336                      void *data   _U_)
2337 {
2338     alljoyn_ardp_tree_data tree_data = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2339     gint packet_length = tvb_reported_length(tvb);
2340     proto_item *alljoyn_item = NULL;
2341     gboolean fragmentedPacket = FALSE;
2342 
2343     if(protocol_is_alljoyn_message(tvb, 0, FALSE)) {
2344         return dissect_AllJoyn_message(tvb, pinfo, tree, 0);
2345     }
2346 
2347     if(!protocol_is_ardp(tvb)) {
2348         return 0;
2349     }
2350 
2351     pinfo->desegment_len = 0;
2352 
2353     /* Add a subtree covering the remainder of the packet */
2354     alljoyn_item = proto_tree_add_item(tree, proto_AllJoyn_ardp, tvb, 0, -1, ENC_NA);
2355     tree_data.alljoyn_tree = proto_item_add_subtree(alljoyn_item, ett_alljoyn_ardp);
2356 
2357     ardp_parse_header(tvb, pinfo, &tree_data);
2358 
2359     /* Is desegmention needed? */
2360     if(pinfo->desegment_len != 0) {
2361         return tree_data.offset;
2362     }
2363 
2364     if(tree_data.offset != 0) {
2365         /* This is ARDP traffic. Mark it as such at the top level. */
2366         col_set_str(pinfo->cinfo, COL_PROTOCOL, "ALLJOYN-ARDP");
2367     }
2368 
2369     if(tree_data.offset < packet_length) {
2370         gint return_value = 0;
2371 
2372         /* We have dissected the ARDP portion. Is the remainder an AllJoyn message? */
2373         if(protocol_is_alljoyn_message(tvb, tree_data.offset, TRUE)) {
2374             return_value = dissect_AllJoyn_message(tvb, pinfo, tree, tree_data.offset);
2375         }
2376         else {
2377             fragmentedPacket = !tree_data.syn && (tree_data.sequence > tree_data.start_sequence);
2378         }
2379 
2380         /* return_value will be the offset into the successfully parsed
2381          * buffer, the requested length of a reassembled packet (with pinfo->desegment_len
2382          * and pinfo->desegment_offset set appropriately), 0 if desegmentation is needed but
2383          * isn't available, or the initial value (tree_data.offset) if no progress was made.
2384          * If dissect_AllJoyn_message() made progress or is requesting desegmentation then
2385          * return leaving the column info as handled by the AllJoyn message dissector. If
2386          * not then we fall through to set the column info in this dissector.
2387          */
2388         if(return_value > tree_data.offset) {
2389             return return_value;
2390         }
2391     }
2392 
2393     col_clear(pinfo->cinfo, COL_INFO);
2394 
2395     col_append_str(pinfo->cinfo, COL_INFO, "flags:");
2396     if(tree_data.syn) {
2397         col_append_str(pinfo->cinfo, COL_INFO, " SYN");
2398     }
2399     if(tree_data.ack) {
2400         col_append_str(pinfo->cinfo, COL_INFO, " ACK");
2401     }
2402     if(tree_data.eak) {
2403         col_append_str(pinfo->cinfo, COL_INFO, " EAK");
2404     }
2405     if(tree_data.rst) {
2406         col_append_str(pinfo->cinfo, COL_INFO, " RST");
2407     }
2408     if(tree_data.nul) {
2409         col_append_str(pinfo->cinfo, COL_INFO, " NUL");
2410     }
2411 
2412     col_append_fstr(pinfo->cinfo, COL_INFO, " SEQ: %10u", tree_data.sequence);
2413     col_append_fstr(pinfo->cinfo, COL_INFO, " ACK: %10u", tree_data.acknowledge);
2414 
2415     if(fragmentedPacket) {
2416         guint fragment = (tree_data.sequence - tree_data.start_sequence) + 1;
2417 
2418         col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Fragment %d of %d for a previous ALLJOYN message", fragment, tree_data.fragment_count);
2419     }
2420 
2421     return tree_data.offset;
2422 }
2423 
2424 void
2425 proto_register_AllJoyn(void)
2426 {
2427     expert_module_t* expert_alljoyn;
2428 
2429     /* A header field is something you can search/filter on.
2430      *
2431      * We create a structure to register our fields. It consists of an
2432      * array of hf_register_info structures, each of which are of the format
2433      * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
2434      * The array below defines what elements we will be displaying. These
2435      * declarations are simply a definition Wireshark uses to determine the data
2436      * type, when we later dissect the packet.
2437      */
2438     static hf_register_info hf[] = {
2439         /******************
2440          * Wireshark header fields for the name service protocol.
2441          ******************/
2442         {&hf_alljoyn_ns_header,
2443          {"Header", "alljoyn.header",
2444           FT_NONE, BASE_NONE, NULL, 0x0,
2445           NULL, HFILL}
2446         },
2447         {&hf_alljoyn_ns_sender_version,
2448          {"Sender Version", "alljoyn.header.sendversion",
2449           FT_UINT8, BASE_DEC, NULL, 0xF0,
2450           NULL, HFILL}
2451         },
2452         {&hf_alljoyn_ns_message_version,
2453          {"Message Version", "alljoyn.header.messageversion",
2454           FT_UINT8, BASE_DEC, NULL, 0x0F,
2455           NULL, HFILL}
2456         },
2457         {&hf_alljoyn_ns_questions,
2458          {"Questions", "alljoyn.header.questions",
2459           FT_UINT8, BASE_DEC, NULL, 0x0,
2460           NULL, HFILL}
2461         },
2462         {&hf_alljoyn_ns_answers,
2463          {"Answers", "alljoyn.header.answers",
2464           FT_UINT8, BASE_DEC, NULL, 0x0,
2465           NULL, HFILL}
2466         },
2467         {&hf_alljoyn_ns_timer,
2468          {"Timer", "alljoyn.header.timer",
2469           FT_UINT8, BASE_DEC, NULL, 0x0,
2470           NULL, HFILL}
2471         },
2472 
2473         {&hf_alljoyn_ns_whohas,
2474          {"Who-Has Message", "alljoyn.whohas",
2475           FT_NONE, BASE_NONE, NULL, 0x0,
2476           NULL, HFILL}
2477         },
2478         {&hf_alljoyn_ns_whohas_t_flag,
2479          {"TCP", "alljoyn.whohas.T",
2480           FT_BOOLEAN, 8, NULL, WHOHAS_T,
2481           NULL, HFILL}
2482         },
2483         {&hf_alljoyn_ns_whohas_u_flag,
2484          {"UDP", "alljoyn.whohas.U",
2485           FT_BOOLEAN, 8, NULL, WHOHAS_U,
2486           NULL, HFILL}
2487         },
2488         {&hf_alljoyn_ns_whohas_s_flag,
2489          {"IPv6", "alljoyn.whohas.S",
2490           FT_BOOLEAN, 8, NULL, WHOHAS_S,
2491           NULL, HFILL}
2492         },
2493         {&hf_alljoyn_ns_whohas_f_flag,
2494          {"IPv4", "alljoyn.whohas.F",
2495           FT_BOOLEAN, 8, NULL, WHOHAS_F,
2496           NULL, HFILL}
2497         },
2498         {&hf_alljoyn_ns_whohas_count,
2499          {"Count", "alljoyn.whohas.count",
2500           FT_UINT8, BASE_DEC, NULL, 0x0,
2501           NULL, HFILL}
2502         },
2503 
2504         {&hf_alljoyn_answer,
2505          {"Is-At Message", "alljoyn.isat",
2506           FT_NONE, BASE_NONE, NULL, 0x0,
2507           NULL, HFILL}
2508         },
2509         {&hf_alljoyn_isat_entry,
2510          {"Advertisement Entry", "alljoyn.isat_entry",
2511           FT_NONE, BASE_NONE, NULL, 0x0,
2512           NULL, HFILL}
2513         },
2514         {&hf_alljoyn_isat_guid_string,
2515          {"GUID String", "alljoyn.isat_guid_string",
2516           FT_NONE, BASE_NONE, NULL, 0x0,
2517           NULL, HFILL}
2518         },
2519 
2520         /* Common to V0 and V1 IS-AT messages. */
2521         {&hf_alljoyn_ns_isat_g_flag,
2522          {"GUID", "alljoyn.isat.G",
2523           FT_BOOLEAN, 8, NULL, ISAT_G,
2524           NULL, HFILL}
2525         },
2526         {&hf_alljoyn_ns_isat_c_flag,
2527          {"Complete", "alljoyn.isat.C",
2528           FT_BOOLEAN, 8, NULL, ISAT_C,
2529           NULL, HFILL}
2530         },
2531         {&hf_alljoyn_ns_isat_count,
2532          {"Count", "alljoyn.isat.count",
2533           FT_UINT8, BASE_DEC, NULL, 0x0,
2534           NULL, HFILL}
2535         },
2536         {&hf_alljoyn_ns_isat_ipv6,
2537          {"IPv6 Address", "alljoyn.isat.ipv6",
2538           FT_IPv6, BASE_NONE, NULL, 0x0,
2539           NULL, HFILL}
2540         },
2541         {&hf_alljoyn_ns_isat_ipv4,
2542          {"IPv4 Address", "alljoyn.isat.ipv4",
2543           FT_IPv4, BASE_NONE, NULL, 0x0,
2544           NULL, HFILL}
2545         },
2546 
2547         /* Version 0 IS-AT messages. */
2548         {&hf_alljoyn_ns_isat_t_flag,
2549          {"TCP", "alljoyn.isat.T",
2550           FT_BOOLEAN, 8, NULL, ISAT_T,
2551           NULL, HFILL}
2552         },
2553         {&hf_alljoyn_ns_isat_u_flag,
2554          {"UDP", "alljoyn.isat.U",
2555           FT_BOOLEAN, 8, NULL, ISAT_U,
2556           NULL, HFILL}
2557         },
2558         {&hf_alljoyn_ns_isat_s_flag,
2559          {"IPv6", "alljoyn.isat.S",
2560           FT_BOOLEAN, 8, NULL, ISAT_S,
2561           NULL, HFILL}
2562         },
2563         {&hf_alljoyn_ns_isat_f_flag,
2564          {"IPv4", "alljoyn.isat.F",
2565           FT_BOOLEAN, 8, NULL, ISAT_F,
2566           NULL, HFILL}
2567         },
2568         {&hf_alljoyn_ns_isat_port,
2569          {"Port", "alljoyn.isat.port",
2570           FT_UINT16, BASE_DEC, NULL, 0x0,
2571           NULL, HFILL}
2572         },
2573 
2574         /* Version 1 IS-AT messages. */
2575         {&hf_alljoyn_ns_isat_u6_flag,
2576          {"IPv6 UDP", "alljoyn.isat.U6",
2577           FT_BOOLEAN, 8, NULL, ISAT_U6,
2578           NULL, HFILL}
2579         },
2580         {&hf_alljoyn_ns_isat_r6_flag,
2581          {"IPv6 TCP", "alljoyn.isat.R6",
2582           FT_BOOLEAN, 8, NULL, ISAT_R6,
2583           NULL, HFILL}
2584         },
2585         {&hf_alljoyn_ns_isat_u4_flag,
2586          {"IPv4 UDP", "alljoyn.isat.U4",
2587           FT_BOOLEAN, 8, NULL, ISAT_U4,
2588           NULL, HFILL}
2589         },
2590         {&hf_alljoyn_ns_isat_r4_flag,
2591          {"IPv4 TCP", "alljoyn.isat.R4",
2592           FT_BOOLEAN, 8, NULL, ISAT_R4,
2593           NULL, HFILL}
2594         },
2595 
2596         {&hf_alljoyn_ns_isat_transport_mask,
2597          {"Transport Mask", "alljoyn.isat.TransportMask",
2598           FT_UINT16, BASE_HEX, NULL, 0x0,
2599           NULL, HFILL}
2600         },
2601 
2602         {&hf_alljoyn_ns_isat_transport_mask_local,
2603          {"Local Transport", "alljoyn.isat.TransportMask.Local",
2604           FT_BOOLEAN, 16, NULL, TRANSPORT_LOCAL,
2605           NULL, HFILL}
2606         },
2607         {&hf_alljoyn_ns_isat_transport_mask_bluetooth,
2608          {"Bluetooth Transport", "alljoyn.isat.TransportMask.Bluetooth",
2609           FT_BOOLEAN, 16, NULL, TRANSPORT_BLUETOOTH,
2610           NULL, HFILL}
2611         },
2612         {&hf_alljoyn_ns_isat_transport_mask_tcp,
2613          {"TCP Transport", "alljoyn.isat.TransportMask.TCP",
2614           FT_BOOLEAN, 16, NULL, TRANSPORT_TCP,
2615           NULL, HFILL}
2616         },
2617         {&hf_alljoyn_ns_isat_transport_mask_wwan,
2618          {"Wireless WAN Transport", "alljoyn.isat.TransportMask.WWAN",
2619           FT_BOOLEAN, 16, NULL, TRANSPORT_WWAN,
2620           NULL, HFILL}
2621         },
2622         {&hf_alljoyn_ns_isat_transport_mask_lan,
2623          {"Wired LAN Transport", "alljoyn.isat.TransportMask.LAN",
2624           FT_BOOLEAN, 16, NULL, TRANSPORT_LAN,
2625           NULL, HFILL}
2626         },
2627         {&hf_alljoyn_ns_isat_transport_mask_ice,
2628          {"ICE protocol Transport", "alljoyn.isat.TransportMask.ICE",
2629           FT_BOOLEAN, 16, NULL, TRANSPORT_ICE,
2630           NULL, HFILL}
2631         },
2632         {&hf_alljoyn_ns_isat_transport_mask_wfd,
2633          {"Wi-Fi Direct Transport", "alljoyn.isat.TransportMask.WFD",
2634           FT_BOOLEAN, 16, NULL, TRANSPORT_WFD,
2635           NULL, HFILL}
2636         },
2637 
2638         /******************
2639          * Wireshark header fields for the message protocol.
2640          ******************/
2641         {&hf_alljoyn_connect_byte_value,
2642          {"Connect Initial Byte", "alljoyn.InitialByte",
2643           FT_UINT8, BASE_HEX, NULL, 0x0,
2644           NULL, HFILL}
2645         },
2646 
2647         /*
2648          * Wireshark header fields for the SASL messages.
2649          */
2650         {&hf_alljoyn_sasl_command,
2651          {"SASL command", "alljoyn.SASL.command",
2652           FT_STRING, BASE_NONE, NULL, 0x0,
2653           NULL, HFILL}
2654         },
2655         {&hf_alljoyn_sasl_parameter,
2656          {"SASL parameter", "alljoyn.SASL.parameter",
2657           FT_STRING, BASE_NONE, NULL, 0x0,
2658           NULL, HFILL}
2659         },
2660 
2661         /*
2662          * Wireshark header fields for the AllJoyn message header.
2663          */
2664         {&hf_alljoyn_mess_header,
2665          {"Message Header", "alljoyn.mess_header",
2666           FT_BYTES, BASE_NONE, NULL, 0x0,
2667           NULL, HFILL}
2668         },
2669         {&hf_alljoyn_mess_header_endian,
2670          {"Endianness", "alljoyn.mess_header.endianness",
2671           FT_CHAR, BASE_HEX, VALS(endian_encoding_vals), 0x0,
2672           NULL, HFILL}
2673         },
2674         {&hf_alljoyn_mess_header_type,
2675          {"Message type", "alljoyn.mess_header.type",
2676           FT_UINT8, BASE_DEC, VALS(message_header_encoding_vals), 0x0,
2677           NULL, HFILL}
2678         },
2679         {&hf_alljoyn_mess_header_flags,
2680          {"Flags", "alljoyn.mess_header.flags",
2681           FT_UINT8, BASE_HEX, NULL, 0x0,
2682           NULL, HFILL}
2683         },
2684 
2685         /* Individual fields of the flags byte. */
2686         {&hf_alljoyn_mess_header_flags_no_reply,
2687          {"No reply expected", "alljoyn.mess_header.flags.noreply",
2688           FT_BOOLEAN, 8, NULL, MESSAGE_HEADER_FLAG_NO_REPLY_EXPECTED,
2689           NULL, HFILL}
2690         },
2691         {&hf_alljoyn_mess_header_flags_no_auto_start,
2692          {"No auto start", "alljoyn.mess_header.flags.noautostart",
2693           FT_BOOLEAN, 8, NULL, MESSAGE_HEADER_FLAG_NO_AUTO_START,
2694           NULL, HFILL}
2695         },
2696         {&hf_alljoyn_mess_header_flags_allow_remote_msg,
2697          {"Allow remote messages", "alljoyn.mess_header.flags.allowremotemessages",
2698           FT_BOOLEAN, 8, NULL, MESSAGE_HEADER_FLAG_ALLOW_REMOTE_MSG,
2699           NULL, HFILL}
2700         },
2701         {&hf_alljoyn_mess_header_flags_sessionless,
2702          {"Sessionless", "alljoyn.mess_header.flags.sessionless",
2703           FT_BOOLEAN, 8, NULL, MESSAGE_HEADER_FLAG_SESSIONLESS,
2704           NULL, HFILL}
2705         },
2706         {&hf_alljoyn_mess_header_flags_global_broadcast,
2707          {"Allow global broadcast", "alljoyn.mess_header.flags.globalbroadcast",
2708           FT_BOOLEAN, 8, NULL, MESSAGE_HEADER_FLAG_GLOBAL_BROADCAST,
2709           NULL, HFILL}
2710         },
2711         {&hf_alljoyn_mess_header_flags_compressed,
2712          {"Compressed", "alljoyn.mess_header.flags.compressed",
2713           FT_BOOLEAN, 8, NULL, MESSAGE_HEADER_FLAG_COMPRESSED,
2714           NULL, HFILL}
2715         },
2716         {&hf_alljoyn_mess_header_flags_encrypted,
2717          {"Encrypted", "alljoyn.mess_header.flags.encrypted",
2718           FT_BOOLEAN, 8, NULL, MESSAGE_HEADER_FLAG_ENCRYPTED,
2719           NULL, HFILL}
2720         },
2721 
2722         {&hf_alljoyn_mess_header_majorversion,
2723          {"Major version", "alljoyn.mess_header.majorversion",
2724           FT_UINT8, BASE_DEC, NULL, 0,
2725           NULL, HFILL}
2726         },
2727         {&hf_alljoyn_mess_header_body_length,
2728          {"Body length", "alljoyn.mess_header.bodylength",
2729           FT_UINT32, BASE_DEC, NULL, 0,
2730           NULL, HFILL}
2731         },
2732         {&hf_alljoyn_mess_header_serial,
2733          {"Serial number", "alljoyn.mess_header.serial",
2734           FT_UINT32, BASE_DEC, NULL, 0,
2735           NULL, HFILL}
2736         },
2737         {&hf_alljoyn_mess_header_header_length,
2738          {"Header length", "alljoyn.mess_header.headerlength",
2739           FT_UINT32, BASE_DEC, NULL, 0,
2740           NULL, HFILL}
2741         },
2742 
2743         {&hf_alljoyn_mess_header_fields,
2744          {"Header fields", "alljoyn.mess_header.fields",
2745           FT_BYTES, BASE_NONE, NULL, 0,
2746           NULL, HFILL}
2747         },
2748         {&hf_alljoyn_mess_header_field,
2749          {"Header field", "alljoyn.mess_header.field",
2750           FT_UINT8, BASE_HEX, VALS(mess_header_field_encoding_vals), 0,
2751           NULL, HFILL}
2752         },
2753         {&hf_alljoyn_mess_body_header_fieldcode,
2754          {"Field code", "alljoyn.message.fieldcode",
2755           FT_UINT8, BASE_HEX, NULL, 0,
2756           NULL, HFILL}
2757         },
2758         {&hf_alljoyn_mess_body_header_typeid,
2759          {"Type ID", "alljoyn.message.typeid",
2760           FT_UINT8, BASE_CUSTOM, CF_FUNC(alljoyn_typeid), 0,
2761           NULL, HFILL}
2762         },
2763 
2764         {&hf_alljoyn_mess_body_parameters,
2765          {"Parameters", "alljoyn.parameters",
2766           FT_NONE, BASE_NONE, NULL, 0,
2767           NULL, HFILL}
2768         },
2769         {&hf_alljoyn_mess_body_array,
2770          {"Array", "alljoyn.array",
2771           FT_NONE, BASE_NONE, NULL, 0,
2772           NULL, HFILL}
2773         },
2774         {&hf_alljoyn_mess_body_structure,
2775          {"struct", "alljoyn.structure",
2776           FT_NONE, BASE_NONE, NULL, 0,
2777           NULL, HFILL}
2778         },
2779         {&hf_alljoyn_mess_body_dictionary_entry,
2780          {"dictionary entry", "alljoyn.dictionary_entry",
2781           FT_NONE, BASE_NONE, NULL, 0,
2782           NULL, HFILL}
2783         },
2784         {&hf_alljoyn_mess_body_variant,
2785          {"Variant '", "alljoyn.variant",
2786           FT_NONE, BASE_NONE, NULL, 0,
2787           NULL, HFILL}
2788         },
2789         {&hf_alljoyn_mess_body_signature_length,
2790          {"Signature length", "alljoyn.parameter.signature_length",
2791           FT_UINT8, BASE_DEC, NULL, 0,
2792           NULL, HFILL}
2793         },
2794         {&hf_alljoyn_mess_body_signature,
2795          {"Signature", "alljoyn.parameter.signature",
2796           FT_STRING, BASE_NONE, NULL, 0x0,
2797           NULL, HFILL}
2798         },
2799 
2800         {&hf_alljoyn_boolean,
2801          {"Boolean", "alljoyn.boolean",
2802           FT_BOOLEAN, BASE_NONE, NULL, 0,
2803           NULL, HFILL}
2804         },
2805         {&hf_alljoyn_uint8,
2806          {"Unsigned byte", "alljoyn.uint8",
2807           FT_UINT8, BASE_DEC, NULL, 0,
2808           NULL, HFILL}
2809         },
2810         {&hf_alljoyn_int16,
2811          {"Signed int16", "alljoyn.int16",
2812           FT_INT16, BASE_DEC, NULL, 0,
2813           NULL, HFILL}
2814         },
2815         {&hf_alljoyn_uint16,
2816          {"Unsigned int16", "alljoyn.uint16",
2817           FT_UINT16, BASE_DEC, NULL, 0,
2818           NULL, HFILL}
2819         },
2820         {&hf_alljoyn_handle,
2821          {"Handle", "alljoyn.handle",
2822           FT_UINT32, BASE_HEX, NULL, 0,
2823           NULL, HFILL}
2824         },
2825         {&hf_alljoyn_int32,
2826          {"Signed int32", "alljoyn.int32",
2827           FT_INT32, BASE_DEC, NULL, 0,
2828           NULL, HFILL}
2829         },
2830         {&hf_alljoyn_uint32,
2831          {"Unsigned int32", "alljoyn.uint32",
2832           FT_UINT32, BASE_DEC, NULL, 0,
2833           NULL, HFILL}
2834         },
2835         {&hf_alljoyn_int64,
2836          {"Signed int64", "alljoyn.int64",
2837           FT_INT64, BASE_DEC, NULL, 0,
2838           NULL, HFILL}
2839         },
2840         {&hf_alljoyn_uint64,
2841          {"Unsigned int64", "alljoyn.uint64",
2842           FT_UINT64, BASE_DEC, NULL, 0,
2843           NULL, HFILL}
2844         },
2845         {&hf_alljoyn_double,
2846          {"Double", "alljoyn.double",
2847           FT_DOUBLE, BASE_NONE, NULL, 0,
2848           NULL, HFILL}
2849         },
2850         {&hf_padding,
2851          {"Padding", "alljoyn.padding",
2852           FT_BYTES, BASE_NONE, NULL, 0,
2853           NULL, HFILL}
2854         },
2855 
2856         /*
2857          * Strings are composed of a size and a data array.
2858          */
2859         {&hf_alljoyn_string,
2860          {"Bus Name", "alljoyn.string",
2861           FT_NONE, BASE_NONE, NULL, 0x0,
2862           NULL, HFILL}
2863         },
2864         {&hf_alljoyn_string_size_8bit,
2865          {"String Size 8-bit", "alljoyn.string.size8bit",
2866           FT_UINT8, BASE_DEC, NULL, 0x0,
2867           NULL, HFILL}
2868         },
2869         {&hf_alljoyn_string_size_32bit,
2870          {"String Size 32-bit", "alljoyn.string.size32bit",
2871           FT_UINT32, BASE_DEC, NULL, 0x0,
2872           NULL, HFILL}
2873         },
2874         {&hf_alljoyn_string_data,
2875          {"String Data", "alljoyn.string.data",
2876           FT_STRING, BASE_NONE, NULL, 0x0,
2877           NULL, HFILL}
2878         },
2879         /******************
2880          * Wireshark header fields for the AllJoyn Reliable Data Protocol.
2881          ******************/
2882         {&hf_ardp_syn_flag,
2883          {"SYN", "ardp.hdr.SYN",
2884           FT_BOOLEAN, 8, NULL, ARDP_SYN,
2885           NULL, HFILL}
2886         },
2887         {&hf_ardp_ack_flag,
2888          {"ACK", "ardp.hdr.ACK",
2889           FT_BOOLEAN, 8, NULL, ARDP_ACK,
2890           NULL, HFILL}},
2891         {&hf_ardp_eak_flag,
2892          {"EAK", "ardp.hdr.EAK",
2893           FT_BOOLEAN, 8, NULL, ARDP_EAK,
2894           NULL, HFILL}},
2895         {&hf_ardp_rst_flag,
2896          {"RST", "ardp.hdr.RST",
2897           FT_BOOLEAN, 8, NULL, ARDP_RST,
2898           NULL, HFILL}},
2899         {&hf_ardp_nul_flag,
2900          {"NUL", "ardp.hdr.NUL",
2901           FT_BOOLEAN, 8, NULL, ARDP_NUL,
2902           NULL, HFILL}},
2903         {&hf_ardp_unused_flag,
2904          {"UNUSED", "ardp.hdr.UNUSED",
2905           FT_BOOLEAN, 8, NULL, ARDP_UNUSED,
2906           NULL, HFILL}},
2907         {&hf_ardp_version_field,
2908          {"VER", "ardp.hdr.ver",
2909           FT_UINT8, BASE_HEX, NULL, ARDP_VER,
2910           NULL, HFILL}},
2911         {&hf_ardp_hlen,
2912          {"Header Length", "ardp.hdr.hlen",
2913           FT_UINT8, BASE_DEC, NULL, 0x0,
2914           NULL, HFILL}},
2915         {&hf_ardp_src,
2916          {"Source Port", "ardp.hdr.src",
2917           FT_UINT16, BASE_DEC, NULL, 0x0,
2918           NULL, HFILL}},
2919         {&hf_ardp_dst,
2920          {"Destination Port", "ardp.hdr.dst",
2921           FT_UINT16, BASE_DEC, NULL, 0x0,
2922           NULL, HFILL}},
2923         {&hf_ardp_dlen,
2924          {"Data Length", "ardp.hdr.dlen",
2925           FT_UINT16, BASE_DEC, NULL, 0x0,
2926           NULL, HFILL}},
2927         {&hf_ardp_seq,
2928          {"Sequence", "ardp.hdr.seq",
2929           FT_UINT32, BASE_DEC, NULL, 0x0,
2930           NULL, HFILL}},
2931         {&hf_ardp_ack,
2932          {"Acknowledge", "ardp.hdr.ack",
2933           FT_UINT32, BASE_DEC, NULL, 0x0,
2934           NULL, HFILL}},
2935         {&hf_ardp_ttl,
2936          {"Time to Live", "ardp.hdr.ttl",
2937           FT_UINT32, BASE_DEC, NULL, 0x0,
2938           NULL, HFILL}},
2939         {&hf_ardp_lcs,
2940          {"Last Consumed Sequence", "ardp.hdr.lcs",
2941           FT_UINT32, BASE_DEC, NULL, 0x0,
2942           NULL, HFILL}},
2943         {&hf_ardp_nsa,
2944          {"Next Sequence to ACK", "ardp.hdr.nsa",
2945           FT_UINT32, BASE_DEC, NULL, 0x0,
2946           NULL, HFILL}},
2947         {&hf_ardp_fss,
2948          {"Fragment Starting Sequence", "ardp.hdr.fss",
2949           FT_UINT32, BASE_DEC, NULL, 0x0,
2950           NULL, HFILL}},
2951         {&hf_ardp_fcnt,
2952          {"Fragment Count", "ardp.hdr.fcnt",
2953           FT_UINT16, BASE_HEX, NULL, 0x0,
2954           NULL, HFILL}},
2955         {&hf_ardp_bmp,
2956          {"EACK Bitmap", "ardp.hdr.bmp",
2957           FT_UINT8, BASE_HEX, NULL, 0x0,
2958           NULL, HFILL}},
2959         {&hf_ardp_segmax,
2960          {"Segment Max", "ardp.hdr.segmentmax",
2961           FT_UINT16, BASE_DEC, NULL, 0x0,
2962           NULL, HFILL}},
2963         {&hf_ardp_segbmax,
2964          {"Segment Buffer Max", "ardp.hdr.segmentbmax",
2965           FT_UINT32, BASE_DEC, NULL, 0x0,
2966           NULL, HFILL}},
2967         {&hf_ardp_dackt,
2968          {"Receiver's delayed ACK timeout", "ardp.hdr.dackt",
2969           FT_UINT16, BASE_DEC, NULL, 0x0,
2970           NULL, HFILL}},
2971         {&hf_ardp_options,
2972          {"Options", "ardp.hdr.options",
2973           FT_UINT16, BASE_HEX, NULL, 0x0,
2974           NULL, HFILL}},
2975     };
2976 
2977     static gint *ett[] = {
2978         &ett_alljoyn_ns,
2979         &ett_alljoyn_ns_header,
2980         &ett_alljoyn_ns_answers,
2981         &ett_alljoyn_ns_guid_string,
2982         &ett_alljoyn_ns_isat_entry,
2983         &ett_alljoyn_ns_string,
2984         &ett_alljoyn_whohas,
2985         &ett_alljoyn_string,
2986         &ett_alljoyn_isat_entry,
2987         &ett_alljoyn_mess,
2988         &ett_alljoyn_header,
2989         &ett_alljoyn_header_flags,
2990         &ett_alljoyn_mess_header_field,
2991         &ett_alljoyn_mess_header,
2992         &ett_alljoyn_mess_body_parameters,
2993         &ett_alljoyn_ardp
2994     };
2995 
2996     static ei_register_info ei[] = {
2997         { &ei_alljoyn_empty_arg,
2998             { "alljoyn.empty_arg", PI_MALFORMED, PI_ERROR,
2999                 "Argument is empty", EXPFILL }}
3000     };
3001 
3002     /* The following are protocols as opposed to data within a protocol. These appear
3003      * in Wireshark a divider/header between different groups of data.
3004      */
3005 
3006     /* Name service protocols. */                        /* name, short name, abbrev */
3007     proto_AllJoyn_ns = proto_register_protocol("AllJoyn Name Service Protocol", "AllJoyn NS", "ajns");
3008 
3009     /* Message protocols */
3010     proto_AllJoyn_mess = proto_register_protocol("AllJoyn Message Protocol", "AllJoyn", "aj");
3011 
3012     proto_register_field_array(proto_AllJoyn_ns, hf, array_length(hf));
3013     proto_register_subtree_array(ett, array_length(ett));
3014     expert_alljoyn = expert_register_protocol(proto_AllJoyn_mess);
3015     expert_register_field_array(expert_alljoyn, ei, array_length(ei));
3016 
3017     /* ARDP */                        /* name, short name, abbrev */
3018     proto_AllJoyn_ardp = proto_register_protocol("AllJoyn Reliable Datagram Protocol", "AllJoyn ARDP", "ardp");
3019 }
3020 
3021 void
3022 proto_reg_handoff_AllJoyn(void)
3023 {
3024     dissector_handle_t alljoyn_handle_ns;
3025     dissector_handle_t alljoyn_handle_ardp;
3026 
3027     alljoyn_handle_ns = create_dissector_handle(dissect_AllJoyn_name_server, proto_AllJoyn_ns);
3028     alljoyn_handle_ardp = create_dissector_handle(dissect_AllJoyn_ardp, proto_AllJoyn_ardp);
3029     dissector_add_uint_with_preference("tcp.port", ALLJOYN_NAME_SERVER_PORT, alljoyn_handle_ns);
3030     dissector_add_uint_with_preference("tcp.port", ALLJOYN_MESSAGE_PORT, alljoyn_handle_ardp);
3031 
3032     dissector_add_uint_with_preference("udp.port", ALLJOYN_NAME_SERVER_PORT, alljoyn_handle_ns);
3033 
3034     /* The ARDP dissector will directly call the AllJoyn message dissector if needed.
3035      * This includes the case where there is no ARDP data. */
3036     dissector_add_uint_with_preference("udp.port", ALLJOYN_MESSAGE_PORT, alljoyn_handle_ardp);
3037 }
3038 
3039 /*
3040  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3041  *
3042  * Local variables:
3043  * c-basic-offset: 4
3044  * tab-width: 8
3045  * indent-tabs-mode: nil
3046  * End:
3047  *
3048  * vi: set shiftwidth=4 tabstop=8 expandtab:
3049  * :indentSize=4:tabSize=8:noTabs=true:
3050  */
3051