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_expiry = -1;
248 static int hf_acn_first_memeber_to_ack = -1;
249 static int hf_acn_first_missed_sequence = -1;
250 static int hf_acn_ip_address_type = -1;
251 static int hf_acn_ipv4 = -1;
252 static int hf_acn_ipv6 = -1;
253 static int hf_acn_last_memeber_to_ack = -1;
254 static int hf_acn_last_missed_sequence = -1;
255 static int hf_acn_mak_threshold = -1;
256 static int hf_acn_member_id = -1;
257 static int hf_acn_nak_holdoff = -1;
258 static int hf_acn_nak_max_wait = -1;
259 static int hf_acn_nak_modulus = -1;
260 static int hf_acn_nak_outbound_flag = -1;
261 static int hf_acn_oldest_available_wrapper = -1;
262 static int hf_acn_packet_identifier = -1;
263 static int hf_acn_pdu = -1;
264 static int hf_acn_pdu_flag_d = -1;
265 static int hf_acn_pdu_flag_h = -1;
266 static int hf_acn_pdu_flag_l = -1;
267 static int hf_acn_pdu_flag_v = -1;
268 static int hf_acn_pdu_flags = -1;
269 static int hf_acn_pdu_length = -1;
270 static int hf_acn_port = -1;
271 static int hf_acn_postamble_size = -1;
272 static int hf_acn_preamble_size = -1;
273 static int hf_acn_protocol_id = -1;
274 static int hf_acn_reason_code = -1;
275 static int hf_acn_reciprocal_channel = -1;
276 static int hf_acn_refuse_code = -1;
277 static int hf_acn_reliable_sequence_number = -1;
278 /* static int hf_acn_sdt_pdu = -1; */
279 static int hf_acn_sdt_vector = -1;
280 static int hf_acn_dmx_vector = -1;
281 /* static int hf_acn_session_count = -1; */
282 static int hf_acn_total_sequence_number = -1;
283 static int hf_acn_dmx_source_name = -1;
284 static int hf_acn_dmx_priority = -1;
285 static int hf_acn_dmx_2_reserved = -1;
286 static int hf_acn_dmx_sequence_number = -1;
287 static int hf_acn_dmx_2_options = -1;
288 static int hf_acn_dmx_2_option_p = -1;
289 static int hf_acn_dmx_2_option_s = -1;
290 static int hf_acn_dmx_universe = -1;
292 static int hf_acn_dmx_start_code = -1;
293 static int hf_acn_dmx_2_first_property_address = -1;
294 static int hf_acn_dmx_increment = -1;
295 static int hf_acn_dmx_count = -1;
296 static int hf_acn_dmx_2_start_code = -1;
298 /* static int hf_acn_dmx_dmp_vector = -1; */
300 /* Try heuristic ACN decode */
301 static gboolean global_acn_heur = FALSE;
302 static gboolean global_acn_dmx_enable = FALSE;
303 static gint global_acn_dmx_display_view = 0;
304 static gint global_acn_dmx_display_line_format = 0;
305 static gboolean global_acn_dmx_display_zeros = FALSE;
306 static gboolean global_acn_dmx_display_leading_zeros = FALSE;
309 static const value_string acn_protocol_id_vals[] = {
310 { ACN_PROTOCOL_ID_SDT, "SDT Protocol" },
311 { ACN_PROTOCOL_ID_DMP, "DMP Protocol" },
312 { ACN_PROTOCOL_ID_DMX, "DMX Protocol" },
313 { ACN_PROTOCOL_ID_DMX_2, "Ratified DMX Protocol" },
317 static const value_string acn_dmp_adt_r_vals[] = {
323 static const value_string acn_dmp_adt_v_vals[] = {
329 static const value_string acn_dmp_adt_d_vals[] = {
330 { ACN_DMP_ADT_D_NS, "Non-range, single data item" },
331 { ACN_DMP_ADT_D_RS, "Range, single data item" },
332 { ACN_DMP_ADT_D_RE, "Range, array of equal size data items" },
333 { ACN_DMP_ADT_D_RM, "Range, series of mixed size data items" },
337 static const value_string acn_dmp_adt_a_vals[] = {
338 { ACN_DMP_ADT_A_1, "1 octet" },
339 { ACN_DMP_ADT_A_2, "2 octets" },
340 { ACN_DMP_ADT_A_4, "4 octets" },
341 { ACN_DMP_ADT_A_R, "reserved" },
346 static const value_string acn_sdt_vector_vals[] = {
347 {ACN_SDT_VECTOR_UNKNOWN, "Unknown"},
348 {ACN_SDT_VECTOR_REL_WRAP, "Reliable Wrapper"},
349 {ACN_SDT_VECTOR_UNREL_WRAP, "Unreliable Wrapper"},
350 {ACN_SDT_VECTOR_CHANNEL_PARAMS, "Channel Parameters"},
351 {ACN_SDT_VECTOR_JOIN, "Join"},
352 {ACN_SDT_VECTOR_JOIN_REFUSE, "Join Refuse"},
353 {ACN_SDT_VECTOR_JOIN_ACCEPT, "Join Accept"},
354 {ACN_SDT_VECTOR_LEAVE, "Leave"},
355 {ACN_SDT_VECTOR_LEAVING, "Leaving"},
356 {ACN_SDT_VECTOR_CONNECT, "Connect"},
357 {ACN_SDT_VECTOR_CONNECT_ACCEPT, "Connect Accept"},
358 {ACN_SDT_VECTOR_CONNECT_REFUSE, "Connect Refuse"},
359 {ACN_SDT_VECTOR_DISCONNECT, "Disconnect"},
360 {ACN_SDT_VECTOR_DISCONNECTING, "Disconnecting"},
361 {ACN_SDT_VECTOR_ACK, "Ack"},
362 {ACN_SDT_VECTOR_NAK, "Nak"},
363 {ACN_SDT_VECTOR_GET_SESSION, "Get Session"},
364 {ACN_SDT_VECTOR_SESSIONS, "Sessions"},
368 static const value_string acn_dmx_vector_vals[] = {
369 {ACN_DMX_VECTOR, "Streaming DMX"},
373 static const value_string acn_dmp_vector_vals[] = {
374 {ACN_DMP_VECTOR_UNKNOWN, "Unknown"},
375 {ACN_DMP_VECTOR_GET_PROPERTY, "Get Property"},
376 {ACN_DMP_VECTOR_SET_PROPERTY, "Set Property"},
377 {ACN_DMP_VECTOR_GET_PROPERTY_REPLY, "Get property reply"},
378 {ACN_DMP_VECTOR_EVENT, "Event"},
379 {ACN_DMP_VECTOR_MAP_PROPERTY, "Map Property"},
380 {ACN_DMP_VECTOR_UNMAP_PROPERTY, "Unmap Property"},
381 {ACN_DMP_VECTOR_SUBSCRIBE, "Subscribe"},
382 {ACN_DMP_VECTOR_UNSUBSCRIBE, "Unsubscribe"},
383 {ACN_DMP_VECTOR_GET_PROPERTY_FAIL, "Get Property Fail"},
384 {ACN_DMP_VECTOR_SET_PROPERTY_FAIL, "Set Property Fail"},
385 {ACN_DMP_VECTOR_MAP_PROPERTY_FAIL, "Map Property Fail"},
386 {ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT, "Subscribe Accept"},
387 {ACN_DMP_VECTOR_SUBSCRIBE_REJECT, "Subscribe Reject"},
388 {ACN_DMP_VECTOR_ALLOCATE_MAP, "Allocate Map"},
389 {ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY, "Allocate Map Reply"},
390 {ACN_DMP_VECTOR_DEALLOCATE_MAP, "Deallocate Map"},
394 static const value_string acn_ip_address_type_vals[] = {
395 { ACN_ADDR_NULL, "Null"},
396 { ACN_ADDR_IPV4, "IPv4"},
397 { ACN_ADDR_IPV6, "IPv6"},
398 { ACN_ADDR_IPPORT, "Port"},
402 static const value_string acn_refuse_code_vals[] = {
403 { ACN_REFUSE_CODE_NONSPECIFIC, "Nonspecific" },
404 { ACN_REFUSE_CODE_ILLEGAL_PARAMS, "Illegal Parameters" },
405 { ACN_REFUSE_CODE_LOW_RESOURCES, "Low Resources" },
406 { ACN_REFUSE_CODE_ALREADY_MEMBER, "Already Member" },
407 { ACN_REFUSE_CODE_BAD_ADDR_TYPE, "Bad Address Type" },
408 { ACN_REFUSE_CODE_NO_RECIP_CHAN, "No Reciprocal Channel" },
412 static const value_string acn_reason_code_vals[] = {
413 { ACN_REASON_CODE_NONSPECIFIC, "Nonspecific" },
414 { ACN_REASON_CODE_NO_RECIP_CHAN, "No Reciprocal Channel" },
415 { ACN_REASON_CODE_CHANNEL_EXPIRED, "Channel Expired" },
416 { ACN_REASON_CODE_LOST_SEQUENCE, "Lost Sequence" },
417 { ACN_REASON_CODE_SATURATED, "Saturated" },
418 { ACN_REASON_CODE_TRANS_ADDR_CHANGING, "Transport Address Changing" },
419 { ACN_REASON_CODE_ASKED_TO_LEAVE, "Asked to Leave" },
420 { ACN_REASON_CODE_NO_RECIPIENT, "No Recipient"},
424 static const value_string acn_dmp_reason_code_vals[] = {
425 { ACN_DMP_REASON_CODE_NONSPECIFIC, "Nonspecific" },
426 { ACN_DMP_REASON_CODE_NOT_A_PROPERTY, "Not a Property" },
427 { ACN_DMP_REASON_CODE_WRITE_ONLY, "Write Only" },
428 { ACN_DMP_REASON_CODE_NOT_WRITABLE, "Not Writable" },
429 { ACN_DMP_REASON_CODE_DATA_ERROR, "Data Error" },
430 { ACN_DMP_REASON_CODE_MAPS_NOT_SUPPORTED, "Maps not Supported" },
431 { ACN_DMP_REASON_CODE_SPACE_NOT_AVAILABLE, "Space not Available" },
432 { ACN_DMP_REASON_CODE_PROP_NOT_MAPPABLE, "Property not Mappable"},
433 { ACN_DMP_REASON_CODE_MAP_NOT_ALLOCATED, "Map not Allocated"},
434 { ACN_DMP_REASON_CODE_SUBSCRIPTION_NOT_SUPPORTED, "Subscription not Supported"},
435 { ACN_DMP_REASON_CODE_NO_SUBSCRIPTIONS_SUPPORTED, "No Subscriptions Supported"},
439 static const enum_val_t dmx_display_view[] = {
440 { "hex" , "Hex ", ACN_PREF_DMX_DISPLAY_HEX },
441 { "decimal", "Decimal", ACN_PREF_DMX_DISPLAY_DEC },
442 { "percent", "Percent", ACN_PREF_DMX_DISPLAY_PER },
446 static const enum_val_t dmx_display_line_format[] = {
447 { "20 per line", "20 per line", ACN_PREF_DMX_DISPLAY_20PL },
448 { "16 per line", "16 per line", ACN_PREF_DMX_DISPLAY_16PL },
452 /******************************************************************************/
453 /* Test to see if it is an ACN Packet */
455 is_acn(tvbuff_t *tvb)
457 static const char acn_packet_id[] = "ASC-E1.17\0\0\0"; /* must be 12 bytes */
459 if (tvb_length(tvb) < (4+sizeof(acn_packet_id)))
462 /* Check the bytes in octets 4 - 16 */
463 if (tvb_memeql(tvb, 4, acn_packet_id, sizeof(acn_packet_id)-1) != 0)
470 /******************************************************************************/
471 /* Heuristic dissector */
473 dissect_acn_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ )
475 /* This is a heuristic dissector, which means we get all the UDP
476 * traffic not sent to a known dissector and not claimed by
477 * a heuristic dissector called before us!
480 /* abort if not enabled! */
481 if (!global_acn_heur) return FALSE;
483 /* abort if it is NOT an ACN packet */
484 if (!is_acn(tvb)) return FALSE;
486 /* else, dissect it */
487 dissect_acn(tvb, pinfo, tree);
491 /******************************************************************************/
492 /* Adds tree branch for channel owner info block */
494 acn_add_channel_owner_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
497 proto_tree *this_tree;
498 guint32 session_count;
501 pi = proto_tree_add_text(tree, tvb, offset, 8, "Channel Owner Info Block");
502 this_tree = proto_item_add_subtree(pi, ett_acn_channel_owner_info_block);
504 proto_tree_add_item(this_tree, hf_acn_member_id, tvb, offset, 2, ENC_BIG_ENDIAN);
506 proto_tree_add_item(this_tree, hf_acn_channel_number, tvb, offset, 2, ENC_BIG_ENDIAN);
508 offset += acn_add_address(tvb, pinfo, this_tree, offset, "Destination Address:");
509 offset += acn_add_address(tvb, pinfo, this_tree, offset, "Source Address:");
511 session_count = tvb_get_ntohs(tvb, offset);
512 for (x=0; x<session_count; x++) {
513 pi = proto_tree_add_item(this_tree, hf_acn_protocol_id, tvb, offset, 4, ENC_BIG_ENDIAN);
514 proto_item_append_text(pi, " #%d", x+1);
520 /******************************************************************************/
521 /* Adds tree branch for channel member info block */
523 acn_add_channel_member_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
526 proto_tree *this_tree;
527 guint32 session_count;
530 pi = proto_tree_add_text(tree, tvb, offset, 8, "Channel Member Info Block");
531 this_tree = proto_item_add_subtree(pi, ett_acn_channel_member_info_block);
533 proto_tree_add_item(this_tree, hf_acn_member_id, tvb, offset, 2, ENC_BIG_ENDIAN);
535 proto_tree_add_item(this_tree, hf_acn_cid, tvb, offset, 16, ENC_BIG_ENDIAN);
537 proto_tree_add_item(this_tree, hf_acn_channel_number, tvb, offset, 2, ENC_BIG_ENDIAN);
539 offset += acn_add_address(tvb, pinfo, this_tree, offset, "Destination Address:");
540 offset += acn_add_address(tvb, pinfo, this_tree, offset, "Source Address:");
541 proto_tree_add_item(this_tree, hf_acn_reciprocal_channel, tvb, offset, 2, ENC_BIG_ENDIAN);
544 session_count = tvb_get_ntohs(tvb, offset);
545 for (x=0; x<session_count; x++) {
546 pi = proto_tree_add_item(this_tree, hf_acn_protocol_id, tvb, offset, 4, ENC_BIG_ENDIAN);
547 proto_item_append_text(pi, " #%d", x+1);
554 /******************************************************************************/
555 /* Add labeled expiry */
557 acn_add_expiry(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label)
559 proto_tree_add_text(tree, tvb, offset, 2, "%s %d", label, tvb_get_guint8(tvb, offset));
565 /******************************************************************************/
566 /* Adds tree branch for channel parameters */
568 acn_add_channel_parameter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
571 proto_tree *param_tree;
573 pi = proto_tree_add_text(tree, tvb, offset, 8, "Channel Parameter Block");
574 param_tree = proto_item_add_subtree(pi, ett_acn_channel_parameter);
575 proto_tree_add_item(param_tree, hf_acn_expiry, tvb, offset, 1, ENC_BIG_ENDIAN);
577 proto_tree_add_item(param_tree, hf_acn_nak_outbound_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
579 proto_tree_add_item(param_tree, hf_acn_nak_holdoff, tvb, offset, 2, ENC_BIG_ENDIAN);
581 proto_tree_add_item(param_tree, hf_acn_nak_modulus, tvb, offset, 2, ENC_BIG_ENDIAN);
583 proto_tree_add_item(param_tree, hf_acn_nak_max_wait, tvb, offset, 2, ENC_BIG_ENDIAN);
585 return offset; /* bytes used */
589 /******************************************************************************/
590 /* Add an address tree */
592 acn_add_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label)
595 proto_tree *addr_tree = NULL;
596 guint8 ip_address_type;
601 struct e_in6_addr IPv6;
605 ip_address_type = tvb_get_guint8(tvb, offset);
607 switch (ip_address_type) {
609 proto_tree_add_item(tree, hf_acn_ip_address_type, tvb, offset, 1, ENC_BIG_ENDIAN);
613 /* Build tree and add type*/
614 pi = proto_tree_add_text(tree, tvb, offset, 7, "%s", label);
615 addr_tree = proto_item_add_subtree(pi, ett_acn_address);
616 proto_tree_add_item(addr_tree, hf_acn_ip_address_type, tvb, offset, 1, ENC_BIG_ENDIAN);
619 port = tvb_get_ntohs(tvb, offset);
620 proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, ENC_BIG_ENDIAN);
623 proto_tree_add_item(addr_tree, hf_acn_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
624 /* Append port and address to tree item */
625 IPv4 = tvb_get_ipv4(tvb, offset);
626 SET_ADDRESS(&addr, AT_IPv4, sizeof(IPv4), &IPv4);
627 proto_item_append_text(pi, " %s, Port %d", address_to_str(wmem_packet_scope(), &addr), port);
631 /* Build tree and add type*/
632 pi = proto_tree_add_text(tree, tvb, offset, 19, "%s", label);
633 addr_tree = proto_item_add_subtree(pi, ett_acn_address);
634 proto_tree_add_item(addr_tree, hf_acn_ip_address_type, tvb, offset, 1, ENC_BIG_ENDIAN);
637 port = tvb_get_ntohs(tvb, offset);
638 proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, ENC_BIG_ENDIAN);
641 proto_tree_add_item(addr_tree, hf_acn_ipv6, tvb, offset, 16, ENC_NA);
642 /* Append port and address to tree item */
643 tvb_get_ipv6(tvb, offset, &IPv6);
644 SET_ADDRESS(&addr, AT_IPv6, sizeof(struct e_in6_addr), &IPv6);
645 proto_item_append_text(pi, " %s, Port %d", address_to_str(wmem_packet_scope(), &addr), port);
648 case ACN_ADDR_IPPORT:
649 /* Build tree and add type*/
650 pi = proto_tree_add_text(tree, tvb, offset, 3, "%s", label);
651 addr_tree = proto_item_add_subtree(pi, ett_acn_address);
652 proto_tree_add_item(addr_tree, hf_acn_ip_address_type, tvb, offset, 1, ENC_BIG_ENDIAN);
655 port = tvb_get_ntohs(tvb, offset);
656 proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, ENC_BIG_ENDIAN);
657 /* Append port to tree item */
658 proto_item_append_text(pi, " %s Port %d", address_to_str(wmem_packet_scope(), &addr), port);
665 /******************************************************************************/
666 /* Adds tree branch for address type */
668 acn_add_dmp_address_type(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
671 proto_tree *this_tree = NULL;
675 /* header contains address and data type */
676 adt->flags = tvb_get_guint8(tvb, offset);
678 D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
679 name = val_to_str(D, acn_dmp_adt_d_vals, "not valid (%d)");
680 pi = proto_tree_add_text(tree, tvb, offset, 1, "Address and Data Type: %s", name);
682 this_tree = proto_item_add_subtree(pi, ett_acn_address_type);
683 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_v, tvb, offset, 1, adt->flags);
684 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_r, tvb, offset, 1, adt->flags);
685 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_d, tvb, offset, 1, adt->flags);
686 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_x, tvb, offset, 1, adt->flags);
687 proto_tree_add_uint(this_tree, hf_acn_dmp_adt_a, tvb, offset, 1, adt->flags);
690 return offset; /* bytes used */
693 /******************************************************************************/
694 /* Add an dmp address */
696 acn_add_dmp_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
698 guint32 start_offset;
702 start_offset = offset;
704 D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
705 A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
708 case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
711 switch (A) { /* address */
712 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
713 adt->address = tvb_get_guint8(tvb, offset);
717 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
718 adt->address = tvb_get_ntohs(tvb, offset);
722 case ACN_DMP_ADT_A_4: /* Four octet address, (range: one octet address, increment, and count). */
723 adt->address = tvb_get_ntohl(tvb, offset);
727 default: /* and ACN_DMP_ADT_A_R (Four octet address, (range: four octet address, increment, and count)*/
729 } /* of switch (A) */
731 if (adt->flags & ACN_DMP_ADT_FLAG_V) {
732 proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Virtual Address: 0x%X", adt->address);
734 proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Actual Address: 0x%X", adt->address);
738 case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
740 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
741 adt->address = tvb_get_guint8(tvb, offset);
743 adt->increment = tvb_get_guint8(tvb, offset);
745 adt->count = tvb_get_guint8(tvb, offset);
749 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
750 adt->address = tvb_get_ntohs(tvb, offset);
752 adt->increment = tvb_get_ntohs(tvb, offset);
754 adt->count = tvb_get_ntohs(tvb, offset);
758 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
759 adt->address = tvb_get_ntohl(tvb, offset);
761 adt->increment = tvb_get_ntohl(tvb, offset);
763 adt->count = tvb_get_ntohl(tvb, offset);
767 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
769 } /* of switch (A) */
771 if (adt->flags & ACN_DMP_ADT_FLAG_V) {
772 proto_tree_add_text(tree, tvb, start_offset, bytes_used,
773 "Virtual Address first: 0x%X, inc: %d, count: %d",
774 adt->address, adt->increment, adt->count);
776 proto_tree_add_text(tree, tvb, start_offset, bytes_used,
777 "Actual Address first: 0x%X, inc: %d, count: %d",
778 adt->address, adt->increment, adt->count);
782 case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
784 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
785 adt->address = tvb_get_guint8(tvb, offset);
787 adt->increment = tvb_get_guint8(tvb, offset);
789 adt->count = tvb_get_guint8(tvb, offset);
793 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
794 adt->address = tvb_get_ntohs(tvb, offset);
796 adt->increment = tvb_get_ntohs(tvb, offset);
798 adt->count = tvb_get_ntohs(tvb, offset);
802 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
803 adt->address = tvb_get_ntohl(tvb, offset);
805 adt->increment = tvb_get_ntohl(tvb, offset);
807 adt->count = tvb_get_ntohl(tvb, offset);
811 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
813 } /* of switch (A) */
815 if (adt->flags & ACN_DMP_ADT_FLAG_V) {
816 proto_tree_add_text(tree, tvb, start_offset, bytes_used,
817 "Virtual Address first: 0x%X, inc: %d, count: %d",
818 adt->address, adt->increment, adt->count);
820 proto_tree_add_text(tree, tvb, start_offset, bytes_used,
821 "Actual Address first: 0x%X, inc: %d, count: %d",
822 adt->address, adt->increment, adt->count);
826 case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
828 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
829 adt->address = tvb_get_guint8(tvb, offset);
831 adt->increment = tvb_get_guint8(tvb, offset);
833 adt->count = tvb_get_guint8(tvb, offset);
837 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
838 adt->address = tvb_get_ntohs(tvb, offset);
840 adt->increment = tvb_get_ntohs(tvb, offset);
842 adt->count = tvb_get_ntohs(tvb, offset);
846 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
847 adt->address = tvb_get_ntohl(tvb, offset);
849 adt->increment = tvb_get_ntohl(tvb, offset);
851 adt->count = tvb_get_ntohl(tvb, offset);
855 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
857 } /* of switch (A) */
859 if (adt->flags & ACN_DMP_ADT_FLAG_V) {
860 proto_tree_add_text(tree, tvb, start_offset, bytes_used,
861 "Virtual Address first: 0x%X, inc: %d, count: %d",
862 adt->address, adt->increment, adt->count);
864 proto_tree_add_text(tree, tvb, start_offset, bytes_used,
865 "Actual Address first: 0x%X, inc: %d, count: %d",
866 adt->address, adt->increment, adt->count);
869 } /* of switch (D) */
875 /*******************************************************************************/
876 /* Display DMP Data */
877 #define BUFFER_SIZE 128
879 acn_add_dmp_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
884 guint32 data_address;
886 gchar buffer[BUFFER_SIZE];
888 guint32 ok_to_process = FALSE;
892 /* We would like to rip through Property Address-Data pairs */
893 /* but since we don't now how many there are nor how big the data size is, */
894 /* it not possible. So, we just show the whole thing as a block of date! */
896 /* There are a few exceptions however */
897 /* 1) if the address type is ACN_DMP_ADT_D_NS or ACN_DMP_ADT_D_RS and */
898 /* or ACN_DMP_ADT_D_RE */
899 /* then number of bytes is <= count + 4. Each value is at least one byte */
900 /* and another address/data pair is at least 4 bytes so if the remaining */
901 /* bytes is less than the count plus 4 then the remaining data */
902 /* must be all data */
904 /* 2) if the address type is ACN_DMP_ADT_D_RE and the number of bytes */
905 /* equals the number of bytes in remaining in the pdu then there is */
906 /* a 1 to one match */
908 D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
910 case ACN_DMP_ADT_D_NS:
911 case ACN_DMP_ADT_D_RS:
912 if (adt->data_length <= adt->count + 4) {
913 ok_to_process = TRUE;
916 case ACN_DMP_ADT_D_RE:
917 if (adt->count == 0) {
920 if (adt->data_length <= adt->count + 4) {
921 ok_to_process = TRUE;
926 if (!ok_to_process) {
927 data_size = adt->data_length;
928 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
930 proto_item_set_text(ti, "Data and more Address-Data Pairs (further dissection not possible)");
934 A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
937 case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
938 /* calculate data size */
939 data_size = adt->data_length;
940 data_address = adt->address;
943 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
944 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
946 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
947 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
949 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
950 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
952 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
959 data_value = tvb_get_guint8(tvb, offset);
960 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %2.2X", buffer, data_value);
963 data_value = tvb_get_ntohs(tvb, offset);
964 proto_tree_add_uint_format(tree, hf_acn_data16, tvb, offset, 2, data_value, "%s %4.4X", buffer, data_value);
967 data_value = tvb_get_ntoh24(tvb, offset);
968 proto_tree_add_uint_format(tree, hf_acn_data24, tvb, offset, 3, data_value, "%s %6.6X", buffer, data_value);
971 data_value = tvb_get_ntohl(tvb, offset);
972 proto_tree_add_uint_format(tree, hf_acn_data32, tvb, offset, 4, data_value, "%s %8.8X", buffer, data_value);
975 /* build string of values */
976 for (y=0; y<20 && y<data_size; y++) {
977 data_value = tvb_get_guint8(tvb, offset+y);
978 g_snprintf(buffer, BUFFER_SIZE, "%s %2.2X", buffer, data_value);
981 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
983 /* change the text */
984 proto_item_set_text(ti, "%s", buffer);
986 } /* of switch (data_size) */
990 case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
991 /* calculate data size */
992 data_size = adt->data_length;
993 data_address = adt->address;
995 for (x=0; x<adt->count; x++) {
997 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
998 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1000 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1001 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1003 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1004 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1006 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1010 switch (data_size) {
1012 data_value = tvb_get_guint8(tvb, offset);
1013 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %2.2X", buffer, data_value);
1016 data_value = tvb_get_ntohs(tvb, offset);
1017 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 2, data_value, "%s %4.4X", buffer, data_value);
1020 data_value = tvb_get_ntoh24(tvb, offset);
1021 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 3, data_value, "%s %6.6X", buffer, data_value);
1024 data_value = tvb_get_ntohl(tvb, offset);
1025 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 4, data_value, "%s %8.8X", buffer, data_value);
1028 /* build string of values */
1029 for (y=0; y<20 && y<data_size; y++) {
1030 data_value = tvb_get_guint8(tvb, offset+y);
1031 g_snprintf(buffer, BUFFER_SIZE, "%s %2.2X", buffer, data_value);
1034 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
1035 /* change the text */
1036 proto_item_set_text(ti, "%s", buffer);
1038 } /* of switch (data_size) */
1039 data_address += adt->increment;
1040 } /* of (x=0;x<adt->count;x++) */
1041 offset += data_size;
1044 case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
1045 /* calculate data size */
1046 data_size = adt->data_length / adt->count;
1047 data_address = adt->address;
1049 for (x=0; x<adt->count; x++) {
1051 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1052 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1054 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1055 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1057 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1058 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1060 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1064 switch (data_size) {
1066 data_value = tvb_get_guint8(tvb, offset);
1067 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %2.2X", buffer, data_value);
1070 data_value = tvb_get_ntohs(tvb, offset);
1071 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 2, data_value, "%s %4.4X", buffer, data_value);
1074 data_value = tvb_get_ntoh24(tvb, offset);
1075 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 3, data_value, "%s %6.6X", buffer, data_value);
1078 data_value = tvb_get_ntohl(tvb, offset);
1079 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 4, data_value, "%s %8.8X", buffer, data_value);
1082 /* build string of values */
1083 for (y=0; y<20 && y<data_size; y++) {
1084 data_value = tvb_get_guint8(tvb, offset+y);
1085 g_snprintf(buffer, BUFFER_SIZE, "%s %2.2X", buffer, data_value);
1088 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
1089 /* change the text */
1090 proto_item_set_text(ti, "%s", buffer);
1092 } /* of switch (data_size) */
1094 offset += data_size;
1095 data_address += adt->increment;
1096 } /* of (x=0;x<adt->count;x++) */
1099 case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
1100 data_size = adt->data_length;
1101 ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, ENC_NA);
1102 offset += data_size;
1103 /* change the text */
1104 proto_item_set_text(ti, "Mixed size data items");
1106 } /* of switch (D) */
1111 /*******************************************************************************/
1112 /* Display DMP Reason codes */
1113 #define BUFFER_SIZE 128
1115 acn_add_dmp_reason_codes(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
1119 guint32 data_address;
1122 gchar buffer[BUFFER_SIZE];
1127 D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
1128 A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
1130 case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
1131 data_address = adt->address;
1133 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1134 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1136 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1137 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1139 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1140 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1142 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1147 data_value = tvb_get_guint8(tvb, offset);
1148 name = val_to_str(data_value, acn_dmp_reason_code_vals, "reason not valid (%d)");
1149 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, name);
1153 case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
1154 data_address = adt->address;
1155 for (x=0; x<adt->count; x++) {
1157 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1158 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1160 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1161 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1163 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1164 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1166 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1171 data_value = tvb_get_guint8(tvb, offset);
1172 name = val_to_str(data_value, acn_dmp_reason_code_vals, "reason not valid (%d)");
1173 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, name);
1175 data_address += adt->increment;
1176 } /* of (x=0;x<adt->count;x++) */
1180 case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
1181 case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
1182 data_address = adt->address;
1183 for (x=0; x<adt->count; x++) {
1185 case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1186 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%2.2X ->", data_address);
1188 case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1189 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%4.4X ->", data_address);
1191 case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1192 g_snprintf(buffer, BUFFER_SIZE, "Addr 0x%8.8X ->", data_address);
1194 default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1198 data_value = tvb_get_guint8(tvb, offset);
1199 name = val_to_str(data_value, acn_dmp_reason_code_vals, "reason not valid (%d)");
1200 proto_tree_add_uint_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, name);
1201 data_address += adt->increment;
1203 } /* of (x=0;x<adt->count;x++) */
1205 } /* of switch (D) */
1210 /******************************************************************************/
1211 /* Dissect wrapped SDT PDU */
1213 dissect_acn_dmp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
1215 /* common to all pdu */
1219 guint32 pdu_flvh_length; /* flags, length, vector, header */
1225 guint32 vector_offset;
1226 guint32 header_offset;
1227 guint32 data_offset;
1230 guint32 data_length;
1231 guint32 address_count;
1233 proto_item *ti, *pi;
1234 proto_tree *pdu_tree = NULL;
1235 proto_tree *flag_tree = NULL;
1239 acn_dmp_adt_type adt = {0,0,0,0,0,0};
1240 acn_dmp_adt_type adt2 = {0,0,0,0,0,0};
1243 /* save start of pdu block */
1246 /* get PDU flags and length flag first */
1247 octet = tvb_get_guint8(tvb, offset++);
1248 pdu_flags = octet & 0xf0;
1249 length1 = octet & 0x0f; /* bottom 4 bits only */
1250 length2 = tvb_get_guint8(tvb, offset++);
1252 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1253 /* flvh = flags, length, vector, header */
1254 if (pdu_flags & ACN_PDU_FLAG_L) {
1255 length3 = tvb_get_guint8(tvb, offset);
1257 pdu_length = length3 | (length2 << 8) | (length1 << 16);
1258 pdu_flvh_length = 3;
1260 pdu_length = length2 | (length1 << 8);
1261 pdu_flvh_length = 2;
1263 /* offset should now be pointing to vector (if one exists) */
1265 /* Add pdu item and tree */
1266 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
1267 pdu_tree = proto_item_add_subtree(ti, ett_acn_dmp_pdu);
1269 /* Add flag item and tree */
1270 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1271 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1272 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1273 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1274 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1275 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1277 /* Add PDU Length item */
1278 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1280 /* Set vector offset */
1281 if (pdu_flags & ACN_PDU_FLAG_V) {
1282 /* use new values */
1283 vector_offset = offset;
1284 last_pdu_offsets->vector = offset;
1288 /* use last values */
1289 vector_offset = last_pdu_offsets->vector;
1291 /* offset should now be pointing to header (if one exists) */
1293 /* Add Vector item */
1294 vector = tvb_get_guint8(tvb, vector_offset);
1295 proto_tree_add_uint(pdu_tree, hf_acn_dmp_vector, tvb, vector_offset, 1, vector);
1297 /* Add Vector item to tree*/
1298 name = val_to_str(vector, acn_dmp_vector_vals, "not valid (%d)");
1299 proto_item_append_text(ti, ": ");
1300 proto_item_append_text(ti, "%s", name);
1302 /* Set header offset */
1303 if (pdu_flags & ACN_PDU_FLAG_H) {
1304 /* use new values */
1305 header_offset = offset;
1306 last_pdu_offsets->header = offset;
1310 /* use last values */
1311 header_offset = last_pdu_offsets->header;
1313 /* offset should now be pointing to data (if one exists) */
1315 /* header contains address and data type */
1316 acn_add_dmp_address_type(tvb, pinfo, pdu_tree, header_offset, &adt);
1319 if (pdu_flags & ACN_PDU_FLAG_D) {
1320 /* use new values */
1321 data_offset = offset;
1322 data_length = pdu_length - pdu_flvh_length;
1323 last_pdu_offsets->data = offset;
1324 last_pdu_offsets->data_length = data_length;
1326 /* use last values */
1327 data_offset = last_pdu_offsets->data;
1328 data_length = last_pdu_offsets->data_length;
1330 end_offset = data_offset + data_length;
1333 case ACN_DMP_VECTOR_UNKNOWN:
1335 case ACN_DMP_VECTOR_GET_PROPERTY:
1336 /* Rip trough property address */
1337 while (data_offset < end_offset) {
1338 old_offset = data_offset;
1339 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1340 if (old_offset == data_offset) break;
1343 case ACN_DMP_VECTOR_SET_PROPERTY:
1344 /* Rip through Property Address-Data pairs */
1345 /* But, in reality, this generally won't work as we have know way of */
1346 /* calculating the next Address-Data pair */
1347 while (data_offset < end_offset) {
1348 old_offset = data_offset;
1349 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1350 if (old_offset == data_offset) break;
1352 adt.data_length = data_length - (data_offset - old_offset);
1353 old_offset = data_offset;
1354 data_offset = acn_add_dmp_data(tvb, pinfo, pdu_tree, data_offset, &adt);
1355 if (old_offset == data_offset) break;
1358 case ACN_DMP_VECTOR_GET_PROPERTY_REPLY:
1359 /* Rip through Property Address-Data pairs */
1360 /* But, in reality, this generally won't work as we have know way of */
1361 /* calculating the next Address-Data pair */
1362 while (data_offset < end_offset) {
1363 old_offset = data_offset;
1364 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1365 if (old_offset == data_offset) break;
1367 adt.data_length = data_length - (data_offset - old_offset);
1368 old_offset = data_offset;
1369 data_offset = acn_add_dmp_data(tvb, pinfo, pdu_tree, data_offset, &adt);
1370 if (old_offset == data_offset) break;
1373 case ACN_DMP_VECTOR_EVENT:
1374 /* Rip through Property Address-Data pairs */
1375 /* But, in reality, this generally won't work as we have know way of */
1376 /* calculating the next Address-Data pair */
1377 while (data_offset < end_offset) {
1378 old_offset = data_offset;
1379 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1380 if (old_offset == data_offset) break;
1382 adt.data_length = data_length - (data_offset - old_offset);
1383 old_offset = data_offset;
1384 data_offset = acn_add_dmp_data(tvb, pinfo, pdu_tree, data_offset, &adt);
1385 if (old_offset == data_offset) break;
1388 case ACN_DMP_VECTOR_MAP_PROPERTY:
1389 /* Virtual Address type */
1390 data_offset = acn_add_dmp_address_type(tvb, pinfo, pdu_tree, data_offset, &adt2);
1391 /* Rip through Actual-Virtual Address Pairs */
1392 while (data_offset < end_offset) {
1394 old_offset = data_offset;
1395 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1396 if (old_offset == data_offset) break;
1397 D = ACN_DMP_ADT_EXTRACT_D(adt.flags);
1399 case ACN_DMP_ADT_D_NS:
1402 case ACN_DMP_ADT_D_RS:
1405 case ACN_DMP_ADT_D_RE:
1406 address_count = adt.count;
1408 /*case ACN_DMP_ADT_D_RM: */
1411 return pdu_start + pdu_length;
1416 while (address_count > 0) {
1417 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt2);
1422 case ACN_DMP_VECTOR_UNMAP_PROPERTY:
1423 /* Rip trough Actaul Proptery Address */
1424 while (data_offset < end_offset) {
1425 old_offset = data_offset;
1426 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1427 if (old_offset == data_offset) break;
1430 case ACN_DMP_VECTOR_SUBSCRIBE:
1431 /* Rip trough Proptery Address */
1432 while (data_offset < end_offset) {
1433 old_offset = data_offset;
1434 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1435 if (old_offset == data_offset) break;
1438 case ACN_DMP_VECTOR_UNSUBSCRIBE:
1439 /* Rip trough Proptery Address */
1440 while (data_offset < end_offset) {
1441 old_offset = data_offset;
1442 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1443 if (old_offset == data_offset) break;
1446 case ACN_DMP_VECTOR_GET_PROPERTY_FAIL:
1447 /* Rip trough Address-Reason Code Pairs */
1448 while (data_offset < end_offset) {
1449 old_offset = data_offset;
1450 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1451 if (old_offset == data_offset) break;
1453 adt.data_length = data_length - (data_offset - old_offset);
1454 old_offset = data_offset;
1455 data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1456 if (old_offset == data_offset) break;
1459 case ACN_DMP_VECTOR_SET_PROPERTY_FAIL:
1460 /* Rip trough Address-Reason Code Pairs */
1461 while (data_offset < end_offset) {
1462 old_offset = data_offset;
1463 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1464 if (old_offset == data_offset) break;
1466 adt.data_length = data_length - (data_offset - old_offset);
1467 old_offset = data_offset;
1468 data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1469 if (old_offset == data_offset) break;
1472 case ACN_DMP_VECTOR_MAP_PROPERTY_FAIL:
1473 /* Rip trough Address-Reason Code Pairs */
1474 while (data_offset < end_offset) {
1475 old_offset = data_offset;
1476 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1477 if (old_offset == data_offset) break;
1479 adt.data_length = data_length - (data_offset - old_offset);
1480 old_offset = data_offset;
1481 data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1482 if (old_offset == data_offset) break;
1485 case ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT:
1486 /* Rip through Property Addrsses */
1487 while (data_offset < end_offset) {
1488 old_offset = data_offset;
1489 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1490 if (old_offset == data_offset) break;
1493 case ACN_DMP_VECTOR_SUBSCRIBE_REJECT:
1494 /* Rip trough Address-Reason Code Pairs */
1495 while (data_offset < end_offset) {
1496 old_offset = data_offset;
1497 data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1498 if (old_offset == data_offset) break;
1500 adt.data_length = data_length - (data_offset - old_offset);
1501 old_offset = data_offset;
1502 data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1503 if (old_offset == data_offset) break;
1506 case ACN_DMP_VECTOR_ALLOCATE_MAP:
1507 /* No data for this */
1509 case ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY:
1510 /* Single reason code */
1511 proto_tree_add_item(pdu_tree, hf_acn_dmp_reason_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
1512 /* data_offset += 1; */
1513 case ACN_DMP_VECTOR_DEALLOCATE_MAP:
1514 /* No data for this */
1518 return pdu_start + pdu_length;
1522 /******************************************************************************/
1523 /* Dissect wrapped SDT PDU */
1525 dissect_acn_sdt_wrapped_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, acn_pdu_offsets *last_pdu_offsets)
1527 /* common to all pdu */
1531 guint32 pdu_flvh_length; /* flags, length, vector, header */
1536 guint32 vector_offset;
1537 guint32 data_offset;
1538 guint32 data_length;
1540 proto_item *ti, *pi;
1541 proto_tree *pdu_tree = NULL;
1542 proto_tree *flag_tree = NULL;
1548 /* save start of pdu block */
1551 /* get PDU flags and length flag first */
1552 octet = tvb_get_guint8(tvb, offset++);
1553 pdu_flags = octet & 0xf0;
1554 length1 = octet & 0x0f; /* bottom 4 bits only */
1555 length2 = tvb_get_guint8(tvb, offset++);
1557 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1558 /* flvh = flags, length, vector, header */
1559 if (pdu_flags & ACN_PDU_FLAG_L) {
1560 length3 = tvb_get_guint8(tvb, offset);
1562 pdu_length = length3 | (length2 << 8) | (length1 << 16);
1563 pdu_flvh_length = 3;
1565 pdu_length = length2 | (length1 << 8);
1566 pdu_flvh_length = 2;
1568 /* offset should now be pointing to vector (if one exists) */
1570 /* Add pdu item and tree */
1571 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
1572 pdu_tree = proto_item_add_subtree(ti, ett_acn_sdt_pdu);
1574 /* Add flag item and tree */
1575 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1576 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1577 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1578 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1579 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1580 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1582 /* Add PDU Length item */
1583 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1585 /* Set vector offset */
1586 if (pdu_flags & ACN_PDU_FLAG_V) {
1587 /* use new values */
1588 vector_offset = offset;
1589 last_pdu_offsets->vector = offset;
1593 /* use last values */
1594 vector_offset = last_pdu_offsets->vector;
1596 /* offset should now be pointing to header (if one exists) */
1598 /* Add Vector item */
1599 vector = tvb_get_guint8(tvb, vector_offset);
1600 proto_tree_add_uint(pdu_tree, hf_acn_sdt_vector, tvb, vector_offset, 1, vector);
1602 /* Add Vector item to tree*/
1603 name = val_to_str(vector, acn_sdt_vector_vals, "not valid (%d)");
1604 proto_item_append_text(ti, ": ");
1605 proto_item_append_text(ti, "%s", name);
1607 /* NO HEADER DATA ON THESE* (at least so far) */
1610 if (pdu_flags & ACN_PDU_FLAG_D) {
1611 /* use new values */
1612 data_offset = offset;
1613 data_length = pdu_length - pdu_flvh_length;
1614 last_pdu_offsets->data = offset;
1615 last_pdu_offsets->data_length = data_length;
1617 /* use last values */
1618 data_offset = last_pdu_offsets->data;
1619 /*data_length = last_pdu_offsets->data_length;*/
1623 case ACN_SDT_VECTOR_ACK:
1624 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1625 /*data_offset += 4;*/
1627 case ACN_SDT_VECTOR_CHANNEL_PARAMS:
1628 data_offset = acn_add_channel_parameter(tvb, pinfo, pdu_tree, data_offset);
1629 data_offset = acn_add_address(tvb, pinfo, pdu_tree, data_offset, "Ad-hoc Address:");
1630 /*data_offset =*/ acn_add_expiry(tvb, pinfo, pdu_tree, data_offset, "Ad-hoc Expiry:");
1632 case ACN_SDT_VECTOR_LEAVE:
1635 case ACN_SDT_VECTOR_CONNECT:
1636 /* Protocol ID item */
1637 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1638 /*data_offset += 4;*/
1640 case ACN_SDT_VECTOR_CONNECT_ACCEPT:
1641 /* Protocol ID item */
1642 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1643 /*data_offset += 4;*/
1645 case ACN_SDT_VECTOR_CONNECT_REFUSE:
1646 /* Protocol ID item */
1647 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1649 proto_tree_add_item(pdu_tree, hf_acn_refuse_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
1650 /*data_offset += 1;*/
1652 case ACN_SDT_VECTOR_DISCONNECT:
1653 /* Protocol ID item */
1654 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1655 /*data_offset += 4;*/
1657 case ACN_SDT_VECTOR_DISCONNECTING:
1658 /* Protocol ID item */
1659 proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, ENC_BIG_ENDIAN);
1661 proto_tree_add_item(pdu_tree, hf_acn_reason_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
1662 /*data_offset += 1;*/
1667 return pdu_start + pdu_length;
1671 /******************************************************************************/
1672 /* Dissect SDT Client PDU */
1674 dissect_acn_sdt_client_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
1676 /* common to all pdu */
1680 guint32 pdu_flvh_length; /* flags, length, vector, header */
1681 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
1686 guint32 vector_offset;
1687 guint32 header_offset;
1688 guint32 data_offset;
1689 guint32 data_length;
1693 proto_item *ti, *pi;
1694 proto_tree *pdu_tree = NULL;
1695 proto_tree *flag_tree = NULL;
1700 guint32 protocol_id;
1701 guint16 association;
1703 /* save start of pdu block */
1705 pdu_offsets.start = pdu_start;
1707 /* get PDU flags and length flag first */
1708 octet = tvb_get_guint8(tvb, offset++);
1709 pdu_flags = octet & 0xf0;
1710 length1 = octet & 0x0f; /* bottom 4 bits only */
1711 length2 = tvb_get_guint8(tvb, offset++);
1713 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1714 /* flvh = flags, length, vector, header */
1715 if (pdu_flags & ACN_PDU_FLAG_L) {
1716 length3 = tvb_get_guint8(tvb, offset);
1718 pdu_length = length3 | (length2 << 8) | (length1 << 16);
1719 pdu_flvh_length = 3;
1721 pdu_length = length2 | (length1 << 8);
1722 pdu_flvh_length = 2;
1724 /* offset should now be pointing to vector (if one exists) */
1726 /* Add pdu item and tree */
1727 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
1728 pdu_tree = proto_item_add_subtree(ti, ett_acn_sdt_client_pdu);
1730 /* Add flag item and tree */
1731 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1732 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1733 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1734 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1735 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1736 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1738 /* Add PDU Length item */
1739 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1741 /* Set vector offset */
1742 if (pdu_flags & ACN_PDU_FLAG_V) {
1743 /* use new values */
1744 vector_offset = offset;
1745 last_pdu_offsets->vector = offset;
1747 pdu_flvh_length += 2;
1749 /* use last values */
1750 vector_offset = last_pdu_offsets->vector;
1752 /* offset should now be pointing to header (if one exists) */
1754 /* add Member ID item */
1755 member_id = tvb_get_ntohs(tvb, vector_offset);
1756 proto_tree_add_uint(pdu_tree, hf_acn_member_id, tvb, vector_offset, 2, member_id);
1758 /* Set header offset */
1759 if (pdu_flags & ACN_PDU_FLAG_H) {
1760 /* use new values */
1761 header_offset = offset;
1762 last_pdu_offsets->header = offset;
1764 pdu_flvh_length += 6;
1766 /* use last values */
1767 header_offset = last_pdu_offsets->header;
1769 /* offset should now be pointing to data (if one exists) */
1771 /* add Protocol ID item (Header)*/
1772 protocol_id = tvb_get_ntohl(tvb, header_offset);
1773 proto_tree_add_uint(pdu_tree, hf_acn_protocol_id, tvb, header_offset, 4, protocol_id);
1776 /* Add protocol to tree*/
1777 name = val_to_str(protocol_id, acn_protocol_id_vals, "id not valid (%d)");
1778 proto_item_append_text(ti, ": ");
1779 proto_item_append_text(ti, "%s", name);
1781 /* add association item */
1782 association = tvb_get_ntohs(tvb, header_offset);
1783 proto_tree_add_uint(pdu_tree, hf_acn_association, tvb, header_offset, 2, association);
1784 /*header_offset += 2;*/
1787 if (pdu_flags & ACN_PDU_FLAG_D) {
1788 /* use new values */
1789 data_offset = offset;
1790 data_length = pdu_length - pdu_flvh_length;
1791 last_pdu_offsets->data = offset;
1792 last_pdu_offsets->data_length = data_length;
1794 /* use last values */
1795 data_offset = last_pdu_offsets->data;
1796 data_length = last_pdu_offsets->data_length;
1798 end_offset = data_offset + data_length;
1800 switch (protocol_id) {
1801 case ACN_PROTOCOL_ID_SDT:
1802 while (data_offset < end_offset) {
1803 old_offset = data_offset;
1804 data_offset = dissect_acn_sdt_wrapped_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
1805 if (old_offset == data_offset) break;
1808 case ACN_PROTOCOL_ID_DMP:
1809 while (data_offset < end_offset) {
1810 old_offset = data_offset;
1811 data_offset = dissect_acn_dmp_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
1812 if (data_offset == old_offset) break;
1816 return pdu_start + pdu_length;
1820 /******************************************************************************/
1821 /* level to string (ascii) */
1822 /* level : 8 bit value */
1823 /* string : pointer to buffer to fill */
1824 /* leading_char: character to buffer left of digits */
1825 /* min_char : mininum number of characters (for filling, not including space)*/
1826 /* show_zero: show zeros or dots */
1827 /* also adds a space to right end */
1829 /* returns end of string */
1830 /* faster than printf() */
1832 ltos(guint8 level, gchar *string, guint8 base, gchar leading_char, guint8 min_chars, gboolean show_zero)
1836 if (base < 2 || base > 16) {
1840 /* deal with zeros */
1841 if ((level == 0) && (!show_zero)) {
1842 for (i=0; i<min_chars; i++) {
1851 /* do our convert, comes out backwards! */
1853 string[i++] = "0123456789ABCDEF"[level % base];
1854 } while ((level /= base) > 0);
1856 /* expand to needed character */
1857 for (; i<min_chars; i++) {
1858 string[i] = leading_char;
1863 /* now reverse (and correct) the order */
1864 g_strreverse(string);
1866 /* add a space at the end (ok it's at the start but it will be at the end)*/
1873 /******************************************************************************/
1874 /* Dissect DMX data PDU */
1875 #define BUFFER_SIZE 128
1877 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)
1879 /* common to all pdu */
1883 guint32 pdu_flvh_length; /* flags, length, vector, header */
1888 guint32 vector_offset;
1889 guint32 data_offset;
1891 guint32 data_length;
1892 guint32 header_offset;
1896 proto_item *ti, *pi;
1897 proto_tree *pdu_tree = NULL;
1898 proto_tree *flag_tree = NULL;
1899 /* proto_tree *addr_tree = NULL; */
1902 acn_dmp_adt_type adt = {0,0,0,0,0,0};
1905 gchar buffer[BUFFER_SIZE];
1915 guint16 dmx_start_code;
1919 /* save start of pdu block */
1922 /* get PDU flags and length flag first */
1923 octet = tvb_get_guint8(tvb, offset++);
1924 pdu_flags = octet & 0xf0;
1925 length1 = octet & 0x0f; /* bottom 4 bits only */
1926 length2 = tvb_get_guint8(tvb, offset++);
1928 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1929 /* flvh = flags, length, vector, header */
1930 if (pdu_flags & ACN_PDU_FLAG_L) {
1931 length3 = tvb_get_guint8(tvb, offset);
1933 pdu_length = length3 | (length2 << 8) | (length1 << 16);
1934 pdu_flvh_length = 3;
1936 pdu_length = length2 | (length1 << 8);
1937 pdu_flvh_length = 2;
1939 /* offset should now be pointing to vector (if one exists) */
1941 /* Add pdu item and tree */
1942 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
1943 pdu_tree = proto_item_add_subtree(ti, ett_acn_dmx_data_pdu);
1945 /* Add flag item and tree */
1946 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1947 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1948 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1949 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1950 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1951 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
1953 /* Add PDU Length item */
1954 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1956 /* Set vector offset */
1957 if (pdu_flags & ACN_PDU_FLAG_V) {
1958 /* use new values */
1959 vector_offset = offset;
1960 last_pdu_offsets->vector = offset;
1962 pdu_flvh_length += 1;
1964 /* use last values */
1965 vector_offset = last_pdu_offsets->vector;
1967 /* offset should now be pointing to header (if one exists) */
1969 /* Add Vector item */
1970 vector = tvb_get_guint8(tvb, vector_offset);
1971 proto_tree_add_uint(pdu_tree, hf_acn_dmp_vector, tvb, vector_offset, 1, vector);
1973 /* Add Vector item to tree*/
1974 name = val_to_str(vector, acn_dmp_vector_vals, "not valid (%d)");
1975 proto_item_append_text(ti, ": ");
1976 proto_item_append_text(ti, "%s", name);
1978 /* Set header offset */
1979 if (pdu_flags & ACN_PDU_FLAG_H) {
1980 /* use new values */
1981 header_offset = offset;
1982 last_pdu_offsets->header = offset;
1986 /* use last values */
1987 header_offset = last_pdu_offsets->header;
1989 /* offset should now be pointing to data (if one exists) */
1991 /* process based on vector */
1992 acn_add_dmp_address_type(tvb, pinfo, pdu_tree, header_offset, &adt);
1995 if (pdu_flags & ACN_PDU_FLAG_D) {
1996 /* use new values */
1997 data_offset = offset;
1998 data_length = pdu_length - pdu_flvh_length;
1999 last_pdu_offsets->data = offset;
2000 last_pdu_offsets->data_length = data_length;
2002 /* use last values */
2003 data_offset = last_pdu_offsets->data;
2004 data_length = last_pdu_offsets->data_length;
2006 end_offset = data_offset + data_length;
2009 case ACN_DMP_VECTOR_SET_PROPERTY:
2010 dmx_start_code = tvb_get_ntohs(tvb, data_offset);
2011 if (protocol_id==ACN_PROTOCOL_ID_DMX_2) {
2012 proto_tree_add_item(pdu_tree, hf_acn_dmx_2_first_property_address, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2014 proto_tree_add_item(pdu_tree, hf_acn_dmx_start_code, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2017 proto_tree_add_item(pdu_tree, hf_acn_dmx_increment, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2019 dmx_count = tvb_get_ntohs(tvb, data_offset);
2020 proto_tree_add_item(pdu_tree, hf_acn_dmx_count, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2023 if (protocol_id==ACN_PROTOCOL_ID_DMX_2) {
2024 proto_tree_add_item(pdu_tree, hf_acn_dmx_2_start_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2031 switch (global_acn_dmx_display_line_format) {
2032 case ACN_PREF_DMX_DISPLAY_16PL:
2041 /* values base on display mode */
2042 switch ((guint)global_acn_dmx_display_view) {
2043 case ACN_PREF_DMX_DISPLAY_HEX:
2047 /* case ACN_PREF_DMX_DISPLAY_PER: */
2053 /* do we display leading zeros */
2054 if (global_acn_dmx_display_leading_zeros) {
2060 /* add a snippet to info (this may be slow) */
2061 col_append_fstr(pinfo->cinfo,COL_INFO, ", Sc %02x, [%02x %02x %02x %02x %02x %02x...]",
2063 tvb_get_guint8(tvb, data_offset),
2064 tvb_get_guint8(tvb, data_offset+1),
2065 tvb_get_guint8(tvb, data_offset+2),
2066 tvb_get_guint8(tvb, data_offset+3),
2067 tvb_get_guint8(tvb, data_offset+4),
2068 tvb_get_guint8(tvb, data_offset+5));
2070 /* add a header line */
2071 g_snprintf(buffer, BUFFER_SIZE, "%-10s: ", "Data...");
2074 for (x=0; x<perline; x++) {
2075 buf_ptr = ltos((guint8)(x+1), buf_ptr, 10, ' ', min_char, FALSE);
2076 if ((x+1)==halfline) {
2082 proto_tree_add_text(pdu_tree, tvb, data_offset, dmx_count, "%s", buffer);
2084 /* start our line */
2085 g_snprintf(buffer, BUFFER_SIZE, "001-%03d: ", perline);
2086 buf_ptr = buffer + 9;
2090 for (x=data_offset; x<end_offset; x++) {
2091 level = tvb_get_guint8(tvb, x);
2092 if (global_acn_dmx_display_view==ACN_PREF_DMX_DISPLAY_PER) {
2093 if ((level > 0) && (level < 3)) {
2096 level = level * 100 / 255;
2099 buf_ptr = ltos(level, buf_ptr, base, leading_char, min_char, global_acn_dmx_display_zeros);
2103 if (item_cnt == perline || x == (end_offset-1)) {
2105 proto_tree_add_text(pdu_tree, tvb, data_offset, item_cnt, "%s", buffer);
2106 data_offset += perline;
2107 g_snprintf(buffer, BUFFER_SIZE, "%03d-%03d: ",total_cnt, total_cnt+perline);
2108 buf_ptr = buffer + 9;
2111 /* add separator character */
2112 if (item_cnt == halfline) {
2120 address data type (fixed at 0xA2)
2121 start code - 1 byte, reserved (should be 0)
2122 - 1 byte, start code (0x255)
2123 - 2 bytes, packet offset (should be 0000)
2124 address increment - 4 bytes (ignore)
2125 number of dmx values - 4 bytes (0-512)
2126 dmx values 0-512 bytes (data)
2131 return pdu_start + pdu_length;
2136 /******************************************************************************/
2137 /* Dissect DMX Base PDU */
2139 dissect_acn_dmx_pdu(guint32 protocol_id, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
2141 /* common to all pdu */
2145 guint32 pdu_flvh_length; /* flags, length, vector, header */
2146 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2148 guint8 option_flags;
2152 guint32 vector_offset;
2153 guint32 data_offset;
2154 guint32 data_length;
2156 proto_item *ti, *pi;
2157 proto_tree *pdu_tree = NULL;
2158 proto_tree *flag_tree = NULL;
2169 /* save start of pdu block */
2171 pdu_offsets.start = pdu_start;
2173 /* get PDU flags and length flag first */
2174 octet = tvb_get_guint8(tvb, offset++);
2175 pdu_flags = octet & 0xf0;
2176 length1 = octet & 0x0f; /* bottom 4 bits only */
2177 length2 = tvb_get_guint8(tvb, offset++);
2179 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2180 /* flvh = flags, length, vector, header */
2181 if (pdu_flags & ACN_PDU_FLAG_L) {
2182 length3 = tvb_get_guint8(tvb, offset);
2184 pdu_length = length3 | (length2 << 8) | (length1 << 16);
2185 pdu_flvh_length = 3;
2187 pdu_length = length2 | (length1 << 8);
2188 pdu_flvh_length = 2;
2191 /* offset should now be pointing to vector (if one exists) */
2193 /* Add pdu item and tree */
2194 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
2195 pdu_tree = proto_item_add_subtree(ti, ett_acn_dmx_pdu);
2197 /* Add flag item and tree */
2198 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
2199 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
2200 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2201 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2202 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2203 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2205 /* Add PDU Length item */
2206 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
2208 /* Set vector offset */
2209 if (pdu_flags & ACN_PDU_FLAG_V) {
2210 /* use new values */
2211 vector_offset = offset;
2212 last_pdu_offsets->vector = offset;
2214 pdu_flvh_length += 4;
2216 /* use last values */
2217 vector_offset = last_pdu_offsets->vector;
2219 /* offset should now be pointing to header (if one exists) */
2221 /* Add Vector item */
2222 vector = tvb_get_ntohl(tvb, vector_offset);
2223 proto_tree_add_item(pdu_tree, hf_acn_dmx_vector, tvb, vector_offset, 4, ENC_BIG_ENDIAN);
2224 /* vector_offset +=4; */
2226 /* Add Vector item to tree*/
2227 name = val_to_str(vector, acn_dmx_vector_vals, "not valid (%d)");
2228 proto_item_append_text(ti, ": %s", name);
2230 /* NO HEADER DATA ON THESE* (at least so far) */
2233 if (pdu_flags & ACN_PDU_FLAG_D) {
2234 /* use new values */
2235 data_offset = offset;
2236 data_length = pdu_length - pdu_flvh_length;
2237 last_pdu_offsets->data = offset;
2238 last_pdu_offsets->data_length = data_length;
2240 /* use last values */
2241 data_offset = last_pdu_offsets->data;
2242 /*data_length = last_pdu_offsets->data_length;*/
2245 /* process based on vector */
2248 if (protocol_id==ACN_PROTOCOL_ID_DMX_2) {
2249 proto_tree_add_item(pdu_tree, hf_acn_dmx_source_name, tvb, data_offset, 64, ENC_UTF_8|ENC_NA);
2252 proto_tree_add_item(pdu_tree, hf_acn_dmx_source_name, tvb, data_offset, 32, ENC_UTF_8|ENC_NA);
2256 priority = tvb_get_guint8(tvb, data_offset);
2257 proto_tree_add_item(pdu_tree, hf_acn_dmx_priority, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2260 if (protocol_id==ACN_PROTOCOL_ID_DMX_2) {
2261 proto_tree_add_item(pdu_tree, hf_acn_dmx_2_reserved, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2265 sequence = tvb_get_guint8(tvb, data_offset);
2266 proto_tree_add_item(pdu_tree, hf_acn_dmx_sequence_number, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2269 if (protocol_id == ACN_PROTOCOL_ID_DMX_2) {
2270 option_flags = tvb_get_guint8(tvb, data_offset);
2271 pi = proto_tree_add_uint(pdu_tree, hf_acn_dmx_2_options, tvb, data_offset, 1, option_flags);
2272 flag_tree = proto_item_add_subtree(pi, ett_acn_dmx_2_options);
2273 proto_tree_add_item(flag_tree, hf_acn_dmx_2_option_p, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2274 proto_tree_add_item(flag_tree, hf_acn_dmx_2_option_s, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2278 universe = tvb_get_ntohs(tvb, data_offset);
2279 proto_tree_add_item(pdu_tree, hf_acn_dmx_universe , tvb, data_offset, 2, ENC_BIG_ENDIAN);
2282 /* add universe to info */
2283 col_append_fstr(pinfo->cinfo,COL_INFO, ", Universe %d, Seq %3d", universe, sequence );
2284 proto_item_append_text(ti, ", Universe: %d, Priority: %d", universe, priority);
2286 /*data_offset =*/ dissect_acn_dmx_data_pdu(protocol_id, tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2290 return pdu_start + pdu_length;
2293 /******************************************************************************/
2294 /* Dissect SDT Base PDU */
2296 dissect_acn_sdt_base_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
2298 /* common to all pdu */
2302 guint32 pdu_flvh_length; /* flags, length, vector, header */
2303 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2308 guint32 vector_offset;
2309 guint32 data_offset;
2312 guint32 data_length;
2314 proto_item *ti, *pi;
2315 proto_tree *pdu_tree = NULL;
2316 proto_tree *flag_tree = NULL;
2323 /* save start of pdu block */
2325 pdu_offsets.start = pdu_start;
2327 /* get PDU flags and length flag first */
2328 octet = tvb_get_guint8(tvb, offset++);
2329 pdu_flags = octet & 0xf0;
2330 length1 = octet & 0x0f; /* bottom 4 bits only */
2331 length2 = tvb_get_guint8(tvb, offset++);
2333 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2334 /* flvh = flags, length, vector, header */
2335 if (pdu_flags & ACN_PDU_FLAG_L) {
2336 length3 = tvb_get_guint8(tvb, offset);
2338 pdu_length = length3 | (length2 << 8) | (length1 << 16);
2339 pdu_flvh_length = 3;
2341 pdu_length = length2 | (length1 << 8);
2342 pdu_flvh_length = 2;
2344 /* offset should now be pointing to vector (if one exists) */
2346 /* Add pdu item and tree */
2347 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
2348 pdu_tree = proto_item_add_subtree(ti, ett_acn_sdt_base_pdu);
2350 /* Add flag item and tree */
2351 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
2352 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
2353 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2354 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2355 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2356 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2358 /* Add PDU Length item */
2359 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
2361 /* Set vector offset */
2362 if (pdu_flags & ACN_PDU_FLAG_V) {
2363 /* use new values */
2364 vector_offset = offset;
2365 last_pdu_offsets->vector = offset;
2369 /* use last values */
2370 vector_offset = last_pdu_offsets->vector;
2372 /* offset should now be pointing to header (if one exists) */
2374 /* Add Vector item */
2375 vector = tvb_get_guint8(tvb, vector_offset);
2376 proto_tree_add_uint(pdu_tree, hf_acn_sdt_vector, tvb, vector_offset, 1, vector);
2378 /* Add Vector item to tree*/
2379 name = val_to_str(vector, acn_sdt_vector_vals, "not valid (%d)");
2380 proto_item_append_text(ti, ": ");
2381 proto_item_append_text(ti, "%s", name);
2383 /* NO HEADER DATA ON THESE* (at least so far) */
2386 if (pdu_flags & ACN_PDU_FLAG_D) {
2387 /* use new values */
2388 data_offset = offset;
2389 data_length = pdu_length - pdu_flvh_length;
2390 last_pdu_offsets->data = offset;
2391 last_pdu_offsets->data_length = data_length;
2393 /* use last values */
2394 data_offset = last_pdu_offsets->data;
2395 data_length = last_pdu_offsets->data_length;
2397 end_offset = data_offset + data_length;
2399 /* process based on vector */
2401 case ACN_SDT_VECTOR_UNKNOWN:
2403 case ACN_SDT_VECTOR_REL_WRAP:
2404 case ACN_SDT_VECTOR_UNREL_WRAP:
2405 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2407 proto_tree_add_item(pdu_tree, hf_acn_total_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2409 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2411 proto_tree_add_item(pdu_tree, hf_acn_oldest_available_wrapper, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2413 proto_tree_add_item(pdu_tree, hf_acn_first_memeber_to_ack, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2415 proto_tree_add_item(pdu_tree, hf_acn_last_memeber_to_ack, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2417 proto_tree_add_item(pdu_tree, hf_acn_mak_threshold, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2420 while (data_offset < end_offset) {
2421 old_offset = data_offset;
2422 data_offset = dissect_acn_sdt_client_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2423 if (data_offset == old_offset) break;
2426 case ACN_SDT_VECTOR_CHANNEL_PARAMS:
2428 case ACN_SDT_VECTOR_JOIN:
2429 proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2431 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2433 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2435 proto_tree_add_item(pdu_tree, hf_acn_reciprocal_channel, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2437 proto_tree_add_item(pdu_tree, hf_acn_total_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2439 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2441 data_offset = acn_add_address(tvb, pinfo, pdu_tree, data_offset, "Destination Address:");
2442 data_offset = acn_add_channel_parameter(tvb, pinfo, pdu_tree, data_offset);
2443 /*data_offset =*/ acn_add_expiry(tvb, pinfo, pdu_tree, data_offset, "Ad-hoc Expiry:");
2445 case ACN_SDT_VECTOR_JOIN_REFUSE:
2446 pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2448 proto_item_append_text(pi, "(Leader)");
2449 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2451 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2453 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2455 proto_tree_add_item(pdu_tree, hf_acn_refuse_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2458 case ACN_SDT_VECTOR_JOIN_ACCEPT:
2459 pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2461 proto_item_append_text(pi, "(Leader)");
2462 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2464 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2466 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2468 proto_tree_add_item(pdu_tree, hf_acn_reciprocal_channel, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2469 /*data_offset += 2;*/
2471 case ACN_SDT_VECTOR_LEAVE:
2473 case ACN_SDT_VECTOR_LEAVING:
2474 pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2476 proto_item_append_text(pi, "(Leader)");
2477 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2479 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2481 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2483 proto_tree_add_item(pdu_tree, hf_acn_reason_code, tvb, data_offset, 1, ENC_BIG_ENDIAN);
2486 case ACN_SDT_VECTOR_CONNECT:
2488 case ACN_SDT_VECTOR_CONNECT_ACCEPT:
2490 case ACN_SDT_VECTOR_CONNECT_REFUSE:
2492 case ACN_SDT_VECTOR_DISCONNECT:
2494 case ACN_SDT_VECTOR_DISCONNECTING:
2496 case ACN_SDT_VECTOR_ACK:
2498 case ACN_SDT_VECTOR_NAK:
2499 pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2501 proto_item_append_text(pi, "(Leader)");
2502 proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2504 proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2506 proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2508 proto_tree_add_item(pdu_tree, hf_acn_first_missed_sequence, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2510 proto_tree_add_item(pdu_tree, hf_acn_last_missed_sequence, tvb, data_offset, 4, ENC_BIG_ENDIAN);
2511 /*data_offset += 4;*/
2513 case ACN_SDT_VECTOR_GET_SESSION:
2514 proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, ENC_BIG_ENDIAN);
2515 /*data_offset += 16;*/
2517 case ACN_SDT_VECTOR_SESSIONS:
2518 member_id = tvb_get_ntohs(tvb, data_offset);
2519 switch (member_id) {
2521 /*data_offset =*/ acn_add_channel_owner_info_block(tvb, pinfo, pdu_tree, data_offset);
2524 /*data_offset =*/ acn_add_channel_member_info_block(tvb, pinfo, pdu_tree, data_offset);
2530 return pdu_start + pdu_length;
2533 /******************************************************************************/
2534 /* Dissect Root PDU */
2536 dissect_acn_root_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
2538 /* common to all pdu */
2542 guint32 pdu_flvh_length; /* flags, length, vector, header */
2543 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2548 guint32 vector_offset;
2549 guint32 header_offset;
2550 guint32 data_offset;
2553 guint32 data_length;
2555 proto_item *ti, *pi;
2556 proto_tree *pdu_tree = NULL;
2557 proto_tree *flag_tree = NULL;
2560 guint32 protocol_id;
2563 /* save start of pdu block */
2565 pdu_offsets.start = pdu_start;
2567 /* get PDU flags and length flag first */
2568 octet = tvb_get_guint8(tvb, offset++);
2569 pdu_flags = octet & 0xf0;
2570 length1 = octet & 0x0f; /* bottom 4 bits only */
2571 length2 = tvb_get_guint8(tvb, offset++);
2573 /* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2574 /* flvh = flags, length, vector, header */
2575 if (pdu_flags & ACN_PDU_FLAG_L) {
2576 length3 = tvb_get_guint8(tvb, offset);
2578 pdu_length = length3 | (length2 << 8) | (length1 << 16);
2579 pdu_flvh_length = 3;
2581 pdu_length = length2 | (length1 << 8);
2582 pdu_flvh_length = 2;
2584 /* offset should now be pointing to vector (if one exists) */
2586 /* Add pdu item and tree */
2587 ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, ENC_NA);
2588 pdu_tree = proto_item_add_subtree(ti, ett_acn_root_pdu);
2590 /* Add flag item and tree */
2591 pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
2592 flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
2593 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2594 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2595 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2596 proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, ENC_BIG_ENDIAN);
2598 /* Add PDU Length item */
2599 proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
2601 /* Set vector offset */
2602 if (pdu_flags & ACN_PDU_FLAG_V) {
2603 /* use new values */
2604 vector_offset = offset;
2605 last_pdu_offsets->vector = offset;
2607 pdu_flvh_length += 4;
2609 /* use last values */
2610 vector_offset = last_pdu_offsets->vector;
2612 /* offset should now be pointing to header (if one exists) */
2616 /* Get Protocol ID (vector) */
2617 protocol_id = tvb_get_ntohl(tvb, vector_offset);
2618 proto_tree_add_uint(pdu_tree, hf_acn_protocol_id, tvb, vector_offset, 4, protocol_id);
2620 /* process based on protocol_id */
2621 switch (protocol_id) {
2622 case ACN_PROTOCOL_ID_DMX:
2623 case ACN_PROTOCOL_ID_DMX_2:
2624 if (global_acn_dmx_enable) {
2625 proto_item_append_text(ti,": Root DMX");
2627 /* Set header offset */
2628 if (pdu_flags & ACN_PDU_FLAG_H) {
2629 /* use new values */
2630 header_offset = offset;
2631 last_pdu_offsets->header = offset;
2633 pdu_flvh_length += 16;
2635 /* use last values */
2636 header_offset = last_pdu_offsets->header;
2638 /* offset should now be pointing to data (if one exists) */
2640 /* get Header (CID) 16 bytes */
2641 tvb_get_guid(tvb, header_offset, &guid, ENC_BIG_ENDIAN);
2642 proto_item_append_text(ti, ", Src: %s", guid_to_ep_str(&guid));
2644 /* add cid to info */
2645 col_add_fstr(pinfo->cinfo,COL_INFO, "CID %s", guid_to_ep_str(&guid));
2647 proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, header_offset, 16, ENC_BIG_ENDIAN);
2648 /*header_offset += 16;*/
2651 if (pdu_flags & ACN_PDU_FLAG_D) {
2652 /* use new values */
2653 data_offset = offset;
2654 data_length = pdu_length - pdu_flvh_length;
2655 last_pdu_offsets->data = offset;
2656 last_pdu_offsets->data_length = data_length;
2658 /* use last values */
2659 data_offset = last_pdu_offsets->data;
2660 data_length = last_pdu_offsets->data_length;
2662 end_offset = data_offset + data_length;
2664 /* adjust for what we used */
2665 while (data_offset < end_offset) {
2666 old_offset = data_offset;
2667 data_offset = dissect_acn_dmx_pdu(protocol_id, tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2668 if (data_offset == old_offset) break;
2672 case ACN_PROTOCOL_ID_SDT:
2674 proto_item_append_text(ti,": Root SDT");
2676 /* Set header offset */
2677 if (pdu_flags & ACN_PDU_FLAG_H) {
2678 /* use new values */
2679 header_offset = offset;
2680 last_pdu_offsets->header = offset;
2682 pdu_flvh_length += 16;
2684 /* use last values */
2685 header_offset = last_pdu_offsets->header;
2687 /* offset should now be pointing to data (if one exists) */
2689 /* get Header (CID) 16 bytes */
2690 tvb_get_guid(tvb, header_offset, &guid, ENC_BIG_ENDIAN);
2691 proto_item_append_text(ti, ", Src: %s", guid_to_ep_str(&guid));
2693 proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, header_offset, 16, ENC_BIG_ENDIAN);
2694 /*header_offset += 16;*/
2697 if (pdu_flags & ACN_PDU_FLAG_D) {
2698 /* use new values */
2699 data_offset = offset;
2700 data_length = pdu_length - pdu_flvh_length;
2701 last_pdu_offsets->data = offset;
2702 last_pdu_offsets->data_length = data_length;
2704 /* use last values */
2705 data_offset = last_pdu_offsets->data;
2706 data_length = last_pdu_offsets->data_length;
2708 end_offset = data_offset + data_length;
2710 /* adjust for what we used */
2711 while (data_offset < end_offset) {
2712 old_offset = data_offset;
2713 data_offset = dissect_acn_sdt_base_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2714 if (data_offset == old_offset) break;
2719 return pdu_start + pdu_length;
2722 /******************************************************************************/
2725 dissect_acn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2727 proto_item *ti = NULL;
2728 proto_tree *acn_tree = NULL;
2729 guint32 data_offset = 0;
2732 acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2734 /* if (!is_acn(tvb)) { */
2738 /* Set the protocol column */
2739 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACN");
2741 col_add_fstr(pinfo->cinfo,COL_INFO, "ACN [Src Port: %d, Dst Port: %d]", pinfo->srcport, pinfo->destport );
2743 if (tree) { /* we are being asked for details */
2744 ti = proto_tree_add_item(tree, proto_acn, tvb, 0, -1, ENC_NA);
2745 acn_tree = proto_item_add_subtree(ti, ett_acn);
2747 /* add preamble, postamble and ACN Packet ID */
2748 proto_tree_add_item(acn_tree, hf_acn_preamble_size, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2750 proto_tree_add_item(acn_tree, hf_acn_postamble_size, tvb, data_offset, 2, ENC_BIG_ENDIAN);
2752 proto_tree_add_item(acn_tree, hf_acn_packet_identifier, tvb, data_offset, 12, ENC_UTF_8|ENC_NA);
2755 /* one past the last byte */
2756 end_offset = data_offset + tvb_reported_length_remaining(tvb, data_offset);
2757 while (data_offset < end_offset) {
2758 old_offset = data_offset;
2759 data_offset = dissect_acn_root_pdu(tvb, pinfo, acn_tree, data_offset, &pdu_offsets);
2760 if (data_offset == old_offset) break;
2763 return tvb_length(tvb);
2766 /******************************************************************************/
2767 /* Register protocol */
2769 proto_register_acn(void)
2771 static hf_register_info hf[] = {
2772 /**************************************************************************/
2773 /* In alphabetical order */
2776 { &hf_acn_ip_address_type,
2777 { "Addr Type", "acn.ip_address_type",
2778 FT_UINT8, BASE_DEC, VALS(acn_ip_address_type_vals), 0x0,
2782 { &hf_acn_association,
2783 { "Association", "acn.association",
2784 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2787 /* Channel Number */
2788 { &hf_acn_channel_number,
2789 { "Channel Number", "acn.channel_number",
2790 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2796 FT_GUID, BASE_NONE, NULL, 0x0,
2799 /* Client Protocol ID */
2801 { &hf_acn_client_protocol_id,
2802 { "Client Protocol ID", "acn.client_protocol_id",
2803 FT_UINT32, BASE_DEC, VALS(acn_protocol_id_vals), 0x0,
2809 { "Data", "acn.dmp_data",
2810 FT_BYTES, BASE_NONE, NULL, 0x0,
2814 { "Addr", "acn.dmp_data8",
2815 FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
2819 { "Addr", "acn.dmp_data16",
2820 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2824 { "Addr", "acn.dmp_data24",
2825 FT_UINT24, BASE_DEC_HEX, NULL, 0x0,
2829 { "Addr", "acn.dmp_data32",
2830 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2834 /* DMP Address type*/
2837 { "Address and Data Type", "acn.dmp_adt",
2838 FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
2842 { &hf_acn_dmp_adt_a,
2843 { "Size", "acn.dmp_adt_a",
2844 FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_a_vals), 0x03,
2847 { &hf_acn_dmp_adt_d,
2848 { "Data Type", "acn.dmp_adt_d",
2849 FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_d_vals), 0x30,
2852 { &hf_acn_dmp_adt_r,
2853 { "Relative", "acn.dmp_adt_r",
2854 FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_r_vals), 0x40,
2857 { &hf_acn_dmp_adt_v,
2858 { "Virtual", "acn.dmp_adt_v",
2859 FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_v_vals), 0x80,
2862 { &hf_acn_dmp_adt_x,
2863 { "Reserved", "acn.dmp_adt_x",
2864 FT_UINT8, BASE_DEC, NULL, 0x0c,
2868 /* DMP Reason Code */
2869 { &hf_acn_dmp_reason_code,
2870 { "Reason Code", "acn.dmp_reason_code",
2871 FT_UINT8, BASE_DEC, VALS(acn_dmp_reason_code_vals), 0x0,
2876 { &hf_acn_dmp_vector,
2877 { "DMP Vector", "acn.dmp_vector",
2878 FT_UINT8, BASE_DEC, VALS(acn_dmp_vector_vals), 0x0,
2883 { "Expiry", "acn.expiry",
2884 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2887 /* First Member to ACK */
2888 { &hf_acn_first_memeber_to_ack,
2889 { "First Member to ACK", "acn.first_member_to_ack",
2890 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2893 /* First Missed Sequence */
2894 { &hf_acn_first_missed_sequence,
2895 { "First Missed Sequence", "acn.first_missed_sequence",
2896 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2901 { "IPV4", "acn.ipv4",
2902 FT_IPv4, BASE_NONE, NULL, 0x0,
2907 { "IPV6", "acn.ipv6",
2908 FT_IPv6, BASE_NONE, NULL, 0x0,
2911 /* Last Member to ACK */
2912 { &hf_acn_last_memeber_to_ack,
2913 { "Last Member to ACK", "acn.last_member_to_ack",
2914 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2917 /* Last Missed Sequence */
2918 { &hf_acn_last_missed_sequence,
2919 { "Last Missed Sequence", "acn.last_missed_sequence",
2920 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2924 { &hf_acn_mak_threshold,
2925 { "MAK Threshold", "acn.mak_threshold",
2926 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2930 { &hf_acn_member_id,
2931 { "Member ID", "acn.member_id",
2932 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2936 { &hf_acn_nak_holdoff,
2937 { "NAK holdoff (ms)", "acn.nak_holdoff",
2938 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2942 { &hf_acn_nak_max_wait,
2943 { "NAK Max Wait (ms)", "acn.nak_max_wait",
2944 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2948 { &hf_acn_nak_modulus,
2949 { "NAK Modulus", "acn.nak_modulus",
2950 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2953 /* NAK Outbound Flag */
2954 { &hf_acn_nak_outbound_flag,
2955 { "NAK Outbound Flag", "acn.nak_outbound_flag",
2956 FT_BOOLEAN, 8, NULL, 0x80,
2959 /* Oldest Available Wrapper */
2960 { &hf_acn_oldest_available_wrapper,
2961 { "Oldest Available Wrapper", "acn.oldest_available_wrapper",
2962 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2965 /* Preamble Sizet */
2966 { &hf_acn_preamble_size,
2967 { "Size of preamble", "acn.preamble_size",
2968 FT_UINT16, BASE_DEC, NULL, 0x0,
2969 "Preamble size in bytes", HFILL }
2971 /* Packet Identifier */
2972 { &hf_acn_packet_identifier,
2973 { "Packet Identifier", "acn.packet_identifier",
2974 FT_STRING, BASE_NONE, NULL, 0x0,
2980 FT_NONE, BASE_NONE, NULL, 0x0,
2984 { &hf_acn_pdu_flags,
2985 { "Flags", "acn.pdu.flags",
2986 FT_UINT8, BASE_HEX, NULL, 0x0,
2987 "PDU Flags", HFILL }
2989 { &hf_acn_pdu_flag_d,
2990 { "Data", "acn.pdu.flag_d",
2991 FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_D,
2992 "Data flag", HFILL }
2994 { &hf_acn_pdu_flag_h,
2995 { "Header", "acn.pdu.flag_h",
2996 FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_H,
2997 "Header flag", HFILL }
2999 { &hf_acn_pdu_flag_l,
3000 { "Length", "acn.pdu.flag_l",
3001 FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_L,
3002 "Length flag", HFILL }
3004 { &hf_acn_pdu_flag_v,
3005 { "Vector", "acn.pdu.flag_v",
3006 FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_V,
3007 "Vector flag", HFILL }
3010 { &hf_acn_pdu_length,
3011 { "Length", "acn.pdu.length",
3012 FT_UINT32, BASE_DEC, NULL, 0x0,
3013 "PDU Length", HFILL }
3017 { "Port", "acn.port",
3018 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3021 /* Postamble Size */
3022 { &hf_acn_postamble_size,
3023 { "Size of postamble", "acn.postamble_size",
3024 FT_UINT16, BASE_DEC, NULL, 0x0,
3025 "Postamble size in bytes", HFILL }
3028 { &hf_acn_protocol_id,
3029 { "Protocol ID", "acn.protocol_id",
3030 FT_UINT32, BASE_DEC, VALS(acn_protocol_id_vals), 0x0,
3034 { &hf_acn_reason_code,
3035 { "Reason Code", "acn.reason_code",
3036 FT_UINT8, BASE_DEC, VALS(acn_reason_code_vals), 0x0,
3039 /* Reciprocal Channel */
3040 { &hf_acn_reciprocal_channel,
3041 { "Reciprocal Channel Number", "acn.reciprocal_channel",
3042 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3043 "Reciprocal Channel", HFILL }
3046 { &hf_acn_refuse_code,
3047 { "Refuse Code", "acn.refuse_code",
3048 FT_UINT8, BASE_DEC, VALS(acn_refuse_code_vals), 0x0,
3051 /* Reliable Sequence Number */
3052 { &hf_acn_reliable_sequence_number,
3053 { "Reliable Sequence Number", "acn.reliable_sequence_number",
3054 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
3058 { &hf_acn_sdt_vector,
3059 { "STD Vector", "acn.sdt_vector",
3060 FT_UINT8, BASE_DEC, VALS(acn_sdt_vector_vals), 0x0,
3065 { &hf_acn_dmx_vector,
3066 { "Vector", "acn.dmx_vector",
3067 FT_UINT32, BASE_DEC, VALS(acn_dmx_vector_vals), 0x0,
3068 "DMX Vector", HFILL }
3070 /* DMX Source Name */
3071 { &hf_acn_dmx_source_name,
3072 { "Source", "acn.dmx.source_name",
3073 FT_STRING, BASE_NONE, NULL, 0x0,
3074 "DMX Source Name", HFILL }
3078 { &hf_acn_dmx_priority,
3079 { "Priority", "acn.dmx.priority",
3080 FT_UINT8, BASE_DEC, NULL, 0x0,
3081 "DMX Priority", HFILL }
3084 /* DMX 2 reserved */
3085 { &hf_acn_dmx_2_reserved,
3086 { "Reserved", "acn.dmx.reserved",
3087 FT_UINT16, BASE_DEC, NULL, 0x0,
3088 "DMX Reserved", HFILL }
3091 /* DMX Sequence number */
3092 { &hf_acn_dmx_sequence_number,
3093 { "Seq No", "acn.dmx.seq_number",
3094 FT_UINT8, BASE_DEC, NULL, 0x0,
3095 "DMX Sequence Number", HFILL }
3099 { &hf_acn_dmx_2_options,
3100 { "Options", "acn.dmx.options",
3101 FT_UINT8, BASE_DEC, NULL, 0x0,
3102 "DMX Options", HFILL }
3105 { &hf_acn_dmx_2_option_p,
3106 { "Preview Data", "acn.dmx.option_p",
3107 FT_BOOLEAN, 8, NULL, ACN_DMX_OPTION_P,
3108 "Preview Data flag", HFILL }
3111 { &hf_acn_dmx_2_option_s,
3112 { "Stream Terminated", "acn.dmx.option_s",
3113 FT_BOOLEAN, 8, NULL, ACN_DMX_OPTION_S,
3114 "Stream Terminated flag", HFILL }
3118 { &hf_acn_dmx_universe,
3119 { "Universe", "acn.dmx.universe",
3120 FT_UINT16, BASE_DEC, NULL, 0x0,
3121 "DMX Universe", HFILL }
3124 /* DMX Start Code */
3125 { &hf_acn_dmx_start_code,
3126 { "Start Code", "acn.dmx.start_code",
3127 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3128 "DMX Start Code", HFILL }
3131 /* DMX 2 First Property Address */
3132 { &hf_acn_dmx_2_first_property_address,
3133 { "First Property Address", "acn.dmx.start_code",
3134 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3135 "DMX First Property Address", HFILL }
3138 /* DMX Address Increment */
3139 { &hf_acn_dmx_increment,
3140 { "Increment", "acn.dmx.increment",
3141 FT_UINT16, BASE_DEC, NULL, 0x0,
3142 "DMX Increment", HFILL }
3145 /* DMX Packet Count */
3146 { &hf_acn_dmx_count,
3147 { "Count", "acn.dmx.count",
3148 FT_UINT16, BASE_DEC, NULL, 0x0,
3149 "DMX Count", HFILL }
3152 /* DMX 2 Start Code */
3153 { &hf_acn_dmx_2_start_code,
3154 { "Start Code", "acn.dmx.start_code2",
3155 FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
3156 "DMX Start Code", HFILL }
3161 { &hf_acn_session_count,
3162 { "Session Count", "acn.session_count",
3163 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
3167 /* Total Sequence Number */
3168 { &hf_acn_total_sequence_number,
3169 { "Total Sequence Number", "acn.total_sequence_number",
3170 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
3175 /* Setup protocol subtree array */
3176 static gint *ett[] = {
3178 &ett_acn_channel_owner_info_block,
3179 &ett_acn_channel_member_info_block,
3180 &ett_acn_channel_parameter,
3182 &ett_acn_address_type,
3186 &ett_acn_sdt_client_pdu,
3187 &ett_acn_sdt_base_pdu,
3189 &ett_acn_dmx_address,
3190 &ett_acn_dmx_2_options,
3191 &ett_acn_dmx_data_pdu,
3195 module_t *acn_module;
3196 proto_acn = proto_register_protocol (
3197 "Architecture for Control Networks", /* name */
3198 "ACN", /* short name */
3202 proto_register_field_array(proto_acn, hf, array_length(hf));
3203 proto_register_subtree_array(ett, array_length(ett));
3205 acn_module = prefs_register_protocol(proto_acn, NULL);
3206 prefs_register_bool_preference(acn_module, "heuristic_acn",
3208 "Enable Architecture for Control Networks dissector (ANSI BSR E1.17)",
3211 prefs_register_bool_preference(acn_module, "dmx_enable",
3213 "Enable Streaming DMX extension dissector (ANSI BSR E1.31)",
3214 &global_acn_dmx_enable);
3216 prefs_register_enum_preference(acn_module, "dmx_display_view",
3217 "DMX, display format",
3219 &global_acn_dmx_display_view,
3223 prefs_register_bool_preference(acn_module, "dmx_display_zeros",
3224 "DMX, display zeros",
3225 "Display zeros instead of dots",
3226 &global_acn_dmx_display_zeros);
3228 prefs_register_bool_preference(acn_module, "dmx_display_leading_zeros",
3229 "DMX, display leading zeros",
3230 "Display leading zeros on levels",
3231 &global_acn_dmx_display_leading_zeros);
3233 prefs_register_enum_preference(acn_module, "dmx_display_line_format",
3234 "DMX, display line format",
3235 "Display line format",
3236 &global_acn_dmx_display_line_format,
3237 dmx_display_line_format,
3242 /******************************************************************************/
3243 /* Register handoff */
3245 proto_reg_handoff_acn(void)
3247 /* dissector_handle_t acn_handle; */
3248 /* acn_handle = new_create_dissector_handle(dissect_acn, proto_acn); */
3249 /* dissector_add_handle("udp.port", acn_handle); */
3250 heur_dissector_add("udp", dissect_acn_heur, proto_acn);
3260 * indent-tabs-mode: nil
3263 * ex: set shiftwidth=2 tabstop=8 expandtab:
3264 * :indentSize=2:tabSize=8:noTabs=true: