2 * Routines for ACN packet disassembly
6 * Copyright (c) 2003 by Erwin Rol <erwin@erwinrol.com>
7 * Copyright (c) 2006 by Electronic Theatre Controls, Inc.
8 * Bill Florac <bflorac@etcconnect.com>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1999 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 Add reading of DDL files so we can futher explode DMP packets
32 For some of the Set/Get properties where we have a range of data
33 it would be better to show the block of data rather and
34 address-data pair on each line...
36 Build CID to "Name" table from file so we can display real names
46 #include <epan/packet.h>
47 #include <epan/prefs.h>
48 #include <epan/ipv6-utils.h>
50 /* Forward declarations */
51 void proto_register_acn(void);
52 void proto_reg_handoff_acn(void);
55 #define ACN_PDU_FLAG_L 0x80
56 #define ACN_PDU_FLAG_V 0x40
57 #define ACN_PDU_FLAG_H 0x20
58 #define ACN_PDU_FLAG_D 0x10
60 #define ACN_DMX_OPTION_P 0x80
61 #define ACN_DMX_OPTION_S 0x40
63 #define ACN_DMP_ADT_FLAG_V 0x80 /* V = Specifies whether address is a virtual address or not. */
64 #define ACN_DMP_ADT_FLAG_R 0x40 /* R = Specifies whether address is relative to last valid address in packet or not. */
65 #define ACN_DMP_ADT_FLAG_D 0x30 /* D1, D0 = Specify non-range or range address, single data, equal size
66 or mixed size data array */
67 #define ACN_DMP_ADT_EXTRACT_D(f) (((f) & ACN_DMP_ADT_FLAG_D) >> 4)
69 #define ACN_DMP_ADT_FLAG_X 0x0c /* X1, X0 = These bits are reserved and their values shall be set to 0
70 when encoded. Their values shall be ignored when decoding. */
72 #define ACN_DMP_ADT_FLAG_A 0x03 /* A1, A0 = Size of Address elements */
73 #define ACN_DMP_ADT_EXTRACT_A(f) ((f) & ACN_DMP_ADT_FLAG_A)
75 #define ACN_DMP_ADT_V_VIRTUAL 0
76 #define ACN_DMP_ADT_V_ACTUAL 1
78 #define ACN_DMP_ADT_R_ABSOLUTE 0
79 #define ACN_DMP_ADT_R_RELATIVE 1
81 #define ACN_DMP_ADT_D_NS 0
82 #define ACN_DMP_ADT_D_RS 1
83 #define ACN_DMP_ADT_D_RE 2
84 #define ACN_DMP_ADT_D_RM 3
86 #define ACN_DMP_ADT_A_1 0
87 #define ACN_DMP_ADT_A_2 1
88 #define ACN_DMP_ADT_A_4 2
89 #define ACN_DMP_ADT_A_R 3
91 #define ACN_PROTOCOL_ID_SDT 1
92 #define ACN_PROTOCOL_ID_DMP 2
93 #define ACN_PROTOCOL_ID_DMX 3
94 #define ACN_PROTOCOL_ID_DMX_2 4
96 #define ACN_ADDR_NULL 0
97 #define ACN_ADDR_IPV4 1
98 #define ACN_ADDR_IPV6 2
99 #define ACN_ADDR_IPPORT 3
102 #define ACN_SDT_VECTOR_UNKNOWN 0
103 #define ACN_SDT_VECTOR_REL_WRAP 1
104 #define ACN_SDT_VECTOR_UNREL_WRAP 2
105 #define ACN_SDT_VECTOR_CHANNEL_PARAMS 3
106 #define ACN_SDT_VECTOR_JOIN 4
107 #define ACN_SDT_VECTOR_JOIN_REFUSE 5
108 #define ACN_SDT_VECTOR_JOIN_ACCEPT 6
109 #define ACN_SDT_VECTOR_LEAVE 7
110 #define ACN_SDT_VECTOR_LEAVING 8
111 #define ACN_SDT_VECTOR_CONNECT 9
112 #define ACN_SDT_VECTOR_CONNECT_ACCEPT 10
113 #define ACN_SDT_VECTOR_CONNECT_REFUSE 11
114 #define ACN_SDT_VECTOR_DISCONNECT 12
115 #define ACN_SDT_VECTOR_DISCONNECTING 13
116 #define ACN_SDT_VECTOR_ACK 14
117 #define ACN_SDT_VECTOR_NAK 15
118 #define ACN_SDT_VECTOR_GET_SESSION 16
119 #define ACN_SDT_VECTOR_SESSIONS 17
121 #define ACN_REFUSE_CODE_NONSPECIFIC 1
122 #define ACN_REFUSE_CODE_ILLEGAL_PARAMS 2
123 #define ACN_REFUSE_CODE_LOW_RESOURCES 3
124 #define ACN_REFUSE_CODE_ALREADY_MEMBER 4
125 #define ACN_REFUSE_CODE_BAD_ADDR_TYPE 5
126 #define ACN_REFUSE_CODE_NO_RECIP_CHAN 6
128 #define ACN_REASON_CODE_NONSPECIFIC 1
129 /*#define ACN_REASON_CODE_ 2 */
130 /*#define ACN_REASON_CODE_ 3 */
131 /*#define ACN_REASON_CODE_ 4 */
132 /*#define ACN_REASON_CODE_ 5 */
133 #define ACN_REASON_CODE_NO_RECIP_CHAN 6
134 #define ACN_REASON_CODE_CHANNEL_EXPIRED 7
135 #define ACN_REASON_CODE_LOST_SEQUENCE 8
136 #define ACN_REASON_CODE_SATURATED 9
137 #define ACN_REASON_CODE_TRANS_ADDR_CHANGING 10
138 #define ACN_REASON_CODE_ASKED_TO_LEAVE 11
139 #define ACN_REASON_CODE_NO_RECIPIENT 12
141 #define ACN_DMP_VECTOR_UNKNOWN 0
142 #define ACN_DMP_VECTOR_GET_PROPERTY 1
143 #define ACN_DMP_VECTOR_SET_PROPERTY 2
144 #define ACN_DMP_VECTOR_GET_PROPERTY_REPLY 3
145 #define ACN_DMP_VECTOR_EVENT 4
146 #define ACN_DMP_VECTOR_MAP_PROPERTY 5
147 #define ACN_DMP_VECTOR_UNMAP_PROPERTY 6
148 #define ACN_DMP_VECTOR_SUBSCRIBE 7
149 #define ACN_DMP_VECTOR_UNSUBSCRIBE 8
150 #define ACN_DMP_VECTOR_GET_PROPERTY_FAIL 9
151 #define ACN_DMP_VECTOR_SET_PROPERTY_FAIL 10
152 #define ACN_DMP_VECTOR_MAP_PROPERTY_FAIL 11
153 #define ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT 12
154 #define ACN_DMP_VECTOR_SUBSCRIBE_REJECT 13
155 #define ACN_DMP_VECTOR_ALLOCATE_MAP 14
156 #define ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY 15
157 #define ACN_DMP_VECTOR_DEALLOCATE_MAP 16
159 #define ACN_DMP_REASON_CODE_NONSPECIFIC 1
160 #define ACN_DMP_REASON_CODE_NOT_A_PROPERTY 2
161 #define ACN_DMP_REASON_CODE_WRITE_ONLY 3
162 #define ACN_DMP_REASON_CODE_NOT_WRITABLE 4
163 #define ACN_DMP_REASON_CODE_DATA_ERROR 5
164 #define ACN_DMP_REASON_CODE_MAPS_NOT_SUPPORTED 6
165 #define ACN_DMP_REASON_CODE_SPACE_NOT_AVAILABLE 7
166 #define ACN_DMP_REASON_CODE_PROP_NOT_MAPPABLE 8
167 #define ACN_DMP_REASON_CODE_MAP_NOT_ALLOCATED 9
168 #define ACN_DMP_REASON_CODE_SUBSCRIPTION_NOT_SUPPORTED 10
169 #define ACN_DMP_REASON_CODE_NO_SUBSCRIPTIONS_SUPPORTED 11
171 #define ACN_DMX_VECTOR 2
173 #define ACN_PREF_DMX_DISPLAY_HEX 0
174 #define ACN_PREF_DMX_DISPLAY_DEC 1
175 #define ACN_PREF_DMX_DISPLAY_PER 2
177 #define ACN_PREF_DMX_DISPLAY_20PL 0
178 #define ACN_PREF_DMX_DISPLAY_16PL 1
192 guint32 address
; /* or first address */
201 * ANSI BSR E1.17 Architecture for Control Networks
205 #define ACTUAL_ADDRESS 0
206 /* forward reference */
207 static guint32
acn_add_address(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, const char *label
);
208 static int dissect_acn(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
210 /* Global variables */
211 static int proto_acn
= -1;
212 static gint ett_acn
= -1;
213 static gint ett_acn_channel_owner_info_block
= -1;
214 static gint ett_acn_channel_member_info_block
= -1;
215 static gint ett_acn_channel_parameter
= -1;
216 static gint ett_acn_address
= -1;
217 static gint ett_acn_address_type
= -1;
218 static gint ett_acn_pdu_flags
= -1;
219 static gint ett_acn_dmp_pdu
= -1;
220 static gint ett_acn_sdt_pdu
= -1;
221 static gint ett_acn_sdt_client_pdu
= -1;
222 static gint ett_acn_sdt_base_pdu
= -1;
223 static gint ett_acn_root_pdu
= -1;
224 static gint ett_acn_dmx_address
= -1;
225 static gint ett_acn_dmx_2_options
= -1;
226 static gint ett_acn_dmx_data_pdu
= -1;
227 static gint ett_acn_dmx_pdu
= -1;
229 /* Register fields */
230 /* In alphabetical order */
231 static int hf_acn_association
= -1;
232 static int hf_acn_channel_number
= -1;
233 static int hf_acn_cid
= -1;
234 /* static int hf_acn_client_protocol_id = -1; */
235 static int hf_acn_data
= -1;
236 static int hf_acn_data8
= -1;
237 static int hf_acn_data16
= -1;
238 static int hf_acn_data24
= -1;
239 static int hf_acn_data32
= -1;
240 /* static int hf_acn_dmp_adt = -1; */ /* address and data type*/
241 static int hf_acn_dmp_adt_a
= -1;
242 static int hf_acn_dmp_adt_v
= -1;
243 static int hf_acn_dmp_adt_r
= -1;
244 static int hf_acn_dmp_adt_d
= -1;
245 static int hf_acn_dmp_adt_x
= -1;
246 static int hf_acn_dmp_reason_code
= -1;
247 static int hf_acn_dmp_vector
= -1;
248 static int hf_acn_expiry
= -1;
249 static int hf_acn_first_memeber_to_ack
= -1;
250 static int hf_acn_first_missed_sequence
= -1;
251 static int hf_acn_ip_address_type
= -1;
252 static int hf_acn_ipv4
= -1;
253 static int hf_acn_ipv6
= -1;
254 static int hf_acn_last_memeber_to_ack
= -1;
255 static int hf_acn_last_missed_sequence
= -1;
256 static int hf_acn_mak_threshold
= -1;
257 static int hf_acn_member_id
= -1;
258 static int hf_acn_nak_holdoff
= -1;
259 static int hf_acn_nak_max_wait
= -1;
260 static int hf_acn_nak_modulus
= -1;
261 static int hf_acn_nak_outbound_flag
= -1;
262 static int hf_acn_oldest_available_wrapper
= -1;
263 static int hf_acn_packet_identifier
= -1;
264 static int hf_acn_pdu
= -1;
265 static int hf_acn_pdu_flag_d
= -1;
266 static int hf_acn_pdu_flag_h
= -1;
267 static int hf_acn_pdu_flag_l
= -1;
268 static int hf_acn_pdu_flag_v
= -1;
269 static int hf_acn_pdu_flags
= -1;
270 static int hf_acn_pdu_length
= -1;
271 static int hf_acn_port
= -1;
272 static int hf_acn_postamble_size
= -1;
273 static int hf_acn_preamble_size
= -1;
274 static int hf_acn_protocol_id
= -1;
275 static int hf_acn_reason_code
= -1;
276 static int hf_acn_reciprocal_channel
= -1;
277 static int hf_acn_refuse_code
= -1;
278 static int hf_acn_reliable_sequence_number
= -1;
279 /* static int hf_acn_sdt_pdu = -1; */
280 static int hf_acn_sdt_vector
= -1;
281 static int hf_acn_dmx_vector
= -1;
282 /* static int hf_acn_session_count = -1; */
283 static int hf_acn_total_sequence_number
= -1;
284 static int hf_acn_dmx_source_name
= -1;
285 static int hf_acn_dmx_priority
= -1;
286 static int hf_acn_dmx_2_reserved
= -1;
287 static int hf_acn_dmx_sequence_number
= -1;
288 static int hf_acn_dmx_2_options
= -1;
289 static int hf_acn_dmx_2_option_p
= -1;
290 static int hf_acn_dmx_2_option_s
= -1;
291 static int hf_acn_dmx_universe
= -1;
293 static int hf_acn_dmx_start_code
= -1;
294 static int hf_acn_dmx_2_first_property_address
= -1;
295 static int hf_acn_dmx_increment
= -1;
296 static int hf_acn_dmx_count
= -1;
297 static int hf_acn_dmx_2_start_code
= -1;
299 /* static int hf_acn_dmx_dmp_vector = -1; */
301 /* Try heuristic ACN decode */
302 static gboolean global_acn_heur
= FALSE
;
303 static gboolean global_acn_dmx_enable
= FALSE
;
304 static gint global_acn_dmx_display_view
= 0;
305 static gint global_acn_dmx_display_line_format
= 0;
306 static gboolean global_acn_dmx_display_zeros
= FALSE
;
307 static gboolean global_acn_dmx_display_leading_zeros
= FALSE
;
310 static const value_string acn_protocol_id_vals
[] = {
311 { ACN_PROTOCOL_ID_SDT
, "SDT Protocol" },
312 { ACN_PROTOCOL_ID_DMP
, "DMP Protocol" },
313 { ACN_PROTOCOL_ID_DMX
, "DMX Protocol" },
314 { ACN_PROTOCOL_ID_DMX_2
, "Ratified DMX Protocol" },
318 static const value_string acn_dmp_adt_r_vals
[] = {
324 static const value_string acn_dmp_adt_v_vals
[] = {
330 static const value_string acn_dmp_adt_d_vals
[] = {
331 { ACN_DMP_ADT_D_NS
, "Non-range, single data item" },
332 { ACN_DMP_ADT_D_RS
, "Range, single data item" },
333 { ACN_DMP_ADT_D_RE
, "Range, array of equal size data items" },
334 { ACN_DMP_ADT_D_RM
, "Range, series of mixed size data items" },
338 static const value_string acn_dmp_adt_a_vals
[] = {
339 { ACN_DMP_ADT_A_1
, "1 octet" },
340 { ACN_DMP_ADT_A_2
, "2 octets" },
341 { ACN_DMP_ADT_A_4
, "4 octets" },
342 { ACN_DMP_ADT_A_R
, "reserved" },
347 static const value_string acn_sdt_vector_vals
[] = {
348 {ACN_SDT_VECTOR_UNKNOWN
, "Unknown"},
349 {ACN_SDT_VECTOR_REL_WRAP
, "Reliable Wrapper"},
350 {ACN_SDT_VECTOR_UNREL_WRAP
, "Unreliable Wrapper"},
351 {ACN_SDT_VECTOR_CHANNEL_PARAMS
, "Channel Parameters"},
352 {ACN_SDT_VECTOR_JOIN
, "Join"},
353 {ACN_SDT_VECTOR_JOIN_REFUSE
, "Join Refuse"},
354 {ACN_SDT_VECTOR_JOIN_ACCEPT
, "Join Accept"},
355 {ACN_SDT_VECTOR_LEAVE
, "Leave"},
356 {ACN_SDT_VECTOR_LEAVING
, "Leaving"},
357 {ACN_SDT_VECTOR_CONNECT
, "Connect"},
358 {ACN_SDT_VECTOR_CONNECT_ACCEPT
, "Connect Accept"},
359 {ACN_SDT_VECTOR_CONNECT_REFUSE
, "Connect Refuse"},
360 {ACN_SDT_VECTOR_DISCONNECT
, "Disconnect"},
361 {ACN_SDT_VECTOR_DISCONNECTING
, "Disconnecting"},
362 {ACN_SDT_VECTOR_ACK
, "Ack"},
363 {ACN_SDT_VECTOR_NAK
, "Nak"},
364 {ACN_SDT_VECTOR_GET_SESSION
, "Get Session"},
365 {ACN_SDT_VECTOR_SESSIONS
, "Sessions"},
369 static const value_string acn_dmx_vector_vals
[] = {
370 {ACN_DMX_VECTOR
, "Streaming DMX"},
374 static const value_string acn_dmp_vector_vals
[] = {
375 {ACN_DMP_VECTOR_UNKNOWN
, "Unknown"},
376 {ACN_DMP_VECTOR_GET_PROPERTY
, "Get Property"},
377 {ACN_DMP_VECTOR_SET_PROPERTY
, "Set Property"},
378 {ACN_DMP_VECTOR_GET_PROPERTY_REPLY
, "Get property reply"},
379 {ACN_DMP_VECTOR_EVENT
, "Event"},
380 {ACN_DMP_VECTOR_MAP_PROPERTY
, "Map Property"},
381 {ACN_DMP_VECTOR_UNMAP_PROPERTY
, "Unmap Property"},
382 {ACN_DMP_VECTOR_SUBSCRIBE
, "Subscribe"},
383 {ACN_DMP_VECTOR_UNSUBSCRIBE
, "Unsubscribe"},
384 {ACN_DMP_VECTOR_GET_PROPERTY_FAIL
, "Get Property Fail"},
385 {ACN_DMP_VECTOR_SET_PROPERTY_FAIL
, "Set Property Fail"},
386 {ACN_DMP_VECTOR_MAP_PROPERTY_FAIL
, "Map Property Fail"},
387 {ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT
, "Subscribe Accept"},
388 {ACN_DMP_VECTOR_SUBSCRIBE_REJECT
, "Subscribe Reject"},
389 {ACN_DMP_VECTOR_ALLOCATE_MAP
, "Allocate Map"},
390 {ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY
, "Allocate Map Reply"},
391 {ACN_DMP_VECTOR_DEALLOCATE_MAP
, "Deallocate Map"},
395 static const value_string acn_ip_address_type_vals
[] = {
396 { ACN_ADDR_NULL
, "Null"},
397 { ACN_ADDR_IPV4
, "IPv4"},
398 { ACN_ADDR_IPV6
, "IPv6"},
399 { ACN_ADDR_IPPORT
, "Port"},
403 static const value_string acn_refuse_code_vals
[] = {
404 { ACN_REFUSE_CODE_NONSPECIFIC
, "Nonspecific" },
405 { ACN_REFUSE_CODE_ILLEGAL_PARAMS
, "Illegal Parameters" },
406 { ACN_REFUSE_CODE_LOW_RESOURCES
, "Low Resources" },
407 { ACN_REFUSE_CODE_ALREADY_MEMBER
, "Already Member" },
408 { ACN_REFUSE_CODE_BAD_ADDR_TYPE
, "Bad Address Type" },
409 { ACN_REFUSE_CODE_NO_RECIP_CHAN
, "No Reciprocal Channel" },
413 static const value_string acn_reason_code_vals
[] = {
414 { ACN_REASON_CODE_NONSPECIFIC
, "Nonspecific" },
415 { ACN_REASON_CODE_NO_RECIP_CHAN
, "No Reciprocal Channel" },
416 { ACN_REASON_CODE_CHANNEL_EXPIRED
, "Channel Expired" },
417 { ACN_REASON_CODE_LOST_SEQUENCE
, "Lost Sequence" },
418 { ACN_REASON_CODE_SATURATED
, "Saturated" },
419 { ACN_REASON_CODE_TRANS_ADDR_CHANGING
, "Transport Address Changing" },
420 { ACN_REASON_CODE_ASKED_TO_LEAVE
, "Asked to Leave" },
421 { ACN_REASON_CODE_NO_RECIPIENT
, "No Recipient"},
425 static const value_string acn_dmp_reason_code_vals
[] = {
426 { ACN_DMP_REASON_CODE_NONSPECIFIC
, "Nonspecific" },
427 { ACN_DMP_REASON_CODE_NOT_A_PROPERTY
, "Not a Property" },
428 { ACN_DMP_REASON_CODE_WRITE_ONLY
, "Write Only" },
429 { ACN_DMP_REASON_CODE_NOT_WRITABLE
, "Not Writable" },
430 { ACN_DMP_REASON_CODE_DATA_ERROR
, "Data Error" },
431 { ACN_DMP_REASON_CODE_MAPS_NOT_SUPPORTED
, "Maps not Supported" },
432 { ACN_DMP_REASON_CODE_SPACE_NOT_AVAILABLE
, "Space not Available" },
433 { ACN_DMP_REASON_CODE_PROP_NOT_MAPPABLE
, "Property not Mappable"},
434 { ACN_DMP_REASON_CODE_MAP_NOT_ALLOCATED
, "Map not Allocated"},
435 { ACN_DMP_REASON_CODE_SUBSCRIPTION_NOT_SUPPORTED
, "Subscription not Supported"},
436 { ACN_DMP_REASON_CODE_NO_SUBSCRIPTIONS_SUPPORTED
, "No Subscriptions Supported"},
440 static const enum_val_t dmx_display_view
[] = {
441 { "hex" , "Hex ", ACN_PREF_DMX_DISPLAY_HEX
},
442 { "decimal", "Decimal", ACN_PREF_DMX_DISPLAY_DEC
},
443 { "percent", "Percent", ACN_PREF_DMX_DISPLAY_PER
},
447 static const enum_val_t dmx_display_line_format
[] = {
448 { "20 per line", "20 per line", ACN_PREF_DMX_DISPLAY_20PL
},
449 { "16 per line", "16 per line", ACN_PREF_DMX_DISPLAY_16PL
},
453 /******************************************************************************/
454 /* Test to see if it is an ACN Packet */
456 is_acn(tvbuff_t
*tvb
)
458 static char acn_packet_id
[] = "ASC-E1.17\0\0\0"; /* must be 12 bytes */
460 if (tvb_length(tvb
) < (4+sizeof(acn_packet_id
)))
463 /* Check the bytes in octets 4 - 16 */
464 if (tvb_memeql(tvb
, 4, acn_packet_id
, sizeof(acn_packet_id
)-1) != 0)
471 /******************************************************************************/
472 /* Heuristic dissector */
474 dissect_acn_heur( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
476 /* This is a heuristic dissector, which means we get all the UDP
477 * traffic not sent to a known dissector and not claimed by
478 * a heuristic dissector called before us!
481 /* abort if not enabled! */
482 if (!global_acn_heur
) return FALSE
;
484 /* abort if it is NOT an ACN packet */
485 if (!is_acn(tvb
)) return FALSE
;
487 /* else, dissect it */
488 dissect_acn(tvb
, pinfo
, tree
);
492 /******************************************************************************/
493 /* Adds tree branch for channel owner info block */
495 acn_add_channel_owner_info_block(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
498 proto_tree
*this_tree
;
499 guint32 session_count
;
502 pi
= proto_tree_add_text(tree
, tvb
, offset
, 8, "Channel Owner Info Block");
503 this_tree
= proto_item_add_subtree(pi
, ett_acn_channel_owner_info_block
);
505 proto_tree_add_item(this_tree
, hf_acn_member_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
507 proto_tree_add_item(this_tree
, hf_acn_channel_number
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
509 offset
+= acn_add_address(tvb
, pinfo
, this_tree
, offset
, "Destination Address:");
510 offset
+= acn_add_address(tvb
, pinfo
, this_tree
, offset
, "Source Address:");
512 session_count
= tvb_get_ntohs(tvb
, offset
);
513 for (x
=0; x
<session_count
; x
++) {
514 pi
= proto_tree_add_item(this_tree
, hf_acn_protocol_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
515 proto_item_append_text(pi
, " #%d", x
+1);
521 /******************************************************************************/
522 /* Adds tree branch for channel member info block */
524 acn_add_channel_member_info_block(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
527 proto_tree
*this_tree
;
528 guint32 session_count
;
531 pi
= proto_tree_add_text(tree
, tvb
, offset
, 8, "Channel Member Info Block");
532 this_tree
= proto_item_add_subtree(pi
, ett_acn_channel_member_info_block
);
534 proto_tree_add_item(this_tree
, hf_acn_member_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
536 proto_tree_add_item(this_tree
, hf_acn_cid
, tvb
, offset
, 16, ENC_BIG_ENDIAN
);
538 proto_tree_add_item(this_tree
, hf_acn_channel_number
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
540 offset
+= acn_add_address(tvb
, pinfo
, this_tree
, offset
, "Destination Address:");
541 offset
+= acn_add_address(tvb
, pinfo
, this_tree
, offset
, "Source Address:");
542 proto_tree_add_item(this_tree
, hf_acn_reciprocal_channel
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
545 session_count
= tvb_get_ntohs(tvb
, offset
);
546 for (x
=0; x
<session_count
; x
++) {
547 pi
= proto_tree_add_item(this_tree
, hf_acn_protocol_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
548 proto_item_append_text(pi
, " #%d", x
+1);
555 /******************************************************************************/
556 /* Add labeled expiry */
558 acn_add_expiry(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, const char *label
)
560 proto_tree_add_text(tree
, tvb
, offset
, 2, "%s %d", label
, tvb_get_guint8(tvb
, offset
));
566 /******************************************************************************/
567 /* Adds tree branch for channel parameters */
569 acn_add_channel_parameter(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
)
572 proto_tree
*param_tree
;
574 pi
= proto_tree_add_text(tree
, tvb
, offset
, 8, "Channel Parameter Block");
575 param_tree
= proto_item_add_subtree(pi
, ett_acn_channel_parameter
);
576 proto_tree_add_item(param_tree
, hf_acn_expiry
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
578 proto_tree_add_item(param_tree
, hf_acn_nak_outbound_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
580 proto_tree_add_item(param_tree
, hf_acn_nak_holdoff
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
582 proto_tree_add_item(param_tree
, hf_acn_nak_modulus
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
584 proto_tree_add_item(param_tree
, hf_acn_nak_max_wait
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
586 return offset
; /* bytes used */
590 /******************************************************************************/
591 /* Add an address tree */
593 acn_add_address(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, const char *label
)
596 proto_tree
*addr_tree
= NULL
;
597 guint8 ip_address_type
;
602 struct e_in6_addr IPv6
;
606 ip_address_type
= tvb_get_guint8(tvb
, offset
);
608 switch (ip_address_type
) {
610 proto_tree_add_item(tree
, hf_acn_ip_address_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
614 /* Build tree and add type*/
615 pi
= proto_tree_add_text(tree
, tvb
, offset
, 7, "%s", label
);
616 addr_tree
= proto_item_add_subtree(pi
, ett_acn_address
);
617 proto_tree_add_item(addr_tree
, hf_acn_ip_address_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
620 port
= tvb_get_ntohs(tvb
, offset
);
621 proto_tree_add_item(addr_tree
, hf_acn_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
624 proto_tree_add_item(addr_tree
, hf_acn_ipv4
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
625 /* Append port and address to tree item */
626 IPv4
= tvb_get_ipv4(tvb
, offset
);
627 SET_ADDRESS(&addr
, AT_IPv4
, sizeof(IPv4
), &IPv4
);
628 proto_item_append_text(pi
, " %s, Port %d", ep_address_to_str(&addr
), port
);
632 /* Build tree and add type*/
633 pi
= proto_tree_add_text(tree
, tvb
, offset
, 19, "%s", label
);
634 addr_tree
= proto_item_add_subtree(pi
, ett_acn_address
);
635 proto_tree_add_item(addr_tree
, hf_acn_ip_address_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
638 port
= tvb_get_ntohs(tvb
, offset
);
639 proto_tree_add_item(addr_tree
, hf_acn_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
642 proto_tree_add_item(addr_tree
, hf_acn_ipv6
, tvb
, offset
, 16, ENC_NA
);
643 /* Append port and address to tree item */
644 tvb_get_ipv6(tvb
, offset
, &IPv6
);
645 SET_ADDRESS(&addr
, AT_IPv6
, sizeof(struct e_in6_addr
), &IPv6
);
646 proto_item_append_text(pi
, " %s, Port %d", ep_address_to_str(&addr
), port
);
649 case ACN_ADDR_IPPORT
:
650 /* Build tree and add type*/
651 pi
= proto_tree_add_text(tree
, tvb
, offset
, 3, "%s", label
);
652 addr_tree
= proto_item_add_subtree(pi
, ett_acn_address
);
653 proto_tree_add_item(addr_tree
, hf_acn_ip_address_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
656 port
= tvb_get_ntohs(tvb
, offset
);
657 proto_tree_add_item(addr_tree
, hf_acn_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
658 /* Append port to tree item */
659 proto_item_append_text(pi
, " %s Port %d", ep_address_to_str(&addr
), port
);
666 /******************************************************************************/
667 /* Adds tree branch for address type */
669 acn_add_dmp_address_type(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, acn_dmp_adt_type
*adt
)
672 proto_tree
*this_tree
= NULL
;
676 /* header contains address and data type */
677 adt
->flags
= tvb_get_guint8(tvb
, offset
);
679 D
= ACN_DMP_ADT_EXTRACT_D(adt
->flags
);
680 name
= val_to_str(D
, acn_dmp_adt_d_vals
, "not valid (%d)");
681 pi
= proto_tree_add_text(tree
, tvb
, offset
, 1, "Address and Data Type: %s", name
);
683 this_tree
= proto_item_add_subtree(pi
, ett_acn_address_type
);
684 proto_tree_add_uint(this_tree
, hf_acn_dmp_adt_v
, tvb
, offset
, 1, adt
->flags
);
685 proto_tree_add_uint(this_tree
, hf_acn_dmp_adt_r
, tvb
, offset
, 1, adt
->flags
);
686 proto_tree_add_uint(this_tree
, hf_acn_dmp_adt_d
, tvb
, offset
, 1, adt
->flags
);
687 proto_tree_add_uint(this_tree
, hf_acn_dmp_adt_x
, tvb
, offset
, 1, adt
->flags
);
688 proto_tree_add_uint(this_tree
, hf_acn_dmp_adt_a
, tvb
, offset
, 1, adt
->flags
);
691 return offset
; /* bytes used */
694 /******************************************************************************/
695 /* Add an dmp address */
697 acn_add_dmp_address(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, acn_dmp_adt_type
*adt
)
699 guint32 start_offset
;
703 start_offset
= offset
;
705 D
= ACN_DMP_ADT_EXTRACT_D(adt
->flags
);
706 A
= ACN_DMP_ADT_EXTRACT_A(adt
->flags
);
709 case ACN_DMP_ADT_D_NS
: /* Non-range address, Single data item */
712 switch (A
) { /* address */
713 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
714 adt
->address
= tvb_get_guint8(tvb
, offset
);
718 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
719 adt
->address
= tvb_get_ntohs(tvb
, offset
);
723 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: one octet address, increment, and count). */
724 adt
->address
= tvb_get_ntohl(tvb
, offset
);
728 default: /* and ACN_DMP_ADT_A_R (Four octet address, (range: four octet address, increment, and count)*/
730 } /* of switch (A) */
732 if (adt
->flags
& ACN_DMP_ADT_FLAG_V
) {
733 proto_tree_add_text(tree
, tvb
, start_offset
, bytes_used
, "Virtual Address: 0x%X", adt
->address
);
735 proto_tree_add_text(tree
, tvb
, start_offset
, bytes_used
, "Actual Address: 0x%X", adt
->address
);
739 case ACN_DMP_ADT_D_RS
: /* Range address, Single data item */
741 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
742 adt
->address
= tvb_get_guint8(tvb
, offset
);
744 adt
->increment
= tvb_get_guint8(tvb
, offset
);
746 adt
->count
= tvb_get_guint8(tvb
, offset
);
750 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
751 adt
->address
= tvb_get_ntohs(tvb
, offset
);
753 adt
->increment
= tvb_get_ntohs(tvb
, offset
);
755 adt
->count
= tvb_get_ntohs(tvb
, offset
);
759 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: four octet address, increment, and count). */
760 adt
->address
= tvb_get_ntohl(tvb
, offset
);
762 adt
->increment
= tvb_get_ntohl(tvb
, offset
);
764 adt
->count
= tvb_get_ntohl(tvb
, offset
);
768 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
770 } /* of switch (A) */
772 if (adt
->flags
& ACN_DMP_ADT_FLAG_V
) {
773 proto_tree_add_text(tree
, tvb
, start_offset
, bytes_used
,
774 "Virtual Address first: 0x%X, inc: %d, count: %d",
775 adt
->address
, adt
->increment
, adt
->count
);
777 proto_tree_add_text(tree
, tvb
, start_offset
, bytes_used
,
778 "Actual Address first: 0x%X, inc: %d, count: %d",
779 adt
->address
, adt
->increment
, adt
->count
);
783 case ACN_DMP_ADT_D_RE
: /* Range address, Array of equal size data items */
785 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
786 adt
->address
= tvb_get_guint8(tvb
, offset
);
788 adt
->increment
= tvb_get_guint8(tvb
, offset
);
790 adt
->count
= tvb_get_guint8(tvb
, offset
);
794 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
795 adt
->address
= tvb_get_ntohs(tvb
, offset
);
797 adt
->increment
= tvb_get_ntohs(tvb
, offset
);
799 adt
->count
= tvb_get_ntohs(tvb
, offset
);
803 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: four octet address, increment, and count). */
804 adt
->address
= tvb_get_ntohl(tvb
, offset
);
806 adt
->increment
= tvb_get_ntohl(tvb
, offset
);
808 adt
->count
= tvb_get_ntohl(tvb
, offset
);
812 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
814 } /* of switch (A) */
816 if (adt
->flags
& ACN_DMP_ADT_FLAG_V
) {
817 proto_tree_add_text(tree
, tvb
, start_offset
, bytes_used
,
818 "Virtual Address first: 0x%X, inc: %d, count: %d",
819 adt
->address
, adt
->increment
, adt
->count
);
821 proto_tree_add_text(tree
, tvb
, start_offset
, bytes_used
,
822 "Actual Address first: 0x%X, inc: %d, count: %d",
823 adt
->address
, adt
->increment
, adt
->count
);
827 case ACN_DMP_ADT_D_RM
: /* Range address, Series of mixed size data items */
829 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
830 adt
->address
= tvb_get_guint8(tvb
, offset
);
832 adt
->increment
= tvb_get_guint8(tvb
, offset
);
834 adt
->count
= tvb_get_guint8(tvb
, offset
);
838 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
839 adt
->address
= tvb_get_ntohs(tvb
, offset
);
841 adt
->increment
= tvb_get_ntohs(tvb
, offset
);
843 adt
->count
= tvb_get_ntohs(tvb
, offset
);
847 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: four octet address, increment, and count). */
848 adt
->address
= tvb_get_ntohl(tvb
, offset
);
850 adt
->increment
= tvb_get_ntohl(tvb
, offset
);
852 adt
->count
= tvb_get_ntohl(tvb
, offset
);
856 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
858 } /* of switch (A) */
860 if (adt
->flags
& ACN_DMP_ADT_FLAG_V
) {
861 proto_tree_add_text(tree
, tvb
, start_offset
, bytes_used
,
862 "Virtual Address first: 0x%X, inc: %d, count: %d",
863 adt
->address
, adt
->increment
, adt
->count
);
865 proto_tree_add_text(tree
, tvb
, start_offset
, bytes_used
,
866 "Actual Address first: 0x%X, inc: %d, count: %d",
867 adt
->address
, adt
->increment
, adt
->count
);
870 } /* of switch (D) */
876 /*******************************************************************************/
877 /* Display DMP Data */
878 #define BUFFER_SIZE 128
880 acn_add_dmp_data(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, acn_dmp_adt_type
*adt
)
885 guint32 data_address
;
887 gchar buffer
[BUFFER_SIZE
];
889 guint32 ok_to_process
= FALSE
;
893 /* We would like to rip through Property Address-Data pairs */
894 /* but since we don't now how many there are nor how big the data size is, */
895 /* it not possible. So, we just show the whole thing as a block of date! */
897 /* There are a few exceptions however */
898 /* 1) if the address type is ACN_DMP_ADT_D_NS or ACN_DMP_ADT_D_RS and */
899 /* or ACN_DMP_ADT_D_RE */
900 /* then number of bytes is <= count + 4. Each value is at least one byte */
901 /* and another address/data pair is at least 4 bytes so if the remaining */
902 /* bytes is less than the count plus 4 then the remaining data */
903 /* must be all data */
905 /* 2) if the address type is ACN_DMP_ADT_D_RE and the number of bytes */
906 /* equals the number of bytes in remaining in the pdu then there is */
907 /* a 1 to one match */
909 D
= ACN_DMP_ADT_EXTRACT_D(adt
->flags
);
911 case ACN_DMP_ADT_D_NS
:
912 case ACN_DMP_ADT_D_RS
:
913 if (adt
->data_length
<= adt
->count
+ 4) {
914 ok_to_process
= TRUE
;
917 case ACN_DMP_ADT_D_RE
:
918 if (adt
->count
== 0) {
921 if (adt
->data_length
<= adt
->count
+ 4) {
922 ok_to_process
= TRUE
;
927 if (!ok_to_process
) {
928 data_size
= adt
->data_length
;
929 ti
= proto_tree_add_item(tree
, hf_acn_data
, tvb
, offset
, data_size
, ENC_NA
);
931 proto_item_set_text(ti
, "Data and more Address-Data Pairs (further dissection not possible)");
935 A
= ACN_DMP_ADT_EXTRACT_A(adt
->flags
);
938 case ACN_DMP_ADT_D_NS
: /* Non-range address, Single data item */
939 /* calculate data size */
940 data_size
= adt
->data_length
;
941 data_address
= adt
->address
;
944 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
945 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%2.2X ->", data_address
);
947 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
948 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%4.4X ->", data_address
);
950 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: four octet address, increment, and count). */
951 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%8.8X ->", data_address
);
953 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
960 data_value
= tvb_get_guint8(tvb
, offset
);
961 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 1, data_value
, "%s %2.2X", buffer
, data_value
);
964 data_value
= tvb_get_ntohs(tvb
, offset
);
965 proto_tree_add_uint_format(tree
, hf_acn_data16
, tvb
, offset
, 2, data_value
, "%s %4.4X", buffer
, data_value
);
968 data_value
= tvb_get_ntoh24(tvb
, offset
);
969 proto_tree_add_uint_format(tree
, hf_acn_data24
, tvb
, offset
, 3, data_value
, "%s %6.6X", buffer
, data_value
);
972 data_value
= tvb_get_ntohl(tvb
, offset
);
973 proto_tree_add_uint_format(tree
, hf_acn_data32
, tvb
, offset
, 4, data_value
, "%s %8.8X", buffer
, data_value
);
976 /* build string of values */
977 for (y
=0; y
<20 && y
<data_size
; y
++) {
978 data_value
= tvb_get_guint8(tvb
, offset
+y
);
979 g_snprintf(buffer
, BUFFER_SIZE
, "%s %2.2X", buffer
, data_value
);
982 ti
= proto_tree_add_item(tree
, hf_acn_data
, tvb
, offset
, data_size
, ENC_NA
);
984 /* change the text */
985 proto_item_set_text(ti
, "%s", buffer
);
987 } /* of switch (data_size) */
991 case ACN_DMP_ADT_D_RS
: /* Range address, Single data item */
992 /* calculate data size */
993 data_size
= adt
->data_length
;
994 data_address
= adt
->address
;
996 for (x
=0; x
<adt
->count
; x
++) {
998 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
999 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%2.2X ->", data_address
);
1001 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
1002 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%4.4X ->", data_address
);
1004 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: four octet address, increment, and count). */
1005 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%8.8X ->", data_address
);
1007 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1011 switch (data_size
) {
1013 data_value
= tvb_get_guint8(tvb
, offset
);
1014 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 1, data_value
, "%s %2.2X", buffer
, data_value
);
1017 data_value
= tvb_get_ntohs(tvb
, offset
);
1018 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 2, data_value
, "%s %4.4X", buffer
, data_value
);
1021 data_value
= tvb_get_ntoh24(tvb
, offset
);
1022 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 3, data_value
, "%s %6.6X", buffer
, data_value
);
1025 data_value
= tvb_get_ntohl(tvb
, offset
);
1026 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 4, data_value
, "%s %8.8X", buffer
, data_value
);
1029 /* build string of values */
1030 for (y
=0; y
<20 && y
<data_size
; y
++) {
1031 data_value
= tvb_get_guint8(tvb
, offset
+y
);
1032 g_snprintf(buffer
, BUFFER_SIZE
, "%s %2.2X", buffer
, data_value
);
1035 ti
= proto_tree_add_item(tree
, hf_acn_data
, tvb
, offset
, data_size
, ENC_NA
);
1036 /* change the text */
1037 proto_item_set_text(ti
, "%s", buffer
);
1039 } /* of switch (data_size) */
1040 data_address
+= adt
->increment
;
1041 } /* of (x=0;x<adt->count;x++) */
1042 offset
+= data_size
;
1045 case ACN_DMP_ADT_D_RE
: /* Range address, Array of equal size data items */
1046 /* calculate data size */
1047 data_size
= adt
->data_length
/ adt
->count
;
1048 data_address
= adt
->address
;
1050 for (x
=0; x
<adt
->count
; x
++) {
1052 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
1053 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%2.2X ->", data_address
);
1055 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
1056 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%4.4X ->", data_address
);
1058 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: four octet address, increment, and count). */
1059 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%8.8X ->", data_address
);
1061 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1065 switch (data_size
) {
1067 data_value
= tvb_get_guint8(tvb
, offset
);
1068 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 1, data_value
, "%s %2.2X", buffer
, data_value
);
1071 data_value
= tvb_get_ntohs(tvb
, offset
);
1072 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 2, data_value
, "%s %4.4X", buffer
, data_value
);
1075 data_value
= tvb_get_ntoh24(tvb
, offset
);
1076 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 3, data_value
, "%s %6.6X", buffer
, data_value
);
1079 data_value
= tvb_get_ntohl(tvb
, offset
);
1080 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 4, data_value
, "%s %8.8X", buffer
, data_value
);
1083 /* build string of values */
1084 for (y
=0; y
<20 && y
<data_size
; y
++) {
1085 data_value
= tvb_get_guint8(tvb
, offset
+y
);
1086 g_snprintf(buffer
, BUFFER_SIZE
, "%s %2.2X", buffer
, data_value
);
1089 ti
= proto_tree_add_item(tree
, hf_acn_data
, tvb
, offset
, data_size
, ENC_NA
);
1090 /* change the text */
1091 proto_item_set_text(ti
, "%s", buffer
);
1093 } /* of switch (data_size) */
1095 offset
+= data_size
;
1096 data_address
+= adt
->increment
;
1097 } /* of (x=0;x<adt->count;x++) */
1100 case ACN_DMP_ADT_D_RM
: /* Range address, Series of mixed size data items */
1101 data_size
= adt
->data_length
;
1102 ti
= proto_tree_add_item(tree
, hf_acn_data
, tvb
, offset
, data_size
, ENC_NA
);
1103 offset
+= data_size
;
1104 /* change the text */
1105 proto_item_set_text(ti
, "Mixed size data items");
1107 } /* of switch (D) */
1112 /*******************************************************************************/
1113 /* Display DMP Reason codes */
1114 #define BUFFER_SIZE 128
1116 acn_add_dmp_reason_codes(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, acn_dmp_adt_type
*adt
)
1120 guint32 data_address
;
1123 gchar buffer
[BUFFER_SIZE
];
1128 D
= ACN_DMP_ADT_EXTRACT_D(adt
->flags
);
1129 A
= ACN_DMP_ADT_EXTRACT_A(adt
->flags
);
1131 case ACN_DMP_ADT_D_NS
: /* Non-range address, Single data item */
1132 data_address
= adt
->address
;
1134 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
1135 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%2.2X ->", data_address
);
1137 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
1138 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%4.4X ->", data_address
);
1140 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: four octet address, increment, and count). */
1141 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%8.8X ->", data_address
);
1143 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1148 data_value
= tvb_get_guint8(tvb
, offset
);
1149 name
= val_to_str(data_value
, acn_dmp_reason_code_vals
, "reason not valid (%d)");
1150 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 1, data_value
, "%s %s", buffer
, name
);
1154 case ACN_DMP_ADT_D_RS
: /* Range address, Single data item */
1155 data_address
= adt
->address
;
1156 for (x
=0; x
<adt
->count
; x
++) {
1158 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
1159 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%2.2X ->", data_address
);
1161 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
1162 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%4.4X ->", data_address
);
1164 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: four octet address, increment, and count). */
1165 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%8.8X ->", data_address
);
1167 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1172 data_value
= tvb_get_guint8(tvb
, offset
);
1173 name
= val_to_str(data_value
, acn_dmp_reason_code_vals
, "reason not valid (%d)");
1174 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 1, data_value
, "%s %s", buffer
, name
);
1176 data_address
+= adt
->increment
;
1177 } /* of (x=0;x<adt->count;x++) */
1181 case ACN_DMP_ADT_D_RE
: /* Range address, Array of equal size data items */
1182 case ACN_DMP_ADT_D_RM
: /* Range address, Series of mixed size data items */
1183 data_address
= adt
->address
;
1184 for (x
=0; x
<adt
->count
; x
++) {
1186 case ACN_DMP_ADT_A_1
: /* One octet address, (range: one octet address, increment, and count). */
1187 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%2.2X ->", data_address
);
1189 case ACN_DMP_ADT_A_2
: /* Two octet address, (range: two octet address, increment, and count). */
1190 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%4.4X ->", data_address
);
1192 case ACN_DMP_ADT_A_4
: /* Four octet address, (range: four octet address, increment, and count). */
1193 g_snprintf(buffer
, BUFFER_SIZE
, "Addr 0x%8.8X ->", data_address
);
1195 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1199 data_value
= tvb_get_guint8(tvb
, offset
);
1200 name
= val_to_str(data_value
, acn_dmp_reason_code_vals
, "reason not valid (%d)");
1201 proto_tree_add_uint_format(tree
, hf_acn_data8
, tvb
, offset
, 1, data_value
, "%s %s", buffer
, name
);
1202 data_address
+= adt
->increment
;
1204 } /* of (x=0;x<adt->count;x++) */
1206 } /* of switch (D) */
1211 /******************************************************************************/
1212 /* Dissect wrapped SDT PDU */
1214 dissect_acn_dmp_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, acn_pdu_offsets
*last_pdu_offsets
)
1216 /* common to all pdu */
1220 guint32 pdu_flvh_length
; /* flags, length, vector, header */
1226 guint32 vector_offset
;
1227 guint32 header_offset
;
1228 guint32 data_offset
;
1231 guint32 data_length
;
1232 guint32 address_count
;
1234 proto_item
*ti
, *pi
;
1235 proto_tree
*pdu_tree
= NULL
;
1236 proto_tree
*flag_tree
= NULL
;
1240 acn_dmp_adt_type adt
= {0,0,0,0,0,0};
1241 acn_dmp_adt_type adt2
= {0,0,0,0,0,0};
1244 /* save start of pdu block */
1247 /* get PDU flags and length flag first */
1248 octet
= tvb_get_guint8(tvb
, offset
++);
1249 pdu_flags
= octet
& 0xf0;
1250 length1
= octet
& 0x0f; /* bottom 4 bits only */
1251 length2
= tvb_get_guint8(tvb
, offset
++);
1253 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1254 /* flvh = flags, length, vector, header */
1255 if (pdu_flags
& ACN_PDU_FLAG_L
) {
1256 length3
= tvb_get_guint8(tvb
, offset
);
1258 pdu_length
= length3
| (length2
<< 8) | (length1
<< 16);
1259 pdu_flvh_length
= 3;
1261 pdu_length
= length2
| (length1
<< 8);
1262 pdu_flvh_length
= 2;
1264 /* offset should now be pointing to vector (if one exists) */
1266 /* Add pdu item and tree */
1267 ti
= proto_tree_add_item(tree
, hf_acn_pdu
, tvb
, pdu_start
, pdu_length
, ENC_NA
);
1268 pdu_tree
= proto_item_add_subtree(ti
, ett_acn_dmp_pdu
);
1270 /* Add flag item and tree */
1271 pi
= proto_tree_add_uint(pdu_tree
, hf_acn_pdu_flags
, tvb
, pdu_start
, 1, pdu_flags
);
1272 flag_tree
= proto_item_add_subtree(pi
, ett_acn_pdu_flags
);
1273 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_l
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1274 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_v
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1275 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_h
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1276 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_d
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1278 /* Add PDU Length item */
1279 proto_tree_add_uint(pdu_tree
, hf_acn_pdu_length
, tvb
, pdu_start
, pdu_flvh_length
, pdu_length
);
1281 /* Set vector offset */
1282 if (pdu_flags
& ACN_PDU_FLAG_V
) {
1283 /* use new values */
1284 vector_offset
= offset
;
1285 last_pdu_offsets
->vector
= offset
;
1289 /* use last values */
1290 vector_offset
= last_pdu_offsets
->vector
;
1292 /* offset should now be pointing to header (if one exists) */
1294 /* Add Vector item */
1295 vector
= tvb_get_guint8(tvb
, vector_offset
);
1296 proto_tree_add_uint(pdu_tree
, hf_acn_dmp_vector
, tvb
, vector_offset
, 1, vector
);
1298 /* Add Vector item to tree*/
1299 name
= val_to_str(vector
, acn_dmp_vector_vals
, "not valid (%d)");
1300 proto_item_append_text(ti
, ": ");
1301 proto_item_append_text(ti
, "%s", name
);
1303 /* Set header offset */
1304 if (pdu_flags
& ACN_PDU_FLAG_H
) {
1305 /* use new values */
1306 header_offset
= offset
;
1307 last_pdu_offsets
->header
= offset
;
1311 /* use last values */
1312 header_offset
= last_pdu_offsets
->header
;
1314 /* offset should now be pointing to data (if one exists) */
1316 /* header contains address and data type */
1317 acn_add_dmp_address_type(tvb
, pinfo
, pdu_tree
, header_offset
, &adt
);
1320 if (pdu_flags
& ACN_PDU_FLAG_D
) {
1321 /* use new values */
1322 data_offset
= offset
;
1323 data_length
= pdu_length
- pdu_flvh_length
;
1324 last_pdu_offsets
->data
= offset
;
1325 last_pdu_offsets
->data_length
= data_length
;
1327 /* use last values */
1328 data_offset
= last_pdu_offsets
->data
;
1329 data_length
= last_pdu_offsets
->data_length
;
1331 end_offset
= data_offset
+ data_length
;
1334 case ACN_DMP_VECTOR_UNKNOWN
:
1336 case ACN_DMP_VECTOR_GET_PROPERTY
:
1337 /* Rip trough property address */
1338 while (data_offset
< end_offset
) {
1339 old_offset
= data_offset
;
1340 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1341 if (old_offset
== data_offset
) break;
1344 case ACN_DMP_VECTOR_SET_PROPERTY
:
1345 /* Rip through Property Address-Data pairs */
1346 /* But, in reality, this generally won't work as we have know way of */
1347 /* calculating the next Address-Data pair */
1348 while (data_offset
< end_offset
) {
1349 old_offset
= data_offset
;
1350 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1351 if (old_offset
== data_offset
) break;
1353 adt
.data_length
= data_length
- (data_offset
- old_offset
);
1354 old_offset
= data_offset
;
1355 data_offset
= acn_add_dmp_data(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1356 if (old_offset
== data_offset
) break;
1359 case ACN_DMP_VECTOR_GET_PROPERTY_REPLY
:
1360 /* Rip through Property Address-Data pairs */
1361 /* But, in reality, this generally won't work as we have know way of */
1362 /* calculating the next Address-Data pair */
1363 while (data_offset
< end_offset
) {
1364 old_offset
= data_offset
;
1365 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1366 if (old_offset
== data_offset
) break;
1368 adt
.data_length
= data_length
- (data_offset
- old_offset
);
1369 old_offset
= data_offset
;
1370 data_offset
= acn_add_dmp_data(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1371 if (old_offset
== data_offset
) break;
1374 case ACN_DMP_VECTOR_EVENT
:
1375 /* Rip through Property Address-Data pairs */
1376 /* But, in reality, this generally won't work as we have know way of */
1377 /* calculating the next Address-Data pair */
1378 while (data_offset
< end_offset
) {
1379 old_offset
= data_offset
;
1380 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1381 if (old_offset
== data_offset
) break;
1383 adt
.data_length
= data_length
- (data_offset
- old_offset
);
1384 old_offset
= data_offset
;
1385 data_offset
= acn_add_dmp_data(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1386 if (old_offset
== data_offset
) break;
1389 case ACN_DMP_VECTOR_MAP_PROPERTY
:
1390 /* Virtual Address type */
1391 data_offset
= acn_add_dmp_address_type(tvb
, pinfo
, pdu_tree
, data_offset
, &adt2
);
1392 /* Rip through Actual-Virtual Address Pairs */
1393 while (data_offset
< end_offset
) {
1395 old_offset
= data_offset
;
1396 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1397 if (old_offset
== data_offset
) break;
1398 D
= ACN_DMP_ADT_EXTRACT_D(adt
.flags
);
1400 case ACN_DMP_ADT_D_NS
:
1403 case ACN_DMP_ADT_D_RS
:
1406 case ACN_DMP_ADT_D_RE
:
1407 address_count
= adt
.count
;
1409 /*case ACN_DMP_ADT_D_RM: */
1412 return pdu_start
+ pdu_length
;
1417 while (address_count
> 0) {
1418 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt2
);
1423 case ACN_DMP_VECTOR_UNMAP_PROPERTY
:
1424 /* Rip trough Actaul Proptery Address */
1425 while (data_offset
< end_offset
) {
1426 old_offset
= data_offset
;
1427 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1428 if (old_offset
== data_offset
) break;
1431 case ACN_DMP_VECTOR_SUBSCRIBE
:
1432 /* Rip trough Proptery Address */
1433 while (data_offset
< end_offset
) {
1434 old_offset
= data_offset
;
1435 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1436 if (old_offset
== data_offset
) break;
1439 case ACN_DMP_VECTOR_UNSUBSCRIBE
:
1440 /* Rip trough Proptery Address */
1441 while (data_offset
< end_offset
) {
1442 old_offset
= data_offset
;
1443 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1444 if (old_offset
== data_offset
) break;
1447 case ACN_DMP_VECTOR_GET_PROPERTY_FAIL
:
1448 /* Rip trough Address-Reason Code Pairs */
1449 while (data_offset
< end_offset
) {
1450 old_offset
= data_offset
;
1451 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1452 if (old_offset
== data_offset
) break;
1454 adt
.data_length
= data_length
- (data_offset
- old_offset
);
1455 old_offset
= data_offset
;
1456 data_offset
= acn_add_dmp_reason_codes(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1457 if (old_offset
== data_offset
) break;
1460 case ACN_DMP_VECTOR_SET_PROPERTY_FAIL
:
1461 /* Rip trough Address-Reason Code Pairs */
1462 while (data_offset
< end_offset
) {
1463 old_offset
= data_offset
;
1464 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1465 if (old_offset
== data_offset
) break;
1467 adt
.data_length
= data_length
- (data_offset
- old_offset
);
1468 old_offset
= data_offset
;
1469 data_offset
= acn_add_dmp_reason_codes(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1470 if (old_offset
== data_offset
) break;
1473 case ACN_DMP_VECTOR_MAP_PROPERTY_FAIL
:
1474 /* Rip trough Address-Reason Code Pairs */
1475 while (data_offset
< end_offset
) {
1476 old_offset
= data_offset
;
1477 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1478 if (old_offset
== data_offset
) break;
1480 adt
.data_length
= data_length
- (data_offset
- old_offset
);
1481 old_offset
= data_offset
;
1482 data_offset
= acn_add_dmp_reason_codes(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1483 if (old_offset
== data_offset
) break;
1486 case ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT
:
1487 /* Rip through Property Addrsses */
1488 while (data_offset
< end_offset
) {
1489 old_offset
= data_offset
;
1490 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1491 if (old_offset
== data_offset
) break;
1494 case ACN_DMP_VECTOR_SUBSCRIBE_REJECT
:
1495 /* Rip trough Address-Reason Code Pairs */
1496 while (data_offset
< end_offset
) {
1497 old_offset
= data_offset
;
1498 data_offset
= acn_add_dmp_address(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1499 if (old_offset
== data_offset
) break;
1501 adt
.data_length
= data_length
- (data_offset
- old_offset
);
1502 old_offset
= data_offset
;
1503 data_offset
= acn_add_dmp_reason_codes(tvb
, pinfo
, pdu_tree
, data_offset
, &adt
);
1504 if (old_offset
== data_offset
) break;
1507 case ACN_DMP_VECTOR_ALLOCATE_MAP
:
1508 /* No data for this */
1510 case ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY
:
1511 /* Single reason code */
1512 proto_tree_add_item(pdu_tree
, hf_acn_dmp_reason_code
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
1513 /* data_offset += 1; */
1514 case ACN_DMP_VECTOR_DEALLOCATE_MAP
:
1515 /* No data for this */
1519 return pdu_start
+ pdu_length
;
1523 /******************************************************************************/
1524 /* Dissect wrapped SDT PDU */
1526 dissect_acn_sdt_wrapped_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, int offset
, acn_pdu_offsets
*last_pdu_offsets
)
1528 /* common to all pdu */
1532 guint32 pdu_flvh_length
; /* flags, length, vector, header */
1537 guint32 vector_offset
;
1538 guint32 data_offset
;
1539 guint32 data_length
;
1541 proto_item
*ti
, *pi
;
1542 proto_tree
*pdu_tree
= NULL
;
1543 proto_tree
*flag_tree
= NULL
;
1549 /* save start of pdu block */
1552 /* get PDU flags and length flag first */
1553 octet
= tvb_get_guint8(tvb
, offset
++);
1554 pdu_flags
= octet
& 0xf0;
1555 length1
= octet
& 0x0f; /* bottom 4 bits only */
1556 length2
= tvb_get_guint8(tvb
, offset
++);
1558 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1559 /* flvh = flags, length, vector, header */
1560 if (pdu_flags
& ACN_PDU_FLAG_L
) {
1561 length3
= tvb_get_guint8(tvb
, offset
);
1563 pdu_length
= length3
| (length2
<< 8) | (length1
<< 16);
1564 pdu_flvh_length
= 3;
1566 pdu_length
= length2
| (length1
<< 8);
1567 pdu_flvh_length
= 2;
1569 /* offset should now be pointing to vector (if one exists) */
1571 /* Add pdu item and tree */
1572 ti
= proto_tree_add_item(tree
, hf_acn_pdu
, tvb
, pdu_start
, pdu_length
, ENC_NA
);
1573 pdu_tree
= proto_item_add_subtree(ti
, ett_acn_sdt_pdu
);
1575 /* Add flag item and tree */
1576 pi
= proto_tree_add_uint(pdu_tree
, hf_acn_pdu_flags
, tvb
, pdu_start
, 1, pdu_flags
);
1577 flag_tree
= proto_item_add_subtree(pi
, ett_acn_pdu_flags
);
1578 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_l
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1579 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_v
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1580 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_h
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1581 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_d
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1583 /* Add PDU Length item */
1584 proto_tree_add_uint(pdu_tree
, hf_acn_pdu_length
, tvb
, pdu_start
, pdu_flvh_length
, pdu_length
);
1586 /* Set vector offset */
1587 if (pdu_flags
& ACN_PDU_FLAG_V
) {
1588 /* use new values */
1589 vector_offset
= offset
;
1590 last_pdu_offsets
->vector
= offset
;
1594 /* use last values */
1595 vector_offset
= last_pdu_offsets
->vector
;
1597 /* offset should now be pointing to header (if one exists) */
1599 /* Add Vector item */
1600 vector
= tvb_get_guint8(tvb
, vector_offset
);
1601 proto_tree_add_uint(pdu_tree
, hf_acn_sdt_vector
, tvb
, vector_offset
, 1, vector
);
1603 /* Add Vector item to tree*/
1604 name
= val_to_str(vector
, acn_sdt_vector_vals
, "not valid (%d)");
1605 proto_item_append_text(ti
, ": ");
1606 proto_item_append_text(ti
, "%s", name
);
1608 /* NO HEADER DATA ON THESE* (at least so far) */
1611 if (pdu_flags
& ACN_PDU_FLAG_D
) {
1612 /* use new values */
1613 data_offset
= offset
;
1614 data_length
= pdu_length
- pdu_flvh_length
;
1615 last_pdu_offsets
->data
= offset
;
1616 last_pdu_offsets
->data_length
= data_length
;
1618 /* use last values */
1619 data_offset
= last_pdu_offsets
->data
;
1620 /*data_length = last_pdu_offsets->data_length;*/
1624 case ACN_SDT_VECTOR_ACK
:
1625 proto_tree_add_item(pdu_tree
, hf_acn_reliable_sequence_number
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
1626 /*data_offset += 4;*/
1628 case ACN_SDT_VECTOR_CHANNEL_PARAMS
:
1629 data_offset
= acn_add_channel_parameter(tvb
, pinfo
, pdu_tree
, data_offset
);
1630 data_offset
= acn_add_address(tvb
, pinfo
, pdu_tree
, data_offset
, "Ad-hoc Address:");
1631 /*data_offset =*/ acn_add_expiry(tvb
, pinfo
, pdu_tree
, data_offset
, "Ad-hoc Expiry:");
1633 case ACN_SDT_VECTOR_LEAVE
:
1636 case ACN_SDT_VECTOR_CONNECT
:
1637 /* Protocol ID item */
1638 proto_tree_add_item(pdu_tree
, hf_acn_protocol_id
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
1639 /*data_offset += 4;*/
1641 case ACN_SDT_VECTOR_CONNECT_ACCEPT
:
1642 /* Protocol ID item */
1643 proto_tree_add_item(pdu_tree
, hf_acn_protocol_id
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
1644 /*data_offset += 4;*/
1646 case ACN_SDT_VECTOR_CONNECT_REFUSE
:
1647 /* Protocol ID item */
1648 proto_tree_add_item(pdu_tree
, hf_acn_protocol_id
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
1650 proto_tree_add_item(pdu_tree
, hf_acn_refuse_code
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
1651 /*data_offset += 1;*/
1653 case ACN_SDT_VECTOR_DISCONNECT
:
1654 /* Protocol ID item */
1655 proto_tree_add_item(pdu_tree
, hf_acn_protocol_id
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
1656 /*data_offset += 4;*/
1658 case ACN_SDT_VECTOR_DISCONNECTING
:
1659 /* Protocol ID item */
1660 proto_tree_add_item(pdu_tree
, hf_acn_protocol_id
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
1662 proto_tree_add_item(pdu_tree
, hf_acn_reason_code
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
1663 /*data_offset += 1;*/
1668 return pdu_start
+ pdu_length
;
1672 /******************************************************************************/
1673 /* Dissect SDT Client PDU */
1675 dissect_acn_sdt_client_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, acn_pdu_offsets
*last_pdu_offsets
)
1677 /* common to all pdu */
1681 guint32 pdu_flvh_length
; /* flags, length, vector, header */
1682 acn_pdu_offsets pdu_offsets
= {0,0,0,0,0};
1687 guint32 vector_offset
;
1688 guint32 header_offset
;
1689 guint32 data_offset
;
1690 guint32 data_length
;
1694 proto_item
*ti
, *pi
;
1695 proto_tree
*pdu_tree
= NULL
;
1696 proto_tree
*flag_tree
= NULL
;
1701 guint32 protocol_id
;
1702 guint16 association
;
1704 /* save start of pdu block */
1706 pdu_offsets
.start
= pdu_start
;
1708 /* get PDU flags and length flag first */
1709 octet
= tvb_get_guint8(tvb
, offset
++);
1710 pdu_flags
= octet
& 0xf0;
1711 length1
= octet
& 0x0f; /* bottom 4 bits only */
1712 length2
= tvb_get_guint8(tvb
, offset
++);
1714 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1715 /* flvh = flags, length, vector, header */
1716 if (pdu_flags
& ACN_PDU_FLAG_L
) {
1717 length3
= tvb_get_guint8(tvb
, offset
);
1719 pdu_length
= length3
| (length2
<< 8) | (length1
<< 16);
1720 pdu_flvh_length
= 3;
1722 pdu_length
= length2
| (length1
<< 8);
1723 pdu_flvh_length
= 2;
1725 /* offset should now be pointing to vector (if one exists) */
1727 /* Add pdu item and tree */
1728 ti
= proto_tree_add_item(tree
, hf_acn_pdu
, tvb
, pdu_start
, pdu_length
, ENC_NA
);
1729 pdu_tree
= proto_item_add_subtree(ti
, ett_acn_sdt_client_pdu
);
1731 /* Add flag item and tree */
1732 pi
= proto_tree_add_uint(pdu_tree
, hf_acn_pdu_flags
, tvb
, pdu_start
, 1, pdu_flags
);
1733 flag_tree
= proto_item_add_subtree(pi
, ett_acn_pdu_flags
);
1734 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_l
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1735 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_v
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1736 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_h
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1737 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_d
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1739 /* Add PDU Length item */
1740 proto_tree_add_uint(pdu_tree
, hf_acn_pdu_length
, tvb
, pdu_start
, pdu_flvh_length
, pdu_length
);
1742 /* Set vector offset */
1743 if (pdu_flags
& ACN_PDU_FLAG_V
) {
1744 /* use new values */
1745 vector_offset
= offset
;
1746 last_pdu_offsets
->vector
= offset
;
1748 pdu_flvh_length
+= 2;
1750 /* use last values */
1751 vector_offset
= last_pdu_offsets
->vector
;
1753 /* offset should now be pointing to header (if one exists) */
1755 /* add Member ID item */
1756 member_id
= tvb_get_ntohs(tvb
, vector_offset
);
1757 proto_tree_add_uint(pdu_tree
, hf_acn_member_id
, tvb
, vector_offset
, 2, member_id
);
1759 /* Set header offset */
1760 if (pdu_flags
& ACN_PDU_FLAG_H
) {
1761 /* use new values */
1762 header_offset
= offset
;
1763 last_pdu_offsets
->header
= offset
;
1765 pdu_flvh_length
+= 6;
1767 /* use last values */
1768 header_offset
= last_pdu_offsets
->header
;
1770 /* offset should now be pointing to data (if one exists) */
1772 /* add Protocol ID item (Header)*/
1773 protocol_id
= tvb_get_ntohl(tvb
, header_offset
);
1774 proto_tree_add_uint(pdu_tree
, hf_acn_protocol_id
, tvb
, header_offset
, 4, protocol_id
);
1777 /* Add protocol to tree*/
1778 name
= val_to_str(protocol_id
, acn_protocol_id_vals
, "id not valid (%d)");
1779 proto_item_append_text(ti
, ": ");
1780 proto_item_append_text(ti
, "%s", name
);
1782 /* add association item */
1783 association
= tvb_get_ntohs(tvb
, header_offset
);
1784 proto_tree_add_uint(pdu_tree
, hf_acn_association
, tvb
, header_offset
, 2, association
);
1785 /*header_offset += 2;*/
1788 if (pdu_flags
& ACN_PDU_FLAG_D
) {
1789 /* use new values */
1790 data_offset
= offset
;
1791 data_length
= pdu_length
- pdu_flvh_length
;
1792 last_pdu_offsets
->data
= offset
;
1793 last_pdu_offsets
->data_length
= data_length
;
1795 /* use last values */
1796 data_offset
= last_pdu_offsets
->data
;
1797 data_length
= last_pdu_offsets
->data_length
;
1799 end_offset
= data_offset
+ data_length
;
1801 switch (protocol_id
) {
1802 case ACN_PROTOCOL_ID_SDT
:
1803 while (data_offset
< end_offset
) {
1804 old_offset
= data_offset
;
1805 data_offset
= dissect_acn_sdt_wrapped_pdu(tvb
, pinfo
, pdu_tree
, data_offset
, &pdu_offsets
);
1806 if (old_offset
== data_offset
) break;
1809 case ACN_PROTOCOL_ID_DMP
:
1810 while (data_offset
< end_offset
) {
1811 old_offset
= data_offset
;
1812 data_offset
= dissect_acn_dmp_pdu(tvb
, pinfo
, pdu_tree
, data_offset
, &pdu_offsets
);
1813 if (data_offset
== old_offset
) break;
1817 return pdu_start
+ pdu_length
;
1821 /******************************************************************************/
1822 /* level to string (ascii) */
1823 /* level : 8 bit value */
1824 /* string : pointer to buffer to fill */
1825 /* leading_char: character to buffer left of digits */
1826 /* min_char : mininum number of characters (for filling, not including space)*/
1827 /* show_zero: show zeros or dots */
1828 /* also adds a space to right end */
1830 /* returns end of string */
1831 /* faster than printf() */
1833 ltos(guint8 level
, gchar
*string
, guint8 base
, gchar leading_char
, guint8 min_chars
, gboolean show_zero
)
1837 if (base
< 2 || base
> 16) {
1841 /* deal with zeros */
1842 if ((level
== 0) && (!show_zero
)) {
1843 for (i
=0; i
<min_chars
; i
++) {
1852 /* do our convert, comes out backwords! */
1854 string
[i
++] = "0123456789ABCDEF"[level
% base
];
1855 } while ((level
/= base
) > 0);
1857 /* expand to needed character */
1858 for (; i
<min_chars
; i
++) {
1859 string
[i
] = leading_char
;
1864 /* now reverse (and correct) the order */
1865 g_strreverse(string
);
1867 /* add a space at the end (ok it's at the start but it will be at the end)*/
1874 /******************************************************************************/
1875 /* Dissect DMX data PDU */
1876 #define BUFFER_SIZE 128
1878 dissect_acn_dmx_data_pdu(guint32 protocol_id
, tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, acn_pdu_offsets
*last_pdu_offsets
)
1880 /* common to all pdu */
1884 guint32 pdu_flvh_length
; /* flags, length, vector, header */
1889 guint32 vector_offset
;
1890 guint32 data_offset
;
1892 guint32 data_length
;
1893 guint32 header_offset
;
1897 proto_item
*ti
, *pi
;
1898 proto_tree
*pdu_tree
= NULL
;
1899 proto_tree
*flag_tree
= NULL
;
1900 /* proto_tree *addr_tree = NULL; */
1903 acn_dmp_adt_type adt
= {0,0,0,0,0,0};
1906 gchar buffer
[BUFFER_SIZE
];
1916 guint16 dmx_start_code
;
1920 /* save start of pdu block */
1923 /* get PDU flags and length flag first */
1924 octet
= tvb_get_guint8(tvb
, offset
++);
1925 pdu_flags
= octet
& 0xf0;
1926 length1
= octet
& 0x0f; /* bottom 4 bits only */
1927 length2
= tvb_get_guint8(tvb
, offset
++);
1929 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1930 /* flvh = flags, length, vector, header */
1931 if (pdu_flags
& ACN_PDU_FLAG_L
) {
1932 length3
= tvb_get_guint8(tvb
, offset
);
1934 pdu_length
= length3
| (length2
<< 8) | (length1
<< 16);
1935 pdu_flvh_length
= 3;
1937 pdu_length
= length2
| (length1
<< 8);
1938 pdu_flvh_length
= 2;
1940 /* offset should now be pointing to vector (if one exists) */
1942 /* Add pdu item and tree */
1943 ti
= proto_tree_add_item(tree
, hf_acn_pdu
, tvb
, pdu_start
, pdu_length
, ENC_NA
);
1944 pdu_tree
= proto_item_add_subtree(ti
, ett_acn_dmx_data_pdu
);
1946 /* Add flag item and tree */
1947 pi
= proto_tree_add_uint(pdu_tree
, hf_acn_pdu_flags
, tvb
, pdu_start
, 1, pdu_flags
);
1948 flag_tree
= proto_item_add_subtree(pi
, ett_acn_pdu_flags
);
1949 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_l
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1950 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_v
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1951 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_h
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1952 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_d
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
1954 /* Add PDU Length item */
1955 proto_tree_add_uint(pdu_tree
, hf_acn_pdu_length
, tvb
, pdu_start
, pdu_flvh_length
, pdu_length
);
1957 /* Set vector offset */
1958 if (pdu_flags
& ACN_PDU_FLAG_V
) {
1959 /* use new values */
1960 vector_offset
= offset
;
1961 last_pdu_offsets
->vector
= offset
;
1963 pdu_flvh_length
+= 1;
1965 /* use last values */
1966 vector_offset
= last_pdu_offsets
->vector
;
1968 /* offset should now be pointing to header (if one exists) */
1970 /* Add Vector item */
1971 vector
= tvb_get_guint8(tvb
, vector_offset
);
1972 proto_tree_add_uint(pdu_tree
, hf_acn_dmp_vector
, tvb
, vector_offset
, 1, vector
);
1974 /* Add Vector item to tree*/
1975 name
= val_to_str(vector
, acn_dmp_vector_vals
, "not valid (%d)");
1976 proto_item_append_text(ti
, ": ");
1977 proto_item_append_text(ti
, "%s", name
);
1979 /* Set header offset */
1980 if (pdu_flags
& ACN_PDU_FLAG_H
) {
1981 /* use new values */
1982 header_offset
= offset
;
1983 last_pdu_offsets
->header
= offset
;
1987 /* use last values */
1988 header_offset
= last_pdu_offsets
->header
;
1990 /* offset should now be pointing to data (if one exists) */
1992 /* process based on vector */
1993 acn_add_dmp_address_type(tvb
, pinfo
, pdu_tree
, header_offset
, &adt
);
1996 if (pdu_flags
& ACN_PDU_FLAG_D
) {
1997 /* use new values */
1998 data_offset
= offset
;
1999 data_length
= pdu_length
- pdu_flvh_length
;
2000 last_pdu_offsets
->data
= offset
;
2001 last_pdu_offsets
->data_length
= data_length
;
2003 /* use last values */
2004 data_offset
= last_pdu_offsets
->data
;
2005 data_length
= last_pdu_offsets
->data_length
;
2007 end_offset
= data_offset
+ data_length
;
2010 case ACN_DMP_VECTOR_SET_PROPERTY
:
2011 dmx_start_code
= tvb_get_ntohs(tvb
, data_offset
);
2012 if (protocol_id
==ACN_PROTOCOL_ID_DMX_2
) {
2013 proto_tree_add_item(pdu_tree
, hf_acn_dmx_2_first_property_address
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2015 proto_tree_add_item(pdu_tree
, hf_acn_dmx_start_code
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2018 proto_tree_add_item(pdu_tree
, hf_acn_dmx_increment
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2020 dmx_count
= tvb_get_ntohs(tvb
, data_offset
);
2021 proto_tree_add_item(pdu_tree
, hf_acn_dmx_count
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2024 if (protocol_id
==ACN_PROTOCOL_ID_DMX_2
) {
2025 proto_tree_add_item(pdu_tree
, hf_acn_dmx_2_start_code
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
2032 switch (global_acn_dmx_display_line_format
) {
2033 case ACN_PREF_DMX_DISPLAY_16PL
:
2042 /* values base on display mode */
2043 switch ((guint
)global_acn_dmx_display_view
) {
2044 case ACN_PREF_DMX_DISPLAY_HEX
:
2048 /* case ACN_PREF_DMX_DISPLAY_PER: */
2054 /* do we display leading zeros */
2055 if (global_acn_dmx_display_leading_zeros
) {
2061 /* add a snippet to info (this may be slow) */
2062 col_append_fstr(pinfo
->cinfo
,COL_INFO
, ", Sc %02x, [%02x %02x %02x %02x %02x %02x...]",
2064 tvb_get_guint8(tvb
, data_offset
),
2065 tvb_get_guint8(tvb
, data_offset
+1),
2066 tvb_get_guint8(tvb
, data_offset
+2),
2067 tvb_get_guint8(tvb
, data_offset
+3),
2068 tvb_get_guint8(tvb
, data_offset
+4),
2069 tvb_get_guint8(tvb
, data_offset
+5));
2071 /* add a header line */
2072 g_snprintf(buffer
, BUFFER_SIZE
, "%-10s: ", "Data...");
2075 for (x
=0; x
<perline
; x
++) {
2076 buf_ptr
= ltos((guint8
)(x
+1), buf_ptr
, 10, ' ', min_char
, FALSE
);
2077 if ((x
+1)==halfline
) {
2083 proto_tree_add_text(pdu_tree
, tvb
, data_offset
, dmx_count
, "%s", buffer
);
2085 /* start our line */
2086 g_snprintf(buffer
, BUFFER_SIZE
, "001-%03d: ", perline
);
2087 buf_ptr
= buffer
+ 9;
2091 for (x
=data_offset
; x
<end_offset
; x
++) {
2092 level
= tvb_get_guint8(tvb
, x
);
2093 if (global_acn_dmx_display_view
==ACN_PREF_DMX_DISPLAY_PER
) {
2094 if ((level
> 0) && (level
< 3)) {
2097 level
= level
* 100 / 255;
2100 buf_ptr
= ltos(level
, buf_ptr
, base
, leading_char
, min_char
, global_acn_dmx_display_zeros
);
2104 if (item_cnt
== perline
|| x
== (end_offset
-1)) {
2106 proto_tree_add_text(pdu_tree
, tvb
, data_offset
, item_cnt
, "%s", buffer
);
2107 data_offset
+= perline
;
2108 g_snprintf(buffer
, BUFFER_SIZE
, "%03d-%03d: ",total_cnt
, total_cnt
+perline
);
2109 buf_ptr
= buffer
+ 9;
2112 /* add separator character */
2113 if (item_cnt
== halfline
) {
2121 address data type (fixed at 0xA2)
2122 start code - 1 byte, reserved (should be 0)
2123 - 1 byte, start code (0x255)
2124 - 2 bytes, packet offset (should be 0000)
2125 address increment - 4 bytes (ignore)
2126 number of dmx values - 4 bytes (0-512)
2127 dmx values 0-512 bytes (data)
2132 return pdu_start
+ pdu_length
;
2137 /******************************************************************************/
2138 /* Dissect DMX Base PDU */
2140 dissect_acn_dmx_pdu(guint32 protocol_id
, tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, acn_pdu_offsets
*last_pdu_offsets
)
2142 /* common to all pdu */
2146 guint32 pdu_flvh_length
; /* flags, length, vector, header */
2147 acn_pdu_offsets pdu_offsets
= {0,0,0,0,0};
2149 guint8 option_flags
;
2153 guint32 vector_offset
;
2154 guint32 data_offset
;
2155 guint32 data_length
;
2157 proto_item
*ti
, *pi
;
2158 proto_tree
*pdu_tree
= NULL
;
2159 proto_tree
*flag_tree
= NULL
;
2170 /* save start of pdu block */
2172 pdu_offsets
.start
= pdu_start
;
2174 /* get PDU flags and length flag first */
2175 octet
= tvb_get_guint8(tvb
, offset
++);
2176 pdu_flags
= octet
& 0xf0;
2177 length1
= octet
& 0x0f; /* bottom 4 bits only */
2178 length2
= tvb_get_guint8(tvb
, offset
++);
2180 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2181 /* flvh = flags, length, vector, header */
2182 if (pdu_flags
& ACN_PDU_FLAG_L
) {
2183 length3
= tvb_get_guint8(tvb
, offset
);
2185 pdu_length
= length3
| (length2
<< 8) | (length1
<< 16);
2186 pdu_flvh_length
= 3;
2188 pdu_length
= length2
| (length1
<< 8);
2189 pdu_flvh_length
= 2;
2192 /* offset should now be pointing to vector (if one exists) */
2194 /* Add pdu item and tree */
2195 ti
= proto_tree_add_item(tree
, hf_acn_pdu
, tvb
, pdu_start
, pdu_length
, ENC_NA
);
2196 pdu_tree
= proto_item_add_subtree(ti
, ett_acn_dmx_pdu
);
2198 /* Add flag item and tree */
2199 pi
= proto_tree_add_uint(pdu_tree
, hf_acn_pdu_flags
, tvb
, pdu_start
, 1, pdu_flags
);
2200 flag_tree
= proto_item_add_subtree(pi
, ett_acn_pdu_flags
);
2201 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_l
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2202 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_v
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2203 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_h
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2204 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_d
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2206 /* Add PDU Length item */
2207 proto_tree_add_uint(pdu_tree
, hf_acn_pdu_length
, tvb
, pdu_start
, pdu_flvh_length
, pdu_length
);
2209 /* Set vector offset */
2210 if (pdu_flags
& ACN_PDU_FLAG_V
) {
2211 /* use new values */
2212 vector_offset
= offset
;
2213 last_pdu_offsets
->vector
= offset
;
2215 pdu_flvh_length
+= 4;
2217 /* use last values */
2218 vector_offset
= last_pdu_offsets
->vector
;
2220 /* offset should now be pointing to header (if one exists) */
2222 /* Add Vector item */
2223 vector
= tvb_get_ntohl(tvb
, vector_offset
);
2224 proto_tree_add_item(pdu_tree
, hf_acn_dmx_vector
, tvb
, vector_offset
, 4, ENC_BIG_ENDIAN
);
2225 /* vector_offset +=4; */
2227 /* Add Vector item to tree*/
2228 name
= val_to_str(vector
, acn_dmx_vector_vals
, "not valid (%d)");
2229 proto_item_append_text(ti
, ": %s", name
);
2231 /* NO HEADER DATA ON THESE* (at least so far) */
2234 if (pdu_flags
& ACN_PDU_FLAG_D
) {
2235 /* use new values */
2236 data_offset
= offset
;
2237 data_length
= pdu_length
- pdu_flvh_length
;
2238 last_pdu_offsets
->data
= offset
;
2239 last_pdu_offsets
->data_length
= data_length
;
2241 /* use last values */
2242 data_offset
= last_pdu_offsets
->data
;
2243 /*data_length = last_pdu_offsets->data_length;*/
2246 /* process based on vector */
2249 if (protocol_id
==ACN_PROTOCOL_ID_DMX_2
) {
2250 proto_tree_add_item(pdu_tree
, hf_acn_dmx_source_name
, tvb
, data_offset
, 64, ENC_UTF_8
|ENC_NA
);
2253 proto_tree_add_item(pdu_tree
, hf_acn_dmx_source_name
, tvb
, data_offset
, 32, ENC_UTF_8
|ENC_NA
);
2257 priority
= tvb_get_guint8(tvb
, data_offset
);
2258 proto_tree_add_item(pdu_tree
, hf_acn_dmx_priority
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
2261 if (protocol_id
==ACN_PROTOCOL_ID_DMX_2
) {
2262 proto_tree_add_item(pdu_tree
, hf_acn_dmx_2_reserved
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2266 sequence
= tvb_get_guint8(tvb
, data_offset
);
2267 proto_tree_add_item(pdu_tree
, hf_acn_dmx_sequence_number
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
2270 if (protocol_id
== ACN_PROTOCOL_ID_DMX_2
) {
2271 option_flags
= tvb_get_guint8(tvb
, data_offset
);
2272 pi
= proto_tree_add_uint(pdu_tree
, hf_acn_dmx_2_options
, tvb
, data_offset
, 1, option_flags
);
2273 flag_tree
= proto_item_add_subtree(pi
, ett_acn_dmx_2_options
);
2274 proto_tree_add_item(flag_tree
, hf_acn_dmx_2_option_p
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
2275 proto_tree_add_item(flag_tree
, hf_acn_dmx_2_option_s
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
2279 universe
= tvb_get_ntohs(tvb
, data_offset
);
2280 proto_tree_add_item(pdu_tree
, hf_acn_dmx_universe
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2283 /* add universe to info */
2284 col_append_fstr(pinfo
->cinfo
,COL_INFO
, ", Universe %d, Seq %3d", universe
, sequence
);
2285 proto_item_append_text(ti
, ", Universe: %d, Priority: %d", universe
, priority
);
2287 /*data_offset =*/ dissect_acn_dmx_data_pdu(protocol_id
, tvb
, pinfo
, pdu_tree
, data_offset
, &pdu_offsets
);
2291 return pdu_start
+ pdu_length
;
2294 /******************************************************************************/
2295 /* Dissect SDT Base PDU */
2297 dissect_acn_sdt_base_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, acn_pdu_offsets
*last_pdu_offsets
)
2299 /* common to all pdu */
2303 guint32 pdu_flvh_length
; /* flags, length, vector, header */
2304 acn_pdu_offsets pdu_offsets
= {0,0,0,0,0};
2309 guint32 vector_offset
;
2310 guint32 data_offset
;
2313 guint32 data_length
;
2315 proto_item
*ti
, *pi
;
2316 proto_tree
*pdu_tree
= NULL
;
2317 proto_tree
*flag_tree
= NULL
;
2324 /* save start of pdu block */
2326 pdu_offsets
.start
= pdu_start
;
2328 /* get PDU flags and length flag first */
2329 octet
= tvb_get_guint8(tvb
, offset
++);
2330 pdu_flags
= octet
& 0xf0;
2331 length1
= octet
& 0x0f; /* bottom 4 bits only */
2332 length2
= tvb_get_guint8(tvb
, offset
++);
2334 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2335 /* flvh = flags, length, vector, header */
2336 if (pdu_flags
& ACN_PDU_FLAG_L
) {
2337 length3
= tvb_get_guint8(tvb
, offset
);
2339 pdu_length
= length3
| (length2
<< 8) | (length1
<< 16);
2340 pdu_flvh_length
= 3;
2342 pdu_length
= length2
| (length1
<< 8);
2343 pdu_flvh_length
= 2;
2345 /* offset should now be pointing to vector (if one exists) */
2347 /* Add pdu item and tree */
2348 ti
= proto_tree_add_item(tree
, hf_acn_pdu
, tvb
, pdu_start
, pdu_length
, ENC_NA
);
2349 pdu_tree
= proto_item_add_subtree(ti
, ett_acn_sdt_base_pdu
);
2351 /* Add flag item and tree */
2352 pi
= proto_tree_add_uint(pdu_tree
, hf_acn_pdu_flags
, tvb
, pdu_start
, 1, pdu_flags
);
2353 flag_tree
= proto_item_add_subtree(pi
, ett_acn_pdu_flags
);
2354 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_l
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2355 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_v
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2356 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_h
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2357 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_d
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2359 /* Add PDU Length item */
2360 proto_tree_add_uint(pdu_tree
, hf_acn_pdu_length
, tvb
, pdu_start
, pdu_flvh_length
, pdu_length
);
2362 /* Set vector offset */
2363 if (pdu_flags
& ACN_PDU_FLAG_V
) {
2364 /* use new values */
2365 vector_offset
= offset
;
2366 last_pdu_offsets
->vector
= offset
;
2370 /* use last values */
2371 vector_offset
= last_pdu_offsets
->vector
;
2373 /* offset should now be pointing to header (if one exists) */
2375 /* Add Vector item */
2376 vector
= tvb_get_guint8(tvb
, vector_offset
);
2377 proto_tree_add_uint(pdu_tree
, hf_acn_sdt_vector
, tvb
, vector_offset
, 1, vector
);
2379 /* Add Vector item to tree*/
2380 name
= val_to_str(vector
, acn_sdt_vector_vals
, "not valid (%d)");
2381 proto_item_append_text(ti
, ": ");
2382 proto_item_append_text(ti
, "%s", name
);
2384 /* NO HEADER DATA ON THESE* (at least so far) */
2387 if (pdu_flags
& ACN_PDU_FLAG_D
) {
2388 /* use new values */
2389 data_offset
= offset
;
2390 data_length
= pdu_length
- pdu_flvh_length
;
2391 last_pdu_offsets
->data
= offset
;
2392 last_pdu_offsets
->data_length
= data_length
;
2394 /* use last values */
2395 data_offset
= last_pdu_offsets
->data
;
2396 data_length
= last_pdu_offsets
->data_length
;
2398 end_offset
= data_offset
+ data_length
;
2400 /* process based on vector */
2402 case ACN_SDT_VECTOR_UNKNOWN
:
2404 case ACN_SDT_VECTOR_REL_WRAP
:
2405 case ACN_SDT_VECTOR_UNREL_WRAP
:
2406 proto_tree_add_item(pdu_tree
, hf_acn_channel_number
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2408 proto_tree_add_item(pdu_tree
, hf_acn_total_sequence_number
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2410 proto_tree_add_item(pdu_tree
, hf_acn_reliable_sequence_number
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2412 proto_tree_add_item(pdu_tree
, hf_acn_oldest_available_wrapper
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2414 proto_tree_add_item(pdu_tree
, hf_acn_first_memeber_to_ack
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2416 proto_tree_add_item(pdu_tree
, hf_acn_last_memeber_to_ack
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2418 proto_tree_add_item(pdu_tree
, hf_acn_mak_threshold
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2421 while (data_offset
< end_offset
) {
2422 old_offset
= data_offset
;
2423 data_offset
= dissect_acn_sdt_client_pdu(tvb
, pinfo
, pdu_tree
, data_offset
, &pdu_offsets
);
2424 if (data_offset
== old_offset
) break;
2427 case ACN_SDT_VECTOR_CHANNEL_PARAMS
:
2429 case ACN_SDT_VECTOR_JOIN
:
2430 proto_tree_add_item(pdu_tree
, hf_acn_cid
, tvb
, data_offset
, 16, ENC_BIG_ENDIAN
);
2432 proto_tree_add_item(pdu_tree
, hf_acn_member_id
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2434 proto_tree_add_item(pdu_tree
, hf_acn_channel_number
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2436 proto_tree_add_item(pdu_tree
, hf_acn_reciprocal_channel
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2438 proto_tree_add_item(pdu_tree
, hf_acn_total_sequence_number
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2440 proto_tree_add_item(pdu_tree
, hf_acn_reliable_sequence_number
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2442 data_offset
= acn_add_address(tvb
, pinfo
, pdu_tree
, data_offset
, "Destination Address:");
2443 data_offset
= acn_add_channel_parameter(tvb
, pinfo
, pdu_tree
, data_offset
);
2444 /*data_offset =*/ acn_add_expiry(tvb
, pinfo
, pdu_tree
, data_offset
, "Ad-hoc Expiry:");
2446 case ACN_SDT_VECTOR_JOIN_REFUSE
:
2447 pi
= proto_tree_add_item(pdu_tree
, hf_acn_cid
, tvb
, data_offset
, 16, ENC_BIG_ENDIAN
);
2449 proto_item_append_text(pi
, "(Leader)");
2450 proto_tree_add_item(pdu_tree
, hf_acn_channel_number
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2452 proto_tree_add_item(pdu_tree
, hf_acn_member_id
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2454 proto_tree_add_item(pdu_tree
, hf_acn_reliable_sequence_number
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2456 proto_tree_add_item(pdu_tree
, hf_acn_refuse_code
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
2459 case ACN_SDT_VECTOR_JOIN_ACCEPT
:
2460 pi
= proto_tree_add_item(pdu_tree
, hf_acn_cid
, tvb
, data_offset
, 16, ENC_BIG_ENDIAN
);
2462 proto_item_append_text(pi
, "(Leader)");
2463 proto_tree_add_item(pdu_tree
, hf_acn_channel_number
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2465 proto_tree_add_item(pdu_tree
, hf_acn_member_id
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2467 proto_tree_add_item(pdu_tree
, hf_acn_reliable_sequence_number
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2469 proto_tree_add_item(pdu_tree
, hf_acn_reciprocal_channel
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2470 /*data_offset += 2;*/
2472 case ACN_SDT_VECTOR_LEAVE
:
2474 case ACN_SDT_VECTOR_LEAVING
:
2475 pi
= proto_tree_add_item(pdu_tree
, hf_acn_cid
, tvb
, data_offset
, 16, ENC_BIG_ENDIAN
);
2477 proto_item_append_text(pi
, "(Leader)");
2478 proto_tree_add_item(pdu_tree
, hf_acn_channel_number
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2480 proto_tree_add_item(pdu_tree
, hf_acn_member_id
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2482 proto_tree_add_item(pdu_tree
, hf_acn_reliable_sequence_number
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2484 proto_tree_add_item(pdu_tree
, hf_acn_reason_code
, tvb
, data_offset
, 1, ENC_BIG_ENDIAN
);
2487 case ACN_SDT_VECTOR_CONNECT
:
2489 case ACN_SDT_VECTOR_CONNECT_ACCEPT
:
2491 case ACN_SDT_VECTOR_CONNECT_REFUSE
:
2493 case ACN_SDT_VECTOR_DISCONNECT
:
2495 case ACN_SDT_VECTOR_DISCONNECTING
:
2497 case ACN_SDT_VECTOR_ACK
:
2499 case ACN_SDT_VECTOR_NAK
:
2500 pi
= proto_tree_add_item(pdu_tree
, hf_acn_cid
, tvb
, data_offset
, 16, ENC_BIG_ENDIAN
);
2502 proto_item_append_text(pi
, "(Leader)");
2503 proto_tree_add_item(pdu_tree
, hf_acn_channel_number
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2505 proto_tree_add_item(pdu_tree
, hf_acn_member_id
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2507 proto_tree_add_item(pdu_tree
, hf_acn_reliable_sequence_number
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2509 proto_tree_add_item(pdu_tree
, hf_acn_first_missed_sequence
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2511 proto_tree_add_item(pdu_tree
, hf_acn_last_missed_sequence
, tvb
, data_offset
, 4, ENC_BIG_ENDIAN
);
2512 /*data_offset += 4;*/
2514 case ACN_SDT_VECTOR_GET_SESSION
:
2515 proto_tree_add_item(pdu_tree
, hf_acn_cid
, tvb
, data_offset
, 16, ENC_BIG_ENDIAN
);
2516 /*data_offset += 16;*/
2518 case ACN_SDT_VECTOR_SESSIONS
:
2519 member_id
= tvb_get_ntohs(tvb
, data_offset
);
2520 switch (member_id
) {
2522 /*data_offset =*/ acn_add_channel_owner_info_block(tvb
, pinfo
, pdu_tree
, data_offset
);
2525 /*data_offset =*/ acn_add_channel_member_info_block(tvb
, pinfo
, pdu_tree
, data_offset
);
2531 return pdu_start
+ pdu_length
;
2534 /******************************************************************************/
2535 /* Dissect Root PDU */
2537 dissect_acn_root_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, acn_pdu_offsets
*last_pdu_offsets
)
2539 /* common to all pdu */
2543 guint32 pdu_flvh_length
; /* flags, length, vector, header */
2544 acn_pdu_offsets pdu_offsets
= {0,0,0,0,0};
2549 guint32 vector_offset
;
2550 guint32 header_offset
;
2551 guint32 data_offset
;
2554 guint32 data_length
;
2556 proto_item
*ti
, *pi
;
2557 proto_tree
*pdu_tree
= NULL
;
2558 proto_tree
*flag_tree
= NULL
;
2561 guint32 protocol_id
;
2564 /* save start of pdu block */
2566 pdu_offsets
.start
= pdu_start
;
2568 /* get PDU flags and length flag first */
2569 octet
= tvb_get_guint8(tvb
, offset
++);
2570 pdu_flags
= octet
& 0xf0;
2571 length1
= octet
& 0x0f; /* bottom 4 bits only */
2572 length2
= tvb_get_guint8(tvb
, offset
++);
2574 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2575 /* flvh = flags, length, vector, header */
2576 if (pdu_flags
& ACN_PDU_FLAG_L
) {
2577 length3
= tvb_get_guint8(tvb
, offset
);
2579 pdu_length
= length3
| (length2
<< 8) | (length1
<< 16);
2580 pdu_flvh_length
= 3;
2582 pdu_length
= length2
| (length1
<< 8);
2583 pdu_flvh_length
= 2;
2585 /* offset should now be pointing to vector (if one exists) */
2587 /* Add pdu item and tree */
2588 ti
= proto_tree_add_item(tree
, hf_acn_pdu
, tvb
, pdu_start
, pdu_length
, ENC_NA
);
2589 pdu_tree
= proto_item_add_subtree(ti
, ett_acn_root_pdu
);
2591 /* Add flag item and tree */
2592 pi
= proto_tree_add_uint(pdu_tree
, hf_acn_pdu_flags
, tvb
, pdu_start
, 1, pdu_flags
);
2593 flag_tree
= proto_item_add_subtree(pi
, ett_acn_pdu_flags
);
2594 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_l
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2595 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_v
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2596 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_h
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2597 proto_tree_add_item(flag_tree
, hf_acn_pdu_flag_d
, tvb
, pdu_start
, 1, ENC_BIG_ENDIAN
);
2599 /* Add PDU Length item */
2600 proto_tree_add_uint(pdu_tree
, hf_acn_pdu_length
, tvb
, pdu_start
, pdu_flvh_length
, pdu_length
);
2602 /* Set vector offset */
2603 if (pdu_flags
& ACN_PDU_FLAG_V
) {
2604 /* use new values */
2605 vector_offset
= offset
;
2606 last_pdu_offsets
->vector
= offset
;
2608 pdu_flvh_length
+= 4;
2610 /* use last values */
2611 vector_offset
= last_pdu_offsets
->vector
;
2613 /* offset should now be pointing to header (if one exists) */
2617 /* Get Protocol ID (vector) */
2618 protocol_id
= tvb_get_ntohl(tvb
, vector_offset
);
2619 proto_tree_add_uint(pdu_tree
, hf_acn_protocol_id
, tvb
, vector_offset
, 4, protocol_id
);
2621 /* process based on protocol_id */
2622 switch (protocol_id
) {
2623 case ACN_PROTOCOL_ID_DMX
:
2624 case ACN_PROTOCOL_ID_DMX_2
:
2625 if (global_acn_dmx_enable
) {
2626 proto_item_append_text(ti
,": Root DMX");
2628 /* Set header offset */
2629 if (pdu_flags
& ACN_PDU_FLAG_H
) {
2630 /* use new values */
2631 header_offset
= offset
;
2632 last_pdu_offsets
->header
= offset
;
2634 pdu_flvh_length
+= 16;
2636 /* use last values */
2637 header_offset
= last_pdu_offsets
->header
;
2639 /* offset should now be pointing to data (if one exists) */
2641 /* get Header (CID) 16 bytes */
2642 tvb_get_guid(tvb
, header_offset
, &guid
, ENC_BIG_ENDIAN
);
2643 proto_item_append_text(ti
, ", Src: %s", guid_to_str(&guid
));
2645 /* add cid to info */
2646 col_add_fstr(pinfo
->cinfo
,COL_INFO
, "CID %s", guid_to_str(&guid
));
2648 proto_tree_add_item(pdu_tree
, hf_acn_cid
, tvb
, header_offset
, 16, ENC_BIG_ENDIAN
);
2649 /*header_offset += 16;*/
2652 if (pdu_flags
& ACN_PDU_FLAG_D
) {
2653 /* use new values */
2654 data_offset
= offset
;
2655 data_length
= pdu_length
- pdu_flvh_length
;
2656 last_pdu_offsets
->data
= offset
;
2657 last_pdu_offsets
->data_length
= data_length
;
2659 /* use last values */
2660 data_offset
= last_pdu_offsets
->data
;
2661 data_length
= last_pdu_offsets
->data_length
;
2663 end_offset
= data_offset
+ data_length
;
2665 /* adjust for what we used */
2666 while (data_offset
< end_offset
) {
2667 old_offset
= data_offset
;
2668 data_offset
= dissect_acn_dmx_pdu(protocol_id
, tvb
, pinfo
, pdu_tree
, data_offset
, &pdu_offsets
);
2669 if (data_offset
== old_offset
) break;
2673 case ACN_PROTOCOL_ID_SDT
:
2675 proto_item_append_text(ti
,": Root SDT");
2677 /* Set header offset */
2678 if (pdu_flags
& ACN_PDU_FLAG_H
) {
2679 /* use new values */
2680 header_offset
= offset
;
2681 last_pdu_offsets
->header
= offset
;
2683 pdu_flvh_length
+= 16;
2685 /* use last values */
2686 header_offset
= last_pdu_offsets
->header
;
2688 /* offset should now be pointing to data (if one exists) */
2690 /* get Header (CID) 16 bytes */
2691 tvb_get_guid(tvb
, header_offset
, &guid
, ENC_BIG_ENDIAN
);
2692 proto_item_append_text(ti
, ", Src: %s", guid_to_str(&guid
));
2694 proto_tree_add_item(pdu_tree
, hf_acn_cid
, tvb
, header_offset
, 16, ENC_BIG_ENDIAN
);
2695 /*header_offset += 16;*/
2698 if (pdu_flags
& ACN_PDU_FLAG_D
) {
2699 /* use new values */
2700 data_offset
= offset
;
2701 data_length
= pdu_length
- pdu_flvh_length
;
2702 last_pdu_offsets
->data
= offset
;
2703 last_pdu_offsets
->data_length
= data_length
;
2705 /* use last values */
2706 data_offset
= last_pdu_offsets
->data
;
2707 data_length
= last_pdu_offsets
->data_length
;
2709 end_offset
= data_offset
+ data_length
;
2711 /* adjust for what we used */
2712 while (data_offset
< end_offset
) {
2713 old_offset
= data_offset
;
2714 data_offset
= dissect_acn_sdt_base_pdu(tvb
, pinfo
, pdu_tree
, data_offset
, &pdu_offsets
);
2715 if (data_offset
== old_offset
) break;
2720 return pdu_start
+ pdu_length
;
2723 /******************************************************************************/
2726 dissect_acn(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
2728 proto_item
*ti
= NULL
;
2729 proto_tree
*acn_tree
= NULL
;
2730 guint32 data_offset
= 0;
2733 acn_pdu_offsets pdu_offsets
= {0,0,0,0,0};
2735 /* if (!is_acn(tvb)) { */
2739 /* Set the protocol column */
2740 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ACN");
2742 col_add_fstr(pinfo
->cinfo
,COL_INFO
, "ACN [Src Port: %d, Dst Port: %d]", pinfo
->srcport
, pinfo
->destport
);
2744 if (tree
) { /* we are being asked for details */
2745 ti
= proto_tree_add_item(tree
, proto_acn
, tvb
, 0, -1, ENC_NA
);
2746 acn_tree
= proto_item_add_subtree(ti
, ett_acn
);
2748 /* add preamble, postamble and ACN Packet ID */
2749 proto_tree_add_item(acn_tree
, hf_acn_preamble_size
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2751 proto_tree_add_item(acn_tree
, hf_acn_postamble_size
, tvb
, data_offset
, 2, ENC_BIG_ENDIAN
);
2753 proto_tree_add_item(acn_tree
, hf_acn_packet_identifier
, tvb
, data_offset
, 12, ENC_UTF_8
|ENC_NA
);
2756 /* one past the last byte */
2757 end_offset
= data_offset
+ tvb_reported_length_remaining(tvb
, data_offset
);
2758 while (data_offset
< end_offset
) {
2759 old_offset
= data_offset
;
2760 data_offset
= dissect_acn_root_pdu(tvb
, pinfo
, acn_tree
, data_offset
, &pdu_offsets
);
2761 if (data_offset
== old_offset
) break;
2764 return tvb_length(tvb
);
2767 /******************************************************************************/
2768 /* Register protocol */
2770 proto_register_acn(void)
2772 static hf_register_info hf
[] = {
2773 /**************************************************************************/
2774 /* In alphabetical order */
2777 { &hf_acn_ip_address_type
,
2778 { "Addr Type", "acn.ip_address_type",
2779 FT_UINT8
, BASE_DEC
, VALS(acn_ip_address_type_vals
), 0x0,
2783 { &hf_acn_association
,
2784 { "Association", "acn.association",
2785 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2788 /* Channel Number */
2789 { &hf_acn_channel_number
,
2790 { "Channel Number", "acn.channel_number",
2791 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2797 FT_GUID
, BASE_NONE
, NULL
, 0x0,
2800 /* Client Protocol ID */
2802 { &hf_acn_client_protocol_id
,
2803 { "Client Protocol ID", "acn.client_protocol_id",
2804 FT_UINT32
, BASE_DEC
, VALS(acn_protocol_id_vals
), 0x0,
2810 { "Data", "acn.dmp_data",
2811 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2815 { "Addr", "acn.dmp_data8",
2816 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x0,
2820 { "Addr", "acn.dmp_data16",
2821 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2825 { "Addr", "acn.dmp_data24",
2826 FT_UINT24
, BASE_DEC_HEX
, NULL
, 0x0,
2830 { "Addr", "acn.dmp_data32",
2831 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
2835 /* DMP Address type*/
2838 { "Address and Data Type", "acn.dmp_adt",
2839 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x0,
2843 { &hf_acn_dmp_adt_a
,
2844 { "Size", "acn.dmp_adt_a",
2845 FT_UINT8
, BASE_DEC
, VALS(acn_dmp_adt_a_vals
), 0x03,
2848 { &hf_acn_dmp_adt_d
,
2849 { "Data Type", "acn.dmp_adt_d",
2850 FT_UINT8
, BASE_DEC
, VALS(acn_dmp_adt_d_vals
), 0x30,
2853 { &hf_acn_dmp_adt_r
,
2854 { "Relative", "acn.dmp_adt_r",
2855 FT_UINT8
, BASE_DEC
, VALS(acn_dmp_adt_r_vals
), 0x40,
2858 { &hf_acn_dmp_adt_v
,
2859 { "Virtual", "acn.dmp_adt_v",
2860 FT_UINT8
, BASE_DEC
, VALS(acn_dmp_adt_v_vals
), 0x80,
2863 { &hf_acn_dmp_adt_x
,
2864 { "Reserved", "acn.dmp_adt_x",
2865 FT_UINT8
, BASE_DEC
, NULL
, 0x0c,
2869 /* DMP Reason Code */
2870 { &hf_acn_dmp_reason_code
,
2871 { "Reason Code", "acn.dmp_reason_code",
2872 FT_UINT8
, BASE_DEC
, VALS(acn_dmp_reason_code_vals
), 0x0,
2877 { &hf_acn_dmp_vector
,
2878 { "DMP Vector", "acn.dmp_vector",
2879 FT_UINT8
, BASE_DEC
, VALS(acn_dmp_vector_vals
), 0x0,
2884 { "Expiry", "acn.expiry",
2885 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2888 /* First Member to ACK */
2889 { &hf_acn_first_memeber_to_ack
,
2890 { "First Member to ACK", "acn.first_member_to_ack",
2891 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2894 /* First Missed Sequence */
2895 { &hf_acn_first_missed_sequence
,
2896 { "First Missed Sequence", "acn.first_missed_sequence",
2897 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
2902 { "IPV4", "acn.ipv4",
2903 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
2908 { "IPV6", "acn.ipv6",
2909 FT_IPv6
, BASE_NONE
, NULL
, 0x0,
2912 /* Last Member to ACK */
2913 { &hf_acn_last_memeber_to_ack
,
2914 { "Last Member to ACK", "acn.last_member_to_ack",
2915 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2918 /* Last Missed Sequence */
2919 { &hf_acn_last_missed_sequence
,
2920 { "Last Missed Sequence", "acn.last_missed_sequence",
2921 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
2925 { &hf_acn_mak_threshold
,
2926 { "MAK Threshold", "acn.mak_threshold",
2927 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2931 { &hf_acn_member_id
,
2932 { "Member ID", "acn.member_id",
2933 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2937 { &hf_acn_nak_holdoff
,
2938 { "NAK holdoff (ms)", "acn.nak_holdoff",
2939 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2943 { &hf_acn_nak_max_wait
,
2944 { "NAK Max Wait (ms)", "acn.nak_max_wait",
2945 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2949 { &hf_acn_nak_modulus
,
2950 { "NAK Modulus", "acn.nak_modulus",
2951 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
2954 /* NAK Outbound Flag */
2955 { &hf_acn_nak_outbound_flag
,
2956 { "NAK Outbound Flag", "acn.nak_outbound_flag",
2957 FT_BOOLEAN
, 8, NULL
, 0x80,
2960 /* Oldest Available Wrapper */
2961 { &hf_acn_oldest_available_wrapper
,
2962 { "Oldest Available Wrapper", "acn.oldest_available_wrapper",
2963 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
2966 /* Preamble Sizet */
2967 { &hf_acn_preamble_size
,
2968 { "Size of preamble", "acn.preamble_size",
2969 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2970 "Preamble size in bytes", HFILL
}
2972 /* Packet Identifier */
2973 { &hf_acn_packet_identifier
,
2974 { "Packet Identifier", "acn.packet_identifier",
2975 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2981 FT_NONE
, BASE_NONE
, NULL
, 0x0,
2985 { &hf_acn_pdu_flags
,
2986 { "Flags", "acn.pdu.flags",
2987 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2988 "PDU Flags", HFILL
}
2990 { &hf_acn_pdu_flag_d
,
2991 { "Data", "acn.pdu.flag_d",
2992 FT_BOOLEAN
, 8, NULL
, ACN_PDU_FLAG_D
,
2993 "Data flag", HFILL
}
2995 { &hf_acn_pdu_flag_h
,
2996 { "Header", "acn.pdu.flag_h",
2997 FT_BOOLEAN
, 8, NULL
, ACN_PDU_FLAG_H
,
2998 "Header flag", HFILL
}
3000 { &hf_acn_pdu_flag_l
,
3001 { "Length", "acn.pdu.flag_l",
3002 FT_BOOLEAN
, 8, NULL
, ACN_PDU_FLAG_L
,
3003 "Length flag", HFILL
}
3005 { &hf_acn_pdu_flag_v
,
3006 { "Vector", "acn.pdu.flag_v",
3007 FT_BOOLEAN
, 8, NULL
, ACN_PDU_FLAG_V
,
3008 "Vector flag", HFILL
}
3011 { &hf_acn_pdu_length
,
3012 { "Length", "acn.pdu.length",
3013 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3014 "PDU Length", HFILL
}
3018 { "Port", "acn.port",
3019 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
3022 /* Postamble Size */
3023 { &hf_acn_postamble_size
,
3024 { "Size of postamble", "acn.postamble_size",
3025 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3026 "Postamble size in bytes", HFILL
}
3029 { &hf_acn_protocol_id
,
3030 { "Protocol ID", "acn.protocol_id",
3031 FT_UINT32
, BASE_DEC
, VALS(acn_protocol_id_vals
), 0x0,
3035 { &hf_acn_reason_code
,
3036 { "Reason Code", "acn.reason_code",
3037 FT_UINT8
, BASE_DEC
, VALS(acn_reason_code_vals
), 0x0,
3040 /* Reciprocal Channel */
3041 { &hf_acn_reciprocal_channel
,
3042 { "Reciprocal Channel Number", "acn.reciprocal_channel",
3043 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
3044 "Reciprocal Channel", HFILL
}
3047 { &hf_acn_refuse_code
,
3048 { "Refuse Code", "acn.refuse_code",
3049 FT_UINT8
, BASE_DEC
, VALS(acn_refuse_code_vals
), 0x0,
3052 /* Reliable Sequence Number */
3053 { &hf_acn_reliable_sequence_number
,
3054 { "Reliable Sequence Number", "acn.reliable_sequence_number",
3055 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
3059 { &hf_acn_sdt_vector
,
3060 { "STD Vector", "acn.sdt_vector",
3061 FT_UINT8
, BASE_DEC
, VALS(acn_sdt_vector_vals
), 0x0,
3066 { &hf_acn_dmx_vector
,
3067 { "Vector", "acn.dmx_vector",
3068 FT_UINT32
, BASE_DEC
, VALS(acn_dmx_vector_vals
), 0x0,
3069 "DMX Vector", HFILL
}
3071 /* DMX Source Name */
3072 { &hf_acn_dmx_source_name
,
3073 { "Source", "acn.dmx.source_name",
3074 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3075 "DMX Source Name", HFILL
}
3079 { &hf_acn_dmx_priority
,
3080 { "Priority", "acn.dmx.priority",
3081 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3082 "DMX Priority", HFILL
}
3085 /* DMX 2 reserved */
3086 { &hf_acn_dmx_2_reserved
,
3087 { "Reserved", "acn.dmx.reserved",
3088 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3089 "DMX Reserved", HFILL
}
3092 /* DMX Sequence number */
3093 { &hf_acn_dmx_sequence_number
,
3094 { "Seq No", "acn.dmx.seq_number",
3095 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3096 "DMX Sequence Number", HFILL
}
3100 { &hf_acn_dmx_2_options
,
3101 { "Options", "acn.dmx.options",
3102 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
3103 "DMX Options", HFILL
}
3106 { &hf_acn_dmx_2_option_p
,
3107 { "Preview Data", "acn.dmx.option_p",
3108 FT_BOOLEAN
, 8, NULL
, ACN_DMX_OPTION_P
,
3109 "Preview Data flag", HFILL
}
3112 { &hf_acn_dmx_2_option_s
,
3113 { "Stream Terminated", "acn.dmx.option_s",
3114 FT_BOOLEAN
, 8, NULL
, ACN_DMX_OPTION_S
,
3115 "Stream Terminated flag", HFILL
}
3119 { &hf_acn_dmx_universe
,
3120 { "Universe", "acn.dmx.universe",
3121 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3122 "DMX Universe", HFILL
}
3125 /* DMX Start Code */
3126 { &hf_acn_dmx_start_code
,
3127 { "Start Code", "acn.dmx.start_code",
3128 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
3129 "DMX Start Code", HFILL
}
3132 /* DMX 2 First Property Address */
3133 { &hf_acn_dmx_2_first_property_address
,
3134 { "First Property Address", "acn.dmx.start_code",
3135 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
3136 "DMX First Property Address", HFILL
}
3139 /* DMX Address Increment */
3140 { &hf_acn_dmx_increment
,
3141 { "Increment", "acn.dmx.increment",
3142 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3143 "DMX Increment", HFILL
}
3146 /* DMX Packet Count */
3147 { &hf_acn_dmx_count
,
3148 { "Count", "acn.dmx.count",
3149 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3150 "DMX Count", HFILL
}
3153 /* DMX 2 Start Code */
3154 { &hf_acn_dmx_2_start_code
,
3155 { "Start Code", "acn.dmx.start_code2",
3156 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x0,
3157 "DMX Start Code", HFILL
}
3162 { &hf_acn_session_count
,
3163 { "Session Count", "acn.session_count",
3164 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
3168 /* Total Sequence Number */
3169 { &hf_acn_total_sequence_number
,
3170 { "Total Sequence Number", "acn.total_sequence_number",
3171 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
3176 /* Setup protocol subtree array */
3177 static gint
*ett
[] = {
3179 &ett_acn_channel_owner_info_block
,
3180 &ett_acn_channel_member_info_block
,
3181 &ett_acn_channel_parameter
,
3183 &ett_acn_address_type
,
3187 &ett_acn_sdt_client_pdu
,
3188 &ett_acn_sdt_base_pdu
,
3190 &ett_acn_dmx_address
,
3191 &ett_acn_dmx_2_options
,
3192 &ett_acn_dmx_data_pdu
,
3196 module_t
*acn_module
;
3197 proto_acn
= proto_register_protocol (
3198 "Architecture for Control Networks", /* name */
3199 "ACN", /* short name */
3203 proto_register_field_array(proto_acn
, hf
, array_length(hf
));
3204 proto_register_subtree_array(ett
, array_length(ett
));
3206 acn_module
= prefs_register_protocol(proto_acn
, NULL
);
3207 prefs_register_bool_preference(acn_module
, "heuristic_acn",
3209 "Enable Architecture for Control Networks dissector (ANSI BSR E1.17)",
3212 prefs_register_bool_preference(acn_module
, "dmx_enable",
3214 "Enable Streaming DMX extension dissector (ANSI BSR E1.31)",
3215 &global_acn_dmx_enable
);
3217 prefs_register_enum_preference(acn_module
, "dmx_display_view",
3218 "DMX, display format",
3220 &global_acn_dmx_display_view
,
3224 prefs_register_bool_preference(acn_module
, "dmx_display_zeros",
3225 "DMX, display zeros",
3226 "Display zeros instead of dots",
3227 &global_acn_dmx_display_zeros
);
3229 prefs_register_bool_preference(acn_module
, "dmx_display_leading_zeros",
3230 "DMX, display leading zeros",
3231 "Display leading zeros on levels",
3232 &global_acn_dmx_display_leading_zeros
);
3234 prefs_register_enum_preference(acn_module
, "dmx_display_line_format",
3235 "DMX, display line format",
3236 "Display line format",
3237 &global_acn_dmx_display_line_format
,
3238 dmx_display_line_format
,
3243 /******************************************************************************/
3244 /* Register handoff */
3246 proto_reg_handoff_acn(void)
3248 /* dissector_handle_t acn_handle; */
3249 /* acn_handle = new_create_dissector_handle(dissect_acn, proto_acn); */
3250 /* dissector_add_handle("udp.port", acn_handle); */
3251 heur_dissector_add("udp", dissect_acn_heur
, proto_acn
);