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
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
;
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
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. */
132 /* Bitmasks for v0 IS-AT messages. */
138 /* Bitmasks for v1 IS-AT messages. */
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" },
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" },
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
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" },
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
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
,
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
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
,
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
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
,
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
385 get_uint32(tvbuff_t
*tvb
,
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
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.
408 handle_message_connect(tvbuff_t
*tvb
,
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
);
428 typedef struct _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
,
464 for(command_index
= 0; command_index
< sasl_commands_count
; command_index
++) {
467 cmd
= &sasl_commands
[command_index
];
469 if(0 == tvb_strneql(tvb
, offset
, cmd
->text
, cmd
->length
)) {
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
;
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.
509 handle_message_sasl(tvbuff_t
*tvb
,
512 proto_tree
*message_tree
)
514 int return_value
= offset
;
515 const sasl_cmd
*command
;
517 command
= find_sasl_command(tvb
, offset
);
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
;
535 /* If we can't desegment then return 0 meaning we didn't do anything. */
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
);
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
;
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
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
574 get_message_header_endianness(tvbuff_t
*tvb
,
580 /* The endianness field. */
581 endianness
= tvb_get_uint8(tvb
, offset
+ ENDIANNESS_OFFSET
);
586 encoding
= ENC_LITTLE_ENDIAN
;
589 encoding
= ENC_BIG_ENDIAN
;
592 encoding
= ENC_ALLJOYN_BAD_ENCODING
;
599 /* This is called by handle_message_field() to handle bytes of particular values
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.
607 handle_message_header_expected_byte(tvbuff_t
*tvb
,
609 proto_tree
*field_tree
,
610 uint8_t expected_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
);
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" },
670 pad_according_to_type(int offset
, int field_starting_offset
, int max_offset
, uint8_t type
)
682 offset
= round_to_8byte(offset
, field_starting_offset
);
694 offset
= round_to_4byte(offset
, field_starting_offset
);
699 offset
= round_to_2byte(offset
, field_starting_offset
);
715 if(offset
> max_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.
730 append_struct_signature(proto_item
*item
,
731 const uint8_t *signature
,
732 int signature_max_length
,
733 const uint8_t type_stop
)
737 int signature_length
= 0;
740 proto_item_append_text(item
, "%c", ' ');
741 type_start
= *signature
;
744 if(type_start
== *signature
) {
748 if(type_stop
== *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.
773 // NOLINTNEXTLINE(misc-no-recursion)
774 advance_to_end_of_signature(packet_info
*pinfo
, const uint8_t **signature
, uint8_t *signature_length
)
778 int8_t end_type
= ARG_INVALID
;
780 increment_dissection_depth(pinfo
);
782 while (*signature_length
> 0 && **signature
&& !done
) {
783 current_type
= *(++(*signature
));
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. */
798 advance_to_end_of_signature(pinfo
, signature
, signature_length
);
802 advance_to_end_of_signature(pinfo
, signature
, signature_length
);
806 advance_to_end_of_signature(pinfo
, signature
, signature_length
);
826 default: /* Unrecognized signature. Bail out. */
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.
884 // NOLINTNEXTLINE(misc-no-recursion)
885 parse_arg(tvbuff_t
*tvb
,
887 proto_item
*header_item
,
890 proto_tree
*field_tree
,
894 const uint8_t **signature
,
895 uint8_t *signature_length
,
896 int field_starting_offset
)
900 int saved_offset
= offset
;
905 offset
= round_to_8byte(offset
+ 1, field_starting_offset
);
908 case ARG_ARRAY
: /* AllJoyn array container type */
912 const uint8_t *sig_saved
;
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
);
949 advance_to_end_of_signature(pinfo
, signature
, signature_length
);
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
;
960 sig_pointer
= sig_saved
;
961 remaining_sig_length
= sig_length_saved
;
963 offset
= parse_arg(tvb
,
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
);
984 proto_item_append_text(item
, " of %d '%s' elements", number_of_items
, format_char(pinfo
->pool
, *sig_saved
));
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
);
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
);
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'. */
1021 proto_tree_add_item(field_tree
, hf_alljoyn_mess_body_signature_length
, tvb
, offset
, 1, encoding
);
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
);
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
);
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
);
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
);
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
);
1077 proto_tree_add_item(field_tree
, hf_alljoyn_string_data
, tvb
, offset
, length
, ENC_ASCII
);
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
);
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'. */
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
);
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
);
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
);
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
);
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
);
1150 proto_tree_add_item(field_tree
, hf_alljoyn_uint32
, tvb
, offset
, 4, encoding
);
1156 case ARG_VARIANT
: /* AllJoyn variant container type */
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
);
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
);
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
);
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
);
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
);
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 */
1231 if(type_id
== ARG_STRUCT
) {
1232 hf
= hf_alljoyn_mess_body_structure
;
1235 hf
= hf_alljoyn_mess_body_dictionary_entry
;
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
,
1272 field_starting_offset
);
1275 decrement_dissection_depth(pinfo
);
1277 proto_item_set_end(item
, tvb
, offset
);
1282 /* Just say we are done with this packet. */
1283 offset
= tvb_reported_length(tvb
);
1287 if (*signature
&& *signature_length
> 0 && ARG_ARRAY
!= type_id
&& HDR_INVALID
== field_code
) {
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
);
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.
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.
1322 handle_message_field(tvbuff_t
*tvb
,
1324 proto_item
*header_tree
,
1327 const uint8_t **signature
,
1328 uint8_t *signature_length
)
1330 proto_tree
*field_tree
;
1331 proto_item
*item
, *field_item
;
1334 bool is_reply_to
= false;
1335 int starting_offset
= offset
;
1338 field_code
= tvb_get_uint8(tvb
, offset
);
1340 if(HDR_REPLY_SERIAL
== field_code
) {
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
);
1350 /* We expect a byte of 0x01 here. */
1351 handle_message_header_expected_byte(tvb
, offset
, field_tree
, 0x01);
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
);
1358 /* We expect a byte of 0x00 here. */
1359 handle_message_header_expected_byte(tvb
, offset
, field_tree
, 0x00);
1362 offset
= parse_arg(tvb
,
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
);
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
,
1401 proto_item
*header_tree
,
1404 uint32_t header_length
,
1405 uint8_t *signature_length
)
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
);
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.
1434 handle_message_body_parameters(tvbuff_t
*tvb
,
1436 proto_tree
*header_tree
,
1439 int32_t body_length
,
1440 const uint8_t *signature
,
1441 uint8_t signature_length
)
1443 int packet_length
, end_of_body
;
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
,
1466 tree
, /* Add the args to the Parameters tree. */
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.
1498 handle_message_header_body(tvbuff_t
*tvb
,
1501 proto_item
*message_tree
,
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
;
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
1542 if(packet_length_needed
> remaining_packet_length
) {
1543 if(!set_pinfo_desegment(pinfo
, offset
, packet_length_needed
- remaining_packet_length
)) {
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
;
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
,
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.
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)
1645 /* There is no initial connect byte or SASL when using ARDP. */
1647 /* initial byte for a connect message. */
1648 if(tvb_get_uint8(tvb
, offset
) == 0)
1651 if(find_sasl_command(tvb
, offset
) != NULL
)
1655 if(get_message_header_endianness(tvb
, offset
) == ENC_ALLJOYN_BAD_ENCODING
)
1658 if((length
< offset
+ 2) || (try_val_to_str(tvb_get_uint8(tvb
, offset
+ 1), message_header_encoding_vals
) == NULL
))
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
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.
1685 dissect_AllJoyn_message(tvbuff_t
*tvb
,
1690 proto_item
*message_item
;
1691 proto_tree
*message_tree
;
1692 int last_offset
= -1;
1694 bool is_ardp
= false;
1696 /* If called after dissecting the ARDP protocol. This is the only time the offset will not be zero. */
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. */
1717 offset
= handle_message_connect(tvb
, pinfo
, offset
, message_tree
);
1719 if(offset
>= packet_length
) {
1723 offset
= handle_message_sasl(tvb
, pinfo
, offset
, message_tree
);
1725 if(offset
>= packet_length
) {
1730 offset
= handle_message_header_body(tvb
, pinfo
, offset
, message_tree
, is_ardp
);
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
;
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
);
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
);
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
);
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:
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.
1818 ns_parse_answers_v0(tvbuff_t
*tvb
, int* offset
, proto_tree
* alljoyn_tree
, uint8_t answers
)
1821 proto_item
*alljoyn_answers_ti
;
1822 proto_tree
*alljoyn_answers_tree
;
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
);
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
);
1842 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_port
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
1845 if(flags
& ISAT_S
) {
1846 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_ipv6
, tvb
, *offset
, 16, ENC_NA
);
1850 if(flags
& ISAT_F
) {
1851 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_ipv4
, tvb
, *offset
, 4, ENC_BIG_ENDIAN
);
1855 if(flags
& ISAT_G
) {
1856 proto_item
*alljoyn_string_ti
;
1857 proto_tree
*alljoyn_string_tree
;
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
);
1869 proto_tree_add_item(alljoyn_string_tree
, hf_alljoyn_string_data
, tvb
, *offset
, guid_size
, ENC_ASCII
);
1870 (*offset
) += guid_size
;
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
);
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:
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.
1947 ns_parse_answers_v1(tvbuff_t
*tvb
, int* offset
, proto_tree
* alljoyn_tree
, uint8_t answers
)
1950 proto_item
*alljoyn_answers_ti
;
1951 proto_tree
*alljoyn_answers_tree
;
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
);
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
);
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
);
1988 if(flags
& ISAT_R4
) {
1989 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_ipv4
, tvb
, *offset
, 4, ENC_BIG_ENDIAN
);
1992 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_port
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
1996 if(flags
& ISAT_U4
) {
1997 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_ipv4
, tvb
, *offset
, 4, ENC_BIG_ENDIAN
);
2000 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_port
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
2004 if(flags
& ISAT_R6
) {
2005 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_ipv6
, tvb
, *offset
, 16, ENC_NA
);
2008 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_port
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
2012 if(flags
& ISAT_U6
) {
2013 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_ipv6
, tvb
, *offset
, 16, ENC_NA
);
2016 proto_tree_add_item(alljoyn_answers_tree
, hf_alljoyn_ns_isat_port
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
2020 if(flags
& ISAT_G
) {
2021 proto_item
*alljoyn_string_ti
;
2022 proto_tree
*alljoyn_string_tree
;
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
);
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. */
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
);
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.
2073 dissect_AllJoyn_name_server(tvbuff_t
*tvb
,
2078 proto_item
*alljoyn_item
, *header_item
;
2079 proto_tree
*alljoyn_tree
, *header_tree
;
2080 uint8_t questions
, answers
;
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;
2102 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "VERSION %u", version
);
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
);
2110 proto_tree_add_item(header_tree
, hf_alljoyn_ns_answers
, tvb
, offset
, 1, ENC_NA
);
2111 answers
= tvb_get_uint8(tvb
, offset
);
2115 col_append_str(pinfo
->cinfo
, COL_INFO
, " ISAT");
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
);
2124 if(tree
) { /* we are being asked for details */
2125 ns_parse_questions(tvb
, &offset
, alljoyn_tree
, questions
, version
);
2129 ns_parse_answers_v0(tvb
, &offset
, alljoyn_tree
, answers
);
2132 ns_parse_answers_v1(tvb
, &offset
, alljoyn_tree
, answers
);
2135 /* XXX - expert info */
2136 /* This case being unsupported is reported in the column info by
2137 * the caller of this function. */
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
2156 unsigned start_sequence
;
2157 uint16_t fragment_count
;
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..
2170 ardp_parse_header(tvbuff_t
*tvb
,
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;
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;
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;
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. */
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.
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) {
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
) {
2315 if(!(flags
& ARDP_SYN
) && header_length
< ARDP_FIXED_HDR_LEN
) {
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.
2343 dissect_AllJoyn_ardp(tvbuff_t
*tvb
,
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
)) {
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
);
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:");
2407 col_append_str(pinfo
->cinfo
, COL_INFO
, " SYN");
2410 col_append_str(pinfo
->cinfo
, COL_INFO
, " ACK");
2413 col_append_str(pinfo
->cinfo
, COL_INFO
, " EAK");
2416 col_append_str(pinfo
->cinfo
, COL_INFO
, " RST");
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
;
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
[] = {
2450 * Wireshark header fields for the name service protocol.
2452 {&hf_alljoyn_ns_header
,
2453 {"Header", "alljoyn.header",
2454 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2457 {&hf_alljoyn_ns_sender_version
,
2458 {"Sender Version", "alljoyn.header.sendversion",
2459 FT_UINT8
, BASE_DEC
, NULL
, 0xF0,
2462 {&hf_alljoyn_ns_message_version
,
2463 {"Message Version", "alljoyn.header.messageversion",
2464 FT_UINT8
, BASE_DEC
, NULL
, 0x0F,
2467 {&hf_alljoyn_ns_questions
,
2468 {"Questions", "alljoyn.header.questions",
2469 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2472 {&hf_alljoyn_ns_answers
,
2473 {"Answers", "alljoyn.header.answers",
2474 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2477 {&hf_alljoyn_ns_timer
,
2478 {"Timer", "alljoyn.header.timer",
2479 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2483 {&hf_alljoyn_ns_whohas
,
2484 {"Who-Has Message", "alljoyn.whohas",
2485 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2488 {&hf_alljoyn_ns_whohas_t_flag
,
2489 {"TCP", "alljoyn.whohas.T",
2490 FT_BOOLEAN
, 8, NULL
, WHOHAS_T
,
2493 {&hf_alljoyn_ns_whohas_u_flag
,
2494 {"UDP", "alljoyn.whohas.U",
2495 FT_BOOLEAN
, 8, NULL
, WHOHAS_U
,
2498 {&hf_alljoyn_ns_whohas_s_flag
,
2499 {"IPv6", "alljoyn.whohas.S",
2500 FT_BOOLEAN
, 8, NULL
, WHOHAS_S
,
2503 {&hf_alljoyn_ns_whohas_f_flag
,
2504 {"IPv4", "alljoyn.whohas.F",
2505 FT_BOOLEAN
, 8, NULL
, WHOHAS_F
,
2508 {&hf_alljoyn_ns_whohas_count
,
2509 {"Count", "alljoyn.whohas.count",
2510 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2514 {&hf_alljoyn_answer
,
2515 {"Is-At Message", "alljoyn.isat",
2516 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2519 {&hf_alljoyn_isat_entry
,
2520 {"Advertisement Entry", "alljoyn.isat_entry",
2521 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2524 {&hf_alljoyn_isat_guid_string
,
2525 {"GUID String", "alljoyn.isat_guid_string",
2526 FT_NONE
, BASE_NONE
, NULL
, 0x0,
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
,
2536 {&hf_alljoyn_ns_isat_c_flag
,
2537 {"Complete", "alljoyn.isat.C",
2538 FT_BOOLEAN
, 8, NULL
, ISAT_C
,
2541 {&hf_alljoyn_ns_isat_count
,
2542 {"Count", "alljoyn.isat.count",
2543 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2546 {&hf_alljoyn_ns_isat_ipv6
,
2547 {"IPv6 Address", "alljoyn.isat.ipv6",
2548 FT_IPv6
, BASE_NONE
, NULL
, 0x0,
2551 {&hf_alljoyn_ns_isat_ipv4
,
2552 {"IPv4 Address", "alljoyn.isat.ipv4",
2553 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
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
,
2563 {&hf_alljoyn_ns_isat_u_flag
,
2564 {"UDP", "alljoyn.isat.U",
2565 FT_BOOLEAN
, 8, NULL
, ISAT_U
,
2568 {&hf_alljoyn_ns_isat_s_flag
,
2569 {"IPv6", "alljoyn.isat.S",
2570 FT_BOOLEAN
, 8, NULL
, ISAT_S
,
2573 {&hf_alljoyn_ns_isat_f_flag
,
2574 {"IPv4", "alljoyn.isat.F",
2575 FT_BOOLEAN
, 8, NULL
, ISAT_F
,
2578 {&hf_alljoyn_ns_isat_port
,
2579 {"Port", "alljoyn.isat.port",
2580 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
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
,
2590 {&hf_alljoyn_ns_isat_r6_flag
,
2591 {"IPv6 TCP", "alljoyn.isat.R6",
2592 FT_BOOLEAN
, 8, NULL
, ISAT_R6
,
2595 {&hf_alljoyn_ns_isat_u4_flag
,
2596 {"IPv4 UDP", "alljoyn.isat.U4",
2597 FT_BOOLEAN
, 8, NULL
, ISAT_U4
,
2600 {&hf_alljoyn_ns_isat_r4_flag
,
2601 {"IPv4 TCP", "alljoyn.isat.R4",
2602 FT_BOOLEAN
, 8, NULL
, ISAT_R4
,
2606 {&hf_alljoyn_ns_isat_transport_mask
,
2607 {"Transport Mask", "alljoyn.isat.TransportMask",
2608 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2612 {&hf_alljoyn_ns_isat_transport_mask_local
,
2613 {"Local Transport", "alljoyn.isat.TransportMask.Local",
2614 FT_BOOLEAN
, 16, NULL
, TRANSPORT_LOCAL
,
2617 {&hf_alljoyn_ns_isat_transport_mask_bluetooth
,
2618 {"Bluetooth Transport", "alljoyn.isat.TransportMask.Bluetooth",
2619 FT_BOOLEAN
, 16, NULL
, TRANSPORT_BLUETOOTH
,
2622 {&hf_alljoyn_ns_isat_transport_mask_tcp
,
2623 {"TCP Transport", "alljoyn.isat.TransportMask.TCP",
2624 FT_BOOLEAN
, 16, NULL
, TRANSPORT_TCP
,
2627 {&hf_alljoyn_ns_isat_transport_mask_wwan
,
2628 {"Wireless WAN Transport", "alljoyn.isat.TransportMask.WWAN",
2629 FT_BOOLEAN
, 16, NULL
, TRANSPORT_WWAN
,
2632 {&hf_alljoyn_ns_isat_transport_mask_lan
,
2633 {"Wired LAN Transport", "alljoyn.isat.TransportMask.LAN",
2634 FT_BOOLEAN
, 16, NULL
, TRANSPORT_LAN
,
2637 {&hf_alljoyn_ns_isat_transport_mask_ice
,
2638 {"ICE protocol Transport", "alljoyn.isat.TransportMask.ICE",
2639 FT_BOOLEAN
, 16, NULL
, TRANSPORT_ICE
,
2642 {&hf_alljoyn_ns_isat_transport_mask_wfd
,
2643 {"Wi-Fi Direct Transport", "alljoyn.isat.TransportMask.WFD",
2644 FT_BOOLEAN
, 16, NULL
, TRANSPORT_WFD
,
2649 * Wireshark header fields for the message protocol.
2651 {&hf_alljoyn_connect_byte_value
,
2652 {"Connect Initial Byte", "alljoyn.InitialByte",
2653 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
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,
2665 {&hf_alljoyn_sasl_parameter
,
2666 {"SASL parameter", "alljoyn.SASL.parameter",
2667 FT_STRING
, BASE_NONE
, NULL
, 0x0,
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,
2679 {&hf_alljoyn_mess_header_endian
,
2680 {"Endianness", "alljoyn.mess_header.endianness",
2681 FT_CHAR
, BASE_HEX
, VALS(endian_encoding_vals
), 0x0,
2684 {&hf_alljoyn_mess_header_type
,
2685 {"Message type", "alljoyn.mess_header.type",
2686 FT_UINT8
, BASE_DEC
, VALS(message_header_encoding_vals
), 0x0,
2689 {&hf_alljoyn_mess_header_flags
,
2690 {"Flags", "alljoyn.mess_header.flags",
2691 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
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
,
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
,
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
,
2711 {&hf_alljoyn_mess_header_flags_sessionless
,
2712 {"Sessionless", "alljoyn.mess_header.flags.sessionless",
2713 FT_BOOLEAN
, 8, NULL
, MESSAGE_HEADER_FLAG_SESSIONLESS
,
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
,
2721 {&hf_alljoyn_mess_header_flags_compressed
,
2722 {"Compressed", "alljoyn.mess_header.flags.compressed",
2723 FT_BOOLEAN
, 8, NULL
, MESSAGE_HEADER_FLAG_COMPRESSED
,
2726 {&hf_alljoyn_mess_header_flags_encrypted
,
2727 {"Encrypted", "alljoyn.mess_header.flags.encrypted",
2728 FT_BOOLEAN
, 8, NULL
, MESSAGE_HEADER_FLAG_ENCRYPTED
,
2732 {&hf_alljoyn_mess_header_majorversion
,
2733 {"Major version", "alljoyn.mess_header.majorversion",
2734 FT_UINT8
, BASE_DEC
, NULL
, 0,
2737 {&hf_alljoyn_mess_header_body_length
,
2738 {"Body length", "alljoyn.mess_header.bodylength",
2739 FT_UINT32
, BASE_DEC
, NULL
, 0,
2742 {&hf_alljoyn_mess_header_serial
,
2743 {"Serial number", "alljoyn.mess_header.serial",
2744 FT_UINT32
, BASE_DEC
, NULL
, 0,
2747 {&hf_alljoyn_mess_header_header_length
,
2748 {"Header length", "alljoyn.mess_header.headerlength",
2749 FT_UINT32
, BASE_DEC
, NULL
, 0,
2753 {&hf_alljoyn_mess_header_fields
,
2754 {"Header fields", "alljoyn.mess_header.fields",
2755 FT_BYTES
, BASE_NONE
, NULL
, 0,
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,
2763 {&hf_alljoyn_mess_body_header_fieldcode
,
2764 {"Field code", "alljoyn.message.fieldcode",
2765 FT_UINT8
, BASE_HEX
, NULL
, 0,
2768 {&hf_alljoyn_mess_body_header_typeid
,
2769 {"Type ID", "alljoyn.message.typeid",
2770 FT_CHAR
, BASE_HEX
, VALS(header_type_vals
), 0,
2774 {&hf_alljoyn_mess_body_parameters
,
2775 {"Parameters", "alljoyn.parameters",
2776 FT_NONE
, BASE_NONE
, NULL
, 0,
2779 {&hf_alljoyn_mess_body_array
,
2780 {"Array", "alljoyn.array",
2781 FT_NONE
, BASE_NONE
, NULL
, 0,
2784 {&hf_alljoyn_mess_body_structure
,
2785 {"struct", "alljoyn.structure",
2786 FT_NONE
, BASE_NONE
, NULL
, 0,
2789 {&hf_alljoyn_mess_body_dictionary_entry
,
2790 {"dictionary entry", "alljoyn.dictionary_entry",
2791 FT_NONE
, BASE_NONE
, NULL
, 0,
2794 {&hf_alljoyn_mess_body_variant
,
2795 {"Variant '", "alljoyn.variant",
2796 FT_NONE
, BASE_NONE
, NULL
, 0,
2799 {&hf_alljoyn_mess_body_signature_length
,
2800 {"Signature length", "alljoyn.parameter.signature_length",
2801 FT_UINT8
, BASE_DEC
, NULL
, 0,
2804 {&hf_alljoyn_mess_body_signature
,
2805 {"Signature", "alljoyn.parameter.signature",
2806 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2810 {&hf_alljoyn_boolean
,
2811 {"Boolean", "alljoyn.boolean",
2812 FT_BOOLEAN
, BASE_NONE
, NULL
, 0,
2816 {"Unsigned byte", "alljoyn.uint8",
2817 FT_UINT8
, BASE_DEC
, NULL
, 0,
2821 {"Signed int16", "alljoyn.int16",
2822 FT_INT16
, BASE_DEC
, NULL
, 0,
2825 {&hf_alljoyn_uint16
,
2826 {"Unsigned int16", "alljoyn.uint16",
2827 FT_UINT16
, BASE_DEC
, NULL
, 0,
2830 {&hf_alljoyn_handle
,
2831 {"Handle", "alljoyn.handle",
2832 FT_UINT32
, BASE_HEX
, NULL
, 0,
2836 {"Signed int32", "alljoyn.int32",
2837 FT_INT32
, BASE_DEC
, NULL
, 0,
2840 {&hf_alljoyn_uint32
,
2841 {"Unsigned int32", "alljoyn.uint32",
2842 FT_UINT32
, BASE_DEC
, NULL
, 0,
2846 {"Signed int64", "alljoyn.int64",
2847 FT_INT64
, BASE_DEC
, NULL
, 0,
2850 {&hf_alljoyn_uint64
,
2851 {"Unsigned int64", "alljoyn.uint64",
2852 FT_UINT64
, BASE_DEC
, NULL
, 0,
2855 {&hf_alljoyn_double
,
2856 {"Double", "alljoyn.double",
2857 FT_DOUBLE
, BASE_NONE
, NULL
, 0,
2861 {"Padding", "alljoyn.padding",
2862 FT_BYTES
, BASE_NONE
, NULL
, 0,
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,
2874 {&hf_alljoyn_string_size_8bit
,
2875 {"String Size 8-bit", "alljoyn.string.size8bit",
2876 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2879 {&hf_alljoyn_string_size_32bit
,
2880 {"String Size 32-bit", "alljoyn.string.size32bit",
2881 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2884 {&hf_alljoyn_string_data
,
2885 {"String Data", "alljoyn.string.data",
2886 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2890 * Wireshark header fields for the AllJoyn Reliable Data Protocol.
2893 {"SYN", "ardp.hdr.SYN",
2894 FT_BOOLEAN
, 8, NULL
, ARDP_SYN
,
2898 {"ACK", "ardp.hdr.ACK",
2899 FT_BOOLEAN
, 8, NULL
, ARDP_ACK
,
2902 {"EAK", "ardp.hdr.EAK",
2903 FT_BOOLEAN
, 8, NULL
, ARDP_EAK
,
2906 {"RST", "ardp.hdr.RST",
2907 FT_BOOLEAN
, 8, NULL
, ARDP_RST
,
2910 {"NUL", "ardp.hdr.NUL",
2911 FT_BOOLEAN
, 8, NULL
, ARDP_NUL
,
2913 {&hf_ardp_unused_flag
,
2914 {"UNUSED", "ardp.hdr.UNUSED",
2915 FT_BOOLEAN
, 8, NULL
, ARDP_UNUSED
,
2917 {&hf_ardp_version_field
,
2918 {"VER", "ardp.hdr.ver",
2919 FT_UINT8
, BASE_HEX
, NULL
, ARDP_VER
,
2922 {"Header Length", "ardp.hdr.hlen",
2923 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2926 {"Source Port", "ardp.hdr.src",
2927 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2930 {"Destination Port", "ardp.hdr.dst",
2931 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2934 {"Data Length", "ardp.hdr.dlen",
2935 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2938 {"Sequence", "ardp.hdr.seq",
2939 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2942 {"Acknowledge", "ardp.hdr.ack",
2943 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2946 {"Time to Live", "ardp.hdr.ttl",
2947 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2950 {"Last Consumed Sequence", "ardp.hdr.lcs",
2951 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2954 {"Next Sequence to ACK", "ardp.hdr.nsa",
2955 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2958 {"Fragment Starting Sequence", "ardp.hdr.fss",
2959 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2962 {"Fragment Count", "ardp.hdr.fcnt",
2963 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2966 {"EACK Bitmap", "ardp.hdr.bmp",
2967 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2970 {"Segment Max", "ardp.hdr.segmentmax",
2971 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2974 {"Segment Buffer Max", "ardp.hdr.segmentbmax",
2975 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2978 {"Receiver's delayed ACK timeout", "ardp.hdr.dackt",
2979 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2982 {"Options", "ardp.hdr.options",
2983 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
2987 static int *ett
[] = {
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
,
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
,
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
);
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
3052 * indent-tabs-mode: nil
3055 * vi: set shiftwidth=4 tabstop=8 expandtab:
3056 * :indentSize=4:tabSize=8:noTabs=true: