2 * Routines for ACN packet disassembly
4 * Copyright (c) 2003 by Erwin Rol <erwin@erwinrol.com>
5 * Copyright (c) 2006 by Electronic Theatre Controls, Inc.
6 * Bill Florac <bflorac@etcconnect.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1999 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 Add reading of DDL files so we can futher explode DMP packets
30 For some of the Set/Get properties where we have a range of data
31 it would be better to show the block of data rather and
32 address-data pair on each line...
34 Build CID to "Name" table from file so we can display real names
44 #include <epan/packet.h>
45 #include <epan/prefs.h>
46 #include <epan/ipv6-utils.h>
47 #include <epan/to_str.h>
49 /* Forward declarations */
50 void proto_register_acn(void);
51 void proto_reg_handoff_acn(void);
54 #define ACN_PDU_FLAG_L 0x80
55 #define ACN_PDU_FLAG_V 0x40
56 #define ACN_PDU_FLAG_H 0x20
57 #define ACN_PDU_FLAG_D 0x10
59 #define ACN_DMX_OPTION_P 0x80
60 #define ACN_DMX_OPTION_S 0x40
62 #define ACN_DMP_ADT_FLAG_V 0x80 /* V = Specifies whether address is a virtual address or not. */
63 #define ACN_DMP_ADT_FLAG_R 0x40 /* R = Specifies whether address is relative to last valid address in packet or not. */
64 #define ACN_DMP_ADT_FLAG_D 0x30 /* D1, D0 = Specify non-range or range address, single data, equal size
65 or mixed size data array */
66 #define ACN_DMP_ADT_EXTRACT_D(f) (((f) & ACN_DMP_ADT_FLAG_D) >> 4)
68 #define ACN_DMP_ADT_FLAG_X 0x0c /* X1, X0 = These bits are reserved and their values shall be set to 0
69 when encoded. Their values shall be ignored when decoding. */
71 #define ACN_DMP_ADT_FLAG_A 0x03 /* A1, A0 = Size of Address elements */
72 #define ACN_DMP_ADT_EXTRACT_A(f) ((f) & ACN_DMP_ADT_FLAG_A)
74 #define ACN_DMP_ADT_V_VIRTUAL 0
75 #define ACN_DMP_ADT_V_ACTUAL 1
77 #define ACN_DMP_ADT_R_ABSOLUTE 0
78 #define ACN_DMP_ADT_R_RELATIVE 1
80 #define ACN_DMP_ADT_D_NS 0
81 #define ACN_DMP_ADT_D_RS 1
82 #define ACN_DMP_ADT_D_RE 2
83 #define ACN_DMP_ADT_D_RM 3
85 #define ACN_DMP_ADT_A_1 0
86 #define ACN_DMP_ADT_A_2 1
87 #define ACN_DMP_ADT_A_4 2
88 #define ACN_DMP_ADT_A_R 3
90 #define ACN_PROTOCOL_ID_SDT 1
91 #define ACN_PROTOCOL_ID_DMP 2
92 #define ACN_PROTOCOL_ID_DMX 3
93 #define ACN_PROTOCOL_ID_DMX_2 4
95 #define ACN_ADDR_NULL 0
96 #define ACN_ADDR_IPV4 1
97 #define ACN_ADDR_IPV6 2
98 #define ACN_ADDR_IPPORT 3
101 #define ACN_SDT_VECTOR_UNKNOWN 0
102 #define ACN_SDT_VECTOR_REL_WRAP 1
103 #define ACN_SDT_VECTOR_UNREL_WRAP 2
104 #define ACN_SDT_VECTOR_CHANNEL_PARAMS 3
105 #define ACN_SDT_VECTOR_JOIN 4
106 #define ACN_SDT_VECTOR_JOIN_REFUSE 5
107 #define ACN_SDT_VECTOR_JOIN_ACCEPT 6
108 #define ACN_SDT_VECTOR_LEAVE 7
109 #define ACN_SDT_VECTOR_LEAVING 8
110 #define ACN_SDT_VECTOR_CONNECT 9
111 #define ACN_SDT_VECTOR_CONNECT_ACCEPT 10
112 #define ACN_SDT_VECTOR_CONNECT_REFUSE 11
113 #define ACN_SDT_VECTOR_DISCONNECT 12
114 #define ACN_SDT_VECTOR_DISCONNECTING 13
115 #define ACN_SDT_VECTOR_ACK 14
116 #define ACN_SDT_VECTOR_NAK 15
117 #define ACN_SDT_VECTOR_GET_SESSION 16
118 #define ACN_SDT_VECTOR_SESSIONS 17
120 #define ACN_REFUSE_CODE_NONSPECIFIC 1
121 #define ACN_REFUSE_CODE_ILLEGAL_PARAMS 2
122 #define ACN_REFUSE_CODE_LOW_RESOURCES 3
123 #define ACN_REFUSE_CODE_ALREADY_MEMBER 4
124 #define ACN_REFUSE_CODE_BAD_ADDR_TYPE 5
125 #define ACN_REFUSE_CODE_NO_RECIP_CHAN 6
127 #define ACN_REASON_CODE_NONSPECIFIC 1
128 /*#define ACN_REASON_CODE_ 2 */
129 /*#define ACN_REASON_CODE_ 3 */
130 /*#define ACN_REASON_CODE_ 4 */
131 /*#define ACN_REASON_CODE_ 5 */
132 #define ACN_REASON_CODE_NO_RECIP_CHAN 6
133 #define ACN_REASON_CODE_CHANNEL_EXPIRED 7
134 #define ACN_REASON_CODE_LOST_SEQUENCE 8
135 #define ACN_REASON_CODE_SATURATED 9
136 #define ACN_REASON_CODE_TRANS_ADDR_CHANGING 10
137 #define ACN_REASON_CODE_ASKED_TO_LEAVE 11
138 #define ACN_REASON_CODE_NO_RECIPIENT 12
140 #define ACN_DMP_VECTOR_UNKNOWN 0
141 #define ACN_DMP_VECTOR_GET_PROPERTY 1
142 #define ACN_DMP_VECTOR_SET_PROPERTY 2
143 #define ACN_DMP_VECTOR_GET_PROPERTY_REPLY 3
144 #define ACN_DMP_VECTOR_EVENT 4
145 #define ACN_DMP_VECTOR_MAP_PROPERTY 5
146 #define ACN_DMP_VECTOR_UNMAP_PROPERTY 6
147 #define ACN_DMP_VECTOR_SUBSCRIBE 7
148 #define ACN_DMP_VECTOR_UNSUBSCRIBE 8
149 #define ACN_DMP_VECTOR_GET_PROPERTY_FAIL 9
150 #define ACN_DMP_VECTOR_SET_PROPERTY_FAIL 10
151 #define ACN_DMP_VECTOR_MAP_PROPERTY_FAIL 11
152 #define ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT 12
153 #define ACN_DMP_VECTOR_SUBSCRIBE_REJECT 13
154 #define ACN_DMP_VECTOR_ALLOCATE_MAP 14
155 #define ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY 15
156 #define ACN_DMP_VECTOR_DEALLOCATE_MAP 16
158 #define ACN_DMP_REASON_CODE_NONSPECIFIC 1
159 #define ACN_DMP_REASON_CODE_NOT_A_PROPERTY 2
160 #define ACN_DMP_REASON_CODE_WRITE_ONLY 3
161 #define ACN_DMP_REASON_CODE_NOT_WRITABLE 4
162 #define ACN_DMP_REASON_CODE_DATA_ERROR 5
163 #define ACN_DMP_REASON_CODE_MAPS_NOT_SUPPORTED 6
164 #define ACN_DMP_REASON_CODE_SPACE_NOT_AVAILABLE 7
165 #define ACN_DMP_REASON_CODE_PROP_NOT_MAPPABLE 8
166 #define ACN_DMP_REASON_CODE_MAP_NOT_ALLOCATED 9
167 #define ACN_DMP_REASON_CODE_SUBSCRIPTION_NOT_SUPPORTED 10
168 #define ACN_DMP_REASON_CODE_NO_SUBSCRIPTIONS_SUPPORTED 11
170 #define ACN_DMX_VECTOR 2
172 #define ACN_PREF_DMX_DISPLAY_HEX 0
173 #define ACN_PREF_DMX_DISPLAY_DEC 1
174 #define ACN_PREF_DMX_DISPLAY_PER 2
176 #define ACN_PREF_DMX_DISPLAY_20PL 0
177 #define ACN_PREF_DMX_DISPLAY_16PL 1
191 guint32 address; /* or first address */
200 * ANSI BSR E1.17 Architecture for Control Networks
204 #define ACTUAL_ADDRESS 0
205 /* forward reference */
206 static guint32 acn_add_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label);
207 static int dissect_acn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
209 /* Global variables */
210 static int proto_acn = -1;
211 static gint ett_acn = -1;
212 static gint ett_acn_channel_owner_info_block = -1;
213 static gint ett_acn_channel_member_info_block = -1;
214 static gint ett_acn_channel_parameter = -1;
215 static gint ett_acn_address = -1;
216 static gint ett_acn_address_type = -1;
217 static gint ett_acn_pdu_flags = -1;
218 static gint ett_acn_dmp_pdu = -1;
219 static gint ett_acn_sdt_pdu = -1;
220 static gint ett_acn_sdt_client_pdu = -1;
221 static gint ett_acn_sdt_base_pdu = -1;
222 static gint ett_acn_root_pdu = -1;
223 static gint ett_acn_dmx_address = -1;
224 static gint ett_acn_dmx_2_options = -1;
225 static gint ett_acn_dmx_data_pdu = -1;
226 static gint ett_acn_dmx_pdu = -1;
228 /* Register fields */
229 /* In alphabetical order */
230 static int hf_acn_association = -1;
231 static int hf_acn_channel_number = -1;
232 static int hf_acn_cid = -1;
233 /* static int hf_acn_client_protocol_id = -1; */
234 static int hf_acn_data = -1;
235 static int hf_acn_data8 = -1;
236 static int hf_acn_data16 = -1;
237 static int hf_acn_data24 = -1;
238 static int hf_acn_data32 = -1;
239 /* static int hf_acn_dmp_adt = -1; */ /* address and data type*/
240 static int hf_acn_dmp_adt_a = -1;
241 static int hf_acn_dmp_adt_v = -1;
242 static int hf_acn_dmp_adt_r = -1;
243 static int hf_acn_dmp_adt_d = -1;
244 static int hf_acn_dmp_adt_x = -1;
245 static int hf_acn_dmp_reason_code = -1;
246 static int hf_acn_dmp_vector = -1;
247 static int hf_acn_dmp_actual_address = -1;
248 static int hf_acn_dmp_virtual_address = -1;
249 static int hf_acn_dmp_actual_address_first = -1;
250 static int hf_acn_dmp_virtual_address_first = -1;
251 static int hf_acn_expiry = -1;
252 static int hf_acn_first_memeber_to_ack = -1;
253 static int hf_acn_first_missed_sequence = -1;
254 static int hf_acn_ip_address_type = -1;
255 static int hf_acn_ipv4 = -1;
256 static int hf_acn_ipv6 = -1;
257 static int hf_acn_last_memeber_to_ack = -1;
258 static int hf_acn_last_missed_sequence = -1;
259 static int hf_acn_mak_threshold = -1;
260 static int hf_acn_member_id = -1;
261 static int hf_acn_nak_holdoff = -1;
262 static int hf_acn_nak_max_wait = -1;
263 static int hf_acn_nak_modulus = -1;
264 static int hf_acn_nak_outbound_flag = -1;
265 static int hf_acn_oldest_available_wrapper = -1;
266 static int hf_acn_packet_identifier = -1;
267 static int hf_acn_pdu = -1;
268 static int hf_acn_pdu_flag_d = -1;
269 static int hf_acn_pdu_flag_h = -1;
270 static int hf_acn_pdu_flag_l = -1;
271 static int hf_acn_pdu_flag_v = -1;
272 static int hf_acn_pdu_flags = -1;
273 static int hf_acn_pdu_length = -1;
274 static int hf_acn_port = -1;
275 static int hf_acn_postamble_size = -1;
276 static int hf_acn_preamble_size = -1;
277 static int hf_acn_protocol_id = -1;
278 static int hf_acn_reason_code = -1;
279 static int hf_acn_reciprocal_channel = -1;
280 static int hf_acn_refuse_code = -1;
281 static int hf_acn_reliable_sequence_number = -1;
282 static int hf_acn_adhoc_expiry = -1;
283 /* static int hf_acn_sdt_pdu = -1; */
284 static int hf_acn_sdt_vector = -1;
285 static int hf_acn_dmx_vector = -1;
286 /* static int hf_acn_session_count = -1; */
287 static int hf_acn_total_sequence_number = -1;
288 static int hf_acn_dmx_source_name = -1;
289 static int hf_acn_dmx_priority = -1;
290 static int hf_acn_dmx_2_reserved = -1;
291 static int hf_acn_dmx_sequence_number = -1;
292 static int hf_acn_dmx_2_options = -1;
293 static int hf_acn_dmx_2_option_p = -1;
294 static int hf_acn_dmx_2_option_s = -1;
295 static int hf_acn_dmx_universe = -1;
297 static int hf_acn_dmx_start_code = -1;
298 static int hf_acn_dmx_2_first_property_address = -1;
299 static int hf_acn_dmx_increment = -1;
300 static int hf_acn_dmx_count = -1;
301 static int hf_acn_dmx_2_start_code = -1;
302 static int hf_acn_dmx_data = -1;
304 /* static int hf_acn_dmx_dmp_vector = -1; */
306 /* Try heuristic ACN decode */
307 static gboolean global_acn_heur = FALSE;
308 static gboolean global_acn_dmx_enable = FALSE;
309 static gint global_acn_dmx_display_view = 0;
310 static gint global_acn_dmx_display_line_format = 0;
311 static gboolean global_acn_dmx_display_zeros = FALSE;
312 static gboolean global_acn_dmx_display_leading_zeros = FALSE;
315 static const value_string acn_protocol_id_vals[] = {
316 { ACN_PROTOCOL_ID_SDT, "SDT Protocol" },
317 { ACN_PROTOCOL_ID_DMP, "DMP Protocol" },
318 { ACN_PROTOCOL_ID_DMX, "DMX Protocol" },
319 { ACN_PROTOCOL_ID_DMX_2, "Ratified DMX Protocol" },
323 static const value_string acn_dmp_adt_r_vals[] = {
329 static const value_string acn_dmp_adt_v_vals[] = {
335 static const value_string acn_dmp_adt_d_vals[] = {
336 { ACN_DMP_ADT_D_NS, "Non-range, single data item" },
337 { ACN_DMP_ADT_D_RS, "Range, single data item" },
338 { ACN_DMP_ADT_D_RE, "Range, array of equal size data items" },
339 { ACN_DMP_ADT_D_RM, "Range, series of mixed size data items" },
343 static const value_string acn_dmp_adt_a_vals[] = {
344 { ACN_DMP_ADT_A_1, "1 octet" },
345 { ACN_DMP_ADT_A_2, "2 octets" },
346 { ACN_DMP_ADT_A_4, "4 octets" },
347 { ACN_DMP_ADT_A_R, "reserved" },
352 static const value_string acn_sdt_vector_vals[] = {
353 {ACN_SDT_VECTOR_UNKNOWN, "Unknown"},
354 {ACN_SDT_VECTOR_REL_WRAP, "Reliable Wrapper"},
355 {ACN_SDT_VECTOR_UNREL_WRAP, "Unreliable Wrapper"},
356 {ACN_SDT_VECTOR_CHANNEL_PARAMS, "Channel Parameters"},
357 {ACN_SDT_VECTOR_JOIN, "Join"},
358 {ACN_SDT_VECTOR_JOIN_REFUSE, "Join Refuse"},
359 {ACN_SDT_VECTOR_JOIN_ACCEPT, "Join Accept"},
360 {ACN_SDT_VECTOR_LEAVE, "Leave"},
361 {ACN_SDT_VECTOR_LEAVING, "Leaving"},
362 {ACN_SDT_VECTOR_CONNECT, "Connect"},
363 {ACN_SDT_VECTOR_CONNECT_ACCEPT, "Connect Accept"},
364 {ACN_SDT_VECTOR_CONNECT_REFUSE, "Connect Refuse"},
365 {ACN_SDT_VECTOR_DISCONNECT, "Disconnect"},
366 {ACN_SDT_VECTOR_DISCONNECTING, "Disconnecting"},
367 {ACN_SDT_VECTOR_ACK, "Ack"},
368 {ACN_SDT_VECTOR_NAK, "Nak"},
369 {ACN_SDT_VECTOR_GET_SESSION, "Get Session"},
370 {ACN_SDT_VECTOR_SESSIONS, "Sessions"},
374 static const value_string acn_dmx_vector_vals[] = {
375 {ACN_DMX_VECTOR, "Streaming DMX"},
379 static const value_string acn_dmp_vector_vals[] = {
380 {ACN_DMP_VECTOR_UNKNOWN, "Unknown"},
381 {ACN_DMP_VECTOR_GET_PROPERTY, "Get Property"},
382 {ACN_DMP_VECTOR_SET_PROPERTY, "Set Property"},
383 {ACN_DMP_VECTOR_GET_PROPERTY_REPLY, "Get property reply"},
384 {ACN_DMP_VECTOR_EVENT, "Event"},
385 {ACN_DMP_VECTOR_MAP_PROPERTY, "Map Property"},
386 {ACN_DMP_VECTOR_UNMAP_PROPERTY, "Unmap Property"},
387 {ACN_DMP_VECTOR_SUBSCRIBE, "Subscribe"},
388 {ACN_DMP_VECTOR_UNSUBSCRIBE, "Unsubscribe"},
389 {ACN_DMP_VECTOR_GET_PROPERTY_FAIL, "Get Property Fail"},
390 {ACN_DMP_VECTOR_SET_PROPERTY_FAIL, "Set Property Fail"},
391 {ACN_DMP_VECTOR_MAP_PROPERTY_FAIL, "Map Property Fail"},
392 {ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT, "Subscribe Accept"},
393 {ACN_DMP_VECTOR_SUBSCRIBE_REJECT, "Subscribe Reject"},
394 {ACN_DMP_VECTOR_ALLOCATE_MAP, "Allocate Map"},
395 {ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY, "Allocate Map Reply"},
396 {ACN_DMP_VECTOR_DEALLOCATE_MAP, "Deallocate Map"},
400 static const value_string acn_ip_address_type_vals[] = {
401 { ACN_ADDR_NULL, "Null"},
402 { ACN_ADDR_IPV4, "IPv4"},
403 { ACN_ADDR_IPV6, "IPv6"},
404 { ACN_ADDR_IPPORT, "Port"},
408 static const value_string acn_refuse_code_vals[] = {
409 { ACN_REFUSE_CODE_NONSPECIFIC, "Nonspecific" },
410 { ACN_REFUSE_CODE_ILLEGAL_PARAMS, "Illegal Parameters" },
411 { ACN_REFUSE_CODE_LOW_RESOURCES, "Low Resources" },
412 { ACN_REFUSE_CODE_ALREADY_MEMBER, "Already Member" },
413 { ACN_REFUSE_CODE_BAD_ADDR_TYPE, "Bad Address Type" },
414 { ACN_REFUSE_CODE_NO_RECIP_CHAN, "No Reciprocal Channel" },
418 static const value_string acn_reason_code_vals[] = {
419 { ACN_REASON_CODE_NONSPECIFIC, "Nonspecific" },
420 { ACN_REASON_CODE_NO_RECIP_CHAN, "No Reciprocal Channel" },
421 { ACN_REASON_CODE_CHANNEL_EXPIRED, "Channel Expired" },
422 { ACN_REASON_CODE_LOST_SEQUENCE, "Lost Sequence" },
423 { ACN_REASON_CODE_SATURATED, "Saturated" },
424 { ACN_REASON_CODE_TRANS_ADDR_CHANGING, "Transport Address Changing" },
425 { ACN_REASON_CODE_ASKED_TO_LEAVE, "Asked to Leave" },
426 { ACN_REASON_CODE_NO_RECIPIENT, "No Recipient"},
430 static const value_string acn_dmp_reason_code_vals[] = {
431 { ACN_DMP_REASON_CODE_NONSPECIFIC, "Nonspecific" },
432 { ACN_DMP_REASON_CODE_NOT_A_PROPERTY, "Not a Property" },
433 { ACN_DMP_REASON_CODE_WRITE_ONLY, "Write Only" },
434 { ACN_DMP_REASON_CODE_NOT_WRITABLE, "Not Writable" },
435 { ACN_DMP_REASON_CODE_DATA_ERROR, "Data Error" },
436 { ACN_DMP_REASON_CODE_MAPS_NOT_SUPPORTED, "Maps not Supported" },
437 { ACN_DMP_REASON_CODE_SPACE_NOT_AVAILABLE, "Space not Available" },
438 { ACN_DMP_REASON_CODE_PROP_NOT_MAPPABLE, "Property not Mappable"},
439 { ACN_DMP_REASON_CODE_MAP_NOT_ALLOCATED, "Map not Allocated"},
440 { ACN_DMP_REASON_CODE_SUBSCRIPTION_NOT_SUPPORTED, "Subscription not Supported"},
441 { ACN_DMP_REASON_CODE_NO_SUBSCRIPTIONS_SUPPORTED, "No Subscriptions Supported"},
445 static const enum_val_t dmx_display_view[] = {
446 { "hex" , "Hex ", ACN_PREF_DMX_DISPLAY_HEX },
447 { "decimal", "Decimal", ACN_PREF_DMX_DISPLAY_DEC },
448 { "percent", "Percent", ACN_PREF_DMX_DISPLAY_PER },
452 static const enum_val_t dmx_display_line_format[] = {
453 { "20 per line", "20 per line", ACN_PREF_DMX_DISPLAY_20PL },
454 { "16 per line", "16 per line", ACN_PREF_DMX_DISPLAY_16PL },
458 /******************************************************************************/
459 /* Test to see if it is an ACN Packet */
461 is_acn(tvbuff_t *tvb)
463 static const char acn_packet_id[] = "ASC-E1.17\0\0\0"; /* must be 12 bytes */
465 if (tvb_captured_length(tvb) < (4+sizeof(acn_packet_id)))
468 /* Check the bytes in octets 4 - 16 */
469 if (tvb_memeql(tvb, 4, acn_packet_id, sizeof(acn_packet_id)-1) != 0)
476 /******************************************************************************/
477 /* Heuristic dissector */
479 dissect_acn_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ )
481 /* This is a heuristic dissector, which means we get all the UDP
482 * traffic not sent to a known dissector and not claimed by
483 * a heuristic dissector called before us!
486 /* abort if not enabled! */
487 if (!global_acn_heur) return FALSE;
489 /* abort if it is NOT an ACN packet */
490 if (!is_acn(tvb)) return FALSE;
492 /* else, dissect it */
493 dissect_acn(tvb, pinfo, tree);
497 /******************************************************************************/
498 /* Adds tree branch for channel owner info block */
500 acn_add_channel_owner_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
503 proto_tree *this_tree;
504 guint32 session_count;
507 this_tree = proto_tree_add_subtree(tree, tvb, offset, 8, ett_acn_channel_owner_info_block, NULL,
508 "Channel Owner Info Block");
510 proto_tree_add_item(this_tree, hf_acn_member_id, tvb, offset, 2, ENC_BIG_ENDIAN);
512 proto_tree_add_item(this_tree, hf_acn_channel_number, tvb, offset, 2, ENC_BIG_ENDIAN);
514 offset += acn_add_address(tvb, pinfo, this_tree, offset, "Destination Address:");
515 offset += acn_add_address(tvb, pinfo, this_tree, offset, "Source Address:");
517 session_count = tvb_get_ntohs(tvb, offset);
518 for (x=0; x<session_count; x++) {
519 pi = proto_tree_add_item(this_tree, hf_acn_protocol_id, tvb, offset, 4, ENC_BIG_ENDIAN);
520 proto_item_append_text(pi, " #%d", x+1);
526 /******************************************************************************/
527 /* Adds tree branch for channel member info block */
529 acn_add_channel_member_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
532 proto_tree *this_tree;
533 guint32 session_count;
536 this_tree = proto_tree_add_subtree(tree, tvb, offset, 8, ett_acn_channel_member_info_block,
537 NULL, "Channel Member Info Block");
539 proto_tree_add_item(this_tree, hf_acn_member_id, tvb, offset, 2, ENC_BIG_ENDIAN);
541 proto_tree_add_item(this_tree, hf_acn_cid, tvb, offset, 16, ENC_BIG_ENDIAN);
543 proto_tree_add_item(this_tree, hf_acn_channel_number, tvb, offset, 2, ENC_BIG_ENDIAN);
545 offset += acn_add_address(tvb, pinfo, this_tree, offset, "Destination Address:");
546 offset += acn_add_address(tvb, pinfo, this_tree, offset, "Source Address:");
547 proto_tree_add_item(this_tree, hf_acn_reciprocal_channel, tvb, offset, 2, ENC_BIG_ENDIAN);
550 session_count = tvb_get_ntohs(tvb, offset);
551 for (x=0; x<session_count; x++) {
552 pi = proto_tree_add_item(this_tree, hf_acn_protocol_id, tvb, offset, 4, ENC_BIG_ENDIAN);
553 proto_item_append_text(pi, " #%d", x+1);
560 /******************************************************************************/
561 /* Add labeled expiry */
563 acn_add_expiry(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, int hf)
565 proto_tree_add_item(tree, hf, tvb, offset, 2, ENC_NA);
571 /******************************************************************************/
572 /* Adds tree branch for channel parameters */
574 acn_add_channel_parameter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
576 proto_tree *param_tree;
578 param_tree = proto_tree_add_subtree(tree, tvb, offset, 8, ett_acn_channel_parameter,
579 NULL, "Channel Parameter Block");
581 proto_tree_add_item(param_tree, hf_acn_expiry, tvb, offset, 1, ENC_BIG_ENDIAN);
583 proto_tree_add_item(param_tree, hf_acn_nak_outbound_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
585 proto_tree_add_item(param_tree, hf_acn_nak_holdoff, tvb, offset, 2, ENC_BIG_ENDIAN);
587 proto_tree_add_item(param_tree, hf_acn_nak_modulus, tvb, offset, 2, ENC_BIG_ENDIAN);
589 proto_tree_add_item(param_tree, hf_acn_nak_max_wait, tvb, offset, 2, ENC_BIG_ENDIAN);
591 return offset; /* bytes used */
595 /******************************************************************************/
596 /* Add an address tree */
598 acn_add_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label)
601 proto_tree *addr_tree = NULL;
602 guint8 ip_address_type;
607 struct e_in6_addr IPv6;
611 ip_address_type = tvb_get_guint8(tvb, offset);
613 switch (ip_address_type) {
615 proto_tree_add_item(tree, hf_acn_ip_address_type, tvb, offset, 1, ENC_BIG_ENDIAN);
619 /* Build tree and add type*/
620 addr_tree = proto_tree_add_subtree(tree, tvb, offset, 7, ett_acn_address, &pi, label);
621 proto_tree_add_item(addr_tree, hf_acn_ip_address_type, tvb, offset, 1, ENC_BIG_ENDIAN);
624 port = tvb_get_ntohs(tvb, offset);
625 proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, ENC_BIG_ENDIAN);
628 proto_tree_add_item(addr_tree, hf_acn_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
629 /* Append port and address to tree item */
630 IPv4 = tvb_get_ipv4(tvb, offset);
631 SET_ADDRESS(&addr, AT_IPv4, sizeof(IPv4), &IPv4);
632 proto_item_append_text(pi, " %s, Port %d", address_to_str(wmem_packet_scope(), &addr), port);
636 /* Build tree and add type*/
637 addr_tree = proto_tree_add_subtree(tree, tvb, offset, 19, ett_acn_address, &pi, label);
638 proto_tree_add_item(addr_tree, hf_acn_ip_address_type, tvb, offset, 1, ENC_BIG_ENDIAN);
641 port = tvb_get_ntohs(tvb, offset);
642 proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, ENC_BIG_ENDIAN);
645 proto_tree_add_item(addr_tree, hf_acn_ipv6, tvb, offset, 16, ENC_NA);
646 /* Append port and address to tree item */
647 tvb_get_ipv6(tvb, offset, &IPv6);
648 SET_ADDRESS(&addr, AT_IPv6, sizeof(struct e_in6_addr), &IPv6);
649 proto_item_append_text(pi, " %s, Port %d", address_to_str(wmem_packet_scope(), &addr), port);
652 case ACN_ADDR_IPPORT:
653 /* Build tree and add type*/
654 addr_tree = proto_tree_add_subtree(tree, tvb, offset, 3, ett_acn_address, &pi, label);
655 proto_tree_add_item(addr_tree, hf_acn_ip_address_type, tvb, offset, 1, ENC_BIG_ENDIAN);
658 port = tvb_get_ntohs(tvb, offset);
659 proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, ENC_BIG_ENDIAN);
660 /* Append port to tree item */
661 proto_item_append_text(pi, " %s Port %d", address_to_str(wmem_packet_scope(), &addr), port);
668 /******************************************************************************/
669 /* Adds tree branch for address type */
671 acn_add_dmp_address_type(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
673 proto_tree *this_tree;
677 /* header contains address and data type */
678 adt->flags = tvb_get_guint8(tvb, offset);
680 D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
681 name = val_to_str(D, acn_dmp_adt_d_vals, "not valid (%d)");
682 this_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_acn_address_type,
683 NULL, "Address and Data Type: %s", name);
685 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_v, tvb, offset, 1, adt->flags);
686 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_r, tvb, offset, 1, adt->flags);
687 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_d, tvb, offset, 1, adt->flags);
688 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_x, tvb, offset, 1, adt->flags);
689 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_a, tvb, offset, 1, adt->flags);
692 return offset; /* bytes used */
695 /******************************************************************************/
696 /* Add an dmp address */
698 acn_add_dmp_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
700 guint32 start_offset;
704 start_offset = offset;
706 D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
707 A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
710 case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
713 switch (A) { /* address */
714 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
715 adt->address = tvb_get_guint8(tvb, offset);
719 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
720 adt->address = tvb_get_ntohs(tvb, offset);
724 case ACN_DMP_ADT_A_4: /* Four octet address, (range: one octet address, increment, and count). */
725 adt->address = tvb_get_ntohl(tvb, offset);
729 default: /* and ACN_DMP_ADT_A_R (Four octet address, (range: four octet address, increment, and count)*/
731 } /* of switch (A) */
733 if (adt->flags & ACN_DMP_ADT_FLAG_V) {
734 proto_tree_add_uint(tree, hf_acn_dmp_virtual_address, tvb, start_offset, bytes_used, adt->address);
736 proto_tree_add_uint(tree, hf_acn_dmp_actual_address, tvb, start_offset, bytes_used, adt->address);
740 case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
742 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
743 adt->address = tvb_get_guint8(tvb, offset);
745 adt->increment = tvb_get_guint8(tvb, offset);
747 adt->count = tvb_get_guint8(tvb, offset);
751 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
752 adt->address = tvb_get_ntohs(tvb, offset);
754 adt->increment = tvb_get_ntohs(tvb, offset);
756 adt->count = tvb_get_ntohs(tvb, offset);
760 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
761 adt->address = tvb_get_ntohl(tvb, offset);
763 adt->increment = tvb_get_ntohl(tvb, offset);
765 adt->count = tvb_get_ntohl(tvb, offset);
769 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
771 } /* of switch (A) */
773 if (adt->flags & ACN_DMP_ADT_FLAG_V) {
774 proto_tree_add_uint_format_value(tree, hf_acn_dmp_virtual_address_first, tvb, start_offset, bytes_used,
775 adt->address, "0x%X, inc: %d, count: %d",
776 adt->address, adt->increment, adt->count);
778 proto_tree_add_uint_format_value(tree, hf_acn_dmp_actual_address_first, tvb, start_offset, bytes_used,
779 adt->address, "0x%X, inc: %d, count: %d",
780 adt->address, adt->increment, adt->count);
784 case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
786 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
787 adt->address = tvb_get_guint8(tvb, offset);
789 adt->increment = tvb_get_guint8(tvb, offset);
791 adt->count = tvb_get_guint8(tvb, offset);
795 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
796 adt->address = tvb_get_ntohs(tvb, offset);
798 adt->increment = tvb_get_ntohs(tvb, offset);
800 adt->count = tvb_get_ntohs(tvb, offset);
804 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
805 adt->address = tvb_get_ntohl(tvb, offset);
807 adt->increment = tvb_get_ntohl(tvb, offset);
809 adt->count = tvb_get_ntohl(tvb, offset);
813 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
815 } /* of switch (A) */
817 if (adt->flags & ACN_DMP_ADT_FLAG_V) {
818 proto_tree_add_uint_format_value(tree, hf_acn_dmp_virtual_address_first, tvb, start_offset, bytes_used,
819 adt->address, "0x%X, inc: %d, count: %d",
820 adt->address, adt->increment, adt->count);
822 proto_tree_add_uint_format_value(tree, hf_acn_dmp_actual_address_first, tvb, start_offset, bytes_used,
823 adt->address, "0x%X, inc: %d, count: %d",
824 adt->address, adt->increment, adt->count);
828 case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
830 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
831 adt->address = tvb_get_guint8(tvb, offset);
833 adt->increment = tvb_get_guint8(tvb, offset);
835 adt->count = tvb_get_guint8(tvb, offset);
839 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
840 adt->address = tvb_get_ntohs(tvb, offset);
842 adt->increment = tvb_get_ntohs(tvb, offset);
844 adt->count = tvb_get_ntohs(tvb, offset);
848 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
849 adt->address = tvb_get_ntohl(tvb, offset);
851 adt->increment = tvb_get_ntohl(tvb, offset);
853 adt->count = tvb_get_ntohl(tvb, offset);
857 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
859 } /* of switch (A) */
861 if (adt->flags & ACN_DMP_ADT_FLAG_V) {
862 proto_tree_add_uint_format_value(tree, hf_acn_dmp_virtual_address_first, tvb, start_offset, bytes_used,
863 adt->address, "0x%X, inc: %d, count: %d",
864 adt->address, adt->increment, adt->count);
866 proto_tree_add_uint_format_value(tree, hf_acn_dmp_actual_address_first, tvb, start_offset, bytes_used,
867 adt->address, "0x%X, inc: %d, count: %d",
868 adt->address, adt->increment, adt->count);
871 } /* of switch (D) */
877 /*******************************************************************************/
878 /* Display DMP Data */
879 #define BUFFER_SIZE 128
881 acn_add_dmp_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
886 guint32 data_address;
888 gchar buffer[BUFFER_SIZE];
890 guint32 ok_to_process = FALSE;
894 /* We would like to rip through Property Address-Data pairs */
895 /* but since we don't now how many there are nor how big the data size is, */
896 /* it not possible. So, we just show the whole thing as a block of date! */
898 /* There are a few exceptions however */
899 /* 1) if the address type is ACN_DMP_ADT_D_NS or ACN_DMP_ADT_D_RS and */
900 /* or ACN_DMP_ADT_D_RE */
901 /* then number of bytes is <= count + 4. Each value is at least one byte */
902 /* and another address/data pair is at least 4 bytes so if the remaining */
903 /* bytes is less than the count plus 4 then the remaining data */
904 /* must be all data */
906 /* 2) if the address type is ACN_DMP_ADT_D_RE and the number of bytes */
907 /* equals the number of bytes in remaining in the pdu then there is */
908 /* a 1 to one match */
910 D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
912 case ACN_DMP_ADT_D_NS:
913 case ACN_DMP_ADT_D_RS:
914 if (adt->data_length <= adt->count + 4) {
915 ok_to_process = TRUE;
918 case ACN_DMP_ADT_D_RE:
919 if (adt->count == 0) {
922 if (adt->data_length <= adt->count + 4) {
923 ok_to_process = TRUE;
928 if (!ok_to_process) {
929 data_size = adt->data_length;
930 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
932 proto_item_set_text(ti, "Data and more Address-Data Pairs (further dissection not possible)");
936 A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
939 case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
940 /* calculate data size */
941 data_size = adt->data_length;
942 data_address = adt->address;
945 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
946 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
948 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
949 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
951 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
952 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
954 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
961 data_value = tvb_get_guint8(tvb, offset);
962 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %2.2X", buffer, data_value);
965 data_value = tvb_get_ntohs(tvb, offset);
966 proto_tree_add_uint_format(tree, hf_acn_data16, tvb, offset, 2, data_value, "%s %4.4X", buffer, data_value);
969 data_value = tvb_get_ntoh24(tvb, offset);
970 proto_tree_add_uint_format(tree, hf_acn_data24, tvb, offset, 3, data_value, "%s %6.6X", buffer, data_value);
973 data_value = tvb_get_ntohl(tvb, offset);
974 proto_tree_add_uint_format(tree, hf_acn_data32, tvb, offset, 4, data_value, "%s %8.8X", buffer, data_value);
977 /* build string of values */
978 for (y=0; y<20 && y<data_size; y++) {
979 data_value = tvb_get_guint8(tvb, offset+y);
980 g_snprintf(buffer, BUFFER_SIZE, "%s %2.2X", buffer, data_value);
983 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
985 /* change the text */
986 proto_item_set_text(ti, "%s", buffer);
988 } /* of switch (data_size) */
992 case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
993 /* calculate data size */
994 data_size = adt->data_length;
995 data_address = adt->address;
997 for (x=0; x<adt->count; x++) {
999 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1000 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1002 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1003 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1005 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1006 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1008 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1012 switch (data_size) {
1014 data_value = tvb_get_guint8(tvb, offset);
1015 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %2.2X", buffer, data_value);
1018 data_value = tvb_get_ntohs(tvb, offset);
1019 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 2, data_value, "%s %4.4X", buffer, data_value);
1022 data_value = tvb_get_ntoh24(tvb, offset);
1023 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 3, data_value, "%s %6.6X", buffer, data_value);
1026 data_value = tvb_get_ntohl(tvb, offset);
1027 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 4, data_value, "%s %8.8X", buffer, data_value);
1030 /* build string of values */
1031 for (y=0; y<20 && y<data_size; y++) {
1032 data_value = tvb_get_guint8(tvb, offset+y);
1033 g_snprintf(buffer, BUFFER_SIZE, "%s %2.2X", buffer, data_value);
1036 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
1037 /* change the text */
1038 proto_item_set_text(ti, "%s", buffer);
1040 } /* of switch (data_size) */
1041 data_address += adt->increment;
1042 } /* of (x=0;x<adt->count;x++) */
1043 offset += data_size;
1046 case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
1047 /* calculate data size */
1048 data_size = adt->data_length / adt->count;
1049 data_address = adt->address;
1051 for (x=0; x<adt->count; x++) {
1053 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1054 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1056 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1057 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1059 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1060 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1062 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1066 switch (data_size) {
1068 data_value = tvb_get_guint8(tvb, offset);
1069 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %2.2X", buffer, data_value);
1072 data_value = tvb_get_ntohs(tvb, offset);
1073 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 2, data_value, "%s %4.4X", buffer, data_value);
1076 data_value = tvb_get_ntoh24(tvb, offset);
1077 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 3, data_value, "%s %6.6X", buffer, data_value);
1080 data_value = tvb_get_ntohl(tvb, offset);
1081 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 4, data_value, "%s %8.8X", buffer, data_value);
1084 /* build string of values */
1085 for (y=0; y<20 && y<data_size; y++) {
1086 data_value = tvb_get_guint8(tvb, offset+y);
1087 g_snprintf(buffer, BUFFER_SIZE, "%s %2.2X", buffer, data_value);
1090 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
1091 /* change the text */
1092 proto_item_set_text(ti, "%s", buffer);
1094 } /* of switch (data_size) */
1096 offset += data_size;
1097 data_address += adt->increment;
1098 } /* of (x=0;x<adt->count;x++) */
1101 case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
1102 data_size = adt->data_length;
1103 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
1104 offset += data_size;
1105 /* change the text */
1106 proto_item_set_text(ti, "Mixed size data items");
1108 } /* of switch (D) */
1113 /*******************************************************************************/
1114 /* Display DMP Reason codes */
1115 #define BUFFER_SIZE 128
1117 acn_add_dmp_reason_codes(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
1121 guint32 data_address;
1124 gchar buffer[BUFFER_SIZE];
1129 D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
1130 A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
1132 case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
1133 data_address = adt->address;
1135 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1136 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1138 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1139 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1141 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1142 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1144 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1149 data_value = tvb_get_guint8(tvb, offset);
1150 name = val_to_str(data_value, acn_dmp_reason_code_vals, "reason not valid (%d)");
1151 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, name);
1155 case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
1156 data_address = adt->address;
1157 for (x=0; x<adt->count; x++) {
1159 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1160 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1162 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1163 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1165 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1166 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1168 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1173 data_value = tvb_get_guint8(tvb, offset);
1174 name = val_to_str(data_value, acn_dmp_reason_code_vals, "reason not valid (%d)");
1175 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, name);
1177 data_address += adt->increment;
1178 } /* of (x=0;x<adt->count;x++) */
1182 case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
1183 case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
1184 data_address = adt->address;
1185 for (x=0; x<adt->count; x++) {
1187 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1188 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1190 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1191 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1193 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1194 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1196 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1200 data_value = tvb_get_guint8(tvb, offset);
1201 name = val_to_str(data_value, acn_dmp_reason_code_vals, "reason not valid (%d)");
1202 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, name);
1203 data_address += adt->increment;
1205 } /* of (x=0;x<adt->count;x++) */
1207 } /* of switch (D) */
1212 /******************************************************************************/
1213 /* Dissect wrapped SDT PDU */
1215 dissect_acn_dmp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
1217 /* common to all pdu */
1221 guint32 pdu_flvh_length; /* flags, length, vector, header */
1227 guint32 vector_offset;
1228 guint32 header_offset;
1229 guint32 data_offset;
1232 guint32 data_length;
1233 guint32 address_count;
1235 proto_item *ti, *pi;
1236 proto_tree *pdu_tree = NULL;
1237 proto_tree *flag_tree = NULL;
1241 acn_dmp_adt_type adt = {0,0,0,0,0,0};
1242 acn_dmp_adt_type adt2 = {0,0,0,0,0,0};
1245 /* save start of pdu block */
1248 /* get PDU flags and length flag first */
1249 octet = tvb_get_guint8(tvb, offset++);
1250 pdu_flags = octet & 0xf0;
1251 length1 = octet & 0x0f; /* bottom 4 bits only */
1252 length2 = tvb_get_guint8(tvb, offset++);
1254 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1255 /* flvh = flags, length, vector, header */
1256 if (pdu_flags & ACN_PDU_FLAG_L) {
1257 length3 = tvb_get_guint8(tvb, offset);
1259 pdu_length = length3 | (length2 << 8) | (length1 << 16);
1260 pdu_flvh_length = 3;
1262 pdu_length = length2 | (length1 << 8);
1263 pdu_flvh_length = 2;
1265 /* offset should now be pointing to vector (if one exists) */
1267 /* Add pdu item and tree */
1268 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
1269 pdu_tree = proto_item_add_subtree(ti, ett_acn_dmp_pdu);
1271 /* Add flag item and tree */
1272 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1273 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1274 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1275 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1276 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1277 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1279 /* Add PDU Length item */
1280 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1282 /* Set vector offset */
1283 if (pdu_flags & ACN_PDU_FLAG_V) {
1284 /* use new values */
1285 vector_offset = offset;
1286 last_pdu_offsets->vector = offset;
1290 /* use last values */
1291 vector_offset = last_pdu_offsets->vector;
1293 /* offset should now be pointing to header (if one exists) */
1295 /* Add Vector item */
1296 vector = tvb_get_guint8(tvb, vector_offset);
1297 proto_tree_add_uint(pdu_tree, hf_acn_dmp_vector, tvb, vector_offset, 1, vector);
1299 /* Add Vector item to tree*/
1300 name = val_to_str(vector, acn_dmp_vector_vals, "not valid (%d)");
1301 proto_item_append_text(ti, ": ");
1302 proto_item_append_text(ti, "%s", name);
1304 /* Set header offset */
1305 if (pdu_flags & ACN_PDU_FLAG_H) {
1306 /* use new values */
1307 header_offset = offset;
1308 last_pdu_offsets->header = offset;
1312 /* use last values */
1313 header_offset = last_pdu_offsets->header;
1315 /* offset should now be pointing to data (if one exists) */
1317 /* header contains address and data type */
1318 acn_add_dmp_address_type(tvb, pinfo, pdu_tree, header_offset, &adt);
1321 if (pdu_flags & ACN_PDU_FLAG_D) {
1322 /* use new values */
1323 data_offset = offset;
1324 data_length = pdu_length - pdu_flvh_length;
1325 last_pdu_offsets->data = offset;
1326 last_pdu_offsets->data_length = data_length;
1328 /* use last values */
1329 data_offset = last_pdu_offsets->data;
1330 data_length = last_pdu_offsets->data_length;
1332 end_offset = data_offset + data_length;
1335 case ACN_DMP_VECTOR_UNKNOWN:
1337 case ACN_DMP_VECTOR_GET_PROPERTY:
1338 /* Rip trough property address */
1339 while (data_offset < end_offset) {
1340 old_offset = data_offset;
1341 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1342 if (old_offset == data_offset) break;
1345 case ACN_DMP_VECTOR_SET_PROPERTY:
1346 /* Rip through Property Address-Data pairs */
1347 /* But, in reality, this generally won't work as we have know way of */
1348 /* calculating the next Address-Data pair */
1349 while (data_offset < end_offset) {
1350 old_offset = data_offset;
1351 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1352 if (old_offset == data_offset) break;
1354 adt.data_length = data_length - (data_offset - old_offset);
1355 old_offset = data_offset;
1356 data_offset = acn_add_dmp_data(tvb, pinfo, pdu_tree, data_offset, &adt);
1357 if (old_offset == data_offset) break;
1360 case ACN_DMP_VECTOR_GET_PROPERTY_REPLY:
1361 /* Rip through Property Address-Data pairs */
1362 /* But, in reality, this generally won't work as we have know way of */
1363 /* calculating the next Address-Data pair */
1364 while (data_offset < end_offset) {
1365 old_offset = data_offset;
1366 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1367 if (old_offset == data_offset) break;
1369 adt.data_length = data_length - (data_offset - old_offset);
1370 old_offset = data_offset;
1371 data_offset = acn_add_dmp_data(tvb, pinfo, pdu_tree, data_offset, &adt);
1372 if (old_offset == data_offset) break;
1375 case ACN_DMP_VECTOR_EVENT:
1376 /* Rip through Property Address-Data pairs */
1377 /* But, in reality, this generally won't work as we have know way of */
1378 /* calculating the next Address-Data pair */
1379 while (data_offset < end_offset) {
1380 old_offset = data_offset;
1381 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1382 if (old_offset == data_offset) break;
1384 adt.data_length = data_length - (data_offset - old_offset);
1385 old_offset = data_offset;
1386 data_offset = acn_add_dmp_data(tvb, pinfo, pdu_tree, data_offset, &adt);
1387 if (old_offset == data_offset) break;
1390 case ACN_DMP_VECTOR_MAP_PROPERTY:
1391 /* Virtual Address type */
1392 data_offset = acn_add_dmp_address_type(tvb, pinfo, pdu_tree, data_offset, &adt2);
1393 /* Rip through Actual-Virtual Address Pairs */
1394 while (data_offset < end_offset) {
1396 old_offset = data_offset;
1397 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1398 if (old_offset == data_offset) break;
1399 D = ACN_DMP_ADT_EXTRACT_D(adt.flags);
1401 case ACN_DMP_ADT_D_NS:
1404 case ACN_DMP_ADT_D_RS:
1407 case ACN_DMP_ADT_D_RE:
1408 address_count = adt.count;
1410 /*case ACN_DMP_ADT_D_RM: */
1413 return pdu_start + pdu_length;
1418 while (address_count > 0) {
1419 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt2);
1424 case ACN_DMP_VECTOR_UNMAP_PROPERTY:
1425 /* Rip trough Actaul Proptery Address */
1426 while (data_offset < end_offset) {
1427 old_offset = data_offset;
1428 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1429 if (old_offset == data_offset) break;
1432 case ACN_DMP_VECTOR_SUBSCRIBE:
1433 /* Rip trough Proptery Address */
1434 while (data_offset < end_offset) {
1435 old_offset = data_offset;
1436 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1437 if (old_offset == data_offset) break;
1440 case ACN_DMP_VECTOR_UNSUBSCRIBE:
1441 /* Rip trough Proptery Address */
1442 while (data_offset < end_offset) {
1443 old_offset = data_offset;
1444 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1445 if (old_offset == data_offset) break;
1448 case ACN_DMP_VECTOR_GET_PROPERTY_FAIL:
1449 /* Rip trough Address-Reason Code Pairs */
1450 while (data_offset < end_offset) {
1451 old_offset = data_offset;
1452 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1453 if (old_offset == data_offset) break;
1455 adt.data_length = data_length - (data_offset - old_offset);
1456 old_offset = data_offset;
1457 data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1458 if (old_offset == data_offset) break;
1461 case ACN_DMP_VECTOR_SET_PROPERTY_FAIL:
1462 /* Rip trough Address-Reason Code Pairs */
1463 while (data_offset < end_offset) {
1464 old_offset = data_offset;
1465 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1466 if (old_offset == data_offset) break;
1468 adt.data_length = data_length - (data_offset - old_offset);
1469 old_offset = data_offset;
1470 data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1471 if (old_offset == data_offset) break;
1474 case ACN_DMP_VECTOR_MAP_PROPERTY_FAIL:
1475 /* Rip trough Address-Reason Code Pairs */
1476 while (data_offset < end_offset) {
1477 old_offset = data_offset;
1478 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1479 if (old_offset == data_offset) break;
1481 adt.data_length = data_length - (data_offset - old_offset);
1482 old_offset = data_offset;
1483 data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1484 if (old_offset == data_offset) break;
1487 case ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT:
1488 /* Rip through Property Addrsses */
1489 while (data_offset < end_offset) {
1490 old_offset = data_offset;
1491 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1492 if (old_offset == data_offset) break;
1495 case ACN_DMP_VECTOR_SUBSCRIBE_REJECT:
1496 /* Rip trough Address-Reason Code Pairs */
1497 while (data_offset < end_offset) {
1498 old_offset = data_offset;
1499 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1500 if (old_offset == data_offset) break;
1502 adt.data_length = data_length - (data_offset - old_offset);
1503 old_offset = data_offset;
1504 data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1505 if (old_offset == data_offset) break;
1508 case ACN_DMP_VECTOR_ALLOCATE_MAP:
1509 /* No data for this */
1511 case ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY:
1512 /* Single reason code */
1513 proto_tree_add_item(pdu_tree, hf_acn_dmp_reason_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
1514 /* data_offset += 1; */
1515 case ACN_DMP_VECTOR_DEALLOCATE_MAP:
1516 /* No data for this */
1520 return pdu_start + pdu_length;
1524 /******************************************************************************/
1525 /* Dissect wrapped SDT PDU */
1527 dissect_acn_sdt_wrapped_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, acn_pdu_offsets *last_pdu_offsets)
1529 /* common to all pdu */
1533 guint32 pdu_flvh_length; /* flags, length, vector, header */
1538 guint32 vector_offset;
1539 guint32 data_offset;
1540 guint32 data_length;
1542 proto_item *ti, *pi;
1543 proto_tree *pdu_tree = NULL;
1544 proto_tree *flag_tree = NULL;
1550 /* save start of pdu block */
1553 /* get PDU flags and length flag first */
1554 octet = tvb_get_guint8(tvb, offset++);
1555 pdu_flags = octet & 0xf0;
1556 length1 = octet & 0x0f; /* bottom 4 bits only */
1557 length2 = tvb_get_guint8(tvb, offset++);
1559 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1560 /* flvh = flags, length, vector, header */
1561 if (pdu_flags & ACN_PDU_FLAG_L) {
1562 length3 = tvb_get_guint8(tvb, offset);
1564 pdu_length = length3 | (length2 << 8) | (length1 << 16);
1565 pdu_flvh_length = 3;
1567 pdu_length = length2 | (length1 << 8);
1568 pdu_flvh_length = 2;
1570 /* offset should now be pointing to vector (if one exists) */
1572 /* Add pdu item and tree */
1573 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
1574 pdu_tree = proto_item_add_subtree(ti, ett_acn_sdt_pdu);
1576 /* Add flag item and tree */
1577 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1578 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1579 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1580 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1581 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1582 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1584 /* Add PDU Length item */
1585 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1587 /* Set vector offset */
1588 if (pdu_flags & ACN_PDU_FLAG_V) {
1589 /* use new values */
1590 vector_offset = offset;
1591 last_pdu_offsets->vector = offset;
1595 /* use last values */
1596 vector_offset = last_pdu_offsets->vector;
1598 /* offset should now be pointing to header (if one exists) */
1600 /* Add Vector item */
1601 vector = tvb_get_guint8(tvb, vector_offset);
1602 proto_tree_add_uint(pdu_tree, hf_acn_sdt_vector, tvb, vector_offset, 1, vector);
1604 /* Add Vector item to tree*/
1605 name = val_to_str(vector, acn_sdt_vector_vals, "not valid (%d)");
1606 proto_item_append_text(ti, ": ");
1607 proto_item_append_text(ti, "%s", name);
1609 /* NO HEADER DATA ON THESE* (at least so far) */
1612 if (pdu_flags & ACN_PDU_FLAG_D) {
1613 /* use new values */
1614 data_offset = offset;
1615 data_length = pdu_length - pdu_flvh_length;
1616 last_pdu_offsets->data = offset;
1617 last_pdu_offsets->data_length = data_length;
1619 /* use last values */
1620 data_offset = last_pdu_offsets->data;
1621 /*data_length = last_pdu_offsets->data_length;*/
1625 case ACN_SDT_VECTOR_ACK:
1626 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1627 /*data_offset += 4;*/
1629 case ACN_SDT_VECTOR_CHANNEL_PARAMS:
1630 data_offset = acn_add_channel_parameter(tvb, pinfo, pdu_tree, data_offset);
1631 data_offset = acn_add_address(tvb, pinfo, pdu_tree, data_offset, "Ad-hoc Address:");
1632 /*data_offset =*/ acn_add_expiry(tvb, pinfo, pdu_tree, data_offset, hf_acn_adhoc_expiry);
1634 case ACN_SDT_VECTOR_LEAVE:
1637 case ACN_SDT_VECTOR_CONNECT:
1638 /* Protocol ID item */
1639 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1640 /*data_offset += 4;*/
1642 case ACN_SDT_VECTOR_CONNECT_ACCEPT:
1643 /* Protocol ID item */
1644 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1645 /*data_offset += 4;*/
1647 case ACN_SDT_VECTOR_CONNECT_REFUSE:
1648 /* Protocol ID item */
1649 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1651 proto_tree_add_item(pdu_tree, hf_acn_refuse_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
1652 /*data_offset += 1;*/
1654 case ACN_SDT_VECTOR_DISCONNECT:
1655 /* Protocol ID item */
1656 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1657 /*data_offset += 4;*/
1659 case ACN_SDT_VECTOR_DISCONNECTING:
1660 /* Protocol ID item */
1661 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1663 proto_tree_add_item(pdu_tree, hf_acn_reason_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
1664 /*data_offset += 1;*/
1669 return pdu_start + pdu_length;
1673 /******************************************************************************/
1674 /* Dissect SDT Client PDU */
1676 dissect_acn_sdt_client_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
1678 /* common to all pdu */
1682 guint32 pdu_flvh_length; /* flags, length, vector, header */
1683 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
1688 guint32 vector_offset;
1689 guint32 header_offset;
1690 guint32 data_offset;
1691 guint32 data_length;
1695 proto_item *ti, *pi;
1696 proto_tree *pdu_tree = NULL;
1697 proto_tree *flag_tree = NULL;
1702 guint32 protocol_id;
1703 guint16 association;
1705 /* save start of pdu block */
1707 pdu_offsets.start = pdu_start;
1709 /* get PDU flags and length flag first */
1710 octet = tvb_get_guint8(tvb, offset++);
1711 pdu_flags = octet & 0xf0;
1712 length1 = octet & 0x0f; /* bottom 4 bits only */
1713 length2 = tvb_get_guint8(tvb, offset++);
1715 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1716 /* flvh = flags, length, vector, header */
1717 if (pdu_flags & ACN_PDU_FLAG_L) {
1718 length3 = tvb_get_guint8(tvb, offset);
1720 pdu_length = length3 | (length2 << 8) | (length1 << 16);
1721 pdu_flvh_length = 3;
1723 pdu_length = length2 | (length1 << 8);
1724 pdu_flvh_length = 2;
1726 /* offset should now be pointing to vector (if one exists) */
1728 /* Add pdu item and tree */
1729 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
1730 pdu_tree = proto_item_add_subtree(ti, ett_acn_sdt_client_pdu);
1732 /* Add flag item and tree */
1733 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1734 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1735 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1736 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1737 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1738 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1740 /* Add PDU Length item */
1741 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1743 /* Set vector offset */
1744 if (pdu_flags & ACN_PDU_FLAG_V) {
1745 /* use new values */
1746 vector_offset = offset;
1747 last_pdu_offsets->vector = offset;
1749 pdu_flvh_length += 2;
1751 /* use last values */
1752 vector_offset = last_pdu_offsets->vector;
1754 /* offset should now be pointing to header (if one exists) */
1756 /* add Member ID item */
1757 member_id = tvb_get_ntohs(tvb, vector_offset);
1758 proto_tree_add_uint(pdu_tree, hf_acn_member_id, tvb, vector_offset, 2, member_id);
1760 /* Set header offset */
1761 if (pdu_flags & ACN_PDU_FLAG_H) {
1762 /* use new values */
1763 header_offset = offset;
1764 last_pdu_offsets->header = offset;
1766 pdu_flvh_length += 6;
1768 /* use last values */
1769 header_offset = last_pdu_offsets->header;
1771 /* offset should now be pointing to data (if one exists) */
1773 /* add Protocol ID item (Header)*/
1774 protocol_id = tvb_get_ntohl(tvb, header_offset);
1775 proto_tree_add_uint(pdu_tree, hf_acn_protocol_id, tvb, header_offset, 4, protocol_id);
1778 /* Add protocol to tree*/
1779 name = val_to_str(protocol_id, acn_protocol_id_vals, "id not valid (%d)");
1780 proto_item_append_text(ti, ": ");
1781 proto_item_append_text(ti, "%s", name);
1783 /* add association item */
1784 association = tvb_get_ntohs(tvb, header_offset);
1785 proto_tree_add_uint(pdu_tree, hf_acn_association, tvb, header_offset, 2, association);
1786 /*header_offset += 2;*/
1789 if (pdu_flags & ACN_PDU_FLAG_D) {
1790 /* use new values */
1791 data_offset = offset;
1792 data_length = pdu_length - pdu_flvh_length;
1793 last_pdu_offsets->data = offset;
1794 last_pdu_offsets->data_length = data_length;
1796 /* use last values */
1797 data_offset = last_pdu_offsets->data;
1798 data_length = last_pdu_offsets->data_length;
1800 end_offset = data_offset + data_length;
1802 switch (protocol_id) {
1803 case ACN_PROTOCOL_ID_SDT:
1804 while (data_offset < end_offset) {
1805 old_offset = data_offset;
1806 data_offset = dissect_acn_sdt_wrapped_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
1807 if (old_offset == data_offset) break;
1810 case ACN_PROTOCOL_ID_DMP:
1811 while (data_offset < end_offset) {
1812 old_offset = data_offset;
1813 data_offset = dissect_acn_dmp_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
1814 if (data_offset == old_offset) break;
1818 return pdu_start + pdu_length;
1822 /******************************************************************************/
1823 /* level to string (ascii) */
1824 /* level : 8 bit value */
1825 /* string : pointer to buffer to fill */
1826 /* leading_char: character to buffer left of digits */
1827 /* min_char : mininum number of characters (for filling, not including space)*/
1828 /* show_zero: show zeros or dots */
1829 /* also adds a space to right end */
1831 /* returns end of string */
1832 /* faster than printf() */
1834 ltos(guint8 level, gchar *string, guint8 base, gchar leading_char, guint8 min_chars, gboolean show_zero)
1838 if (base < 2 || base > 16) {
1842 /* deal with zeros */
1843 if ((level == 0) && (!show_zero)) {
1844 for (i=0; i<min_chars; i++) {
1853 /* do our convert, comes out backwards! */
1855 string[i++] = "0123456789ABCDEF"[level % base];
1856 } while ((level /= base) > 0);
1858 /* expand to needed character */
1859 for (; i<min_chars; i++) {
1860 string[i] = leading_char;
1865 /* now reverse (and correct) the order */
1866 g_strreverse(string);
1868 /* add a space at the end (ok it's at the start but it will be at the end)*/
1875 /******************************************************************************/
1876 /* Dissect DMX data PDU */
1877 #define BUFFER_SIZE 128
1879 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)
1881 /* common to all pdu */
1885 guint32 pdu_flvh_length; /* flags, length, vector, header */
1890 guint32 vector_offset;
1891 guint32 data_offset;
1893 guint32 data_length;
1894 guint32 header_offset;
1898 proto_item *ti, *pi;
1899 proto_tree *pdu_tree = NULL;
1900 proto_tree *flag_tree = NULL;
1901 /* proto_tree *addr_tree = NULL; */
1904 acn_dmp_adt_type adt = {0,0,0,0,0,0};
1907 gchar buffer[BUFFER_SIZE];
1917 guint16 dmx_start_code;
1921 /* save start of pdu block */
1924 /* get PDU flags and length flag first */
1925 octet = tvb_get_guint8(tvb, offset++);
1926 pdu_flags = octet & 0xf0;
1927 length1 = octet & 0x0f; /* bottom 4 bits only */
1928 length2 = tvb_get_guint8(tvb, offset++);
1930 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1931 /* flvh = flags, length, vector, header */
1932 if (pdu_flags & ACN_PDU_FLAG_L) {
1933 length3 = tvb_get_guint8(tvb, offset);
1935 pdu_length = length3 | (length2 << 8) | (length1 << 16);
1936 pdu_flvh_length = 3;
1938 pdu_length = length2 | (length1 << 8);
1939 pdu_flvh_length = 2;
1941 /* offset should now be pointing to vector (if one exists) */
1943 /* Add pdu item and tree */
1944 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
1945 pdu_tree = proto_item_add_subtree(ti, ett_acn_dmx_data_pdu);
1947 /* Add flag item and tree */
1948 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1949 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1950 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1951 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1952 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1953 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1955 /* Add PDU Length item */
1956 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1958 /* Set vector offset */
1959 if (pdu_flags & ACN_PDU_FLAG_V) {
1960 /* use new values */
1961 vector_offset = offset;
1962 last_pdu_offsets->vector = offset;
1964 pdu_flvh_length += 1;
1966 /* use last values */
1967 vector_offset = last_pdu_offsets->vector;
1969 /* offset should now be pointing to header (if one exists) */
1971 /* Add Vector item */
1972 vector = tvb_get_guint8(tvb, vector_offset);
1973 proto_tree_add_uint(pdu_tree, hf_acn_dmp_vector, tvb, vector_offset, 1, vector);
1975 /* Add Vector item to tree*/
1976 name = val_to_str(vector, acn_dmp_vector_vals, "not valid (%d)");
1977 proto_item_append_text(ti, ": ");
1978 proto_item_append_text(ti, "%s", name);
1980 /* Set header offset */
1981 if (pdu_flags & ACN_PDU_FLAG_H) {
1982 /* use new values */
1983 header_offset = offset;
1984 last_pdu_offsets->header = offset;
1988 /* use last values */
1989 header_offset = last_pdu_offsets->header;
1991 /* offset should now be pointing to data (if one exists) */
1993 /* process based on vector */
1994 acn_add_dmp_address_type(tvb, pinfo, pdu_tree, header_offset, &adt);
1997 if (pdu_flags & ACN_PDU_FLAG_D) {
1998 /* use new values */
1999 data_offset = offset;
2000 data_length = pdu_length - pdu_flvh_length;
2001 last_pdu_offsets->data = offset;
2002 last_pdu_offsets->data_length = data_length;
2004 /* use last values */
2005 data_offset = last_pdu_offsets->data;
2006 data_length = last_pdu_offsets->data_length;
2008 end_offset = data_offset + data_length;
2011 case ACN_DMP_VECTOR_SET_PROPERTY:
2012 dmx_start_code = tvb_get_ntohs(tvb, data_offset);
2013 if (protocol_id==ACN_PROTOCOL_ID_DMX_2) {
2014 proto_tree_add_item(pdu_tree, hf_acn_dmx_2_first_property_address, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2016 proto_tree_add_item(pdu_tree, hf_acn_dmx_start_code, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2019 proto_tree_add_item(pdu_tree, hf_acn_dmx_increment, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2021 dmx_count = tvb_get_ntohs(tvb, data_offset);
2022 proto_tree_add_item(pdu_tree, hf_acn_dmx_count, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2025 if (protocol_id==ACN_PROTOCOL_ID_DMX_2) {
2026 proto_tree_add_item(pdu_tree, hf_acn_dmx_2_start_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2033 switch (global_acn_dmx_display_line_format) {
2034 case ACN_PREF_DMX_DISPLAY_16PL:
2043 /* values base on display mode */
2044 switch ((guint)global_acn_dmx_display_view) {
2045 case ACN_PREF_DMX_DISPLAY_HEX:
2049 /* case ACN_PREF_DMX_DISPLAY_PER: */
2055 /* do we display leading zeros */
2056 if (global_acn_dmx_display_leading_zeros) {
2062 /* add a snippet to info (this may be slow) */
2063 col_append_fstr(pinfo->cinfo,COL_INFO, ", Sc %02x, [%02x %02x %02x %02x %02x %02x...]",
2065 tvb_get_guint8(tvb, data_offset),
2066 tvb_get_guint8(tvb, data_offset+1),
2067 tvb_get_guint8(tvb, data_offset+2),
2068 tvb_get_guint8(tvb, data_offset+3),
2069 tvb_get_guint8(tvb, data_offset+4),
2070 tvb_get_guint8(tvb, data_offset+5));
2072 /* add a header line */
2073 for (x=0; x<perline; x++) {
2074 buf_ptr = ltos((guint8)(x+1), buf_ptr, 10, ' ', min_char, FALSE);
2075 if ((x+1)==halfline) {
2081 proto_tree_add_string(pdu_tree, hf_acn_dmx_data, tvb, data_offset, dmx_count, buffer);
2083 /* start our line */
2084 g_snprintf(buffer, BUFFER_SIZE, "001-%03d: ", perline);
2085 buf_ptr = buffer + 9;
2089 for (x=data_offset; x<end_offset; x++) {
2090 level = tvb_get_guint8(tvb, x);
2091 if (global_acn_dmx_display_view==ACN_PREF_DMX_DISPLAY_PER) {
2092 if ((level > 0) && (level < 3)) {
2095 level = level * 100 / 255;
2098 buf_ptr = ltos(level, buf_ptr, base, leading_char, min_char, global_acn_dmx_display_zeros);
2102 if (item_cnt == perline || x == (end_offset-1)) {
2104 proto_tree_add_string_format(pdu_tree, hf_acn_dmx_data, tvb, data_offset, item_cnt, buffer, "%s", buffer);
2105 data_offset += perline;
2106 g_snprintf(buffer, BUFFER_SIZE, "%03d-%03d: ",total_cnt, total_cnt+perline);
2107 buf_ptr = buffer + 9;
2110 /* add separator character */
2111 if (item_cnt == halfline) {
2119 address data type (fixed at 0xA2)
2120 start code - 1 byte, reserved (should be 0)
2121 - 1 byte, start code (0x255)
2122 - 2 bytes, packet offset (should be 0000)
2123 address increment - 4 bytes (ignore)
2124 number of dmx values - 4 bytes (0-512)
2125 dmx values 0-512 bytes (data)
2130 return pdu_start + pdu_length;
2135 /******************************************************************************/
2136 /* Dissect DMX Base PDU */
2138 dissect_acn_dmx_pdu(guint32 protocol_id, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
2140 /* common to all pdu */
2144 guint32 pdu_flvh_length; /* flags, length, vector, header */
2145 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2147 guint8 option_flags;
2151 guint32 vector_offset;
2152 guint32 data_offset;
2153 guint32 data_length;
2155 proto_item *ti, *pi;
2156 proto_tree *pdu_tree = NULL;
2157 proto_tree *flag_tree = NULL;
2168 /* save start of pdu block */
2170 pdu_offsets.start = pdu_start;
2172 /* get PDU flags and length flag first */
2173 octet = tvb_get_guint8(tvb, offset++);
2174 pdu_flags = octet & 0xf0;
2175 length1 = octet & 0x0f; /* bottom 4 bits only */
2176 length2 = tvb_get_guint8(tvb, offset++);
2178 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2179 /* flvh = flags, length, vector, header */
2180 if (pdu_flags & ACN_PDU_FLAG_L) {
2181 length3 = tvb_get_guint8(tvb, offset);
2183 pdu_length = length3 | (length2 << 8) | (length1 << 16);
2184 pdu_flvh_length = 3;
2186 pdu_length = length2 | (length1 << 8);
2187 pdu_flvh_length = 2;
2190 /* offset should now be pointing to vector (if one exists) */
2192 /* Add pdu item and tree */
2193 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
2194 pdu_tree = proto_item_add_subtree(ti, ett_acn_dmx_pdu);
2196 /* Add flag item and tree */
2197 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
2198 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
2199 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2200 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2201 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2202 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2204 /* Add PDU Length item */
2205 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
2207 /* Set vector offset */
2208 if (pdu_flags & ACN_PDU_FLAG_V) {
2209 /* use new values */
2210 vector_offset = offset;
2211 last_pdu_offsets->vector = offset;
2213 pdu_flvh_length += 4;
2215 /* use last values */
2216 vector_offset = last_pdu_offsets->vector;
2218 /* offset should now be pointing to header (if one exists) */
2220 /* Add Vector item */
2221 vector = tvb_get_ntohl(tvb, vector_offset);
2222 proto_tree_add_item(pdu_tree, hf_acn_dmx_vector, tvb, vector_offset, 4, ENC_BIG_ENDIAN);
2223 /* vector_offset +=4; */
2225 /* Add Vector item to tree*/
2226 name = val_to_str(vector, acn_dmx_vector_vals, "not valid (%d)");
2227 proto_item_append_text(ti, ": %s", name);
2229 /* NO HEADER DATA ON THESE* (at least so far) */
2232 if (pdu_flags & ACN_PDU_FLAG_D) {
2233 /* use new values */
2234 data_offset = offset;
2235 data_length = pdu_length - pdu_flvh_length;
2236 last_pdu_offsets->data = offset;
2237 last_pdu_offsets->data_length = data_length;
2239 /* use last values */
2240 data_offset = last_pdu_offsets->data;
2241 /*data_length = last_pdu_offsets->data_length;*/
2244 /* process based on vector */
2247 if (protocol_id==ACN_PROTOCOL_ID_DMX_2) {
2248 proto_tree_add_item(pdu_tree, hf_acn_dmx_source_name, tvb, data_offset, 64, ENC_UTF_8|ENC_NA);
2251 proto_tree_add_item(pdu_tree, hf_acn_dmx_source_name, tvb, data_offset, 32, ENC_UTF_8|ENC_NA);
2255 priority = tvb_get_guint8(tvb, data_offset);
2256 proto_tree_add_item(pdu_tree, hf_acn_dmx_priority, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2259 if (protocol_id==ACN_PROTOCOL_ID_DMX_2) {
2260 proto_tree_add_item(pdu_tree, hf_acn_dmx_2_reserved, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2264 sequence = tvb_get_guint8(tvb, data_offset);
2265 proto_tree_add_item(pdu_tree, hf_acn_dmx_sequence_number, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2268 if (protocol_id == ACN_PROTOCOL_ID_DMX_2) {
2269 option_flags = tvb_get_guint8(tvb, data_offset);
2270 pi = proto_tree_add_uint(pdu_tree, hf_acn_dmx_2_options, tvb, data_offset, 1, option_flags);
2271 flag_tree = proto_item_add_subtree(pi, ett_acn_dmx_2_options);
2272 proto_tree_add_item(flag_tree, hf_acn_dmx_2_option_p, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2273 proto_tree_add_item(flag_tree, hf_acn_dmx_2_option_s, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2277 universe = tvb_get_ntohs(tvb, data_offset);
2278 proto_tree_add_item(pdu_tree, hf_acn_dmx_universe , tvb, data_offset, 2, ENC_BIG_ENDIAN);
2281 /* add universe to info */
2282 col_append_fstr(pinfo->cinfo,COL_INFO, ", Universe %d, Seq %3d", universe, sequence );
2283 proto_item_append_text(ti, ", Universe: %d, Priority: %d", universe, priority);
2285 /*data_offset =*/ dissect_acn_dmx_data_pdu(protocol_id, tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2289 return pdu_start + pdu_length;
2292 /******************************************************************************/
2293 /* Dissect SDT Base PDU */
2295 dissect_acn_sdt_base_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
2297 /* common to all pdu */
2301 guint32 pdu_flvh_length; /* flags, length, vector, header */
2302 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2307 guint32 vector_offset;
2308 guint32 data_offset;
2311 guint32 data_length;
2313 proto_item *ti, *pi;
2314 proto_tree *pdu_tree = NULL;
2315 proto_tree *flag_tree = NULL;
2322 /* save start of pdu block */
2324 pdu_offsets.start = pdu_start;
2326 /* get PDU flags and length flag first */
2327 octet = tvb_get_guint8(tvb, offset++);
2328 pdu_flags = octet & 0xf0;
2329 length1 = octet & 0x0f; /* bottom 4 bits only */
2330 length2 = tvb_get_guint8(tvb, offset++);
2332 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2333 /* flvh = flags, length, vector, header */
2334 if (pdu_flags & ACN_PDU_FLAG_L) {
2335 length3 = tvb_get_guint8(tvb, offset);
2337 pdu_length = length3 | (length2 << 8) | (length1 << 16);
2338 pdu_flvh_length = 3;
2340 pdu_length = length2 | (length1 << 8);
2341 pdu_flvh_length = 2;
2343 /* offset should now be pointing to vector (if one exists) */
2345 /* Add pdu item and tree */
2346 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
2347 pdu_tree = proto_item_add_subtree(ti, ett_acn_sdt_base_pdu);
2349 /* Add flag item and tree */
2350 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
2351 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
2352 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2353 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2354 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2355 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2357 /* Add PDU Length item */
2358 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
2360 /* Set vector offset */
2361 if (pdu_flags & ACN_PDU_FLAG_V) {
2362 /* use new values */
2363 vector_offset = offset;
2364 last_pdu_offsets->vector = offset;
2368 /* use last values */
2369 vector_offset = last_pdu_offsets->vector;
2371 /* offset should now be pointing to header (if one exists) */
2373 /* Add Vector item */
2374 vector = tvb_get_guint8(tvb, vector_offset);
2375 proto_tree_add_uint(pdu_tree, hf_acn_sdt_vector, tvb, vector_offset, 1, vector);
2377 /* Add Vector item to tree*/
2378 name = val_to_str(vector, acn_sdt_vector_vals, "not valid (%d)");
2379 proto_item_append_text(ti, ": ");
2380 proto_item_append_text(ti, "%s", name);
2382 /* NO HEADER DATA ON THESE* (at least so far) */
2385 if (pdu_flags & ACN_PDU_FLAG_D) {
2386 /* use new values */
2387 data_offset = offset;
2388 data_length = pdu_length - pdu_flvh_length;
2389 last_pdu_offsets->data = offset;
2390 last_pdu_offsets->data_length = data_length;
2392 /* use last values */
2393 data_offset = last_pdu_offsets->data;
2394 data_length = last_pdu_offsets->data_length;
2396 end_offset = data_offset + data_length;
2398 /* process based on vector */
2400 case ACN_SDT_VECTOR_UNKNOWN:
2402 case ACN_SDT_VECTOR_REL_WRAP:
2403 case ACN_SDT_VECTOR_UNREL_WRAP:
2404 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2406 proto_tree_add_item(pdu_tree, hf_acn_total_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2408 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2410 proto_tree_add_item(pdu_tree, hf_acn_oldest_available_wrapper, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2412 proto_tree_add_item(pdu_tree, hf_acn_first_memeber_to_ack, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2414 proto_tree_add_item(pdu_tree, hf_acn_last_memeber_to_ack, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2416 proto_tree_add_item(pdu_tree, hf_acn_mak_threshold, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2419 while (data_offset < end_offset) {
2420 old_offset = data_offset;
2421 data_offset = dissect_acn_sdt_client_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2422 if (data_offset == old_offset) break;
2425 case ACN_SDT_VECTOR_CHANNEL_PARAMS:
2427 case ACN_SDT_VECTOR_JOIN:
2428 proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2430 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2432 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2434 proto_tree_add_item(pdu_tree, hf_acn_reciprocal_channel, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2436 proto_tree_add_item(pdu_tree, hf_acn_total_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2438 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2440 data_offset = acn_add_address(tvb, pinfo, pdu_tree, data_offset, "Destination Address:");
2441 data_offset = acn_add_channel_parameter(tvb, pinfo, pdu_tree, data_offset);
2442 /*data_offset =*/ acn_add_expiry(tvb, pinfo, pdu_tree, data_offset, hf_acn_adhoc_expiry);
2444 case ACN_SDT_VECTOR_JOIN_REFUSE:
2445 pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2447 proto_item_append_text(pi, "(Leader)");
2448 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2450 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2452 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2454 proto_tree_add_item(pdu_tree, hf_acn_refuse_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2457 case ACN_SDT_VECTOR_JOIN_ACCEPT:
2458 pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2460 proto_item_append_text(pi, "(Leader)");
2461 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2463 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2465 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2467 proto_tree_add_item(pdu_tree, hf_acn_reciprocal_channel, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2468 /*data_offset += 2;*/
2470 case ACN_SDT_VECTOR_LEAVE:
2472 case ACN_SDT_VECTOR_LEAVING:
2473 pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2475 proto_item_append_text(pi, "(Leader)");
2476 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2478 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2480 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2482 proto_tree_add_item(pdu_tree, hf_acn_reason_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2485 case ACN_SDT_VECTOR_CONNECT:
2487 case ACN_SDT_VECTOR_CONNECT_ACCEPT:
2489 case ACN_SDT_VECTOR_CONNECT_REFUSE:
2491 case ACN_SDT_VECTOR_DISCONNECT:
2493 case ACN_SDT_VECTOR_DISCONNECTING:
2495 case ACN_SDT_VECTOR_ACK:
2497 case ACN_SDT_VECTOR_NAK:
2498 pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2500 proto_item_append_text(pi, "(Leader)");
2501 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2503 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2505 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2507 proto_tree_add_item(pdu_tree, hf_acn_first_missed_sequence, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2509 proto_tree_add_item(pdu_tree, hf_acn_last_missed_sequence, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2510 /*data_offset += 4;*/
2512 case ACN_SDT_VECTOR_GET_SESSION:
2513 proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2514 /*data_offset += 16;*/
2516 case ACN_SDT_VECTOR_SESSIONS:
2517 member_id = tvb_get_ntohs(tvb, data_offset);
2518 switch (member_id) {
2520 /*data_offset =*/ acn_add_channel_owner_info_block(tvb, pinfo, pdu_tree, data_offset);
2523 /*data_offset =*/ acn_add_channel_member_info_block(tvb, pinfo, pdu_tree, data_offset);
2529 return pdu_start + pdu_length;
2532 /******************************************************************************/
2533 /* Dissect Root PDU */
2535 dissect_acn_root_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
2537 /* common to all pdu */
2541 guint32 pdu_flvh_length; /* flags, length, vector, header */
2542 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2547 guint32 vector_offset;
2548 guint32 header_offset;
2549 guint32 data_offset;
2552 guint32 data_length;
2554 proto_item *ti, *pi;
2555 proto_tree *pdu_tree = NULL;
2556 proto_tree *flag_tree = NULL;
2559 guint32 protocol_id;
2562 /* save start of pdu block */
2564 pdu_offsets.start = pdu_start;
2566 /* get PDU flags and length flag first */
2567 octet = tvb_get_guint8(tvb, offset++);
2568 pdu_flags = octet & 0xf0;
2569 length1 = octet & 0x0f; /* bottom 4 bits only */
2570 length2 = tvb_get_guint8(tvb, offset++);
2572 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2573 /* flvh = flags, length, vector, header */
2574 if (pdu_flags & ACN_PDU_FLAG_L) {
2575 length3 = tvb_get_guint8(tvb, offset);
2577 pdu_length = length3 | (length2 << 8) | (length1 << 16);
2578 pdu_flvh_length = 3;
2580 pdu_length = length2 | (length1 << 8);
2581 pdu_flvh_length = 2;
2583 /* offset should now be pointing to vector (if one exists) */
2585 /* Add pdu item and tree */
2586 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
2587 pdu_tree = proto_item_add_subtree(ti, ett_acn_root_pdu);
2589 /* Add flag item and tree */
2590 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
2591 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
2592 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2593 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2594 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2595 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2597 /* Add PDU Length item */
2598 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
2600 /* Set vector offset */
2601 if (pdu_flags & ACN_PDU_FLAG_V) {
2602 /* use new values */
2603 vector_offset = offset;
2604 last_pdu_offsets->vector = offset;
2606 pdu_flvh_length += 4;
2608 /* use last values */
2609 vector_offset = last_pdu_offsets->vector;
2611 /* offset should now be pointing to header (if one exists) */
2615 /* Get Protocol ID (vector) */
2616 protocol_id = tvb_get_ntohl(tvb, vector_offset);
2617 proto_tree_add_uint(pdu_tree, hf_acn_protocol_id, tvb, vector_offset, 4, protocol_id);
2619 /* process based on protocol_id */
2620 switch (protocol_id) {
2621 case ACN_PROTOCOL_ID_DMX:
2622 case ACN_PROTOCOL_ID_DMX_2:
2623 if (global_acn_dmx_enable) {
2624 proto_item_append_text(ti,": Root DMX");
2626 /* Set header offset */
2627 if (pdu_flags & ACN_PDU_FLAG_H) {
2628 /* use new values */
2629 header_offset = offset;
2630 last_pdu_offsets->header = offset;
2632 pdu_flvh_length += 16;
2634 /* use last values */
2635 header_offset = last_pdu_offsets->header;
2637 /* offset should now be pointing to data (if one exists) */
2639 /* get Header (CID) 16 bytes */
2640 tvb_get_guid(tvb, header_offset, &guid, ENC_BIG_ENDIAN);
2641 proto_item_append_text(ti, ", Src: %s", guid_to_ep_str(&guid));
2643 /* add cid to info */
2644 col_add_fstr(pinfo->cinfo,COL_INFO, "CID %s", guid_to_ep_str(&guid));
2646 proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, header_offset, 16, ENC_BIG_ENDIAN);
2647 /*header_offset += 16;*/
2650 if (pdu_flags & ACN_PDU_FLAG_D) {
2651 /* use new values */
2652 data_offset = offset;
2653 data_length = pdu_length - pdu_flvh_length;
2654 last_pdu_offsets->data = offset;
2655 last_pdu_offsets->data_length = data_length;
2657 /* use last values */
2658 data_offset = last_pdu_offsets->data;
2659 data_length = last_pdu_offsets->data_length;
2661 end_offset = data_offset + data_length;
2663 /* adjust for what we used */
2664 while (data_offset < end_offset) {
2665 old_offset = data_offset;
2666 data_offset = dissect_acn_dmx_pdu(protocol_id, tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2667 if (data_offset == old_offset) break;
2671 case ACN_PROTOCOL_ID_SDT:
2673 proto_item_append_text(ti,": Root SDT");
2675 /* Set header offset */
2676 if (pdu_flags & ACN_PDU_FLAG_H) {
2677 /* use new values */
2678 header_offset = offset;
2679 last_pdu_offsets->header = offset;
2681 pdu_flvh_length += 16;
2683 /* use last values */
2684 header_offset = last_pdu_offsets->header;
2686 /* offset should now be pointing to data (if one exists) */
2688 /* get Header (CID) 16 bytes */
2689 tvb_get_guid(tvb, header_offset, &guid, ENC_BIG_ENDIAN);
2690 proto_item_append_text(ti, ", Src: %s", guid_to_ep_str(&guid));
2692 proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, header_offset, 16, ENC_BIG_ENDIAN);
2693 /*header_offset += 16;*/
2696 if (pdu_flags & ACN_PDU_FLAG_D) {
2697 /* use new values */
2698 data_offset = offset;
2699 data_length = pdu_length - pdu_flvh_length;
2700 last_pdu_offsets->data = offset;
2701 last_pdu_offsets->data_length = data_length;
2703 /* use last values */
2704 data_offset = last_pdu_offsets->data;
2705 data_length = last_pdu_offsets->data_length;
2707 end_offset = data_offset + data_length;
2709 /* adjust for what we used */
2710 while (data_offset < end_offset) {
2711 old_offset = data_offset;
2712 data_offset = dissect_acn_sdt_base_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2713 if (data_offset == old_offset) break;
2718 return pdu_start + pdu_length;
2721 /******************************************************************************/
2724 dissect_acn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2726 proto_item *ti = NULL;
2727 proto_tree *acn_tree = NULL;
2728 guint32 data_offset = 0;
2731 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2733 /* if (!is_acn(tvb)) { */
2737 /* Set the protocol column */
2738 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACN");
2740 col_add_fstr(pinfo->cinfo,COL_INFO, "ACN [Src Port: %d, Dst Port: %d]", pinfo->srcport, pinfo->destport );
2742 if (tree) { /* we are being asked for details */
2743 ti = proto_tree_add_item(tree, proto_acn, tvb, 0, -1, ENC_NA);
2744 acn_tree = proto_item_add_subtree(ti, ett_acn);
2746 /* add preamble, postamble and ACN Packet ID */
2747 proto_tree_add_item(acn_tree, hf_acn_preamble_size, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2749 proto_tree_add_item(acn_tree, hf_acn_postamble_size, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2751 proto_tree_add_item(acn_tree, hf_acn_packet_identifier, tvb, data_offset, 12, ENC_UTF_8|ENC_NA);
2754 /* one past the last byte */
2755 end_offset = data_offset + tvb_reported_length_remaining(tvb, data_offset);
2756 while (data_offset < end_offset) {
2757 old_offset = data_offset;
2758 data_offset = dissect_acn_root_pdu(tvb, pinfo, acn_tree, data_offset, &pdu_offsets);
2759 if (data_offset == old_offset) break;
2762 return tvb_captured_length(tvb);
2765 /******************************************************************************/
2766 /* Register protocol */
2768 proto_register_acn(void)
2770 static hf_register_info hf[] = {
2771 /**************************************************************************/
2772 /* In alphabetical order */
2775 { &hf_acn_ip_address_type,
2776 { "Addr Type", "acn.ip_address_type",
2777 FT_UINT8, BASE_DEC, VALS(acn_ip_address_type_vals), 0x0,
2781 { &hf_acn_association,
2782 { "Association", "acn.association",
2783 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2786 /* Channel Number */
2787 { &hf_acn_channel_number,
2788 { "Channel Number", "acn.channel_number",
2789 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2795 FT_GUID, BASE_NONE, NULL, 0x0,
2798 /* Client Protocol ID */
2800 { &hf_acn_client_protocol_id,
2801 { "Client Protocol ID", "acn.client_protocol_id",
2802 FT_UINT32, BASE_DEC, VALS(acn_protocol_id_vals), 0x0,
2808 { "Data", "acn.dmp_data",
2809 FT_BYTES, BASE_NONE, NULL, 0x0,
2813 { "Addr", "acn.dmp_data8",
2814 FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
2818 { "Addr", "acn.dmp_data16",
2819 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2823 { "Addr", "acn.dmp_data24",
2824 FT_UINT24, BASE_DEC_HEX, NULL, 0x0,
2828 { "Addr", "acn.dmp_data32",
2829 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2833 /* DMP Address type*/
2836 { "Address and Data Type", "acn.dmp_adt",
2837 FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
2841 { &hf_acn_dmp_adt_a,
2842 { "Size", "acn.dmp_adt_a",
2843 FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_a_vals), 0x03,
2846 { &hf_acn_dmp_adt_d,
2847 { "Data Type", "acn.dmp_adt_d",
2848 FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_d_vals), 0x30,
2851 { &hf_acn_dmp_adt_r,
2852 { "Relative", "acn.dmp_adt_r",
2853 FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_r_vals), 0x40,
2856 { &hf_acn_dmp_adt_v,
2857 { "Virtual", "acn.dmp_adt_v",
2858 FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_v_vals), 0x80,
2861 { &hf_acn_dmp_adt_x,
2862 { "Reserved", "acn.dmp_adt_x",
2863 FT_UINT8, BASE_DEC, NULL, 0x0c,
2867 /* DMP Reason Code */
2868 { &hf_acn_dmp_reason_code,
2869 { "Reason Code", "acn.dmp_reason_code",
2870 FT_UINT8, BASE_DEC, VALS(acn_dmp_reason_code_vals), 0x0,
2875 { &hf_acn_dmp_vector,
2876 { "DMP Vector", "acn.dmp_vector",
2877 FT_UINT8, BASE_DEC, VALS(acn_dmp_vector_vals), 0x0,
2881 { &hf_acn_dmp_actual_address,
2882 { "Actual Address", "acn.dmp_actual_address",
2883 FT_UINT32, BASE_HEX, NULL, 0x0,
2887 { &hf_acn_dmp_virtual_address,
2888 { "Virtual Address", "acn.dmp_virtual_address",
2889 FT_UINT32, BASE_HEX, NULL, 0x0,
2893 { &hf_acn_dmp_actual_address_first,
2894 { "Actual Address First", "acn.dmp_actual_address_first",
2895 FT_UINT32, BASE_HEX, NULL, 0x0,
2899 { &hf_acn_dmp_virtual_address_first,
2900 { "Virtual Address First", "acn.dmp_virtual_address_first",
2901 FT_UINT32, BASE_HEX, NULL, 0x0,
2907 { "Expiry", "acn.expiry",
2908 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2911 /* First Member to ACK */
2912 { &hf_acn_first_memeber_to_ack,
2913 { "First Member to ACK", "acn.first_member_to_ack",
2914 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2917 /* First Missed Sequence */
2918 { &hf_acn_first_missed_sequence,
2919 { "First Missed Sequence", "acn.first_missed_sequence",
2920 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2925 { "IPV4", "acn.ipv4",
2926 FT_IPv4, BASE_NONE, NULL, 0x0,
2931 { "IPV6", "acn.ipv6",
2932 FT_IPv6, BASE_NONE, NULL, 0x0,
2935 /* Last Member to ACK */
2936 { &hf_acn_last_memeber_to_ack,
2937 { "Last Member to ACK", "acn.last_member_to_ack",
2938 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2941 /* Last Missed Sequence */
2942 { &hf_acn_last_missed_sequence,
2943 { "Last Missed Sequence", "acn.last_missed_sequence",
2944 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2948 { &hf_acn_mak_threshold,
2949 { "MAK Threshold", "acn.mak_threshold",
2950 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2954 { &hf_acn_member_id,
2955 { "Member ID", "acn.member_id",
2956 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2960 { &hf_acn_nak_holdoff,
2961 { "NAK holdoff (ms)", "acn.nak_holdoff",
2962 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2966 { &hf_acn_nak_max_wait,
2967 { "NAK Max Wait (ms)", "acn.nak_max_wait",
2968 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2972 { &hf_acn_nak_modulus,
2973 { "NAK Modulus", "acn.nak_modulus",
2974 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2977 /* NAK Outbound Flag */
2978 { &hf_acn_nak_outbound_flag,
2979 { "NAK Outbound Flag", "acn.nak_outbound_flag",
2980 FT_BOOLEAN, 8, NULL, 0x80,
2983 /* Oldest Available Wrapper */
2984 { &hf_acn_oldest_available_wrapper,
2985 { "Oldest Available Wrapper", "acn.oldest_available_wrapper",
2986 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2989 /* Preamble Sizet */
2990 { &hf_acn_preamble_size,
2991 { "Size of preamble", "acn.preamble_size",
2992 FT_UINT16, BASE_DEC, NULL, 0x0,
2993 "Preamble size in bytes", HFILL }
2995 /* Packet Identifier */
2996 { &hf_acn_packet_identifier,
2997 { "Packet Identifier", "acn.packet_identifier",
2998 FT_STRING, BASE_NONE, NULL, 0x0,
3004 FT_NONE, BASE_NONE, NULL, 0x0,
3008 { &hf_acn_pdu_flags,
3009 { "Flags", "acn.pdu.flags",
3010 FT_UINT8, BASE_HEX, NULL, 0x0,
3011 "PDU Flags", HFILL }
3013 { &hf_acn_pdu_flag_d,
3014 { "Data", "acn.pdu.flag_d",
3015 FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_D,
3016 "Data flag", HFILL }
3018 { &hf_acn_pdu_flag_h,
3019 { "Header", "acn.pdu.flag_h",
3020 FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_H,
3021 "Header flag", HFILL }
3023 { &hf_acn_pdu_flag_l,
3024 { "Length", "acn.pdu.flag_l",
3025 FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_L,
3026 "Length flag", HFILL }
3028 { &hf_acn_pdu_flag_v,
3029 { "Vector", "acn.pdu.flag_v",
3030 FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_V,
3031 "Vector flag", HFILL }
3034 { &hf_acn_pdu_length,
3035 { "Length", "acn.pdu.length",
3036 FT_UINT32, BASE_DEC, NULL, 0x0,
3037 "PDU Length", HFILL }
3041 { "Port", "acn.port",
3042 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3045 /* Postamble Size */
3046 { &hf_acn_postamble_size,
3047 { "Size of postamble", "acn.postamble_size",
3048 FT_UINT16, BASE_DEC, NULL, 0x0,
3049 "Postamble size in bytes", HFILL }
3052 { &hf_acn_protocol_id,
3053 { "Protocol ID", "acn.protocol_id",
3054 FT_UINT32, BASE_DEC, VALS(acn_protocol_id_vals), 0x0,
3058 { &hf_acn_reason_code,
3059 { "Reason Code", "acn.reason_code",
3060 FT_UINT8, BASE_DEC, VALS(acn_reason_code_vals), 0x0,
3063 /* Reciprocal Channel */
3064 { &hf_acn_reciprocal_channel,
3065 { "Reciprocal Channel Number", "acn.reciprocal_channel",
3066 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3067 "Reciprocal Channel", HFILL }
3070 { &hf_acn_refuse_code,
3071 { "Refuse Code", "acn.refuse_code",
3072 FT_UINT8, BASE_DEC, VALS(acn_refuse_code_vals), 0x0,
3075 /* Reliable Sequence Number */
3076 { &hf_acn_reliable_sequence_number,
3077 { "Reliable Sequence Number", "acn.reliable_sequence_number",
3078 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
3082 { &hf_acn_adhoc_expiry,
3083 { "Ad-hoc Expiry", "acn.adhoc_expiry",
3084 FT_UINT8, BASE_DEC, NULL, 0x0,
3088 { &hf_acn_sdt_vector,
3089 { "STD Vector", "acn.sdt_vector",
3090 FT_UINT8, BASE_DEC, VALS(acn_sdt_vector_vals), 0x0,
3095 { &hf_acn_dmx_vector,
3096 { "Vector", "acn.dmx_vector",
3097 FT_UINT32, BASE_DEC, VALS(acn_dmx_vector_vals), 0x0,
3098 "DMX Vector", HFILL }
3100 /* DMX Source Name */
3101 { &hf_acn_dmx_source_name,
3102 { "Source", "acn.dmx.source_name",
3103 FT_STRING, BASE_NONE, NULL, 0x0,
3104 "DMX Source Name", HFILL }
3108 { &hf_acn_dmx_priority,
3109 { "Priority", "acn.dmx.priority",
3110 FT_UINT8, BASE_DEC, NULL, 0x0,
3111 "DMX Priority", HFILL }
3114 /* DMX 2 reserved */
3115 { &hf_acn_dmx_2_reserved,
3116 { "Reserved", "acn.dmx.reserved",
3117 FT_UINT16, BASE_DEC, NULL, 0x0,
3118 "DMX Reserved", HFILL }
3121 /* DMX Sequence number */
3122 { &hf_acn_dmx_sequence_number,
3123 { "Seq No", "acn.dmx.seq_number",
3124 FT_UINT8, BASE_DEC, NULL, 0x0,
3125 "DMX Sequence Number", HFILL }
3129 { &hf_acn_dmx_2_options,
3130 { "Options", "acn.dmx.options",
3131 FT_UINT8, BASE_DEC, NULL, 0x0,
3132 "DMX Options", HFILL }
3135 { &hf_acn_dmx_2_option_p,
3136 { "Preview Data", "acn.dmx.option_p",
3137 FT_BOOLEAN, 8, NULL, ACN_DMX_OPTION_P,
3138 "Preview Data flag", HFILL }
3141 { &hf_acn_dmx_2_option_s,
3142 { "Stream Terminated", "acn.dmx.option_s",
3143 FT_BOOLEAN, 8, NULL, ACN_DMX_OPTION_S,
3144 "Stream Terminated flag", HFILL }
3148 { &hf_acn_dmx_universe,
3149 { "Universe", "acn.dmx.universe",
3150 FT_UINT16, BASE_DEC, NULL, 0x0,
3151 "DMX Universe", HFILL }
3154 /* DMX Start Code */
3155 { &hf_acn_dmx_start_code,
3156 { "Start Code", "acn.dmx.start_code",
3157 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3158 "DMX Start Code", HFILL }
3161 /* DMX 2 First Property Address */
3162 { &hf_acn_dmx_2_first_property_address,
3163 { "First Property Address", "acn.dmx.start_code",
3164 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3165 "DMX First Property Address", HFILL }
3168 /* DMX Address Increment */
3169 { &hf_acn_dmx_increment,
3170 { "Increment", "acn.dmx.increment",
3171 FT_UINT16, BASE_DEC, NULL, 0x0,
3172 "DMX Increment", HFILL }
3175 /* DMX Packet Count */
3176 { &hf_acn_dmx_count,
3177 { "Count", "acn.dmx.count",
3178 FT_UINT16, BASE_DEC, NULL, 0x0,
3179 "DMX Count", HFILL }
3182 /* DMX 2 Start Code */
3183 { &hf_acn_dmx_2_start_code,
3184 { "Start Code", "acn.dmx.start_code2",
3185 FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
3186 "DMX Start Code", HFILL }
3190 { "Data", "acn.dmx.data",
3191 FT_BYTES, BASE_NONE, NULL, 0x0,
3197 { &hf_acn_session_count,
3198 { "Session Count", "acn.session_count",
3199 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3203 /* Total Sequence Number */
3204 { &hf_acn_total_sequence_number,
3205 { "Total Sequence Number", "acn.total_sequence_number",
3206 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
3211 /* Setup protocol subtree array */
3212 static gint *ett[] = {
3214 &ett_acn_channel_owner_info_block,
3215 &ett_acn_channel_member_info_block,
3216 &ett_acn_channel_parameter,
3218 &ett_acn_address_type,
3222 &ett_acn_sdt_client_pdu,
3223 &ett_acn_sdt_base_pdu,
3225 &ett_acn_dmx_address,
3226 &ett_acn_dmx_2_options,
3227 &ett_acn_dmx_data_pdu,
3231 module_t *acn_module;
3232 proto_acn = proto_register_protocol (
3233 "Architecture for Control Networks", /* name */
3234 "ACN", /* short name */
3238 proto_register_field_array(proto_acn, hf, array_length(hf));
3239 proto_register_subtree_array(ett, array_length(ett));
3241 acn_module = prefs_register_protocol(proto_acn, NULL);
3242 prefs_register_bool_preference(acn_module, "heuristic_acn",
3244 "Enable Architecture for Control Networks dissector (ANSI BSR E1.17)",
3247 prefs_register_bool_preference(acn_module, "dmx_enable",
3249 "Enable Streaming DMX extension dissector (ANSI BSR E1.31)",
3250 &global_acn_dmx_enable);
3252 prefs_register_enum_preference(acn_module, "dmx_display_view",
3253 "DMX, display format",
3255 &global_acn_dmx_display_view,
3259 prefs_register_bool_preference(acn_module, "dmx_display_zeros",
3260 "DMX, display zeros",
3261 "Display zeros instead of dots",
3262 &global_acn_dmx_display_zeros);
3264 prefs_register_bool_preference(acn_module, "dmx_display_leading_zeros",
3265 "DMX, display leading zeros",
3266 "Display leading zeros on levels",
3267 &global_acn_dmx_display_leading_zeros);
3269 prefs_register_enum_preference(acn_module, "dmx_display_line_format",
3270 "DMX, display line format",
3271 "Display line format",
3272 &global_acn_dmx_display_line_format,
3273 dmx_display_line_format,
3278 /******************************************************************************/
3279 /* Register handoff */
3281 proto_reg_handoff_acn(void)
3283 /* dissector_handle_t acn_handle; */
3284 /* acn_handle = new_create_dissector_handle(dissect_acn, proto_acn); */
3285 /* dissector_add_for_decode_as("udp.port", acn_handle); */
3286 heur_dissector_add("udp", dissect_acn_heur, proto_acn);
3296 * indent-tabs-mode: nil
3299 * ex: set shiftwidth=2 tabstop=8 expandtab:
3300 * :indentSize=2:tabSize=8:noTabs=true: