2
* Routines for ACN packet disassembly
4
* $Id: packet-acn.c 20119 2006-12-11 21:28:07Z jake $
6
* Copyright (c) 2003 by Erwin Rol <erwin@erwinrol.com>
7
* Copyright (c) 2006 by Electronic Theatre Controls, Inc.
8
* Bill Florac <bflorac@etcconnect.com>
10
* Wireshark - Network traffic analyzer
11
* By Gerald Combs <gerald@wireshark.org>
12
* Copyright 1999 Gerald Combs
14
* This program is free software; you can redistribute it and/or
15
* modify it under the terms of the GNU General Public License
16
* as published by the Free Software Foundation; either version 2
17
* of the License, or (at your option) any later version.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program; if not, write to the Free Software
26
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31
Add reading of DDL files so we can futher explode DMP packets
32
For some of the Set/Get properties where we have a range of data
33
it would be better to show the block of data rather and
34
address-data pair on each line...
36
Build CID to "Name" table from file so we can display real names
48
#include <epan/packet.h>
49
#include <epan/prefs.h>
50
#include <epan/emem.h>
51
#include <epan/packet.h>
52
#include <epan/ipv6-utils.h>
55
#include "packet-acn.h"
59
* ANSI BSR E1.17 Architecture for Control Networks
63
#define ACTUAL_ADDRESS 0
64
/* forward reference */
65
static gboolean dissect_acn_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree );
66
static guint32 acn_add_channel_owner_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset);
67
static guint32 acn_add_channel_member_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset);
68
static guint32 acn_add_expiry(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label);
69
static guint32 acn_add_channel_parameter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset);
70
static guint32 acn_add_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label);
71
static guint32 acn_add_dmp_address_type(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt);
72
static guint32 acn_add_dmp_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt);
73
static guint32 dissect_acn_dmp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets);
74
static guint32 dissect_acn_sdt_wrapped_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, acn_pdu_offsets *last_pdu_offsets);
75
static guint32 dissect_acn_sdt_client_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets);
76
static guint32 dissect_acn_dmx_data_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets);
77
static guint32 dissect_acn_dmx_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets);
78
static guint32 dissect_acn_sdt_base_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets);
79
static guint32 dissect_acn_root_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets);
80
static int dissect_acn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
81
static gboolean is_acn(tvbuff_t *tvb);
82
void proto_register_acn(void);
83
void proto_reg_handoff_acn(void);
85
/* Global variables */
86
static int proto_acn = -1;
87
static gint ett_acn = -1;
88
static gint ett_acn_channel_owner_info_block = -1;
89
static gint ett_acn_channel_member_info_block = -1;
90
static gint ett_acn_channel_parameter = -1;
91
static gint ett_acn_address = -1;
92
static gint ett_acn_address_type = -1;
93
static gint ett_acn_pdu_flags = -1;
94
static gint ett_acn_dmp_pdu = -1;
95
static gint ett_acn_sdt_pdu = -1;
96
static gint ett_acn_sdt_client_pdu = -1;
97
static gint ett_acn_sdt_base_pdu = -1;
98
static gint ett_acn_root_pdu = -1;
99
static gint ett_acn_dmx_address = -1;
100
static gint ett_acn_dmx_data_pdu = -1;
101
static gint ett_acn_dmx_pdu = -1;
103
/* Register fields */
104
/* In alphabetical order */
105
static int hf_acn_association = -1;
106
static int hf_acn_channel_number = -1;
107
static int hf_acn_cid = -1;
108
static int hf_acn_client_protocol_id = -1;
109
static int hf_acn_data = -1;
110
static int hf_acn_data8 = -1;
111
static int hf_acn_data16 = -1;
112
static int hf_acn_data24 = -1;
113
static int hf_acn_data32 = -1;
114
static int hf_acn_dmp_address1 = -1;
115
static int hf_acn_dmp_address2 = -1;
116
static int hf_acn_dmp_address4 = -1;
117
static int hf_acn_dmp_adt = -1; /* address and data type*/
118
static int hf_acn_dmp_adt_a = -1;
119
static int hf_acn_dmp_adt_v = -1;
120
static int hf_acn_dmp_adt_r = -1;
121
static int hf_acn_dmp_adt_d = -1;
122
static int hf_acn_dmp_adt_x = -1;
123
static int hf_acn_dmp_reason_code = -1;
124
static int hf_acn_dmp_vector = -1;
125
static int hf_acn_dmp_address_data_pairs = -1;
126
static int hf_acn_expiry = -1;
127
static int hf_acn_first_memeber_to_ack = -1;
128
static int hf_acn_first_missed_sequence = -1;
129
static int hf_acn_ip_address_type = -1;
130
static int hf_acn_ipv4 = -1;
131
static int hf_acn_ipv6 = -1;
132
static int hf_acn_last_memeber_to_ack = -1;
133
static int hf_acn_last_missed_sequence = -1;
134
static int hf_acn_mak_threshold = -1;
135
static int hf_acn_member_id = -1;
136
static int hf_acn_nak_holdoff = -1;
137
static int hf_acn_nak_max_wait = -1;
138
static int hf_acn_nak_modulus = -1;
139
static int hf_acn_nak_outbound_flag = -1;
140
static int hf_acn_oldest_available_wrapper = -1;
141
static int hf_acn_packet_identifier = -1;
142
static int hf_acn_pdu = -1;
143
static int hf_acn_pdu_flag_d = -1;
144
static int hf_acn_pdu_flag_h = -1;
145
static int hf_acn_pdu_flag_l = -1;
146
static int hf_acn_pdu_flag_v = -1;
147
static int hf_acn_pdu_flags = -1;
148
static int hf_acn_pdu_length = -1;
149
static int hf_acn_port = -1;
150
static int hf_acn_postamble_size = -1;
151
static int hf_acn_preamble_size = -1;
152
static int hf_acn_protocol_id = -1;
153
static int hf_acn_reason_code = -1;
154
static int hf_acn_reciprocal_channel = -1;
155
static int hf_acn_refuse_code = -1;
156
static int hf_acn_reliable_sequence_number = -1;
157
/* static int hf_acn_sdt_pdu = -1; */
158
static int hf_acn_sdt_vector = -1;
159
static int hf_acn_dmx_vector = -1;
160
static int hf_acn_session_count = -1;
161
static int hf_acn_total_sequence_number = -1;
162
static int hf_acn_dmx_source_name = -1;
163
static int hf_acn_dmx_priority = -1;
164
static int hf_acn_dmx_sequence_number = -1;
165
static int hf_acn_dmx_universe = -1;
166
/* static int hf_acn_dmx_dmp_vector = -1; */
168
/* Try heuristic ACN decode */
169
static gboolean global_acn_heur = FALSE;
170
static gboolean global_acn_dmx_enable = FALSE;
171
static gint global_acn_dmx_display_view = 0;
172
static gboolean global_acn_dmx_display_zeros = FALSE;
173
static gboolean global_acn_dmx_display_leading_zeros = FALSE;
176
static const value_string acn_protocol_id_vals[] = {
177
{ ACN_PROTOCOL_ID_SDT, "SDT Protocol" },
178
{ ACN_PROTOCOL_ID_DMP, "DMP Protocol" },
179
{ ACN_PROTOCOL_ID_DMX, "DMX Protocol" },
183
static const value_string acn_dmp_adt_r_vals[] = {
189
static const value_string acn_dmp_adt_v_vals[] = {
195
static const value_string acn_dmp_adt_d_vals[] = {
196
{ ACN_DMP_ADT_D_NS, "Non-range, single data item" },
197
{ ACN_DMP_ADT_D_RS, "Range, single data item" },
198
{ ACN_DMP_ADT_D_RE, "Range, array of equal size data items" },
199
{ ACN_DMP_ADT_D_RM, "Range, series of mixed size data items" },
203
static const value_string acn_dmp_adt_a_vals[] = {
204
{ ACN_DMP_ADT_A_1, "1 octet" },
205
{ ACN_DMP_ADT_A_2, "2 octets" },
206
{ ACN_DMP_ADT_A_4, "4 octets" },
207
{ ACN_DMP_ADT_A_R, "reserved" },
212
static const value_string acn_sdt_vector_vals[] = {
213
{ACN_SDT_VECTOR_UNKNOWN, "Unknown"},
214
{ACN_SDT_VECTOR_REL_WRAP, "Reliable Wrapper"},
215
{ACN_SDT_VECTOR_UNREL_WRAP, "Unreliable Wrapper"},
216
{ACN_SDT_VECTOR_CHANNEL_PARAMS, "Channel Parameters"},
217
{ACN_SDT_VECTOR_JOIN, "Join"},
218
{ACN_SDT_VECTOR_JOIN_REFUSE, "Join Refuse"},
219
{ACN_SDT_VECTOR_JOIN_ACCEPT, "Join Accept"},
220
{ACN_SDT_VECTOR_LEAVE, "Leave"},
221
{ACN_SDT_VECTOR_LEAVING, "Leaving"},
222
{ACN_SDT_VECTOR_CONNECT, "Connect"},
223
{ACN_SDT_VECTOR_CONNECT_ACCEPT, "Connect Accept"},
224
{ACN_SDT_VECTOR_CONNECT_REFUSE, "Connect Refuse"},
225
{ACN_SDT_VECTOR_DISCONNECT, "Disconnect"},
226
{ACN_SDT_VECTOR_DISCONNECTING, "Disconnecting"},
227
{ACN_SDT_VECTOR_ACK, "Ack"},
228
{ACN_SDT_VECTOR_NAK, "Nak"},
229
{ACN_SDT_VECTOR_GET_SESSION, "Get Session"},
230
{ACN_SDT_VECTOR_SESSIONS, "Sessions"},
234
static const value_string acn_dmx_vector_vals[] = {
235
{ACN_DMX_VECTOR, "Streaming DMX"},
239
static const value_string acn_dmp_vector_vals[] = {
240
{ACN_DMP_VECTOR_UNKNOWN, "Unknown"},
241
{ACN_DMP_VECTOR_GET_PROPERTY, "Get Property"},
242
{ACN_DMP_VECTOR_SET_PROPERTY, "Set Property"},
243
{ACN_DMP_VECTOR_GET_PROPERTY_REPLY, "Get property reply"},
244
{ACN_DMP_VECTOR_EVENT, "Event"},
245
{ACN_DMP_VECTOR_MAP_PROPERTY, "Map Property"},
246
{ACN_DMP_VECTOR_UNMAP_PROPERTY, "Unmap Property"},
247
{ACN_DMP_VECTOR_SUBSCRIBE, "Subscribe"},
248
{ACN_DMP_VECTOR_UNSUBSCRIBE, "Unsubscribe"},
249
{ACN_DMP_VECTOR_GET_PROPERTY_FAIL, "Get Property Fail"},
250
{ACN_DMP_VECTOR_SET_PROPERTY_FAIL, "Set Property Fail"},
251
{ACN_DMP_VECTOR_MAP_PROPERTY_FAIL, "Map Property Fail"},
252
{ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT, "Subscribe Accept"},
253
{ACN_DMP_VECTOR_SUBSCRIBE_REJECT, "Subscribe Reject"},
254
{ACN_DMP_VECTOR_ALLOCATE_MAP, "Allocate Map"},
255
{ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY, "Allocate Map Reply"},
256
{ACN_DMP_VECTOR_DEALLOCATE_MAP, "Deallocate Map"},
260
static const value_string acn_ip_address_type_vals[] = {
261
{ ACN_ADDR_NULL, "Null"},
262
{ ACN_ADDR_IPV4, "IPv4"},
263
{ ACN_ADDR_IPV6, "IPv6"},
264
{ ACN_ADDR_IPPORT, "Port"},
268
static const value_string acn_refuse_code_vals[] = {
269
{ ACN_REFUSE_CODE_NONSPECIFIC, "Nonspecific" },
270
{ ACN_REFUSE_CODE_ILLEGAL_PARAMS, "Illegal Parameters" },
271
{ ACN_REFUSE_CODE_LOW_RESOURCES, "Low Resources" },
272
{ ACN_REFUSE_CODE_ALREADY_MEMBER, "Already Member" },
273
{ ACN_REFUSE_CODE_BAD_ADDR_TYPE, "Bad Address Type" },
274
{ ACN_REFUSE_CODE_NO_RECIP_CHAN, "No Reciprocal Channel" },
278
static const value_string acn_reason_code_vals[] = {
279
{ ACN_REASON_CODE_NONSPECIFIC, "Nonspecific" },
280
{ ACN_REASON_CODE_NO_RECIP_CHAN, "No Reciprocal Channel" },
281
{ ACN_REASON_CODE_CHANNEL_EXPIRED, "Channel Expired" },
282
{ ACN_REASON_CODE_LOST_SEQUENCE, "Lost Sequence" },
283
{ ACN_REASON_CODE_SATURATED, "Saturated" },
284
{ ACN_REASON_CODE_TRANS_ADDR_CHANGING, "Transport Address Changing" },
285
{ ACN_REASON_CODE_ASKED_TO_LEAVE, "Asked to Leave" },
286
{ ACN_REASON_CODE_NO_RECIPIENT, "No Recipient"},
290
static const value_string acn_dmp_reason_code_vals[] = {
291
{ ACN_DMP_REASON_CODE_NONSPECIFIC, "Nonspecific" },
292
{ ACN_DMP_REASON_CODE_NOT_A_PROPERTY, "Not a Property" },
293
{ ACN_DMP_REASON_CODE_WRITE_ONLY, "Write Only" },
294
{ ACN_DMP_REASON_CODE_NOT_WRITABLE, "Not Writable" },
295
{ ACN_DMP_REASON_CODE_DATA_ERROR, "Data Error" },
296
{ ACN_DMP_REASON_CODE_MAPS_NOT_SUPPORTED, "Maps not Supported" },
297
{ ACN_DMP_REASON_CODE_SPACE_NOT_AVAILABLE, "Space not Available" },
298
{ ACN_DMP_REASON_CODE_PROP_NOT_MAPABLE, "Property not Mapable"},
299
{ ACN_DMP_REASON_CODE_MAP_NOT_ALLOCATED, "Map not Allocated"},
300
{ ACN_DMP_REASON_CODE_SUBSCRIPTION_NOT_SUPPORTED, "Subscription not Supported"},
301
{ ACN_DMP_REASON_CODE_NO_SUBSCRIPTIONS_SUPPORTED, "No Subscriptions Supported"},
305
static const enum_val_t dmx_display_view[] = {
306
{ "hex" , "Hex ", ACN_PREF_DMX_DISPLAY_HEX },
307
{ "decimal", "Decimal", ACN_PREF_DMX_DISPLAY_DEC },
308
{ "percent", "Percent", ACN_PREF_DMX_DISPLAY_PER },
312
/******************************************************************************/
313
/* Test to see if it is an ACN Packet */
314
static gboolean is_acn(tvbuff_t *tvb)
316
static char acn_packet_id[] = "ASC-E1.17\0\0\0"; /* must be 12 bytes */
319
/* Get the fields in octets 2 - 12 octet */
320
packet_id = tvb_get_ephemeral_string(tvb, 4, 12);
321
if (memcmp(packet_id, &acn_packet_id, 12) == 0) {
328
/******************************************************************************/
329
/* Heuristic dissector */
331
dissect_acn_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
333
/* This is a heuristic dissector, which means we get all the UDP
334
* traffic not sent to a known dissector and not claimed by
335
* a heuristic dissector called before us!
338
/* abort if not enabled! */
339
if (!global_acn_heur) return FALSE;
341
/* abort if it is NOT an ACN packet */
342
if (!is_acn(tvb)) return FALSE;
344
/* else, dissect it */
345
dissect_acn(tvb, pinfo, tree);
349
/******************************************************************************/
350
/* Adds tree branch for channel owner info block */
352
acn_add_channel_owner_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset)
355
proto_tree *this_tree = NULL;
356
guint32 session_count;
359
pi = proto_tree_add_text(this_tree, tvb, offset, 8, "Channel Owner Info Block");
360
this_tree = proto_item_add_subtree(pi, ett_acn_channel_owner_info_block);
362
proto_tree_add_item(this_tree, hf_acn_member_id, tvb, offset, 2, FALSE);
364
proto_tree_add_item(this_tree, hf_acn_channel_number, tvb, offset, 2, FALSE);
366
offset += acn_add_address(tvb, pinfo, this_tree, offset, "Destination Address:");
367
offset += acn_add_address(tvb, pinfo, this_tree, offset, "Source Address:");
369
session_count = tvb_get_ntohs(tvb, offset);
370
for (x=0; x<session_count; x++) {
371
pi = proto_tree_add_item(this_tree, hf_acn_protocol_id, tvb, offset, 4, FALSE);
372
proto_item_append_text(pi, " #%d", x+1);
378
/******************************************************************************/
379
/* Adds tree branch for channel member info block */
381
acn_add_channel_member_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset)
384
proto_tree *this_tree = NULL;
385
guint32 session_count;
388
pi = proto_tree_add_text(this_tree, tvb, offset, 8, "Channel Member Info Block");
389
this_tree = proto_item_add_subtree(pi, ett_acn_channel_member_info_block);
391
proto_tree_add_item(this_tree, hf_acn_member_id, tvb, offset, 2, FALSE);
393
proto_tree_add_item(this_tree, hf_acn_cid, tvb, offset, 16, FALSE);
395
proto_tree_add_item(this_tree, hf_acn_channel_number, tvb, offset, 2, FALSE);
397
offset += acn_add_address(tvb, pinfo, this_tree, offset, "Destination Address:");
398
offset += acn_add_address(tvb, pinfo, this_tree, offset, "Source Address:");
399
proto_tree_add_item(this_tree, hf_acn_reciprocal_channel, tvb, offset, 2, FALSE);
402
session_count = tvb_get_ntohs(tvb, offset);
403
for (x=0; x<session_count; x++) {
404
pi = proto_tree_add_item(this_tree, hf_acn_protocol_id, tvb, offset, 4, FALSE);
405
proto_item_append_text(pi, " #%d", x+1);
412
/******************************************************************************/
413
/* Add labeled expiry */
415
acn_add_expiry(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label)
417
proto_tree_add_text(tree, tvb, offset, 2, "%s %d", label, tvb_get_guint8(tvb, offset));
423
/******************************************************************************/
424
/* Adds tree branch for channel parameters */
426
acn_add_channel_parameter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
429
proto_tree *param_tree = NULL;
431
pi = proto_tree_add_text(tree, tvb, offset, 8, "Channel Parameter Block");
432
param_tree = proto_item_add_subtree(pi, ett_acn_channel_parameter);
433
proto_tree_add_item(param_tree, hf_acn_expiry, tvb, offset, 1, FALSE);
435
proto_tree_add_item(param_tree, hf_acn_nak_outbound_flag, tvb, offset, 1, FALSE);
437
proto_tree_add_item(param_tree, hf_acn_nak_holdoff, tvb, offset, 2, FALSE);
439
proto_tree_add_item(param_tree, hf_acn_nak_modulus, tvb, offset, 2, FALSE);
441
proto_tree_add_item(param_tree, hf_acn_nak_max_wait, tvb, offset, 2, FALSE);
443
return offset; /* bytes used */
447
/******************************************************************************/
448
/* Add an address tree */
450
acn_add_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label)
453
proto_tree *addr_tree = NULL;
454
guint8 ip_address_type;
459
struct e_in6_addr IPv6;
463
ip_address_type = tvb_get_guint8(tvb, offset);
465
switch (ip_address_type) {
469
/* Build tree and add type*/
470
pi = proto_tree_add_text(tree, tvb, offset, 7, label);
471
addr_tree = proto_item_add_subtree(pi, ett_acn_address);
472
proto_tree_add_item(addr_tree, hf_acn_ip_address_type, tvb, offset, 1, FALSE);
475
port = tvb_get_ntohs(tvb, offset);
476
proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, FALSE);
479
proto_tree_add_item(addr_tree, hf_acn_ipv4, tvb, offset, 4, FALSE);
480
/* Append port and address to tree item */
481
IPv4 = tvb_get_ipv4(tvb, offset);
482
SET_ADDRESS(&addr, AT_IPv4, sizeof(IPv4), &IPv4);
483
proto_item_append_text(pi, " %s, Port %d", address_to_str(&addr), port);
487
/* Build tree and add type*/
488
pi = proto_tree_add_text(tree, tvb, offset, 19, label);
489
addr_tree = proto_item_add_subtree(pi, ett_acn_address);
490
proto_tree_add_item(addr_tree, hf_acn_ip_address_type, tvb, offset, 1, FALSE);
493
port = tvb_get_ntohs(tvb, offset);
494
proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, FALSE);
497
proto_tree_add_item(addr_tree, hf_acn_ipv6, tvb, offset, 16, FALSE);
498
/* Append port and address to tree item */
499
tvb_get_ipv6(tvb, offset, &IPv6);
500
SET_ADDRESS(&addr, AT_IPv6, sizeof(struct e_in6_addr), &IPv6);
501
proto_item_append_text(pi, " %s, Port %d", address_to_str(&addr), port);
504
case ACN_ADDR_IPPORT:
505
/* Build tree and add type*/
506
pi = proto_tree_add_text(tree, tvb, offset, 3, label);
507
addr_tree = proto_item_add_subtree(pi, ett_acn_address);
508
proto_tree_add_item(addr_tree, hf_acn_ip_address_type, tvb, offset, 1, FALSE);
511
port = tvb_get_ntohs(tvb, offset);
512
proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, FALSE);
513
/* Append port to tree item */
514
proto_item_append_text(pi, " %s Port %d", address_to_str(&addr), port);
521
/******************************************************************************/
522
/* Adds tree branch for address type */
524
acn_add_dmp_address_type(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
527
proto_tree *this_tree = NULL;
530
/* header contains address and data type */
531
adt->flags = tvb_get_guint8(tvb, offset);
533
D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
534
pi = proto_tree_add_text(tree, tvb, offset, 1, "Address and Data Type: %s (%d)", match_strval(D, acn_dmp_adt_d_vals), D);
536
this_tree = proto_item_add_subtree(pi, ett_acn_address_type);
537
proto_tree_add_uint(this_tree, hf_acn_dmp_adt_v, tvb, offset, 1, adt->flags);
538
proto_tree_add_uint(this_tree, hf_acn_dmp_adt_r, tvb, offset, 1, adt->flags);
539
proto_tree_add_uint(this_tree, hf_acn_dmp_adt_d, tvb, offset, 1, adt->flags);
540
proto_tree_add_uint(this_tree, hf_acn_dmp_adt_x, tvb, offset, 1, adt->flags);
541
proto_tree_add_uint(this_tree, hf_acn_dmp_adt_a, tvb, offset, 1, adt->flags);
544
return offset; /* bytes used */
547
/******************************************************************************/
548
/* Add an dmp address */
550
acn_add_dmp_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
552
guint32 start_offset;
556
start_offset = offset;
558
D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
559
A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
561
case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
564
switch (A) { /* address */
565
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
566
adt->address = tvb_get_guint8(tvb, offset);
570
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
571
adt->address = tvb_get_ntohs(tvb, offset);
575
case ACN_DMP_ADT_A_4: /* Four octet address, (range: one octet address, increment, and count). */
576
adt->address = tvb_get_ntohl(tvb, offset);
580
default: /* and ACN_DMP_ADT_A_R (Four octet address, (range: four octet address, increment, and count)*/
582
} /* of switch (A) */
584
if (adt->flags & ACN_DMP_ADT_FLAG_V) {
585
proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Virtual Address: %d", adt->address);
587
proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Actual Address: %d", adt->address);
591
case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
593
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
594
adt->address = tvb_get_guint8(tvb, offset);
596
adt->increment = tvb_get_guint8(tvb, offset);
598
adt->count = tvb_get_guint8(tvb, offset);
602
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
603
adt->address = tvb_get_ntohs(tvb, offset);
605
adt->increment = tvb_get_ntohs(tvb, offset);
607
adt->count = tvb_get_ntohs(tvb, offset);
611
case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
612
adt->address = tvb_get_ntohl(tvb, offset);
614
adt->increment = tvb_get_ntohl(tvb, offset);
616
adt->count = tvb_get_ntohl(tvb, offset);
620
default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
622
} /* of switch (A) */
624
if (adt->flags & ACN_DMP_ADT_FLAG_V) {
625
proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Virtual Address first: %d, inc: %d, count: %d", adt->address, adt->increment, adt->count);
627
proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Actual Address first: %d, inc: %d, count: %d", adt->address, adt->increment, adt->count);
631
case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
633
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
634
adt->address = tvb_get_guint8(tvb, offset);
636
adt->increment = tvb_get_guint8(tvb, offset);
638
adt->count = tvb_get_guint8(tvb, offset);
642
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
643
adt->address = tvb_get_ntohs(tvb, offset);
645
adt->increment = tvb_get_ntohs(tvb, offset);
647
adt->count = tvb_get_ntohs(tvb, offset);
651
case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
652
adt->address = tvb_get_ntohl(tvb, offset);
654
adt->increment = tvb_get_ntohl(tvb, offset);
656
adt->count = tvb_get_ntohl(tvb, offset);
660
default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
662
} /* of switch (A) */
664
if (adt->flags & ACN_DMP_ADT_FLAG_V) {
665
proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Virtual Address first: %d, inc: %d, count: %d", adt->address, adt->increment, adt->count);
667
proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Actual Address first: %d, inc: %d, count: %d", adt->address, adt->increment, adt->count);
671
case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
673
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
674
adt->address = tvb_get_guint8(tvb, offset);
676
adt->increment = tvb_get_guint8(tvb, offset);
678
adt->count = tvb_get_guint8(tvb, offset);
682
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
683
adt->address = tvb_get_ntohs(tvb, offset);
685
adt->increment = tvb_get_ntohs(tvb, offset);
687
adt->count = tvb_get_ntohs(tvb, offset);
691
case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
692
adt->address = tvb_get_ntohl(tvb, offset);
694
adt->increment = tvb_get_ntohl(tvb, offset);
696
adt->count = tvb_get_ntohl(tvb, offset);
700
default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
702
} /* of switch (A) */
704
if (adt->flags & ACN_DMP_ADT_FLAG_V) {
705
proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Virtual Address first: %d, inc: %d, count: %d", adt->address, adt->increment, adt->count);
707
proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Actual Address first: %d, inc: %d, count: %d", adt->address, adt->increment, adt->count);
710
} /* of switch (D) */
716
/*******************************************************************************/
717
/* Display DMP Data */
719
acn_add_dmp_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
722
guint32 start_offset;
725
guint32 data_address;
729
guint32 ok_to_process = FALSE;
731
start_offset = offset;
733
/* We would like to rip through Property Address-Data pairs */
734
/* but since we don't now how many there are nor how big the data size is, */
735
/* it not possible. So, we just show the whole thing as a block of date! */
737
/* There are a few exceptions however */
738
/* 1) if the address type is ACN_DMP_ADT_D_NS or ACN_DMP_ADT_D_RS and */
739
/* or ACN_DMP_ADT_D_RE */
740
/* then number of bytes is <= count + 4. Each value is at least one byte */
741
/* and another address/data pair is at least 4 bytes so if the remaining */
742
/* bytes is less than the count plus 4 then the remaining data */
743
/* must be all data */
745
/* 2) if the address type is ACN_DMP_ADT_D_RE and the number of bytes */
746
/* equals the number of bytes in remaining in the pdu then there is */
747
/* a 1 to one match */
749
D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
751
case ACN_DMP_ADT_D_NS:
752
case ACN_DMP_ADT_D_RS:
753
if (adt->data_length <= adt->count + 4) {
754
ok_to_process = TRUE;
757
case ACN_DMP_ADT_D_RE:
758
if (adt->data_length == adt->count) {
759
ok_to_process = TRUE;
761
if (adt->data_length <= adt->count + 4) {
762
ok_to_process = TRUE;
767
if (!ok_to_process) {
768
data_size = adt->data_length;
769
ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, FALSE);
771
proto_item_set_text(ti, "Data and more Address-Data Pairs (further dissection not possible)");
775
/* Allocate some memory, not using ep_alloc here as there could be LOT of calls to
776
this in the same capture frame. Could use se_alloc...
778
#define BUFFER_SIZE 128
779
buffer = g_malloc(BUFFER_SIZE);
782
A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
784
case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
785
/* calculate data size */
786
data_size = adt->data_length;
787
data_address = adt->address;
790
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
791
g_snprintf(buffer, BUFFER_SIZE, "Addr %2.2X ->", data_address);
793
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
794
g_snprintf(buffer, BUFFER_SIZE, "Addr %4.4X ->", data_address);
796
case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
797
g_snprintf(buffer, BUFFER_SIZE, "Addr %8.8X ->", data_address);
799
default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
805
data_value = tvb_get_guint8(tvb, offset);
806
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %2.2X", buffer, data_value);
809
data_value = tvb_get_ntohs(tvb, offset);
810
proto_tree_add_int_format(tree, hf_acn_data16, tvb, offset, 2, data_value, "%s %4.4X", buffer, data_value);
813
data_value = tvb_get_ntoh24(tvb, offset);
814
proto_tree_add_int_format(tree, hf_acn_data24, tvb, offset, 3, data_value, "%s %6.6X", buffer, data_value);
817
data_value = tvb_get_ntohl(tvb, offset);
818
proto_tree_add_int_format(tree, hf_acn_data32, tvb, offset, 4, data_value, "%s %8.8X", buffer, data_value);
821
/* build string of values */
822
for (y=0;y<20 && y<data_size;y++) {
823
data_value = tvb_get_guint8(tvb, offset+y);
824
g_snprintf(buffer, BUFFER_SIZE, "%s %2.2X", buffer, data_value);
827
ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, FALSE);
829
/* change the text */
830
proto_item_set_text(ti, "%s", buffer);
832
} /* of switch (data_size) */
836
case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
837
/* calculate data size */
838
data_size = adt->data_length;
839
data_address = adt->address;
841
for (x=0;x<adt->count;x++) {
843
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
844
g_snprintf(buffer, BUFFER_SIZE, "Addr %2.2X ->", data_address);
846
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
847
g_snprintf(buffer, BUFFER_SIZE, "Addr %4.4X ->", data_address);
849
case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
850
g_snprintf(buffer, BUFFER_SIZE, "Addr %8.8X ->", data_address);
852
default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
858
data_value = tvb_get_guint8(tvb, offset);
859
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %2.2X", buffer, data_value);
862
data_value = tvb_get_ntohs(tvb, offset);
863
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 2, data_value, "%s %4.4X", buffer, data_value);
866
data_value = tvb_get_ntoh24(tvb, offset);
867
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 3, data_value, "%s %6.6X", buffer, data_value);
870
data_value = tvb_get_ntohl(tvb, offset);
871
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 4, data_value, "%s %8.8X", buffer, data_value);
874
/* build string of values */
875
for (y=0;y<20 && y<data_size;y++) {
876
data_value = tvb_get_guint8(tvb, offset+y);
877
g_snprintf(buffer, BUFFER_SIZE, "%s %2.2X", buffer, data_value);
880
ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, FALSE);
881
/* change the text */
882
proto_item_set_text(ti, "%s", buffer);
884
} /* of switch (data_size) */
885
data_address += adt->increment;
886
} /* of (x=0;x<adt->count;x++) */
890
case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
891
/* calculate data size */
892
data_size = adt->data_length / adt->count;
893
data_address = adt->address;
895
for (x=0;x<adt->count;x++) {
897
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
898
g_snprintf(buffer, BUFFER_SIZE, "Addr %2.2X ->", data_address);
900
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
901
g_snprintf(buffer, BUFFER_SIZE, "Addr %4.4X ->", data_address);
903
case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
904
g_snprintf(buffer, BUFFER_SIZE, "Addr %8.8X ->", data_address);
906
default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
912
data_value = tvb_get_guint8(tvb, offset);
913
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %2.2X", buffer, data_value);
916
data_value = tvb_get_ntohs(tvb, offset);
917
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 2, data_value, "%s %4.4X", buffer, data_value);
920
data_value = tvb_get_ntoh24(tvb, offset);
921
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 3, data_value, "%s %6.6X", buffer, data_value);
924
data_value = tvb_get_ntohl(tvb, offset);
925
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 4, data_value, "%s %8.8X", buffer, data_value);
928
/* build string of values */
929
for (y=0;y<20 && y<data_size;y++) {
930
data_value = tvb_get_guint8(tvb, offset+y);
931
g_snprintf(buffer, BUFFER_SIZE, "%s %2.2X", buffer, data_value);
934
ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, FALSE);
935
/* change the text */
936
proto_item_set_text(ti, "%s", buffer);
938
} /* of switch (data_size) */
941
data_address += adt->increment;
942
} /* of (x=0;x<adt->count;x++) */
945
case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
946
data_size = adt->data_length;
947
ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, FALSE);
949
/* change the text */
950
proto_item_set_text(ti, "Mixed size data items");
952
} /* of switch (D) */
953
/* free our memory! */
959
/*******************************************************************************/
960
/* Display DMP Reason codes */
962
acn_add_dmp_reason_codes(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
965
guint32 start_offset;
967
guint32 data_address;
973
start_offset = offset;
975
/* Allocate some memory, not using ep_alloc here as there could be LOT of calls to
976
this in the same capture frame. Could use se_alloc...
978
#define BUFFER_SIZE 128
979
buffer = g_malloc(BUFFER_SIZE);
983
D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
984
A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
986
case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
987
data_address = adt->address;
989
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
990
g_snprintf(buffer, BUFFER_SIZE, "Addr %2.2X ->", data_address);
992
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
993
g_snprintf(buffer, BUFFER_SIZE, "Addr %4.4X ->", data_address);
995
case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
996
g_snprintf(buffer, BUFFER_SIZE, "Addr %8.8X ->", data_address);
998
default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1003
data_value = tvb_get_guint8(tvb, offset);
1004
/* convert to string */
1005
ptr = match_strval(data_value, acn_dmp_reason_code_vals);
1007
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, ptr);
1011
case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
1012
data_address = adt->address;
1013
for (x=0;x<adt->count;x++) {
1015
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1016
g_snprintf(buffer, BUFFER_SIZE, "Addr %2.2X ->", data_address);
1018
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1019
g_snprintf(buffer, BUFFER_SIZE, "Addr %4.4X ->", data_address);
1021
case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1022
g_snprintf(buffer, BUFFER_SIZE, "Addr %8.8X ->", data_address);
1024
default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1029
data_value = tvb_get_guint8(tvb, offset);
1030
/* convert to string */
1031
ptr = match_strval(data_value, acn_dmp_reason_code_vals);
1033
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, ptr);
1034
data_address += adt->increment;
1035
} /* of (x=0;x<adt->count;x++) */
1039
case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
1040
case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
1041
data_address = adt->address;
1042
for (x=0;x<adt->count;x++) {
1044
case ACN_DMP_ADT_A_1: /* One octet address, (range: one octet address, increment, and count). */
1045
g_snprintf(buffer, BUFFER_SIZE, "Addr %2.2X ->", data_address);
1047
case ACN_DMP_ADT_A_2: /* Two octet address, (range: two octet address, increment, and count). */
1048
g_snprintf(buffer, BUFFER_SIZE, "Addr %4.4X ->", data_address);
1050
case ACN_DMP_ADT_A_4: /* Four octet address, (range: four octet address, increment, and count). */
1051
g_snprintf(buffer, BUFFER_SIZE, "Addr %8.8X ->", data_address);
1053
default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
1057
data_value = tvb_get_guint8(tvb, offset);
1058
/* convert to string */
1059
ptr = match_strval(data_value, acn_dmp_reason_code_vals);
1061
proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, ptr);
1062
data_address += adt->increment;
1064
} /* of (x=0;x<adt->count;x++) */
1066
} /* of switch (D) */
1067
/* free our memory! */
1073
/******************************************************************************/
1074
/* Dissect wrapped SDT PDU */
1076
dissect_acn_dmp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
1078
/* common to all pdu */
1082
guint32 pdu_flvh_length; /* flags, length, vector, header */
1083
acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
1089
guint32 vector_offset;
1090
guint32 header_offset;
1091
guint32 data_offset;
1094
guint32 data_length;
1095
guint32 address_count;
1097
proto_item *ti, *pi;
1098
proto_tree *pdu_tree = NULL;
1099
proto_tree *flag_tree = NULL;
1103
acn_dmp_adt_type adt = {0,0,0,0,0,0};
1104
acn_dmp_adt_type adt2 = {0,0,0,0,0,0};
1107
/* save start of pdu block */
1109
pdu_offsets.start = pdu_start;
1111
/* get PDU flags and length flag first */
1112
octet = tvb_get_guint8(tvb, offset++);
1113
pdu_flags = octet & 0xf0;
1114
length1 = octet & 0x0f; /* bottom 4 bits only */
1115
length2 = tvb_get_guint8(tvb, offset++);
1117
/* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1118
/* flvh = flags, length, vector, header */
1119
if (pdu_flags & ACN_PDU_FLAG_L) {
1120
length3 = tvb_get_guint8(tvb, offset);
1122
pdu_length = length3 | (length2 << 8) | (length1 << 16);
1123
pdu_flvh_length = 3;
1125
pdu_length = length2 | (length1 << 8);
1126
pdu_flvh_length = 2;
1128
/* offset should now be pointing to vector (if one exists) */
1130
/* Add pdu item and tree */
1131
ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, FALSE);
1132
pdu_tree = proto_item_add_subtree(ti, ett_acn_dmp_pdu);
1134
/* Add flag item and tree */
1135
pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1136
flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1137
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, FALSE);
1138
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, FALSE);
1139
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, FALSE);
1140
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, FALSE);
1142
/* Add PDU Length item */
1143
proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1145
/* Set vector offset */
1146
if (pdu_flags & ACN_PDU_FLAG_V) {
1147
/* use new values */
1148
vector_offset = offset;
1149
last_pdu_offsets->vector = offset;
1153
/* use last values */
1154
vector_offset = last_pdu_offsets->vector;
1156
/* offset should now be pointing to header (if one exists) */
1158
/* Add Vector item */
1159
vector = tvb_get_guint8(tvb, vector_offset);
1160
proto_tree_add_uint(pdu_tree, hf_acn_dmp_vector, tvb, vector_offset, 1, vector);
1162
/* Add Vector item to tree*/
1163
ptr = match_strval(vector, acn_dmp_vector_vals);
1164
proto_item_append_text(ti, ": ");
1165
proto_item_append_text(ti, ptr);
1167
/* Set header offset */
1168
if (pdu_flags & ACN_PDU_FLAG_H) {
1169
/* use new values */
1170
header_offset = offset;
1171
last_pdu_offsets->header = offset;
1175
/* use last values */
1176
header_offset = last_pdu_offsets->header;
1178
/* offset should now be pointing to data (if one exists) */
1180
/* header contains address and data type */
1181
acn_add_dmp_address_type(tvb, pinfo, pdu_tree, header_offset, &adt);
1184
if (pdu_flags & ACN_PDU_FLAG_D) {
1185
/* use new values */
1186
data_offset = offset;
1187
data_length = pdu_length - pdu_flvh_length;
1188
last_pdu_offsets->data = offset;
1189
last_pdu_offsets->data_length = data_length;
1191
/* use last values */
1192
data_offset = last_pdu_offsets->data;
1193
data_length = last_pdu_offsets->data_length;
1195
end_offset = data_offset + data_length;
1198
case ACN_DMP_VECTOR_UNKNOWN:
1200
case ACN_DMP_VECTOR_GET_PROPERTY:
1201
/* Rip trough property address */
1202
while (data_offset < end_offset) {
1203
old_offset = data_offset;
1204
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1205
if (old_offset == data_offset) break;
1208
case ACN_DMP_VECTOR_SET_PROPERTY:
1209
/* Rip through Property Address-Data pairs */
1210
/* But, in reality, this generally won't work as we have know way of */
1211
/* calculating the next Address-Data pair */
1212
while (data_offset < end_offset) {
1213
old_offset = data_offset;
1214
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1215
if (old_offset == data_offset) break;
1217
adt.data_length = data_length - (data_offset - old_offset);
1218
old_offset = data_offset;
1219
data_offset = acn_add_dmp_data(tvb, pinfo, pdu_tree, data_offset, &adt);
1220
if (old_offset == data_offset) break;
1223
case ACN_DMP_VECTOR_GET_PROPERTY_REPLY:
1224
/* Rip through Property Address-Data pairs */
1225
/* But, in reality, this generally won't work as we have know way of */
1226
/* calculating the next Address-Data pair */
1227
while (data_offset < end_offset) {
1228
old_offset = data_offset;
1229
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1230
if (old_offset == data_offset) break;
1233
adt.data_length = data_length - (data_offset - old_offset);
1234
old_offset = data_offset;
1235
data_offset = acn_add_dmp_data(tvb, pinfo, pdu_tree, data_offset, &adt);
1236
if (old_offset == data_offset) break;
1239
case ACN_DMP_VECTOR_EVENT:
1240
/* Rip through Property Address-Data pairs */
1241
/* But, in reality, this generally won't work as we have know way of */
1242
/* calculating the next Address-Data pair */
1243
while (data_offset < end_offset) {
1244
old_offset = data_offset;
1245
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1246
if (old_offset == data_offset) break;
1248
adt.data_length = data_length - (data_offset - old_offset);
1249
old_offset = data_offset;
1250
data_offset = acn_add_dmp_data(tvb, pinfo, pdu_tree, data_offset, &adt);
1251
if (old_offset == data_offset) break;
1254
case ACN_DMP_VECTOR_MAP_PROPERTY:
1255
/* Virtual Address type */
1256
data_offset = acn_add_dmp_address_type(tvb, pinfo, pdu_tree, data_offset, &adt2);
1257
/* Rip through Actual-Virtual Address Pairs */
1258
while (data_offset < end_offset) {
1260
old_offset = data_offset;
1261
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1262
if (old_offset == data_offset) break;
1263
D = ACN_DMP_ADT_EXTRACT_D(adt.flags);
1265
case ACN_DMP_ADT_D_NS:
1268
case ACN_DMP_ADT_D_RS:
1271
case ACN_DMP_ADT_D_RE:
1272
address_count = adt.count;
1274
/*case ACN_DMP_ADT_D_RM: */
1277
return pdu_start + pdu_length;
1282
while (address_count > 0) {
1283
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt2);
1288
case ACN_DMP_VECTOR_UNMAP_PROPERTY:
1289
/* Rip trough Actaul Proptery Address */
1290
while (data_offset < end_offset) {
1291
old_offset = data_offset;
1292
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1293
if (old_offset == data_offset) break;
1296
case ACN_DMP_VECTOR_SUBSCRIBE:
1297
/* Rip trough Proptery Address */
1298
while (data_offset < end_offset) {
1299
old_offset = data_offset;
1300
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1301
if (old_offset == data_offset) break;
1304
case ACN_DMP_VECTOR_UNSUBSCRIBE:
1305
/* Rip trough Proptery Address */
1306
while (data_offset < end_offset) {
1307
old_offset = data_offset;
1308
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1309
if (old_offset == data_offset) break;
1312
case ACN_DMP_VECTOR_GET_PROPERTY_FAIL:
1313
/* Rip trough Address-Reason Code Pairs */
1314
while (data_offset < end_offset) {
1315
old_offset = data_offset;
1316
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1317
if (old_offset == data_offset) break;
1319
adt.data_length = data_length - (data_offset - old_offset);
1320
old_offset = data_offset;
1321
data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1322
if (old_offset == data_offset) break;
1325
case ACN_DMP_VECTOR_SET_PROPERTY_FAIL:
1326
/* Rip trough Address-Reason Code Pairs */
1327
while (data_offset < end_offset) {
1328
old_offset = data_offset;
1329
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1330
if (old_offset == data_offset) break;
1332
adt.data_length = data_length - (data_offset - old_offset);
1333
old_offset = data_offset;
1334
data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1335
if (old_offset == data_offset) break;
1338
case ACN_DMP_VECTOR_MAP_PROPERTY_FAIL:
1339
/* Rip trough Address-Reason Code Pairs */
1340
while (data_offset < end_offset) {
1341
old_offset = data_offset;
1342
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1343
if (old_offset == data_offset) break;
1345
adt.data_length = data_length - (data_offset - old_offset);
1346
old_offset = data_offset;
1347
data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1348
if (old_offset == data_offset) break;
1351
case ACN_DMP_VECTOR_SUBSCRIBE_ACCEPT:
1352
/* Rip through Property Addrsses */
1353
while (data_offset < end_offset) {
1354
old_offset = data_offset;
1355
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1356
if (old_offset == data_offset) break;
1359
case ACN_DMP_VECTOR_SUBSCRIBE_REJECT:
1360
/* Rip trough Address-Reason Code Pairs */
1361
while (data_offset < end_offset) {
1362
old_offset = data_offset;
1363
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1364
if (old_offset == data_offset) break;
1366
adt.data_length = data_length - (data_offset - old_offset);
1367
old_offset = data_offset;
1368
data_offset = acn_add_dmp_reason_codes(tvb, pinfo, pdu_tree, data_offset, &adt);
1369
if (old_offset == data_offset) break;
1372
case ACN_DMP_VECTOR_ALLOCATE_MAP:
1373
/* No data for this */
1375
case ACN_DMP_VECTOR_ALLOCATE_MAP_REPLY:
1376
/* Single reason code */
1377
proto_tree_add_item(pdu_tree, hf_acn_dmp_reason_code, tvb, data_offset, 1, FALSE);
1379
case ACN_DMP_VECTOR_DEALLOCATE_MAP:
1380
/* No data for this */
1384
return pdu_start + pdu_length;
1388
/******************************************************************************/
1389
/* Dissect wrapped SDT PDU */
1391
dissect_acn_sdt_wrapped_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, acn_pdu_offsets *last_pdu_offsets)
1393
/* common to all pdu */
1397
guint32 pdu_flvh_length; /* flags, length, vector, header */
1398
acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
1403
guint32 vector_offset;
1404
guint32 data_offset;
1406
guint32 data_length;
1408
proto_item *ti, *pi;
1409
proto_tree *pdu_tree = NULL;
1410
proto_tree *flag_tree = NULL;
1416
/* save start of pdu block */
1418
pdu_offsets.start = pdu_start;
1420
/* get PDU flags and length flag first */
1421
octet = tvb_get_guint8(tvb, offset++);
1422
pdu_flags = octet & 0xf0;
1423
length1 = octet & 0x0f; /* bottom 4 bits only */
1424
length2 = tvb_get_guint8(tvb, offset++);
1426
/* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1427
/* flvh = flags, length, vector, header */
1428
if (pdu_flags & ACN_PDU_FLAG_L) {
1429
length3 = tvb_get_guint8(tvb, offset);
1431
pdu_length = length3 | (length2 << 8) | (length1 << 16);
1432
pdu_flvh_length = 3;
1434
pdu_length = length2 | (length1 << 8);
1435
pdu_flvh_length = 2;
1437
/* offset should now be pointing to vector (if one exists) */
1439
/* Add pdu item and tree */
1440
ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, FALSE);
1441
pdu_tree = proto_item_add_subtree(ti, ett_acn_sdt_pdu);
1443
/* Add flag item and tree */
1444
pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1445
flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1446
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, FALSE);
1447
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, FALSE);
1448
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, FALSE);
1449
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, FALSE);
1451
/* Add PDU Length item */
1452
proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1454
/* Set vector offset */
1455
if (pdu_flags & ACN_PDU_FLAG_V) {
1456
/* use new values */
1457
vector_offset = offset;
1458
last_pdu_offsets->vector = offset;
1462
/* use last values */
1463
vector_offset = last_pdu_offsets->vector;
1465
/* offset should now be pointing to header (if one exists) */
1467
/* Add Vector item */
1468
vector = tvb_get_guint8(tvb, vector_offset);
1469
proto_tree_add_uint(pdu_tree, hf_acn_sdt_vector, tvb, vector_offset, 1, vector);
1471
/* Add Vector item to tree*/
1472
ptr = match_strval(vector, acn_sdt_vector_vals);
1473
proto_item_append_text(ti, ": ");
1474
proto_item_append_text(ti, ptr);
1476
/* NO HEADER DATA ON THESE* (at least so far) */
1479
if (pdu_flags & ACN_PDU_FLAG_D) {
1480
/* use new values */
1481
data_offset = offset;
1482
data_length = pdu_length - pdu_flvh_length;
1483
last_pdu_offsets->data = offset;
1484
last_pdu_offsets->data_length = data_length;
1486
/* use last values */
1487
data_offset = last_pdu_offsets->data;
1488
data_length = last_pdu_offsets->data_length;
1490
end_offset = data_offset + data_length;
1493
case ACN_SDT_VECTOR_ACK:
1494
proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
1497
case ACN_SDT_VECTOR_CHANNEL_PARAMS:
1498
data_offset = acn_add_channel_parameter(tvb, pinfo, pdu_tree, data_offset);
1499
data_offset = acn_add_address(tvb, pinfo, pdu_tree, data_offset, "Ad-hoc Address:");
1500
data_offset = acn_add_expiry(tvb, pinfo, pdu_tree, data_offset, "Ad-hoc Expiry:");
1502
case ACN_SDT_VECTOR_LEAVE:
1505
case ACN_SDT_VECTOR_CONNECT:
1506
/* Protocol ID item */
1507
proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, FALSE);
1510
case ACN_SDT_VECTOR_CONNECT_ACCEPT:
1511
/* Protocol ID item */
1512
proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, FALSE);
1515
case ACN_SDT_VECTOR_CONNECT_REFUSE:
1516
/* Protocol ID item */
1517
proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, FALSE);
1519
proto_tree_add_item(pdu_tree, hf_acn_refuse_code, tvb, data_offset, 1, FALSE);
1522
case ACN_SDT_VECTOR_DISCONNECT:
1523
/* Protocol ID item */
1524
proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, FALSE);
1527
case ACN_SDT_VECTOR_DISCONNECTING:
1528
/* Protocol ID item */
1529
proto_tree_add_item(pdu_tree, hf_acn_protocol_id, tvb, data_offset, 4, FALSE);
1531
proto_tree_add_item(pdu_tree, hf_acn_reason_code, tvb, data_offset, 1, FALSE);
1537
return pdu_start + pdu_length;
1541
/******************************************************************************/
1542
/* Dissect SDT Client PDU */
1544
dissect_acn_sdt_client_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
1546
/* common to all pdu */
1550
guint32 pdu_flvh_length; /* flags, length, vector, header */
1551
acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
1556
guint32 vector_offset;
1557
guint32 header_offset;
1558
guint32 data_offset;
1559
guint32 data_length;
1563
proto_item *ti, *pi;
1564
proto_tree *pdu_tree = NULL;
1565
proto_tree *flag_tree = NULL;
1570
guint32 protocol_id;
1571
guint16 association;
1573
/* save start of pdu block */
1575
pdu_offsets.start = pdu_start;
1577
/* get PDU flags and length flag first */
1578
octet = tvb_get_guint8(tvb, offset++);
1579
pdu_flags = octet & 0xf0;
1580
length1 = octet & 0x0f; /* bottom 4 bits only */
1581
length2 = tvb_get_guint8(tvb, offset++);
1583
/* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1584
/* flvh = flags, length, vector, header */
1585
if (pdu_flags & ACN_PDU_FLAG_L) {
1586
length3 = tvb_get_guint8(tvb, offset);
1588
pdu_length = length3 | (length2 << 8) | (length1 << 16);
1589
pdu_flvh_length = 3;
1591
pdu_length = length2 | (length1 << 8);
1592
pdu_flvh_length = 2;
1594
/* offset should now be pointing to vector (if one exists) */
1596
/* Add pdu item and tree */
1597
ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, FALSE);
1598
pdu_tree = proto_item_add_subtree(ti, ett_acn_sdt_client_pdu);
1600
/* Add flag item and tree */
1601
pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1602
flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1603
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, FALSE);
1604
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, FALSE);
1605
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, FALSE);
1606
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, FALSE);
1608
/* Add PDU Length item */
1609
proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1611
/* Set vector offset */
1612
if (pdu_flags & ACN_PDU_FLAG_V) {
1613
/* use new values */
1614
vector_offset = offset;
1615
last_pdu_offsets->vector = offset;
1617
pdu_flvh_length += 2;
1619
/* use last values */
1620
vector_offset = last_pdu_offsets->vector;
1622
/* offset should now be pointing to header (if one exists) */
1624
/* add Member ID item */
1625
member_id = tvb_get_ntohs(tvb, vector_offset);
1626
proto_tree_add_uint(pdu_tree, hf_acn_member_id, tvb, vector_offset, 2, member_id);
1628
/* Set header offset */
1629
if (pdu_flags & ACN_PDU_FLAG_H) {
1630
/* use new values */
1631
header_offset = offset;
1632
last_pdu_offsets->header = offset;
1634
pdu_flvh_length += 6;
1636
/* use last values */
1637
header_offset = last_pdu_offsets->header;
1639
/* offset should now be pointing to data (if one exists) */
1641
/* add Protocol ID item (Header)*/
1642
protocol_id = tvb_get_ntohl(tvb, header_offset);
1643
proto_tree_add_uint(pdu_tree, hf_acn_protocol_id, tvb, header_offset, 4, protocol_id);
1646
/* Add protocol to tree*/
1647
ptr = match_strval(protocol_id, acn_protocol_id_vals);
1648
proto_item_append_text(ti, ": ");
1649
proto_item_append_text(ti, ptr);
1651
/* add association item */
1652
association = tvb_get_ntohs(tvb, header_offset);
1653
proto_tree_add_uint(pdu_tree, hf_acn_association, tvb, header_offset, 2, association);
1657
if (pdu_flags & ACN_PDU_FLAG_D) {
1658
/* use new values */
1659
data_offset = offset;
1660
data_length = pdu_length - pdu_flvh_length;
1661
last_pdu_offsets->data = offset;
1662
last_pdu_offsets->data_length = data_length;
1664
/* use last values */
1665
data_offset = last_pdu_offsets->data;
1666
data_length = last_pdu_offsets->data_length;
1668
end_offset = data_offset + data_length;
1670
switch (protocol_id) {
1671
case ACN_PROTOCOL_ID_SDT:
1672
while (data_offset < end_offset) {
1673
old_offset = data_offset;
1674
data_offset = dissect_acn_sdt_wrapped_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
1675
if (old_offset == data_offset) break;
1678
case ACN_PROTOCOL_ID_DMP:
1679
while (data_offset < end_offset) {
1680
old_offset = data_offset;
1681
data_offset = dissect_acn_dmp_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
1682
if (data_offset == old_offset) break;
1686
return pdu_start + pdu_length;
1690
/******************************************************************************/
1691
/* reverses the characters in a string */
1697
for (i=0, j=strlen(s)-1; i < j; i++, j--) {
1705
/******************************************************************************/
1706
/* level to string (ascii) */
1707
/* level : 8 bit value */
1708
/* string : pointer to buffer to fill */
1709
/* leading_char: character to buffer left of digits */
1710
/* min_char : mininum number of characters (for filling, not including space)*/
1711
/* show_zero: show zeros or dots */
1712
/* also adds a space to right end */
1714
/* returns end of string */
1715
/* faster than printf() */
1717
ltos(guint8 level, gchar *string, guint8 base, gchar leading_char, guint8 min_chars, gboolean show_zero)
1721
if (base < 2 || base > 16) {
1725
/* deal with zeros */
1726
if ((level == 0) && (!show_zero)) {
1727
for (i=0;i<min_chars;i++) {
1736
/* do our convert, comes out backwords! */
1738
string[i++] = "0123456789ABCDEF"[level % base];
1739
} while ((level /= base) > 0);
1741
/* expand to needed character */
1742
for (;i<min_chars;i++) {
1743
string[i] = leading_char;
1748
/* now reverse (and correct) the order */
1751
/* add a space at the end (ok its at the start but it will be at the end)*/
1758
/******************************************************************************/
1759
/* Dissect DMX data PDU */
1761
dissect_acn_dmx_data_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
1763
/* common to all pdu */
1767
guint32 pdu_flvh_length; /* flags, length, vector, header */
1768
acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
1773
guint32 vector_offset;
1774
guint32 data_offset;
1777
guint32 data_length;
1778
guint32 header_offset;
1783
proto_item *ti, *pi;
1784
proto_tree *pdu_tree = NULL;
1785
proto_tree *flag_tree = NULL;
1786
/* proto_tree *addr_tree = NULL; */
1789
acn_dmp_adt_type adt = {0,0,0,0,0,0};
1801
/* save start of pdu block */
1803
pdu_offsets.start = pdu_start;
1805
/* get PDU flags and length flag first */
1806
octet = tvb_get_guint8(tvb, offset++);
1807
pdu_flags = octet & 0xf0;
1808
length1 = octet & 0x0f; /* bottom 4 bits only */
1809
length2 = tvb_get_guint8(tvb, offset++);
1811
/* if length flag is set, then we have a 20 bit length else we have a 12 bit */
1812
/* flvh = flags, length, vector, header */
1813
if (pdu_flags & ACN_PDU_FLAG_L) {
1814
length3 = tvb_get_guint8(tvb, offset);
1816
pdu_length = length3 | (length2 << 8) | (length1 << 16);
1817
pdu_flvh_length = 3;
1819
pdu_length = length2 | (length1 << 8);
1820
pdu_flvh_length = 2;
1822
/* offset should now be pointing to vector (if one exists) */
1824
/* Add pdu item and tree */
1825
ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, FALSE);
1826
pdu_tree = proto_item_add_subtree(ti, ett_acn_dmx_data_pdu);
1828
/* Add flag item and tree */
1829
pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
1830
flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
1831
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, FALSE);
1832
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, FALSE);
1833
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, FALSE);
1834
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, FALSE);
1836
/* Add PDU Length item */
1837
proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
1839
/* Set vector offset */
1840
if (pdu_flags & ACN_PDU_FLAG_V) {
1841
/* use new values */
1842
vector_offset = offset;
1843
last_pdu_offsets->vector = offset;
1845
pdu_flvh_length += 1;
1847
/* use last values */
1848
vector_offset = last_pdu_offsets->vector;
1850
/* offset should now be pointing to header (if one exists) */
1852
/* Add Vector item */
1853
vector = tvb_get_guint8(tvb, vector_offset);
1854
proto_tree_add_uint(pdu_tree, hf_acn_dmp_vector, tvb, vector_offset, 1, vector);
1856
/* Add Vector item to tree*/
1857
ptr = match_strval(vector, acn_dmp_vector_vals);
1858
proto_item_append_text(ti, ": ");
1859
proto_item_append_text(ti, ptr);
1861
/* Set header offset */
1862
if (pdu_flags & ACN_PDU_FLAG_H) {
1863
/* use new values */
1864
header_offset = offset;
1865
last_pdu_offsets->header = offset;
1869
/* use last values */
1870
header_offset = last_pdu_offsets->header;
1872
/* offset should now be pointing to data (if one exists) */
1874
/* process based on vector */
1875
acn_add_dmp_address_type(tvb, pinfo, pdu_tree, header_offset, &adt);
1878
if (pdu_flags & ACN_PDU_FLAG_D) {
1879
/* use new values */
1880
data_offset = offset;
1881
data_length = pdu_length - pdu_flvh_length;
1882
last_pdu_offsets->data = offset;
1883
last_pdu_offsets->data_length = data_length;
1885
/* use last values */
1886
data_offset = last_pdu_offsets->data;
1887
data_length = last_pdu_offsets->data_length;
1889
end_offset = data_offset + data_length;
1892
case ACN_DMP_VECTOR_SET_PROPERTY:
1893
old_offset = data_offset;
1894
data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt);
1895
if (data_offset == old_offset) break;
1897
#define BUFFER_SIZE 128
1899
buffer = ep_alloc(BUFFER_SIZE);
1903
/* values base on display mode */
1904
switch ((guint)global_acn_dmx_display_view) {
1905
case ACN_PREF_DMX_DISPLAY_HEX:
1909
/* case ACN_PREF_DMX_DISPLAY_PER: */
1915
/* do we display leading zeros */
1916
if (global_acn_dmx_display_leading_zeros) {
1922
/* add a header line */
1923
memset(buffer, ' ', 10);
1925
for (x=1;x<=20;x++) {
1926
buf_ptr = ltos((guint8)x, buf_ptr, 10, ' ', min_char, FALSE);
1933
proto_tree_add_text(pdu_tree, tvb, data_offset, 0, buffer);
1935
/* start our line */
1936
g_snprintf(buffer, BUFFER_SIZE, "001-020: ");
1937
buf_ptr = buffer + 9;
1941
for (x=data_offset; x < end_offset; x++) {
1942
level = tvb_get_guint8(tvb, x);
1943
if (global_acn_dmx_display_view==ACN_PREF_DMX_DISPLAY_PER) {
1944
if ((level > 0) && (level < 3)) {
1947
level = level * 100 / 255;
1950
buf_ptr = ltos(level, buf_ptr, base, leading_char, min_char, global_acn_dmx_display_zeros);
1954
if (item_cnt == 20 || x == (end_offset-1)) {
1956
proto_tree_add_text(pdu_tree, tvb, data_offset, item_cnt, buffer);
1958
g_snprintf(buffer, BUFFER_SIZE, "%03d-%03d: ",total_cnt, total_cnt+20);
1959
buf_ptr = buffer + 9;
1962
/* add separater character */
1963
if (item_cnt == 10) {
1971
address data type (fixed at 0xA2)
1972
start code - 1 byte, reserved (should be 0)
1973
- 1 byte, start code (0x255)
1974
- 2 bytes, packet offset (should be 0000)
1975
address increment - 4 bytes (ignore)
1976
number of dmx values - 4 bytes (0-512)
1977
dmx values 0-512 bytes (data)
1982
return pdu_start + pdu_length;
1987
/******************************************************************************/
1988
/* Dissect DMX Base PDU */
1990
dissect_acn_dmx_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
1992
/* common to all pdu */
1996
guint32 pdu_flvh_length; /* flags, length, vector, header */
1997
acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2002
guint32 vector_offset;
2003
guint32 data_offset;
2005
guint32 data_length;
2007
proto_item *ti, *pi;
2008
proto_tree *pdu_tree = NULL;
2009
proto_tree *flag_tree = NULL;
2017
/* save start of pdu block */
2019
pdu_offsets.start = pdu_start;
2021
/* get PDU flags and length flag first */
2022
octet = tvb_get_guint8(tvb, offset++);
2023
pdu_flags = octet & 0xf0;
2024
length1 = octet & 0x0f; /* bottom 4 bits only */
2025
length2 = tvb_get_guint8(tvb, offset++);
2027
/* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2028
/* flvh = flags, length, vector, header */
2029
if (pdu_flags & ACN_PDU_FLAG_L) {
2030
length3 = tvb_get_guint8(tvb, offset);
2032
pdu_length = length3 | (length2 << 8) | (length1 << 16);
2033
pdu_flvh_length = 3;
2035
pdu_length = length2 | (length1 << 8);
2036
pdu_flvh_length = 2;
2039
/* offset should now be pointing to vector (if one exists) */
2041
/* Add pdu item and tree */
2042
ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, FALSE);
2043
pdu_tree = proto_item_add_subtree(ti, ett_acn_dmx_pdu);
2045
/* Add flag item and tree */
2046
pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
2047
flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
2048
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, FALSE);
2049
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, FALSE);
2050
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, FALSE);
2051
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, FALSE);
2053
/* Add PDU Length item */
2054
proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
2056
/* Set vector offset */
2057
if (pdu_flags & ACN_PDU_FLAG_V) {
2058
/* use new values */
2059
vector_offset = offset;
2060
last_pdu_offsets->vector = offset;
2062
pdu_flvh_length += 4;
2064
/* use last values */
2065
vector_offset = last_pdu_offsets->vector;
2067
/* offset should now be pointing to header (if one exists) */
2069
/* Add Vector item */
2070
vector = tvb_get_ntohl(tvb, vector_offset);
2071
proto_tree_add_item(pdu_tree, hf_acn_dmx_vector, tvb, vector_offset, 4, FALSE);
2072
/* vector_offset +=4; */
2074
/* Add Vector item to tree*/
2075
proto_item_append_text(ti, ": %s", match_strval(vector, acn_dmx_vector_vals));
2077
/* NO HEADER DATA ON THESE* (at least so far) */
2080
if (pdu_flags & ACN_PDU_FLAG_D) {
2081
/* use new values */
2082
data_offset = offset;
2083
data_length = pdu_length - pdu_flvh_length;
2084
last_pdu_offsets->data = offset;
2085
last_pdu_offsets->data_length = data_length;
2087
/* use last values */
2088
data_offset = last_pdu_offsets->data;
2089
data_length = last_pdu_offsets->data_length;
2091
end_offset = data_offset + data_length;
2093
/* process based on vector */
2096
proto_tree_add_item(pdu_tree, hf_acn_dmx_source_name, tvb, data_offset, 32, FALSE);
2099
priority = tvb_get_guint8(tvb, data_offset);
2100
proto_tree_add_item(pdu_tree, hf_acn_dmx_priority, tvb, data_offset, 1, FALSE);
2103
proto_tree_add_item(pdu_tree, hf_acn_dmx_sequence_number, tvb, data_offset, 1, FALSE);
2106
universe = tvb_get_ntohs(tvb, data_offset);
2107
proto_tree_add_item(pdu_tree, hf_acn_dmx_universe , tvb, data_offset, 2, FALSE);
2110
proto_item_append_text(ti, ", Universe: %d, Priority: %d", universe, priority);
2112
data_offset = dissect_acn_dmx_data_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2116
return pdu_start + pdu_length;
2119
/******************************************************************************/
2120
/* Dissect SDT Base PDU */
2122
dissect_acn_sdt_base_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
2124
/* common to all pdu */
2128
guint32 pdu_flvh_length; /* flags, length, vector, header */
2129
acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2134
guint32 vector_offset;
2135
guint32 data_offset;
2138
guint32 data_length;
2140
proto_item *ti, *pi;
2141
proto_tree *pdu_tree = NULL;
2142
proto_tree *flag_tree = NULL;
2149
/* save start of pdu block */
2151
pdu_offsets.start = pdu_start;
2153
/* get PDU flags and length flag first */
2154
octet = tvb_get_guint8(tvb, offset++);
2155
pdu_flags = octet & 0xf0;
2156
length1 = octet & 0x0f; /* bottom 4 bits only */
2157
length2 = tvb_get_guint8(tvb, offset++);
2159
/* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2160
/* flvh = flags, length, vector, header */
2161
if (pdu_flags & ACN_PDU_FLAG_L) {
2162
length3 = tvb_get_guint8(tvb, offset);
2164
pdu_length = length3 | (length2 << 8) | (length1 << 16);
2165
pdu_flvh_length = 3;
2167
pdu_length = length2 | (length1 << 8);
2168
pdu_flvh_length = 2;
2170
/* offset should now be pointing to vector (if one exists) */
2172
/* Add pdu item and tree */
2173
ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, FALSE);
2174
pdu_tree = proto_item_add_subtree(ti, ett_acn_sdt_base_pdu);
2176
/* Add flag item and tree */
2177
pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
2178
flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
2179
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, FALSE);
2180
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, FALSE);
2181
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, FALSE);
2182
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, FALSE);
2184
/* Add PDU Length item */
2185
proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
2187
/* Set vector offset */
2188
if (pdu_flags & ACN_PDU_FLAG_V) {
2189
/* use new values */
2190
vector_offset = offset;
2191
last_pdu_offsets->vector = offset;
2195
/* use last values */
2196
vector_offset = last_pdu_offsets->vector;
2198
/* offset should now be pointing to header (if one exists) */
2200
/* Add Vector item */
2201
vector = tvb_get_guint8(tvb, vector_offset);
2202
proto_tree_add_uint(pdu_tree, hf_acn_sdt_vector, tvb, vector_offset, 1, vector);
2204
/* Add Vector item to tree*/
2205
ptr = match_strval(vector, acn_sdt_vector_vals);
2206
proto_item_append_text(ti, ": ");
2207
proto_item_append_text(ti, ptr);
2209
/* NO HEADER DATA ON THESE* (at least so far) */
2212
if (pdu_flags & ACN_PDU_FLAG_D) {
2213
/* use new values */
2214
data_offset = offset;
2215
data_length = pdu_length - pdu_flvh_length;
2216
last_pdu_offsets->data = offset;
2217
last_pdu_offsets->data_length = data_length;
2219
/* use last values */
2220
data_offset = last_pdu_offsets->data;
2221
data_length = last_pdu_offsets->data_length;
2223
end_offset = data_offset + data_length;
2225
/* process based on vector */
2227
case ACN_SDT_VECTOR_UNKNOWN:
2229
case ACN_SDT_VECTOR_REL_WRAP:
2230
case ACN_SDT_VECTOR_UNREL_WRAP:
2231
proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
2233
proto_tree_add_item(pdu_tree, hf_acn_total_sequence_number, tvb, data_offset, 4, FALSE);
2235
proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
2237
proto_tree_add_item(pdu_tree, hf_acn_oldest_available_wrapper, tvb, data_offset, 4, FALSE);
2239
proto_tree_add_item(pdu_tree, hf_acn_first_memeber_to_ack, tvb, data_offset, 2, FALSE);
2241
proto_tree_add_item(pdu_tree, hf_acn_last_memeber_to_ack, tvb, data_offset, 2, FALSE);
2243
proto_tree_add_item(pdu_tree, hf_acn_mak_threshold, tvb, data_offset, 2, FALSE);
2246
while (data_offset < end_offset) {
2247
old_offset = data_offset;
2248
data_offset = dissect_acn_sdt_client_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2249
if (data_offset == old_offset) break;
2252
case ACN_SDT_VECTOR_CHANNEL_PARAMS:
2254
case ACN_SDT_VECTOR_JOIN:
2255
proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
2257
proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
2259
proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
2261
proto_tree_add_item(pdu_tree, hf_acn_reciprocal_channel, tvb, data_offset, 2, FALSE);
2263
proto_tree_add_item(pdu_tree, hf_acn_total_sequence_number, tvb, data_offset, 4, FALSE);
2265
proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
2267
data_offset = acn_add_address(tvb, pinfo, pdu_tree, data_offset, "Destination Address:");
2268
data_offset = acn_add_channel_parameter(tvb, pinfo, pdu_tree, data_offset);
2269
data_offset = acn_add_expiry(tvb, pinfo, pdu_tree, data_offset, "Ad-hoc Expiry:");
2271
case ACN_SDT_VECTOR_JOIN_REFUSE:
2272
pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
2274
proto_item_append_text(pi, "(Leader)");
2275
proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
2277
proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
2279
proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
2281
proto_tree_add_item(pdu_tree, hf_acn_refuse_code, tvb, data_offset, 1, FALSE);
2284
case ACN_SDT_VECTOR_JOIN_ACCEPT:
2285
pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
2287
proto_item_append_text(pi, "(Leader)");
2288
proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
2290
proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
2292
proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
2294
proto_tree_add_item(pdu_tree, hf_acn_reciprocal_channel, tvb, data_offset, 2, FALSE);
2297
case ACN_SDT_VECTOR_LEAVE:
2299
case ACN_SDT_VECTOR_LEAVING:
2300
pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
2302
proto_item_append_text(pi, "(Leader)");
2303
proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
2305
proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
2307
proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
2309
proto_tree_add_item(pdu_tree, hf_acn_reason_code, tvb, data_offset, 1, FALSE);
2312
case ACN_SDT_VECTOR_CONNECT:
2314
case ACN_SDT_VECTOR_CONNECT_ACCEPT:
2316
case ACN_SDT_VECTOR_CONNECT_REFUSE:
2318
case ACN_SDT_VECTOR_DISCONNECT:
2320
case ACN_SDT_VECTOR_DISCONNECTING:
2322
case ACN_SDT_VECTOR_ACK:
2324
case ACN_SDT_VECTOR_NAK:
2325
pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
2327
proto_item_append_text(pi, "(Leader)");
2328
proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
2330
proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
2332
proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
2334
proto_tree_add_item(pdu_tree, hf_acn_first_missed_sequence, tvb, data_offset, 4, FALSE);
2336
proto_tree_add_item(pdu_tree, hf_acn_last_missed_sequence, tvb, data_offset, 4, FALSE);
2339
case ACN_SDT_VECTOR_GET_SESSION:
2340
proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
2343
case ACN_SDT_VECTOR_SESSIONS:
2344
member_id = tvb_get_ntohs(tvb, data_offset);
2345
switch (member_id) {
2347
data_offset = acn_add_channel_owner_info_block(tvb, pinfo, pdu_tree, data_offset);
2350
data_offset = acn_add_channel_member_info_block(tvb, pinfo, pdu_tree, data_offset);
2356
return pdu_start + pdu_length;
2359
/******************************************************************************/
2360
/* Dissect Root PDU */
2362
dissect_acn_root_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
2364
/* common to all pdu */
2368
guint32 pdu_flvh_length; /* flags, length, vector, header */
2369
acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2374
guint32 vector_offset;
2375
guint32 header_offset;
2376
guint32 data_offset;
2379
guint32 data_length;
2381
proto_item *ti, *pi;
2382
proto_tree *pdu_tree = NULL;
2383
proto_tree *flag_tree = NULL;
2386
guint32 protocol_id;
2389
/* save start of pdu block */
2391
pdu_offsets.start = pdu_start;
2393
/* get PDU flags and length flag first */
2394
octet = tvb_get_guint8(tvb, offset++);
2395
pdu_flags = octet & 0xf0;
2396
length1 = octet & 0x0f; /* bottom 4 bits only */
2397
length2 = tvb_get_guint8(tvb, offset++);
2399
/* if length flag is set, then we have a 20 bit length else we have a 12 bit */
2400
/* flvh = flags, length, vector, header */
2401
if (pdu_flags & ACN_PDU_FLAG_L) {
2402
length3 = tvb_get_guint8(tvb, offset);
2404
pdu_length = length3 | (length2 << 8) | (length1 << 16);
2405
pdu_flvh_length = 3;
2407
pdu_length = length2 | (length1 << 8);
2408
pdu_flvh_length = 2;
2410
/* offset should now be pointing to vector (if one exists) */
2412
/* Add pdu item and tree */
2413
ti = proto_tree_add_item(tree, hf_acn_pdu, tvb, pdu_start, pdu_length, FALSE);
2414
pdu_tree = proto_item_add_subtree(ti, ett_acn_root_pdu);
2416
/* Add flag item and tree */
2417
pi = proto_tree_add_uint(pdu_tree, hf_acn_pdu_flags, tvb, pdu_start, 1, pdu_flags);
2418
flag_tree = proto_item_add_subtree(pi, ett_acn_pdu_flags);
2419
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_l, tvb, pdu_start, 1, FALSE);
2420
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_v, tvb, pdu_start, 1, FALSE);
2421
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_h, tvb, pdu_start, 1, FALSE);
2422
proto_tree_add_item(flag_tree, hf_acn_pdu_flag_d, tvb, pdu_start, 1, FALSE);
2424
/* Add PDU Length item */
2425
proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
2427
/* Set vector offset */
2428
if (pdu_flags & ACN_PDU_FLAG_V) {
2429
/* use new values */
2430
vector_offset = offset;
2431
last_pdu_offsets->vector = offset;
2433
pdu_flvh_length += 4;
2435
/* use last values */
2436
vector_offset = last_pdu_offsets->vector;
2438
/* offset should now be pointing to header (if one exists) */
2442
/* Get Protocol ID (vector) */
2443
protocol_id = tvb_get_ntohl(tvb, vector_offset);
2444
proto_tree_add_uint(pdu_tree, hf_acn_protocol_id, tvb, vector_offset, 4, protocol_id);
2446
/* process based on protocol_id */
2447
switch (protocol_id) {
2448
case ACN_PROTOCOL_ID_DMX:
2449
if (global_acn_dmx_enable) {
2450
proto_item_append_text(ti,": Root DMX");
2452
/* Set header offset */
2453
if (pdu_flags & ACN_PDU_FLAG_H) {
2454
/* use new values */
2455
header_offset = offset;
2456
last_pdu_offsets->header = offset;
2458
pdu_flvh_length += 16;
2460
/* use last values */
2461
header_offset = last_pdu_offsets->header;
2463
/* offset should now be pointing to data (if one exists) */
2465
/* get Header (CID) 16 bytes */
2466
tvb_get_guid(tvb, header_offset, &guid, FALSE);
2467
proto_item_append_text(ti, ", Src: %s", guid_to_str(&guid));
2469
proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, header_offset, 16, FALSE);
2470
header_offset += 16;
2473
if (pdu_flags & ACN_PDU_FLAG_D) {
2474
/* use new values */
2475
data_offset = offset;
2476
data_length = pdu_length - pdu_flvh_length;
2477
last_pdu_offsets->data = offset;
2478
last_pdu_offsets->data_length = data_length;
2480
/* use last values */
2481
data_offset = last_pdu_offsets->data;
2482
data_length = last_pdu_offsets->data_length;
2484
end_offset = data_offset + data_length;
2486
/* adjust for what we used */
2487
while (data_offset < end_offset) {
2488
old_offset = data_offset;
2489
data_offset = dissect_acn_dmx_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2490
if (data_offset == old_offset) break;
2494
case ACN_PROTOCOL_ID_SDT:
2496
proto_item_append_text(ti,": Root SDT");
2498
/* Set header offset */
2499
if (pdu_flags & ACN_PDU_FLAG_H) {
2500
/* use new values */
2501
header_offset = offset;
2502
last_pdu_offsets->header = offset;
2504
pdu_flvh_length += 16;
2506
/* use last values */
2507
header_offset = last_pdu_offsets->header;
2509
/* offset should now be pointing to data (if one exists) */
2511
/* get Header (CID) 16 bytes */
2512
tvb_get_guid(tvb, header_offset, &guid, FALSE);
2513
proto_item_append_text(ti, ", Src: %s", guid_to_str(&guid));
2515
proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, header_offset, 16, FALSE);
2516
header_offset += 16;
2519
if (pdu_flags & ACN_PDU_FLAG_D) {
2520
/* use new values */
2521
data_offset = offset;
2522
data_length = pdu_length - pdu_flvh_length;
2523
last_pdu_offsets->data = offset;
2524
last_pdu_offsets->data_length = data_length;
2526
/* use last values */
2527
data_offset = last_pdu_offsets->data;
2528
data_length = last_pdu_offsets->data_length;
2530
end_offset = data_offset + data_length;
2532
/* adjust for what we used */
2533
while (data_offset < end_offset) {
2534
old_offset = data_offset;
2535
data_offset = dissect_acn_sdt_base_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
2536
if (data_offset == old_offset) break;
2541
return pdu_start + pdu_length;
2544
/******************************************************************************/
2547
dissect_acn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2549
proto_item *ti = NULL;
2550
proto_tree *acn_tree = NULL;
2551
guint32 data_offset = 0;
2554
acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
2556
/* if (!is_acn(tvb)) { */
2560
/* Set the protocol column */
2561
if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2562
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACN");
2565
/* Clear out stuff in the info column */
2566
if(check_col(pinfo->cinfo,COL_INFO)){
2567
/* col_clear(pinfo->cinfo,COL_INFO); */
2568
col_add_fstr(pinfo->cinfo,COL_INFO, "ACN [Src Port: %d, Dst Port: %d]", pinfo->srcport, pinfo->destport );
2571
if (tree) { /* we are being asked for details */
2572
ti = proto_tree_add_item(tree, proto_acn, tvb, 0, -1, FALSE);
2573
acn_tree = proto_item_add_subtree(ti, ett_acn);
2575
pdu_offsets.start = data_offset;
2577
/* add preamble, postamble and ACN Packet ID */
2578
proto_tree_add_item(acn_tree, hf_acn_preamble_size, tvb, data_offset, 2, FALSE);
2580
proto_tree_add_item(acn_tree, hf_acn_postamble_size, tvb, data_offset, 2, FALSE);
2582
proto_tree_add_item(acn_tree, hf_acn_packet_identifier, tvb, data_offset, 12, FALSE);
2585
/* one past the last byte */
2586
end_offset = data_offset + tvb_reported_length_remaining(tvb, data_offset);
2587
while (data_offset < end_offset) {
2588
old_offset = data_offset;
2589
data_offset = dissect_acn_root_pdu(tvb, pinfo, acn_tree, data_offset, &pdu_offsets);
2590
if (data_offset == old_offset) break;
2593
return tvb_length(tvb);
2596
/******************************************************************************/
2597
/* Register protocol */
2598
void proto_register_acn(void)
2600
static hf_register_info hf[] = {
2601
/**************************************************************************/
2602
/* In alphabetical order */
2605
{ &hf_acn_ip_address_type,
2606
{ "Type", "acn.ip_address_type",
2607
FT_UINT8, BASE_DEC, VALS(acn_ip_address_type_vals), 0x0,
2611
{ &hf_acn_association,
2612
{ "Association", "acn.association",
2613
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2614
"Association", HFILL }
2616
/* Channel Number */
2617
{ &hf_acn_channel_number,
2618
{ "Channel Number", "acn.channel_number",
2619
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2620
"Channel Number", HFILL }
2625
FT_GUID, BASE_NONE, NULL, 0x0,
2628
/* Client Protocol ID */
2629
{ &hf_acn_client_protocol_id,
2630
{ "Client Protocol ID", "acn.client_protocol_id",
2631
FT_UINT32, BASE_DEC, VALS(acn_protocol_id_vals), 0x0,
2632
"ClientProtocol ID", HFILL }
2636
{ "Data", "acn.dmp_data",
2637
FT_BYTES, BASE_HEX, NULL, 0x0,
2641
{ "Addr", "acn.dmp_data8",
2642
FT_INT8, BASE_DEC_HEX, NULL, 0x0,
2646
{ "Addr", "acn.dmp_data16",
2647
FT_INT16, BASE_DEC_HEX, NULL, 0x0,
2651
{ "Addr", "acn.dmp_data24",
2652
FT_INT24, BASE_DEC_HEX, NULL, 0x0,
2656
{ "Addr", "acn.dmp_data32",
2657
FT_INT32, BASE_DEC_HEX, NULL, 0x0,
2661
{ &hf_acn_dmp_address_data_pairs,
2662
{ "Address-Data Pairs", "acn.dmp_address_data_pairs",
2663
FT_BYTES, BASE_DEC, NULL, 0x0,
2664
"More address-data pairs", HFILL }
2668
{ &hf_acn_dmp_address1,
2669
{ "Address", "acn.dmp_address",
2670
FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
2673
{ &hf_acn_dmp_address2,
2674
{ "Address", "acn.dmp_address",
2675
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2678
{ &hf_acn_dmp_address4,
2679
{ "Address", "acn.dmp_address",
2680
FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2684
/* DMP Address type*/
2686
{ "Address and Data Type", "acn.dmp_adt",
2687
FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
2688
"Address and Data Type", HFILL }
2690
{ &hf_acn_dmp_adt_a,
2691
{ "Size", "acn.dmp_adt_a",
2692
FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_a_vals), 0x03,
2695
{ &hf_acn_dmp_adt_d,
2696
{ "Data Type", "acn.dmp_adt_d",
2697
FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_d_vals), 0x30,
2698
"Data Type", HFILL }
2700
{ &hf_acn_dmp_adt_r,
2701
{ "Relative", "acn.dmp_adt_r",
2702
FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_r_vals), 0x40,
2705
{ &hf_acn_dmp_adt_v,
2706
{ "Virtual", "acn.dmp_adt_v",
2707
FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_v_vals), 0x80,
2710
{ &hf_acn_dmp_adt_x,
2711
{ "Reserved", "acn.dmp_adt_x",
2712
FT_UINT8, BASE_DEC, NULL, 0x0c,
2716
/* DMP Reason Code */
2717
{ &hf_acn_dmp_reason_code,
2718
{ "Reason Code", "acn.dmp_reason_code",
2719
FT_UINT8, BASE_DEC, VALS(acn_dmp_reason_code_vals), 0x0,
2720
"Reason Code", HFILL }
2724
{ &hf_acn_dmp_vector,
2725
{ "DMP Vector", "acn.dmp_vector",
2726
FT_UINT8, BASE_DEC, VALS(acn_dmp_vector_vals), 0x0,
2727
"DMP Vector", HFILL }
2731
{ "Expiry", "acn.expiry",
2732
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2735
/* First Member to ACK */
2736
{ &hf_acn_first_memeber_to_ack,
2737
{ "First Member to ACK", "acn.first_member_to_ack",
2738
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2739
"First Member to ACK", HFILL }
2741
/* First Missed Sequence */
2742
{ &hf_acn_first_missed_sequence,
2743
{ "First Missed Sequence", "acn.first_missed_sequence",
2744
FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2745
"First Missed Sequence", HFILL }
2749
{ "IPV4", "acn.ipv4",
2750
FT_IPv4, BASE_NONE, NULL, 0x0,
2755
{ "IPV6", "acn.ipv6",
2756
FT_IPv6, BASE_NONE, NULL, 0x0,
2759
/* Last Member to ACK */
2760
{ &hf_acn_last_memeber_to_ack,
2761
{ "Last Member to ACK", "acn.last_member_to_ack",
2762
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2763
"Last Member to ACK", HFILL }
2765
/* Last Missed Sequence */
2766
{ &hf_acn_last_missed_sequence,
2767
{ "Last Missed Sequence", "acn.last_missed_sequence",
2768
FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2769
"Last Missed Sequence", HFILL }
2772
{ &hf_acn_mak_threshold,
2773
{ "MAK Threshold", "acn.mak_threshold",
2774
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2775
"MAK Threshold", HFILL }
2778
{ &hf_acn_member_id,
2779
{ "Member ID", "acn.member_id",
2780
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2781
"Member ID", HFILL }
2784
{ &hf_acn_nak_holdoff,
2785
{ "NAK holdoff (ms)", "acn.nak_holdoff",
2786
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2787
"NAK holdoff", HFILL }
2790
{ &hf_acn_nak_max_wait,
2791
{ "NAK Max Wait (ms)", "acn.nak_max_wait",
2792
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2793
"NAK Max Wait", HFILL }
2796
{ &hf_acn_nak_modulus,
2797
{ "NAK Modulus", "acn.nak_modulus",
2798
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2799
"NAK Modulus", HFILL }
2801
/* NAK Outbound Flag */
2802
{ &hf_acn_nak_outbound_flag,
2803
{ "NAK Outbound Flag", "acn.nak_outbound_flag",
2804
FT_BOOLEAN, 8, NULL, 0x80,
2805
"NAK Outbound Flag", HFILL }
2807
/* Oldest Available Wrapper */
2808
{ &hf_acn_oldest_available_wrapper,
2809
{ "Oldest Available Wrapper", "acn.oldest_available_wrapper",
2810
FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2811
"Oldest Available Wrapper", HFILL }
2813
/* Preamble Sizet */
2814
{ &hf_acn_preamble_size,
2815
{ "Size of preamble", "acn.preamble_size",
2816
FT_UINT16, BASE_DEC, NULL, 0x0,
2817
"Preamble size in bytes", HFILL }
2819
/* Packet Identifier */
2820
{ &hf_acn_packet_identifier,
2821
{ "Packet Identifier", "acn.packet_identifier",
2822
FT_STRING, BASE_NONE, NULL, 0x0,
2823
"Packet Identififer", HFILL }
2828
FT_NONE, BASE_NONE, NULL, 0x0,
2832
{ &hf_acn_pdu_flags,
2833
{ "Flags", "acn.pdu.flags",
2834
FT_UINT8, BASE_HEX, NULL, 0x0,
2835
"PDU Flags", HFILL }
2837
{ &hf_acn_pdu_flag_d,
2838
{ "Data", "acn.pdu.flag_d",
2839
FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_D,
2840
"Data flag", HFILL }
2842
{ &hf_acn_pdu_flag_h,
2843
{ "Header", "acn.pdu.flag_h",
2844
FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_H,
2845
"Header flag", HFILL }
2847
{ &hf_acn_pdu_flag_l,
2848
{ "Length", "acn.pdu.flag_l",
2849
FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_L,
2850
"Length flag", HFILL }
2852
{ &hf_acn_pdu_flag_v,
2853
{ "Vector", "acn.pdu.flag_v",
2854
FT_BOOLEAN, 8, NULL, ACN_PDU_FLAG_V,
2855
"Vector flag", HFILL }
2858
{ &hf_acn_pdu_length,
2859
{ "Length", "acn.pdu.flag_d",
2860
FT_UINT32, BASE_DEC, NULL, 0x0,
2861
"PDU Length", HFILL }
2865
{ "Port", "acn.port",
2866
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2869
/* Postamble Size */
2870
{ &hf_acn_postamble_size,
2871
{ "Size of postamble", "acn.postamble_size",
2872
FT_UINT16, BASE_DEC, NULL, 0x0,
2873
"Postamble size in bytes", HFILL }
2876
{ &hf_acn_protocol_id,
2877
{ "Protocol ID", "acn.protocol_id",
2878
FT_UINT32, BASE_DEC, VALS(acn_protocol_id_vals), 0x0,
2879
"Protocol ID", HFILL }
2882
{ &hf_acn_reason_code,
2883
{ "Reason Code", "acn.reason_code",
2884
FT_UINT8, BASE_DEC, VALS(acn_reason_code_vals), 0x0,
2885
"Reason Code", HFILL }
2887
/* Reciprocal Channel */
2888
{ &hf_acn_reciprocal_channel,
2889
{ "Reciprocal Sequence Number", "acn.acn_reciprocal_channel",
2890
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2891
"Reciprocal Channel", HFILL }
2894
{ &hf_acn_refuse_code,
2895
{ "Refuse Code", "acn.acn_refuse_code",
2896
FT_UINT8, BASE_DEC, VALS(acn_refuse_code_vals), 0x0,
2897
"Refuse Code", HFILL }
2899
/* Reliable Sequence Number */
2900
{ &hf_acn_reliable_sequence_number,
2901
{ "Reliable Sequence Number", "acn.reliable_sequence_number",
2902
FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2903
"Reliable Sequence Number", HFILL }
2906
{ &hf_acn_sdt_vector,
2907
{ "STD Vector", "acn.sdt_vector",
2908
FT_UINT8, BASE_DEC, VALS(acn_sdt_vector_vals), 0x0,
2909
"STD Vector", HFILL }
2913
{ &hf_acn_dmx_vector,
2914
{ "Vector", "acn.dmx_vector",
2915
FT_UINT32, BASE_DEC, VALS(acn_dmx_vector_vals), 0x0,
2916
"DMX Vector", HFILL }
2918
/* DMX Source Name */
2919
{ &hf_acn_dmx_source_name,
2920
{ "Source", "acn.dmx.source_name",
2921
FT_STRING, BASE_NONE, NULL, 0x0,
2922
"DMX Source Name", HFILL }
2926
{ &hf_acn_dmx_priority,
2927
{ "Priority", "acn.dmx.priority",
2928
FT_UINT8, BASE_DEC, NULL, 0x0,
2929
"DMX Priority", HFILL }
2931
/* DMX Sequence number */
2932
{ &hf_acn_dmx_sequence_number,
2933
{ "Seq No", "acn.dmx.seq_number",
2934
FT_UINT8, BASE_DEC, NULL, 0x0,
2935
"DMX Sequence Number", HFILL }
2938
{ &hf_acn_dmx_universe,
2939
{ "Universe", "acn.dmx.universe",
2940
FT_UINT16, BASE_DEC, NULL, 0x0,
2941
"DMX Universe", HFILL }
2944
{ &hf_acn_session_count,
2945
{ "Session Count", "acn.session_count",
2946
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
2947
"Session Count", HFILL }
2949
/* Total Sequence Number */
2950
{ &hf_acn_total_sequence_number,
2951
{ "Total Sequence Number", "acn.total_sequence_number",
2952
FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2953
"Total Sequence Number", HFILL }
2957
/* Setup protocol subtree array */
2958
static gint *ett[] = {
2960
&ett_acn_channel_owner_info_block,
2961
&ett_acn_channel_member_info_block,
2962
&ett_acn_channel_parameter,
2964
&ett_acn_address_type,
2968
&ett_acn_sdt_client_pdu,
2969
&ett_acn_sdt_base_pdu,
2971
&ett_acn_dmx_address,
2972
&ett_acn_dmx_data_pdu,
2976
module_t *acn_module;
2977
if (proto_acn == -1) {
2978
proto_acn = proto_register_protocol (
2979
"Architecture for Control Networks", /* name */
2980
"ACN", /* short name */
2985
acn_module = prefs_register_protocol(proto_acn, proto_reg_handoff_acn);
2986
proto_register_field_array(proto_acn, hf, array_length(hf));
2987
proto_register_subtree_array(ett, array_length(ett));
2988
prefs_register_bool_preference(acn_module, "heuristic_acn",
2990
"Enable Architecture for Control Networks dissector (ANSI BSR E1.17)",
2993
prefs_register_bool_preference(acn_module, "dmx_enable",
2995
"Enable Streaming DMX extension dissector (ANSI BSR E1.31)",
2996
&global_acn_dmx_enable);
2998
prefs_register_enum_preference(acn_module, "dmx_display_view",
2999
"DMX, display format",
3001
&global_acn_dmx_display_view,
3005
prefs_register_bool_preference(acn_module, "dmx_display_zeros",
3006
"DMX, display zeros",
3007
"Display zeros instead of dots",
3008
&global_acn_dmx_display_zeros);
3010
prefs_register_bool_preference(acn_module, "dmx_display_leading_zeros",
3011
"DMX, display leading zeros",
3012
"Display leading zeros on levels",
3013
&global_acn_dmx_display_leading_zeros);
3017
/******************************************************************************/
3018
/* Register handoff */
3020
proto_reg_handoff_acn(void)
3022
static guint initialized = FALSE;
3023
/* static dissector_handle_t acn_handle; */
3026
/* acn_handle = new_create_dissector_handle(dissect_acn, proto_acn); */
3027
/* dissector_add("udp.port", 0, acn_handle); */
3028
heur_dissector_add("udp", dissect_acn_heur, proto_acn);