~ubuntu-branches/ubuntu/gutsy/wireshark/gutsy-security

« back to all changes in this revision

Viewing changes to epan/dissectors/packet-acn.c

  • Committer: Bazaar Package Importer
  • Author(s): Frederic Peters
  • Date: 2007-04-01 08:58:40 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070401085840-or3qhrpv8alt1bwg
Tags: 0.99.5-1
* New upstream release.
* debian/patches/09_idl2wrs.dpatch: updated to patch idl2wrs.sh.in.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* packet-acn.c
 
2
 * Routines for ACN packet disassembly
 
3
 *
 
4
 * $Id: packet-acn.c 20119 2006-12-11 21:28:07Z jake $
 
5
 *
 
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>
 
9
 *
 
10
 * Wireshark - Network traffic analyzer
 
11
 * By Gerald Combs <gerald@wireshark.org>
 
12
 * Copyright 1999 Gerald Combs
 
13
 *
 
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.
 
18
 *
 
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.
 
23
 *
 
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.
 
27
 */
 
28
 
 
29
 /*
 
30
    Todo: 
 
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...
 
35
 
 
36
      Build CID to "Name" table from file so we can display real names 
 
37
      rather than CIDs
 
38
 */
 
39
 
 
40
/* Include files */
 
41
 
 
42
#ifdef HAVE_CONFIG_H
 
43
#include "config.h"
 
44
#endif
 
45
 
 
46
#include <gmodule.h>
 
47
 
 
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>
 
53
#include <string.h>
 
54
 
 
55
#include "packet-acn.h"
 
56
 
 
57
/*
 
58
 * See
 
59
 * ANSI BSR E1.17 Architecture for Control Networks
 
60
 * ANSI BSR E1.31
 
61
 */
 
62
 
 
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);
 
84
 
 
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;
 
102
 
 
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; */
 
167
 
 
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;
 
174
 
 
175
 
 
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" }, 
 
180
  { 0,       NULL },
 
181
};
 
182
 
 
183
static const value_string acn_dmp_adt_r_vals[] = {
 
184
  { 0, "Relative" }, 
 
185
  { 1, "Absolute" }, 
 
186
  { 0,       NULL },
 
187
};
 
188
 
 
189
static const value_string acn_dmp_adt_v_vals[] = {
 
190
  { 0, "Actual" }, 
 
191
  { 1, "Virtual" }, 
 
192
  { 0,       NULL },
 
193
};
 
194
 
 
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" }, 
 
200
  { 0,       NULL },
 
201
};
 
202
 
 
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" }, 
 
208
  { 0,       NULL },
 
209
};
 
210
 
 
211
 
 
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"},
 
231
  { 0,       NULL },
 
232
};
 
233
 
 
234
static const value_string acn_dmx_vector_vals[] = {
 
235
  {ACN_DMX_VECTOR,  "Streaming DMX"},
 
236
  { 0,       NULL },
 
237
};
 
238
 
 
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"},
 
257
  { 0,       NULL },
 
258
};
 
259
 
 
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"},
 
265
  { 0,       NULL },
 
266
};
 
267
 
 
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" }, 
 
275
  { 0,       NULL },
 
276
};
 
277
 
 
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"},
 
287
  { 0,       NULL },
 
288
};
 
289
 
 
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"},
 
302
  { 0,       NULL },
 
303
};
 
304
 
 
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  },
 
309
  { NULL, NULL, 0 }
 
310
};
 
311
 
 
312
/******************************************************************************/
 
313
/* Test to see if it is an ACN Packet                                         */
 
314
static gboolean is_acn(tvbuff_t *tvb) 
 
315
{
 
316
  static char acn_packet_id[] = "ASC-E1.17\0\0\0";  /* must be 12 bytes */
 
317
  guint8      *packet_id;
 
318
 
 
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) {
 
322
    return TRUE;
 
323
  }
 
324
  return FALSE;
 
325
}
 
326
 
 
327
 
 
328
/******************************************************************************/
 
329
/* Heuristic dissector                                                        */
 
330
static gboolean
 
331
dissect_acn_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
 
332
{
 
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!
 
336
         */
 
337
 
 
338
  /* abort if not enabled! */
 
339
  if (!global_acn_heur) return FALSE;
 
340
 
 
341
  /* abort if it is NOT an ACN packet */
 
342
  if (!is_acn(tvb)) return FALSE;
 
343
 
 
344
  /* else, dissect it */
 
345
  dissect_acn(tvb, pinfo, tree);
 
346
  return TRUE;
 
347
}
 
348
 
 
349
/******************************************************************************/
 
350
/*  Adds tree branch for channel owner info block                             */
 
351
static guint32
 
352
acn_add_channel_owner_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset)
 
353
{
 
354
  proto_item *pi;
 
355
  proto_tree *this_tree = NULL;
 
356
  guint32 session_count;
 
357
  guint32 x;
 
358
 
 
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);
 
361
 
 
362
  proto_tree_add_item(this_tree, hf_acn_member_id, tvb, offset, 2, FALSE);
 
363
  offset += 2;
 
364
  proto_tree_add_item(this_tree, hf_acn_channel_number, tvb, offset, 2, FALSE);
 
365
  offset += 2;
 
366
  offset += acn_add_address(tvb, pinfo, this_tree, offset, "Destination Address:");
 
367
  offset += acn_add_address(tvb, pinfo, this_tree, offset, "Source Address:");
 
368
 
 
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);
 
373
    offset += 4;
 
374
  }
 
375
  return offset;
 
376
}
 
377
 
 
378
/******************************************************************************/
 
379
/*  Adds tree branch for channel member info block                            */
 
380
static guint32
 
381
acn_add_channel_member_info_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset)
 
382
{
 
383
  proto_item *pi;
 
384
  proto_tree *this_tree = NULL;
 
385
  guint32 session_count;
 
386
  guint32 x;
 
387
 
 
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);
 
390
 
 
391
  proto_tree_add_item(this_tree, hf_acn_member_id, tvb, offset, 2, FALSE);
 
392
  offset += 2;
 
393
  proto_tree_add_item(this_tree, hf_acn_cid, tvb, offset, 16, FALSE);
 
394
  offset += 16;
 
395
  proto_tree_add_item(this_tree, hf_acn_channel_number, tvb, offset, 2, FALSE);
 
396
  offset += 2;
 
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);
 
400
  offset += 2;
 
401
 
 
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);
 
406
    offset += 4;
 
407
  }
 
408
  return offset;
 
409
}
 
410
 
 
411
 
 
412
/******************************************************************************/
 
413
/* Add labeled expiry                                                         */
 
414
static guint32
 
415
acn_add_expiry(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label)
 
416
{
 
417
  proto_tree_add_text(tree, tvb, offset, 2, "%s %d", label, tvb_get_guint8(tvb, offset));
 
418
  offset += 1;
 
419
  return offset;
 
420
}
 
421
 
 
422
 
 
423
/******************************************************************************/
 
424
/*  Adds tree branch for channel parameters                                   */
 
425
static guint32
 
426
acn_add_channel_parameter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
 
427
{
 
428
  proto_item *pi;
 
429
  proto_tree *param_tree = NULL;
 
430
 
 
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);
 
434
  offset += 1;
 
435
  proto_tree_add_item(param_tree, hf_acn_nak_outbound_flag, tvb, offset, 1, FALSE);
 
436
  offset += 1;
 
437
  proto_tree_add_item(param_tree, hf_acn_nak_holdoff, tvb, offset, 2, FALSE);
 
438
  offset += 2;
 
439
  proto_tree_add_item(param_tree, hf_acn_nak_modulus, tvb, offset, 2, FALSE);
 
440
  offset += 2;
 
441
  proto_tree_add_item(param_tree, hf_acn_nak_max_wait, tvb, offset, 2, FALSE);
 
442
  offset += 2;
 
443
  return offset; /* bytes used */
 
444
}
 
445
 
 
446
 
 
447
/******************************************************************************/
 
448
/* Add an address tree                                                        */
 
449
static guint32
 
450
acn_add_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, const char *label)
 
451
{
 
452
  proto_item *pi;
 
453
  proto_tree *addr_tree = NULL;
 
454
  guint8 ip_address_type;
 
455
 
 
456
  address addr;
 
457
  guint32  IPv4;
 
458
  guint32  port;
 
459
  struct e_in6_addr IPv6;
 
460
 
 
461
 
 
462
  /* Get type */
 
463
  ip_address_type = tvb_get_guint8(tvb, offset);
 
464
 
 
465
  switch (ip_address_type) {
 
466
  case ACN_ADDR_NULL:
 
467
    break;
 
468
  case ACN_ADDR_IPV4:
 
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);
 
473
    offset +=1;
 
474
    /* Add port */
 
475
    port = tvb_get_ntohs(tvb, offset);
 
476
    proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, FALSE);
 
477
    offset += 2;
 
478
    /* Add Address */
 
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);
 
484
    offset += 4;
 
485
    break;
 
486
  case ACN_ADDR_IPV6:
 
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);
 
491
    offset +=1;
 
492
    /* Add port */
 
493
    port = tvb_get_ntohs(tvb, offset);
 
494
    proto_tree_add_item(addr_tree, hf_acn_port, tvb, offset, 2, FALSE);
 
495
    offset += 2;
 
496
    /* Add Address */
 
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);
 
502
    offset += 16;
 
503
    break;
 
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);
 
509
    offset +=1;
 
510
    /* Add port */
 
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);
 
515
    offset += 2;
 
516
    break;
 
517
  }
 
518
  return offset;
 
519
}
 
520
 
 
521
/******************************************************************************/
 
522
/*  Adds tree branch for address type                             */
 
523
static guint32
 
524
acn_add_dmp_address_type(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
 
525
{
 
526
  proto_item *pi;
 
527
  proto_tree *this_tree = NULL;
 
528
  guint8 D;
 
529
 
 
530
    /* header contains address and data type */
 
531
  adt->flags = tvb_get_guint8(tvb, offset);
 
532
 
 
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);
 
535
 
 
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);
 
542
  offset++;
 
543
 
 
544
  return offset; /* bytes used */
 
545
}
 
546
 
 
547
/******************************************************************************/
 
548
/* Add an dmp address                                                         */
 
549
static guint32
 
550
acn_add_dmp_address(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
 
551
{
 
552
  guint32 start_offset;
 
553
  guint32 bytes_used;
 
554
  guint8 D, A;
 
555
 
 
556
  start_offset = offset;
 
557
 
 
558
  D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
 
559
  A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
 
560
  switch (D) {
 
561
    case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
 
562
      adt->increment = 1;
 
563
      adt->count = 1;
 
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);
 
567
          offset += 1;
 
568
          bytes_used = 1;
 
569
          break;
 
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);
 
572
          offset += 2;
 
573
          bytes_used = 2;
 
574
          break;
 
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);
 
577
          offset += 4;
 
578
          bytes_used = 4;
 
579
          break;
 
580
        default: /* and ACN_DMP_ADT_A_R (Four octet address, (range: four octet address, increment, and count)*/
 
581
          return offset;
 
582
      } /* of switch (A)  */
 
583
 
 
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);
 
586
      } else {
 
587
        proto_tree_add_text(tree, tvb, start_offset, bytes_used, "Actual Address: %d", adt->address);
 
588
      }
 
589
      break;
 
590
 
 
591
    case ACN_DMP_ADT_D_RS: /* Range address, Single data item */
 
592
      switch (A) {
 
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);
 
595
          offset += 1;
 
596
          adt->increment =   tvb_get_guint8(tvb, offset);
 
597
          offset += 1;
 
598
          adt->count =   tvb_get_guint8(tvb, offset);
 
599
          offset += 1;
 
600
          bytes_used = 3;
 
601
          break;
 
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);
 
604
          offset += 2;
 
605
          adt->increment =   tvb_get_ntohs(tvb, offset);
 
606
          offset += 2;
 
607
          adt->count =   tvb_get_ntohs(tvb, offset);
 
608
          offset += 2;
 
609
          bytes_used = 6;
 
610
          break;
 
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);
 
613
          offset += 4;
 
614
          adt->increment =   tvb_get_ntohl(tvb, offset);
 
615
          offset += 4;
 
616
          adt->count =   tvb_get_ntohl(tvb, offset);
 
617
          offset += 12;
 
618
          bytes_used = 12;
 
619
          break;
 
620
        default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
 
621
          return offset;
 
622
      } /* of switch (A)  */
 
623
 
 
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);
 
626
      } else {
 
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);
 
628
      }
 
629
      break;
 
630
 
 
631
    case ACN_DMP_ADT_D_RE: /* Range address, Array of equal size data items */
 
632
      switch (A) {
 
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);
 
635
          offset += 1;
 
636
          adt->increment =   tvb_get_guint8(tvb, offset);
 
637
          offset += 1;
 
638
          adt->count =   tvb_get_guint8(tvb, offset);
 
639
          offset += 1;
 
640
          bytes_used = 3;
 
641
          break;
 
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);
 
644
          offset += 2;
 
645
          adt->increment =   tvb_get_ntohs(tvb, offset);
 
646
          offset += 2;
 
647
          adt->count =   tvb_get_ntohs(tvb, offset);
 
648
          offset += 2;
 
649
          bytes_used = 6;
 
650
          break;
 
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);
 
653
          offset += 4;
 
654
          adt->increment =   tvb_get_ntohl(tvb, offset);
 
655
          offset += 4;
 
656
          adt->count =   tvb_get_ntohl(tvb, offset);
 
657
          offset += 12;
 
658
          bytes_used = 12;
 
659
          break;
 
660
        default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
 
661
          return offset;
 
662
      } /* of switch (A)  */
 
663
 
 
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);
 
666
      } else {
 
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);
 
668
      }
 
669
      break;
 
670
 
 
671
    case ACN_DMP_ADT_D_RM: /* Range address, Series of mixed size data items */
 
672
      switch (A) {
 
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);
 
675
          offset += 1;
 
676
          adt->increment =   tvb_get_guint8(tvb, offset);
 
677
          offset += 1;
 
678
          adt->count =   tvb_get_guint8(tvb, offset);
 
679
          offset += 1;
 
680
          bytes_used = 3;
 
681
          break;
 
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);
 
684
          offset += 2;
 
685
          adt->increment =   tvb_get_ntohs(tvb, offset);
 
686
          offset += 2;
 
687
          adt->count =   tvb_get_ntohs(tvb, offset);
 
688
          offset += 2;
 
689
          bytes_used = 6;
 
690
          break;
 
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);
 
693
          offset += 4;
 
694
          adt->increment =   tvb_get_ntohl(tvb, offset);
 
695
          offset += 4;
 
696
          adt->count =   tvb_get_ntohl(tvb, offset);
 
697
          offset += 12;
 
698
          bytes_used = 12;
 
699
          break;
 
700
        default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
 
701
          return offset;
 
702
      } /* of switch (A)  */
 
703
      
 
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);
 
706
      } else {
 
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);
 
708
      }
 
709
      break;
 
710
  } /* of switch (D) */
 
711
  
 
712
  return offset;
 
713
}
 
714
 
 
715
 
 
716
/*******************************************************************************/
 
717
/* Display DMP Data                                                            */
 
718
static guint32
 
719
acn_add_dmp_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
 
720
{
 
721
  guint8 D, A;
 
722
  guint32 start_offset;
 
723
  guint32 data_size;
 
724
  guint32 data_value;
 
725
  guint32 data_address;
 
726
  guint32 x,y;
 
727
  gchar *buffer=NULL;
 
728
  proto_item *ti;
 
729
  guint32 ok_to_process = FALSE;
 
730
 
 
731
  start_offset = offset;
 
732
 
 
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!    */
 
736
  /*                                                                          */
 
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                                                      */
 
744
  /*                                                                          */
 
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                                                      */
 
748
 
 
749
  D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
 
750
  switch (D) {
 
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;
 
755
      }
 
756
      break;
 
757
    case ACN_DMP_ADT_D_RE:
 
758
      if (adt->data_length == adt->count) {
 
759
        ok_to_process = TRUE;
 
760
      }
 
761
      if (adt->data_length <= adt->count + 4) {
 
762
        ok_to_process = TRUE;
 
763
      }
 
764
      break;
 
765
  }
 
766
  
 
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);
 
770
    offset += data_size;
 
771
    proto_item_set_text(ti, "Data and more Address-Data Pairs (further dissection not possible)");
 
772
    return offset;
 
773
  } 
 
774
 
 
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...
 
777
  */
 
778
  #define BUFFER_SIZE 128
 
779
  buffer = g_malloc(BUFFER_SIZE);
 
780
  buffer[0] = 0;
 
781
 
 
782
  A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
 
783
  switch (D) {
 
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;
 
788
 
 
789
      switch (A) {
 
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);
 
792
          break;
 
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);
 
795
          break;
 
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);
 
798
          break;
 
799
        default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
 
800
          return offset;
 
801
      }
 
802
 
 
803
      switch (data_size) {
 
804
        case 1:
 
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);
 
807
          break;
 
808
        case 2:
 
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);
 
811
          break;
 
812
        case 3:
 
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);
 
815
          break;
 
816
        case 4:
 
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);
 
819
          break;
 
820
        default:
 
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);
 
825
          }
 
826
          /* add the item */
 
827
          ti = proto_tree_add_item(tree, hf_acn_data, tvb, offset, data_size, FALSE);
 
828
          offset += data_size;
 
829
          /* change the text */
 
830
          proto_item_set_text(ti, "%s", buffer);
 
831
          break;
 
832
      } /* of switch (data_size) */
 
833
      offset += data_size;
 
834
      break;
 
835
 
 
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;
 
840
 
 
841
      for (x=0;x<adt->count;x++) {
 
842
        switch (A) {
 
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);
 
845
            break;
 
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);
 
848
            break;
 
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);
 
851
            break;
 
852
          default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
 
853
            return offset;
 
854
        }
 
855
 
 
856
        switch (data_size) {
 
857
          case 1:
 
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);
 
860
            break;
 
861
          case 2:
 
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);
 
864
            break;
 
865
          case 3:
 
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);
 
868
            break;
 
869
          case 4:
 
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);
 
872
            break;
 
873
          default:
 
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);
 
878
            }
 
879
            /* add the item */
 
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);
 
883
            break;
 
884
        } /* of switch (data_size) */
 
885
        data_address += adt->increment;
 
886
      } /* of (x=0;x<adt->count;x++) */
 
887
      offset += data_size;
 
888
      break;
 
889
 
 
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;
 
894
 
 
895
      for (x=0;x<adt->count;x++) {
 
896
        switch (A) {
 
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);
 
899
            break;
 
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);
 
902
            break;
 
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);
 
905
            break;
 
906
          default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
 
907
            return offset;
 
908
        }
 
909
 
 
910
        switch (data_size) {
 
911
          case 1:
 
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);
 
914
            break;
 
915
          case 2:
 
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);
 
918
            break;
 
919
          case 3:
 
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);
 
922
            break;
 
923
          case 4:
 
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);
 
926
            break;
 
927
          default:
 
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);
 
932
            }
 
933
            /* add the item */
 
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);
 
937
            break;
 
938
        } /* of switch (data_size) */
 
939
 
 
940
        offset += data_size;
 
941
        data_address += adt->increment;
 
942
      } /* of (x=0;x<adt->count;x++) */
 
943
      break;
 
944
 
 
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);
 
948
      offset += data_size;
 
949
      /* change the text */
 
950
      proto_item_set_text(ti, "Mixed size data items");
 
951
      break;
 
952
  } /* of switch (D) */
 
953
  /* free our memory! */
 
954
  g_free(buffer);
 
955
  
 
956
  return offset;
 
957
}
 
958
 
 
959
/*******************************************************************************/
 
960
/* Display DMP Reason codes                                                    */
 
961
static guint32
 
962
acn_add_dmp_reason_codes(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, acn_dmp_adt_type *adt)
 
963
{
 
964
  guint8 D, A;
 
965
  guint32 start_offset;
 
966
  guint32 data_value;
 
967
  guint32 data_address;
 
968
  guint32 x;
 
969
 
 
970
  char *buffer=NULL;
 
971
  const gchar *ptr;
 
972
 
 
973
  start_offset = offset;
 
974
 
 
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...
 
977
  */
 
978
  #define BUFFER_SIZE 128
 
979
  buffer = g_malloc(BUFFER_SIZE);
 
980
 
 
981
  buffer[0] = 0;
 
982
 
 
983
  D = ACN_DMP_ADT_EXTRACT_D(adt->flags);
 
984
  A = ACN_DMP_ADT_EXTRACT_A(adt->flags);
 
985
  switch (D) {
 
986
    case ACN_DMP_ADT_D_NS: /* Non-range address, Single data item */
 
987
      data_address = adt->address;
 
988
      switch (A) {
 
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);
 
991
          break;
 
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);
 
994
          break;
 
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);
 
997
          break;
 
998
        default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
 
999
          return offset;
 
1000
      }
 
1001
 
 
1002
      /* Get reason */
 
1003
      data_value = tvb_get_guint8(tvb, offset); 
 
1004
      /* convert to string */
 
1005
      ptr = match_strval(data_value, acn_dmp_reason_code_vals); 
 
1006
      /* Add item */
 
1007
      proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, ptr);
 
1008
      offset++;
 
1009
      break;
 
1010
 
 
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++) {
 
1014
        switch (A) {
 
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);
 
1017
            break;
 
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);
 
1020
            break;
 
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);
 
1023
            break;
 
1024
          default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
 
1025
            return offset;
 
1026
        }
 
1027
 
 
1028
        /* Get reason */
 
1029
        data_value = tvb_get_guint8(tvb, offset); 
 
1030
        /* convert to string */
 
1031
        ptr = match_strval(data_value, acn_dmp_reason_code_vals); 
 
1032
        /* Add item */
 
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++) */
 
1036
      offset++;
 
1037
      break;
 
1038
 
 
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++) {
 
1043
        switch (A) {
 
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);
 
1046
            break;
 
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);
 
1049
            break;
 
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);
 
1052
            break;
 
1053
          default: /* and ACN_DMP_ADT_A_R, this reserved....so it has no meaning yet */
 
1054
            return offset;
 
1055
        }
 
1056
        /* Get reason */
 
1057
        data_value = tvb_get_guint8(tvb, offset); 
 
1058
        /* convert to string */
 
1059
        ptr = match_strval(data_value, acn_dmp_reason_code_vals); 
 
1060
        /* Add item */
 
1061
        proto_tree_add_int_format(tree, hf_acn_data8, tvb, offset, 1, data_value, "%s %s", buffer, ptr);
 
1062
        data_address += adt->increment;
 
1063
        offset++;
 
1064
      } /* of (x=0;x<adt->count;x++) */
 
1065
      break;
 
1066
  } /* of switch (D) */
 
1067
  /* free our memory! */
 
1068
  g_free(buffer);
 
1069
  
 
1070
  return offset;
 
1071
}
 
1072
 
 
1073
/******************************************************************************/
 
1074
/* Dissect wrapped SDT PDU                                                    */
 
1075
static guint32
 
1076
dissect_acn_dmp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
 
1077
{
 
1078
  /* common to all pdu */
 
1079
  guint8 pdu_flags;
 
1080
  guint32 pdu_start;
 
1081
  guint32 pdu_length;
 
1082
  guint32 pdu_flvh_length; /* flags, length, vector, header */
 
1083
  acn_pdu_offsets pdu_offsets = {0,0,0,0,0};
 
1084
  guint8 D;
 
1085
  guint8 octet;
 
1086
  guint32 length1;
 
1087
  guint32 length2;
 
1088
  guint32 length3;
 
1089
  guint32 vector_offset;
 
1090
  guint32 header_offset;
 
1091
  guint32 data_offset;
 
1092
  guint32 old_offset;
 
1093
  guint32 end_offset;
 
1094
  guint32 data_length;
 
1095
  guint32 address_count;
 
1096
 
 
1097
  proto_item *ti, *pi;
 
1098
  proto_tree *pdu_tree = NULL;
 
1099
  proto_tree *flag_tree = NULL;
 
1100
  
 
1101
  /* this pdu */
 
1102
  const gchar *ptr;
 
1103
  acn_dmp_adt_type adt = {0,0,0,0,0,0};
 
1104
  acn_dmp_adt_type adt2 = {0,0,0,0,0,0};
 
1105
  guint32 vector;
 
1106
 
 
1107
  /* save start of pdu block */
 
1108
  pdu_start = offset;
 
1109
  pdu_offsets.start = pdu_start;
 
1110
 
 
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++);  
 
1116
 
 
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);
 
1121
    offset++;
 
1122
    pdu_length = length3 | (length2 << 8) | (length1 << 16);
 
1123
    pdu_flvh_length = 3;
 
1124
  } else {
 
1125
    pdu_length = length2 | (length1 << 8);
 
1126
    pdu_flvh_length = 2;
 
1127
  }
 
1128
  /* offset should now be pointing to vector (if one exists) */
 
1129
 
 
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);
 
1133
 
 
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);
 
1141
 
 
1142
  /* Add PDU Length item */
 
1143
  proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
 
1144
 
 
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;
 
1150
    offset++;
 
1151
    pdu_flvh_length++;
 
1152
  } else {
 
1153
    /* use last values */
 
1154
    vector_offset = last_pdu_offsets->vector;
 
1155
  }
 
1156
  /* offset should now be pointing to header (if one exists) */
 
1157
 
 
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);
 
1161
 
 
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);
 
1166
 
 
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;
 
1172
    offset++;
 
1173
    pdu_flvh_length++;
 
1174
  } else {
 
1175
    /* use last values */
 
1176
    header_offset = last_pdu_offsets->header;
 
1177
  }
 
1178
  /* offset should now be pointing to data (if one exists) */
 
1179
 
 
1180
  /* header contains address and data type */
 
1181
  acn_add_dmp_address_type(tvb, pinfo, pdu_tree, header_offset, &adt);
 
1182
 
 
1183
  /* Adjust data */
 
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;
 
1190
  } else {
 
1191
    /* use last values */
 
1192
    data_offset = last_pdu_offsets->data;
 
1193
    data_length = last_pdu_offsets->data_length;
 
1194
  }
 
1195
  end_offset = data_offset + data_length;
 
1196
 
 
1197
  switch (vector) {
 
1198
  case ACN_DMP_VECTOR_UNKNOWN:
 
1199
    break;
 
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;
 
1206
    }
 
1207
    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;
 
1216
 
 
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;
 
1221
    }
 
1222
    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;
 
1231
 
 
1232
 
 
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;
 
1237
    }
 
1238
    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;
 
1247
 
 
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;
 
1252
    }
 
1253
    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) {
 
1259
      /* actual */
 
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);
 
1264
      switch (D) {
 
1265
        case ACN_DMP_ADT_D_NS:
 
1266
          address_count = 1;
 
1267
          break;
 
1268
        case ACN_DMP_ADT_D_RS:
 
1269
          address_count = 1;
 
1270
          break;
 
1271
        case ACN_DMP_ADT_D_RE:
 
1272
          address_count = adt.count;
 
1273
          break;
 
1274
        /*case ACN_DMP_ADT_D_RM: */
 
1275
        default: 
 
1276
          /* OUCH */
 
1277
          return pdu_start + pdu_length;
 
1278
          break;
 
1279
      }
 
1280
 
 
1281
      /* virtual */
 
1282
      while (address_count > 0) {
 
1283
        data_offset = acn_add_dmp_address(tvb, pinfo, pdu_tree, data_offset, &adt2);
 
1284
        address_count--;
 
1285
      }
 
1286
    }
 
1287
    break;
 
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;
 
1294
    }
 
1295
    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;
 
1302
    }
 
1303
    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;
 
1310
    }
 
1311
    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;
 
1318
 
 
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;
 
1323
    }
 
1324
    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;
 
1331
 
 
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;
 
1336
    }
 
1337
    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;
 
1344
 
 
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;
 
1349
    }
 
1350
    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;
 
1357
    }
 
1358
    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;
 
1365
 
 
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;
 
1370
    }
 
1371
    break;
 
1372
  case ACN_DMP_VECTOR_ALLOCATE_MAP:
 
1373
    /* No data for this */
 
1374
    break;
 
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);
 
1378
    data_offset++;
 
1379
  case ACN_DMP_VECTOR_DEALLOCATE_MAP:
 
1380
    /* No data for this */
 
1381
    break;
 
1382
  }
 
1383
 
 
1384
  return pdu_start + pdu_length;
 
1385
}
 
1386
 
 
1387
 
 
1388
/******************************************************************************/
 
1389
/* Dissect wrapped SDT PDU                                                    */
 
1390
static guint32
 
1391
dissect_acn_sdt_wrapped_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, acn_pdu_offsets *last_pdu_offsets)
 
1392
{
 
1393
  /* common to all pdu */
 
1394
  guint8 pdu_flags;
 
1395
  guint32 pdu_start;
 
1396
  guint32 pdu_length;
 
1397
  guint32 pdu_flvh_length; /* flags, length, vector, header */
 
1398
  acn_pdu_offsets pdu_offsets = {0,0,0,0,0}; 
 
1399
  guint8 octet;
 
1400
  guint32 length1;
 
1401
  guint32 length2;
 
1402
  guint32 length3;
 
1403
  guint32 vector_offset;
 
1404
  guint32 data_offset;
 
1405
  guint32 end_offset;
 
1406
  guint32 data_length;
 
1407
 
 
1408
  proto_item *ti, *pi;
 
1409
  proto_tree *pdu_tree = NULL;
 
1410
  proto_tree *flag_tree = NULL;
 
1411
 
 
1412
  /* this pdu */
 
1413
  const gchar *ptr;
 
1414
  guint32 vector;
 
1415
 
 
1416
  /* save start of pdu block */
 
1417
  pdu_start = offset;
 
1418
  pdu_offsets.start = pdu_start;
 
1419
 
 
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++);  
 
1425
 
 
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);
 
1430
    offset++;
 
1431
    pdu_length = length3 | (length2 << 8) | (length1 << 16);
 
1432
    pdu_flvh_length = 3;
 
1433
  } else {
 
1434
    pdu_length = length2 | (length1 << 8);
 
1435
    pdu_flvh_length = 2;
 
1436
  }
 
1437
  /* offset should now be pointing to vector (if one exists) */
 
1438
 
 
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);
 
1442
 
 
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);
 
1450
 
 
1451
  /* Add PDU Length item */
 
1452
  proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
 
1453
 
 
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;
 
1459
    offset++;
 
1460
    pdu_flvh_length++;
 
1461
  } else {
 
1462
    /* use last values */
 
1463
    vector_offset = last_pdu_offsets->vector;
 
1464
  }
 
1465
  /* offset should now be pointing to header (if one exists) */
 
1466
 
 
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);
 
1470
 
 
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);
 
1475
 
 
1476
  /* NO HEADER DATA ON THESE* (at least so far) */
 
1477
 
 
1478
  /* Adjust data */
 
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;
 
1485
  } else {
 
1486
    /* use last values */
 
1487
    data_offset = last_pdu_offsets->data;
 
1488
    data_length = last_pdu_offsets->data_length;
 
1489
  }
 
1490
  end_offset = data_offset + data_length;
 
1491
 
 
1492
  switch (vector) {
 
1493
  case ACN_SDT_VECTOR_ACK:
 
1494
    proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
 
1495
    data_offset += 4;
 
1496
    break;
 
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:");
 
1501
   break;
 
1502
  case ACN_SDT_VECTOR_LEAVE:
 
1503
    /* nothing more */
 
1504
    break;
 
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);
 
1508
    data_offset += 4;
 
1509
    break;
 
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);
 
1513
    data_offset += 4;
 
1514
    break;
 
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);
 
1518
    data_offset += 4;
 
1519
    proto_tree_add_item(pdu_tree, hf_acn_refuse_code, tvb, data_offset, 1, FALSE);
 
1520
    data_offset++;
 
1521
    break;
 
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);
 
1525
    data_offset += 4;
 
1526
    break;
 
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);
 
1530
    data_offset += 4;
 
1531
    proto_tree_add_item(pdu_tree, hf_acn_reason_code, tvb, data_offset, 1, FALSE);
 
1532
    data_offset++;
 
1533
    break;
 
1534
 
 
1535
  }
 
1536
 
 
1537
  return pdu_start + pdu_length;
 
1538
}
 
1539
 
 
1540
 
 
1541
/******************************************************************************/
 
1542
/* Dissect SDT Client PDU                                                     */
 
1543
static guint32
 
1544
dissect_acn_sdt_client_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
 
1545
{
 
1546
  /* common to all pdu */
 
1547
  guint8 pdu_flags;
 
1548
  guint32 pdu_start;
 
1549
  guint32 pdu_length;
 
1550
  guint32 pdu_flvh_length; /* flags, length, vector, header */
 
1551
  acn_pdu_offsets pdu_offsets = {0,0,0,0,0}; 
 
1552
  guint8 octet;
 
1553
  guint32 length1;
 
1554
  guint32 length2;
 
1555
  guint32 length3;
 
1556
  guint32 vector_offset;
 
1557
  guint32 header_offset;
 
1558
  guint32 data_offset;
 
1559
  guint32 data_length;
 
1560
  guint32 old_offset;
 
1561
  guint32 end_offset;
 
1562
 
 
1563
  proto_item *ti, *pi;
 
1564
  proto_tree *pdu_tree = NULL;
 
1565
  proto_tree *flag_tree = NULL;
 
1566
 
 
1567
  /* this pdu */
 
1568
  const gchar *ptr;
 
1569
  guint32 member_id;
 
1570
  guint32 protocol_id;
 
1571
  guint16 association;
 
1572
 
 
1573
  /* save start of pdu block */
 
1574
  pdu_start = offset;
 
1575
  pdu_offsets.start = pdu_start;
 
1576
 
 
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++);  
 
1582
 
 
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);
 
1587
    offset++;
 
1588
    pdu_length = length3 | (length2 << 8) | (length1 << 16);
 
1589
    pdu_flvh_length = 3;
 
1590
  } else {
 
1591
    pdu_length = length2 | (length1 << 8);
 
1592
    pdu_flvh_length = 2;
 
1593
  }
 
1594
  /* offset should now be pointing to vector (if one exists) */
 
1595
 
 
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);
 
1599
 
 
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);
 
1607
 
 
1608
  /* Add PDU Length item */
 
1609
  proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
 
1610
 
 
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;
 
1616
    offset += 2;
 
1617
    pdu_flvh_length += 2;
 
1618
  } else {
 
1619
    /* use last values */
 
1620
    vector_offset = last_pdu_offsets->vector;
 
1621
  }
 
1622
  /* offset should now be pointing to header (if one exists) */
 
1623
 
 
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);
 
1627
 
 
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;
 
1633
    offset += 6;
 
1634
    pdu_flvh_length += 6;
 
1635
  } else {
 
1636
    /* use last values */
 
1637
    header_offset = last_pdu_offsets->header;
 
1638
  }
 
1639
  /* offset should now be pointing to data (if one exists) */
 
1640
 
 
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);
 
1644
  header_offset += 4;
 
1645
 
 
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);
 
1650
 
 
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);
 
1654
  header_offset += 2;
 
1655
 
 
1656
  /* Adjust data */
 
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;
 
1663
  } else {
 
1664
    /* use last values */
 
1665
    data_offset = last_pdu_offsets->data;
 
1666
    data_length = last_pdu_offsets->data_length;
 
1667
  }
 
1668
  end_offset = data_offset + data_length;
 
1669
 
 
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;
 
1676
    }
 
1677
    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;
 
1683
    }
 
1684
    break;
 
1685
  }
 
1686
  return pdu_start + pdu_length;
 
1687
}
 
1688
 
 
1689
 
 
1690
/******************************************************************************/
 
1691
/* reverses the characters in a string */
 
1692
static void
 
1693
reverse(char *s)
 
1694
{
 
1695
        char c;
 
1696
  long i,j;
 
1697
  for (i=0, j=strlen(s)-1; i < j; i++, j--) {
 
1698
    c = s[i];
 
1699
    s[i] = s[j];
 
1700
    s[j] = c;
 
1701
  }
 
1702
}
 
1703
 
 
1704
 
 
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                                             */
 
1713
/*                                                                            */
 
1714
/*  returns end of string                                                     */
 
1715
/*  faster than printf()                                                      */
 
1716
static char *
 
1717
ltos(guint8 level, gchar *string, guint8 base, gchar leading_char, guint8 min_chars, gboolean show_zero)
 
1718
{
 
1719
  guint8 i;
 
1720
  /* verify base */
 
1721
  if (base < 2 || base > 16) {
 
1722
    *string = '\0';
 
1723
    return(string);
 
1724
  }
 
1725
  /* deal with zeros */
 
1726
  if ((level == 0) && (!show_zero)) {
 
1727
    for (i=0;i<min_chars;i++) {
 
1728
      string[i] = '.';
 
1729
    }
 
1730
    string[i++] = ' ';
 
1731
    string[i] = '\0';
 
1732
    return(string + i);
 
1733
  }
 
1734
 
 
1735
  i = 0;
 
1736
  /* do our convert, comes out backwords! */
 
1737
  do { 
 
1738
    string[i++] = "0123456789ABCDEF"[level % base];
 
1739
  } while ((level /= base) > 0);
 
1740
 
 
1741
  /* expand to needed character */
 
1742
  for (;i<min_chars;i++) {
 
1743
    string[i] = leading_char;
 
1744
  }
 
1745
  /* terminate */
 
1746
  string[i] = '\0';
 
1747
 
 
1748
  /* now reverse (and correct) the order */
 
1749
  reverse(string);
 
1750
 
 
1751
  /* add a space at the end (ok its at the start but it will be at the end)*/
 
1752
  string[i++] = ' ';
 
1753
  string[i] = '\0';
 
1754
  return(string + i);
 
1755
}
 
1756
 
 
1757
 
 
1758
/******************************************************************************/
 
1759
/* Dissect DMX data PDU                                                       */
 
1760
static guint32
 
1761
dissect_acn_dmx_data_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
 
1762
{
 
1763
  /* common to all pdu */
 
1764
  guint8 pdu_flags;
 
1765
  guint32 pdu_start;
 
1766
  guint32 pdu_length;
 
1767
  guint32 pdu_flvh_length; /* flags, length, vector, header */
 
1768
  acn_pdu_offsets pdu_offsets = {0,0,0,0,0}; 
 
1769
  guint8 octet;
 
1770
  guint32 length1;
 
1771
  guint32 length2;
 
1772
  guint32 length3;
 
1773
  guint32 vector_offset;
 
1774
  guint32 data_offset;
 
1775
  guint32 end_offset;
 
1776
  guint32 old_offset;
 
1777
  guint32 data_length;
 
1778
  guint32 header_offset;
 
1779
  guint32 total_cnt;
 
1780
  guint32 item_cnt;
 
1781
 
 
1782
 
 
1783
  proto_item *ti, *pi;
 
1784
  proto_tree *pdu_tree = NULL;
 
1785
  proto_tree *flag_tree = NULL;
 
1786
/*  proto_tree *addr_tree = NULL; */
 
1787
 
 
1788
/* this pdu */
 
1789
  acn_dmp_adt_type adt = {0,0,0,0,0,0};
 
1790
  const gchar *ptr;
 
1791
  guint32 vector;
 
1792
  char *buffer=NULL;
 
1793
  char *buf_ptr;
 
1794
  guint32 x;
 
1795
  guint8 level;
 
1796
  guint8  min_char;
 
1797
  guint8  base;
 
1798
  gchar   leading_char;
 
1799
 
 
1800
 
 
1801
  /* save start of pdu block */
 
1802
  pdu_start = offset;
 
1803
  pdu_offsets.start = pdu_start;
 
1804
 
 
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++);  
 
1810
 
 
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);
 
1815
    offset++;
 
1816
    pdu_length = length3 | (length2 << 8) | (length1 << 16);
 
1817
    pdu_flvh_length = 3;
 
1818
  } else {
 
1819
    pdu_length = length2 | (length1 << 8);
 
1820
    pdu_flvh_length = 2;
 
1821
  }
 
1822
  /* offset should now be pointing to vector (if one exists) */
 
1823
 
 
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);
 
1827
 
 
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);
 
1835
 
 
1836
  /* Add PDU Length item */
 
1837
  proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
 
1838
 
 
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;
 
1844
    offset += 1;
 
1845
    pdu_flvh_length += 1;
 
1846
  } else {
 
1847
    /* use last values */
 
1848
    vector_offset = last_pdu_offsets->vector;
 
1849
  }
 
1850
  /* offset should now be pointing to header (if one exists) */
 
1851
 
 
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);
 
1855
 
 
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);
 
1860
 
 
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;
 
1866
    offset++;
 
1867
    pdu_flvh_length++;
 
1868
  } else {
 
1869
    /* use last values */
 
1870
    header_offset = last_pdu_offsets->header;
 
1871
  }
 
1872
  /* offset should now be pointing to data (if one exists) */
 
1873
 
 
1874
  /* process based on vector */
 
1875
  acn_add_dmp_address_type(tvb, pinfo, pdu_tree, header_offset, &adt);
 
1876
 
 
1877
  /* Adjust data */
 
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;
 
1884
  } else {
 
1885
    /* use last values */
 
1886
    data_offset = last_pdu_offsets->data;
 
1887
    data_length = last_pdu_offsets->data_length;
 
1888
  }
 
1889
  end_offset = data_offset + data_length;
 
1890
 
 
1891
  switch (vector) {
 
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;
 
1896
 
 
1897
#define BUFFER_SIZE 128
 
1898
 
 
1899
      buffer = ep_alloc(BUFFER_SIZE);
 
1900
      buffer[0] = 0;
 
1901
      buf_ptr = buffer;
 
1902
 
 
1903
      /* values base on display mode */
 
1904
      switch ((guint)global_acn_dmx_display_view) {
 
1905
        case ACN_PREF_DMX_DISPLAY_HEX:
 
1906
          min_char = 2;
 
1907
          base = 16;
 
1908
          break;
 
1909
/*        case ACN_PREF_DMX_DISPLAY_PER: */
 
1910
        default:
 
1911
          min_char = 3;
 
1912
          base = 10;
 
1913
      }
 
1914
 
 
1915
      /* do we display leading zeros */
 
1916
      if (global_acn_dmx_display_leading_zeros) {
 
1917
        leading_char = '0';
 
1918
      } else {
 
1919
        leading_char = ' ';
 
1920
      }
 
1921
 
 
1922
      /* add a header line */
 
1923
      memset(buffer, ' ', 10);
 
1924
      buf_ptr += 9;
 
1925
      for (x=1;x<=20;x++) {
 
1926
        buf_ptr = ltos((guint8)x, buf_ptr, 10, ' ', min_char, FALSE);
 
1927
        if (x==10) {
 
1928
          *buf_ptr++ =  '|';
 
1929
          *buf_ptr++ =  ' ';
 
1930
        }
 
1931
      }
 
1932
      *buf_ptr = '\0';
 
1933
      proto_tree_add_text(pdu_tree, tvb, data_offset, 0, buffer);
 
1934
 
 
1935
      /* start our line */
 
1936
      g_snprintf(buffer, BUFFER_SIZE, "001-020: ");
 
1937
      buf_ptr = buffer + 9;
 
1938
 
 
1939
      total_cnt = 0;
 
1940
      item_cnt = 0;
 
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)) {
 
1945
            level = 1;
 
1946
          } else {
 
1947
            level = level * 100 / 255;
 
1948
          }
 
1949
        }
 
1950
        buf_ptr = ltos(level, buf_ptr, base, leading_char, min_char, global_acn_dmx_display_zeros);
 
1951
        total_cnt++;
 
1952
        item_cnt++;
 
1953
 
 
1954
        if (item_cnt == 20 || x == (end_offset-1)) {
 
1955
          /* add leader... */
 
1956
          proto_tree_add_text(pdu_tree, tvb, data_offset, item_cnt, buffer);
 
1957
          data_offset += 20;
 
1958
          g_snprintf(buffer, BUFFER_SIZE, "%03d-%03d: ",total_cnt, total_cnt+20);
 
1959
          buf_ptr = buffer + 9;
 
1960
          item_cnt = 0;
 
1961
        } else {
 
1962
          /* add separater character */
 
1963
          if (item_cnt == 10) {
 
1964
            *buf_ptr++ = '|';
 
1965
            *buf_ptr++ = ' ';
 
1966
            *buf_ptr = '\0';
 
1967
          }
 
1968
        }
 
1969
      }
 
1970
    /* NOTE:
 
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)
 
1978
     */
 
1979
    
 
1980
    break;
 
1981
  }
 
1982
  return pdu_start + pdu_length;
 
1983
}
 
1984
 
 
1985
 
 
1986
 
 
1987
/******************************************************************************/
 
1988
/* Dissect DMX Base PDU                                                       */
 
1989
static guint32
 
1990
dissect_acn_dmx_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
 
1991
{
 
1992
  /* common to all pdu */
 
1993
  guint8 pdu_flags;
 
1994
  guint32 pdu_start;
 
1995
  guint32 pdu_length;
 
1996
  guint32 pdu_flvh_length; /* flags, length, vector, header */
 
1997
  acn_pdu_offsets pdu_offsets = {0,0,0,0,0}; 
 
1998
  guint8 octet;
 
1999
  guint32 length1;
 
2000
  guint32 length2;
 
2001
  guint32 length3;
 
2002
  guint32 vector_offset;
 
2003
  guint32 data_offset;
 
2004
  guint32 end_offset;
 
2005
  guint32 data_length;
 
2006
 
 
2007
  proto_item *ti, *pi;
 
2008
  proto_tree *pdu_tree = NULL;
 
2009
  proto_tree *flag_tree = NULL;
 
2010
 
 
2011
/* this pdu */
 
2012
  guint32 vector;
 
2013
 
 
2014
  guint32 universe;
 
2015
  guint32 priority;
 
2016
 
 
2017
  /* save start of pdu block */
 
2018
  pdu_start = offset;
 
2019
  pdu_offsets.start = pdu_start;
 
2020
 
 
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++);  
 
2026
 
 
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);
 
2031
    offset++;
 
2032
    pdu_length = length3 | (length2 << 8) | (length1 << 16);
 
2033
    pdu_flvh_length = 3;
 
2034
  } else {
 
2035
    pdu_length = length2 | (length1 << 8);
 
2036
    pdu_flvh_length = 2;
 
2037
  }
 
2038
 
 
2039
  /* offset should now be pointing to vector (if one exists) */
 
2040
 
 
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);
 
2044
 
 
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);
 
2052
 
 
2053
  /* Add PDU Length item */
 
2054
  proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
 
2055
 
 
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;
 
2061
    offset += 4;
 
2062
    pdu_flvh_length += 4;
 
2063
  } else {
 
2064
    /* use last values */
 
2065
    vector_offset = last_pdu_offsets->vector;
 
2066
  }
 
2067
  /* offset should now be pointing to header (if one exists) */
 
2068
 
 
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; */
 
2073
 
 
2074
  /* Add Vector item to tree*/
 
2075
  proto_item_append_text(ti, ": %s", match_strval(vector, acn_dmx_vector_vals));
 
2076
 
 
2077
  /* NO HEADER DATA ON THESE* (at least so far) */
 
2078
 
 
2079
  /* Adjust data */
 
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;
 
2086
  } else {
 
2087
    /* use last values */
 
2088
    data_offset = last_pdu_offsets->data;
 
2089
    data_length = last_pdu_offsets->data_length;
 
2090
  }
 
2091
  end_offset = data_offset + data_length;
 
2092
 
 
2093
  /* process based on vector */
 
2094
  switch (vector) {
 
2095
  case 0x02:
 
2096
    proto_tree_add_item(pdu_tree, hf_acn_dmx_source_name, tvb, data_offset, 32, FALSE);
 
2097
    data_offset += 32;
 
2098
 
 
2099
    priority = tvb_get_guint8(tvb, data_offset); 
 
2100
    proto_tree_add_item(pdu_tree, hf_acn_dmx_priority, tvb, data_offset, 1, FALSE);
 
2101
    data_offset += 1;
 
2102
 
 
2103
    proto_tree_add_item(pdu_tree, hf_acn_dmx_sequence_number, tvb, data_offset, 1, FALSE);
 
2104
    data_offset += 1;
 
2105
 
 
2106
    universe = tvb_get_ntohs(tvb, data_offset); 
 
2107
    proto_tree_add_item(pdu_tree, hf_acn_dmx_universe       , tvb, data_offset, 2, FALSE);
 
2108
    data_offset += 2;
 
2109
 
 
2110
    proto_item_append_text(ti, ", Universe: %d, Priority: %d", universe, priority);
 
2111
 
 
2112
    data_offset = dissect_acn_dmx_data_pdu(tvb, pinfo, pdu_tree, data_offset, &pdu_offsets);
 
2113
 
 
2114
    break;
 
2115
  }
 
2116
  return pdu_start + pdu_length;
 
2117
}
 
2118
 
 
2119
/******************************************************************************/
 
2120
/* Dissect SDT Base PDU                                                       */
 
2121
static guint32
 
2122
dissect_acn_sdt_base_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
 
2123
{
 
2124
  /* common to all pdu */
 
2125
  guint8 pdu_flags;
 
2126
  guint32 pdu_start;
 
2127
  guint32 pdu_length;
 
2128
  guint32 pdu_flvh_length; /* flags, length, vector, header */
 
2129
  acn_pdu_offsets pdu_offsets = {0,0,0,0,0}; 
 
2130
  guint8 octet;
 
2131
  guint32 length1;
 
2132
  guint32 length2;
 
2133
  guint32 length3;
 
2134
  guint32 vector_offset;
 
2135
  guint32 data_offset;
 
2136
  guint32 end_offset;
 
2137
  guint32 old_offset;
 
2138
  guint32 data_length;
 
2139
 
 
2140
  proto_item *ti, *pi;
 
2141
  proto_tree *pdu_tree = NULL;
 
2142
  proto_tree *flag_tree = NULL;
 
2143
 
 
2144
  /* this pdu */
 
2145
  const gchar *ptr;
 
2146
  guint32 vector;
 
2147
  guint32 member_id;
 
2148
 
 
2149
  /* save start of pdu block */
 
2150
  pdu_start = offset;
 
2151
  pdu_offsets.start = pdu_start;
 
2152
 
 
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++);  
 
2158
 
 
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);
 
2163
    offset++; 
 
2164
    pdu_length = length3 | (length2 << 8) | (length1 << 16);
 
2165
    pdu_flvh_length = 3;
 
2166
  } else {
 
2167
    pdu_length = length2 | (length1 << 8);
 
2168
    pdu_flvh_length = 2;
 
2169
  }
 
2170
  /* offset should now be pointing to vector (if one exists) */
 
2171
 
 
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);
 
2175
 
 
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);
 
2183
 
 
2184
  /* Add PDU Length item */
 
2185
  proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
 
2186
 
 
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;
 
2192
    offset++;
 
2193
    pdu_flvh_length++;
 
2194
  } else {
 
2195
    /* use last values */
 
2196
    vector_offset = last_pdu_offsets->vector;
 
2197
  }
 
2198
  /* offset should now be pointing to header (if one exists) */
 
2199
 
 
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);
 
2203
 
 
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);
 
2208
 
 
2209
  /* NO HEADER DATA ON THESE* (at least so far) */
 
2210
 
 
2211
  /* Adjust data */
 
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;
 
2218
  } else {
 
2219
    /* use last values */
 
2220
    data_offset = last_pdu_offsets->data;
 
2221
    data_length = last_pdu_offsets->data_length;
 
2222
  }
 
2223
  end_offset = data_offset + data_length;
 
2224
 
 
2225
  /* process based on vector */
 
2226
  switch (vector) {
 
2227
  case ACN_SDT_VECTOR_UNKNOWN:
 
2228
    break;
 
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);
 
2232
    data_offset += 2;
 
2233
    proto_tree_add_item(pdu_tree, hf_acn_total_sequence_number, tvb, data_offset, 4, FALSE);
 
2234
    data_offset += 4;
 
2235
    proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
 
2236
    data_offset += 4;
 
2237
    proto_tree_add_item(pdu_tree, hf_acn_oldest_available_wrapper, tvb, data_offset, 4, FALSE);
 
2238
    data_offset += 4;
 
2239
    proto_tree_add_item(pdu_tree, hf_acn_first_memeber_to_ack, tvb, data_offset, 2, FALSE);
 
2240
    data_offset += 2;
 
2241
    proto_tree_add_item(pdu_tree, hf_acn_last_memeber_to_ack, tvb, data_offset, 2, FALSE);
 
2242
    data_offset += 2;
 
2243
    proto_tree_add_item(pdu_tree, hf_acn_mak_threshold, tvb, data_offset, 2, FALSE);
 
2244
    data_offset += 2;
 
2245
 
 
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;
 
2250
    }
 
2251
    break;
 
2252
  case ACN_SDT_VECTOR_CHANNEL_PARAMS:
 
2253
    break;
 
2254
  case ACN_SDT_VECTOR_JOIN:
 
2255
    proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
 
2256
    data_offset += 16;
 
2257
    proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
 
2258
    data_offset += 2;
 
2259
    proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
 
2260
    data_offset += 2;
 
2261
    proto_tree_add_item(pdu_tree, hf_acn_reciprocal_channel, tvb, data_offset, 2, FALSE);
 
2262
    data_offset += 2;
 
2263
    proto_tree_add_item(pdu_tree, hf_acn_total_sequence_number, tvb, data_offset, 4, FALSE);
 
2264
    data_offset += 4;
 
2265
    proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
 
2266
    data_offset += 4;
 
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:");
 
2270
    break;
 
2271
  case ACN_SDT_VECTOR_JOIN_REFUSE:
 
2272
    pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
 
2273
    data_offset += 16;
 
2274
    proto_item_append_text(pi, "(Leader)");
 
2275
    proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
 
2276
    data_offset += 2;
 
2277
    proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
 
2278
    data_offset += 2;
 
2279
    proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
 
2280
    data_offset += 4;
 
2281
    proto_tree_add_item(pdu_tree, hf_acn_refuse_code, tvb, data_offset, 1, FALSE);
 
2282
    data_offset ++;
 
2283
    break;
 
2284
  case ACN_SDT_VECTOR_JOIN_ACCEPT:
 
2285
    pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
 
2286
    data_offset += 16;
 
2287
    proto_item_append_text(pi, "(Leader)");
 
2288
    proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
 
2289
    data_offset += 2;
 
2290
    proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
 
2291
    data_offset += 2;
 
2292
    proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
 
2293
    data_offset += 4;
 
2294
    proto_tree_add_item(pdu_tree, hf_acn_reciprocal_channel, tvb, data_offset, 2, FALSE);
 
2295
    data_offset += 2;
 
2296
    break;
 
2297
  case ACN_SDT_VECTOR_LEAVE:
 
2298
    break;
 
2299
  case ACN_SDT_VECTOR_LEAVING:
 
2300
    pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
 
2301
    data_offset += 16;
 
2302
    proto_item_append_text(pi, "(Leader)");
 
2303
    proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
 
2304
    data_offset += 2;
 
2305
    proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
 
2306
    data_offset += 2;
 
2307
    proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
 
2308
    data_offset += 4;
 
2309
    proto_tree_add_item(pdu_tree, hf_acn_reason_code, tvb, data_offset, 1, FALSE);
 
2310
    offset++;
 
2311
    break;
 
2312
  case ACN_SDT_VECTOR_CONNECT:
 
2313
    break;
 
2314
  case ACN_SDT_VECTOR_CONNECT_ACCEPT:
 
2315
    break;
 
2316
  case ACN_SDT_VECTOR_CONNECT_REFUSE:
 
2317
    break;
 
2318
  case ACN_SDT_VECTOR_DISCONNECT:
 
2319
    break;
 
2320
  case ACN_SDT_VECTOR_DISCONNECTING:
 
2321
    break;
 
2322
  case ACN_SDT_VECTOR_ACK:
 
2323
    break;
 
2324
  case ACN_SDT_VECTOR_NAK:
 
2325
    pi = proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
 
2326
    data_offset += 16;
 
2327
    proto_item_append_text(pi, "(Leader)");
 
2328
    proto_tree_add_item(pdu_tree, hf_acn_channel_number, tvb, data_offset, 2, FALSE);
 
2329
    data_offset += 2;
 
2330
    proto_tree_add_item(pdu_tree, hf_acn_member_id, tvb, data_offset, 2, FALSE);
 
2331
    data_offset += 2;
 
2332
    proto_tree_add_item(pdu_tree, hf_acn_reliable_sequence_number, tvb, data_offset, 4, FALSE);
 
2333
    data_offset += 4;
 
2334
    proto_tree_add_item(pdu_tree, hf_acn_first_missed_sequence, tvb, data_offset, 4, FALSE);
 
2335
    data_offset += 4;
 
2336
    proto_tree_add_item(pdu_tree, hf_acn_last_missed_sequence, tvb, data_offset, 4, FALSE);
 
2337
    data_offset += 4;
 
2338
    break;
 
2339
  case ACN_SDT_VECTOR_GET_SESSION:
 
2340
    proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, data_offset, 16, FALSE);
 
2341
    data_offset += 16;
 
2342
    break;
 
2343
  case ACN_SDT_VECTOR_SESSIONS:
 
2344
    member_id = tvb_get_ntohs(tvb, data_offset);
 
2345
    switch (member_id) {
 
2346
    case 0:
 
2347
      data_offset = acn_add_channel_owner_info_block(tvb, pinfo, pdu_tree, data_offset);
 
2348
      break;
 
2349
    case 1:
 
2350
      data_offset = acn_add_channel_member_info_block(tvb, pinfo, pdu_tree, data_offset);
 
2351
      break;
 
2352
    }
 
2353
    break;
 
2354
  }
 
2355
 
 
2356
  return pdu_start + pdu_length;
 
2357
}
 
2358
 
 
2359
/******************************************************************************/
 
2360
/* Dissect Root PDU                                                           */
 
2361
static guint32
 
2362
dissect_acn_root_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, acn_pdu_offsets *last_pdu_offsets)
 
2363
{
 
2364
  /* common to all pdu */
 
2365
  guint8 pdu_flags;
 
2366
  guint32 pdu_start;
 
2367
  guint32 pdu_length;
 
2368
  guint32 pdu_flvh_length; /* flags, length, vector, header */
 
2369
  acn_pdu_offsets pdu_offsets = {0,0,0,0,0}; 
 
2370
  guint8 octet;
 
2371
  guint32 length1;
 
2372
  guint32 length2;
 
2373
  guint32 length3;
 
2374
  guint32 vector_offset;
 
2375
  guint32 header_offset;
 
2376
  guint32 data_offset;
 
2377
  guint32 end_offset;
 
2378
  guint32 old_offset;
 
2379
  guint32 data_length;
 
2380
 
 
2381
  proto_item *ti, *pi;
 
2382
  proto_tree *pdu_tree = NULL;
 
2383
  proto_tree *flag_tree = NULL;
 
2384
 
 
2385
  /* this pdu */
 
2386
  guint32 protocol_id;
 
2387
  e_guid_t guid;
 
2388
 
 
2389
  /* save start of pdu block */
 
2390
  pdu_start = offset;
 
2391
  pdu_offsets.start = pdu_start;
 
2392
 
 
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++);  
 
2398
 
 
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);
 
2403
    offset++;
 
2404
    pdu_length = length3 | (length2 << 8) | (length1 << 16);
 
2405
    pdu_flvh_length = 3;
 
2406
  } else {
 
2407
    pdu_length = length2 | (length1 << 8);
 
2408
    pdu_flvh_length = 2;
 
2409
  }
 
2410
  /* offset should now be pointing to vector (if one exists) */
 
2411
 
 
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);
 
2415
 
 
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);
 
2423
 
 
2424
  /* Add PDU Length item */
 
2425
  proto_tree_add_uint(pdu_tree, hf_acn_pdu_length, tvb, pdu_start, pdu_flvh_length, pdu_length);
 
2426
 
 
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;
 
2432
    offset += 4;
 
2433
    pdu_flvh_length += 4;
 
2434
  } else {
 
2435
    /* use last values */
 
2436
    vector_offset = last_pdu_offsets->vector;
 
2437
  }
 
2438
  /* offset should now be pointing to header (if one exists) */
 
2439
 
 
2440
 
 
2441
 
 
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);
 
2445
  
 
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");
 
2451
  
 
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;
 
2457
        offset += 16;
 
2458
        pdu_flvh_length += 16;
 
2459
      } else {
 
2460
        /* use last values */
 
2461
        header_offset = last_pdu_offsets->header;
 
2462
      }
 
2463
      /* offset should now be pointing to data (if one exists) */
 
2464
  
 
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));
 
2468
 
 
2469
      proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, header_offset, 16, FALSE);
 
2470
      header_offset += 16;
 
2471
  
 
2472
      /* Adjust data */
 
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;
 
2479
      } else {
 
2480
        /* use last values */
 
2481
        data_offset = last_pdu_offsets->data;
 
2482
        data_length = last_pdu_offsets->data_length;
 
2483
      }
 
2484
      end_offset = data_offset + data_length; 
 
2485
 
 
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;
 
2491
      }
 
2492
    }
 
2493
    break;
 
2494
  case ACN_PROTOCOL_ID_SDT:
 
2495
    /* Adjust header */
 
2496
    proto_item_append_text(ti,": Root SDT");
 
2497
 
 
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;
 
2503
      offset += 16;
 
2504
      pdu_flvh_length += 16;
 
2505
    } else {
 
2506
      /* use last values */
 
2507
      header_offset = last_pdu_offsets->header;
 
2508
    }
 
2509
    /* offset should now be pointing to data (if one exists) */
 
2510
 
 
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));
 
2514
 
 
2515
    proto_tree_add_item(pdu_tree, hf_acn_cid, tvb, header_offset, 16, FALSE);
 
2516
    header_offset += 16;
 
2517
 
 
2518
    /* Adjust data */
 
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;
 
2525
    } else {
 
2526
      /* use last values */
 
2527
      data_offset = last_pdu_offsets->data;
 
2528
      data_length = last_pdu_offsets->data_length;
 
2529
    }
 
2530
    end_offset = data_offset + data_length;
 
2531
 
 
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;
 
2537
    }
 
2538
    break;
 
2539
  }
 
2540
 
 
2541
  return pdu_start + pdu_length;
 
2542
}
 
2543
 
 
2544
/******************************************************************************/
 
2545
/* Dissect ACN                                                                */
 
2546
static int
 
2547
dissect_acn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
2548
{
 
2549
  proto_item *ti = NULL;
 
2550
  proto_tree *acn_tree = NULL;
 
2551
  guint32 data_offset = 0;
 
2552
  guint32 old_offset;
 
2553
  guint32 end_offset;
 
2554
  acn_pdu_offsets pdu_offsets = {0,0,0,0,0}; 
 
2555
 
 
2556
/*   if (!is_acn(tvb)) { */
 
2557
/*     return 0;         */
 
2558
/*   }                   */
 
2559
 
 
2560
  /* Set the protocol column */
 
2561
  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
 
2562
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACN");
 
2563
  }
 
2564
 
 
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 );
 
2569
  }
 
2570
 
 
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);
 
2574
 
 
2575
    pdu_offsets.start = data_offset;
 
2576
 
 
2577
    /* add preamble, postamble and ACN Packet ID */
 
2578
    proto_tree_add_item(acn_tree, hf_acn_preamble_size, tvb, data_offset, 2, FALSE);
 
2579
    data_offset += 2;
 
2580
    proto_tree_add_item(acn_tree, hf_acn_postamble_size, tvb, data_offset, 2, FALSE);
 
2581
    data_offset += 2;
 
2582
    proto_tree_add_item(acn_tree, hf_acn_packet_identifier, tvb, data_offset, 12, FALSE);
 
2583
    data_offset += 12;
 
2584
 
 
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;
 
2591
    }
 
2592
  }
 
2593
  return tvb_length(tvb);
 
2594
}
 
2595
 
 
2596
/******************************************************************************/
 
2597
/* Register protocol                                                          */
 
2598
void proto_register_acn(void)
 
2599
{
 
2600
  static hf_register_info hf[] = {
 
2601
    /**************************************************************************/
 
2602
    /* In alphabetical order */
 
2603
    /* Address Type */
 
2604
    /* PDU flags*/
 
2605
    { &hf_acn_ip_address_type,
 
2606
      { "Type", "acn.ip_address_type",
 
2607
        FT_UINT8, BASE_DEC, VALS(acn_ip_address_type_vals), 0x0,
 
2608
        "Type", HFILL }
 
2609
    },
 
2610
    /* Association */
 
2611
    { &hf_acn_association,
 
2612
      { "Association", "acn.association",
 
2613
        FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
 
2614
        "Association", HFILL }
 
2615
    },
 
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 }
 
2621
    },
 
2622
    /* CID */
 
2623
    { &hf_acn_cid,
 
2624
      { "CID", "acn.cid",
 
2625
        FT_GUID, BASE_NONE, NULL, 0x0,
 
2626
        NULL, HFILL }
 
2627
    },
 
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 }
 
2633
    },
 
2634
    /* DMP data */
 
2635
    { &hf_acn_data,
 
2636
      { "Data", "acn.dmp_data",
 
2637
        FT_BYTES, BASE_HEX, NULL, 0x0,
 
2638
        "Data", HFILL }
 
2639
    },
 
2640
    { &hf_acn_data8,
 
2641
      { "Addr", "acn.dmp_data8",
 
2642
        FT_INT8, BASE_DEC_HEX, NULL, 0x0,
 
2643
        "Data8", HFILL }
 
2644
    },
 
2645
    { &hf_acn_data16,
 
2646
      { "Addr", "acn.dmp_data16",
 
2647
        FT_INT16, BASE_DEC_HEX, NULL, 0x0,
 
2648
        "Data16", HFILL }
 
2649
    },
 
2650
    { &hf_acn_data24,
 
2651
      { "Addr", "acn.dmp_data24",
 
2652
        FT_INT24, BASE_DEC_HEX, NULL, 0x0,
 
2653
        "Data24", HFILL }
 
2654
    },
 
2655
    { &hf_acn_data32,
 
2656
      { "Addr", "acn.dmp_data32",
 
2657
        FT_INT32, BASE_DEC_HEX, NULL, 0x0,
 
2658
        "Data32", HFILL }
 
2659
    },
 
2660
 
 
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 }
 
2665
    },
 
2666
 
 
2667
    /* DMP Address */
 
2668
    { &hf_acn_dmp_address1,
 
2669
      { "Address", "acn.dmp_address",
 
2670
        FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
 
2671
        "Address", HFILL }
 
2672
    },
 
2673
    { &hf_acn_dmp_address2,
 
2674
      { "Address", "acn.dmp_address",
 
2675
        FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
 
2676
        "Address", HFILL }
 
2677
    },
 
2678
    { &hf_acn_dmp_address4,
 
2679
      { "Address", "acn.dmp_address",
 
2680
        FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
 
2681
        "Address", HFILL }
 
2682
    },
 
2683
 
 
2684
    /* DMP Address type*/
 
2685
    { &hf_acn_dmp_adt,
 
2686
      { "Address and Data Type", "acn.dmp_adt",
 
2687
        FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
 
2688
        "Address and Data Type", HFILL }
 
2689
    },
 
2690
    { &hf_acn_dmp_adt_a,
 
2691
      { "Size", "acn.dmp_adt_a",
 
2692
        FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_a_vals), 0x03,
 
2693
        "Size", HFILL }
 
2694
    },
 
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 }
 
2699
    },
 
2700
    { &hf_acn_dmp_adt_r,
 
2701
      { "Relative", "acn.dmp_adt_r",
 
2702
        FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_r_vals), 0x40,
 
2703
        "Relative", HFILL }
 
2704
    },
 
2705
    { &hf_acn_dmp_adt_v,
 
2706
      { "Virtual", "acn.dmp_adt_v",
 
2707
        FT_UINT8, BASE_DEC, VALS(acn_dmp_adt_v_vals), 0x80,
 
2708
        "Virtual", HFILL }
 
2709
    },
 
2710
    { &hf_acn_dmp_adt_x,
 
2711
      { "Reserved", "acn.dmp_adt_x",
 
2712
        FT_UINT8, BASE_DEC, NULL, 0x0c,
 
2713
        "Reserved", HFILL }
 
2714
    },
 
2715
 
 
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 }
 
2721
    },
 
2722
 
 
2723
    /* DMP Vector */
 
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 }
 
2728
    },
 
2729
    /* Expiry */
 
2730
    { &hf_acn_expiry,
 
2731
      { "Expiry", "acn.expiry",
 
2732
        FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
 
2733
        "Expiry", HFILL }
 
2734
    },
 
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 }
 
2740
    },
 
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 }
 
2746
    },
 
2747
    /* IPV4 */
 
2748
    { &hf_acn_ipv4,
 
2749
      { "IPV4", "acn.ipv4",
 
2750
        FT_IPv4, BASE_NONE, NULL, 0x0,
 
2751
        "IPV4", HFILL }
 
2752
    },
 
2753
    /* IPV6 */
 
2754
    { &hf_acn_ipv6,
 
2755
      { "IPV6", "acn.ipv6",
 
2756
        FT_IPv6, BASE_NONE, NULL, 0x0,
 
2757
        "IPV6", HFILL }
 
2758
    },
 
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 }
 
2764
    },
 
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 }
 
2770
    },
 
2771
    /* MAK threshold */
 
2772
    { &hf_acn_mak_threshold,
 
2773
      { "MAK Threshold", "acn.mak_threshold",
 
2774
        FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
 
2775
        "MAK Threshold", HFILL }
 
2776
    },
 
2777
    /* MemberID */
 
2778
    { &hf_acn_member_id,
 
2779
      { "Member ID", "acn.member_id",
 
2780
        FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
 
2781
        "Member ID", HFILL }
 
2782
    },
 
2783
    /* NAK Holdoff */
 
2784
    { &hf_acn_nak_holdoff,
 
2785
      { "NAK holdoff (ms)", "acn.nak_holdoff",
 
2786
        FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
 
2787
        "NAK holdoff", HFILL }
 
2788
    },
 
2789
    /* NAK Max Wait */
 
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 }
 
2794
    },
 
2795
    /* NAK Modulus */
 
2796
    { &hf_acn_nak_modulus,
 
2797
      { "NAK Modulus", "acn.nak_modulus",
 
2798
        FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
 
2799
        "NAK Modulus", HFILL }
 
2800
    },
 
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 }
 
2806
    },
 
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 }
 
2812
    },
 
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 }
 
2818
    },
 
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 }
 
2824
    },
 
2825
    /* PDU */
 
2826
    { &hf_acn_pdu,
 
2827
      { "PDU", "acn.pdu",
 
2828
        FT_NONE, BASE_NONE, NULL, 0x0,
 
2829
        "PDU", HFILL }
 
2830
    },
 
2831
    /* PDU flags*/
 
2832
    { &hf_acn_pdu_flags,
 
2833
      { "Flags", "acn.pdu.flags",
 
2834
        FT_UINT8, BASE_HEX, NULL, 0x0,
 
2835
        "PDU Flags", HFILL }
 
2836
    },
 
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 }
 
2841
    },
 
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 }
 
2846
    },
 
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 }
 
2851
    },
 
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 }
 
2856
    },
 
2857
    /* PDU Length */
 
2858
    { &hf_acn_pdu_length,
 
2859
      { "Length", "acn.pdu.flag_d",
 
2860
        FT_UINT32, BASE_DEC, NULL, 0x0,
 
2861
        "PDU Length", HFILL }
 
2862
    },
 
2863
    /* Port */
 
2864
    { &hf_acn_port,
 
2865
      { "Port", "acn.port",
 
2866
        FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
 
2867
        "Port", HFILL }
 
2868
    },
 
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 }
 
2874
    },
 
2875
    /* Protocol ID */
 
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 }
 
2880
    },
 
2881
    /* Reason Code */
 
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 }
 
2886
    },
 
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 }
 
2892
    },
 
2893
    /* Refuse Code */
 
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 }
 
2898
    },
 
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 }
 
2904
    },
 
2905
    /* SDT Vector */
 
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 }
 
2910
    },
 
2911
 
 
2912
    /* DMX Vector */
 
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 }
 
2917
    },
 
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 }
 
2923
    },
 
2924
 
 
2925
    /* DMX priority */
 
2926
    { &hf_acn_dmx_priority,
 
2927
      { "Priority", "acn.dmx.priority",
 
2928
        FT_UINT8, BASE_DEC, NULL, 0x0,
 
2929
        "DMX Priority", HFILL }
 
2930
    },
 
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 }
 
2936
    },
 
2937
    /* DMX Universe */
 
2938
    { &hf_acn_dmx_universe,
 
2939
      { "Universe", "acn.dmx.universe",
 
2940
        FT_UINT16, BASE_DEC, NULL, 0x0,
 
2941
        "DMX Universe", HFILL }
 
2942
    },
 
2943
    /* Session Count */
 
2944
    { &hf_acn_session_count,
 
2945
      { "Session Count", "acn.session_count",
 
2946
        FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
 
2947
        "Session Count", HFILL }
 
2948
    },
 
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 }
 
2954
    },
 
2955
  };
 
2956
 
 
2957
  /* Setup protocol subtree array */
 
2958
  static gint *ett[] = {
 
2959
    &ett_acn,
 
2960
    &ett_acn_channel_owner_info_block,
 
2961
    &ett_acn_channel_member_info_block,
 
2962
    &ett_acn_channel_parameter,
 
2963
    &ett_acn_address,
 
2964
    &ett_acn_address_type,
 
2965
    &ett_acn_pdu_flags,
 
2966
    &ett_acn_dmp_pdu,
 
2967
    &ett_acn_sdt_pdu,
 
2968
    &ett_acn_sdt_client_pdu,
 
2969
    &ett_acn_sdt_base_pdu,
 
2970
    &ett_acn_root_pdu,
 
2971
    &ett_acn_dmx_address,
 
2972
    &ett_acn_dmx_data_pdu,
 
2973
    &ett_acn_dmx_pdu
 
2974
  };
 
2975
 
 
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 */
 
2981
      "acn"                               /* abbrev */
 
2982
      );
 
2983
  }
 
2984
 
 
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",
 
2989
                                 "Decode ACN",
 
2990
                                 "Enable Architecture for Control Networks dissector (ANSI BSR E1.17)",
 
2991
                                 &global_acn_heur);
 
2992
 
 
2993
  prefs_register_bool_preference(acn_module, "dmx_enable",
 
2994
                                 "Streaming DMX", 
 
2995
                                 "Enable Streaming DMX extension dissector (ANSI BSR E1.31)",
 
2996
                                 &global_acn_dmx_enable);
 
2997
 
 
2998
  prefs_register_enum_preference(acn_module, "dmx_display_view",
 
2999
                                 "DMX, display format", 
 
3000
                                 "Display format", 
 
3001
                                 &global_acn_dmx_display_view,
 
3002
                                 dmx_display_view, 
 
3003
                                 TRUE);
 
3004
 
 
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);
 
3009
 
 
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);
 
3014
}
 
3015
 
 
3016
 
 
3017
/******************************************************************************/
 
3018
/* Register handoff                                                           */
 
3019
void
 
3020
proto_reg_handoff_acn(void)
 
3021
{
 
3022
  static guint initialized = FALSE;
 
3023
  /* static dissector_handle_t acn_handle; */
 
3024
 
 
3025
  if (!initialized) {
 
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);
 
3029
    initialized = TRUE;
 
3030
  }
 
3031
}
 
3032