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